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