Linux Audio

Check our new training course

Loading...
  1/*
  2 * drivers/staging/omapdrm/omap_drv.c
  3 *
  4 * Copyright (C) 2011 Texas Instruments
  5 * Author: Rob Clark <rob@ti.com>
  6 *
  7 * This program is free software; you can redistribute it and/or modify it
  8 * under the terms of the GNU General Public License version 2 as published by
  9 * the Free Software Foundation.
 10 *
 11 * This program is distributed in the hope that it will be useful, but WITHOUT
 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 14 * more details.
 15 *
 16 * You should have received a copy of the GNU General Public License along with
 17 * this program.  If not, see <http://www.gnu.org/licenses/>.
 18 */
 19
 20#include "omap_drv.h"
 21
 22#include "drm_crtc_helper.h"
 23#include "drm_fb_helper.h"
 24#include "omap_dmm_tiler.h"
 25
 26#define DRIVER_NAME		MODULE_NAME
 27#define DRIVER_DESC		"OMAP DRM"
 28#define DRIVER_DATE		"20110917"
 29#define DRIVER_MAJOR		1
 30#define DRIVER_MINOR		0
 31#define DRIVER_PATCHLEVEL	0
 32
 33struct drm_device *drm_device;
 34
 35static int num_crtc = CONFIG_DRM_OMAP_NUM_CRTCS;
 36
 37MODULE_PARM_DESC(num_crtc, "Number of overlays to use as CRTCs");
 38module_param(num_crtc, int, 0600);
 39
 40/*
 41 * mode config funcs
 42 */
 43
 44/* Notes about mapping DSS and DRM entities:
 45 *    CRTC:        overlay
 46 *    encoder:     manager.. with some extension to allow one primary CRTC
 47 *                 and zero or more video CRTC's to be mapped to one encoder?
 48 *    connector:   dssdev.. manager can be attached/detached from different
 49 *                 devices
 50 */
 51
 52static void omap_fb_output_poll_changed(struct drm_device *dev)
 53{
 54	struct omap_drm_private *priv = dev->dev_private;
 55	DBG("dev=%p", dev);
 56	if (priv->fbdev) {
 57		drm_fb_helper_hotplug_event(priv->fbdev);
 58	}
 59}
 60
 61static const struct drm_mode_config_funcs omap_mode_config_funcs = {
 62	.fb_create = omap_framebuffer_create,
 63	.output_poll_changed = omap_fb_output_poll_changed,
 64};
 65
 66static int get_connector_type(struct omap_dss_device *dssdev)
 67{
 68	switch (dssdev->type) {
 69	case OMAP_DISPLAY_TYPE_HDMI:
 70		return DRM_MODE_CONNECTOR_HDMIA;
 71	case OMAP_DISPLAY_TYPE_DPI:
 72		if (!strcmp(dssdev->name, "dvi"))
 73			return DRM_MODE_CONNECTOR_DVID;
 74		/* fallthrough */
 75	default:
 76		return DRM_MODE_CONNECTOR_Unknown;
 77	}
 78}
 79
 80#if 0 /* enable when dss2 supports hotplug */
 81static int omap_drm_notifier(struct notifier_block *nb,
 82		unsigned long evt, void *arg)
 83{
 84	switch (evt) {
 85	case OMAP_DSS_SIZE_CHANGE:
 86	case OMAP_DSS_HOTPLUG_CONNECT:
 87	case OMAP_DSS_HOTPLUG_DISCONNECT: {
 88		struct drm_device *dev = drm_device;
 89		DBG("hotplug event: evt=%d, dev=%p", evt, dev);
 90		if (dev) {
 91			drm_sysfs_hotplug_event(dev);
 92		}
 93		return NOTIFY_OK;
 94	}
 95	default:  /* don't care about other events for now */
 96		return NOTIFY_DONE;
 97	}
 98}
 99#endif
100
101static void dump_video_chains(void)
102{
103	int i;
104
105	DBG("dumping video chains: ");
106	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
107		struct omap_overlay *ovl = omap_dss_get_overlay(i);
108		struct omap_overlay_manager *mgr = ovl->manager;
109		struct omap_dss_device *dssdev = mgr ? mgr->device : NULL;
110		if (dssdev) {
111			DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name,
112						dssdev->name);
113		} else if (mgr) {
114			DBG("%d: %s -> %s", i, ovl->name, mgr->name);
115		} else {
116			DBG("%d: %s", i, ovl->name);
117		}
118	}
119}
120
121/* create encoders for each manager */
122static int create_encoder(struct drm_device *dev,
123		struct omap_overlay_manager *mgr)
124{
125	struct omap_drm_private *priv = dev->dev_private;
126	struct drm_encoder *encoder = omap_encoder_init(dev, mgr);
127
128	if (!encoder) {
129		dev_err(dev->dev, "could not create encoder: %s\n",
130				mgr->name);
131		return -ENOMEM;
132	}
133
134	BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
135
136	priv->encoders[priv->num_encoders++] = encoder;
137
138	return 0;
139}
140
141/* create connectors for each display device */
142static int create_connector(struct drm_device *dev,
143		struct omap_dss_device *dssdev)
144{
145	struct omap_drm_private *priv = dev->dev_private;
146	static struct notifier_block *notifier;
147	struct drm_connector *connector;
148	int j;
149
150	if (!dssdev->driver) {
151		dev_warn(dev->dev, "%s has no driver.. skipping it\n",
152				dssdev->name);
153		return 0;
154	}
155
156	if (!(dssdev->driver->get_timings ||
157				dssdev->driver->read_edid)) {
158		dev_warn(dev->dev, "%s driver does not support "
159			"get_timings or read_edid.. skipping it!\n",
160			dssdev->name);
161		return 0;
162	}
163
164	connector = omap_connector_init(dev,
165			get_connector_type(dssdev), dssdev);
166
167	if (!connector) {
168		dev_err(dev->dev, "could not create connector: %s\n",
169				dssdev->name);
170		return -ENOMEM;
171	}
172
173	BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
174
175	priv->connectors[priv->num_connectors++] = connector;
176
177#if 0 /* enable when dss2 supports hotplug */
178	notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
179	notifier->notifier_call = omap_drm_notifier;
180	omap_dss_add_notify(dssdev, notifier);
181#else
182	notifier = NULL;
183#endif
184
185	for (j = 0; j < priv->num_encoders; j++) {
186		struct omap_overlay_manager *mgr =
187			omap_encoder_get_manager(priv->encoders[j]);
188		if (mgr->device == dssdev) {
189			drm_mode_connector_attach_encoder(connector,
190					priv->encoders[j]);
191		}
192	}
193
194	return 0;
195}
196
197/* create up to max_overlays CRTCs mapping to overlays.. by default,
198 * connect the overlays to different managers/encoders, giving priority
199 * to encoders connected to connectors with a detected connection
200 */
201static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
202		int *j, unsigned int connected_connectors)
203{
204	struct omap_drm_private *priv = dev->dev_private;
205	struct omap_overlay_manager *mgr = NULL;
206	struct drm_crtc *crtc;
207
208	/* find next best connector, ones with detected connection first
209	 */
210	while (*j < priv->num_connectors && !mgr) {
211		if (connected_connectors & (1 << *j)) {
212			struct drm_encoder *encoder =
213				omap_connector_attached_encoder(
214						priv->connectors[*j]);
215			if (encoder) {
216				mgr = omap_encoder_get_manager(encoder);
217			}
218		}
219		(*j)++;
220	}
221
222	/* if we couldn't find another connected connector, lets start
223	 * looking at the unconnected connectors:
224	 *
225	 * note: it might not be immediately apparent, but thanks to
226	 * the !mgr check in both this loop and the one above, the only
227	 * way to enter this loop is with *j == priv->num_connectors,
228	 * so idx can never go negative.
229	 */
230	while (*j < 2 * priv->num_connectors && !mgr) {
231		int idx = *j - priv->num_connectors;
232		if (!(connected_connectors & (1 << idx))) {
233			struct drm_encoder *encoder =
234				omap_connector_attached_encoder(
235						priv->connectors[idx]);
236			if (encoder) {
237				mgr = omap_encoder_get_manager(encoder);
238			}
239		}
240		(*j)++;
241	}
242
243	crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);
244
245	if (!crtc) {
246		dev_err(dev->dev, "could not create CRTC: %s\n",
247				ovl->name);
248		return -ENOMEM;
249	}
250
251	BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
252
253	priv->crtcs[priv->num_crtcs++] = crtc;
254
255	return 0;
256}
257
258static int create_plane(struct drm_device *dev, struct omap_overlay *ovl,
259		unsigned int possible_crtcs)
260{
261	struct omap_drm_private *priv = dev->dev_private;
262	struct drm_plane *plane =
263			omap_plane_init(dev, ovl, possible_crtcs, false);
264
265	if (!plane) {
266		dev_err(dev->dev, "could not create plane: %s\n",
267				ovl->name);
268		return -ENOMEM;
269	}
270
271	BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
272
273	priv->planes[priv->num_planes++] = plane;
274
275	return 0;
276}
277
278static int match_dev_name(struct omap_dss_device *dssdev, void *data)
279{
280	return !strcmp(dssdev->name, data);
281}
282
283static unsigned int detect_connectors(struct drm_device *dev)
284{
285	struct omap_drm_private *priv = dev->dev_private;
286	unsigned int connected_connectors = 0;
287	int i;
288
289	for (i = 0; i < priv->num_connectors; i++) {
290		struct drm_connector *connector = priv->connectors[i];
291		if (omap_connector_detect(connector, true) ==
292				connector_status_connected) {
293			connected_connectors |= (1 << i);
294		}
295	}
296
297	return connected_connectors;
298}
299
300static int omap_modeset_init(struct drm_device *dev)
301{
302	const struct omap_drm_platform_data *pdata = dev->dev->platform_data;
303	struct omap_kms_platform_data *kms_pdata = NULL;
304	struct omap_drm_private *priv = dev->dev_private;
305	struct omap_dss_device *dssdev = NULL;
306	int i, j;
307	unsigned int connected_connectors = 0;
308
309	drm_mode_config_init(dev);
310
311	if (pdata && pdata->kms_pdata) {
312		kms_pdata = pdata->kms_pdata;
313
314		/* if platform data is provided by the board file, use it to
315		 * control which overlays, managers, and devices we own.
316		 */
317		for (i = 0; i < kms_pdata->mgr_cnt; i++) {
318			struct omap_overlay_manager *mgr =
319				omap_dss_get_overlay_manager(
320						kms_pdata->mgr_ids[i]);
321			create_encoder(dev, mgr);
322		}
323
324		for (i = 0; i < kms_pdata->dev_cnt; i++) {
325			struct omap_dss_device *dssdev =
326				omap_dss_find_device(
327					(void *)kms_pdata->dev_names[i],
328					match_dev_name);
329			if (!dssdev) {
330				dev_warn(dev->dev, "no such dssdev: %s\n",
331						kms_pdata->dev_names[i]);
332				continue;
333			}
334			create_connector(dev, dssdev);
335		}
336
337		connected_connectors = detect_connectors(dev);
338
339		j = 0;
340		for (i = 0; i < kms_pdata->ovl_cnt; i++) {
341			struct omap_overlay *ovl =
342				omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
343			create_crtc(dev, ovl, &j, connected_connectors);
344		}
345
346		for (i = 0; i < kms_pdata->pln_cnt; i++) {
347			struct omap_overlay *ovl =
348				omap_dss_get_overlay(kms_pdata->pln_ids[i]);
349			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
350		}
351	} else {
352		/* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
353		 * to make educated guesses about everything else
354		 */
355		int max_overlays = min(omap_dss_get_num_overlays(), num_crtc);
356
357		for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
358			create_encoder(dev, omap_dss_get_overlay_manager(i));
359		}
360
361		for_each_dss_dev(dssdev) {
362			create_connector(dev, dssdev);
363		}
364
365		connected_connectors = detect_connectors(dev);
366
367		j = 0;
368		for (i = 0; i < max_overlays; i++) {
369			create_crtc(dev, omap_dss_get_overlay(i),
370					&j, connected_connectors);
371		}
372
373		/* use any remaining overlays as drm planes */
374		for (; i < omap_dss_get_num_overlays(); i++) {
375			struct omap_overlay *ovl = omap_dss_get_overlay(i);
376			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
377		}
378	}
379
380	/* for now keep the mapping of CRTCs and encoders static.. */
381	for (i = 0; i < priv->num_encoders; i++) {
382		struct drm_encoder *encoder = priv->encoders[i];
383		struct omap_overlay_manager *mgr =
384				omap_encoder_get_manager(encoder);
385
386		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
387
388		DBG("%s: possible_crtcs=%08x", mgr->name,
389					encoder->possible_crtcs);
390	}
391
392	dump_video_chains();
393
394	dev->mode_config.min_width = 32;
395	dev->mode_config.min_height = 32;
396
397	/* note: eventually will need some cpu_is_omapXYZ() type stuff here
398	 * to fill in these limits properly on different OMAP generations..
399	 */
400	dev->mode_config.max_width = 2048;
401	dev->mode_config.max_height = 2048;
402
403	dev->mode_config.funcs = &omap_mode_config_funcs;
404
405	return 0;
406}
407
408static void omap_modeset_free(struct drm_device *dev)
409{
410	drm_mode_config_cleanup(dev);
411}
412
413/*
414 * drm ioctl funcs
415 */
416
417
418static int ioctl_get_param(struct drm_device *dev, void *data,
419		struct drm_file *file_priv)
420{
421	struct drm_omap_param *args = data;
422
423	DBG("%p: param=%llu", dev, args->param);
424
425	switch (args->param) {
426	case OMAP_PARAM_CHIPSET_ID:
427		args->value = GET_OMAP_TYPE;
428		break;
429	default:
430		DBG("unknown parameter %lld", args->param);
431		return -EINVAL;
432	}
433
434	return 0;
435}
436
437static int ioctl_set_param(struct drm_device *dev, void *data,
438		struct drm_file *file_priv)
439{
440	struct drm_omap_param *args = data;
441
442	switch (args->param) {
443	default:
444		DBG("unknown parameter %lld", args->param);
445		return -EINVAL;
446	}
447
448	return 0;
449}
450
451static int ioctl_gem_new(struct drm_device *dev, void *data,
452		struct drm_file *file_priv)
453{
454	struct drm_omap_gem_new *args = data;
455	DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
456			args->size.bytes, args->flags);
457	return omap_gem_new_handle(dev, file_priv, args->size,
458			args->flags, &args->handle);
459}
460
461static int ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
462		struct drm_file *file_priv)
463{
464	struct drm_omap_gem_cpu_prep *args = data;
465	struct drm_gem_object *obj;
466	int ret;
467
468	VERB("%p:%p: handle=%d, op=%x", dev, file_priv, args->handle, args->op);
469
470	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
471	if (!obj) {
472		return -ENOENT;
473	}
474
475	ret = omap_gem_op_sync(obj, args->op);
476
477	if (!ret) {
478		ret = omap_gem_op_start(obj, args->op);
479	}
480
481	drm_gem_object_unreference_unlocked(obj);
482
483	return ret;
484}
485
486static int ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
487		struct drm_file *file_priv)
488{
489	struct drm_omap_gem_cpu_fini *args = data;
490	struct drm_gem_object *obj;
491	int ret;
492
493	VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
494
495	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
496	if (!obj) {
497		return -ENOENT;
498	}
499
500	/* XXX flushy, flushy */
501	ret = 0;
502
503	if (!ret) {
504		ret = omap_gem_op_finish(obj, args->op);
505	}
506
507	drm_gem_object_unreference_unlocked(obj);
508
509	return ret;
510}
511
512static int ioctl_gem_info(struct drm_device *dev, void *data,
513		struct drm_file *file_priv)
514{
515	struct drm_omap_gem_info *args = data;
516	struct drm_gem_object *obj;
517	int ret = 0;
518
519	DBG("%p:%p: handle=%d", dev, file_priv, args->handle);
520
521	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
522	if (!obj) {
523		return -ENOENT;
524	}
525
526	args->size = omap_gem_mmap_size(obj);
527	args->offset = omap_gem_mmap_offset(obj);
528
529	drm_gem_object_unreference_unlocked(obj);
530
531	return ret;
532}
533
534struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
535	DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
536	DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
537	DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
538	DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
539	DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
540	DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_UNLOCKED|DRM_AUTH),
541};
542
543/*
544 * drm driver funcs
545 */
546
547/**
548 * load - setup chip and create an initial config
549 * @dev: DRM device
550 * @flags: startup flags
551 *
552 * The driver load routine has to do several things:
553 *   - initialize the memory manager
554 *   - allocate initial config memory
555 *   - setup the DRM framebuffer with the allocated memory
556 */
557static int dev_load(struct drm_device *dev, unsigned long flags)
558{
559	struct omap_drm_private *priv;
560	int ret;
561
562	DBG("load: dev=%p", dev);
563
564	drm_device = dev;
565
566	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
567	if (!priv) {
568		dev_err(dev->dev, "could not allocate priv\n");
569		return -ENOMEM;
570	}
571
572	dev->dev_private = priv;
573
574	priv->wq = alloc_workqueue("omapdrm",
575			WQ_UNBOUND | WQ_NON_REENTRANT, 1);
576
577	INIT_LIST_HEAD(&priv->obj_list);
578
579	omap_gem_init(dev);
580
581	ret = omap_modeset_init(dev);
582	if (ret) {
583		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
584		dev->dev_private = NULL;
585		kfree(priv);
586		return ret;
587	}
588
589	priv->fbdev = omap_fbdev_init(dev);
590	if (!priv->fbdev) {
591		dev_warn(dev->dev, "omap_fbdev_init failed\n");
592		/* well, limp along without an fbdev.. maybe X11 will work? */
593	}
594
595	drm_kms_helper_poll_init(dev);
596
597	ret = drm_vblank_init(dev, priv->num_crtcs);
598	if (ret) {
599		dev_warn(dev->dev, "could not init vblank\n");
600	}
601
602	return 0;
603}
604
605static int dev_unload(struct drm_device *dev)
606{
607	struct omap_drm_private *priv = dev->dev_private;
608
609	DBG("unload: dev=%p", dev);
610
611	drm_vblank_cleanup(dev);
612	drm_kms_helper_poll_fini(dev);
613
614	omap_fbdev_free(dev);
615	omap_modeset_free(dev);
616	omap_gem_deinit(dev);
617
618	flush_workqueue(priv->wq);
619	destroy_workqueue(priv->wq);
620
621	kfree(dev->dev_private);
622	dev->dev_private = NULL;
623
624	return 0;
625}
626
627static int dev_open(struct drm_device *dev, struct drm_file *file)
628{
629	file->driver_priv = NULL;
630
631	DBG("open: dev=%p, file=%p", dev, file);
632
633	return 0;
634}
635
636static int dev_firstopen(struct drm_device *dev)
637{
638	DBG("firstopen: dev=%p", dev);
639	return 0;
640}
641
642/**
643 * lastclose - clean up after all DRM clients have exited
644 * @dev: DRM device
645 *
646 * Take care of cleaning up after all DRM clients have exited.  In the
647 * mode setting case, we want to restore the kernel's initial mode (just
648 * in case the last client left us in a bad state).
649 */
650static void dev_lastclose(struct drm_device *dev)
651{
652	/* we don't support vga-switcheroo.. so just make sure the fbdev
653	 * mode is active
654	 */
655	struct omap_drm_private *priv = dev->dev_private;
656	int ret;
657
658	DBG("lastclose: dev=%p", dev);
659
660	ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
661	if (ret)
662		DBG("failed to restore crtc mode");
663}
664
665static void dev_preclose(struct drm_device *dev, struct drm_file *file)
666{
667	DBG("preclose: dev=%p", dev);
668}
669
670static void dev_postclose(struct drm_device *dev, struct drm_file *file)
671{
672	DBG("postclose: dev=%p, file=%p", dev, file);
673}
674
675/**
676 * enable_vblank - enable vblank interrupt events
677 * @dev: DRM device
678 * @crtc: which irq to enable
679 *
680 * Enable vblank interrupts for @crtc.  If the device doesn't have
681 * a hardware vblank counter, this routine should be a no-op, since
682 * interrupts will have to stay on to keep the count accurate.
683 *
684 * RETURNS
685 * Zero on success, appropriate errno if the given @crtc's vblank
686 * interrupt cannot be enabled.
687 */
688static int dev_enable_vblank(struct drm_device *dev, int crtc)
689{
690	DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc);
691	return 0;
692}
693
694/**
695 * disable_vblank - disable vblank interrupt events
696 * @dev: DRM device
697 * @crtc: which irq to enable
698 *
699 * Disable vblank interrupts for @crtc.  If the device doesn't have
700 * a hardware vblank counter, this routine should be a no-op, since
701 * interrupts will have to stay on to keep the count accurate.
702 */
703static void dev_disable_vblank(struct drm_device *dev, int crtc)
704{
705	DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc);
706}
707
708static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS)
709{
710	return IRQ_HANDLED;
711}
712
713static void dev_irq_preinstall(struct drm_device *dev)
714{
715	DBG("irq_preinstall: dev=%p", dev);
716}
717
718static int dev_irq_postinstall(struct drm_device *dev)
719{
720	DBG("irq_postinstall: dev=%p", dev);
721	return 0;
722}
723
724static void dev_irq_uninstall(struct drm_device *dev)
725{
726	DBG("irq_uninstall: dev=%p", dev);
727}
728
729static const struct vm_operations_struct omap_gem_vm_ops = {
730	.fault = omap_gem_fault,
731	.open = drm_gem_vm_open,
732	.close = drm_gem_vm_close,
733};
734
735static const struct file_operations omapdriver_fops = {
736		.owner = THIS_MODULE,
737		.open = drm_open,
738		.unlocked_ioctl = drm_ioctl,
739		.release = drm_release,
740		.mmap = omap_gem_mmap,
741		.poll = drm_poll,
742		.fasync = drm_fasync,
743		.read = drm_read,
744		.llseek = noop_llseek,
745};
746
747static struct drm_driver omap_drm_driver = {
748		.driver_features =
749				DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
750		.load = dev_load,
751		.unload = dev_unload,
752		.open = dev_open,
753		.firstopen = dev_firstopen,
754		.lastclose = dev_lastclose,
755		.preclose = dev_preclose,
756		.postclose = dev_postclose,
757		.get_vblank_counter = drm_vblank_count,
758		.enable_vblank = dev_enable_vblank,
759		.disable_vblank = dev_disable_vblank,
760		.irq_preinstall = dev_irq_preinstall,
761		.irq_postinstall = dev_irq_postinstall,
762		.irq_uninstall = dev_irq_uninstall,
763		.irq_handler = dev_irq_handler,
764		.reclaim_buffers = drm_core_reclaim_buffers,
765#ifdef CONFIG_DEBUG_FS
766		.debugfs_init = omap_debugfs_init,
767		.debugfs_cleanup = omap_debugfs_cleanup,
768#endif
769		.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
770		.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
771		.gem_prime_export = omap_gem_prime_export,
772		.gem_prime_import = omap_gem_prime_import,
773		.gem_init_object = omap_gem_init_object,
774		.gem_free_object = omap_gem_free_object,
775		.gem_vm_ops = &omap_gem_vm_ops,
776		.dumb_create = omap_gem_dumb_create,
777		.dumb_map_offset = omap_gem_dumb_map_offset,
778		.dumb_destroy = omap_gem_dumb_destroy,
779		.ioctls = ioctls,
780		.num_ioctls = DRM_OMAP_NUM_IOCTLS,
781		.fops = &omapdriver_fops,
782		.name = DRIVER_NAME,
783		.desc = DRIVER_DESC,
784		.date = DRIVER_DATE,
785		.major = DRIVER_MAJOR,
786		.minor = DRIVER_MINOR,
787		.patchlevel = DRIVER_PATCHLEVEL,
788};
789
790static int pdev_suspend(struct platform_device *pDevice, pm_message_t state)
791{
792	DBG("");
793	return 0;
794}
795
796static int pdev_resume(struct platform_device *device)
797{
798	DBG("");
799	return 0;
800}
801
802static void pdev_shutdown(struct platform_device *device)
803{
804	DBG("");
805}
806
807static int pdev_probe(struct platform_device *device)
808{
809	DBG("%s", device->name);
810	return drm_platform_init(&omap_drm_driver, device);
811}
812
813static int pdev_remove(struct platform_device *device)
814{
815	DBG("");
816	drm_platform_exit(&omap_drm_driver, device);
817
818	platform_driver_unregister(&omap_dmm_driver);
819	return 0;
820}
821
822struct platform_driver pdev = {
823		.driver = {
824			.name = DRIVER_NAME,
825			.owner = THIS_MODULE,
826		},
827		.probe = pdev_probe,
828		.remove = pdev_remove,
829		.suspend = pdev_suspend,
830		.resume = pdev_resume,
831		.shutdown = pdev_shutdown,
832};
833
834static int __init omap_drm_init(void)
835{
836	DBG("init");
837	if (platform_driver_register(&omap_dmm_driver)) {
838		/* we can continue on without DMM.. so not fatal */
839		dev_err(NULL, "DMM registration failed\n");
840	}
841	return platform_driver_register(&pdev);
842}
843
844static void __exit omap_drm_fini(void)
845{
846	DBG("fini");
847	platform_driver_unregister(&pdev);
848}
849
850/* need late_initcall() so we load after dss_driver's are loaded */
851late_initcall(omap_drm_init);
852module_exit(omap_drm_fini);
853
854MODULE_AUTHOR("Rob Clark <rob@ti.com>");
855MODULE_DESCRIPTION("OMAP DRM Display Driver");
856MODULE_ALIAS("platform:" DRIVER_NAME);
857MODULE_LICENSE("GPL v2");