929dcbc0758a2941c669a962d0c05ec8e5a50467
[linux-2.6-microblaze.git] / drivers / gpu / drm / drm_aperture.c
1 // SPDX-License-Identifier: MIT
2
3 #include <drm/drm_aperture.h>
4 #include <drm/drm_fb_helper.h>
5
6 /**
7  * DOC: overview
8  *
9  * A graphics device might be supported by different drivers, but only one
10  * driver can be active at any given time. Many systems load a generic
11  * graphics drivers, such as EFI-GOP or VESA, early during the boot process.
12  * During later boot stages, they replace the generic driver with a dedicated,
13  * hardware-specific driver. To take over the device the dedicated driver
14  * first has to remove the generic driver. DRM aperture functions manage
15  * ownership of DRM framebuffer memory and hand-over between drivers.
16  *
17  * DRM drivers should call drm_aperture_remove_conflicting_framebuffers()
18  * at the top of their probe function. The function removes any generic
19  * driver that is currently associated with the given framebuffer memory.
20  * If the framebuffer is located at PCI BAR 0, the rsp code looks as in the
21  * example given below.
22  *
23  * .. code-block:: c
24  *
25  *      static int remove_conflicting_framebuffers(struct pci_dev *pdev)
26  *      {
27  *              bool primary = false;
28  *              resource_size_t base, size;
29  *              int ret;
30  *
31  *              base = pci_resource_start(pdev, 0);
32  *              size = pci_resource_len(pdev, 0);
33  *      #ifdef CONFIG_X86
34  *              primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
35  *      #endif
36  *
37  *              return drm_aperture_remove_conflicting_framebuffers(base, size, primary,
38  *                                                                  "example driver");
39  *      }
40  *
41  *      static int probe(struct pci_dev *pdev)
42  *      {
43  *              int ret;
44  *
45  *              // Remove any generic drivers...
46  *              ret = remove_conflicting_framebuffers(pdev);
47  *              if (ret)
48  *                      return ret;
49  *
50  *              // ... and initialize the hardware.
51  *              ...
52  *
53  *              drm_dev_register();
54  *
55  *              return 0;
56  *      }
57  *
58  * PCI device drivers should call
59  * drm_aperture_remove_conflicting_pci_framebuffers() and let it detect the
60  * framebuffer apertures automatically. Device drivers without knowledge of
61  * the framebuffer's location shall call drm_aperture_remove_framebuffers(),
62  * which removes all drivers for known framebuffer.
63  */
64
65 /**
66  * drm_aperture_remove_conflicting_framebuffers - remove existing framebuffers in the given range
67  * @base: the aperture's base address in physical memory
68  * @size: aperture size in bytes
69  * @primary: also kick vga16fb if present
70  * @name: requesting driver name
71  *
72  * This function removes graphics device drivers which use memory range described by
73  * @base and @size.
74  *
75  * Returns:
76  * 0 on success, or a negative errno code otherwise
77  */
78 int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
79                                                  bool primary, const char *name)
80 {
81         struct apertures_struct *a;
82         int ret;
83
84         a = alloc_apertures(1);
85         if (!a)
86                 return -ENOMEM;
87
88         a->ranges[0].base = base;
89         a->ranges[0].size = size;
90
91         ret = drm_fb_helper_remove_conflicting_framebuffers(a, name, primary);
92         kfree(a);
93
94         return ret;
95 }
96 EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
97
98 /**
99  * drm_aperture_remove_conflicting_pci_framebuffers - remove existing framebuffers for PCI devices
100  * @pdev: PCI device
101  * @name: requesting driver name
102  *
103  * This function removes graphics device drivers using memory range configured
104  * for any of @pdev's memory bars. The function assumes that PCI device with
105  * shadowed ROM drives a primary display and so kicks out vga16fb.
106  *
107  * Returns:
108  * 0 on success, or a negative errno code otherwise
109  */
110 int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
111 {
112         return drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, name);
113 }
114 EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers);