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 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_driver_data_p driver_data = obj_context->driver_data;
406
407 if (pipeline_param->surface_region != NULL) {
408 drv_debug_msg(VIDEO_DEBUG_ERROR, "Cann't scale\n");
409 vaStatus = VA_STATUS_ERROR_UNKNOWN;
410 goto out;
411 }
412
413 if (pipeline_param->output_region != NULL) {
414 drv_debug_msg(VIDEO_DEBUG_ERROR, "Cann't scale\n");
415 vaStatus = VA_STATUS_ERROR_UNKNOWN;
416 goto out;
417 }
418
419 if (pipeline_param->output_background_color != 0) {
420 drv_debug_msg(VIDEO_DEBUG_ERROR, "Cann't support background color here\n");
421 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
422 goto out;
423 }
424
425 if (pipeline_param->filters == NULL) {
426 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filter setting filters = %p\n", pipeline_param->filters);
427 vaStatus = VA_STATUS_ERROR_UNKNOWN;
428 goto out;
429 }
430
431 #if 0
432 /* for pass filter */
433 if (pipeline_param->num_filters == 0 || pipeline_param->num_filters > VssProcPipelineMaxNumFilters) {
434 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filter number = %d\n", pipeline_param->num_filters);
435 vaStatus = VA_STATUS_ERROR_UNKNOWN;
436 goto out;
437 }
438 #endif
439
440 if (pipeline_param->forward_references == NULL) {
441 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid forward_refereces %p setting\n", pipeline_param->forward_references);
442 vaStatus = VA_STATUS_ERROR_UNKNOWN;
443 goto out;
444 }
445
446 /* should we check it? since the begining it's not VSP_FORWARD_REF_NUM */
447 if (pipeline_param->num_forward_references != VSP_FORWARD_REF_NUM) {
448 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);
449 vaStatus = VA_STATUS_ERROR_UNKNOWN;
450 goto out;
451 }
452
453 /* first picture, need to setup the VSP context */
454 if (ctx->obj_context->frame_count == 0)
455 vsp_cmdbuf_vpp_context(cmdbuf, VssGenInitializeContext, CONTEXT_VPP_ID, VSP_APP_ID_FRC_VPP);
456
457 /* get the input surface */
458 if (!(pipeline_param->pipeline_flags & VA_PIPELINE_FLAG_END)) {
459 input_surface = SURFACE(pipeline_param->surface);
460 if (input_surface == NULL) {
461 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid input surface %x\n", pipeline_param->surface);
462 vaStatus = VA_STATUS_ERROR_UNKNOWN;
463 goto out;
464 }
465 } else {
466 input_surface = NULL;
467 }
468
469 /* if it is the first pipeline command */
470 if (pipeline_param->num_filters != ctx->num_filters || pipeline_param->num_filters == 0) {
471 if (ctx->num_filters != 0) {
472 drv_debug_msg(VIDEO_DEBUG_ERROR, "can not reset pipeline in the mid of post-processing or without create a new context\n");
473 vaStatus = VA_STATUS_ERROR_UNKNOWN;
474 goto out;
475 } else {
476 /* save filters */
477 ctx->num_filters = pipeline_param->num_filters;
478 if (ctx->num_filters == 0) {
479 ctx->filters = NULL;
480 } else {
481 ctx->filters = (VABufferID *) calloc(ctx->num_filters, sizeof(*ctx->filters));
482 if (ctx->filters == NULL) {
483 drv_debug_msg(VIDEO_DEBUG_ERROR, "can not reset pipeline in the mid of post-processing or without create a new context\n");
484 vaStatus = VA_STATUS_ERROR_UNKNOWN;
485 goto out;
486 }
487 memcpy(ctx->filters, pipeline_param->filters, ctx->num_filters * sizeof(*ctx->filters));
488 }
489
490 /* set pipeline command to FW */
491 vaStatus = vsp_set_pipeline(ctx);
492 if (vaStatus) {
493 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to set pipeline\n");
494 goto out;
495 }
496
497 /* set filter parameter to FW, record frc parameter buffer */
498 vaStatus = vsp_set_filter_param(ctx);
499 if (vaStatus) {
500 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to set filter parameter\n");
501 goto out;
502 }
503 }
504 } else {
505 /* else ignore pipeline/filter setting */
506 #if 0
507 /* FIXME: we can save these check for PnP */
508 for (i = 0; i < pipeline_param->num_filters; i++) {
509 if (pipeline_param->filters[i] != ctx->filters[i]) {
510 drv_debug_msg(VIDEO_DEBUG_ERROR, "can not reset pipeline in the mid of post-processing or without create a new context\n");
511 vaStatus = VA_STATUS_ERROR_UNKNOWN;
512 goto out;
513 }
514 }
515 #endif
516 }
517
518 /* fill picture command to FW */
519 if (ctx->frc_buf != NULL)
520 frc_param = (VAProcFilterParameterBufferFrameRateConversion *)ctx->frc_buf->buffer_data;
521 else
522 frc_param = NULL;
523
524 /* end picture command */
525 if (pipeline_param->pipeline_flags & VA_PIPELINE_FLAG_END) {
526 cell_end_param->num_input_pictures = 0;
527 cell_end_param->num_output_pictures = 0;
528 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VPP_ID, &cmdbuf->param_mem, VssProcPictureCommand,
529 ctx->end_param_offset, sizeof(struct VssProcPictureParameterBuffer));
530 /* Destory the VSP context */
531 vsp_cmdbuf_vpp_context(cmdbuf, VssGenDestroyContext, CONTEXT_VPP_ID, 0);
532 goto out;
533 }
534
535 #ifdef PSBVIDEO_VPP_TILING
536 /* get the tiling flag*/
537 tiled = GET_SURFACE_INFO_tiling(input_surface->psb_surface);
538 #endif
539 /* According to VIED's design, the width must be multiple of 16 */
540 width = ALIGN_TO_16(input_surface->width);
541 if (width > (int)input_surface->psb_surface->stride)
542 width = (int)input_surface->psb_surface->stride;
543
544 /* Setup input surface */
545 cell_proc_picture_param->num_input_pictures = 1;
546 cell_proc_picture_param->input_picture[0].surface_id = pipeline_param->surface;
547 vsp_cmdbuf_reloc_pic_param(&(cell_proc_picture_param->input_picture[0].base), ctx->pic_param_offset, &(input_surface->psb_surface->buf),
548 cmdbuf->param_mem_loc, cell_proc_picture_param);
549 cell_proc_picture_param->input_picture[0].height = input_surface->height_origin;
550 cell_proc_picture_param->input_picture[0].width = width;
551 cell_proc_picture_param->input_picture[0].irq = 0;
552 cell_proc_picture_param->input_picture[0].stride = input_surface->psb_surface->stride;
553 cell_proc_picture_param->input_picture[0].format = ctx->format;
554 cell_proc_picture_param->input_picture[0].tiled = tiled;
555 cell_proc_picture_param->input_picture[0].rot_angle = 0;
556
557 /* Setup output surfaces */
558 if (frc_param == NULL)
559 cell_proc_picture_param->num_output_pictures = 1;
560 else
561 cell_proc_picture_param->num_output_pictures = frc_param->num_output_frames + 1;
562
563 for (i = 0; i < cell_proc_picture_param->num_output_pictures; ++i) {
564 if (i == 0) {
565 cur_output_surf = ctx->obj_context->current_render_target;
566
567 #ifdef PSBVIDEO_MRFL_VPP_ROTATE
568 /* The rotation info is saved in the first frame */
569 rotation_angle = GET_SURFACE_INFO_rotate(cur_output_surf->psb_surface);
570 switch (rotation_angle) {
571 case VA_ROTATION_90:
572 vsp_rotation_angle = VSP_ROTATION_90;
573 break;
574 case VA_ROTATION_180:
575 vsp_rotation_angle = VSP_ROTATION_180;
576 break;
577 case VA_ROTATION_270:
578 vsp_rotation_angle = VSP_ROTATION_270;
579 break;
580 default:
581 vsp_rotation_angle = VSP_ROTATION_NONE;
582 }
583 #endif
584 } else {
585 if (frc_param == NULL) {
586 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid output surface numbers %x\n",
587 cell_proc_picture_param->num_output_pictures);
588 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
589 goto out;
590 }
591
592 cur_output_surf = SURFACE(frc_param->output_frames[i-1]);
593 if (cur_output_surf == NULL) {
594 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid input surface %x\n", frc_param->output_frames[i-1]);
595 vaStatus = VA_STATUS_ERROR_UNKNOWN;
596 goto out;
597 }
598
599 #ifdef PSBVIDEO_MRFL_VPP_ROTATE
600 /* VPP rotation is just for 1080P */
601 if (tiled && rotation_angle != VA_ROTATION_NONE) {
602 if (VA_STATUS_SUCCESS != psb_CreateRotateSurface(obj_context, cur_output_surf, rotation_angle)) {
603 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc rotation surface!\n");
604 vaStatus = VA_STATUS_ERROR_UNKNOWN;
605 goto out;
606 }
607 }
608 #endif
609 }
610
611 if (tiled && rotation_angle != VA_ROTATION_NONE) {
612 #ifdef PSBVIDEO_MRFL_VPP_ROTATE
613 /* For 90d and 270d, we need to alloc rotation buff and
614 * copy the 0d data from input to output
615 */
616 psb_buffer_map(&(input_surface->psb_surface->buf), &src_addr);
617 psb_buffer_map(&(cur_output_surf->psb_surface->buf), &dest_addr);
618 memcpy(dest_addr, src_addr, cur_output_surf->psb_surface->size);
619 psb_buffer_unmap(&(cur_output_surf->psb_surface->buf));
620 psb_buffer_unmap(&(input_surface->psb_surface->buf));
621
622 output_surface = cur_output_surf->out_loop_surface;
623
624 /* According to VIED's design, the width must be multiple of 16 */
625 width = ALIGN_TO_16(cur_output_surf->height_origin);
626 if (width > cur_output_surf->out_loop_surface->stride)
627 width = cur_output_surf->out_loop_surface->stride;
628 height = cur_output_surf->width;
629 stride = cur_output_surf->out_loop_surface->stride;
630 #endif
631 } else {
632 output_surface = cur_output_surf->psb_surface;
633
634 /* According to VIED's design, the width must be multiple of 16 */
635 width = ALIGN_TO_16(cur_output_surf->width);
636 if (width > (int)cur_output_surf->psb_surface->stride)
637 width = cur_output_surf->psb_surface->stride;
638 height = cur_output_surf->height_origin;
639 stride = cur_output_surf->psb_surface->stride;
640
641 /* Check the rotate bit */
642 if (pipeline_param->rotation_state == VA_ROTATION_90)
643 vsp_rotation_angle = VSP_ROTATION_90;
644 else if (pipeline_param->rotation_state == VA_ROTATION_180)
645 vsp_rotation_angle = VSP_ROTATION_180;
646 else if (pipeline_param->rotation_state == VA_ROTATION_270)
647 vsp_rotation_angle = VSP_ROTATION_270;
648 else
649 vsp_rotation_angle = VSP_ROTATION_NONE;
650 }
651
652 cell_proc_picture_param->output_picture[i].surface_id = wsbmKBufHandle(wsbmKBuf(output_surface->buf.drm_buf));
653
654 vsp_cmdbuf_reloc_pic_param(&(cell_proc_picture_param->output_picture[i].base),
655 ctx->pic_param_offset, &(output_surface->buf),
656 cmdbuf->param_mem_loc, cell_proc_picture_param);
657 cell_proc_picture_param->output_picture[i].height = height;
658 cell_proc_picture_param->output_picture[i].width = width;
659 cell_proc_picture_param->output_picture[i].stride = stride;
660 cell_proc_picture_param->output_picture[i].irq = 1;
661 cell_proc_picture_param->output_picture[i].format = ctx->format;
662 cell_proc_picture_param->output_picture[i].rot_angle = vsp_rotation_angle;
663 cell_proc_picture_param->output_picture[i].tiled = tiled;
664 }
665
666 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VPP_ID, &cmdbuf->param_mem, VssProcPictureCommand,
667 ctx->pic_param_offset, sizeof(struct VssProcPictureParameterBuffer));
668
669 vsp_cmdbuf_fence_pic_param(cmdbuf, wsbmKBufHandle(wsbmKBuf(cmdbuf->param_mem.drm_buf)));
670
671 #if 0
672 /* handle reference frames, ignore backward reference */
673 for (i = 0; i < pipeline_param->num_forward_references; ++i) {
674 cur_output_surf = SURFACE(pipeline_param->forward_references[i]);
675 if (cur_output_surf == NULL)
676 continue;
677 if (vsp_cmdbuf_buffer_ref(cmdbuf, &cur_output_surf->psb_surface->buf) < 0) {
678 drv_debug_msg(VIDEO_DEBUG_ERROR, "vsp_cmdbuf_buffer_ref() failed\n");
679 vaStatus = VA_STATUS_ERROR_UNKNOWN;
680 goto out;
681 }
682 }
683 #endif
684 out:
685 free(pipeline_param);
686 obj_buffer->buffer_data = NULL;
687 obj_buffer->size = 0;
688
689 return vaStatus;
690 }
691
vsp_VPP_RenderPicture(object_context_p obj_context,object_buffer_p * buffers,int num_buffers)692 static VAStatus vsp_VPP_RenderPicture(
693 object_context_p obj_context,
694 object_buffer_p *buffers,
695 int num_buffers)
696 {
697 int i;
698 INIT_CONTEXT_VPP;
699 VAProcPipelineParameterBuffer *pipeline_param = NULL;
700 VAStatus vaStatus = VA_STATUS_SUCCESS;
701
702 for (i = 0; i < num_buffers; i++) {
703 object_buffer_p obj_buffer = buffers[i];
704 pipeline_param = (VAProcPipelineParameterBuffer *) obj_buffer->buffer_data;
705
706 switch (obj_buffer->type) {
707 case VAProcPipelineParameterBufferType:
708 if (!pipeline_param->num_filters && pipeline_param->blend_state)
709 /* For Security Composer */
710 vaStatus = vsp_compose_process_pipeline_param(ctx, obj_context, obj_buffer);
711 else
712 /* For VPP/FRC */
713 vaStatus = vsp__VPP_process_pipeline_param(ctx, obj_context, obj_buffer);
714 DEBUG_FAILURE;
715 break;
716 default:
717 vaStatus = VA_STATUS_ERROR_UNKNOWN;
718 DEBUG_FAILURE;
719 }
720 if (vaStatus != VA_STATUS_SUCCESS) {
721 break;
722 }
723 }
724
725 return vaStatus;
726 }
727
vsp_VPP_BeginPicture(object_context_p obj_context)728 static VAStatus vsp_VPP_BeginPicture(
729 object_context_p obj_context)
730 {
731 int ret;
732 VAStatus vaStatus = VA_STATUS_SUCCESS;
733 INIT_CONTEXT_VPP;
734 vsp_cmdbuf_p cmdbuf;
735
736 /* Initialise the command buffer */
737 ret = vsp_context_get_next_cmdbuf(ctx->obj_context);
738 if (ret) {
739 drv_debug_msg(VIDEO_DEBUG_GENERAL, "get next cmdbuf fail\n");
740 vaStatus = VA_STATUS_ERROR_UNKNOWN;
741 return vaStatus;
742 }
743
744 cmdbuf = obj_context->vsp_cmdbuf;
745
746 /* map param mem */
747 vaStatus = psb_buffer_map(&cmdbuf->param_mem, &cmdbuf->param_mem_p);
748 if (vaStatus) {
749 return vaStatus;
750 }
751
752 cmdbuf->pic_param_p = cmdbuf->param_mem_p + ctx->pic_param_offset;
753 cmdbuf->end_param_p = cmdbuf->param_mem_p + ctx->end_param_offset;
754 cmdbuf->pipeline_param_p = cmdbuf->param_mem_p + ctx->pipeline_param_offset;
755 cmdbuf->denoise_param_p = cmdbuf->param_mem_p + ctx->denoise_param_offset;
756 cmdbuf->enhancer_param_p = cmdbuf->param_mem_p + ctx->enhancer_param_offset;
757 cmdbuf->sharpen_param_p = cmdbuf->param_mem_p + ctx->sharpen_param_offset;
758 cmdbuf->frc_param_p = cmdbuf->param_mem_p + ctx->frc_param_offset;
759 cmdbuf->compose_param_p = cmdbuf->param_mem_p + ctx->compose_param_offset;
760
761 return VA_STATUS_SUCCESS;
762 }
763
vsp_VPP_EndPicture(object_context_p obj_context)764 static VAStatus vsp_VPP_EndPicture(
765 object_context_p obj_context)
766 {
767 INIT_CONTEXT_VPP;
768 psb_driver_data_p driver_data = obj_context->driver_data;
769 vsp_cmdbuf_p cmdbuf = obj_context->vsp_cmdbuf;
770
771 if(cmdbuf->param_mem_p != NULL) {
772 psb_buffer_unmap(&cmdbuf->param_mem);
773 cmdbuf->param_mem_p = NULL;
774 cmdbuf->pic_param_p = NULL;
775 cmdbuf->end_param_p = NULL;
776 cmdbuf->pipeline_param_p = NULL;
777 cmdbuf->denoise_param_p = NULL;
778 cmdbuf->enhancer_param_p = NULL;
779 cmdbuf->sharpen_param_p = NULL;
780 cmdbuf->frc_param_p = NULL;
781 cmdbuf->compose_param_p = NULL;
782 }
783
784 if (vsp_context_flush_cmdbuf(ctx->obj_context)) {
785 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VPP: flush deblock cmdbuf error\n");
786 return VA_STATUS_ERROR_UNKNOWN;
787 }
788
789 return VA_STATUS_SUCCESS;
790 }
791
792 struct format_vtable_s vsp_VPP_vtable = {
793 queryConfigAttributes:
794 vsp_VPP_QueryConfigAttributes,
795 validateConfig:
796 vsp_VPP_ValidateConfig,
797 createContext:
798 vsp_VPP_CreateContext,
799 destroyContext:
800 vsp_VPP_DestroyContext,
801 beginPicture:
802 vsp_VPP_BeginPicture,
803 renderPicture:
804 vsp_VPP_RenderPicture,
805 endPicture:
806 vsp_VPP_EndPicture
807 };
808
vsp_QueryVideoProcFilters(VADriverContextP ctx,VAContextID context,VAProcFilterType * filters,unsigned int * num_filters)809 VAStatus vsp_QueryVideoProcFilters(
810 VADriverContextP ctx,
811 VAContextID context,
812 VAProcFilterType *filters,
813 unsigned int *num_filters
814 )
815 {
816 INIT_DRIVER_DATA;
817 VAStatus vaStatus = VA_STATUS_SUCCESS;
818 object_context_p obj_context;
819 object_config_p obj_config;
820 VAEntrypoint tmp;
821 int count;
822
823 /* check if ctx is right */
824 obj_context = CONTEXT(context);
825 if (NULL == obj_context) {
826 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
827 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
828 goto err;
829 }
830
831 obj_config = CONFIG(obj_context->config_id);
832 if (NULL == obj_config) {
833 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
834 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
835 goto err;
836 }
837
838 tmp = obj_config->entrypoint;
839 if (tmp != VAEntrypointVideoProc) {
840 drv_debug_msg(VIDEO_DEBUG_ERROR, "current entrypoint is %d, not VAEntrypointVideoProc\n", tmp);
841 vaStatus = VA_STATUS_ERROR_UNKNOWN;
842 goto err;
843 }
844
845 /* check if filters and num_filters is valid */
846 if (NULL == num_filters || NULL == filters) {
847 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filters, filters);
848 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
849 goto err;
850 }
851
852 /* check if the filter array size is valid */
853 if (*num_filters < VSP_SUPPORTED_FILTERS_NUM) {
854 drv_debug_msg(VIDEO_DEBUG_ERROR, "The filters array size(%d) is NOT valid! Supported filters num is %d\n",
855 *num_filters, VSP_SUPPORTED_FILTERS_NUM);
856 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
857 *num_filters = VSP_SUPPORTED_FILTERS_NUM;
858 goto err;
859 }
860
861 /* check if current HW support Video proc */
862 if (IS_MRFL(driver_data)) {
863 count = 0;
864 filters[count++] = VAProcFilterDeblocking;
865 filters[count++] = VAProcFilterNoiseReduction;
866 filters[count++] = VAProcFilterSharpening;
867 filters[count++] = VAProcFilterColorBalance;
868 filters[count++] = VAProcFilterFrameRateConversion;
869 *num_filters = count;
870 } else {
871 *num_filters = 0;
872 }
873 err:
874 return vaStatus;
875 }
876
vsp_QueryVideoProcFilterCaps(VADriverContextP ctx,VAContextID context,VAProcFilterType type,void * filter_caps,unsigned int * num_filter_caps)877 VAStatus vsp_QueryVideoProcFilterCaps(
878 VADriverContextP ctx,
879 VAContextID context,
880 VAProcFilterType type,
881 void *filter_caps,
882 unsigned int *num_filter_caps
883 )
884 {
885 INIT_DRIVER_DATA;
886 VAStatus vaStatus = VA_STATUS_SUCCESS;
887 object_context_p obj_context;
888 object_config_p obj_config;
889 VAEntrypoint tmp;
890 VAProcFilterCap *denoise_cap, *deblock_cap;
891 VAProcFilterCap *sharpen_cap;
892 VAProcFilterCapColorBalance *color_balance_cap;
893 VAProcFilterCap *frc_cap;
894
895 /* check if context is right */
896 obj_context = CONTEXT(context);
897 if (NULL == obj_context) {
898 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
899 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
900 goto err;
901 }
902
903 obj_config = CONFIG(obj_context->config_id);
904 if (NULL == obj_config) {
905 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
906 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
907 goto err;
908 }
909
910 /* check if filter_caps and num_filter_caps is right */
911 if (NULL == num_filter_caps || NULL == filter_caps){
912 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters %p, filters %p\n", num_filter_caps, filter_caps);
913 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
914 goto err;
915 }
916
917 if (*num_filter_caps < 1) {
918 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide input parameter num_filters == %d (> 1)\n", *num_filter_caps);
919 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
920 goto err;
921 }
922
923 /* check if curent HW support and return corresponding caps */
924 if (IS_MRFL(driver_data)) {
925 /* FIXME: we should use a constant table to return caps */
926 switch (type) {
927 case VAProcFilterNoiseReduction:
928 denoise_cap = filter_caps;
929 denoise_cap->range.min_value = MIN_VPP_PARAM;
930 denoise_cap->range.max_value = MAX_VPP_PARAM;
931 denoise_cap->range.default_value = MIN_VPP_PARAM;
932 denoise_cap->range.step = STEP_VPP_PARAM;
933 *num_filter_caps = 1;
934 break;
935 case VAProcFilterDeblocking:
936 deblock_cap = filter_caps;
937 deblock_cap->range.min_value = MIN_VPP_PARAM;
938 deblock_cap->range.max_value = MAX_VPP_PARAM;
939 deblock_cap->range.default_value = MIN_VPP_PARAM;
940 deblock_cap->range.step = STEP_VPP_PARAM;
941 *num_filter_caps = 1;
942 break;
943
944 case VAProcFilterSharpening:
945 sharpen_cap = filter_caps;
946 sharpen_cap->range.min_value = MIN_VPP_PARAM;
947 sharpen_cap->range.max_value = MAX_VPP_PARAM;
948 sharpen_cap->range.default_value = MIN_VPP_PARAM;
949 sharpen_cap->range.step = STEP_VPP_PARAM;
950 *num_filter_caps = 1;
951 break;
952
953 case VAProcFilterColorBalance:
954 if (*num_filter_caps < VSP_COLOR_ENHANCE_FEATURES) {
955 drv_debug_msg(VIDEO_DEBUG_ERROR, "filter cap num is should big than %d(%d)\n",
956 VSP_COLOR_ENHANCE_FEATURES, *num_filter_caps);
957 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
958 *num_filter_caps = VSP_COLOR_ENHANCE_FEATURES;
959 goto err;
960 }
961 color_balance_cap = filter_caps;
962 color_balance_cap->type = VAProcColorBalanceAutoSaturation;
963 color_balance_cap->range.min_value = MIN_VPP_AUTO_PARAM;
964 color_balance_cap->range.max_value = MAX_VPP_AUTO_PARAM;
965 color_balance_cap->range.default_value = MIN_VPP_AUTO_PARAM;
966 color_balance_cap->range.step = STEP_VPP_AUTO_PARAM;
967
968 color_balance_cap++;
969 color_balance_cap->type = VAProcColorBalanceAutoBrightness;
970 color_balance_cap->range.min_value = MIN_VPP_AUTO_PARAM;
971 color_balance_cap->range.max_value = MAX_VPP_AUTO_PARAM;
972 color_balance_cap->range.default_value = MIN_VPP_AUTO_PARAM;
973 color_balance_cap->range.step = STEP_VPP_AUTO_PARAM;
974
975 *num_filter_caps = 2;
976 break;
977
978 case VAProcFilterFrameRateConversion:
979 frc_cap = filter_caps;
980 frc_cap->range.min_value = 2;
981 frc_cap->range.max_value = 4;
982 frc_cap->range.default_value = 2;
983 /* FIXME: it's a set, step is helpless */
984 frc_cap->range.step = 0.5;
985 *num_filter_caps = 1;
986 break;
987
988 default:
989 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalide filter type %d\n", type);
990 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER;
991 *num_filter_caps = 0;
992 goto err;
993 }
994 } else {
995 *num_filter_caps = 0;
996 }
997
998 err:
999 return vaStatus;
1000 }
1001
vsp_QueryVideoProcPipelineCaps(VADriverContextP ctx,VAContextID context,VABufferID * filters,unsigned int num_filters,VAProcPipelineCaps * pipeline_caps)1002 VAStatus vsp_QueryVideoProcPipelineCaps(
1003 VADriverContextP ctx,
1004 VAContextID context,
1005 VABufferID *filters,
1006 unsigned int num_filters,
1007 VAProcPipelineCaps *pipeline_caps
1008 )
1009 {
1010 INIT_DRIVER_DATA;
1011 VAStatus vaStatus = VA_STATUS_SUCCESS;
1012 object_context_p obj_context;
1013 object_config_p obj_config;
1014 VAEntrypoint tmp;
1015 unsigned int i, j;
1016 VAProcFilterParameterBuffer *deblock, *denoise, *sharpen;
1017 VAProcFilterParameterBufferFrameRateConversion *frc;
1018 VAProcFilterParameterBufferColorBalance *balance;
1019 VAProcFilterParameterBufferBase *base;
1020 object_buffer_p buf;
1021 uint32_t enabled_brightness, enabled_saturation;
1022 float ratio;
1023 int res_set;
1024 int strength;
1025 context_VPP_p vpp_ctx;
1026 int combination_check;
1027
1028 /* check if ctx is right */
1029 obj_context = CONTEXT(context);
1030 if (NULL == obj_context) {
1031 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find context\n");
1032 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1033 goto err;
1034 }
1035
1036 vpp_ctx = (context_VPP_p) obj_context->format_data;
1037
1038 obj_config = CONFIG(obj_context->config_id);
1039 if (NULL == obj_config) {
1040 drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to find config\n");
1041 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1042 goto err;
1043 }
1044
1045 /* Don't check the filter number.
1046 * According to VIED's design, without any filter, HW will just copy input data
1047 */
1048 #if 0
1049 if (num_filters == 0) {
1050 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_filters %d\n", num_filters);
1051 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1052 goto err;
1053 }
1054 #endif
1055 if (NULL == filters || pipeline_caps == NULL) {
1056 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid filters %p or pipeline_caps %p\n", filters, pipeline_caps);
1057 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1058 goto err;
1059 }
1060
1061 /* base on HW capability check the filters and return pipeline caps */
1062 if (IS_MRFL(driver_data)) {
1063 pipeline_caps->pipeline_flags = 0;
1064 pipeline_caps->filter_flags = 0;
1065 pipeline_caps->num_forward_references = VSP_FORWARD_REF_NUM;
1066 pipeline_caps->num_backward_references = 0;
1067
1068 /* check the input color standard */
1069 if (pipeline_caps->input_color_standards == NULL){
1070 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid input color standard array!\n");
1071 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1072 goto err;
1073 }
1074 if (pipeline_caps->num_input_color_standards < COLOR_STANDARDS_NUM) {
1075 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_input_color_standards %d\n", pipeline_caps->num_input_color_standards);
1076 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1077 pipeline_caps->num_input_color_standards = COLOR_STANDARDS_NUM;
1078 goto err;
1079 }
1080 pipeline_caps->input_color_standards[0] = VAProcColorStandardNone;
1081 pipeline_caps->num_input_color_standards = COLOR_STANDARDS_NUM;
1082
1083 /* check the output color standard */
1084 if (pipeline_caps->output_color_standards == NULL){
1085 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid output color standard array!\n");
1086 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1087 goto err;
1088 }
1089 if (pipeline_caps->num_output_color_standards < COLOR_STANDARDS_NUM) {
1090 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid num_output_color_standards %d\n", pipeline_caps->num_output_color_standards);
1091 vaStatus = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1092 pipeline_caps->num_output_color_standards = COLOR_STANDARDS_NUM;
1093 goto err;
1094 }
1095 pipeline_caps->output_color_standards[0] = VAProcColorStandardNone;
1096 pipeline_caps->num_output_color_standards = COLOR_STANDARDS_NUM;
1097
1098 /* check the resolution */
1099 res_set = check_resolution(obj_context->picture_width,
1100 obj_context->picture_height);
1101 if (res_set == NOT_SUPPORTED_RESOLUTION) {
1102 vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
1103 goto err;
1104 }
1105
1106 /* Blend type */
1107 pipeline_caps->blend_flags = VA_BLEND_PREMULTIPLIED_ALPHA;
1108
1109 if (getenv("VSP_PIPELINE_CHECK") != NULL)
1110 combination_check = 1;
1111 else
1112 combination_check = 0;
1113
1114 /* FIXME: should check filter value settings here */
1115 for (i = 0; i < num_filters; ++i) {
1116 /* find buffer */
1117 buf = BUFFER(*(filters + i));
1118 if (!buf) {
1119 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1120 goto err;
1121 }
1122
1123 base = (VAProcFilterParameterBufferBase *)buf->buffer_data;
1124 /* check filter buffer setting */
1125 switch (base->type) {
1126 case VAProcFilterDeblocking:
1127 deblock = (VAProcFilterParameterBuffer *)base;
1128
1129 if (combination_check &&
1130 vpp_chain_caps[res_set].deblock_enabled != FILTER_ENABLED) {
1131 drv_debug_msg(VIDEO_DEBUG_ERROR, "The deblock is DISABLE for %d format\n", res_set);
1132 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
1133 goto err;
1134 } else {
1135 /* check if the value is right */
1136 strength = check_vpp_strength(deblock->value);
1137 if (strength == INVALID_STRENGTH) {
1138 vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
1139 goto err;
1140 }
1141 memcpy(&vpp_ctx->denoise_deblock_param,
1142 &vpp_strength[strength].denoise_deblock[res_set],
1143 sizeof(vpp_ctx->denoise_deblock_param));
1144 }
1145 break;
1146
1147 case VAProcFilterNoiseReduction:
1148 denoise = (VAProcFilterParameterBuffer *)base;
1149
1150 if (combination_check &&
1151 vpp_chain_caps[res_set].denoise_enabled != FILTER_ENABLED) {
1152 drv_debug_msg(VIDEO_DEBUG_ERROR, "The denoise is DISABLE for %d format\n", res_set);
1153 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
1154 goto err;
1155 } else {
1156 strength = check_vpp_strength(denoise->value);
1157 if (strength == INVALID_STRENGTH) {
1158 vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
1159 goto err;
1160 }
1161 memcpy(&vpp_ctx->denoise_deblock_param,
1162 &vpp_strength[strength].denoise_deblock[res_set],
1163 sizeof(vpp_ctx->denoise_deblock_param));
1164 }
1165 break;
1166
1167 case VAProcFilterSharpening:
1168 sharpen = (VAProcFilterParameterBuffer *)base;
1169
1170 if (combination_check &&
1171 vpp_chain_caps[res_set].sharpen_enabled != FILTER_ENABLED) {
1172 drv_debug_msg(VIDEO_DEBUG_ERROR, "The sharpen is DISABLE for %d format\n", res_set);
1173 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
1174 goto err;
1175 } else {
1176 strength = check_vpp_strength(sharpen->value);
1177 if (strength == INVALID_STRENGTH) {
1178 vaStatus = VA_STATUS_ERROR_INVALID_VALUE;
1179 goto err;
1180 }
1181 memcpy(&vpp_ctx->sharpen_param,
1182 &vpp_strength[strength].sharpen[res_set],
1183 sizeof(vpp_ctx->sharpen_param));
1184 }
1185 break;
1186
1187 case VAProcFilterColorBalance:
1188 balance = (VAProcFilterParameterBufferColorBalance *)base;
1189
1190 enabled_brightness = 0;
1191 enabled_saturation = 0;
1192
1193 for (j = 0; j < buf->num_elements; ++j, ++balance) {
1194 if (balance->attrib == VAProcColorBalanceAutoSaturation &&
1195 balance->value == MAX_VPP_AUTO_PARAM) {
1196 enabled_saturation = 1;
1197 } else if (balance->attrib == VAProcColorBalanceAutoBrightness &&
1198 balance->value == MAX_VPP_AUTO_PARAM) {
1199 enabled_brightness = 1;
1200 } else {
1201 drv_debug_msg(VIDEO_DEBUG_ERROR, "The color_banlance do NOT support this attrib %d\n",
1202 balance->attrib);
1203 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER;
1204 goto err;
1205 }
1206 }
1207
1208 /* check filter chain */
1209 if (combination_check &&
1210 vpp_chain_caps[res_set].color_balance_enabled != FILTER_ENABLED) {
1211 drv_debug_msg(VIDEO_DEBUG_ERROR, "The color_balance is DISABLE for %d format\n", res_set);
1212 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
1213 goto err;
1214 } else {
1215 strength = MEDIUM_STRENGTH;
1216 memcpy(&vpp_ctx->enhancer_param,
1217 &vpp_strength[strength].enhancer[res_set],
1218 sizeof(vpp_ctx->enhancer_param));
1219 if (!enabled_saturation)
1220 vpp_ctx->enhancer_param.chroma_amm = 0;
1221 if (!enabled_brightness)
1222 vpp_ctx->enhancer_param.luma_amm = 0;
1223 }
1224
1225 break;
1226
1227 case VAProcFilterFrameRateConversion:
1228 frc = (VAProcFilterParameterBufferFrameRateConversion *)base;
1229
1230 /* check frame rate */
1231 ratio = frc->output_fps / (float)frc->input_fps;
1232
1233 if (!((ratio == 2 || ratio == 2.5 || ratio == 4) && frc->output_fps <= 60)) {
1234 drv_debug_msg(VIDEO_DEBUG_ERROR, "The FRC do NOT support the ration(%f) and fps(%d)\n",
1235 ratio, frc->output_fps);
1236 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_FILTER;
1237 goto err;
1238 }
1239
1240 /* check the chain */
1241 if (combination_check &&
1242 vpp_chain_caps[res_set].frc_enabled != FILTER_ENABLED) {
1243 drv_debug_msg(VIDEO_DEBUG_ERROR, "The FRC is DISABLE for %d format\n", res_set);
1244 vaStatus = VA_STATUS_ERROR_INVALID_FILTER_CHAIN;
1245 goto err;
1246 }
1247
1248 break;
1249 default:
1250 drv_debug_msg(VIDEO_DEBUG_ERROR, "Do NOT support the filter type %d\n", base->type);
1251 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1252 goto err;
1253 }
1254 }
1255 } else {
1256 drv_debug_msg(VIDEO_DEBUG_ERROR, "no HW support\n");
1257 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1258 goto err;
1259 }
1260 err:
1261 return vaStatus;
1262 }
1263
vsp_set_pipeline(context_VPP_p ctx)1264 static VAStatus vsp_set_pipeline(context_VPP_p ctx)
1265 {
1266 VAStatus vaStatus = VA_STATUS_SUCCESS;
1267 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
1268 struct VssProcPipelineParameterBuffer *cell_pipeline_param = (struct VssProcPipelineParameterBuffer *)cmdbuf->pipeline_param_p;
1269 unsigned int i, j, filter_count, check_filter = 0;
1270 VAProcFilterParameterBufferBase *cur_param;
1271 enum VssProcFilterType tmp;
1272 psb_driver_data_p driver_data = ctx->obj_context->driver_data;
1273
1274 /* set intermediate buffer */
1275 cell_pipeline_param->intermediate_buffer_size = VSP_INTERMEDIATE_BUF_SIZE;
1276 cell_pipeline_param->intermediate_buffer_base = wsbmBOOffsetHint(ctx->intermediate_buf->drm_buf);
1277
1278 /* init pipeline cmd */
1279 for (i = 0; i < VssProcPipelineMaxNumFilters; ++i)
1280 cell_pipeline_param->filter_pipeline[i] = -1;
1281 cell_pipeline_param->num_filters = 0;
1282
1283 filter_count = 0;
1284
1285 /* store filter buffer object */
1286 if (ctx->num_filters != 0) {
1287 for (i = 0; i < ctx->num_filters; ++i)
1288 ctx->filter_buf[i] = BUFFER(ctx->filters[i]);
1289 } else {
1290 goto finished;
1291 }
1292
1293 /* loop the filter, set correct pipeline param for FW */
1294 for (i = 0; i < ctx->num_filters; ++i) {
1295 cur_param = (VAProcFilterParameterBufferBase *)ctx->filter_buf[i]->buffer_data;
1296 switch (cur_param->type) {
1297 case VAProcFilterNone:
1298 goto finished;
1299 break;
1300 case VAProcFilterNoiseReduction:
1301 case VAProcFilterDeblocking:
1302 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterDenoise;
1303 check_filter++;
1304 break;
1305 case VAProcFilterSharpening:
1306 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterSharpening;
1307 break;
1308 case VAProcFilterColorBalance:
1309 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterColorEnhancement;
1310 break;
1311 case VAProcFilterFrameRateConversion:
1312 cell_pipeline_param->filter_pipeline[filter_count++] = VssProcFilterFrameRateConversion;
1313 break;
1314 default:
1315 cell_pipeline_param->filter_pipeline[filter_count++] = -1;
1316 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1317 goto out;
1318 }
1319 }
1320
1321 /* Denoise and Deblock is alternative */
1322 if (check_filter >= 2) {
1323 drv_debug_msg(VIDEO_DEBUG_ERROR, "Denoise and Deblock is alternative!\n");
1324 cell_pipeline_param->filter_pipeline[filter_count++] = -1;
1325 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1326 goto out;
1327 }
1328
1329 finished:
1330 cell_pipeline_param->num_filters = filter_count;
1331
1332 /* reorder */
1333 for (i = 1; i < filter_count; ++i)
1334 for (j = i; j > 0; --j)
1335 if (cell_pipeline_param->filter_pipeline[j] < cell_pipeline_param->filter_pipeline[j - 1]) {
1336 /* swap */
1337 tmp = cell_pipeline_param->filter_pipeline[j];
1338 cell_pipeline_param->filter_pipeline[j] = cell_pipeline_param->filter_pipeline[j - 1];
1339 cell_pipeline_param->filter_pipeline[j - 1] = tmp;
1340 }
1341
1342 vsp_cmdbuf_insert_command(cmdbuf, CONTEXT_VPP_ID, &cmdbuf->param_mem, VssProcPipelineParameterCommand,
1343 ctx->pipeline_param_offset, sizeof(struct VssProcPipelineParameterBuffer));
1344 out:
1345 return vaStatus;
1346 }
1347
vsp_set_filter_param(context_VPP_p ctx)1348 static VAStatus vsp_set_filter_param(context_VPP_p ctx)
1349 {
1350 VAStatus vaStatus = VA_STATUS_SUCCESS;
1351 vsp_cmdbuf_p cmdbuf = ctx->obj_context->vsp_cmdbuf;
1352 struct VssProcDenoiseParameterBuffer *cell_denoiser_param = (struct VssProcDenoiseParameterBuffer *)cmdbuf->denoise_param_p;
1353 struct VssProcColorEnhancementParameterBuffer *cell_enhancer_param = (struct VssProcColorEnhancementParameterBuffer *)cmdbuf->enhancer_param_p;
1354 struct VssProcSharpenParameterBuffer *cell_sharpen_param = (struct VssProcSharpenParameterBuffer *)cmdbuf->sharpen_param_p;
1355 struct VssProcFrcParameterBuffer *cell_proc_frc_param = (struct VssProcFrcParameterBuffer *)cmdbuf->frc_param_p;
1356 VAProcFilterParameterBufferBase *cur_param = NULL;
1357 VAProcFilterParameterBufferFrameRateConversion *frc_param = NULL;
1358 unsigned int i;
1359 float ratio;
1360
1361 for (i = 0; i < ctx->num_filters; ++i) {
1362 cur_param = (VAProcFilterParameterBufferBase *)ctx->filter_buf[i]->buffer_data;
1363 switch (cur_param->type) {
1364 case VAProcFilterDeblocking:
1365 memcpy(cell_denoiser_param,
1366 &ctx->denoise_deblock_param,
1367 sizeof(ctx->denoise_deblock_param));
1368 cell_denoiser_param->type = VssProcDeblock;
1369
1370 vsp_cmdbuf_insert_command(cmdbuf,
1371 CONTEXT_VPP_ID,
1372 &cmdbuf->param_mem,
1373 VssProcDenoiseParameterCommand,
1374 ctx->denoise_param_offset,
1375 sizeof(struct VssProcDenoiseParameterBuffer));
1376 break;
1377
1378 case VAProcFilterNoiseReduction:
1379 memcpy(cell_denoiser_param,
1380 &ctx->denoise_deblock_param,
1381 sizeof(ctx->denoise_deblock_param));
1382 cell_denoiser_param->type = VssProcDegrain;
1383
1384 vsp_cmdbuf_insert_command(cmdbuf,
1385 CONTEXT_VPP_ID,
1386 &cmdbuf->param_mem,
1387 VssProcDenoiseParameterCommand,
1388 ctx->denoise_param_offset,
1389 sizeof(struct VssProcDenoiseParameterBuffer));
1390 break;
1391
1392 case VAProcFilterSharpening:
1393 memcpy(cell_sharpen_param,
1394 &ctx->sharpen_param,
1395 sizeof(ctx->sharpen_param));
1396
1397 vsp_cmdbuf_insert_command(cmdbuf,
1398 CONTEXT_VPP_ID,
1399 &cmdbuf->param_mem,
1400 VssProcSharpenParameterCommand,
1401 ctx->sharpen_param_offset,
1402 sizeof(struct VssProcSharpenParameterBuffer));
1403 break;
1404
1405 case VAProcFilterColorBalance:
1406 memcpy(cell_enhancer_param,
1407 &ctx->enhancer_param,
1408 sizeof(ctx->enhancer_param));
1409
1410 vsp_cmdbuf_insert_command(cmdbuf,
1411 CONTEXT_VPP_ID,
1412 &cmdbuf->param_mem,
1413 VssProcColorEnhancementParameterCommand,
1414 ctx->enhancer_param_offset,
1415 sizeof(struct VssProcColorEnhancementParameterBuffer));
1416
1417 break;
1418
1419 case VAProcFilterFrameRateConversion:
1420 ctx->frc_buf = ctx->filter_buf[i];
1421
1422 frc_param = (VAProcFilterParameterBufferFrameRateConversion *)ctx->filter_buf[i]->buffer_data;
1423 ratio = frc_param->output_fps / (float)frc_param->input_fps;
1424
1425 /* set the FRC quality */
1426 /* cell_proc_frc_param->quality = VssFrcMediumQuality; */
1427 cell_proc_frc_param->quality = VssFrcHighQuality;
1428
1429 /* check if the input fps is in the range of HW capability */
1430 if (ratio == 2)
1431 cell_proc_frc_param->conversion_rate = VssFrc2xConversionRate;
1432 else if (ratio == 2.5)
1433 cell_proc_frc_param->conversion_rate = VssFrc2_5xConversionRate;
1434 else if (ratio == 4)
1435 cell_proc_frc_param->conversion_rate = VssFrc4xConversionRate;
1436 else if (ratio == 1.25)
1437 cell_proc_frc_param->conversion_rate = VssFrc1_25xConversionRate;
1438 else {
1439 drv_debug_msg(VIDEO_DEBUG_ERROR, "invalid frame rate conversion ratio %f \n", ratio);
1440 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1441 goto out;
1442 }
1443
1444 vsp_cmdbuf_insert_command(cmdbuf,
1445 CONTEXT_VPP_ID,
1446 &cmdbuf->param_mem,
1447 VssProcFrcParameterCommand,
1448 ctx->frc_param_offset,
1449 sizeof(struct VssProcFrcParameterBuffer));
1450 break;
1451 default:
1452 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1453 goto out;
1454 }
1455 }
1456 out:
1457 return vaStatus;
1458 }
1459
check_resolution(int width,int height)1460 static int check_resolution(int width, int height)
1461 {
1462 int ret;
1463 int image_area;
1464
1465 if (height < MIN_SUPPORTED_HEIGHT || height > MAX_SUPPORTED_HEIGHT)
1466 return NOT_SUPPORTED_RESOLUTION;
1467
1468 image_area = height * width;
1469
1470 if (image_area <= QVGA_AREA)
1471 ret = QCIF_TO_QVGA;
1472 else if (image_area <= VGA_AREA)
1473 ret = QVGA_TO_VGA;
1474 else if (image_area <= SD_AREA)
1475 ret = VGA_TO_SD;
1476 else if (image_area <= HD720P_AREA)
1477 ret = SD_TO_720P;
1478 else if (image_area <= HD1080P_AREA)
1479 ret = HD720P_TO_1080P;
1480 else
1481 ret = NOT_SUPPORTED_RESOLUTION;
1482
1483 return ret;
1484 }
1485
1486 /*
1487 * The strength area is:
1488 *
1489 * 0______33______66______100
1490 * LOW MED HIGH
1491 *
1492 * MIN=0; MAX=100; STEP=33
1493 */
check_vpp_strength(int value)1494 static int check_vpp_strength(int value)
1495 {
1496 if (value < MIN_VPP_PARAM || value > MAX_VPP_PARAM)
1497 return INVALID_STRENGTH;
1498
1499 if (value >= MIN_VPP_PARAM &&
1500 value < MIN_VPP_PARAM + STEP_VPP_PARAM)
1501 return LOW_STRENGTH;
1502 else if (value >= MIN_VPP_PARAM + STEP_VPP_PARAM &&
1503 value < MIN_VPP_PARAM + 2 * STEP_VPP_PARAM)
1504 return MEDIUM_STRENGTH;
1505 else
1506 return HIGH_STRENGTH;
1507 }
1508