@@ -3,6 +3,8 @@
* Copyright © 2018-2020 Intel Corporation
*/
+#include <linux/dma-buf.h>
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
@@ -11,12 +13,14 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_plane_helper.h>
#include "kmb_drv.h"
#include "kmb_plane.h"
#include "kmb_regs.h"
+#include "kmb_vidmem.h"
const u32 layer_irqs[] = {
LCD_INT_VL0,
@@ -296,6 +300,9 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
unsigned char plane_id;
int num_planes;
static dma_addr_t addr[MAX_SUB_PLANES];
+ struct viv_vidmem_metadata *md = NULL;
+ struct drm_gem_object *gem_obj;
+ unsigned int cb_stride, cr_stride;
if (!plane || !new_plane_state || !old_plane_state)
return;
@@ -325,6 +332,16 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
drm_dbg(&kmb->drm,
"src_w=%d src_h=%d, fb->format->format=0x%x fb->flags=0x%x\n",
src_w, src_h, fb->format->format, fb->flags);
+ gem_obj = drm_gem_fb_get_obj(fb, plane_id);
+ if (gem_obj && gem_obj->import_attach &&
+ gem_obj->import_attach->dmabuf &&
+ gem_obj->import_attach->dmabuf->priv) {
+ md = gem_obj->import_attach->dmabuf->priv;
+
+ /* Check if metadata is coming from hantro driver */
+ if (md->magic != HANTRO_IMAGE_VIV_META_DATA_MAGIC)
+ md = NULL;
+ }
width = fb->width;
height = fb->height;
@@ -332,8 +349,13 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
drm_dbg(&kmb->drm, "dma_len=%d ", dma_len);
kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN(plane_id), dma_len);
kmb_write_lcd(kmb, LCD_LAYERn_DMA_LEN_SHADOW(plane_id), dma_len);
- kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
- fb->pitches[0]);
+ if (md) {
+ kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
+ md->plane[0].stride);
+ } else {
+ kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_VSTRIDE(plane_id),
+ fb->pitches[0]);
+ }
kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
(width * fb->format->cpp[0]));
@@ -344,13 +366,19 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
val |= get_bits_per_pixel(fb->format);
/* Program Cb/Cr for planar formats */
if (num_planes > 1) {
- kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
- width * fb->format->cpp[0]);
- kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
- (width * fb->format->cpp[0]));
-
- addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state,
- U_PLANE);
+ cb_stride = md ? md->plane[1].stride :
+ width * fb->format->cpp[0];
+ kmb_write_lcd(kmb,
+ LCD_LAYERn_DMA_CB_LINE_VSTRIDE(plane_id),
+ cb_stride);
+
+ if (md) {
+ addr[U_PLANE] = addr[Y_PLANE] + md->plane[1].offset;
+ } else {
+ addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb,
+ new_plane_state,
+ U_PLANE);
+ }
/* check if Cb/Cr is swapped*/
if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))
kmb_write_lcd(kmb,
@@ -362,17 +390,25 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
addr[U_PLANE]);
if (num_planes == 3) {
+ cr_stride = md ? md->plane[2].stride :
+ width * fb->format->cpp[0];
kmb_write_lcd(kmb,
LCD_LAYERn_DMA_CR_LINE_VSTRIDE(plane_id),
- ((width) * fb->format->cpp[0]));
+ cr_stride);
kmb_write_lcd(kmb,
LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
((width) * fb->format->cpp[0]));
- addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
+ if (md) {
+ addr[V_PLANE] = addr[Y_PLANE] +
+ md->plane[2].offset;
+ } else {
+ addr[V_PLANE] =
+ drm_fb_cma_get_gem_addr(fb,
new_plane_state,
V_PLANE);
+ }
/* check if Cb/Cr is swapped*/
if (val & LCD_LAYER_CRCB_ORDER)
new file mode 100644
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright © 2018-2020 Intel Corporation
+ */
+
+#ifndef __KMB_VIDMEM_H__
+#define __KMB_VIDMEM_H__
+
+#define HANTRO_MAGIC(ch0, ch1, ch2, ch3) \
+ ((unsigned long)(unsigned char)(ch0) | \
+ ((unsigned long)(unsigned char)(ch1) << 8) | \
+ ((unsigned long)(unsigned char)(ch2) << 16) | \
+ ((unsigned long)(unsigned char)(ch3) << 24))
+
+#define HANTRO_IMAGE_VIV_META_DATA_MAGIC HANTRO_MAGIC('V', 'I', 'V', 'M')
+
+struct viv_vidmem_metadata {
+ u32 magic; // __FOURCC('v', 'i', 'v', 'm')
+ u32 dmabuf_size; // DMABUF buffer size in byte (Maximum 4GB)
+ u32 time_stamp; // time stamp for the DMABUF buffer
+
+ u32 image_format; // ImageFormat, determined plane number.
+ u32 compressed; // if DMABUF buffer is compressed by DEC400
+ struct {
+ u32 offset; // plane buffer address offset from DMABUF address
+ u32 stride; // pitch in bytes
+ u32 width; // width in pixels
+ u32 height; // height in pixels
+
+ u32 tile_format; // uncompressed tile format
+ u32 compress_format; // tile mode for DEC400
+
+ /** tile status buffer offset within this plane buffer. when it is 0,
+ * indicates using separate tile status buffer
+ */
+ u32 ts_offset;
+ /** fd of separate tile status buffer of the plane buffer */
+ u32 ts_fd;
+ /** valid fd of the ts buffer in consumer side. */
+ u32 ts_fd2;
+ /** the vpu virtual address for this ts data buffer */
+ u32 ts_vaddr;
+
+ /** gpu fastclear enabled for the plane buffer */
+ u32 fc_enabled;
+ /** gpu fastclear color value (lower 32 bits) for the plane buffer */
+ u32 fc_value_lower;
+ /** gpu fastclear color value (upper 32 bits) for the plane buffer */
+ u32 fc_value_upper;
+ } plane[3];
+};
+#endif /*__KMB_VIDMEM_H__*/