18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 208c2ecf20Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 218c2ecf20Sopenharmony_ci * SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Authors: 248c2ecf20Sopenharmony_ci * Kevin Tian <kevin.tian@intel.com> 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Contributors: 278c2ecf20Sopenharmony_ci * Bing Niu <bing.niu@intel.com> 288c2ecf20Sopenharmony_ci * Xu Han <xu.han@intel.com> 298c2ecf20Sopenharmony_ci * Ping Gao <ping.a.gao@intel.com> 308c2ecf20Sopenharmony_ci * Xiaoguang Chen <xiaoguang.chen@intel.com> 318c2ecf20Sopenharmony_ci * Yang Liu <yang2.liu@intel.com> 328c2ecf20Sopenharmony_ci * Tina Zhang <tina.zhang@intel.com> 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <uapi/drm/drm_fourcc.h> 378c2ecf20Sopenharmony_ci#include "i915_drv.h" 388c2ecf20Sopenharmony_ci#include "gvt.h" 398c2ecf20Sopenharmony_ci#include "i915_pvinfo.h" 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define PRIMARY_FORMAT_NUM 16 428c2ecf20Sopenharmony_cistruct pixel_format { 438c2ecf20Sopenharmony_ci int drm_format; /* Pixel format in DRM definition */ 448c2ecf20Sopenharmony_ci int bpp; /* Bits per pixel, 0 indicates invalid */ 458c2ecf20Sopenharmony_ci char *desc; /* The description */ 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic struct pixel_format bdw_pixel_formats[] = { 498c2ecf20Sopenharmony_ci {DRM_FORMAT_C8, 8, "8-bit Indexed"}, 508c2ecf20Sopenharmony_ci {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"}, 518c2ecf20Sopenharmony_ci {DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"}, 528c2ecf20Sopenharmony_ci {DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"}, 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci {DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"}, 558c2ecf20Sopenharmony_ci {DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* non-supported format has bpp default to 0 */ 588c2ecf20Sopenharmony_ci {0, 0, NULL}, 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic struct pixel_format skl_pixel_formats[] = { 628c2ecf20Sopenharmony_ci {DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"}, 638c2ecf20Sopenharmony_ci {DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"}, 648c2ecf20Sopenharmony_ci {DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"}, 658c2ecf20Sopenharmony_ci {DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"}, 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci {DRM_FORMAT_C8, 8, "8-bit Indexed"}, 688c2ecf20Sopenharmony_ci {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"}, 698c2ecf20Sopenharmony_ci {DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"}, 708c2ecf20Sopenharmony_ci {DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"}, 738c2ecf20Sopenharmony_ci {DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"}, 748c2ecf20Sopenharmony_ci {DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"}, 758c2ecf20Sopenharmony_ci {DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"}, 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* non-supported format has bpp default to 0 */ 788c2ecf20Sopenharmony_ci {0, 0, NULL}, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic int bdw_format_to_drm(int format) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci int bdw_pixel_formats_index = 6; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci switch (format) { 868c2ecf20Sopenharmony_ci case DISPPLANE_8BPP: 878c2ecf20Sopenharmony_ci bdw_pixel_formats_index = 0; 888c2ecf20Sopenharmony_ci break; 898c2ecf20Sopenharmony_ci case DISPPLANE_BGRX565: 908c2ecf20Sopenharmony_ci bdw_pixel_formats_index = 1; 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci case DISPPLANE_BGRX888: 938c2ecf20Sopenharmony_ci bdw_pixel_formats_index = 2; 948c2ecf20Sopenharmony_ci break; 958c2ecf20Sopenharmony_ci case DISPPLANE_RGBX101010: 968c2ecf20Sopenharmony_ci bdw_pixel_formats_index = 3; 978c2ecf20Sopenharmony_ci break; 988c2ecf20Sopenharmony_ci case DISPPLANE_BGRX101010: 998c2ecf20Sopenharmony_ci bdw_pixel_formats_index = 4; 1008c2ecf20Sopenharmony_ci break; 1018c2ecf20Sopenharmony_ci case DISPPLANE_RGBX888: 1028c2ecf20Sopenharmony_ci bdw_pixel_formats_index = 5; 1038c2ecf20Sopenharmony_ci break; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci default: 1068c2ecf20Sopenharmony_ci break; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci return bdw_pixel_formats_index; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic int skl_format_to_drm(int format, bool rgb_order, bool alpha, 1138c2ecf20Sopenharmony_ci int yuv_order) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci int skl_pixel_formats_index = 12; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci switch (format) { 1188c2ecf20Sopenharmony_ci case PLANE_CTL_FORMAT_INDEXED: 1198c2ecf20Sopenharmony_ci skl_pixel_formats_index = 4; 1208c2ecf20Sopenharmony_ci break; 1218c2ecf20Sopenharmony_ci case PLANE_CTL_FORMAT_RGB_565: 1228c2ecf20Sopenharmony_ci skl_pixel_formats_index = 5; 1238c2ecf20Sopenharmony_ci break; 1248c2ecf20Sopenharmony_ci case PLANE_CTL_FORMAT_XRGB_8888: 1258c2ecf20Sopenharmony_ci if (rgb_order) 1268c2ecf20Sopenharmony_ci skl_pixel_formats_index = alpha ? 6 : 7; 1278c2ecf20Sopenharmony_ci else 1288c2ecf20Sopenharmony_ci skl_pixel_formats_index = alpha ? 8 : 9; 1298c2ecf20Sopenharmony_ci break; 1308c2ecf20Sopenharmony_ci case PLANE_CTL_FORMAT_XRGB_2101010: 1318c2ecf20Sopenharmony_ci skl_pixel_formats_index = rgb_order ? 10 : 11; 1328c2ecf20Sopenharmony_ci break; 1338c2ecf20Sopenharmony_ci case PLANE_CTL_FORMAT_YUV422: 1348c2ecf20Sopenharmony_ci skl_pixel_formats_index = yuv_order >> 16; 1358c2ecf20Sopenharmony_ci if (skl_pixel_formats_index > 3) 1368c2ecf20Sopenharmony_ci return -EINVAL; 1378c2ecf20Sopenharmony_ci break; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci default: 1408c2ecf20Sopenharmony_ci break; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return skl_pixel_formats_index; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe, 1478c2ecf20Sopenharmony_ci u32 tiled, int stride_mask, int bpp) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(pipe)) & stride_mask; 1528c2ecf20Sopenharmony_ci u32 stride = stride_reg; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) >= 9) { 1558c2ecf20Sopenharmony_ci switch (tiled) { 1568c2ecf20Sopenharmony_ci case PLANE_CTL_TILED_LINEAR: 1578c2ecf20Sopenharmony_ci stride = stride_reg * 64; 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci case PLANE_CTL_TILED_X: 1608c2ecf20Sopenharmony_ci stride = stride_reg * 512; 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci case PLANE_CTL_TILED_Y: 1638c2ecf20Sopenharmony_ci stride = stride_reg * 128; 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case PLANE_CTL_TILED_YF: 1668c2ecf20Sopenharmony_ci if (bpp == 8) 1678c2ecf20Sopenharmony_ci stride = stride_reg * 64; 1688c2ecf20Sopenharmony_ci else if (bpp == 16 || bpp == 32 || bpp == 64) 1698c2ecf20Sopenharmony_ci stride = stride_reg * 128; 1708c2ecf20Sopenharmony_ci else 1718c2ecf20Sopenharmony_ci gvt_dbg_core("skl: unsupported bpp:%d\n", bpp); 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci default: 1748c2ecf20Sopenharmony_ci gvt_dbg_core("skl: unsupported tile format:%x\n", 1758c2ecf20Sopenharmony_ci tiled); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return stride; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic int get_active_pipe(struct intel_vgpu *vgpu) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci int i; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci for (i = 0; i < I915_MAX_PIPES; i++) 1878c2ecf20Sopenharmony_ci if (pipe_is_enabled(vgpu, i)) 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return i; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci/** 1948c2ecf20Sopenharmony_ci * intel_vgpu_decode_primary_plane - Decode primary plane 1958c2ecf20Sopenharmony_ci * @vgpu: input vgpu 1968c2ecf20Sopenharmony_ci * @plane: primary plane to save decoded info 1978c2ecf20Sopenharmony_ci * This function is called for decoding plane 1988c2ecf20Sopenharmony_ci * 1998c2ecf20Sopenharmony_ci * Returns: 2008c2ecf20Sopenharmony_ci * 0 on success, non-zero if failed. 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_ciint intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, 2038c2ecf20Sopenharmony_ci struct intel_vgpu_primary_plane_format *plane) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; 2068c2ecf20Sopenharmony_ci u32 val, fmt; 2078c2ecf20Sopenharmony_ci int pipe; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci pipe = get_active_pipe(vgpu); 2108c2ecf20Sopenharmony_ci if (pipe >= I915_MAX_PIPES) 2118c2ecf20Sopenharmony_ci return -ENODEV; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, DSPCNTR(pipe)); 2148c2ecf20Sopenharmony_ci plane->enabled = !!(val & DISPLAY_PLANE_ENABLE); 2158c2ecf20Sopenharmony_ci if (!plane->enabled) 2168c2ecf20Sopenharmony_ci return -ENODEV; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) >= 9) { 2198c2ecf20Sopenharmony_ci plane->tiled = val & PLANE_CTL_TILED_MASK; 2208c2ecf20Sopenharmony_ci fmt = skl_format_to_drm( 2218c2ecf20Sopenharmony_ci val & PLANE_CTL_FORMAT_MASK, 2228c2ecf20Sopenharmony_ci val & PLANE_CTL_ORDER_RGBX, 2238c2ecf20Sopenharmony_ci val & PLANE_CTL_ALPHA_MASK, 2248c2ecf20Sopenharmony_ci val & PLANE_CTL_YUV422_ORDER_MASK); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (fmt >= ARRAY_SIZE(skl_pixel_formats)) { 2278c2ecf20Sopenharmony_ci gvt_vgpu_err("Out-of-bounds pixel format index\n"); 2288c2ecf20Sopenharmony_ci return -EINVAL; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci plane->bpp = skl_pixel_formats[fmt].bpp; 2328c2ecf20Sopenharmony_ci plane->drm_format = skl_pixel_formats[fmt].drm_format; 2338c2ecf20Sopenharmony_ci } else { 2348c2ecf20Sopenharmony_ci plane->tiled = val & DISPPLANE_TILED; 2358c2ecf20Sopenharmony_ci fmt = bdw_format_to_drm(val & DISPPLANE_PIXFORMAT_MASK); 2368c2ecf20Sopenharmony_ci plane->bpp = bdw_pixel_formats[fmt].bpp; 2378c2ecf20Sopenharmony_ci plane->drm_format = bdw_pixel_formats[fmt].drm_format; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (!plane->bpp) { 2418c2ecf20Sopenharmony_ci gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); 2428c2ecf20Sopenharmony_ci return -EINVAL; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci plane->hw_format = fmt; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci plane->base = vgpu_vreg_t(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK; 2488c2ecf20Sopenharmony_ci if (!vgpu_gmadr_is_valid(vgpu, plane->base)) 2498c2ecf20Sopenharmony_ci return -EINVAL; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 2528c2ecf20Sopenharmony_ci if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 2538c2ecf20Sopenharmony_ci gvt_vgpu_err("Translate primary plane gma 0x%x to gpa fail\n", 2548c2ecf20Sopenharmony_ci plane->base); 2558c2ecf20Sopenharmony_ci return -EINVAL; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci plane->stride = intel_vgpu_get_stride(vgpu, pipe, plane->tiled, 2598c2ecf20Sopenharmony_ci (INTEL_GEN(dev_priv) >= 9) ? 2608c2ecf20Sopenharmony_ci (_PRI_PLANE_STRIDE_MASK >> 6) : 2618c2ecf20Sopenharmony_ci _PRI_PLANE_STRIDE_MASK, plane->bpp); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci plane->width = (vgpu_vreg_t(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >> 2648c2ecf20Sopenharmony_ci _PIPE_H_SRCSZ_SHIFT; 2658c2ecf20Sopenharmony_ci plane->width += 1; 2668c2ecf20Sopenharmony_ci plane->height = (vgpu_vreg_t(vgpu, PIPESRC(pipe)) & 2678c2ecf20Sopenharmony_ci _PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT; 2688c2ecf20Sopenharmony_ci plane->height += 1; /* raw height is one minus the real value */ 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, DSPTILEOFF(pipe)); 2718c2ecf20Sopenharmony_ci plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >> 2728c2ecf20Sopenharmony_ci _PRI_PLANE_X_OFF_SHIFT; 2738c2ecf20Sopenharmony_ci plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >> 2748c2ecf20Sopenharmony_ci _PRI_PLANE_Y_OFF_SHIFT; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return 0; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci#define CURSOR_FORMAT_NUM (1 << 6) 2808c2ecf20Sopenharmony_cistruct cursor_mode_format { 2818c2ecf20Sopenharmony_ci int drm_format; /* Pixel format in DRM definition */ 2828c2ecf20Sopenharmony_ci u8 bpp; /* Bits per pixel; 0 indicates invalid */ 2838c2ecf20Sopenharmony_ci u32 width; /* In pixel */ 2848c2ecf20Sopenharmony_ci u32 height; /* In lines */ 2858c2ecf20Sopenharmony_ci char *desc; /* The description */ 2868c2ecf20Sopenharmony_ci}; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic struct cursor_mode_format cursor_pixel_formats[] = { 2898c2ecf20Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"}, 2908c2ecf20Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"}, 2918c2ecf20Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, 2928c2ecf20Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* non-supported format has bpp default to 0 */ 2958c2ecf20Sopenharmony_ci {0, 0, 0, 0, NULL}, 2968c2ecf20Sopenharmony_ci}; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int cursor_mode_to_drm(int mode) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci int cursor_pixel_formats_index = 4; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci switch (mode) { 3038c2ecf20Sopenharmony_ci case MCURSOR_MODE_128_ARGB_AX: 3048c2ecf20Sopenharmony_ci cursor_pixel_formats_index = 0; 3058c2ecf20Sopenharmony_ci break; 3068c2ecf20Sopenharmony_ci case MCURSOR_MODE_256_ARGB_AX: 3078c2ecf20Sopenharmony_ci cursor_pixel_formats_index = 1; 3088c2ecf20Sopenharmony_ci break; 3098c2ecf20Sopenharmony_ci case MCURSOR_MODE_64_ARGB_AX: 3108c2ecf20Sopenharmony_ci cursor_pixel_formats_index = 2; 3118c2ecf20Sopenharmony_ci break; 3128c2ecf20Sopenharmony_ci case MCURSOR_MODE_64_32B_AX: 3138c2ecf20Sopenharmony_ci cursor_pixel_formats_index = 3; 3148c2ecf20Sopenharmony_ci break; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci default: 3178c2ecf20Sopenharmony_ci break; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci return cursor_pixel_formats_index; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci/** 3248c2ecf20Sopenharmony_ci * intel_vgpu_decode_cursor_plane - Decode sprite plane 3258c2ecf20Sopenharmony_ci * @vgpu: input vgpu 3268c2ecf20Sopenharmony_ci * @plane: cursor plane to save decoded info 3278c2ecf20Sopenharmony_ci * This function is called for decoding plane 3288c2ecf20Sopenharmony_ci * 3298c2ecf20Sopenharmony_ci * Returns: 3308c2ecf20Sopenharmony_ci * 0 on success, non-zero if failed. 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_ciint intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, 3338c2ecf20Sopenharmony_ci struct intel_vgpu_cursor_plane_format *plane) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; 3368c2ecf20Sopenharmony_ci u32 val, mode, index; 3378c2ecf20Sopenharmony_ci u32 alpha_plane, alpha_force; 3388c2ecf20Sopenharmony_ci int pipe; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci pipe = get_active_pipe(vgpu); 3418c2ecf20Sopenharmony_ci if (pipe >= I915_MAX_PIPES) 3428c2ecf20Sopenharmony_ci return -ENODEV; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, CURCNTR(pipe)); 3458c2ecf20Sopenharmony_ci mode = val & MCURSOR_MODE; 3468c2ecf20Sopenharmony_ci plane->enabled = (mode != MCURSOR_MODE_DISABLE); 3478c2ecf20Sopenharmony_ci if (!plane->enabled) 3488c2ecf20Sopenharmony_ci return -ENODEV; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci index = cursor_mode_to_drm(mode); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (!cursor_pixel_formats[index].bpp) { 3538c2ecf20Sopenharmony_ci gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode); 3548c2ecf20Sopenharmony_ci return -EINVAL; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci plane->mode = mode; 3578c2ecf20Sopenharmony_ci plane->bpp = cursor_pixel_formats[index].bpp; 3588c2ecf20Sopenharmony_ci plane->drm_format = cursor_pixel_formats[index].drm_format; 3598c2ecf20Sopenharmony_ci plane->width = cursor_pixel_formats[index].width; 3608c2ecf20Sopenharmony_ci plane->height = cursor_pixel_formats[index].height; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >> 3638c2ecf20Sopenharmony_ci _CURSOR_ALPHA_PLANE_SHIFT; 3648c2ecf20Sopenharmony_ci alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >> 3658c2ecf20Sopenharmony_ci _CURSOR_ALPHA_FORCE_SHIFT; 3668c2ecf20Sopenharmony_ci if (alpha_plane || alpha_force) 3678c2ecf20Sopenharmony_ci gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n", 3688c2ecf20Sopenharmony_ci alpha_plane, alpha_force); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci plane->base = vgpu_vreg_t(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK; 3718c2ecf20Sopenharmony_ci if (!vgpu_gmadr_is_valid(vgpu, plane->base)) 3728c2ecf20Sopenharmony_ci return -EINVAL; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 3758c2ecf20Sopenharmony_ci if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 3768c2ecf20Sopenharmony_ci gvt_vgpu_err("Translate cursor plane gma 0x%x to gpa fail\n", 3778c2ecf20Sopenharmony_ci plane->base); 3788c2ecf20Sopenharmony_ci return -EINVAL; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, CURPOS(pipe)); 3828c2ecf20Sopenharmony_ci plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT; 3838c2ecf20Sopenharmony_ci plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT; 3848c2ecf20Sopenharmony_ci plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT; 3858c2ecf20Sopenharmony_ci plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci plane->x_hot = vgpu_vreg_t(vgpu, vgtif_reg(cursor_x_hot)); 3888c2ecf20Sopenharmony_ci plane->y_hot = vgpu_vreg_t(vgpu, vgtif_reg(cursor_y_hot)); 3898c2ecf20Sopenharmony_ci return 0; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci#define SPRITE_FORMAT_NUM (1 << 3) 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic struct pixel_format sprite_pixel_formats[SPRITE_FORMAT_NUM] = { 3958c2ecf20Sopenharmony_ci [0x0] = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"}, 3968c2ecf20Sopenharmony_ci [0x1] = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"}, 3978c2ecf20Sopenharmony_ci [0x2] = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"}, 3988c2ecf20Sopenharmony_ci [0x4] = {DRM_FORMAT_AYUV, 32, 3998c2ecf20Sopenharmony_ci "YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"}, 4008c2ecf20Sopenharmony_ci}; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci/** 4038c2ecf20Sopenharmony_ci * intel_vgpu_decode_sprite_plane - Decode sprite plane 4048c2ecf20Sopenharmony_ci * @vgpu: input vgpu 4058c2ecf20Sopenharmony_ci * @plane: sprite plane to save decoded info 4068c2ecf20Sopenharmony_ci * This function is called for decoding plane 4078c2ecf20Sopenharmony_ci * 4088c2ecf20Sopenharmony_ci * Returns: 4098c2ecf20Sopenharmony_ci * 0 on success, non-zero if failed. 4108c2ecf20Sopenharmony_ci */ 4118c2ecf20Sopenharmony_ciint intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu, 4128c2ecf20Sopenharmony_ci struct intel_vgpu_sprite_plane_format *plane) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci u32 val, fmt; 4158c2ecf20Sopenharmony_ci u32 color_order, yuv_order; 4168c2ecf20Sopenharmony_ci int drm_format; 4178c2ecf20Sopenharmony_ci int pipe; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci pipe = get_active_pipe(vgpu); 4208c2ecf20Sopenharmony_ci if (pipe >= I915_MAX_PIPES) 4218c2ecf20Sopenharmony_ci return -ENODEV; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPRCTL(pipe)); 4248c2ecf20Sopenharmony_ci plane->enabled = !!(val & SPRITE_ENABLE); 4258c2ecf20Sopenharmony_ci if (!plane->enabled) 4268c2ecf20Sopenharmony_ci return -ENODEV; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci plane->tiled = !!(val & SPRITE_TILED); 4298c2ecf20Sopenharmony_ci color_order = !!(val & SPRITE_RGB_ORDER_RGBX); 4308c2ecf20Sopenharmony_ci yuv_order = (val & SPRITE_YUV_BYTE_ORDER_MASK) >> 4318c2ecf20Sopenharmony_ci _SPRITE_YUV_ORDER_SHIFT; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci fmt = (val & SPRITE_PIXFORMAT_MASK) >> _SPRITE_FMT_SHIFT; 4348c2ecf20Sopenharmony_ci if (!sprite_pixel_formats[fmt].bpp) { 4358c2ecf20Sopenharmony_ci gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); 4368c2ecf20Sopenharmony_ci return -EINVAL; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci plane->hw_format = fmt; 4398c2ecf20Sopenharmony_ci plane->bpp = sprite_pixel_formats[fmt].bpp; 4408c2ecf20Sopenharmony_ci drm_format = sprite_pixel_formats[fmt].drm_format; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci /* Order of RGB values in an RGBxxx buffer may be ordered RGB or 4438c2ecf20Sopenharmony_ci * BGR depending on the state of the color_order field 4448c2ecf20Sopenharmony_ci */ 4458c2ecf20Sopenharmony_ci if (!color_order) { 4468c2ecf20Sopenharmony_ci if (drm_format == DRM_FORMAT_XRGB2101010) 4478c2ecf20Sopenharmony_ci drm_format = DRM_FORMAT_XBGR2101010; 4488c2ecf20Sopenharmony_ci else if (drm_format == DRM_FORMAT_XRGB8888) 4498c2ecf20Sopenharmony_ci drm_format = DRM_FORMAT_XBGR8888; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (drm_format == DRM_FORMAT_YUV422) { 4538c2ecf20Sopenharmony_ci switch (yuv_order) { 4548c2ecf20Sopenharmony_ci case 0: 4558c2ecf20Sopenharmony_ci drm_format = DRM_FORMAT_YUYV; 4568c2ecf20Sopenharmony_ci break; 4578c2ecf20Sopenharmony_ci case 1: 4588c2ecf20Sopenharmony_ci drm_format = DRM_FORMAT_UYVY; 4598c2ecf20Sopenharmony_ci break; 4608c2ecf20Sopenharmony_ci case 2: 4618c2ecf20Sopenharmony_ci drm_format = DRM_FORMAT_YVYU; 4628c2ecf20Sopenharmony_ci break; 4638c2ecf20Sopenharmony_ci case 3: 4648c2ecf20Sopenharmony_ci drm_format = DRM_FORMAT_VYUY; 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci default: 4678c2ecf20Sopenharmony_ci /* yuv_order has only 2 bits */ 4688c2ecf20Sopenharmony_ci break; 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci plane->drm_format = drm_format; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci plane->base = vgpu_vreg_t(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK; 4758c2ecf20Sopenharmony_ci if (!vgpu_gmadr_is_valid(vgpu, plane->base)) 4768c2ecf20Sopenharmony_ci return -EINVAL; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 4798c2ecf20Sopenharmony_ci if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 4808c2ecf20Sopenharmony_ci gvt_vgpu_err("Translate sprite plane gma 0x%x to gpa fail\n", 4818c2ecf20Sopenharmony_ci plane->base); 4828c2ecf20Sopenharmony_ci return -EINVAL; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci plane->stride = vgpu_vreg_t(vgpu, SPRSTRIDE(pipe)) & 4868c2ecf20Sopenharmony_ci _SPRITE_STRIDE_MASK; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPRSIZE(pipe)); 4898c2ecf20Sopenharmony_ci plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >> 4908c2ecf20Sopenharmony_ci _SPRITE_SIZE_HEIGHT_SHIFT; 4918c2ecf20Sopenharmony_ci plane->width = (val & _SPRITE_SIZE_WIDTH_MASK) >> 4928c2ecf20Sopenharmony_ci _SPRITE_SIZE_WIDTH_SHIFT; 4938c2ecf20Sopenharmony_ci plane->height += 1; /* raw height is one minus the real value */ 4948c2ecf20Sopenharmony_ci plane->width += 1; /* raw width is one minus the real value */ 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPRPOS(pipe)); 4978c2ecf20Sopenharmony_ci plane->x_pos = (val & _SPRITE_POS_X_MASK) >> _SPRITE_POS_X_SHIFT; 4988c2ecf20Sopenharmony_ci plane->y_pos = (val & _SPRITE_POS_Y_MASK) >> _SPRITE_POS_Y_SHIFT; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPROFFSET(pipe)); 5018c2ecf20Sopenharmony_ci plane->x_offset = (val & _SPRITE_OFFSET_START_X_MASK) >> 5028c2ecf20Sopenharmony_ci _SPRITE_OFFSET_START_X_SHIFT; 5038c2ecf20Sopenharmony_ci plane->y_offset = (val & _SPRITE_OFFSET_START_Y_MASK) >> 5048c2ecf20Sopenharmony_ci _SPRITE_OFFSET_START_Y_SHIFT; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci return 0; 5078c2ecf20Sopenharmony_ci} 508