psb_drv_video.c revision c188aa00cc5a56361298b94be444d70bc148eb40
1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Waldo Bastian <waldo.bastian@intel.com>
27 *
28 */
29
30#include <va/va_backend.h>
31#include <va/va_backend_tpi.h>
32#include <va/va_backend_egl.h>
33#ifdef PSBVIDEO_MRFL_VPP
34#include <va/va_backend_vpp.h>
35#endif
36#include <va/va_dricommon.h>
37
38#include "psb_drv_video.h"
39#include "psb_texture.h"
40#include "psb_cmdbuf.h"
41#include "lnc_cmdbuf.h"
42#include "pnw_cmdbuf.h"
43#include "tng_cmdbuf.h"
44#ifdef PSBVIDEO_MRFL_VPP
45#include "vsp_cmdbuf.h"
46#endif
47#include "psb_surface.h"
48
49#ifdef PSBVIDEO_MRST
50#include "psb_MPEG2.h"
51#include "psb_MPEG4.h"
52#include "psb_H264.h"
53#include "psb_VC1.h"
54#include "lnc_MPEG4ES.h"
55#include "lnc_H264ES.h"
56#include "lnc_H263ES.h"
57#endif
58#include "pnw_MPEG2.h"
59#include "pnw_MPEG4.h"
60#include "pnw_H264.h"
61#include "pnw_VC1.h"
62#include "tng_jpegdec.h"
63#include "tng_VP8.h"
64#ifdef PSBVIDEO_MFLD
65#include "pnw_MPEG4ES.h"
66#include "pnw_H264ES.h"
67#include "pnw_H263ES.h"
68#include "pnw_jpeg.h"
69#endif
70#ifdef PSBVIDEO_MRFL
71#include "tng_H264ES.h"
72#include "tng_H263ES.h"
73#include "tng_MPEG4ES.h"
74#include "tng_jpegES.h"
75#endif
76#ifdef PSBVIDEO_MRFL_VPP
77#include "vsp_VPP.h"
78#endif
79#include "psb_output.h"
80#include <stdio.h>
81#include <string.h>
82#include <stdarg.h>
83#include <time.h>
84#include <unistd.h>
85#include <wsbm/wsbm_pool.h>
86#include <wsbm/wsbm_manager.h>
87#include <wsbm/wsbm_util.h>
88#include <wsbm/wsbm_fencemgr.h>
89#include <linux/videodev2.h>
90#include <errno.h>
91
92#include "psb_def.h"
93#include "psb_drv_debug.h"
94#include "psb_ws_driver.h"
95#include "pnw_rotate.h"
96#include "psb_surface_attrib.h"
97
98#ifndef PSB_PACKAGE_VERSION
99#define PSB_PACKAGE_VERSION "Undefined"
100#endif
101
102#define PSB_DRV_VERSION  PSB_PACKAGE_VERSION
103#define PSB_CHG_REVISION "(0X00000071)"
104
105#define PSB_STR_VENDOR_MRST     "Intel GMA500-MRST-" PSB_DRV_VERSION " " PSB_CHG_REVISION
106#define PSB_STR_VENDOR_MFLD     "Intel GMA500-MFLD-" PSB_DRV_VERSION " " PSB_CHG_REVISION
107#define PSB_STR_VENDOR_MRFL     "Intel GMA500-MRFL-" PSB_DRV_VERSION " " PSB_CHG_REVISION
108#define PSB_STR_VENDOR_LEXINGTON     "Intel GMA500-LEXINGTON-" PSB_DRV_VERSION " " PSB_CHG_REVISION
109
110#define MAX_UNUSED_BUFFERS      16
111
112#define PSB_MAX_FLIP_DELAY (1000/30/10)
113
114#include <signal.h>
115
116extern int force_texure_1080p_60fps;
117
118#define EXPORT __attribute__ ((visibility("default")))
119
120#define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
121
122#ifdef PSBVIDEO_MRFL_VPP
123#define INIT_FORMAT_VTABLE format_vtable_p format_vtable = ((profile < PSB_MAX_PROFILES) && (entrypoint < PSB_MAX_ENTRYPOINTS)) ? (profile == VAProfileNone? driver_data->vpp_profile : driver_data->profile2Format[profile][entrypoint]) : NULL;
124#else
125#define INIT_FORMAT_VTABLE format_vtable_p format_vtable = ((profile < PSB_MAX_PROFILES) && (entrypoint < PSB_MAX_ENTRYPOINTS)) ? driver_data->profile2Format[profile][entrypoint] : NULL;
126#endif
127
128#define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
129#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
130#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
131#define BUFFER(id)  ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
132
133#define CONFIG_ID_OFFSET        0x01000000
134#define CONTEXT_ID_OFFSET       0x02000000
135#define SURFACE_ID_OFFSET       0x03000000
136#define BUFFER_ID_OFFSET        0x04000000
137#define IMAGE_ID_OFFSET         0x05000000
138#define SUBPIC_ID_OFFSET        0x06000000
139
140static int psb_get_device_info(VADriverContextP ctx);
141
142
143void psb_init_surface_pvr2dbuf(psb_driver_data_p driver_data);
144void psb_free_surface_pvr2dbuf(psb_driver_data_p driver_data);
145
146VAStatus psb_QueryConfigProfiles(
147    VADriverContextP ctx,
148    VAProfile *profile_list,    /* out */
149    int *num_profiles            /* out */
150)
151{
152    DEBUG_FUNC_ENTER
153    (void) ctx; /* unused */
154    int i = 0;
155    VAStatus vaStatus = VA_STATUS_SUCCESS;
156    INIT_DRIVER_DATA
157
158    if (NULL == profile_list) {
159        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
160        DEBUG_FAILURE;
161        return vaStatus;
162    }
163    if (NULL == num_profiles) {
164        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
165        DEBUG_FAILURE;
166        return vaStatus;
167    }
168#ifdef PSBVIDEO_MRFL_VPP
169    profile_list[i++] = VAProfileNone;
170#endif
171//    profile_list[i++] = VAProfileMPEG2Simple;
172    profile_list[i++] = VAProfileMPEG2Main;
173    profile_list[i++] = VAProfileMPEG4Simple;
174    profile_list[i++] = VAProfileMPEG4AdvancedSimple;
175//    profile_list[i++] = VAProfileMPEG4Main;
176    profile_list[i++] = VAProfileH264Baseline;
177    profile_list[i++] = VAProfileH264Main;
178    profile_list[i++] = VAProfileH264High;
179    profile_list[i++] = VAProfileH264StereoHigh;
180    profile_list[i++] = VAProfileVC1Simple;
181    profile_list[i++] = VAProfileVC1Main;
182    profile_list[i++] = VAProfileVC1Advanced;
183
184    if (IS_MRFL(driver_data)) {
185        profile_list[i++] = VAProfileH263Baseline;
186        profile_list[i++] = VAProfileJPEGBaseline;
187    } else if (IS_MFLD(driver_data)) {
188        profile_list[i++] = VAProfileH263Baseline;
189        profile_list[i++] = VAProfileJPEGBaseline;
190    } else if (IS_MRST(driver_data))
191        profile_list[i++] = VAProfileH263Baseline;
192    profile_list[i++] = VAProfileH264ConstrainedBaseline;
193
194    /* If the assert fails then PSB_MAX_PROFILES needs to be bigger */
195    ASSERT(i <= PSB_MAX_PROFILES);
196    *num_profiles = i;
197    DEBUG_FUNC_EXIT
198    return VA_STATUS_SUCCESS;
199}
200
201VAStatus psb_QueryConfigEntrypoints(
202    VADriverContextP ctx,
203    VAProfile profile,
204    VAEntrypoint  *entrypoint_list,    /* out */
205    int *num_entrypoints        /* out */
206)
207{
208    DEBUG_FUNC_ENTER
209    INIT_DRIVER_DATA
210    VAStatus vaStatus = VA_STATUS_SUCCESS;
211    int entrypoints = 0;
212    int i;
213
214    if (NULL == entrypoint_list) {
215        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
216        DEBUG_FAILURE;
217        return vaStatus;
218    }
219    if (NULL == num_entrypoints || profile >= PSB_MAX_PROFILES) {
220        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
221        DEBUG_FAILURE;
222        return vaStatus;
223    }
224
225    for (i = 0; i < PSB_MAX_ENTRYPOINTS; i++) {
226#ifdef PSBVIDEO_MRFL_VPP
227        if (profile == VAProfileNone && driver_data->vpp_profile &&
228            i == VAEntrypointVideoProc) {
229                entrypoints++;
230                *entrypoint_list++ = i;
231	    } else if (profile != VAProfileNone && driver_data->profile2Format[profile][i]) {
232                entrypoints++;
233                *entrypoint_list++ = i;
234        }
235#else
236        if (driver_data->profile2Format[profile][i]) {
237            entrypoints++;
238            *entrypoint_list++ = i;
239        }
240#endif
241    }
242
243    /* If the assert fails then PSB_MAX_ENTRYPOINTS needs to be bigger */
244    ASSERT(entrypoints <= PSB_MAX_ENTRYPOINTS);
245
246    if (0 == entrypoints) {
247        return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
248    }
249
250    *num_entrypoints = entrypoints;
251    DEBUG_FUNC_EXIT
252    return VA_STATUS_SUCCESS;
253}
254
255/*
256 * Figure out if we should return VA_STATUS_ERROR_UNSUPPORTED_PROFILE
257 * or VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT
258 */
259static VAStatus psb__error_unsupported_profile_entrypoint(psb_driver_data_p driver_data, VAProfile profile, VAEntrypoint entrypoint)
260{
261    /* Does the driver support _any_ entrypoint for this profile? */
262    if (profile < PSB_MAX_PROFILES) {
263        int i;
264
265        /* Do the parameter check for MFLD and MRFLD */
266        if (profile == VAProfileNone)
267            return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
268
269        for (i = 0; i < PSB_MAX_ENTRYPOINTS; i++) {
270            if (driver_data->profile2Format[profile][i]) {
271                /* There is an entrypoint, so the profile is supported */
272                return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
273            }
274        }
275    }
276    return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
277}
278
279VAStatus psb_GetConfigAttributes(
280    VADriverContextP ctx,
281    VAProfile profile,
282    VAEntrypoint entrypoint,
283    VAConfigAttrib *attrib_list,    /* in/out */
284    int num_attribs
285)
286{
287    DEBUG_FUNC_ENTER
288    INIT_DRIVER_DATA
289    INIT_FORMAT_VTABLE
290    int i;
291    VAStatus vaStatus = VA_STATUS_SUCCESS;
292    if (NULL == format_vtable) {
293        return psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint);
294    }
295    if (NULL == attrib_list) {
296        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
297        DEBUG_FAILURE;
298        return vaStatus;
299    }
300    if (num_attribs <= 0) {
301        return VA_STATUS_ERROR_INVALID_PARAMETER;
302    }
303
304    /* Generic attributes */
305    for (i = 0; i < num_attribs; i++) {
306        switch (attrib_list[i].type) {
307        case VAConfigAttribRTFormat:
308            attrib_list[i].value = VA_RT_FORMAT_YUV420;
309            if (entrypoint == VAEntrypointEncPicture)
310                attrib_list[i].value |= VA_RT_FORMAT_YUV422;
311            if ((profile == VAProfileJPEGBaseline) && (entrypoint == VAEntrypointVLD))
312                attrib_list[i].value |= VA_RT_FORMAT_YUV444;
313            break;
314
315        default:
316            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
317            break;
318        }
319    }
320    /* format specific attributes */
321    format_vtable->queryConfigAttributes(profile, entrypoint, attrib_list, num_attribs);
322    DEBUG_FUNC_EXIT
323    return VA_STATUS_SUCCESS;
324}
325
326static VAStatus psb__update_attribute(object_config_p obj_config, VAConfigAttrib *attrib)
327{
328    int i;
329    /* Check existing attributes */
330    for (i = 0; i < obj_config->attrib_count; i++) {
331        if (obj_config->attrib_list[i].type == attrib->type) {
332            /* Update existing attribute */
333            obj_config->attrib_list[i].value = attrib->value;
334            return VA_STATUS_SUCCESS;
335        }
336    }
337    if (obj_config->attrib_count < PSB_MAX_CONFIG_ATTRIBUTES) {
338        i = obj_config->attrib_count;
339        obj_config->attrib_list[i].type = attrib->type;
340        obj_config->attrib_list[i].value = attrib->value;
341        obj_config->attrib_count++;
342        return VA_STATUS_SUCCESS;
343    }
344    return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
345}
346
347static VAStatus psb__validate_config(object_config_p obj_config)
348{
349    int i;
350    /* Check all attributes */
351    for (i = 0; i < obj_config->attrib_count; i++) {
352        switch (obj_config->attrib_list[i].type) {
353        case VAConfigAttribRTFormat:
354            if (!(obj_config->attrib_list[i].value == VA_RT_FORMAT_YUV420
355                  || (obj_config->attrib_list[i].value == VA_RT_FORMAT_YUV422 &&
356                      obj_config->entrypoint == VAEntrypointEncPicture)
357                  || (obj_config->attrib_list[i].value == (VA_RT_FORMAT_YUV444 | VA_RT_FORMAT_YUV420 )))) {
358                return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
359            }
360            break;
361
362        default:
363            /*
364             * Ignore unknown attributes here, it
365             * may be format specific.
366             */
367            break;
368        }
369    }
370    return VA_STATUS_SUCCESS;
371}
372
373static int psb_get_active_entrypoint_number(
374    VADriverContextP ctx,
375    unsigned int entrypoint)
376{
377    INIT_DRIVER_DATA;
378    struct drm_lnc_video_getparam_arg arg;
379    int count = 0;
380    int ret;
381
382    if (VAEntrypointVLD > entrypoint ||
383        entrypoint > VAEntrypointEncPicture) {
384        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s :Invalid entrypoint %d.\n",
385                           __FUNCTION__, entrypoint);
386        return -1;
387    }
388
389    arg.key = PNW_VIDEO_QUERY_ENTRY;
390    arg.value = (uint64_t)((unsigned long) &count);
391    arg.arg = (uint64_t)((unsigned int)&entrypoint);
392    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
393                              &arg, sizeof(arg));
394    if (ret) {
395        drv_debug_msg(VIDEO_DEBUG_ERROR, "%s drmCommandWriteRead fails %d.\n",
396                           __FUNCTION__, ret);
397        return -1;
398    }
399
400    return count;
401}
402
403VAStatus psb_CreateConfig(
404    VADriverContextP ctx,
405    VAProfile profile,
406    VAEntrypoint entrypoint,
407    VAConfigAttrib *attrib_list,
408    int num_attribs,
409    VAConfigID *config_id        /* out */
410)
411{
412    DEBUG_FUNC_ENTER
413    INIT_DRIVER_DATA
414    INIT_FORMAT_VTABLE
415    VAStatus vaStatus = VA_STATUS_SUCCESS;
416    int configID;
417    object_config_p obj_config;
418    int i;
419
420    drv_debug_msg(VIDEO_DEBUG_INIT, "CreateConfig profile:%d, entrypoint:%d, num_attribs:%d.\n",
421        profile, entrypoint, num_attribs);
422    /*echo 8 > /sys/module/pvrsrvkm/parameters/no_ec will disable error concealment*/
423    if ((profile == VAProfileH264ConstrainedBaseline) && (VAEntrypointVLD == entrypoint)) {
424        char ec_disable[2];
425        FILE *ec_fp = fopen("/sys/module/pvrsrvkm/parameters/no_ec", "r");
426        if (ec_fp) {
427            if (fgets(ec_disable, 2, ec_fp) != NULL) {
428                /* force profile to VAProfileH264High */
429                if (strcmp(ec_disable, "8") == 0) {
430                    drv_debug_msg(VIDEO_DEBUG_INIT, "disabled error concealment by setting profile to VAProfileH264High\n");
431                    profile = VAProfileH264High;
432                }
433            }
434            fclose(ec_fp);
435        }
436    }
437
438    if (NULL == config_id) {
439        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
440        return vaStatus;
441    }
442
443    if (num_attribs < 0) {
444        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
445    }
446
447    if (NULL == attrib_list) {
448        vaStatus =  VA_STATUS_ERROR_INVALID_PARAMETER;
449        return vaStatus;
450    }
451
452    if (NULL == format_vtable) {
453        vaStatus = psb__error_unsupported_profile_entrypoint(driver_data, profile, entrypoint);
454    }
455
456    if (VA_STATUS_SUCCESS != vaStatus) {
457        return vaStatus;
458    }
459
460    if ((IS_MFLD(driver_data)) &&
461        ((VAEntrypointEncPicture == entrypoint)
462	|| (VAEntrypointEncSlice == entrypoint))) {
463	int active_slc, active_pic;
464        /* Only allow one encoding entrypoint at the sametime.
465	 * But if video encoding request comes when process JPEG encoding,
466	 * it will wait until current JPEG picture encoding finish.
467	 * Further JPEG encoding should fall back to software path.*/
468	active_slc = psb_get_active_entrypoint_number(ctx, VAEntrypointEncSlice);
469	active_pic = psb_get_active_entrypoint_number(ctx, VAEntrypointEncPicture);
470
471	if (active_slc > 0) {
472	    drv_debug_msg(VIDEO_DEBUG_ERROR, "There already is a active video encoding entrypoint."
473		   "Entrypoint %d isn't available.\n", entrypoint);
474	    return VA_STATUS_ERROR_HW_BUSY;
475	}
476	else if (active_pic > 0 && VAEntrypointEncPicture == entrypoint) {
477	    drv_debug_msg(VIDEO_DEBUG_ERROR, "There already is a active picture encoding entrypoint."
478		   "Entrypoint %d isn't available.\n", entrypoint);
479	    return VA_STATUS_ERROR_HW_BUSY;
480	}
481    }
482
483    configID = object_heap_allocate(&driver_data->config_heap);
484    obj_config = CONFIG(configID);
485    if (NULL == obj_config) {
486        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
487        return vaStatus;
488    }
489
490
491    MEMSET_OBJECT(obj_config, struct object_config_s);
492
493    obj_config->profile = profile;
494    obj_config->format_vtable = format_vtable;
495    obj_config->entrypoint = entrypoint;
496    obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
497    obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
498    obj_config->attrib_count = 1;
499
500    for (i = 0; i < num_attribs; i++) {
501        if (attrib_list[i].type > VAConfigAttribRateControl)
502            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
503
504        vaStatus = psb__update_attribute(obj_config, &(attrib_list[i]));
505        if (VA_STATUS_SUCCESS != vaStatus) {
506            break;
507        }
508    }
509
510    if (VA_STATUS_SUCCESS == vaStatus) {
511        vaStatus = psb__validate_config(obj_config);
512    }
513
514    if (VA_STATUS_SUCCESS == vaStatus) {
515        vaStatus = format_vtable->validateConfig(obj_config);
516    }
517
518    /* Error recovery */
519    if (VA_STATUS_SUCCESS != vaStatus) {
520        object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
521    } else {
522        *config_id = configID;
523    }
524
525#ifdef PSBVIDEO_MSVDX_EC
526    if((getenv("PSB_VIDEO_NOEC") == NULL)
527        && (profile == VAProfileH264ConstrainedBaseline)) {
528        drv_debug_msg(VIDEO_DEBUG_INIT, "profile is VAProfileH264ConstrainedBaseline, error concealment is enabled. \n");
529        driver_data->ec_enabled = 1;
530    } else {
531        driver_data->ec_enabled = 0;
532    }
533#else
534    driver_data->ec_enabled = 0;
535#endif
536    DEBUG_FUNC_EXIT
537    return vaStatus;
538}
539
540VAStatus psb_DestroyConfig(
541    VADriverContextP ctx,
542    VAConfigID config_id
543)
544{
545    DEBUG_FUNC_ENTER
546    INIT_DRIVER_DATA
547    VAStatus vaStatus = VA_STATUS_SUCCESS;
548    object_config_p obj_config;
549
550    obj_config = CONFIG(config_id);
551    if (NULL == obj_config) {
552        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
553        DEBUG_FAILURE;
554        return vaStatus;
555    }
556
557    object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
558    DEBUG_FUNC_EXIT
559    return vaStatus;
560}
561
562VAStatus psb_QueryConfigAttributes(
563    VADriverContextP ctx,
564    VAConfigID config_id,
565    VAProfile *profile,        /* out */
566    VAEntrypoint *entrypoint,     /* out */
567    VAConfigAttrib *attrib_list,    /* out */
568    int *num_attribs        /* out */
569)
570{
571    DEBUG_FUNC_ENTER
572    INIT_DRIVER_DATA
573    VAStatus vaStatus = VA_STATUS_SUCCESS;
574    object_config_p obj_config;
575    int i;
576
577    if (NULL == profile) {
578        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
579        DEBUG_FAILURE;
580        return vaStatus;
581    }
582    if (NULL == entrypoint) {
583        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
584        DEBUG_FAILURE;
585        return vaStatus;
586    }
587    if (NULL == attrib_list) {
588        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
589        DEBUG_FAILURE;
590        return vaStatus;
591    }
592    if (NULL == num_attribs) {
593        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
594        DEBUG_FAILURE;
595        return vaStatus;
596    }
597    obj_config = CONFIG(config_id);
598    if (NULL == obj_config) {
599        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
600        DEBUG_FAILURE;
601        return vaStatus;
602    }
603
604    *profile = obj_config->profile;
605    *entrypoint = obj_config->entrypoint;
606    *num_attribs =  obj_config->attrib_count;
607    for (i = 0; i < obj_config->attrib_count; i++) {
608        attrib_list[i] = obj_config->attrib_list[i];
609    }
610
611    DEBUG_FUNC_EXIT
612    return vaStatus;
613}
614
615void psb__destroy_surface(psb_driver_data_p driver_data, object_surface_p obj_surface)
616{
617    if (NULL != obj_surface) {
618        /* delete subpicture association */
619        psb_SurfaceDeassociateSubpict(driver_data, obj_surface);
620
621	psb_surface_sync(obj_surface->psb_surface);
622        psb_surface_destroy(obj_surface->psb_surface);
623
624        if (obj_surface->psb_surface_rotate) {
625            psb_surface_destroy(obj_surface->psb_surface_rotate);
626        }
627
628        free(obj_surface->psb_surface);
629        object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
630    }
631}
632
633static
634VAStatus psb__checkSurfaceDimensions(psb_driver_data_p driver_data, int width, int height)
635{
636    if (driver_data->video_sd_disabled) {
637        return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
638    }
639    if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) {
640        return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
641    }
642    if (driver_data->video_hd_disabled) {
643        if ((width > 1024) || (height > 576)) {
644            return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
645        }
646    }
647
648    return VA_STATUS_SUCCESS;
649}
650
651
652VAStatus psb_CreateSurfaces2(
653    VADriverContextP ctx,
654    int format,
655    int width,
656    int height,
657    VASurfaceID *surface_list,        /* out */
658    int num_surfaces,
659    VASurfaceAttrib *attrib_list,
660    int num_attribs
661)
662{
663    DEBUG_FUNC_ENTER
664    INIT_DRIVER_DATA
665    VAStatus vaStatus = VA_STATUS_SUCCESS;
666    int i, height_origin, buffer_stride = 0;
667    driver_data->protected = (VA_RT_FORMAT_PROTECTED & format);
668    unsigned long fourcc;
669    unsigned int flags = 0;
670
671    format = format & (~VA_RT_FORMAT_PROTECTED);
672    if (num_surfaces <= 0) {
673        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
674        DEBUG_FAILURE;
675        return vaStatus;
676    }
677    if (NULL == surface_list) {
678        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
679        DEBUG_FAILURE;
680        return vaStatus;
681    }
682
683    if ((attrib_list != NULL) && (num_attribs > 0)) {
684        for (i = 0; i < num_attribs; i++, attrib_list++) {
685            if (!attrib_list)
686                return VA_STATUS_ERROR_INVALID_PARAMETER;
687            switch (attrib_list->type) {
688            default:
689                drv_debug_msg(VIDEO_DEBUG_ERROR, "Unsupported attribute.\n");
690                return VA_STATUS_ERROR_INVALID_PARAMETER;
691            }
692        }
693    }
694
695    /* We only support one format */
696    if ((VA_RT_FORMAT_YUV420 != format)
697        && (VA_RT_FORMAT_YUV422 != format)
698        && (VA_RT_FORMAT_YUV444 != format)) {
699        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
700        DEBUG_FAILURE;
701        return vaStatus;
702    }
703
704    vaStatus = psb__checkSurfaceDimensions(driver_data, width, height);
705    if (VA_STATUS_SUCCESS != vaStatus) {
706        DEBUG_FAILURE;
707        return vaStatus;
708    }
709
710    /* Adjust height to be a multiple of 32 (height of macroblock in interlaced mode) */
711    height_origin = height;
712    height = (height + 0x1f) & ~0x1f;
713
714
715    for (i = 0; i < num_surfaces; i++) {
716        int surfaceID;
717        object_surface_p obj_surface;
718        psb_surface_p psb_surface;
719
720        surfaceID = object_heap_allocate(&driver_data->surface_heap);
721        obj_surface = SURFACE(surfaceID);
722        if (NULL == obj_surface) {
723            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
724            DEBUG_FAILURE;
725            break;
726        }
727        MEMSET_OBJECT(obj_surface, struct object_surface_s);
728
729        obj_surface->surface_id = surfaceID;
730        surface_list[i] = surfaceID;
731        obj_surface->context_id = -1;
732        obj_surface->width = width;
733        obj_surface->height = height;
734        obj_surface->width_r = width;
735        obj_surface->height_r = height;
736        obj_surface->height_origin = height_origin;
737        obj_surface->share_info = NULL;
738
739        psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
740        if (NULL == psb_surface) {
741            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
742            obj_surface->surface_id = VA_INVALID_SURFACE;
743            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
744            DEBUG_FAILURE;
745            break;
746        }
747
748        switch (format) {
749        case VA_RT_FORMAT_YUV444:
750            fourcc = VA_FOURCC_YV32; /* allocate 4 planar */
751            break;
752        case VA_RT_FORMAT_YUV422:
753            fourcc = VA_FOURCC_YV16;
754            break;
755        case VA_RT_FORMAT_YUV420:
756        default:
757            fourcc = VA_FOURCC_NV12;
758            break;
759        }
760
761        flags |= driver_data->protected ? IS_PROTECTED : 0;
762        vaStatus = psb_surface_create(driver_data, width, height, fourcc,
763                                      flags, psb_surface);
764
765        if (VA_STATUS_SUCCESS != vaStatus) {
766            free(psb_surface);
767            object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface);
768            obj_surface->surface_id = VA_INVALID_SURFACE;
769            DEBUG_FAILURE;
770            break;
771        }
772        buffer_stride = psb_surface->stride;
773        /* by default, surface fourcc is NV12 */
774        psb_surface->extra_info[4] = fourcc;
775        obj_surface->psb_surface = psb_surface;
776    }
777
778    /* Error recovery */
779    if (VA_STATUS_SUCCESS != vaStatus) {
780        /* surface_list[i-1] was the last successful allocation */
781        for (; i--;) {
782            object_surface_p obj_surface = SURFACE(surface_list[i]);
783            psb__destroy_surface(driver_data, obj_surface);
784            surface_list[i] = VA_INVALID_SURFACE;
785        }
786        drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaces failed\n");
787        return vaStatus;
788    }
789    DEBUG_FUNC_EXIT
790    return vaStatus;
791}
792
793
794VAStatus psb_DestroySurfaces(
795    VADriverContextP ctx,
796    VASurfaceID *surface_list,
797    int num_surfaces
798)
799{
800    INIT_DRIVER_DATA
801    int i;
802
803    if (num_surfaces <= 0) {
804        return VA_STATUS_ERROR_INVALID_PARAMETER;
805    }
806
807    /* Free PVR2D buffer wrapped from the surfaces */
808    psb_free_surface_pvr2dbuf(driver_data);
809
810    /* Make validation happy */
811    for (i = 0; i < num_surfaces; i++) {
812        object_surface_p obj_surface = SURFACE(surface_list[i]);
813        if (obj_surface == NULL) {
814            return VA_STATUS_ERROR_INVALID_SURFACE;
815        }
816        if (obj_surface->derived_imgcnt > 0) {
817            drv_debug_msg(VIDEO_DEBUG_ERROR, "Some surface is deriving by images\n");
818            return VA_STATUS_ERROR_OPERATION_FAILED;
819        }
820    }
821
822    for (i = 0; i < num_surfaces; i++) {
823        object_surface_p obj_surface = SURFACE(surface_list[i]);
824
825        if (driver_data->cur_displaying_surface == surface_list[i]) {
826            /* Surface is being displaying. Need to stop overlay here */
827            psb_coverlay_stop(ctx);
828        }
829        drv_debug_msg(VIDEO_DEBUG_INIT, "%s : obj_surface->surface_id = 0x%x\n",__FUNCTION__, obj_surface->surface_id);
830        if (obj_surface->share_info) {
831            psb_DestroySurfaceGralloc(obj_surface);
832        }
833        psb__destroy_surface(driver_data, obj_surface);
834        surface_list[i] = VA_INVALID_SURFACE;
835    }
836
837    DEBUG_FUNC_EXIT
838    return VA_STATUS_SUCCESS;
839}
840
841int psb_new_context(psb_driver_data_p driver_data, int ctx_type)
842{
843    struct drm_lnc_video_getparam_arg arg;
844    int ret = 0;
845
846    arg.key = IMG_VIDEO_NEW_CONTEXT;
847    arg.value = (uint64_t)((unsigned long) & ctx_type);
848    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
849                              &arg, sizeof(arg));
850    if (ret != 0)
851        drv_debug_msg(VIDEO_DEBUG_ERROR, "Set context %d failed\n", ctx_type);
852
853    return ret;
854}
855
856#ifdef PSBVIDEO_MSVDX_DEC_TILING
857int psb_update_context(psb_driver_data_p driver_data, unsigned long ctx_type)
858{
859    struct drm_lnc_video_getparam_arg arg;
860    int ret = 0;
861
862    arg.key = IMG_VIDEO_UPDATE_CONTEXT;
863    arg.value = (uint64_t)((unsigned long) & ctx_type);
864    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
865                              &arg, sizeof(arg));
866    if (ret != 0)
867        psb__error_message("Update context %d failed\n", ctx_type);
868
869    return ret;
870}
871#endif
872
873int psb_rm_context(psb_driver_data_p driver_data)
874{
875    struct drm_lnc_video_getparam_arg arg;
876    int tmp;
877    int ret = 0;
878
879    arg.key = IMG_VIDEO_RM_CONTEXT;
880    arg.value = (uint64_t)((unsigned long) & tmp); /* value is ignored */
881    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
882                              &arg, sizeof(arg));
883    if (ret != 0)
884        drv_debug_msg(VIDEO_DEBUG_ERROR, "Remove context failed\n");
885
886    return ret;
887}
888
889unsigned long psb__tile_stride_log2_256(int w)
890{
891    int stride_mode = 0;
892
893    if (512 >= w)
894        stride_mode = 1;
895    else if (1024 >= w)
896        stride_mode = 2;
897    else if (2048 >= w)
898        stride_mode = 3;
899    else if (4096 >= w)
900        stride_mode = 4;
901
902    return stride_mode;
903}
904
905VAStatus psb_CreateContext(
906    VADriverContextP ctx,
907    VAConfigID config_id,
908    int picture_width,
909    int picture_height,
910    int flag,
911    VASurfaceID *render_targets,
912    int num_render_targets,
913    VAContextID *context        /* out */
914)
915{
916    DEBUG_FUNC_ENTER
917    INIT_DRIVER_DATA
918    VAStatus vaStatus = VA_STATUS_SUCCESS;
919    object_config_p obj_config;
920    int cmdbuf_num, encode = 0, proc = 0;
921    int i;
922    drv_debug_msg(VIDEO_DEBUG_INIT, "CreateContext config_id:%d, pic_w:%d, pic_h:%d, flag:%d, num_render_targets:%d.\n",
923        config_id, picture_width, picture_height, flag, num_render_targets);
924
925    if (num_render_targets <= 0) {
926        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
927        DEBUG_FAILURE;
928        return vaStatus;
929    }
930
931    if (NULL == render_targets) {
932        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
933        DEBUG_FAILURE;
934        return vaStatus;
935    }
936    if (NULL == context) {
937        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
938        DEBUG_FAILURE;
939        return vaStatus;
940    }
941
942    vaStatus = psb__checkSurfaceDimensions(driver_data, picture_width, picture_height);
943    if (VA_STATUS_SUCCESS != vaStatus) {
944        DEBUG_FAILURE;
945        return vaStatus;
946    }
947
948    obj_config = CONFIG(config_id);
949    if (NULL == obj_config) {
950        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
951        DEBUG_FAILURE;
952        return vaStatus;
953    }
954
955    int contextID = object_heap_allocate(&driver_data->context_heap);
956    object_context_p obj_context = CONTEXT(contextID);
957    if (NULL == obj_context) {
958        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
959        DEBUG_FAILURE;
960        return vaStatus;
961    }
962
963    *context = contextID;
964
965    MEMSET_OBJECT(obj_context, struct object_context_s);
966
967    obj_context->driver_data = driver_data;
968    obj_context->current_render_target = NULL;
969    obj_context->ec_target = NULL;
970    obj_context->ec_candidate = NULL;
971    obj_context->is_oold = driver_data->is_oold;
972    obj_context->context_id = contextID;
973    obj_context->config_id = config_id;
974    obj_context->picture_width = picture_width;
975    obj_context->picture_height = picture_height;
976    obj_context->num_render_targets = num_render_targets;
977    obj_context->render_targets = (VASurfaceID *) calloc(1, num_render_targets * sizeof(VASurfaceID));
978    if (obj_context->render_targets == NULL) {
979        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
980        DEBUG_FAILURE;
981
982        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
983
984        return vaStatus;
985    }
986
987    /* allocate buffer points for vaRenderPicture */
988    obj_context->num_buffers = 10;
989    obj_context->buffer_list = (object_buffer_p *) calloc(1, sizeof(object_buffer_p) * obj_context->num_buffers);
990    if (obj_context->buffer_list == NULL) {
991        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
992        DEBUG_FAILURE;
993
994        free(obj_context->render_targets);
995        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
996
997        return vaStatus;
998    }
999
1000    memset(obj_context->buffers_unused, 0, sizeof(obj_context->buffers_unused));
1001    memset(obj_context->buffers_unused_count, 0, sizeof(obj_context->buffers_unused_count));
1002    memset(obj_context->buffers_unused_tail, 0, sizeof(obj_context->buffers_unused_tail));
1003    memset(obj_context->buffers_active, 0, sizeof(obj_context->buffers_active));
1004
1005    if (obj_config->entrypoint == VAEntrypointEncSlice
1006        || obj_config->entrypoint == VAEntrypointEncPicture) {
1007        encode = 1;
1008    }
1009#ifdef PSBVIDEO_MRFL_VPP
1010    if (obj_config->entrypoint == VAEntrypointVideoProc)
1011        proc = 1;
1012#endif
1013
1014    if (encode)
1015        cmdbuf_num = LNC_MAX_CMDBUFS_ENCODE;
1016    else if (proc)
1017        cmdbuf_num = VSP_MAX_CMDBUFS;
1018    else
1019        cmdbuf_num = PSB_MAX_CMDBUFS;
1020
1021    for (i = 0; i < num_render_targets; i++) {
1022        object_surface_p obj_surface = SURFACE(render_targets[i]);
1023        psb_surface_p psb_surface;
1024
1025        if (NULL == obj_surface) {
1026            vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1027            DEBUG_FAILURE;
1028            break;
1029        }
1030
1031        psb_surface = obj_surface->psb_surface;
1032
1033        /* Clear format specific surface info */
1034        obj_context->render_targets[i] = render_targets[i];
1035        obj_surface->context_id = contextID; /* Claim ownership of surface */
1036#ifdef PSBVIDEO_MSVDX_DEC_TILING
1037        if (GET_SURFACE_INFO_tiling(psb_surface))
1038            obj_context->msvdx_tile = psb__tile_stride_log2_256(obj_surface->width);
1039#endif
1040#if 0
1041        /* for decode, move the surface into |TT */
1042        if ((encode == 0) && /* decode */
1043            ((psb_surface->buf.pl_flags & DRM_PSB_FLAG_MEM_RAR) == 0)) /* surface not in RAR */
1044            psb_buffer_setstatus(&obj_surface->psb_surface->buf,
1045                                 WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED, DRM_PSB_FLAG_MEM_MMU);
1046#endif
1047    }
1048
1049    obj_context->va_flags = flag;
1050    obj_context->format_vtable = obj_config->format_vtable;
1051    obj_context->format_data = NULL;
1052
1053    if (VA_STATUS_SUCCESS == vaStatus) {
1054        vaStatus = obj_context->format_vtable->createContext(obj_context, obj_config);
1055    }
1056
1057    /* Error recovery */
1058    if (VA_STATUS_SUCCESS != vaStatus) {
1059        obj_context->context_id = -1;
1060        obj_context->config_id = -1;
1061        obj_context->picture_width = 0;
1062        obj_context->picture_height = 0;
1063        free(obj_context->render_targets);
1064        free(obj_context->buffer_list);
1065        obj_context->num_buffers = 0;
1066        obj_context->render_targets = NULL;
1067        obj_context->num_render_targets = 0;
1068        obj_context->va_flags = 0;
1069        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1070
1071        return vaStatus;
1072    }
1073
1074    /* initialize cmdbuf */
1075    for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) {
1076        obj_context->lnc_cmdbuf_list[i] = NULL;
1077    }
1078
1079    for (i = 0; i < PNW_MAX_CMDBUFS_ENCODE; i++) {
1080        obj_context->pnw_cmdbuf_list[i] = NULL;
1081    }
1082
1083#ifdef PSBVIDEO_MRFL
1084    for (i = 0; i < TNG_MAX_CMDBUFS_ENCODE; i++) {
1085        obj_context->tng_cmdbuf_list[i] = NULL;
1086    }
1087#endif
1088
1089#ifdef PSBVIDEO_MRFL_VPP
1090    for (i = 0; i < VSP_MAX_CMDBUFS; i++) {
1091        obj_context->vsp_cmdbuf_list[i] = NULL;
1092    }
1093#endif
1094
1095    for (i = 0; i < PSB_MAX_CMDBUFS; i++) {
1096        obj_context->cmdbuf_list[i] = NULL;
1097    }
1098
1099    for (i = 0; i < cmdbuf_num; i++) {
1100        void  *cmdbuf = NULL;
1101
1102        if (encode) { /* Topaz encode context */
1103#ifdef PSBVIDEO_MRFL
1104            if (IS_MRFL(obj_context->driver_data))
1105                cmdbuf = calloc(1, sizeof(struct tng_cmdbuf_s));
1106#endif
1107#ifdef PSBVIDEO_MFLD
1108            if (IS_MFLD(obj_context->driver_data))
1109                cmdbuf = calloc(1, sizeof(struct pnw_cmdbuf_s));
1110#endif
1111#ifdef PSBVIDEO_MRST
1112            if (IS_MRST(obj_context->driver_data))
1113                cmdbuf = calloc(1, sizeof(struct lnc_cmdbuf_s));
1114#endif
1115        } else if (proc) { /* VSP VPP context */
1116#ifdef PSBVIDEO_MRFL_VPP
1117            if (IS_MRFL(obj_context->driver_data))
1118                cmdbuf = calloc(1, sizeof(struct vsp_cmdbuf_s));
1119#endif
1120        } else /* MSVDX decode context */
1121            cmdbuf =  calloc(1, sizeof(struct psb_cmdbuf_s));
1122
1123        if (NULL == cmdbuf) {
1124            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1125            DEBUG_FAILURE;
1126            break;
1127        }
1128
1129        if (encode) { /* Topaz encode context */
1130
1131#ifdef PSBVIDEO_MRFL
1132            if (IS_MRFL(obj_context->driver_data))
1133                vaStatus = tng_cmdbuf_create(obj_context, driver_data, (tng_cmdbuf_p)cmdbuf);
1134#endif
1135#ifdef PSBVIDEO_MFLD
1136            if (IS_MFLD(obj_context->driver_data))
1137                vaStatus = pnw_cmdbuf_create(obj_context, driver_data, (pnw_cmdbuf_p)cmdbuf);
1138#endif
1139#ifdef PSBVIDEO_MRST
1140            if (IS_MRST(obj_context->driver_data))
1141                vaStatus = lnc_cmdbuf_create(obj_context, driver_data, (lnc_cmdbuf_p)cmdbuf);
1142#endif
1143        } else if (proc) { /* VSP VPP context */
1144#ifdef PSBVIDEO_MRFL_VPP
1145            if (IS_MRFL(obj_context->driver_data))
1146                vaStatus = vsp_cmdbuf_create(obj_context, driver_data, (vsp_cmdbuf_p)cmdbuf);
1147#endif
1148        } else /* MSVDX decode context */
1149            vaStatus = psb_cmdbuf_create(obj_context, driver_data, (psb_cmdbuf_p)cmdbuf);
1150
1151        if (VA_STATUS_SUCCESS != vaStatus) {
1152            free(cmdbuf);
1153            DEBUG_FAILURE;
1154            break;
1155        }
1156
1157        if (encode) { /* Topaz encode context */
1158            if (i >= LNC_MAX_CMDBUFS_ENCODE) {
1159                free(cmdbuf);
1160                DEBUG_FAILURE;
1161                break;
1162            }
1163
1164#ifdef PSBVIDEO_MRFL
1165            if (IS_MRFL(obj_context->driver_data))
1166                obj_context->tng_cmdbuf_list[i] = (tng_cmdbuf_p)cmdbuf;
1167#endif
1168#ifdef PSBVIDEO_MFLD
1169            if (IS_MFLD(obj_context->driver_data))
1170                obj_context->pnw_cmdbuf_list[i] = (pnw_cmdbuf_p)cmdbuf;
1171#endif
1172#ifdef PSBVIDEO_MRST
1173            if (IS_MRST(obj_context->driver_data))
1174                obj_context->lnc_cmdbuf_list[i] = (lnc_cmdbuf_p)cmdbuf;
1175#endif
1176        } else if (proc) { /* VSP VPP context */
1177#ifdef PSBVIDEO_MRFL_VPP
1178            if (IS_MRFL(obj_context->driver_data))
1179                obj_context->vsp_cmdbuf_list[i] = (vsp_cmdbuf_p)cmdbuf;
1180#endif
1181        } else /* MSVDX decode context */
1182            obj_context->cmdbuf_list[i] = (psb_cmdbuf_p)cmdbuf;
1183    }
1184
1185    obj_context->cmdbuf_current = -1;
1186    obj_context->cmdbuf = NULL;
1187    obj_context->lnc_cmdbuf = NULL;
1188    obj_context->pnw_cmdbuf = NULL;
1189    obj_context->tng_cmdbuf = NULL;
1190#ifdef PSBVIDEO_MRFL_VPP
1191    obj_context->vsp_cmdbuf = NULL;
1192#endif
1193    obj_context->frame_count = 0;
1194    obj_context->slice_count = 0;
1195    obj_context->msvdx_context = ((driver_data->msvdx_context_base & 0xff0000) >> 16) |
1196                                 ((contextID & 0xff000000) >> 16);
1197#ifdef ANDROID
1198    obj_context->msvdx_context = ((driver_data->drm_fd & 0xf) << 4) |
1199                                 ((unsigned int)gettid() & 0xf);
1200#endif
1201    obj_context->profile = obj_config->profile;
1202    obj_context->entry_point = obj_config->entrypoint;
1203
1204    /* Error recovery */
1205    if (VA_STATUS_SUCCESS != vaStatus) {
1206        if (cmdbuf_num > LNC_MAX_CMDBUFS_ENCODE)
1207            cmdbuf_num = LNC_MAX_CMDBUFS_ENCODE;
1208        for (i = 0; i < cmdbuf_num; i++) {
1209            if (obj_context->lnc_cmdbuf_list[i]) {
1210                lnc_cmdbuf_destroy(obj_context->lnc_cmdbuf_list[i]);
1211                free(obj_context->lnc_cmdbuf_list[i]);
1212                obj_context->lnc_cmdbuf_list[i] = NULL;
1213            }
1214            if (obj_context->pnw_cmdbuf_list[i]) {
1215                pnw_cmdbuf_destroy(obj_context->pnw_cmdbuf_list[i]);
1216                free(obj_context->pnw_cmdbuf_list[i]);
1217                obj_context->pnw_cmdbuf_list[i] = NULL;
1218            }
1219#ifdef PSBVIDEO_MRFL
1220            if (obj_context->tng_cmdbuf_list[i]) {
1221                tng_cmdbuf_destroy(obj_context->tng_cmdbuf_list[i]);
1222                free(obj_context->tng_cmdbuf_list[i]);
1223                obj_context->tng_cmdbuf_list[i] = NULL;
1224            }
1225#endif
1226            if (obj_context->cmdbuf_list[i]) {
1227                psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]);
1228                free(obj_context->cmdbuf_list[i]);
1229                obj_context->cmdbuf_list[i] = NULL;
1230            }
1231#ifdef PSBVIDEO_MRFL_VPP
1232            if (obj_context->vsp_cmdbuf_list[i]) {
1233                vsp_cmdbuf_destroy(obj_context->vsp_cmdbuf_list[i]);
1234                free(obj_context->vsp_cmdbuf_list[i]);
1235                obj_context->vsp_cmdbuf_list[i] = NULL;
1236            }
1237#endif
1238        }
1239
1240        obj_context->cmdbuf = NULL;
1241        obj_context->lnc_cmdbuf = NULL;
1242#ifdef PSBVIDEO_MRFL_VPP
1243        obj_context->vsp_cmdbuf = NULL;
1244#endif
1245
1246        obj_context->context_id = -1;
1247        obj_context->config_id = -1;
1248        obj_context->picture_width = 0;
1249        obj_context->picture_height = 0;
1250        free(obj_context->render_targets);
1251        free(obj_context->buffer_list);
1252        obj_context->num_buffers = 0;
1253        obj_context->render_targets = NULL;
1254        obj_context->num_render_targets = 0;
1255        obj_context->va_flags = 0;
1256        object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1257    }
1258    obj_context->ctp_type = ((obj_config->profile << 8) |
1259                             obj_config->entrypoint | driver_data->protected);
1260
1261    if (!encode) {
1262        obj_context->ctp_type |= ((obj_context->msvdx_tile & 0xff) << 16);
1263    }
1264
1265    psb_new_context(driver_data, obj_context->ctp_type | driver_data->protected);
1266
1267    DEBUG_FUNC_EXIT
1268    return vaStatus;
1269}
1270
1271static VAStatus psb__allocate_malloc_buffer(object_buffer_p obj_buffer, int size)
1272{
1273    VAStatus vaStatus = VA_STATUS_SUCCESS;
1274
1275    obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size);
1276    if (NULL == obj_buffer->buffer_data) {
1277        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1278        DEBUG_FAILURE;
1279    }
1280    return vaStatus;
1281}
1282
1283static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer);
1284
1285static VAStatus psb__allocate_BO_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer, int size, unsigned char *data, VABufferType type)
1286{
1287    VAStatus vaStatus = VA_STATUS_SUCCESS;
1288
1289    ASSERT(NULL == obj_buffer->buffer_data);
1290
1291    if (obj_buffer->psb_buffer && (psb_bs_queued == obj_buffer->psb_buffer->status)) {
1292        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Abandoning BO for buffer %08x type %s\n", obj_buffer->base.id,
1293                                 buffer_type_to_string(obj_buffer->type));
1294        /* need to set psb_buffer aside and get another one */
1295        obj_buffer->psb_buffer->status = psb_bs_abandoned;
1296        obj_buffer->psb_buffer = NULL;
1297        obj_buffer->size = 0;
1298        obj_buffer->alloc_size = 0;
1299    }
1300
1301    if (type == VAProtectedSliceDataBufferType) {
1302        if (obj_buffer->psb_buffer) {
1303            drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: old RAR slice buffer with RAR handle 0%08x, current RAR handle 0x%08x\n",
1304                                     obj_buffer->psb_buffer->rar_handle, (uint32_t)data);
1305            drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: force old RAR buffer destroy and new buffer re-allocation by set size=0\n");
1306            obj_buffer->alloc_size = 0;
1307        }
1308    }
1309
1310    if (obj_buffer->alloc_size < (unsigned int)size) {
1311        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Buffer size mismatch: Need %d, currently have %d\n", size, obj_buffer->alloc_size);
1312        if (obj_buffer->psb_buffer) {
1313            if (obj_buffer->buffer_data) {
1314                psb__unmap_buffer(obj_buffer);
1315            }
1316            psb_buffer_destroy(obj_buffer->psb_buffer);
1317            obj_buffer->alloc_size = 0;
1318        } else {
1319            obj_buffer->psb_buffer = (psb_buffer_p) calloc(1, sizeof(struct psb_buffer_s));
1320            if (NULL == obj_buffer->psb_buffer) {
1321                vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1322                DEBUG_FAILURE;
1323            }
1324        }
1325        if (VA_STATUS_SUCCESS == vaStatus) {
1326            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate new GPU buffers for vaCreateBuffer:type=%s,size=%d.\n",
1327                                     buffer_type_to_string(obj_buffer->type), size);
1328
1329            size = (size + 0x7fff) & ~0x7fff; /* Round up */
1330            if (obj_buffer->type == VAImageBufferType) /* Xserver side PutSurface, Image/subpicture buffer
1331                                                        * should be shared between two process
1332                                                        */
1333                vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu_shared, obj_buffer->psb_buffer);
1334            else if (obj_buffer->type == VAProtectedSliceDataBufferType) {
1335                vaStatus = psb_buffer_reference_imr(driver_data, (uint32_t)data, obj_buffer->psb_buffer);
1336            }
1337            else if (obj_buffer->type == VAEncCodedBufferType)
1338#ifdef ANDROID
1339                vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu_cached, obj_buffer->psb_buffer);
1340#else
1341                vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, obj_buffer->psb_buffer);
1342#endif
1343            else
1344                vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, obj_buffer->psb_buffer);
1345            if (VA_STATUS_SUCCESS != vaStatus) {
1346                free(obj_buffer->psb_buffer);
1347                obj_buffer->psb_buffer = NULL;
1348                DEBUG_FAILURE;
1349            } else {
1350                obj_buffer->alloc_size = size;
1351            }
1352        }
1353    }
1354    return vaStatus;
1355}
1356
1357static VAStatus psb__map_buffer(object_buffer_p obj_buffer)
1358{
1359    if (obj_buffer->psb_buffer) {
1360        return psb_buffer_map(obj_buffer->psb_buffer, &obj_buffer->buffer_data);
1361    }
1362    return VA_STATUS_SUCCESS;
1363}
1364
1365static VAStatus psb__unmap_buffer(object_buffer_p obj_buffer)
1366{
1367    if (obj_buffer->psb_buffer) {
1368        obj_buffer->buffer_data = NULL;
1369        return psb_buffer_unmap(obj_buffer->psb_buffer);
1370    }
1371    return VA_STATUS_SUCCESS;
1372}
1373
1374static void psb__destroy_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer)
1375{
1376    if (obj_buffer->psb_buffer) {
1377        if (obj_buffer->buffer_data) {
1378            psb__unmap_buffer(obj_buffer);
1379        }
1380        psb_buffer_destroy(obj_buffer->psb_buffer);
1381        free(obj_buffer->psb_buffer);
1382        obj_buffer->psb_buffer = NULL;
1383    }
1384
1385    if (NULL != obj_buffer->buffer_data) {
1386        free(obj_buffer->buffer_data);
1387        obj_buffer->buffer_data = NULL;
1388        obj_buffer->size = 0;
1389    }
1390
1391    object_heap_free(&driver_data->buffer_heap, (object_base_p) obj_buffer);
1392}
1393
1394void psb__suspend_buffer(psb_driver_data_p driver_data, object_buffer_p obj_buffer)
1395{
1396    if (obj_buffer->context) {
1397        VABufferType type = obj_buffer->type;
1398        object_context_p obj_context = obj_buffer->context;
1399
1400        /* Remove buffer from active list */
1401        *obj_buffer->pptr_prev_next = obj_buffer->ptr_next;
1402
1403        /* Add buffer to tail of unused list */
1404        obj_buffer->ptr_next = NULL;
1405        obj_buffer->last_used = obj_context->frame_count;
1406        if (obj_context->buffers_unused_tail[type]) {
1407            obj_buffer->pptr_prev_next = &(obj_context->buffers_unused_tail[type]->ptr_next);
1408        } else {
1409            obj_buffer->pptr_prev_next = &(obj_context->buffers_unused[type]);
1410        }
1411        *obj_buffer->pptr_prev_next = obj_buffer;
1412        obj_context->buffers_unused_tail[type] = obj_buffer;
1413        obj_context->buffers_unused_count[type]++;
1414
1415        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Adding buffer %08x type %s to unused list. unused count = %d\n", obj_buffer->base.id,
1416                                 buffer_type_to_string(obj_buffer->type), obj_context->buffers_unused_count[type]);
1417
1418        object_heap_suspend_object((object_base_p) obj_buffer, 1); /* suspend */
1419        return;
1420    }
1421
1422    if (obj_buffer->psb_buffer && (psb_bs_queued == obj_buffer->psb_buffer->status)) {
1423        /* need to set psb_buffer aside */
1424        obj_buffer->psb_buffer->status = psb_bs_abandoned;
1425        obj_buffer->psb_buffer = NULL;
1426    }
1427
1428    psb__destroy_buffer(driver_data, obj_buffer);
1429}
1430
1431static void psb__destroy_context(psb_driver_data_p driver_data, object_context_p obj_context)
1432{
1433    int encode, i;
1434
1435    if (obj_context->entry_point == VAEntrypointEncSlice)
1436        encode = 1;
1437    else
1438        encode = 0;
1439
1440    obj_context->format_vtable->destroyContext(obj_context);
1441
1442    for (i = 0; i < PSB_MAX_BUFFERTYPES; i++) {
1443        object_buffer_p obj_buffer;
1444        obj_buffer = obj_context->buffers_active[i];
1445        for (; obj_buffer; obj_buffer = obj_buffer->ptr_next) {
1446            drv_debug_msg(VIDEO_DEBUG_INIT, "%s: destroying active buffer %08x\n", __FUNCTION__, obj_buffer->base.id);
1447            psb__destroy_buffer(driver_data, obj_buffer);
1448        }
1449        obj_buffer = obj_context->buffers_unused[i];
1450        for (; obj_buffer; obj_buffer = obj_buffer->ptr_next) {
1451            drv_debug_msg(VIDEO_DEBUG_INIT, "%s: destroying unused buffer %08x\n", __FUNCTION__, obj_buffer->base.id);
1452            psb__destroy_buffer(driver_data, obj_buffer);
1453        }
1454        obj_context->buffers_unused_count[i] = 0;
1455    }
1456
1457    for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) {
1458        if (obj_context->lnc_cmdbuf_list[i]) {
1459            lnc_cmdbuf_destroy(obj_context->lnc_cmdbuf_list[i]);
1460            free(obj_context->lnc_cmdbuf_list[i]);
1461            obj_context->lnc_cmdbuf_list[i] = NULL;
1462        }
1463    }
1464
1465    for (i = 0; i < LNC_MAX_CMDBUFS_ENCODE; i++) {
1466        if (obj_context->pnw_cmdbuf_list[i]) {
1467            pnw_cmdbuf_destroy(obj_context->pnw_cmdbuf_list[i]);
1468            free(obj_context->pnw_cmdbuf_list[i]);
1469            obj_context->pnw_cmdbuf_list[i] = NULL;
1470        }
1471    }
1472#ifdef PSBVIDEO_MRFL
1473    for (i = 0; i < TNG_MAX_CMDBUFS_ENCODE; i++) {
1474        if (obj_context->tng_cmdbuf_list[i]) {
1475            tng_cmdbuf_destroy(obj_context->tng_cmdbuf_list[i]);
1476            free(obj_context->tng_cmdbuf_list[i]);
1477            obj_context->tng_cmdbuf_list[i] = NULL;
1478        }
1479    }
1480#endif
1481#ifdef PSBVIDEO_MRFL_VPP
1482    for (i = 0; i < VSP_MAX_CMDBUFS; i++) {
1483        if (obj_context->vsp_cmdbuf_list[i]) {
1484            vsp_cmdbuf_destroy(obj_context->vsp_cmdbuf_list[i]);
1485            free(obj_context->vsp_cmdbuf_list[i]);
1486            obj_context->vsp_cmdbuf_list[i] = NULL;
1487        }
1488    }
1489#endif
1490
1491    for (i = 0; i < PSB_MAX_CMDBUFS; i++) {
1492        if (obj_context->cmdbuf_list[i]) {
1493            psb_cmdbuf_destroy(obj_context->cmdbuf_list[i]);
1494            free(obj_context->cmdbuf_list[i]);
1495            obj_context->cmdbuf_list[i] = NULL;
1496        }
1497    }
1498    obj_context->cmdbuf = NULL;
1499    obj_context->lnc_cmdbuf = NULL;
1500#ifdef PSBVIDEO_MRFL_VPP
1501    obj_context->vsp_cmdbuf = NULL;
1502#endif
1503
1504    obj_context->context_id = -1;
1505    obj_context->config_id = -1;
1506    obj_context->picture_width = 0;
1507    obj_context->picture_height = 0;
1508    if (obj_context->render_targets)
1509        free(obj_context->render_targets);
1510    obj_context->render_targets = NULL;
1511    obj_context->num_render_targets = 0;
1512    obj_context->va_flags = 0;
1513
1514    obj_context->current_render_target = NULL;
1515    obj_context->ec_target = NULL;
1516    obj_context->ec_candidate = NULL;
1517    if (obj_context->buffer_list)
1518        free(obj_context->buffer_list);
1519    obj_context->num_buffers = 0;
1520
1521    object_heap_free(&driver_data->context_heap, (object_base_p) obj_context);
1522
1523    psb_rm_context(driver_data);
1524}
1525
1526VAStatus psb_DestroyContext(
1527    VADriverContextP ctx,
1528    VAContextID context
1529)
1530{
1531    DEBUG_FUNC_ENTER
1532    INIT_DRIVER_DATA
1533    VAStatus vaStatus = VA_STATUS_SUCCESS;
1534    object_context_p obj_context = CONTEXT(context);
1535    if (NULL == obj_context) {
1536        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1537        DEBUG_FAILURE;
1538        return vaStatus;
1539    }
1540
1541    psb__destroy_context(driver_data, obj_context);
1542
1543    DEBUG_FUNC_EXIT
1544    return vaStatus;
1545}
1546
1547VAStatus psb__CreateBuffer(
1548    psb_driver_data_p driver_data,
1549    object_context_p obj_context,       /* in */
1550    VABufferType type,  /* in */
1551    unsigned int size,          /* in */
1552    unsigned int num_elements, /* in */
1553    unsigned char *data,         /* in */
1554    VABufferID *buf_desc    /* out */
1555)
1556{
1557    DEBUG_FUNC_ENTER
1558    VAStatus vaStatus = VA_STATUS_SUCCESS;
1559    int bufferID;
1560    object_buffer_p obj_buffer = obj_context ? obj_context->buffers_unused[type] : NULL;
1561    int unused_count = obj_context ? obj_context->buffers_unused_count[type] : 0;
1562
1563
1564    /*
1565     * Buffer Management
1566     * For each buffer type, maintain
1567     *   - a LRU sorted list of unused buffers
1568     *   - a list of active buffers
1569     * We only create a new buffer when
1570     *   - no unused buffers are available
1571     *   - the last unused buffer is still queued
1572     *   - the last unused buffer was used very recently and may still be fenced
1573     *      - used recently is defined as within the current frame_count (subject to tweaks)
1574     *
1575     * The buffer that is returned will be moved to the list of active buffers
1576     *   - vaDestroyBuffer and vaRenderPicture will move the active buffer back to the list of unused buffers
1577    */
1578    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Requesting buffer creation, size=%d,elements=%d,type=%s\n", size, num_elements,
1579                             buffer_type_to_string(type));
1580
1581    /* on MFLD, data is IMR offset, and could be 0 */
1582    /*
1583    if ((type == VAProtectedSliceDataBufferType) && (data == NULL)) {
1584        drv_debug_msg(VIDEO_DEBUG_ERROR, "RAR: Create protected slice buffer, but RAR handle is NULL\n");
1585        return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE ;
1586    }
1587    */
1588
1589    if (obj_buffer && obj_buffer->psb_buffer) {
1590        if (psb_bs_queued == obj_buffer->psb_buffer->status) {
1591            /* Buffer is still queued, allocate new buffer instead */
1592            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Skipping idle buffer %08x, still queued\n", obj_buffer->base.id);
1593            obj_buffer = NULL;
1594        } else if ((obj_buffer->last_used == obj_context->frame_count) && (unused_count < MAX_UNUSED_BUFFERS)) {
1595            /* Buffer was used for this frame, allocate new buffer instead */
1596            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Skipping idle buffer %08x, recently used. Unused = %d\n", obj_buffer->base.id, unused_count);
1597            obj_buffer = NULL;
1598        } else if (obj_context->frame_count - obj_buffer->last_used < 5) {
1599            /* Buffer was used for previous frame, allocate new buffer instead */
1600            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Skipping idle buffer %08x used by frame %d. Unused = %d\n", obj_buffer->base.id, obj_buffer->last_used, unused_count);
1601            obj_buffer = NULL;
1602        }
1603    }
1604
1605    if (obj_buffer) {
1606        bufferID = obj_buffer->base.id;
1607        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Reusing buffer %08x type %s from unused list. Unused = %d\n", bufferID,
1608                                 buffer_type_to_string(type), unused_count);
1609
1610        /* Remove from unused list */
1611        obj_context->buffers_unused[type] = obj_buffer->ptr_next;
1612        if (obj_context->buffers_unused[type]) {
1613            obj_context->buffers_unused[type]->pptr_prev_next = &(obj_context->buffers_unused[type]);
1614            ASSERT(obj_context->buffers_unused_tail[type] != obj_buffer);
1615        } else {
1616            ASSERT(obj_context->buffers_unused_tail[type] == obj_buffer);
1617            obj_context->buffers_unused_tail[type] = 0;
1618        }
1619        obj_context->buffers_unused_count[type]--;
1620
1621        object_heap_suspend_object((object_base_p)obj_buffer, 0); /* Make BufferID valid again */
1622        ASSERT(type == obj_buffer->type);
1623        ASSERT(obj_context == obj_buffer->context);
1624    } else {
1625        bufferID = object_heap_allocate(&driver_data->buffer_heap);
1626        obj_buffer = BUFFER(bufferID);
1627        if (NULL == obj_buffer) {
1628            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1629            DEBUG_FAILURE;
1630            return vaStatus;
1631        }
1632
1633        MEMSET_OBJECT(obj_buffer, struct object_buffer_s);
1634
1635        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocating new buffer %08x type %s.\n", bufferID, buffer_type_to_string(type));
1636        obj_buffer->type = type;
1637        obj_buffer->buffer_data = NULL;
1638        obj_buffer->psb_buffer = NULL;
1639        obj_buffer->size = 0;
1640        obj_buffer->max_num_elements = 0;
1641        obj_buffer->alloc_size = 0;
1642        obj_buffer->context = obj_context;
1643    }
1644    if (obj_context) {
1645        /* Add to front of active list */
1646        obj_buffer->ptr_next = obj_context->buffers_active[type];
1647        if (obj_buffer->ptr_next) {
1648            obj_buffer->ptr_next->pptr_prev_next = &(obj_buffer->ptr_next);
1649        }
1650        obj_buffer->pptr_prev_next = &(obj_context->buffers_active[type]);
1651        *obj_buffer->pptr_prev_next = obj_buffer;
1652    }
1653
1654    switch (obj_buffer->type) {
1655    case VABitPlaneBufferType:
1656    case VASliceDataBufferType:
1657    case VAResidualDataBufferType:
1658    case VAImageBufferType:
1659    case VASliceGroupMapBufferType:
1660    case VAEncCodedBufferType:
1661    case VAProtectedSliceDataBufferType:
1662        vaStatus = psb__allocate_BO_buffer(driver_data, obj_buffer, size * num_elements, data, obj_buffer->type);
1663        DEBUG_FAILURE;
1664        break;
1665    case VAPictureParameterBufferType:
1666    case VAIQMatrixBufferType:
1667    case VASliceParameterBufferType:
1668    case VAMacroblockParameterBufferType:
1669    case VADeblockingParameterBufferType:
1670    case VAEncPackedHeaderParameterBufferType:
1671    case VAEncPackedHeaderDataBufferType:
1672    case VAEncSequenceParameterBufferType:
1673    case VAEncPictureParameterBufferType:
1674    case VAEncSliceParameterBufferType:
1675    case VAQMatrixBufferType:
1676    case VAEncMiscParameterBufferType:
1677    case VAProbabilityBufferType:
1678    case VAHuffmanTableBufferType:
1679#ifdef PSBVIDEO_MRFL_VPP
1680    case VAProcPipelineParameterBufferType:
1681    case VAProcFilterParameterBufferType:
1682#endif
1683        drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate new malloc buffers for vaCreateBuffer:type=%s,size=%d, buffer_data=%p.\n",
1684                                 buffer_type_to_string(type), size, obj_buffer->buffer_data);
1685        vaStatus = psb__allocate_malloc_buffer(obj_buffer, size * num_elements);
1686        DEBUG_FAILURE;
1687        break;
1688
1689    default:
1690        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1691        DEBUG_FAILURE;
1692        break;;
1693    }
1694
1695    if (VA_STATUS_SUCCESS == vaStatus) {
1696        obj_buffer->size = size;
1697        obj_buffer->max_num_elements = num_elements;
1698        obj_buffer->num_elements = num_elements;
1699        if (data && (obj_buffer->type != VAProtectedSliceDataBufferType)) {
1700            vaStatus = psb__map_buffer(obj_buffer);
1701            if (VA_STATUS_SUCCESS == vaStatus) {
1702                memcpy(obj_buffer->buffer_data, data, size * num_elements);
1703
1704                psb__unmap_buffer(obj_buffer);
1705            }
1706        }
1707    }
1708    if (VA_STATUS_SUCCESS == vaStatus) {
1709        *buf_desc = bufferID;
1710    } else {
1711        psb__destroy_buffer(driver_data, obj_buffer);
1712    }
1713
1714    DEBUG_FUNC_EXIT
1715    return vaStatus;
1716}
1717
1718VAStatus psb_CreateBuffer(
1719    VADriverContextP ctx,
1720    VAContextID context,        /* in */
1721    VABufferType type,  /* in */
1722    unsigned int size,          /* in */
1723    unsigned int num_elements, /* in */
1724    void *data,         /* in */
1725    VABufferID *buf_desc    /* out */
1726)
1727{
1728    DEBUG_FUNC_ENTER
1729    INIT_DRIVER_DATA
1730    VAStatus vaStatus = VA_STATUS_SUCCESS;
1731
1732    if (num_elements <= 0) {
1733        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1734        DEBUG_FAILURE;
1735        return vaStatus;
1736    }
1737
1738    switch (type) {
1739    case VABitPlaneBufferType:
1740    case VASliceDataBufferType:
1741    case VAProtectedSliceDataBufferType:
1742    case VAResidualDataBufferType:
1743    case VASliceGroupMapBufferType:
1744    case VAPictureParameterBufferType:
1745    case VAIQMatrixBufferType:
1746    case VASliceParameterBufferType:
1747    case VAMacroblockParameterBufferType:
1748    case VADeblockingParameterBufferType:
1749    case VAEncCodedBufferType:
1750    case VAEncSequenceParameterBufferType:
1751    case VAEncPictureParameterBufferType:
1752    case VAEncSliceParameterBufferType:
1753    case VAEncPackedHeaderParameterBufferType:
1754    case VAEncPackedHeaderDataBufferType:
1755    case VAQMatrixBufferType:
1756    case VAEncMiscParameterBufferType:
1757    case VAProbabilityBufferType:
1758    case VAHuffmanTableBufferType:
1759#ifdef PSBVIDEO_MRFL_VPP
1760    case VAProcPipelineParameterBufferType:
1761    case VAProcFilterParameterBufferType:
1762#endif
1763        break;
1764
1765    default:
1766        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1767        DEBUG_FAILURE;
1768        return vaStatus;
1769    }
1770
1771    object_context_p obj_context = CONTEXT(context);
1772    if (NULL == obj_context) {
1773        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1774        DEBUG_FAILURE;
1775        return vaStatus;
1776    }
1777    if (NULL == buf_desc) {
1778        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1779        DEBUG_FAILURE;
1780        return vaStatus;
1781    }
1782
1783    vaStatus = psb__CreateBuffer(driver_data, obj_context, type, size, num_elements, data, buf_desc);
1784
1785    DEBUG_FUNC_EXIT
1786    return vaStatus;
1787}
1788
1789
1790VAStatus psb_BufferInfo(
1791    VADriverContextP ctx,
1792    VABufferID buf_id,  /* in */
1793    VABufferType *type, /* out */
1794    unsigned int *size,         /* out */
1795    unsigned int *num_elements /* out */
1796)
1797{
1798    DEBUG_FUNC_ENTER
1799    INIT_DRIVER_DATA
1800    VAStatus vaStatus = VA_STATUS_SUCCESS;
1801
1802    object_buffer_p obj_buffer = BUFFER(buf_id);
1803    if (NULL == obj_buffer) {
1804        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
1805        DEBUG_FAILURE;
1806        return vaStatus;
1807    }
1808
1809    *type = obj_buffer->type;
1810    *size = obj_buffer->size;
1811    *num_elements = obj_buffer->num_elements;
1812    DEBUG_FUNC_EXIT
1813    return VA_STATUS_SUCCESS;
1814}
1815
1816
1817VAStatus psb_BufferSetNumElements(
1818    VADriverContextP ctx,
1819    VABufferID buf_id,    /* in */
1820    unsigned int num_elements    /* in */
1821)
1822{
1823    DEBUG_FUNC_ENTER
1824    INIT_DRIVER_DATA
1825    VAStatus vaStatus = VA_STATUS_SUCCESS;
1826    object_buffer_p obj_buffer = BUFFER(buf_id);
1827    if (NULL == obj_buffer) {
1828        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
1829        DEBUG_FAILURE;
1830        return vaStatus;
1831    }
1832
1833    if ((num_elements <= 0) || (num_elements > obj_buffer->max_num_elements)) {
1834        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1835    }
1836    if (VA_STATUS_SUCCESS == vaStatus) {
1837        obj_buffer->num_elements = num_elements;
1838    }
1839
1840    DEBUG_FUNC_EXIT
1841    return vaStatus;
1842}
1843
1844VAStatus psb_MapBuffer(
1845    VADriverContextP ctx,
1846    VABufferID buf_id,    /* in */
1847    void **pbuf         /* out */
1848)
1849{
1850    DEBUG_FUNC_ENTER
1851    INIT_DRIVER_DATA
1852    VAStatus vaStatus = VA_STATUS_SUCCESS;
1853    object_buffer_p obj_buffer = BUFFER(buf_id);
1854    if (NULL == obj_buffer) {
1855        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
1856        DEBUG_FAILURE;
1857        return vaStatus;
1858    }
1859
1860
1861    if (NULL == pbuf) {
1862        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
1863        DEBUG_FAILURE;
1864        return vaStatus;
1865    }
1866
1867    vaStatus = psb__map_buffer(obj_buffer);
1868    if (VA_STATUS_SUCCESS != vaStatus) {
1869        DEBUG_FAILURE;
1870        return vaStatus;
1871    }
1872
1873    if (NULL != obj_buffer->buffer_data) {
1874        *pbuf = obj_buffer->buffer_data;
1875
1876        /* specifically for Topaz encode
1877         * write validate coded data offset in CodedBuffer
1878         */
1879        if (obj_buffer->type == VAEncCodedBufferType)
1880            psb_codedbuf_map_mangle(ctx, obj_buffer, pbuf);
1881        /* *(IMG_UINT32 *)((unsigned char *)obj_buffer->buffer_data + 4) = 16; */
1882    } else {
1883        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1884    }
1885    DEBUG_FUNC_EXIT
1886    return vaStatus;
1887}
1888
1889VAStatus psb_UnmapBuffer(
1890    VADriverContextP ctx,
1891    VABufferID buf_id    /* in */
1892)
1893{
1894    DEBUG_FUNC_ENTER
1895    INIT_DRIVER_DATA
1896    VAStatus vaStatus = VA_STATUS_SUCCESS;
1897    object_buffer_p obj_buffer = BUFFER(buf_id);
1898    if (NULL == obj_buffer) {
1899        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
1900        DEBUG_FAILURE;
1901        return vaStatus;
1902    }
1903
1904    vaStatus = psb__unmap_buffer(obj_buffer);
1905    DEBUG_FUNC_EXIT
1906    return vaStatus;
1907}
1908
1909
1910VAStatus psb_DestroyBuffer(
1911    VADriverContextP ctx,
1912    VABufferID buffer_id
1913)
1914{
1915    DEBUG_FUNC_ENTER
1916    INIT_DRIVER_DATA
1917    VAStatus vaStatus = VA_STATUS_SUCCESS;
1918    object_buffer_p obj_buffer = BUFFER(buffer_id);
1919
1920    if (NULL == obj_buffer) {
1921        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
1922        DEBUG_FAILURE;
1923        return vaStatus;
1924    }
1925
1926    psb__suspend_buffer(driver_data, obj_buffer);
1927    DEBUG_FUNC_EXIT
1928    return vaStatus;
1929}
1930
1931
1932VAStatus psb_BeginPicture(
1933    VADriverContextP ctx,
1934    VAContextID context,
1935    VASurfaceID render_target
1936)
1937{
1938    DEBUG_FUNC_ENTER
1939    INIT_DRIVER_DATA
1940    VAStatus vaStatus = VA_STATUS_SUCCESS;
1941    object_context_p obj_context;
1942    object_surface_p obj_surface;
1943    object_config_p obj_config;
1944
1945    obj_context = CONTEXT(context);
1946    if (NULL == obj_context) {
1947        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1948        DEBUG_FAILURE;
1949        return vaStatus;
1950    }
1951
1952    /* Must not be within BeginPicture / EndPicture already */
1953    ASSERT(obj_context->current_render_target == NULL);
1954
1955    obj_surface = SURFACE(render_target);
1956    if (NULL == obj_surface) {
1957        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1958        DEBUG_FAILURE;
1959        return vaStatus;
1960    }
1961
1962    obj_context->current_render_surface_id = render_target;
1963    obj_context->current_render_target = obj_surface;
1964    obj_context->slice_count = 0;
1965
1966    obj_config = CONFIG(obj_context->config_id);
1967    /* if the surface is decode render target, and in displaying */
1968    if (obj_config &&
1969        (obj_config->entrypoint != VAEntrypointEncSlice) &&
1970        (driver_data->cur_displaying_surface == render_target))
1971        drv_debug_msg(VIDEO_DEBUG_ERROR, "WARNING: rendering a displaying surface, may see tearing\n");
1972
1973    if (VA_STATUS_SUCCESS == vaStatus) {
1974        vaStatus = obj_context->format_vtable->beginPicture(obj_context);
1975    }
1976
1977#ifdef ANDROID
1978    /* want msvdx to do rotate
1979     * but check per-context stream type: interlace or not
1980     */
1981    if ((obj_config->entrypoint != VAEntrypointEncSlice) &&
1982        (obj_config->entrypoint != VAEntrypointEncPicture) &&
1983        driver_data->native_window) {
1984        psb_RecalcRotate(ctx, obj_context);
1985    }
1986#endif
1987
1988    if (obj_context->interlaced_stream || driver_data->disable_msvdx_rotate ||
1989        (driver_data->render_mode == VA_RENDER_MODE_EXTERNAL_GPU && force_texure_1080p_60fps)) {
1990        int i;
1991
1992        obj_context->msvdx_rotate = 0;
1993        for (i = 0; i < obj_context->num_render_targets; i++) {
1994            object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]);
1995            /*we invalidate all surfaces's rotate buffer share info here.*/
1996            if (obj_surface && obj_surface->share_info) {
1997                obj_surface->share_info->surface_rotate = 0;
1998            }
1999	    }
2000    }
2001    else
2002        obj_context->msvdx_rotate = driver_data->msvdx_rotate_want;
2003
2004    /* the main surface track current rotate information
2005     * try to reuse the allocated rotate surfaces and don't destroy them
2006     * thus the rotation info in obj_surface->psb_surface_rotate may not be updated
2007     */
2008
2009    SET_SURFACE_INFO_rotate(obj_surface->psb_surface, obj_context->msvdx_rotate);
2010    if (CONTEXT_ROTATE(obj_context)) {
2011        psb_CreateRotateSurface(ctx, obj_surface, obj_context->msvdx_rotate);
2012        /* for 1080p 60fps clip, need force to use surface texture to display video */
2013        if (force_texure_1080p_60fps && driver_data->render_mode == VA_RENDER_MODE_EXTERNAL_GPU &&
2014            obj_surface->share_info)
2015            obj_surface->share_info->force_output_method = 1;
2016    }
2017
2018    if (driver_data->is_oold &&  !obj_surface->psb_surface->in_loop_buf) {
2019        psb_surface_p psb_surface = obj_surface->psb_surface;
2020
2021        psb_surface->in_loop_buf = calloc(1, sizeof(struct psb_buffer_s));
2022        if (NULL == psb_surface->in_loop_buf) {
2023            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2024            DEBUG_FAILURE;
2025            return vaStatus;
2026        }
2027
2028        /* FIXME: For RAR surface, need allocate RAR buffer  */
2029        vaStatus = psb_buffer_create(obj_context->driver_data,
2030                                     psb_surface->size,
2031                                     psb_bt_surface,
2032                                     psb_surface->in_loop_buf);
2033    } else if (!driver_data->is_oold && obj_surface->psb_surface->in_loop_buf) {
2034        psb_surface_p psb_surface = obj_surface->psb_surface;
2035
2036        psb_buffer_destroy(psb_surface->in_loop_buf);
2037        free(psb_surface->in_loop_buf);
2038        psb_surface->in_loop_buf = NULL;
2039    }
2040    obj_context->is_oold = driver_data->is_oold;
2041
2042    drv_debug_msg(VIDEO_DEBUG_GENERAL, "---BeginPicture 0x%08x for frame %d --\n",
2043                             render_target, obj_context->frame_count);
2044    psb__trace_message("------Trace frame %d------\n", obj_context->frame_count);
2045
2046    DEBUG_FUNC_EXIT
2047    return vaStatus;
2048}
2049
2050VAStatus psb_RenderPicture(
2051    VADriverContextP ctx,
2052    VAContextID context,
2053    VABufferID *buffers,
2054    int num_buffers
2055)
2056{
2057    DEBUG_FUNC_ENTER
2058    INIT_DRIVER_DATA
2059    VAStatus vaStatus = VA_STATUS_SUCCESS;
2060    object_context_p obj_context;
2061    object_buffer_p *buffer_list;
2062    int i;
2063
2064    obj_context = CONTEXT(context);
2065    if (NULL == obj_context) {
2066        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2067        DEBUG_FAILURE;
2068        return vaStatus;
2069    }
2070
2071    if (num_buffers <= 0) {
2072        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2073        DEBUG_FAILURE;
2074        return vaStatus;
2075    }
2076
2077    if (NULL == buffers) {
2078        /* Don't crash on NULL pointers */
2079        vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2080        DEBUG_FAILURE;
2081        return vaStatus;
2082    }
2083    /* Must be within BeginPicture / EndPicture */
2084    ASSERT(obj_context->current_render_target != NULL);
2085
2086    if (num_buffers > obj_context->num_buffers) {
2087        free(obj_context->buffer_list);
2088
2089        obj_context->buffer_list = (object_buffer_p *) calloc(1, sizeof(object_buffer_p) * num_buffers);
2090        if (obj_context->buffer_list == NULL) {
2091            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
2092            obj_context->num_buffers = 0;
2093        }
2094
2095        obj_context->num_buffers = num_buffers;
2096    }
2097    buffer_list = obj_context->buffer_list;
2098
2099    if (VA_STATUS_SUCCESS == vaStatus) {
2100        /* Lookup buffer references */
2101        for (i = 0; i < num_buffers; i++) {
2102            object_buffer_p obj_buffer = BUFFER(buffers[i]);
2103            if (NULL == obj_buffer) {
2104                vaStatus = VA_STATUS_ERROR_INVALID_BUFFER;
2105                DEBUG_FAILURE;
2106                return vaStatus;
2107            }
2108            buffer_list[i] = obj_buffer;
2109            drv_debug_msg(VIDEO_DEBUG_GENERAL, "Render buffer %08x type %s\n", obj_buffer->base.id,
2110                                     buffer_type_to_string(obj_buffer->type));
2111        }
2112    }
2113
2114    if (VA_STATUS_SUCCESS == vaStatus) {
2115        vaStatus = obj_context->format_vtable->renderPicture(obj_context, buffer_list, num_buffers);
2116    }
2117
2118    if (buffer_list) {
2119        /* Release buffers */
2120        for (i = 0; i < num_buffers; i++) {
2121            if (buffer_list[i]) {
2122                psb__suspend_buffer(driver_data, buffer_list[i]);
2123            }
2124        }
2125    }
2126
2127    DEBUG_FUNC_EXIT
2128    return vaStatus;
2129}
2130
2131VAStatus psb_EndPicture(
2132    VADriverContextP ctx,
2133    VAContextID context
2134)
2135{
2136    DEBUG_FUNC_ENTER
2137    INIT_DRIVER_DATA
2138    VAStatus vaStatus;
2139    object_context_p obj_context;
2140
2141    obj_context = CONTEXT(context);
2142    if (NULL == obj_context) {
2143        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
2144        DEBUG_FAILURE;
2145        return vaStatus;
2146    }
2147
2148    vaStatus = obj_context->format_vtable->endPicture(obj_context);
2149
2150    drv_debug_msg(VIDEO_DEBUG_GENERAL, "---EndPicture for frame %d --\n", obj_context->frame_count);
2151
2152    obj_context->current_render_target = NULL;
2153    obj_context->frame_count++;
2154
2155    psb__trace_message("FrameCount = %03d\n", obj_context->frame_count);
2156    drv_debug_msg(VIDEO_DEBUG_GENERAL, "FrameCount = %03d\n", obj_context->frame_count);
2157    psb__trace_message(NULL);
2158
2159    DEBUG_FUNC_EXIT
2160    return vaStatus;
2161}
2162
2163
2164static void psb__surface_usage(
2165    psb_driver_data_p driver_data,
2166    object_surface_p obj_surface,
2167    int *decode, int *encode, int *rc_enable, int *proc
2168)
2169{
2170    object_context_p obj_context;
2171    object_config_p obj_config;
2172    VAEntrypoint tmp;
2173    unsigned int eRCmode;
2174    int i;
2175
2176
2177    *decode = 0;
2178    *encode = 0;
2179    *rc_enable = 0;
2180    *proc = 0;
2181
2182    obj_context = CONTEXT(obj_surface->context_id);
2183    if (NULL == obj_context) /* not associate with a context */
2184        return;
2185
2186    obj_config = CONFIG(obj_context->config_id);
2187    if (NULL == obj_config) /* not have a validate context */
2188        return;
2189
2190    tmp = obj_config->entrypoint;
2191
2192    *encode = (tmp == VAEntrypointEncSlice) || (tmp == VAEntrypointEncPicture);
2193    *decode = (VAEntrypointVLD <= tmp) && (tmp <= VAEntrypointDeblocking);
2194#ifdef PSBVIDEO_MRFL_VPP
2195    *proc = (VAEntrypointVideoProc == tmp);
2196#endif
2197
2198    if (*encode) {
2199        for (i = 0; i < obj_config->attrib_count; i++) {
2200            if (obj_config->attrib_list[i].type == VAConfigAttribRateControl)
2201                break;
2202        }
2203
2204        if (i >= obj_config->attrib_count)
2205            eRCmode = VA_RC_NONE;
2206        else
2207            eRCmode = obj_config->attrib_list[i].value;
2208
2209        if (eRCmode == VA_RC_NONE)
2210            *rc_enable = 0;
2211        else
2212            *rc_enable = 1;
2213    }
2214}
2215
2216VAStatus psb_SyncSurface(
2217    VADriverContextP ctx,
2218    VASurfaceID render_target
2219)
2220{
2221    DEBUG_FUNC_ENTER
2222    INIT_DRIVER_DATA
2223    VAStatus vaStatus = VA_STATUS_SUCCESS;
2224    object_surface_p obj_surface;
2225    int decode = 0, encode = 0, rc_enable = 0, proc = 0;
2226
2227    drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_SyncSurface: 0x%08x\n", render_target);
2228
2229    obj_surface = SURFACE(render_target);
2230    if (NULL == obj_surface) {
2231        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2232        DEBUG_FAILURE;
2233        return vaStatus;
2234    }
2235
2236    /* The cur_displaying_surface indicates the surface being displayed by overlay.
2237     * The diaplay_timestamp records the time point of put surface, which would
2238     * be set to zero while using texture blit.*/
2239
2240    /* don't use mutex here for performance concern... */
2241    //pthread_mutex_lock(&output->output_mutex);
2242    if (render_target == driver_data->cur_displaying_surface)
2243        vaStatus = VA_STATUS_ERROR_SURFACE_IN_DISPLAYING;
2244    else if ((VA_INVALID_SURFACE != driver_data->cur_displaying_surface)    /* use overlay */
2245             && (render_target == driver_data->last_displaying_surface)) {  /* It's the last displaying surface*/
2246        object_surface_p cur_obj_surface = SURFACE(driver_data->cur_displaying_surface);
2247        /*  The flip operation on current displaying surface could be delayed to
2248         *  next VBlank and hadn't been finished yet. Then, the last displaying
2249         *  surface shouldn't be freed, because the hardware may not
2250         *  complete loading data of it. Any change of the last surface could
2251         *  have a impect on the scrren.*/
2252        if (NULL != cur_obj_surface) {
2253            while ((GetTickCount() - cur_obj_surface->display_timestamp) < PSB_MAX_FLIP_DELAY)
2254                usleep(PSB_MAX_FLIP_DELAY * 1000);
2255        }
2256    }
2257    //pthread_mutex_unlock(&output->output_mutex);
2258
2259    if (vaStatus != VA_STATUS_ERROR_SURFACE_IN_DISPLAYING)
2260        vaStatus = psb_surface_sync(obj_surface->psb_surface);
2261
2262    /* report any error of decode for Android */
2263    psb__surface_usage(driver_data, obj_surface, &decode, &encode, &rc_enable, &proc);
2264
2265    if (decode && IS_MRST(driver_data)) {
2266        struct drm_lnc_video_getparam_arg arg;
2267        uint32_t ret, handle, fw_status = 0;
2268        handle = wsbmKBufHandle(wsbmKBuf(obj_surface->psb_surface->buf.drm_buf));
2269        arg.key = IMG_VIDEO_DECODE_STATUS;
2270        arg.arg = (uint64_t)((unsigned long) & handle);
2271        arg.value = (uint64_t)((unsigned long) & fw_status);
2272        ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
2273                                  &arg, sizeof(arg));
2274        if (ret == 0) {
2275            if (fw_status != 0)
2276                vaStatus = VA_STATUS_ERROR_DECODING_ERROR;
2277        } else {
2278            drv_debug_msg(VIDEO_DEBUG_GENERAL, "IMG_VIDEO_DECODE_STATUS ioctl return failed.\n");
2279            vaStatus = VA_STATUS_ERROR_UNKNOWN;
2280        }
2281    } else if (proc && IS_MRFL(driver_data)) {
2282        /* FIXME: does it need a new surface sync mechanism for FRC? */
2283    }
2284//    psb__dump_NV_buffers(obj_surface, 0, 0, obj_surface->width, obj_surface->height);
2285    DEBUG_FAILURE;
2286    DEBUG_FUNC_EXIT
2287    return vaStatus;
2288}
2289
2290
2291VAStatus psb_QuerySurfaceStatus(
2292    VADriverContextP ctx,
2293    VASurfaceID render_target,
2294    VASurfaceStatus *status    /* out */
2295)
2296{
2297    DEBUG_FUNC_ENTER
2298    INIT_DRIVER_DATA
2299    VAStatus vaStatus = VA_STATUS_SUCCESS;
2300    object_surface_p obj_surface;
2301    VASurfaceStatus surface_status;
2302    int frame_skip = 0, encode = 0, decode = 0, rc_enable = 0, proc = 0;
2303
2304    obj_surface = SURFACE(render_target);
2305    if (NULL == obj_surface) {
2306        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2307        DEBUG_FAILURE;
2308        return vaStatus;
2309    }
2310    if (NULL == status) {
2311        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
2312        DEBUG_FAILURE;
2313        return vaStatus;
2314    }
2315
2316    vaStatus = psb_surface_query_status(obj_surface->psb_surface, &surface_status);
2317
2318    /* The cur_displaying_surface indicates the surface being displayed by overlay.
2319     * The diaplay_timestamp records the time point of put surface, which would
2320     * be set to zero while using texture blit.*/
2321    pthread_mutex_lock(&driver_data->output_mutex);
2322    if (render_target == driver_data->cur_displaying_surface)
2323        surface_status = VASurfaceDisplaying;
2324    else if ((VA_INVALID_SURFACE != driver_data->cur_displaying_surface)    /* use overlay */
2325             && (render_target == driver_data->last_displaying_surface)) {  /* It's the last displaying surface*/
2326        object_surface_p cur_obj_surface = SURFACE(driver_data->cur_displaying_surface);
2327        /*The flip operation on current displaying surface could be delayed to
2328         *  next VBlank and hadn't been finished yet. Then, the last displaying
2329         *  surface shouldn't be freed, because the hardware may not
2330         *  complete loading data of it. Any change of the last surface could
2331         *  have a impect on the scrren.*/
2332        if ((NULL != cur_obj_surface)
2333            && ((GetTickCount() - cur_obj_surface->display_timestamp) < PSB_MAX_FLIP_DELAY)) {
2334            surface_status = VASurfaceDisplaying;
2335        }
2336    }
2337    pthread_mutex_unlock(&driver_data->output_mutex);
2338
2339    /* try to get frameskip flag for encode */
2340    psb__surface_usage(driver_data, obj_surface, &decode, &encode, &rc_enable, &proc);
2341    if (encode && rc_enable) {
2342        if (IS_MRST(driver_data))
2343            lnc_surface_get_frameskip(driver_data, obj_surface->psb_surface, &frame_skip);
2344        else
2345            pnw_surface_get_frameskip(driver_data, obj_surface->psb_surface, &frame_skip);
2346
2347        if (frame_skip == 1) {
2348            surface_status = surface_status | VASurfaceSkipped;
2349            drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s next frame of 0x%08x is skipped",
2350                    __FUNCTION__, render_target);
2351        }
2352    } else if (decode) {
2353        if (obj_surface->share_info) {
2354            if (obj_surface->share_info->renderStatus == 1) {
2355                surface_status = VASurfaceDisplaying;
2356            } else if (obj_surface->share_info->renderStatus == 0) {
2357                surface_status = VASurfaceReady;
2358            }
2359        }
2360    } else if (proc) {
2361        /* FIXME: does it need a new surface sync mechanism for FRC? */
2362    }
2363
2364    *status = surface_status;
2365    DEBUG_FUNC_EXIT
2366    return vaStatus;
2367}
2368
2369VAStatus psb_QuerySurfaceError(
2370    VADriverContextP ctx,
2371    VASurfaceID render_target,
2372    VAStatus error_status,
2373    void **error_info /*out*/
2374)
2375{
2376    DEBUG_FUNC_ENTER
2377    INIT_DRIVER_DATA
2378    VAStatus vaStatus = VA_STATUS_SUCCESS;
2379    object_surface_p obj_surface;
2380    uint32_t i;
2381
2382    obj_surface = SURFACE(render_target);
2383    if (NULL == obj_surface) {
2384        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2385        DEBUG_FAILURE;
2386        return vaStatus;
2387    }
2388
2389#ifdef PSBVIDEO_MSVDX_EC
2390    if (driver_data->ec_enabled == 0) {
2391#else
2392    if (!IS_MRST(driver_data) || (driver_data->ec_enabled == 0)) {
2393#endif
2394        drv_debug_msg(VIDEO_DEBUG_GENERAL, "error concealment is not supported for this profile.\n");
2395        error_info = NULL;
2396        return VA_STATUS_ERROR_UNKNOWN;
2397    }
2398
2399    if (error_status == VA_STATUS_ERROR_DECODING_ERROR) {
2400        drm_psb_msvdx_decode_status_t *decode_status = driver_data->msvdx_decode_status;
2401        struct drm_lnc_video_getparam_arg arg;
2402        uint32_t ret, handle;
2403        handle = wsbmKBufHandle(wsbmKBuf(obj_surface->psb_surface->buf.drm_buf));
2404
2405        arg.key = IMG_VIDEO_MB_ERROR;
2406        arg.arg = (uint64_t)((unsigned long) & handle);
2407        arg.value = (uint64_t)((unsigned long)decode_status);
2408        ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
2409                                  &arg, sizeof(arg));
2410
2411#ifndef _FOR_FPGA_
2412        if (decode_status->num_region > MAX_MB_ERRORS) {
2413            drv_debug_msg(VIDEO_DEBUG_GENERAL, "too much mb errors are reported.\n");
2414            return VA_STATUS_ERROR_UNKNOWN;
2415        }
2416        i = 0;
2417        for (i = 0; i < decode_status->num_region; ++i) {
2418/*
2419            driver_data->surface_mb_error[i].status = 1;
2420            driver_data->surface_mb_error[i].start_mb = decode_status->start_error_mb_list[i];
2421            driver_data->surface_mb_error[i].end_mb = decode_status->end_error_mb_list[i];
2422            driver_data->surface_mb_error[i].decode_error_type = decode_status->slice_missing_or_error[i];
2423*/
2424        }
2425#endif
2426        driver_data->surface_mb_error[i].status = -1;
2427        *error_info = driver_data->surface_mb_error;
2428    } else {
2429        error_info = NULL;
2430        return VA_STATUS_ERROR_UNKNOWN;
2431    }
2432    DEBUG_FUNC_EXIT
2433    return vaStatus;
2434}
2435
2436VAStatus psb_LockSurface(
2437    VADriverContextP ctx,
2438    VASurfaceID surface,
2439    unsigned int *fourcc, /* following are output argument */
2440    unsigned int *luma_stride,
2441    unsigned int *chroma_u_stride,
2442    unsigned int *chroma_v_stride,
2443    unsigned int *luma_offset,
2444    unsigned int *chroma_u_offset,
2445    unsigned int *chroma_v_offset,
2446    unsigned int *buffer_name,
2447    void **buffer
2448)
2449{
2450    DEBUG_FUNC_ENTER
2451    INIT_DRIVER_DATA
2452    VAStatus vaStatus = VA_STATUS_SUCCESS;
2453    unsigned char *surface_data;
2454    int ret;
2455
2456    object_surface_p obj_surface = SURFACE(surface);
2457    psb_surface_p psb_surface;
2458    if (NULL == obj_surface) {
2459        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2460        DEBUG_FAILURE;
2461        return vaStatus;
2462    }
2463
2464    psb_surface = obj_surface->psb_surface;
2465    if (buffer_name)
2466        *buffer_name = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
2467
2468    if (buffer) { /* map the surface buffer */
2469        uint32_t srf_buf_ofs = 0;
2470        ret = psb_buffer_map(&psb_surface->buf, &surface_data);
2471        if (ret) {
2472            *buffer = NULL;
2473            vaStatus = VA_STATUS_ERROR_UNKNOWN;
2474            DEBUG_FAILURE;
2475            return vaStatus;
2476        }
2477        srf_buf_ofs = psb_surface->buf.buffer_ofs;
2478        *buffer = surface_data + srf_buf_ofs;
2479    }
2480
2481    *fourcc = VA_FOURCC_NV12;
2482    *luma_stride = psb_surface->stride;
2483    *chroma_u_stride = psb_surface->stride;
2484    *chroma_v_stride = psb_surface->stride;
2485    *luma_offset = 0;
2486    *chroma_u_offset = obj_surface->height * psb_surface->stride;
2487    *chroma_v_offset = obj_surface->height * psb_surface->stride + 1;
2488    DEBUG_FUNC_EXIT
2489    return vaStatus;
2490}
2491
2492
2493VAStatus psb_UnlockSurface(
2494    VADriverContextP ctx,
2495    VASurfaceID surface
2496)
2497{
2498    DEBUG_FUNC_ENTER
2499    INIT_DRIVER_DATA
2500    VAStatus vaStatus = VA_STATUS_SUCCESS;
2501
2502    object_surface_p obj_surface = SURFACE(surface);
2503    if (NULL == obj_surface) {
2504        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2505        DEBUG_FAILURE;
2506        return vaStatus;
2507    }
2508
2509    psb_surface_p psb_surface = obj_surface->psb_surface;
2510
2511    psb_buffer_unmap(&psb_surface->buf);
2512
2513    DEBUG_FUNC_EXIT
2514    return VA_STATUS_SUCCESS;
2515}
2516
2517VAStatus psb_GetEGLClientBufferFromSurface(
2518    VADriverContextP ctx,
2519    VASurfaceID surface,
2520    void **buffer
2521)
2522{
2523    DEBUG_FUNC_ENTER
2524    INIT_DRIVER_DATA
2525    VAStatus vaStatus = VA_STATUS_SUCCESS;
2526
2527    object_surface_p obj_surface = SURFACE(surface);
2528    if (NULL == obj_surface) {
2529        vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
2530        DEBUG_FAILURE;
2531        return vaStatus;
2532    }
2533
2534    psb_surface_p psb_surface = obj_surface->psb_surface;
2535    *buffer = (unsigned char *)psb_surface->bc_buffer;
2536
2537    DEBUG_FUNC_EXIT
2538    return vaStatus;
2539}
2540
2541
2542VAStatus psb_PutSurfaceBuf(
2543    VADriverContextP ctx,
2544    VASurfaceID surface,
2545    unsigned char* data,
2546    int* data_len,
2547    short srcx,
2548    short srcy,
2549    unsigned short srcw,
2550    unsigned short srch,
2551    short destx,
2552    short desty,
2553    unsigned short destw,
2554    unsigned short desth,
2555    VARectangle *cliprects, /* client supplied clip list */
2556    unsigned int number_cliprects, /* number of clip rects in the clip list */
2557    unsigned int flags /* de-interlacing flags */
2558)
2559{
2560    DEBUG_FUNC_ENTER
2561    INIT_DRIVER_DATA;
2562    object_surface_p obj_surface = SURFACE(surface);
2563    psb_surface_p psb_surface;
2564
2565    obj_surface = SURFACE(surface);
2566    psb_surface = obj_surface->psb_surface;
2567
2568    psb_putsurface_textureblit(ctx, data, surface, srcx, srcy, srcw, srch, destx, desty, destw, desth, 1, /* check subpicture */
2569                               obj_surface->width, obj_surface->height,
2570                               psb_surface->stride, psb_surface->buf.drm_buf,
2571                               psb_surface->buf.pl_flags, 1 /* wrap dst */);
2572
2573    DEBUG_FUNC_EXIT
2574    return VA_STATUS_SUCCESS;
2575}
2576
2577VAStatus psb_SetTimestampForSurface(
2578    VADriverContextP ctx,
2579    VASurfaceID surface,
2580    long long timestamp
2581)
2582{
2583    INIT_DRIVER_DATA;
2584    object_surface_p obj_surface = SURFACE(surface);
2585
2586    obj_surface = SURFACE(surface);
2587
2588    if (obj_surface->share_info) {
2589        obj_surface->share_info->timestamp = timestamp;
2590        return VA_STATUS_SUCCESS;
2591    } else {
2592        return VA_STATUS_ERROR_UNKNOWN;
2593    }
2594}
2595
2596
2597int  LOCK_HARDWARE(psb_driver_data_p driver_data)
2598{
2599    char ret = 0;
2600
2601    if (driver_data->dri2 || driver_data->dri_dummy)
2602        return 0;
2603
2604    pthread_mutex_lock(&driver_data->drm_mutex);
2605    DRM_CAS(driver_data->drm_lock, driver_data->drm_context,
2606            (DRM_LOCK_HELD | driver_data->drm_context), ret);
2607    if (ret) {
2608        ret = drmGetLock(driver_data->drm_fd, driver_data->drm_context, 0);
2609        /* driver_data->contended_lock=1; */
2610    }
2611
2612    return ret;
2613}
2614
2615int UNLOCK_HARDWARE(psb_driver_data_p driver_data)
2616{
2617    /* driver_data->contended_lock=0; */
2618    if (driver_data->dri2 || driver_data->dri_dummy)
2619        return 0;
2620
2621    DRM_UNLOCK(driver_data->drm_fd, driver_data->drm_lock, driver_data->drm_context);
2622    pthread_mutex_unlock(&driver_data->drm_mutex);
2623
2624    return 0;
2625}
2626
2627
2628static void psb__deinitDRM(VADriverContextP ctx)
2629{
2630    INIT_DRIVER_DATA
2631    struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
2632
2633    if (driver_data->main_pool) {
2634        driver_data->main_pool->takeDown(driver_data->main_pool);
2635        driver_data->main_pool = NULL;
2636    }
2637    if (driver_data->fence_mgr) {
2638        wsbmFenceMgrTTMTakedown(driver_data->fence_mgr);
2639        driver_data->fence_mgr = NULL;
2640    }
2641
2642    if (wsbmIsInitialized())
2643        wsbmTakedown();
2644
2645    close(driver_data->drm_fd);
2646    driver_data->drm_fd = dri_state->fd = -1;
2647}
2648
2649
2650static VAStatus psb__initDRI(VADriverContextP ctx)
2651{
2652    INIT_DRIVER_DATA
2653    struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
2654
2655    assert(dri_state);
2656#ifdef _FOR_FPGA_
2657    dri_state->driConnectedFlag = VA_DUMMY;
2658    /* ON FPGA machine, psb may co-exist with gfx's drm driver */
2659    dri_state->fd = open("/dev/dri/card1", O_RDWR);
2660    if (dri_state->fd < 0)
2661        dri_state->fd = open("/dev/dri/card0", O_RDWR);
2662    assert(dri_state->fd >= 0);
2663#endif
2664    assert(dri_state->driConnectedFlag == VA_DRI2 ||
2665           dri_state->driConnectedFlag == VA_DUMMY);
2666
2667    driver_data->drm_fd = dri_state->fd;
2668    driver_data->dri_dummy = (dri_state->driConnectedFlag == VA_DUMMY);
2669    driver_data->dri2 = (dri_state->driConnectedFlag == VA_DRI2);
2670    driver_data->ws_priv = NULL;
2671    driver_data->bus_id = NULL;
2672
2673    return VA_STATUS_SUCCESS;
2674}
2675
2676
2677static VAStatus psb__initTTM(VADriverContextP ctx)
2678{
2679    INIT_DRIVER_DATA
2680
2681    const char drm_ext[] = "psb_ttm_placement_alphadrop";
2682    union drm_psb_extension_arg arg;
2683    struct _WsbmBufferPool *pool;
2684    int ret;
2685    const char exec_ext[] = "psb_ttm_execbuf_alphadrop";
2686    union drm_psb_extension_arg exec_arg;
2687    const char lncvideo_getparam_ext[] = "lnc_video_getparam";
2688    union drm_psb_extension_arg lncvideo_getparam_arg;
2689
2690    /* init wsbm */
2691    ret = wsbmInit(wsbmNullThreadFuncs(), psbVNodeFuncs());
2692    if (ret) {
2693        drv_debug_msg(VIDEO_DEBUG_ERROR, "failed initializing libwsbm.\n");
2694        return VA_STATUS_ERROR_UNKNOWN;
2695    }
2696
2697    strncpy(arg.extension, drm_ext, sizeof(arg.extension));
2698    /* FIXME: should check dri enabled?
2699     * it seems not init dri here at all
2700     */
2701    ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION,
2702                              &arg, sizeof(arg));
2703    if (ret != 0 || !arg.rep.exists) {
2704        drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to detect DRM extension \"%s\".\n",
2705                           drm_ext);
2706        driver_data->main_pool = NULL;
2707        return VA_STATUS_ERROR_UNKNOWN;
2708    } else {
2709        pool = wsbmTTMPoolInit(driver_data->drm_fd,
2710                               arg.rep.driver_ioctl_offset);
2711        if (pool == NULL) {
2712            drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get ttm pool\n");
2713            return VA_STATUS_ERROR_UNKNOWN;
2714        }
2715        driver_data->main_pool = pool;
2716    }
2717
2718    strncpy(exec_arg.extension, exec_ext, sizeof(exec_arg.extension));
2719    ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &exec_arg,
2720                              sizeof(exec_arg));
2721    if (ret != 0 || !exec_arg.rep.exists) {
2722        drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to detect DRM extension \"%s\".\n",
2723                           exec_ext);
2724        return FALSE;
2725    }
2726    driver_data->execIoctlOffset = exec_arg.rep.driver_ioctl_offset;
2727
2728    strncpy(lncvideo_getparam_arg.extension, lncvideo_getparam_ext, sizeof(lncvideo_getparam_arg.extension));
2729    ret = drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_EXTENSION, &lncvideo_getparam_arg,
2730                              sizeof(lncvideo_getparam_arg));
2731    if (ret != 0 || !lncvideo_getparam_arg.rep.exists) {
2732        drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to detect DRM extension \"%s\".\n",
2733                           lncvideo_getparam_ext);
2734        /* return FALSE; */ /* not reture FALSE, so it still can run */
2735    }
2736    driver_data->getParamIoctlOffset = lncvideo_getparam_arg.rep.driver_ioctl_offset;
2737    return VA_STATUS_SUCCESS;
2738}
2739
2740static VAStatus psb__initDRM(VADriverContextP ctx)
2741{
2742    VAStatus vaStatus;
2743
2744    vaStatus = psb__initDRI(ctx);
2745
2746    if (vaStatus == VA_STATUS_SUCCESS)
2747        return psb__initTTM(ctx);
2748    else
2749        return vaStatus;
2750}
2751
2752VAStatus psb_Terminate(VADriverContextP ctx)
2753{
2754    DEBUG_FUNC_ENTER
2755    INIT_DRIVER_DATA
2756    object_subpic_p obj_subpic;
2757    object_image_p obj_image;
2758    object_buffer_p obj_buffer;
2759    object_surface_p obj_surface;
2760    object_context_p obj_context;
2761    object_config_p obj_config;
2762    object_heap_iterator iter;
2763
2764    drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: begin to tear down\n");
2765
2766    /* Clean up left over contexts */
2767    obj_context = (object_context_p) object_heap_first(&driver_data->context_heap, &iter);
2768    while (obj_context) {
2769        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: contextID %08x still allocated, destroying\n", obj_context->base.id);
2770        psb__destroy_context(driver_data, obj_context);
2771        obj_context = (object_context_p) object_heap_next(&driver_data->context_heap, &iter);
2772    }
2773    object_heap_destroy(&driver_data->context_heap);
2774
2775    /* Clean up SubpicIDs */
2776    obj_subpic = (object_subpic_p) object_heap_first(&driver_data->subpic_heap, &iter);
2777    while (obj_subpic) {
2778        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: subpictureID %08x still allocated, destroying\n", obj_subpic->base.id);
2779        psb__destroy_subpicture(driver_data, obj_subpic);
2780        obj_subpic = (object_subpic_p) object_heap_next(&driver_data->subpic_heap, &iter);
2781    }
2782    object_heap_destroy(&driver_data->subpic_heap);
2783
2784    /* Clean up ImageIDs */
2785    obj_image = (object_image_p) object_heap_first(&driver_data->image_heap, &iter);
2786    while (obj_image) {
2787        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: imageID %08x still allocated, destroying\n", obj_image->base.id);
2788        psb__destroy_image(driver_data, obj_image);
2789        obj_image = (object_image_p) object_heap_next(&driver_data->image_heap, &iter);
2790    }
2791    object_heap_destroy(&driver_data->image_heap);
2792
2793    /* Clean up left over buffers */
2794    obj_buffer = (object_buffer_p) object_heap_first(&driver_data->buffer_heap, &iter);
2795    while (obj_buffer) {
2796        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: bufferID %08x still allocated, destroying\n", obj_buffer->base.id);
2797        psb__destroy_buffer(driver_data, obj_buffer);
2798        obj_buffer = (object_buffer_p) object_heap_next(&driver_data->buffer_heap, &iter);
2799    }
2800    object_heap_destroy(&driver_data->buffer_heap);
2801
2802    /* Clean up left over surfaces */
2803
2804    /* Free PVR2D buffer wrapped from the surfaces */
2805    psb_free_surface_pvr2dbuf(driver_data);
2806    obj_surface = (object_surface_p) object_heap_first(&driver_data->surface_heap, &iter);
2807    while (obj_surface) {
2808        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: surfaceID %08x still allocated, destroying\n", obj_surface->base.id);
2809        psb__destroy_surface(driver_data, obj_surface);
2810        obj_surface = (object_surface_p) object_heap_next(&driver_data->surface_heap, &iter);
2811    }
2812    object_heap_destroy(&driver_data->surface_heap);
2813
2814    /* Clean up configIDs */
2815    obj_config = (object_config_p) object_heap_first(&driver_data->config_heap, &iter);
2816    while (obj_config) {
2817        object_heap_free(&driver_data->config_heap, (object_base_p) obj_config);
2818        obj_config = (object_config_p) object_heap_next(&driver_data->config_heap, &iter);
2819    }
2820    object_heap_destroy(&driver_data->config_heap);
2821
2822    if (driver_data->camera_bo) {
2823        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: clearup camera global BO\n");
2824
2825        psb_buffer_destroy((psb_buffer_p)driver_data->camera_bo);
2826        free(driver_data->camera_bo);
2827        driver_data->camera_bo = NULL;
2828    }
2829
2830    if (driver_data->rar_bo) {
2831        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: clearup RAR global BO\n");
2832
2833        psb_buffer_destroy((psb_buffer_p)driver_data->rar_bo);
2834        free(driver_data->rar_bo);
2835        driver_data->rar_bo = NULL;
2836    }
2837
2838    if (driver_data->ws_priv) {
2839        drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: tear down output portion\n");
2840
2841        psb_deinitOutput(ctx);
2842        driver_data->ws_priv = NULL;
2843    }
2844
2845    drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: de-initialized DRM\n");
2846
2847    psb__deinitDRM(ctx);
2848
2849    if (driver_data->msvdx_decode_status)
2850        free(driver_data->msvdx_decode_status);
2851
2852    if (driver_data->surface_mb_error)
2853        free(driver_data->surface_mb_error);
2854
2855    free(ctx->pDriverData);
2856    free(ctx->vtable_egl);
2857    free(ctx->vtable_tpi);
2858
2859    ctx->pDriverData = NULL;
2860    drv_debug_msg(VIDEO_DEBUG_INIT, "vaTerminate: goodbye\n\n");
2861
2862    psb__close_log();
2863    DEBUG_FUNC_EXIT
2864    return VA_STATUS_SUCCESS;
2865}
2866
2867EXPORT VAStatus __vaDriverInit_0_31(VADriverContextP ctx)
2868{
2869    psb_driver_data_p driver_data;
2870    struct VADriverVTableTPI *tpi;
2871    struct VADriverVTableEGL *va_egl;
2872    int result;
2873
2874    if (psb_video_trace_fp) {
2875        /* make gdb always stop here */
2876        signal(SIGUSR1, SIG_IGN);
2877        kill(getpid(), SIGUSR1);
2878    }
2879
2880    psb__open_log();
2881
2882    drv_debug_msg(VIDEO_DEBUG_INIT, "vaInitilize: start the journey\n");
2883
2884    ctx->version_major = 0;
2885    ctx->version_minor = 31;
2886
2887    ctx->max_profiles = PSB_MAX_PROFILES;
2888    ctx->max_entrypoints = PSB_MAX_ENTRYPOINTS;
2889    ctx->max_attributes = PSB_MAX_CONFIG_ATTRIBUTES;
2890    ctx->max_image_formats = PSB_MAX_IMAGE_FORMATS;
2891    ctx->max_subpic_formats = PSB_MAX_SUBPIC_FORMATS;
2892    ctx->max_display_attributes = PSB_MAX_DISPLAY_ATTRIBUTES;
2893
2894    ctx->vtable->vaTerminate = psb_Terminate;
2895    ctx->vtable->vaQueryConfigEntrypoints = psb_QueryConfigEntrypoints;
2896    ctx->vtable->vaTerminate = psb_Terminate;
2897    ctx->vtable->vaQueryConfigProfiles = psb_QueryConfigProfiles;
2898    ctx->vtable->vaQueryConfigEntrypoints = psb_QueryConfigEntrypoints;
2899    ctx->vtable->vaQueryConfigAttributes = psb_QueryConfigAttributes;
2900    ctx->vtable->vaCreateConfig = psb_CreateConfig;
2901    ctx->vtable->vaDestroyConfig = psb_DestroyConfig;
2902    ctx->vtable->vaGetConfigAttributes = psb_GetConfigAttributes;
2903    ctx->vtable->vaCreateSurfaces2 = psb_CreateSurfaces2;
2904    ctx->vtable->vaCreateSurfaces = NULL;
2905    ctx->vtable->vaDestroySurfaces = psb_DestroySurfaces;
2906    ctx->vtable->vaCreateContext = psb_CreateContext;
2907    ctx->vtable->vaDestroyContext = psb_DestroyContext;
2908    ctx->vtable->vaCreateBuffer = psb_CreateBuffer;
2909    ctx->vtable->vaBufferSetNumElements = psb_BufferSetNumElements;
2910    ctx->vtable->vaMapBuffer = psb_MapBuffer;
2911    ctx->vtable->vaUnmapBuffer = psb_UnmapBuffer;
2912    ctx->vtable->vaDestroyBuffer = psb_DestroyBuffer;
2913    ctx->vtable->vaBeginPicture = psb_BeginPicture;
2914    ctx->vtable->vaRenderPicture = psb_RenderPicture;
2915    ctx->vtable->vaEndPicture = psb_EndPicture;
2916    ctx->vtable->vaSyncSurface = psb_SyncSurface;
2917    ctx->vtable->vaQuerySurfaceStatus = psb_QuerySurfaceStatus;
2918    ctx->vtable->vaQuerySurfaceError = psb_QuerySurfaceError;
2919    ctx->vtable->vaPutSurface = psb_PutSurface;
2920    ctx->vtable->vaQueryImageFormats = psb_QueryImageFormats;
2921    ctx->vtable->vaCreateImage = psb_CreateImage;
2922    ctx->vtable->vaDeriveImage = psb_DeriveImage;
2923    ctx->vtable->vaDestroyImage = psb_DestroyImage;
2924    ctx->vtable->vaSetImagePalette = psb_SetImagePalette;
2925    ctx->vtable->vaGetImage = psb_GetImage;
2926    ctx->vtable->vaPutImage = psb_PutImage;
2927    ctx->vtable->vaQuerySubpictureFormats = psb_QuerySubpictureFormats;
2928    ctx->vtable->vaCreateSubpicture = psb_CreateSubpicture;
2929    ctx->vtable->vaDestroySubpicture = psb_DestroySubpicture;
2930    ctx->vtable->vaSetSubpictureImage = psb_SetSubpictureImage;
2931    ctx->vtable->vaSetSubpictureChromakey = psb_SetSubpictureChromakey;
2932    ctx->vtable->vaSetSubpictureGlobalAlpha = psb_SetSubpictureGlobalAlpha;
2933    ctx->vtable->vaAssociateSubpicture = psb_AssociateSubpicture;
2934    ctx->vtable->vaDeassociateSubpicture = psb_DeassociateSubpicture;
2935    ctx->vtable->vaQueryDisplayAttributes = psb_QueryDisplayAttributes;
2936    ctx->vtable->vaGetDisplayAttributes = psb_GetDisplayAttributes;
2937    ctx->vtable->vaSetDisplayAttributes = psb_SetDisplayAttributes;
2938    ctx->vtable->vaBufferInfo = psb_BufferInfo;
2939    ctx->vtable->vaLockSurface = psb_LockSurface;
2940    ctx->vtable->vaUnlockSurface = psb_UnlockSurface;
2941#ifdef PSBVIDEO_MRFL_VPP
2942    ctx->vtable_vpp->vaQueryVideoProcFilters = vsp_QueryVideoProcFilters;
2943    ctx->vtable_vpp->vaQueryVideoProcFilterCaps = vsp_QueryVideoProcFilterCaps;
2944    ctx->vtable_vpp->vaQueryVideoProcPipelineCaps = vsp_QueryVideoProcPipelineCaps;
2945#endif
2946    ctx->vtable_tpi = calloc(1, sizeof(struct VADriverVTableTPI));
2947    if (NULL == ctx->vtable_tpi)
2948        return VA_STATUS_ERROR_ALLOCATION_FAILED;
2949
2950    tpi = (struct VADriverVTableTPI *)ctx->vtable_tpi;
2951    tpi->vaCreateSurfacesWithAttribute = psb_CreateSurfacesWithAttribute;
2952    tpi->vaPutSurfaceBuf = psb_PutSurfaceBuf;
2953    tpi->vaSetTimestampForSurface = psb_SetTimestampForSurface;
2954
2955    ctx->vtable_egl = calloc(1, sizeof(struct VADriverVTableEGL));
2956    if (NULL == ctx->vtable_egl)
2957        return VA_STATUS_ERROR_ALLOCATION_FAILED;
2958
2959    va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
2960    va_egl->vaGetEGLClientBufferFromSurface = psb_GetEGLClientBufferFromSurface;
2961
2962    driver_data = (psb_driver_data_p) calloc(1, sizeof(*driver_data));
2963    ctx->pDriverData = (unsigned char *) driver_data;
2964    if (NULL == driver_data) {
2965        if (ctx->vtable_tpi)
2966            free(ctx->vtable_tpi);
2967        if (ctx->vtable_egl)
2968            free(ctx->vtable_egl);
2969        return VA_STATUS_ERROR_ALLOCATION_FAILED;
2970    }
2971
2972    if (VA_STATUS_SUCCESS != psb__initDRM(ctx)) {
2973        free(ctx->pDriverData);
2974        ctx->pDriverData = NULL;
2975        return VA_STATUS_ERROR_UNKNOWN;
2976    }
2977
2978    pthread_mutex_init(&driver_data->drm_mutex, NULL);
2979
2980    /*
2981     * To read PBO.MSR.CCF Mode and Status Register C-Spec -p112
2982     */
2983#define PCI_PORT5_REG80_VIDEO_SD_DISABLE        0x0008
2984#define PCI_PORT5_REG80_VIDEO_HD_DISABLE        0x0010
2985
2986#if 0
2987    struct drm_psb_hw_info hw_info;
2988    do {
2989        result = drmCommandRead(driver_data->drm_fd, DRM_PSB_HW_INFO, &hw_info, sizeof(hw_info));
2990    } while (result == EAGAIN);
2991
2992    if (result != 0) {
2993        psb__deinitDRM(ctx);
2994        free(ctx->pDriverData);
2995        ctx->pDriverData = NULL;
2996        return VA_STATUS_ERROR_UNKNOWN;
2997    }
2998
2999    driver_data->video_sd_disabled = !!(hw_info.caps & PCI_PORT5_REG80_VIDEO_SD_DISABLE);
3000    driver_data->video_hd_disabled = !!(hw_info.caps & PCI_PORT5_REG80_VIDEO_HD_DISABLE);
3001    drv_debug_msg(VIDEO_DEBUG_GENERAL, "hw_info: rev_id = %08x capabilities = %08x\n", hw_info.rev_id, hw_info.caps);
3002    drv_debug_msg(VIDEO_DEBUG_GENERAL, "hw_info: video_sd_disable=%d,video_hd_disable=%d\n",
3003                             driver_data->video_sd_disabled, driver_data->video_hd_disabled);
3004    if (driver_data->video_sd_disabled != 0) {
3005        drv_debug_msg(VIDEO_DEBUG_ERROR, "MRST: hw_info shows video_sd_disable is true,fix it manually\n");
3006        driver_data->video_sd_disabled = 0;
3007    }
3008    if (driver_data->video_hd_disabled != 0) {
3009        drv_debug_msg(VIDEO_DEBUG_ERROR, "MRST: hw_info shows video_hd_disable is true,fix it manually\n");
3010        driver_data->video_hd_disabled = 0;
3011    }
3012#endif
3013
3014    if (0 != psb_get_device_info(ctx)) {
3015        drv_debug_msg(VIDEO_DEBUG_ERROR, "ERROR: failed to get video device info\n");
3016        driver_data->encode_supported = 1;
3017        driver_data->decode_supported = 1;
3018        driver_data->hd_encode_supported = 1;
3019        driver_data->hd_decode_supported = 1;
3020    }
3021
3022    psb_init_surface_pvr2dbuf(driver_data);
3023
3024    struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
3025    if (dri_state->driConnectedFlag == VA_DRI1 ||
3026        dri_state->driConnectedFlag == VA_DRI2 ||
3027        dri_state->driConnectedFlag == VA_DUMMY) {
3028        if (VA_STATUS_SUCCESS != psb_initOutput(ctx)) {
3029            psb__deinitDRM(ctx);
3030            free(ctx->pDriverData);
3031            ctx->pDriverData = NULL;
3032            return VA_STATUS_ERROR_UNKNOWN;
3033        }
3034    }
3035
3036    driver_data->msvdx_context_base = (((unsigned int) getpid()) & 0xffff) << 16;
3037#ifdef PSBVIDEO_MRFL
3038    if (IS_MRFL(driver_data)) {
3039        drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield topazhp encoder\n");
3040        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &tng_H264ES_vtable;
3041        driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &tng_H264ES_vtable;
3042        driver_data->profile2Format[VAProfileH264High][VAEntrypointEncSlice] = &tng_H264ES_vtable;
3043        driver_data->profile2Format[VAProfileH264StereoHigh][VAEntrypointEncSlice] = &tng_H264ES_vtable;
3044        driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &tng_H263ES_vtable;
3045        driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointEncPicture] = &tng_JPEGES_vtable;
3046        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &tng_MPEG4ES_vtable;
3047        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &tng_MPEG4ES_vtable;
3048    }
3049#endif
3050#ifdef PSBVIDEO_MRFL_VPP
3051    if (IS_MRFL(driver_data)) {
3052        drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield vsp vpp\n");
3053        driver_data->vpp_profile = &vsp_VPP_vtable;
3054    }
3055#endif
3056
3057#ifdef PSBVIDEO_MRFL_DEC
3058    if (IS_MRFL(driver_data)) {
3059        drv_debug_msg(VIDEO_DEBUG_GENERAL, "merrifield VXD392 decoder\n");
3060	driver_data->profile2Format[VAProfileVP8Version0_3][VAEntrypointVLD] = &tng_VP8_vtable;
3061        driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointVLD] = &tng_JPEG_vtable;
3062
3063        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &pnw_MPEG4_vtable;
3064        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &pnw_MPEG4_vtable;
3065
3066        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &pnw_H264_vtable;
3067        driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &pnw_H264_vtable;
3068        driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &pnw_H264_vtable;
3069
3070        driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &pnw_VC1_vtable;
3071        driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &pnw_VC1_vtable;
3072        driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &pnw_VC1_vtable;
3073        driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &pnw_H264_vtable;
3074    }
3075#endif
3076
3077#ifdef PSBVIDEO_MFLD
3078    if (IS_MFLD(driver_data)) {
3079        driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &pnw_H263ES_vtable;
3080        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &pnw_H264ES_vtable;
3081        driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &pnw_H264ES_vtable;
3082        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &pnw_MPEG4ES_vtable;
3083        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &pnw_MPEG4ES_vtable;
3084        driver_data->profile2Format[VAProfileJPEGBaseline][VAEntrypointEncPicture] = &pnw_JPEG_vtable;
3085
3086        driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &pnw_MPEG2_vtable;
3087
3088        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &pnw_MPEG4_vtable;
3089        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &pnw_MPEG4_vtable;
3090
3091        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &pnw_H264_vtable;
3092        driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &pnw_H264_vtable;
3093        driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &pnw_H264_vtable;
3094
3095        driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &pnw_VC1_vtable;
3096        driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &pnw_VC1_vtable;
3097        driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &pnw_VC1_vtable;
3098        driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &pnw_H264_vtable;
3099    }
3100#endif
3101#ifdef PSBVIDEO_MRST
3102    if (IS_MRST(driver_data)) {
3103    driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointVLD] = &psb_MPEG2_vtable;
3104    driver_data->profile2Format[VAProfileMPEG2Main][VAEntrypointMoComp] = &psb_MPEG2MC_vtable;
3105
3106    driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointVLD] = &psb_MPEG4_vtable;
3107    driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointVLD] = &psb_MPEG4_vtable;
3108
3109    driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointVLD] = &psb_H264_vtable;
3110    driver_data->profile2Format[VAProfileH264Main][VAEntrypointVLD] = &psb_H264_vtable;
3111    driver_data->profile2Format[VAProfileH264High][VAEntrypointVLD] = &psb_H264_vtable;
3112    driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &psb_H264_vtable;
3113
3114    driver_data->profile2Format[VAProfileVC1Simple][VAEntrypointVLD] = &psb_VC1_vtable;
3115    driver_data->profile2Format[VAProfileVC1Main][VAEntrypointVLD] = &psb_VC1_vtable;
3116    driver_data->profile2Format[VAProfileVC1Advanced][VAEntrypointVLD] = &psb_VC1_vtable;
3117    driver_data->profile2Format[VAProfileH264ConstrainedBaseline][VAEntrypointVLD] = &psb_H264_vtable;
3118
3119    if(driver_data->encode_supported) {
3120
3121        driver_data->profile2Format[VAProfileH263Baseline][VAEntrypointEncSlice] = &lnc_H263ES_vtable;
3122        driver_data->profile2Format[VAProfileH264Baseline][VAEntrypointEncSlice] = &lnc_H264ES_vtable;
3123        driver_data->profile2Format[VAProfileH264Main][VAEntrypointEncSlice] = &lnc_H264ES_vtable;
3124        driver_data->profile2Format[VAProfileMPEG4Simple][VAEntrypointEncSlice] = &lnc_MPEG4ES_vtable;
3125        driver_data->profile2Format[VAProfileMPEG4AdvancedSimple][VAEntrypointEncSlice] = &lnc_MPEG4ES_vtable;
3126    }
3127}
3128#endif
3129    result = object_heap_init(&driver_data->config_heap, sizeof(struct object_config_s), CONFIG_ID_OFFSET);
3130    ASSERT(result == 0);
3131
3132    result = object_heap_init(&driver_data->context_heap, sizeof(struct object_context_s), CONTEXT_ID_OFFSET);
3133    ASSERT(result == 0);
3134
3135    result = object_heap_init(&driver_data->surface_heap, sizeof(struct object_surface_s), SURFACE_ID_OFFSET);
3136    ASSERT(result == 0);
3137
3138    result = object_heap_init(&driver_data->buffer_heap, sizeof(struct object_buffer_s), BUFFER_ID_OFFSET);
3139    ASSERT(result == 0);
3140
3141    result = object_heap_init(&driver_data->image_heap, sizeof(struct object_image_s), IMAGE_ID_OFFSET);
3142    ASSERT(result == 0);
3143
3144    result = object_heap_init(&driver_data->subpic_heap, sizeof(struct object_subpic_s), SUBPIC_ID_OFFSET);
3145    ASSERT(result == 0);
3146
3147    driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
3148    driver_data->last_displaying_surface = VA_INVALID_SURFACE;
3149
3150    driver_data->clear_color = 0;
3151    driver_data->blend_color = 0;
3152    driver_data->blend_mode = 0;
3153    driver_data->overlay_auto_paint_color_key = 0;
3154
3155    if (IS_MRFL(driver_data))
3156        ctx->str_vendor = PSB_STR_VENDOR_MRFL;
3157    else if (IS_MFLD(driver_data))
3158    {
3159        if (IS_LEXINGTON(driver_data))
3160            ctx->str_vendor = PSB_STR_VENDOR_LEXINGTON;
3161        else
3162            ctx->str_vendor = PSB_STR_VENDOR_MFLD;
3163    }
3164    else
3165        ctx->str_vendor = PSB_STR_VENDOR_MRST;
3166
3167    driver_data->msvdx_decode_status = calloc(1, sizeof(drm_psb_msvdx_decode_status_t));
3168    if (NULL == driver_data->msvdx_decode_status) {
3169        return VA_STATUS_ERROR_ALLOCATION_FAILED;
3170    }
3171    driver_data->surface_mb_error = calloc(MAX_MB_ERRORS, sizeof(VASurfaceDecodeMBErrors));
3172    if (NULL == driver_data->surface_mb_error) {
3173        return VA_STATUS_ERROR_ALLOCATION_FAILED;
3174    }
3175
3176    drv_debug_msg(VIDEO_DEBUG_INIT, "vaInitilize: succeeded!\n\n");
3177
3178#ifdef ANDROID
3179#ifndef PSBVIDEO_MRFL
3180    gralloc_init();
3181#endif
3182#endif
3183    return VA_STATUS_SUCCESS;
3184}
3185
3186
3187EXPORT VAStatus __vaDriverInit_0_32(VADriverContextP ctx)
3188{
3189    return __vaDriverInit_0_31(ctx);
3190}
3191
3192
3193
3194static int psb_get_device_info(VADriverContextP ctx)
3195{
3196    INIT_DRIVER_DATA;
3197    struct drm_lnc_video_getparam_arg arg;
3198    unsigned long device_info;
3199    int ret = 0;
3200    unsigned long video_capability;
3201    unsigned long pci_device;
3202
3203    driver_data->dev_id = 0x4100; /* by default MRST */
3204
3205    arg.key = LNC_VIDEO_DEVICE_INFO;
3206    arg.value = (uint64_t)((unsigned long) & device_info);
3207    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
3208                              &arg, sizeof(arg));
3209    if (ret != 0) {
3210        drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to get video device info\n");
3211        return ret;
3212    }
3213
3214    pci_device = (device_info >> 16) & 0xffff;
3215    video_capability = device_info & 0xffff;
3216
3217    driver_data->dev_id = pci_device;
3218    drv_debug_msg(VIDEO_DEBUG_INIT, "Retrieve Device ID 0x%08x\n", driver_data->dev_id);
3219
3220    if ((IS_MRST(driver_data) && (pci_device != 0x4101)) ||
3221        IS_MFLD(driver_data) || IS_MRFL(driver_data))
3222        driver_data->encode_supported = 1;
3223    else /* 0x4101 or other device hasn't encode support */
3224        driver_data->encode_supported = 0;
3225
3226    if (IS_MRST(driver_data)) {
3227        driver_data->decode_supported = !(video_capability & 0x2);
3228        driver_data->hd_decode_supported = !(video_capability & 0x3);
3229        driver_data->hd_encode_supported = !(video_capability & 0x4);
3230
3231        drv_debug_msg(VIDEO_DEBUG_INIT, "video capability: decode %s, HD decode %s\n",
3232                                 driver_data->decode_supported ? "support" : "not support",
3233                                 driver_data->hd_decode_supported ? "support" : "not support");
3234
3235        drv_debug_msg(VIDEO_DEBUG_INIT, "video capability: encode %s, HD encode %s\n",
3236                                 driver_data->encode_supported ? "support" : "not support",
3237                                 driver_data->hd_encode_supported ? "support" : "not support");
3238
3239    } else {
3240        driver_data->decode_supported = 1;
3241        driver_data->hd_decode_supported = 1;
3242        driver_data->hd_encode_supported = 1;
3243    }
3244
3245    return ret;
3246}
3247