OMAPLFB/DSSCOMP: Added support for non-gralloc layers in Post2
Reworked OMAPLFB to work with new layer indexing in hwc. Post2
layers are now specified directly (vs. assuming co-ordered
dsscomp and post2 layers).
This allows specifying non-post2 layers, such as static images
that HWC may choose to display on external displays.
Added support to display external FBMEM images in addition
to the layers passed to Post2.
Change-Id: I4f7e4946c7656c0d1c70e4f89649054ea253e92a
Signed-off-by: Lajos Molnar <lajos@ti.com>
diff --git a/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c b/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c
index 69b0dfe..53ad0c0 100644
--- a/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c
+++ b/drivers/gpu/pvr/omaplfb/omaplfb_displayclass.c
@@ -878,6 +878,13 @@
{
struct tiler_pa_info *apsTilerPAs[5];
IMG_UINT32 i, k;
+ struct {
+ IMG_UINTPTR_T uiAddr;
+ IMG_UINTPTR_T uiUVAddr;
+ struct tiler_pa_info *psTilerInfo;
+ } asMemInfo[5];
+
+ memset(asMemInfo, 0, sizeof(asMemInfo));
if(uiDssDataLength != sizeof(*psDssData))
{
@@ -904,30 +911,23 @@
psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetByteSize(ppsMemInfos[i], &uByteSize);
ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
- apsTilerPAs[k] = NULL;
-
psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr);
- /* NV12 buffers do not need meminfos */
- if(psDssData->ovls[k].cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ /* TILER buffers do not need meminfos */
+ if(is_tiler_addr((u32)phyAddr.uiAddr))
{
- /* must have still 2 meminfos in array */
- BUG_ON(i + 1 >= ui32NumMemInfos);
- psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
-
- i++;
- psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr);
- psDssData->ovls[k].uv = (u32)phyAddr.uiAddr;
-
- continue;
- }
- /* check if it is a TILER buffer */
- else if(is_tiler_addr((u32)phyAddr.uiAddr))
- {
- psDssData->ovls[k].ba = (u32)phyAddr.uiAddr;
+ asMemInfo[k].uiAddr = phyAddr.uiAddr;
+ if (tiler_fmt((u32)phyAddr.uiAddr) == TILFMT_8BIT) {
+ /* NV12 buffers have 2 meminfos */
+ BUG_ON(i + 1 >= ui32NumMemInfos);
+ i++;
+ psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], 0, &phyAddr);
+ asMemInfo[k].uiUVAddr = phyAddr.uiAddr;
+ }
continue;
}
+ /* normal gralloc layer */
psTilerInfo = kzalloc(sizeof(*psTilerInfo), GFP_KERNEL);
if(!psTilerInfo)
{
@@ -943,7 +943,6 @@
psTilerInfo->num_pg = ui32NumPages;
psTilerInfo->memtype = TILER_MEM_USING;
-
for(j = 0; j < ui32NumPages; j++)
{
psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &phyAddr);
@@ -952,23 +951,37 @@
/* need base address for in-page offset */
psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr);
- psDssData->ovls[k].ba = (u32)virtAddr;
- apsTilerPAs[k] = psTilerInfo;
+ asMemInfo[k].uiAddr = (IMG_UINTPTR_T) virtAddr;
+ asMemInfo[k].psTilerInfo = psTilerInfo;
}
- /* set up cloned layer addresses (but don't duplicate tiler_pas) */
- for(i = k; i < psDssData->num_ovls && i < ARRAY_SIZE(apsTilerPAs); i++)
+ for(i = 0; i < psDssData->num_ovls; i++)
{
- unsigned int ix = psDssData->ovls[i].ba;
- if(ix >= ARRAY_SIZE(apsTilerPAs))
+ unsigned int ix;
+ apsTilerPAs[i] = NULL;
+
+ /* only supporting Post2, cloned and fbmem layers */
+ if (psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_LAYER_IX &&
+ psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_OVL_IX &&
+ psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_FB)
+ psDssData->ovls[i].cfg.enabled = false;
+
+ if (psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_LAYER_IX)
+ continue;
+
+ /* Post2 layers */
+ ix = psDssData->ovls[i].ba;
+ if (ix >= k)
{
- WARN(1, "Invalid clone layer (%u); skipping all cloned layers", ix);
- psDssData->num_ovls = k;
- break;
+ WARN(1, "Invalid Post2 layer (%u)", ix);
+ psDssData->ovls[i].cfg.enabled = false;
+ continue;
}
- apsTilerPAs[i] = apsTilerPAs[ix];
- psDssData->ovls[i].ba = psDssData->ovls[ix].ba;
- psDssData->ovls[i].uv = psDssData->ovls[ix].uv;
+
+ psDssData->ovls[i].addressing = OMAP_DSS_BUFADDR_DIRECT;
+ psDssData->ovls[i].ba = (u32) asMemInfo[ix].uiAddr;
+ psDssData->ovls[i].uv = (u32) asMemInfo[ix].uiUVAddr;
+ apsTilerPAs[i] = asMemInfo[ix].psTilerInfo;
}
dsscomp_gralloc_queue(psDssData, apsTilerPAs, false,
@@ -1164,7 +1177,7 @@
goto ErrorModPut;
}
- psLINFBInfo->fix.smem_start = ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
+ ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
psPVRFBInfo->sSysAddr.uiAddr = phys;
psPVRFBInfo->sCPUVAddr = 0;
diff --git a/drivers/video/omap2/dsscomp/gralloc.c b/drivers/video/omap2/dsscomp/gralloc.c
index 3c01bb5..cbc9203 100644
--- a/drivers/video/omap2/dsscomp/gralloc.c
+++ b/drivers/video/omap2/dsscomp/gralloc.c
@@ -298,25 +298,57 @@
if (d->mgrs[mgr_ix].swap_rb)
swap_rb_in_ovl_info(d->ovls + i);
+ /* copy prior overlay to avoid mapping layers twice to 1D */
+ if (oi->addressing == OMAP_DSS_BUFADDR_OVL_IX) {
+ unsigned int j = oi->ba;
+ if (j >= i) {
+ WARN(1, "Invalid clone layer (%u)", j);
+ goto skip_buffer;
+ }
+
+ oi->ba = d->ovls[j].ba;
+ oi->uv = d->ovls[j].uv;
+ goto skip_map1d;
+ } else if (oi->addressing == OMAP_DSS_BUFADDR_FB) {
+ /* get fb */
+ int fb_ix = (oi->ba >> 28);
+ int fb_uv_ix = (oi->uv >> 28);
+ struct fb_info *fbi = NULL, *fbi_uv = NULL;
+ size_t size = oi->cfg.height * oi->cfg.stride;
+ if (fb_ix >= num_registered_fb ||
+ (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12 &&
+ fb_uv_ix >= num_registered_fb)) {
+ WARN(1, "display has no framebuffer");
+ goto skip_buffer;
+ }
+
+ fbi = fbi_uv = registered_fb[fb_ix];
+ if (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12)
+ fbi_uv = registered_fb[fb_uv_ix];
+
+ if (size + oi->ba > fbi->fix.smem_len ||
+ (oi->cfg.color_mode == OMAP_DSS_COLOR_NV12 &&
+ (size >> 1) + oi->uv > fbi_uv->fix.smem_len)) {
+ WARN(1, "image outside of framebuffer memory");
+ goto skip_buffer;
+ }
+
+ oi->ba += fbi->fix.smem_start;
+ oi->uv += fbi_uv->fix.smem_start;
+ goto skip_map1d;
+ }
+
/* map non-TILER buffers to 1D */
/* skip 2D and disabled layers */
if (!pas[i] || !oi->cfg.enabled)
goto skip_map1d;
- /* framebuffer is marked with uv = 0 and is contiguous */
- if (!oi->uv) {
- oi->ba = pas[i]->mem[0] + (oi->ba & ~PAGE_MASK);
- goto skip_map1d;
- }
-
if (!slot) {
if (down_timeout(&free_slots_sem,
msecs_to_jiffies(100))) {
dev_warn(DEV(cdev), "could not obtain tiler slot");
- /* disable unpinned layers */
- oi->cfg.enabled = false;
- goto skip_map1d;
+ goto skip_buffer;
}
mutex_lock(&mtx);
slot = list_first_entry(&free_slots, typeof(*slot), q);
@@ -332,9 +364,7 @@
if (slot_used + size > slot->size) {
dev_err(DEV(cdev), "tiler slot not big enough for frame %d + %d > %d",
slot_used, size, slot->size);
- /* disable unpinned layers */
- oi->cfg.enabled = false;
- goto skip_map1d;
+ goto skip_buffer;
}
/* "map" into TILER 1D - will happen after loop */
@@ -343,6 +373,10 @@
memcpy(slot->page_map + slot_used, pas[i]->mem,
sizeof(*slot->page_map) * size);
slot_used += size;
+ goto skip_map1d;
+
+skip_buffer:
+ oi->cfg.enabled = false;
skip_map1d:
if (oi->cfg.enabled)
diff --git a/include/video/dsscomp.h b/include/video/dsscomp.h
index d857961..4fdcb0c 100644
--- a/include/video/dsscomp.h
+++ b/include/video/dsscomp.h
@@ -354,6 +354,9 @@
OMAP_DSS_BUFADDR_BYTYPE, /* using buffer types */
OMAP_DSS_BUFADDR_ION, /* using ion handle(s) */
OMAP_DSS_BUFADDR_GRALLOC, /* using gralloc handle */
+ OMAP_DSS_BUFADDR_OVL_IX, /* using a prior overlay */
+ OMAP_DSS_BUFADDR_LAYER_IX, /* using a Post2 layer */
+ OMAP_DSS_BUFADDR_FB, /* using framebuffer memory */
};
struct dss2_ovl_info {
@@ -382,8 +385,13 @@
};
/* kernel-space interfaces */
+
+ /*
+ * for fbmem, highest 4-bits of address is fb index,
+ * rest of the bits are the offset
+ */
struct {
- __u32 ba; /* base address */
+ __u32 ba; /* base address or index */
__u32 uv; /* uv address */
};
};