Home | History | Annotate | Download | only in src
      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 (at) intel.com>
     27  *
     28  */
     29 
     30 #include <wsbm/wsbm_manager.h>
     31 
     32 #include "psb_def.h"
     33 #include "psb_surface.h"
     34 #include "psb_drv_debug.h"
     35 
     36 /*
     37  * Create surface
     38  */
     39 VAStatus psb_surface_create(psb_driver_data_p driver_data,
     40                             int width, int height, int fourcc, unsigned int flags,
     41                             psb_surface_p psb_surface /* out */
     42                            )
     43 {
     44     int ret = 0;
     45     int buffer_type = psb_bt_surface;
     46 
     47 #ifndef BAYTRAIL
     48     if ((flags & IS_ROTATED) || (driver_data->render_mode & VA_RENDER_MODE_LOCAL_OVERLAY))
     49         buffer_type = psb_bt_surface_tt;
     50 #endif
     51 
     52 #ifdef PSBVIDEO_MSVDX_DEC_TILING
     53     int tiling = GET_SURFACE_INFO_tiling(psb_surface);
     54     if (tiling)
     55         buffer_type = psb_bt_surface_tiling;
     56 #endif
     57 
     58     if (fourcc == VA_FOURCC_NV12) {
     59         if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) {
     60             return VA_STATUS_ERROR_ALLOCATION_FAILED;
     61         }
     62 
     63         if (0) {
     64             ;
     65         } else if (512 >= width) {
     66             psb_surface->stride_mode = STRIDE_512;
     67             psb_surface->stride = 512;
     68         } else if (1024 >= width) {
     69             psb_surface->stride_mode = STRIDE_1024;
     70             psb_surface->stride = 1024;
     71         } else if (1280 >= width) {
     72             psb_surface->stride_mode = STRIDE_1280;
     73             psb_surface->stride = 1280;
     74 #ifdef PSBVIDEO_MSVDX_DEC_TILING
     75             if (tiling) {
     76                 psb_surface->stride_mode = STRIDE_2048;
     77                 psb_surface->stride = 2048;
     78             }
     79 #endif
     80         } else if (2048 >= width) {
     81             psb_surface->stride_mode = STRIDE_2048;
     82             psb_surface->stride = 2048;
     83         } else if (4096 >= width) {
     84             psb_surface->stride_mode = STRIDE_4096;
     85             psb_surface->stride = 4096;
     86         } else {
     87             psb_surface->stride_mode = STRIDE_NA;
     88             psb_surface->stride = (width + 0x3f) & ~0x3f;
     89         }
     90 
     91         psb_surface->luma_offset = 0;
     92         psb_surface->chroma_offset = psb_surface->stride * height;
     93         psb_surface->size = (psb_surface->stride * height * 3) / 2;
     94         psb_surface->extra_info[4] = VA_FOURCC_NV12;
     95     } else if (fourcc == VA_FOURCC_RGBA) {
     96         unsigned int pitchAlignMask = 63;
     97         psb_surface->stride_mode = STRIDE_NA;
     98         psb_surface->stride = (width * 4 + pitchAlignMask) & ~pitchAlignMask;;
     99         psb_surface->luma_offset = 0;
    100         psb_surface->chroma_offset = 0;
    101         psb_surface->size = psb_surface->stride * height;
    102         psb_surface->extra_info[4] = VA_FOURCC_RGBA;
    103     } else if (fourcc == VA_FOURCC_YV16) {
    104         if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) {
    105             return VA_STATUS_ERROR_ALLOCATION_FAILED;
    106         }
    107 
    108         if (0) {
    109             ;
    110         } else if (512 >= width) {
    111             psb_surface->stride_mode = STRIDE_512;
    112             psb_surface->stride = 512;
    113         } else if (1024 >= width) {
    114             psb_surface->stride_mode = STRIDE_1024;
    115             psb_surface->stride = 1024;
    116         } else if (1280 >= width) {
    117             psb_surface->stride_mode = STRIDE_1280;
    118             psb_surface->stride = 1280;
    119 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    120             if (tiling) {
    121                 psb_surface->stride_mode = STRIDE_2048;
    122                 psb_surface->stride = 2048;
    123             }
    124 #endif
    125         } else if (2048 >= width) {
    126             psb_surface->stride_mode = STRIDE_2048;
    127             psb_surface->stride = 2048;
    128         } else if (4096 >= width) {
    129             psb_surface->stride_mode = STRIDE_4096;
    130             psb_surface->stride = 4096;
    131         } else {
    132             psb_surface->stride_mode = STRIDE_NA;
    133             psb_surface->stride = (width + 0x3f) & ~0x3f;
    134         }
    135 
    136         psb_surface->luma_offset = 0;
    137         psb_surface->chroma_offset = psb_surface->stride * height;
    138         psb_surface->size = psb_surface->stride * height * 2;
    139         psb_surface->extra_info[4] = VA_FOURCC_YV16;
    140     } else if (fourcc == VA_FOURCC_YV32) {
    141         psb_surface->stride_mode = STRIDE_NA;
    142         psb_surface->stride = (width + 0x3f) & ~0x3f; /*round up to 16 */
    143         psb_surface->luma_offset = 0;
    144         psb_surface->chroma_offset = psb_surface->stride * height;
    145         psb_surface->size = psb_surface->stride * height * 4;
    146         psb_surface->extra_info[4] = VA_FOURCC_YV32;
    147     }
    148 
    149     if (flags & IS_PROTECTED)
    150         SET_SURFACE_INFO_protect(psb_surface, 1);
    151 
    152     ret = psb_buffer_create(driver_data, psb_surface->size, buffer_type, &psb_surface->buf);
    153 
    154     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
    155 }
    156 
    157 
    158 
    159 VAStatus psb_surface_create_for_userptr(
    160     psb_driver_data_p driver_data,
    161     int width, int height,
    162     unsigned size, /* total buffer size need to be allocated */
    163     unsigned int __maybe_unused fourcc, /* expected fourcc */
    164     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
    165     unsigned int __maybe_unused chroma_u_stride, /* chroma stride */
    166     unsigned int __maybe_unused chroma_v_stride,
    167     unsigned int luma_offset, /* could be 0 */
    168     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
    169     unsigned int __maybe_unused chroma_v_offset,
    170     psb_surface_p psb_surface /* out */
    171 )
    172 {
    173     int ret;
    174 
    175     if ((width <= 0) || (width > 5120) || (height <= 0) || (height > 5120))
    176         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    177 
    178     psb_surface->stride_mode = STRIDE_NA;
    179     psb_surface->stride = luma_stride;
    180 
    181 
    182     psb_surface->luma_offset = luma_offset;
    183     psb_surface->chroma_offset = chroma_u_offset;
    184     psb_surface->size = size;
    185     psb_surface->extra_info[4] = VA_FOURCC_NV12;
    186     psb_surface->extra_info[8] = VA_FOURCC_NV12;
    187 
    188     ret = psb_buffer_create(driver_data, psb_surface->size, psb_bt_cpu_vpu_shared, &psb_surface->buf);
    189 
    190     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
    191 }
    192 
    193 VAStatus psb_surface_create_from_kbuf(
    194     psb_driver_data_p driver_data,
    195     int width, int height,
    196     unsigned size, /* total buffer size need to be allocated */
    197     unsigned int __maybe_unused fourcc, /* expected fourcc */
    198     int __maybe_unused kbuf_handle,
    199     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
    200     unsigned int __maybe_unused chroma_u_stride, /* chroma stride */
    201     unsigned int __maybe_unused chroma_v_stride,
    202     unsigned int __maybe_unused luma_offset, /* could be 0 */
    203     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
    204     unsigned int __maybe_unused chroma_v_offset,
    205     psb_surface_p psb_surface /* out */
    206 )
    207 {
    208     int ret;
    209 
    210     if ((width <= 0) || (width > 5120) || (height <= 0) || (height > 5120))
    211         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    212 
    213     psb_surface->stride = luma_stride;
    214 
    215     if (0) {
    216         ;
    217     } else if (512 == luma_stride) {
    218         psb_surface->stride_mode = STRIDE_512;
    219     } else if (1024 == luma_stride) {
    220         psb_surface->stride_mode = STRIDE_1024;
    221     } else if (1280 == luma_stride) {
    222         psb_surface->stride_mode = STRIDE_1280;
    223     } else if (2048 == luma_stride) {
    224         psb_surface->stride_mode = STRIDE_2048;
    225     } else if (4096 == luma_stride) {
    226         psb_surface->stride_mode = STRIDE_4096;
    227     } else {
    228         psb_surface->stride_mode = STRIDE_NA;
    229     }
    230 
    231     psb_surface->luma_offset = luma_offset;
    232     psb_surface->chroma_offset = chroma_u_offset;
    233     psb_surface->size = size;
    234     psb_surface->extra_info[4] = VA_FOURCC_NV12;
    235     psb_surface->extra_info[8] = VA_FOURCC_NV12;
    236 
    237     ret = psb_kbuffer_reference(driver_data, &psb_surface->buf, kbuf_handle);
    238 
    239     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
    240 }
    241 
    242 #if PSB_MFLD_DUMMY_CODE
    243 /* id_or_ofs: it is frame ID or frame offset in camear device memory
    244  *     for CI frame: it it always frame offset currently
    245  *     for v4l2 buf: it is offset used in V4L2 buffer mmap
    246  */
    247 VAStatus psb_surface_create_camera(psb_driver_data_p driver_data,
    248                                    int width, int height, int stride, int size,
    249                                    psb_surface_p psb_surface, /* out */
    250                                    int is_v4l2,
    251                                    unsigned int id_or_ofs
    252                                   )
    253 {
    254     int ret;
    255 
    256     if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) {
    257         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    258     }
    259 
    260     psb_surface->stride = stride;
    261     if ((width == 640) && (height == 360)) {
    262         drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI Frame is 640x360, and allocated as 640x368,adjust chroma_offset\n");
    263         psb_surface->chroma_offset = psb_surface->stride * 368;
    264     } else
    265         psb_surface->chroma_offset = psb_surface->stride * height;
    266     psb_surface->size = (psb_surface->stride * height * 3) / 2;
    267 
    268     ret = psb_buffer_create_camera(driver_data, &psb_surface->buf,
    269                                    is_v4l2, id_or_ofs);
    270 
    271     if (ret != VA_STATUS_SUCCESS) {
    272         psb_surface_destroy(psb_surface);
    273 
    274         drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n");
    275         return ret;
    276     }
    277 
    278     return VA_STATUS_SUCCESS;
    279 }
    280 
    281 /* id_or_ofs: it is frame ID or frame offset in camear device memory
    282  *     for CI frame: it it always frame offset currently
    283  *     for v4l2 buf: it is offset used in V4L2 buffer mmap
    284  * user_ptr: virtual address of user buffer.
    285  */
    286 VAStatus psb_surface_create_camera_from_ub(psb_driver_data_p driver_data,
    287         int width, int height, int stride, int size,
    288         psb_surface_p psb_surface, /* out */
    289         int is_v4l2,
    290         unsigned int id_or_ofs,
    291         const unsigned long *user_ptr)
    292 {
    293     int ret;
    294 
    295     if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) {
    296         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    297     }
    298 
    299     psb_surface->stride = stride;
    300     psb_surface->chroma_offset = psb_surface->stride * height;
    301     psb_surface->size = (psb_surface->stride * height * 3) / 2;
    302 
    303     ret = psb_buffer_create_camera_from_ub(driver_data, &psb_surface->buf,
    304                                            is_v4l2, psb_surface->size, user_ptr);
    305 
    306     if (ret != VA_STATUS_SUCCESS) {
    307         psb_surface_destroy(psb_surface);
    308 
    309         drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n");
    310         return ret;
    311     }
    312 
    313     return VA_STATUS_SUCCESS;
    314 }
    315 #endif
    316 
    317 /*
    318  * Temporarily map surface and set all chroma values of surface to 'chroma'
    319  */
    320 VAStatus psb_surface_set_chroma(psb_surface_p psb_surface, int chroma)
    321 {
    322     unsigned char *surface_data;
    323     int ret = psb_buffer_map(&psb_surface->buf, &surface_data);
    324 
    325     if (ret) return VA_STATUS_ERROR_UNKNOWN;
    326 
    327     memset(surface_data + psb_surface->chroma_offset, chroma, psb_surface->size - psb_surface->chroma_offset);
    328 
    329     psb_buffer_unmap(&psb_surface->buf);
    330 
    331     return VA_STATUS_SUCCESS;
    332 }
    333 
    334 /*
    335  * Destroy surface
    336  */
    337 void psb_surface_destroy(psb_surface_p psb_surface)
    338 {
    339     psb_buffer_destroy(&psb_surface->buf);
    340     if (NULL != psb_surface->in_loop_buf)
    341         psb_buffer_destroy(psb_surface->in_loop_buf);
    342 
    343 }
    344 
    345 VAStatus psb_surface_sync(psb_surface_p psb_surface)
    346 {
    347     wsbmBOWaitIdle(psb_surface->buf.drm_buf, 0);
    348 
    349     return VA_STATUS_SUCCESS;
    350 }
    351 
    352 VAStatus psb_surface_query_status(psb_surface_p psb_surface, VASurfaceStatus *status)
    353 {
    354     int ret;
    355     uint32_t synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE | WSBM_SYNCCPU_DONT_BLOCK;
    356 
    357     ret = wsbmBOSyncForCpu(psb_surface->buf.drm_buf, synccpu_flag);
    358 
    359     if (ret == 0) {
    360         (void) wsbmBOReleaseFromCpu(psb_surface->buf.drm_buf, synccpu_flag);
    361         *status = VASurfaceReady;
    362     } else {
    363         *status = VASurfaceRendering;
    364     }
    365     return VA_STATUS_SUCCESS;
    366 }
    367 
    368 /*
    369  * Set current displaying surface info to kernel
    370  * so that other component can access it in another process
    371  */
    372 int psb_surface_set_displaying(psb_driver_data_p driver_data,
    373                                int width, int height,
    374                                psb_surface_p psb_surface)
    375 {
    376     struct drm_lnc_video_getparam_arg arg;
    377     struct drm_video_displaying_frameinfo value;
    378     int ret = 0;
    379 
    380     if (psb_surface) {
    381         value.buf_handle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
    382         value.width = width;
    383         value.height = height;
    384         value.size = psb_surface->size;
    385         value.format = psb_surface->extra_info[4];
    386         value.luma_stride = psb_surface->stride;
    387         value.chroma_u_stride = psb_surface->stride;
    388         value.chroma_v_stride = psb_surface->stride;
    389         value.luma_offset = psb_surface->luma_offset;
    390         value.chroma_u_offset = psb_surface->chroma_offset;
    391         value.chroma_v_offset = psb_surface->chroma_offset;
    392     } else /* clean kernel displaying surface info */
    393         memset(&value, 0, sizeof(value));
    394 
    395     arg.key = IMG_VIDEO_SET_DISPLAYING_FRAME;
    396     arg.value = (uint64_t)((unsigned long) & value);
    397     ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
    398                               &arg, sizeof(arg));
    399     if (ret != 0)
    400         drv_debug_msg(VIDEO_DEBUG_ERROR, "IMG_VIDEO_SET_DISPLAYING_FRAME failed\n");
    401 
    402     return ret;
    403 }
    404