xref: /freebsd-src/sys/dev/drm2/drm_platform.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1592ffb21SWarner Losh /*
2592ffb21SWarner Losh  * Derived from drm_pci.c
3592ffb21SWarner Losh  *
4592ffb21SWarner Losh  * Copyright 2003 José Fonseca.
5592ffb21SWarner Losh  * Copyright 2003 Leif Delgass.
6592ffb21SWarner Losh  * Copyright (c) 2009, Code Aurora Forum.
7592ffb21SWarner Losh  * All Rights Reserved.
8592ffb21SWarner Losh  *
9592ffb21SWarner Losh  * Permission is hereby granted, free of charge, to any person obtaining a
10592ffb21SWarner Losh  * copy of this software and associated documentation files (the "Software"),
11592ffb21SWarner Losh  * to deal in the Software without restriction, including without limitation
12592ffb21SWarner Losh  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13592ffb21SWarner Losh  * and/or sell copies of the Software, and to permit persons to whom the
14592ffb21SWarner Losh  * Software is furnished to do so, subject to the following conditions:
15592ffb21SWarner Losh  *
16592ffb21SWarner Losh  * The above copyright notice and this permission notice (including the next
17592ffb21SWarner Losh  * paragraph) shall be included in all copies or substantial portions of the
18592ffb21SWarner Losh  * Software.
19592ffb21SWarner Losh  *
20592ffb21SWarner Losh  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21592ffb21SWarner Losh  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22592ffb21SWarner Losh  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23592ffb21SWarner Losh  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24592ffb21SWarner Losh  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25592ffb21SWarner Losh  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26592ffb21SWarner Losh  */
27592ffb21SWarner Losh #include <sys/cdefs.h>
28592ffb21SWarner Losh #include <dev/drm2/drmP.h>
29592ffb21SWarner Losh 
drm_platform_free_irq(struct drm_device * dev)30592ffb21SWarner Losh static void drm_platform_free_irq(struct drm_device *dev)
31592ffb21SWarner Losh {
32592ffb21SWarner Losh 	if (dev->irqr == NULL)
33592ffb21SWarner Losh 		return;
34592ffb21SWarner Losh 
35592ffb21SWarner Losh 	bus_release_resource(dev->dev, SYS_RES_IRQ,
36592ffb21SWarner Losh 	    dev->irqrid, dev->irqr);
37592ffb21SWarner Losh 
38592ffb21SWarner Losh 	dev->irqr = NULL;
39592ffb21SWarner Losh 	dev->irq = 0;
40592ffb21SWarner Losh }
41592ffb21SWarner Losh 
drm_platform_get_name(struct drm_device * dev)42592ffb21SWarner Losh static const char *drm_platform_get_name(struct drm_device *dev)
43592ffb21SWarner Losh {
44592ffb21SWarner Losh 	return dev->driver->name;
45592ffb21SWarner Losh }
46592ffb21SWarner Losh 
drm_platform_set_busid(struct drm_device * dev,struct drm_master * master)47592ffb21SWarner Losh static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master)
48592ffb21SWarner Losh {
49592ffb21SWarner Losh 	int len, ret, id;
50592ffb21SWarner Losh 
51592ffb21SWarner Losh 	master->unique_len = 13 + strlen(dev->driver->name);
52592ffb21SWarner Losh 	master->unique_size = master->unique_len;
53592ffb21SWarner Losh 	master->unique = malloc(master->unique_len + 1, DRM_MEM_DRIVER, M_NOWAIT);
54592ffb21SWarner Losh 
55592ffb21SWarner Losh 	if (master->unique == NULL)
56592ffb21SWarner Losh 		return -ENOMEM;
57592ffb21SWarner Losh 
58592ffb21SWarner Losh 	id = 0; // XXX dev->driver->id;
59592ffb21SWarner Losh 
60592ffb21SWarner Losh 	/* if only a single instance of the platform device, id will be
61592ffb21SWarner Losh 	 * set to -1.. use 0 instead to avoid a funny looking bus-id:
62592ffb21SWarner Losh 	 */
63592ffb21SWarner Losh 	if (id == -1)
64592ffb21SWarner Losh 		id = 0;
65592ffb21SWarner Losh 
66592ffb21SWarner Losh 	len = snprintf(master->unique, master->unique_len,
67592ffb21SWarner Losh 			"platform:%s:%02d", dev->driver->name, id);
68592ffb21SWarner Losh 
69592ffb21SWarner Losh 	if (len > master->unique_len) {
70592ffb21SWarner Losh 		DRM_ERROR("Unique buffer overflowed\n");
71592ffb21SWarner Losh 		ret = -EINVAL;
72592ffb21SWarner Losh 		goto err;
73592ffb21SWarner Losh 	}
74592ffb21SWarner Losh 
75592ffb21SWarner Losh 	return 0;
76592ffb21SWarner Losh err:
77592ffb21SWarner Losh 	return ret;
78592ffb21SWarner Losh }
79592ffb21SWarner Losh 
drm_platform_get_irq(struct drm_device * dev)80592ffb21SWarner Losh static int drm_platform_get_irq(struct drm_device *dev)
81592ffb21SWarner Losh {
82592ffb21SWarner Losh 	if (dev->irqr)
83592ffb21SWarner Losh 		return (dev->irq);
84592ffb21SWarner Losh 
85592ffb21SWarner Losh 	dev->irqr = bus_alloc_resource_any(dev->dev, SYS_RES_IRQ,
86592ffb21SWarner Losh 	    &dev->irqrid, RF_SHAREABLE);
87592ffb21SWarner Losh 	if (!dev->irqr) {
88592ffb21SWarner Losh 		dev_err(dev->dev, "Failed to allocate IRQ\n");
89592ffb21SWarner Losh 		return (0);
90592ffb21SWarner Losh 	}
91592ffb21SWarner Losh 
92592ffb21SWarner Losh 	dev->irq = (int) rman_get_start(dev->irqr);
93592ffb21SWarner Losh 
94592ffb21SWarner Losh 	return (dev->irq);
95592ffb21SWarner Losh }
96592ffb21SWarner Losh 
97592ffb21SWarner Losh static struct drm_bus drm_platform_bus = {
98592ffb21SWarner Losh 	.bus_type = DRIVER_BUS_PLATFORM,
99592ffb21SWarner Losh 	.get_irq = drm_platform_get_irq,
100592ffb21SWarner Losh 	.free_irq = drm_platform_free_irq,
101592ffb21SWarner Losh 	.get_name = drm_platform_get_name,
102592ffb21SWarner Losh 	.set_busid = drm_platform_set_busid,
103592ffb21SWarner Losh };
104592ffb21SWarner Losh 
105592ffb21SWarner Losh /**
106592ffb21SWarner Losh  * Register.
107592ffb21SWarner Losh  *
108*17db4b52SGordon Bergling  * \param platdev - Platform device structure
109592ffb21SWarner Losh  * \return zero on success or a negative number on failure.
110592ffb21SWarner Losh  *
111592ffb21SWarner Losh  * Attempt to gets inter module "drm" information. If we are first
112592ffb21SWarner Losh  * then register the character device and inter module information.
113592ffb21SWarner Losh  * Try and register, if we fail to register, backout previous work.
114592ffb21SWarner Losh  */
115592ffb21SWarner Losh 
drm_get_platform_dev(device_t kdev,struct drm_device * dev,struct drm_driver * driver)116592ffb21SWarner Losh int drm_get_platform_dev(device_t kdev, struct drm_device *dev,
117592ffb21SWarner Losh 			 struct drm_driver *driver)
118592ffb21SWarner Losh {
119592ffb21SWarner Losh 	int ret;
120592ffb21SWarner Losh 
121592ffb21SWarner Losh 	DRM_DEBUG("\n");
122592ffb21SWarner Losh 
123592ffb21SWarner Losh 	driver->bus = &drm_platform_bus;
124592ffb21SWarner Losh 
125592ffb21SWarner Losh 	dev->dev = kdev;
126592ffb21SWarner Losh 
127592ffb21SWarner Losh 	sx_xlock(&drm_global_mutex);
128592ffb21SWarner Losh 
129592ffb21SWarner Losh 	ret = drm_fill_in_dev(dev, driver);
130592ffb21SWarner Losh 
131592ffb21SWarner Losh 	if (ret) {
132592ffb21SWarner Losh 		printf("DRM: Fill_in_dev failed.\n");
133592ffb21SWarner Losh 		goto err_g1;
134592ffb21SWarner Losh 	}
135592ffb21SWarner Losh 
136592ffb21SWarner Losh 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
137592ffb21SWarner Losh 		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
138592ffb21SWarner Losh 		if (ret)
139592ffb21SWarner Losh 			goto err_g1;
140592ffb21SWarner Losh 	}
141592ffb21SWarner Losh 
142592ffb21SWarner Losh 	ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
143592ffb21SWarner Losh 	if (ret)
144592ffb21SWarner Losh 		goto err_g2;
145592ffb21SWarner Losh 
146592ffb21SWarner Losh 	if (dev->driver->load) {
147592ffb21SWarner Losh 		ret = dev->driver->load(dev, 0);
148592ffb21SWarner Losh 		if (ret)
149592ffb21SWarner Losh 			goto err_g3;
150592ffb21SWarner Losh 	}
151592ffb21SWarner Losh 
152592ffb21SWarner Losh 	/* setup the grouping for the legacy output */
153592ffb21SWarner Losh 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
154592ffb21SWarner Losh 		ret = drm_mode_group_init_legacy_group(dev,
155592ffb21SWarner Losh 				&dev->primary->mode_group);
156592ffb21SWarner Losh 		if (ret)
157592ffb21SWarner Losh 			goto err_g3;
158592ffb21SWarner Losh 	}
159592ffb21SWarner Losh 
160592ffb21SWarner Losh #ifdef FREEBSD_NOTYET
161592ffb21SWarner Losh 	list_add_tail(&dev->driver_item, &driver->device_list);
162592ffb21SWarner Losh #endif /* FREEBSD_NOTYET */
163592ffb21SWarner Losh 
164592ffb21SWarner Losh 	sx_xunlock(&drm_global_mutex);
165592ffb21SWarner Losh 
166592ffb21SWarner Losh 	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
167592ffb21SWarner Losh 		 driver->name, driver->major, driver->minor, driver->patchlevel,
168592ffb21SWarner Losh 		 driver->date, dev->primary->index);
169592ffb21SWarner Losh 
170592ffb21SWarner Losh 	return 0;
171592ffb21SWarner Losh 
172592ffb21SWarner Losh err_g3:
173592ffb21SWarner Losh 	drm_put_minor(&dev->primary);
174592ffb21SWarner Losh err_g2:
175592ffb21SWarner Losh 	if (drm_core_check_feature(dev, DRIVER_MODESET))
176592ffb21SWarner Losh 		drm_put_minor(&dev->control);
177592ffb21SWarner Losh err_g1:
178592ffb21SWarner Losh 	sx_xunlock(&drm_global_mutex);
179592ffb21SWarner Losh 	return ret;
180592ffb21SWarner Losh }
181592ffb21SWarner Losh EXPORT_SYMBOL(drm_get_platform_dev);
182