Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • lyudess/linux
1 result
Show changes
Commits on Source (9)
......@@ -13,7 +13,8 @@ use crate::{
kms::{
KmsImpl,
private::KmsImpl as KmsImplPrivate,
KmsDriver
KmsDriver,
ModeConfigInfo,
}
},
device,
......@@ -129,6 +130,17 @@ pub struct AllocOps {
pub trait AllocImpl: Sealed + drm::gem::IntoGEMObject {
/// The C callback operations for this memory manager.
const ALLOC_OPS: AllocOps;
/// Setup the fbdev implementation for a KMS driver using this [`AllocImpl`].
///
/// # Safety
///
/// This function must only be called once immediately after registration by the DRM crate.
#[cfg(CONFIG_DRM_FBDEV_EMULATION = "y")]
unsafe fn setup_fbdev(
drm: &drm::device::Device<Self::Driver>,
mode_config_info: &ModeConfigInfo
);
}
/// The DRM `Driver` trait.
......@@ -145,7 +157,7 @@ pub trait Driver {
/// The type used to manage memory for this driver.
///
/// Should be either `drm::gem::Object<T>` or `drm::gem::shmem::Object<T>`.
type Object: AllocImpl;
type Object: AllocImpl<Driver = Self> where Self: Sized;
/// The type used to represent a DRM File (client)
type File: drm::file::DriverFile;
......@@ -190,9 +202,12 @@ impl<T: Driver> Registration<T> {
return Err(Error::from_errno(ret));
}
if let Some(ref info) = mode_config_info {
// SAFETY: We just registered the device above
unsafe { T::Kms::setup_fbdev(&drm, info) };
#[cfg(CONFIG_DRM_FBDEV_EMULATION = "y")]
if has_kms {
if let Some(ref info) = mode_config_info {
// SAFETY: We just registered the device above, and this is within the DRM create
unsafe { T::Object::setup_fbdev(&drm, info) };
}
}
Ok(Self(drm))
......
......@@ -10,7 +10,7 @@ pub mod shmem;
use crate::{
alloc::flags::*,
bindings,
drm::{device, drv, file},
drm::{device, drv, file, kms},
error::{to_result, Result},
prelude::*,
};
......@@ -301,6 +301,21 @@ impl<T: DriverObject> drv::AllocImpl for Object<T> {
dumb_create: None,
dumb_map_offset: None,
};
#[cfg(CONFIG_DRM_FBDEV_EMULATION = "y")]
#[inline]
unsafe fn setup_fbdev(
drm: &device::Device<T::Driver>,
mode_config_info: &kms::ModeConfigInfo
) {
// SAFETY:
// - This implementation of `AllocImpl` is proof that this driver is using the GEM dma
// helpers.
// - `as_raw()` always returns a pointer to an initialized DRM device.
// - Our safety contract ensures that `drm` was just registered, and that we're being called
// from the DRM crate
unsafe { bindings::drm_fbdev_dma_setup(drm.as_raw(), mode_config_info.preferred_depth) };
}
}
/// A reference-counted shared reference to a base GEM object.
......
......@@ -4,7 +4,7 @@
//!
//! C header: [`include/linux/drm/drm_gem_shmem_helper.h`](../../../../include/linux/drm/drm_gem_shmem_helper.h)
use crate::drm::{device, drv, gem};
use crate::drm::{device, drv, gem, kms};
use crate::{
error::{from_err_ptr, to_result},
prelude::*,
......@@ -277,6 +277,21 @@ impl<T: DriverObject> drv::AllocImpl for Object<T> {
dumb_create: Some(bindings::drm_gem_shmem_dumb_create),
dumb_map_offset: None,
};
#[cfg(CONFIG_DRM_FBDEV_EMULATION = "y")]
#[inline]
unsafe fn setup_fbdev(
drm: &device::Device<T::Driver>,
mode_config_info: &kms::ModeConfigInfo
) {
// SAFETY:
// - This implementation of `AllocImpl` is proof that this driver is using the GEM shmem
// helpers.
// - `as_raw()` always returns a pointer to an initialized DRM device.
// - Our safety contract ensures that `drm` was just registered, and that we're being called
// from the DRM crate.
unsafe { bindings::drm_fbdev_shmem_setup(drm.as_raw(), mode_config_info.preferred_depth) };
}
}
/// A virtual mapping for a shmem-backed GEM object in kernel address space.
......
......@@ -6,14 +6,13 @@ pub mod atomic;
pub mod connector;
pub mod crtc;
pub mod encoder;
pub mod fbdev;
pub mod framebuffer;
pub mod plane;
pub mod vblank;
use crate::{
drm::{
drv::Driver,
drv::{Driver, AllocImpl},
device::Device
},
device,
......@@ -67,15 +66,6 @@ pub(crate) mod private {
unsafe fn setup_kms(drm: &Device<Self::Driver>) -> Result<ModeConfigInfo> {
build_error::build_error("This should never be reachable")
}
/// The callback for setting up fbdev emulation on a KMS device.
///
/// # Safety
///
/// `drm` must be registered.
unsafe fn setup_fbdev(drm: &Device<Self::Driver>, mode_config_info: &ModeConfigInfo) {
build_error::build_error("This should never be reachable")
}
}
}
......@@ -125,12 +115,6 @@ impl<'a, T: Driver> UnregisteredKmsDevice<'a, T> {
/// [`PhantomData<Self>`]: PhantomData
#[vtable]
pub trait KmsDriver: Driver {
/// The fbdev implementation to use for this [`Device`].
///
/// Which implementation may be used here depends on the GEM implementation specified in
/// [`Driver::Object`]. See [`fbdev`] for more information.
type Fbdev: fbdev::FbdevImpl;
/// Return a [`ModeConfigInfo`] structure for this [`device::Device`].
fn mode_config_info(
dev: &device::Device,
......@@ -238,10 +222,6 @@ impl<T: KmsDriver> private::KmsImpl for T {
Ok(mode_config_info)
}
unsafe fn setup_fbdev(drm: &Device<Self::Driver>, mode_config_info: &ModeConfigInfo) {
<<T as KmsDriver>::Fbdev as fbdev::private::FbdevImpl>::setup_fbdev(drm, mode_config_info)
}
}
impl<T: KmsDriver> KmsImpl for T {}
......
......@@ -373,13 +373,13 @@ impl<T: KmsDriver> AtomicStateComposer<T> {
/// A token proving that no modesets for a commit have completed.
///
/// This token is proof that no commits have yet completed, and is provided as an argument to
/// [`Kms::atomic_commit_tail`]. This may be used with
/// [`KmsDriver::atomic_commit_tail`]. This may be used with
/// [`AtomicCommitTail::commit_modeset_disables`].
pub struct ModesetsReadyToken<'a>(PhantomData<&'a ()>);
/// A token proving that modeset disables for a commit have completed.
///
/// This token is proof that an implementor's [`Kms::atomic_commit_tail`] phase has finished
/// This token is proof that an implementor's [`KmsDriver::atomic_commit_tail`] phase has finished
/// committing any operations which disable mode objects. It is returned by
/// [`AtomicCommitTail::commit_modeset_disables`], and can be used with
/// [`AtomicCommitTail::commit_modeset_enables`] to acquire a [`EnablesCommittedToken`].
......@@ -387,7 +387,7 @@ pub struct DisablesCommittedToken<'a>(PhantomData<&'a ()>);
/// A token proving that modeset enables for a commit have completed.
///
/// This token is proof that an implementor's [`Kms::atomic_commit_tail`] phase has finished
/// This token is proof that an implementor's [`KmsDriver::atomic_commit_tail`] phase has finished
/// committing any operations which enable mode objects. It is returned by
/// [`AtomicCommitTail::commit_modeset_enables`].
pub struct EnablesCommittedToken<'a>(PhantomData<&'a ()>);
......@@ -395,20 +395,20 @@ pub struct EnablesCommittedToken<'a>(PhantomData<&'a ()>);
/// A token proving that no plane updates for a commit have completed.
///
/// This token is proof that no plane updates have yet been completed within an implementor's
/// [`Kms::atomic_commit_tail`] implementation, and that we are ready to begin updating planes. It
/// is provided as an argument to [`Kms::atomic_commit_tail`].
/// [`KmsDriver::atomic_commit_tail`] implementation, and that we are ready to begin updating planes. It
/// is provided as an argument to [`KmsDriver::atomic_commit_tail`].
pub struct PlaneUpdatesReadyToken<'a>(PhantomData<&'a ()>);
/// A token proving that all plane updates for a commit have completed.
///
/// This token is proof that all plane updates within an implementor's [`Kms::atomic_commit_tail`]
/// This token is proof that all plane updates within an implementor's [`KmsDriver::atomic_commit_tail`]
/// implementation have completed. It is returned by [`AtomicCommitTail::commit_planes`].
pub struct PlaneUpdatesCommittedToken<'a>(PhantomData<&'a ()>);
/// An [`AtomicState`] interface that allows a driver to control the [`atomic_commit_tail`]
/// callback.
///
/// This object is provided as an argument to [`Kms::atomic_commit_tail`], and represents an atomic
/// This object is provided as an argument to [`KmsDriver::atomic_commit_tail`], and represents an atomic
/// state within the commit tail phase which is still in the process of being committed to hardware.
/// It may be used to control the order in which the commit process happens.
///
......@@ -578,7 +578,7 @@ pub(crate) unsafe extern "C" fn commit_tail_callback<T: KmsDriver>(
/// It may be assumed that [`drm_atomic_helper_commit_hw_done`] has been called as long as this type
/// exists.
///
/// [`atomic_commit_tail`]: Kms::atomic_commit_tail
/// [`atomic_commit_tail`]: KmsDriver::atomic_commit_tail
/// [`drm_atomic_helper_commit_hw_done`]: srctree/include/drm/drm_atomic_helper.h
pub struct CommittedAtomicState<'a, T: KmsDriver>(&'a AtomicState<T>);
......
......@@ -200,7 +200,7 @@ impl<T: DriverConnector> Connector<T> {
/// TODO: Add a way to handle creating connectors after device registration. Also, that's why we
/// don't ask for a UnregisteredKms device here.
///
/// [`Kms::create_objects`]: kernel::drm::kms::Kms::create_objects
/// [`KmsDriver::create_objects`]: kernel::drm::kms::KmsDriver::create_objects
pub fn new(
dev: &Device<T::Driver>,
type_: u32,
......
......@@ -276,10 +276,10 @@ unsafe impl<T: DriverCrtc> StaticModeObject for Crtc<T> { }
impl<T: DriverCrtc> Crtc<T> {
/// Construct a new [`Crtc`].
///
/// A driver may use this from their [`Kms::create_objects`] callback in order to construct new
/// [`Crtc`] objects.
/// A driver may use this from their [`KmsDriver::create_objects`] callback in order to
/// construct new [`Crtc`] objects.
///
/// [`Kms::create_objects`]: kernel::drm::kms::Kms::create_objects
/// [`KmsDriver::create_objects`]: kernel::drm::kms::KmsDriver::create_objects
pub fn new<'a, 'b: 'a, P, C>(
dev: &'a UnregisteredKmsDevice<'a, T::Driver>,
primary: &'a Plane<P>,
......
......@@ -204,10 +204,10 @@ unsafe impl<T: DriverEncoder> AsRawEncoder for Encoder<T> {
impl<T: DriverEncoder> Encoder<T> {
/// Construct a new [`Encoder`].
///
/// A driver may use this from their [`Kms::create_objects`] callback in order to construct new
/// [`Encoder`] objects.
/// A driver may use this from their [`KmsDriver::create_objects`] callback in order to
/// construct new [`Encoder`] objects.
///
/// [`Kms::create_objects`]: kernel::drm::kms::Kms::create_objects
/// [`KmsDriver::create_objects`]: kernel::drm::kms::KmsDriver::create_objects
pub fn new<'a, 'b: 'a>(
dev: &'a UnregisteredKmsDevice<'a, T::Driver>,
type_: u32,
......
//! Fbdev helper implementations for rust.
//!
//! This module provides the various Fbdev implementations that can be used by Rust KMS drivers.
use core::marker::*;
use crate::{private::Sealed, drm::{kms::*, device::Device, gem}};
use bindings;
#[cfg(CONFIG_DRM_GEM_SHMEM_HELPER = "y")]
mod shmem;
#[cfg(CONFIG_DRM_GEM_SHMEM_HELPER = "y")]
pub use shmem::FbdevShmem;
pub(crate) mod private {
use super::*;
pub trait FbdevImpl {
/// Setup the fbdev implementation for this KMS driver.
fn setup_fbdev<T: Driver>(drm: &Device<T>, mode_config_info: &ModeConfigInfo);
}
}
/// The main trait for a driver's DRM implementation.
///
/// Drivers are expected not to implement this directly, and to instead use one of the objects
/// provided by this module such as [`FbdevDma`] and [`FbdevShmem`].
pub trait FbdevImpl: private::FbdevImpl {}
/// The fbdev implementation for drivers using the gem DMA helpers.
///
/// Drivers which use the gem DMA helpers ([`gem::Object`]) should use this for their [`Kms::Fbdev`]
/// type.
pub struct FbdevDma<T: Driver>(PhantomData<T>);
impl<T, G> private::FbdevImpl for FbdevDma<T>
where
T: Driver<Object = gem::Object<G>>,
G: gem::DriverObject
{
#[inline]
fn setup_fbdev<D: Driver>(drm: &Device<D>, mode_config_info: &ModeConfigInfo) {
// SAFETY: Our implementation bounds re proof that this driver is using the gem dma helpers
unsafe { bindings::drm_fbdev_dma_setup(drm.as_raw(), mode_config_info.preferred_depth) };
}
}
impl<T, G> FbdevImpl for FbdevDma<T>
where
T: Driver<Object = gem::Object<G>>,
G: gem::DriverObject
{}
//! The GEM shmem fbdev implementation for rust.
//!
//! This module provides an Fbdev implementation that can be used by Rust KMS drivers using the GEM
//! shmem helpers provided by [`shmem`].
use core::marker::*;
use crate::drm::{gem::shmem, kms::*, device::Device};
use super::{private::FbdevImpl as FbdevImplPrivate, FbdevImpl};
use bindings;
/// The fbdev implementation for drivers using the gem shmem helpers.
///
/// KMS Drivers which use the GEM helpers provided by [`shmem`] should use this for [`Kms::Fbdev`].
pub struct FbdevShmem<T: Driver>(PhantomData<T>);
impl<T, G> FbdevImplPrivate for FbdevShmem<T>
where
T: Driver<Object = shmem::Object<G>>,
G: shmem::DriverObject
{
#[inline]
fn setup_fbdev<D: Driver>(drm: &Device<D>, mode_config_info: &ModeConfigInfo) {
// SAFETY: Our implementation bounds are proof that this driver is using the gem shmem
// helpers
unsafe { bindings::drm_fbdev_shmem_setup(drm.as_raw(), mode_config_info.preferred_depth) };
}
}
impl<T, G> FbdevImpl for FbdevShmem<T>
where
T: Driver<Object = shmem::Object<G>>,
G: shmem::DriverObject
{}
......@@ -206,10 +206,10 @@ impl<T: DriverPlane> Deref for Plane<T> {
impl<T: DriverPlane> Plane<T> {
/// Construct a new [`Plane`].
///
/// A driver may use this from their [`Kms::create_objects`] callback in order to construct new
/// A driver may use this from their [`KmsDriver::create_objects`] callback in order to construct new
/// [`Plane`] objects.
///
/// [`Kms::create_objects`]: kernel::drm::kms::Kms::create_objects
/// [`KmsDriver::create_objects`]: kernel::drm::kms::KmsDriver::create_objects
pub fn new<'a, 'b: 'a, const FMT_COUNT: usize, const MOD_COUNT: usize>(
dev: &'a UnregisteredKmsDevice<'a, T::Driver>,
possible_crtcs: u32,
......