xref: /linux/drivers/gpu/nova-core/driver.rs (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use kernel::{
4     auxiliary, c_str,
5     device::Core,
6     pci,
7     pci::{Class, ClassMask, Vendor},
8     prelude::*,
9     sizes::SZ_16M,
10     sync::Arc,
11 };
12 
13 use crate::gpu::Gpu;
14 
15 #[pin_data]
16 pub(crate) struct NovaCore {
17     #[pin]
18     pub(crate) gpu: Gpu,
19     _reg: auxiliary::Registration,
20 }
21 
22 const BAR0_SIZE: usize = SZ_16M;
23 pub(crate) type Bar0 = pci::Bar<BAR0_SIZE>;
24 
25 kernel::pci_device_table!(
26     PCI_TABLE,
27     MODULE_PCI_TABLE,
28     <NovaCore as pci::Driver>::IdInfo,
29     [
30         // Modern NVIDIA GPUs will show up as either VGA or 3D controllers.
31         (
32             pci::DeviceId::from_class_and_vendor(
33                 Class::DISPLAY_VGA,
34                 ClassMask::ClassSubclass,
35                 Vendor::NVIDIA
36             ),
37             ()
38         ),
39         (
40             pci::DeviceId::from_class_and_vendor(
41                 Class::DISPLAY_3D,
42                 ClassMask::ClassSubclass,
43                 Vendor::NVIDIA
44             ),
45             ()
46         ),
47     ]
48 );
49 
50 impl pci::Driver for NovaCore {
51     type IdInfo = ();
52     const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
53 
54     fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
55         dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n");
56 
57         pdev.enable_device_mem()?;
58         pdev.set_master();
59 
60         let devres_bar = Arc::pin_init(
61             pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")),
62             GFP_KERNEL,
63         )?;
64 
65         // Used to provided a `&Bar0` to `Gpu::new` without tying it to the lifetime of
66         // `devres_bar`.
67         let bar_clone = Arc::clone(&devres_bar);
68         let bar = bar_clone.access(pdev.as_ref())?;
69 
70         let this = KBox::pin_init(
71             try_pin_init!(Self {
72                 gpu <- Gpu::new(pdev, devres_bar, bar),
73                 _reg: auxiliary::Registration::new(
74                     pdev.as_ref(),
75                     c_str!("nova-drm"),
76                     0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID.
77                     crate::MODULE_NAME
78                 )?,
79             }),
80             GFP_KERNEL,
81         )?;
82 
83         Ok(this)
84     }
85 
86     fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
87         this.gpu.unbind(pdev.as_ref());
88     }
89 }
90