gfx-gtt: enhanced GTT memory manager to support different buffer types.
authorJackie Li <yaodong.li@intel.com>
Wed, 23 Nov 2011 15:00:06 +0000 (23:00 +0800)
committerGross, Mark <mark.gross@intel.com>
Thu, 24 Nov 2011 08:48:55 +0000 (00:48 -0800)
This is patch 2/5 of HWC enabling.

Added three interfaces to GTT memory manager to support follow buffers:
1) all kinds of PVR meminfo
2) BCD buffer
3) user mode allocated buffer.

Change-Id: I9bdcd4f18cf01ab58976c495d51b0aa0a3d27583
Signed-off-by: Jackie Li <yaodong.li@intel.com>
Reviewed-on: http://android.intel.com:8080/25090
Reviewed-by: buildbot <buildbot@intel.com>
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Tested-by: Gross, Mark <mark.gross@intel.com>
drivers/staging/mrst/bc_video/bufferclass_video_linux.c
drivers/staging/mrst/bc_video/bufferclass_video_linux.h
drivers/staging/mrst/drv/psb_drm.h
drivers/staging/mrst/drv/psb_drv.c
drivers/staging/mrst/drv/psb_gtt.c
drivers/staging/mrst/drv/psb_pvr_glue.c
drivers/staging/mrst/drv/psb_pvr_glue.h

index 8b42692..a67c2eb 100755 (executable)
@@ -898,3 +898,54 @@ BC_Camera_Bridge(BC_Video_ioctl_package * psBridge, unsigned long pAddr)
        return 0;
 }
 EXPORT_SYMBOL_GPL(BC_Camera_Bridge);
+
+int BCGetBuffer(int devId, int bufferId, BC_VIDEO_BUFFER **bc_buffer)
+{
+       BC_VIDEO_DEVINFO *devInfo;
+       unsigned long bufferCount;
+       BC_VIDEO_BUFFER *buffer;
+
+       if (devId < 0 || devId > BC_CAMERA_DEVICEID || !bc_buffer)
+               return -EINVAL;
+
+       devInfo = GetAnchorPtr(devId);
+       if (!devInfo)
+               return -ENODEV;
+
+       bufferCount = devInfo->ulNumBuffers;
+       if (bufferId >= bufferCount)
+               return -EINVAL;
+
+       buffer = &devInfo->psSystemBuffer[bufferId];
+       *bc_buffer = buffer;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(BCGetBuffer);
+
+int BCGetDeviceBufferCount(int devId)
+{
+       BC_VIDEO_DEVINFO *devInfo;
+
+       if (devId < 0 || devId > BC_CAMERA_DEVICEID)
+               return -EINVAL;
+
+       devInfo = GetAnchorPtr(devId);
+       if (!devInfo)
+               return -ENODEV;
+       return devInfo->ulNumBuffers;
+}
+EXPORT_SYMBOL_GPL(BCGetDeviceBufferCount);
+
+int BCGetDeviceStride(int devId)
+{
+       BC_VIDEO_DEVINFO *devInfo;
+
+       if (devId < 0 || devId > BC_CAMERA_DEVICEID)
+               return -EINVAL;
+
+       devInfo = GetAnchorPtr(devId);
+       if (!devInfo)
+               return -ENODEV;
+
+       return devInfo->sBufferInfo.ui32ByteStride;
+}
index 292e788..10d9f67 100755 (executable)
@@ -66,4 +66,5 @@ typedef struct bc_buf_ptr {
 
 int BC_Camera_Bridge(BC_Video_ioctl_package *spBridge, unsigned long pAddr);
 int BC_DestroyBuffers(int id);
+
 #endif
index 7ee2a5a..b13f774 100644 (file)
@@ -566,15 +566,15 @@ struct drm_psb_stolen_memory_arg {
 #define REGRWBITS_PIPEBSRC                     (1 << 4)
 #define REGRWBITS_VTOTAL_A                     (1 << 5)
 #define REGRWBITS_VTOTAL_B                     (1 << 6)
-#define REGRWBITS_DSPACNTR     (1 << 8)
-#define REGRWBITS_DSPBCNTR     (1 << 9)
-#define REGRWBITS_DSPCCNTR     (1 << 10)
+#define REGRWBITS_DSPACNTR                     (1 << 8)
+#define REGRWBITS_DSPBCNTR                     (1 << 9)
+#define REGRWBITS_DSPCCNTR                     (1 << 10)
 #define REGRWBITS_SPRITE_UPDATE                        (1 << 11)
 /*Overlay Register Bits*/
 #define OV_REGRWBITS_OVADD                     (1 << 0)
 #define OV_REGRWBITS_OGAM_ALL                  (1 << 1)
 
-#define OVC_REGRWBITS_OVADD                  (1 << 2)
+#define OVC_REGRWBITS_OVADD                    (1 << 2)
 #define OVC_REGRWBITS_OGAM_ALL                 (1 << 3)
 /*sprite update fields*/
 #define SPRITE_UPDATE_SURFACE                  (0x00000001UL)
@@ -606,8 +606,6 @@ struct drm_psb_register_rw_arg {
 
        uint32_t display_read_mask;
        uint32_t display_write_mask;
-       uint32_t sprite_context_mask;
-       struct intel_sprite_context sprite_context;
        struct {
                uint32_t pfit_controls;
                uint32_t pfit_autoscale_ratios;
@@ -620,6 +618,9 @@ struct drm_psb_register_rw_arg {
                uint32_t dspcntr_b;
        } display;
 
+       uint32_t sprite_context_mask;
+       struct intel_sprite_context sprite_context;
+
        uint32_t overlay_read_mask;
        uint32_t overlay_write_mask;
 
@@ -657,10 +658,24 @@ struct drm_psb_register_rw_arg {
        uint32_t subpicture_disable_mask;
 };
 
+enum {
+       PSB_GTT_MAP_TYPE_MEMINFO = 0,
+       PSB_GTT_MAP_TYPE_BCD,
+       PSB_GTT_MAP_TYPE_BCD_INFO,
+       PSB_GTT_MAP_TYPE_VIRTUAL,
+};
+
 struct psb_gtt_mapping_arg {
+       uint32_t type;
        void *hKernelMemInfo;
        uint32_t offset_pages;
        uint32_t page_align;
+       uint32_t bcd_device_id;
+       uint32_t bcd_buffer_id;
+       uint32_t bcd_buffer_count;
+       uint32_t bcd_buffer_stride;
+       uint32_t vaddr;
+       uint32_t size;
 };
 
 struct drm_psb_getpageaddrs_arg {
index 97ea257..6195895 100755 (executable)
@@ -2719,6 +2719,7 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
        UHBUsage usage =
                arg->b_force_hw_on ? OSPM_UHB_FORCE_POWER_ON : OSPM_UHB_ONLY_IF_ON;
        uint32_t ovadd;
+
        if (arg->sprite_context_mask & REGRWBITS_SPRITE_UPDATE) {
                if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage))
                        return -EAGAIN;
@@ -2733,21 +2734,28 @@ static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
                        return -EINVAL;
 
                if ((arg->sprite_context.update_mask & SPRITE_UPDATE_POSITION))
-                       PSB_WVDC32(arg->sprite_context.pos, DSPAPOS + reg_offset);
+                       PSB_WVDC32(arg->sprite_context.pos,
+                               DSPAPOS + reg_offset);
 
                if ((arg->sprite_context.update_mask & SPRITE_UPDATE_SIZE)) {
-                       PSB_WVDC32(arg->sprite_context.size, DSPASIZE + reg_offset);
-                       PSB_WVDC32(arg->sprite_context.stride, DSPASTRIDE + reg_offset);
+                       PSB_WVDC32(arg->sprite_context.size,
+                               DSPASIZE + reg_offset);
+                       PSB_WVDC32(arg->sprite_context.stride,
+                               DSPASTRIDE + reg_offset);
                }
 
                if ((arg->sprite_context.update_mask & SPRITE_UPDATE_SURFACE)) {
-                       PSB_WVDC32(arg->sprite_context.linoff, DSPALINOFF + reg_offset);
-                       PSB_WVDC32(arg->sprite_context.surf, DSPASURF + reg_offset);
+                       PSB_WVDC32(arg->sprite_context.linoff,
+                               DSPALINOFF + reg_offset);
+                       PSB_WVDC32(arg->sprite_context.surf,
+                               DSPASURF + reg_offset);
                }
 
                if ((arg->sprite_context.update_mask & SPRITE_UPDATE_CONTROL)) {
-                       PSB_WVDC32(arg->sprite_context.cntr, DSPACNTR + reg_offset);
-                       PSB_WVDC32(PSB_RVDC32(DSPASURF + reg_offset), DSPASURF + reg_offset);
+                       PSB_WVDC32(arg->sprite_context.cntr,
+                               DSPACNTR + reg_offset);
+                       PSB_WVDC32(PSB_RVDC32(DSPASURF + reg_offset),
+                               DSPASURF + reg_offset);
                }
                ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
        }
index 8b0f435..53d2ecf 100644 (file)
@@ -167,8 +167,6 @@ int psb_gtt_init(struct psb_gtt *pg, int resume)
                goto out_err;
        }
 
-       DRM_DEBUG("%s: vram kernel virtual address %p\n", pg->vram_addr);
-
        tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
                   (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
 
@@ -318,7 +316,6 @@ static int psb_gtt_insert_pfn_list(struct psb_gtt *pg, u32 *pfn_list,
        return 0;
 }
 
-
 int psb_gtt_insert_phys_addresses(struct psb_gtt *pg, IMG_CPU_PHYADDR *pPhysFrames,
                                  unsigned offset_pages, unsigned num_pages, int type)
 {
@@ -456,7 +453,7 @@ static int psb_gtt_mm_get_ht_by_pid_locked(struct psb_gtt_mm *mm,
 
        ret = drm_ht_find_item(&mm->hash, tgid, &entry);
        if (ret) {
-               DRM_DEBUG("Cannot find entry pid=%ld\n", tgid);
+               DRM_DEBUG("Cannot find entry pid=%d\n", tgid);
                return ret;
        }
 
@@ -518,7 +515,7 @@ static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm,
        spin_lock(&mm->lock);
        ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
        if (!ret) {
-               DRM_DEBUG("Entry for tgid %ld exist, hentry %p\n",
+               DRM_DEBUG("Entry for tgid %d exist, hentry %p\n",
                          tgid, hentry);
                *entry = hentry;
                spin_unlock(&mm->lock);
@@ -526,7 +523,7 @@ static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm,
        }
        spin_unlock(&mm->lock);
 
-       DRM_DEBUG("Entry for tgid %ld doesn't exist, will create it\n", tgid);
+       DRM_DEBUG("Entry for tgid %d doesn't exist, will create it\n", tgid);
 
        hentry = kzalloc(sizeof(struct psb_gtt_hash_entry), GFP_KERNEL);
        if (!hentry) {
@@ -557,7 +554,7 @@ psb_gtt_mm_remove_ht_locked(struct psb_gtt_mm *mm, u32 tgid) {
 
        ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &tmp);
        if (ret) {
-               DRM_DEBUG("Cannot find entry pid %ld\n", tgid);
+               DRM_DEBUG("Cannot find entry pid %d\n", tgid);
                return NULL;
        }
 
@@ -599,7 +596,7 @@ psb_gtt_mm_get_mem_mapping_locked(struct drm_open_hash *ht,
 
        ret = drm_ht_find_item(ht, key, &entry);
        if (ret) {
-               DRM_DEBUG("Cannot find key %ld\n", key);
+               DRM_DEBUG("Cannot find key %d\n", key);
                return ret;
        }
 
@@ -662,7 +659,7 @@ psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm,
        spin_lock(&mm->lock);
        ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &mapping);
        if (!ret) {
-               DRM_DEBUG("mapping entry for key %ld exists, entry %p\n",
+               DRM_DEBUG("mapping entry for key %d exists, entry %p\n",
                          key, mapping);
                *entry = mapping;
                spin_unlock(&mm->lock);
@@ -670,7 +667,7 @@ psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm,
        }
        spin_unlock(&mm->lock);
 
-       DRM_DEBUG("Mapping entry for key %ld doesn't exist, will create it\n",
+       DRM_DEBUG("Mapping entry for key %d doesn't exist, will create it\n",
                  key);
 
        mapping = kzalloc(sizeof(struct psb_gtt_mem_mapping), GFP_KERNEL);
@@ -699,7 +696,7 @@ psb_gtt_mm_remove_mem_mapping_locked(struct drm_open_hash *ht, u32 key) {
 
        ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &tmp);
        if (ret) {
-               DRM_DEBUG("Cannot find key %ld\n", key);
+               DRM_DEBUG("Cannot find key %d\n", key);
                return NULL;
        }
 
@@ -773,7 +770,7 @@ static int psb_gtt_remove_node(struct psb_gtt_mm *mm,
        spin_lock(&mm->lock);
        ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
        if (ret) {
-               DRM_DEBUG("Cannot find entry for pid %ld\n", tgid);
+               DRM_DEBUG("Cannot find entry for pid %d\n", tgid);
                spin_unlock(&mm->lock);
                return ret;
        }
@@ -794,7 +791,7 @@ static int psb_gtt_remove_node(struct psb_gtt_mm *mm,
 
        /*check the count of mapping entry*/
        if (!hentry->count) {
-               DRM_DEBUG("count of mapping entry is zero, tgid=%ld\n", tgid);
+               DRM_DEBUG("count of mapping entry is zero, tgid=%d\n", tgid);
                psb_gtt_mm_remove_free_ht_locked(mm, tgid);
        }
 
@@ -859,39 +856,40 @@ int psb_gtt_map_meminfo(struct drm_device *dev,
        uint32_t size, pages, offset_pages;
        void *kmem;
        struct drm_mm_node *node;
-       struct page **page_list;
+       u32 *pfn_list = 0;
        struct psb_gtt_mem_mapping *mapping = NULL;
        int ret;
 
        ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
        if (ret) {
-               DRM_DEBUG("Cannot find kernelMemInfo handle %ld\n",
-                         hKernelMemInfo);
+               DRM_DEBUG("Cannot find kernelMemInfo handle %d\n",
+                         (int)hKernelMemInfo);
                return -EINVAL;
        }
 
-       DRM_DEBUG("Got psKernelMemInfo %p for handle %lx\n",
+       DRM_DEBUG("Got psKernelMemInfo %p for handle %x\n",
                  psKernelMemInfo, (u32)hKernelMemInfo);
 
        size = psKernelMemInfo->uAllocSize;
        kmem = psKernelMemInfo->pvLinAddrKM;
        pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
-       DRM_DEBUG("KerMemInfo size %ld, cpuVadr %lx, pages %ld, osMemHdl %lx\n",
-                 size, kmem, pages, psKernelMemInfo->sMemBlk.hOSMemHandle);
+       DRM_DEBUG("KerMemInfo size %d, cpuVadr %x, pages %d, osMemHdl %x\n",
+                 size, kmem, pages,
+                 (int)psKernelMemInfo->sMemBlk.hOSMemHandle);
 
        if (!kmem)
                DRM_DEBUG("kmem is NULL");
 
        /*get pages*/
        ret = psb_get_pages_by_mem_handle(psKernelMemInfo->sMemBlk.hOSMemHandle,
-                                         &page_list);
+                                         &pfn_list, pages);
        if (ret) {
                DRM_DEBUG("get pages error\n");
                return ret;
        }
 
-       DRM_DEBUG("get %ld pages\n", pages);
+       DRM_DEBUG("get %d pages\n", pages);
 
        /*alloc memory in TT apeture*/
        ret = psb_gtt_mm_alloc_mem(mm, pages, page_align, &node);
@@ -914,24 +912,27 @@ int psb_gtt_map_meminfo(struct drm_device *dev,
        node = mapping->node;
        offset_pages = node->start;
 
-       DRM_DEBUG("get free node for %ld pages, offset %ld pages",
+       DRM_DEBUG("get free node for %d pages, offset %d pages",
                  pages, offset_pages);
 
        /*update gtt*/
-       psb_gtt_insert_pages(pg, page_list,
+       psb_gtt_insert_pfn_list(pg, pfn_list,
                             (unsigned)offset_pages,
                             (unsigned)pages,
                             0,
                             0,
                             0);
 
+       /*free pfn_list if allocated*/
+       kfree(pfn_list);
+
        *offset = offset_pages;
        return 0;
 
 failed_add_node:
        psb_gtt_mm_free_mem(mm, node);
 failed_pages_alloc:
-       kfree(page_list);
+       kfree(pfn_list);
        return ret;
 }
 
@@ -967,6 +968,243 @@ int psb_gtt_unmap_meminfo(struct drm_device *dev, IMG_HANDLE hKernelMemInfo)
        return 0;
 }
 
+static int psb_gtt_map_bcd(struct drm_device *dev,
+                       uint32_t device_id,
+                       uint32_t buffer_id,
+                       uint32_t page_align,
+                       uint32_t *offset)
+{
+       struct drm_psb_private *dev_priv
+               = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+       struct psb_gtt *pg = dev_priv->pg;
+       uint32_t pages, offset_pages;
+       struct drm_mm_node *node;
+       u32 *pfn_list = 0;
+       struct psb_gtt_mem_mapping *mapping = NULL;
+       int ret;
+
+       /*get pages*/
+       ret = psb_get_bcd_pages(device_id, buffer_id, &pfn_list, &pages);
+       if (ret) {
+               DRM_DEBUG("get pages error\n");
+               return ret;
+       }
+
+       DRM_DEBUG("get %d pages\n", pages);
+
+       /*alloc memory in TT apeture*/
+       ret = psb_gtt_mm_alloc_mem(mm, pages, page_align, &node);
+       if (ret) {
+               DRM_DEBUG("alloc TT memory error\n");
+               goto failed_pages_alloc;
+       }
+
+       /*update psb_gtt_mm*/
+       ret = psb_gtt_add_node(mm,
+                              (u32)psb_get_tgid(),
+                              ((device_id << 16) | (buffer_id)),
+                              node,
+                              &mapping);
+       if (ret) {
+               DRM_DEBUG("add_node failed");
+               goto failed_add_node;
+       }
+
+       node = mapping->node;
+       offset_pages = node->start;
+
+       DRM_DEBUG("get free node for %d pages, offset %d pages",
+                 pages, offset_pages);
+
+       /*update gtt*/
+       psb_gtt_insert_pfn_list(pg, pfn_list,
+                            (unsigned)offset_pages,
+                            (unsigned)pages,
+                            0,
+                            0,
+                            0);
+
+       /*free pfn_list if allocated*/
+       kfree(pfn_list);
+
+       *offset = offset_pages;
+       return 0;
+
+failed_add_node:
+       psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+       kfree(pfn_list);
+       return ret;
+}
+
+static int psb_gtt_unmap_bcd(struct drm_device *dev,
+                       uint32_t device_id,
+                       uint32_t buffer_id)
+{
+       struct drm_psb_private *dev_priv
+               = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+       struct psb_gtt *pg = dev_priv->pg;
+       uint32_t pages, offset_pages;
+       struct drm_mm_node *node;
+       int ret;
+
+       ret = psb_gtt_remove_node(mm,
+                                 (u32)psb_get_tgid(),
+                                 ((device_id << 16) | buffer_id),
+                                 &node);
+       if (ret) {
+               DRM_DEBUG("remove node failed\n");
+               return ret;
+       }
+
+       /*remove gtt entries*/
+       offset_pages = node->start;
+       pages = node->size;
+
+       psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+
+       /*free tt node*/
+       psb_gtt_mm_free_mem(mm, node);
+       return 0;
+}
+
+static int psb_gtt_get_bcd_device_info(struct drm_device *dev,
+                               uint32_t bcd_id,
+                               uint32_t *buf_count,
+                               uint32_t *buf_stride)
+{
+       int count;
+       int stride;
+
+       if (!buf_count || !buf_stride) {
+               DRM_ERROR("invalid parameters\n");
+               return -EINVAL;
+       }
+
+       count = psb_get_bcd_buffer_count(bcd_id);
+       if (count <= 0) {
+               DRM_ERROR("failed to get bcd %d buffer count\n", bcd_id);
+               return -EINVAL;
+       }
+
+       stride = psb_get_bcd_buffer_stride(bcd_id);
+       if (stride <= 0) {
+               DRM_ERROR("failed to get bcd %d buffer stride\n", bcd_id);
+               return -EINVAL;
+       }
+
+       *buf_count = count;
+       *buf_stride = stride;
+
+       return 0;
+}
+
+static int psb_gtt_map_vaddr(struct drm_device *dev,
+                       uint32_t vaddr,
+                       uint32_t size,
+                       uint32_t page_align,
+                       uint32_t *offset)
+{
+       struct drm_psb_private *dev_priv
+               = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+       struct psb_gtt *pg = dev_priv->pg;
+       uint32_t pages, offset_pages;
+       struct drm_mm_node *node;
+       u32 *pfn_list = 0;
+       struct psb_gtt_mem_mapping *mapping = NULL;
+       int ret;
+
+       /*get pages*/
+       ret = psb_get_vaddr_pages(vaddr, size, &pfn_list, &pages);
+       if (ret) {
+               DRM_DEBUG("get pages error\n");
+               return ret;
+       }
+
+       DRM_DEBUG("get %d pages\n", pages);
+
+       /*alloc memory in TT apeture*/
+       ret = psb_gtt_mm_alloc_mem(mm, pages, page_align, &node);
+       if (ret) {
+               DRM_DEBUG("alloc TT memory error\n");
+               goto failed_pages_alloc;
+       }
+
+       /*update psb_gtt_mm*/
+       ret = psb_gtt_add_node(mm,
+                              (u32)psb_get_tgid(),
+                              vaddr,
+                              node,
+                              &mapping);
+       if (ret) {
+               DRM_DEBUG("add_node failed");
+               goto failed_add_node;
+       }
+
+       node = mapping->node;
+       offset_pages = node->start;
+
+       DRM_DEBUG("get free node for %d pages, offset %d pages",
+                 pages, offset_pages);
+
+       /*update gtt*/
+       psb_gtt_insert_pfn_list(pg, pfn_list,
+                            (unsigned)offset_pages,
+                            (unsigned)pages,
+                            0,
+                            0,
+                            0);
+
+       /*free pfn_list if allocated*/
+       kfree(pfn_list);
+
+       *offset = offset_pages;
+       return 0;
+
+failed_add_node:
+       psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+       kfree(pfn_list);
+       return ret;
+}
+
+static int psb_gtt_unmap_vaddr(struct drm_device *dev,
+                       uint32_t vaddr,
+                       uint32_t size)
+{
+       struct drm_psb_private *dev_priv
+               = (struct drm_psb_private *)dev->dev_private;
+       struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+       struct psb_gtt *pg = dev_priv->pg;
+       uint32_t pages, offset_pages;
+       struct drm_mm_node *node;
+       int ret;
+
+       ret = psb_gtt_remove_node(mm,
+                                 (u32)psb_get_tgid(),
+                                 vaddr,
+                                 &node);
+       if (ret) {
+               DRM_DEBUG("remove node failed\n");
+               return ret;
+       }
+
+       /*remove gtt entries*/
+       offset_pages = node->start;
+       pages = node->size;
+
+       psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+
+       /*free tt node*/
+       psb_gtt_mm_free_mem(mm, node);
+       return 0;
+}
+
 int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv)
 {
@@ -974,13 +1212,42 @@ int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
        = (struct psb_gtt_mapping_arg *)data;
        uint32_t *offset_pages = &arg->offset_pages;
        uint32_t page_align = arg->page_align;
+       uint32_t device_id = arg->bcd_device_id;
+       uint32_t buffer_id = arg->bcd_buffer_id;
+       uint32_t *buffer_count = &arg->bcd_buffer_count;
+       uint32_t *buffer_stride = &arg->bcd_buffer_stride;
+       uint32_t vaddr = arg->vaddr;
+       uint32_t size = arg->size;
+       uint32_t type = arg->type;
 
        DRM_DEBUG("\n");
 
-       return psb_gtt_map_meminfo(dev,
+       switch (type) {
+       case PSB_GTT_MAP_TYPE_MEMINFO:
+               return psb_gtt_map_meminfo(dev,
                                arg->hKernelMemInfo,
                                page_align,
                                offset_pages);
+       case PSB_GTT_MAP_TYPE_BCD:
+               return psb_gtt_map_bcd(dev,
+                               device_id, buffer_id,
+                               page_align,
+                               offset_pages);
+       case PSB_GTT_MAP_TYPE_VIRTUAL:
+               return psb_gtt_map_vaddr(dev,
+                                       vaddr,
+                                       size,
+                                       page_align,
+                                       offset_pages);
+       case PSB_GTT_MAP_TYPE_BCD_INFO:
+               return psb_gtt_get_bcd_device_info(dev,
+                                               device_id,
+                                               buffer_count,
+                                               buffer_stride);
+       default:
+               DRM_ERROR("unsupported buffer type %d\n", type);
+               return -EINVAL;
+       }
 }
 
 int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
@@ -988,11 +1255,26 @@ int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
 {
 
        struct psb_gtt_mapping_arg *arg
-       = (struct psb_gtt_mapping_arg *)data;
+               = (struct psb_gtt_mapping_arg *)data;
+       uint32_t device_id = arg->bcd_device_id;
+       uint32_t buffer_id = arg->bcd_buffer_id;
+       uint32_t vaddr = arg->vaddr;
+       uint32_t size = arg->size;
+       uint32_t type = arg->type;
 
        DRM_DEBUG("\n");
 
-       return psb_gtt_unmap_meminfo(dev, arg->hKernelMemInfo);
+       switch (type) {
+       case PSB_GTT_MAP_TYPE_MEMINFO:
+               return psb_gtt_unmap_meminfo(dev, arg->hKernelMemInfo);
+       case PSB_GTT_MAP_TYPE_BCD:
+               return psb_gtt_unmap_bcd(dev, device_id, buffer_id);
+       case PSB_GTT_MAP_TYPE_VIRTUAL:
+               return psb_gtt_unmap_vaddr(dev, vaddr, size);
+       default:
+               DRM_ERROR("unsupported buffer type %d\n", type);
+               return -EINVAL;
+       }
 }
 
 int psb_gtt_map_pvr_memory(struct drm_device *dev,
@@ -1035,7 +1317,8 @@ int psb_gtt_map_pvr_memory(struct drm_device *dev,
        node = mapping->node;
        offset_pages = node->start;
 
-       DRM_DEBUG("get free node for %ld pages, offset %ld pages", pages, offset_pages);
+       DRM_DEBUG("get free node for %d pages, offset %d pages",
+               pages, offset_pages);
 
        /*update gtt*/
        psb_gtt_insert_phys_addresses(pg, pPages, (unsigned)offset_pages, (unsigned)ui32PagesNum, 0);
index 88641c1..92bbe1f 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "psb_pvr_glue.h"
+#include <asm/page.h>
 
 /**
  * FIXME: should NOT use these file under env/linux directly
@@ -43,7 +44,7 @@ int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo,
 
        *ppsKernelMemInfo = psKernelMemInfo;
 
-       DRM_DEBUG("Got Kernel MemInfo for handle %lx\n",
+       DRM_DEBUG("Got Kernel MemInfo for handle %x\n",
                  (IMG_UINT32)hKernelMemInfo);
        return 0;
 }
@@ -53,22 +54,172 @@ IMG_UINT32 psb_get_tgid(void)
        return OSGetCurrentProcessIDKM();
 }
 
-int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle, struct page ***pages)
+int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle,
+                               u32 **pfn_list,
+                               int page_count)
 {
        LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
-       struct page **page_list;
+       u32 *pfns = 0;
+       IMG_CPU_PHYADDR phys_addr;
+       int i;
 
-       if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
-               DRM_ERROR("MemArea type is not LINUX_MEM_AREA_ALLOC_PAGES\n");
+       if (!pfn_list)
                return -EINVAL;
+
+       /*allocate page list*/
+       pfns = kzalloc(page_count * sizeof(u32), GFP_KERNEL);
+       if (!pfns) {
+               DRM_ERROR("No memory\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < page_count; i++) {
+               phys_addr.uiAddr = 0;
+
+               phys_addr =
+                       LinuxMemAreaToCpuPAddr(psLinuxMemArea, i * PAGE_SIZE);
+               pfns[i] = ((u32)phys_addr.uiAddr) >> PAGE_SHIFT;
        }
 
-       page_list = psLinuxMemArea->uData.sPageList.pvPageList;
-       if (!page_list) {
-               DRM_DEBUG("Page List is NULL\n");
+       *pfn_list = pfns;
+       return 0;
+}
+
+int psb_get_bcd_pages(u32 device_id, u32 buffer_id, u32 **pfn_list, int *pages)
+{
+       BC_VIDEO_BUFFER *buffer;
+       u32 size;
+       u32 num_pages;
+       int is_contig;
+       int err;
+       u32 phys_addr;
+       u32 *pfns = 0;
+       int i;
+
+       if (!pfn_list || !pages)
+               return -EINVAL;
+
+       err = BCGetBuffer(device_id, buffer_id, &buffer);
+       if (err)
+               return err;
+
+       size = buffer->ulSize;
+       num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+       is_contig = buffer->is_conti_addr;
+
+       /*allocate page list*/
+       pfns = kzalloc(num_pages * sizeof(u32), GFP_KERNEL);
+       if (!pfns) {
+               DRM_ERROR("No memory\n");
                return -ENOMEM;
        }
 
-       *pages = page_list;
+       if (is_contig) {
+               phys_addr = (u32)buffer->psSysAddr[0].uiAddr;
+               for (i = 0; i < num_pages; i++)
+                       pfns[i] = (phys_addr + i * PAGE_SIZE) >> PAGE_SHIFT;
+       } else {
+               for (i = 0; i < num_pages; i++) {
+                       phys_addr = (u32)buffer->psSysAddr[i].uiAddr;
+                       pfns[i] = phys_addr >> PAGE_SHIFT;
+               }
+       }
+
+       *pfn_list = pfns;
+       *pages = num_pages;
+
        return 0;
 }
+
+int psb_get_vaddr_pages(u32 vaddr, u32 size, u32 **pfn_list, int *page_count)
+{
+       u32 num_pages;
+       struct page **pages = 0;
+       struct task_struct *task = current;
+       struct mm_struct *mm = task->mm;
+       struct vm_area_struct *vma;
+       u32 *pfns = 0;
+       int ret;
+       int i;
+
+       if (unlikely(!pfn_list || !page_count || !vaddr || !size))
+               return -EINVAL;
+
+       num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+       pages = kzalloc(num_pages * sizeof(struct page *), GFP_KERNEL);
+       if (unlikely(!pages)) {
+               DRM_ERROR("Failed to allocate page list\n");
+               return -ENOMEM;
+       }
+
+       down_read(&mm->mmap_sem);
+       ret = get_user_pages(task, mm, vaddr, num_pages, 0, 0, pages, NULL);
+       up_read(&mm->mmap_sem);
+
+       if (ret <= 0) {
+               DRM_DEBUG("failed to get user pages\n");
+               kfree(pages);
+               pages = 0;
+       } else {
+               DRM_DEBUG("num_pages %d, ret %d\n", num_pages, ret);
+               num_pages = ret;
+       }
+
+       /*allocate page list*/
+       pfns = kzalloc(num_pages * sizeof(u32), GFP_KERNEL);
+       if (!pfns) {
+               DRM_ERROR("No memory\n");
+               goto get_page_err;
+       }
+
+       if (!pages) {
+               DRM_ERROR("No pages found, trying to follow pfn\n");
+               for (i = 0; i < num_pages; i++) {
+                       vma = find_vma(mm, vaddr + i * PAGE_SIZE);
+                       if (!vma) {
+                               DRM_ERROR("failed to find vma\n");
+                               goto find_vma_err;
+                       }
+
+                       ret = follow_pfn(vma,
+                               (unsigned long)(vaddr + i * PAGE_SIZE),
+                               (unsigned long *)&pfns[i]);
+                       if (ret) {
+                               DRM_ERROR("failed to follow pfn\n");
+                               goto follow_pfn_err;
+                       }
+               }
+       } else {
+               DRM_ERROR("Found pages\n");
+               for (i = 0; i < num_pages; i++)
+                       pfns[i] = page_to_pfn(pages[i]);
+       }
+
+       *pfn_list = pfns;
+       *page_count = num_pages;
+
+       kfree(pages);
+
+       return 0;
+find_vma_err:
+follow_pfn_err:
+       kfree(pfns);
+get_page_err:
+       if (pages) {
+               for (i = 0; i < num_pages; i++)
+                       put_page(pages[i]);
+               kfree(pages);
+       }
+       return -EINVAL;
+}
+
+int psb_get_bcd_buffer_count(uint32_t bcd_id)
+{
+       return BCGetDeviceBufferCount(bcd_id);
+}
+
+int psb_get_bcd_buffer_stride(uint32_t bcd_id)
+{
+       return BCGetDeviceStride(bcd_id);
+}
index 3c2ae45..9b16356 100644 (file)
 
 #include "psb_drv.h"
 #include "services_headers.h"
+#include "bufferclass_video.h"
+
+int BCGetBuffer(int devId, int bufferId, BC_VIDEO_BUFFER **bc_buffer);
+int BCGetDeviceBufferCount(int devId);
+int BCGetDeviceStride(int devId);
 
 extern int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo,
                                PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
 extern IMG_UINT32 psb_get_tgid(void);
 extern int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle,
-                                       struct page ***pages);
+                                       u32 **pfn_list,
+                                       int page_count);
+extern int psb_get_bcd_pages(u32 device_id, u32 buffer_id, u32 **pfn_list,
+                               int *pages);
+extern int psb_get_vaddr_pages(u32 vaddr, u32 size, u32 **pfn_list, int *pages);
+extern int psb_get_bcd_buffer_count(uint32_t bcd_id);
+extern int psb_get_bcd_buffer_stride(uint32_t bcd_id);