]> xenbits.xen.org Git - xenclient/ioemu.git/commitdiff
Imporved intel driver:
authorJean Guyader <jean.guyader@eu.citrix.com>
Sun, 19 Apr 2009 17:45:15 +0000 (18:45 +0100)
committerJean Guyader <jean.guyader@eu.citrix.com>
Sun, 19 Apr 2009 17:48:56 +0000 (18:48 +0100)
- Now work if only surface B is enabled.
- Be a bit more carefull when we setup the linesize.
  The vga doesn't like weird linesize (0 or -1).

intel.c

diff --git a/intel.c b/intel.c
index a790d2f5c486d8a884223381722f973bcfe94062..16c719eb1dd4d2fe5da4b7bb7cc383a2717f110e 100644 (file)
--- a/intel.c
+++ b/intel.c
@@ -29,7 +29,8 @@
 #define REG_DR_DSPBSTRIDE      0x71188
 #define REG_DR_PIPEBCONF       0x71008
 
-#define REG_DE_PIPEASRC                0x6001c
+#define REG_DR_PIPEASRC                0x6001c
+#define REG_DR_PIPEBSRC                0x6101c
 
 extern int                      vga_passthrough;
 uint32_t                        guest_framebuffer;
@@ -61,19 +62,78 @@ static inline unsigned int intel_get_reg(unsigned int reg)
     return *(unsigned int*)(intel_mmio + reg);
 }
 
+static inline void intel_get_res(unsigned int *x, unsigned int *y)
+{
+    unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF);
+    unsigned int *pipebconf = (unsigned int *)(intel_mmio + REG_DR_PIPEBCONF);
+
+    if ((*pipeaconf & (1 << 30)))
+    {
+           *x = ((intel_get_reg(REG_DR_PIPEASRC) >> 16) & 0xfff) + 1;
+           *y = (intel_get_reg(REG_DR_PIPEASRC) & 0xfff) + 1;
+           return;
+    }
+    if ((*pipebconf & (1 << 30)))
+    {
+           *x = ((intel_get_reg(REG_DR_PIPEBSRC) >> 16) & 0xfff) + 1;
+           *y = (intel_get_reg(REG_DR_PIPEBSRC) & 0xfff) + 1;
+           return;
+    }
+
+    INTEL_DEBUG("No pipe available (PIPEACONF=0x%x,PIPEBCONF=0x%x)!!\n",
+               *pipeaconf, *pipebconf);
+    exit(2);
+}
+
+static inline unsigned int get_surf(void)
+{
+    unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
+    unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR);
+
+    if ((*dspacntr & (1 << 31)))
+        return *(unsigned int *)(intel_mmio + REG_DR_DSPASURF);
+    if ((*dspbcntr & (1 << 31)))
+        return *(unsigned int *)(intel_mmio + REG_DR_DSPBSURF);
+
+    INTEL_DEBUG("No surface available (DSPACNTR=0x%x,DSPBCNTR=0x%x)!!\n",
+               *dspacntr, *dspbcntr);
+    exit(2);
+}
+
 static inline int is_linear(void)
 {
     unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
-    if (((*dspacntr) & (1 << 10)) == 0)
+    unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR);
+
+    if (((*dspacntr & (1 << 31)) && (*dspacntr & (1 << 10) == 0)) ||
+       ((*dspbcntr & (1 << 31)) && (*dspbcntr & (1 << 10)) == 0))
+    {
+       INTEL_DEBUG("Framebuffer is linear\n");
         return 1;
+    }
     else
         return 0;
 }
 
-static inline unsigned int intel_get_pitch(void)
+static inline void intel_get_pitch(DisplayState *ds)
 {
-    unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
-    return *dspastride;
+    unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
+    unsigned int *dspbcntr = (unsigned int *)(intel_mmio + REG_DR_DSPBCNTR);
+
+    if (*dspacntr != -1 && (*dspacntr & (1 << 31)))
+    {
+        ds->linesize = *(unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
+       return;
+    }
+    if (*dspbcntr != -1 && (*dspbcntr & (1 << 31)))
+    {
+        ds->linesize = *(unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE);
+       return;
+    }
+
+    INTEL_DEBUG("No surface available (DSPACNTR=0x%x,DSPBCNTR=0x%x)!!\n",
+               *dspacntr, *dspbcntr);
+    ds->linesize = ds->width * (ds->depth / 8);
 }
 
 static inline unsigned int intel_get_offset(DisplayState *ds, int x, int y)
@@ -84,9 +144,10 @@ static inline unsigned int intel_get_offset(DisplayState *ds, int x, int y)
 static void intel_update_linear(DisplayState *ds, int x, int y, int w, int h)
 {
     int i, bpp = lds->depth / 8;
-    unsigned char *s, *d;
+    unsigned char *s, *d, *d2;
+
     s = lds->data;
-    d = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF));
+    d = (unsigned char *)(intel_mem + get_surf());
     s += (lds->linesize * y) + bpp * x;
     d += (lds->linesize * y) + bpp * x;
     for (i = 0; i < h; i++) {
@@ -109,21 +170,24 @@ static void intel_force_linear(int linesize)
     unsigned int *dspbstride = (unsigned int *)(intel_mmio + REG_DR_DSPBSTRIDE);
 
     unsigned int surfa, surfb, pipea, pipeb;
+    char pipeaenabled = !!(*pipeaconf & (1 << 30));
     char pipebenabled = !!(*pipebconf & (1 << 30));
 
+    if (pipeaenabled)
+    {
+        INTEL_DEBUG("PIPEACONF enabled.\n");
 
-    INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR));
-
-    /* Disable surface */
-    pipea = *pipeaconf & (0x3 << 18);
-    *pipeaconf &= ~(0x3 << 18);
-    *dspacntr |= (1 << 31);
-    /* Address of the surface to map to */
-    surfa = *dspasurf;
-    *dspasurf = 0x00000000;
-    *dspacntr &= ~(1 << 31);
-    *dspasurf = 0x00000000;
-    *pipeaconf |= pipea;
+        /* Disable surface */
+       pipea = *pipeaconf & (0x3 << 18);
+       *pipeaconf &= ~(0x3 << 18);
+       *dspacntr |= (1 << 31);
+       /* Address of the surface to map to */
+       surfa = *dspasurf;
+       *dspasurf = 0x00000000;
+       *dspacntr &= ~(1 << 31);
+       *dspasurf = 0x00000000;
+       *pipeaconf |= pipea;
+    }
 
     if (pipebenabled) {
         INTEL_DEBUG("PIPEBCONF enabled.\n");
@@ -142,13 +206,16 @@ static void intel_force_linear(int linesize)
 
     usleep(20000);
 
-    *pipeaconf &= ~(0x3 << 18);
-    /* Enable surface linear mode */
-    *dspacntr &= ~(1 << 10);
-    if (linesize) *dspastride = linesize;
-    *dspasurf = surfa;
-    *dspacntr |= (1 << 31);
-    *pipeaconf |= pipea;
+    if (pipeaenabled)
+    {
+        *pipeaconf &= ~(0x3 << 18);
+       /* Enable surface linear mode */
+       *dspacntr &= ~(1 << 10);
+       if (linesize) *dspastride = linesize;
+       *dspasurf = surfa;
+       *dspacntr |= (1 << 31);
+       *pipeaconf |= pipea;
+    }
 
     if (pipebenabled) {
         *pipebconf &= ~(0x3 << 18);
@@ -175,20 +242,20 @@ static void set_fb_mapping(void)
     unsigned long nr_pfn;
 
     unset_vga_acc();
-    fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer);
+    fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + get_surf()), guest_framebuffer);
     nr_pfn = (lds->linesize * lds->height) >> TARGET_PAGE_BITS;
 
     rc = xc_domain_memory_mapping(xc_handle,
             domid,
             (guest_framebuffer >> TARGET_PAGE_BITS),
-            ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS),
+            ((intel_fb_base + get_surf()) >> TARGET_PAGE_BITS),
             nr_pfn,
             DPCI_ADD_MAPPING);
     if (rc) {
         fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
         return;
     }
-    map_s = ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS);
+    map_s = ((intel_fb_base + get_surf()) >> TARGET_PAGE_BITS);
     map_d = (guest_framebuffer >> TARGET_PAGE_BITS);
     map_size = nr_pfn;
 }
@@ -255,12 +322,15 @@ static void intel_resize_shared(DisplayState *ds, int w, int h, int depth, int l
 
 static void intel_resize(DisplayState *ds, int w, int h)
 {
-    int old_linesize = ds->linesize;
-    INTEL_DEBUG("intel_resize: no shared buffer, linesize=%d\n", ds->linesize);
+    int old_linesize;
+
+    INTEL_DEBUG("intel_resize: no shared buffer, w=%d,h=%d,linesize=%d\n",
+               w, h, ds->linesize);
+    old_linesize = ds->linesize;
     ds->width = w;
     ds->height = h;
     ds->depth = 32;
-    ds->linesize = intel_get_pitch();
+    intel_get_pitch(ds);
     if (map_size) {
         unset_fb_mapping();
         unset_data_mappings(1);
@@ -281,7 +351,7 @@ static void intel_resize(DisplayState *ds, int w, int h)
         set_data_pointer();
     }
     if (intel_have_focus)
-        memset((unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)), 0x0, IntelX * IntelY);
+        memset((unsigned char *)(intel_mem + get_surf()), 0x0, IntelX * IntelY);
     if (refresh) {
         if (old_data) {
             unsigned char *s, *d;
@@ -296,6 +366,8 @@ static void intel_resize(DisplayState *ds, int w, int h)
         }
         refresh = 0;
     }
+    INTEL_DEBUG("intel_resize: done, w=%d,h=%d,linesize=%d\n",
+               ds->width, ds->height, ds->linesize);
 }
 
 static void intel_refresh(DisplayState *ds)
@@ -351,7 +423,7 @@ static void intel_init_mapping(void)
 
 static void set_data_pointer(void)
 {
-    lds->data = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF));
+    lds->data = (unsigned char *)(intel_mem + get_surf());
     lds->data = lds->data +
                 lds->linesize * ((IntelY - lds->height) / 2) +
                 4 * ((IntelX - lds->width) / 2);
@@ -375,7 +447,7 @@ static void unset_data_mappings(int mapping)
         old_data = NULL;
         lds->data = realloc(lds->data, lds->linesize * lds->height);
         memcpy(lds->data,
-                (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)),
+                (unsigned char *)(intel_mem + get_surf()),
                 lds->linesize * lds->height);
         memcpy(buffer_pointer,
                 lds->data,
@@ -407,8 +479,7 @@ void intel_focus(int focus)
     if (focus) {
         if (!is_linear()) {
            IntelPitch = intel_get_reg(REG_DR_DSPASTRIDE);
-           IntelX = ((intel_get_reg(REG_DE_PIPEASRC) >> 16) & 0xfff) + 1;
-           IntelY = (intel_get_reg(REG_DE_PIPEASRC) & 0xfff) + 1;
+           intel_get_res(&IntelX, &IntelY);
            INTEL_DEBUG("Resolution is %dx%d\n", IntelX, IntelY);
         }
         refresh = 1;
@@ -478,12 +549,8 @@ void intel_display_init(DisplayState *ds)
 {
     INTEL_DEBUG("\n");
 
-    xenstore_watch_screenshot_node();
-
     intel_init_mapping();
 
-    INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_reg(REG_DR_DSPASURF));
-
     ds->shared_buf = 0;
     intel_resize(ds, 640, 480);
     lds = ds;