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@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
vsp_VPP_QueryConfigAttributes(VAProfile __maybe_unused profile,VAEntrypoint __maybe_unused entrypoint,VAConfigAttrib __maybe_unused * attrib_list,int __maybe_unused num_attribs)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
vsp_VPP_ValidateConfig(object_config_p obj_config)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
vsp__VPP_check_legal_picture(object_context_p obj_context,object_config_p obj_config)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
vsp_VPP_CreateContext(object_context_p obj_context,object_config_p obj_config)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
vsp_VPP_DestroyContext(object_context_p obj_context)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
vsp__VPP_process_pipeline_param(context_VPP_p ctx,object_context_p obj_context,object_buffer_p obj_buffer)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
vsp_VPP_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)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
vsp_VPP_BeginPicture(object_context_p obj_context)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
vsp_VPP_EndPicture(object_context_p obj_context)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
vsp_QueryVideoProcFilters(VADriverContextP ctx,VAContextID context,VAProcFilterType * filters,unsigned int * num_filters)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
vsp_QueryVideoProcFilterCaps(VADriverContextP ctx,VAContextID context,VAProcFilterType type,void * filter_caps,unsigned int * num_filter_caps)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
vsp_QueryVideoProcPipelineCaps(VADriverContextP ctx,VAContextID context,VABufferID * filters,unsigned int num_filters,VAProcPipelineCaps * pipeline_caps)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
vsp_set_pipeline(context_VPP_p ctx)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
vsp_set_filter_param(context_VPP_p ctx)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
check_resolution(int width,int height)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 */
check_vpp_strength(int value)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