![]() |
|
|||
0001 // SPDX-License-Identifier: MIT 0002 0003 #include <linux/aperture.h> 0004 #include <linux/platform_device.h> 0005 0006 #include <drm/drm_aperture.h> 0007 #include <drm/drm_drv.h> 0008 #include <drm/drm_print.h> 0009 0010 /** 0011 * DOC: overview 0012 * 0013 * A graphics device might be supported by different drivers, but only one 0014 * driver can be active at any given time. Many systems load a generic 0015 * graphics drivers, such as EFI-GOP or VESA, early during the boot process. 0016 * During later boot stages, they replace the generic driver with a dedicated, 0017 * hardware-specific driver. To take over the device the dedicated driver 0018 * first has to remove the generic driver. DRM aperture functions manage 0019 * ownership of DRM framebuffer memory and hand-over between drivers. 0020 * 0021 * DRM drivers should call drm_aperture_remove_conflicting_framebuffers() 0022 * at the top of their probe function. The function removes any generic 0023 * driver that is currently associated with the given framebuffer memory. 0024 * If the framebuffer is located at PCI BAR 0, the rsp code looks as in the 0025 * example given below. 0026 * 0027 * .. code-block:: c 0028 * 0029 * static const struct drm_driver example_driver = { 0030 * ... 0031 * }; 0032 * 0033 * static int remove_conflicting_framebuffers(struct pci_dev *pdev) 0034 * { 0035 * bool primary = false; 0036 * resource_size_t base, size; 0037 * int ret; 0038 * 0039 * base = pci_resource_start(pdev, 0); 0040 * size = pci_resource_len(pdev, 0); 0041 * #ifdef CONFIG_X86 0042 * primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; 0043 * #endif 0044 * 0045 * return drm_aperture_remove_conflicting_framebuffers(base, size, primary, 0046 * &example_driver); 0047 * } 0048 * 0049 * static int probe(struct pci_dev *pdev) 0050 * { 0051 * int ret; 0052 * 0053 * // Remove any generic drivers... 0054 * ret = remove_conflicting_framebuffers(pdev); 0055 * if (ret) 0056 * return ret; 0057 * 0058 * // ... and initialize the hardware. 0059 * ... 0060 * 0061 * drm_dev_register(); 0062 * 0063 * return 0; 0064 * } 0065 * 0066 * PCI device drivers should call 0067 * drm_aperture_remove_conflicting_pci_framebuffers() and let it detect the 0068 * framebuffer apertures automatically. Device drivers without knowledge of 0069 * the framebuffer's location shall call drm_aperture_remove_framebuffers(), 0070 * which removes all drivers for known framebuffer. 0071 * 0072 * Drivers that are susceptible to being removed by other drivers, such as 0073 * generic EFI or VESA drivers, have to register themselves as owners of their 0074 * given framebuffer memory. Ownership of the framebuffer memory is achieved 0075 * by calling devm_aperture_acquire_from_firmware(). On success, the driver 0076 * is the owner of the framebuffer range. The function fails if the 0077 * framebuffer is already by another driver. See below for an example. 0078 * 0079 * .. code-block:: c 0080 * 0081 * static int acquire_framebuffers(struct drm_device *dev, struct platform_device *pdev) 0082 * { 0083 * resource_size_t base, size; 0084 * 0085 * mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 0086 * if (!mem) 0087 * return -EINVAL; 0088 * base = mem->start; 0089 * size = resource_size(mem); 0090 * 0091 * return devm_acquire_aperture_from_firmware(dev, base, size); 0092 * } 0093 * 0094 * static int probe(struct platform_device *pdev) 0095 * { 0096 * struct drm_device *dev; 0097 * int ret; 0098 * 0099 * // ... Initialize the device... 0100 * dev = devm_drm_dev_alloc(); 0101 * ... 0102 * 0103 * // ... and acquire ownership of the framebuffer. 0104 * ret = acquire_framebuffers(dev, pdev); 0105 * if (ret) 0106 * return ret; 0107 * 0108 * drm_dev_register(dev, 0); 0109 * 0110 * return 0; 0111 * } 0112 * 0113 * The generic driver is now subject to forced removal by other drivers. This 0114 * only works for platform drivers that support hot unplug. 0115 * When a driver calls drm_aperture_remove_conflicting_framebuffers() et al 0116 * for the registered framebuffer range, the aperture helpers call 0117 * platform_device_unregister() and the generic driver unloads itself. It 0118 * may not access the device's registers, framebuffer memory, ROM, etc 0119 * afterwards. 0120 */ 0121 0122 /** 0123 * devm_aperture_acquire_from_firmware - Acquires ownership of a firmware framebuffer 0124 * on behalf of a DRM driver. 0125 * @dev: the DRM device to own the framebuffer memory 0126 * @base: the framebuffer's byte offset in physical memory 0127 * @size: the framebuffer size in bytes 0128 * 0129 * Installs the given device as the new owner of the framebuffer. The function 0130 * expects the framebuffer to be provided by a platform device that has been 0131 * set up by firmware. Firmware can be any generic interface, such as EFI, 0132 * VESA, VGA, etc. If the native hardware driver takes over ownership of the 0133 * framebuffer range, the firmware state gets lost. Aperture helpers will then 0134 * unregister the platform device automatically. Acquired apertures are 0135 * released automatically if the underlying device goes away. 0136 * 0137 * The function fails if the framebuffer range, or parts of it, is currently 0138 * owned by another driver. To evict current owners, callers should use 0139 * drm_aperture_remove_conflicting_framebuffers() et al. before calling this 0140 * function. The function also fails if the given device is not a platform 0141 * device. 0142 * 0143 * Returns: 0144 * 0 on success, or a negative errno value otherwise. 0145 */ 0146 int devm_aperture_acquire_from_firmware(struct drm_device *dev, resource_size_t base, 0147 resource_size_t size) 0148 { 0149 struct platform_device *pdev; 0150 0151 if (drm_WARN_ON(dev, !dev_is_platform(dev->dev))) 0152 return -EINVAL; 0153 0154 pdev = to_platform_device(dev->dev); 0155 0156 return devm_aperture_acquire_for_platform_device(pdev, base, size); 0157 } 0158 EXPORT_SYMBOL(devm_aperture_acquire_from_firmware); 0159 0160 /** 0161 * drm_aperture_remove_conflicting_framebuffers - remove existing framebuffers in the given range 0162 * @base: the aperture's base address in physical memory 0163 * @size: aperture size in bytes 0164 * @primary: also kick vga16fb if present 0165 * @req_driver: requesting DRM driver 0166 * 0167 * This function removes graphics device drivers which use memory range described by 0168 * @base and @size. 0169 * 0170 * Returns: 0171 * 0 on success, or a negative errno code otherwise 0172 */ 0173 int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size, 0174 bool primary, const struct drm_driver *req_driver) 0175 { 0176 return aperture_remove_conflicting_devices(base, size, primary, req_driver->name); 0177 } 0178 EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers); 0179 0180 /** 0181 * drm_aperture_remove_conflicting_pci_framebuffers - remove existing framebuffers for PCI devices 0182 * @pdev: PCI device 0183 * @req_driver: requesting DRM driver 0184 * 0185 * This function removes graphics device drivers using memory range configured 0186 * for any of @pdev's memory bars. The function assumes that PCI device with 0187 * shadowed ROM drives a primary display and so kicks out vga16fb. 0188 * 0189 * Returns: 0190 * 0 on success, or a negative errno code otherwise 0191 */ 0192 int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, 0193 const struct drm_driver *req_driver) 0194 { 0195 return aperture_remove_conflicting_pci_devices(pdev, req_driver->name); 0196 } 0197 EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |