All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] geode updates.
@ 2005-08-12  0:06 James Simmons
  2005-08-17 12:10 ` David Vrabel
  0 siblings, 1 reply; 6+ messages in thread
From: James Simmons @ 2005-08-12  0:06 UTC (permalink / raw)
  To: David Vrabel; +Cc: Linux Fbdev development list


Okay I see what you meant. So what I did was create two hardware devices. 
One a pci device for the Cyrix video so it will show up in the sysfs pci 
tree. A second platform device for the embedded geode GX processsor. The 
framebuffer device is uses both devices but considered itself attached to 
the embedded core. Try it out!


diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/video/geode/display_gx1.c fbdev-2.6/drivers/video/geode/display_gx1.c
--- linus-2.6/drivers/video/geode/display_gx1.c	2005-07-11 10:07:21.000000000 -0700
+++ fbdev-2.6/drivers/video/geode/display_gx1.c	2005-08-11 16:40:57.000000000 -0700
@@ -61,7 +61,6 @@
 	if (!mc_regs)
 		return -ENOMEM;
 
-
 	/* Calculate the total size of both DIMM0 and DIMM1. */
 	bank_cfg = readl(mc_regs + MC_BANK_CFG);
 
@@ -72,9 +71,7 @@
 	}
 
 	fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;
-
 	iounmap(mc_regs);
-
 	return dram_size - fb_base;
 }
 
@@ -86,32 +83,32 @@
 	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
 
 	/* Unlock the display controller registers. */
-	readl(par->dc_regs + DC_UNLOCK);
-	writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+	readl(par->dc_ops->dc_regs + DC_UNLOCK);
+	writel(DC_UNLOCK_CODE, par->dc_ops->dc_regs + DC_UNLOCK);
 
-	gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
-	tcfg = readl(par->dc_regs + DC_TIMING_CFG);
+	gcfg = readl(par->dc_ops->dc_regs + DC_GENERAL_CFG);
+	tcfg = readl(par->dc_ops->dc_regs + DC_TIMING_CFG);
 
 	/* Blank the display and disable the timing generator. */
 	tcfg &= ~(DC_TCFG_BLKE | DC_TCFG_TGEN);
-	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+	writel(tcfg, par->dc_ops->dc_regs + DC_TIMING_CFG);
 
 	/* Wait for pending memory requests before disabling the FIFO load. */
 	udelay(100);
 
 	/* Disable FIFO load and compression. */
 	gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+	writel(gcfg, par->dc_ops->dc_regs + DC_GENERAL_CFG);
 
 	/* Setup DCLK and its divisor. */
 	gcfg &= ~DC_GCFG_DCLK_MASK;
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+	writel(gcfg, par->dc_ops->dc_regs + DC_GENERAL_CFG);
 
-	par->vid_ops->set_dclk(info);
+	par->vid_ops->set_dclk(par->vid_ops, info->var.pixclock);
 
 	dclk_div = DC_GCFG_DCLK_DIV_1; /* FIXME: may need to divide DCLK by 2 sometimes? */
 	gcfg |= dclk_div;
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+	writel(gcfg, par->dc_ops->dc_regs + DC_GENERAL_CFG);
 
 	/* Wait for the clock generatation to settle.  This is needed since
 	 * some of the register writes that follow require that clock to be
@@ -132,12 +129,12 @@
 	/* FIXME: Set pixel and line double bits if necessary. */
 
 	/* Framebuffer start offset. */
-	writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+	writel(0, par->dc_ops->dc_regs + DC_FB_ST_OFFSET);
 
 	/* Line delta and line buffer length. */
-	writel(info->fix.line_length >> 2, par->dc_regs + DC_LINE_DELTA);
+	writel(info->fix.line_length >> 2, par->dc_ops->dc_regs + DC_LINE_DELTA);
 	writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
-	       par->dc_regs + DC_BUF_SIZE);
+	       par->dc_ops->dc_regs + DC_BUF_SIZE);
 
 	/* Output configuration. Enable panel data, set pixel format. */
 	ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
@@ -163,31 +160,31 @@
 	vtotal = vblankend;
 
 	val = (hactive - 1) | ((htotal - 1) << 16);
-	writel(val, par->dc_regs + DC_H_TIMING_1);
+	writel(val, par->dc_ops->dc_regs + DC_H_TIMING_1);
 	val = (hblankstart - 1) | ((hblankend - 1) << 16);
-	writel(val, par->dc_regs + DC_H_TIMING_2);
+	writel(val, par->dc_ops->dc_regs + DC_H_TIMING_2);
 	val = (hsyncstart - 1) | ((hsyncend - 1) << 16);
-	writel(val, par->dc_regs + DC_H_TIMING_3);
-	writel(val, par->dc_regs + DC_FP_H_TIMING);
+	writel(val, par->dc_ops->dc_regs + DC_H_TIMING_3);
+	writel(val, par->dc_ops->dc_regs + DC_FP_H_TIMING);
 	val = (vactive - 1) | ((vtotal - 1) << 16);
-	writel(val, par->dc_regs + DC_V_TIMING_1);
+	writel(val, par->dc_ops->dc_regs + DC_V_TIMING_1);
 	val = (vblankstart - 1) | ((vblankend - 1) << 16);
-	writel(val, par->dc_regs + DC_V_TIMING_2);
+	writel(val, par->dc_ops->dc_regs + DC_V_TIMING_2);
 	val = (vsyncstart - 1) | ((vsyncend - 1) << 16);
-	writel(val, par->dc_regs + DC_V_TIMING_3);
+	writel(val, par->dc_ops->dc_regs + DC_V_TIMING_3);
 	val = (vsyncstart - 2) | ((vsyncend - 2) << 16);
-	writel(val, par->dc_regs + DC_FP_V_TIMING);
+	writel(val, par->dc_ops->dc_regs + DC_FP_V_TIMING);
 
 	/* Write final register values. */
-	writel(ocfg, par->dc_regs + DC_OUTPUT_CFG);
-	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+	writel(ocfg, par->dc_ops->dc_regs + DC_OUTPUT_CFG);
+	writel(tcfg, par->dc_ops->dc_regs + DC_TIMING_CFG);
 	udelay(1000); /* delay after TIMING_CFG. FIXME: perhaps a little long */
-	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+	writel(gcfg, par->dc_ops->dc_regs + DC_GENERAL_CFG);
 
-	par->vid_ops->configure_display(info);
+	par->vid_ops->configure_display(par->vid_ops, info);
 
 	/* Relock display controller registers */
-	writel(0, par->dc_regs + DC_UNLOCK);
+	writel(0, par->dc_ops->dc_regs + DC_UNLOCK);
 
 	/* FIXME: write line_length and bpp to Graphics Pipeline GP_BLT_STATUS
 	 * register. */
@@ -204,11 +201,12 @@
 	val |= (green >>  4) & 0x00fc0;
 	val |= (blue  >> 10) & 0x0003f;
 
-	writel(regno, par->dc_regs + DC_PAL_ADDRESS);
-	writel(val, par->dc_regs + DC_PAL_DATA);
+	writel(regno, par->dc_ops->dc_regs + DC_PAL_ADDRESS);
+	writel(val, par->dc_ops->dc_regs + DC_PAL_DATA);
 }
 
 struct geode_dc_ops gx1_dc_ops = {
 	.set_mode	 = gx1_set_mode,
 	.set_palette_reg = gx1_set_hw_palette_reg,
 };
+
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/video/geode/geodefb.h fbdev-2.6/drivers/video/geode/geodefb.h
--- linus-2.6/drivers/video/geode/geodefb.h	2005-07-11 10:07:21.000000000 -0700
+++ fbdev-2.6/drivers/video/geode/geodefb.h	2005-08-11 16:35:34.000000000 -0700
@@ -17,21 +17,20 @@
 struct geode_dc_ops {
 	void (*set_mode)(struct fb_info *);
 	void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, unsigned);
+	void __iomem *dc_regs;
 };
 
 struct geode_vid_ops {
-	void (*set_dclk)(struct fb_info *);
-	void (*configure_display)(struct fb_info *);
-	int  (*blank_display)(struct fb_info *, int blank_mode);
+	void (*set_dclk)(struct geode_vid_ops *ops, u32 pixclock);
+	void (*configure_display)(struct geode_vid_ops *ops, struct fb_info *);
+	int  (*blank_display)(struct geode_vid_ops *ops, struct fb_info *, int blank_mode);
+	void __iomem *vid_regs;
 };
 
 struct geodefb_par {
 	int enable_crt;
 	int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
 	int panel_y;
-	struct pci_dev *vid_dev;
-	void __iomem *dc_regs;
-	void __iomem *vid_regs;
 	struct geode_dc_ops  *dc_ops;
 	struct geode_vid_ops *vid_ops;
 };
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/video/geode/gx1fb_core.c fbdev-2.6/drivers/video/geode/gx1fb_core.c
--- linus-2.6/drivers/video/geode/gx1fb_core.c	2005-07-11 10:07:21.000000000 -0700
+++ fbdev-2.6/drivers/video/geode/gx1fb_core.c	2005-08-11 16:36:35.000000000 -0700
@@ -26,10 +26,68 @@
 #include "display_gx1.h"
 #include "video_cs5530.h"
 
+extern struct pci_driver cs5530_driver;
+
 static char mode_option[32] = "640x480-16@60";
 static int  crt_option = 1;
 static char panel_option[32] = "";
 
+/* Modes relevant to the GX1 (taken from modedb.c) */
+static const struct fb_videomode __initdata gx1_modedb[] = {
+	/* 640x480-60 VESA */
+	{ NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 640x480-75 VESA */
+	{ NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 640x480-85 VESA */
+	{ NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-60 VESA */
+	{ NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-75 VESA */
+	{ NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 800x600-85 VESA */
+	{ NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-60 VESA */
+	{ NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-75 VESA */
+	{ NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1024x768-85 VESA */
+	{ NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x960-60 VESA */
+	{ NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x960-85 VESA */
+	{ NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-60 VESA */
+	{ NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-75 VESA */
+	{ NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1280x1024-85 VESA */
+	{ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
 static int gx1_line_delta(int xres, int bpp)
 {
 	int line_delta = xres * (bpp >> 3);
@@ -47,8 +105,6 @@
 {
 	struct geodefb_par *par = info->par;
 
-	printk(KERN_DEBUG "%s()\n", __FUNCTION__);
-
 	/* Maximum resolution is 1280x1024. */
 	if (var->xres > 1280 || var->yres > 1024)
 		return -EINVAL;
@@ -143,44 +199,26 @@
 {
 	struct geodefb_par *par = info->par;
 
-	return par->vid_ops->blank_display(info, blank_mode);
+	return par->vid_ops->blank_display(par->vid_ops, info, blank_mode);
 }
 
-static int __init gx1fb_map_video_memory(struct fb_info *info)
+static int __init gx1fb_map_video_memory(struct fb_info *info, struct platform_device *dev)
 {
 	struct geodefb_par *par = info->par;
-	unsigned gx_base;
-	int fb_len;
-
-	gx_base = gx1_gx_base();
-	if (!gx_base)
-		return -ENODEV;
-
-	par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX,
-				      PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL);
-	if (!par->vid_dev)
-		return -ENODEV;
-
-	par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1),
-				pci_resource_len(par->vid_dev, 1));
-	if (!par->vid_regs)
-		return -ENOMEM;
 
-	par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
-	if (!par->dc_regs)
+	if (dev->num_resources != 2)
+                return -EBUSY;
+	par->dc_ops->dc_regs = ioremap(dev->resource[0].start, 0x100);
+	if (!par->dc_ops->dc_regs)
 		return -ENOMEM;
 
-	info->fix.smem_start = gx_base + 0x800000;
-	if ((fb_len = gx1_frame_buffer_size()) < 0)
-		return -ENOMEM;
-	info->fix.smem_len = fb_len;
+	info->fix.smem_len = dev->resource[1].end - dev->resource[1].start;
+	info->fix.smem_start = dev->resource[1].start;
 	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
 	if (!info->screen_base)
 		return -ENOMEM;
-
 	printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n",
 	       info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start);
-
 	return 0;
 }
 
@@ -216,13 +254,13 @@
 	.fb_cursor	= soft_cursor,
 };
 
-static struct fb_info * __init gx1fb_init_fbinfo(void)
+static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
 {
-	struct fb_info *info;
 	struct geodefb_par *par;
-
+	struct fb_info *info;
+	
 	/* Alloc enough space for the pseudo palette. */
-	info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, NULL);
+	info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
 	if (!info)
 		return NULL;
 
@@ -263,37 +301,29 @@
 	return info;
 }
 
-
-static struct fb_info *gx1fb_info;
-
-static int __init gx1fb_init(void)
+static int __init gx1fb_probe(struct device *device)
 {
+	struct platform_device *dev = to_platform_device(device);
+	struct geodefb_par *par;
 	struct fb_info *info;
-        struct geodefb_par *par;
 	int ret;
 
-#ifndef MODULE
-	if (fb_get_options("gx1fb", NULL))
-		return -ENODEV;
-#endif
-
-	info = gx1fb_init_fbinfo();
+	info = gx1fb_init_fbinfo(&dev->dev);
 	if (!info)
 		return -ENOMEM;
-	gx1fb_info = info;
-
 	par = info->par;
 
 	/* GX1 display controller and CS5530 video device */
 	par->dc_ops  = &gx1_dc_ops;
 	par->vid_ops = &cs5530_vid_ops;
 
-	if ((ret = gx1fb_map_video_memory(info)) < 0) {
+	if ((ret = gx1fb_map_video_memory(info, dev)) < 0) {
 		printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id);
 		goto err;
 	}
 
-	ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
+	ret = fb_find_mode(&info->var, info, mode_option,
+			   gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16);
 	if (ret == 0 || ret == 4) {
 		printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id);
 		ret = -EINVAL;
@@ -310,37 +340,104 @@
 		ret = -EINVAL;
 		goto err;
 	}
+	dev_set_drvdata(&dev->dev, info);
 	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
 	return 0;
 
   err:
 	if (info->screen_base)
 		iounmap(info->screen_base);
-	if (par->vid_regs)
-		iounmap(par->vid_regs);
-	if (par->dc_regs)
-		iounmap(par->dc_regs);
-	if (par->vid_dev)
-		pci_dev_put(par->vid_dev);
+	if (par->dc_ops->dc_regs)
+		iounmap(par->dc_ops->dc_regs);
 	if (info)
 		framebuffer_release(info);
 	return ret;
 }
 
-static void __exit gx1fb_cleanup(void)
+static int __exit gx1fb_remove(struct device *dev)
 {
-	struct fb_info *info = gx1fb_info;
-	struct geodefb_par *par = gx1fb_info->par;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct geodefb_par *par = info->par;
 
 	unregister_framebuffer(info);
 
 	iounmap((void __iomem *)info->screen_base);
-	iounmap(par->vid_regs);
-	iounmap(par->dc_regs);
+	iounmap(par->dc_ops->dc_regs);
+	dev_set_drvdata(dev, NULL);
+	framebuffer_release(info);
+	return 0;
+}
 
-	pci_dev_put(par->vid_dev);
+static struct platform_device *gx1fb_device;
 
-	framebuffer_release(info);
+static struct device_driver gx1fb_driver = {
+	.name		= "geodefb",
+	.bus		= &platform_bus_type,
+	.probe		= gx1fb_probe,
+	.remove		= gx1fb_remove,
+};
+
+static int __init gx1fb_init(void)
+{
+	struct resource *gx1_resource = NULL, *gx2_resource = NULL;
+	unsigned gx_base;
+	int len, ret;
+
+#ifndef MODULE
+	if (fb_get_options("gx1fb", NULL))
+		return -ENODEV;
+#endif
+	gx_base = gx1_gx_base();
+	if (!gx_base)
+		return -ENODEV;
+
+	if ((len = gx1_frame_buffer_size()) < 0)
+		return -ENOMEM;
+
+	ret = pci_register_driver(&cs5530_driver);
+	if (ret < 0)
+		return ret;
+
+	ret = driver_register(&gx1fb_driver);
+	if (ret < 0) {
+		pci_unregister_driver(&cs5530_driver);
+		return ret;
+	}
+
+        gx1_resource = request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)");
+	if (!gx1_resource) {
+		driver_unregister(&gx1fb_driver);	
+		pci_unregister_driver(&cs5530_driver);
+		return -EBUSY;
+	}
+
+        gx2_resource = request_mem_region(gx_base + 0x800000, len, "gx1fb frame buffer");
+	if (!gx1_resource) {
+		release_resource(gx1_resource);
+		driver_unregister(&gx1fb_driver);
+		pci_unregister_driver(&cs5530_driver);
+		return -EBUSY;
+	}
+
+	gx1fb_device = platform_device_register_simple("geodefb", -1, gx1_resource, 2);
+	if (IS_ERR(gx1fb_device)) {
+		release_resource(gx2_resource);
+		release_resource(gx1_resource);
+		driver_unregister(&gx1fb_driver);
+		pci_unregister_driver(&cs5530_driver);
+		return PTR_ERR(gx1fb_device);
+	}
+	return ret;
+}
+
+static void __exit gx1fb_cleanup(void)
+{
+	// unregister the Cyrix video component.
+	pci_unregister_driver(&cs5530_driver);
+
+	// unregister the embedded graphics core.
+	platform_device_unregister(gx1fb_device);
+	driver_unregister(&gx1fb_driver);
 }
 
 module_init(gx1fb_init);
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/video/geode/Kconfig fbdev-2.6/drivers/video/geode/Kconfig
--- linus-2.6/drivers/video/geode/Kconfig	2005-07-11 10:07:21.000000000 -0700
+++ fbdev-2.6/drivers/video/geode/Kconfig	2005-08-11 13:34:58.000000000 -0700
@@ -21,9 +21,7 @@
 	  Framebuffer driver for the display controller integrated into the
 	  AMD Geode GX1 processor.
 
-	  This driver is also available as a module ( = code which can be
-	  inserted and removed from the running kernel whenever you want). The
-	  module will be called gx1fb. If you want to compile it as a module,
-	  say M here and read <file:Documentation/modules.txt>.
+	  To compile this driver as a module, choose M here: the module will be
+	  called gx1fb.
 
 	  If unsure, say N.
diff -urN -X /home/jsimmons/dontdiff linus-2.6/drivers/video/geode/video_cs5530.c fbdev-2.6/drivers/video/geode/video_cs5530.c
--- linus-2.6/drivers/video/geode/video_cs5530.c	2005-07-11 10:07:21.000000000 -0700
+++ fbdev-2.6/drivers/video/geode/video_cs5530.c	2005-08-11 13:34:58.000000000 -0700
@@ -14,6 +14,7 @@
  */
 #include <linux/fb.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/delay.h>
 
@@ -69,21 +70,18 @@
 	{  4310, 0x2FB1B802, }, /* 232.0000 */
 };
 
-#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
-
-static void cs5530_set_dclk_frequency(struct fb_info *info)
+static void cs5530_set_dclk_frequency(struct geode_vid_ops *ops, u32 pixclock)
 {
-	struct geodefb_par *par = info->par;
-	int i;
-	u32 value;
 	long min, diff;
+	u32 value;
+	int i;
 
 	/* Search the table for the closest pixclock. */
 	value = cs5530_pll_table[0].pll_value;
-	min = cs5530_pll_table[0].pixclock - info->var.pixclock;
+	min = cs5530_pll_table[0].pixclock - pixclock;
 	if (min < 0) min = -min;
-	for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
-		diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
+	for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) {
+		diff = cs5530_pll_table[i].pixclock - pixclock;
 		if (diff < 0L) diff = -diff;
 		if (diff < min) {
 			min = diff;
@@ -91,19 +89,19 @@
 		}
 	}
 
-	writel(value, par->vid_regs + CS5530_DOT_CLK_CONFIG);
-	writel(value | 0x80000100, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
+	writel(value, ops->vid_regs + CS5530_DOT_CLK_CONFIG);
+	writel(value | 0x80000100, ops->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
 	udelay(500); /* wait for PLL to settle */
-	writel(value & 0x7FFFFFFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
-	writel(value & 0x7FFFFEFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
+	writel(value & 0x7FFFFFFF, ops->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
+	writel(value & 0x7FFFFEFF, ops->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
 }
 
-static void cs5530_configure_display(struct fb_info *info)
+static void cs5530_configure_display(struct geode_vid_ops *ops, struct fb_info *info)
 {
 	struct geodefb_par *par = info->par;
 	u32 dcfg;
 
-	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+	dcfg = readl(ops->vid_regs + CS5530_DISPLAY_CONFIG);
 
 	/* Clear bits from existing mode. */
 	dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK
@@ -133,10 +131,10 @@
 	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
 		dcfg |= CS5530_DCFG_CRT_VSYNC_POL;
 
-	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+	writel(dcfg, ops->vid_regs + CS5530_DISPLAY_CONFIG);
 }
 
-static int cs5530_blank_display(struct fb_info *info, int blank_mode)
+static int cs5530_blank_display(struct geode_vid_ops *ops, struct fb_info *info, int blank_mode)
 {
 	struct geodefb_par *par = info->par;
 	u32 dcfg;
@@ -162,7 +160,7 @@
 		return -EINVAL;
 	}
 
-	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+	dcfg = readl(ops->vid_regs + CS5530_DISPLAY_CONFIG);
 
 	dcfg &= ~(CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN
 		  | CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN
@@ -182,9 +180,7 @@
 		if (hsync && vsync)
 			dcfg |= CS5530_DCFG_FP_PWR_EN;
 	}
-
-	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
-
+	writel(dcfg, ops->vid_regs + CS5530_DISPLAY_CONFIG);
 	return 0;
 }
 
@@ -193,3 +189,59 @@
 	.configure_display = cs5530_configure_display,
 	.blank_display     = cs5530_blank_display,
 };
+
+static int __init cs5530_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int ret = 0;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0)
+		goto err;
+
+	ret = pci_request_region(pdev, 1, "Cyrix 5530 (video)");
+	if (ret < 0)
+		goto err;
+
+	cs5530_vid_ops.vid_regs = ioremap(pci_resource_start(pdev, 1),
+					  pci_resource_len(pdev, 1));
+	if (!cs5530_vid_ops.vid_regs) {
+		pci_release_region(pdev, 1);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	pci_set_drvdata(pdev, &cs5530_vid_ops);
+	return 0;
+err:
+	pci_disable_device(pdev);
+	pci_dev_put(pdev);
+	return ret;
+}
+
+static void cs5530_remove(struct pci_dev *pdev)
+{
+	struct geode_vid_ops *vid_ops = pci_get_drvdata(pdev);
+
+	iounmap(vid_ops->vid_regs);
+	pci_release_region(pdev, 1);
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
+	pci_dev_put(pdev);
+}
+
+static struct pci_device_id cs5530_id_table[] = {
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cs5530_id_table);
+
+struct pci_driver cs5530_driver = {
+	.name		= "Cyrix 5530 video",
+	.id_table	= cs5530_id_table,
+	.probe		= cs5530_probe,
+	.remove		= cs5530_remove,
+};
+


-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-08-18 20:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-12  0:06 [PATCH] geode updates James Simmons
2005-08-17 12:10 ` David Vrabel
2005-08-17 16:31   ` James Simmons
2005-08-17 16:36   ` James Simmons
2005-08-18  2:02     ` Andrew Morton
2005-08-18 20:00       ` James Simmons

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.