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