]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/via-unichrome-drm-bugfixes.patch
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / via-unichrome-drm-bugfixes.patch
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/via-unichrome-drm-bugfixes.patch b/src/patches/suse-2.6.27.31/patches.drivers/via-unichrome-drm-bugfixes.patch
deleted file mode 100644 (file)
index 577d5e1..0000000
+++ /dev/null
@@ -1,919 +0,0 @@
-From: Bruce Chang <BruceChang@via.com.tw>
-Subject: via: Unichrome DRM bugfixes
-
-1. Patch the system hang issue caused by multi X support when doing
-   switch user.
-2. Patch system hang issue caused by 3D scaling+ACPI
-3. Patch segmentation fault issue caused by playing video with AGP after
-   resume from suspend.
-4. Reverse the wrong modification we did on the in-line source for
-   coding style only. So ther should no typedef structure...
-5. Move private AGP structure into public.
-6. Remove the modification we did for bypassing DMA check to improve
-   performance.
-
-
-Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-
----
- drivers/gpu/drm/via/via_dma.c |  341 +++++++++++++++++++++++++++++++++++++++++-
- drivers/gpu/drm/via/via_drv.c |   12 +
- drivers/gpu/drm/via/via_drv.h |   12 +
- drivers/gpu/drm/via/via_map.c |   45 +++++
- drivers/gpu/drm/via/via_mm.c  |  137 +++++++++++++++-
- include/drm/via_drm.h         |   43 +++++
- 6 files changed, 576 insertions(+), 14 deletions(-)
-
---- a/drivers/gpu/drm/via/via_dma.c
-+++ b/drivers/gpu/drm/via/via_dma.c
-@@ -68,6 +68,15 @@
-       *vb++ = (w2);                           \
-       dev_priv->dma_low += 8;
-+#define VIA_OUT_VIDEO_AGP_BUFFER(cmd1, cmd2)    \
-+      do {                                    \
-+              *cur_virtual++ = cmd1;          \
-+              *cur_virtual++ = cmd2;          \
-+              cmdbuf_info.cmd_size += 8;      \
-+      } while (0);
-+
-+static void via_cmdbuf_flush(struct drm_via_private *dev_priv,
-+      uint32_t cmd_type);
- static void via_cmdbuf_start(drm_via_private_t * dev_priv);
- static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
- static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
-@@ -75,6 +84,7 @@ static void via_cmdbuf_rewind(drm_via_pr
- static int via_wait_idle(drm_via_private_t * dev_priv);
- static void via_pad_cache(drm_via_private_t * dev_priv, int qwords);
-+
- /*
-  * Free space in command buffer.
-  */
-@@ -155,17 +165,35 @@ static inline uint32_t *via_check_dma(dr
- int via_dma_cleanup(struct drm_device * dev)
- {
-+      struct drm_via_video_save_head *pnode;
-+      int i;
-+
-+
-+      for (pnode = via_video_save_head; pnode; pnode =
-+              (struct drm_via_video_save_head *)pnode->next)
-+              memcpy(pnode->psystemmem, pnode->pvideomem, pnode->size);
-       if (dev->dev_private) {
-               drm_via_private_t *dev_priv =
-                   (drm_via_private_t *) dev->dev_private;
-               if (dev_priv->ring.virtual_start) {
--                      via_cmdbuf_reset(dev_priv);
-+                      if (dev_priv->cr_status == CR_FOR_RINGBUFFER)
-+                              via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
-+
-+                      via_wait_idle(dev_priv);
-                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
-                       dev_priv->ring.virtual_start = NULL;
-               }
-+              for (i = 0; i < 3; i++) {
-+                      if (dev_priv->video_agp_address_map[i].handle &&
-+                       dev_priv->video_agp_address_map[i].size)
-+                              drm_core_ioremapfree(dev_priv->
-+                              video_agp_address_map+i, dev);
-+                      /*Fix for suspend reuse video buf*/
-+                      dev_priv->video_agp_address_map[i].handle = NULL;
-+              }
-       }
-       return 0;
-@@ -175,6 +203,7 @@ static int via_initialize(struct drm_dev
-                         drm_via_private_t * dev_priv,
-                         drm_via_dma_init_t * init)
- {
-+      struct drm_via_video_save_head *pnode;
-       if (!dev_priv || !dev_priv->mmio) {
-               DRM_ERROR("via_dma_init called before via_map_init\n");
-               return -EFAULT;
-@@ -194,6 +223,9 @@ static int via_initialize(struct drm_dev
-               DRM_ERROR("AGP DMA is not supported on this chip\n");
-               return -EINVAL;
-       }
-+
-+      for (pnode = via_video_save_head; pnode; pnode = pnode->next)
-+              memcpy(pnode->pvideomem, pnode->psystemmem, pnode->size);
-       dev_priv->ring.map.offset = dev->agp->base + init->offset;
-       dev_priv->ring.map.size = init->size;
-@@ -224,6 +256,7 @@ static int via_initialize(struct drm_dev
-       via_cmdbuf_start(dev_priv);
-+      dev_priv->cr_status = CR_FOR_RINGBUFFER;
-       return 0;
- }
-@@ -332,12 +365,42 @@ static int via_flush_ioctl(struct drm_de
- static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
- {
-       drm_via_cmdbuffer_t *cmdbuf = data;
--      int ret;
-+      drm_via_private_t *dev_priv = dev->dev_private;
-+      int ret = 0, count;
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
-+      if (dev_priv->cr_status == CR_FOR_VIDEO) {
-+              /* Because our driver will hook CR stop cmd behind video cmd,
-+              * all we need to do here is to wait for CR idle,
-+              * and initialize ring buffer.
-+              */
-+              count = 10000000;
-+              while (count-- && (VIA_READ(VIA_REG_STATUS) &
-+                      VIA_CMD_RGTR_BUSY))
-+                      cpu_relax();
-+              /* Seldom happen */
-+              if (count < 0) {
-+                      DRM_INFO("The CR can't be idle from video agp cmd \
-+                              dispatch when it is needed by ring buffer \n");
-+                      return -1;
-+              }
-+              /* CR has been idle so that we need to initialize ring buffer */
-+              dev_priv->dma_ptr = dev_priv->ring.virtual_start;
-+              dev_priv->dma_low = 0;
-+              dev_priv->dma_high = 0x1000000;
-+              dev_priv->dma_wrap = 0x1000000;
-+              dev_priv->dma_offset = 0x0;
-+              dev_priv->last_pause_ptr = NULL;
-+              dev_priv->hw_addr_ptr = dev_priv->mmio->handle + 0x418;
-+
-+              via_cmdbuf_start(dev_priv);
-+
-+              dev_priv->cr_status = CR_FOR_RINGBUFFER;
-+
-+      }
-       ret = via_dispatch_cmdbuffer(dev, cmdbuf);
-       if (ret) {
-               return ret;
-@@ -346,6 +409,134 @@ static int via_cmdbuffer(struct drm_devi
-       return 0;
- }
-+int via_cmdbuffer_video_agp(struct drm_device *dev, void *data,
-+      struct drm_file *file_priv)
-+{
-+      drm_via_private_t *dev_priv = dev->dev_private;
-+      struct drm_via_video_agp_cmd cmdbuf_info;
-+      int count;
-+      u32 start_addr, start_addr_lo;
-+      u32 end_addr, end_addr_lo;
-+      u32 pause_addr, pause_addr_hi, pause_addr_lo;
-+      u32 *cur_virtual;
-+      u32 command;
-+      int i = 0;
-+      struct drm_map map;
-+
-+      LOCK_TEST_WITH_RETURN(dev, file_priv);
-+
-+      /* Check whether CR services for ring buffer or for video engine. */
-+      if (dev_priv->cr_status == CR_FOR_RINGBUFFER) {
-+              /* Here we need to hook stop cmd in tail of ringbuffer
-+               * in order to stop CR, for we will reset start/end/pause
-+               * address for fetch cmd from video AGP buffer
-+               */
-+               via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
-+      }
-+
-+      /* Set CR status here to avoid ring buffer crush in case we
-+      * can't initialize CR for video properly
-+      */
-+      dev_priv->cr_status = CR_FOR_VIDEO;
-+
-+      /* Wait idle since we will reset CR relevant registers. */
-+      count = 10000000;
-+      while (count-- && (VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY))
-+              cpu_relax();
-+
-+      /* Seldom happen */
-+      if (count < 0) {
-+              DRM_INFO("The CR can't be idle from video agp cmd dispatch \
-+                      when it is needed by ring buffer \n");
-+              return -1;
-+      }
-+
-+      /* Till here, the CR has been idle, all need to here is to initialize
-+      * CR START/END/PAUSE address registers according to video AGP buffer
-+      * location and size. BE LUCKY!!!
-+      */
-+      cmdbuf_info = *(struct drm_via_video_agp_cmd *)data;
-+
-+      start_addr = cmdbuf_info.offset + dev->agp->base;
-+      end_addr = cmdbuf_info.buffer_size + start_addr;
-+
-+      if ((cmdbuf_info.buffer_size & 0xFF) ||
-+      (start_addr + 2 * 0xFF > end_addr) ||
-+      start_addr & 0xFF) {
-+              DRM_INFO("The video cmd is too large or you didn't set the \
-+                      video cmd 2 DWORD alignment. \n");
-+              return -1;
-+      }
-+
-+      map.offset = start_addr;
-+      map.size = cmdbuf_info.buffer_size;
-+      map.type = map.flags = map.mtrr = 0;
-+      map.handle = 0;
-+
-+      for (i = 0; i < 3; i++) {
-+              if ((dev_priv->video_agp_address_map[i].offset == map.offset) &&
-+              (dev_priv->video_agp_address_map[i].size == map.size) &&
-+              dev_priv->video_agp_address_map[i].handle) {
-+                      map.handle = dev_priv->video_agp_address_map[i].handle;
-+                      break;
-+              }
-+              if (!dev_priv->video_agp_address_map[i].handle)
-+                      break;
-+      }
-+
-+      /* Check whether this agp cmd buffer has already been remaped before */
-+      /* case: Never be remaped before */
-+      if (!map.handle) {
-+              drm_core_ioremap(&map, dev);
-+              if (!map.handle)
-+                      return -1;
-+              /* there is a free hole for filling in this address map */
-+              if (i < 3)
-+                      dev_priv->video_agp_address_map[i] = map;
-+              else {
-+                      drm_core_ioremapfree(dev_priv->video_agp_address_map,
-+                              dev);
-+                      dev_priv->video_agp_address_map[0] = map;
-+              }
-+      }
-+
-+      cur_virtual = map.handle + cmdbuf_info.cmd_size;
-+
-+      VIA_OUT_VIDEO_AGP_BUFFER(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
-+                      (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
-+
-+      /* pause register need 0xFF alignment */
-+      do {
-+              VIA_OUT_VIDEO_AGP_BUFFER(HC_DUMMY, HC_DUMMY);
-+      } while (cmdbuf_info.cmd_size & 0xFF);
-+      pause_addr = cmdbuf_info.cmd_size + start_addr - 8;
-+
-+      pause_addr_lo = ((HC_SubA_HAGPBpL << 24) | HC_HAGPBpID_STOP |
-+      (pause_addr & HC_HAGPBpL_MASK));
-+      pause_addr_hi = ((HC_SubA_HAGPBpH << 24) | (pause_addr >> 24));
-+      start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
-+      end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
-+      command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
-+                 ((end_addr & 0xff000000) >> 16));
-+      *(cur_virtual-2) = pause_addr_hi;
-+      *(cur_virtual-1) = pause_addr_lo;
-+
-+      via_flush_write_combine();
-+
-+      VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-+      VIA_WRITE(VIA_REG_TRANSPACE, command);
-+      VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
-+      VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
-+
-+      VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
-+      VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
-+      DRM_WRITEMEMORYBARRIER();
-+      /* fire */
-+      VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
-+
-+      return 0;
-+}
-+
- static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
-                                     drm_via_cmdbuffer_t * cmd)
- {
-@@ -735,6 +926,146 @@ static int via_cmdbuf_size(struct drm_de
-       return ret;
- }
-+/*The following functions are for ACPI*/
-+
-+static void initialize3Dengine(drm_via_private_t *dev_priv)
-+{
-+      int i = 0;
-+
-+      VIA_WRITE(0x43C, 0x00010000);
-+
-+      for (i = 0; i <= 0x7D; i++)
-+              VIA_WRITE(0x440, (unsigned long) i << 24);
-+
-+      VIA_WRITE(0x43C, 0x00020000);
-+
-+      for (i = 0; i <= 0x94; i++)
-+              VIA_WRITE(0x440, (unsigned long) i << 24);
-+
-+      VIA_WRITE(0x440, 0x82400000);
-+      VIA_WRITE(0x43C, 0x01020000);
-+
-+      for (i = 0; i <= 0x94; i++)
-+              VIA_WRITE(0x440, (unsigned long) i << 24);
-+
-+      VIA_WRITE(0x440, 0x82400000);
-+      VIA_WRITE(0x43C, 0xfe020000);
-+
-+      for (i = 0; i <= 0x03; i++)
-+              VIA_WRITE(0x440, (unsigned long) i << 24);
-+
-+      VIA_WRITE(0x43C, 0x00030000);
-+
-+      for (i = 0; i <= 0xff; i++)
-+              VIA_WRITE(0x440, 0);
-+
-+      VIA_WRITE(0x43C, 0x00100000);
-+      VIA_WRITE(0x440, 0x00333004);
-+      VIA_WRITE(0x440, 0x10000002);
-+      VIA_WRITE(0x440, 0x60000000);
-+      VIA_WRITE(0x440, 0x61000000);
-+      VIA_WRITE(0x440, 0x62000000);
-+      VIA_WRITE(0x440, 0x63000000);
-+      VIA_WRITE(0x440, 0x64000000);
-+
-+      VIA_WRITE(0x43C, 0x00fe0000);
-+      VIA_WRITE(0x440, 0x40008c0f);
-+      VIA_WRITE(0x440, 0x44000000);
-+      VIA_WRITE(0x440, 0x45080C04);
-+      VIA_WRITE(0x440, 0x46800408);
-+      VIA_WRITE(0x440, 0x50000000);
-+      VIA_WRITE(0x440, 0x51000000);
-+      VIA_WRITE(0x440, 0x52000000);
-+      VIA_WRITE(0x440, 0x53000000);
-+
-+
-+      VIA_WRITE(0x43C, 0x00fe0000);
-+      VIA_WRITE(0x440, 0x08000001);
-+      VIA_WRITE(0x440, 0x0A000183);
-+      VIA_WRITE(0x440, 0x0B00019F);
-+      VIA_WRITE(0x440, 0x0C00018B);
-+      VIA_WRITE(0x440, 0x0D00019B);
-+      VIA_WRITE(0x440, 0x0E000000);
-+      VIA_WRITE(0x440, 0x0F000000);
-+      VIA_WRITE(0x440, 0x10000000);
-+      VIA_WRITE(0x440, 0x11000000);
-+      VIA_WRITE(0x440, 0x20000000);
-+}
-+/* For acpi case, when system resume from suspend or hibernate,
-+ * need to re-initialize dma info into HW
-+ */
-+int via_drm_resume(struct pci_dev *pci)
-+{
-+      struct drm_device *dev = (struct drm_device *)pci_get_drvdata(pci);
-+      drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-+      struct drm_via_video_save_head *pnode = 0;
-+
-+      if (!dev_priv->initialize)
-+              return 0;
-+      /* when resume, initialize 3d registers */
-+      initialize3Dengine(dev_priv);
-+
-+      /* here we need to restore some video memory content */
-+      for (pnode = via_video_save_head; pnode; pnode = pnode->next)
-+              memcpy(pnode->pvideomem, pnode->psystemmem, pnode->size);
-+
-+      /* if pci path, return */
-+      if (!dev_priv->ring.virtual_start)
-+              return 0;
-+
-+      dev_priv->dma_ptr = dev_priv->ring.virtual_start;
-+      dev_priv->dma_low = 0;
-+      dev_priv->dma_high = 0x1000000;
-+      dev_priv->dma_wrap = 0x1000000;
-+      dev_priv->dma_offset = 0x0;
-+      dev_priv->last_pause_ptr = NULL;
-+      dev_priv->hw_addr_ptr = dev_priv->mmio->handle + 0x418;
-+
-+      via_cmdbuf_start(dev_priv);
-+
-+      return 0;
-+}
-+
-+int via_drm_suspend(struct pci_dev *pci, pm_message_t state)
-+{
-+      struct drm_device *dev = (struct drm_device *)pci_get_drvdata(pci);
-+      drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-+
-+      struct drm_via_video_save_head *pnode = 0;
-+
-+      if (!dev_priv->initialize)
-+              return 0;
-+      /*here we need to save some video mem information into system memory,
-+      to keep the system consistent between suspend *before* and *after*
-+      1.save only necessary */
-+      for (pnode = via_video_save_head; pnode;
-+              pnode = (struct drm_via_video_save_head *)pnode->next)
-+              memcpy(pnode->psystemmem, pnode->pvideomem, pnode->size);
-+
-+      /* Only agp path need to flush the cmd */
-+      if (dev_priv->ring.virtual_start)
-+              via_cmdbuf_reset(dev_priv);
-+
-+      return 0;
-+}
-+int via_drm_authmagic(struct drm_device *dev, void *data,
-+      struct drm_file *file_priv)
-+{
-+      return 0;
-+}
-+
-+int via_drm_init_judge(struct drm_device *dev, void *data,
-+      struct drm_file *file_priv)
-+{
-+      struct drm_via_private *dev_priv = dev->dev_private;
-+
-+      if (dev_priv->initialize)
-+              *(int *)data = 1;
-+      else
-+              *(int *)data = -1;
-+      return 0;
-+}
-+
- struct drm_ioctl_desc via_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH),
-@@ -742,6 +1073,7 @@ struct drm_ioctl_desc via_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_VIA_GET_INFO, via_get_drm_info, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
-@@ -749,7 +1081,10 @@ struct drm_ioctl_desc via_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
--      DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
-+      DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH),
-+      DRM_IOCTL_DEF(DRM_VIA_AUTH_MAGIC, via_drm_authmagic, 0),
-+      DRM_IOCTL_DEF(DRM_VIA_FLUSH_VIDEO, via_cmdbuffer_video_agp, 0),
-+      DRM_IOCTL_DEF(DRM_VIA_INIT_JUDGE, via_drm_init_judge, 0)
- };
- int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
---- a/drivers/gpu/drm/via/via_drv.c
-+++ b/drivers/gpu/drm/via/via_drv.c
-@@ -37,10 +37,16 @@ static struct pci_device_id pciidlist[] 
-       viadrv_PCI_IDS
- };
-+int  via_driver_open(struct drm_device *dev, struct drm_file *priv)
-+{
-+    priv->authenticated = 1;
-+    return 0;
-+}
- static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
-           DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
-+      .open = via_driver_open,
-       .load = via_driver_load,
-       .unload = via_driver_unload,
-       .context_dtor = via_final_context,
-@@ -68,8 +74,10 @@ static struct drm_driver driver = {
-                .fasync = drm_fasync,
-       },
-       .pci_driver = {
--               .name = DRIVER_NAME,
--               .id_table = pciidlist,
-+              .name = DRIVER_NAME,
-+              .id_table = pciidlist,
-+              .suspend = via_drm_suspend,
-+              .resume = via_drm_resume,
-       },
-       .name = DRIVER_NAME,
---- a/drivers/gpu/drm/via/via_drv.h
-+++ b/drivers/gpu/drm/via/via_drv.h
-@@ -62,6 +62,7 @@ typedef struct drm_via_private {
-       drm_local_map_t *sarea;
-       drm_local_map_t *fb;
-       drm_local_map_t *mmio;
-+      enum drm_agp_type agptype;
-       unsigned long agpAddr;
-       wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
-       char *dma_ptr;
-@@ -93,7 +94,13 @@ typedef struct drm_via_private {
-       unsigned long vram_offset;
-       unsigned long agp_offset;
-       drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
-+      struct drm_map video_agp_address_map[3];
-+      enum {
-+      CR_FOR_RINGBUFFER,
-+      CR_FOR_VIDEO
-+      } cr_status;
-       uint32_t dma_diff;
-+      int initialize;
- } drm_via_private_t;
- enum via_family {
-@@ -119,6 +126,8 @@ extern int via_mem_free(struct drm_devic
- extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
- extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
- extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
-+extern int via_get_drm_info(struct drm_device *dev, void *data,
-+      struct drm_file *file_priv);
- extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
- extern int via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv );
- extern int via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv );
-@@ -150,4 +159,7 @@ extern void via_lastclose(struct drm_dev
- extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
- extern void via_init_dmablit(struct drm_device *dev);
-+extern int via_drm_resume(struct pci_dev *dev);
-+extern int via_drm_suspend(struct pci_dev *dev, pm_message_t state);
-+
- #endif
---- a/drivers/gpu/drm/via/via_map.c
-+++ b/drivers/gpu/drm/via/via_map.c
-@@ -25,6 +25,7 @@
- #include "via_drm.h"
- #include "via_drv.h"
-+static int associate;
- static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
- {
-       drm_via_private_t *dev_priv = dev->dev_private;
-@@ -65,12 +66,35 @@ static int via_do_init_map(struct drm_de
-       via_init_dmablit(dev);
-       dev->dev_private = (void *)dev_priv;
-+
-+      /* from doing this, we has the stuff in prev data
-+       * structure to manage agp
-+       */
-+      if (init->agp_type != DISABLED) {
-+              dev->agp_buffer_map = drm_core_findmap(dev, init->agp_offset);
-+              if (!dev->agp_buffer_map) {
-+                      DRM_ERROR("failed to find dma buffer region!\n");
-+                      return -EINVAL;
-+              }
-+              if (init->agp_type == AGP_DOUBLE_BUFFER)
-+                      dev_priv->agptype = AGP_DOUBLE_BUFFER;
-+              if (init->agp_type == AGP_RING_BUFFER)
-+                      dev_priv->agptype = AGP_RING_BUFFER;
-+      } else {
-+              dev_priv->agptype = DISABLED;
-+              dev->agp_buffer_map = 0;
-+      }
-+      /* end */
-+      dev_priv->initialize = 1;
-+
-       return 0;
- }
- int via_do_cleanup_map(struct drm_device * dev)
- {
-+      drm_via_private_t *dev_priv = dev->dev_private;
-       via_dma_cleanup(dev);
-+      dev_priv->initialize = 0;
-       return 0;
- }
-@@ -95,6 +119,11 @@ int via_driver_load(struct drm_device *d
- {
-       drm_via_private_t *dev_priv;
-       int ret = 0;
-+      if (!associate) {
-+              pci_set_drvdata(dev->pdev, dev);
-+              dev->pdev->driver = &dev->driver->pci_driver;
-+              associate = 1;
-+      }
-       dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-@@ -121,3 +150,19 @@ int via_driver_unload(struct drm_device 
-       return 0;
- }
-+int via_get_drm_info(struct drm_device *dev, void *data,
-+      struct drm_file *file_priv)
-+{
-+      drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-+      struct drm_via_info *info = data;
-+
-+      if (!dev_priv->initialize)
-+              return -EINVAL;
-+
-+      info->RegSize = dev_priv->mmio->size;
-+      info->AgpSize = dev->agp_buffer_map->size;
-+      info->RegHandle = dev_priv->mmio->offset;
-+      info->AgpHandle = dev->agp_buffer_map->offset;
-+
-+      return 0;
-+}
---- a/drivers/gpu/drm/via/via_mm.c
-+++ b/drivers/gpu/drm/via/via_mm.c
-@@ -30,6 +30,7 @@
- #include "via_drv.h"
- #include "drm_sman.h"
-+struct drm_via_video_save_head *via_video_save_head;
- #define VIA_MM_ALIGN_SHIFT 4
- #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
-@@ -56,6 +57,8 @@ int via_agp_init(struct drm_device *dev,
-       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
-       return 0;
- }
-+static void *global_dev;
-+static void *global_file_priv;
- int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
- {
-@@ -78,6 +81,8 @@ int via_fb_init(struct drm_device *dev, 
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
-+      global_dev = dev;
-+      global_file_priv = file_priv;
-       return 0;
-@@ -115,6 +120,84 @@ void via_lastclose(struct drm_device *de
-       mutex_unlock(&dev->struct_mutex);
- }
-+static int via_videomem_presave_ok(drm_via_private_t *dev_priv,
-+      drm_via_mem_t *mem)
-+{
-+      void *pvideomem = 0, *psystemmem = 0;
-+      struct drm_via_video_save_head *pnode = 0;
-+
-+      if (!mem || !mem->size || (mem->type != VIA_MEM_VIDEO_SAVE))
-+              return 0;
-+
-+      /* here the mem->offset is the absolute address,
-+       * not the offset within videomem
-+       */
-+      pvideomem = (void *)ioremap(dev_priv->fb->offset + mem->offset,
-+              mem->size);
-+      if (!pvideomem)
-+              return 0;
-+
-+      psystemmem = kmalloc(mem->size, GFP_KERNEL);
-+      if (!psystemmem) {
-+              iounmap(pvideomem);
-+              return 0;
-+      }
-+
-+      /* map success, then save this information into
-+       * a data structure for later saving usage
-+       */
-+      pnode = kmalloc(
-+              sizeof(struct drm_via_video_save_head), GFP_KERNEL);
-+      if (!pnode) {
-+              iounmap(pvideomem);
-+              kfree(psystemmem);
-+              return 0;
-+      }
-+
-+      pnode->next = 0;
-+      pnode->psystemmem = psystemmem;
-+      pnode->pvideomem = pvideomem;
-+      pnode->size = mem->size;
-+      pnode->token = mem->offset;
-+
-+      /* insert this node into list */
-+      if (!via_video_save_head) {
-+              via_video_save_head = pnode;
-+      } else {
-+              pnode->next = via_video_save_head;
-+              via_video_save_head = pnode;
-+      }
-+
-+      return 1;
-+}
-+
-+static int via_videomem_housekeep_ok(drm_via_mem_t *mem)
-+{
-+      struct drm_via_video_save_head **ppnode = 0;
-+      struct drm_via_video_save_head *tmpnode = 0;
-+      /* if this mem's token match with one node of the list */
-+      for (ppnode = &via_video_save_head; *ppnode;
-+      ppnode = (struct drm_via_video_save_head **)(&((*ppnode)->next))) {
-+              if ((*ppnode)->token == mem->offset)
-+                      break;
-+      }
-+
-+      if (*ppnode == 0) {
-+              /* not found, the user may specify the wrong mem node to free */
-+              return 0;
-+      }
-+
-+      /* delete this node from the list and then
-+      *free all the mem to avoid memory leak
-+      */
-+      tmpnode = *ppnode;
-+      *ppnode = (*ppnode)->next;
-+      iounmap(tmpnode->pvideomem);
-+      kfree(tmpnode->psystemmem);
-+      kfree(tmpnode);
-+
-+      return 1;
-+}
- int via_mem_alloc(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
- {
-@@ -124,12 +207,13 @@ int via_mem_alloc(struct drm_device *dev
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned long tmpSize;
--      if (mem->type > VIA_MEM_AGP) {
-+      if (mem->type > VIA_MEM_VIDEO_SAVE) {
-               DRM_ERROR("Unknown memory type allocation\n");
-               return -EINVAL;
-       }
-       mutex_lock(&dev->struct_mutex);
--      if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
-+      if (0 == ((mem->type == VIA_MEM_VIDEO ||
-+              mem->type == VIA_MEM_VIDEO_SAVE) ? dev_priv->vram_initialized :
-                     dev_priv->agp_initialized)) {
-               DRM_ERROR
-                   ("Attempt to allocate from uninitialized memory manager.\n");
-@@ -138,15 +222,25 @@ int via_mem_alloc(struct drm_device *dev
-       }
-       tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
--      item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0,
--                            (unsigned long)file_priv);
-+      item = drm_sman_alloc(&dev_priv->sman,
-+              (mem->type == VIA_MEM_VIDEO_SAVE ? VIA_MEM_VIDEO : mem->type),
-+                      tmpSize, 0, (unsigned long)file_priv);
-       mutex_unlock(&dev->struct_mutex);
-       if (item) {
--              mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
--                            dev_priv->vram_offset : dev_priv->agp_offset) +
--                  (item->mm->
--                   offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
-+              mem->offset = ((mem->type == VIA_MEM_VIDEO ||
-+                      mem->type == VIA_MEM_VIDEO_SAVE) ?
-+                      dev_priv->vram_offset : dev_priv->agp_offset) +
-+                      (item->mm->offset(item->mm, item->mm_info) <<
-+                      VIA_MM_ALIGN_SHIFT);
-               mem->index = item->user_hash.key;
-+              if (mem->type == VIA_MEM_VIDEO_SAVE) {
-+                      if (!via_videomem_presave_ok(dev_priv, mem)) {
-+                              mutex_lock(&dev->struct_mutex);
-+                              drm_sman_free_key(&dev_priv->sman, mem->index);
-+                              mutex_unlock(&dev->struct_mutex);
-+                              retval = -ENOMEM;
-+                      }
-+              }
-       } else {
-               mem->offset = 0;
-               mem->size = 0;
-@@ -166,6 +260,10 @@ int via_mem_free(struct drm_device *dev,
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_free_key(&dev_priv->sman, mem->index);
-+      if (mem->type == VIA_MEM_VIDEO_SAVE) {
-+              if (!via_videomem_housekeep_ok(mem))
-+                      ret = -EINVAL;
-+      }
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("free = 0x%lx\n", mem->index);
-@@ -192,3 +290,26 @@ void via_reclaim_buffers_locked(struct d
-       mutex_unlock(&dev->struct_mutex);
-       return;
- }
-+static int via_fb_alloc(drm_via_mem_t *mem)
-+{
-+      struct drm_device *dev = global_dev;
-+      struct drm_file *file_priv = global_file_priv;
-+
-+      if (dev && file_priv)
-+              return via_mem_alloc(dev, mem, file_priv);
-+      else
-+              return -EINVAL;
-+}
-+EXPORT_SYMBOL(via_fb_alloc);
-+
-+static int via_fb_free(drm_via_mem_t *mem)
-+{
-+      struct drm_device *dev = global_dev;
-+      struct drm_file *file_priv = global_file_priv;
-+
-+      if (dev && file_priv)
-+              return via_mem_free(dev, mem, file_priv);
-+      else
-+              return -EINVAL;
-+}
-+EXPORT_SYMBOL(via_fb_free);
---- a/include/drm/via_drm.h
-+++ b/include/drm/via_drm.h
-@@ -51,6 +51,12 @@
- #define VIA_LOG_MIN_TEX_REGION_SIZE 16
- #endif
-+struct drm_via_info {
-+      unsigned long AgpHandle;
-+      unsigned long AgpSize;
-+      unsigned long RegHandle;
-+      unsigned long RegSize;
-+} ;
- #define VIA_UPLOAD_TEX0IMAGE  0x1     /* handled clientside */
- #define VIA_UPLOAD_TEX1IMAGE  0x2     /* handled clientside */
- #define VIA_UPLOAD_CTX        0x4
-@@ -67,7 +73,7 @@
- #define DRM_VIA_FB_INIT               0x03
- #define DRM_VIA_MAP_INIT      0x04
- #define DRM_VIA_DEC_FUTEX       0x05
--#define NOT_USED
-+#define DRM_VIA_GET_INFO    0x06
- #define DRM_VIA_DMA_INIT      0x07
- #define DRM_VIA_CMDBUFFER     0x08
- #define DRM_VIA_FLUSH         0x09
-@@ -77,6 +83,9 @@
- #define DRM_VIA_WAIT_IRQ        0x0d
- #define DRM_VIA_DMA_BLIT        0x0e
- #define DRM_VIA_BLIT_SYNC       0x0f
-+#define DRM_VIA_AUTH_MAGIC      0x11
-+#define DRM_VIA_FLUSH_VIDEO   0x12
-+#define DRM_VIA_INIT_JUDGE    0x16
- #define DRM_IOCTL_VIA_ALLOCMEM          DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
- #define DRM_IOCTL_VIA_FREEMEM   DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
-@@ -84,6 +93,8 @@
- #define DRM_IOCTL_VIA_FB_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t)
- #define DRM_IOCTL_VIA_MAP_INIT          DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t)
- #define DRM_IOCTL_VIA_DEC_FUTEX   DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t)
-+#define DRM_IOCTL_VIA_GET_INFO    DRM_IOR(DRM_COMMAND_BASE + \
-+                                      DRM_VIA_GET_INFO, struct drm_via_info)
- #define DRM_IOCTL_VIA_DMA_INIT          DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t)
- #define DRM_IOCTL_VIA_CMDBUFFER         DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t)
- #define DRM_IOCTL_VIA_FLUSH     DRM_IO(  DRM_COMMAND_BASE + DRM_VIA_FLUSH)
-@@ -91,8 +102,14 @@
- #define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
-                                           drm_via_cmdbuf_size_t)
- #define DRM_IOCTL_VIA_WAIT_IRQ    DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
-+#define DRM_IOCTL_VIA_FLUSH_VIDEO DRM_IOW(DRM_COMMAND_BASE + \
-+                      DRM_VIA_FLUSH_VIDEO, struct drm_via_video_agp_cmd)
- #define DRM_IOCTL_VIA_DMA_BLIT    DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)
- #define DRM_IOCTL_VIA_BLIT_SYNC   DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)
-+#define DRM_IOCTL_VIA_AUTH_MAGIC  DRM_IOW(DRM_COMMAND_BASE + \
-+                                      DRM_VIA_AUTH_MAGIC, drm_auth_t)
-+#define DRM_IOCTL_VIA_INIT_JUDGE  DRM_IOR(DRM_COMMAND_BASE + \
-+                                      DRM_VIA_INIT_JUDGE, int)
- /* Indices into buf.Setup where various bits of state are mirrored per
-  * context and per buffer.  These can be fired at the card as a unit,
-@@ -112,6 +129,13 @@
- #define VIA_MEM_SYSTEM  2
- #define VIA_MEM_MIXED   3
- #define VIA_MEM_UNKNOWN 4
-+#define VIA_MEM_VIDEO_SAVE      2 /*For video memory need to be saved in ACPI */
-+
-+enum drm_agp_type {
-+      AGP_RING_BUFFER,
-+      AGP_DOUBLE_BUFFER,
-+      DISABLED
-+};
- typedef struct {
-       uint32_t offset;
-@@ -141,6 +165,8 @@ typedef struct _drm_via_init {
-       unsigned long fb_offset;
-       unsigned long mmio_offset;
-       unsigned long agpAddr;
-+      unsigned long agp_offset;
-+      enum drm_agp_type agp_type;
- } drm_via_init_t;
- typedef struct _drm_via_futex {
-@@ -245,6 +271,12 @@ typedef union drm_via_irqwait {
-       struct drm_wait_vblank_reply reply;
- } drm_via_irqwait_t;
-+struct drm_via_video_agp_cmd {
-+      u32 offset;
-+      u32 cmd_size;
-+      u32 buffer_size;
-+} ;
-+
- typedef struct drm_via_blitsync {
-       uint32_t sync_handle;
-       unsigned engine;
-@@ -272,4 +304,13 @@ typedef struct drm_via_dmablit {
-       drm_via_blitsync_t sync;
- } drm_via_dmablit_t;
-+struct drm_via_video_save_head {
-+    void *pvideomem;
-+    void *psystemmem;
-+    int size;
-+    /* token used to identify this video memory */
-+    unsigned long token;
-+    void *next;
-+} ;
-+extern struct drm_via_video_save_head *via_video_save_head;
- #endif                                /* _VIA_DRM_H_ */