diff options
author | Wang Zhenyu <zhenyu.z.wang@intel.com> | 2007-06-10 01:58:19 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-06-10 01:58:19 -0400 |
commit | dc7a93190c21edbf3ed23e678ad04f852b9cff28 (patch) | |
tree | cc05781518d289b91b4da869881273205fe7ccb1 /drivers/char/drm | |
parent | 2f4042b186b9bfe82f48fe801619c6c285c16bef (diff) |
drm/i915: Add support for the G33, Q33, and Q35 chipsets.
These require that the status page be referenced by a pointer in GTT, rather
than phsyical memory. So, we have the X Server allocate that memory and tell
us the address, instead.
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm')
-rw-r--r-- | drivers/char/drm/drm_pciids.h | 3 | ||||
-rw-r--r-- | drivers/char/drm/i915_dma.c | 87 | ||||
-rw-r--r-- | drivers/char/drm/i915_drm.h | 5 | ||||
-rw-r--r-- | drivers/char/drm/i915_drv.h | 2 |
4 files changed, 80 insertions, 17 deletions
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index e908462051fd..aa6335032d1e 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -305,6 +305,9 @@ | |||
305 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 305 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
306 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 306 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
307 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 307 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
308 | {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
309 | {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
310 | {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
308 | {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 311 | {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
309 | {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 312 | {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
310 | {0, 0, 0} | 313 | {0, 0, 0} |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 730dfeea042d..ea52740af4f6 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -38,6 +38,10 @@ | |||
38 | dev->pci_device == 0x2A02 || \ | 38 | dev->pci_device == 0x2A02 || \ |
39 | dev->pci_device == 0x2A12) | 39 | dev->pci_device == 0x2A12) |
40 | 40 | ||
41 | #define IS_G33(dev) (dev->pci_device == 0x29b2 || \ | ||
42 | dev->pci_device == 0x29c2 || \ | ||
43 | dev->pci_device == 0x29d2) | ||
44 | |||
41 | /* Really want an OS-independent resettable timer. Would like to have | 45 | /* Really want an OS-independent resettable timer. Would like to have |
42 | * this loop run for (eg) 3 sec, but have the timer reset every time | 46 | * this loop run for (eg) 3 sec, but have the timer reset every time |
43 | * the head pointer changes, so that EBUSY only happens if the ring | 47 | * the head pointer changes, so that EBUSY only happens if the ring |
@@ -107,6 +111,12 @@ static int i915_dma_cleanup(drm_device_t * dev) | |||
107 | I915_WRITE(0x02080, 0x1ffff000); | 111 | I915_WRITE(0x02080, 0x1ffff000); |
108 | } | 112 | } |
109 | 113 | ||
114 | if (dev_priv->status_gfx_addr) { | ||
115 | dev_priv->status_gfx_addr = 0; | ||
116 | drm_core_ioremapfree(&dev_priv->hws_map, dev); | ||
117 | I915_WRITE(0x2080, 0x1ffff000); | ||
118 | } | ||
119 | |||
110 | drm_free(dev->dev_private, sizeof(drm_i915_private_t), | 120 | drm_free(dev->dev_private, sizeof(drm_i915_private_t), |
111 | DRM_MEM_DRIVER); | 121 | DRM_MEM_DRIVER); |
112 | 122 | ||
@@ -180,26 +190,24 @@ static int i915_initialize(drm_device_t * dev, | |||
180 | dev_priv->allow_batchbuffer = 1; | 190 | dev_priv->allow_batchbuffer = 1; |
181 | 191 | ||
182 | /* Program Hardware Status Page */ | 192 | /* Program Hardware Status Page */ |
183 | dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, | 193 | if (!IS_G33(dev)) { |
184 | 0xffffffff); | 194 | dev_priv->status_page_dmah = |
195 | drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); | ||
196 | |||
197 | if (!dev_priv->status_page_dmah) { | ||
198 | dev->dev_private = (void *)dev_priv; | ||
199 | i915_dma_cleanup(dev); | ||
200 | DRM_ERROR("Can not allocate hardware status page\n"); | ||
201 | return DRM_ERR(ENOMEM); | ||
202 | } | ||
203 | dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; | ||
204 | dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; | ||
185 | 205 | ||
186 | if (!dev_priv->status_page_dmah) { | 206 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); |
187 | dev->dev_private = (void *)dev_priv; | 207 | I915_WRITE(0x02080, dev_priv->dma_status_page); |
188 | i915_dma_cleanup(dev); | ||
189 | DRM_ERROR("Can not allocate hardware status page\n"); | ||
190 | return DRM_ERR(ENOMEM); | ||
191 | } | 208 | } |
192 | dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; | ||
193 | dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; | ||
194 | |||
195 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); | ||
196 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); | ||
197 | |||
198 | I915_WRITE(0x02080, dev_priv->dma_status_page); | ||
199 | DRM_DEBUG("Enabled hardware status page\n"); | 209 | DRM_DEBUG("Enabled hardware status page\n"); |
200 | |||
201 | dev->dev_private = (void *)dev_priv; | 210 | dev->dev_private = (void *)dev_priv; |
202 | |||
203 | return 0; | 211 | return 0; |
204 | } | 212 | } |
205 | 213 | ||
@@ -232,7 +240,10 @@ static int i915_dma_resume(drm_device_t * dev) | |||
232 | } | 240 | } |
233 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); | 241 | DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); |
234 | 242 | ||
235 | I915_WRITE(0x02080, dev_priv->dma_status_page); | 243 | if (dev_priv->status_gfx_addr != 0) |
244 | I915_WRITE(0x02080, dev_priv->status_gfx_addr); | ||
245 | else | ||
246 | I915_WRITE(0x02080, dev_priv->dma_status_page); | ||
236 | DRM_DEBUG("Enabled hardware status page\n"); | 247 | DRM_DEBUG("Enabled hardware status page\n"); |
237 | 248 | ||
238 | return 0; | 249 | return 0; |
@@ -740,6 +751,47 @@ static int i915_setparam(DRM_IOCTL_ARGS) | |||
740 | return 0; | 751 | return 0; |
741 | } | 752 | } |
742 | 753 | ||
754 | static int i915_set_status_page(DRM_IOCTL_ARGS) | ||
755 | { | ||
756 | DRM_DEVICE; | ||
757 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
758 | drm_i915_hws_addr_t hws; | ||
759 | |||
760 | if (!dev_priv) { | ||
761 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
762 | return DRM_ERR(EINVAL); | ||
763 | } | ||
764 | DRM_COPY_FROM_USER_IOCTL(hws, (drm_i915_hws_addr_t __user *) data, | ||
765 | sizeof(hws)); | ||
766 | printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws.addr); | ||
767 | |||
768 | dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12); | ||
769 | |||
770 | dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws.addr; | ||
771 | dev_priv->hws_map.size = 4*1024; | ||
772 | dev_priv->hws_map.type = 0; | ||
773 | dev_priv->hws_map.flags = 0; | ||
774 | dev_priv->hws_map.mtrr = 0; | ||
775 | |||
776 | drm_core_ioremap(&dev_priv->hws_map, dev); | ||
777 | if (dev_priv->hws_map.handle == NULL) { | ||
778 | dev->dev_private = (void *)dev_priv; | ||
779 | i915_dma_cleanup(dev); | ||
780 | dev_priv->status_gfx_addr = 0; | ||
781 | DRM_ERROR("can not ioremap virtual address for" | ||
782 | " G33 hw status page\n"); | ||
783 | return DRM_ERR(ENOMEM); | ||
784 | } | ||
785 | dev_priv->hw_status_page = dev_priv->hws_map.handle; | ||
786 | |||
787 | memset(dev_priv->hw_status_page, 0, PAGE_SIZE); | ||
788 | I915_WRITE(0x02080, dev_priv->status_gfx_addr); | ||
789 | DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n", | ||
790 | dev_priv->status_gfx_addr); | ||
791 | DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page); | ||
792 | return 0; | ||
793 | } | ||
794 | |||
743 | int i915_driver_load(drm_device_t *dev, unsigned long flags) | 795 | int i915_driver_load(drm_device_t *dev, unsigned long flags) |
744 | { | 796 | { |
745 | /* i915 has 4 more counters */ | 797 | /* i915 has 4 more counters */ |
@@ -786,6 +838,7 @@ drm_ioctl_desc_t i915_ioctls[] = { | |||
786 | [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, | 838 | [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, |
787 | [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, | 839 | [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, |
788 | [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH}, | 840 | [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH}, |
841 | [DRM_IOCTL_NR(DRM_I915_HWS_ADDR)] = {i915_set_status_page, DRM_AUTH}, | ||
789 | }; | 842 | }; |
790 | 843 | ||
791 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 844 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 96a468886a7a..7b7b68b96f31 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
@@ -142,6 +142,7 @@ typedef struct _drm_i915_sarea { | |||
142 | #define DRM_I915_SET_VBLANK_PIPE 0x0d | 142 | #define DRM_I915_SET_VBLANK_PIPE 0x0d |
143 | #define DRM_I915_GET_VBLANK_PIPE 0x0e | 143 | #define DRM_I915_GET_VBLANK_PIPE 0x0e |
144 | #define DRM_I915_VBLANK_SWAP 0x0f | 144 | #define DRM_I915_VBLANK_SWAP 0x0f |
145 | #define DRM_I915_HWS_ADDR 0x11 | ||
145 | 146 | ||
146 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 147 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
147 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 148 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
@@ -262,4 +263,8 @@ typedef struct drm_i915_vblank_swap { | |||
262 | unsigned int sequence; | 263 | unsigned int sequence; |
263 | } drm_i915_vblank_swap_t; | 264 | } drm_i915_vblank_swap_t; |
264 | 265 | ||
266 | typedef struct drm_i915_hws_addr { | ||
267 | uint64_t addr; | ||
268 | } drm_i915_hws_addr_t; | ||
269 | |||
265 | #endif /* _I915_DRM_H_ */ | 270 | #endif /* _I915_DRM_H_ */ |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 93cdcfe6aa84..85e323acb95d 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -91,6 +91,8 @@ typedef struct drm_i915_private { | |||
91 | void *hw_status_page; | 91 | void *hw_status_page; |
92 | dma_addr_t dma_status_page; | 92 | dma_addr_t dma_status_page; |
93 | unsigned long counter; | 93 | unsigned long counter; |
94 | unsigned int status_gfx_addr; | ||
95 | drm_local_map_t hws_map; | ||
94 | 96 | ||
95 | unsigned int cpp; | 97 | unsigned int cpp; |
96 | int back_offset; | 98 | int back_offset; |