aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_pci.c
diff options
context:
space:
mode:
authorJordan Crouse <jcrouse@codeaurora.org>2010-05-27 15:40:25 -0400
committerDave Airlie <airlied@redhat.com>2010-05-31 20:07:39 -0400
commitdcdb167402cbdca1d021bdfa5f63995ee0a79317 (patch)
tree3cd0ab1189d972b59daaaf863f518d7b94d2de7a /drivers/gpu/drm/drm_pci.c
parent01d73a6967f12fe6c4bbde1834a9fe662264a2eb (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.c143
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
125EXPORT_SYMBOL(drm_pci_free); 125EXPORT_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 */
139int 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
204err_g4:
205 drm_put_minor(&dev->primary);
206err_g3:
207 if (drm_core_check_feature(dev, DRIVER_MODESET))
208 drm_put_minor(&dev->control);
209err_g2:
210 pci_disable_device(pdev);
211err_g1:
212 kfree(dev);
213 return ret;
214}
215EXPORT_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 */
228int 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
264int drm_pci_init(struct drm_driver *driver)
265{
266 return -1;
267}
268
269#endif
127/*@}*/ 270/*@}*/