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