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