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);
+ u32 last_line_size;
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",
return -EINVAL;
}
- if ((u64) height * buf->pitch[i] + buf->offset[i] >
- buf->dma_bufs[i]->size) {
+ switch (dev->ops->quirks.buffer_padding) {
+ case ADF_BUFFER_PADDED_TO_PITCH:
+ last_line_size = buf->pitch[i];
+ break;
+
+ case ADF_BUFFER_UNPADDED:
+ last_line_size = width * cpp;
+ break;
+
+ default:
+ BUG();
+ }
+
+ if ((u64) (height - 1) * buf->pitch[i] + last_line_size +
+ 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);
int minor;
};
+/**
+ * struct adf_device_quirks - common display device quirks
+ *
+ * @buffer_padding: whether the last scanline of a buffer extends to the
+ * buffer's pitch (@ADF_BUFFER_PADDED_TO_PITCH) or just to the visible
+ * width (@ADF_BUFFER_UNPADDED)
+ */
+struct adf_device_quirks {
+ /* optional, defaults to ADF_BUFFER_PADDED_TO_PITCH */
+ enum {
+ ADF_BUFFER_PADDED_TO_PITCH = 0,
+ ADF_BUFFER_UNPADDED = 1,
+ } buffer_padding;
+};
+
/**
* struct adf_device_ops - display device implementation ops
*
* @owner: device's module
* @base: common operations (see &struct adf_obj_ops)
+ * @quirks: device's quirks (see &struct adf_device_quirks)
*
* @attach: attach overlay engine @eng to interface @intf. Return 0 on success
* or error code (<0) on failure.
/* required */
struct module *owner;
const struct adf_obj_ops base;
+ /* optional */
+ const struct adf_device_quirks quirks;
/* optional */
int (*attach)(struct adf_device *dev, struct adf_overlay_engine *eng,