diff options
author | Jordan Crouse <jcrouse@codeaurora.org> | 2010-05-27 15:40:25 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-31 20:07:39 -0400 |
commit | dcdb167402cbdca1d021bdfa5f63995ee0a79317 (patch) | |
tree | 3cd0ab1189d972b59daaaf863f518d7b94d2de7a /drivers/gpu/drm/drm_pci.c | |
parent | 01d73a6967f12fe6c4bbde1834a9fe662264a2eb (diff) |
drm: Add support for platform devices to register as DRM devices
Allow platform devices without PCI resources to be DRM devices.
[airlied: fixup warnings with dev pointers]
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_pci.c')
-rw-r--r-- | drivers/gpu/drm/drm_pci.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 2ea9ad4a8d69..e20f78b542a7 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c | |||
@@ -124,4 +124,147 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah) | |||
124 | 124 | ||
125 | EXPORT_SYMBOL(drm_pci_free); | 125 | EXPORT_SYMBOL(drm_pci_free); |
126 | 126 | ||
127 | #ifdef CONFIG_PCI | ||
128 | /** | ||
129 | * Register. | ||
130 | * | ||
131 | * \param pdev - PCI device structure | ||
132 | * \param ent entry from the PCI ID table with device type flags | ||
133 | * \return zero on success or a negative number on failure. | ||
134 | * | ||
135 | * Attempt to gets inter module "drm" information. If we are first | ||
136 | * then register the character device and inter module information. | ||
137 | * Try and register, if we fail to register, backout previous work. | ||
138 | */ | ||
139 | int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | ||
140 | struct drm_driver *driver) | ||
141 | { | ||
142 | struct drm_device *dev; | ||
143 | int ret; | ||
144 | |||
145 | DRM_DEBUG("\n"); | ||
146 | |||
147 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
148 | if (!dev) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | ret = pci_enable_device(pdev); | ||
152 | if (ret) | ||
153 | goto err_g1; | ||
154 | |||
155 | pci_set_master(pdev); | ||
156 | |||
157 | dev->pdev = pdev; | ||
158 | dev->dev = &pdev->dev; | ||
159 | |||
160 | dev->pci_device = pdev->device; | ||
161 | dev->pci_vendor = pdev->vendor; | ||
162 | |||
163 | #ifdef __alpha__ | ||
164 | dev->hose = pdev->sysdata; | ||
165 | #endif | ||
166 | |||
167 | if ((ret = drm_fill_in_dev(dev, ent, driver))) { | ||
168 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | ||
169 | goto err_g2; | ||
170 | } | ||
171 | |||
172 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
173 | pci_set_drvdata(pdev, dev); | ||
174 | ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); | ||
175 | if (ret) | ||
176 | goto err_g2; | ||
177 | } | ||
178 | |||
179 | if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) | ||
180 | goto err_g3; | ||
181 | |||
182 | if (dev->driver->load) { | ||
183 | ret = dev->driver->load(dev, ent->driver_data); | ||
184 | if (ret) | ||
185 | goto err_g4; | ||
186 | } | ||
187 | |||
188 | /* setup the grouping for the legacy output */ | ||
189 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
190 | ret = drm_mode_group_init_legacy_group(dev, | ||
191 | &dev->primary->mode_group); | ||
192 | if (ret) | ||
193 | goto err_g4; | ||
194 | } | ||
195 | |||
196 | list_add_tail(&dev->driver_item, &driver->device_list); | ||
197 | |||
198 | DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", | ||
199 | driver->name, driver->major, driver->minor, driver->patchlevel, | ||
200 | driver->date, pci_name(pdev), dev->primary->index); | ||
201 | |||
202 | return 0; | ||
203 | |||
204 | err_g4: | ||
205 | drm_put_minor(&dev->primary); | ||
206 | err_g3: | ||
207 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
208 | drm_put_minor(&dev->control); | ||
209 | err_g2: | ||
210 | pci_disable_device(pdev); | ||
211 | err_g1: | ||
212 | kfree(dev); | ||
213 | return ret; | ||
214 | } | ||
215 | EXPORT_SYMBOL(drm_get_pci_dev); | ||
216 | |||
217 | /** | ||
218 | * PCI device initialization. Called via drm_init at module load time, | ||
219 | * | ||
220 | * \return zero on success or a negative number on failure. | ||
221 | * | ||
222 | * Initializes a drm_device structures,registering the | ||
223 | * stubs and initializing the AGP device. | ||
224 | * | ||
225 | * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and | ||
226 | * after the initialization for driver customization. | ||
227 | */ | ||
228 | int drm_pci_init(struct drm_driver *driver) | ||
229 | { | ||
230 | struct pci_dev *pdev = NULL; | ||
231 | const struct pci_device_id *pid; | ||
232 | int i; | ||
233 | |||
234 | if (driver->driver_features & DRIVER_MODESET) | ||
235 | return pci_register_driver(&driver->pci_driver); | ||
236 | |||
237 | /* If not using KMS, fall back to stealth mode manual scanning. */ | ||
238 | for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { | ||
239 | pid = &driver->pci_driver.id_table[i]; | ||
240 | |||
241 | /* Loop around setting up a DRM device for each PCI device | ||
242 | * matching our ID and device class. If we had the internal | ||
243 | * function that pci_get_subsys and pci_get_class used, we'd | ||
244 | * be able to just pass pid in instead of doing a two-stage | ||
245 | * thing. | ||
246 | */ | ||
247 | pdev = NULL; | ||
248 | while ((pdev = | ||
249 | pci_get_subsys(pid->vendor, pid->device, pid->subvendor, | ||
250 | pid->subdevice, pdev)) != NULL) { | ||
251 | if ((pdev->class & pid->class_mask) != pid->class) | ||
252 | continue; | ||
253 | |||
254 | /* stealth mode requires a manual probe */ | ||
255 | pci_dev_get(pdev); | ||
256 | drm_get_pci_dev(pdev, pid, driver); | ||
257 | } | ||
258 | } | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | #else | ||
263 | |||
264 | int drm_pci_init(struct drm_driver *driver) | ||
265 | { | ||
266 | return -1; | ||
267 | } | ||
268 | |||
269 | #endif | ||
127 | /*@}*/ | 270 | /*@}*/ |