mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-30 08:02:30 +00:00
Fixups
- Fix several problems to IPPv2 merged to mainline recentely. . An align problem of width size that IPP driver incorrectly calculated the real buffer size. . Horizontal and vertical flip problem. . Per-plane global alpha for XRGB modes. . Incorrect variant of the YUV modes. - Fix plane overlapping problem. . The stange order of overlapping planes on XRGB modes by setting global alpha value to maximum value. Cleanup - Rename a enum type, drm_ipp_size_id, to one specific to Exynos, drm_exynos_ipp_limit_type. - Replace {un/reference} with {put,get} functions. . it replaces several reference/unreference functions with Linux kernel nameing standard. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJbOcEtAAoJEFc4NIkMQxK4fOIQALMX/zww/9iqbLmQCE0q1Idi VmEV/os/Is0yxYXndluKbSVrRlf4bi54ETATOVoxuIlBxPwbJn3q7CdXbOUsc123 1n5PThLW9g7L9/oIPRgYXDn80rSdoy9AvR04f24AbP95xkCwLosxKOpMkFia9irH jaYXDuP0hxHXeMCt8B18OUM0JhY9rad7yPJgRINeFfRAWe1+qPoR68HeztVLCi4G f6VBkgoKDGH8ngQIEtkC0p6ouN/z8kcVtcA5Ob9KIld9hnztU84I7sidP4StkPUS kvbICe2ro7xPbEIRDn7AzjYAmPJHJEHxKrvbDlOoRGhRuqHHK8HyRhIiOsFYPZgW liGVXUvEaV7WjaSL6eAtzSxaLsPC9Z7lj0Ry/x/P+aZrREceaOkOI23C0g13zmPs MCVVnt0asJDPxI2o1epy1AQoAnaVVshuJhpRQYBvYhiNcL7JLyooczGuROFVkQ2q Chg9wgM8R5LEh6vnt7ZZHmD3bSsIY0OUzoQvoF1WP1EIItusYw5DQNL4CrbQY1rb oooz8UP+rGiPKnfZcNruBrT13EQdOE7dz26W+cHRjmZmDDU/8QDnaSnLqD3xr6Yv 2vTyaB8pWWZttih01tADkDqA+rmRnd3ffyA1Zjwzv7Tey6pW8uqiSwoZrAZuj7ek aq0SJRXt6dvoY6nDFy5R =+7bq -----END PGP SIGNATURE----- Merge tag 'exynos-drm-fixes-for-v4.18-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-fixes Fixups - Fix several problems to IPPv2 merged to mainline recentely. . An align problem of width size that IPP driver incorrectly calculated the real buffer size. . Horizontal and vertical flip problem. . Per-plane global alpha for XRGB modes. . Incorrect variant of the YUV modes. - Fix plane overlapping problem. . The stange order of overlapping planes on XRGB modes by setting global alpha value to maximum value. Cleanup - Rename a enum type, drm_ipp_size_id, to one specific to Exynos, drm_exynos_ipp_limit_type. - Replace {un/reference} with {put,get} functions. . it replaces several reference/unreference functions with Linux kernel nameing standard. Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/1530512041-21392-1-git-send-email-inki.dae@samsung.com
This commit is contained in:
commit
c78d1f9d95
11 changed files with 149 additions and 102 deletions
|
@ -265,7 +265,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
|
|||
unsigned long val;
|
||||
|
||||
val = readl(ctx->addr + DECON_WINCONx(win));
|
||||
val &= ~WINCONx_BPPMODE_MASK;
|
||||
val &= WINCONx_ENWIN_F;
|
||||
|
||||
switch (fb->format->format) {
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
|
@ -356,8 +356,8 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
|
|||
writel(val, ctx->addr + DECON_VIDOSDxB(win));
|
||||
}
|
||||
|
||||
val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
|
||||
VIDOSD_Wx_ALPHA_B_F(0x0);
|
||||
val = VIDOSD_Wx_ALPHA_R_F(0xff) | VIDOSD_Wx_ALPHA_G_F(0xff) |
|
||||
VIDOSD_Wx_ALPHA_B_F(0xff);
|
||||
writel(val, ctx->addr + DECON_VIDOSDxC(win));
|
||||
|
||||
val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
|
||||
|
|
|
@ -420,7 +420,7 @@ static int exynos_drm_bind(struct device *dev)
|
|||
err_free_private:
|
||||
kfree(private);
|
||||
err_free_drm:
|
||||
drm_dev_unref(drm);
|
||||
drm_dev_put(drm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -444,7 +444,7 @@ static void exynos_drm_unbind(struct device *dev)
|
|||
drm->dev_private = NULL;
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
drm_dev_unref(drm);
|
||||
drm_dev_put(drm);
|
||||
}
|
||||
|
||||
static const struct component_master_ops exynos_drm_ops = {
|
||||
|
|
|
@ -138,7 +138,7 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
|||
|
||||
err:
|
||||
while (i--)
|
||||
drm_gem_object_unreference_unlocked(&exynos_gem[i]->base);
|
||||
drm_gem_object_put_unlocked(&exynos_gem[i]->base);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
|
@ -470,17 +470,18 @@ static void fimc_src_set_transf(struct fimc_context *ctx, unsigned int rotation)
|
|||
static void fimc_set_window(struct fimc_context *ctx,
|
||||
struct exynos_drm_ipp_buffer *buf)
|
||||
{
|
||||
unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
|
||||
u32 cfg, h1, h2, v1, v2;
|
||||
|
||||
/* cropped image */
|
||||
h1 = buf->rect.x;
|
||||
h2 = buf->buf.width - buf->rect.w - buf->rect.x;
|
||||
h2 = real_width - buf->rect.w - buf->rect.x;
|
||||
v1 = buf->rect.y;
|
||||
v2 = buf->buf.height - buf->rect.h - buf->rect.y;
|
||||
|
||||
DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
|
||||
buf->rect.x, buf->rect.y, buf->rect.w, buf->rect.h,
|
||||
buf->buf.width, buf->buf.height);
|
||||
real_width, buf->buf.height);
|
||||
DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
|
||||
|
||||
/*
|
||||
|
@ -503,12 +504,13 @@ static void fimc_set_window(struct fimc_context *ctx,
|
|||
static void fimc_src_set_size(struct fimc_context *ctx,
|
||||
struct exynos_drm_ipp_buffer *buf)
|
||||
{
|
||||
unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", buf->buf.width, buf->buf.height);
|
||||
DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", real_width, buf->buf.height);
|
||||
|
||||
/* original size */
|
||||
cfg = (EXYNOS_ORGISIZE_HORIZONTAL(buf->buf.width) |
|
||||
cfg = (EXYNOS_ORGISIZE_HORIZONTAL(real_width) |
|
||||
EXYNOS_ORGISIZE_VERTICAL(buf->buf.height));
|
||||
|
||||
fimc_write(ctx, cfg, EXYNOS_ORGISIZE);
|
||||
|
@ -529,7 +531,7 @@ static void fimc_src_set_size(struct fimc_context *ctx,
|
|||
* for now, we support only ITU601 8 bit mode
|
||||
*/
|
||||
cfg = (EXYNOS_CISRCFMT_ITU601_8BIT |
|
||||
EXYNOS_CISRCFMT_SOURCEHSIZE(buf->buf.width) |
|
||||
EXYNOS_CISRCFMT_SOURCEHSIZE(real_width) |
|
||||
EXYNOS_CISRCFMT_SOURCEVSIZE(buf->buf.height));
|
||||
fimc_write(ctx, cfg, EXYNOS_CISRCFMT);
|
||||
|
||||
|
@ -842,12 +844,13 @@ static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
|
|||
static void fimc_dst_set_size(struct fimc_context *ctx,
|
||||
struct exynos_drm_ipp_buffer *buf)
|
||||
{
|
||||
unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0];
|
||||
u32 cfg, cfg_ext;
|
||||
|
||||
DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", buf->buf.width, buf->buf.height);
|
||||
DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", real_width, buf->buf.height);
|
||||
|
||||
/* original size */
|
||||
cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(buf->buf.width) |
|
||||
cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(real_width) |
|
||||
EXYNOS_ORGOSIZE_VERTICAL(buf->buf.height));
|
||||
|
||||
fimc_write(ctx, cfg, EXYNOS_ORGOSIZE);
|
||||
|
|
|
@ -143,7 +143,7 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
|||
DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle);
|
||||
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
|
|||
|
||||
exynos_gem = to_exynos_gem(obj);
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
|
||||
return exynos_gem->size;
|
||||
}
|
||||
|
@ -329,13 +329,13 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
|
|||
return;
|
||||
}
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
|
||||
/*
|
||||
* decrease obj->refcount one more time because we has already
|
||||
* increased it at exynos_drm_gem_get_dma_addr().
|
||||
*/
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
}
|
||||
|
||||
static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
|
||||
|
@ -383,7 +383,7 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
|||
args->flags = exynos_gem->flags;
|
||||
args->size = exynos_gem->size;
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -492,21 +492,25 @@ static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt)
|
|||
GSC_IN_CHROMA_ORDER_CRCB);
|
||||
break;
|
||||
case DRM_FORMAT_NV21:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV61:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB |
|
||||
GSC_IN_YUV420_2P);
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV422_2P);
|
||||
break;
|
||||
case DRM_FORMAT_YUV422:
|
||||
cfg |= GSC_IN_YUV422_3P;
|
||||
break;
|
||||
case DRM_FORMAT_YUV420:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_YVU420:
|
||||
cfg |= GSC_IN_YUV420_3P;
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_NV12:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV16:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR |
|
||||
GSC_IN_YUV420_2P);
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV422_2P);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -523,30 +527,30 @@ static void gsc_src_set_transf(struct gsc_context *ctx, unsigned int rotation)
|
|||
|
||||
switch (degree) {
|
||||
case DRM_MODE_ROTATE_0:
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg |= GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_X)
|
||||
cfg |= GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg |= GSC_IN_ROT_YFLIP;
|
||||
break;
|
||||
case DRM_MODE_ROTATE_90:
|
||||
cfg |= GSC_IN_ROT_90;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg |= GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_X)
|
||||
cfg |= GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg |= GSC_IN_ROT_YFLIP;
|
||||
break;
|
||||
case DRM_MODE_ROTATE_180:
|
||||
cfg |= GSC_IN_ROT_180;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg &= ~GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_X)
|
||||
cfg &= ~GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg &= ~GSC_IN_ROT_YFLIP;
|
||||
break;
|
||||
case DRM_MODE_ROTATE_270:
|
||||
cfg |= GSC_IN_ROT_270;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg &= ~GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_X)
|
||||
cfg &= ~GSC_IN_ROT_XFLIP;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
cfg &= ~GSC_IN_ROT_YFLIP;
|
||||
break;
|
||||
}
|
||||
|
@ -577,7 +581,7 @@ static void gsc_src_set_size(struct gsc_context *ctx,
|
|||
cfg &= ~(GSC_SRCIMG_HEIGHT_MASK |
|
||||
GSC_SRCIMG_WIDTH_MASK);
|
||||
|
||||
cfg |= (GSC_SRCIMG_WIDTH(buf->buf.width) |
|
||||
cfg |= (GSC_SRCIMG_WIDTH(buf->buf.pitch[0] / buf->format->cpp[0]) |
|
||||
GSC_SRCIMG_HEIGHT(buf->buf.height));
|
||||
|
||||
gsc_write(cfg, GSC_SRCIMG_SIZE);
|
||||
|
@ -672,18 +676,25 @@ static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt)
|
|||
GSC_OUT_CHROMA_ORDER_CRCB);
|
||||
break;
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV61:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV61:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV422_2P);
|
||||
break;
|
||||
case DRM_FORMAT_YUV422:
|
||||
cfg |= GSC_OUT_YUV422_3P;
|
||||
break;
|
||||
case DRM_FORMAT_YUV420:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_YVU420:
|
||||
cfg |= GSC_OUT_YUV420_3P;
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_NV12:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV16:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR |
|
||||
GSC_OUT_YUV420_2P);
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV422_2P);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -868,7 +879,7 @@ static void gsc_dst_set_size(struct gsc_context *ctx,
|
|||
/* original size */
|
||||
cfg = gsc_read(GSC_DSTIMG_SIZE);
|
||||
cfg &= ~(GSC_DSTIMG_HEIGHT_MASK | GSC_DSTIMG_WIDTH_MASK);
|
||||
cfg |= GSC_DSTIMG_WIDTH(buf->buf.width) |
|
||||
cfg |= GSC_DSTIMG_WIDTH(buf->buf.pitch[0] / buf->format->cpp[0]) |
|
||||
GSC_DSTIMG_HEIGHT(buf->buf.height);
|
||||
gsc_write(cfg, GSC_DSTIMG_SIZE);
|
||||
|
||||
|
@ -1341,7 +1352,7 @@ static const struct drm_exynos_ipp_limit gsc_5420_limits[] = {
|
|||
};
|
||||
|
||||
static const struct drm_exynos_ipp_limit gsc_5433_limits[] = {
|
||||
{ IPP_SIZE_LIMIT(BUFFER, .h = { 32, 8191, 2 }, .v = { 16, 8191, 2 }) },
|
||||
{ IPP_SIZE_LIMIT(BUFFER, .h = { 32, 8191, 16 }, .v = { 16, 8191, 2 }) },
|
||||
{ IPP_SIZE_LIMIT(AREA, .h = { 16, 4800, 1 }, .v = { 8, 3344, 1 }) },
|
||||
{ IPP_SIZE_LIMIT(ROTATED, .h = { 32, 2047 }, .v = { 8, 8191 }) },
|
||||
{ IPP_SCALE_LIMIT(.h = { (1 << 16) / 16, (1 << 16) * 8 },
|
||||
|
|
|
@ -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 :
|
||||
|
@ -428,7 +407,7 @@ enum drm_ipp_size_id {
|
|||
IPP_LIMIT_BUFFER, IPP_LIMIT_AREA, IPP_LIMIT_ROTATED, IPP_LIMIT_MAX
|
||||
};
|
||||
|
||||
static const enum drm_ipp_size_id limit_id_fallback[IPP_LIMIT_MAX][4] = {
|
||||
static const enum drm_exynos_ipp_limit_type limit_id_fallback[IPP_LIMIT_MAX][4] = {
|
||||
[IPP_LIMIT_BUFFER] = { DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER },
|
||||
[IPP_LIMIT_AREA] = { DRM_EXYNOS_IPP_LIMIT_SIZE_AREA,
|
||||
DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER },
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
|
|||
if (plane->state) {
|
||||
exynos_state = to_exynos_plane_state(plane->state);
|
||||
if (exynos_state->base.fb)
|
||||
drm_framebuffer_unreference(exynos_state->base.fb);
|
||||
drm_framebuffer_put(exynos_state->base.fb);
|
||||
kfree(exynos_state);
|
||||
plane->state = NULL;
|
||||
}
|
||||
|
|
|
@ -168,9 +168,9 @@ static void rotator_dst_set_transf(struct rot_context *rot,
|
|||
val &= ~ROT_CONTROL_FLIP_MASK;
|
||||
|
||||
if (rotation & DRM_MODE_REFLECT_X)
|
||||
val |= ROT_CONTROL_FLIP_HORIZONTAL;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
val |= ROT_CONTROL_FLIP_VERTICAL;
|
||||
if (rotation & DRM_MODE_REFLECT_Y)
|
||||
val |= ROT_CONTROL_FLIP_HORIZONTAL;
|
||||
|
||||
val &= ~ROT_CONTROL_ROT_MASK;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define scaler_write(cfg, offset) writel(cfg, scaler->regs + (offset))
|
||||
#define SCALER_MAX_CLK 4
|
||||
#define SCALER_AUTOSUSPEND_DELAY 2000
|
||||
#define SCALER_RESET_WAIT_RETRIES 100
|
||||
|
||||
struct scaler_data {
|
||||
const char *clk_name[SCALER_MAX_CLK];
|
||||
|
@ -51,9 +52,9 @@ struct scaler_context {
|
|||
static u32 scaler_get_format(u32 drm_fmt)
|
||||
{
|
||||
switch (drm_fmt) {
|
||||
case DRM_FORMAT_NV21:
|
||||
return SCALER_YUV420_2P_UV;
|
||||
case DRM_FORMAT_NV12:
|
||||
return SCALER_YUV420_2P_UV;
|
||||
case DRM_FORMAT_NV21:
|
||||
return SCALER_YUV420_2P_VU;
|
||||
case DRM_FORMAT_YUV420:
|
||||
return SCALER_YUV420_3P;
|
||||
|
@ -63,15 +64,15 @@ static u32 scaler_get_format(u32 drm_fmt)
|
|||
return SCALER_YUV422_1P_UYVY;
|
||||
case DRM_FORMAT_YVYU:
|
||||
return SCALER_YUV422_1P_YVYU;
|
||||
case DRM_FORMAT_NV61:
|
||||
return SCALER_YUV422_2P_UV;
|
||||
case DRM_FORMAT_NV16:
|
||||
return SCALER_YUV422_2P_UV;
|
||||
case DRM_FORMAT_NV61:
|
||||
return SCALER_YUV422_2P_VU;
|
||||
case DRM_FORMAT_YUV422:
|
||||
return SCALER_YUV422_3P;
|
||||
case DRM_FORMAT_NV42:
|
||||
return SCALER_YUV444_2P_UV;
|
||||
case DRM_FORMAT_NV24:
|
||||
return SCALER_YUV444_2P_UV;
|
||||
case DRM_FORMAT_NV42:
|
||||
return SCALER_YUV444_2P_VU;
|
||||
case DRM_FORMAT_YUV444:
|
||||
return SCALER_YUV444_3P;
|
||||
|
@ -100,6 +101,23 @@ static u32 scaler_get_format(u32 drm_fmt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int scaler_reset(struct scaler_context *scaler)
|
||||
{
|
||||
int retry = SCALER_RESET_WAIT_RETRIES;
|
||||
|
||||
scaler_write(SCALER_CFG_SOFT_RESET, SCALER_CFG);
|
||||
do {
|
||||
cpu_relax();
|
||||
} while (retry > 1 &&
|
||||
scaler_read(SCALER_CFG) & SCALER_CFG_SOFT_RESET);
|
||||
do {
|
||||
cpu_relax();
|
||||
scaler_write(1, SCALER_INT_EN);
|
||||
} while (retry > 0 && scaler_read(SCALER_INT_EN) != 1);
|
||||
|
||||
return retry ? 0 : -EIO;
|
||||
}
|
||||
|
||||
static inline void scaler_enable_int(struct scaler_context *scaler)
|
||||
{
|
||||
u32 val;
|
||||
|
@ -354,9 +372,13 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
|
|||
u32 dst_fmt = scaler_get_format(task->dst.buf.fourcc);
|
||||
struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect;
|
||||
|
||||
scaler->task = task;
|
||||
|
||||
pm_runtime_get_sync(scaler->dev);
|
||||
if (scaler_reset(scaler)) {
|
||||
pm_runtime_put(scaler->dev);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
scaler->task = task;
|
||||
|
||||
scaler_set_src_fmt(scaler, src_fmt);
|
||||
scaler_set_src_base(scaler, &task->src);
|
||||
|
@ -394,7 +416,11 @@ static inline void scaler_disable_int(struct scaler_context *scaler)
|
|||
|
||||
static inline u32 scaler_get_int_status(struct scaler_context *scaler)
|
||||
{
|
||||
return scaler_read(SCALER_INT_STATUS);
|
||||
u32 val = scaler_read(SCALER_INT_STATUS);
|
||||
|
||||
scaler_write(val, SCALER_INT_STATUS);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline int scaler_task_done(u32 val)
|
||||
|
|
|
@ -138,6 +138,7 @@
|
|||
#define GSC_OUT_YUV420_3P (3 << 4)
|
||||
#define GSC_OUT_YUV422_1P (4 << 4)
|
||||
#define GSC_OUT_YUV422_2P (5 << 4)
|
||||
#define GSC_OUT_YUV422_3P (6 << 4)
|
||||
#define GSC_OUT_YUV444 (7 << 4)
|
||||
#define GSC_OUT_TILE_TYPE_MASK (1 << 2)
|
||||
#define GSC_OUT_TILE_C_16x8 (0 << 2)
|
||||
|
|
Loading…
Reference in a new issue