Commit f9055e74 authored by Chris Wilson's avatar Chris Wilson

drm/i915/overlay: Use the ioctl parameters directly

The user parameters to put_image are not copied back to userspace
(DRM_IOW), and so we can modify the ioctl parameters (having already been
copied to a temporary kernel struct) directly and use those in place,
avoiding another temporary malloc and lots of manual copying.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180906190144.1272-2-chris@chris-wilson.co.uk
parent c8124d39
...@@ -487,23 +487,6 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv) ...@@ -487,23 +487,6 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv)
overlay->active = false; overlay->active = false;
} }
struct put_image_params {
int format;
short dst_x;
short dst_y;
short dst_w;
short dst_h;
short src_w;
short src_scan_h;
short src_scan_w;
short src_h;
short stride_Y;
short stride_UV;
int offset_Y;
int offset_U;
int offset_V;
};
static int packed_depth_bytes(u32 format) static int packed_depth_bytes(u32 format)
{ {
switch (format & I915_OVERLAY_DEPTH_MASK) { switch (format & I915_OVERLAY_DEPTH_MASK) {
...@@ -618,25 +601,25 @@ static void update_polyphase_filter(struct overlay_registers __iomem *regs) ...@@ -618,25 +601,25 @@ static void update_polyphase_filter(struct overlay_registers __iomem *regs)
static bool update_scaling_factors(struct intel_overlay *overlay, static bool update_scaling_factors(struct intel_overlay *overlay,
struct overlay_registers __iomem *regs, struct overlay_registers __iomem *regs,
struct put_image_params *params) struct drm_intel_overlay_put_image *params)
{ {
/* fixed point with a 12 bit shift */ /* fixed point with a 12 bit shift */
u32 xscale, yscale, xscale_UV, yscale_UV; u32 xscale, yscale, xscale_UV, yscale_UV;
#define FP_SHIFT 12 #define FP_SHIFT 12
#define FRACT_MASK 0xfff #define FRACT_MASK 0xfff
bool scale_changed = false; bool scale_changed = false;
int uv_hscale = uv_hsubsampling(params->format); int uv_hscale = uv_hsubsampling(params->flags);
int uv_vscale = uv_vsubsampling(params->format); int uv_vscale = uv_vsubsampling(params->flags);
if (params->dst_w > 1) if (params->dst_width > 1)
xscale = ((params->src_scan_w - 1) << FP_SHIFT) xscale = ((params->src_scan_width - 1) << FP_SHIFT) /
/(params->dst_w); params->dst_width;
else else
xscale = 1 << FP_SHIFT; xscale = 1 << FP_SHIFT;
if (params->dst_h > 1) if (params->dst_height > 1)
yscale = ((params->src_scan_h - 1) << FP_SHIFT) yscale = ((params->src_scan_height - 1) << FP_SHIFT) /
/(params->dst_h); params->dst_height;
else else
yscale = 1 << FP_SHIFT; yscale = 1 << FP_SHIFT;
...@@ -713,12 +696,12 @@ static void update_colorkey(struct intel_overlay *overlay, ...@@ -713,12 +696,12 @@ static void update_colorkey(struct intel_overlay *overlay,
iowrite32(flags, &regs->DCLRKM); iowrite32(flags, &regs->DCLRKM);
} }
static u32 overlay_cmd_reg(struct put_image_params *params) static u32 overlay_cmd_reg(struct drm_intel_overlay_put_image *params)
{ {
u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0; u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0;
if (params->format & I915_OVERLAY_YUV_PLANAR) { if (params->flags & I915_OVERLAY_YUV_PLANAR) {
switch (params->format & I915_OVERLAY_DEPTH_MASK) { switch (params->flags & I915_OVERLAY_DEPTH_MASK) {
case I915_OVERLAY_YUV422: case I915_OVERLAY_YUV422:
cmd |= OCMD_YUV_422_PLANAR; cmd |= OCMD_YUV_422_PLANAR;
break; break;
...@@ -731,7 +714,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params) ...@@ -731,7 +714,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
break; break;
} }
} else { /* YUV packed */ } else { /* YUV packed */
switch (params->format & I915_OVERLAY_DEPTH_MASK) { switch (params->flags & I915_OVERLAY_DEPTH_MASK) {
case I915_OVERLAY_YUV422: case I915_OVERLAY_YUV422:
cmd |= OCMD_YUV_422_PACKED; cmd |= OCMD_YUV_422_PACKED;
break; break;
...@@ -740,7 +723,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params) ...@@ -740,7 +723,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
break; break;
} }
switch (params->format & I915_OVERLAY_SWAP_MASK) { switch (params->flags & I915_OVERLAY_SWAP_MASK) {
case I915_OVERLAY_NO_SWAP: case I915_OVERLAY_NO_SWAP:
break; break;
case I915_OVERLAY_UV_SWAP: case I915_OVERLAY_UV_SWAP:
...@@ -760,7 +743,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params) ...@@ -760,7 +743,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
static int intel_overlay_do_put_image(struct intel_overlay *overlay, static int intel_overlay_do_put_image(struct intel_overlay *overlay,
struct drm_i915_gem_object *new_bo, struct drm_i915_gem_object *new_bo,
struct put_image_params *params) struct drm_intel_overlay_put_image *params)
{ {
struct overlay_registers __iomem *regs = overlay->regs; struct overlay_registers __iomem *regs = overlay->regs;
struct drm_i915_private *dev_priv = overlay->i915; struct drm_i915_private *dev_priv = overlay->i915;
...@@ -806,35 +789,40 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ...@@ -806,35 +789,40 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
goto out_unpin; goto out_unpin;
} }
iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS); iowrite32(params->dst_y << 16 | params->dst_x, &regs->DWINPOS);
iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ); iowrite32(params->dst_height << 16 | params->dst_width, &regs->DWINSZ);
if (params->format & I915_OVERLAY_YUV_PACKED) if (params->flags & I915_OVERLAY_YUV_PACKED)
tmp_width = packed_width_bytes(params->format, params->src_w); tmp_width = packed_width_bytes(params->flags,
params->src_width);
else else
tmp_width = params->src_w; tmp_width = params->src_width;
swidth = params->src_w; swidth = params->src_width;
swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width); swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width);
sheight = params->src_h; sheight = params->src_height;
iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y); iowrite32(i915_ggtt_offset(vma) + params->offset_Y, &regs->OBUF_0Y);
ostride = params->stride_Y; ostride = params->stride_Y;
if (params->format & I915_OVERLAY_YUV_PLANAR) { if (params->flags & I915_OVERLAY_YUV_PLANAR) {
int uv_hscale = uv_hsubsampling(params->format); int uv_hscale = uv_hsubsampling(params->flags);
int uv_vscale = uv_vsubsampling(params->format); int uv_vscale = uv_vsubsampling(params->flags);
u32 tmp_U, tmp_V; u32 tmp_U, tmp_V;
swidth |= (params->src_w/uv_hscale) << 16;
swidth |= (params->src_width / uv_hscale) << 16;
sheight |= (params->src_height / uv_vscale) << 16;
tmp_U = calc_swidthsw(dev_priv, params->offset_U, tmp_U = calc_swidthsw(dev_priv, params->offset_U,
params->src_w/uv_hscale); params->src_width / uv_hscale);
tmp_V = calc_swidthsw(dev_priv, params->offset_V, tmp_V = calc_swidthsw(dev_priv, params->offset_V,
params->src_w/uv_hscale); params->src_width / uv_hscale);
swidthsw |= max_t(u32, tmp_U, tmp_V) << 16; swidthsw |= max(tmp_U, tmp_V) << 16;
sheight |= (params->src_h/uv_vscale) << 16;
iowrite32(i915_ggtt_offset(vma) + params->offset_U, iowrite32(i915_ggtt_offset(vma) + params->offset_U,
&regs->OBUF_0U); &regs->OBUF_0U);
iowrite32(i915_ggtt_offset(vma) + params->offset_V, iowrite32(i915_ggtt_offset(vma) + params->offset_V,
&regs->OBUF_0V); &regs->OBUF_0V);
ostride |= params->stride_UV << 16; ostride |= params->stride_UV << 16;
} }
...@@ -938,15 +926,16 @@ static int check_overlay_dst(struct intel_overlay *overlay, ...@@ -938,15 +926,16 @@ static int check_overlay_dst(struct intel_overlay *overlay,
return -EINVAL; return -EINVAL;
} }
static int check_overlay_scaling(struct put_image_params *rec) static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec)
{ {
u32 tmp; u32 tmp;
/* downscaling limit is 8.0 */ /* downscaling limit is 8.0 */
tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16; tmp = ((rec->src_scan_height << 16) / rec->dst_height) >> 16;
if (tmp > 7) if (tmp > 7)
return -EINVAL; return -EINVAL;
tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16;
tmp = ((rec->src_scan_width << 16) / rec->dst_width) >> 16;
if (tmp > 7) if (tmp > 7)
return -EINVAL; return -EINVAL;
...@@ -1067,13 +1056,12 @@ static int check_overlay_src(struct drm_i915_private *dev_priv, ...@@ -1067,13 +1056,12 @@ static int check_overlay_src(struct drm_i915_private *dev_priv,
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_intel_overlay_put_image *put_image_rec = data; struct drm_intel_overlay_put_image *params = data;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_overlay *overlay; struct intel_overlay *overlay;
struct drm_crtc *drmmode_crtc; struct drm_crtc *drmmode_crtc;
struct intel_crtc *crtc; struct intel_crtc *crtc;
struct drm_i915_gem_object *new_bo; struct drm_i915_gem_object *new_bo;
struct put_image_params *params;
int ret; int ret;
overlay = dev_priv->overlay; overlay = dev_priv->overlay;
...@@ -1082,7 +1070,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, ...@@ -1082,7 +1070,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
return -ENODEV; return -ENODEV;
} }
if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { if (!(params->flags & I915_OVERLAY_ENABLE)) {
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -1094,22 +1082,14 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, ...@@ -1094,22 +1082,14 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
return ret; return ret;
} }
params = kmalloc(sizeof(*params), GFP_KERNEL); drmmode_crtc = drm_crtc_find(dev, file_priv, params->crtc_id);
if (!params) if (!drmmode_crtc)
return -ENOMEM; return -ENOENT;
drmmode_crtc = drm_crtc_find(dev, file_priv, put_image_rec->crtc_id);
if (!drmmode_crtc) {
ret = -ENOENT;
goto out_free;
}
crtc = to_intel_crtc(drmmode_crtc); crtc = to_intel_crtc(drmmode_crtc);
new_bo = i915_gem_object_lookup(file_priv, put_image_rec->bo_handle); new_bo = i915_gem_object_lookup(file_priv, params->bo_handle);
if (!new_bo) { if (!new_bo)
ret = -ENOENT; return -ENOENT;
goto out_free;
}
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -1145,42 +1125,27 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, ...@@ -1145,42 +1125,27 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
overlay->pfit_active = false; overlay->pfit_active = false;
} }
ret = check_overlay_dst(overlay, put_image_rec); ret = check_overlay_dst(overlay, params);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
if (overlay->pfit_active) { if (overlay->pfit_active) {
params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / params->dst_y = (((u32)params->dst_y << 12) /
overlay->pfit_vscale_ratio); overlay->pfit_vscale_ratio);
/* shifting right rounds downwards, so add 1 */ /* shifting right rounds downwards, so add 1 */
params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / params->dst_height = (((u32)params->dst_height << 12) /
overlay->pfit_vscale_ratio) + 1; overlay->pfit_vscale_ratio) + 1;
} else {
params->dst_y = put_image_rec->dst_y;
params->dst_h = put_image_rec->dst_height;
} }
params->dst_x = put_image_rec->dst_x;
params->dst_w = put_image_rec->dst_width; if (params->src_scan_height > params->src_height ||
params->src_scan_width > params->src_width) {
params->src_w = put_image_rec->src_width;
params->src_h = put_image_rec->src_height;
params->src_scan_w = put_image_rec->src_scan_width;
params->src_scan_h = put_image_rec->src_scan_height;
if (params->src_scan_h > params->src_h ||
params->src_scan_w > params->src_w) {
ret = -EINVAL; ret = -EINVAL;
goto out_unlock; goto out_unlock;
} }
ret = check_overlay_src(dev_priv, put_image_rec, new_bo); ret = check_overlay_src(dev_priv, params, new_bo);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK;
params->stride_Y = put_image_rec->stride_Y;
params->stride_UV = put_image_rec->stride_UV;
params->offset_Y = put_image_rec->offset_Y;
params->offset_U = put_image_rec->offset_U;
params->offset_V = put_image_rec->offset_V;
/* Check scaling after src size to prevent a divide-by-zero. */ /* Check scaling after src size to prevent a divide-by-zero. */
ret = check_overlay_scaling(params); ret = check_overlay_scaling(params);
...@@ -1195,16 +1160,12 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, ...@@ -1195,16 +1160,12 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
i915_gem_object_put(new_bo); i915_gem_object_put(new_bo);
kfree(params);
return 0; return 0;
out_unlock: out_unlock:
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
i915_gem_object_put(new_bo); i915_gem_object_put(new_bo);
out_free:
kfree(params);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment