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