/* Function to register the AF character device driver. */ int __init af_init(void) { int err; int result = 0; result = AF_GET_CCDC_FMTCFG; result = result & AF_VPEN_MASK; result = result >> AF_FMTCG_VPEN; /* H3A Module cannot be inserted if CCDC path for H3A is not registered */ if (!(result)) { /* Module cannot be inserted if CCDC is not configured */ printk("\n Davinci AF driver cannot be loaded"); printk("\n VIDEO PORT is not enabled "); printk("\n CCDC needs to be configured"); return -1; } /*Register the driver in the kernel. Get major number dynamically */ result = alloc_chrdev_region(&dev, AF_MAJOR_NUMBER, AF_NR_DEVS, DEVICE_NAME); if (result < 0) { printk("Error : Could not register character device"); return -ENODEV; } /*allocate memory for device structure and initialize it with 0 */ af_dev_configptr = (struct af_device *)kmalloc(sizeof(struct af_device), GFP_KERNEL); if (!af_dev_configptr) { printk("Error : kmalloc fail"); unregister_chrdev_region(dev, AF_NR_DEVS); return -ENOMEM; } /* Initialize character device */ cdev_init(&c_dev, &af_fops); c_dev.owner = THIS_MODULE; c_dev.ops = &af_fops; err = cdev_add(&c_dev, dev, 1); if (err) { printk("Error : Error in Adding Davinci AF"); unregister_chrdev_region(dev, AF_NR_DEVS); if (af_dev_configptr) kfree(af_dev_configptr); return -err; } /* Registe Character device */ register_chrdev(MAJOR(dev), DEVICE_NAME, &af_fops); /* register driver as a platform driver */ if (driver_register(&af_driver) != 0) { unregister_chrdev_region(dev, 1); cdev_del(&c_dev); return -EINVAL; } /* Register the drive as a platform device */ if (platform_device_register(&afdevice) != 0) { driver_unregister(&af_driver); unregister_chrdev_region(dev, 1); unregister_chrdev(MAJOR(dev), DEVICE_NAME); cdev_del(&c_dev); return -EINVAL; } af_class = class_create(THIS_MODULE, "davinci_af"); if (!af_class) { platform_device_unregister(&afdevice); printk("Error : Error in creating device class"); unregister_chrdev_region(dev, AF_NR_DEVS); if (af_dev_configptr) kfree(af_dev_configptr); cdev_del(&c_dev); return -EIO; } class_device_create(af_class, NULL, dev, NULL, "davinci_af"); /* Set up the Interrupt handler for H3AINT interrupt */ result = vpss_request_irq(VPSS_H3AINT, af_isr, SA_SHIRQ, "dm644xh3a_af", (void *)af_dev_configptr); if (result != 0) { printk("Error : Request IRQ Failed"); unregister_chrdev_region(dev, AF_NR_DEVS); if (af_dev_configptr) kfree(af_dev_configptr); class_device_destroy(af_class, dev); driver_unregister(&af_driver); platform_device_unregister(&afdevice); class_destroy(af_class); cdev_del(&c_dev); unregister_chrdev(MAJOR(dev), DEVICE_NAME); return result; } /* Initialize device structure */ memset(af_dev_configptr, 0, sizeof(struct af_device)); af_dev_configptr->in_use = AF_NOT_IN_USE; af_dev_configptr->buffer_filled = 0; return 0; /*Sucess */ }
static void __exit mod_exit(void) { struct list_head *u; struct list_head *unext; struct list_head *registeredlistp; struct registered_user *user; int found_user; int i; #ifdef USE_CLASS_SIMPLE class_simple_device_remove(MKDEV(major, 0)); class_simple_destroy(dma_class); #else #ifdef USE_CLASS_DEVICE class_device_destroy(dma_class, MKDEV(major, 0)); #else device_destroy(dma_class, MKDEV(major, 0)); #endif // USE_CLASS_DEVICE class_destroy(dma_class); #endif // USE_CLASS_SIMPLE unregister_chrdev(major, "edma"); /* * Free all "owned" channels now. They're supposed to get either * explicitly freed, or auto-freed when the file descriptor for * this device driver is closed by a process (which itself might happen * during auto-close if the process doesn't explicitly close the file * descriptor), but a process might crash or otherwise not get to the * auto-close point. The following code will run when the module is * removed from the kernel (w/ rmmod). */ for (i = 0; i < NCHAN; i++) { found_user = 0; if (mutex_lock_interruptible(&edma_mutex)) { return; } registeredlistp = &channels[i].users; u = registeredlistp->next; while (u != registeredlistp) { found_user = 1; unext = u->next; user = list_entry(u, struct registered_user, element); list_del(u); kfree(user); u = unext; } if (found_user) { release_channel(i); } mutex_unlock(&edma_mutex); } __D("edma unregistered\n"); }