diff options
author | Greg Hackmann <ghackmann@google.com> | 2013-10-15 12:51:20 -0700 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2016-02-16 13:53:12 -0800 |
commit | 1f9e414c3a3bc12277c707617f0f49c2f02e51bd (patch) | |
tree | ebc2257b9673c8e5681c589993bcdbd62c9fd959 /drivers/video | |
parent | e45fc30f3ee796625e26a8a9d7936bd273e1018f (diff) |
video: adf: add helpers for validating custom formats
Many custom formats look a lot like the standard ones, but with
different subsampling, bpp, etc. Expose and document
adf_buffer_validate()'s main body, so drivers can reuse its logic when
validating these formats.
Change-Id: I1d06981c9e5aab26f3ab2956c08c679f2c823bcc
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/adf/adf.c | 64 | ||||
-rw-r--r-- | drivers/video/adf/adf_client.c | 49 |
2 files changed, 71 insertions, 42 deletions
diff --git a/drivers/video/adf/adf.c b/drivers/video/adf/adf.c index 79511759d2a5..64f763d02dcf 100644 --- a/drivers/video/adf/adf.c +++ b/drivers/video/adf/adf.c @@ -1027,6 +1027,70 @@ void adf_format_str(u32 format, char buf[ADF_FORMAT_STR_SIZE]) } EXPORT_SYMBOL(adf_format_str); +/** + * adf_format_validate_yuv - validate the number and size of planes in buffers + * with a custom YUV format. + * + * @dev: ADF device performing the validation + * @buf: buffer to validate + * @num_planes: expected number of planes + * @hsub: expected horizontal chroma subsampling factor, in pixels + * @vsub: expected vertical chroma subsampling factor, in pixels + * @cpp: expected bytes per pixel for each plane (length @num_planes) + * + * adf_format_validate_yuv() is intended to be called as a helper from @dev's + * validate_custom_format() op. + * + * Returns 0 if @buf has the expected number of planes and each plane + * has sufficient size, or -EINVAL otherwise. + */ +int adf_format_validate_yuv(struct adf_device *dev, struct adf_buffer *buf, + u8 num_planes, u8 hsub, u8 vsub, u8 cpp[]) +{ + u8 i; + + if (num_planes != buf->n_planes) { + char format_str[ADF_FORMAT_STR_SIZE]; + adf_format_str(buf->format, format_str); + dev_err(&dev->base.dev, "%u planes expected for format %s but %u planes provided\n", + num_planes, format_str, buf->n_planes); + return -EINVAL; + } + + if (buf->w == 0 || buf->w % hsub) { + dev_err(&dev->base.dev, "bad buffer width %u\n", buf->w); + return -EINVAL; + } + + if (buf->h == 0 || buf->h % vsub) { + dev_err(&dev->base.dev, "bad buffer height %u\n", buf->h); + return -EINVAL; + } + + for (i = 0; i < num_planes; i++) { + u32 width = buf->w / (i != 0 ? hsub : 1); + u32 height = buf->h / (i != 0 ? vsub : 1); + u8 cpp = adf_format_plane_cpp(buf->format, i); + + if (buf->pitch[i] < (u64) width * cpp) { + dev_err(&dev->base.dev, "plane %u pitch is shorter than buffer width (pitch = %u, width = %u, bpp = %u)\n", + i, buf->pitch[i], width, cpp * 8); + return -EINVAL; + } + + if ((u64) height * buf->pitch[i] + buf->offset[i] > + buf->dma_bufs[i]->size) { + dev_err(&dev->base.dev, "plane %u buffer too small (height = %u, pitch = %u, offset = %u, size = %zu)\n", + i, height, buf->pitch[i], + buf->offset[i], buf->dma_bufs[i]->size); + return -EINVAL; + } + } + + return 0; +} +EXPORT_SYMBOL(adf_format_validate_yuv); + void adf_modeinfo_set_name(struct drm_mode_modeinfo *mode) { bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; diff --git a/drivers/video/adf/adf_client.c b/drivers/video/adf/adf_client.c index 48e97ef262fb..e4a792135072 100644 --- a/drivers/video/adf/adf_client.c +++ b/drivers/video/adf/adf_client.c @@ -244,7 +244,8 @@ static int adf_buffer_validate(struct adf_buffer *buf) { struct adf_overlay_engine *eng = buf->overlay_engine; struct device *dev = &eng->base.dev; - u8 hsub, vsub, num_planes, i; + struct adf_device *parent = adf_overlay_engine_parent(eng); + u8 hsub, vsub, num_planes, cpp[ADF_MAX_PLANES], i; if (!adf_overlay_engine_supports_format(eng, buf->format)) { char format_str[ADF_FORMAT_STR_SIZE]; @@ -253,53 +254,17 @@ static int adf_buffer_validate(struct adf_buffer *buf) return -EINVAL; } - if (!adf_format_is_standard(buf->format)) { - struct adf_device *parent = adf_overlay_engine_parent(eng); + if (!adf_format_is_standard(buf->format)) return parent->ops->validate_custom_format(parent, buf); - } hsub = adf_format_horz_chroma_subsampling(buf->format); vsub = adf_format_vert_chroma_subsampling(buf->format); num_planes = adf_format_num_planes(buf->format); + for (i = 0; i < num_planes; i++) + cpp[i] = adf_format_plane_cpp(buf->format, i); - if (num_planes != buf->n_planes) { - char format_str[ADF_FORMAT_STR_SIZE]; - adf_format_str(buf->format, format_str); - dev_err(dev, "%u planes expected for format %s but %u planes provided\n", - num_planes, format_str, buf->n_planes); - return -EINVAL; - } - - if (buf->w == 0 || buf->w % hsub) { - dev_err(dev, "bad buffer width %u\n", buf->w); - return -EINVAL; - } - - if (buf->h == 0 || buf->h % vsub) { - dev_err(dev, "bad buffer height %u\n", buf->h); - return -EINVAL; - } - - for (i = 0; i < num_planes; i++) { - u32 width = buf->w / (i != 0 ? hsub : 1); - u32 height = buf->h / (i != 0 ? vsub : 1); - u8 cpp = adf_format_plane_cpp(buf->format, i); - - if (buf->pitch[i] < (u64) width * cpp) { - dev_err(dev, "plane %u pitch is shorter than buffer width (pitch = %u, width = %u, bpp = %u)\n", - i, buf->pitch[i], width, cpp * 8); - return -EINVAL; - } - - if ((u64) height * buf->pitch[i] + buf->offset[i] > - buf->dma_bufs[i]->size) { - dev_err(dev, "plane %u buffer too small (height = %u, pitch = %u, offset = %u, size = %zu)\n", - i, height, buf->pitch[i], - buf->offset[i], buf->dma_bufs[i]->size); - } - } - - return 0; + return adf_format_validate_yuv(parent, buf, num_planes, hsub, vsub, + cpp); } static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf, |