xref: /linux/rust/kernel/drm/driver.rs (revision 6ad005ce6994599e2ae338007a54dd21063aae15)
107c90160SAsahi Lina // SPDX-License-Identifier: GPL-2.0 OR MIT
207c90160SAsahi Lina 
307c90160SAsahi Lina //! DRM driver core.
407c90160SAsahi Lina //!
5c2783c7cSMiguel Ojeda //! C header: [`include/drm/drm_drv.h`](srctree/include/drm/drm_drv.h)
607c90160SAsahi Lina 
70600032cSAsahi Lina use crate::{
8b7a12492SLyude Paul     bindings,
9b7a12492SLyude Paul     device,
10b7a12492SLyude Paul     devres,
11b7a12492SLyude Paul     drm,
12*6ad005ceSLyude Paul     error::to_result,
130600032cSAsahi Lina     prelude::*,
14b7a12492SLyude Paul     sync::aref::ARef, //
150600032cSAsahi Lina };
1607c90160SAsahi Lina 
1707c90160SAsahi Lina /// Driver use the GEM memory manager. This should be set for all modern drivers.
1807c90160SAsahi Lina pub(crate) const FEAT_GEM: u32 = bindings::drm_driver_feature_DRIVER_GEM;
1907c90160SAsahi Lina 
2007c90160SAsahi Lina /// Information data for a DRM Driver.
2107c90160SAsahi Lina pub struct DriverInfo {
2207c90160SAsahi Lina     /// Driver major version.
2307c90160SAsahi Lina     pub major: i32,
2407c90160SAsahi Lina     /// Driver minor version.
2507c90160SAsahi Lina     pub minor: i32,
2607c90160SAsahi Lina     /// Driver patchlevel version.
2707c90160SAsahi Lina     pub patchlevel: i32,
2807c90160SAsahi Lina     /// Driver name.
2907c90160SAsahi Lina     pub name: &'static CStr,
3007c90160SAsahi Lina     /// Driver description.
3107c90160SAsahi Lina     pub desc: &'static CStr,
3207c90160SAsahi Lina }
3307c90160SAsahi Lina 
3407c90160SAsahi Lina /// Internal memory management operation set, normally created by memory managers (e.g. GEM).
3507c90160SAsahi Lina pub struct AllocOps {
3607c90160SAsahi Lina     pub(crate) gem_create_object: Option<
3707c90160SAsahi Lina         unsafe extern "C" fn(
3807c90160SAsahi Lina             dev: *mut bindings::drm_device,
3907c90160SAsahi Lina             size: usize,
4007c90160SAsahi Lina         ) -> *mut bindings::drm_gem_object,
4107c90160SAsahi Lina     >,
4207c90160SAsahi Lina     pub(crate) prime_handle_to_fd: Option<
4307c90160SAsahi Lina         unsafe extern "C" fn(
4407c90160SAsahi Lina             dev: *mut bindings::drm_device,
4507c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
4607c90160SAsahi Lina             handle: u32,
4707c90160SAsahi Lina             flags: u32,
4807c90160SAsahi Lina             prime_fd: *mut core::ffi::c_int,
4907c90160SAsahi Lina         ) -> core::ffi::c_int,
5007c90160SAsahi Lina     >,
5107c90160SAsahi Lina     pub(crate) prime_fd_to_handle: Option<
5207c90160SAsahi Lina         unsafe extern "C" fn(
5307c90160SAsahi Lina             dev: *mut bindings::drm_device,
5407c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
5507c90160SAsahi Lina             prime_fd: core::ffi::c_int,
5607c90160SAsahi Lina             handle: *mut u32,
5707c90160SAsahi Lina         ) -> core::ffi::c_int,
5807c90160SAsahi Lina     >,
5907c90160SAsahi Lina     pub(crate) gem_prime_import: Option<
6007c90160SAsahi Lina         unsafe extern "C" fn(
6107c90160SAsahi Lina             dev: *mut bindings::drm_device,
6207c90160SAsahi Lina             dma_buf: *mut bindings::dma_buf,
6307c90160SAsahi Lina         ) -> *mut bindings::drm_gem_object,
6407c90160SAsahi Lina     >,
6507c90160SAsahi Lina     pub(crate) gem_prime_import_sg_table: Option<
6607c90160SAsahi Lina         unsafe extern "C" fn(
6707c90160SAsahi Lina             dev: *mut bindings::drm_device,
6807c90160SAsahi Lina             attach: *mut bindings::dma_buf_attachment,
6907c90160SAsahi Lina             sgt: *mut bindings::sg_table,
7007c90160SAsahi Lina         ) -> *mut bindings::drm_gem_object,
7107c90160SAsahi Lina     >,
7207c90160SAsahi Lina     pub(crate) dumb_create: Option<
7307c90160SAsahi Lina         unsafe extern "C" fn(
7407c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
7507c90160SAsahi Lina             dev: *mut bindings::drm_device,
7607c90160SAsahi Lina             args: *mut bindings::drm_mode_create_dumb,
7707c90160SAsahi Lina         ) -> core::ffi::c_int,
7807c90160SAsahi Lina     >,
7907c90160SAsahi Lina     pub(crate) dumb_map_offset: Option<
8007c90160SAsahi Lina         unsafe extern "C" fn(
8107c90160SAsahi Lina             file_priv: *mut bindings::drm_file,
8207c90160SAsahi Lina             dev: *mut bindings::drm_device,
8307c90160SAsahi Lina             handle: u32,
8407c90160SAsahi Lina             offset: *mut u64,
8507c90160SAsahi Lina         ) -> core::ffi::c_int,
8607c90160SAsahi Lina     >,
8707c90160SAsahi Lina }
8807c90160SAsahi Lina 
8907c90160SAsahi Lina /// Trait for memory manager implementations. Implemented internally.
90c284d3e4SAsahi Lina pub trait AllocImpl: super::private::Sealed + drm::gem::IntoGEMObject {
916ea42e91SLyude Paul     /// The [`Driver`] implementation for this [`AllocImpl`].
926ea42e91SLyude Paul     type Driver: drm::Driver;
936ea42e91SLyude Paul 
9407c90160SAsahi Lina     /// The C callback operations for this memory manager.
9507c90160SAsahi Lina     const ALLOC_OPS: AllocOps;
9607c90160SAsahi Lina }
9707c90160SAsahi Lina 
9807c90160SAsahi Lina /// The DRM `Driver` trait.
9907c90160SAsahi Lina ///
10007c90160SAsahi Lina /// This trait must be implemented by drivers in order to create a `struct drm_device` and `struct
10107c90160SAsahi Lina /// drm_driver` to be registered in the DRM subsystem.
10207c90160SAsahi Lina #[vtable]
10307c90160SAsahi Lina pub trait Driver {
10407c90160SAsahi Lina     /// Context data associated with the DRM driver
10507c90160SAsahi Lina     type Data: Sync + Send;
10607c90160SAsahi Lina 
10707c90160SAsahi Lina     /// The type used to manage memory for this driver.
10807c90160SAsahi Lina     type Object: AllocImpl;
10907c90160SAsahi Lina 
110a98a73beSAsahi Lina     /// The type used to represent a DRM File (client)
111a98a73beSAsahi Lina     type File: drm::file::DriverFile;
112a98a73beSAsahi Lina 
11307c90160SAsahi Lina     /// Driver metadata
11407c90160SAsahi Lina     const INFO: DriverInfo;
11507c90160SAsahi Lina 
11607c90160SAsahi Lina     /// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`.
11707c90160SAsahi Lina     const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor];
11807c90160SAsahi Lina }
1190600032cSAsahi Lina 
1200600032cSAsahi Lina /// The registration type of a `drm::Device`.
1210600032cSAsahi Lina ///
1220600032cSAsahi Lina /// Once the `Registration` structure is dropped, the device is unregistered.
1230600032cSAsahi Lina pub struct Registration<T: Driver>(ARef<drm::Device<T>>);
1240600032cSAsahi Lina 
1250600032cSAsahi Lina impl<T: Driver> Registration<T> {
1260600032cSAsahi Lina     fn new(drm: &drm::Device<T>, flags: usize) -> Result<Self> {
1270600032cSAsahi Lina         // SAFETY: `drm.as_raw()` is valid by the invariants of `drm::Device`.
1280600032cSAsahi Lina         to_result(unsafe { bindings::drm_dev_register(drm.as_raw(), flags) })?;
1290600032cSAsahi Lina 
1300600032cSAsahi Lina         Ok(Self(drm.into()))
1310600032cSAsahi Lina     }
1320600032cSAsahi Lina 
133638eeda8SLyude Paul     /// Registers a new [`Device`](drm::Device) with userspace.
134638eeda8SLyude Paul     ///
135638eeda8SLyude Paul     /// Ownership of the [`Registration`] object is passed to [`devres::register`].
1360600032cSAsahi Lina     pub fn new_foreign_owned(
1370600032cSAsahi Lina         drm: &drm::Device<T>,
1380600032cSAsahi Lina         dev: &device::Device<device::Bound>,
1390600032cSAsahi Lina         flags: usize,
14046ae8fd7SDanilo Krummrich     ) -> Result
14146ae8fd7SDanilo Krummrich     where
14246ae8fd7SDanilo Krummrich         T: 'static,
14346ae8fd7SDanilo Krummrich     {
1440600032cSAsahi Lina         if drm.as_ref().as_raw() != dev.as_raw() {
1450600032cSAsahi Lina             return Err(EINVAL);
1460600032cSAsahi Lina         }
1470600032cSAsahi Lina 
1480600032cSAsahi Lina         let reg = Registration::<T>::new(drm, flags)?;
14946ae8fd7SDanilo Krummrich 
15046ae8fd7SDanilo Krummrich         devres::register(dev, reg, GFP_KERNEL)
1510600032cSAsahi Lina     }
1520600032cSAsahi Lina 
1530600032cSAsahi Lina     /// Returns a reference to the `Device` instance for this registration.
1540600032cSAsahi Lina     pub fn device(&self) -> &drm::Device<T> {
1550600032cSAsahi Lina         &self.0
1560600032cSAsahi Lina     }
1570600032cSAsahi Lina }
1580600032cSAsahi Lina 
1590600032cSAsahi Lina // SAFETY: `Registration` doesn't offer any methods or access to fields when shared between
1600600032cSAsahi Lina // threads, hence it's safe to share it.
1610600032cSAsahi Lina unsafe impl<T: Driver> Sync for Registration<T> {}
1620600032cSAsahi Lina 
1630600032cSAsahi Lina // SAFETY: Registration with and unregistration from the DRM subsystem can happen from any thread.
1640600032cSAsahi Lina unsafe impl<T: Driver> Send for Registration<T> {}
1650600032cSAsahi Lina 
1660600032cSAsahi Lina impl<T: Driver> Drop for Registration<T> {
1670600032cSAsahi Lina     fn drop(&mut self) {
1680600032cSAsahi Lina         // SAFETY: Safe by the invariant of `ARef<drm::Device<T>>`. The existence of this
1690600032cSAsahi Lina         // `Registration` also guarantees the this `drm::Device` is actually registered.
1700600032cSAsahi Lina         unsafe { bindings::drm_dev_unregister(self.0.as_raw()) };
1710600032cSAsahi Lina     }
1720600032cSAsahi Lina }
173