2 * Copyright (c) 2014 Spreadtrum Communications, Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
18 #include <drm/sprd_drm.h>
20 #include <linux/of_irq.h>
23 #include "sprd_drm_drv.h"
24 #include "sprd_drm_gem.h"
25 #ifdef CONFIG_DRM_SPRD_DMABUF
26 #include "sprd_drm_dmabuf.h"
28 #include "sprd_drm_irq.h"
29 #include "sprd_drm_ipp.h"
31 #include <video/ion_sprd.h>
33 #include <soc/sprd/cpuidle.h>
35 #define DRIVER_NAME "sprd"
36 #define DRIVER_DESC "SPRD SoC DRM"
37 #define DRIVER_DATE "2014"
38 #define DRIVER_MAJOR 1
39 #define DRIVER_MINOR 0
41 #define VBLANK_OFF_DELAY 500
43 struct sprd_drm_gem_info_data {
44 struct drm_file *filp;
48 static int sprd_drm_gem_one_info(int id, void *ptr, void *data)
50 struct drm_gem_object *obj = (struct drm_gem_object *)ptr;
51 struct sprd_drm_gem_info_data *gem_info_data = data;
52 struct pid *pid = gem_info_data->filp->pid;
53 struct drm_sprd_file_private *file_priv =
54 gem_info_data->filp->driver_priv;
55 struct sprd_drm_gem_obj *sprd_gem;
56 struct sprd_drm_gem_buf *buf;
59 DRM_ERROR("failed to get drm_gem_object\n");
63 drm_gem_object_reference(obj);
65 sprd_gem = to_sprd_gem_obj(obj);
66 buf = sprd_gem->buffer;
68 seq_printf(gem_info_data->m,
69 "%5d\t%5d\t%4d\t%4d\t\t%4d\t0x%08lx\t0x%x\t%4d\t%4d\t\t"
74 atomic_read(&obj->refcount.refcount) - 1,
75 atomic_read(&obj->handle_count),
79 obj->export_dma_buf ? 1 : 0,
80 obj->import_attach ? 1 : 0,
84 drm_gem_object_unreference(obj);
89 static int sprd_drm_gem_info(struct seq_file *m, void *data)
91 struct drm_info_node *node = (struct drm_info_node *)m->private;
92 struct drm_device *drm_dev = node->minor->dev;
93 struct sprd_drm_gem_info_data gem_info_data;
96 seq_puts(gem_info_data.m,
97 "pid\ttgid\thandle\trefcount\thcount\tsize\t\tflags\t"
98 "pfnmap\texport_to_fd\timport_from_fd\tobj_addr\t"
100 mutex_lock(&drm_dev->struct_mutex);
102 list_for_each_entry(gem_info_data.filp, &drm_dev->filelist, lhead) {
103 spin_lock(&gem_info_data.filp->table_lock);
104 idr_for_each(&gem_info_data.filp->object_idr,
105 sprd_drm_gem_one_info, &gem_info_data);
106 spin_unlock(&gem_info_data.filp->table_lock);
109 mutex_unlock(&drm_dev->struct_mutex);
114 static struct drm_info_list sprd_drm_debugfs_list[] = {
115 {"gem_info", sprd_drm_gem_info, DRIVER_GEM},
117 #define SPRD_DRM_DEBUGFS_ENTRIES ARRAY_SIZE(sprd_drm_debugfs_list)
119 static struct notifier_block sprd_drm_cpu_idle_notifier = {
120 .notifier_call = sprd_drm_cpuidle_notify,
123 static DEVICE_ATTR(vblank_freq, S_IRUGO | S_IWUSR, sprd_drm_vblank_freq_show,
124 sprd_drm_vblank_freq_store);
126 static struct attribute *sprd_drm_vblank_freq_attrs[] = {
127 &dev_attr_vblank_freq.attr,
131 struct attribute_group sprd_drm_vblank_freq_attrs_group = {
132 .attrs = sprd_drm_vblank_freq_attrs,
135 static int sprd_drm_load(struct drm_device *dev, unsigned long flags)
137 struct sprd_drm_private *private;
138 struct platform_device *pdev;
140 struct resource *res;
142 struct drm_minor *minor;
143 #ifdef CONFIG_DRM_DPMS_IOCTL
144 struct sprd_drm_dpms_work *dpms_work;
148 minor = dev->primary;
150 DRM_DEBUG_DRIVER("%s\n", __FILE__);
152 pdev = dev->driver->kdriver.platform_device;
154 DRM_ERROR("failed to get platform device.\n");
158 private = devm_kzalloc(&pdev->dev, sizeof(*private), GFP_KERNEL);
160 DRM_ERROR("failed to alloc dev private data.\n");
164 INIT_LIST_HEAD(&private->pageflip_event_list);
165 dev->dev_private = (void *)private;
167 private->sprd_drm_ion_client = sprd_ion_client_create("drm");
168 if (!private->sprd_drm_ion_client) {
169 DRM_ERROR("Unable to create ION client\n");
174 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sprdfb");
176 DRM_ERROR("failed to get DISPC base address\n");
180 private->reg_size = resource_size(res);
181 private->regs = devm_ioremap(&pdev->dev, res->start,
183 if (unlikely(!private->regs)) {
184 DRM_ERROR("failed to map DISPC base\n");
188 private->irq = platform_get_irq_byname(pdev, "sprd_drm_irq");
190 private->irq = platform_get_irq(pdev, 1);
192 if (private->irq <= 0)
193 DRM_ERROR("interrupt not registered\n");
195 private->drm_dev = dev;
197 private->nb_ctrl.notifier_call = sprd_drm_notifier_ctrl;
198 if (sprdfb_nb_register(&private->nb_ctrl))
199 pr_err("could not register sprd_fb notify callback\n");
201 /* init workqueue for fake vsync */
202 INIT_WORK(&private->fake_vbl_work,
203 sprd_drm_fake_vblank_handler);
204 private->fake_vbl_hz = VBLANK_DEF_HZ;
205 private->vbl_itv_us = (unsigned long int)(VBLANK_INTERVAL(VBLANK_DEF_HZ));
206 ret = sysfs_create_group(&dev->dev->kobj, &sprd_drm_vblank_freq_attrs_group);
208 pr_err("sysfs group creation failed, ret = %d\n", ret);
210 drm_mode_config_init(dev);
211 ret = drm_vblank_init(dev, MAX_CRTC);
216 * probe sub drivers such as display controller and hdmi driver,
217 * that were registered at probe() of platform driver
218 * to the sub driver and create encoder and connector for them.
220 ret = sprd_drm_device_register(dev);
224 dev->vblank_disable_allowed = 1;
225 drm_vblank_offdelay = VBLANK_OFF_DELAY;
226 minor = dev->primary;
227 ret = drm_debugfs_create_files(sprd_drm_debugfs_list,
228 SPRD_DRM_DEBUGFS_ENTRIES,
229 minor->debugfs_root, minor);
231 DRM_DEBUG_DRIVER("failed to create sprd-drm debugfs.\n");
233 #ifdef CONFIG_DRM_DPMS_IOCTL
234 dpms_work = kzalloc(sizeof(*dpms_work), GFP_KERNEL);
236 DRM_ERROR("failed to alloc dpms_work.\n");
240 dpms_work->private = private;
241 private->dpms_work = dpms_work;
242 INIT_WORK((struct work_struct *)private->dpms_work,
243 sprd_drm_dpms_work_ops);
245 init_completion(&private->dpms_comp);
246 mutex_init(&private->dpms_lock);
249 if (register_sc_cpuidle_notifier(&sprd_drm_cpu_idle_notifier))
250 DRM_ERROR("failed to setup light sleep notifier\n");
254 #ifdef CONFIG_DRM_DPMS_IOCTL
256 sprd_drm_device_unregister(dev);
259 drm_vblank_cleanup(dev);
261 drm_mode_config_cleanup(dev);
267 static int sprd_drm_unload(struct drm_device *dev)
269 struct sprd_drm_private *private =
270 (struct sprd_drm_private *)dev->dev_private;
272 DRM_DEBUG_DRIVER("%s\n", __FILE__);
274 if (unregister_sc_cpuidle_notifier(&sprd_drm_cpu_idle_notifier))
275 DRM_ERROR("failed to unset light sleep notifier\n");
277 #ifdef CONFIG_DRM_DPMS_IOCTL
278 kfree(private->dpms_work);
281 sprdfb_nb_unregister(&private->nb_ctrl);
283 #ifdef CONFIG_DRM_SPRD_KMS
284 sprd_drm_fbdev_fini(dev);
286 sprd_drm_device_unregister(dev);
287 drm_vblank_cleanup(dev);
288 #ifdef CONFIG_DRM_SPRD_KMS
289 drm_kms_helper_poll_fini(dev);
291 drm_mode_config_cleanup(dev);
296 drm_debugfs_remove_files(sprd_drm_debugfs_list,
297 SPRD_DRM_DEBUGFS_ENTRIES, dev->primary);
302 static int sprd_drm_open(struct drm_device *dev, struct drm_file *file)
304 struct drm_sprd_file_private *file_priv;
306 DRM_DEBUG_DRIVER("%s\n", __FILE__);
308 file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
312 file_priv->tgid = task_tgid_nr(current);
313 file->driver_priv = file_priv;
315 return sprd_drm_subdrv_open(dev, file);
318 static void sprd_drm_preclose(struct drm_device *dev,
319 struct drm_file *file)
321 struct sprd_drm_private *private = dev->dev_private;
322 struct drm_pending_vblank_event *e, *t;
325 DRM_DEBUG_DRIVER("%s\n", __FILE__);
327 /* release events of current file */
328 spin_lock_irqsave(&dev->event_lock, flags);
329 list_for_each_entry_safe(e, t, &private->pageflip_event_list,
331 if (e->base.file_priv == file) {
332 list_del(&e->base.link);
333 e->base.destroy(&e->base);
336 spin_unlock_irqrestore(&dev->event_lock, flags);
338 sprd_drm_subdrv_close(dev, file);
341 static void sprd_drm_postclose(struct drm_device *dev, struct drm_file *file)
343 DRM_DEBUG_DRIVER("%s\n", __FILE__);
345 if (!file->driver_priv)
348 kfree(file->driver_priv);
349 file->driver_priv = NULL;
352 static void sprd_drm_lastclose(struct drm_device *dev)
354 DRM_DEBUG_DRIVER("%s\n", __FILE__);
358 sprd_drm_irq_preinstall(struct drm_device *dev)
360 DRM_DEBUG("%s %d\n", __func__, __LINE__);
361 dev->irq_enabled = 0;
366 sprd_drm_irq_postinstall(struct drm_device *dev)
368 struct sprd_drm_private *private = dev->dev_private;
371 DRM_DEBUG("%s %d\n", __func__, __LINE__);
373 for (i = 0; i < MAX_CRTC; i++)
374 atomic_set(&private->vbl_trg_cnt[i], 0);
376 dev->irq_enabled = 1;
381 sprd_drm_irq_uninstall(struct drm_device *dev)
383 struct sprd_drm_private *private = dev->dev_private;
386 DRM_DEBUG("%s %d\n", __func__, __LINE__);
388 for (i = 0; i < MAX_CRTC; i++)
389 atomic_set(&private->vbl_trg_cnt[i], 0);
391 dev->irq_enabled = 0;
395 #ifdef CONFIG_DRM_DPMS_IOCTL
396 static BLOCKING_NOTIFIER_HEAD(sprd_drm_nb_list);
398 int sprd_drm_nb_register(struct notifier_block *nb)
400 return blocking_notifier_chain_register(
401 &sprd_drm_nb_list, nb);
404 int sprd_drm_nb_unregister(struct notifier_block *nb)
406 return blocking_notifier_chain_unregister(
407 &sprd_drm_nb_list, nb);
410 int sprd_drm_nb_send_event(unsigned long val, void *v)
412 return blocking_notifier_call_chain(
413 &sprd_drm_nb_list, val, v);
416 void sprd_drm_free_dpms_event(struct drm_pending_event *event)
418 DRM_INFO("%s:base[0x%x]\n", "free_dpms_evt", (int)event);
423 void *sprd_drm_get_dpms_event(struct sprd_drm_private *private,
424 struct drm_file *file_priv, struct drm_control_dpms *req)
426 struct drm_device *dev = private->drm_dev;
427 struct drm_sprd_send_dpms_event *e = NULL;
430 e = kzalloc(sizeof(*e), GFP_KERNEL);
432 DRM_ERROR("failed to allocate event.\n");
433 spin_lock_irqsave(&dev->event_lock, flags);
434 file_priv->event_space += sizeof(e->event);
435 spin_unlock_irqrestore(&dev->event_lock, flags);
439 e->event.base.type = DRM_DPMS_EVENT;
440 e->event.base.length = sizeof(e->event);
441 e->event.crtc_id = req->crtc_id;
442 e->event.dpms = req->dpms;
443 e->event.user_data = req->user_data;
445 e->base.event = &e->event.base;
446 e->base.file_priv = file_priv;
447 e->base.destroy = sprd_drm_free_dpms_event;
449 DRM_INFO("%s:base[0x%x]dpms[%d]data[0x%x]\n",
450 "get_dpms_evt", (int)&e->base, e->event.dpms,
451 (int)e->event.user_data);
457 static void sprd_drm_control_dpms(enum drm_crtc_id crtc_id,
460 struct sprd_drm_nb_event event;
462 DRM_INFO("%s:crtc_id[%d]mode[%d]\n", __func__, crtc_id, mode);
464 event.index = crtc_id;
465 event.data = (void *)mode;
467 sprd_drm_nb_send_event(SPRD_DRM_DPMS_CTRL, (void *)&event);
469 DRM_INFO("%s:crtc_id[%d]mode[%d]done\n", __func__, crtc_id, mode);
474 void sprd_drm_put_dpms_event(struct sprd_drm_private *private,
475 struct drm_sprd_send_dpms_event *e)
477 struct drm_device *dev = private->drm_dev;
480 DRM_INFO("%s:base[0x%x]dpms[%d]data[0x%x]\n",
481 "put_dpms_evt", (int)&e->base, e->event.dpms,
482 (int)e->event.user_data);
484 spin_lock_irqsave(&dev->event_lock, flags);
485 list_add_tail(&e->base.link, &e->base.file_priv->event_list);
486 wake_up_interruptible(&e->base.file_priv->event_wait);
487 spin_unlock_irqrestore(&dev->event_lock, flags);
492 void sprd_drm_dpms_work_ops(struct work_struct *work)
494 struct sprd_drm_dpms_work *dpms_work =
495 (struct sprd_drm_dpms_work *)work;
496 struct drm_sprd_send_dpms_event *e = dpms_work->event;
497 struct sprd_drm_private *private = dpms_work->private;
499 mutex_lock(&private->dpms_lock);
501 DRM_INFO("%s:base[0x%x]con_id[%d]dpms[%d]data[0x%x]\n",
502 "dpms_work", (int)&e->base, e->event.crtc_id,
503 e->event.dpms, (int)e->event.user_data);
505 sprd_drm_control_dpms(e->event.crtc_id, e->event.dpms);
507 sprd_drm_put_dpms_event(private, e);
509 complete_all(&private->dpms_comp);
511 DRM_INFO("%s:base[0x%x]dpms[%d]done\n", "dpms_work",
512 (int)&e->base, e->event.dpms);
514 mutex_unlock(&private->dpms_lock);
519 int sprd_drm_handle_dpms(struct sprd_drm_private *private,
520 struct drm_control_dpms *req, struct drm_file *file)
524 if (req->type == DPMS_EVENT_DRIVEN) {
525 struct sprd_drm_dpms_work *dpms_work;
526 struct drm_sprd_send_dpms_event *e =
527 sprd_drm_get_dpms_event(private, file, req);
534 if (completion_done(&private->dpms_comp))
535 INIT_COMPLETION(private->dpms_comp);
537 dpms_work = private->dpms_work;
538 dpms_work->event = e;
539 schedule_work((struct work_struct *)dpms_work);
541 sprd_drm_control_dpms(req->crtc_id, req->dpms);
547 int sprd_drm_dpms_ioctl(struct drm_device *dev,
549 struct drm_file *file)
551 struct drm_control_dpms *req = data;
552 struct sprd_drm_private *private = dev->dev_private;
555 DRM_INFO("[%s][%d][%s]\n", __func__, req->dpms,
556 req->type ? "ASYNC" : "SYNC");
558 ret = sprd_drm_handle_dpms(private, req, file);
561 DRM_INFO("[%s][%d][%s]ret[%d]\n", __func__, req->dpms,
562 req->type ? "ASYNC" : "SYNC", ret);
568 static const struct vm_operations_struct sprd_drm_gem_vm_ops = {
569 .fault = sprd_drm_gem_fault,
570 .open = drm_gem_vm_open,
571 .close = drm_gem_vm_close,
574 static struct drm_ioctl_desc sprd_ioctls[] = {
575 DRM_IOCTL_DEF_DRV(SPRD_GEM_CREATE, sprd_drm_gem_create_ioctl,
576 DRM_UNLOCKED | DRM_AUTH),
577 DRM_IOCTL_DEF_DRV(SPRD_GEM_MAP_OFFSET,
578 sprd_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
580 DRM_IOCTL_DEF_DRV(SPRD_GEM_MMAP,
581 sprd_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
582 DRM_IOCTL_DEF_DRV(SPRD_GEM_MMAP_IOMMU,
583 sprd_drm_gem_mmap_iommu_ioctl, DRM_UNLOCKED | DRM_AUTH),
584 DRM_IOCTL_DEF_DRV(SPRD_GEM_UNMAP_IOMMU, sprd_drm_gem_unmap_iommu_ioctl,
585 DRM_UNLOCKED | DRM_AUTH),
586 DRM_IOCTL_DEF_DRV(SPRD_GEM_GET,
587 sprd_drm_gem_get_ioctl, DRM_UNLOCKED),
588 DRM_IOCTL_DEF_DRV(SPRD_GEM_LOCK_HANDLE,
589 sprd_gem_lock_handle_ioctl, DRM_UNLOCKED),
590 DRM_IOCTL_DEF_DRV(SPRD_GEM_UNLOCK_HANDLE,
591 sprd_gem_unlock_handle_ioctl, DRM_UNLOCKED),
592 DRM_IOCTL_DEF_DRV(SPRD_GEM_CACHE_OP,
593 sprd_gem_cache_op_ioctl, DRM_UNLOCKED),
594 DRM_IOCTL_DEF_DRV(SPRD_GEM_INDEX_CREATE, sprd_drm_gem_create_index_ioctl,
595 DRM_UNLOCKED | DRM_AUTH),
596 #ifdef CONFIG_DRM_SPRD_IPP
597 DRM_IOCTL_DEF_DRV(SPRD_IPP_GET_PROPERTY,
598 sprd_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH),
599 DRM_IOCTL_DEF_DRV(SPRD_IPP_SET_PROPERTY,
600 sprd_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH),
601 DRM_IOCTL_DEF_DRV(SPRD_IPP_QUEUE_BUF,
602 sprd_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH),
603 DRM_IOCTL_DEF_DRV(SPRD_IPP_CMD_CTRL,
604 sprd_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH),
606 #ifdef CONFIG_DRM_DPMS_IOCTL
607 DRM_IOCTL_DEF_DRV(DPMS_CONTROL,
608 sprd_drm_dpms_ioctl, DRM_UNLOCKED | DRM_AUTH),
612 static const struct file_operations sprd_drm_driver_fops = {
613 .owner = THIS_MODULE,
615 .mmap = sprd_drm_gem_mmap,
618 .unlocked_ioctl = drm_ioctl,
619 .release = drm_release,
622 static struct drm_driver sprd_drm_driver = {
623 .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
624 DRIVER_GEM | DRIVER_PRIME,
625 .load = sprd_drm_load,
626 .unload = sprd_drm_unload,
627 .open = sprd_drm_open,
628 .preclose = sprd_drm_preclose,
629 .lastclose = sprd_drm_lastclose,
630 .postclose = sprd_drm_postclose,
631 .get_vblank_counter = sprd_drm_get_vblank_counter,
632 .prepare_vblank = sprd_prepare_vblank,
633 .enable_vblank = sprd_enable_vblank,
634 .disable_vblank = sprd_disable_vblank,
635 .gem_init_object = sprd_drm_gem_init_object,
636 .gem_free_object = sprd_drm_gem_free_object,
637 .gem_vm_ops = &sprd_drm_gem_vm_ops,
638 .dumb_create = sprd_drm_gem_dumb_create,
639 .dumb_map_offset = sprd_drm_gem_dumb_map_offset,
640 .dumb_destroy = sprd_drm_gem_dumb_destroy,
641 .prime_handle_to_fd = sprd_drm_gem_prime_handle_to_fd,
642 .prime_fd_to_handle = sprd_drm_gem_prime_fd_to_handle,
643 #ifdef CONFIG_DRM_SPRD_DMABUF
644 .gem_prime_export = sprd_dmabuf_prime_export,
645 .gem_prime_import = sprd_dmabuf_prime_import,
647 .ioctls = sprd_ioctls,
648 .fops = &sprd_drm_driver_fops,
649 .irq_handler = sprd_drm_irq_handler,
650 .irq_preinstall = sprd_drm_irq_preinstall,
651 .irq_postinstall = sprd_drm_irq_postinstall,
652 .irq_uninstall = sprd_drm_irq_uninstall,
656 .major = DRIVER_MAJOR,
657 .minor = DRIVER_MINOR,
660 static int sprd_drm_platform_probe(struct platform_device *pdev)
662 DRM_DEBUG_DRIVER("%s\n", __FILE__);
664 sprd_drm_driver.num_ioctls = DRM_ARRAY_SIZE(sprd_ioctls);
665 sprd_drm_driver.kdriver.platform_device = pdev;
667 return drm_platform_init(&sprd_drm_driver, pdev);
670 static int sprd_drm_platform_remove(struct platform_device *pdev)
672 DRM_DEBUG_DRIVER("%s\n", __FILE__);
674 drm_platform_exit(&sprd_drm_driver, pdev);
680 static const struct of_device_id sprd_drm_dt_match[] = {
681 { .compatible = "sprd,sprd_drm",},
684 MODULE_DEVICE_TABLE(of, sprd_drm_dt_match);
687 static struct platform_driver sprd_drm_platform_driver = {
688 .probe = sprd_drm_platform_probe,
689 .remove = sprd_drm_platform_remove,
691 .owner = THIS_MODULE,
694 .of_match_table = of_match_ptr(sprd_drm_dt_match),
699 static int __init sprd_drm_init(void)
703 DRM_DEBUG_DRIVER("%s\n", __FILE__);
705 #ifdef CONFIG_DRM_SPRD_GSP
706 ret = platform_driver_register(&gsp_driver);
711 #ifdef CONFIG_DRM_SPRD_IPP
712 ret = platform_driver_register(&ipp_driver);
717 ret = platform_driver_register(&sprd_drm_platform_driver);
724 #ifdef CONFIG_DRM_SPRD_IPP
725 platform_driver_unregister(&ipp_driver);
729 #ifdef CONFIG_DRM_SPRD_GSP
730 platform_driver_unregister(&gsp_driver);
737 static void __exit sprd_drm_exit(void)
739 DRM_DEBUG_DRIVER("%s\n", __FILE__);
741 platform_driver_unregister(&sprd_drm_platform_driver);
743 #ifdef CONFIG_DRM_SPRD_IPP
744 platform_driver_unregister(&ipp_driver);
747 #ifdef CONFIG_DRM_SPRD_GSP
748 platform_driver_unregister(&gsp_driver);
752 //module_init(sprd_drm_init);
753 late_initcall(sprd_drm_init);
754 module_exit(sprd_drm_exit);
756 MODULE_AUTHOR("frank.dong@spreadtrum.com");
757 MODULE_DESCRIPTION("Spreadtrum SoC DRM Driver");
758 MODULE_LICENSE("GPL");