xref: /titanic_50/usr/src/uts/intel/io/drm/radeon_drv.c (revision 193974072f41a843678abf5f61979c748687e66b)
1e57b9183Scg149915 /*
2e57b9183Scg149915  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3e57b9183Scg149915  * Use is subject to license terms.
4e57b9183Scg149915  */
5e57b9183Scg149915 /*
6e57b9183Scg149915  * radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
7e57b9183Scg149915  * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
8e57b9183Scg149915  */
9e57b9183Scg149915 /*
10e57b9183Scg149915  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
11e57b9183Scg149915  * All Rights Reserved.
12e57b9183Scg149915  *
13e57b9183Scg149915  * Permission is hereby granted, free of charge, to any person obtaining a
14e57b9183Scg149915  * copy of this software and associated documentation files (the "Software"),
15e57b9183Scg149915  * to deal in the Software without restriction, including without limitation
16e57b9183Scg149915  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17e57b9183Scg149915  * and/or sell copies of the Software, and to permit persons to whom the
18e57b9183Scg149915  * Software is furnished to do so, subject to the following conditions:
19e57b9183Scg149915  *
20e57b9183Scg149915  * The above copyright notice and this permission notice (including the next
21e57b9183Scg149915  * paragraph) shall be included in all copies or substantial portions of the
22e57b9183Scg149915  * Software.
23e57b9183Scg149915  *
24e57b9183Scg149915  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25e57b9183Scg149915  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26e57b9183Scg149915  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
27e57b9183Scg149915  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28e57b9183Scg149915  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29e57b9183Scg149915  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30e57b9183Scg149915  * OTHER DEALINGS IN THE SOFTWARE.
31e57b9183Scg149915  *
32e57b9183Scg149915  * Authors:
33e57b9183Scg149915  *    Gareth Hughes <gareth@valinux.com>
34e57b9183Scg149915  *
35e57b9183Scg149915  */
36e57b9183Scg149915 
37e57b9183Scg149915 #include "drmP.h"
38e57b9183Scg149915 #include "drm.h"
39e57b9183Scg149915 #include "radeon_drm.h"
40e57b9183Scg149915 #include "radeon_drv.h"
41e57b9183Scg149915 #include "drm_pciids.h"
42e57b9183Scg149915 
43e57b9183Scg149915 int radeon_no_wb = 1;
44e57b9183Scg149915 
45e57b9183Scg149915 /*
46e57b9183Scg149915  * cb_ops entrypoint
47e57b9183Scg149915  */
48e57b9183Scg149915 extern struct cb_ops drm_cb_ops;
49e57b9183Scg149915 
50e57b9183Scg149915 /* drv_PCI_IDs comes from drm_pciids.h */
51e57b9183Scg149915 static drm_pci_id_list_t radeon_pciidlist[] = {
52e57b9183Scg149915 	radeon_PCI_IDS
53e57b9183Scg149915 };
54e57b9183Scg149915 
55e57b9183Scg149915 /*
56e57b9183Scg149915  * module entrypoint
57e57b9183Scg149915  */
58e57b9183Scg149915 static int radeon_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
59e57b9183Scg149915 static int radeon_attach(dev_info_t *, ddi_attach_cmd_t);
60e57b9183Scg149915 static int radeon_detach(dev_info_t *, ddi_detach_cmd_t);
61e57b9183Scg149915 
62e57b9183Scg149915 extern void radeon_init_ioctl_arrays(void);
63e57b9183Scg149915 extern uint_t radeon_driver_irq_handler(caddr_t);
64e57b9183Scg149915 extern int drm_get_pci_index_reg(dev_info_t *, uint_t, uint_t, off_t *);
65e57b9183Scg149915 
66e57b9183Scg149915 /*
67e57b9183Scg149915  * Local routines
68e57b9183Scg149915  */
69e57b9183Scg149915 static void radeon_configure(drm_driver_t *);
70e57b9183Scg149915 
71e57b9183Scg149915 /*
72e57b9183Scg149915  * DRM driver
73e57b9183Scg149915  */
74e57b9183Scg149915 static drm_driver_t	radeon_driver = {0};
75e57b9183Scg149915 
76e57b9183Scg149915 static struct dev_ops radeon_dev_ops = {
77e57b9183Scg149915 	DEVO_REV,			/* devo_rev */
78e57b9183Scg149915 	0,				/* devo_refcnt */
79e57b9183Scg149915 	radeon_info,			/* devo_getinfo */
80e57b9183Scg149915 	nulldev,			/* devo_identify */
81e57b9183Scg149915 	nulldev,			/* devo_probe */
82e57b9183Scg149915 	radeon_attach,			/* devo_attach */
83e57b9183Scg149915 	radeon_detach,			/* devo_detach */
84e57b9183Scg149915 	nodev,				/* devo_reset */
85e57b9183Scg149915 	&drm_cb_ops,			/* devo_cb_ops */
86e57b9183Scg149915 	NULL,				/* devo_bus_ops */
87*19397407SSherry Moore 	NULL,				/* power */
88*19397407SSherry Moore 	ddi_quiesce_not_supported,	/* devo_quiesce */
89e57b9183Scg149915 };
90e57b9183Scg149915 
91e57b9183Scg149915 static struct modldrv modldrv = {
92e57b9183Scg149915 	&mod_driverops,			/* drv_modops */
93613b2871SRichard Bean 	"radeon DRM driver",		/* drv_linkinfo */
94e57b9183Scg149915 	&radeon_dev_ops,			/* drv_dev_ops */
95e57b9183Scg149915 };
96e57b9183Scg149915 
97e57b9183Scg149915 static struct modlinkage modlinkage = {
98e57b9183Scg149915 	MODREV_1, (void *) &modldrv, NULL
99e57b9183Scg149915 };
100e57b9183Scg149915 
101e57b9183Scg149915 
102e57b9183Scg149915 /*
103e57b9183Scg149915  * softstate head
104e57b9183Scg149915  */
105e57b9183Scg149915 static void 	*radeon_statep;
106e57b9183Scg149915 
107e57b9183Scg149915 int
_init(void)108e57b9183Scg149915 _init(void)
109e57b9183Scg149915 {
110e57b9183Scg149915 	int error;
111e57b9183Scg149915 
112e57b9183Scg149915 	radeon_configure(&radeon_driver);
113e57b9183Scg149915 
114e57b9183Scg149915 	if ((error = ddi_soft_state_init(&radeon_statep,
115e57b9183Scg149915 	    sizeof (drm_device_t), DRM_MAX_INSTANCES)) != 0)
116e57b9183Scg149915 		return (error);
117e57b9183Scg149915 
118e57b9183Scg149915 	if ((error = mod_install(&modlinkage)) != 0) {
119e57b9183Scg149915 		ddi_soft_state_fini(&radeon_statep);
120e57b9183Scg149915 		return (error);
121e57b9183Scg149915 	}
122e57b9183Scg149915 
123e57b9183Scg149915 	return (error);
124e57b9183Scg149915 
125e57b9183Scg149915 }	/* _init() */
126e57b9183Scg149915 
127e57b9183Scg149915 int
_fini(void)128e57b9183Scg149915 _fini(void)
129e57b9183Scg149915 {
130e57b9183Scg149915 	int error;
131e57b9183Scg149915 
132e57b9183Scg149915 	if ((error = mod_remove(&modlinkage)) != 0)
133e57b9183Scg149915 		return (error);
134e57b9183Scg149915 
135e57b9183Scg149915 	(void) ddi_soft_state_fini(&radeon_statep);
136e57b9183Scg149915 
137e57b9183Scg149915 	return (0);
138e57b9183Scg149915 
139e57b9183Scg149915 }	/* _fini() */
140e57b9183Scg149915 
141e57b9183Scg149915 int
_info(struct modinfo * modinfop)142e57b9183Scg149915 _info(struct modinfo *modinfop)
143e57b9183Scg149915 {
144e57b9183Scg149915 	return (mod_info(&modlinkage, modinfop));
145e57b9183Scg149915 
146e57b9183Scg149915 }	/* _info() */
147e57b9183Scg149915 
148e57b9183Scg149915 
149e57b9183Scg149915 static int
radeon_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)150e57b9183Scg149915 radeon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
151e57b9183Scg149915 {
152e57b9183Scg149915 	drm_device_t	*statep;
153e57b9183Scg149915 	void		*handle;
154e57b9183Scg149915 	int		unit;
155e57b9183Scg149915 
156e57b9183Scg149915 	if (cmd != DDI_ATTACH) {
157e57b9183Scg149915 		DRM_ERROR("radeon_attach: only attach op supported");
158e57b9183Scg149915 		return (DDI_FAILURE);
159e57b9183Scg149915 	}
160e57b9183Scg149915 
161e57b9183Scg149915 	unit =  ddi_get_instance(dip);
162e57b9183Scg149915 	if (ddi_soft_state_zalloc(radeon_statep, unit) != DDI_SUCCESS) {
163e57b9183Scg149915 		cmn_err(CE_WARN,
164e57b9183Scg149915 		    "radeon_attach: alloc softstate failed unit=%d", unit);
165e57b9183Scg149915 		return (DDI_FAILURE);
166e57b9183Scg149915 	}
167e57b9183Scg149915 	statep = ddi_get_soft_state(radeon_statep, unit);
168e57b9183Scg149915 	statep->dip = dip;
169e57b9183Scg149915 	statep->driver = &radeon_driver;
170e57b9183Scg149915 
171e57b9183Scg149915 	/*
172e57b9183Scg149915 	 * Call drm_supp_register to create minor nodes for us
173e57b9183Scg149915 	 */
174e57b9183Scg149915 	handle = drm_supp_register(dip, statep);
175e57b9183Scg149915 	if (handle == NULL) {
176e57b9183Scg149915 		DRM_ERROR("radeon_attach: drm_supp_register failed");
177e57b9183Scg149915 		goto err_exit1;
178e57b9183Scg149915 	}
179e57b9183Scg149915 	statep->drm_handle = handle;
180e57b9183Scg149915 
181e57b9183Scg149915 	/*
182e57b9183Scg149915 	 * After drm_supp_register, we can call drm_xxx routine
183e57b9183Scg149915 	 */
184e57b9183Scg149915 	statep->drm_supported = DRM_UNSUPPORT;
185e57b9183Scg149915 	if (drm_probe(statep, radeon_pciidlist) != DDI_SUCCESS) {
186e57b9183Scg149915 		DRM_ERROR("radeon_open: "
187e57b9183Scg149915 		    "DRM current don't support this graphics card");
188e57b9183Scg149915 		goto err_exit2;
189e57b9183Scg149915 	}
190e57b9183Scg149915 	statep->drm_supported = DRM_SUPPORT;
191e57b9183Scg149915 
192e57b9183Scg149915 	/* call common attach code */
193e57b9183Scg149915 	if (drm_attach(statep) != DDI_SUCCESS) {
194e57b9183Scg149915 		DRM_ERROR("radeon_attach: drm_attach failed");
195e57b9183Scg149915 		goto err_exit2;
196e57b9183Scg149915 	}
197e57b9183Scg149915 	return (DDI_SUCCESS);
198e57b9183Scg149915 
199e57b9183Scg149915 err_exit2:
200e57b9183Scg149915 	(void) drm_supp_unregister(handle);
201e57b9183Scg149915 err_exit1:
202e57b9183Scg149915 	(void) ddi_soft_state_free(radeon_statep, unit);
203e57b9183Scg149915 	return (DDI_FAILURE);
204e57b9183Scg149915 
205e57b9183Scg149915 }	/* radeon_attach() */
206e57b9183Scg149915 
207e57b9183Scg149915 static int
radeon_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)208e57b9183Scg149915 radeon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
209e57b9183Scg149915 {
210e57b9183Scg149915 	drm_device_t	*statep;
211e57b9183Scg149915 	int			unit;
212e57b9183Scg149915 
213e57b9183Scg149915 	if (cmd != DDI_DETACH)
214e57b9183Scg149915 		return (DDI_FAILURE);
215e57b9183Scg149915 
216e57b9183Scg149915 	unit =  ddi_get_instance(dip);
217e57b9183Scg149915 	statep = ddi_get_soft_state(radeon_statep, unit);
218e57b9183Scg149915 	if (statep == NULL)
219e57b9183Scg149915 		return (DDI_FAILURE);
220e57b9183Scg149915 
221e57b9183Scg149915 	(void) drm_detach(statep);
222e57b9183Scg149915 	(void) drm_supp_unregister(statep->drm_handle);
223e57b9183Scg149915 	(void) ddi_soft_state_free(radeon_statep, unit);
224e57b9183Scg149915 
225e57b9183Scg149915 	return (DDI_SUCCESS);
226e57b9183Scg149915 
227e57b9183Scg149915 }	/* radeon_detach() */
228e57b9183Scg149915 
229e57b9183Scg149915 /*ARGSUSED*/
230e57b9183Scg149915 static int
radeon_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)231e57b9183Scg149915 radeon_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
232e57b9183Scg149915 {
233e57b9183Scg149915 	drm_device_t	*statep;
234e57b9183Scg149915 	int 		error = DDI_SUCCESS;
235e57b9183Scg149915 	int 		unit;
236e57b9183Scg149915 
237e57b9183Scg149915 	unit = drm_dev_to_instance((dev_t)arg);
238e57b9183Scg149915 	switch (infocmd) {
239e57b9183Scg149915 	case DDI_INFO_DEVT2DEVINFO:
240e57b9183Scg149915 		statep = ddi_get_soft_state(radeon_statep, unit);
241e57b9183Scg149915 		if (statep == NULL || statep->dip == NULL) {
242e57b9183Scg149915 			error = DDI_FAILURE;
243e57b9183Scg149915 		} else {
244e57b9183Scg149915 			*result = (void *) statep->dip;
245e57b9183Scg149915 			error = DDI_SUCCESS;
246e57b9183Scg149915 		}
247e57b9183Scg149915 		break;
248e57b9183Scg149915 	case DDI_INFO_DEVT2INSTANCE:
249e57b9183Scg149915 		*result = (void *)(uintptr_t)unit;
250e57b9183Scg149915 		error = DDI_SUCCESS;
251e57b9183Scg149915 		break;
252e57b9183Scg149915 	default:
253e57b9183Scg149915 		error = DDI_FAILURE;
254e57b9183Scg149915 		break;
255e57b9183Scg149915 	}
256e57b9183Scg149915 	return (error);
257e57b9183Scg149915 
258e57b9183Scg149915 }	/* radeon_info() */
259e57b9183Scg149915 
260e57b9183Scg149915 static void
radeon_configure(drm_driver_t * driver)261e57b9183Scg149915 radeon_configure(drm_driver_t *driver)
262e57b9183Scg149915 {
263e57b9183Scg149915 	driver->buf_priv_size = sizeof (drm_radeon_buf_priv_t);
264e57b9183Scg149915 	driver->load			= radeon_driver_load;
265e57b9183Scg149915 	driver->unload		= radeon_driver_unload;
266e57b9183Scg149915 	driver->firstopen		= radeon_driver_firstopen;
267e57b9183Scg149915 	driver->open			= radeon_driver_open;
268e57b9183Scg149915 	driver->preclose		= radeon_driver_preclose;
269e57b9183Scg149915 	driver->postclose		= radeon_driver_postclose;
270e57b9183Scg149915 	driver->lastclose		= radeon_driver_lastclose;
271e57b9183Scg149915 	driver->vblank_wait		= radeon_driver_vblank_wait;
272e57b9183Scg149915 	driver->vblank_wait2		= radeon_driver_vblank_wait2;
273e57b9183Scg149915 	driver->irq_preinstall	= radeon_driver_irq_preinstall;
274e57b9183Scg149915 	driver->irq_postinstall	= radeon_driver_irq_postinstall;
275e57b9183Scg149915 	driver->irq_uninstall	= radeon_driver_irq_uninstall;
276e57b9183Scg149915 	driver->irq_handler		= radeon_driver_irq_handler;
277e57b9183Scg149915 	driver->dma_ioctl		= radeon_cp_buffers;
278e57b9183Scg149915 
279e57b9183Scg149915 	driver->driver_ioctls	= radeon_ioctls;
280e57b9183Scg149915 	driver->max_driver_ioctl	= radeon_max_ioctl;
281e57b9183Scg149915 
282e57b9183Scg149915 	driver->driver_name		= DRIVER_NAME;
283e57b9183Scg149915 	driver->driver_desc		= DRIVER_DESC;
284e57b9183Scg149915 	driver->driver_date		= DRIVER_DATE;
285e57b9183Scg149915 	driver->driver_major		= DRIVER_MAJOR;
286e57b9183Scg149915 	driver->driver_minor		= DRIVER_MINOR;
287e57b9183Scg149915 	driver->driver_patchlevel	= DRIVER_PATCHLEVEL;
288e57b9183Scg149915 
289e57b9183Scg149915 	driver->use_agp		= 1;
290e57b9183Scg149915 	driver->use_mtrr		= 1;
291e57b9183Scg149915 	driver->use_pci_dma		= 1;
292e57b9183Scg149915 	driver->use_sg		= 1;
293e57b9183Scg149915 	driver->use_dma		= 1;
294e57b9183Scg149915 	driver->use_irq		= 1;
295e57b9183Scg149915 	driver->use_vbl_irq		= 1;
296e57b9183Scg149915 	driver->use_vbl_irq2		= 1;
297e57b9183Scg149915 
298e57b9183Scg149915 }	/* radeon_configure() */
299