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