1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Binglin Chen <binglin.chen (at) intel.com> 26 * 27 */ 28 29 #include "vsp_VPP.h" 30 #include "psb_buffer.h" 31 #include "psb_surface.h" 32 #include "vsp_cmdbuf.h" 33 #include "psb_drv_debug.h" 34 #include "vsp_compose.h" 35 36 #include <strings.h> 37 38 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 39 #define INIT_CONTEXT_VPP context_VPP_p ctx = (context_VPP_p) obj_context->format_data; 40 #define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) 41 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) 42 #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id )) 43 44 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id )) 45 46 #define KB 1024 47 #define MB (KB * KB) 48 #define VSP_CONTEXT_BUF_SIZE (60*KB) 49 #define VSP_INTERMEDIATE_BUF_SIZE (29*MB) 50 51 #define MAX_VPP_PARAM (100) 52 #define MIN_VPP_PARAM (0) 53 #define STEP_VPP_PARAM (33) 54 #define MAX_VPP_AUTO_PARAM (1) 55 #define MIN_VPP_AUTO_PARAM (0) 56 #define STEP_VPP_AUTO_PARAM (1) 57 58 #define VSP_FORWARD_REF_NUM 3 59 60 #define VSP_COLOR_ENHANCE_FEATURES 2 61 62 #define ALIGN_TO_128(value) ((value + 128 - 1) & ~(128 - 1)) 63 #define ALIGN_TO_16(value) ((value + 16 - 1) & ~(16 - 1)) 64 65 #define QVGA_AREA (320 * 240) 66 #define VGA_AREA (640 * 480) 67 #define SD_AREA (720 * 576) 68 #define HD720P_AREA (1280 * 720) 69 #define HD1080P_AREA (1920 * 1088) 70 71 #define MIN_SUPPORTED_HEIGHT 96 72 #define MAX_SUPPORTED_HEIGHT 1088 73 74 /** 75 * The number of supported filter is 5: 76 * VAProcFilterDeblocking 77 * VAProcFilterNoiseReduction 78 * VAProcFilterSharpening 79 * VAProcFilterColorBalance 80 * VAProcFilterFrameRateConversion 81 */ 82 #define VSP_SUPPORTED_FILTERS_NUM 5 83 84 /* The size of supported color standard */ 85 #define COLOR_STANDARDS_NUM 1 86 87 enum resolution_set { 88 NOT_SUPPORTED_RESOLUTION = -1, 89 QCIF_TO_QVGA = 0, 90 QVGA_TO_VGA, 91 VGA_TO_SD, 92 SD_TO_720P, 93 HD720P_TO_1080P, 94 RESOLUTION_SET_NUM 95 }; 96 97 struct vpp_chain_capability { 98 int frc_enabled; 99 int sharpen_enabled; 100 int color_balance_enabled; 101 int denoise_enabled; 102 int deblock_enabled; 103 }; 104 105 enum filter_status { 106 FILTER_DISABLED = 0, 107 FILTER_ENABLED 108 }; 109 110 struct vpp_chain_capability vpp_chain_caps[RESOLUTION_SET_NUM] = { 111 [HD720P_TO_1080P] = {FILTER_ENABLED, FILTER_ENABLED, FILTER_DISABLED, FILTER_DISABLED, FILTER_DISABLED}, 112 [SD_TO_720P] = {FILTER_ENABLED, FILTER_ENABLED, FILTER_DISABLED, FILTER_DISABLED, FILTER_DISABLED}, 113 [VGA_TO_SD] = {FILTER_ENABLED, FILTER_ENABLED, FILTER_DISABLED, FILTER_DISABLED, FILTER_DISABLED}, 114 [QVGA_TO_VGA] = {FILTER_ENABLED, FILTER_ENABLED, FILTER_ENABLED, FILTER_ENABLED, FILTER_DISABLED}, 115 [QCIF_TO_QVGA] = {FILTER_ENABLED, FILTER_ENABLED, FILTER_ENABLED, FILTER_DISABLED, FILTER_ENABLED} 116 }; 117 118 struct filter_strength { 119 struct VssProcDenoiseParameterBuffer denoise_deblock[RESOLUTION_SET_NUM]; 120 struct VssProcColorEnhancementParameterBuffer enhancer[RESOLUTION_SET_NUM]; 121 struct VssProcSharpenParameterBuffer sharpen[RESOLUTION_SET_NUM]; 122 }; 123 124 enum filter_strength_type { 125 INVALID_STRENGTH = -1, 126 LOW_STRENGTH = 0, 127 MEDIUM_STRENGTH, 128 HIGH_STRENGTH, 129 STRENGTH_NUM 130 }; 131 132 #define SHARPEN_ON (1) 133 134 struct filter_strength vpp_strength[STRENGTH_NUM] = { 135 [LOW_STRENGTH] = { 136 /* structure: 137 * type(0-Denoise,1-Deblock), value_thr, cnt_thr, coef, temp_thr1, temp_thr2, _pad[2] 138 */ 139 .denoise_deblock = { 140 [QCIF_TO_QVGA] = {1, 15, 47, 35, 0, 0, {0, 0}}, 141 [QVGA_TO_VGA] = {0, 7, 48, 47, 0, 0, {0, 0}}, 142 [VGA_TO_SD] = {0, 10, 8, 9, 1, 3, {0, 0}}, 143 [SD_TO_720P] = {0, 10, 48, 47, 0, 0, {0, 0}}, 144 [HD720P_TO_1080P] = {0, 10, 48, 47, 0, 0, {0, 0}} 145 }, 146 /* structure: 147 * temp_detect, temp_correct, clip_thr, mid_thr, luma_amm, chroma_amm, _pad[2] 148 */ 149 .enhancer = { 150 [QCIF_TO_QVGA] = {200, 100, 1, 42, 40, 60, {0, 0}}, 151 [QVGA_TO_VGA] = {220, 180, 1, 42, 40, 60, {0, 0}}, 152 [VGA_TO_SD] = {220, 200, 1, 42, 40, 60, {0, 0}}, 153 [SD_TO_720P] = {100, 100, 5, 33, 0, 0, {0, 0}}, 154 [HD720P_TO_1080P] = {100, 100, 5, 33, 0, 0, {0, 0}} 155 }, 156 .sharpen = { 157 [QCIF_TO_QVGA] = { .quality = SHARPEN_ON }, 158 [QVGA_TO_VGA] = { .quality = SHARPEN_ON }, 159 [VGA_TO_SD] = { .quality = SHARPEN_ON }, 160 [SD_TO_720P] = { .quality = SHARPEN_ON }, 161 [HD720P_TO_1080P] = { .quality = SHARPEN_ON } 162 } 163 }, 164 [MEDIUM_STRENGTH] = { 165 .denoise_deblock = { 166 [QCIF_TO_QVGA] = {1, 25, 47, 12, 0, 0, {0, 0}}, 167 [QVGA_TO_VGA] = {0, 10, 48, 47, 0, 0, {0, 0}}, 168 [VGA_TO_SD] = {0, 20, 8, 9, 2, 4, {0, 0}}, 169 [SD_TO_720P] = {0, 10, 48, 47, 0, 0, {0, 0}}, 170 [HD720P_TO_1080P] = {0, 10, 48, 47, 0, 0, {0, 0}} 171 }, 172 .enhancer = { 173 [QCIF_TO_QVGA] = {100, 100, 1, 33, 100, 100, {0, 0}}, 174 [QVGA_TO_VGA] = {100, 180, 1, 33, 100, 100, {0, 0}}, 175 [VGA_TO_SD] = {100, 200, 1, 33, 100, 100, {0, 0}}, 176 [SD_TO_720P] = {100, 100, 5, 33, 0, 0, {0, 0}}, 177 [HD720P_TO_1080P] = {100, 100, 5, 33, 0, 0, {0, 0}} 178 }, 179 .sharpen = { 180 [QCIF_TO_QVGA] = { .quality = SHARPEN_ON }, 181 [QVGA_TO_VGA] = { .quality = SHARPEN_ON }, 182 [VGA_TO_SD] = { .quality = SHARPEN_ON }, 183 [SD_TO_720P] = { .quality = SHARPEN_ON }, 184 [HD720P_TO_1080P] = { .quality = SHARPEN_ON } 185 } 186 }, 187 [HIGH_STRENGTH] = { 188 .denoise_deblock = { 189 [QCIF_TO_QVGA] = {1, 30, 40, 10, 0, 0, {0, 0}}, 190 [QVGA_TO_VGA] = {0, 15, 45, 25, 0, 0, {0, 0}}, 191 [VGA_TO_SD] = {0, 20, 7, 5, 3, 6, {0, 0}}, 192 [SD_TO_720P] = {0, 10, 48, 47, 0, 0, {0, 0}}, 193 [HD720P_TO_1080P] = {0, 10, 48, 47, 0, 0, {0, 0}} 194 }, 195 .enhancer = { 196 [QCIF_TO_QVGA] = {100, 100, 5, 33, 150, 200, {0, 0}}, 197 [QVGA_TO_VGA] = {100, 180, 5, 33, 150, 200, {0, 0}}, 198 [VGA_TO_SD] = {100, 200, 5, 33, 100, 150, {0, 0}}, 199 [SD_TO_720P] = {100, 100, 5, 33, 0, 0, {0, 0}}, 200 [HD720P_TO_1080P] = {100, 100, 5, 33, 0, 0, {0, 0}} 201 }, 202 .sharpen = { 203 [QCIF_TO_QVGA] = { .quality = SHARPEN_ON }, 204 [QVGA_TO_VGA] = { .quality = SHARPEN_ON }, 205 [VGA_TO_SD] = { .quality = SHARPEN_ON }, 206 [SD_TO_720P] = { .quality = SHARPEN_ON }, 207 [HD720P_TO_1080P] = { .quality = SHARPEN_ON } 208 } 209 } 210 }; 211 212 static void vsp_VPP_DestroyContext(object_context_p obj_context); 213 static VAStatus vsp_set_pipeline(context_VPP_p ctx); 214 static VAStatus vsp_set_filter_param(context_VPP_p ctx); 215 static VAStatus vsp__VPP_check_legal_picture(object_context_p obj_context, object_config_p obj_config); 216 static int check_resolution(int width, int height); 217 static int check_vpp_strength(int value); 218 219 static void vsp_VPP_QueryConfigAttributes( 220 VAProfile __maybe_unused profile, 221 VAEntrypoint __maybe_unused entrypoint, 222 VAConfigAttrib __maybe_unused *attrib_list, 223 int __maybe_unused num_attribs) 224 { 225 /* No VPP specific attributes */ 226 return; 227 } 228 229 static VAStatus vsp_VPP_ValidateConfig( 230 object_config_p obj_config) 231 { 232 int i; 233 /* Check all attributes */ 234 for (i = 0; i < obj_config->attrib_count; i++) { 235 switch (obj_config->attrib_list[i].type) { 236 case VAConfigAttribRTFormat: 237 /* Ignore */ 238 break; 239 240 default: 241 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 242 } 243 } 244 245 return VA_STATUS_SUCCESS; 246 } 247 248 static VAStatus vsp__VPP_check_legal_picture(object_context_p obj_context, object_config_p obj_config) 249 { 250 VAStatus vaStatus = VA_STATUS_SUCCESS; 251 252 if (NULL == obj_context) { 253 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; 254 DEBUG_FAILURE; 255 return vaStatus; 256 } 257 258 if (NULL == obj_config) { 259 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG; 260 DEBUG_FAILURE; 261 return vaStatus; 262 } 263 264 return vaStatus; 265 } 266 267 static VAStatus vsp_VPP_CreateContext( 268 object_context_p obj_context, 269 object_config_p obj_config) 270 { 271 VAStatus vaStatus = VA_STATUS_SUCCESS; 272 context_VPP_p ctx; 273 int i; 274 275 /* Validate flag */ 276 /* Validate picture dimensions */ 277 vaStatus = vsp__VPP_check_legal_picture(obj_context, obj_config); 278 if (VA_STATUS_SUCCESS != vaStatus) { 279 DEBUG_FAILURE; 280 return vaStatus; 281 } 282 283 ctx = (context_VPP_p) calloc(1, sizeof(struct context_VPP_s)); 284 if (NULL == ctx) { 285 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 286 DEBUG_FAILURE; 287 return vaStatus; 288 } 289 290 ctx->filters = NULL; 291 ctx->num_filters = 0; 292 293 ctx->frc_buf = NULL; 294 295 /* set size */ 296 ctx->param_sz = 0; 297 ctx->pic_param_sz = ALIGN_TO_128(sizeof(struct VssProcPictureParameterBuffer)); 298 ctx->param_sz += ctx->pic_param_sz; 299 ctx->end_param_sz = ALIGN_TO_128(sizeof(struct VssProcPictureParameterBuffer)); 300 ctx->param_sz += ctx->end_param_sz; 301 302 ctx->pipeline_param_sz = ALIGN_TO_128(sizeof(struct VssProcPipelineParameterBuffer)); 303 ctx->param_sz += ctx->pipeline_param_sz; 304 ctx->denoise_param_sz = ALIGN_TO_128(sizeof(struct VssProcDenoiseParameterBuffer)); 305 ctx->param_sz += ctx->denoise_param_sz; 306 ctx->enhancer_param_sz = ALIGN_TO_128(sizeof(struct VssProcColorEnhancementParameterBuffer)); 307 ctx->param_sz += ctx->enhancer_param_sz; 308 ctx->sharpen_param_sz = ALIGN_TO_128(sizeof(struct VssProcSharpenParameterBuffer)); 309 ctx->param_sz += ctx->sharpen_param_sz; 310 ctx->frc_param_sz = ALIGN_TO_128(sizeof(struct VssProcFrcParameterBuffer)); 311 ctx->param_sz += ctx->frc_param_sz; 312 ctx->compose_param_sz = ALIGN_TO_128(sizeof(struct VssWiDi_ComposeSequenceParameterBuffer)); 313 ctx->param_sz += ctx->compose_param_sz; 314 315 /* set offset */ 316 ctx->pic_param_offset = 0; 317 ctx->end_param_offset = ctx->pic_param_offset + ctx->pic_param_sz; 318 ctx->pipeline_param_offset = ctx->end_param_offset + ctx->end_param_sz; 319 ctx->denoise_param_offset = ctx->pipeline_param_offset + ctx->pipeline_param_sz; 320 ctx->enhancer_param_offset = ctx->denoise_param_offset + ctx->denoise_param_sz; 321 ctx->sharpen_param_offset = ctx->enhancer_param_offset + ctx->enhancer_param_sz; 322 ctx->frc_param_offset = ctx->sharpen_param_offset + ctx->sharpen_param_sz; 323 /* For composer, it'll start on 0 */ 324 ctx->compose_param_offset = 0; 325 326 /* create intermediate buffer */ 327 ctx->intermediate_buf = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s)); 328 if (NULL == ctx->intermediate_buf) { 329 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 330 DEBUG_FAILURE; 331 goto out; 332 } 333 vaStatus = psb_buffer_create(obj_context->driver_data, VSP_INTERMEDIATE_BUF_SIZE, psb_bt_vpu_only, ctx->intermediate_buf); 334 if (VA_STATUS_SUCCESS != vaStatus) { 335 goto out; 336 } 337 338 obj_context->format_data = (void*) ctx; 339 ctx->obj_context = obj_context; 340 341 for (i = 0; i < obj_config->attrib_count; ++i) { 342 if (VAConfigAttribRTFormat == obj_config->attrib_list[i].type) { 343 switch (obj_config->attrib_list[i].value) { 344 case VA_RT_FORMAT_YUV420: 345 ctx->format = VSP_NV12; 346 break; 347 case VA_RT_FORMAT_YUV422: 348 ctx->format = VSP_NV16; 349 default: 350 ctx->format = VSP_NV12; 351 break; 352 } 353 break; 354 } 355 } 356 357 bzero(&ctx->denoise_deblock_param, sizeof(ctx->denoise_deblock_param)); 358 bzero(&ctx->enhancer_param, sizeof(ctx->enhancer_param)); 359 bzero(&ctx->sharpen_param, sizeof(ctx->sharpen_param)); 360 361 return vaStatus; 362 out: 363 vsp_VPP_DestroyContext(obj_context); 364 365 if (ctx) { 366 if(ctx->intermediate_buf != NULL) 367 free(ctx->intermediate_buf); 368 free(ctx); 369 ctx = NULL; 370 } 371 372 return vaStatus; 373 } 374 375 static void vsp_VPP_DestroyContext( 376 object_context_p obj_context) 377 { 378 INIT_CONTEXT_VPP; 379 380 if (ctx->intermediate_buf) { 381 psb_buffer_destroy(ctx->intermediate_buf); 382 383 free(ctx->intermediate_buf); 384 ctx->intermediate_buf = NULL; 385 } 386 387 if (ctx->filters) { 388 free(ctx->filters); 389 ctx->num_filters = 0; 390 } 391 392 free(obj_context->format_data); 393 obj_context->format_data = NULL; 394 } 395 396 static VAStatus vsp__VPP_process_pipeline_param(context_VPP_p ctx, object_context_p obj_context, object_buffer_p obj_buffer) 397 { 398 VAStatus vaStatus = VA_STATUS_SUCCESS; 399 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf; 400 unsigned int i = 0; 401 VAProcPipelineParameterBuffer *pipeline_param = (VAProcPipelineParameterBuffer *) obj_buffer->buffer_data; 402 struct VssProcPictureParameterBuffer *cell_proc_picture_param = (struct VssProcPictureParameterBuffer *)cmdbuf->pic_param_p; 403 struct VssProcPictureParameterBuffer *cell_end_param = (struct VssProcPictureParameterBuffer *)cmdbuf->end_param_p; 404 VAProcFilterParameterBufferFrameRateConversion *frc_param; 405 object_surface_p input_surface = NULL; 406 object_surface_p cur_output_surf = NULL; 407 unsigned int rotation_angle = 0, vsp_rotation_angle = 0; 408 unsigned int tiled = 0, width = 0, height = 0, stride = 0; 409 unsigned char *src_addr, *dest_addr; 410 struct psb_surface_s *output_surface; 411 psb_surface_share_info_p input_share_info = NULL; 412 psb_surface_share_info_p output_share_info = NULL; 413 enum vsp_format format; 414 415 416 psb_driver_data_p driver_data = obj_context->driver_data; 417 418 if (pipeline_param->surface_region != NULL) { 419 drv_debug_msg(VIDEO_DEBUG_ERROR, "Cann't scale\n"); 420 vaStatus = VA_STATUS_ERROR_UNKNOWN; 421 goto out; 422 } 423 424 if (pipeline_param->output_region != NULL) { 425 drv_debug_msg(VIDEO_DEBUG_ERROR, "Cann't scale\n"); 426 vaStatus = VA_STATUS_ERROR_UNKNOWN; 427 goto out; 428 } 429 430 if (pipeline_param->output_background_color != 0) { 431 drv_debug_msg(VIDEO_DEBUG_ERROR, "Cann't support background color here\n"); 432 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 433 goto out; 434 } 435 436 if (pipeline_param->filters == NULL) { 437 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filter setting filters = %p\n", pipeline_param->filters); 438 vaStatus = VA_STATUS_ERROR_UNKNOWN; 439 goto out; 440 } 441 442 #if 0 443 /* for pass filter */ 444 if (pipeline_param->num_filters == 0 || pipeline_param->num_filters > VssProcPipelineMaxNumFilters) { 445 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filter number = %d\n", pipeline_param->num_filters); 446 vaStatus = VA_STATUS_ERROR_UNKNOWN; 447 goto out; 448 } 449 #endif 450 451 if (pipeline_param->forward_references == NULL) { 452 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid forward_refereces %p setting\n", pipeline_param->forward_references); 453 vaStatus = VA_STATUS_ERROR_UNKNOWN; 454 goto out; 455 } 456 457 /* should we check it? since the begining it's not VSP_FORWARD_REF_NUM */ 458 if (pipeline_param->num_forward_references != VSP_FORWARD_REF_NUM) { 459 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_forward_refereces %d setting, should be %d\n", pipeline_param->num_forward_references, VSP_FORWARD_REF_NUM); 460 vaStatus = VA_STATUS_ERROR_UNKNOWN; 461 goto out; 462 } 463 464 /* first picture, need to setup the VSP context */ 465 if (ctx->obj_context->frame_count == 0) 466 vsp_cmdbuf_vpp_context(cmdbuf, VssGenInitializeContext, CONTEXT_VPP_ID, VSP_APP_ID_FRC_VPP); 467 468 /* get the input surface */ 469 if (!(pipeline_param->pipeline_flags & VA_PIPELINE_FLAG_END)) { 470 input_surface = SURFACE(pipeline_param->surface); 471 if (input_surface == NULL) { 472 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid input surface %x\n", pipeline_param->surface); 473 vaStatus = VA_STATUS_ERROR_UNKNOWN; 474 goto out; 475 } 476 } else { 477 input_surface = NULL; 478 } 479 480 /* if it is the first pipeline command */ 481 if (pipeline_param->num_filters != ctx->num_filters || pipeline_param->num_filters == 0) { 482 if (ctx->num_filters != 0) { 483 drv_debug_msg(VIDEO_DEBUG_ERROR, "can not reset pipeline in the mid of post-processing or without create a new context\n"); 484 vaStatus = VA_STATUS_ERROR_UNKNOWN; 485 goto out; 486 } else { 487 /* save filters */ 488 ctx->num_filters = pipeline_param->num_filters; 489 if (ctx->num_filters == 0) { 490 ctx->filters = NULL; 491 } else { 492 ctx->filters = (VABufferID *) calloc(ctx->num_filters, sizeof(*ctx->filters)); 493 if (ctx->filters == NULL) { 494 drv_debug_msg(VIDEO_DEBUG_ERROR, "can not reset pipeline in the mid of post-processing or without create a new context\n"); 495 vaStatus = VA_STATUS_ERROR_UNKNOWN; 496 goto out; 497 } 498 memcpy(ctx->filters, pipeline_param->filters, ctx->num_filters * sizeof(*ctx->filters)); 499 } 500 501 /* set pipeline command to FW */ 502 vaStatus = vsp_set_pipeline(ctx); 503 if (vaStatus) { 504 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to set pipeline\n"); 505 goto out; 506 } 507 508 /* set filter parameter to FW, record frc parameter buffer */ 509 vaStatus = vsp_set_filter_param(ctx); 510 if (vaStatus) { 511 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to set filter parameter\n"); 512 goto out; 513 } 514 } 515 } else { 516 /* else ignore pipeline/filter setting */ 517 #if 0 518 /* FIXME: we can save these check for PnP */ 519 for (i = 0; i < pipeline_param->num_filters; i++) { 520 if (pipeline_param->filters[i] != ctx->filters[i]) { 521 drv_debug_msg(VIDEO_DEBUG_ERROR, "can not reset pipeline in the mid of post-processing or without create a new context\n"); 522 vaStatus = VA_STATUS_ERROR_UNKNOWN; 523 goto out; 524 } 525 } 526 #endif 527 } 528 529 /* fill picture command to FW */ 530 if (ctx->frc_buf != NULL) 531 frc_param = (VAProcFilterParameterBufferFrameRateConversion *)ctx->frc_buf->buffer_data; 532 else 533 frc_param = NULL; 534 535 /* end picture command */ 536 if (pipeline_param->pipeline_flags & VA_PIPELINE_FLAG_END) { 537 cell_end_param->num_input_pictures = 0; 538 cell_end_param->num_output_pictures = 0; 539 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VPP_ID, &cmdbuf->param_mem, VssProcPictureCommand, 540 ctx->end_param_offset, sizeof(struct VssProcPictureParameterBuffer)); 541 /* Destory the VSP context */ 542 vsp_cmdbuf_vpp_context(cmdbuf, VssGenDestroyContext, CONTEXT_VPP_ID, 0); 543 goto out; 544 } 545 546 #ifdef PSBVIDEO_VPP_TILING 547 /* get the tiling flag*/ 548 tiled = GET_SURFACE_INFO_tiling(input_surface->psb_surface); 549 #endif 550 551 /* get the surface format info */ 552 switch (input_surface->psb_surface->extra_info[8]) { 553 case VA_FOURCC_YV12: 554 format = VSP_YV12; 555 break; 556 case VA_FOURCC_NV12: 557 format = VSP_NV12; 558 break; 559 default: 560 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 561 drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12 and YV12 format!\n"); 562 goto out; 563 } 564 565 /* According to VIED's design, the width must be multiple of 16 */ 566 width = ALIGN_TO_16(input_surface->width); 567 if (width > input_surface->psb_surface->stride) 568 width = input_surface->psb_surface->stride; 569 570 /* get the input share info */ 571 input_share_info = input_surface->share_info; 572 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s The input surface %p share info %p\n", __func__, input_surface,input_surface->share_info); 573 574 /* Setup input surface */ 575 cell_proc_picture_param->num_input_pictures = 1; 576 cell_proc_picture_param->input_picture[0].surface_id = pipeline_param->surface; 577 vsp_cmdbuf_reloc_pic_param(&(cell_proc_picture_param->input_picture[0].base), ctx->pic_param_offset, &(input_surface->psb_surface->buf), 578 cmdbuf->param_mem_loc, cell_proc_picture_param); 579 cell_proc_picture_param->input_picture[0].height = input_surface->height; 580 cell_proc_picture_param->input_picture[0].width = width; 581 cell_proc_picture_param->input_picture[0].irq = 0; 582 cell_proc_picture_param->input_picture[0].stride = input_surface->psb_surface->stride; 583 cell_proc_picture_param->input_picture[0].format = format; 584 cell_proc_picture_param->input_picture[0].tiled = tiled; 585 cell_proc_picture_param->input_picture[0].rot_angle = 0; 586 587 /* Setup output surfaces */ 588 if (frc_param == NULL) 589 cell_proc_picture_param->num_output_pictures = 1; 590 else 591 cell_proc_picture_param->num_output_pictures = frc_param->num_output_frames + 1; 592 593 for (i = 0; i < cell_proc_picture_param->num_output_pictures; ++i) { 594 if (i == 0) { 595 cur_output_surf = ctx->obj_context->current_render_target; 596 597 #ifdef PSBVIDEO_MRFL_VPP_ROTATE 598 /* The rotation info is saved in the first frame */ 599 rotation_angle = GET_SURFACE_INFO_rotate(cur_output_surf->psb_surface); 600 switch (rotation_angle) { 601 case VA_ROTATION_90: 602 vsp_rotation_angle = VSP_ROTATION_90; 603 break; 604 case VA_ROTATION_180: 605 vsp_rotation_angle = VSP_ROTATION_180; 606 break; 607 case VA_ROTATION_270: 608 vsp_rotation_angle = VSP_ROTATION_270; 609 break; 610 default: 611 vsp_rotation_angle = VSP_ROTATION_NONE; 612 } 613 #endif 614 } else { 615 if (frc_param == NULL) { 616 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid output surface numbers %x\n", 617 cell_proc_picture_param->num_output_pictures); 618 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 619 goto out; 620 } 621 622 cur_output_surf = SURFACE(frc_param->output_frames[i-1]); 623 if (cur_output_surf == NULL) { 624 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid input surface %x\n", frc_param->output_frames[i-1]); 625 vaStatus = VA_STATUS_ERROR_UNKNOWN; 626 goto out; 627 } 628 629 #ifdef PSBVIDEO_MRFL_VPP_ROTATE 630 /* VPP rotation is just for 1080P */ 631 if (tiled && rotation_angle != VA_ROTATION_NONE) { 632 if (VA_STATUS_SUCCESS != psb_CreateRotateSurface(obj_context, cur_output_surf, rotation_angle)) { 633 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc rotation surface!\n"); 634 vaStatus = VA_STATUS_ERROR_UNKNOWN; 635 goto out; 636 } 637 } 638 #endif 639 } 640 641 if (tiled && rotation_angle != VA_ROTATION_NONE) { 642 #ifdef PSBVIDEO_MRFL_VPP_ROTATE 643 /* For 90d and 270d, we need to alloc rotation buff and 644 * copy the 0d data from input to output 645 */ 646 psb_buffer_map(&(input_surface->psb_surface->buf), &src_addr); 647 psb_buffer_map(&(cur_output_surf->psb_surface->buf), &dest_addr); 648 memcpy(dest_addr, src_addr, cur_output_surf->psb_surface->size); 649 psb_buffer_unmap(&(cur_output_surf->psb_surface->buf)); 650 psb_buffer_unmap(&(input_surface->psb_surface->buf)); 651 652 output_surface = cur_output_surf->out_loop_surface; 653 654 /* According to VIED's design, the width must be multiple of 16 */ 655 width = ALIGN_TO_16(cur_output_surf->height_origin); 656 if (width > cur_output_surf->out_loop_surface->stride) 657 width = cur_output_surf->out_loop_surface->stride; 658 height = cur_output_surf->width; 659 stride = cur_output_surf->out_loop_surface->stride; 660 #endif 661 } else { 662 output_surface = cur_output_surf->psb_surface; 663 664 /* According to VIED's design, the width must be multiple of 16 */ 665 width = ALIGN_TO_16(cur_output_surf->width); 666 if (width > cur_output_surf->psb_surface->stride) 667 width = cur_output_surf->psb_surface->stride; 668 height = cur_output_surf->height; 669 stride = cur_output_surf->psb_surface->stride; 670 671 /* Check the rotate bit */ 672 if (pipeline_param->rotation_state == VA_ROTATION_90) 673 vsp_rotation_angle = VSP_ROTATION_90; 674 else if (pipeline_param->rotation_state == VA_ROTATION_180) 675 vsp_rotation_angle = VSP_ROTATION_180; 676 else if (pipeline_param->rotation_state == VA_ROTATION_270) 677 vsp_rotation_angle = VSP_ROTATION_270; 678 else 679 vsp_rotation_angle = VSP_ROTATION_NONE; 680 } 681 682 cell_proc_picture_param->output_picture[i].surface_id = wsbmKBufHandle(wsbmKBuf(output_surface->buf.drm_buf)); 683 684 vsp_cmdbuf_reloc_pic_param(&(cell_proc_picture_param->output_picture[i].base), 685 ctx->pic_param_offset, &(output_surface->buf), 686 cmdbuf->param_mem_loc, cell_proc_picture_param); 687 cell_proc_picture_param->output_picture[i].height = height; 688 cell_proc_picture_param->output_picture[i].width = width; 689 cell_proc_picture_param->output_picture[i].stride = stride; 690 cell_proc_picture_param->output_picture[i].irq = 1; 691 cell_proc_picture_param->output_picture[i].format = format; 692 cell_proc_picture_param->output_picture[i].rot_angle = vsp_rotation_angle; 693 cell_proc_picture_param->output_picture[i].tiled = tiled; 694 695 /* copy the input share info to output */ 696 output_share_info = cur_output_surf->share_info; 697 if (input_share_info != NULL && output_share_info != NULL) { 698 output_share_info->native_window = input_share_info->native_window; 699 output_share_info->force_output_method = input_share_info->force_output_method; 700 output_share_info->surface_protected = input_share_info->surface_protected; 701 output_share_info->bob_deinterlace = input_share_info->bob_deinterlace; 702 703 output_share_info->crop_width = input_share_info->crop_width; 704 output_share_info->crop_height = input_share_info->crop_height; 705 output_share_info->coded_width = input_share_info->coded_width; 706 output_share_info->coded_height = input_share_info->coded_height; 707 drv_debug_msg(VIDEO_DEBUG_GENERAL, "The input/output wxh %dx%d\n",input_share_info->width,input_share_info->height); 708 } else { 709 drv_debug_msg(VIDEO_DEBUG_WARNING, "The input/output share_info is NULL!!\n"); 710 } 711 } 712 713 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VPP_ID, &cmdbuf->param_mem, VssProcPictureCommand, 714 ctx->pic_param_offset, sizeof(struct VssProcPictureParameterBuffer)); 715 716 vsp_cmdbuf_fence_pic_param(cmdbuf, wsbmKBufHandle(wsbmKBuf(cmdbuf->param_mem.drm_buf))); 717 718 #if 0 719 /* handle reference frames, ignore backward reference */ 720 for (i = 0; i < pipeline_param->num_forward_references; ++i) { 721 cur_output_surf = SURFACE(pipeline_param->forward_references[i]); 722 if (cur_output_surf == NULL) 723 continue; 724 if (vsp_cmdbuf_buffer_ref(cmdbuf, &cur_output_surf->psb_surface->buf) < 0) { 725 drv_debug_msg(VIDEO_DEBUG_ERROR, "vsp_cmdbuf_buffer_ref() failed\n"); 726 vaStatus = VA_STATUS_ERROR_UNKNOWN; 727 goto out; 728 } 729 } 730 #endif 731 out: 732 free(pipeline_param); 733 obj_buffer->buffer_data = NULL; 734 obj_buffer->size = 0; 735 736 return vaStatus; 737 } 738 739 static VAStatus vsp_VPP_RenderPicture( 740 object_context_p obj_context, 741 object_buffer_p *buffers, 742 int num_buffers) 743 { 744 int i; 745 INIT_CONTEXT_VPP; 746 VAProcPipelineParameterBuffer *pipeline_param = NULL; 747 VAStatus vaStatus = VA_STATUS_SUCCESS; 748 749 for (i = 0; i < num_buffers; i++) { 750 object_buffer_p obj_buffer = buffers[i]; 751 pipeline_param = (VAProcPipelineParameterBuffer *) obj_buffer->buffer_data; 752 753 switch (obj_buffer->type) { 754 case VAProcPipelineParameterBufferType: 755 if (!pipeline_param->num_filters && pipeline_param->blend_state) 756 /* For Security Composer */ 757 vaStatus = vsp_compose_process_pipeline_param(ctx, obj_context, obj_buffer); 758 else 759 /* For VPP/FRC */ 760 vaStatus = vsp__VPP_process_pipeline_param(ctx, obj_context, obj_buffer); 761 DEBUG_FAILURE; 762 break; 763 default: 764 vaStatus = VA_STATUS_ERROR_UNKNOWN; 765 DEBUG_FAILURE; 766 } 767 if (vaStatus != VA_STATUS_SUCCESS) { 768 break; 769 } 770 } 771 772 return vaStatus; 773 } 774 775 static VAStatus vsp_VPP_BeginPicture( 776 object_context_p obj_context) 777 { 778 int ret; 779 VAStatus vaStatus = VA_STATUS_SUCCESS; 780 INIT_CONTEXT_VPP; 781 vsp_cmdbuf_p cmdbuf; 782 783 /* Initialise the command buffer */ 784 ret = vsp_context_get_next_cmdbuf(ctx->obj_context); 785 if (ret) { 786 drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n"); 787 vaStatus = VA_STATUS_ERROR_UNKNOWN; 788 return vaStatus; 789 } 790 791 cmdbuf = obj_context->vsp_cmdbuf; 792 793 /* map param mem */ 794 vaStatus = psb_buffer_map(&cmdbuf->param_mem, &cmdbuf->param_mem_p); 795 if (vaStatus) { 796 return vaStatus; 797 } 798 799 cmdbuf->pic_param_p = cmdbuf->param_mem_p + ctx->pic_param_offset; 800 cmdbuf->end_param_p = cmdbuf->param_mem_p + ctx->end_param_offset; 801 cmdbuf->pipeline_param_p = cmdbuf->param_mem_p + ctx->pipeline_param_offset; 802 cmdbuf->denoise_param_p = cmdbuf->param_mem_p + ctx->denoise_param_offset; 803 cmdbuf->enhancer_param_p = cmdbuf->param_mem_p + ctx->enhancer_param_offset; 804 cmdbuf->sharpen_param_p = cmdbuf->param_mem_p + ctx->sharpen_param_offset; 805 cmdbuf->frc_param_p = cmdbuf->param_mem_p + ctx->frc_param_offset; 806 cmdbuf->compose_param_p = cmdbuf->param_mem_p + ctx->compose_param_offset; 807 808 return VA_STATUS_SUCCESS; 809 } 810 811 static VAStatus vsp_VPP_EndPicture( 812 object_context_p obj_context) 813 { 814 INIT_CONTEXT_VPP; 815 psb_driver_data_p driver_data = obj_context->driver_data; 816 vsp_cmdbuf_p cmdbuf = obj_context->vsp_cmdbuf; 817 818 if(cmdbuf->param_mem_p != NULL) { 819 psb_buffer_unmap(&cmdbuf->param_mem); 820 cmdbuf->param_mem_p = NULL; 821 cmdbuf->pic_param_p = NULL; 822 cmdbuf->end_param_p = NULL; 823 cmdbuf->pipeline_param_p = NULL; 824 cmdbuf->denoise_param_p = NULL; 825 cmdbuf->enhancer_param_p = NULL; 826 cmdbuf->sharpen_param_p = NULL; 827 cmdbuf->frc_param_p = NULL; 828 cmdbuf->compose_param_p = NULL; 829 } 830 831 if (vsp_context_flush_cmdbuf(ctx->obj_context)) { 832 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VPP: flush deblock cmdbuf error\n"); 833 return VA_STATUS_ERROR_UNKNOWN; 834 } 835 836 return VA_STATUS_SUCCESS; 837 } 838 839 struct format_vtable_s vsp_VPP_vtable = { 840 queryConfigAttributes: 841 vsp_VPP_QueryConfigAttributes, 842 validateConfig: 843 vsp_VPP_ValidateConfig, 844 createContext: 845 vsp_VPP_CreateContext, 846 destroyContext: 847 vsp_VPP_DestroyContext, 848 beginPicture: 849 vsp_VPP_BeginPicture, 850 renderPicture: 851 vsp_VPP_RenderPicture, 852 endPicture: 853 vsp_VPP_EndPicture 854 }; 855 856 VAStatus vsp_QueryVideoProcFilters( 857 VADriverContextP ctx, 858 VAContextID context, 859 VAProcFilterType *filters, 860 unsigned int *num_filters 861 ) 862 { 863 INIT_DRIVER_DATA; 864 VAStatus vaStatus = VA_STATUS_SUCCESS; 865 object_context_p obj_context; 866 object_config_p obj_config; 867 VAEntrypoint tmp; 868 int count; 869 870 /* check if ctx is right */ 871 obj_context = CONTEXT(context); 872 if (NULL == obj_context) { 873 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n"); 874 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; 875 goto err; 876 } 877 878 obj_config = CONFIG(obj_context->config_id); 879 if (NULL == obj_config) { 880 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n"); 881 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG; 882 goto err; 883 } 884 885 tmp = obj_config->entrypoint; 886 if (tmp != VAEntrypointVideoProc) { 887 drv_debug_msg(VIDEO_DEBUG_ERROR, "current entrypoint is %d, not VAEntrypointVideoProc\n", tmp); 888 vaStatus = VA_STATUS_ERROR_UNKNOWN; 889 goto err; 890 } 891 892 /* check if filters and num_filters is valid */ 893 if (NULL == num_filters || NULL == filters) { 894 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filters, filters); 895 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 896 goto err; 897 } 898 899 /* check if the filter array size is valid */ 900 if (*num_filters < VSP_SUPPORTED_FILTERS_NUM) { 901 drv_debug_msg(VIDEO_DEBUG_ERROR, "The filters array size(%d) is NOT valid! Supported filters num is %d\n", 902 *num_filters, VSP_SUPPORTED_FILTERS_NUM); 903 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 904 *num_filters = VSP_SUPPORTED_FILTERS_NUM; 905 goto err; 906 } 907 908 /* check if current HW support Video proc */ 909 if (IS_MRFL(driver_data)) { 910 count = 0; 911 filters[count++] = VAProcFilterDeblocking; 912 filters[count++] = VAProcFilterNoiseReduction; 913 filters[count++] = VAProcFilterSharpening; 914 filters[count++] = VAProcFilterColorBalance; 915 filters[count++] = VAProcFilterFrameRateConversion; 916 *num_filters = count; 917 } else { 918 *num_filters = 0; 919 } 920 err: 921 return vaStatus; 922 } 923 924 VAStatus vsp_QueryVideoProcFilterCaps( 925 VADriverContextP ctx, 926 VAContextID context, 927 VAProcFilterType type, 928 void *filter_caps, 929 unsigned int *num_filter_caps 930 ) 931 { 932 INIT_DRIVER_DATA; 933 VAStatus vaStatus = VA_STATUS_SUCCESS; 934 object_context_p obj_context; 935 object_config_p obj_config; 936 VAEntrypoint tmp; 937 VAProcFilterCap *denoise_cap, *deblock_cap; 938 VAProcFilterCap *sharpen_cap; 939 VAProcFilterCapColorBalance *color_balance_cap; 940 VAProcFilterCap *frc_cap; 941 942 /* check if context is right */ 943 obj_context = CONTEXT(context); 944 if (NULL == obj_context) { 945 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n"); 946 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; 947 goto err; 948 } 949 950 obj_config = CONFIG(obj_context->config_id); 951 if (NULL == obj_config) { 952 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n"); 953 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG; 954 goto err; 955 } 956 957 /* check if filter_caps and num_filter_caps is right */ 958 if (NULL == num_filter_caps || NULL == filter_caps){ 959 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filter_caps, filter_caps); 960 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 961 goto err; 962 } 963 964 if (*num_filter_caps < 1) { 965 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters == %d (> 1)\n", *num_filter_caps); 966 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 967 goto err; 968 } 969 970 /* check if curent HW support and return corresponding caps */ 971 if (IS_MRFL(driver_data)) { 972 /* FIXME: we should use a constant table to return caps */ 973 switch (type) { 974 case VAProcFilterNoiseReduction: 975 denoise_cap = filter_caps; 976 denoise_cap->range.min_value = MIN_VPP_PARAM; 977 denoise_cap->range.max_value = MAX_VPP_PARAM; 978 denoise_cap->range.default_value = MIN_VPP_PARAM; 979 denoise_cap->range.step = STEP_VPP_PARAM; 980 *num_filter_caps = 1; 981 break; 982 case VAProcFilterDeblocking: 983 deblock_cap = filter_caps; 984 deblock_cap->range.min_value = MIN_VPP_PARAM; 985 deblock_cap->range.max_value = MAX_VPP_PARAM; 986 deblock_cap->range.default_value = MIN_VPP_PARAM; 987 deblock_cap->range.step = STEP_VPP_PARAM; 988 *num_filter_caps = 1; 989 break; 990 991 case VAProcFilterSharpening: 992 sharpen_cap = filter_caps; 993 sharpen_cap->range.min_value = MIN_VPP_PARAM; 994 sharpen_cap->range.max_value = MAX_VPP_PARAM; 995 sharpen_cap->range.default_value = MIN_VPP_PARAM; 996 sharpen_cap->range.step = STEP_VPP_PARAM; 997 *num_filter_caps = 1; 998 break; 999 1000 case VAProcFilterColorBalance: 1001 if (*num_filter_caps < VSP_COLOR_ENHANCE_FEATURES) { 1002 drv_debug_msg(VIDEO_DEBUG_ERROR, "filter cap num is should big than %d(%d)\n", 1003 VSP_COLOR_ENHANCE_FEATURES, *num_filter_caps); 1004 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 1005 *num_filter_caps = VSP_COLOR_ENHANCE_FEATURES; 1006 goto err; 1007 } 1008 color_balance_cap = filter_caps; 1009 color_balance_cap->type = VAProcColorBalanceAutoSaturation; 1010 color_balance_cap->range.min_value = MIN_VPP_AUTO_PARAM; 1011 color_balance_cap->range.max_value = MAX_VPP_AUTO_PARAM; 1012 color_balance_cap->range.default_value = MIN_VPP_AUTO_PARAM; 1013 color_balance_cap->range.step = STEP_VPP_AUTO_PARAM; 1014 1015 color_balance_cap++; 1016 color_balance_cap->type = VAProcColorBalanceAutoBrightness; 1017 color_balance_cap->range.min_value = MIN_VPP_AUTO_PARAM; 1018 color_balance_cap->range.max_value = MAX_VPP_AUTO_PARAM; 1019 color_balance_cap->range.default_value = MIN_VPP_AUTO_PARAM; 1020 color_balance_cap->range.step = STEP_VPP_AUTO_PARAM; 1021 1022 *num_filter_caps = 2; 1023 break; 1024 1025 case VAProcFilterFrameRateConversion: 1026 frc_cap = filter_caps; 1027 frc_cap->range.min_value = 2; 1028 frc_cap->range.max_value = 4; 1029 frc_cap->range.default_value = 2; 1030 /* FIXME: it's a set, step is helpless */ 1031 frc_cap->range.step = 0.5; 1032 *num_filter_caps = 1; 1033 break; 1034 1035 default: 1036 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide filter type %d\n", type); 1037 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER; 1038 *num_filter_caps = 0; 1039 goto err; 1040 } 1041 } else { 1042 *num_filter_caps = 0; 1043 } 1044 1045 err: 1046 return vaStatus; 1047 } 1048 1049 VAStatus vsp_QueryVideoProcPipelineCaps( 1050 VADriverContextP ctx, 1051 VAContextID context, 1052 VABufferID *filters, 1053 unsigned int num_filters, 1054 VAProcPipelineCaps *pipeline_caps 1055 ) 1056 { 1057 INIT_DRIVER_DATA; 1058 VAStatus vaStatus = VA_STATUS_SUCCESS; 1059 object_context_p obj_context; 1060 object_config_p obj_config; 1061 VAEntrypoint tmp; 1062 unsigned int i, j; 1063 VAProcFilterParameterBuffer *deblock, *denoise, *sharpen; 1064 VAProcFilterParameterBufferFrameRateConversion *frc; 1065 VAProcFilterParameterBufferColorBalance *balance; 1066 VAProcFilterParameterBufferBase *base; 1067 object_buffer_p buf; 1068 uint32_t enabled_brightness, enabled_saturation; 1069 float ratio; 1070 int res_set; 1071 int strength; 1072 context_VPP_p vpp_ctx; 1073 int combination_check; 1074 1075 /* check if ctx is right */ 1076 obj_context = CONTEXT(context); 1077 if (NULL == obj_context) { 1078 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n"); 1079 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; 1080 goto err; 1081 } 1082 1083 vpp_ctx = (context_VPP_p) obj_context->format_data; 1084 1085 obj_config = CONFIG(obj_context->config_id); 1086 if (NULL == obj_config) { 1087 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n"); 1088 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG; 1089 goto err; 1090 } 1091 1092 /* Don't check the filter number. 1093 * According to VIED's design, without any filter, HW will just copy input data 1094 */ 1095 #if 0 1096 if (num_filters == 0) { 1097 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_filters %d\n", num_filters); 1098 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 1099 goto err; 1100 } 1101 #endif 1102 if (NULL == filters || pipeline_caps == NULL) { 1103 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filters %p or pipeline_caps %p\n", filters, pipeline_caps); 1104 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 1105 goto err; 1106 } 1107 1108 /* base on HW capability check the filters and return pipeline caps */ 1109 if (IS_MRFL(driver_data)) { 1110 pipeline_caps->pipeline_flags = 0; 1111 pipeline_caps->filter_flags = 0; 1112 pipeline_caps->num_forward_references = VSP_FORWARD_REF_NUM; 1113 pipeline_caps->num_backward_references = 0; 1114 1115 /* check the input color standard */ 1116 if (pipeline_caps->input_color_standards == NULL){ 1117 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid input color standard array!\n"); 1118 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 1119 goto err; 1120 } 1121 if (pipeline_caps->num_input_color_standards < COLOR_STANDARDS_NUM) { 1122 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_input_color_standards %d\n", pipeline_caps->num_input_color_standards); 1123 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 1124 pipeline_caps->num_input_color_standards = COLOR_STANDARDS_NUM; 1125 goto err; 1126 } 1127 pipeline_caps->input_color_standards[0] = VAProcColorStandardNone; 1128 pipeline_caps->num_input_color_standards = COLOR_STANDARDS_NUM; 1129 1130 /* check the output color standard */ 1131 if (pipeline_caps->output_color_standards == NULL){ 1132 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid output color standard array!\n"); 1133 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 1134 goto err; 1135 } 1136 if (pipeline_caps->num_output_color_standards < COLOR_STANDARDS_NUM) { 1137 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_output_color_standards %d\n", pipeline_caps->num_output_color_standards); 1138 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 1139 pipeline_caps->num_output_color_standards = COLOR_STANDARDS_NUM; 1140 goto err; 1141 } 1142 pipeline_caps->output_color_standards[0] = VAProcColorStandardNone; 1143 pipeline_caps->num_output_color_standards = COLOR_STANDARDS_NUM; 1144 1145 /* check the resolution */ 1146 res_set = check_resolution(obj_context->picture_width, 1147 obj_context->picture_height); 1148 if (res_set == NOT_SUPPORTED_RESOLUTION) { 1149 vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; 1150 goto err; 1151 } 1152 1153 /* Blend type */ 1154 pipeline_caps->blend_flags = VA_BLEND_PREMULTIPLIED_ALPHA; 1155 1156 if (getenv("VSP_PIPELINE_CHECK") != NULL) 1157 combination_check = 1; 1158 else 1159 combination_check = 0; 1160 1161 /* FIXME: should check filter value settings here */ 1162 for (i = 0; i < num_filters; ++i) { 1163 /* find buffer */ 1164 buf = BUFFER(*(filters + i)); 1165 if (!buf) { 1166 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1167 goto err; 1168 } 1169 1170 base = (VAProcFilterParameterBufferBase *)buf->buffer_data; 1171 /* check filter buffer setting */ 1172 switch (base->type) { 1173 case VAProcFilterDeblocking: 1174 deblock = (VAProcFilterParameterBuffer *)base; 1175 1176 if (combination_check && 1177 vpp_chain_caps[res_set].deblock_enabled != FILTER_ENABLED) { 1178 drv_debug_msg(VIDEO_DEBUG_ERROR, "The deblock is DISABLE for %d format\n", res_set); 1179 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN; 1180 goto err; 1181 } else { 1182 /* check if the value is right */ 1183 strength = check_vpp_strength(deblock->value); 1184 if (strength == INVALID_STRENGTH) { 1185 vaStatus = VA_STATUS_ERROR_INVALID_VALUE; 1186 goto err; 1187 } 1188 memcpy(&vpp_ctx->denoise_deblock_param, 1189 &vpp_strength[strength].denoise_deblock[res_set], 1190 sizeof(vpp_ctx->denoise_deblock_param)); 1191 } 1192 break; 1193 1194 case VAProcFilterNoiseReduction: 1195 denoise = (VAProcFilterParameterBuffer *)base; 1196 1197 if (combination_check && 1198 vpp_chain_caps[res_set].denoise_enabled != FILTER_ENABLED) { 1199 drv_debug_msg(VIDEO_DEBUG_ERROR, "The denoise is DISABLE for %d format\n", res_set); 1200 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN; 1201 goto err; 1202 } else { 1203 strength = check_vpp_strength(denoise->value); 1204 if (strength == INVALID_STRENGTH) { 1205 vaStatus = VA_STATUS_ERROR_INVALID_VALUE; 1206 goto err; 1207 } 1208 memcpy(&vpp_ctx->denoise_deblock_param, 1209 &vpp_strength[strength].denoise_deblock[res_set], 1210 sizeof(vpp_ctx->denoise_deblock_param)); 1211 } 1212 break; 1213 1214 case VAProcFilterSharpening: 1215 sharpen = (VAProcFilterParameterBuffer *)base; 1216 1217 if (combination_check && 1218 vpp_chain_caps[res_set].sharpen_enabled != FILTER_ENABLED) { 1219 drv_debug_msg(VIDEO_DEBUG_ERROR, "The sharpen is DISABLE for %d format\n", res_set); 1220 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN; 1221 goto err; 1222 } else { 1223 strength = check_vpp_strength(sharpen->value); 1224 if (strength == INVALID_STRENGTH) { 1225 vaStatus = VA_STATUS_ERROR_INVALID_VALUE; 1226 goto err; 1227 } 1228 memcpy(&vpp_ctx->sharpen_param, 1229 &vpp_strength[strength].sharpen[res_set], 1230 sizeof(vpp_ctx->sharpen_param)); 1231 } 1232 break; 1233 1234 case VAProcFilterColorBalance: 1235 balance = (VAProcFilterParameterBufferColorBalance *)base; 1236 1237 enabled_brightness = 0; 1238 enabled_saturation = 0; 1239 1240 for (j = 0; j < buf->num_elements; ++j, ++balance) { 1241 if (balance->attrib == VAProcColorBalanceAutoSaturation && 1242 balance->value == MAX_VPP_AUTO_PARAM) { 1243 enabled_saturation = 1; 1244 } else if (balance->attrib == VAProcColorBalanceAutoBrightness && 1245 balance->value == MAX_VPP_AUTO_PARAM) { 1246 enabled_brightness = 1; 1247 } else { 1248 drv_debug_msg(VIDEO_DEBUG_ERROR, "The color_banlance do NOT support this attrib %d\n", 1249 balance->attrib); 1250 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER; 1251 goto err; 1252 } 1253 } 1254 1255 /* check filter chain */ 1256 if (combination_check && 1257 vpp_chain_caps[res_set].color_balance_enabled != FILTER_ENABLED) { 1258 drv_debug_msg(VIDEO_DEBUG_ERROR, "The color_balance is DISABLE for %d format\n", res_set); 1259 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN; 1260 goto err; 1261 } else { 1262 strength = MEDIUM_STRENGTH; 1263 memcpy(&vpp_ctx->enhancer_param, 1264 &vpp_strength[strength].enhancer[res_set], 1265 sizeof(vpp_ctx->enhancer_param)); 1266 if (!enabled_saturation) 1267 vpp_ctx->enhancer_param.chroma_amm = 0; 1268 if (!enabled_brightness) 1269 vpp_ctx->enhancer_param.luma_amm = 0; 1270 } 1271 1272 break; 1273 1274 case VAProcFilterFrameRateConversion: 1275 frc = (VAProcFilterParameterBufferFrameRateConversion *)base; 1276 1277 /* check frame rate */ 1278 ratio = frc->output_fps / (float)frc->input_fps; 1279 1280 if (!((ratio == 2 || ratio == 2.5 || ratio == 4) && frc->output_fps <= 60)) { 1281 drv_debug_msg(VIDEO_DEBUG_ERROR, "The FRC do NOT support the ration(%f) and fps(%d)\n", 1282 ratio, frc->output_fps); 1283 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER; 1284 goto err; 1285 } 1286 1287 /* check the chain */ 1288 if (combination_check && 1289 vpp_chain_caps[res_set].frc_enabled != FILTER_ENABLED) { 1290 drv_debug_msg(VIDEO_DEBUG_ERROR, "The FRC is DISABLE for %d format\n", res_set); 1291 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN; 1292 goto err; 1293 } 1294 1295 break; 1296 default: 1297 drv_debug_msg(VIDEO_DEBUG_ERROR, "Do NOT support the filter type %d\n", base->type); 1298 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1299 goto err; 1300 } 1301 } 1302 } else { 1303 drv_debug_msg(VIDEO_DEBUG_ERROR, "no HW support\n"); 1304 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1305 goto err; 1306 } 1307 err: 1308 return vaStatus; 1309 } 1310 1311 static VAStatus vsp_set_pipeline(context_VPP_p ctx) 1312 { 1313 VAStatus vaStatus = VA_STATUS_SUCCESS; 1314 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf; 1315 struct VssProcPipelineParameterBuffer *cell_pipeline_param = (struct VssProcPipelineParameterBuffer *)cmdbuf->pipeline_param_p; 1316 unsigned int i, j, filter_count, check_filter = 0; 1317 VAProcFilterParameterBufferBase *cur_param; 1318 enum VssProcFilterType tmp; 1319 psb_driver_data_p driver_data = ctx->obj_context->driver_data; 1320 1321 /* set intermediate buffer */ 1322 cell_pipeline_param->intermediate_buffer_size = VSP_INTERMEDIATE_BUF_SIZE; 1323 cell_pipeline_param->intermediate_buffer_base = wsbmBOOffsetHint(ctx->intermediate_buf->drm_buf); 1324 1325 /* init pipeline cmd */ 1326 for (i = 0; i < VssProcPipelineMaxNumFilters; ++i) 1327 cell_pipeline_param->filter_pipeline[i] = -1; 1328 cell_pipeline_param->num_filters = 0; 1329 1330 filter_count = 0; 1331 1332 /* store filter buffer object */ 1333 if (ctx->num_filters != 0) { 1334 for (i = 0; i < ctx->num_filters; ++i) 1335 ctx->filter_buf[i] = BUFFER(ctx->filters[i]); 1336 } else { 1337 goto finished; 1338 } 1339 1340 /* loop the filter, set correct pipeline param for FW */ 1341 for (i = 0; i < ctx->num_filters; ++i) { 1342 cur_param = (VAProcFilterParameterBufferBase *)ctx->filter_buf[i]->buffer_data; 1343 switch (cur_param->type) { 1344 case VAProcFilterNone: 1345 goto finished; 1346 break; 1347 case VAProcFilterNoiseReduction: 1348 case VAProcFilterDeblocking: 1349 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterDenoise; 1350 check_filter++; 1351 break; 1352 case VAProcFilterSharpening: 1353 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterSharpening; 1354 break; 1355 case VAProcFilterColorBalance: 1356 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterColorEnhancement; 1357 break; 1358 case VAProcFilterFrameRateConversion: 1359 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterFrameRateConversion; 1360 break; 1361 default: 1362 cell_pipeline_param->filter_pipeline[filter_count++] = -1; 1363 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1364 goto out; 1365 } 1366 } 1367 1368 /* Denoise and Deblock is alternative */ 1369 if (check_filter >= 2) { 1370 drv_debug_msg(VIDEO_DEBUG_ERROR, "Denoise and Deblock is alternative!\n"); 1371 cell_pipeline_param->filter_pipeline[filter_count++] = -1; 1372 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1373 goto out; 1374 } 1375 1376 finished: 1377 cell_pipeline_param->num_filters = filter_count; 1378 1379 /* reorder */ 1380 for (i = 1; i < filter_count; ++i) 1381 for (j = i; j > 0; --j) 1382 if (cell_pipeline_param->filter_pipeline[j] < cell_pipeline_param->filter_pipeline[j - 1]) { 1383 /* swap */ 1384 tmp = cell_pipeline_param->filter_pipeline[j]; 1385 cell_pipeline_param->filter_pipeline[j] = cell_pipeline_param->filter_pipeline[j - 1]; 1386 cell_pipeline_param->filter_pipeline[j - 1] = tmp; 1387 } 1388 1389 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VPP_ID, &cmdbuf->param_mem, VssProcPipelineParameterCommand, 1390 ctx->pipeline_param_offset, sizeof(struct VssProcPipelineParameterBuffer)); 1391 out: 1392 return vaStatus; 1393 } 1394 1395 static VAStatus vsp_set_filter_param(context_VPP_p ctx) 1396 { 1397 VAStatus vaStatus = VA_STATUS_SUCCESS; 1398 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf; 1399 struct VssProcDenoiseParameterBuffer *cell_denoiser_param = (struct VssProcDenoiseParameterBuffer *)cmdbuf->denoise_param_p; 1400 struct VssProcColorEnhancementParameterBuffer *cell_enhancer_param = (struct VssProcColorEnhancementParameterBuffer *)cmdbuf->enhancer_param_p; 1401 struct VssProcSharpenParameterBuffer *cell_sharpen_param = (struct VssProcSharpenParameterBuffer *)cmdbuf->sharpen_param_p; 1402 struct VssProcFrcParameterBuffer *cell_proc_frc_param = (struct VssProcFrcParameterBuffer *)cmdbuf->frc_param_p; 1403 VAProcFilterParameterBufferBase *cur_param = NULL; 1404 VAProcFilterParameterBufferFrameRateConversion *frc_param = NULL; 1405 unsigned int i; 1406 float ratio; 1407 1408 for (i = 0; i < ctx->num_filters; ++i) { 1409 cur_param = (VAProcFilterParameterBufferBase *)ctx->filter_buf[i]->buffer_data; 1410 switch (cur_param->type) { 1411 case VAProcFilterDeblocking: 1412 memcpy(cell_denoiser_param, 1413 &ctx->denoise_deblock_param, 1414 sizeof(ctx->denoise_deblock_param)); 1415 cell_denoiser_param->type = VssProcDeblock; 1416 1417 vsp_cmdbuf_insert_command(cmdbuf, 1418 CONTEXT_VPP_ID, 1419 &cmdbuf->param_mem, 1420 VssProcDenoiseParameterCommand, 1421 ctx->denoise_param_offset, 1422 sizeof(struct VssProcDenoiseParameterBuffer)); 1423 break; 1424 1425 case VAProcFilterNoiseReduction: 1426 memcpy(cell_denoiser_param, 1427 &ctx->denoise_deblock_param, 1428 sizeof(ctx->denoise_deblock_param)); 1429 cell_denoiser_param->type = VssProcDegrain; 1430 1431 vsp_cmdbuf_insert_command(cmdbuf, 1432 CONTEXT_VPP_ID, 1433 &cmdbuf->param_mem, 1434 VssProcDenoiseParameterCommand, 1435 ctx->denoise_param_offset, 1436 sizeof(struct VssProcDenoiseParameterBuffer)); 1437 break; 1438 1439 case VAProcFilterSharpening: 1440 memcpy(cell_sharpen_param, 1441 &ctx->sharpen_param, 1442 sizeof(ctx->sharpen_param)); 1443 1444 vsp_cmdbuf_insert_command(cmdbuf, 1445 CONTEXT_VPP_ID, 1446 &cmdbuf->param_mem, 1447 VssProcSharpenParameterCommand, 1448 ctx->sharpen_param_offset, 1449 sizeof(struct VssProcSharpenParameterBuffer)); 1450 break; 1451 1452 case VAProcFilterColorBalance: 1453 memcpy(cell_enhancer_param, 1454 &ctx->enhancer_param, 1455 sizeof(ctx->enhancer_param)); 1456 1457 vsp_cmdbuf_insert_command(cmdbuf, 1458 CONTEXT_VPP_ID, 1459 &cmdbuf->param_mem, 1460 VssProcColorEnhancementParameterCommand, 1461 ctx->enhancer_param_offset, 1462 sizeof(struct VssProcColorEnhancementParameterBuffer)); 1463 1464 break; 1465 1466 case VAProcFilterFrameRateConversion: 1467 ctx->frc_buf = ctx->filter_buf[i]; 1468 1469 frc_param = (VAProcFilterParameterBufferFrameRateConversion *)ctx->filter_buf[i]->buffer_data; 1470 ratio = frc_param->output_fps / (float)frc_param->input_fps; 1471 1472 /* set the FRC quality */ 1473 /* cell_proc_frc_param->quality = VssFrcMediumQuality; */ 1474 cell_proc_frc_param->quality = VssFrcHighQuality; 1475 1476 /* check if the input fps is in the range of HW capability */ 1477 if (ratio == 2) 1478 cell_proc_frc_param->conversion_rate = VssFrc2xConversionRate; 1479 else if (ratio == 2.5) 1480 cell_proc_frc_param->conversion_rate = VssFrc2_5xConversionRate; 1481 else if (ratio == 4) 1482 cell_proc_frc_param->conversion_rate = VssFrc4xConversionRate; 1483 else if (ratio == 1.25) 1484 cell_proc_frc_param->conversion_rate = VssFrc1_25xConversionRate; 1485 else { 1486 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid frame rate conversion ratio %f \n", ratio); 1487 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1488 goto out; 1489 } 1490 1491 vsp_cmdbuf_insert_command(cmdbuf, 1492 CONTEXT_VPP_ID, 1493 &cmdbuf->param_mem, 1494 VssProcFrcParameterCommand, 1495 ctx->frc_param_offset, 1496 sizeof(struct VssProcFrcParameterBuffer)); 1497 break; 1498 default: 1499 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1500 goto out; 1501 } 1502 } 1503 out: 1504 return vaStatus; 1505 } 1506 1507 static int check_resolution(int width, int height) 1508 { 1509 int ret; 1510 int image_area; 1511 1512 if (height < MIN_SUPPORTED_HEIGHT || height > MAX_SUPPORTED_HEIGHT) 1513 return NOT_SUPPORTED_RESOLUTION; 1514 1515 image_area = height * width; 1516 1517 if (image_area <= QVGA_AREA) 1518 ret = QCIF_TO_QVGA; 1519 else if (image_area <= VGA_AREA) 1520 ret = QVGA_TO_VGA; 1521 else if (image_area <= SD_AREA) 1522 ret = VGA_TO_SD; 1523 else if (image_area <= HD720P_AREA) 1524 ret = SD_TO_720P; 1525 else if (image_area <= HD1080P_AREA) 1526 ret = HD720P_TO_1080P; 1527 else 1528 ret = NOT_SUPPORTED_RESOLUTION; 1529 1530 return ret; 1531 } 1532 1533 /* 1534 * The strength area is: 1535 * 1536 * 0______33______66______100 1537 * LOW MED HIGH 1538 * 1539 * MIN=0; MAX=100; STEP=33 1540 */ 1541 static int check_vpp_strength(int value) 1542 { 1543 if (value < MIN_VPP_PARAM || value > MAX_VPP_PARAM) 1544 return INVALID_STRENGTH; 1545 1546 if (value >= MIN_VPP_PARAM && 1547 value < MIN_VPP_PARAM + STEP_VPP_PARAM) 1548 return LOW_STRENGTH; 1549 else if (value >= MIN_VPP_PARAM + STEP_VPP_PARAM && 1550 value < MIN_VPP_PARAM + 2 * STEP_VPP_PARAM) 1551 return MEDIUM_STRENGTH; 1552 else 1553 return HIGH_STRENGTH; 1554 } 1555