forked from Minki/linux
drm/exynos: ipp: Rework checking for the correct buffer formats
Prepare a common function for size and scale checks and call it for source and destination buffers. Then also move there the state-less checks from exynos_drm_ipp_task_setup_buffer, so the format information is already available in limits processing. Finally perform the IPP_LIMIT_BUFFER check on the real width of the buffer (the width calculated from the provided buffer pitch). Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
parent
2d8aa4ef6a
commit
69705ad210
@ -345,27 +345,6 @@ static int exynos_drm_ipp_task_setup_buffer(struct exynos_drm_ipp_buffer *buf,
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
/* basic checks */
|
||||
if (buf->buf.width == 0 || buf->buf.height == 0)
|
||||
return -EINVAL;
|
||||
buf->format = drm_format_info(buf->buf.fourcc);
|
||||
for (i = 0; i < buf->format->num_planes; i++) {
|
||||
unsigned int width = (i == 0) ? buf->buf.width :
|
||||
DIV_ROUND_UP(buf->buf.width, buf->format->hsub);
|
||||
|
||||
if (buf->buf.pitch[i] == 0)
|
||||
buf->buf.pitch[i] = width * buf->format->cpp[i];
|
||||
if (buf->buf.pitch[i] < width * buf->format->cpp[i])
|
||||
return -EINVAL;
|
||||
if (!buf->buf.gem_id[i])
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* pitch for additional planes must match */
|
||||
if (buf->format->num_planes > 2 &&
|
||||
buf->buf.pitch[1] != buf->buf.pitch[2])
|
||||
return -EINVAL;
|
||||
|
||||
/* get GEM buffers and check their size */
|
||||
for (i = 0; i < buf->format->num_planes; i++) {
|
||||
unsigned int height = (i == 0) ? buf->buf.height :
|
||||
@ -495,12 +474,13 @@ static int exynos_drm_ipp_check_size_limits(struct exynos_drm_ipp_buffer *buf,
|
||||
enum drm_ipp_size_id id = rotate ? IPP_LIMIT_ROTATED : IPP_LIMIT_AREA;
|
||||
struct drm_ipp_limit l;
|
||||
struct drm_exynos_ipp_limit_val *lh = &l.h, *lv = &l.v;
|
||||
int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
|
||||
|
||||
if (!limits)
|
||||
return 0;
|
||||
|
||||
__get_size_limit(limits, num_limits, IPP_LIMIT_BUFFER, &l);
|
||||
if (!__size_limit_check(buf->buf.width, &l.h) ||
|
||||
if (!__size_limit_check(real_width, &l.h) ||
|
||||
!__size_limit_check(buf->buf.height, &l.v))
|
||||
return -EINVAL;
|
||||
|
||||
@ -560,10 +540,62 @@ static int exynos_drm_ipp_check_scale_limits(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_drm_ipp_check_format(struct exynos_drm_ipp_task *task,
|
||||
struct exynos_drm_ipp_buffer *buf,
|
||||
struct exynos_drm_ipp_buffer *src,
|
||||
struct exynos_drm_ipp_buffer *dst,
|
||||
bool rotate, bool swap)
|
||||
{
|
||||
const struct exynos_drm_ipp_formats *fmt;
|
||||
int ret, i;
|
||||
|
||||
fmt = __ipp_format_get(task->ipp, buf->buf.fourcc, buf->buf.modifier,
|
||||
buf == src ? DRM_EXYNOS_IPP_FORMAT_SOURCE :
|
||||
DRM_EXYNOS_IPP_FORMAT_DESTINATION);
|
||||
if (!fmt) {
|
||||
DRM_DEBUG_DRIVER("Task %pK: %s format not supported\n", task,
|
||||
buf == src ? "src" : "dst");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* basic checks */
|
||||
if (buf->buf.width == 0 || buf->buf.height == 0)
|
||||
return -EINVAL;
|
||||
|
||||
buf->format = drm_format_info(buf->buf.fourcc);
|
||||
for (i = 0; i < buf->format->num_planes; i++) {
|
||||
unsigned int width = (i == 0) ? buf->buf.width :
|
||||
DIV_ROUND_UP(buf->buf.width, buf->format->hsub);
|
||||
|
||||
if (buf->buf.pitch[i] == 0)
|
||||
buf->buf.pitch[i] = width * buf->format->cpp[i];
|
||||
if (buf->buf.pitch[i] < width * buf->format->cpp[i])
|
||||
return -EINVAL;
|
||||
if (!buf->buf.gem_id[i])
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* pitch for additional planes must match */
|
||||
if (buf->format->num_planes > 2 &&
|
||||
buf->buf.pitch[1] != buf->buf.pitch[2])
|
||||
return -EINVAL;
|
||||
|
||||
/* check driver limits */
|
||||
ret = exynos_drm_ipp_check_size_limits(buf, fmt->limits,
|
||||
fmt->num_limits,
|
||||
rotate,
|
||||
buf == dst ? swap : false);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect,
|
||||
fmt->limits,
|
||||
fmt->num_limits, swap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
|
||||
{
|
||||
struct exynos_drm_ipp *ipp = task->ipp;
|
||||
const struct exynos_drm_ipp_formats *src_fmt, *dst_fmt;
|
||||
struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst;
|
||||
unsigned int rotation = task->transform.rotation;
|
||||
int ret = 0;
|
||||
@ -607,37 +639,11 @@ static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
src_fmt = __ipp_format_get(ipp, src->buf.fourcc, src->buf.modifier,
|
||||
DRM_EXYNOS_IPP_FORMAT_SOURCE);
|
||||
if (!src_fmt) {
|
||||
DRM_DEBUG_DRIVER("Task %pK: src format not supported\n", task);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = exynos_drm_ipp_check_size_limits(src, src_fmt->limits,
|
||||
src_fmt->num_limits,
|
||||
rotate, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect,
|
||||
src_fmt->limits,
|
||||
src_fmt->num_limits, swap);
|
||||
ret = exynos_drm_ipp_check_format(task, src, src, dst, rotate, swap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dst_fmt = __ipp_format_get(ipp, dst->buf.fourcc, dst->buf.modifier,
|
||||
DRM_EXYNOS_IPP_FORMAT_DESTINATION);
|
||||
if (!dst_fmt) {
|
||||
DRM_DEBUG_DRIVER("Task %pK: dst format not supported\n", task);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = exynos_drm_ipp_check_size_limits(dst, dst_fmt->limits,
|
||||
dst_fmt->num_limits,
|
||||
false, swap);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect,
|
||||
dst_fmt->limits,
|
||||
dst_fmt->num_limits, swap);
|
||||
ret = exynos_drm_ipp_check_format(task, dst, src, dst, false, swap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user