UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Contributor
Contributor
224 Views
Registered: ‎11-23-2017

Linux VDMA Drivers Not working

Jump to solution

Hello !

I have interfaced CMOS camera with my zynq7020 custom board. I can read the video frames over HDMI port. The vivado hardware design is working fine. I wrote bare-metal drivers in SDK. The system works well.

But now i want to run the system using Linux kernel modulei wrote . but it does not work . 

here is my Linux drivers and bare-metal drivers . With Bare-metal drivers , i can see the video output over HDMI .

First Bare-metal Drivers


int main ()
{
	unsigned int i=0;
   print("---Entering main---\n\r");

      print("\r\n Running AxiVDMASelfTestExample() for axi_vdma_0...\r\n");
   for(i=0;i<1280*720*3;i++){
   Xil_Out8((VIDEO_BASEADDR0 + i), 0);
   Xil_Out8((VIDEO_BASEADDR1 + i+1), 0x00);
   Xil_Out8((VIDEO_BASEADDR2 + i+2), 0x00);
   }

 //  iic_config_init();   //Remove comments for camera output resolution at 640 x 480


   Xil_Out32((FILTER_BASEADDR + 0x010),480);
   Xil_Out32((FILTER_BASEADDR + 0x018),752);
   Xil_Out32((FILTER_BASEADDR + 0x00),129);
   //Default camera Resolution is 752 x 480

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   //AXI VDMA S2MM REGISTERS
  Xil_Out32((VDMA_BASEADDR + 0x030), 0x08B);// enable circular mode
   Xil_Out32((VDMA_BASEADDR + 0x03C), 0x0F);
   Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0); // start address
   Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1); // start address
   Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2); // start address
   Xil_Out32((VDMA_BASEADDR + 0x0A8), (1280*3)); //	Screen Resolution Horizontal Length
   Xil_Out32((VDMA_BASEADDR + 0x0A4), (1280*3)); //
   Xil_Out32((VDMA_BASEADDR + 0x0A0),720); //

//AXI VDMA MM2S REGISTERS
   Xil_Out32((VDMA_BASEADDR + 0x000), 0x03); // enable circular mode
   Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); // start address
   Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1); // start address
   Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2); // start address
   Xil_Out32((VDMA_BASEADDR + 0x058), (1280*3)); // 1280 X 720 Resolution
   Xil_Out32((VDMA_BASEADDR + 0x054), (1280*3)); //
   Xil_Out32((VDMA_BASEADDR + 0x050), 720); //


   return 0;
}

Now Equivalent Linux Drivers . ) No Video Output . 

#define DEVICE_NAME   			"AXI_VDMA_DEVICE"
#define CLASS_NAME    			"axi_vdma"
#define VDMA_BASE	 	         0x43000000
//MM2S Registers
#define MM2S_VDMACR                 0x00
#define MM2S_VDMASR                 0x4
#define MM2S_VSIZE                  0x50
#define MM2S_HSIZE                  0x54
#define MM2S_FRMDLY_STRIDE          0x58
#define MM2S_START_ADDRESS0         0x5C
#define MM2S_START_ADDRESS1         0x60
#define MM2S_START_ADDRESS2         0x64
//S2MM Registers
#define S2MM_VDMACR                 0x30
#define S2MM_VDMASR                 0x34
#define S2MM_VSIZE                  0xA0
#define S2MM_HSIZE                  0xA4
#define S2MM_FRMDLY_STRIDE          0xA8
#define S2MM_START_ADDRESS0         0xAC
#define S2MM_START_ADDRESS1         0xB0
#define S2MM_START_ADDRESS2         0xB4

//Frame Buffer Address on DDR (Physical Addresses)
#define Frame_Buffer_Addr0		   	     		//
#define Frame_Buffer_Addr1
#define Frame_Buffer_Addr2

//IMAGE FILTER Physical Addresses
#define IMAGE_FILTER_BASE       0x43C00000
#define IMAGE_FILTER_CONTROL    0x00
#define IMAGE_FILTER_ROWS       0x10
#define IMAGE_FILTER_COLS       0x18


MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harry-SJTU");
MODULE_DESCRIPTION("A simple Linux driver for the AXI VDMA.");
MODULE_VERSION("1.0");

static void __iomem *vdma_virt_addr;
static void __iomem *virt_frame_buf_addr;
static void __iomem *image_filter_virt_addr;
unsigned int  length;
static int    message[1024] = {0};
static int    majorNumber;

static struct class*  axivdmaclass  = NULL;
static struct device* axivdmaDevice = NULL;
static int     axi_vdma_open(struct inode *, struct file *);
static int     axi_vdma_release(struct inode *, struct file *);
static ssize_t axi_vdma_read(struct file *, char *, size_t, loff_t *);
static ssize_t axi_vdma_write(struct file *, const char *, size_t, loff_t *);

static int axi_vdma_open(struct inode *inodep, struct file *filep){
   printk(KERN_INFO "AXI VDMA: Device has been opened time(s)\n");
   return 0;
}

static struct file_operations axi_vdma={
.owner=THIS_MODULE,
.open=axi_vdma_open,
.release=axi_vdma_release,
.read=axi_vdma_read,
.write=axi_vdma_write,
};

static int __init axi_vdma_init(void){
// Try to dynamically allocate a major number for the device -- more difficult but worth it
   majorNumber = register_chrdev(0, DEVICE_NAME, &axi_vdma);
   if (majorNumber<0){
      printk(KERN_ALERT "axivdma failed to register a major number\n");
      return majorNumber;
   }
   printk(KERN_INFO "axivdma: registered correctly with major number %d\n", majorNumber);


   // Register the device class
   axivdmaclass = class_create(THIS_MODULE, CLASS_NAME);
   if (IS_ERR(axivdmaclass)){                // Check for error and clean up if there is
      unregister_chrdev(majorNumber, DEVICE_NAME);
      printk(KERN_ALERT "Failed to register device class\n");
      return PTR_ERR(axivdmaclass);          // Correct way to return an error on a pointer
   }

   // Register the device driver
   axivdmaDevice= device_create(axivdmaclass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
   if (IS_ERR(axivdmaDevice)){               // Clean up if there is an error
      class_destroy(axivdmaclass);           // Repeated code but the alternative is goto statements
      unregister_chrdev(majorNumber, DEVICE_NAME);
      printk(KERN_ALERT "Failed to create the device\n");
      return PTR_ERR(axivdmaDevice);
   }

   printk(KERN_INFO "axivdma: device class registered correctly\n");

//request memory region on DDR for Frame Buffers

if(request_mem_region(0x10000000,0x1000000,"axi_vdma_memory")==NULL){
printk("failed to request memory region\n");
}

//MAP Frame BUFFER Memory  (Could be DDR/OCM)
virt_frame_buf_addr = ioremap_nocache(0x10000000,0x1000000);

       if (!virt_frame_buf_addr ) {
                printk("Could not map physical memory to virtual\n");
                return -1;
        }

//INITIALIZE FRAME BUFFER MEMORY TO ZERO
memset_io(virt_frame_buf_addr,0x0,0x1000000);

printk("Frame buffer initialized");

	//MAP AXI IMAGE FILTER BASE ADDRESS
image_filter_virt_addr=ioremap_nocache(IMAGE_FILTER_BASE,124);

if (!image_filter_virt_addr) {
               printk("Could not map Image Filter \n");
               return -1;
        }

iowrite32(129,(void __iomem *)(image_filter_virt_addr + IMAGE_FILTER_CONTROL));

iowrite32(752,(void __iomem *)(image_filter_virt_addr + IMAGE_FILTER_COLS));

iowrite32(480,(void __iomem *)(image_filter_virt_addr + IMAGE_FILTER_ROWS));
//MAP AXI VDMA BASE ADDRESS
vdma_virt_addr=ioremap_nocache(VDMA_BASE,65535);

if (!vdma_virt_addr) {
               printk("Could not map AXI VDMA\n");
               return -1;
        }
// MM2S Registers Configurations

        //START MM2S VDMA
	iowrite32(0x03,(void __iomem *)(vdma_virt_addr + MM2S_VDMACR));
	printk("MM2S CONTROL REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_VDMACR)));

    //Frame Buffer Addr0
    iowrite32(0x10000000,(void __iomem *)(vdma_virt_addr + MM2S_START_ADDRESS0));
	printk("Frame Buffer0 REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_START_ADDRESS0)));

	//Frame Buffer Addr1
	iowrite32(0x102A3000,(void __iomem *)(vdma_virt_addr + MM2S_START_ADDRESS1));
	printk("Frame Buffer1 REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_START_ADDRESS1)));

	//Frame Buffer Addr2
	iowrite32(0x10546000,(void __iomem *)(vdma_virt_addr + MM2S_START_ADDRESS2));
	printk("Frame Buffer2 REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_START_ADDRESS2)));

    //Stride
	iowrite32(1280*3,(void __iomem *)(vdma_virt_addr + MM2S_FRMDLY_STRIDE));
	printk("MM2S Stride REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_FRMDLY_STRIDE)));

    //HSIZE
	iowrite32(1280*3,(void __iomem *)(vdma_virt_addr + MM2S_HSIZE));
	printk("MM2S HSIZE REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_HSIZE)));

    //VSIZE
	iowrite32(720*3,(void __iomem *)(vdma_virt_addr + MM2S_VSIZE));
	printk("MM2S VSIZE REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_VSIZE)));

	// S2MM Registers Configurations

        //START S2MM VDMA
	iowrite32(0x8B,(void __iomem *)(vdma_virt_addr + S2MM_VDMACR));
	printk("S2MM CONTROL REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_VDMACR)));

    //Frame Buffer Addr0
    iowrite32(0x10000000,(void __iomem *)(vdma_virt_addr + S2MM_START_ADDRESS0));
	printk("Frame Buffer0 REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_START_ADDRESS0)));

	//Frame Buffer Addr1
	iowrite32(0x102A3000,(void __iomem *)(vdma_virt_addr + S2MM_START_ADDRESS1));
	printk("Frame Buffer1 REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_START_ADDRESS1)));

	//Frame Buffer Addr2
	iowrite32(0x10546000,(void __iomem *)(vdma_virt_addr + S2MM_START_ADDRESS2));
	printk("Frame Buffer2  REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_START_ADDRESS2)));

    //Stride
	iowrite32(1280*3,(void __iomem *)(vdma_virt_addr + S2MM_FRMDLY_STRIDE));
	printk("S2MM Stride REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_FRMDLY_STRIDE)));

    //HSIZE
	iowrite32(1280*3,(void __iomem *)(vdma_virt_addr + S2MM_HSIZE));
	printk("S2MM HSIZE REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_HSIZE)));

    //VSIZE
	iowrite32(720*3,(void __iomem *)(vdma_virt_addr + MM2S_VSIZE));
	printk("S2MM VSIZE REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_VSIZE)));


	printk("MM2S STATUS REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + MM2S_VDMASR)));
	printk("S2MM STATUS REGISTER %d\n", ioread32((void __iomem *)(vdma_virt_addr + S2MM_VDMASR)));

return 0;

}

//Read Function
static ssize_t axi_vdma_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
    return 0;

}
//Write Function
static ssize_t axi_vdma_read(struct file *filep, char *buffer, size_t len, loff_t *offset){

    return 0;

}

static int axi_vdma_release(struct inode *inodep, struct file *filep){
  printk(KERN_INFO "AXI VDMA: Device successfully closed\n");
  return 0;
}

static void __exit axi_vdma_exit(void){
	device_destroy(axivdmaclass, MKDEV(majorNumber, 0));     // remove the device
   	class_unregister(axivdmaclass);                          // unregister the device class
   	class_destroy(axivdmaclass);                             // remove the device class
   	unregister_chrdev(majorNumber, DEVICE_NAME);             // unregister the major num
	release_mem_region(0x10000000 ,0x1000000);
        printk(KERN_INFO "AXI VDMA Exit\n");
}
module_init(axi_vdma_init);
module_exit(axi_vdma_exit);

Please help to figure out why i can't see the output with my Linux drivers when i run modprobe camera.ko 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Contributor
Contributor
192 Views
Registered: ‎11-23-2017

Re: Linux VDMA Drivers Not working

Jump to solution

there is no node on device tree about HDMI. other video pipe-line components such as Video-In to AXI4 Stream etc. is also not described. becasue it does not take any configurations from CPU . so, HDMI also does not need take any configrutaions/ commands to run. 

0 Kudos
4 Replies
Scholar watari
Scholar
214 Views
Registered: ‎06-16-2013

Re: Linux VDMA Drivers Not working

Jump to solution

Hi @haroonrl123 

 

Did you use kernel module of HDMI Tx in linux ?

If yes, would you share the result of the following command on linux ?

 

$ ls /sys/devices/platform/amba_pl@0/<your HDMI Tx SS>

 

Best regards,

0 Kudos
Contributor
Contributor
211 Views
Registered: ‎11-23-2017

Re: Linux VDMA Drivers Not working

Jump to solution

No . I haven't used HDMI TX module. i am using custom HDMI IP in my hardware design which works and does not need any on-fly configuration. why do i need HDM Tx drivers ?

0 Kudos
Scholar watari
Scholar
205 Views
Registered: ‎06-16-2013

Re: Linux VDMA Drivers Not working

Jump to solution

Hi @haroonrl123 

 

It's my misunderstanding about HDMI Tx.

Did you describe about this driver in device tree blob ?

 

Best regards,

0 Kudos
Highlighted
Contributor
Contributor
193 Views
Registered: ‎11-23-2017

Re: Linux VDMA Drivers Not working

Jump to solution

there is no node on device tree about HDMI. other video pipe-line components such as Video-In to AXI4 Stream etc. is also not described. becasue it does not take any configurations from CPU . so, HDMI also does not need take any configrutaions/ commands to run. 

0 Kudos