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 
    187     ret = psb_buffer_create(driver_data, psb_surface->size, psb_bt_cpu_vpu_shared, &psb_surface->buf);
    188 
    189     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
    190 }
    191 
    192 VAStatus psb_surface_create_from_kbuf(
    193     psb_driver_data_p driver_data,
    194     int width, int height,
    195     unsigned size, /* total buffer size need to be allocated */
    196     unsigned int __maybe_unused fourcc, /* expected fourcc */
    197     int __maybe_unused kbuf_handle,
    198     unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
    199     unsigned int __maybe_unused chroma_u_stride, /* chroma stride */
    200     unsigned int __maybe_unused chroma_v_stride,
    201     unsigned int __maybe_unused luma_offset, /* could be 0 */
    202     unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
    203     unsigned int __maybe_unused chroma_v_offset,
    204     psb_surface_p psb_surface /* out */
    205 )
    206 {
    207     int ret;
    208 
    209     if ((width <= 0) || (width > 5120) || (height <= 0) || (height > 5120))
    210         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    211 
    212     psb_surface->stride = luma_stride;
    213 
    214     if (0) {
    215         ;
    216     } else if (512 == luma_stride) {
    217         psb_surface->stride_mode = STRIDE_512;
    218     } else if (1024 == luma_stride) {
    219         psb_surface->stride_mode = STRIDE_1024;
    220     } else if (1280 == luma_stride) {
    221         psb_surface->stride_mode = STRIDE_1280;
    222     } else if (2048 == luma_stride) {
    223         psb_surface->stride_mode = STRIDE_2048;
    224     } else if (4096 == luma_stride) {
    225         psb_surface->stride_mode = STRIDE_4096;
    226     } else {
    227         psb_surface->stride_mode = STRIDE_NA;
    228     }
    229 
    230     psb_surface->luma_offset = luma_offset;
    231     psb_surface->chroma_offset = chroma_u_offset;
    232     psb_surface->size = size;
    233     psb_surface->extra_info[4] = VA_FOURCC_NV12;
    234 
    235     ret = psb_kbuffer_reference(driver_data, &psb_surface->buf, kbuf_handle);
    236 
    237     return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
    238 }
    239 
    240 #if PSB_MFLD_DUMMY_CODE
    241 /* id_or_ofs: it is frame ID or frame offset in camear device memory
    242  *     for CI frame: it it always frame offset currently
    243  *     for v4l2 buf: it is offset used in V4L2 buffer mmap
    244  */
    245 VAStatus psb_surface_create_camera(psb_driver_data_p driver_data,
    246                                    int width, int height, int stride, int size,
    247                                    psb_surface_p psb_surface, /* out */
    248                                    int is_v4l2,
    249                                    unsigned int id_or_ofs
    250                                   )
    251 {
    252     int ret;
    253 
    254     if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) {
    255         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    256     }
    257 
    258     psb_surface->stride = stride;
    259     if ((width == 640) && (height == 360)) {
    260         drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI Frame is 640x360, and allocated as 640x368,adjust chroma_offset\n");
    261         psb_surface->chroma_offset = psb_surface->stride * 368;
    262     } else
    263         psb_surface->chroma_offset = psb_surface->stride * height;
    264     psb_surface->size = (psb_surface->stride * height * 3) / 2;
    265 
    266     ret = psb_buffer_create_camera(driver_data, &psb_surface->buf,
    267                                    is_v4l2, id_or_ofs);
    268 
    269     if (ret != VA_STATUS_SUCCESS) {
    270         psb_surface_destroy(psb_surface);
    271 
    272         drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n");
    273         return ret;
    274     }
    275 
    276     return VA_STATUS_SUCCESS;
    277 }
    278 
    279 /* id_or_ofs: it is frame ID or frame offset in camear device memory
    280  *     for CI frame: it it always frame offset currently
    281  *     for v4l2 buf: it is offset used in V4L2 buffer mmap
    282  * user_ptr: virtual address of user buffer.
    283  */
    284 VAStatus psb_surface_create_camera_from_ub(psb_driver_data_p driver_data,
    285         int width, int height, int stride, int size,
    286         psb_surface_p psb_surface, /* out */
    287         int is_v4l2,
    288         unsigned int id_or_ofs,
    289         const unsigned long *user_ptr)
    290 {
    291     int ret;
    292 
    293     if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) {
    294         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    295     }
    296 
    297     psb_surface->stride = stride;
    298     psb_surface->chroma_offset = psb_surface->stride * height;
    299     psb_surface->size = (psb_surface->stride * height * 3) / 2;
    300 
    301     ret = psb_buffer_create_camera_from_ub(driver_data, &psb_surface->buf,
    302                                            is_v4l2, psb_surface->size, user_ptr);
    303 
    304     if (ret != VA_STATUS_SUCCESS) {
    305         psb_surface_destroy(psb_surface);
    306 
    307         drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n");
    308         return ret;
    309     }
    310 
    311     return VA_STATUS_SUCCESS;
    312 }
    313 #endif
    314 
    315 /*
    316  * Temporarily map surface and set all chroma values of surface to 'chroma'
    317  */
    318 VAStatus psb_surface_set_chroma(psb_surface_p psb_surface, int chroma)
    319 {
    320     unsigned char *surface_data;
    321     int ret = psb_buffer_map(&psb_surface->buf, &surface_data);
    322 
    323     if (ret) return VA_STATUS_ERROR_UNKNOWN;
    324 
    325     memset(surface_data + psb_surface->chroma_offset, chroma, psb_surface->size - psb_surface->chroma_offset);
    326 
    327     psb_buffer_unmap(&psb_surface->buf);
    328 
    329     return VA_STATUS_SUCCESS;
    330 }
    331 
    332 /*
    333  * Destroy surface
    334  */
    335 void psb_surface_destroy(psb_surface_p psb_surface)
    336 {
    337     psb_buffer_destroy(&psb_surface->buf);
    338     if (NULL != psb_surface->in_loop_buf)
    339         psb_buffer_destroy(psb_surface->in_loop_buf);
    340 
    341 }
    342 
    343 VAStatus psb_surface_sync(psb_surface_p psb_surface)
    344 {
    345     wsbmBOWaitIdle(psb_surface->buf.drm_buf, 0);
    346 
    347     return VA_STATUS_SUCCESS;
    348 }
    349 
    350 VAStatus psb_surface_query_status(psb_surface_p psb_surface, VASurfaceStatus *status)
    351 {
    352     int ret;
    353     uint32_t synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE | WSBM_SYNCCPU_DONT_BLOCK;
    354 
    355     ret = wsbmBOSyncForCpu(psb_surface->buf.drm_buf, synccpu_flag);
    356 
    357     if (ret == 0) {
    358         (void) wsbmBOReleaseFromCpu(psb_surface->buf.drm_buf, synccpu_flag);
    359         *status = VASurfaceReady;
    360     } else {
    361         *status = VASurfaceRendering;
    362     }
    363     return VA_STATUS_SUCCESS;
    364 }
    365 
    366 /*
    367  * Set current displaying surface info to kernel
    368  * so that other component can access it in another process
    369  */
    370 int psb_surface_set_displaying(psb_driver_data_p driver_data,
    371                                int width, int height,
    372                                psb_surface_p psb_surface)
    373 {
    374     struct drm_lnc_video_getparam_arg arg;
    375     struct drm_video_displaying_frameinfo value;
    376     int ret = 0;
    377 
    378     if (psb_surface) {
    379         value.buf_handle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
    380         value.width = width;
    381         value.height = height;
    382         value.size = psb_surface->size;
    383         value.format = psb_surface->extra_info[4];
    384         value.luma_stride = psb_surface->stride;
    385         value.chroma_u_stride = psb_surface->stride;
    386         value.chroma_v_stride = psb_surface->stride;
    387         value.luma_offset = psb_surface->luma_offset;
    388         value.chroma_u_offset = psb_surface->chroma_offset;
    389         value.chroma_v_offset = psb_surface->chroma_offset;
    390     } else /* clean kernel displaying surface info */
    391         memset(&value, 0, sizeof(value));
    392 
    393     arg.key = IMG_VIDEO_SET_DISPLAYING_FRAME;
    394     arg.value = (uint64_t)((unsigned long) & value);
    395     ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
    396                               &arg, sizeof(arg));
    397     if (ret != 0)
    398         drv_debug_msg(VIDEO_DEBUG_ERROR, "IMG_VIDEO_SET_DISPLAYING_FRAME failed\n");
    399 
    400     return ret;
    401 }
    402