Browse Source

Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/kms: fix kms/fbdev colormap support properly.
  drm: Add the basic check for the detailed timing in EDID
  drm/radeon/kms: ignore vga arbiter return.
Linus Torvalds 15 years ago
parent
commit
d4f452f825
3 changed files with 47 additions and 17 deletions
  1. 15 0
      drivers/gpu/drm/drm_edid.c
  2. 29 13
      drivers/gpu/drm/drm_fb_helper.c
  3. 3 4
      drivers/gpu/drm/radeon/radeon_device.c

+ 15 - 0
drivers/gpu/drm/drm_edid.c

@@ -626,6 +626,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 		return NULL;
 	}
 
+	/* it is incorrect if hsync/vsync width is zero */
+	if (!hsync_pulse_width || !vsync_pulse_width) {
+		DRM_DEBUG_KMS("Incorrect Detailed timing. "
+				"Wrong Hsync/Vsync pulse width\n");
+		return NULL;
+	}
 	mode = drm_mode_create(dev);
 	if (!mode)
 		return NULL;
@@ -647,6 +653,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 	mode->vsync_end = mode->vsync_start + vsync_pulse_width;
 	mode->vtotal = mode->vdisplay + vblank;
 
+	/* perform the basic check for the detailed timing */
+	if (mode->hsync_end > mode->htotal ||
+		mode->vsync_end > mode->vtotal) {
+		drm_mode_destroy(dev, mode);
+		DRM_DEBUG_KMS("Incorrect detailed timing. "
+				"Sync is beyond the blank.\n");
+		return NULL;
+	}
+
 	drm_mode_set_name(mode);
 
 	if (pt->misc & DRM_EDID_PT_INTERLACED)

+ 29 - 13
drivers/gpu/drm/drm_fb_helper.c

@@ -454,22 +454,39 @@ out_free:
 }
 EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
 
-static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
+static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
 		     u16 blue, u16 regno, struct fb_info *info)
 {
 	struct drm_fb_helper *fb_helper = info->par;
 	struct drm_framebuffer *fb = fb_helper->fb;
 	int pindex;
 
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 *palette;
+		u32 value;
+		/* place color in psuedopalette */
+		if (regno > 16)
+			return -EINVAL;
+		palette = (u32 *)info->pseudo_palette;
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+		value = (red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset);
+		palette[regno] = value;
+		return 0;
+	}
+
 	pindex = regno;
 
 	if (fb->bits_per_pixel == 16) {
 		pindex = regno << 3;
 
 		if (fb->depth == 16 && regno > 63)
-			return;
+			return -EINVAL;
 		if (fb->depth == 15 && regno > 31)
-			return;
+			return -EINVAL;
 
 		if (fb->depth == 16) {
 			u16 r, g, b;
@@ -493,13 +510,7 @@ static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
 
 	if (fb->depth != 16)
 		fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
-
-	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		((u32 *) fb->pseudo_palette)[regno] =
-			(regno << info->var.red.offset) |
-			(regno << info->var.green.offset) |
-			(regno << info->var.blue.offset);
-	}
+	return 0;
 }
 
 int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
@@ -536,7 +547,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
 			if (transp)
 				htransp = *transp++;
 
-			setcolreg(crtc, hred, hgreen, hblue, start++, info);
+			rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
+			if (rc)
+				return rc;
 		}
 		crtc_funcs->load_lut(crtc);
 	}
@@ -555,6 +568,7 @@ int drm_fb_helper_setcolreg(unsigned regno,
 	struct drm_device *dev = fb_helper->dev;
 	struct drm_crtc *crtc;
 	int i;
+	int ret;
 
 	if (regno > 255)
 		return 1;
@@ -568,8 +582,10 @@ int drm_fb_helper_setcolreg(unsigned regno,
 		if (i == fb_helper->crtc_count)
 			continue;
 
+		ret = setcolreg(crtc, red, green, blue, regno, info);
+		if (ret)
+			return ret;
 
-		setcolreg(crtc, red, green, blue, regno, info);
 		crtc_funcs->load_lut(crtc);
 	}
 	return 0;
@@ -928,7 +944,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
 {
 	info->fix.type = FB_TYPE_PACKED_PIXELS;
 	info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
-		FB_VISUAL_DIRECTCOLOR;
+		FB_VISUAL_TRUECOLOR;
 	info->fix.type_aux = 0;
 	info->fix.xpanstep = 1; /* doing it in hw */
 	info->fix.ypanstep = 1; /* doing it in hw */

+ 3 - 4
drivers/gpu/drm/radeon/radeon_device.c

@@ -582,10 +582,9 @@ int radeon_device_init(struct radeon_device *rdev,
 	DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
 
 	/* if we have > 1 VGA cards, then disable the radeon VGA resources */
-	r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
-	if (r) {
-		return -EINVAL;
-	}
+	/* this will fail for cards that aren't VGA class devices, just
+	 * ignore it */
+	vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
 
 	r = radeon_init(rdev);
 	if (r)