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