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