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
87enum 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
97struct 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
105enum filter_status {
106	FILTER_DISABLED = 0,
107	FILTER_ENABLED
108};
109
110struct 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
118struct 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
124enum 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
134struct 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
212static void vsp_VPP_DestroyContext(object_context_p obj_context);
213static VAStatus vsp_set_pipeline(context_VPP_p ctx);
214static VAStatus vsp_set_filter_param(context_VPP_p ctx);
215static VAStatus vsp__VPP_check_legal_picture(object_context_p obj_context, object_config_p obj_config);
216static int check_resolution(int width, int height);
217static int check_vpp_strength(int value);
218
219static 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
229static 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
248static 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
267static 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;
362out:
363	vsp_VPP_DestroyContext(obj_context);
364
365	if (ctx)
366		free(ctx);
367
368	return vaStatus;
369}
370
371static 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
392static 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
727out:
728	free(pipeline_param);
729	obj_buffer->buffer_data = NULL;
730	obj_buffer->size = 0;
731
732	return vaStatus;
733}
734
735static 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
771static 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
807static 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
835struct format_vtable_s vsp_VPP_vtable = {
836queryConfigAttributes:
837vsp_VPP_QueryConfigAttributes,
838validateConfig:
839vsp_VPP_ValidateConfig,
840createContext:
841vsp_VPP_CreateContext,
842destroyContext:
843vsp_VPP_DestroyContext,
844beginPicture:
845vsp_VPP_BeginPicture,
846renderPicture:
847vsp_VPP_RenderPicture,
848endPicture:
849vsp_VPP_EndPicture
850};
851
852VAStatus 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	}
916err:
917	return vaStatus;
918}
919
920VAStatus 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
1041err:
1042	return vaStatus;
1043}
1044
1045VAStatus 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	}
1303err:
1304	return vaStatus;
1305}
1306
1307static 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
1372finished:
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));
1387out:
1388	return vaStatus;
1389}
1390
1391static 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	}
1499out:
1500	return vaStatus;
1501}
1502
1503static 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 */
1537static 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