1310599Smmel/*
2310599Smmel * Derived from drm_pci.c
3310599Smmel *
4310599Smmel * Copyright 2003 Jos�� Fonseca.
5310599Smmel * Copyright 2003 Leif Delgass.
6310599Smmel * Copyright (c) 2009, Code Aurora Forum.
7310599Smmel * All Rights Reserved.
8310599Smmel *
9310599Smmel * Permission is hereby granted, free of charge, to any person obtaining a
10310599Smmel * copy of this software and associated documentation files (the "Software"),
11310599Smmel * to deal in the Software without restriction, including without limitation
12310599Smmel * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13310599Smmel * and/or sell copies of the Software, and to permit persons to whom the
14310599Smmel * Software is furnished to do so, subject to the following conditions:
15310599Smmel *
16310599Smmel * The above copyright notice and this permission notice (including the next
17310599Smmel * paragraph) shall be included in all copies or substantial portions of the
18310599Smmel * Software.
19310599Smmel *
20310599Smmel * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21310599Smmel * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22310599Smmel * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23310599Smmel * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24310599Smmel * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25310599Smmel * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26310599Smmel */
27310599Smmel#include <sys/cdefs.h>
28310599Smmel__FBSDID("$FreeBSD: stable/11/sys/dev/drm2/drm_platform.c 317011 2017-04-16 08:07:38Z mmel $");
29310599Smmel
30310599Smmel#include <dev/drm2/drmP.h>
31310599Smmel
32310599Smmelstatic void drm_platform_free_irq(struct drm_device *dev)
33310599Smmel{
34310599Smmel	if (dev->irqr == NULL)
35310599Smmel		return;
36310599Smmel
37310599Smmel	bus_release_resource(dev->dev, SYS_RES_IRQ,
38310599Smmel	    dev->irqrid, dev->irqr);
39310599Smmel
40310599Smmel	dev->irqr = NULL;
41310599Smmel	dev->irq = 0;
42310599Smmel}
43310599Smmel
44310599Smmelstatic const char *drm_platform_get_name(struct drm_device *dev)
45310599Smmel{
46310599Smmel	return dev->driver->name;
47310599Smmel}
48310599Smmel
49310599Smmelstatic int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master)
50310599Smmel{
51310599Smmel	int len, ret, id;
52310599Smmel
53310599Smmel	master->unique_len = 13 + strlen(dev->driver->name);
54310599Smmel	master->unique_size = master->unique_len;
55310599Smmel	master->unique = malloc(master->unique_len + 1, DRM_MEM_DRIVER, M_NOWAIT);
56310599Smmel
57310599Smmel	if (master->unique == NULL)
58310599Smmel		return -ENOMEM;
59310599Smmel
60310599Smmel	id = 0; // XXX dev->driver->id;
61310599Smmel
62310599Smmel	/* if only a single instance of the platform device, id will be
63310599Smmel	 * set to -1.. use 0 instead to avoid a funny looking bus-id:
64310599Smmel	 */
65310599Smmel	if (id == -1)
66310599Smmel		id = 0;
67310599Smmel
68310599Smmel	len = snprintf(master->unique, master->unique_len,
69310599Smmel			"platform:%s:%02d", dev->driver->name, id);
70310599Smmel
71310599Smmel	if (len > master->unique_len) {
72310599Smmel		DRM_ERROR("Unique buffer overflowed\n");
73310599Smmel		ret = -EINVAL;
74310599Smmel		goto err;
75310599Smmel	}
76310599Smmel
77310599Smmel	return 0;
78310599Smmelerr:
79310599Smmel	return ret;
80310599Smmel}
81310599Smmel
82310599Smmelstatic int drm_platform_get_irq(struct drm_device *dev)
83310599Smmel{
84310599Smmel	if (dev->irqr)
85310599Smmel		return (dev->irq);
86310599Smmel
87310599Smmel	dev->irqr = bus_alloc_resource_any(dev->dev, SYS_RES_IRQ,
88310599Smmel	    &dev->irqrid, RF_SHAREABLE);
89310599Smmel	if (!dev->irqr) {
90310599Smmel		dev_err(dev->dev, "Failed to allocate IRQ\n");
91310599Smmel		return (0);
92310599Smmel	}
93310599Smmel
94310599Smmel	dev->irq = (int) rman_get_start(dev->irqr);
95310599Smmel
96310599Smmel	return (dev->irq);
97310599Smmel}
98310599Smmel
99310599Smmelstatic struct drm_bus drm_platform_bus = {
100310599Smmel	.bus_type = DRIVER_BUS_PLATFORM,
101310599Smmel	.get_irq = drm_platform_get_irq,
102310599Smmel	.free_irq = drm_platform_free_irq,
103310599Smmel	.get_name = drm_platform_get_name,
104310599Smmel	.set_busid = drm_platform_set_busid,
105310599Smmel};
106310599Smmel
107310599Smmel/**
108310599Smmel * Register.
109310599Smmel *
110310599Smmel * \param platdev - Platform device struture
111310599Smmel * \return zero on success or a negative number on failure.
112310599Smmel *
113310599Smmel * Attempt to gets inter module "drm" information. If we are first
114310599Smmel * then register the character device and inter module information.
115310599Smmel * Try and register, if we fail to register, backout previous work.
116310599Smmel */
117310599Smmel
118310599Smmelint drm_get_platform_dev(device_t kdev, struct drm_device *dev,
119310599Smmel			 struct drm_driver *driver)
120310599Smmel{
121310599Smmel	int ret;
122310599Smmel
123310599Smmel	DRM_DEBUG("\n");
124310599Smmel
125310599Smmel	driver->bus = &drm_platform_bus;
126310599Smmel
127310599Smmel	dev->dev = kdev;
128310599Smmel
129310599Smmel	sx_xlock(&drm_global_mutex);
130310599Smmel
131310599Smmel	ret = drm_fill_in_dev(dev, driver);
132310599Smmel
133310599Smmel	if (ret) {
134310599Smmel		printf("DRM: Fill_in_dev failed.\n");
135310599Smmel		goto err_g1;
136310599Smmel	}
137310599Smmel
138310599Smmel	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
139310599Smmel		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
140310599Smmel		if (ret)
141310599Smmel			goto err_g1;
142310599Smmel	}
143310599Smmel
144310599Smmel	ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
145310599Smmel	if (ret)
146310599Smmel		goto err_g2;
147310599Smmel
148310599Smmel	if (dev->driver->load) {
149310599Smmel		ret = dev->driver->load(dev, 0);
150310599Smmel		if (ret)
151310599Smmel			goto err_g3;
152310599Smmel	}
153310599Smmel
154310599Smmel	/* setup the grouping for the legacy output */
155310599Smmel	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
156310599Smmel		ret = drm_mode_group_init_legacy_group(dev,
157310599Smmel				&dev->primary->mode_group);
158310599Smmel		if (ret)
159310599Smmel			goto err_g3;
160310599Smmel	}
161310599Smmel
162310599Smmel#ifdef FREEBSD_NOTYET
163310599Smmel	list_add_tail(&dev->driver_item, &driver->device_list);
164310599Smmel#endif /* FREEBSD_NOTYET */
165310599Smmel
166310599Smmel	sx_xunlock(&drm_global_mutex);
167310599Smmel
168310599Smmel	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
169310599Smmel		 driver->name, driver->major, driver->minor, driver->patchlevel,
170310599Smmel		 driver->date, dev->primary->index);
171310599Smmel
172310599Smmel	return 0;
173310599Smmel
174310599Smmelerr_g3:
175310599Smmel	drm_put_minor(&dev->primary);
176310599Smmelerr_g2:
177310599Smmel	if (drm_core_check_feature(dev, DRIVER_MODESET))
178310599Smmel		drm_put_minor(&dev->control);
179310599Smmelerr_g1:
180310599Smmel	sx_xunlock(&drm_global_mutex);
181310599Smmel	return ret;
182310599Smmel}
183310599SmmelEXPORT_SYMBOL(drm_get_platform_dev);
184