xref: /netbsd-src/sys/external/bsd/drm2/drm/drm_module.c (revision ee3f67d30ddd501a2a20cee0433575f31d9c3dbf)
1*ee3f67d3Sriastradh /*	$NetBSD: drm_module.c,v 1.32 2023/09/05 20:15:10 riastradh Exp $	*/
26cb10275Sriastradh 
36cb10275Sriastradh /*-
46cb10275Sriastradh  * Copyright (c) 2013 The NetBSD Foundation, Inc.
56cb10275Sriastradh  * All rights reserved.
66cb10275Sriastradh  *
76cb10275Sriastradh  * This code is derived from software contributed to The NetBSD Foundation
86cb10275Sriastradh  * by Taylor R. Campbell.
96cb10275Sriastradh  *
106cb10275Sriastradh  * Redistribution and use in source and binary forms, with or without
116cb10275Sriastradh  * modification, are permitted provided that the following conditions
126cb10275Sriastradh  * are met:
136cb10275Sriastradh  * 1. Redistributions of source code must retain the above copyright
146cb10275Sriastradh  *    notice, this list of conditions and the following disclaimer.
156cb10275Sriastradh  * 2. Redistributions in binary form must reproduce the above copyright
166cb10275Sriastradh  *    notice, this list of conditions and the following disclaimer in the
176cb10275Sriastradh  *    documentation and/or other materials provided with the distribution.
186cb10275Sriastradh  *
196cb10275Sriastradh  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
206cb10275Sriastradh  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216cb10275Sriastradh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226cb10275Sriastradh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
236cb10275Sriastradh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246cb10275Sriastradh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256cb10275Sriastradh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266cb10275Sriastradh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276cb10275Sriastradh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286cb10275Sriastradh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296cb10275Sriastradh  * POSSIBILITY OF SUCH DAMAGE.
306cb10275Sriastradh  */
316cb10275Sriastradh 
326cb10275Sriastradh #include <sys/cdefs.h>
33*ee3f67d3Sriastradh __KERNEL_RCSID(0, "$NetBSD: drm_module.c,v 1.32 2023/09/05 20:15:10 riastradh Exp $");
346cb10275Sriastradh 
356cb10275Sriastradh #include <sys/types.h>
3626e846f0Sriastradh #include <sys/condvar.h>
376585c4c4Sriastradh #include <sys/conf.h>
386cb10275Sriastradh #include <sys/device.h>
396cb10275Sriastradh #include <sys/module.h>
4026e846f0Sriastradh #include <sys/mutex.h>
4177b5597aSriastradh #include <sys/once.h>
42c5f5d171Sriastradh #include <sys/reboot.h>
436cb10275Sriastradh #include <sys/systm.h>
446cb10275Sriastradh 
4577b5597aSriastradh #include <linux/mutex.h>
4677b5597aSriastradh 
478fe3f4a7Sriastradh #include <drm/drm_agpsupport.h>
48429b039cSriastradh #include <drm/drm_bridge.h>
49f21b21b0Sriastradh #include <drm/drm_device.h>
50c48dc052Sriastradh #include <drm/drm_encoder_slave.h>
51453c4aa9Sjmcneill #include <drm/drm_panel.h>
528fe3f4a7Sriastradh #include <drm/drm_print.h>
53f21b21b0Sriastradh #include <drm/drm_sysctl.h>
546cb10275Sriastradh 
55dafabe62Sriastradh #include "../dist/drm/drm_crtc_internal.h"
563f26b5c5Sriastradh #include "../dist/drm/drm_internal.h"
573f26b5c5Sriastradh 
586cb10275Sriastradh /*
59d46aeca2Sriastradh  * XXX This is stupid.
60d46aeca2Sriastradh  *
61d46aeca2Sriastradh  * 1. Builtin modules are broken: they don't get initialized before
62d46aeca2Sriastradh  *    autoconf matches devices, but we need the initialization to be
63d46aeca2Sriastradh  *    run in order to match and attach drmkms drivers.
64d46aeca2Sriastradh  *
65d46aeca2Sriastradh  * 2. The following dependencies are _not_ correct:
66d46aeca2Sriastradh  *    - drmkms can't depend on agp because not all drmkms drivers run
67d46aeca2Sriastradh  *      on platforms guaranteed to have pci, let alone agp
68d46aeca2Sriastradh  *    - drmkms_pci can't depend on agp because not all _pci_ has agp
69d46aeca2Sriastradh  *      (e.g., tegra)
70d46aeca2Sriastradh  *    - radeon (e.g.) can't depend on agp because not all radeon
71d46aeca2Sriastradh  *      devices are on platforms guaranteed to have agp
72d46aeca2Sriastradh  *
73d46aeca2Sriastradh  * 3. We need to register the agp hooks before we try to attach a
74d46aeca2Sriastradh  *    device.
75d46aeca2Sriastradh  *
76d46aeca2Sriastradh  * 4. The only mechanism we have to force this is the
77d46aeca2Sriastradh  *    mumblefrotz_guarantee_initialized kludge.
78d46aeca2Sriastradh  *
79d46aeca2Sriastradh  * 5. We don't know if we even _can_ call
80d46aeca2Sriastradh  *    drmkms_agp_guarantee_initialized unless we know NAGP.
81d46aeca2Sriastradh  *
82d46aeca2Sriastradh  * 6. We don't know NAGP unless we include "agp.h".
83d46aeca2Sriastradh  *
84d46aeca2Sriastradh  * 7. We can't include "agp.h" if the platform has agp.
85d46aeca2Sriastradh  *
86d46aeca2Sriastradh  * 8. The way we determine whether we have agp is NAGP.
87d46aeca2Sriastradh  *
88d46aeca2Sriastradh  * 9. @!*#&^@&*@!&^#@
89d46aeca2Sriastradh  */
90d46aeca2Sriastradh #if defined(__powerpc__) || defined(__i386__) || defined(__x86_64__)
91d46aeca2Sriastradh #include "agp.h"
92*ee3f67d3Sriastradh #include "drmkms_pci.h"
93d46aeca2Sriastradh #endif
94d46aeca2Sriastradh 
95d46aeca2Sriastradh /*
966cb10275Sriastradh  * XXX I2C stuff should be moved to a separate drmkms_i2c module.
976cb10275Sriastradh  */
981c26109fSriastradh MODULE(MODULE_CLASS_DRIVER, drmkms, "drmkms_linux,sysmon_power");
996cb10275Sriastradh 
10077b5597aSriastradh struct mutex	drm_global_mutex;
10177b5597aSriastradh 
1028ba1623fSchristos struct drm_sysctl_def drm_def = DRM_SYSCTL_INIT();
1038ba1623fSchristos 
10477b5597aSriastradh static int
drm_init(void)10577b5597aSriastradh drm_init(void)
10677b5597aSriastradh {
10777b5597aSriastradh 	extern int linux_guarantee_initialized(void);
10877b5597aSriastradh 	int error;
10977b5597aSriastradh 
11077b5597aSriastradh 	error = linux_guarantee_initialized();
11177b5597aSriastradh 	if (error)
11277b5597aSriastradh 		return error;
11377b5597aSriastradh 
11477fcb07cSriastradh 	extern bool drm_core_init_complete;
11577fcb07cSriastradh 	drm_core_init_complete = true;
11677fcb07cSriastradh 
117d46aeca2Sriastradh 	drm_agp_hooks_init();
118*ee3f67d3Sriastradh #if NDRMKMS_PCI > 0 && NAGP > 0
119d46aeca2Sriastradh 	extern int drmkms_agp_guarantee_initialized(void);
120d46aeca2Sriastradh 	error = drmkms_agp_guarantee_initialized();
121d46aeca2Sriastradh 	if (error) {
122d46aeca2Sriastradh 		drm_agp_hooks_fini();
123d46aeca2Sriastradh 		return error;
124d46aeca2Sriastradh 	}
125d46aeca2Sriastradh #endif
126d46aeca2Sriastradh 
12777b5597aSriastradh 	if (ISSET(boothowto, AB_DEBUG))
1285fb65ca2Sriastradh 		__drm_debug = DRM_UT_DRIVER;
12977b5597aSriastradh 
13077b5597aSriastradh 	spin_lock_init(&drm_minor_lock);
13177b5597aSriastradh 	idr_init(&drm_minors_idr);
1329e5fbd4fSriastradh 	_init_srcu_struct(&drm_unplug_srcu, "drmunplg");
13377b5597aSriastradh 	linux_mutex_init(&drm_global_mutex);
1340f849473Sriastradh 	linux_mutex_init(&drm_kernel_fb_helper_lock);
13577b5597aSriastradh 	drm_connector_ida_init();
136453c4aa9Sjmcneill 	drm_panel_init_lock();
137453c4aa9Sjmcneill 	drm_bridge_init_lock();
1388ba1623fSchristos 	drm_sysctl_init(&drm_def);
139c48dc052Sriastradh 	drm_i2c_encoders_init();
14077b5597aSriastradh 
14177b5597aSriastradh 	return 0;
14277b5597aSriastradh }
14377b5597aSriastradh 
14477b5597aSriastradh int
drm_guarantee_initialized(void)14577b5597aSriastradh drm_guarantee_initialized(void)
14677b5597aSriastradh {
147185e03d3Sriastradh #ifdef _MODULE
14877b5597aSriastradh 	return 0;
149185e03d3Sriastradh #else
15077b5597aSriastradh 	static ONCE_DECL(drm_init_once);
15177b5597aSriastradh 
15277b5597aSriastradh 	return RUN_ONCE(&drm_init_once, &drm_init);
1536cb10275Sriastradh #endif
15477b5597aSriastradh }
15577b5597aSriastradh 
15677b5597aSriastradh static void
drm_fini(void)15777b5597aSriastradh drm_fini(void)
15877b5597aSriastradh {
159c48dc052Sriastradh 
160c48dc052Sriastradh 	drm_i2c_encoders_fini();
1618ba1623fSchristos 	drm_sysctl_fini(&drm_def);
162453c4aa9Sjmcneill 	drm_bridge_fini_lock();
163453c4aa9Sjmcneill 	drm_panel_fini_lock();
16477b5597aSriastradh 	drm_connector_ida_destroy();
1650f849473Sriastradh 	linux_mutex_destroy(&drm_kernel_fb_helper_lock);
16677b5597aSriastradh 	linux_mutex_destroy(&drm_global_mutex);
1679e5fbd4fSriastradh 	cleanup_srcu_struct(&drm_unplug_srcu);
16877b5597aSriastradh 	idr_destroy(&drm_minors_idr);
16977b5597aSriastradh 	spin_lock_destroy(&drm_minor_lock);
170d46aeca2Sriastradh 	drm_agp_hooks_fini();
17177b5597aSriastradh }
1726cb10275Sriastradh 
17326e846f0Sriastradh int
drm_irq_by_busid(struct drm_device * dev,void * data,struct drm_file * file)17426e846f0Sriastradh drm_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file)
17526e846f0Sriastradh {
17626e846f0Sriastradh 
17726e846f0Sriastradh 	return -ENODEV;
17826e846f0Sriastradh }
17926e846f0Sriastradh 
1806cb10275Sriastradh static int
drmkms_modcmd(modcmd_t cmd,void * arg __unused)1816cb10275Sriastradh drmkms_modcmd(modcmd_t cmd, void *arg __unused)
1826cb10275Sriastradh {
1836cb10275Sriastradh #ifdef _MODULE
1846cb10275Sriastradh 	devmajor_t bmajor = NODEVMAJOR, cmajor = NODEVMAJOR;
1856cb10275Sriastradh #endif
18677b5597aSriastradh 	int error;
1876cb10275Sriastradh 
1886cb10275Sriastradh 	switch (cmd) {
1896cb10275Sriastradh 	case MODULE_CMD_INIT:
1906cb10275Sriastradh #ifdef _MODULE
19177b5597aSriastradh 		error = drm_init();
19277b5597aSriastradh #else
19377b5597aSriastradh 		error = drm_guarantee_initialized();
19477b5597aSriastradh #endif
19577b5597aSriastradh 		if (error)
19677b5597aSriastradh 			return error;
19777b5597aSriastradh #ifdef _MODULE
1986cb10275Sriastradh 		error = devsw_attach("drm", NULL, &bmajor,
1996cb10275Sriastradh 		    &drm_cdevsw, &cmajor);
2006cb10275Sriastradh 		if (error) {
2016cb10275Sriastradh 			aprint_error("drmkms: unable to attach devsw: %d\n",
2026cb10275Sriastradh 			    error);
20377b5597aSriastradh 			return error;
2046cb10275Sriastradh 		}
2056cb10275Sriastradh #endif
2066cb10275Sriastradh 		return 0;
2076cb10275Sriastradh 
2086cb10275Sriastradh 	case MODULE_CMD_FINI:
2096cb10275Sriastradh #ifdef _MODULE
2102f7fddcfSriastradh 		devsw_detach(NULL, &drm_cdevsw);
2116cb10275Sriastradh #endif
21277b5597aSriastradh 		drm_fini();
2136cb10275Sriastradh 		return 0;
2146cb10275Sriastradh 
2156cb10275Sriastradh 	default:
2166cb10275Sriastradh 		return ENOTTY;
2176cb10275Sriastradh 	}
2186cb10275Sriastradh }
219