107c90160SAsahi Lina // SPDX-License-Identifier: GPL-2.0 OR MIT 207c90160SAsahi Lina 307c90160SAsahi Lina //! DRM driver core. 407c90160SAsahi Lina //! 507c90160SAsahi Lina //! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h) 607c90160SAsahi Lina 70600032cSAsahi Lina use crate::{ 846ae8fd7SDanilo Krummrich bindings, device, devres, drm, 90600032cSAsahi Lina error::{to_result, Result}, 100600032cSAsahi Lina prelude::*, 11*f1f2a22bSShankari Anand sync::aref::ARef, 120600032cSAsahi Lina }; 1307c90160SAsahi Lina use macros::vtable; 1407c90160SAsahi Lina 1507c90160SAsahi Lina /// Driver use the GEM memory manager. This should be set for all modern drivers. 1607c90160SAsahi Lina pub(crate) const FEAT_GEM: u32 = bindings::drm_driver_feature_DRIVER_GEM; 1707c90160SAsahi Lina 1807c90160SAsahi Lina /// Information data for a DRM Driver. 1907c90160SAsahi Lina pub struct DriverInfo { 2007c90160SAsahi Lina /// Driver major version. 2107c90160SAsahi Lina pub major: i32, 2207c90160SAsahi Lina /// Driver minor version. 2307c90160SAsahi Lina pub minor: i32, 2407c90160SAsahi Lina /// Driver patchlevel version. 2507c90160SAsahi Lina pub patchlevel: i32, 2607c90160SAsahi Lina /// Driver name. 2707c90160SAsahi Lina pub name: &'static CStr, 2807c90160SAsahi Lina /// Driver description. 2907c90160SAsahi Lina pub desc: &'static CStr, 3007c90160SAsahi Lina } 3107c90160SAsahi Lina 3207c90160SAsahi Lina /// Internal memory management operation set, normally created by memory managers (e.g. GEM). 3307c90160SAsahi Lina pub struct AllocOps { 3407c90160SAsahi Lina pub(crate) gem_create_object: Option< 3507c90160SAsahi Lina unsafe extern "C" fn( 3607c90160SAsahi Lina dev: *mut bindings::drm_device, 3707c90160SAsahi Lina size: usize, 3807c90160SAsahi Lina ) -> *mut bindings::drm_gem_object, 3907c90160SAsahi Lina >, 4007c90160SAsahi Lina pub(crate) prime_handle_to_fd: Option< 4107c90160SAsahi Lina unsafe extern "C" fn( 4207c90160SAsahi Lina dev: *mut bindings::drm_device, 4307c90160SAsahi Lina file_priv: *mut bindings::drm_file, 4407c90160SAsahi Lina handle: u32, 4507c90160SAsahi Lina flags: u32, 4607c90160SAsahi Lina prime_fd: *mut core::ffi::c_int, 4707c90160SAsahi Lina ) -> core::ffi::c_int, 4807c90160SAsahi Lina >, 4907c90160SAsahi Lina pub(crate) prime_fd_to_handle: Option< 5007c90160SAsahi Lina unsafe extern "C" fn( 5107c90160SAsahi Lina dev: *mut bindings::drm_device, 5207c90160SAsahi Lina file_priv: *mut bindings::drm_file, 5307c90160SAsahi Lina prime_fd: core::ffi::c_int, 5407c90160SAsahi Lina handle: *mut u32, 5507c90160SAsahi Lina ) -> core::ffi::c_int, 5607c90160SAsahi Lina >, 5707c90160SAsahi Lina pub(crate) gem_prime_import: Option< 5807c90160SAsahi Lina unsafe extern "C" fn( 5907c90160SAsahi Lina dev: *mut bindings::drm_device, 6007c90160SAsahi Lina dma_buf: *mut bindings::dma_buf, 6107c90160SAsahi Lina ) -> *mut bindings::drm_gem_object, 6207c90160SAsahi Lina >, 6307c90160SAsahi Lina pub(crate) gem_prime_import_sg_table: Option< 6407c90160SAsahi Lina unsafe extern "C" fn( 6507c90160SAsahi Lina dev: *mut bindings::drm_device, 6607c90160SAsahi Lina attach: *mut bindings::dma_buf_attachment, 6707c90160SAsahi Lina sgt: *mut bindings::sg_table, 6807c90160SAsahi Lina ) -> *mut bindings::drm_gem_object, 6907c90160SAsahi Lina >, 7007c90160SAsahi Lina pub(crate) dumb_create: Option< 7107c90160SAsahi Lina unsafe extern "C" fn( 7207c90160SAsahi Lina file_priv: *mut bindings::drm_file, 7307c90160SAsahi Lina dev: *mut bindings::drm_device, 7407c90160SAsahi Lina args: *mut bindings::drm_mode_create_dumb, 7507c90160SAsahi Lina ) -> core::ffi::c_int, 7607c90160SAsahi Lina >, 7707c90160SAsahi Lina pub(crate) dumb_map_offset: Option< 7807c90160SAsahi Lina unsafe extern "C" fn( 7907c90160SAsahi Lina file_priv: *mut bindings::drm_file, 8007c90160SAsahi Lina dev: *mut bindings::drm_device, 8107c90160SAsahi Lina handle: u32, 8207c90160SAsahi Lina offset: *mut u64, 8307c90160SAsahi Lina ) -> core::ffi::c_int, 8407c90160SAsahi Lina >, 8507c90160SAsahi Lina } 8607c90160SAsahi Lina 8707c90160SAsahi Lina /// Trait for memory manager implementations. Implemented internally. 88c284d3e4SAsahi Lina pub trait AllocImpl: super::private::Sealed + drm::gem::IntoGEMObject { 8907c90160SAsahi Lina /// The C callback operations for this memory manager. 9007c90160SAsahi Lina const ALLOC_OPS: AllocOps; 9107c90160SAsahi Lina } 9207c90160SAsahi Lina 9307c90160SAsahi Lina /// The DRM `Driver` trait. 9407c90160SAsahi Lina /// 9507c90160SAsahi Lina /// This trait must be implemented by drivers in order to create a `struct drm_device` and `struct 9607c90160SAsahi Lina /// drm_driver` to be registered in the DRM subsystem. 9707c90160SAsahi Lina #[vtable] 9807c90160SAsahi Lina pub trait Driver { 9907c90160SAsahi Lina /// Context data associated with the DRM driver 10007c90160SAsahi Lina type Data: Sync + Send; 10107c90160SAsahi Lina 10207c90160SAsahi Lina /// The type used to manage memory for this driver. 10307c90160SAsahi Lina type Object: AllocImpl; 10407c90160SAsahi Lina 105a98a73beSAsahi Lina /// The type used to represent a DRM File (client) 106a98a73beSAsahi Lina type File: drm::file::DriverFile; 107a98a73beSAsahi Lina 10807c90160SAsahi Lina /// Driver metadata 10907c90160SAsahi Lina const INFO: DriverInfo; 11007c90160SAsahi Lina 11107c90160SAsahi Lina /// IOCTL list. See `kernel::drm::ioctl::declare_drm_ioctls!{}`. 11207c90160SAsahi Lina const IOCTLS: &'static [drm::ioctl::DrmIoctlDescriptor]; 11307c90160SAsahi Lina } 1140600032cSAsahi Lina 1150600032cSAsahi Lina /// The registration type of a `drm::Device`. 1160600032cSAsahi Lina /// 1170600032cSAsahi Lina /// Once the `Registration` structure is dropped, the device is unregistered. 1180600032cSAsahi Lina pub struct Registration<T: Driver>(ARef<drm::Device<T>>); 1190600032cSAsahi Lina 1200600032cSAsahi Lina impl<T: Driver> Registration<T> { 1210600032cSAsahi Lina /// Creates a new [`Registration`] and registers it. 1220600032cSAsahi Lina fn new(drm: &drm::Device<T>, flags: usize) -> Result<Self> { 1230600032cSAsahi Lina // SAFETY: `drm.as_raw()` is valid by the invariants of `drm::Device`. 1240600032cSAsahi Lina to_result(unsafe { bindings::drm_dev_register(drm.as_raw(), flags) })?; 1250600032cSAsahi Lina 1260600032cSAsahi Lina Ok(Self(drm.into())) 1270600032cSAsahi Lina } 1280600032cSAsahi Lina 1290600032cSAsahi Lina /// Same as [`Registration::new`}, but transfers ownership of the [`Registration`] to 13046ae8fd7SDanilo Krummrich /// [`devres::register`]. 1310600032cSAsahi Lina pub fn new_foreign_owned( 1320600032cSAsahi Lina drm: &drm::Device<T>, 1330600032cSAsahi Lina dev: &device::Device<device::Bound>, 1340600032cSAsahi Lina flags: usize, 13546ae8fd7SDanilo Krummrich ) -> Result 13646ae8fd7SDanilo Krummrich where 13746ae8fd7SDanilo Krummrich T: 'static, 13846ae8fd7SDanilo Krummrich { 1390600032cSAsahi Lina if drm.as_ref().as_raw() != dev.as_raw() { 1400600032cSAsahi Lina return Err(EINVAL); 1410600032cSAsahi Lina } 1420600032cSAsahi Lina 1430600032cSAsahi Lina let reg = Registration::<T>::new(drm, flags)?; 14446ae8fd7SDanilo Krummrich 14546ae8fd7SDanilo Krummrich devres::register(dev, reg, GFP_KERNEL) 1460600032cSAsahi Lina } 1470600032cSAsahi Lina 1480600032cSAsahi Lina /// Returns a reference to the `Device` instance for this registration. 1490600032cSAsahi Lina pub fn device(&self) -> &drm::Device<T> { 1500600032cSAsahi Lina &self.0 1510600032cSAsahi Lina } 1520600032cSAsahi Lina } 1530600032cSAsahi Lina 1540600032cSAsahi Lina // SAFETY: `Registration` doesn't offer any methods or access to fields when shared between 1550600032cSAsahi Lina // threads, hence it's safe to share it. 1560600032cSAsahi Lina unsafe impl<T: Driver> Sync for Registration<T> {} 1570600032cSAsahi Lina 1580600032cSAsahi Lina // SAFETY: Registration with and unregistration from the DRM subsystem can happen from any thread. 1590600032cSAsahi Lina unsafe impl<T: Driver> Send for Registration<T> {} 1600600032cSAsahi Lina 1610600032cSAsahi Lina impl<T: Driver> Drop for Registration<T> { 1620600032cSAsahi Lina fn drop(&mut self) { 1630600032cSAsahi Lina // SAFETY: Safe by the invariant of `ARef<drm::Device<T>>`. The existence of this 1640600032cSAsahi Lina // `Registration` also guarantees the this `drm::Device` is actually registered. 1650600032cSAsahi Lina unsafe { bindings::drm_dev_unregister(self.0.as_raw()) }; 1660600032cSAsahi Lina } 1670600032cSAsahi Lina } 168