162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the next 1262306a36Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 1362306a36Sopenharmony_ci * Software. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1862306a36Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1962306a36Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2062306a36Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2162306a36Sopenharmony_ci * SOFTWARE. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Authors: 2462306a36Sopenharmony_ci * Kevin Tian <kevin.tian@intel.com> 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * Contributors: 2762306a36Sopenharmony_ci * Bing Niu <bing.niu@intel.com> 2862306a36Sopenharmony_ci * Xu Han <xu.han@intel.com> 2962306a36Sopenharmony_ci * Ping Gao <ping.a.gao@intel.com> 3062306a36Sopenharmony_ci * Xiaoguang Chen <xiaoguang.chen@intel.com> 3162306a36Sopenharmony_ci * Yang Liu <yang2.liu@intel.com> 3262306a36Sopenharmony_ci * Tina Zhang <tina.zhang@intel.com> 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <uapi/drm/drm_fourcc.h> 3762306a36Sopenharmony_ci#include "i915_drv.h" 3862306a36Sopenharmony_ci#include "gvt.h" 3962306a36Sopenharmony_ci#include "i915_pvinfo.h" 4062306a36Sopenharmony_ci#include "i915_reg.h" 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define PRIMARY_FORMAT_NUM 16 4362306a36Sopenharmony_cistruct pixel_format { 4462306a36Sopenharmony_ci int drm_format; /* Pixel format in DRM definition */ 4562306a36Sopenharmony_ci int bpp; /* Bits per pixel, 0 indicates invalid */ 4662306a36Sopenharmony_ci const char *desc; /* The description */ 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const struct pixel_format bdw_pixel_formats[] = { 5062306a36Sopenharmony_ci {DRM_FORMAT_C8, 8, "8-bit Indexed"}, 5162306a36Sopenharmony_ci {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"}, 5262306a36Sopenharmony_ci {DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"}, 5362306a36Sopenharmony_ci {DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"}, 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci {DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"}, 5662306a36Sopenharmony_ci {DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci /* non-supported format has bpp default to 0 */ 5962306a36Sopenharmony_ci {0, 0, NULL}, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const struct pixel_format skl_pixel_formats[] = { 6362306a36Sopenharmony_ci {DRM_FORMAT_YUYV, 16, "16-bit packed YUYV (8:8:8:8 MSB-V:Y2:U:Y1)"}, 6462306a36Sopenharmony_ci {DRM_FORMAT_UYVY, 16, "16-bit packed UYVY (8:8:8:8 MSB-Y2:V:Y1:U)"}, 6562306a36Sopenharmony_ci {DRM_FORMAT_YVYU, 16, "16-bit packed YVYU (8:8:8:8 MSB-U:Y2:V:Y1)"}, 6662306a36Sopenharmony_ci {DRM_FORMAT_VYUY, 16, "16-bit packed VYUY (8:8:8:8 MSB-Y2:U:Y1:V)"}, 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci {DRM_FORMAT_C8, 8, "8-bit Indexed"}, 6962306a36Sopenharmony_ci {DRM_FORMAT_RGB565, 16, "16-bit BGRX (5:6:5 MSB-R:G:B)"}, 7062306a36Sopenharmony_ci {DRM_FORMAT_ABGR8888, 32, "32-bit RGBA (8:8:8:8 MSB-A:B:G:R)"}, 7162306a36Sopenharmony_ci {DRM_FORMAT_XBGR8888, 32, "32-bit RGBX (8:8:8:8 MSB-X:B:G:R)"}, 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, "32-bit BGRA (8:8:8:8 MSB-A:R:G:B)"}, 7462306a36Sopenharmony_ci {DRM_FORMAT_XRGB8888, 32, "32-bit BGRX (8:8:8:8 MSB-X:R:G:B)"}, 7562306a36Sopenharmony_ci {DRM_FORMAT_XBGR2101010, 32, "32-bit RGBX (2:10:10:10 MSB-X:B:G:R)"}, 7662306a36Sopenharmony_ci {DRM_FORMAT_XRGB2101010, 32, "32-bit BGRX (2:10:10:10 MSB-X:R:G:B)"}, 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* non-supported format has bpp default to 0 */ 7962306a36Sopenharmony_ci {0, 0, NULL}, 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic int bdw_format_to_drm(int format) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci int bdw_pixel_formats_index = 6; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci switch (format) { 8762306a36Sopenharmony_ci case DISP_FORMAT_8BPP: 8862306a36Sopenharmony_ci bdw_pixel_formats_index = 0; 8962306a36Sopenharmony_ci break; 9062306a36Sopenharmony_ci case DISP_FORMAT_BGRX565: 9162306a36Sopenharmony_ci bdw_pixel_formats_index = 1; 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci case DISP_FORMAT_BGRX888: 9462306a36Sopenharmony_ci bdw_pixel_formats_index = 2; 9562306a36Sopenharmony_ci break; 9662306a36Sopenharmony_ci case DISP_FORMAT_RGBX101010: 9762306a36Sopenharmony_ci bdw_pixel_formats_index = 3; 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci case DISP_FORMAT_BGRX101010: 10062306a36Sopenharmony_ci bdw_pixel_formats_index = 4; 10162306a36Sopenharmony_ci break; 10262306a36Sopenharmony_ci case DISP_FORMAT_RGBX888: 10362306a36Sopenharmony_ci bdw_pixel_formats_index = 5; 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci default: 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci return bdw_pixel_formats_index; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic int skl_format_to_drm(int format, bool rgb_order, bool alpha, 11462306a36Sopenharmony_ci int yuv_order) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci int skl_pixel_formats_index = 12; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci switch (format) { 11962306a36Sopenharmony_ci case PLANE_CTL_FORMAT_INDEXED: 12062306a36Sopenharmony_ci skl_pixel_formats_index = 4; 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci case PLANE_CTL_FORMAT_RGB_565: 12362306a36Sopenharmony_ci skl_pixel_formats_index = 5; 12462306a36Sopenharmony_ci break; 12562306a36Sopenharmony_ci case PLANE_CTL_FORMAT_XRGB_8888: 12662306a36Sopenharmony_ci if (rgb_order) 12762306a36Sopenharmony_ci skl_pixel_formats_index = alpha ? 6 : 7; 12862306a36Sopenharmony_ci else 12962306a36Sopenharmony_ci skl_pixel_formats_index = alpha ? 8 : 9; 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case PLANE_CTL_FORMAT_XRGB_2101010: 13262306a36Sopenharmony_ci skl_pixel_formats_index = rgb_order ? 10 : 11; 13362306a36Sopenharmony_ci break; 13462306a36Sopenharmony_ci case PLANE_CTL_FORMAT_YUV422: 13562306a36Sopenharmony_ci skl_pixel_formats_index = yuv_order >> 16; 13662306a36Sopenharmony_ci if (skl_pixel_formats_index > 3) 13762306a36Sopenharmony_ci return -EINVAL; 13862306a36Sopenharmony_ci break; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci default: 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci return skl_pixel_formats_index; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic u32 intel_vgpu_get_stride(struct intel_vgpu *vgpu, int pipe, 14862306a36Sopenharmony_ci u32 tiled, int stride_mask, int bpp) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci u32 stride_reg = vgpu_vreg_t(vgpu, DSPSTRIDE(pipe)) & stride_mask; 15362306a36Sopenharmony_ci u32 stride = stride_reg; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (GRAPHICS_VER(dev_priv) >= 9) { 15662306a36Sopenharmony_ci switch (tiled) { 15762306a36Sopenharmony_ci case PLANE_CTL_TILED_LINEAR: 15862306a36Sopenharmony_ci stride = stride_reg * 64; 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci case PLANE_CTL_TILED_X: 16162306a36Sopenharmony_ci stride = stride_reg * 512; 16262306a36Sopenharmony_ci break; 16362306a36Sopenharmony_ci case PLANE_CTL_TILED_Y: 16462306a36Sopenharmony_ci stride = stride_reg * 128; 16562306a36Sopenharmony_ci break; 16662306a36Sopenharmony_ci case PLANE_CTL_TILED_YF: 16762306a36Sopenharmony_ci if (bpp == 8) 16862306a36Sopenharmony_ci stride = stride_reg * 64; 16962306a36Sopenharmony_ci else if (bpp == 16 || bpp == 32 || bpp == 64) 17062306a36Sopenharmony_ci stride = stride_reg * 128; 17162306a36Sopenharmony_ci else 17262306a36Sopenharmony_ci gvt_dbg_core("skl: unsupported bpp:%d\n", bpp); 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci default: 17562306a36Sopenharmony_ci gvt_dbg_core("skl: unsupported tile format:%x\n", 17662306a36Sopenharmony_ci tiled); 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci return stride; 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic int get_active_pipe(struct intel_vgpu *vgpu) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci int i; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci for (i = 0; i < I915_MAX_PIPES; i++) 18862306a36Sopenharmony_ci if (pipe_is_enabled(vgpu, i)) 18962306a36Sopenharmony_ci break; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return i; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/** 19562306a36Sopenharmony_ci * intel_vgpu_decode_primary_plane - Decode primary plane 19662306a36Sopenharmony_ci * @vgpu: input vgpu 19762306a36Sopenharmony_ci * @plane: primary plane to save decoded info 19862306a36Sopenharmony_ci * This function is called for decoding plane 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * Returns: 20162306a36Sopenharmony_ci * 0 on success, non-zero if failed. 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ciint intel_vgpu_decode_primary_plane(struct intel_vgpu *vgpu, 20462306a36Sopenharmony_ci struct intel_vgpu_primary_plane_format *plane) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; 20762306a36Sopenharmony_ci u32 val, fmt; 20862306a36Sopenharmony_ci int pipe; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci pipe = get_active_pipe(vgpu); 21162306a36Sopenharmony_ci if (pipe >= I915_MAX_PIPES) 21262306a36Sopenharmony_ci return -ENODEV; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, DSPCNTR(pipe)); 21562306a36Sopenharmony_ci plane->enabled = !!(val & DISP_ENABLE); 21662306a36Sopenharmony_ci if (!plane->enabled) 21762306a36Sopenharmony_ci return -ENODEV; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (GRAPHICS_VER(dev_priv) >= 9) { 22062306a36Sopenharmony_ci plane->tiled = val & PLANE_CTL_TILED_MASK; 22162306a36Sopenharmony_ci fmt = skl_format_to_drm( 22262306a36Sopenharmony_ci val & PLANE_CTL_FORMAT_MASK_SKL, 22362306a36Sopenharmony_ci val & PLANE_CTL_ORDER_RGBX, 22462306a36Sopenharmony_ci val & PLANE_CTL_ALPHA_MASK, 22562306a36Sopenharmony_ci val & PLANE_CTL_YUV422_ORDER_MASK); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (fmt >= ARRAY_SIZE(skl_pixel_formats)) { 22862306a36Sopenharmony_ci gvt_vgpu_err("Out-of-bounds pixel format index\n"); 22962306a36Sopenharmony_ci return -EINVAL; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci plane->bpp = skl_pixel_formats[fmt].bpp; 23362306a36Sopenharmony_ci plane->drm_format = skl_pixel_formats[fmt].drm_format; 23462306a36Sopenharmony_ci } else { 23562306a36Sopenharmony_ci plane->tiled = val & DISP_TILED; 23662306a36Sopenharmony_ci fmt = bdw_format_to_drm(val & DISP_FORMAT_MASK); 23762306a36Sopenharmony_ci plane->bpp = bdw_pixel_formats[fmt].bpp; 23862306a36Sopenharmony_ci plane->drm_format = bdw_pixel_formats[fmt].drm_format; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (!plane->bpp) { 24262306a36Sopenharmony_ci gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); 24362306a36Sopenharmony_ci return -EINVAL; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci plane->hw_format = fmt; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci plane->base = vgpu_vreg_t(vgpu, DSPSURF(pipe)) & I915_GTT_PAGE_MASK; 24962306a36Sopenharmony_ci if (!vgpu_gmadr_is_valid(vgpu, plane->base)) 25062306a36Sopenharmony_ci return -EINVAL; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 25362306a36Sopenharmony_ci if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 25462306a36Sopenharmony_ci gvt_vgpu_err("Translate primary plane gma 0x%x to gpa fail\n", 25562306a36Sopenharmony_ci plane->base); 25662306a36Sopenharmony_ci return -EINVAL; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci plane->stride = intel_vgpu_get_stride(vgpu, pipe, plane->tiled, 26062306a36Sopenharmony_ci (GRAPHICS_VER(dev_priv) >= 9) ? 26162306a36Sopenharmony_ci (_PRI_PLANE_STRIDE_MASK >> 6) : 26262306a36Sopenharmony_ci _PRI_PLANE_STRIDE_MASK, plane->bpp); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci plane->width = (vgpu_vreg_t(vgpu, PIPESRC(pipe)) & _PIPE_H_SRCSZ_MASK) >> 26562306a36Sopenharmony_ci _PIPE_H_SRCSZ_SHIFT; 26662306a36Sopenharmony_ci plane->width += 1; 26762306a36Sopenharmony_ci plane->height = (vgpu_vreg_t(vgpu, PIPESRC(pipe)) & 26862306a36Sopenharmony_ci _PIPE_V_SRCSZ_MASK) >> _PIPE_V_SRCSZ_SHIFT; 26962306a36Sopenharmony_ci plane->height += 1; /* raw height is one minus the real value */ 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, DSPTILEOFF(pipe)); 27262306a36Sopenharmony_ci plane->x_offset = (val & _PRI_PLANE_X_OFF_MASK) >> 27362306a36Sopenharmony_ci _PRI_PLANE_X_OFF_SHIFT; 27462306a36Sopenharmony_ci plane->y_offset = (val & _PRI_PLANE_Y_OFF_MASK) >> 27562306a36Sopenharmony_ci _PRI_PLANE_Y_OFF_SHIFT; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci#define CURSOR_FORMAT_NUM (1 << 6) 28162306a36Sopenharmony_cistruct cursor_mode_format { 28262306a36Sopenharmony_ci int drm_format; /* Pixel format in DRM definition */ 28362306a36Sopenharmony_ci u8 bpp; /* Bits per pixel; 0 indicates invalid */ 28462306a36Sopenharmony_ci u32 width; /* In pixel */ 28562306a36Sopenharmony_ci u32 height; /* In lines */ 28662306a36Sopenharmony_ci const char *desc; /* The description */ 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic const struct cursor_mode_format cursor_pixel_formats[] = { 29062306a36Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 128, 128, "128x128 32bpp ARGB"}, 29162306a36Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 256, 256, "256x256 32bpp ARGB"}, 29262306a36Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, 29362306a36Sopenharmony_ci {DRM_FORMAT_ARGB8888, 32, 64, 64, "64x64 32bpp ARGB"}, 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* non-supported format has bpp default to 0 */ 29662306a36Sopenharmony_ci {0, 0, 0, 0, NULL}, 29762306a36Sopenharmony_ci}; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic int cursor_mode_to_drm(int mode) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci int cursor_pixel_formats_index = 4; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci switch (mode) { 30462306a36Sopenharmony_ci case MCURSOR_MODE_128_ARGB_AX: 30562306a36Sopenharmony_ci cursor_pixel_formats_index = 0; 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci case MCURSOR_MODE_256_ARGB_AX: 30862306a36Sopenharmony_ci cursor_pixel_formats_index = 1; 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci case MCURSOR_MODE_64_ARGB_AX: 31162306a36Sopenharmony_ci cursor_pixel_formats_index = 2; 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci case MCURSOR_MODE_64_32B_AX: 31462306a36Sopenharmony_ci cursor_pixel_formats_index = 3; 31562306a36Sopenharmony_ci break; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci default: 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci return cursor_pixel_formats_index; 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci/** 32562306a36Sopenharmony_ci * intel_vgpu_decode_cursor_plane - Decode sprite plane 32662306a36Sopenharmony_ci * @vgpu: input vgpu 32762306a36Sopenharmony_ci * @plane: cursor plane to save decoded info 32862306a36Sopenharmony_ci * This function is called for decoding plane 32962306a36Sopenharmony_ci * 33062306a36Sopenharmony_ci * Returns: 33162306a36Sopenharmony_ci * 0 on success, non-zero if failed. 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ciint intel_vgpu_decode_cursor_plane(struct intel_vgpu *vgpu, 33462306a36Sopenharmony_ci struct intel_vgpu_cursor_plane_format *plane) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; 33762306a36Sopenharmony_ci u32 val, mode, index; 33862306a36Sopenharmony_ci u32 alpha_plane, alpha_force; 33962306a36Sopenharmony_ci int pipe; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci pipe = get_active_pipe(vgpu); 34262306a36Sopenharmony_ci if (pipe >= I915_MAX_PIPES) 34362306a36Sopenharmony_ci return -ENODEV; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, CURCNTR(pipe)); 34662306a36Sopenharmony_ci mode = val & MCURSOR_MODE_MASK; 34762306a36Sopenharmony_ci plane->enabled = (mode != MCURSOR_MODE_DISABLE); 34862306a36Sopenharmony_ci if (!plane->enabled) 34962306a36Sopenharmony_ci return -ENODEV; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci index = cursor_mode_to_drm(mode); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (!cursor_pixel_formats[index].bpp) { 35462306a36Sopenharmony_ci gvt_vgpu_err("Non-supported cursor mode (0x%x)\n", mode); 35562306a36Sopenharmony_ci return -EINVAL; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci plane->mode = mode; 35862306a36Sopenharmony_ci plane->bpp = cursor_pixel_formats[index].bpp; 35962306a36Sopenharmony_ci plane->drm_format = cursor_pixel_formats[index].drm_format; 36062306a36Sopenharmony_ci plane->width = cursor_pixel_formats[index].width; 36162306a36Sopenharmony_ci plane->height = cursor_pixel_formats[index].height; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci alpha_plane = (val & _CURSOR_ALPHA_PLANE_MASK) >> 36462306a36Sopenharmony_ci _CURSOR_ALPHA_PLANE_SHIFT; 36562306a36Sopenharmony_ci alpha_force = (val & _CURSOR_ALPHA_FORCE_MASK) >> 36662306a36Sopenharmony_ci _CURSOR_ALPHA_FORCE_SHIFT; 36762306a36Sopenharmony_ci if (alpha_plane || alpha_force) 36862306a36Sopenharmony_ci gvt_dbg_core("alpha_plane=0x%x, alpha_force=0x%x\n", 36962306a36Sopenharmony_ci alpha_plane, alpha_force); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci plane->base = vgpu_vreg_t(vgpu, CURBASE(pipe)) & I915_GTT_PAGE_MASK; 37262306a36Sopenharmony_ci if (!vgpu_gmadr_is_valid(vgpu, plane->base)) 37362306a36Sopenharmony_ci return -EINVAL; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 37662306a36Sopenharmony_ci if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 37762306a36Sopenharmony_ci gvt_vgpu_err("Translate cursor plane gma 0x%x to gpa fail\n", 37862306a36Sopenharmony_ci plane->base); 37962306a36Sopenharmony_ci return -EINVAL; 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, CURPOS(pipe)); 38362306a36Sopenharmony_ci plane->x_pos = (val & _CURSOR_POS_X_MASK) >> _CURSOR_POS_X_SHIFT; 38462306a36Sopenharmony_ci plane->x_sign = (val & _CURSOR_SIGN_X_MASK) >> _CURSOR_SIGN_X_SHIFT; 38562306a36Sopenharmony_ci plane->y_pos = (val & _CURSOR_POS_Y_MASK) >> _CURSOR_POS_Y_SHIFT; 38662306a36Sopenharmony_ci plane->y_sign = (val & _CURSOR_SIGN_Y_MASK) >> _CURSOR_SIGN_Y_SHIFT; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci plane->x_hot = vgpu_vreg_t(vgpu, vgtif_reg(cursor_x_hot)); 38962306a36Sopenharmony_ci plane->y_hot = vgpu_vreg_t(vgpu, vgtif_reg(cursor_y_hot)); 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci#define SPRITE_FORMAT_NUM (1 << 3) 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic const struct pixel_format sprite_pixel_formats[SPRITE_FORMAT_NUM] = { 39662306a36Sopenharmony_ci [0x0] = {DRM_FORMAT_YUV422, 16, "YUV 16-bit 4:2:2 packed"}, 39762306a36Sopenharmony_ci [0x1] = {DRM_FORMAT_XRGB2101010, 32, "RGB 32-bit 2:10:10:10"}, 39862306a36Sopenharmony_ci [0x2] = {DRM_FORMAT_XRGB8888, 32, "RGB 32-bit 8:8:8:8"}, 39962306a36Sopenharmony_ci [0x4] = {DRM_FORMAT_AYUV, 32, 40062306a36Sopenharmony_ci "YUV 32-bit 4:4:4 packed (8:8:8:8 MSB-X:Y:U:V)"}, 40162306a36Sopenharmony_ci}; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci/** 40462306a36Sopenharmony_ci * intel_vgpu_decode_sprite_plane - Decode sprite plane 40562306a36Sopenharmony_ci * @vgpu: input vgpu 40662306a36Sopenharmony_ci * @plane: sprite plane to save decoded info 40762306a36Sopenharmony_ci * This function is called for decoding plane 40862306a36Sopenharmony_ci * 40962306a36Sopenharmony_ci * Returns: 41062306a36Sopenharmony_ci * 0 on success, non-zero if failed. 41162306a36Sopenharmony_ci */ 41262306a36Sopenharmony_ciint intel_vgpu_decode_sprite_plane(struct intel_vgpu *vgpu, 41362306a36Sopenharmony_ci struct intel_vgpu_sprite_plane_format *plane) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci u32 val, fmt; 41662306a36Sopenharmony_ci u32 color_order, yuv_order; 41762306a36Sopenharmony_ci int drm_format; 41862306a36Sopenharmony_ci int pipe; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci pipe = get_active_pipe(vgpu); 42162306a36Sopenharmony_ci if (pipe >= I915_MAX_PIPES) 42262306a36Sopenharmony_ci return -ENODEV; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPRCTL(pipe)); 42562306a36Sopenharmony_ci plane->enabled = !!(val & SPRITE_ENABLE); 42662306a36Sopenharmony_ci if (!plane->enabled) 42762306a36Sopenharmony_ci return -ENODEV; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci plane->tiled = !!(val & SPRITE_TILED); 43062306a36Sopenharmony_ci color_order = !!(val & SPRITE_RGB_ORDER_RGBX); 43162306a36Sopenharmony_ci yuv_order = (val & SPRITE_YUV_ORDER_MASK) >> 43262306a36Sopenharmony_ci _SPRITE_YUV_ORDER_SHIFT; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci fmt = (val & SPRITE_FORMAT_MASK) >> _SPRITE_FMT_SHIFT; 43562306a36Sopenharmony_ci if (!sprite_pixel_formats[fmt].bpp) { 43662306a36Sopenharmony_ci gvt_vgpu_err("Non-supported pixel format (0x%x)\n", fmt); 43762306a36Sopenharmony_ci return -EINVAL; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci plane->hw_format = fmt; 44062306a36Sopenharmony_ci plane->bpp = sprite_pixel_formats[fmt].bpp; 44162306a36Sopenharmony_ci drm_format = sprite_pixel_formats[fmt].drm_format; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci /* Order of RGB values in an RGBxxx buffer may be ordered RGB or 44462306a36Sopenharmony_ci * BGR depending on the state of the color_order field 44562306a36Sopenharmony_ci */ 44662306a36Sopenharmony_ci if (!color_order) { 44762306a36Sopenharmony_ci if (drm_format == DRM_FORMAT_XRGB2101010) 44862306a36Sopenharmony_ci drm_format = DRM_FORMAT_XBGR2101010; 44962306a36Sopenharmony_ci else if (drm_format == DRM_FORMAT_XRGB8888) 45062306a36Sopenharmony_ci drm_format = DRM_FORMAT_XBGR8888; 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (drm_format == DRM_FORMAT_YUV422) { 45462306a36Sopenharmony_ci switch (yuv_order) { 45562306a36Sopenharmony_ci case 0: 45662306a36Sopenharmony_ci drm_format = DRM_FORMAT_YUYV; 45762306a36Sopenharmony_ci break; 45862306a36Sopenharmony_ci case 1: 45962306a36Sopenharmony_ci drm_format = DRM_FORMAT_UYVY; 46062306a36Sopenharmony_ci break; 46162306a36Sopenharmony_ci case 2: 46262306a36Sopenharmony_ci drm_format = DRM_FORMAT_YVYU; 46362306a36Sopenharmony_ci break; 46462306a36Sopenharmony_ci case 3: 46562306a36Sopenharmony_ci drm_format = DRM_FORMAT_VYUY; 46662306a36Sopenharmony_ci break; 46762306a36Sopenharmony_ci default: 46862306a36Sopenharmony_ci /* yuv_order has only 2 bits */ 46962306a36Sopenharmony_ci break; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci plane->drm_format = drm_format; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci plane->base = vgpu_vreg_t(vgpu, SPRSURF(pipe)) & I915_GTT_PAGE_MASK; 47662306a36Sopenharmony_ci if (!vgpu_gmadr_is_valid(vgpu, plane->base)) 47762306a36Sopenharmony_ci return -EINVAL; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci plane->base_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, plane->base); 48062306a36Sopenharmony_ci if (plane->base_gpa == INTEL_GVT_INVALID_ADDR) { 48162306a36Sopenharmony_ci gvt_vgpu_err("Translate sprite plane gma 0x%x to gpa fail\n", 48262306a36Sopenharmony_ci plane->base); 48362306a36Sopenharmony_ci return -EINVAL; 48462306a36Sopenharmony_ci } 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci plane->stride = vgpu_vreg_t(vgpu, SPRSTRIDE(pipe)) & 48762306a36Sopenharmony_ci _SPRITE_STRIDE_MASK; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPRSIZE(pipe)); 49062306a36Sopenharmony_ci plane->height = (val & _SPRITE_SIZE_HEIGHT_MASK) >> 49162306a36Sopenharmony_ci _SPRITE_SIZE_HEIGHT_SHIFT; 49262306a36Sopenharmony_ci plane->width = (val & _SPRITE_SIZE_WIDTH_MASK) >> 49362306a36Sopenharmony_ci _SPRITE_SIZE_WIDTH_SHIFT; 49462306a36Sopenharmony_ci plane->height += 1; /* raw height is one minus the real value */ 49562306a36Sopenharmony_ci plane->width += 1; /* raw width is one minus the real value */ 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPRPOS(pipe)); 49862306a36Sopenharmony_ci plane->x_pos = (val & _SPRITE_POS_X_MASK) >> _SPRITE_POS_X_SHIFT; 49962306a36Sopenharmony_ci plane->y_pos = (val & _SPRITE_POS_Y_MASK) >> _SPRITE_POS_Y_SHIFT; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci val = vgpu_vreg_t(vgpu, SPROFFSET(pipe)); 50262306a36Sopenharmony_ci plane->x_offset = (val & _SPRITE_OFFSET_START_X_MASK) >> 50362306a36Sopenharmony_ci _SPRITE_OFFSET_START_X_SHIFT; 50462306a36Sopenharmony_ci plane->y_offset = (val & _SPRITE_OFFSET_START_Y_MASK) >> 50562306a36Sopenharmony_ci _SPRITE_OFFSET_START_Y_SHIFT; 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci return 0; 50862306a36Sopenharmony_ci} 509