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