drm/sprd: save pid/tgid in private file data
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / gpu / drm / sprd / sprd_drm_drv.c
1 /*
2  * Copyright (c) 2014 Spreadtrum Communications, Inc.
3  *
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.
8  *
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.
13  */
14
15 #include "drmP.h"
16 #include "drm.h"
17
18 #include <drm/sprd_drm.h>
19 #ifdef CONFIG_OF
20 #include <linux/of_irq.h>
21 #endif
22
23 #include "sprd_drm_drv.h"
24 #include "sprd_drm_gem.h"
25 #ifdef CONFIG_DRM_SPRD_DMABUF
26 #include "sprd_drm_dmabuf.h"
27 #endif
28 #include "sprd_drm_irq.h"
29 #include "sprd_drm_ipp.h"
30
31 #include <video/ion_sprd.h>
32 #include "sprdfb.h"
33 #include <soc/sprd/cpuidle.h>
34
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
40
41 #define VBLANK_OFF_DELAY        500
42
43 struct sprd_drm_gem_info_data {
44         struct drm_file *filp;
45         struct seq_file *m;
46 };
47
48 static int sprd_drm_gem_one_info(int id, void *ptr, void *data)
49 {
50         struct drm_gem_object *obj = (struct drm_gem_object *)ptr;
51         struct sprd_drm_gem_info_data *gem_info_data = data;
52         struct drm_sprd_file_private *file_priv =
53                                         gem_info_data->filp->driver_priv;
54         struct sprd_drm_gem_obj *sprd_gem;
55         struct sprd_drm_gem_buf *buf;
56
57         if (!obj) {
58                 DRM_ERROR("failed to get drm_gem_object\n");
59                 return -EFAULT;
60         }
61
62         drm_gem_object_reference(obj);
63
64         sprd_gem = to_sprd_gem_obj(obj);
65         buf = sprd_gem->buffer;
66
67         seq_printf(gem_info_data->m,
68                         "%5d\t%5d\t%4d\t%4d\t\t%4d\t0x%08lx\t0x%x\t%4d\t%4d\t\t"
69                         "%4d\t\t0x%p\t%6d\n",
70                                 file_priv->pid,
71                                 file_priv->tgid,
72                                 id,
73                                 atomic_read(&obj->refcount.refcount) - 1,
74                                 obj->handle_count,
75                                 sprd_gem->size,
76                                 sprd_gem->flags,
77                                 buf->pfnmap,
78                                 obj->dma_buf ? 1 : 0,
79                                 obj->import_attach ? 1 : 0,
80                                 obj,
81                                 obj->name);
82
83         drm_gem_object_unreference(obj);
84
85         return 0;
86 }
87
88 static int sprd_drm_gem_info(struct seq_file *m, void *data)
89 {
90         struct drm_info_node *node = (struct drm_info_node *)m->private;
91         struct drm_device *drm_dev = node->minor->dev;
92         struct sprd_drm_gem_info_data gem_info_data;
93
94         gem_info_data.m = m;
95         seq_puts(gem_info_data.m,
96                         "pid\ttgid\thandle\trefcount\thcount\tsize\t\tflags\t"
97                         "pfnmap\texport_to_fd\timport_from_fd\tobj_addr\t"
98                         "name\n");
99         mutex_lock(&drm_dev->struct_mutex);
100
101         list_for_each_entry(gem_info_data.filp, &drm_dev->filelist, lhead) {
102                 spin_lock(&gem_info_data.filp->table_lock);
103                 idr_for_each(&gem_info_data.filp->object_idr,
104                         sprd_drm_gem_one_info, &gem_info_data);
105                 spin_unlock(&gem_info_data.filp->table_lock);
106         }
107
108         mutex_unlock(&drm_dev->struct_mutex);
109
110         return 0;
111 }
112
113 static struct drm_info_list sprd_drm_debugfs_list[] = {
114         {"gem_info", sprd_drm_gem_info, DRIVER_GEM},
115 };
116 #define SPRD_DRM_DEBUGFS_ENTRIES ARRAY_SIZE(sprd_drm_debugfs_list)
117
118 static struct notifier_block sprd_drm_cpu_idle_notifier = {
119         .notifier_call = sprd_drm_cpuidle_notify,
120 };
121
122 static DEVICE_ATTR(vblank_freq, S_IRUGO | S_IWUSR, sprd_drm_vblank_freq_show,
123                                 sprd_drm_vblank_freq_store);
124
125 static struct attribute *sprd_drm_vblank_freq_attrs[] = {
126         &dev_attr_vblank_freq.attr,
127         NULL,
128 };
129
130 struct attribute_group sprd_drm_vblank_freq_attrs_group = {
131         .attrs = sprd_drm_vblank_freq_attrs,
132 };
133
134 static int sprd_drm_load(struct drm_device *dev, unsigned long flags)
135 {
136         struct sprd_drm_private *private;
137         struct platform_device *pdev;
138 #ifdef CONFIG_OF
139         struct resource *res;
140 #endif
141         struct drm_minor *minor;
142 #ifdef CONFIG_DRM_DPMS_IOCTL
143         struct sprd_drm_dpms_work *dpms_work;
144 #endif
145         int ret;
146
147         minor = dev->primary;
148
149         DRM_DEBUG_DRIVER("%s\n", __FILE__);
150
151         pdev = dev->driver->kdriver.platform_device;
152         if (!pdev) {
153                 DRM_ERROR("failed to get platform device.\n");
154                 return -EFAULT;
155         }
156
157         private = devm_kzalloc(&pdev->dev, sizeof(*private), GFP_KERNEL);
158         if (!private) {
159                 DRM_ERROR("failed to alloc dev private data.\n");
160                 return -ENOMEM;
161         }
162
163         INIT_LIST_HEAD(&private->pageflip_event_list);
164         dev->dev_private = (void *)private;
165
166         private->sprd_drm_ion_client = sprd_ion_client_create("drm");
167         if (!private->sprd_drm_ion_client) {
168                 DRM_ERROR("Unable to create ION client\n");
169                 return -ENOMEM;
170         }
171
172 #ifdef CONFIG_OF
173         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sprdfb");
174         if (!res) {
175                 DRM_ERROR("failed to get DISPC base address\n");
176                 return -ENOMEM;
177         }
178
179         private->reg_size = resource_size(res);
180         private->regs = devm_ioremap(&pdev->dev, res->start,
181                                         private->reg_size);
182         if (unlikely(!private->regs)) {
183                 DRM_ERROR("failed to map DISPC base\n");
184                 return -ENOMEM;
185         }
186
187         private->irq = platform_get_irq_byname(pdev, "sprd_drm_irq");
188 #else
189         private->irq = platform_get_irq(pdev, 1);
190 #endif
191         if (private->irq <= 0)
192                 DRM_ERROR("interrupt not registered\n");
193
194         private->drm_dev = dev;
195
196         private->nb_ctrl.notifier_call = sprd_drm_notifier_ctrl;
197         if (sprdfb_nb_register(&private->nb_ctrl))
198                 pr_err("could not register sprd_fb notify callback\n");
199
200         /* init workqueue for fake vsync */
201         INIT_WORK(&private->fake_vbl_work,
202                         sprd_drm_fake_vblank_handler);
203         private->fake_vbl_hz = VBLANK_DEF_HZ;
204         private->vbl_itv_us = (unsigned long int)(VBLANK_INTERVAL(VBLANK_DEF_HZ));
205         ret = sysfs_create_group(&dev->dev->kobj, &sprd_drm_vblank_freq_attrs_group);
206         if (ret)
207                 pr_err("sysfs group creation failed, ret = %d\n", ret);
208
209         drm_mode_config_init(dev);
210         ret = drm_vblank_init(dev, MAX_CRTC);
211         if (ret)
212                 goto err;
213
214         /*
215          * probe sub drivers such as display controller and hdmi driver,
216          * that were registered at probe() of platform driver
217          * to the sub driver and create encoder and connector for them.
218          */
219         ret = sprd_drm_device_register(dev);
220         if (ret)
221                 goto err_vblank;
222
223         dev->vblank_disable_allowed = 1;
224         drm_vblank_offdelay = VBLANK_OFF_DELAY;
225         minor = dev->primary;
226         ret = drm_debugfs_create_files(sprd_drm_debugfs_list,
227                         SPRD_DRM_DEBUGFS_ENTRIES,
228                         minor->debugfs_root, minor);
229         if (ret)
230                 DRM_DEBUG_DRIVER("failed to create sprd-drm debugfs.\n");
231
232 #ifdef CONFIG_DRM_DPMS_IOCTL
233         dpms_work = kzalloc(sizeof(*dpms_work), GFP_KERNEL);
234         if (!dpms_work) {
235                 DRM_ERROR("failed to alloc dpms_work.\n");
236                 goto err_unreg;
237         }
238
239         dpms_work->private = private;
240         private->dpms_work = dpms_work;
241         INIT_WORK((struct work_struct *)private->dpms_work,
242                 sprd_drm_dpms_work_ops);
243
244         init_completion(&private->dpms_comp);
245         mutex_init(&private->dpms_lock);
246 #endif
247
248         if (register_sc_cpuidle_notifier(&sprd_drm_cpu_idle_notifier))
249                 DRM_ERROR("failed to setup light sleep notifier\n");
250
251         return 0;
252
253 #ifdef CONFIG_DRM_DPMS_IOCTL
254 err_unreg:
255         sprd_drm_device_unregister(dev);
256 #endif
257 err_vblank:
258         drm_vblank_cleanup(dev);
259 err:
260         drm_mode_config_cleanup(dev);
261         kfree(private);
262
263         return ret;
264 }
265
266 static int sprd_drm_unload(struct drm_device *dev)
267 {
268         struct sprd_drm_private *private =
269                 (struct sprd_drm_private *)dev->dev_private;
270
271         DRM_DEBUG_DRIVER("%s\n", __FILE__);
272
273         if (unregister_sc_cpuidle_notifier(&sprd_drm_cpu_idle_notifier))
274                 DRM_ERROR("failed to unset light sleep notifier\n");
275
276 #ifdef CONFIG_DRM_DPMS_IOCTL
277         kfree(private->dpms_work);
278 #endif
279
280         sprdfb_nb_unregister(&private->nb_ctrl);
281
282 #ifdef CONFIG_DRM_SPRD_KMS
283         sprd_drm_fbdev_fini(dev);
284 #endif
285         sprd_drm_device_unregister(dev);
286         drm_vblank_cleanup(dev);
287 #ifdef CONFIG_DRM_SPRD_KMS
288         drm_kms_helper_poll_fini(dev);
289 #endif
290         drm_mode_config_cleanup(dev);
291         kfree(private);
292
293         private = NULL;
294
295         drm_debugfs_remove_files(sprd_drm_debugfs_list,
296                 SPRD_DRM_DEBUGFS_ENTRIES, dev->primary);
297
298         return 0;
299 }
300
301 static int sprd_drm_open(struct drm_device *dev, struct drm_file *file)
302 {
303         struct drm_sprd_file_private *file_priv;
304
305         DRM_DEBUG_DRIVER("%s\n", __FILE__);
306
307         file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
308         if (!file_priv)
309                 return -ENOMEM;
310
311         file->driver_priv = file_priv;
312
313         return sprd_drm_subdrv_open(dev, file);
314 }
315
316 static void sprd_drm_preclose(struct drm_device *dev,
317                                         struct drm_file *file)
318 {
319         struct sprd_drm_private *private = dev->dev_private;
320         struct drm_pending_vblank_event *e, *t;
321         unsigned long flags;
322
323         DRM_DEBUG_DRIVER("%s\n", __FILE__);
324
325         /* release events of current file */
326         spin_lock_irqsave(&dev->event_lock, flags);
327         list_for_each_entry_safe(e, t, &private->pageflip_event_list,
328                         base.link) {
329                 if (e->base.file_priv == file) {
330                         list_del(&e->base.link);
331                         e->base.destroy(&e->base);
332                 }
333         }
334         spin_unlock_irqrestore(&dev->event_lock, flags);
335
336         sprd_drm_subdrv_close(dev, file);
337 }
338
339 static void sprd_drm_postclose(struct drm_device *dev, struct drm_file *file)
340 {
341         DRM_DEBUG_DRIVER("%s\n", __FILE__);
342
343         if (!file->driver_priv)
344                 return;
345
346         kfree(file->driver_priv);
347         file->driver_priv = NULL;
348 }
349
350 static void sprd_drm_lastclose(struct drm_device *dev)
351 {
352         DRM_DEBUG_DRIVER("%s\n", __FILE__);
353 }
354
355 static void
356 sprd_drm_irq_preinstall(struct drm_device *dev)
357 {
358         DRM_DEBUG("%s %d\n", __func__, __LINE__);
359         dev->irq_enabled = 0;
360         return;
361 }
362
363 static int
364 sprd_drm_irq_postinstall(struct drm_device *dev)
365 {
366         struct sprd_drm_private *private = dev->dev_private;
367         int i;
368
369         DRM_DEBUG("%s %d\n", __func__, __LINE__);
370
371         for (i = 0; i < MAX_CRTC; i++)
372                 atomic_set(&private->vbl_trg_cnt[i], 0);
373
374         dev->irq_enabled = 1;
375         return 0;
376 }
377
378 static void
379 sprd_drm_irq_uninstall(struct drm_device *dev)
380 {
381         struct sprd_drm_private *private = dev->dev_private;
382         int i;
383
384         DRM_DEBUG("%s %d\n", __func__, __LINE__);
385
386         for (i = 0; i < MAX_CRTC; i++)
387                 atomic_set(&private->vbl_trg_cnt[i], 0);
388
389         dev->irq_enabled = 0;
390         return;
391 }
392
393 #ifdef CONFIG_DRM_DPMS_IOCTL
394 static BLOCKING_NOTIFIER_HEAD(sprd_drm_nb_list);
395
396 int sprd_drm_nb_register(struct notifier_block *nb)
397 {
398         return blocking_notifier_chain_register(
399                 &sprd_drm_nb_list, nb);
400 }
401
402 int sprd_drm_nb_unregister(struct notifier_block *nb)
403 {
404         return blocking_notifier_chain_unregister(
405                 &sprd_drm_nb_list, nb);
406 }
407
408 int sprd_drm_nb_send_event(unsigned long val, void *v)
409 {
410         return blocking_notifier_call_chain(
411                 &sprd_drm_nb_list, val, v);
412 }
413
414 void sprd_drm_free_dpms_event(struct drm_pending_event *event)
415 {
416         DRM_INFO("%s:base[0x%x]\n", "free_dpms_evt", (int)event);
417
418         kfree(event);
419 }
420
421 void *sprd_drm_get_dpms_event(struct sprd_drm_private *private,
422                 struct drm_file *file_priv, struct drm_control_dpms *req)
423 {
424         struct drm_device *dev = private->drm_dev;
425         struct drm_sprd_send_dpms_event *e = NULL;
426         unsigned long flags;
427
428         e = kzalloc(sizeof(*e), GFP_KERNEL);
429         if (!e) {
430                 DRM_ERROR("failed to allocate event.\n");
431                 spin_lock_irqsave(&dev->event_lock, flags);
432                 file_priv->event_space += sizeof(e->event);
433                 spin_unlock_irqrestore(&dev->event_lock, flags);
434                 goto out;
435         }
436
437         e->event.base.type = DRM_DPMS_EVENT;
438         e->event.base.length = sizeof(e->event);
439         e->event.crtc_id = req->crtc_id;
440         e->event.dpms = req->dpms;
441         e->event.user_data = req->user_data;
442
443         e->base.event = &e->event.base;
444         e->base.file_priv = file_priv;
445         e->base.destroy =  sprd_drm_free_dpms_event;
446
447         DRM_INFO("%s:base[0x%x]dpms[%d]data[0x%x]\n",
448                 "get_dpms_evt", (int)&e->base, e->event.dpms,
449                 (int)e->event.user_data);
450
451 out:
452         return e;
453 }
454
455 static void sprd_drm_control_dpms(enum drm_crtc_id crtc_id,
456                                         int mode)
457 {
458         struct sprd_drm_nb_event event;
459
460         DRM_INFO("%s:crtc_id[%d]mode[%d]\n", __func__, crtc_id, mode);
461
462         event.index = crtc_id;
463         event.data = (void *)mode;
464
465         sprd_drm_nb_send_event(SPRD_DRM_DPMS_CTRL, (void *)&event);
466
467         DRM_INFO("%s:crtc_id[%d]mode[%d]done\n", __func__, crtc_id, mode);
468
469         return;
470 }
471
472 void sprd_drm_put_dpms_event(struct sprd_drm_private *private,
473                 struct drm_sprd_send_dpms_event *e)
474 {
475         struct drm_device *dev = private->drm_dev;
476         unsigned long flags;
477
478         DRM_INFO("%s:base[0x%x]dpms[%d]data[0x%x]\n",
479                 "put_dpms_evt", (int)&e->base, e->event.dpms,
480                 (int)e->event.user_data);
481
482         spin_lock_irqsave(&dev->event_lock, flags);
483         list_add_tail(&e->base.link, &e->base.file_priv->event_list);
484         wake_up_interruptible(&e->base.file_priv->event_wait);
485         spin_unlock_irqrestore(&dev->event_lock, flags);
486
487         return;
488 }
489
490 void sprd_drm_dpms_work_ops(struct work_struct *work)
491 {
492         struct sprd_drm_dpms_work *dpms_work =
493                 (struct sprd_drm_dpms_work *)work;
494         struct drm_sprd_send_dpms_event *e = dpms_work->event;
495         struct sprd_drm_private *private = dpms_work->private;
496
497         mutex_lock(&private->dpms_lock);
498
499         DRM_INFO("%s:base[0x%x]con_id[%d]dpms[%d]data[0x%x]\n",
500                 "dpms_work", (int)&e->base, e->event.crtc_id,
501                 e->event.dpms, (int)e->event.user_data);
502
503         sprd_drm_control_dpms(e->event.crtc_id, e->event.dpms);
504
505         sprd_drm_put_dpms_event(private, e);
506
507         complete_all(&private->dpms_comp);
508
509         DRM_INFO("%s:base[0x%x]dpms[%d]done\n", "dpms_work",
510                 (int)&e->base, e->event.dpms);
511
512         mutex_unlock(&private->dpms_lock);
513
514         return;
515 }
516
517 int sprd_drm_handle_dpms(struct sprd_drm_private *private,
518                 struct drm_control_dpms *req, struct drm_file *file)
519 {
520         int ret = 0;
521
522         if (req->type == DPMS_EVENT_DRIVEN) {
523                 struct sprd_drm_dpms_work *dpms_work;
524                 struct drm_sprd_send_dpms_event *e =
525                         sprd_drm_get_dpms_event(private, file, req);
526
527                 if (!e) {
528                         ret = -ENOMEM;
529                         goto out;
530                 }
531
532                 if (completion_done(&private->dpms_comp))
533                         INIT_COMPLETION(private->dpms_comp);
534
535                 dpms_work = private->dpms_work;
536                 dpms_work->event = e;
537                 schedule_work((struct work_struct *)dpms_work);
538         } else
539                 sprd_drm_control_dpms(req->crtc_id, req->dpms);
540
541 out:
542         return ret;
543 }
544
545 int sprd_drm_dpms_ioctl(struct drm_device *dev,
546                                                 void *data,
547                                                 struct drm_file *file)
548 {
549         struct drm_control_dpms *req = data;
550         struct sprd_drm_private *private = dev->dev_private;
551         int ret = 0;
552
553         DRM_INFO("[%s][%d][%s]\n", __func__, req->dpms,
554                 req->type ? "ASYNC" : "SYNC");
555
556         ret = sprd_drm_handle_dpms(private, req, file);
557
558 out:
559         DRM_INFO("[%s][%d][%s]ret[%d]\n", __func__, req->dpms,
560                 req->type ? "ASYNC" : "SYNC", ret);
561
562         return ret;
563 }
564 #endif
565
566 static const struct vm_operations_struct sprd_drm_gem_vm_ops = {
567         .fault = sprd_drm_gem_fault,
568         .open = drm_gem_vm_open,
569         .close = drm_gem_vm_close,
570 };
571
572 static struct drm_ioctl_desc sprd_ioctls[] = {
573         DRM_IOCTL_DEF_DRV(SPRD_GEM_CREATE, sprd_drm_gem_create_ioctl,
574                         DRM_UNLOCKED | DRM_AUTH),
575         DRM_IOCTL_DEF_DRV(SPRD_GEM_MAP_OFFSET,
576                         sprd_drm_gem_map_offset_ioctl, DRM_UNLOCKED |
577                         DRM_AUTH),
578         DRM_IOCTL_DEF_DRV(SPRD_GEM_MMAP,
579                         sprd_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
580         DRM_IOCTL_DEF_DRV(SPRD_GEM_MMAP_IOMMU,
581                         sprd_drm_gem_mmap_iommu_ioctl, DRM_UNLOCKED | DRM_AUTH),
582         DRM_IOCTL_DEF_DRV(SPRD_GEM_UNMAP_IOMMU, sprd_drm_gem_unmap_iommu_ioctl,
583                         DRM_UNLOCKED | DRM_AUTH),
584         DRM_IOCTL_DEF_DRV(SPRD_GEM_GET,
585                         sprd_drm_gem_get_ioctl, DRM_UNLOCKED),
586         DRM_IOCTL_DEF_DRV(SPRD_GEM_LOCK_HANDLE,
587                         sprd_gem_lock_handle_ioctl, DRM_UNLOCKED),
588         DRM_IOCTL_DEF_DRV(SPRD_GEM_UNLOCK_HANDLE,
589                         sprd_gem_unlock_handle_ioctl, DRM_UNLOCKED),
590         DRM_IOCTL_DEF_DRV(SPRD_GEM_CACHE_OP,
591                         sprd_gem_cache_op_ioctl, DRM_UNLOCKED),
592         DRM_IOCTL_DEF_DRV(SPRD_GEM_INDEX_CREATE, sprd_drm_gem_create_index_ioctl,
593                         DRM_UNLOCKED | DRM_AUTH),
594 #ifdef CONFIG_DRM_SPRD_IPP
595         DRM_IOCTL_DEF_DRV(SPRD_IPP_GET_PROPERTY,
596                         sprd_drm_ipp_get_property, DRM_UNLOCKED | DRM_AUTH),
597         DRM_IOCTL_DEF_DRV(SPRD_IPP_SET_PROPERTY,
598                         sprd_drm_ipp_set_property, DRM_UNLOCKED | DRM_AUTH),
599         DRM_IOCTL_DEF_DRV(SPRD_IPP_QUEUE_BUF,
600                         sprd_drm_ipp_queue_buf, DRM_UNLOCKED | DRM_AUTH),
601         DRM_IOCTL_DEF_DRV(SPRD_IPP_CMD_CTRL,
602                         sprd_drm_ipp_cmd_ctrl, DRM_UNLOCKED | DRM_AUTH),
603 #endif
604 #ifdef CONFIG_DRM_DPMS_IOCTL
605         DRM_IOCTL_DEF_DRV(DPMS_CONTROL,
606                         sprd_drm_dpms_ioctl, DRM_UNLOCKED | DRM_AUTH),
607 #endif
608 };
609
610 static const struct file_operations sprd_drm_driver_fops = {
611         .owner          = THIS_MODULE,
612         .open           = drm_open,
613         .mmap           = sprd_drm_gem_mmap,
614         .poll           = drm_poll,
615         .read           = drm_read,
616         .unlocked_ioctl = drm_ioctl,
617         .release        = drm_release,
618 };
619
620 static struct drm_driver sprd_drm_driver = {
621         .driver_features        = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
622                                         DRIVER_GEM | DRIVER_PRIME,
623         .load                   = sprd_drm_load,
624         .unload                 = sprd_drm_unload,
625         .open                   = sprd_drm_open,
626         .preclose               = sprd_drm_preclose,
627         .lastclose              = sprd_drm_lastclose,
628         .postclose              = sprd_drm_postclose,
629         .get_vblank_counter     = sprd_drm_get_vblank_counter,
630         .prepare_vblank         = sprd_prepare_vblank,
631         .enable_vblank          = sprd_enable_vblank,
632         .disable_vblank         = sprd_disable_vblank,
633         .gem_init_object        = sprd_drm_gem_init_object,
634         .gem_free_object        = sprd_drm_gem_free_object,
635         .gem_vm_ops             = &sprd_drm_gem_vm_ops,
636         .dumb_create            = sprd_drm_gem_dumb_create,
637         .dumb_map_offset        = sprd_drm_gem_dumb_map_offset,
638         .dumb_destroy           = sprd_drm_gem_dumb_destroy,
639         .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
640         .prime_fd_to_handle     = sprd_drm_gem_prime_fd_to_handle,
641 #ifdef CONFIG_DRM_SPRD_DMABUF
642         .gem_prime_export       = sprd_dmabuf_prime_export,
643         .gem_prime_import       = sprd_dmabuf_prime_import,
644 #else
645         .gem_prime_export       = sprd_prime_export,
646         .gem_prime_import       = sprd_prime_import,
647 #endif
648         .ioctls                 = sprd_ioctls,
649         .fops                   = &sprd_drm_driver_fops,
650         .irq_handler            = sprd_drm_irq_handler,
651         .irq_preinstall         = sprd_drm_irq_preinstall,
652         .irq_postinstall        = sprd_drm_irq_postinstall,
653         .irq_uninstall          = sprd_drm_irq_uninstall,
654         .name   = DRIVER_NAME,
655         .desc   = DRIVER_DESC,
656         .date   = DRIVER_DATE,
657         .major  = DRIVER_MAJOR,
658         .minor  = DRIVER_MINOR,
659 };
660
661 static int sprd_drm_platform_probe(struct platform_device *pdev)
662 {
663         DRM_DEBUG_DRIVER("%s\n", __FILE__);
664
665         sprd_drm_driver.num_ioctls = DRM_ARRAY_SIZE(sprd_ioctls);
666         sprd_drm_driver.kdriver.platform_device = pdev;
667
668         return drm_platform_init(&sprd_drm_driver, pdev);
669 }
670
671 static int sprd_drm_platform_remove(struct platform_device *pdev)
672 {
673         DRM_DEBUG_DRIVER("%s\n", __FILE__);
674
675         drm_platform_exit(&sprd_drm_driver, pdev);
676
677         return 0;
678 }
679
680 #ifdef CONFIG_OF
681 static const struct of_device_id sprd_drm_dt_match[] = {
682         { .compatible = "sprd,sprd_drm",},
683         {}
684 };
685 MODULE_DEVICE_TABLE(of, sprd_drm_dt_match);
686 #endif
687
688 static struct platform_driver sprd_drm_platform_driver = {
689         .probe          = sprd_drm_platform_probe,
690         .remove         = sprd_drm_platform_remove,
691         .driver         = {
692                 .owner  = THIS_MODULE,
693                 .name   = "sprd-drm",
694 #ifdef CONFIG_OF
695                 .of_match_table = of_match_ptr(sprd_drm_dt_match),
696 #endif
697         },
698 };
699
700 static int __init sprd_drm_init(void)
701 {
702         int ret;
703
704         DRM_DEBUG_DRIVER("%s\n", __FILE__);
705
706 #ifdef CONFIG_DRM_SPRD_GSP
707         ret = platform_driver_register(&gsp_driver);
708         if (ret < 0)
709                 goto out_gsp;
710 #endif
711
712 #ifdef CONFIG_DRM_SPRD_IPP
713         ret = platform_driver_register(&ipp_driver);
714         if (ret < 0)
715                 goto out_ipp;
716 #endif
717
718         ret = platform_driver_register(&sprd_drm_platform_driver);
719         if (ret < 0)
720                 goto out_drm;
721
722         return 0;
723
724 out_drm:
725 #ifdef CONFIG_DRM_SPRD_IPP
726         platform_driver_unregister(&ipp_driver);
727 out_ipp:
728 #endif
729
730 #ifdef CONFIG_DRM_SPRD_GSP
731         platform_driver_unregister(&gsp_driver);
732 out_gsp:
733 #endif
734
735         return ret;
736 }
737
738 static void __exit sprd_drm_exit(void)
739 {
740         DRM_DEBUG_DRIVER("%s\n", __FILE__);
741
742         platform_driver_unregister(&sprd_drm_platform_driver);
743
744 #ifdef CONFIG_DRM_SPRD_IPP
745         platform_driver_unregister(&ipp_driver);
746 #endif
747
748 #ifdef CONFIG_DRM_SPRD_GSP
749         platform_driver_unregister(&gsp_driver);
750 #endif
751 }
752
753 //module_init(sprd_drm_init);
754 late_initcall(sprd_drm_init);
755 module_exit(sprd_drm_exit);
756
757 MODULE_AUTHOR("frank.dong@spreadtrum.com");
758 MODULE_DESCRIPTION("Spreadtrum SoC DRM Driver");
759 MODULE_LICENSE("GPL");