This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux: CMEM_allocPhys2 alloc mem phy addr ,use CMEM_freePhys free failed

Tool/software: Linux

#include <stdio.h>

#include <string.h>

#include <assert.h>

#include <cmem.h>

 

#define BUF_WIDTH (1280)

#define BUF_HEIGHT (720)

 

typedef struct _cmem_info {

         off_t phy_addr;

         void * vaddr;

         int fd;

}cmeminfo;

 

 

int cmem_use(int bpp,cmeminfo *info)

{

                   int ret_val = 0;

 

                   assert(info);

 

                   printf("CMEM_allocPhys2 begin...\n");

                   CMEM_AllocParams params;

                   params.type = CMEM_HEAP;

                   params.alignment = 0;

                   params.flags = CMEM_CACHED;

 

                   info->phy_addr = CMEM_allocPhys2(CMEM_CMABLOCKID, BUF_WIDTH * BUF_HEIGHT * bpp / 8, &params);

 

                   if(((void *)(info->phy_addr)) == NULL ) {

                            printf("blind area CMEM_allocPhys2 fail,info->phy_addr 0x%x \n",info->phy_addr);

                            ret_val = -1;

                            goto end;

                   }

                   printf("blind area pa 0x%x  \n",info->phy_addr);

 

                   info->vaddr = CMEM_map(info->phy_addr, BUF_WIDTH*BUF_HEIGHT*bpp/8);

                   if(info->vaddr == NULL) {

                            printf("blind area CMEM_map fail \n");

                            ret_val =  -2;

                            goto end;

                   }

 

                   printf("blind area vaddr 0x%x \n",info->vaddr);

 

                   info->fd = CMEM_export_dmabuf(info->vaddr);

                   if(info->fd <= 0) {

                            printf("blind area CMEM_export_dmabuf fail \n");

                            ret_val = -3;

                            goto end;

                   }

 

                   printf("CMEM_allocPhys2 end...\n");

 

end:

                   return ret_val;

}

 

int cmem_free(int bpp,cmeminfo *info)

{

         int ret = 0;

         assert(info);

         CMEM_AllocParams params;

         params.type = CMEM_HEAP;

         params.alignment = 0;

         params.flags = CMEM_CACHED;

 

         ret = CMEM_unmap(info->vaddr,BUF_WIDTH * BUF_HEIGHT * bpp / 8);

         if(ret != 0) {

                   printf("blind area CMEM_unmap fail,ret = %d\n",ret);

                   goto end;

         }

 

         ret = CMEM_freePhys(info->phy_addr,&params);

         if(ret != 0) {

                   printf("blind area CMEM_freePhys fail,ret = %d\n",ret);

                   goto end;

         }

end:

         return ret;

}

 

 

int main(int argc,char *argv[])

{

         printf("%s build %s %s\n",argv[0],__DATE__,__TIME__);

         int ret = 0;

         cmeminfo info;

         memset(&info,0,sizeof(info));

 

         /**

         * cmem init

         */

         ret = CMEM_init();

         if (ret != 0 ){

                   printf("CMEM_init failed , ret : %d \n",ret);

         }

 

         ret = cmem_use(24,&info);

         if (ret != 0 ){

                   printf("cmem_use failed , ret : %d \n",ret);

         }

 

         ret = cmem_free(24,&info);

         if (ret != 0 ){

                   printf("cmem_use failed , ret : %d \n",ret);

         }

 

         /**

         * cmem exit

         */

         ret = CMEM_exit();

         if (ret != 0 ){

                   printf("CMEM_exit failed , ret : %d \n",ret);

         }

         return ret;

}

run error log:

6601.88> ./cmem_test build Aug  6 2018 16:02:40

6601.88> CMEM_allocPhys2 begin...

6601.88> blind area pa 0xbbe00000  [ 1914.639501] CMEMK Error: Failed to free memory at 0xbe86dc08bbe00000

6601.88>

 6601.88> blind area vaddr 0xb6bba000

 6601.88> CMEM_allocPhys2 end...

6601.90> MCEM Erro: freePhys: Failed to free buffer at physical address 0xffffffffbbe00000

6601.90> blind area CMEM_freePhys fail,ret = -1

6601.90> cmem_use failed , ret : -1

  • Hi @,

    which device you use?

    Regards,

    Yordan

  • hi,

    Try closing the exported DMA buf before freeing the physical memory.

    To close the DMA buf simply do close(info->fd)

    If this doesn't work, then just for test try doing physalloc and free without exporting DMA buf and without doing map/unmap just to narrow down where the error could be.

    regards
    Kedar

  • code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
    #include <cmem.h>
    #include <unistd.h>

    #define BUF_WIDTH (1280)
    #define BUF_HEIGHT (720)

    typedef struct _cmem_info {
    off_t phy_addr;
    void * vaddr;
    int fd;
    }cmeminfo;


    int cmem_use(int bpp,cmeminfo *info)
    {
    int ret_val = 0;

    assert(info);

    printf("CMEM_allocPhys2 begin...\n");
    CMEM_AllocParams params;
    params.type = CMEM_HEAP;
    params.alignment = 0;
    params.flags = CMEM_CACHED;

    info->phy_addr = CMEM_allocPhys2(CMEM_CMABLOCKID, BUF_WIDTH * BUF_HEIGHT * bpp / 8, &params);
    printf("blind area pa 0x%x \n",info->phy_addr);

    info->vaddr = CMEM_map(info->phy_addr, BUF_WIDTH*BUF_HEIGHT*bpp/8);
    if(info->vaddr == NULL) {
    printf("blind area CMEM_map fail \n");
    ret_val = -2;
    goto end;
    }

    printf("blind area vaddr 0x%x \n",info->vaddr);

    info->fd = CMEM_export_dmabuf(info->vaddr);
    if(info->fd <= 0) {
    printf("blind area CMEM_export_dmabuf fail \n");
    ret_val = -3;
    goto end;
    }

    printf("CMEM_allocPhys2 end...\n");

    end:
    return ret_val;
    }

    int cmem_free(int bpp,cmeminfo *info)
    {
    int ret = 0;
    assert(info);
    ret = close(info->fd);
    if(ret != 0) {
    printf("blind area close fail,ret = %d\n",ret);
    goto end;
    }
    CMEM_AllocParams params;
    params.type = CMEM_HEAP;
    params.alignment = 0;
    params.flags = CMEM_CACHED;
    ret = CMEM_unmap(info->vaddr,BUF_WIDTH * BUF_HEIGHT * bpp / 8);
    if(ret != 0) {
    printf("blind area CMEM_unmap fail,ret = %d\n",ret);
    goto end;
    }

    ret = CMEM_freePhys(info->phy_addr,&params);
    if(ret != 0) {
    printf("blind area CMEM_freePhys fail,ret = %d\n",ret);
    goto end;
    }
    end:
    return ret;
    }


    int main(int argc,char *argv[])
    {
    printf("%s build %s %s\n",argv[0],__DATE__,__TIME__);
    int ret = 0;
    cmeminfo info;
    memset(&info,0,sizeof(info));

    /**
    * cmem init
    */
    ret = CMEM_init();
    if (ret != 0 ){
    printf("CMEM_init failed , ret : %d \n",ret);
    }

    ret = cmem_use(24,&info);
    if (ret != 0 ){
    printf("cmem_use failed , ret : %d \n",ret);
    }

    ret = cmem_free(24,&info);
    if (ret != 0 ){
    printf("cmem_use failed , ret : %d \n",ret);
    }

    /**
    * cmem exit
    */
    ret = CMEM_exit();
    if (ret != 0 ){
    printf("CMEM_exit failed , ret : %d \n",ret);
    }
    return ret;
    }

    run error log:

    ./cmem_test

    ./cmem_test build Aug 17 2018 10:26:37

    CMEM_allocPhys2 begin...

    blind area pa 0xbbe00000

    blind area vaddr 0xb6b39000 [   20.629940] CMEMK Error: Failed to free memory at 0xbee48c48bbe00000

     

    CMEM_allocPhys2 end...

    CMEM Error: freePhys: Failed to free buffer at physical address 0xffffffffbbe00000

    blind area CMEM_freePhys fail,ret = -1

    cmem_use failed , ret : -1

  • Can you tell the CMEM version you are using ?

  • Hi Kedar Chitnis,

       I check version that Cmem is placed in linuxutils_4_12_00_00.And I don't confirm if this is what you want.

       And we modify the code according to the demo you provided, and still report the follow error.

      How can I solve it?

      The logs:

    108275.69>minigui cmem vaddr 97acb000  
    108275.69>
    108275.70>[    3.917275] Unable to handle kernel NULL pointer dereference at virtual address 00000024
    108275.70>insmod usb module driver
    108275.72>[    3.950325] pgd = f4897280
    108275.75>[    3.953056] [00000024] *pgd=b48bf003, *pmd=b5471003, *pte=00000000
    108275.75>[    3.980455] Internal error: Oops: 207 [#1] PREEMPT SMP ARM
    108275.77>[    3.985964] Modules linked in: dwc3(+) udc_core dwc3_omap extcon texfat(PO) tfat(PO) cmemk(O) memcache(O) pvrsrvkm(O)
    108275.78>[    3.996699] CPU: 0 PID: 311 Comm: avm3d_service Tainted: P           O    4.4.45+ #3
    108275.78>[    4.004474] Hardware name: Generic DRA74X (Flattened Device Tree)
    108275.78>[    4.010592] task: f4aba300 ti: d8218000 task.ti: d8218000
    108275.80>[    4.016020] PC is at cmem_dmabuf_export+0x14/0x140 [cmemk]
    108275.80>[    4.021529] LR is at ioctl+0x154/0x1504 [cmemk]
    108275.81>[    4.026077] pc : [<bf07315c>]    lr : [<bf0743a0>]    psr: 60080013
    108275.81>[    4.026077] sp : d8219e48  ip : d8219ea0  fp : d8219e9c
    108275.81>[    4.037601] r10: bf0795f4  r9 : 992e5cc8  r8 : bf079590
    108275.81>[    4.042846] r7 : bf0779cc  r6 : 00000001  r5 : 00000800  r4 : 00000000
    108275.83>[    4.049398] r3 : 00000000  r2 : bd200000  r1 : 00000002  r0 : 00000000
    108275.84>[    4.055951] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
    108275.84>[    4.063114] Control: 30c5387d  Table: b4897280  DAC: fffffffd
    108275.84>[    4.068880] Process avm3d_service (pid: 311, stack limit = 0xd8218210)
    108275.84>[    4.075431] Stack: (0xd8219e48 to 0xd821a000)
    108275.86>[    4.079806] 9e40:                   97acb000 f49b4648 f5952e40 00000003 d8219e9c d8219e68
    108275.87>[    4.088016] 9e60: bf073760 c00f0748 d8219eb4 d8219e78 c02a56f8 ffe13000 00000800 00000001
    108275.87>[    4.096227] 9e80: bf0779cc bf079590 992e5cc8 bf0795f4 d8219f14 d8219ea0 bf0743a0 bf073154
    108275.89>[    4.104438] 9ea0: d8219f80 00000000 d8219edc d8219eb8 d8219ed8 c02a55c8 f6273cc0 c02a5868
    108275.89>[    4.112649] 9ec0: 0000001f d8219f80 c000fbc4 00000000 d8219f4c d8219ee0 97acb000 992e5cd8
    108275.91>[    4.120859] 9ee0: d8219f2c d8219ef0 c00f3668 992e5cc8 f49b4648 f5952e40 00000003 992e5cc8
    108275.91>[    4.129069] 9f00: d8218000 00000000 d8219f7c d8219f18 c011f848 bf074258 00000000 00000000
    108275.92>[    4.137279] 9f20: f5952e40 00004000 d8219f5c d8219f38 c0129a54 c0081778 b683f114 00000003
    108275.94>[    4.145491] 9f40: 97acb000 0000fe0d 992e5cc8 d8218000 d8219f6c f5952e41 00000003 f5952e40
    108275.94>[    4.153701] 9f60: 0000fe0d 992e5cc8 d8218000 00000000 d8219fa4 d8219f80 c011faa8 c011f464
    108275.94>[    4.161911] 9f80: b683f114 97acb000 97acb000 00000036 c000fbc4 d8218000 00000000 d8219fa8
    108275.95>[    4.170122] 9fa0: c000fa20 c011fa78 b683f114 97acb000 00000003 0000fe0d 992e5cc8 b683f180
    108275.97>[    4.178332] 9fc0: b683f114 97acb000 97acb000 00000036 00d21d00 000002d0 00000001 00000003
    108275.97>[    4.186542] 9fe0: b683f138 992e5cc4 b682e209 b669f4d6 00080030 00000003 bfd6fd7f 7f6ffcff
    108275.97>[    4.194748] Backtrace:
    108275.98>[    4.197219] [<bf073148>] (cmem_dmabuf_export [cmemk]) from [<bf0743a0>] (ioctl+0x154/0x1504 [cmemk])
    108275.98>[    4.206386]  r10:bf0795f4 r9:992e5cc8 r8:bf079590 r7:bf0779cc r6:00000001 r5:00000800
    108275.98>[    4.214287]  r4:ffe13000
    108276.00>[    4.216846] [<bf07424c>] (ioctl [cmemk]) from [<c011f848>] (do_vfs_ioctl+0x3f0/0x614)
    108276.00>[    4.224705]  r10:00000000 r9:d8218000 r8:992e5cc8 r7:00000003 r6:f5952e40 r5:f49b4648
    108276.01>[    4.232600]  r4:992e5cc8
    108276.01>[    4.235151] [<c011f458>] (do_vfs_ioctl) from [<c011faa8>] (SyS_ioctl+0x3c/0x64)
    108276.01>[    4.242487]  r10:00000000 r9:d8218000 r8:992e5cc8 r7:0000fe0d r6:f5952e40 r5:00000003
    108276.01>[    4.250383]  r4:f5952e41
    108276.03>[    4.252937] [<c011fa6c>] (SyS_ioctl) from [<c000fa20>] (ret_fast_syscall+0x0/0x34)
    108276.05>[    4.260535]  r9:d8218000 r8:c000fbc4 r7:00000036 r6:97acb000 r5:97acb000 r4:b683f114
    108276.05>[    4.268348] Code: e92ddff0 e24cb004 e24dd02c e1a04000 (e5945024)
    108276.05> [HOST] [DSP2  ]      4.851521 s: AB02A Model use new param
    108276.06> [HOST] [DSP1  ]      5.047947 s:  UTILS: DMA: Allocated CH (TCC) = 56 (56)

    Thanks,

    Fumao

  • Hi Kedar Chitnis,
       The demo you provided.

      

    5265.loopback.c
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <malloc.h>
    #include <sys/stat.h>
    #include <sys/ioctl.h>
    #include <stdbool.h>
    #include <linux/videodev2.h>
    #include <omap_drm.h>
    #include <omap_drmif.h>
    #include <xf86drmMode.h>
    #include "jpeg.h"
    #include "loopback.h"
    #include "cmem_buf.h"
    #include <linux/dma-buf.h>
    
    #define ERROR(fmt, ...) \
    	do { fprintf(stderr, "ERROR:%s:%d: " fmt "\n", __func__, __LINE__,\
    ##__VA_ARGS__); } while (0)
    
    #define MSG(fmt, ...) \
    	do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0)
    
    /* Dynamic debug. */
    #define DBG(fmt, ...) \
    	do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); } while (0)
    
    /* align x to next highest multiple of 2^n */
    #define ALIGN2(x,n)   (((x) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
    #define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | \
    	((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | \
    	((uint32_t)(uint8_t)(d) << 24 ))
    #define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
    
    #define PAGE_SHIFT 12
    #define NBUF (3)
    #define MAX_DRM_PLANES 5
    #define CAP_WIDTH 800
    #define CAP_HEIGHT 600
    #define PIP_POS_X  25
    #define PIP_POS_Y  25
    #define MAX_ZORDER_VAL 3 //For AM57x device, max zoder value is 3
    
    struct control status;
    
    
    struct dmabuf_buffer {
    	uint32_t fourcc, width, height;
    	int nbo;
    
    #ifdef USE_CMEM_BUF
    	void *cmem_buf;
    #endif //USE_CMEM_BUF
    
    	struct omap_bo *bo[4];
    	uint32_t pitches[4];
    	int fd[4];		/* dmabuf */
    	unsigned fb_id;
    };
    
    struct connector_info {
    	unsigned int id;
    	char mode_str[64];
    	drmModeModeInfo *mode;
    	drmModeEncoder *encoder;
    	int crtc;
    	int pipe;
    };
    
    /*
    * drm output device structure declaration
    */
    struct drm_device_info
    {
    	int fd;
    	int width;
    	int height;
    	char dev_name[9];
    	char name[4];
    	unsigned int bo_flags;
    	struct dmabuf_buffer **buf[2];
    	struct omap_device *dev;
    	unsigned int crtc_id;
    	unsigned int plane_id[2];
    	unsigned int prop_fbid;
    	unsigned int prop_crtcid;
    	uint64_t zorder_val_primary_plane;
    	uint64_t trans_key_mode_val;
    	uint32_t zorder_val[MAX_DRM_PLANES-1];
    } drm_device;
    
    /*
    * V4L2 capture device structure declaration
    */
    struct v4l2_device_info {
    	int type;
    	int fd;
    	enum v4l2_memory memory_mode;
    	unsigned int num_buffers;
    	int width;
    	int height;
    	char dev_name[12];
    	char name[10];
    
    	struct v4l2_buffer *buf;
    	struct v4l2_format fmt;
    	struct dmabuf_buffer **buffers;
    } cap0_device, cap1_device;
    
    /* If the use case need the buffer to be accessed by CPU for some processings,
     * then CMEM buffer can be used as they support cache operations by CPU. 
     * omap_drm buffers doesn't support cache read. CPU can take 10x to 60x 
     * more cycles to operate on non cached buffer. USE_CMEM_BUF macro is disabled
     * by deafult. Macro can be enabled from cmem_buf.h file 
     */
    static struct dmabuf_buffer *alloc_buffer(struct drm_device_info *device,
    		unsigned int fourcc, unsigned int w,
    		unsigned int h)
    {
    	struct dmabuf_buffer *buf;
    	unsigned int bo_handles[4] = {0}, offsets[4] = {0};
    	int ret;
    	int bytes_pp = 2; //capture buffer is in YUYV format
    
    	buf = (struct dmabuf_buffer *) calloc(1, sizeof(struct dmabuf_buffer));
    	if (!buf) {
    		ERROR("allocation failed");
    		return NULL;
    	}
    
    	buf->fourcc = fourcc;
    	buf->width = w;
    	buf->height = h;
    	buf->nbo = 1;
    	buf->pitches[0] = w*bytes_pp;
    
    #ifdef USE_CMEM_BUF
    	//Allocate buffer from CMEM and get the buffer descriptor
    	buf->fd[0]  = alloc_cmem_buffer(w*h*bytes_pp, 1, &buf->cmem_buf);
    
    	if(buf->fd[0] < 0){
    		free_cmem_buffer(buf->cmem_buf);
    		printf(" Cannot export CMEM buffer\n");
    		return NULL;
    	}
    
    	/* Get the omap bo from the fd allocted using CMEM */
    	buf->bo[0] = omap_bo_from_dmabuf(device->dev, buf->fd[0]);
    	if (buf->bo[0]){
    		bo_handles[0] = omap_bo_handle(buf->bo[0]);
    	}
    
    #else //USE_CMEM_BUF
    	//You can use DRM ioctl as well to allocate buffers (DRM_IOCTL_MODE_CREATE_DUMB)
    	//and drmPrimeHandleToFD() to get the buffer descriptors
    	buf->bo[0] = omap_bo_new(device->dev,w*h*bytes_pp, device->bo_flags | OMAP_BO_WC);
    	if (buf->bo[0]){
    		bo_handles[0] = omap_bo_handle(buf->bo[0]);
    	}
    
    	buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
    #endif //USE_CMEM_BUF
    
    	ret = drmModeAddFB2(device->fd, buf->width, buf->height, fourcc,
    		bo_handles, buf->pitches, offsets, &buf->fb_id, 0);
    
    	if (ret) {
    		ERROR("drmModeAddFB2 failed: %s (%d)", strerror(errno), ret);
    		return NULL;
    	}
    
    	return buf;
    }
    
    void free_vid_buffers(struct dmabuf_buffer **buf, unsigned int n)
    {
    	unsigned int i;
    
    	if (buf == NULL) return;
    	for (i = 0; i < n; i++) {
    		if (buf[i]) {
    			close(buf[i]->fd[0]);
    #ifdef USE_CMEM_BUF
    			free_cmem_buffer(buf[i]->cmem_buf);
    #else
    			omap_bo_del(buf[i]->bo[0]);
    #endif //USE_CMEM_BUF
    
    			free(buf[i]);
    		}
    	}
    	free(buf);
    }
    
    
    static struct dmabuf_buffer **get_vid_buffers(struct drm_device_info *device,
    		unsigned int n,
    		unsigned int fourcc, unsigned int w, unsigned int h)
    {
    	struct dmabuf_buffer **bufs;
    	unsigned int i = 0;
    
    	bufs = (struct dmabuf_buffer **) calloc(n, sizeof(*bufs));
    	if (!bufs) {
    		ERROR("allocation failed");
    		goto fail;
    	}
    
    	for (i = 0; i < n; i++) {
    		bufs[i] = alloc_buffer(device, fourcc, w, h);
    		if (!bufs[i]) {
    			ERROR("allocation failed");
    			goto fail;
    		}
    	}
    	return bufs;
    
    fail:
    	return NULL;
    }
    
    static int v4l2_init_device(struct v4l2_device_info *device)
    {
    	int ret;
    	struct v4l2_capability capability;
    
    	/* Open the capture device */
    	device->fd = open((const char *) device->dev_name, O_RDWR);
    	if (device->fd <= 0) {
    		printf("Cannot open %s device\n", device->dev_name);
    		return -1;
    	}
    
    	MSG("\n%s: Opened Channel\n", device->name);
    
    	/* Check if the device is capable of streaming */
    	if (ioctl(device->fd, VIDIOC_QUERYCAP, &capability) < 0) {
    		perror("VIDIOC_QUERYCAP");
    		goto ERROR;
    	}
    
    	if (capability.capabilities & V4L2_CAP_STREAMING)
    		MSG("%s: Capable of streaming\n", device->name);
    	else {
    		ERROR("%s: Not capable of streaming\n", device->name);
    		goto ERROR;
    	}
    
    	{
    		struct v4l2_streamparm streamparam;
    		streamparam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    		if (ioctl(device->fd, VIDIOC_G_PARM, &streamparam) < 0){
    			perror("VIDIOC_G_PARM");
    			goto ERROR;
    		}
    	}
    
    	device->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	ret = ioctl(device->fd, VIDIOC_G_FMT, &device->fmt);
    	if (ret < 0) {
    		ERROR("VIDIOC_G_FMT failed: %s (%d)", strerror(errno), ret);
    		goto ERROR;
    	}
    
    	device->fmt.fmt.pix.pixelformat = FOURCC_STR("YUYV");
    	device->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	device->fmt.fmt.pix.width = device->width;
    	device->fmt.fmt.pix.height = device->height;
    
    	ret = ioctl(device->fd, VIDIOC_S_FMT, &device->fmt);
    	if (ret < 0) {
    		perror("VIDIOC_S_FMT");
    		goto ERROR;
    	}
    
    	MSG("%s: Init done successfully\n", device->name);
    	return 0;
    
    ERROR:
    	close(device->fd);
    
    	return -1;
    }
    
    static void v4l2_exit_device(struct v4l2_device_info *device)
    {
    
    	free(device->buf);
    	close(device->fd);
    
    	return;
    }
    
    
    /*
    * Enable streaming for V4L2 capture device
    */
    static int v4l2_stream_on(struct v4l2_device_info *device)
    {
    	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	int ret = 0;
    
    	ret = ioctl(device->fd, VIDIOC_STREAMON, &type);
    
    	if (ret) {
    		ERROR("VIDIOC_STREAMON failed: %s (%d)", strerror(errno), ret);
    	}
    
    	return ret;
    }
    
    /*
    * Disable streaming for V4L2 capture device
    */
    static int v4l2_stream_off(struct v4l2_device_info *device)
    {
    	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	int ret = -1;
    
    	if (device->fd <= 0) {
    		return ret;
    	}
    
    	ret = ioctl(device->fd, VIDIOC_STREAMOFF, &type);
    
    	if (ret) {
    		ERROR("VIDIOC_STREAMOFF failed: %s (%d)", strerror(errno), ret);
    	}
    
    	return ret;
    }
    
    static int v4l2_request_buffer(struct v4l2_device_info *device,
    		struct dmabuf_buffer **bufs)
    {
    	struct v4l2_requestbuffers reqbuf;
    	unsigned int i;
    	int ret;
    
    	if (device->buf) {
    		// maybe eventually need to support this?
    		ERROR("already reqbuf'd");
    		return -1;
    	}
    
    	reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	reqbuf.memory = device->memory_mode;
    	reqbuf.count = device->num_buffers;
    
    	ret = ioctl(device->fd, VIDIOC_REQBUFS, &reqbuf);
    	if (ret < 0) {
    		ERROR("VIDIOC_REQBUFS failed: %s (%d)", strerror(errno), ret);
    		return ret;
    	}
    
    	if ((reqbuf.count != device->num_buffers) ||
    		(reqbuf.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
    		(reqbuf.memory != V4L2_MEMORY_DMABUF)) {
    			ERROR("unsupported..");
    			return -1;
    	}
    
    	device->num_buffers = reqbuf.count;
    	device->buffers = bufs;
    	device->buf = (struct v4l2_buffer *) calloc(device->num_buffers, \
    			sizeof(struct v4l2_buffer));
    	if (!device->buf) {
    		ERROR("allocation failed");
    		return -1;
    	}
    
    	for (i = 0; i < device->num_buffers; i++) {
    		if (bufs[i]->nbo != 1){
    			ERROR("Number of buffers not right");
    		};
    
    		device->buf[i].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    		device->buf[i].memory = V4L2_MEMORY_DMABUF;
    		device->buf[i].index = i;
    
    		ret = ioctl(device->fd, VIDIOC_QUERYBUF, &device->buf[i]);
    		device->buf[i].m.fd = bufs[i]->fd[0];
    
    		if (ret) {
    			ERROR("VIDIOC_QUERYBUF failed: %s (%d)", strerror(errno), ret);
    			return ret;
    		}
    	}
    
    	return 0;
    }
    
    /*
    * Queue V4L2 buffer
    */
    static int v4l2_queue_buffer(struct v4l2_device_info *device,
    		struct dmabuf_buffer *buf)
    {
    	struct v4l2_buffer *v4l2buf = NULL;
    	int  ret, fd;
    	unsigned char i;
    
    	if(buf->nbo != 1){
    		ERROR("number of bufers not right\n");
    		return -1;
    	}
    
    	fd = buf->fd[0];
    
    	for (i = 0; i < device->num_buffers; i++) {
    		if (device->buf[i].m.fd == fd) {
    			v4l2buf = &device->buf[i];
    		}
    	}
    
    	if (!v4l2buf) {
    		ERROR("invalid buffer");
    		return -1;
    	}
    	ret = ioctl(device->fd, VIDIOC_QBUF, v4l2buf);
    	if (ret) {
    		ERROR("VIDIOC_QBUF failed: %s (%d)", strerror(errno), ret);
    	}
    
    	return ret;
    }
    
    /*
    * DeQueue V4L2 buffer
    */
    struct dmabuf_buffer *v4l2_dequeue_buffer(struct v4l2_device_info *device)
    {
    	struct dmabuf_buffer *buf;
    	struct v4l2_buffer v4l2buf;
    	int ret;
    
    	v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	v4l2buf.memory = V4L2_MEMORY_DMABUF;
    	ret = ioctl(device->fd, VIDIOC_DQBUF, &v4l2buf);
    	if (ret) {
    		ERROR("VIDIOC_DQBUF failed: %s (%d)\n", strerror(errno), ret);
    		return NULL;
    	}
    
    	buf = device->buffers[v4l2buf.index];
    
    	device->buf[v4l2buf.index].timestamp = v4l2buf.timestamp;
    	if(buf->nbo != 1){
    		ERROR("num buffers not proper\n");
    		return NULL;
    	}
    
    	return buf;
    }
    
    
    
    unsigned int get_drm_prop_val(int fd, drmModeObjectPropertiesPtr props,
    							  const char *name)
    {
    	drmModePropertyPtr p;
    	unsigned int i, prop_id = 0; /* Property ID should always be > 0 */
    
    	for (i = 0; !prop_id && i < props->count_props; i++) {
    		p = drmModeGetProperty(fd, props->props[i]);
    		if (!strcmp(p->name, name)){
    			prop_id = p->prop_id;
    			break;
    		}
    		drmModeFreeProperty(p);
    	}
    	if (!prop_id) {
    		printf("Could not find %s property\n", name);
    		drmModeFreeObjectProperties(props);
    		exit(-1);
    	}
    
    	drmModeFreeProperty(p);
    	return props->prop_values[i];
    }
    
    unsigned int find_drm_prop_id(int fd, drmModeObjectPropertiesPtr props,
    							  const char *name)
    {
    	drmModePropertyPtr p;
    	unsigned int i, prop_id = 0; /* Property ID should always be > 0 */
    
    	for (i = 0; !prop_id && i < props->count_props; i++) {
    		p = drmModeGetProperty(fd, props->props[i]);
    		if (!strcmp(p->name, name)){
    			prop_id = p->prop_id;
    			break;
    		}
    		drmModeFreeProperty(p);
    	}
    	if (!prop_id) {
    		printf("Could not find %s property\n", name);
    		drmModeFreeObjectProperties(props);
    		exit(-1);
    	}
    
    	return prop_id;
    }
    
    void add_property(int fd, drmModeAtomicReqPtr req,
    				  drmModeObjectPropertiesPtr props,
    				  unsigned int plane_id,
    				  const char *name, int value)
    {
    	unsigned int prop_id = find_drm_prop_id(fd, props, name);
    	if(drmModeAtomicAddProperty(req, plane_id, prop_id, value) < 0){
    		printf("failed to add property\n");
    	}
    }
    
    void drm_add_plane_property(struct drm_device_info *dev, drmModeAtomicReqPtr req)
    {
    	unsigned int i;
    	unsigned int crtc_x_val = 0;
    	unsigned int crtc_y_val = 0;
    	unsigned int crtc_w_val = dev->width;
    	unsigned int crtc_h_val = dev->height;
    	drmModeObjectProperties *props;
    	unsigned int zorder_val = 1;
    	unsigned int buf_index;
    	struct v4l2_device_info  *v4l2_device;
    
    	for(i = 0; i < status.num_cams; i++){
    		unsigned int plane_id = dev->plane_id[i];
    
    		if(i) {
    			crtc_x_val = PIP_POS_X;
    			crtc_y_val = PIP_POS_Y;
    			crtc_w_val /= 3;
    			crtc_h_val /= 3;
    		}
    		props = drmModeObjectGetProperties(dev->fd, plane_id,
    			DRM_MODE_OBJECT_PLANE);
    
    		if(props == NULL){
    			ERROR("drm obeject properties for plane type is NULL\n");
    			exit (-1);
    		}
    
    		//fb id value will be set every time new frame is to be displayed
    		dev->prop_fbid = find_drm_prop_id(drm_device.fd, props, "FB_ID");
    
    		//Will need to change run time crtc id to disable/enable display of plane
    		dev->prop_crtcid = find_drm_prop_id(drm_device.fd, props, "CRTC_ID");
    
    		//storing zorder val to restore it before quitting the demo
    		drm_device.zorder_val[i] = get_drm_prop_val(drm_device.fd, props, "zorder");
    
    		//Set the fb id based on which camera is chosen to be main camera 
    		if (status.main_cam  == 1){
    			buf_index = (i+1)%2;
    		}
    		else {
    			buf_index = i;
    		}
    
    		if(buf_index == 0){
    			v4l2_device = &cap0_device;
    		}
    		else{
    			v4l2_device = &cap1_device;
    		}
    		printf("w=%d, h=%d\n", v4l2_device->width, v4l2_device->height);
    		add_property(dev->fd, req, props, plane_id, "FB_ID", dev->buf[buf_index][0]->fb_id);
    
    		//set the plane properties once. No need to set these values every time
    		//with the display of frame. 
    		add_property(dev->fd, req, props, plane_id, "CRTC_ID", dev->crtc_id);
    		add_property(dev->fd, req, props, plane_id, "CRTC_X", crtc_x_val);
    		add_property(dev->fd, req, props, plane_id, "CRTC_Y", crtc_y_val);
    		add_property(dev->fd, req, props, plane_id, "CRTC_W", crtc_w_val);
    		add_property(dev->fd, req, props, plane_id, "CRTC_H", crtc_h_val);
    		add_property(dev->fd, req, props, plane_id, "SRC_X", 0);
    		add_property(dev->fd, req, props, plane_id, "SRC_Y", 0);
    		add_property(dev->fd, req, props, plane_id, "SRC_W", v4l2_device->width << 16);
    		add_property(dev->fd, req, props, plane_id, "SRC_H", v4l2_device->height << 16);
    		add_property(dev->fd, req, props, plane_id, "zorder", zorder_val++);
    	}
    }
    
    uint32_t drm_reserve_plane(int fd, unsigned int *ptr_plane_id, int num_planes)
    {
    	unsigned int i;
    	int idx = 0;
    	drmModeObjectProperties *props;
    	drmModePlaneRes *res = drmModeGetPlaneResources(fd);
    	if(res == NULL){
    		ERROR("plane resources not found\n");
    	}
    
    	for (i = 0; i < res->count_planes; i++) {
    		uint32_t plane_id = res->planes[i];
    		unsigned int type_val;
    
    		drmModePlane *plane = drmModeGetPlane(fd, plane_id);
    		if(plane == NULL){
    			ERROR("plane  not found\n");
    		}
    
    		props = drmModeObjectGetProperties(fd, plane->plane_id, DRM_MODE_OBJECT_PLANE);
    
    		if(props == NULL){
    			ERROR("plane (%d) properties not found\n",  plane->plane_id);
    		}
    
    		type_val = get_drm_prop_val(fd, props, "type");
    
    		if(type_val == DRM_PLANE_TYPE_OVERLAY){
    			ptr_plane_id[idx++] = plane_id;
    		}
    
    		drmModeFreeObjectProperties(props);
    		drmModeFreePlane(plane);
    
    		if(idx == num_planes){
    			drmModeFreePlaneResources(res);
    			return 0;
    		}
    	}
    
    	ERROR("plane couldn't be reserved\n");
    	return -1;
    }
    
    
    /* Get crtc id and resolution. */
    void drm_crtc_resolution(struct drm_device_info *device)
    {
    	drmModeCrtc *crtc;
    	int i;
    
    	drmModeResPtr res = drmModeGetResources(device->fd);
    
    	if (res == NULL){
    		ERROR("drmModeGetResources failed: %s\n", strerror(errno));
    		exit(0);
    	};
    
    	for (i = 0; i < res->count_crtcs; i++) {
    		unsigned int crtc_id = res->crtcs[i];
    
    		crtc = drmModeGetCrtc(device->fd, crtc_id);
    		if (!crtc) {
    			DBG("could not get crtc %i: %s\n", res->crtcs[i], strerror(errno));
    			continue;
    		}
    		if (!crtc->mode_valid) {
    			drmModeFreeCrtc(crtc);
    			continue;
    		}
    
    		printf("CRTCs size: %dx%d\n", crtc->width, crtc->height);
    		device->crtc_id = crtc_id;
    		device->width = crtc->width;
    		device->height = crtc->height;
    
    		drmModeFreeCrtc(crtc);
    	}
    
    	drmModeFreeResources(res);
    }
    
    /*
    * DRM restore properties
    */
    static void drm_restore_props(struct drm_device_info *device)
    {
    	unsigned int i;
    	drmModeObjectProperties *props;
    	int ret;
    
    	drmModeAtomicReqPtr req = drmModeAtomicAlloc();
    
    	props = drmModeObjectGetProperties(device->fd, device->crtc_id,
    		DRM_MODE_OBJECT_CRTC);
    
    	//restore trans-key-mode and z-order of promary plane
    	add_property(device->fd, req, props, device->crtc_id, "trans-key-mode", \
    			device->trans_key_mode_val);
    	add_property(device->fd, req, props, device->crtc_id, "zorder", \
    			device->zorder_val_primary_plane);
    
    	//restore z-order of overlay planes
    	for(i = 0; i < status.num_cams; i++){
    		props = drmModeObjectGetProperties(device->fd, device->plane_id[i],
    			DRM_MODE_OBJECT_PLANE);
    
    		if(props == NULL){
    			ERROR("drm obeject properties for plane type is NULL\n");
    			exit (-1);
    		}
    
    		add_property(device->fd, req, props, device->plane_id[i], \
    				"zorder", device->zorder_val[i]);
    	}
    
    	//Commit all the added properties
    	ret = drmModeAtomicCommit(device->fd, req, DRM_MODE_ATOMIC_TEST_ONLY, 0);
    	if(!ret){
    		drmModeAtomicCommit(device->fd, req, 0, 0);
    	}
    	else{
    		ERROR("ret from drmModeAtomicCommit = %d\n", ret);
    	}
    
    	drmModeAtomicFree(req);
    }
    
    /*
    * drm device init
    */
    static int drm_init_device(struct drm_device_info *device)
    {
    	if (!device->fd) {
    		device->fd = drmOpen("omapdrm", NULL);
    		if (device->fd < 0) {
    			ERROR("could not open drm device: %s (%d)", strerror(errno), errno);
    			return -1;
    		}
    	}
    
    	drmSetClientCap(device->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
    	drmSetClientCap(device->fd, DRM_CLIENT_CAP_ATOMIC, 1);
    
    	device->dev = omap_device_new(device->fd);
    
    	/* Get CRTC id and resolution. As well set the global display width and height */
    	drm_crtc_resolution(device);
    
    	/* Store display resolution so GUI can be configured */
    	status.display_xres = device->width;
    	status.display_yres = device->height;
    
    	drm_reserve_plane(device->fd, device->plane_id, status.num_cams);
    
    	return 0;
    }
    
    /*
    *Clean resources while exiting drm device
    */
    static void drm_exit_device(struct drm_device_info *device)
    {
    	drm_restore_props(device);
    	drmSetClientCap(device->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
    	drmSetClientCap(device->fd, DRM_CLIENT_CAP_ATOMIC, 0);
    
    	omap_device_del(device->dev);
    	device->dev = NULL;
    	if (device->fd > 0) {
    		close(device->fd);
    	}
    
    	return;
    }
    
    /*
    * Set up the DSS for blending of video and graphics planes
    */
    static int drm_init_dss(void)
    {
    	drmModeObjectProperties *props;
    	int ret;
        FILE *fp;
        char str[10];
        char trans_key_mode = 2;
    
    	/*
    	* Dual camera demo is supported on Am437x and AM57xx evm. Find which
    	* specific SoC the demo is running to set the trans key mode -
    	* found at the corresponding TRM, for example,
    	* For AM437x: trans_key_mode = 1 GFX Dest Trans
    	*             TransKey applies to GFX overlay, marking which
    	*              pixels come from VID overlays)
    	* For AM57xx: trans_key_mode = 2 Source Key.
    	*             Match on Layer4 makes Layer4 transparent (zorder 3)
    	*
    	* The deault mode is 1 for backward compatibility
    	*/
    
    	fp = fopen("/proc/sys/kernel/hostname", "r");
    	fscanf(fp, "%s", str);
    
    	//terminate the string after the processor name. "-evm" extension is
    	//ignored in case the demo gets supported on other boards like idk etc
    	str[6] = '\0';
    	printf("Running the demo on %s processor\n", str);
    
    	//Set trans-key-mode to 1 if dual camera demo is running on AM437x
    	if (strcmp(str,"am437x") == 0){
    		trans_key_mode = 1;
    	}
    
    	drmModeAtomicReqPtr req = drmModeAtomicAlloc();
    
    	/* Set CRTC properties */
    	props = drmModeObjectGetProperties(drm_device.fd, drm_device.crtc_id,
    		DRM_MODE_OBJECT_CRTC);
    
    	drm_device.zorder_val_primary_plane = get_drm_prop_val(drm_device.fd,
    		props, "zorder");
    	drm_device.trans_key_mode_val = get_drm_prop_val(drm_device.fd, props,
    		"trans-key-mode");
    
    	add_property(drm_device.fd, req, props, drm_device.crtc_id,
    		"trans-key-mode", trans_key_mode);
    	add_property(drm_device.fd, req, props, drm_device.crtc_id,
    		"alpha_blender", 1);
    	add_property(drm_device.fd, req, props, drm_device.crtc_id,
    		"zorder", MAX_ZORDER_VAL);
    
    	/* Set overlay plane properties like zorder, crtc_id, buf_id, src and */
    	/* dst w, h etc                                                       */
    	drm_add_plane_property(&drm_device, req);
    
    	//Commit all the added properties
    	ret = drmModeAtomicCommit(drm_device.fd, req, DRM_MODE_ATOMIC_TEST_ONLY, 0);
    	if(!ret){
    		drmModeAtomicCommit(drm_device.fd, req, 0, 0);
    	}
    	else{
    		ERROR("ret from drmModeAtomicCommit = %d\n", ret);
    		return -1;
    	}
    
    	drmModeAtomicFree(req);
    	return 0;
    }
    
    
    /*
    * drm disable pip layer
    */
    void drm_disable_pip(void)
    {
    	int ret;
    	drmModeAtomicReqPtr req = drmModeAtomicAlloc();
    
    	drmModeAtomicAddProperty(req, drm_device.plane_id[1],
    		drm_device.prop_fbid, 0);
    	drmModeAtomicAddProperty(req, drm_device.plane_id[1],
    		drm_device.prop_crtcid, 0);
    
    	ret = drmModeAtomicCommit(drm_device.fd, req,
    		DRM_MODE_ATOMIC_TEST_ONLY, 0);
    	if(!ret){
    		drmModeAtomicCommit(drm_device.fd, req,
    			0, 0);
    	}
    	else{
    		ERROR("failed to enable plane %d atomically: %s",
    			drm_device.plane_id[!status.main_cam], strerror(errno));
    	}
    
    	drmModeAtomicFree(req);
    }
    
    void drm_enable_pip(void)
    {
    	int ret;
    
    	drmModeAtomicReqPtr req = drmModeAtomicAlloc();
    
    	drmModeAtomicAddProperty(req, drm_device.plane_id[1],
    		drm_device.prop_fbid, drm_device.buf[!status.main_cam][0]->fb_id);
    	drmModeAtomicAddProperty(req, drm_device.plane_id[1],
    		drm_device.prop_crtcid, drm_device.crtc_id);
    
    	ret = drmModeAtomicCommit(drm_device.fd, req,
    		DRM_MODE_ATOMIC_TEST_ONLY, 0);
    
    	if(!ret){
    		drmModeAtomicCommit(drm_device.fd, req, 0, 0);
    	}
    	else{
    		ERROR("failed to enable plane %d atomically: %s",
    			drm_device.plane_id[!status.main_cam], strerror(errno));
    	}
    
    	drmModeAtomicFree(req);
    }
    
    /*
    * Capture v4l2 frame and save to jpeg
    */
    static int capture_frame(struct v4l2_device_info *v4l2_device,
    						 struct dmabuf_buffer *buf)
    {
    #ifdef USE_CMEM_BUF
    	//use cmem_buf pointer for buffer access. Alternatly, if cmem_buf ptr is not
    	// saved, mmap the cmem buffer descriptor (buf->fd[0]) to access buffer 
    	// memory. Don't use omap_bo_map(buf->bo[0]) to get buf ptr, as the functiom
    	// uses drm device fd to map the buffer and not the cmem buf fd.
    	unsigned char *cap_buf = buf->cmem_buf;
    
    	/* Add code to invalidate cache */
    	dma_buf_do_cache_operation(buf->fd[0], (DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ));
    #else //USE_CMEM_BUF
    	unsigned char *cap_buf = omap_bo_map(buf->bo[0]);
    #endif //USE_CMEM_BUF
    
    	jpegWrite(cap_buf, status.num_jpeg, v4l2_device->width, v4l2_device->height);
    
    #ifdef USE_CMEM_BUF
    	/* Add code to writeback cache */
    	//In jpeg compression case, CPU do read only operation on the buffer and hence no need to call this API
    	//Call this function if CPU has written on the cmem shared buffer.
    	//dma_buf_do_cache_operation(buf->fd[0], (DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_READ));
    #endif //USE_CMEM_BUF
    
    
    
    	return 0;
    }
    
    /*
    * Initialize the app resources with default parameters
    */
    void default_parameters(void)
    {
    	/* Main camera display */
    	memset(&drm_device, 0, sizeof(drm_device));
    	strcpy(drm_device.dev_name,"/dev/drm");
    	strcpy(drm_device.name,"drm");
    	drm_device.width=0;
    	drm_device.height=0;
    	drm_device.bo_flags = OMAP_BO_SCANOUT;
    	drm_device.fd = 0;
    
    	/* Main camera */
    	cap0_device.memory_mode = V4L2_MEMORY_DMABUF;
    	cap0_device.num_buffers = NBUF;
    	strcpy(cap0_device.dev_name,"/dev/video1");
    	strcpy(cap0_device.name,"Capture 0");
    	cap0_device.buffers = NULL;
    	cap0_device.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    	cap0_device.width = CAP_WIDTH;
    	cap0_device.height = CAP_HEIGHT;
    
    	/* PiP camera */
    	cap1_device.memory_mode = V4L2_MEMORY_DMABUF;
    	cap1_device.num_buffers = NBUF;
    	strcpy(cap1_device.dev_name,"/dev/video0");
    	strcpy(cap1_device.name,"Capture 1");
    	cap1_device.buffers = NULL;
    	cap1_device.fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
    	cap1_device.width = CAP_WIDTH;
    	cap1_device.height = CAP_HEIGHT;
    
    	/* Set the default parameters for device options */
    	status.main_cam=0;
    	status.num_cams=2;
    	status.num_jpeg=0;
    	if(status.num_cams == 1){
    		status.pip=false;
    	}
    	else{
    		status.pip=true;
    	}
    	status.jpeg=false;
    	status.exit=false;
    
    	/* Ensure that jpeg image save directory exists */
    	mkdir("/usr/share/camera-images/", 0777);
    
    	return;
    }
    
    /*
    * Free resource and exit devices
    */
    void exit_devices(void)
    {
    	v4l2_exit_device(&cap0_device);
    	if (status.num_cams==2) {
    		v4l2_exit_device(&cap1_device);
    	}
    	free_vid_buffers(drm_device.buf[0], NBUF);
    	free_vid_buffers(drm_device.buf[1], NBUF);
    	drm_exit_device(&drm_device);
    }
    
    /*
    * End camera streaming
    */
    void end_streaming(void)
    {
    	v4l2_stream_off(&cap0_device);
    	if (status.num_cams==2) {
    		v4l2_stream_off(&cap1_device);
    	}
    }
    
    void set_plane_properties()
    {
    	int ret;
    	drmModeAtomicReqPtr req = drmModeAtomicAlloc();
    
    	req = drmModeAtomicAlloc();
    
    	drmModeAtomicAddProperty(req, drm_device.plane_id[0],
    		drm_device.prop_fbid, drm_device.buf[status.main_cam][0]->fb_id);
    
    	if(status.pip){
    		drmModeAtomicAddProperty(req, drm_device.plane_id[1],
    			drm_device.prop_fbid, drm_device.buf[!status.main_cam][0]->fb_id);
    	}
    	ret = drmModeAtomicCommit(drm_device.fd, req,
    		DRM_MODE_ATOMIC_TEST_ONLY, 0);
    	if(!ret){
    		drmModeAtomicCommit(drm_device.fd, req,
    			0, 0);
    	}
    	else{
    		ERROR("failed to enable plane %d atomically: %s",
    			drm_device.plane_id[!status.main_cam], strerror(errno));
    	}
    	drmModeAtomicFree(req);
    }
    /*
    * Initializes all drm and v4l2 devices for loopback
    */
    int init_loopback(void)
    {
    	bool status_cam0 = 0;
    	bool status_cam1 = 0;
    
    	/* Declare properties for video and capture devices */
    	default_parameters();
    
    #ifdef USE_CMEM_BUF
    	init_cmem();
    #endif //USE_CMEM_BUF
    
    	/* Initialize the drm display devic */
    	if (drm_init_device(&drm_device)) goto Error;
    
    	/* Check to see if the display resolution is very small.  If so, the
    	* camera capture resolution needs to be lowered so that the scaling
    	* limits of the DSS are not reached */
    	if (drm_device.width < 640) {
    		/* Set capture 0 device resolution */
    		cap0_device.width = 640;
    		cap0_device.height = 480;
    
    		/* Set capture 1 device resolution */
    		cap1_device.width = 640;
    		cap1_device.height = 480;
    	}
    
    	/* Initialize the v4l2 capture devices */
    	if (v4l2_init_device(&cap0_device) < 0) {
    		printf("first camera detection failed\n");
    		/* If there is not a second camera, program can still continue */
    		status.num_cams=1;
    		status.main_cam=1;
    		status.pip=false;
    	}
    	else{
    		unsigned int i;
    		struct dmabuf_buffer **buffers = get_vid_buffers(&drm_device, cap0_device.num_buffers, 
    			cap0_device.fmt.fmt.pix.pixelformat, cap0_device.width, cap0_device.height);
    
    		if (!buffers) {
    			goto Error;
    		}
    
    		drm_device.buf[0] = buffers;
    
    		/* Pass these buffers to the capture drivers */
    		if (v4l2_request_buffer(&cap0_device, buffers) < 0) {
    			goto Error;
    		}
    
    		for (i = 0; i < cap0_device.num_buffers; i++) {
    			v4l2_queue_buffer(&cap0_device, buffers[i]);
    		}
    
    		status_cam0 = 1;
    	}
    
    	if(v4l2_init_device(&cap1_device) < 0) {
    		/* If there is not a second camera, program can still continue */
    		if(status.num_cams ==2){
    			status.num_cams=1;
    			status.pip=false;
    			printf("Only one camera detected\n");
    		}
    		//first camera wasn't detected
    		else if (!status_cam0){
    			printf("No camera detected\n");
    			goto Error;
    		}
    	}
    	else{
    		unsigned int i;
    		struct dmabuf_buffer **buffers = get_vid_buffers(&drm_device, cap1_device.num_buffers, 
    			cap1_device.fmt.fmt.pix.pixelformat, cap1_device.width, cap1_device.height);
    		if (!buffers) {
    			goto Error;
    		}
    
    		drm_device.buf[1] = buffers;
    
    		/* Pass these buffers to the capture drivers */
    		if (v4l2_request_buffer(&cap1_device, buffers) < 0) {
    			goto Error;
    		}
    
    		for (i = 0; i < cap1_device.num_buffers; i++) {
    			v4l2_queue_buffer(&cap1_device, buffers[i]);
    		}
    
    		status_cam1 = 1;
    	}
    
    	/* Enable streaming for the v4l2 capture devices */
    	if(status_cam0){
    		if (v4l2_stream_on(&cap0_device) < 0) goto Error;
    	}
    
    	if (status_cam1) {
    		if (v4l2_stream_on(&cap1_device) < 0) goto Error;
    	}
    
    	/* Configure the DSS to blend video and graphics layers */
    	if (drm_init_dss() < 0 ) goto Error;
    
    	return 0;
    
    Error:
    	status.exit = true;
    	return -1;
    }
    
    static void page_flip_handler(int fd, unsigned int frame,
    							  unsigned int sec, unsigned int usec,
    							  void *data)
    {
    	int *waiting_for_flip = data;
    	*waiting_for_flip = 0;
    }
    
    /*
    * Determines which camera feeds are being displayed and
    * whether a jpeg image needs to be captured.
    */
    void process_frame(void)
    {
    	fd_set fds;
    	int ret, waiting_for_flip = 1;
    	struct dmabuf_buffer *buf[2] = {NULL, NULL};
    	drmModeAtomicReqPtr req = drmModeAtomicAlloc();
    
    	struct v4l2_device_info *v4l2_device[2] =
    	{&cap0_device, &cap1_device};
    
    	drmEventContext evctx = {
    		.version = DRM_EVENT_CONTEXT_VERSION,
    		.vblank_handler = 0,
    		.page_flip_handler = page_flip_handler,
    	};
    
    	/* Request a capture buffer from the driver that can be copied to */
    	/* framebuffer */
    	buf[status.main_cam] =
    		v4l2_dequeue_buffer(v4l2_device[status.main_cam]);
    	drmModeAtomicAddProperty(req, drm_device.plane_id[0],
    		drm_device.prop_fbid, buf[status.main_cam]->fb_id);
    
    	if (status.pip==true) {
    		buf[!status.main_cam] =
    			v4l2_dequeue_buffer(v4l2_device[!status.main_cam]);
    		drmModeAtomicAddProperty(req, drm_device.plane_id[1],
    			drm_device.prop_fbid, buf[!status.main_cam]->fb_id);
    	}
    
    	ret = drmModeAtomicCommit(drm_device.fd, req,
    		DRM_MODE_ATOMIC_TEST_ONLY, 0);
    
    	if(!ret){
    		drmModeAtomicCommit(drm_device.fd, req,
    			DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK, &waiting_for_flip);
    		}
    		else {
    		ERROR("failed to add plane atomically: %s", strerror(errno));
    		}
    
    	drmModeAtomicFree(req);
    
    	/* Save jpeg image if triggered */
    	if (status.jpeg==true) {
    		capture_frame(v4l2_device[status.main_cam], buf[status.main_cam]);
    		status.jpeg=false;
    		status.num_jpeg++;
    		if (status.num_jpeg==10)
    			status.num_jpeg=0;
    	}
    
    	FD_ZERO(&fds);
    	FD_SET(drm_device.fd, &fds);
    
    	while (waiting_for_flip) {
    		ret = select(drm_device.fd + 1, &fds, NULL, NULL, NULL);
    		if (ret < 0) {
    			printf("select err: %s\n", strerror(errno));
    			return;
    		}
    		else if (ret == 0) {
    			printf("select timeout!\n");
    			return;
    		}
    		else if (FD_ISSET(0, &fds)) {
    			continue;
    		}
    		drmHandleEvent(drm_device.fd, &evctx);
    	}
    
    	v4l2_queue_buffer(v4l2_device[status.main_cam], buf[status.main_cam]);
    	if(status.pip == true){
    		v4l2_queue_buffer(v4l2_device[!status.main_cam], buf[!status.main_cam]);
    	}
    }
    

    cmem_buf.c
    #include "cmem_buf.h"
    
    #ifdef USE_CMEM_BUF
    #include <stdio.h>
    #include <unistd.h>
    #include <ti/cmem.h>
    #include <linux/dma-buf.h>
    #include <sys/ioctl.h>
    
    #define CMEM_BLOCKID CMEM_CMABLOCKID
    
    CMEM_AllocParams cmem_alloc_params = {
    	CMEM_HEAP,	/* type */
    	CMEM_CACHED,	/* flags */
    	1		/* alignment */
    };
    
    void init_cmem()
    {
    	CMEM_init();
    }
    
    int alloc_cmem_buffer(unsigned int size, unsigned int align, void *cmem_buf)
    {
    	cmem_alloc_params.alignment = align;
    
    	printf("\n allocating cmem buffer of size 0x%x", size);
    
    	*cmem_buf = CMEM_alloc2(CMEM_BLOCKID, size,
    		&cmem_alloc_params);
    
    	if(cmem_buf == NULL){
    		printf("CMEM allocation failed");
    		return -1;
    	}
    
    	return CMEM_export_dmabuf(cmem_buf);
    }
    
    void free_cmem_buffer(void *cmem_buffer)
    {
    	CMEM_free(cmem_buffer, &cmem_alloc_params);
    }
    
    int dma_buf_do_cache_operation(int dma_buf_fd, uint32_t cache_operation) 
    {
    	int ret;
    	struct dma_buf_sync sync;
    	sync.flags = cache_operation;
    
    	ret = ioctl(dma_buf_fd, DMA_BUF_IOCTL_SYNC, &sync);
    
    	return ret;
    }
    
    #endif //USE_CMEM_BUF

  • Hi Kedar Chitnis,

       This is the code we operate with cmem interface.

                       CMEM_AllocParams params;

                       params.type = CMEM_HEAP;

                       params.alignment = 0;

                       params.flags = CMEM_CACHED;

                       void * vaddr = CMEM_alloc2(CMEM_CMABLOCKID, width * height * bpp / 8, &params);

                       g_va = vaddr;

                       MSG("minigui cmem vaddr %x  \n",vaddr);

                       if(NULL ==  vaddr)

                       {

                                MSG("minigui cmem vaddr is null \n");

                                return NULL;

                               

                       }

                       fd =CMEM_export_dmabuf(vaddr);

                       if(fd <= 0)

                       {

                                ERROR("minigui CMEM_export_dmabuf fail \n");

                                return NULL;

                       }

    display-kms-minigui.c
    /*
     * Copyright (C) 2011 Texas Instruments
     * Author: Rob Clark <rob.clark@linaro.org>
     *
     * This program is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License version 2 as published by
     * the Free Software Foundation.
     *
     * This program is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     * more details.
     *
     * You should have received a copy of the GNU General Public License along with
     * this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    #include "util.h"
    //#include "drv_util.h"
    #include <xf86drmMode.h>
    #include "SVNPLog.h"
    
    
    //extern struct drv_util* g_pUtil;
    static uint32_t g_pa = 0;
    static void* g_va = 0;
    //extern  int gpanelID;
    int minigui_hide = 0;
    int minigui_fbid = 0;
    int minigui_ok = 0;
    int minigui_planeId =0;
    
    static int mode_init = 0;
    extern HAL_INFO debug_hal_info;
    /* NOTE: healthy dose of recycling from libdrm modetest app.. */
    
    /*
     * Mode setting with the kernel interfaces is a bit of a chore.
     * First you have to find the connector in question and make sure the
     * requested mode is available.
     * Then you need to find the encoder attached to that connector so you
     * can bind it with a free crtc.
     */
    static struct connector {
    	uint32_t id;
    	char mode_str[64];
    	drmModeModeInfo *mode;
    	drmModeEncoder *encoder;
    	int crtc;
    	int pipe;
    };
    
    static struct panel_prop {
    	uint32_t id;
    	uint64_t value;
    };
    
    
    
    static struct panel_prop zorder_prop = {
    	.id = G5_DRM_ZORDER,
    	.value = 2,
    };
    
    #define to_display_kms(x) container_of(x, struct display_kms_minigui, base)
    struct display_kms_minigui {
    	struct display base;
    
    	uint32_t connectors_count;
    	struct connector connector[10];
    	drmModePlane *ovr[10];
    
    	int scheduled_flips, completed_flips;
    	uint32_t bo_flags;
    	drmModeResPtr resources;
    	drmModePlaneRes *plane_resources;
    	struct buffer *current;
    };
    
    #define to_buffer_kms(x) container_of(x, struct buffer_kms_minigui, base)
    struct buffer_kms_minigui {
    	struct buffer base;
    	uint32_t fb_id;
    };
    
    static uint32_t used_planes = 0;
    static int ndisplays = 0;
    
    extern  int global_fd ;
    
    static struct omap_bo *
    alloc_bo(struct display *disp, uint32_t bpp, uint32_t width, uint32_t height,
    		uint32_t *bo_handle, uint32_t *pitch,uint32_t pa)
    {
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	struct omap_bo *bo;
    	uint32_t bo_flags = disp_kms->bo_flags;
    	int fd =0;
    #if 1
    	if(pa == 0)
    	{
    		#if 0
    		MSG("minigui CMEM_allocPhys2 begin...\n");
    		CMEM_AllocParams params;
    		params.type = CMEM_HEAP; 
    		params.alignment = 0;
    		params.flags = CMEM_CACHED;
    		g_pa = CMEM_allocPhys2(CMEM_CMABLOCKID, width * height * bpp / 8, &params);
    		pa = g_pa;
    		MSG("minigui CMEM_allocPhys2 end pa = %x...\n",g_pa);
    		#endif
    		CMEM_AllocParams params;
    		params.type = CMEM_HEAP; 
    		params.alignment = 0;
    		params.flags = CMEM_CACHED;
    		void * vaddr = CMEM_alloc2(CMEM_CMABLOCKID, width * height * bpp / 8, &params); 
    		g_va = vaddr;
    		MSG("minigui cmem vaddr %x  \n",vaddr);
    		if(NULL ==  vaddr)
    		{
    			MSG("minigui cmem vaddr is null \n");
    			return NULL;
    			
    		}
    		fd =CMEM_export_dmabuf(vaddr);
    		if(fd <= 0)
    		{
    			ERROR("minigui CMEM_export_dmabuf fail \n");
    			return NULL;
    		}
    
    	}
    	else
    	{
    		g_pa = pa;
    		MSG("minigui CMEM_allocPhys2  pa = %x...\n",g_pa);
    		void * vaddr = CMEM_map(g_pa, width*height*bpp/8);
    		MSG("minigui cmem vaddr %x  \n",vaddr);
    		if(NULL ==  vaddr)
    		{
    			MSG("minigui cmem vaddr is null \n");
    			return NULL;
    			
    		}
    		fd =CMEM_export_dmabuf(vaddr);
    		MSG("minigui cmem vaddr %x  \n",vaddr);
    		if(fd <= 0)
    		{
    			ERROR("minigui CMEM_export_dmabuf fail \n");
    			return NULL;
    		}
    		
    		
    	}
    #endif
    	if ((bo_flags & OMAP_BO_TILED) == OMAP_BO_TILED) {
    		bo_flags &= ~OMAP_BO_TILED;
    		if (bpp == 8) {
    			bo_flags |= OMAP_BO_TILED_8;
    		} else if (bpp == 16) {
    			bo_flags |= OMAP_BO_TILED_16;
    		} else if (bpp == 32) {
    			bo_flags |= OMAP_BO_TILED_32;
    		}
    	}
    	//bo_flags |= OMAP_BO_WC;
    	bo_flags |= OMAP_BO_CACHED;
    
    	if (bo_flags & OMAP_BO_TILED) {
    
    		bo = omap_bo_new_tiled(disp->dev, ALIGN2(width,7), height, bo_flags);
    	} else {
    
    		//bo = omap_bo_new(disp->dev, width * height * bpp / 8, bo_flags);
    	      // bo = (struct omap_bo *)omap_bo_new_paddr(disp->dev, width * height * bpp / 8, OMAP_BO_CACHED, g_pa);
    	      bo = omap_bo_from_dmabuf(disp->dev,fd);
    
    	}
    
    	if (bo) {
    		*bo_handle = omap_bo_handle(bo);
    		*pitch = width * bpp / 8;
    		if (bo_flags & OMAP_BO_TILED)
    			*pitch = ALIGN2(*pitch, PAGE_SHIFT);
    	}
    
    	return bo;
    }
    
    static struct buffer *
    alloc_buffer(struct display *disp, uint32_t fourcc, uint32_t w, uint32_t h,uint32_t pa)
    {
    	struct buffer_kms_minigui *buf_kms;
    	struct buffer *buf;
    	uint32_t bo_handles[4] = {0}, offsets[4] = {0};
    	int ret;
    
    	buf_kms = calloc(1, sizeof(*buf_kms));
    	if (!buf_kms) {
    		SVP_ERROR("allocation failed");
    		return NULL;
    	}
    	buf = &buf_kms->base;
    
    	buf->fourcc = fourcc;
    	buf->width = w;
    	buf->height = h;
    	buf->multiplanar = true;
    
    	buf->nbo = 1;
    
    	if (!fourcc)
    		fourcc = FOURCC('A','R','2','4');
    
    	switch(fourcc) {
    	case FOURCC('A','R','2','4'):
    		buf->nbo = 1;
    		buf->bo[0] = alloc_bo(disp, 32, buf->width, buf->height,
    				&bo_handles[0], &buf->pitches[0],pa);
    		buf->pa[0] = g_pa;
    		buf->va[0] = g_va;
    		if(buf->bo[0] == NULL)
    			goto fail;
    		break;
    	case FOURCC('U','Y','V','Y'):
    	case FOURCC('Y','U','Y','V'):
    		buf->nbo = 1;
    		buf->bo[0] = alloc_bo(disp, 16, buf->width, buf->height,
    				&bo_handles[0], &buf->pitches[0],pa);
    		buf->pa[0] = g_pa;
    		buf->va[0] = g_va;
    		break;
    	case FOURCC('N','V','1','2'):
    		if (1) {
    			buf->nbo = 2;
    			buf->bo[0] = alloc_bo(disp, 8, buf->width, buf->height,
    					&bo_handles[0], &buf->pitches[0],pa);
    			buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
    			buf->pa[0] = g_pa;
    			buf->va[0] = g_va;
    			buf->bo[1] = alloc_bo(disp, 16, buf->width/2, buf->height/2,
    					&bo_handles[1], &buf->pitches[1],pa);
    			buf->fd[1] = omap_bo_dmabuf(buf->bo[1]);
    			buf->pa[1] = g_pa;
    			buf->va[1] = g_va;
    		} else {
    			buf->nbo = 1;
    			buf->bo[0] = alloc_bo(disp, 8, buf->width, buf->height * 3 / 2,
    					&bo_handles[0], &buf->pitches[0],pa);
    			buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
    			bo_handles[1] = bo_handles[0];
    			buf->pitches[1] = buf->pitches[0];
    			offsets[1] = buf->width * buf->height;
    			buf->multiplanar = false;
    			buf->pa[0] = g_pa;
    			buf->va[0] = g_va;
    		}
    		break;
    	case FOURCC('I','4','2','0'):
    		buf->nbo = 3;
    		buf->bo[0] = alloc_bo(disp, 8, buf->width, buf->height,
    				&bo_handles[0], &buf->pitches[0],pa);
    		buf->pa[0] = g_pa;
    		buf->va[0] = g_va;
    		buf->bo[1] = alloc_bo(disp, 8, buf->width/2, buf->height/2,
    				&bo_handles[1], &buf->pitches[1],pa);
    		buf->pa[1] = g_pa;
    		buf->va[1] = g_va;
    		buf->bo[2] = alloc_bo(disp, 8, buf->width/2, buf->height/2,
    				&bo_handles[2], &buf->pitches[2],pa);
    		buf->pa[2] = g_pa;
    		buf->va[2] = g_va;
    		break;
    	default:
    		SVP_ERROR("invalid format: 0x%08x", fourcc);
    		goto fail;
    	}
    
    	ret = drmModeAddFB2(disp->fd, buf->width, buf->height, fourcc,
    			bo_handles, buf->pitches, offsets, &buf_kms->fb_id, 0);
    	if (ret) {
    		SVP_ERROR("drmModeAddFB2 failed: %s (%d)", strerror(errno), ret);
    		goto fail;
    	}
    	//printf("##########diaosu : alloc_buffer :traj fb_id %d \n ##########",buf_kms->fb_id);
    
    	return buf;
    
    fail:
    	// XXX cleanup
    	if(NULL != buf_kms)
    	{
    		free(buf_kms);
    		buf_kms = NULL;
    	}
    	return NULL;
    }
    
    static void
    free_buffers(struct display *disp, uint32_t n)
    {
    	uint32_t i;
    	for (i = 0; i < n; i++) {
                    if (disp->buf[i]) {
    			close(disp->buf[i]->fd[0]);
    			omap_bo_del(disp->buf[i]->bo[0]);
    			if(disp->multiplanar){
    				close(disp->buf[i]->fd[1]);
    				omap_bo_del(disp->buf[i]->bo[1]);
    			}
                    }
            }
    free(disp->buf);
    }
    
    /*
    static void hide_panel(struct display *disp,int panelId)
    {
        // SVP_INFO("render_wait... \n");
    
    	   struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	   //drmDropMaster(disp->fd);
    	   gpanelID = -1;
    	   zorder_prop.value = 1;
    	   SVP_INFO("###vpe show_wait###\n");
    	  //sem_timedwait(&ShowSem);
       	
    }
    
    static void show_panel(struct display *disp,int panelId)
    {
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	 //drmSetMaster(disp->fd);
    	gpanelID = panelId;
    	 zorder_prop.value = 2;
    	//init_gfb = true;
    	
    	SVP_INFO("~~vpe next_loop panelID ~~~~%d \n",gpanelID);
    	//sem_post(&ShowSem);
    }
    */
    
    static struct buffer **
    alloc_buffers(struct display *disp, uint32_t n,
    		uint32_t fourcc, uint32_t w, uint32_t h,uint32_t* pa)
    {
    	struct buffer **bufs;
    	uint32_t i = 0;
    
    	bufs = calloc(n, sizeof(*bufs));
    	if (!bufs) {
    		SVP_ERROR("allocation failed");
    		goto fail;
    	}
    	if(pa != NULL){	
    		for (i = 0; i < n; i++) {
    			bufs[i] = alloc_buffer(disp, fourcc, w, h,pa[i]);
    			if (!bufs[i]) {
    				SVP_ERROR("allocation failed");
    				goto fail;
    			}
    		}
    	}
    	else
    	{
    		for (i = 0; i < n; i++) {
    		bufs[i] = alloc_buffer(disp, fourcc, w, h,0);
    		if (!bufs[i]) {
    			SVP_ERROR("allocation failed");
    			goto fail;
    		}
    		}
    	}
    	disp->buf=bufs;
    
    	return bufs;
    
    fail:
    	// XXX cleanup
    	if(NULL != bufs)
    	{
    		free(bufs);
    		bufs = NULL;
    	}
    	return NULL;
    }
    
    static struct buffer **
    get_buffers(struct display *disp, uint32_t n)
    {
    	//return alloc_buffers(disp, n, 0, disp->width, disp->height);
    	return NULL;
    }
    
    static struct buffer **
    get_vid_buffers_minigui(struct display *disp, uint32_t n,
    		uint32_t fourcc, uint32_t w, uint32_t h,uint32_t* pa)
    {
    	return alloc_buffers(disp, n, fourcc, w, h,pa);
    }
    
    static void
    page_flip_handler(int fd, unsigned int frame,
    		unsigned int sec, unsigned int usec, void *data)
    {
    	struct display *disp = data;
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    
    	disp_kms->completed_flips++;
    
    	SVP_INFO("Page flip: frame=%d, sec=%d, usec=%d, remaining=%d", frame, sec, usec,
    			disp_kms->scheduled_flips - disp_kms->completed_flips);
    }
    
    static int
    post_buffer_minigui(struct display *disp, struct buffer *buf)
    {
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	struct buffer_kms_minigui *buf_kms = to_buffer_kms(buf);
    	int ret, last_err = 0, x = 0;
    	uint32_t i;
    
    	for (i = 0; i < disp_kms->connectors_count; i++) {
    		struct connector *connector = &disp_kms->connector[i];
    
    		if (! connector->mode) {
    			continue;
    		}
    
    		if (! disp_kms->current) {
    			/* first buffer we flip to, setup the mode (since this can't
    			 * be done earlier without a buffer to scanout)
    			 */
    			SVP_INFO("Setting mode %s on connector %d, crtc %d",
    					connector->mode_str, connector->id, connector->crtc);
    
    			ret = drmModeSetCrtc(disp->fd, connector->crtc, buf_kms->fb_id,
    					x, 0, &connector->id, 1, connector->mode);
    
    			x += connector->mode->hdisplay;
    		} else {
    			ret = drmModePageFlip(disp->fd, connector->crtc, buf_kms->fb_id,
    					DRM_MODE_PAGE_FLIP_EVENT, disp);
    			disp_kms->scheduled_flips++;
    		}
    
    		if (ret) {
    			SVP_ERROR("Could not post buffer on crtc %d: %s (%d)",
    					connector->crtc, strerror(errno), ret);
    			last_err = ret;
    			/* well, keep trying the reset of the connectors.. */
    		}
    	}
    
    	/* if we flipped, wait for all flips to complete! */
    	while (disp_kms->scheduled_flips > disp_kms->completed_flips) {
    		drmEventContext evctx = {
    				.version = DRM_EVENT_CONTEXT_VERSION,
    				.page_flip_handler = page_flip_handler,
    		};
    		struct timeval timeout = {
    				.tv_sec = 3,
    				.tv_usec = 0,
    		};
    		fd_set fds;
    
    		FD_ZERO(&fds);
    		FD_SET(disp->fd, &fds);
    
    		ret = select(disp->fd + 1, &fds, NULL, NULL, &timeout);
    		if (ret <= 0) {
    			if (errno == EAGAIN) {
    				continue;    /* keep going */
    			} else {
    				SVP_ERROR("Timeout waiting for flip complete: %s (%d)",
    						strerror(errno), ret);
    				last_err = ret;
    				break;
    			}
    		}
    
    		drmHandleEvent(disp->fd, &evctx);
    	}
    
    	disp_kms->current = buf;
    
    	return last_err;
    }
    static unsigned int find_drm_prop_id(int fd, drmModeObjectPropertiesPtr props,
                                  const char *name)
    {
        drmModePropertyPtr p;
        unsigned int i, prop_id = 0; /* Property ID should always be > 0 */
    
        for (i = 0; !prop_id && i < props->count_props; i++) {
            p = drmModeGetProperty(fd, props->props[i]);
            if (!strcmp(p->name, name)){
                prop_id = p->prop_id;
                break;
            }
            drmModeFreeProperty(p);
        }
        if (!prop_id) {
            printf("Could not find %s property\n", name);
            drmModeFreeObjectProperties(props);
            exit(-1);
        }
    
        return prop_id;
    }
    
    static void add_property(int fd, drmModeAtomicReqPtr req,
                      drmModeObjectPropertiesPtr props,
                      unsigned int plane_id,
                      const char *name, int value)
    {
        unsigned int prop_id = find_drm_prop_id(fd, props, name);
        if(drmModeAtomicAddProperty(req, plane_id, prop_id, value) < 0){
            printf("failed to add property\n");
        }
    }
    
    static int
    get_overlay_plane(struct display *disp, struct buffer *buf)
    {
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	int i, ret;
    
    	for (i = 0; i < disp_kms->connectors_count; i++) {
    		struct connector *connector = &disp_kms->connector[i];
    		drmModeModeInfo *mode = connector->mode;
    
    		disp_kms->ovr[i] = drmModeGetPlane(disp->fd,
    					disp_kms->plane_resources->planes[1]);
    
    		ret = drmModeObjectSetProperty(disp->fd,
    			disp_kms->ovr[i]->plane_id, DRM_MODE_OBJECT_PLANE, 7, 3);
    		if (ret < 0) {
    			SVP_INFO("Could not set Z order for plane");
    			return ret;
    		}
    	}
    	return 0;
    }
    
    static int hide_vid_buffer_minigui(struct display *disp, struct buffer *buf,
    		uint32_t x, uint32_t y, uint32_t w, uint32_t h)
    {
    	//printf("hide_vid_buffer_c \n");
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	struct buffer_kms_minigui *buf_kms = to_buffer_kms(buf);
    	int ret = 0;
    	uint32_t i, j;
    	static int t = 0;
    	drmModeAtomicReq *req;
    	//SVP_INFO("####hide_vid_buffer_c####");
    	//if(traj_hide == 1)
    	//	return 0;
    
    	//g_pUtil->cache_flush(g_pUtil,buf->pa[0],w*h*1,FLUSH_CACHE_OP_CLEAN);
    	//g_pUtil->cache_flush(g_pUtil,buf->pa[1],(w/2)*(h/2)*2,FLUSH_CACHE_OP_CLEAN);
    	//CMEM_cacheInv(buf->vaddr, w*h*(32/8));
    
    	/* ensure we have the overlay setup: */
    	for (i = 0; i < disp_kms->connectors_count; i++) {
    		struct connector *connector = &disp_kms->connector[i];
    		drmModeModeInfo *mode = connector->mode;
    
    		if (! mode) {
    			continue;
    		}
    		if (! disp_kms->ovr[0]) {
    
    			for (j = 0; j < disp_kms->plane_resources->count_planes; j++) {
    				disp_kms->ovr[j] = drmModeGetPlane(disp->fd,
    						disp_kms->plane_resources->planes[j]);
    						if (!disp_kms->ovr[j]) {
    						SVP_INFO("could not get plane %i: %s",
    								disp_kms->plane_resources->planes[j], strerror(errno));
    						drmModeFreePlane(disp_kms->ovr[j]);
    						continue;
    						}					
    				
    			}
    		}
    		if (! disp_kms->ovr[0]) {
    			SVP_INFO("Could not find plane for crtc %d", connector->crtc);
    			ret = -1;
    			/* carry on and see if we can find at least one usable plane */
    			continue;
    		}
    
    		#if 0
    		drmModeObjectProperties *props;
            	props = drmModeObjectGetProperties(disp->fd, disp_kms->plane_resources->planes[1], DRM_MODE_OBJECT_PLANE);
    			
    
    		 req = drmModeAtomicAlloc();
    
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "FB_ID", 0);
    		//add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "FB_ID", buf_kms->fb_id);
    
    		if (t == 0)
    		{
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "CRTC_ID", connector->crtc);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "CRTC_X", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "CRTC_Y", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "CRTC_W", 1280);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "CRTC_H", 720);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "SRC_X", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "SRC_Y", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "SRC_W", 1280 << 16);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "SRC_H", 720 << 16);
    		add_property(disp->fd, req, props, disp_kms->ovr[1]->plane_id, "zorder", 2);
    		
    		    t = 1;
    		}
    		traj_fbid = buf_kms->fb_id;
    		traj_ok = 1;
    		traj_planeId = disp_kms->ovr[1]->plane_id;
    		
    		ret = drmModeAtomicCommit(disp->fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
    		//if (ret)
    		    drmModeAtomicFree(req);
    		#endif
    		minigui_fbid = 0;
    		minigui_ok = 1;
    		minigui_planeId = disp_kms->ovr[0]->plane_id;
    		mode_init = 0;
    		#if 0
    		//drmSetMaster(disp->fd);
    		ret = drmModeSetPlane(disp->fd, disp_kms->ovr[1]->plane_id,
    		connector->crtc, 0, 0,
    		/* make video fullscreen: */
    		0, 0, mode->hdisplay, mode->vdisplay,
    		/* source/cropping coordinates are given in Q16 */
    		x << 16, y << 16, w << 16, h << 16);
    
    		ret = drmModeObjectSetProperty(disp->fd, disp_kms->ovr[1]->plane_id,
    		DRM_MODE_OBJECT_PLANE,
    		G5_DRM_ZORDER, 0);
    		if (ret) {
    			SVP_ERROR("failed to enable plane %d: %s",
    					disp_kms->ovr[i]->plane_id, strerror(errno));
    		}
    		#endif
    		//drmDropMaster(disp->fd);
    	//	traj_hide = 1;
    	//	return 0;
    		
    	}
    
    	return ret;
    	
    }
    
    
    static int
    post_vid_buffer_minigui(struct display *disp, struct buffer *buf,
    		uint32_t x, uint32_t y, uint32_t w, uint32_t h)
    {
    	
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	struct buffer_kms_minigui *buf_kms = to_buffer_kms(buf);
    	int ret = 0;
    	uint32_t i, j;
    	drmModeAtomicReq *req;
    	
    	drmSetMaster(disp->fd);
    
    	//SVP_INFO("####post_vid_buffer_c####");
    	//if(traj_hide == 1)
    	//	return 0;
    
    	//g_pUtil->cache_flush(g_pUtil,buf->pa[0],w*h*1,FLUSH_CACHE_OP_CLEAN);
    	//g_pUtil->cache_flush(g_pUtil,buf->pa[1],(w/2)*(h/2)*2,FLUSH_CACHE_OP_CLEAN);
    	//CMEM_cacheInv(buf->vaddr, w*h*(32/8));
    
    	/* ensure we have the overlay setup: */
    	for (i = 0; i < disp_kms->connectors_count; i++) {
    		struct connector *connector = &disp_kms->connector[i];
    		drmModeModeInfo *mode = connector->mode;
    
    
    		if (! mode) {
    			continue;
    		}
    		if (! disp_kms->ovr[0]) {
    
    			for (j = 0; j < disp_kms->plane_resources->count_planes; j++) {
    				disp_kms->ovr[j] = drmModeGetPlane(disp->fd,
    						disp_kms->plane_resources->planes[j]);
    						if (!disp_kms->ovr[j]) {
    						SVP_INFO("could not get plane %i: %s",
    								disp_kms->plane_resources->planes[j], strerror(errno));
    						drmModeFreePlane(disp_kms->ovr[j]);
    						continue;
    						}					
    				
    			}
    		}
    		if (! disp_kms->ovr[0]) {
    			SVP_INFO("Could not find plane for crtc %d", connector->crtc);
    			ret = -1;
    			/* carry on and see if we can find at least one usable plane */
    			continue;
    		}
    		
    		if (mode_init == 0)
    		{
    		//set the plane properties once. No need to set these values every time
    		//with the display of frame. 
    		drmModeObjectProperties *props;
    		drmModeObjectProperties *props_crtc;
            	props = drmModeObjectGetProperties(disp->fd, disp_kms->plane_resources->planes[0], DRM_MODE_OBJECT_PLANE);
    		if(props == NULL)
    			return ret;
    		props_crtc = drmModeObjectGetProperties(disp->fd, connector->crtc, DRM_MODE_OBJECT_CRTC);
    		if(props_crtc == NULL)
    			return ret;
    		 req = drmModeAtomicAlloc();
    
    		add_property(disp->fd, req, props_crtc, connector->crtc, "trans-key-mode", 2);
    		add_property(disp->fd, req, props_crtc, connector->crtc, "trans-key", 0x00);
    		
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "FB_ID", buf_kms->fb_id);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "CRTC_ID", connector->crtc);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "CRTC_X", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "CRTC_Y", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "CRTC_W", 1280);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "CRTC_H", 720);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "SRC_X", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "SRC_Y", 0);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "SRC_W", 1280 << 16);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "SRC_H", 720 << 16);
    		add_property(disp->fd, req, props, disp_kms->ovr[0]->plane_id, "zorder", 3);
    		
    		ret = drmModeAtomicCommit(disp->fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
    		//if (ret)
    		    drmModeAtomicFree(req);
    
    		    mode_init = 1;
    		}
    	
    		//printf("##########diaosu :post_vid_buffer_c:  traj fb_id %d  ##########\n",buf_kms->fb_id);
    		//printf("##########diaosu :post_vid_buffer_c:  disp_kms->ovr[1]->plane_id %d ##########\n",disp_kms->ovr[1]->plane_id);
    		minigui_fbid = buf_kms->fb_id;
    		minigui_ok = 1;
    		minigui_planeId = disp_kms->ovr[0]->plane_id;
    		
    
    #if 0
    		//drmSetMaster(disp->fd);
    		if(buf->noScale) {
    			ret = drmModeSetPlane(disp->fd, disp_kms->ovr[1]->plane_id,
    				connector->crtc, buf_kms->fb_id, 0,
    				/* Use x and y as co-ordinates of overlay */
    				x, y, buf->width, buf->height,
    				/* Consider source x and y is 0 always */
    				0, 0, w << 16, h << 16);
    		} else {
    			ret = drmModeSetPlane(disp->fd, disp_kms->ovr[1]->plane_id,
    				connector->crtc, buf_kms->fb_id, 0,
    				/* make video fullscreen: */
    				0, 0, mode->hdisplay, mode->vdisplay,
    				/* source/cropping coordinates are given in Q16 */
    				x << 16, y << 16, w << 16, h << 16);
    		}
    		ret = drmModeObjectSetProperty(disp->fd, disp_kms->ovr[1]->plane_id,
    		DRM_MODE_OBJECT_PLANE,
    		G5_DRM_ZORDER, 2);
    		if (ret) {
    			SVP_ERROR("failed to enable plane %d: %s",
    					disp_kms->ovr[i]->plane_id, strerror(errno));
    		}
    #endif
    	}
    
    	return ret;
    }
    
    static void
    close_kms(struct display *disp)
    {
    	omap_device_del(disp->dev);
    	disp->dev = NULL;
    	if (used_planes) {
    		used_planes >>= 1;
    	}
    	if (--ndisplays == 0) {
    		close(global_fd);
    	}
    }
    
    static void
    connector_find_mode(struct display *disp, struct connector *c)
    {
    	struct display_kms_minigui *disp_kms = to_display_kms(disp);
    	drmModeConnector *connector;
    	int i, j;
    
    	/* First, find the connector & mode */
    	c->mode = NULL;
    	for (i = 0; i < disp_kms->resources->count_connectors; i++) {
    		connector = drmModeGetConnector(disp->fd,
    				disp_kms->resources->connectors[i]);
    
    		if (!connector) {
    			SVP_ERROR("could not get connector %i: %s",
    					disp_kms->resources->connectors[i], strerror(errno));
    			drmModeFreeConnector(connector);
    			continue;
    		}
    
    		if (!connector->count_modes) {
    			drmModeFreeConnector(connector);
    			continue;
    		}
    
    		if (connector->connector_id != c->id) {
    			drmModeFreeConnector(connector);
    			continue;
    		}
    
    		for (j = 0; j < connector->count_modes; j++) {
    			c->mode = &connector->modes[j];
    			if (!strcmp(c->mode->name, c->mode_str))
    				break;
    		}
    
    		/* Found it, break out */
    		if (c->mode)
    			break;
    
    		drmModeFreeConnector(connector);
    	}
    
    	if (!c->mode) {
    		SVP_ERROR("failed to find mode \"%s\"", c->mode_str);
    		return;
    	}
    
    	/* Now get the encoder */
    for (i = 0; i < connector->count_encoders; i++) {
    		c->encoder = drmModeGetEncoder(disp->fd,
    				connector->encoders[i]);
    
    		if (!c->encoder) {
    			ERROR("could not get encoder %i: %s",
    					disp_kms->resources->encoders[i], strerror(errno));
    			continue;
    		}
    
    		/* Take the fisrt one, if none is assigned */
    		if (!connector->encoder_id)
    		{
    			connector->encoder_id = c->encoder->encoder_id;
    		}
    
    		if (c->encoder->encoder_id  == connector->encoder_id) {
    			/* find the first valid CRTC if not assigned */
    			if (!c->encoder->crtc_id)
    			{
    				int k;
    				for (k = 0; k < disp_kms->resources->count_crtcs; ++k) {
    					/* check whether this CRTC works with the encoder */
    					if (!(c->encoder->possible_crtcs & (1 << k)))
    						continue;
    
    					c->encoder->crtc_id = disp_kms->resources->crtcs[k];
    					break;
    				}
    
    				if (!c->encoder->crtc_id)
    				{
    					ERROR("Encoder(%d): no CRTC found!\n", c->encoder->encoder_id);
    					drmModeFreeEncoder(c->encoder);
    					continue;
    				}
    			}
    			break;
    		}
    		drmModeFreeEncoder(c->encoder);
    	}
    
    	if (c->crtc == -1)
    		c->crtc = c->encoder->crtc_id;
    
    	/* and figure out which crtc index it is: */
    	for (i = 0; i < disp_kms->resources->count_crtcs; i++) {
    		if (c->crtc == (int)disp_kms->resources->crtcs[i]) {
    			c->pipe = i;
    			break;
    		}
    	}
    }
    
    static void
    disp_kms_usage(void)
    {
    	SVP_INFO("KMS Display Options:");
    	SVP_INFO("\t-1 \t\tforce single-plane buffers");
    	SVP_INFO("\t-t <tiled-mode>\t8, 16, 32, or auto");
    	SVP_INFO("\t-s <connector_id>:<mode>\tset a mode");
    	SVP_INFO("\t-s <connector_id>@<crtc_id>:<mode>\tset a mode");
    }
    
    struct display *
    disp_kms_miningui_open(int argc, char **argv)
    {
    	struct display_kms_minigui *disp_kms = NULL;
    	struct display *disp;
    	int i;
    	int ret;
    
    	disp_kms = calloc(1, sizeof(*disp_kms));
    	if (!disp_kms) {
    		SVP_ERROR("allocation failed");
    		goto fail;
    	}
    	disp = &disp_kms->base;
    
    	while(1)
    	{
    		if(global_fd == NULL)
    		{
    			usleep(10000);
    			continue;
    		}
    		else
    			break;
    	}
    
    	#if 0
    	if (!global_fd) {
    		global_fd = drmOpen("omapdrm", NULL);
    		if (global_fd < 0) {
    			SVP_ERROR("could not open drm device: %s (%d)", strerror(errno), errno);
    			goto fail;
    		}
    	}
    
    	disp->fd = global_fd;
    	ndisplays++;  /* increment the number of displays counter */
    
    	disp->dev = omap_device_new(disp->fd);
    	if (!disp->dev) {
    		SVP_ERROR("couldn't create device");
    		goto fail;
    	}
    	#endif
    	disp->fd = global_fd;
    	disp->dev = omap_device_new(disp->fd);
    	if (!disp->dev) {
    		SVP_ERROR("couldn't create device");
    		goto fail;
    	}
    
    
    	disp->get_buffers = get_buffers;
    	disp->get_vid_buffers_minigui = get_vid_buffers_minigui;
    	disp->post_buffer = post_buffer_minigui;
    	disp->post_vid_buffer_minigui = post_vid_buffer_minigui;
    	disp->hide_vid_buffer_minigui = hide_vid_buffer_minigui;
    	disp->close = close_kms;
    	disp->disp_free_buf = free_buffers ;
    	//disp->show_panel = show_panel;
    	//disp->hide_panel = hide_panel;
    	disp_kms->resources = drmModeGetResources(disp->fd);
    	if (!disp_kms->resources) {
    		SVP_ERROR("drmModeGetResources failed: %s", strerror(errno));
    		goto fail;
    	}
    
    	disp_kms->plane_resources = drmModeGetPlaneResources(disp->fd);
    	if (!disp_kms->plane_resources) {
    		SVP_ERROR("drmModeGetPlaneResources failed: %s", strerror(errno));
    		goto fail;
    	}
    
    	disp->multiplanar = true;
    	
    	ret = drmSetClientCap(disp->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
    	if (ret) {
    		ERROR("no atomic modesetting support: %s\n", strerror(errno));
    		return -1;
    	}
    	/* note: set args to NULL after we've parsed them so other modules know
    	 * that it is already parsed (since the arg parsing is decentralized)
    	 */
    	for (i = 1; i < argc; i++) {
    		if (!argv[i]) {
    			continue;
    		}
    		if (!strcmp("-1", argv[i])) {
    			disp->multiplanar = false;
    		} else if (!strcmp("-t", argv[i])) {
    			int n;
    			argv[i++] = NULL;
    			if (!strcmp(argv[i], "auto")) {
    				n = 0;
    			} else if (sscanf(argv[i], "%d", &n) != 1) {
    				SVP_ERROR("invalid arg: %s", argv[i]);
    				goto fail;
    			}
    
    			disp_kms->bo_flags &= ~OMAP_BO_TILED;
    
    			if (n == 8) {
    				disp_kms->bo_flags |= OMAP_BO_TILED_8;
    			} else if (n == 16) {
    				disp_kms->bo_flags |= OMAP_BO_TILED_16;
    			} else if (n == 32) {
    				disp_kms->bo_flags |= OMAP_BO_TILED_32;
    			} else if (n == 0) {
    				disp_kms->bo_flags |= OMAP_BO_TILED;
    			} else {
    				SVP_ERROR("invalid arg: %s", argv[i]);
    				goto fail;
    			}
    		} else if (!strcmp("-s", argv[i])) {
    			struct connector *connector =
    					&disp_kms->connector[disp_kms->connectors_count++];
    			connector->crtc = -1;
    			argv[i++] = NULL;
    			if (sscanf(argv[i], "%d:%64s",
    				   &connector->id,
    				   connector->mode_str) != 2 &&
    			    sscanf(argv[i], "%d@%d:%64s",
    				   &connector->id,
    				   &connector->crtc,
    				   connector->mode_str) != 3) {
    				// TODO: we could support connector specified as a name too, I suppose
    				SVP_ERROR("invalid arg: %s", argv[i]);
    				goto fail;
    			}
    			disp_kms->bo_flags |= OMAP_BO_SCANOUT;
    		} else {
    			/* ignore */
    			continue;
    		}
    		argv[i] = NULL;
    	}
    	debug_hal_info.minigui_find_mode = 1;
    	disp->width = 0;
    	disp->height = 0;
    	for (i = 0; i < (int)disp_kms->connectors_count; i++) {
    		struct connector *c = &disp_kms->connector[i];
    		connector_find_mode(disp, c);
    		if (c->mode == NULL)
    			continue;
    		/* setup side-by-side virtual display */
    		disp->width += c->mode->hdisplay;
    		if (disp->height < c->mode->vdisplay) {
    			disp->height = c->mode->vdisplay;
    		}
    	}
    	debug_hal_info.minigui_mode_width = disp->width;
    	debug_hal_info.minigui_mode_height = disp->height;
    	SVP_INFO("using %d connectors, %dx%d display, multiplanar: %d",
    			disp_kms->connectors_count, disp->width, disp->height, disp->multiplanar);
    
    	return disp;
    
    fail:
    	// XXX cleanup
    	return NULL;
    }
    

    Thanks,

    Fumao

  • Hi Kedar Chitnis,

       I upgraded cmem to version 4.14.01.00 and still reported cmem error:

    72783.35> [    3.638597] Unable to handle kernel NULL pointer dereference at virtual address 00000024
    72783.37> [    3.672303] pgd = f59a0b40
    72783.43> [    3.685652] [00000024] *pgd=b570a003, *pmd=b4925003, *pte=00000000
    72783.43> [    3.698791] Internal error: Oops: 207 [#1] PREEMPT SMP ARM
    72783.43> [    3.704298] Modules linked in: dwc3(+) udc_core dwc3_omap extcon texfat(PO) tfat(PO) cmemk(O) memcache(O) pvrsrvkm(O)
    72783.43> [    3.715037] CPU: 1 PID: 316 Comm: avm3d_service Tainted: P           O    4.4.45+ #4
    72783.43> [    3.722810] Hardware name: Generic DRA74X (Flattened Device Tree)
    72783.43> [    3.728929] task: df8c2d00 ti: d7e7a000 task.ti: d7e7a000
    72783.43> [    3.734358] PC is at cmem_dmabuf_export+0x14/0x140 [cmemk]
    72783.48> [    3.739869] LR is at ioctl+0x154/0x1504 [cmemk]
    72783.48> [    3.744416] pc : [<bf07315c>]    lr : [<bf0743a0>]    psr: 60080013
    72783.48> [    3.744416] sp : d7e7be48  ip : d7e7bea0  fp : d7e7be9c
    72783.48> [    3.755940] r10: bf0795f4  r9 : 988fecc8  r8 : bf079590
    72783.48> [    3.761184] r7 : bf0779bc  r6 : 00000001  r5 : 00000800  r4 : 00000000
    72783.48> [    3.767735] r3 : 00000000  r2 : bce00000  r1 : 00000002  r0 : 00000000
    72783.48> [    3.774287] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
    72783.53> [    3.781451] Control: 30c5387d  Table: b59a0b40  DAC: 55555555
    72783.53> [    3.787218] Process avm3d_service (pid: 316, stack limit = 0xd7e7a210)
    72783.53> [    3.793770] Stack: (0xd7e7be48 to 0xd7e7c000)
    72783.53> [    3.798144] be40:                   97621000 f631d720 f575f240 00000003 d7e7be9c d7e7be68
    72783.53> [    3.806355] be60: bf073760 c00f0748 d7e7beb4 d7e7be78 c02a56f8 ffe36000 00000800 00000001
    72783.53> [    3.814565] be80: bf0779bc bf079590 988fecc8 bf0795f4 d7e7bf14 d7e7bea0 bf0743a0 bf073154
    72783.57> [    3.822776] bea0: d7e7bf80 00000000 d7e7bedc d7e7beb8 d7e7bed8 c02a55c8 f5900e40 c02a5868
    72783.57> [    3.830987] bec0: 0000001f d7e7bf80 c000fbc4 00000000 d7e7bf4c d7e7bee0 97621000 988fecd8
    72783.57> [    3.839197] bee0: d7e7bf2c d7e7bef0 c00f3668 988fecc8 f631d720 f575f240 00000003 988fecc8
    72783.57> [    3.847408] bf00: d7e7a000 00000000 d7e7bf7c d7e7bf18 c011f848 bf074258 00000000 00000000
    72783.57> [    3.855619] bf20: f575f240 00004000 d7e7bf5c d7e7bf38 c0129a54 c0081778 b683b118 00000003
    72783.57> [    3.863829] bf40: 97621000 0000fe0d 988fecc8 d7e7a000 d7e7bf6c f575f241 00000003 f575f240
    72783.62> [    3.872040] bf60: 0000fe0d 988fecc8 d7e7a000 00000000 d7e7bfa4 d7e7bf80 c011faa8 c011f464
    72783.62> [    3.880250] bf80: b683b118 97621000 97621000 00000036 c000fbc4 d7e7a000 00000000 d7e7bfa8
    72783.62> [    3.888461] bfa0: c000fa20 c011fa78 b683b118 97621000 00000003 0000fe0d 988fecc8 b683b184
    72783.62> [    3.896672] bfc0: b683b118 97621000 97621000 00000036 00d2c400 000002d0 00000001 00000002
    72783.62> [    3.904882] bfe0: b683b13c 988fecc4 b682a209 b669b4d6 00080030 00000003 1288c2b4 c0200010
    72783.62> [    3.913089] Backtrace:
    72783.67> [    3.915560] [<bf073148>] (cmem_dmabuf_export [cmemk]) from [<bf0743a0>] (ioctl+0x154/0x1504 [cmemk])
    72783.67> [    3.924727]  r10:bf0795f4 r9:988fecc8 r8:bf079590 r7:bf0779bc r6:00000001 r5:00000800
    72783.67> [    3.932629]  r4:ffe36000
    72783.67> [    3.935187] [<bf07424c>] (ioctl [cmemk]) from [<c011f848>] (do_vfs_ioctl+0x3f0/0x614)
    72783.67> [    3.943046]  r10:00000000 r9:d7e7a000 r8:988fecc8 r7:00000003 r6:f575f240 r5:f631d720
    72783.67> [    3.950945]  r4:988fecc8
    72783.67> [    3.953498] [<c011f458>] (do_vfs_ioctl) from [<c011faa8>] (SyS_ioctl+0x3c/0x64)
    72783.70> [    3.960835]  r10:00000000 r9:d7e7a000 r8:988fecc8 r7:0000fe0d r6:f575f240 r5:00000003
    72783.70> [    3.968733]  r4:f575f241
    72783.70> [    3.971287] [<c011fa6c>] (SyS_ioctl) from [<c000fa20>] (ret_fast_syscall+0x0/0x34)
    72783.70> [    3.978884]  r9:d7e7a000 r8:c000fbc4 r7:00000036 r6:97621000 r5:97621000 r4:b683b118
    72783.70> [    3.986697] Code: e92ddff0 e24cb004 e24dd02c e1a04000 (e5945024)

    Thanks

    Fumao