* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Thomas Bogendoerfer @ 2011-10-30 22:34 UTC (permalink / raw)
To: Joshua Kinard; +Cc: linux-mips, linux-fbdev, ralf, FlorianSchandinat
In-Reply-To: <4EADB701.9040506@gentoo.org>
On Sun, Oct 30, 2011 at 04:43:45PM -0400, Joshua Kinard wrote:
> Does this handle any glue logic for add-on NIC cards found for Indy and I2?
no, but it will make live a lot easier, because address and interrupts don't
need to be probed by the driver. Right now interrupts are on my todo, since
there is some weirdness between guiness and fullhouse boxes...
> I have a G130 Phobus and a rare ThunderLAN card in my Indy. The Phobus has
> an Altera GIO/PCI glue chip. Not sure about the ThunderLAN. Both have
> normal driver support in the kernel (Phobus is just a Tulip chip).
it still needs something to setup the PCI bus on the card and issue
the probing. The problem with the Tulip Phobos cards is, that they
messed up the endianess, so that none of the Linux Tulip drivers will
work out of the box...
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Joshua Kinard @ 2011-10-30 20:43 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-fbdev, ralf, FlorianSchandinat
In-Reply-To: <20111020221928.0C2191DA27@solo.franken.de>
On 10/20/2011 18:19, Thomas Bogendoerfer wrote:
> SGI IP22/IP28 machines have GIO busses for adding graphics and other
> extension cards. This patch adds support for GIO driver/device
> handling and converts the newport console driver to a GIO driver.
>
> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Does this handle any glue logic for add-on NIC cards found for Indy and I2?
I have a G130 Phobus and a rare ThunderLAN card in my Indy. The Phobus has
an Altera GIO/PCI glue chip. Not sure about the ThunderLAN. Both have
normal driver support in the kernel (Phobus is just a Tulip chip).
--
Joshua Kinard
Gentoo/MIPS
kumba@gentoo.org
4096R/D25D95E3 2011-03-28
"The past tempts us, the present confuses us, the future frightens us. And
our lives slip away, moment by moment, lost in that vast, terrible in-between."
--Emperor Turhan, Centauri Republic
^ permalink raw reply
* Re: [PATCH v2] GIO bus support for SGI IP22/28
From: Florian Tobias Schandinat @ 2011-10-30 15:53 UTC (permalink / raw)
To: Thomas Bogendoerfer; +Cc: linux-mips, linux-fbdev, ralf
In-Reply-To: <20111020221928.0C2191DA27@solo.franken.de>
On 10/20/2011 10:19 PM, Thomas Bogendoerfer wrote:
> SGI IP22/IP28 machines have GIO busses for adding graphics and other
> extension cards. This patch adds support for GIO driver/device
> handling and converts the newport console driver to a GIO driver.
>
> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> ---
>
> Changes to last version:
> - use EXPORT_SYMBOL_GPL
> - ChallengeS has only 2 slots
> - use subsys_initcall for gio detection
>
> Florian, the whole patch should go through the MIPS tree, if it's ok for
> you.
No problem. I'm not even sure whether I'm responsible for it as it is not a
framebuffer but a console driver. Anyway I had a look at the console code so you
may add an
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
if you like.
Best regards,
Florian Tobias Schandinat
> arch/mips/include/asm/gio_device.h | 56 +++++
> arch/mips/sgi-ip22/Makefile | 2 +-
> arch/mips/sgi-ip22/ip22-gio.c | 414 +++++++++++++++++++++++++++++++++++
> arch/mips/sgi-ip22/ip22-mc.c | 10 +-
> arch/mips/sgi-ip22/ip22-setup.c | 21 --
> drivers/video/console/newport_con.c | 61 ++++--
> 6 files changed, 518 insertions(+), 46 deletions(-)
>
> diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h
> new file mode 100644
> index 0000000..5437c84
> --- /dev/null
> +++ b/arch/mips/include/asm/gio_device.h
> @@ -0,0 +1,56 @@
> +#include <linux/device.h>
> +#include <linux/mod_devicetable.h>
> +
> +struct gio_device_id {
> + __u8 id;
> +};
> +
> +struct gio_device {
> + struct device dev;
> + struct resource resource;
> + unsigned int irq;
> + unsigned int slotno;
> +
> + const char *name;
> + struct gio_device_id id;
> + unsigned id32:1;
> + unsigned gio64:1;
> +};
> +#define to_gio_device(d) container_of(d, struct gio_device, dev)
> +
> +struct gio_driver {
> + const char *name;
> + struct module *owner;
> + const struct gio_device_id *id_table;
> +
> + int (*probe)(struct gio_device *, const struct gio_device_id *);
> + void (*remove)(struct gio_device *);
> + int (*suspend)(struct gio_device *, pm_message_t);
> + int (*resume)(struct gio_device *);
> + void (*shutdown)(struct gio_device *);
> +
> + struct device_driver driver;
> +};
> +#define to_gio_driver(drv) container_of(drv, struct gio_driver, driver)
> +
> +extern const struct gio_device_id *gio_match_device(const struct gio_device_id *,
> + const struct gio_device *);
> +extern struct gio_device *gio_dev_get(struct gio_device *);
> +extern void gio_dev_put(struct gio_device *);
> +
> +extern int gio_device_register(struct gio_device *);
> +extern void gio_device_unregister(struct gio_device *);
> +extern void gio_release_dev(struct device *);
> +
> +static inline void gio_device_free(struct gio_device *dev)
> +{
> + gio_release_dev(&dev->dev);
> +}
> +
> +extern int gio_register_driver(struct gio_driver *);
> +extern void gio_unregister_driver(struct gio_driver *);
> +
> +#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev)
> +#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data))
> +
> +extern void gio_set_master(struct gio_device *);
> diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
> index cc53849..411cda9 100644
> --- a/arch/mips/sgi-ip22/Makefile
> +++ b/arch/mips/sgi-ip22/Makefile
> @@ -4,7 +4,7 @@
> #
>
> obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \
> - ip22-platform.o ip22-reset.o ip22-setup.o
> + ip22-platform.o ip22-reset.o ip22-setup.o ip22-gio.o
>
> obj-$(CONFIG_SGI_IP22) += ip22-berr.o
> obj-$(CONFIG_SGI_IP28) += ip28-berr.o
> diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
> new file mode 100644
> index 0000000..d841529
> --- /dev/null
> +++ b/arch/mips/sgi-ip22/ip22-gio.c
> @@ -0,0 +1,414 @@
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +
> +#include <asm/addrspace.h>
> +#include <asm/paccess.h>
> +#include <asm/gio_device.h>
> +#include <asm/sgi/gio.h>
> +#include <asm/sgi/hpc3.h>
> +#include <asm/sgi/mc.h>
> +#include <asm/sgi/ip22.h>
> +
> +static struct bus_type gio_bus;
> +
> +static struct {
> + const char *name;
> + __u8 id;
> +} gio_name_table[] = {
> + { .name = "SGI Impact", .id = 0x10 },
> + { .name = "Phobos G160", .id = 0x35 },
> + /* fake IDs */
> + { .name = "SGI Newport", .id = 0x7e },
> + { .name = "SGI GR2/GR3", .id = 0x7f },
> +};
> +
> +/**
> + * gio_match_device - Tell if an of_device structure has a matching
> + * gio_match structure
> + * @ids: array of of device match structures to search in
> + * @dev: the of device structure to match against
> + *
> + * Used by a driver to check whether an of_device present in the
> + * system is in its list of supported devices.
> + */
> +const struct gio_device_id *gio_match_device(const struct gio_device_id *match,
> + const struct gio_device *dev)
> +{
> + const struct gio_device_id *ids;
> +
> + for (ids = match; ids->id != 0xff; ids++)
> + if (ids->id = dev->id.id)
> + return ids;
> +
> + return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gio_match_device);
> +
> +struct gio_device *gio_dev_get(struct gio_device *dev)
> +{
> + struct device *tmp;
> +
> + if (!dev)
> + return NULL;
> + tmp = get_device(&dev->dev);
> + if (tmp)
> + return to_gio_device(tmp);
> + else
> + return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gio_dev_get);
> +
> +void gio_dev_put(struct gio_device *dev)
> +{
> + if (dev)
> + put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(gio_dev_put);
> +
> +static ssize_t dev_show_name(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct gio_device *giodev;
> +
> + giodev = to_gio_device(dev);
> + return sprintf(buf, "%s", giodev->name);
> +}
> +
> +static DEVICE_ATTR(name, S_IRUGO, dev_show_name, NULL);
> +
> +static ssize_t dev_show_id(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct gio_device *giodev;
> +
> + giodev = to_gio_device(dev);
> + return sprintf(buf, "%x", giodev->id.id);
> +}
> +
> +static DEVICE_ATTR(id, S_IRUGO, dev_show_id, NULL);
> +
> +/**
> + * gio_release_dev - free an gio device structure when all users of it are finished.
> + * @dev: device that's been disconnected
> + *
> + * Will be called only by the device core when all users of this gio device are
> + * done.
> + */
> +void gio_release_dev(struct device *dev)
> +{
> + struct gio_device *giodev;
> +
> + giodev = to_gio_device(dev);
> + kfree(giodev);
> +}
> +EXPORT_SYMBOL_GPL(gio_release_dev);
> +
> +int gio_device_register(struct gio_device *giodev)
> +{
> + int rc;
> +
> + giodev->dev.bus = &gio_bus;
> + rc = device_register(&giodev->dev);
> + if (rc)
> + return rc;
> +
> + rc = device_create_file(&giodev->dev, &dev_attr_name);
> + if (rc)
> + goto err;
> + rc = device_create_file(&giodev->dev, &dev_attr_id);
> + if (rc)
> + goto err;
> +
> + return 0;
> +
> +err:
> + device_unregister(&giodev->dev);
> + return rc;
> +}
> +EXPORT_SYMBOL_GPL(gio_device_register);
> +
> +void gio_device_unregister(struct gio_device *giodev)
> +{
> + device_remove_file(&giodev->dev, &dev_attr_id);
> + device_remove_file(&giodev->dev, &dev_attr_name);
> + device_unregister(&giodev->dev);
> +}
> +EXPORT_SYMBOL_GPL(gio_device_unregister);
> +
> +static int gio_bus_match(struct device *dev, struct device_driver *drv)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *gio_drv = to_gio_driver(drv);
> +
> + return gio_match_device(gio_drv->id_table, gio_dev) != NULL;
> +}
> +
> +static int gio_device_probe(struct device *dev)
> +{
> + int error = -ENODEV;
> + struct gio_driver *drv;
> + struct gio_device *gio_dev;
> + const struct gio_device_id *match;
> +
> + drv = to_gio_driver(dev->driver);
> + gio_dev = to_gio_device(dev);
> +
> + if (!drv->probe)
> + return error;
> +
> + gio_dev_get(gio_dev);
> +
> + match = gio_match_device(drv->id_table, gio_dev);
> + if (match)
> + error = drv->probe(gio_dev, match);
> + if (error)
> + gio_dev_put(gio_dev);
> +
> + return error;
> +}
> +
> +static int gio_device_remove(struct device *dev)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> +
> + if (dev->driver && drv->remove)
> + drv->remove(gio_dev);
> + return 0;
> +}
> +
> +static int gio_device_suspend(struct device *dev, pm_message_t state)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> + int error = 0;
> +
> + if (dev->driver && drv->suspend)
> + error = drv->suspend(gio_dev, state);
> + return error;
> +}
> +
> +static int gio_device_resume(struct device *dev)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> + int error = 0;
> +
> + if (dev->driver && drv->resume)
> + error = drv->resume(gio_dev);
> + return error;
> +}
> +
> +static void gio_device_shutdown(struct device *dev)
> +{
> + struct gio_device *gio_dev = to_gio_device(dev);
> + struct gio_driver *drv = to_gio_driver(dev->driver);
> +
> + if (dev->driver && drv->shutdown)
> + drv->shutdown(gio_dev);
> +}
> +
> +int gio_register_driver(struct gio_driver *drv)
> +{
> + /* initialize common driver fields */
> + if (!drv->driver.name)
> + drv->driver.name = drv->name;
> + if (!drv->driver.owner)
> + drv->driver.owner = drv->owner;
> + drv->driver.bus = &gio_bus;
> +
> + /* register with core */
> + return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(gio_register_driver);
> +
> +void gio_unregister_driver(struct gio_driver *drv)
> +{
> + driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(gio_unregister_driver);
> +
> +void gio_set_master(struct gio_device *dev)
> +{
> + u32 tmp = sgimc->giopar;
> +
> + switch (dev->slotno) {
> + case 0:
> + tmp |= SGIMC_GIOPAR_MASTERGFX;
> + break;
> + case 1:
> + tmp |= SGIMC_GIOPAR_MASTEREXP0;
> + break;
> + case 2:
> + tmp |= SGIMC_GIOPAR_MASTEREXP1;
> + break;
> + }
> + sgimc->giopar = tmp;
> +}
> +EXPORT_SYMBOL_GPL(gio_set_master);
> +
> +void ip22_gio_set_64bit(int slotno)
> +{
> + u32 tmp = sgimc->giopar;
> +
> + switch (slotno) {
> + case 0:
> + tmp |= SGIMC_GIOPAR_GFX64;
> + break;
> + case 1:
> + tmp |= SGIMC_GIOPAR_EXP064;
> + break;
> + case 2:
> + tmp |= SGIMC_GIOPAR_EXP164;
> + break;
> + }
> + sgimc->giopar = tmp;
> +}
> +
> +static int ip22_gio_id(unsigned long addr, u32 *res)
> +{
> + u8 tmp8;
> + u8 tmp16;
> + u32 tmp32;
> + u8 *ptr8;
> + u16 *ptr16;
> + u32 *ptr32;
> +
> + ptr32 = (void *)CKSEG1ADDR(addr);
> + if (!get_dbe(tmp32, ptr32)) {
> + /*
> + * We got no DBE, but this doesn't mean anything.
> + * If GIO is pipelined (which can't be disabled
> + * for GFX slot) we don't get a DBE, but we see
> + * the transfer size as data. So we do an 8bit
> + * and a 16bit access and check whether the common
> + * data matches
> + */
> + ptr8 = (void *)CKSEG1ADDR(addr + 3);
> + get_dbe(tmp8, ptr8);
> + ptr16 = (void *)CKSEG1ADDR(addr + 2);
> + get_dbe(tmp16, ptr16);
> + if (tmp8 = (tmp16 & 0xff) &&
> + tmp8 = (tmp32 & 0xff) &&
> + tmp16 = (tmp32 & 0xffff)) {
> + *res = tmp32;
> + return 1;
> + }
> + }
> + return 0; /* nothing here */
> +}
> +
> +#define HQ2_MYSTERY_OFFS 0x6A07C
> +#define NEWPORT_USTATUS_OFFS 0xF133C
> +
> +static int ip22_is_gr2(unsigned long addr)
> +{
> + u32 tmp;
> + u32 *ptr;
> +
> + /* HQ2 only allows 32bit accesses */
> + ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS);
> + if (!get_dbe(tmp, ptr)) {
> + if (tmp = 0xdeadbeef)
> + return 1;
> + }
> + return 0;
> +}
> +
> +
> +static void ip22_check_gio(int slotno, unsigned long addr)
> +{
> + const char *name = "Unknown";
> + struct gio_device *gio_dev;
> + u32 tmp;
> + __u8 id;
> + int i;
> +
> + /* first look for GR2/GR3 by checking mystery register */
> + if (ip22_is_gr2(addr))
> + tmp = 0x7f;
> + else {
> + if (!ip22_gio_id(addr, &tmp)) {
> + /*
> + * no GIO signature at start address of slot, but
> + * Newport doesn't have one, so let's check usea
> + * status register
> + */
> + if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
> + tmp = 0x7e;
> + else
> + tmp = 0;
> + }
> + }
> + if (tmp) {
> + id = GIO_ID(tmp);
> + if (tmp & GIO_32BIT_ID) {
> + if (tmp & GIO_64BIT_IFACE)
> + ip22_gio_set_64bit(slotno);
> + }
> + for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) {
> + if (id = gio_name_table[i].id) {
> + name = gio_name_table[i].name;
> + break;
> + }
> + }
> + printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
> + slotno, name, id);
> + gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
> + gio_dev->name = name;
> + gio_dev->slotno = slotno;
> + gio_dev->id.id = id;
> + gio_dev->resource.start = addr;
> + gio_dev->resource.end = addr + 0x3fffff;
> + gio_dev->resource.flags = IORESOURCE_MEM;
> + dev_set_name(&gio_dev->dev, "gio%d", slotno);
> + gio_device_register(gio_dev);
> + } else
> + printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
> +}
> +
> +static struct bus_type gio_bus = {
> + .name = "gio",
> + .match = gio_bus_match,
> + .probe = gio_device_probe,
> + .remove = gio_device_remove,
> + .suspend = gio_device_suspend,
> + .resume = gio_device_resume,
> + .shutdown = gio_device_shutdown,
> +};
> +
> +static struct resource gio_bus_resource = {
> + .start = GIO_SLOT_GFX_BASE,
> + .end = GIO_SLOT_GFX_BASE + 0x9fffff,
> + .name = "GIO Bus",
> + .flags = IORESOURCE_MEM,
> +};
> +
> +int __init ip22_gio_init(void)
> +{
> + unsigned int pbdma __maybe_unused;
> + int ret;
> +
> + ret = bus_register(&gio_bus);
> + if (!ret) {
> + request_resource(&iomem_resource, &gio_bus_resource);
> + printk(KERN_INFO "GIO: Probing bus...\n");
> +
> + if (ip22_is_fullhouse() ||
> + !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) {
> + /* Indigo2 and ChallengeS */
> + ip22_check_gio(0, GIO_SLOT_GFX_BASE);
> + ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
> + } else {
> + /* Indy */
> + ip22_check_gio(0, GIO_SLOT_GFX_BASE);
> + ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
> + ip22_check_gio(2, GIO_SLOT_EXP1_BASE);
> + }
> + }
> + return ret;
> +}
> +
> +subsys_initcall(ip22_gio_init);
> +
> diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
> index d22262e..75ada8a 100644
> --- a/arch/mips/sgi-ip22/ip22-mc.c
> +++ b/arch/mips/sgi-ip22/ip22-mc.c
> @@ -139,11 +139,11 @@ void __init sgimc_init(void)
> * zero.
> */
> /* don't touch parity settings for IP28 */
> -#ifndef CONFIG_SGI_IP28
> tmp = sgimc->cpuctrl0;
> - tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
> - SGIMC_CCTRL0_R4KNOCHKPARR);
> +#ifndef CONFIG_SGI_IP28
> + tmp |= SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM;
> #endif
> + tmp |= SGIMC_CCTRL0_R4KNOCHKPARR;
> sgimc->cpuctrl0 = tmp;
>
> /* Step 3: Setup the MC write buffer depth, this is controlled
> @@ -178,7 +178,8 @@ void __init sgimc_init(void)
> */
>
> /* First the basic invariants across all GIO64 implementations. */
> - tmp = SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
> + tmp = sgimc->giopar & SGIMC_GIOPAR_GFX64; /* keep gfx 64bit settings */
> + tmp |= SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
> tmp |= SGIMC_GIOPAR_ONEBUS; /* Only one physical GIO bus exists */
>
> if (ip22_is_fullhouse()) {
> @@ -193,7 +194,6 @@ void __init sgimc_init(void)
> tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp[01] pipelined */
> tmp |= SGIMC_GIOPAR_PLINEEXP1;
> tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */
> - tmp |= SGIMC_GIOPAR_GFX64; /* GFX at 64 bits */
> }
> } else {
> /* Guiness specific settings. */
> diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
> index 5e66213..c7bdfe4 100644
> --- a/arch/mips/sgi-ip22/ip22-setup.c
> +++ b/arch/mips/sgi-ip22/ip22-setup.c
> @@ -26,9 +26,6 @@
> #include <asm/sgi/hpc3.h>
> #include <asm/sgi/ip22.h>
>
> -unsigned long sgi_gfxaddr;
> -EXPORT_SYMBOL_GPL(sgi_gfxaddr);
> -
> extern void ip22_be_init(void) __init;
>
> void __init plat_mem_setup(void)
> @@ -78,22 +75,4 @@ void __init plat_mem_setup(void)
> prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
> add_preferred_console("arc", 0, NULL);
> }
> -
> -#if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
> - {
> - ULONG *gfxinfo;
> - ULONG * (*__vec)(void) = (void *) (long)
> - *((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
> -
> - gfxinfo = __vec();
> - sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
> - && gfxinfo[1] <= 0xc0000000)
> - ? gfxinfo[1] - 0xa0000000 : 0);
> -
> - /* newport addresses? */
> - if (sgi_gfxaddr = 0x1f0f0000 || sgi_gfxaddr = 0x1f4f0000) {
> - conswitchp = &newport_con;
> - }
> - }
> -#endif
> }
> diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
> index 93317b5..628b7ec 100644
> --- a/drivers/video/console/newport_con.c
> +++ b/drivers/video/console/newport_con.c
> @@ -25,14 +25,13 @@
> #include <asm/system.h>
> #include <asm/page.h>
> #include <asm/pgtable.h>
> +#include <asm/gio_device.h>
> +
> #include <video/newport.h>
>
> #include <linux/linux_logo.h>
> #include <linux/font.h>
>
> -
> -extern unsigned long sgi_gfxaddr;
> -
> #define FONT_DATA ((unsigned char *)font_vga_8x16.data)
>
> /* borrowed from fbcon.c */
> @@ -304,12 +303,6 @@ static const char *newport_startup(void)
> {
> int i;
>
> - if (!sgi_gfxaddr)
> - return NULL;
> -
> - if (!npregs)
> - npregs = (struct newport_regs *)/* ioremap cannot fail */
> - ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
> npregs->cset.config = NPORT_CFG_GD0;
>
> if (newport_wait(npregs))
> @@ -743,26 +736,56 @@ const struct consw newport_con = {
> .con_save_screen = DUMMY
> };
>
> -#ifdef MODULE
> -static int __init newport_console_init(void)
> +static int newport_probe(struct gio_device *dev,
> + const struct gio_device_id *id)
> {
> - if (!sgi_gfxaddr)
> - return 0;
> + unsigned long newport_addr;
>
> - if (!npregs)
> - npregs = (struct newport_regs *)/* ioremap cannot fail */
> - ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
> + if (!dev->resource.start)
> + return -EINVAL;
> +
> + if (npregs)
> + return -EBUSY; /* we only support one Newport as console */
> +
> + newport_addr = dev->resource.start + 0xF0000;
> + if (!request_mem_region(newport_addr, 0x10000, "Newport"))
> + return -ENODEV;
> +
> + npregs = (struct newport_regs *)/* ioremap cannot fail */
> + ioremap(newport_addr, sizeof(struct newport_regs));
>
> return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
> }
> -module_init(newport_console_init);
>
> -static void __exit newport_console_exit(void)
> +static void newport_remove(struct gio_device *dev)
> {
> give_up_console(&newport_con);
> iounmap((void *)npregs);
> }
> +
> +static struct gio_device_id newport_ids[] = {
> + { .id = 0x7e },
> + { .id = 0xff }
> +};
> +
> +static struct gio_driver newport_driver = {
> + .name = "newport",
> + .id_table = newport_ids,
> + .probe = newport_probe,
> + .remove = newport_remove,
> +};
> +
> +int __init newport_console_init(void)
> +{
> + return gio_register_driver(&newport_driver);
> +}
> +
> +void __exit newport_console_exit(void)
> +{
> + gio_unregister_driver(&newport_driver);
> +}
> +
> +module_init(newport_console_init);
> module_exit(newport_console_exit);
> -#endif
>
> MODULE_LICENSE("GPL");
>
^ permalink raw reply
* Re: [RESENT][PATCH v2 0/2] fb: add early fb blank feature
From: Florian Tobias Schandinat @ 2011-10-30 11:24 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <003f01cc8280$7510c5c0$5f325140$%dae@samsung.com>
Hi Andrew,
can you take care of this patch series?
It seems like Richard does no longer handle LCD/backlight stuff (why is he
listed as maintainer?) and I really cannot say whether the patch to the LCD code
is correct and therefore I do not intend to carry such a patch without any Ack.
You can add an "Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>"
to the fb patch 2/2 (well actually I think the order should be swapped as 1 does
not compile without 2) but I ask you to handle it as well as it is useless
without the other patch.
Thanks,
Florian Tobias Schandinat
On 10/04/2011 10:29 AM, Inki Dae wrote:
> this patch adds early fb blank feature that a callback of lcd panel driver
> is called prior to specific fb driver's one. in case of MIPI-DSI based video
> mode LCD Panel, for lcd power off, the power off commands should be
> transferred to lcd panel with display and mipi-dsi controller enabled
> because the commands is set to lcd panel at vsync porch period. and in
> opposite case, the callback of fb driver should be called prior to lcd panel
> driver's one because of same issue. and also if fb_blank mode is changed to
> FB_BLANK_POWERDOWN then display controller would be off(clock disable) but
> lcd panel would be still on. at this time, you could see some issue like
> sparkling on lcd panel because video clock to be delivered to ldi module of
> lcd panel was disabled. this issue could occurs for all lcd panels.
>
> the callback order is as the following:
>
> at fb_blank function of fbmem.c
> -> fb_notifier_call_chain(FB_EARLY_EVENT_BLANK)
> -> lcd panel driver's early_set_power()
> -> info->fbops->fb_blank()
> -> spcefic fb driver's fb_blank()
> -> fb_notifier_call_chain(FB_EVENT_BLANK)
> -> lcd panel driver's set_power()
> -> fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK) if
> info->fops->fb_blank() was failed.
>
> fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK) would be called to revert the
> effects of previous FB_EARLY_EVENT_BLANK call. and note that if
> early_set_power() of lcd_ops is NULL then early fb blank callback would be
> ignored.
>
> this patch is based on git repository below:
> git://github.com/schandinat/linux-2.6.git
> branch: fbdev-next
> commit-id: 2b7a905dd0d24d14a1099653ba63b7113a82fc54
>
> Links to previous versions of the patchset:
> v1: < http://lkml.indiana.edu/hypermail/linux/kernel/1109.1/00413.html >
>
> Changelog v2:
> fb: add fb early blank event instead of early_blank_mode variable.
> fb notifier can know whether early blank mode is support or not
> checking if early_set_power callback is NULL or not.
>
> fb: add exception codes at fb_blank().
> the effects of previous FB_EARLY_EVENT_BLANK call should be reverted
> if info->fbops->fb_blank() was failed.
>
> fb: add code clean.
>
> Changelog RESEND:
> fb: fixed condition.
> this patch changes 'if (early_ret < 0)' to 'if (!early_ret)' of
> fb_blank function.
>
> these patch series are as the following:
> [RESEND][PATCH v2 0/2] fb: add early fb blank feature.
> introduce new early fb blank feature.
> [RESEND][PATCH v2 1/2] lcd: add callbacks for early fb event blank support.
> [RESEND][PATCH v2 2/2] fb: add events for early fb event support.
>
> Signed-off-by: Inki Dae <inki.dae@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [GIT PULL] fbdev updates for 3.2
From: Florian Tobias Schandinat @ 2011-10-30 10:14 UTC (permalink / raw)
To: Linus Torvalds; +Cc: LKML, linux-fbdev@vger.kernel.org
Hi Linus,
please pull the following changes to the fbdev subsystem. It contains
- a series from Laurent which touches many different drivers to sanitize their
panning behavior
- two patches to fix the suspend/resume locking issue
- a little fix to our EDID parsing
- a new driver for SMSC UFX6000/7000 USB display devices
- a new driver for Aeroflex Gaisler GRVGA IP core
- a lot of driver updates for OMAP, sh_mobile, fsl-diu-fb, au1200fb, udlfb and
viafb, a few patches to others
It's the same tree (only a different branch) you used to pull viafb updates from
so, I think, you can trust it. You will probably experience some (trivial) merge
conflicts related to xgifb and OMAP, please let me know if you want me to handle
them.
Thanks,
Florian Tobias Schandinat
The following changes since commit 976d167615b64e14bc1491ca51d424e2ba9a5e84:
Linux 3.1-rc9 (2011-10-04 18:11:50 -0700)
are available in the git repository at:
git://github.com/schandinat/linux-2.6.git fbdev-next
Ajay Kumar (1):
video: s3c-fb: Add S5P64X0 specific s3c_fb_driverdata
Anatolij Gustschin (1):
video: mb862xx-i2c: fix for reliable decoder register access
Andrew Kephart (1):
udlfb: Search config descriptor if not at device level
Andy Doan (1):
OMAPFB: make debug message more useful
Archit Taneja (26):
OMAP: DSS2: DISPC: Prepare dispc_dump_regs() for shortening
OMAP: DSS2: DISPC: Shorten dispc_dump_regs()
OMAP: DSS2: DISPC: dispc_save_context() and dispc_restore_context() cleanup
OMAP: DSS2: DISPC: Shorten _dispc_set_color_conv_coef()
OMAP: DSS2: Use a macro to declare size of the fifo_size array in dispc.c
OMAP: DSS2: Use MIPI DSI enums from include/video/mipi_display.h
OMAP: DSS2: DSI: Represent L4 and VP as sources of VC instead of modes
OMAP: DSS2: Create enum for DSI operation modes
OMAP: DSS2: DSI: Introduce generic write functions
OMAP: DSS2: DSI: Remove functions dsi_vc_dcs_read_1() and dsi_vc_dcs_read_2()
OMAP: DSS2: DSI: Split dsi_vc_dcs_read() into 2 functions
OMAP: DSS2: DSI: Introduce generic read functions
OMAP: DSS2: Clean up stallmode and io pad mode selection
OMAP: DSS2: Create an enum for DSI pixel formats
OMAP: DSS2: DSI: Send zero length packet in dsi_vc_send_null()
OMAP: DSS2: DSI Video mode support
OMAPDSS: DISPC: Reduce the number of arguments in dispc_ovl_setup()
OMAPDSS: DISPC: Pass overlay params as arguments to dispc_ovl_setup()
OMAPDSS: DISPC: Create helper function dispc_mgr_is_lcd()
OMAPDSS: DISPC: Get correct pixel clock for TV manager
OMAPDSS: DISPC: Remove hardcoded use of PPL in five tap clock calculation
OMAPDSS: DISPC: Clean up scaling related clock and five tap calculations
OMAPDSS: FEATURES: Create a range param to get max downscaling
OMAPDSS/OMAP_VOUT: Fix incorrect OMAP3-alpha compatibility setting
OMAPDSS: DISPC: VIDEO3 pipeline support
OMAPDSS: DISPC: zorder support for DSS overlays
Arnd Bergmann (1):
video/omap: fix build dependencies
Axel Lin (3):
video: mxsfb: add missing include of linux/module.h
video: nuc900fb: remove include of mach/clkdev.h
video: platinumfb: Add __devexit_p at necessary place
Bernie Thompson (4):
drivers/video/udlfb match class, subclass, and protocol
udlfb: add more comprehensive support for DPMS FB_BLANK_* modes
udlfb: Enable fb_defio by default
udlfb: Enable fbcon access to framebuffer by default
Bruno Prémont (1):
fb: sh-mobile: Fix deadlock risk between lock_fb_info() and console_lock()
Damian Hobson-Garcia (5):
fbdev: sh_mobile_meram: Enable runtime PM
fbdev: sh_mobile_meram: Enable/disable MERAM along with LCDC
fbdev: sh_mobile_meram: Move private data from .h to .c
fbdev: sh_mobile_meram: Backup/restore device registers on shutdown/resume
fbdev: sh_mobile_meram: Assign meram to the SH7372_A4LC power domain
Dan Carpenter (1):
smscufx: change edid data to u8 instead of char
Daniel Morsing (1):
OMAP: DSS2: Don't allow moving managers away from enabled displays
Dima Zavin (1):
OMAP: DSS: dispc: enable/disable clocks in error handler
Dr. David Alan Gilbert (1):
udlfb: fix issues found with Sparse static analysis
Florian Tobias Schandinat (21):
viafb: use display information in info not in var for panning
viafb: improve pitch handling
viafb: use more compact modesetting functions
viafb: kill viafb_load_crtc_timing
viafb: remove superfluous register unlocking/locking
viafb: remove superfluous mode lookup
viafb: simplify viafb_fill_crtc_timing
viafb: remove 640x480-60 CRT special case
viafb: add new funcions to select a single mode
viafb: eliminate viafb_get_pixclock
viafb: use information in var for modesetting
viafb: seperate hardware initialization
viafb: eliminate modetable dependancy of LCD modesetting
viafb: get rid of the remaining modetable structure assumptions
Merge commit 'v3.1-rc2' into HEAD
Merge branch 'pan-fixes' of git://linuxtv.org/pinchartl/fbdev into fbdev-next
Merge branch 'master' of git://git.kernel.org/.../lethal/fbdev-3.x into
fbdev-next
Merge branch 'sh-mobile-lcdc' of git://linuxtv.org/pinchartl/fbdev into
fbdev-next
Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6 into
fbdev-next
Merge commit 'v3.1-rc9' into fbdev-next
Merge branch 'for-florian' of git://gitorious.org/linux-omap-dss2/linux
into fbdev-next
Herton Ronaldo Krzesinski (1):
fb: avoid possible deadlock caused by fb_set_suspend
Jean Delvare (1):
carminefb: Fix module parameters permissions
Jesper Juhl (1):
Remove unneeded version.h includes from drivers/video/
Jingoo Han (1):
video: s3c-fb: Add support EXYNOS4 FIMD
Joe Perches (1):
video: Fix speficied typo
Julia Lawall (1):
drivers/video/msm/mdp.c: adjust error handling code
Kay Sievers (1):
drivers/video/udlfb bind framebuffer to interface.
Kristoffer Glembo (1):
video: Add Aeroflex Gaisler GRVGA framebuffer device driver
Laurent Pinchart (77):
vfb: use display information in info not in var for panning
staging: xgifb: use display information in info not in var for panning
acornfb: Dont BUG() on invalid pan parameters
s3fb: use display information in info not in var for panning
mx3fb: use display information in info not in var for panning
neofb: use display information in info not in var for panning
savagefb: use display information in info not in var for panning
sm501fb: use display information in info not in var for panning
imsttfb: use display information in info not in var for panning
gxt4500: use display information in info not in var for panning
pm2fb: use display information in info not in var for panning
sisfb: use display information in info not in var for panning
atmel_lcdfb: use display information in info not in var for panning
intelfb: use display information in info not in var for panning
tridentfb: use display information in info not in var for panning
vga16fb: use display information in info not in var for panning
radeonfb: use display information in info not in var for panning
hgafb: use display information in info not in var for panning
pm3fb: use display information in info not in var for panning
acornfb: use display information in info not in var for panning
fbdev: unicore32: use display information in info not in var for panning
s3c-fb: use display information in info not in var for panning
mb862xxfb: use display information in info not in var for panning
g364fb: use display information in info not in var for panning
arkfb: use display information in info not in var for panning
68328fb: use display information in info not in var for panning
vt8623fb: use display information in info not in var for panning
vt8500lcdfb: use display information in info not in var for panning
fbdev: da8xx: use display information in info not in var for panning
fbdev: sh_mobile_lcdc: Turn dot clock on before resuming from runtime PM
fbdev: sh_mobile_lcdc: Replace hardcoded register values with macros
fbdev: sh_mobile_lcdc: Don't acknowlege interrupts unintentionally
fbdev: sh_mobile_lcdc: Compute clock pattern using divider denominator
fbdev: sh_mobile_lcdc: Split LCDC start code from sh_mobile_lcdc_start
fbdev: sh_mobile_lcdc: Store the frame buffer base address when panning
fbdev: sh_mobile_lcdc: Restart LCDC in runtime PM resume handler
fbdev: sh_mobile_meram: Replace hardcoded register values with macros
fbdev: sh_mobile_meram: Validate ICB configuration outside mutex
fbdev: sh_mobile_meram: Fix MExxCTL register save on runtime PM suspend
fbdev: sh_mobile_meram: Remove unneeded sh_mobile_meram.h
68328fb: use display information in info not in var for panning
acornfb: Dont BUG() on invalid pan parameters
acornfb: use display information in info not in var for panning
arkfb: use display information in info not in var for panning
atmel_lcdfb: use display information in info not in var for panning
radeonfb: use display information in info not in var for panning
fbdev: da8xx: use display information in info not in var for panning
fbdev: unicore32: use display information in info not in var for panning
g364fb: use display information in info not in var for panning
gxt4500: use display information in info not in var for panning
hgafb: use display information in info not in var for panning
imsttfb: use display information in info not in var for panning
intelfb: use display information in info not in var for panning
mb862xxfb: use display information in info not in var for panning
mx3fb: use display information in info not in var for panning
neofb: use display information in info not in var for panning
pm2fb: use display information in info not in var for panning
pm3fb: use display information in info not in var for panning
s3c-fb: use display information in info not in var for panning
s3fb: use display information in info not in var for panning
savagefb: use display information in info not in var for panning
sisfb: use display information in info not in var for panning
sm501fb: use display information in info not in var for panning
tridentfb: use display information in info not in var for panning
vfb: use display information in info not in var for panning
vga16fb: use display information in info not in var for panning
vt8500lcdfb: use display information in info not in var for panning
vt8623fb: use display information in info not in var for panning
staging: xgifb: use display information in info not in var for panning
sh_mobile_meram: Reset ICBs at unregistration time
fbdev: sh_mobile_lcdc: Adjust requested parameters in .fb_check_var
fbdev: sh_mobile_lcdc: Add support for format changes at runtime
fbdev: sh_mobile_lcdc: use display information in info for panning
fbdev: sh_mobile_lcdc: Update fix.line_length in .fb_set_par()
fbdev: sh_mobile_lcdc: Avoid forward declarations
fbdev: sh_mobile_lcdc: Split channel initialization from probe function
fbdev: sh_mobile_lcdc: Remove sh_mobile_lcdc_set_bpp()
Manjunathappa, Prakash (2):
video: da8xx-fb: Interrupt configuration of revised LCDC IP
video: da8xx-fb: Increased resolution configuration of revised LCDC IP
Manuel Lauss (7):
au1200fb: use framebuffer_alloc()
au1200fb: fixup PM
au1200fb: make number of windows configurable at load time.
au1200fb: switch to FB_SYS helpers
au1200fb: fix hardcoded IRQ
fbdev: au1200fb: silence debug output
fb: fix au1100fb bitrot.
Mayuresh Janorkar (1):
OMAP: DSS2: Add picodlp panel driver
Mythri P K (14):
OMAP4: DSS2: HDMI: HDMI clean up to pass base_address
OMAP4: DSS2: HDMI: Move pll and video configuration
OMAP4: DSS2: HDMI: Use specific HDMI timings structure
OMAP4: DSS2: HDMI: Move HDMI IP independent generic header
OMAP4: DSS2: HDMI: Move the EDID definition from HDMI
OMAP4: DSS2: HDMI: Split the current HDMI driver to move
OMAP4: DSS2: HDMI: Move the HDMI IP dependent audio
OMAP4: DSS2: HDMI: Rename the functions in HDMI IP library
OMAP4: DSS2: HDMI: Function pointer approach to call
OMAP4: DSS2: Rename hdmi_omap4_panel.c to hdmi_panel.c
OMAPDSS: HDMI: Move the comments in avi infoframe
OMAPDSS: HDMI: Replace hdmi_reg struct with u16
OMAPDSS: HDMI: Add missing register definitions
OMAPDSS: HDMI: Add support to dump registers through debugfs
Paul Mundt (4):
Merge branch 'fbdev/panning-fixes'
Merge branch 'fbdev/stable-updates'
Merge branch 'fbdev/stable-updates'
Merge branch 'viafb-next' of git://github.com/schandinat/linux-2.6
Steve Glendinning (2):
Add support for SMSC UFX6000/7000 USB display adapters
smscufx: reduce number of casts in ufx_raw_rect
Stuart Hopkins (1):
udlfb: Add module option to do without shadow framebuffer
Tejun Heo (1):
video: don't use flush_scheduled_work() in fb_defio
Thomas Weber (2):
OMAP: DSS2: Support for Innolux AT070TN83
OMAP: Devkit8000: Change lcd driver to AT070TN83
Timur Tabi (24):
drivers/video: use strings to specify the Freescale DIU monitor port
fbdev: fix indentation in modedb.c
drivers/video: fsl-diu-fb: clean up whitespace and formatting
drivers/video: fsl-diu-fb: clean up printk usage
drivers/video: fsl-diu-fb: remove unused ioctls
drivers/video: fsl-diu-fb: fix compilation warning
drivers/video: fsl-diu-fb: improve device tree usage
drivers/video: fsl-diu-fb: remove redundant default video mode
drivers/video: fsl-diu-fb: improve local variable usage in some functions
drivers/video: fsl-diu-fb: set the driver name to "fsl-diu-fb"
drivers/video: fsl-diu-fb: fix potential memcpy buffer overflow bug
drivers/video: fsl-diu-fb: fix memory leak on error
drivers/video: fsl-diu-fb: use a normal for-loop to uninstall framebuffers
drivers/video: fsl-diu-fb: the video buffer is not I/O memory
drivers/video: fsl-diu-fb: remove unusued MEM_ALLOC_THRESHOLD
drivers/video: fsl-diu-fb: fix some ioctls
drivers/video: fsl-diu-fb: move some definitions out of the header file
drivers/video: fsl-diu-fb: remove broken screen blanking support
drivers/video: fsl-diu-fb: add several new video modes
drivers/video: fsl-diu-fb: use an enum for the AOI index
drivers/video: fsl-diu-fb: remove unused panel operating mode support
drivers/video: fsl-diu-fb: only DIU modes 0 and 1 are supported
drivers/video: fsl-diu-fb: merge diu_hw into fsl_diu_data
drivers/video: fsl-diu-fb: merge diu_pool into fsl_diu_data
Tomi Valkeinen (64):
fbdev: fix parsing of standard timings
OMAP: DSS2: PicoDLP: fix error handling in power_on
OMAP: DSS2: check for manager when enabling display
Revert "HACK: OMAP: DSS2: clk hack for OMAP2/3"
Revert "OMAP: DSS2: HDMI: fix hdmi clock name"
OMAP: DSS2: remove unneeded fck enable/disables
OMAP: DSS2: Change DSI device naming
OMAP4: TWL: Add common omapdss supplies
OMAP: DSS2: DSI: Improve dsi_mux_pads parameters
OMAP: DSS2: Implement dsi_mux_pads for OMAP4
OMAP: OMAPFB: make omapfb start even when a display is missing a driver
OMAP: DSS2: fix clock sources on error and uninit
OMAP: DSS2: Handle manager change in apply
OMAP: DSS2: Remove "EXPERIMENTAL" from Kconfig
OMAP: DSS2: Remove support for non-DISPC overlays
OMAP: DSS2: DISPC: use lookup tables for bit shifts
OMAP: DSS2: Add overlay caps to DSS features
OMAP: DSS2: Add GLOBAL_ALPHA & PRE_MULT_ALPHA to ovl caps
OMAP: DSS2: string parsing cleanups
OMAP: OMAPFB: string parsing cleanups
OMAP: DSS2: DISPC: remove non-existing func prototypes
OMAP: DSS2: DISPC: rename overlay related funcs
OMAP: DSS2: DISPC: rename manager related funcs
OMAP: DSS2: reorganize functions in dss.h
OMAP: DSS2: DISPC: Fix minimum PCD value
OMAP: DSS2: HDMI: use default dividers
OMAP: DSS2: HDMI: change regn definition
OMAP: DSS2: DSI: Add comment about regn
OMAP: DSS2: DISPC: Add missing IRQ definitions
OMAP: DSS2: add dss_get_hdmi_venc_clk_source()
OMAP: DSS2: DISPC: improve dispc_mgr_enable_digit_out()
OMAP: DSS2: HDMI: improve hdmi output enable
OMAP: DSS2: add read_edid() to omap_dss_driver struct
OMAP: DSS2: add detect() to omap_dss_driver struct
OMAP: DSS2: HDMI: make set_timing saner
OMAP: DSS2: HDMI: implement read_edid()
OMAP: DSS2: HDMI: remove edid parsing
OMAP: DSS2: HDMI: split hdmi_core_ddc_edid
OMAP: DSS2: HDMI: clean up edid reading & fix checksum
OMAP: DSS2: HDMI: remove error prints in check_timings
OMAP: DSS2: HDMI: implement detect()
OMAP: DSS2: add panel-dvi driver
OMAP: use dvi panel driver instead of generic-dpi
OMAP: stalker: Remove LCD device from board file
OMAP: DSS2: panel-generic-dpi: remove "generic" panel
OMAP: Add DDC i2c_bus_num to board files
OMAPFB: find best mode from edid
OMAPDSS: Taal: remove external backlight support
OMAPFB: Remove unused lcd drivers
OMAPDSS: Port 2430sdp display driver to DSS2
OMAPDSS: Port the H4 display driver to DSS2
OMAPDSS: Port the Apollon display driver to DSS2
OMAPDSS: Add N800 panel driver
OMAPDSS: remove vaddr from overlay info
OMAP: 4430SDP: Remove unneeded lcd config
OMAP4: 4430SDP: Add panel support to board file
OMAP4: 4430SDP: Add picodlp support to board file
OMAP: RX51: Remove unused old omapfb stuff
OMAP: omap3touchbook: Remove unused lcd stuff
OMAP: 2420SDP: Port the display driver to new DSS2
OMAP: LDP: Port the display driver to new DSS2
OMAP: H4: Port the display driver to new DSS2
OMAP: Apollon: Port the display driver to new DSS2
OMAPDSS: picodlp: add missing #include <linux/module.h>
Wang Shaoyan (2):
viafb: fix pointer type missmatch
viafb: replace strict_strtoul to kstrto* and check return value
Wolfram Sang (1):
video: s3c2410: remove unused variable
Wolfram Stering (1):
mx3fb: fix NULL pointer dereference in screen blanking.
Yong Zhang (1):
video: irq: Remove IRQF_DISABLED
Documentation/fb/udlfb.txt | 39 +-
MAINTAINERS | 6 +
arch/arm/mach-omap2/board-2430sdp.c | 78 +-
arch/arm/mach-omap2/board-3430sdp.c | 7 +-
arch/arm/mach-omap2/board-4430sdp.c | 208 ++-
arch/arm/mach-omap2/board-am3517evm.c | 6 +-
arch/arm/mach-omap2/board-apollon.c | 35 +-
arch/arm/mach-omap2/board-cm-t35.c | 6 +-
arch/arm/mach-omap2/board-devkit8000.c | 10 +-
arch/arm/mach-omap2/board-h4.c | 42 +-
arch/arm/mach-omap2/board-igep0020.c | 8 +-
arch/arm/mach-omap2/board-ldp.c | 123 ++-
arch/arm/mach-omap2/board-omap3beagle.c | 8 +-
arch/arm/mach-omap2/board-omap3evm.c | 7 +-
arch/arm/mach-omap2/board-omap3pandora.c | 2 +-
arch/arm/mach-omap2/board-omap3stalker.c | 40 +-
arch/arm/mach-omap2/board-omap3touchbook.c | 18 -
arch/arm/mach-omap2/board-omap4panda.c | 8 +-
arch/arm/mach-omap2/board-overo.c | 7 +-
arch/arm/mach-omap2/board-rx51.c | 25 -
arch/arm/mach-omap2/display.c | 60 +-
arch/arm/mach-omap2/twl-common.c | 11 +-
arch/arm/mach-shmobile/board-mackerel.c | 1 +
arch/powerpc/platforms/512x/mpc512x_shared.c | 24 +-
arch/powerpc/platforms/85xx/p1022_ds.c | 47 +-
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 55 +-
arch/powerpc/sysdev/fsl_soc.h | 25 +-
drivers/media/video/omap/omap_vout.c | 18 +-
drivers/staging/xgifb/XGI_main_26.c | 22 +-
drivers/video/68328fb.c | 4 +-
drivers/video/Kconfig | 34 +-
drivers/video/Makefile | 2 +
drivers/video/acornfb.c | 5 +-
drivers/video/arkfb.c | 9 +-
drivers/video/atmel_lcdfb.c | 15 +-
drivers/video/aty/radeon_base.c | 10 +-
drivers/video/au1100fb.c | 181 +--
drivers/video/au1100fb.h | 6 +-
drivers/video/au1200fb.c | 299 ++--
drivers/video/backlight/adp8860_bl.c | 1 -
drivers/video/backlight/adp8870_bl.c | 1 -
drivers/video/bf54x-lq043fb.c | 2 +-
drivers/video/bfin-lq035q1-fb.c | 2 +-
drivers/video/bfin-t350mcqb-fb.c | 2 +-
drivers/video/bfin_adv7393fb.c | 2 +-
drivers/video/carminefb.c | 6 +-
drivers/video/controlfb.c | 2 +-
drivers/video/da8xx-fb.c | 186 ++-
drivers/video/fb-puv3.c | 4 +-
drivers/video/fb_defio.c | 3 +-
drivers/video/fbmem.c | 3 -
drivers/video/fbmon.c | 21 +-
drivers/video/fbsysfs.c | 3 +
drivers/video/fsl-diu-fb.c | 992 +++++-----
drivers/video/g364fb.c | 5 +-
drivers/video/grvga.c | 579 ++++++
drivers/video/gxt4500.c | 4 +-
drivers/video/hgafb.c | 4 +-
drivers/video/imsttfb.c | 2 +-
drivers/video/intelfb/intelfbhw.c | 6 +-
drivers/video/mb862xx/mb862xx-i2c.c | 2 +-
drivers/video/mb862xx/mb862xxfbdrv.c | 6 +-
drivers/video/modedb.c | 444 +++---
drivers/video/msm/mddi.c | 2 +-
drivers/video/msm/mdp.c | 6 +-
drivers/video/mx3fb.c | 19 +-
drivers/video/mxsfb.c | 1 +
drivers/video/neofb.c | 4 +-
drivers/video/nuc900fb.c | 3 +-
drivers/video/omap/Kconfig | 29 -
drivers/video/omap/Makefile | 8 -
drivers/video/omap/lcd_2430sdp.c | 203 --
drivers/video/omap/lcd_apollon.c | 136 --
drivers/video/omap/lcd_h4.c | 117 --
drivers/video/omap/lcd_ldp.c | 201 --
drivers/video/omap/lcd_omap3beagle.c | 130 --
drivers/video/omap/lcd_omap3evm.c | 193 --
drivers/video/omap/lcd_overo.c | 180 --
drivers/video/omap2/displays/Kconfig | 28 +-
drivers/video/omap2/displays/Makefile | 3 +
drivers/video/omap2/displays/panel-dvi.c | 363 ++++
drivers/video/omap2/displays/panel-generic-dpi.c | 113 +-
drivers/video/omap2/displays/panel-n8x0.c | 747 ++++++++
drivers/video/omap2/displays/panel-picodlp.c | 594 ++++++
drivers/video/omap2/displays/panel-picodlp.h | 288 +++
drivers/video/omap2/displays/panel-taal.c | 125 +-
drivers/video/omap2/dss/Kconfig | 2 +-
drivers/video/omap2/dss/Makefile | 2 +-
drivers/video/omap2/dss/core.c | 4 +
drivers/video/omap2/dss/dispc.c | 1700 +++++++----------
drivers/video/omap2/dss/dispc.h | 57 +
drivers/video/omap2/dss/display.c | 31 +-
drivers/video/omap2/dss/dpi.c | 28 +-
drivers/video/omap2/dss/dsi.c | 929 ++++++----
drivers/video/omap2/dss/dss.c | 18 +-
drivers/video/omap2/dss/dss.h | 156 +-
drivers/video/omap2/dss/dss_features.c | 130 ++-
drivers/video/omap2/dss/dss_features.h | 17 +-
drivers/video/omap2/dss/hdmi.c | 1260 ++-----------
.../omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} | 68 +-
drivers/video/omap2/dss/manager.c | 191 +--
drivers/video/omap2/dss/overlay.c | 122 +-
drivers/video/omap2/dss/rfbi.c | 45 +-
drivers/video/omap2/dss/sdi.c | 19 +-
drivers/video/omap2/dss/ti_hdmi.h | 138 ++
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 1239 ++++++++++++
.../video/omap2/dss/{hdmi.h => ti_hdmi_4xxx_ip.h} | 400 ++---
drivers/video/omap2/dss/venc.c | 27 +-
drivers/video/omap2/omapfb/Kconfig | 2 +-
drivers/video/omap2/omapfb/omapfb-main.c | 134 ++-
drivers/video/omap2/omapfb/omapfb-sysfs.c | 6 +-
drivers/video/platinumfb.c | 4 +-
drivers/video/pm2fb.c | 6 +-
drivers/video/pm3fb.c | 6 +-
drivers/video/ps3fb.c | 2 +-
drivers/video/pxa3xx-gcu.c | 4 +-
drivers/video/pxafb.c | 2 +-
drivers/video/s3c-fb.c | 117 ++-
drivers/video/s3c2410fb.c | 3 +-
drivers/video/s3fb.c | 9 +-
drivers/video/sa1100fb.c | 3 +-
drivers/video/savage/savagefb_driver.c | 16 +-
drivers/video/sh_mobile_hdmi.c | 47 +-
drivers/video/sh_mobile_lcdcfb.c | 1162 ++++++------
drivers/video/sh_mobile_lcdcfb.h | 12 +-
drivers/video/sh_mobile_meram.c | 208 ++-
drivers/video/sh_mobile_meram.h | 41 -
drivers/video/sis/sis_main.c | 30 +-
drivers/video/skeletonfb.c | 2 +-
drivers/video/sm501fb.c | 6 +-
drivers/video/smscufx.c | 1994 ++++++++++++++++++++
drivers/video/tmiofb.c | 2 +-
drivers/video/tridentfb.c | 4 +-
drivers/video/udlfb.c | 187 ++-
drivers/video/valkyriefb.c | 2 +-
drivers/video/vfb.c | 4 +-
drivers/video/vga16fb.c | 2 +-
drivers/video/via/dvi.c | 34 +-
drivers/video/via/dvi.h | 3 +-
drivers/video/via/global.c | 2 +
drivers/video/via/global.h | 2 +
drivers/video/via/hw.c | 544 +-----
drivers/video/via/hw.h | 285 +---
drivers/video/via/lcd.c | 53 +-
drivers/video/via/lcd.h | 7 +-
drivers/video/via/share.h | 23 +-
drivers/video/via/via-core.c | 2 +-
drivers/video/via/via_modesetting.c | 104 +
drivers/video/via/via_modesetting.h | 23 +
drivers/video/via/viafbdev.c | 182 +-
drivers/video/via/viamode.c | 60 +-
drivers/video/via/viamode.h | 4 +-
drivers/video/vt8500lcdfb.c | 6 +-
drivers/video/vt8623fb.c | 9 +-
drivers/video/xilinxfb.c | 1 -
include/linux/fsl-diu-fb.h | 92 +-
include/video/omap-panel-dvi.h | 37 +
include/video/omap-panel-n8x0.h | 15 +
include/video/omap-panel-nokia-dsi.h | 8 +-
include/video/omap-panel-picodlp.h | 23 +
include/video/omapdss.h | 100 +-
include/video/sh_mobile_lcdc.h | 135 ++-
include/video/udlfb.h | 1 +
163 files changed, 12022 insertions(+), 7619 deletions(-)
create mode 100644 drivers/video/grvga.c
delete mode 100644 drivers/video/omap/lcd_2430sdp.c
delete mode 100644 drivers/video/omap/lcd_apollon.c
delete mode 100644 drivers/video/omap/lcd_h4.c
delete mode 100644 drivers/video/omap/lcd_ldp.c
delete mode 100644 drivers/video/omap/lcd_omap3beagle.c
delete mode 100644 drivers/video/omap/lcd_omap3evm.c
delete mode 100644 drivers/video/omap/lcd_overo.c
create mode 100644 drivers/video/omap2/displays/panel-dvi.c
create mode 100644 drivers/video/omap2/displays/panel-n8x0.c
create mode 100644 drivers/video/omap2/displays/panel-picodlp.c
create mode 100644 drivers/video/omap2/displays/panel-picodlp.h
rename drivers/video/omap2/dss/{hdmi_omap4_panel.c => hdmi_panel.c} (79%)
create mode 100644 drivers/video/omap2/dss/ti_hdmi.h
create mode 100644 drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
rename drivers/video/omap2/dss/{hdmi.h => ti_hdmi_4xxx_ip.h} (54%)
delete mode 100644 drivers/video/sh_mobile_meram.h
create mode 100644 drivers/video/smscufx.c
create mode 100644 include/video/omap-panel-dvi.h
create mode 100644 include/video/omap-panel-n8x0.h
create mode 100644 include/video/omap-panel-picodlp.h
^ permalink raw reply
* [PATCH v3.1] Resurrect Intel740 driver: i740fb
From: Ondrej Zary @ 2011-10-28 20:50 UTC (permalink / raw)
To: linux-fbdev
Cc: Florian Tobias Schandinat, Paul Mundt, Kernel development list
Hello,
this is an v3 attempt to resurrect an old (like 2.4.19) out-of-tree driver for
Intel740 graphics cards and modify it for recent kernels. The old driver is
located at: http://sourceforge.net/projects/i740fbdev/files/
It was easier to create a new driver based on skeletonfb, using most of the
low level HW code from the old driver. The DDC code is completely new.
The driver was tested on two 8MB cards: Protac AG240D and Diamond Stealth II
G460.
Changes in v3:
- added suspend/resume support
- fixed x panning
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
---
this time with Makefile patch
--- linux-2.6.39-rc2-orig/drivers/video/Makefile 2011-04-06 03:30:43.000000000 +0200
+++ linux-2.6.39-rc2/drivers/video/Makefile 2011-07-30 11:34:10.000000000 +0200
@@ -36,6 +36,7 @@ obj-$(CONFIG_FB_CYBER2000) += cyb
obj-$(CONFIG_FB_PM2) += pm2fb.o
obj-$(CONFIG_FB_PM3) += pm3fb.o
+obj-$(CONFIG_FB_I740) += i740fb.o
obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/
obj-$(CONFIG_FB_NVIDIA) += nvidia/
--- linux-2.6.39-rc2-orig/drivers/video/Kconfig 2011-04-06 03:30:43.000000000 +0200
+++ linux-2.6.39-rc2/drivers/video/Kconfig 2011-10-24 23:29:42.000000000 +0200
@@ -1117,6 +1117,17 @@ config FB_RIVA_BACKLIGHT
help
Say Y here if you want to control the backlight of your display.
+config FB_I740
+ tristate "Intel740 support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && FB && PCI
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ help
+ This driver supports graphics cards based on Intel740 chip.
+
config FB_I810
tristate "Intel 810/815 support (EXPERIMENTAL)"
depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740fb.c 2011-10-28 20:03:34.000000000 +0200
@@ -0,0 +1,1286 @@
+/*
+ * i740fb - framebuffer driver for Intel740
+ * Copyright (c) 2011 Ondrej Zary
+ *
+ * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru> which was partially based on:
+ * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * i740fb by Patrick LERDA, v0.9
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/console.h>
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "i740_reg.h"
+
+static char *mode_option __devinitdata;
+
+#ifdef CONFIG_MTRR
+static int mtrr __devinitdata = 1;
+#endif
+
+struct i740fb_par {
+ unsigned char __iomem *regs;
+ bool has_sgram;
+#ifdef CONFIG_MTRR
+ int mtrr_reg;
+#endif
+ bool ddc_registered;
+ struct i2c_adapter ddc_adapter;
+ struct i2c_algo_bit_data ddc_algo;
+ u32 pseudo_palette[16];
+ struct mutex open_lock;
+ unsigned int ref_count;
+
+ u8 crtc[VGA_CRT_C];
+ u8 atc[VGA_ATT_C];
+ u8 gdc[VGA_GFX_C];
+ u8 seq[VGA_SEQ_C];
+ u8 misc;
+ u8 vss;
+
+ /* i740 specific registers */
+ u8 display_cntl;
+ u8 pixelpipe_cfg0;
+ u8 pixelpipe_cfg1;
+ u8 pixelpipe_cfg2;
+ u8 video_clk2_m;
+ u8 video_clk2_n;
+ u8 video_clk2_mn_msbs;
+ u8 video_clk2_div_sel;
+ u8 pll_cntl;
+ u8 address_mapping;
+ u8 io_cntl;
+ u8 bitblt_cntl;
+ u8 ext_vert_total;
+ u8 ext_vert_disp_end;
+ u8 ext_vert_sync_start;
+ u8 ext_vert_blank_start;
+ u8 ext_horiz_total;
+ u8 ext_horiz_blank;
+ u8 ext_offset;
+ u8 interlace_cntl;
+ u32 lmi_fifo_watermark;
+ u8 ext_start_addr;
+ u8 ext_start_addr_hi;
+};
+
+#define DACSPEED8 203
+#define DACSPEED16 163
+#define DACSPEED24_SG 136
+#define DACSPEED24_SD 128
+#define DACSPEED32 86
+
+static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
+ .id = "i740fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 8,
+ .ypanstep = 1,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb(struct i740fb_par *par, u16 port)
+{
+ return vga_mm_r(par->regs, port);
+}
+static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
+{
+ vga_mm_w_fast(par->regs, port, reg, val);
+}
+static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
+{
+ vga_mm_w(par->regs, port, reg);
+ return vga_mm_r(par->regs, port+1);
+}
+static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg, u8 val, u8 mask)
+{
+ vga_mm_w_fast(par->regs, port, reg, (val & mask) | (i740inreg(par, port, reg) & ~mask));
+}
+static inline void i740outb_p(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb_p(struct i740fb_par *par, unsigned short port)
+{
+ return vga_mm_r(par->regs, port);
+}
+
+#define REG_DDC_DRIVE 0x62
+#define REG_DDC_STATE 0x63
+#define DDC_SCL (1 << 3)
+#define DDC_SDA (1 << 2)
+
+static void i740fb_ddc_setscl(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SCL);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SCL;
+ else
+ reg &= ~DDC_SCL;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static void i740fb_ddc_setsda(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SDA);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SDA;
+ else
+ reg &= ~DDC_SDA;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static int i740fb_ddc_getscl(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SCL);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
+}
+
+static int i740fb_ddc_getsda(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SDA);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
+}
+
+static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ strlcpy(par->ddc_adapter.name, info->fix.id,
+ sizeof(par->ddc_adapter.name));
+ par->ddc_adapter.owner = THIS_MODULE;
+ par->ddc_adapter.class = I2C_CLASS_DDC;
+ par->ddc_adapter.algo_data = &par->ddc_algo;
+ par->ddc_adapter.dev.parent = info->device;
+ par->ddc_algo.setsda = i740fb_ddc_setsda;
+ par->ddc_algo.setscl = i740fb_ddc_setscl;
+ par->ddc_algo.getsda = i740fb_ddc_getsda;
+ par->ddc_algo.getscl = i740fb_ddc_getscl;
+ par->ddc_algo.udelay = 10;
+ par->ddc_algo.timeout = 20;
+ par->ddc_algo.data = par;
+
+ i2c_set_adapdata(&par->ddc_adapter, par);
+
+ return i2c_bit_add_bus(&par->ddc_adapter);
+}
+
+static int i740fb_open(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ par->ref_count++;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static int i740fb_release(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ return -EINVAL;
+ }
+
+ par->ref_count--;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
+{
+ /*
+ * Would like to calculate these values automatically, but a generic
+ * algorithm does not seem possible. Note: These FIFO water mark
+ * values were tested on several cards and seem to eliminate the
+ * all of the snow and vertical banding, but fine adjustments will
+ * probably be required for other cards.
+ */
+
+ u32 wm = 0x18120000;
+
+ switch (bpp) {
+ case 8:
+ if (freq > 200) wm = 0x18120000;
+ else if (freq > 175) wm = 0x16110000;
+ else if (freq > 135) wm = 0x120E0000;
+ else wm = 0x100D0000;
+ break;
+ case 15:
+ case 16:
+ if (par->has_sgram) {
+ if (freq > 140) wm = 0x2C1D0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24160000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ } else {
+ if (freq > 160) wm = 0x28200000;
+ else if (freq > 140) wm = 0x2A1E0000;
+ else if (freq > 130) wm = 0x2B1A0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24180000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ }
+ break;
+ case 24:
+ if (par->has_sgram) {
+ if (freq > 130) wm = 0x31200000;
+ else if (freq > 120) wm = 0x2E200000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ } else {
+ if (freq > 120) wm = 0x311F0000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ }
+ break;
+ case 32:
+ if (par->has_sgram) {
+ if (freq > 80) wm = 0x2A200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ } else {
+ if (freq > 80) wm = 0x29200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ }
+ break;
+ }
+
+ return wm;
+}
+
+/* clock calculation from i740fb by Patrick LERDA */
+
+#define I740_RFREQ (1e6)
+#define TARGET_MAX_N 30
+
+#define I740_FFIX 8
+#define I740_REF_FREQ (u32) (66.66666666667 * (1 << I740_FFIX) + 0.5)
+#define I740_MAX_VCO_FREQ (u32)(450.00000000000 * (1 << I740_FFIX) + 0.5)
+
+#define I740_CALC_VCLKfix(m, n, p, d) ((((((m) * I740_REF_FREQ * (4 << ((d) << 1)))) / (n)) + ((1 << (p)) / 2)) / (1 << (p)))
+
+static void i740_calc_vclk(u32 freq_hz, struct i740fb_par *par)
+{
+ u32 freq = freq_hz / (u32)(1e6 / I740_RFREQ);
+ const u32 err_max = freq / (u32)(I740_RFREQ / 0.005 / (1 << I740_FFIX) + 0.5);
+ const u32 err_target = freq / (u32)(I740_RFREQ / 0.001 / (1 << I740_FFIX) + 0.5);
+ u32 err_best = (u32)(512.0 * (1 << I740_FFIX));
+ u32 f_err, f_vco;
+ int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
+ int m, n, i;
+
+ /* find log2(MAX_VCO_FREQ/f_target) */
+ for (i = 0; i < 16; i++)
+ if ((I740_MAX_VCO_FREQ) / (1 << i) < freq / (u32)(I740_RFREQ / (1 << I740_FFIX)))
+ break;
+ i--;
+ p_best = i;
+
+ d_best = 0;
+ f_vco = (freq * (1 << p_best)) / (u32)(I740_RFREQ / (1 << I740_FFIX));
+ freq = freq / (u32)(I740_RFREQ / (1 << I740_FFIX));
+
+ n = 2;
+ do {
+ n++;
+ m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
+
+ if (m < 3)
+ m = 3;
+
+ {
+ u32 f_out = I740_CALC_VCLKfix(m, n, p_best, d_best);
+
+ f_err = (freq - f_out);
+
+ if (abs(f_err) < err_max) {
+ m_best = m;
+ n_best = n;
+ err_best = f_err;
+ }
+ }
+ } while ((abs(f_err) >= err_target) &&
+ ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
+
+ if (abs(f_err) < err_target) {
+ m_best = m;
+ n_best = n;
+ }
+
+ par->video_clk2_m = (m_best-2) & 0xFF;
+ par->video_clk2_n = (n_best-2) & 0xFF;
+ par->video_clk2_mn_msbs = ((((n_best-2) >> 4) & VCO_N_MSBS) |
+ (((m_best-2) >> 8) & VCO_M_MSBS));
+ par->video_clk2_div_sel = ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
+}
+
+static int i740fb_decode_var(const struct fb_var_screeninfo *var, struct i740fb_par *par, struct fb_info *info)
+{
+ /*
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ */
+
+ u32 xres, right, hslen, left, xtotal;
+ u32 yres, lower, vslen, upper, ytotal;
+ u32 vxres, xoffset, vyres, yoffset;
+ u32 bpp, base, dacspeed24;
+ u8 r7;
+ int i;
+
+ dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
+ var->xres, var->yres, var->xres_virtual, var->xres_virtual);
+ dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
+ var->xoffset, var->yoffset, var->bits_per_pixel, var->grayscale);
+ dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
+ var->activate, var->nonstd, var->vmode);
+ dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
+ var->pixclock, var->hsync_len, var->vsync_len);
+ dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
+ var->left_margin, var->right_margin, var->upper_margin, var->lower_margin);
+
+
+ bpp = var->bits_per_pixel;
+ switch (bpp) {
+ case 1 ... 8:
+ bpp = 8;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED8) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n", 1000000 / var->pixclock, DACSPEED8);
+ return -EINVAL;
+ }
+ break;
+ case 9 ... 15:
+ bpp = 15;
+ case 16:
+ if ((((u32)1e6) / var->pixclock) > DACSPEED16) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n", 1000000 / var->pixclock, DACSPEED16);
+ return -EINVAL;
+ }
+ break;
+ case 17 ... 24:
+ bpp = 24;
+ dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
+ if ((((u32)1e6) / var->pixclock) > dacspeed24) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n", 1000000 / var->pixclock, dacspeed24);
+ return -EINVAL;
+ }
+ break;
+ case 25 ... 32:
+ bpp = 32;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED32) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n", 1000000 / var->pixclock, DACSPEED32);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ xres = (var->xres + 7) & ~7;
+ vxres = (var->xres_virtual + 0xF) & ~0xF;
+ if (vxres < xres)
+ vxres = xres;
+
+ xoffset = (var->xoffset + 7) & ~7;
+ xoffset = var->xoffset;
+ if (xres + xoffset > vxres)
+ xoffset = vxres - xres;
+
+ left = (var->left_margin + 7) & ~7;
+ right = (var->right_margin + 7) & ~7;
+ hslen = (var->hsync_len + 7) & ~7;
+
+ yres = var->yres;
+ vyres = var->yres_virtual;
+ if (yres > vyres)
+ vyres = yres;
+
+ yoffset = var->yoffset;
+ if (yres + yoffset > vyres)
+ yoffset = vyres - yres;
+
+ lower = var->lower_margin;
+ vslen = var->vsync_len;
+ upper = var->upper_margin;
+
+ if (vxres * vyres * ((bpp + 1) / 8) > info->screen_size || vyres = yres) {
+ vyres = info->screen_size / vxres / ((bpp + 1) / 8);
+ if (vyres < yres)
+ return -ENOMEM;
+ }
+
+ if (yoffset + yres > vyres)
+ yoffset = vyres - yres;
+
+ xtotal = xres + right + hslen + left;
+ ytotal = yres + lower + vslen + upper;
+
+ par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
+ par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
+ par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
+ par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
+ par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
+ | ((((xres + right + hslen) >> 3) & 0x20) << 2);
+ par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F) | 0x80;
+
+ par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
+
+ r7 = 0x10; /* disable linecompare */
+ if (ytotal & 0x100)
+ r7 |= 0x01;
+ if (ytotal & 0x200)
+ r7 |= 0x20;
+
+ par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+ par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
+ if (var->vmode & FB_VMODE_DOUBLE)
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+ par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
+ par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
+ if ((yres-1) & 0x100)
+ r7 |= 0x02;
+ if ((yres-1) & 0x200)
+ r7 |= 0x40;
+
+ par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
+ par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
+ if ((yres + lower - 1) & 0x100)
+ r7 |= 0x0C;
+ if ((yres + lower - 1) & 0x200) {
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
+ r7 |= 0x80;
+ }
+
+ par->crtc[VGA_CRTC_V_SYNC_END] = ((yres + lower - 1 + vslen) & 0x0F) & ~0x10; /* disabled IRQ */
+ par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF; /* 0x7F for original VGA, but some SVGA chips requires all 8 bits to set */
+
+ par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
+ par->crtc[VGA_CRTC_MODE] = 0xC3 ;
+ par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+ par->crtc[VGA_CRTC_OVERFLOW] = r7;
+
+ par->vss = 0x00; /* 3DA */
+
+ for (i = 0x00; i < 0x10; i++)
+ par->atc[i] = i;
+ par->atc[VGA_ATC_MODE] = 0x81;
+ par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
+ par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+ /*par->atc[VGA_ATC_PEL] = xoffset & 7;*/
+ par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
+
+ par->misc = 0xC3;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ par->misc &= ~0x40;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ par->misc &= ~0x80;
+
+ par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
+ par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+ par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+ par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+
+ par->gdc[VGA_GFX_SR_VALUE] = 0x00;
+ par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
+ par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+ par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
+ par->gdc[VGA_GFX_PLANE_READ] = 0;
+ par->gdc[VGA_GFX_MODE] = 0x02;
+ par->gdc[VGA_GFX_MISC] = 0x05;
+ par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+ par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
+
+ base = (yoffset * vxres + (xoffset & ~7)) >> 2;
+ switch (bpp) {
+ case 8:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
+ par->ext_offset = vxres >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
+ par->bitblt_cntl = COLEXP_8BPP;
+ break;
+ case 15: /* 0rrrrrgg gggbbbbb */
+ case 16: /* rrrrrggg gggbbbbb */
+ par->pixelpipe_cfg1 = (var->green.length = 6) ? DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
+ par->ext_offset = vxres >> 10;
+ par->bitblt_cntl = COLEXP_16BPP;
+ base *= 2;
+ break;
+ case 24:
+ par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
+ par->ext_offset = (vxres * 3) >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
+ par->bitblt_cntl = COLEXP_24BPP;
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+ par->ext_offset = vxres >> 9;
+ par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
+ par->bitblt_cntl = COLEXP_RESERVED; /* Not implemented on i740 */
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+
+ par->pixelpipe_cfg0 = DAC_8_BIT;
+
+ par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
+ par->io_cntl = EXTENDED_CRTC_CNTL;
+ par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
+ par->display_cntl = HIRES_MODE;
+
+ /* Set the MCLK freq */
+ par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
+
+ /* Calculate the extended CRTC regs */
+ par->ext_vert_total = (ytotal - 2) >> 8;
+ par->ext_vert_disp_end = (yres - 1) >> 8;
+ par->ext_vert_sync_start = (yres + lower) >> 8;
+ par->ext_vert_blank_start = (yres + lower) >> 8;
+ par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
+ par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
+
+ par->interlace_cntl = INTERLACE_DISABLE;
+
+ /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode.) */
+ par->atc[VGA_ATC_OVERSCAN] = 0;
+
+ /* Calculate VCLK that most closely matches the requested dot clock */
+ i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ par->misc |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ par->lmi_fifo_watermark = i740_calc_fifo(par, ((int)1e6) / var->pixclock, bpp);
+
+ /*if (!fbmon_valid_timings(var->pixclock, ytotal, xtotal, info))
+ return -EINVAL;*/
+
+ return 0;
+}
+
+static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 16:
+ switch (var->green.length) {
+ default:
+ case 5:
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 5;
+ break;
+ case 6:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->green.length = 6;
+ var->red.length = var->blue.length = 5;
+ break;
+ }
+ break;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 32:
+ var->transp.offset = 24;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->transp.length = var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (info->monspecs.hfmax && info->monspecs.vfmax &&
+ info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void vga_protect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) | 0x20); /* disable the display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
+}
+
+static void vga_unprotect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) & 0xDF); /* reenable display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
+}
+
+static int i740fb_set_par(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 itemp;
+ int i;
+
+ i = i740fb_decode_var(&info->var, par, info);
+ if (i)
+ return i;
+
+ memset(info->screen_base, 0, info->screen_size);
+
+ vga_protect(par);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
+
+ mdelay(1);
+
+ i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
+ i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
+ i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
+ i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
+
+ i740inb(par, 0x3DA);
+ i740outb(par, 0x3C0, 0x00);
+
+ /* update misc output register */
+ i740outb(par, VGA_MIS_W, par->misc | 0x01);
+
+ /* synchronous reset on */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
+ /* write sequencer registers */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+ for (i = 2; i < VGA_SEQ_C; i++)
+ i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
+
+ /* synchronous reset off */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
+
+ /* deprotect CRT registers 0-7 */
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
+
+ /* write CRT registers */
+ for (i = 0; i < VGA_CRT_C; i++)
+ i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
+
+ /* write graphics controller registers */
+ for (i = 0; i < VGA_GFX_C; i++)
+ i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
+
+ /* write attribute controller registers */
+ for (i = 0; i < VGA_ATT_C; i++) {
+ i740inb_p(par, VGA_IS1_RC); /* reset flip-flop */
+ i740outb_p(par, VGA_ATT_IW, i);
+ i740outb_p(par, VGA_ATT_IW, par->atc[i]);
+ }
+
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE]);
+
+ i740inb(par, VGA_IS1_RC);
+ i740outb(par, VGA_ATT_IW, 0x20);
+
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START, par->ext_vert_sync_start);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START, par->ext_vert_blank_start);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
+ i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
+
+ i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL, par->interlace_cntl, INTERLACE_ENABLE);
+ i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
+ i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
+ i740outreg_mask(par, XRX, DISPLAY_CNTL, par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
+
+ i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1, par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
+
+ itemp = readl(par->regs + FWATER_BLC);
+ itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
+ itemp |= par->lmi_fifo_watermark;
+ writel(itemp, par->regs + FWATER_BLC);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
+
+ i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
+ i740outreg_mask(par, XRX, IO_CTNL, par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+
+ if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
+ i740outb(par, VGA_PEL_MSK, 0xFF);
+ i740outb(par, VGA_PEL_IW, 0x00);
+ for (i = 0; i < 256; i++) {
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ }
+ }
+
+ /* Wait for screen to stabilize. */
+ mdelay(50);
+ vga_unprotect(par);
+
+ info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
+ if (info->var.bits_per_pixel = 8)
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ return 0;
+}
+
+static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n", regno, red, green, blue, transp, info->var.bits_per_pixel);
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ if (regno >= 256)
+ return 1;
+ i740outb(info->par, VGA_PEL_IW, regno);
+ i740outb(info->par, VGA_PEL_D, red >> 8);
+ i740outb(info->par, VGA_PEL_D, green >> 8);
+ i740outb(info->par, VGA_PEL_D, blue >> 8);
+ break;
+ case 15:
+ case 16:
+ if (regno >= 16)
+ return 0;
+ if (info->var.green.length = 5)
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+ else if (info->var.green.length = 6)
+ ((u32 *)info->pseudo_palette)[regno] = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+ else
+ return -EINVAL;
+ break;
+ case 24:
+ case 32:
+ if (regno >= 16)
+ return 0;
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int i740fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 base = (var->yoffset * var->xres_virtual + (var->xoffset & ~7)) >> 2;
+
+ dev_dbg(info->device, "pan_display: xoffset: %i, yoffset: %i base: %i\n", var->xoffset, var->yoffset, base);
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ break;
+ case 15:
+ case 16:
+ base *= 2;
+ break;
+ case 24:
+ /*
+ * The last bit does not seem to have any effect on the start
+ * address register in 24bpp mode, so...
+ */
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ /*par->atc[VGA_ATC_PEL] = var->xoffset & 7;*/
+
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI, (base & 0x0000FF00) >> 8);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, (base & 0x3FC00000) >> 22);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
+ /*i740outreg(par, VGA_ATT_W, VGA_ATC_PEL, var->xoffset & 7);*/
+
+ return 0;
+}
+
+static int i740fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ unsigned char SEQ01;
+ int DPMSSyncSelect;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case FB_BLANK_POWERDOWN:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Turn the screen on/off */
+ i740outb(par, SRX, 0x01);
+ SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
+ i740outb(par, SRX, 0x01);
+ i740outb(par, SRX + 1, SEQ01);
+
+ /* Set the DPMS mode */
+ i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
+
+ /* Let fbcon do a soft blank for us */
+ return (blank_mode = FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops i740fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = i740fb_open,
+ .fb_release = i740fb_release,
+ .fb_check_var = i740fb_check_var,
+ .fb_set_par = i740fb_set_par,
+ .fb_setcolreg = i740fb_setcolreg,
+ .fb_blank = i740fb_blank,
+ .fb_pan_display = i740fb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit i740fb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct fb_info *info;
+ struct i740fb_par *par;
+ int ret;
+ bool found = false;
+ u8 *edid;
+
+ info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
+ if (!info) {
+ dev_err(&(dev->dev), "cannot allocate framebuffer\n");
+ return -ENOMEM;
+ }
+
+ par = info->par;
+ mutex_init(&par->open_lock);
+
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.bits_per_pixel = 8;
+ info->fbops = &i740fb_ops;
+ info->pseudo_palette = par->pseudo_palette;
+
+ ret = pci_enable_device(dev);
+ if (ret) {
+ dev_err(info->device, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
+
+ ret = pci_request_regions(dev, info->fix.id);
+ if (ret) {
+ dev_err(info->device, "error requesting regions\n");
+ goto err_request_regions;
+ }
+
+ info->screen_base = pci_ioremap_bar(dev, 0);
+ if (!info->screen_base) {
+ dev_err(info->device, "error remapping base\n");
+ ret = -ENOMEM;
+ goto err_ioremap_1;
+ }
+
+ par->regs = pci_ioremap_bar(dev, 1);
+ if (!par->regs) {
+ dev_err(info->device, "error remapping MMIO\n");
+ ret = -ENOMEM;
+ goto err_ioremap_2;
+ }
+
+ /* detect memory size */
+ if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1) = DRAM_ROW_1_SDRAM)
+ i740outb(par, XRX, DRAM_ROW_BNDRY_1);
+ else
+ i740outb(par, XRX, DRAM_ROW_BNDRY_0);
+ info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
+ /* detect memory type */
+ par->has_sgram = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
+ par->has_sgram = !((par->has_sgram & DRAM_RAS_TIMING) ||
+ (par->has_sgram & DRAM_RAS_PRECHARGE));
+
+ printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
+ pci_name(dev), info->screen_size >> 10,
+ par->has_sgram ? "SGRAM" : "SDRAM");
+
+ info->fix = i740fb_fix;
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ info->fix.mmio_len = pci_resource_len(dev, 1);
+ info->fix.smem_start = pci_resource_start(dev, 0);
+ info->fix.smem_len = info->screen_size;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ if (i740fb_setup_ddc_bus(info) = 0) {
+ par->ddc_registered = true;
+ edid = fb_ddc_read(&par->ddc_adapter);
+ if (edid) {
+ fb_edid_to_monspecs(edid, &info->monspecs);
+ kfree(edid);
+ if (!info->monspecs.modedb)
+ dev_err(info->device, "error getting mode database\n");
+ else {
+ const struct fb_videomode *m;
+
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ &info->modelist);
+ m = fb_find_best_display(&info->monspecs, &info->modelist);
+ if (m) {
+ fb_videomode_to_var(&info->var, m);
+ /* fill all other info->var's fields */
+ if (i740fb_check_var(&info->var, info) = 0)
+ found = true;
+ }
+ }
+ }
+ }
+
+ if (!mode_option && !found)
+ mode_option = "640x480-8@60";
+
+ if (mode_option) {
+ ret = fb_find_mode(&info->var, info, mode_option,
+ info->monspecs.modedb, info->monspecs.modedb_len,
+ NULL, info->var.bits_per_pixel);
+ if (!ret || ret = 4) {
+ dev_err(info->device, "mode %s not found\n", mode_option);
+ ret = -EINVAL;
+ }
+ }
+
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
+ /* maximize virtual vertical size for fast scrolling */
+ info->var.yres_virtual = info->fix.smem_len * 8 /
+ (info->var.bits_per_pixel * info->var.xres_virtual);
+
+ if (ret = -EINVAL)
+ goto err_find_mode;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ dev_err(info->device, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
+ }
+
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(info->device, "error registering framebuffer\n");
+ goto err_reg_framebuffer;
+ }
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ pci_set_drvdata(dev, info);
+#ifdef CONFIG_MTRR
+ if (mtrr) {
+ par->mtrr_reg = -1;
+ par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+ }
+#endif
+ return 0;
+
+err_reg_framebuffer:
+ fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+err_ioremap_2:
+ pci_iounmap(dev, info->screen_base);
+err_ioremap_1:
+ pci_release_regions(dev);
+err_request_regions:
+/* pci_disable_device(dev); */
+err_enable_device:
+ framebuffer_release(info);
+ return ret;
+}
+
+static void __devexit i740fb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ if (info) {
+#ifdef CONFIG_MTRR
+ struct i740fb_par *par = info->par;
+
+ if (par->mtrr_reg >= 0) {
+ mtrr_del(par->mtrr_reg, 0, 0);
+ par->mtrr_reg = -1;
+ }
+#endif
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+ pci_iounmap(dev, info->screen_base);
+ pci_release_regions(dev);
+/* pci_disable_device(dev); */
+ pci_set_drvdata(dev, NULL);
+ framebuffer_release(info);
+ }
+}
+
+#ifdef CONFIG_PM
+static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ /* don't disable console during hibernation and wakeup from it */
+ if (state.event = PM_EVENT_FREEZE || state.event = PM_EVENT_PRETHAW)
+ return 0;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ /* do nothing if framebuffer is not active */
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+ }
+
+ fb_set_suspend(info, 1);
+
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+
+ return 0;
+}
+
+static int i740fb_resume(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ if (par->ref_count = 0)
+ goto fail;
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+ if (pci_enable_device(dev))
+ goto fail;
+
+ i740fb_set_par(info);
+ fb_set_suspend(info, 0);
+
+fail:
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+}
+#else
+#define i740fb_suspend NULL
+#define i740fb_resume NULL
+#endif /* CONFIG_PM */
+
+#define I740_ID_PCI 0x00d1
+#define I740_ID_AGP 0x7800
+
+static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, i740fb_id_table);
+
+static struct pci_driver i740fb_driver = {
+ .name = "i740fb",
+ .id_table = i740fb_id_table,
+ .probe = i740fb_probe,
+ .remove = __devexit_p(i740fb_remove),
+ .suspend = i740fb_suspend,
+ .resume = i740fb_resume,
+};
+
+#ifndef MODULE
+static int __init i740fb_setup(char *options)
+{
+ char *opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+#ifdef CONFIG_MTRR
+ else if (!strncmp(opt, "mtrr:", 5))
+ mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+ else
+ mode_option = opt;
+ }
+
+ return 0;
+}
+#endif
+
+int __init i740fb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("i740fb", &option))
+ return -ENODEV;
+ i740fb_setup(option);
+#endif
+
+ return pci_register_driver(&i740fb_driver);
+}
+
+static void __exit i740fb_exit(void)
+{
+ pci_unregister_driver(&i740fb_driver);
+}
+
+module_init(i740fb_init);
+module_exit(i740fb_exit);
+
+MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for Intel740");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740_reg.h 2011-08-14 23:47:48.000000000 +0200
@@ -0,0 +1,309 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ */
+
+/* I/O register offsets */
+#define SRX VGA_SEQ_I
+#define GRX VGA_GFX_I
+#define ARX VGA_ATT_IW
+#define XRX 0x3D6
+#define MRX 0x3D2
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6
+#define DACSTATE 0x3C7
+#define DACRX 0x3C7
+#define DACWX 0x3C8
+#define DACDATA 0x3C9
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C
+#define START_ADDR_LO 0x0D
+#define VERT_SYNC_END 0x11
+#define EXT_VERT_TOTAL 0x30
+#define EXT_VERT_DISPLAY 0x31
+#define EXT_VERT_SYNC_START 0x32
+#define EXT_VERT_BLANK_START 0x33
+#define EXT_HORIZ_TOTAL 0x35
+#define EXT_HORIZ_BLANK 0x39
+#define EXT_START_ADDR 0x40
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41
+#define EXT_START_ADDR_HI 0x42
+#define INTERLACE_CNTL 0x70
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register */
+#define MSR_R 0x3CC
+#define MSR_W 0x3C2
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0
+#define CGA_BASE 0x3D0
+
+/* System Configuration Extension Registers (XRX) */
+#define IO_CTNL 0x09
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+#define ADDRESS_MAPPING 0x0A
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define BITBLT_CNTL 0x20
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define CHIP_RESET 0x02
+#define BITBLT_STATUS 0x01
+
+#define DISPLAY_CNTL 0x40
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+#define DRAM_ROW_TYPE 0x50
+#define DRAM_ROW_0 0x07
+#define DRAM_ROW_0_SDRAM 0x00
+#define DRAM_ROW_0_EMPTY 0x07
+#define DRAM_ROW_1 0x38
+#define DRAM_ROW_1_SDRAM 0x00
+#define DRAM_ROW_1_EMPTY 0x38
+#define DRAM_ROW_CNTL_LO 0x51
+#define DRAM_CAS_LATENCY 0x10
+#define DRAM_RAS_TIMING 0x08
+#define DRAM_RAS_PRECHARGE 0x04
+#define DRAM_ROW_CNTL_HI 0x52
+#define DRAM_EXT_CNTL 0x53
+#define DRAM_REFRESH_RATE 0x03
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x01
+#define DRAM_REFRESH_FAST_TEST 0x02
+#define DRAM_REFRESH_RESERVED 0x03
+#define DRAM_TIMING 0x54
+#define DRAM_ROW_BNDRY_0 0x55
+#define DRAM_ROW_BNDRY_1 0x56
+
+#define DPMS_SYNC_SELECT 0x61
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+#define PIXPIPE_CONFIG_0 0x80
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+#define PIXPIPE_CONFIG_1 0x81
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+#define PIXPIPE_CONFIG_2 0x82
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+#define CURSOR_CONTROL 0xA0
+#define CURSOR_ORIGIN_SCREEN 0x00
+#define CURSOR_ORIGIN_DISPLAY 0x10
+#define CURSOR_MODE 0x07
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01
+#define CURSOR_MODE_128_2C 0x02
+#define CURSOR_MODE_128_1C 0x03
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_RESERVED 0x07
+#define CURSOR_BASEADDR_LO 0xA2
+#define CURSOR_BASEADDR_HI 0xA3
+#define CURSOR_X_LO 0xA4
+#define CURSOR_X_HI 0xA5
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0xA6
+#define CURSOR_Y_HI 0xA7
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define VCLK2_VCO_M 0xC8
+#define VCLK2_VCO_N 0xC9
+#define VCLK2_VCO_MN_MSBS 0xCA
+#define VCO_N_MSBS 0x30
+#define VCO_M_MSBS 0x03
+#define VCLK2_VCO_DIV_SEL 0xCB
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+#define REF_CLK_DIV_BY_5 0x02
+#define REF_DIV_4 0x00
+#define REF_DIV_1 0x01
+
+#define PLL_CNTL 0xCE
+#define PLL_MEMCLK_SEL 0x03
+#define PLL_MEMCLK__66667KHZ 0x00
+#define PLL_MEMCLK__75000KHZ 0x01
+#define PLL_MEMCLK__88889KHZ 0x02
+#define PLL_MEMCLK_100000KHZ 0x03
+
+/* Multimedia Extension Registers (MRX) */
+#define ACQ_CNTL_1 0x02
+#define ACQ_CNTL_2 0x03
+#define FRAME_CAP_MODE 0x01
+#define CONT_CAP_MODE 0x00
+#define SINGLE_CAP_MODE 0x01
+#define ACQ_CNTL_3 0x04
+#define COL_KEY_CNTL_1 0x3C
+#define BLANK_DISP_OVERLAY 0x20
+
+/* FIFOs */
+#define LP_FIFO 0x1000
+#define HP_FIFO 0x2000
+#define INSTPNT 0x3040
+#define LP_FIFO_COUNT 0x3040
+#define HP_FIFO_COUNT 0x3041
+
+/* FIFO Commands */
+#define CLIENT 0xE0000000
+#define CLIENT_2D 0x60000000
+
+/* Command Parser Mode Register */
+#define COMPARS 0x3038
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+/* Interrupt Control Registers */
+#define IER 0x3030
+#define IIR 0x3032
+#define IMR 0x3034
+#define ISR 0x3036
+#define VMIINTB_EVENT 0x2000
+#define GPIO4_INT 0x1000
+#define DISP_FLIP_EVENT 0x0800
+#define DVD_PORT_DMA 0x0400
+#define DISP_VBLANK 0x0200
+#define FIFO_EMPTY_DMA_DONE 0x0100
+#define INST_PARSER_ERROR 0x0080
+#define USER_DEFINED 0x0040
+#define BREAKPOINT 0x0020
+#define DISP_HORIZ_COUNT 0x0010
+#define DISP_VSYNC 0x0008
+#define CAPTURE_HORIZ_COUNT 0x0004
+#define CAPTURE_VSYNC 0x0002
+#define THREE_D_PIPE_FLUSHED 0x0001
+
+/* FIFO Watermark and Burst Length Control Register */
+#define FWATER_BLC 0x00006000
+#define LMI_BURST_LENGTH 0x7F000000
+#define LMI_FIFO_WATERMARK 0x003F0000
+#define AGP_BURST_LENGTH 0x00007F00
+#define AGP_FIFO_WATERMARK 0x0000003F
+
+/* BitBLT Registers */
+#define SRC_DST_PITCH 0x00040000
+#define DST_PITCH 0x1FFF0000
+#define SRC_PITCH 0x00001FFF
+#define COLEXP_BG_COLOR 0x00040004
+#define COLEXP_FG_COLOR 0x00040008
+#define MONO_SRC_CNTL 0x0004000C
+#define MONO_USE_COLEXP 0x00000000
+#define MONO_USE_SRCEXP 0x08000000
+#define MONO_DATA_ALIGN 0x07000000
+#define MONO_BIT_ALIGN 0x01000000
+#define MONO_BYTE_ALIGN 0x02000000
+#define MONO_WORD_ALIGN 0x03000000
+#define MONO_DWORD_ALIGN 0x04000000
+#define MONO_QWORD_ALIGN 0x05000000
+#define MONO_SRC_INIT_DSCRD 0x003F0000
+#define MONO_SRC_RIGHT_CLIP 0x00003F00
+#define MONO_SRC_LEFT_CLIP 0x0000003F
+#define BITBLT_CONTROL 0x00040010
+#define BLTR_STATUS 0x80000000
+#define DYN_DEPTH 0x03000000
+#define DYN_DEPTH_8BPP 0x00000000
+#define DYN_DEPTH_16BPP 0x01000000
+#define DYN_DEPTH_24BPP 0x02000000
+#define DYN_DEPTH_32BPP 0x03000000 /* Not implemented on the i740 */
+#define DYN_DEPTH_ENABLE 0x00800000
+#define PAT_VERT_ALIGN 0x00700000
+#define SOLID_PAT_SELECT 0x00080000
+#define PAT_IS_IN_COLOR 0x00000000
+#define PAT_IS_MONO 0x00040000
+#define MONO_PAT_TRANSP 0x00020000
+#define COLOR_TRANSP_ROP 0x00000000
+#define COLOR_TRANSP_DST 0x00008000
+#define COLOR_TRANSP_EQ 0x00000000
+#define COLOR_TRANSP_NOT_EQ 0x00010000
+#define COLOR_TRANSP_ENABLE 0x00004000
+#define MONO_SRC_TRANSP 0x00002000
+#define SRC_IS_IN_COLOR 0x00000000
+#define SRC_IS_MONO 0x00001000
+#define SRC_USE_SRC_ADDR 0x00000000
+#define SRC_USE_BLTDATA 0x00000400
+#define BLT_TOP_TO_BOT 0x00000000
+#define BLT_BOT_TO_TOP 0x00000200
+#define BLT_LEFT_TO_RIGHT 0x00000000
+#define BLT_RIGHT_TO_LEFT 0x00000100
+#define BLT_ROP 0x000000FF
+#define BLT_PAT_ADDR 0x00040014
+#define BLT_SRC_ADDR 0x00040018
+#define BLT_DST_ADDR 0x0004001C
+#define BLT_DST_H_W 0x00040020
+#define BLT_DST_HEIGHT 0x1FFF0000
+#define BLT_DST_WIDTH 0x00001FFF
+#define SRCEXP_BG_COLOR 0x00040024
+#define SRCEXP_FG_COLOR 0x00040028
+#define BLTDATA 0x00050000
--
Ondrej Zary
^ permalink raw reply
* [PATCH v3] Resurrect Intel740 driver: i740fb
From: Ondrej Zary @ 2011-10-28 18:43 UTC (permalink / raw)
To: linux-fbdev
Cc: Florian Tobias Schandinat, Paul Mundt, Kernel development list
Hello,
this is an v3 attempt to resurrect an old (like 2.4.19) out-of-tree driver for
Intel740 graphics cards and modify it for recent kernels. The old driver is
located at: http://sourceforge.net/projects/i740fbdev/files/
It was easier to create a new driver based on skeletonfb, using most of the
low level HW code from the old driver. The DDC code is completely new.
The driver was tested on two 8MB cards: Protac AG240D and Diamond Stealth II
G460.
Changes in v3:
- added suspend/resume support
- fixed x panning
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
--- linux-2.6.39-rc2-orig/drivers/video/Kconfig 2011-04-06 03:30:43.000000000 +0200
+++ linux-2.6.39-rc2/drivers/video/Kconfig 2011-10-24 23:29:42.000000000 +0200
@@ -1117,6 +1117,17 @@ config FB_RIVA_BACKLIGHT
help
Say Y here if you want to control the backlight of your display.
+config FB_I740
+ tristate "Intel740 support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && FB && PCI
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select VGASTATE
+ help
+ This driver supports graphics cards based on Intel740 chip.
+
config FB_I810
tristate "Intel 810/815 support (EXPERIMENTAL)"
depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740fb.c 2011-10-28 20:03:34.000000000 +0200
@@ -0,0 +1,1286 @@
+/*
+ * i740fb - framebuffer driver for Intel740
+ * Copyright (c) 2011 Ondrej Zary
+ *
+ * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru> which was partially based on:
+ * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * i740fb by Patrick LERDA, v0.9
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/console.h>
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "i740_reg.h"
+
+static char *mode_option __devinitdata;
+
+#ifdef CONFIG_MTRR
+static int mtrr __devinitdata = 1;
+#endif
+
+struct i740fb_par {
+ unsigned char __iomem *regs;
+ bool has_sgram;
+#ifdef CONFIG_MTRR
+ int mtrr_reg;
+#endif
+ bool ddc_registered;
+ struct i2c_adapter ddc_adapter;
+ struct i2c_algo_bit_data ddc_algo;
+ u32 pseudo_palette[16];
+ struct mutex open_lock;
+ unsigned int ref_count;
+
+ u8 crtc[VGA_CRT_C];
+ u8 atc[VGA_ATT_C];
+ u8 gdc[VGA_GFX_C];
+ u8 seq[VGA_SEQ_C];
+ u8 misc;
+ u8 vss;
+
+ /* i740 specific registers */
+ u8 display_cntl;
+ u8 pixelpipe_cfg0;
+ u8 pixelpipe_cfg1;
+ u8 pixelpipe_cfg2;
+ u8 video_clk2_m;
+ u8 video_clk2_n;
+ u8 video_clk2_mn_msbs;
+ u8 video_clk2_div_sel;
+ u8 pll_cntl;
+ u8 address_mapping;
+ u8 io_cntl;
+ u8 bitblt_cntl;
+ u8 ext_vert_total;
+ u8 ext_vert_disp_end;
+ u8 ext_vert_sync_start;
+ u8 ext_vert_blank_start;
+ u8 ext_horiz_total;
+ u8 ext_horiz_blank;
+ u8 ext_offset;
+ u8 interlace_cntl;
+ u32 lmi_fifo_watermark;
+ u8 ext_start_addr;
+ u8 ext_start_addr_hi;
+};
+
+#define DACSPEED8 203
+#define DACSPEED16 163
+#define DACSPEED24_SG 136
+#define DACSPEED24_SD 128
+#define DACSPEED32 86
+
+static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
+ .id = "i740fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 8,
+ .ypanstep = 1,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb(struct i740fb_par *par, u16 port)
+{
+ return vga_mm_r(par->regs, port);
+}
+static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
+{
+ vga_mm_w_fast(par->regs, port, reg, val);
+}
+static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
+{
+ vga_mm_w(par->regs, port, reg);
+ return vga_mm_r(par->regs, port+1);
+}
+static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg, u8 val, u8 mask)
+{
+ vga_mm_w_fast(par->regs, port, reg, (val & mask) | (i740inreg(par, port, reg) & ~mask));
+}
+static inline void i740outb_p(struct i740fb_par *par, u16 port, u8 val)
+{
+ vga_mm_w(par->regs, port, val);
+}
+static inline u8 i740inb_p(struct i740fb_par *par, unsigned short port)
+{
+ return vga_mm_r(par->regs, port);
+}
+
+#define REG_DDC_DRIVE 0x62
+#define REG_DDC_STATE 0x63
+#define DDC_SCL (1 << 3)
+#define DDC_SDA (1 << 2)
+
+static void i740fb_ddc_setscl(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SCL);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SCL;
+ else
+ reg &= ~DDC_SCL;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static void i740fb_ddc_setsda(void *data, int val)
+{
+ struct i740fb_par *par = data;
+ unsigned char reg;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) | DDC_SDA);
+
+ reg = i740inreg(par, XRX, REG_DDC_STATE);
+ if (val)
+ reg |= DDC_SDA;
+ else
+ reg &= ~DDC_SDA;
+ i740outreg(par, XRX, REG_DDC_STATE, reg);
+}
+
+static int i740fb_ddc_getscl(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SCL);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
+}
+
+static int i740fb_ddc_getsda(void *data)
+{
+ struct i740fb_par *par = data;
+
+ i740outreg(par, XRX, REG_DDC_DRIVE,
+ i740inreg(par, XRX, REG_DDC_DRIVE) & ~DDC_SDA);
+
+ return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
+}
+
+static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ strlcpy(par->ddc_adapter.name, info->fix.id,
+ sizeof(par->ddc_adapter.name));
+ par->ddc_adapter.owner = THIS_MODULE;
+ par->ddc_adapter.class = I2C_CLASS_DDC;
+ par->ddc_adapter.algo_data = &par->ddc_algo;
+ par->ddc_adapter.dev.parent = info->device;
+ par->ddc_algo.setsda = i740fb_ddc_setsda;
+ par->ddc_algo.setscl = i740fb_ddc_setscl;
+ par->ddc_algo.getsda = i740fb_ddc_getsda;
+ par->ddc_algo.getscl = i740fb_ddc_getscl;
+ par->ddc_algo.udelay = 10;
+ par->ddc_algo.timeout = 20;
+ par->ddc_algo.data = par;
+
+ i2c_set_adapdata(&par->ddc_adapter, par);
+
+ return i2c_bit_add_bus(&par->ddc_adapter);
+}
+
+static int i740fb_open(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ par->ref_count++;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static int i740fb_release(struct fb_info *info, int user)
+{
+ struct i740fb_par *par = info->par;
+
+ mutex_lock(&(par->open_lock));
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ return -EINVAL;
+ }
+
+ par->ref_count--;
+ mutex_unlock(&(par->open_lock));
+
+ return 0;
+}
+
+static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
+{
+ /*
+ * Would like to calculate these values automatically, but a generic
+ * algorithm does not seem possible. Note: These FIFO water mark
+ * values were tested on several cards and seem to eliminate the
+ * all of the snow and vertical banding, but fine adjustments will
+ * probably be required for other cards.
+ */
+
+ u32 wm = 0x18120000;
+
+ switch (bpp) {
+ case 8:
+ if (freq > 200) wm = 0x18120000;
+ else if (freq > 175) wm = 0x16110000;
+ else if (freq > 135) wm = 0x120E0000;
+ else wm = 0x100D0000;
+ break;
+ case 15:
+ case 16:
+ if (par->has_sgram) {
+ if (freq > 140) wm = 0x2C1D0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24160000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ } else {
+ if (freq > 160) wm = 0x28200000;
+ else if (freq > 140) wm = 0x2A1E0000;
+ else if (freq > 130) wm = 0x2B1A0000;
+ else if (freq > 120) wm = 0x2C180000;
+ else if (freq > 100) wm = 0x24180000;
+ else if (freq > 90) wm = 0x18120000;
+ else if (freq > 50) wm = 0x16110000;
+ else if (freq > 32) wm = 0x13100000;
+ else wm = 0x120E0000;
+ }
+ break;
+ case 24:
+ if (par->has_sgram) {
+ if (freq > 130) wm = 0x31200000;
+ else if (freq > 120) wm = 0x2E200000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ } else {
+ if (freq > 120) wm = 0x311F0000;
+ else if (freq > 100) wm = 0x2C1D0000;
+ else if (freq > 80) wm = 0x25180000;
+ else if (freq > 64) wm = 0x24160000;
+ else if (freq > 49) wm = 0x18120000;
+ else if (freq > 32) wm = 0x16110000;
+ else wm = 0x13100000;
+ }
+ break;
+ case 32:
+ if (par->has_sgram) {
+ if (freq > 80) wm = 0x2A200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ } else {
+ if (freq > 80) wm = 0x29200000;
+ else if (freq > 60) wm = 0x281A0000;
+ else if (freq > 49) wm = 0x25180000;
+ else if (freq > 32) wm = 0x18120000;
+ else wm = 0x16110000;
+ }
+ break;
+ }
+
+ return wm;
+}
+
+/* clock calculation from i740fb by Patrick LERDA */
+
+#define I740_RFREQ (1e6)
+#define TARGET_MAX_N 30
+
+#define I740_FFIX 8
+#define I740_REF_FREQ (u32) (66.66666666667 * (1 << I740_FFIX) + 0.5)
+#define I740_MAX_VCO_FREQ (u32)(450.00000000000 * (1 << I740_FFIX) + 0.5)
+
+#define I740_CALC_VCLKfix(m, n, p, d) ((((((m) * I740_REF_FREQ * (4 << ((d) << 1)))) / (n)) + ((1 << (p)) / 2)) / (1 << (p)))
+
+static void i740_calc_vclk(u32 freq_hz, struct i740fb_par *par)
+{
+ u32 freq = freq_hz / (u32)(1e6 / I740_RFREQ);
+ const u32 err_max = freq / (u32)(I740_RFREQ / 0.005 / (1 << I740_FFIX) + 0.5);
+ const u32 err_target = freq / (u32)(I740_RFREQ / 0.001 / (1 << I740_FFIX) + 0.5);
+ u32 err_best = (u32)(512.0 * (1 << I740_FFIX));
+ u32 f_err, f_vco;
+ int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
+ int m, n, i;
+
+ /* find log2(MAX_VCO_FREQ/f_target) */
+ for (i = 0; i < 16; i++)
+ if ((I740_MAX_VCO_FREQ) / (1 << i) < freq / (u32)(I740_RFREQ / (1 << I740_FFIX)))
+ break;
+ i--;
+ p_best = i;
+
+ d_best = 0;
+ f_vco = (freq * (1 << p_best)) / (u32)(I740_RFREQ / (1 << I740_FFIX));
+ freq = freq / (u32)(I740_RFREQ / (1 << I740_FFIX));
+
+ n = 2;
+ do {
+ n++;
+ m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
+
+ if (m < 3)
+ m = 3;
+
+ {
+ u32 f_out = I740_CALC_VCLKfix(m, n, p_best, d_best);
+
+ f_err = (freq - f_out);
+
+ if (abs(f_err) < err_max) {
+ m_best = m;
+ n_best = n;
+ err_best = f_err;
+ }
+ }
+ } while ((abs(f_err) >= err_target) &&
+ ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
+
+ if (abs(f_err) < err_target) {
+ m_best = m;
+ n_best = n;
+ }
+
+ par->video_clk2_m = (m_best-2) & 0xFF;
+ par->video_clk2_n = (n_best-2) & 0xFF;
+ par->video_clk2_mn_msbs = ((((n_best-2) >> 4) & VCO_N_MSBS) |
+ (((m_best-2) >> 8) & VCO_M_MSBS));
+ par->video_clk2_div_sel = ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
+}
+
+static int i740fb_decode_var(const struct fb_var_screeninfo *var, struct i740fb_par *par, struct fb_info *info)
+{
+ /*
+ * Get the video params out of 'var'. If a value doesn't fit, round it up,
+ * if it's too big, return -EINVAL.
+ */
+
+ u32 xres, right, hslen, left, xtotal;
+ u32 yres, lower, vslen, upper, ytotal;
+ u32 vxres, xoffset, vyres, yoffset;
+ u32 bpp, base, dacspeed24;
+ u8 r7;
+ int i;
+
+ dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
+ var->xres, var->yres, var->xres_virtual, var->xres_virtual);
+ dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
+ var->xoffset, var->yoffset, var->bits_per_pixel, var->grayscale);
+ dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
+ var->activate, var->nonstd, var->vmode);
+ dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
+ var->pixclock, var->hsync_len, var->vsync_len);
+ dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
+ var->left_margin, var->right_margin, var->upper_margin, var->lower_margin);
+
+
+ bpp = var->bits_per_pixel;
+ switch (bpp) {
+ case 1 ... 8:
+ bpp = 8;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED8) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n", 1000000 / var->pixclock, DACSPEED8);
+ return -EINVAL;
+ }
+ break;
+ case 9 ... 15:
+ bpp = 15;
+ case 16:
+ if ((((u32)1e6) / var->pixclock) > DACSPEED16) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n", 1000000 / var->pixclock, DACSPEED16);
+ return -EINVAL;
+ }
+ break;
+ case 17 ... 24:
+ bpp = 24;
+ dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
+ if ((((u32)1e6) / var->pixclock) > dacspeed24) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n", 1000000 / var->pixclock, dacspeed24);
+ return -EINVAL;
+ }
+ break;
+ case 25 ... 32:
+ bpp = 32;
+ if ((((u32)1e6) / var->pixclock) > DACSPEED32) {
+ dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n", 1000000 / var->pixclock, DACSPEED32);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ xres = (var->xres + 7) & ~7;
+ vxres = (var->xres_virtual + 0xF) & ~0xF;
+ if (vxres < xres)
+ vxres = xres;
+
+ xoffset = (var->xoffset + 7) & ~7;
+ xoffset = var->xoffset;
+ if (xres + xoffset > vxres)
+ xoffset = vxres - xres;
+
+ left = (var->left_margin + 7) & ~7;
+ right = (var->right_margin + 7) & ~7;
+ hslen = (var->hsync_len + 7) & ~7;
+
+ yres = var->yres;
+ vyres = var->yres_virtual;
+ if (yres > vyres)
+ vyres = yres;
+
+ yoffset = var->yoffset;
+ if (yres + yoffset > vyres)
+ yoffset = vyres - yres;
+
+ lower = var->lower_margin;
+ vslen = var->vsync_len;
+ upper = var->upper_margin;
+
+ if (vxres * vyres * ((bpp + 1) / 8) > info->screen_size || vyres = yres) {
+ vyres = info->screen_size / vxres / ((bpp + 1) / 8);
+ if (vyres < yres)
+ return -ENOMEM;
+ }
+
+ if (yoffset + yres > vyres)
+ yoffset = vyres - yres;
+
+ xtotal = xres + right + hslen + left;
+ ytotal = yres + lower + vslen + upper;
+
+ par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
+ par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
+ par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
+ par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
+ par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
+ | ((((xres + right + hslen) >> 3) & 0x20) << 2);
+ par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F) | 0x80;
+
+ par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
+
+ r7 = 0x10; /* disable linecompare */
+ if (ytotal & 0x100)
+ r7 |= 0x01;
+ if (ytotal & 0x200)
+ r7 |= 0x20;
+
+ par->crtc[VGA_CRTC_PRESET_ROW] = 0;
+ par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
+ if (var->vmode & FB_VMODE_DOUBLE)
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
+ par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
+ par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
+ par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
+ if ((yres-1) & 0x100)
+ r7 |= 0x02;
+ if ((yres-1) & 0x200)
+ r7 |= 0x40;
+
+ par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
+ par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
+ if ((yres + lower - 1) & 0x100)
+ r7 |= 0x0C;
+ if ((yres + lower - 1) & 0x200) {
+ par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
+ r7 |= 0x80;
+ }
+
+ par->crtc[VGA_CRTC_V_SYNC_END] = ((yres + lower - 1 + vslen) & 0x0F) & ~0x10; /* disabled IRQ */
+ par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF; /* 0x7F for original VGA, but some SVGA chips requires all 8 bits to set */
+
+ par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
+ par->crtc[VGA_CRTC_MODE] = 0xC3 ;
+ par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
+ par->crtc[VGA_CRTC_OVERFLOW] = r7;
+
+ par->vss = 0x00; /* 3DA */
+
+ for (i = 0x00; i < 0x10; i++)
+ par->atc[i] = i;
+ par->atc[VGA_ATC_MODE] = 0x81;
+ par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
+ par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
+ /*par->atc[VGA_ATC_PEL] = xoffset & 7;*/
+ par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
+
+ par->misc = 0xC3;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ par->misc &= ~0x40;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ par->misc &= ~0x80;
+
+ par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
+ par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
+ par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+ par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
+
+ par->gdc[VGA_GFX_SR_VALUE] = 0x00;
+ par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
+ par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
+ par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
+ par->gdc[VGA_GFX_PLANE_READ] = 0;
+ par->gdc[VGA_GFX_MODE] = 0x02;
+ par->gdc[VGA_GFX_MISC] = 0x05;
+ par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
+ par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
+
+ base = (yoffset * vxres + (xoffset & ~7)) >> 2;
+ switch (bpp) {
+ case 8:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
+ par->ext_offset = vxres >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
+ par->bitblt_cntl = COLEXP_8BPP;
+ break;
+ case 15: /* 0rrrrrgg gggbbbbb */
+ case 16: /* rrrrrggg gggbbbbb */
+ par->pixelpipe_cfg1 = (var->green.length = 6) ? DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
+ par->ext_offset = vxres >> 10;
+ par->bitblt_cntl = COLEXP_16BPP;
+ base *= 2;
+ break;
+ case 24:
+ par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
+ par->ext_offset = (vxres * 3) >> 11;
+ par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
+ par->bitblt_cntl = COLEXP_24BPP;
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
+ par->ext_offset = vxres >> 9;
+ par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
+ par->bitblt_cntl = COLEXP_RESERVED; /* Not implemented on i740 */
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+
+ par->pixelpipe_cfg0 = DAC_8_BIT;
+
+ par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
+ par->io_cntl = EXTENDED_CRTC_CNTL;
+ par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
+ par->display_cntl = HIRES_MODE;
+
+ /* Set the MCLK freq */
+ par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
+
+ /* Calculate the extended CRTC regs */
+ par->ext_vert_total = (ytotal - 2) >> 8;
+ par->ext_vert_disp_end = (yres - 1) >> 8;
+ par->ext_vert_sync_start = (yres + lower) >> 8;
+ par->ext_vert_blank_start = (yres + lower) >> 8;
+ par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
+ par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
+
+ par->interlace_cntl = INTERLACE_DISABLE;
+
+ /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode.) */
+ par->atc[VGA_ATC_OVERSCAN] = 0;
+
+ /* Calculate VCLK that most closely matches the requested dot clock */
+ i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
+
+ /* Since we program the clocks ourselves, always use VCLK2. */
+ par->misc |= 0x0C;
+
+ /* Calculate the FIFO Watermark and Burst Length. */
+ par->lmi_fifo_watermark = i740_calc_fifo(par, ((int)1e6) / var->pixclock, bpp);
+
+ /*if (!fbmon_valid_timings(var->pixclock, ytotal, xtotal, info))
+ return -EINVAL;*/
+
+ return 0;
+}
+
+static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 16:
+ switch (var->green.length) {
+ default:
+ case 5:
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 5;
+ break;
+ case 6:
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->green.length = 6;
+ var->red.length = var->blue.length = 5;
+ break;
+ }
+ break;
+ case 24:
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 32:
+ var->transp.offset = 24;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ var->transp.length = var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (info->monspecs.hfmax && info->monspecs.vfmax &&
+ info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void vga_protect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) | 0x20); /* disable the display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
+}
+
+static void vga_unprotect(struct i740fb_par *par)
+{
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, i740inreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE) & 0xDF); /* reenable display */
+
+ i740inb(par, 0x3DA);
+ i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
+}
+
+static int i740fb_set_par(struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 itemp;
+ int i;
+
+ i = i740fb_decode_var(&info->var, par, info);
+ if (i)
+ return i;
+
+ memset(info->screen_base, 0, info->screen_size);
+
+ vga_protect(par);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
+
+ mdelay(1);
+
+ i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
+ i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
+ i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
+ i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
+
+ i740inb(par, 0x3DA);
+ i740outb(par, 0x3C0, 0x00);
+
+ /* update misc output register */
+ i740outb(par, VGA_MIS_W, par->misc | 0x01);
+
+ /* synchronous reset on */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
+ /* write sequencer registers */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
+ for (i = 2; i < VGA_SEQ_C; i++)
+ i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
+
+ /* synchronous reset off */
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
+
+ /* deprotect CRT registers 0-7 */
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
+
+ /* write CRT registers */
+ for (i = 0; i < VGA_CRT_C; i++)
+ i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
+
+ /* write graphics controller registers */
+ for (i = 0; i < VGA_GFX_C; i++)
+ i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
+
+ /* write attribute controller registers */
+ for (i = 0; i < VGA_ATT_C; i++) {
+ i740inb_p(par, VGA_IS1_RC); /* reset flip-flop */
+ i740outb_p(par, VGA_ATT_IW, i);
+ i740outb_p(par, VGA_ATT_IW, par->atc[i]);
+ }
+
+ i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, par->seq[VGA_SEQ_CLOCK_MODE]);
+
+ i740inb(par, VGA_IS1_RC);
+ i740outb(par, VGA_ATT_IW, 0x20);
+
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START, par->ext_vert_sync_start);
+ i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START, par->ext_vert_blank_start);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
+ i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
+ i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
+
+ i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL, par->interlace_cntl, INTERLACE_ENABLE);
+ i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
+ i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
+ i740outreg_mask(par, XRX, DISPLAY_CNTL, par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
+
+ i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
+
+ i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1, par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
+
+ itemp = readl(par->regs + FWATER_BLC);
+ itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
+ itemp |= par->lmi_fifo_watermark;
+ writel(itemp, par->regs + FWATER_BLC);
+
+ i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
+
+ i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
+ i740outreg_mask(par, XRX, IO_CTNL, par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
+
+ if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
+ i740outb(par, VGA_PEL_MSK, 0xFF);
+ i740outb(par, VGA_PEL_IW, 0x00);
+ for (i = 0; i < 256; i++) {
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ i740outb_p(par, VGA_PEL_D, (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2);
+ }
+ }
+
+ /* Wait for screen to stabilize. */
+ mdelay(50);
+ vga_unprotect(par);
+
+ info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
+ if (info->var.bits_per_pixel = 8)
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ return 0;
+}
+
+static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n", regno, red, green, blue, transp, info->var.bits_per_pixel);
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ if (regno >= 256)
+ return 1;
+ i740outb(info->par, VGA_PEL_IW, regno);
+ i740outb(info->par, VGA_PEL_D, red >> 8);
+ i740outb(info->par, VGA_PEL_D, green >> 8);
+ i740outb(info->par, VGA_PEL_D, blue >> 8);
+ break;
+ case 15:
+ case 16:
+ if (regno >= 16)
+ return 0;
+ if (info->var.green.length = 5)
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xF800) >> 1) | ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+ else if (info->var.green.length = 6)
+ ((u32 *)info->pseudo_palette)[regno] = (red & 0xF800) | ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+ else
+ return -EINVAL;
+ break;
+ case 24:
+ case 32:
+ if (regno >= 16)
+ return 0;
+ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int i740fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+ u32 base = (var->yoffset * var->xres_virtual + (var->xoffset & ~7)) >> 2;
+
+ dev_dbg(info->device, "pan_display: xoffset: %i, yoffset: %i base: %i\n", var->xoffset, var->yoffset, base);
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ break;
+ case 15:
+ case 16:
+ base *= 2;
+ break;
+ case 24:
+ /*
+ * The last bit does not seem to have any effect on the start
+ * address register in 24bpp mode, so...
+ */
+ base &= 0xFFFFFFFE; /* ...ignore the last bit. */
+ base *= 3;
+ break;
+ case 32:
+ base *= 4;
+ break;
+ }
+
+ par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
+ par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
+ par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
+ par->ext_start_addr = ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
+ /*par->atc[VGA_ATC_PEL] = var->xoffset & 7;*/
+
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
+ i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI, (base & 0x0000FF00) >> 8);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, (base & 0x3FC00000) >> 22);
+ i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
+ /*i740outreg(par, VGA_ATT_W, VGA_ATC_PEL, var->xoffset & 7);*/
+
+ return 0;
+}
+
+static int i740fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct i740fb_par *par = info->par;
+
+ unsigned char SEQ01;
+ int DPMSSyncSelect;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ SEQ01 = 0x00;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
+ break;
+ case FB_BLANK_POWERDOWN:
+ SEQ01 = 0x20;
+ DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Turn the screen on/off */
+ i740outb(par, SRX, 0x01);
+ SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
+ i740outb(par, SRX, 0x01);
+ i740outb(par, SRX + 1, SEQ01);
+
+ /* Set the DPMS mode */
+ i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
+
+ /* Let fbcon do a soft blank for us */
+ return (blank_mode = FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops i740fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = i740fb_open,
+ .fb_release = i740fb_release,
+ .fb_check_var = i740fb_check_var,
+ .fb_set_par = i740fb_set_par,
+ .fb_setcolreg = i740fb_setcolreg,
+ .fb_blank = i740fb_blank,
+ .fb_pan_display = i740fb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit i740fb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct fb_info *info;
+ struct i740fb_par *par;
+ int ret;
+ bool found = false;
+ u8 *edid;
+
+ info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
+ if (!info) {
+ dev_err(&(dev->dev), "cannot allocate framebuffer\n");
+ return -ENOMEM;
+ }
+
+ par = info->par;
+ mutex_init(&par->open_lock);
+
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.bits_per_pixel = 8;
+ info->fbops = &i740fb_ops;
+ info->pseudo_palette = par->pseudo_palette;
+
+ ret = pci_enable_device(dev);
+ if (ret) {
+ dev_err(info->device, "cannot enable PCI device\n");
+ goto err_enable_device;
+ }
+
+ ret = pci_request_regions(dev, info->fix.id);
+ if (ret) {
+ dev_err(info->device, "error requesting regions\n");
+ goto err_request_regions;
+ }
+
+ info->screen_base = pci_ioremap_bar(dev, 0);
+ if (!info->screen_base) {
+ dev_err(info->device, "error remapping base\n");
+ ret = -ENOMEM;
+ goto err_ioremap_1;
+ }
+
+ par->regs = pci_ioremap_bar(dev, 1);
+ if (!par->regs) {
+ dev_err(info->device, "error remapping MMIO\n");
+ ret = -ENOMEM;
+ goto err_ioremap_2;
+ }
+
+ /* detect memory size */
+ if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1) = DRAM_ROW_1_SDRAM)
+ i740outb(par, XRX, DRAM_ROW_BNDRY_1);
+ else
+ i740outb(par, XRX, DRAM_ROW_BNDRY_0);
+ info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
+ /* detect memory type */
+ par->has_sgram = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
+ par->has_sgram = !((par->has_sgram & DRAM_RAS_TIMING) ||
+ (par->has_sgram & DRAM_RAS_PRECHARGE));
+
+ printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
+ pci_name(dev), info->screen_size >> 10,
+ par->has_sgram ? "SGRAM" : "SDRAM");
+
+ info->fix = i740fb_fix;
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ info->fix.mmio_len = pci_resource_len(dev, 1);
+ info->fix.smem_start = pci_resource_start(dev, 0);
+ info->fix.smem_len = info->screen_size;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ if (i740fb_setup_ddc_bus(info) = 0) {
+ par->ddc_registered = true;
+ edid = fb_ddc_read(&par->ddc_adapter);
+ if (edid) {
+ fb_edid_to_monspecs(edid, &info->monspecs);
+ kfree(edid);
+ if (!info->monspecs.modedb)
+ dev_err(info->device, "error getting mode database\n");
+ else {
+ const struct fb_videomode *m;
+
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len,
+ &info->modelist);
+ m = fb_find_best_display(&info->monspecs, &info->modelist);
+ if (m) {
+ fb_videomode_to_var(&info->var, m);
+ /* fill all other info->var's fields */
+ if (i740fb_check_var(&info->var, info) = 0)
+ found = true;
+ }
+ }
+ }
+ }
+
+ if (!mode_option && !found)
+ mode_option = "640x480-8@60";
+
+ if (mode_option) {
+ ret = fb_find_mode(&info->var, info, mode_option,
+ info->monspecs.modedb, info->monspecs.modedb_len,
+ NULL, info->var.bits_per_pixel);
+ if (!ret || ret = 4) {
+ dev_err(info->device, "mode %s not found\n", mode_option);
+ ret = -EINVAL;
+ }
+ }
+
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
+ /* maximize virtual vertical size for fast scrolling */
+ info->var.yres_virtual = info->fix.smem_len * 8 /
+ (info->var.bits_per_pixel * info->var.xres_virtual);
+
+ if (ret = -EINVAL)
+ goto err_find_mode;
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret) {
+ dev_err(info->device, "cannot allocate colormap\n");
+ goto err_alloc_cmap;
+ }
+
+ ret = register_framebuffer(info);
+ if (ret) {
+ dev_err(info->device, "error registering framebuffer\n");
+ goto err_reg_framebuffer;
+ }
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ pci_set_drvdata(dev, info);
+#ifdef CONFIG_MTRR
+ if (mtrr) {
+ par->mtrr_reg = -1;
+ par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+ }
+#endif
+ return 0;
+
+err_reg_framebuffer:
+ fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+err_ioremap_2:
+ pci_iounmap(dev, info->screen_base);
+err_ioremap_1:
+ pci_release_regions(dev);
+err_request_regions:
+/* pci_disable_device(dev); */
+err_enable_device:
+ framebuffer_release(info);
+ return ret;
+}
+
+static void __devexit i740fb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ if (info) {
+#ifdef CONFIG_MTRR
+ struct i740fb_par *par = info->par;
+
+ if (par->mtrr_reg >= 0) {
+ mtrr_del(par->mtrr_reg, 0, 0);
+ par->mtrr_reg = -1;
+ }
+#endif
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ if (par->ddc_registered)
+ i2c_del_adapter(&par->ddc_adapter);
+ pci_iounmap(dev, par->regs);
+ pci_iounmap(dev, info->screen_base);
+ pci_release_regions(dev);
+/* pci_disable_device(dev); */
+ pci_set_drvdata(dev, NULL);
+ framebuffer_release(info);
+ }
+}
+
+#ifdef CONFIG_PM
+static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ /* don't disable console during hibernation and wakeup from it */
+ if (state.event = PM_EVENT_FREEZE || state.event = PM_EVENT_PRETHAW)
+ return 0;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ /* do nothing if framebuffer is not active */
+ if (par->ref_count = 0) {
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+ }
+
+ fb_set_suspend(info, 1);
+
+ pci_save_state(dev);
+ pci_disable_device(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
+
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+
+ return 0;
+}
+
+static int i740fb_resume(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct i740fb_par *par = info->par;
+
+ console_lock();
+ mutex_lock(&(par->open_lock));
+
+ if (par->ref_count = 0)
+ goto fail;
+
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+ if (pci_enable_device(dev))
+ goto fail;
+
+ i740fb_set_par(info);
+ fb_set_suspend(info, 0);
+
+fail:
+ mutex_unlock(&(par->open_lock));
+ console_unlock();
+ return 0;
+}
+#else
+#define i740fb_suspend NULL
+#define i740fb_resume NULL
+#endif /* CONFIG_PM */
+
+#define I740_ID_PCI 0x00d1
+#define I740_ID_AGP 0x7800
+
+static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, i740fb_id_table);
+
+static struct pci_driver i740fb_driver = {
+ .name = "i740fb",
+ .id_table = i740fb_id_table,
+ .probe = i740fb_probe,
+ .remove = __devexit_p(i740fb_remove),
+ .suspend = i740fb_suspend,
+ .resume = i740fb_resume,
+};
+
+#ifndef MODULE
+static int __init i740fb_setup(char *options)
+{
+ char *opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+#ifdef CONFIG_MTRR
+ else if (!strncmp(opt, "mtrr:", 5))
+ mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+ else
+ mode_option = opt;
+ }
+
+ return 0;
+}
+#endif
+
+int __init i740fb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("i740fb", &option))
+ return -ENODEV;
+ i740fb_setup(option);
+#endif
+
+ return pci_register_driver(&i740fb_driver);
+}
+
+static void __exit i740fb_exit(void)
+{
+ pci_unregister_driver(&i740fb_driver);
+}
+
+module_init(i740fb_init);
+module_exit(i740fb_exit);
+
+MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for Intel740");
+
+module_param(mode_option, charp, 0444);
+MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
--- /dev/null 2011-10-28 20:05:27.615214131 +0200
+++ linux-2.6.39-rc2/drivers/video/i740_reg.h 2011-08-14 23:47:48.000000000 +0200
@@ -0,0 +1,309 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ */
+
+/* I/O register offsets */
+#define SRX VGA_SEQ_I
+#define GRX VGA_GFX_I
+#define ARX VGA_ATT_IW
+#define XRX 0x3D6
+#define MRX 0x3D2
+
+/* VGA Color Palette Registers */
+#define DACMASK 0x3C6
+#define DACSTATE 0x3C7
+#define DACRX 0x3C7
+#define DACWX 0x3C8
+#define DACDATA 0x3C9
+
+/* CRT Controller Registers (CRX) */
+#define START_ADDR_HI 0x0C
+#define START_ADDR_LO 0x0D
+#define VERT_SYNC_END 0x11
+#define EXT_VERT_TOTAL 0x30
+#define EXT_VERT_DISPLAY 0x31
+#define EXT_VERT_SYNC_START 0x32
+#define EXT_VERT_BLANK_START 0x33
+#define EXT_HORIZ_TOTAL 0x35
+#define EXT_HORIZ_BLANK 0x39
+#define EXT_START_ADDR 0x40
+#define EXT_START_ADDR_ENABLE 0x80
+#define EXT_OFFSET 0x41
+#define EXT_START_ADDR_HI 0x42
+#define INTERLACE_CNTL 0x70
+#define INTERLACE_ENABLE 0x80
+#define INTERLACE_DISABLE 0x00
+
+/* Miscellaneous Output Register */
+#define MSR_R 0x3CC
+#define MSR_W 0x3C2
+#define IO_ADDR_SELECT 0x01
+
+#define MDA_BASE 0x3B0
+#define CGA_BASE 0x3D0
+
+/* System Configuration Extension Registers (XRX) */
+#define IO_CTNL 0x09
+#define EXTENDED_ATTR_CNTL 0x02
+#define EXTENDED_CRTC_CNTL 0x01
+
+#define ADDRESS_MAPPING 0x0A
+#define PACKED_MODE_ENABLE 0x04
+#define LINEAR_MODE_ENABLE 0x02
+#define PAGE_MAPPING_ENABLE 0x01
+
+#define BITBLT_CNTL 0x20
+#define COLEXP_MODE 0x30
+#define COLEXP_8BPP 0x00
+#define COLEXP_16BPP 0x10
+#define COLEXP_24BPP 0x20
+#define COLEXP_RESERVED 0x30
+#define CHIP_RESET 0x02
+#define BITBLT_STATUS 0x01
+
+#define DISPLAY_CNTL 0x40
+#define VGA_WRAP_MODE 0x02
+#define VGA_WRAP_AT_256KB 0x00
+#define VGA_NO_WRAP 0x02
+#define GUI_MODE 0x01
+#define STANDARD_VGA_MODE 0x00
+#define HIRES_MODE 0x01
+
+#define DRAM_ROW_TYPE 0x50
+#define DRAM_ROW_0 0x07
+#define DRAM_ROW_0_SDRAM 0x00
+#define DRAM_ROW_0_EMPTY 0x07
+#define DRAM_ROW_1 0x38
+#define DRAM_ROW_1_SDRAM 0x00
+#define DRAM_ROW_1_EMPTY 0x38
+#define DRAM_ROW_CNTL_LO 0x51
+#define DRAM_CAS_LATENCY 0x10
+#define DRAM_RAS_TIMING 0x08
+#define DRAM_RAS_PRECHARGE 0x04
+#define DRAM_ROW_CNTL_HI 0x52
+#define DRAM_EXT_CNTL 0x53
+#define DRAM_REFRESH_RATE 0x03
+#define DRAM_REFRESH_DISABLE 0x00
+#define DRAM_REFRESH_60HZ 0x01
+#define DRAM_REFRESH_FAST_TEST 0x02
+#define DRAM_REFRESH_RESERVED 0x03
+#define DRAM_TIMING 0x54
+#define DRAM_ROW_BNDRY_0 0x55
+#define DRAM_ROW_BNDRY_1 0x56
+
+#define DPMS_SYNC_SELECT 0x61
+#define VSYNC_CNTL 0x08
+#define VSYNC_ON 0x00
+#define VSYNC_OFF 0x08
+#define HSYNC_CNTL 0x02
+#define HSYNC_ON 0x00
+#define HSYNC_OFF 0x02
+
+#define PIXPIPE_CONFIG_0 0x80
+#define DAC_8_BIT 0x80
+#define DAC_6_BIT 0x00
+#define HW_CURSOR_ENABLE 0x10
+#define EXTENDED_PALETTE 0x01
+
+#define PIXPIPE_CONFIG_1 0x81
+#define DISPLAY_COLOR_MODE 0x0F
+#define DISPLAY_VGA_MODE 0x00
+#define DISPLAY_8BPP_MODE 0x02
+#define DISPLAY_15BPP_MODE 0x04
+#define DISPLAY_16BPP_MODE 0x05
+#define DISPLAY_24BPP_MODE 0x06
+#define DISPLAY_32BPP_MODE 0x07
+
+#define PIXPIPE_CONFIG_2 0x82
+#define DISPLAY_GAMMA_ENABLE 0x08
+#define DISPLAY_GAMMA_DISABLE 0x00
+#define OVERLAY_GAMMA_ENABLE 0x04
+#define OVERLAY_GAMMA_DISABLE 0x00
+
+#define CURSOR_CONTROL 0xA0
+#define CURSOR_ORIGIN_SCREEN 0x00
+#define CURSOR_ORIGIN_DISPLAY 0x10
+#define CURSOR_MODE 0x07
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_32_4C_AX 0x01
+#define CURSOR_MODE_128_2C 0x02
+#define CURSOR_MODE_128_1C 0x03
+#define CURSOR_MODE_64_3C 0x04
+#define CURSOR_MODE_64_4C_AX 0x05
+#define CURSOR_MODE_64_4C 0x06
+#define CURSOR_MODE_RESERVED 0x07
+#define CURSOR_BASEADDR_LO 0xA2
+#define CURSOR_BASEADDR_HI 0xA3
+#define CURSOR_X_LO 0xA4
+#define CURSOR_X_HI 0xA5
+#define CURSOR_X_POS 0x00
+#define CURSOR_X_NEG 0x80
+#define CURSOR_Y_LO 0xA6
+#define CURSOR_Y_HI 0xA7
+#define CURSOR_Y_POS 0x00
+#define CURSOR_Y_NEG 0x80
+
+#define VCLK2_VCO_M 0xC8
+#define VCLK2_VCO_N 0xC9
+#define VCLK2_VCO_MN_MSBS 0xCA
+#define VCO_N_MSBS 0x30
+#define VCO_M_MSBS 0x03
+#define VCLK2_VCO_DIV_SEL 0xCB
+#define POST_DIV_SELECT 0x70
+#define POST_DIV_1 0x00
+#define POST_DIV_2 0x10
+#define POST_DIV_4 0x20
+#define POST_DIV_8 0x30
+#define POST_DIV_16 0x40
+#define POST_DIV_32 0x50
+#define VCO_LOOP_DIV_BY_4M 0x00
+#define VCO_LOOP_DIV_BY_16M 0x04
+#define REF_CLK_DIV_BY_5 0x02
+#define REF_DIV_4 0x00
+#define REF_DIV_1 0x01
+
+#define PLL_CNTL 0xCE
+#define PLL_MEMCLK_SEL 0x03
+#define PLL_MEMCLK__66667KHZ 0x00
+#define PLL_MEMCLK__75000KHZ 0x01
+#define PLL_MEMCLK__88889KHZ 0x02
+#define PLL_MEMCLK_100000KHZ 0x03
+
+/* Multimedia Extension Registers (MRX) */
+#define ACQ_CNTL_1 0x02
+#define ACQ_CNTL_2 0x03
+#define FRAME_CAP_MODE 0x01
+#define CONT_CAP_MODE 0x00
+#define SINGLE_CAP_MODE 0x01
+#define ACQ_CNTL_3 0x04
+#define COL_KEY_CNTL_1 0x3C
+#define BLANK_DISP_OVERLAY 0x20
+
+/* FIFOs */
+#define LP_FIFO 0x1000
+#define HP_FIFO 0x2000
+#define INSTPNT 0x3040
+#define LP_FIFO_COUNT 0x3040
+#define HP_FIFO_COUNT 0x3041
+
+/* FIFO Commands */
+#define CLIENT 0xE0000000
+#define CLIENT_2D 0x60000000
+
+/* Command Parser Mode Register */
+#define COMPARS 0x3038
+#define TWO_D_INST_DISABLE 0x08
+#define THREE_D_INST_DISABLE 0x04
+#define STATE_VAR_UPDATE_DISABLE 0x02
+#define PAL_STIP_DISABLE 0x01
+
+/* Interrupt Control Registers */
+#define IER 0x3030
+#define IIR 0x3032
+#define IMR 0x3034
+#define ISR 0x3036
+#define VMIINTB_EVENT 0x2000
+#define GPIO4_INT 0x1000
+#define DISP_FLIP_EVENT 0x0800
+#define DVD_PORT_DMA 0x0400
+#define DISP_VBLANK 0x0200
+#define FIFO_EMPTY_DMA_DONE 0x0100
+#define INST_PARSER_ERROR 0x0080
+#define USER_DEFINED 0x0040
+#define BREAKPOINT 0x0020
+#define DISP_HORIZ_COUNT 0x0010
+#define DISP_VSYNC 0x0008
+#define CAPTURE_HORIZ_COUNT 0x0004
+#define CAPTURE_VSYNC 0x0002
+#define THREE_D_PIPE_FLUSHED 0x0001
+
+/* FIFO Watermark and Burst Length Control Register */
+#define FWATER_BLC 0x00006000
+#define LMI_BURST_LENGTH 0x7F000000
+#define LMI_FIFO_WATERMARK 0x003F0000
+#define AGP_BURST_LENGTH 0x00007F00
+#define AGP_FIFO_WATERMARK 0x0000003F
+
+/* BitBLT Registers */
+#define SRC_DST_PITCH 0x00040000
+#define DST_PITCH 0x1FFF0000
+#define SRC_PITCH 0x00001FFF
+#define COLEXP_BG_COLOR 0x00040004
+#define COLEXP_FG_COLOR 0x00040008
+#define MONO_SRC_CNTL 0x0004000C
+#define MONO_USE_COLEXP 0x00000000
+#define MONO_USE_SRCEXP 0x08000000
+#define MONO_DATA_ALIGN 0x07000000
+#define MONO_BIT_ALIGN 0x01000000
+#define MONO_BYTE_ALIGN 0x02000000
+#define MONO_WORD_ALIGN 0x03000000
+#define MONO_DWORD_ALIGN 0x04000000
+#define MONO_QWORD_ALIGN 0x05000000
+#define MONO_SRC_INIT_DSCRD 0x003F0000
+#define MONO_SRC_RIGHT_CLIP 0x00003F00
+#define MONO_SRC_LEFT_CLIP 0x0000003F
+#define BITBLT_CONTROL 0x00040010
+#define BLTR_STATUS 0x80000000
+#define DYN_DEPTH 0x03000000
+#define DYN_DEPTH_8BPP 0x00000000
+#define DYN_DEPTH_16BPP 0x01000000
+#define DYN_DEPTH_24BPP 0x02000000
+#define DYN_DEPTH_32BPP 0x03000000 /* Not implemented on the i740 */
+#define DYN_DEPTH_ENABLE 0x00800000
+#define PAT_VERT_ALIGN 0x00700000
+#define SOLID_PAT_SELECT 0x00080000
+#define PAT_IS_IN_COLOR 0x00000000
+#define PAT_IS_MONO 0x00040000
+#define MONO_PAT_TRANSP 0x00020000
+#define COLOR_TRANSP_ROP 0x00000000
+#define COLOR_TRANSP_DST 0x00008000
+#define COLOR_TRANSP_EQ 0x00000000
+#define COLOR_TRANSP_NOT_EQ 0x00010000
+#define COLOR_TRANSP_ENABLE 0x00004000
+#define MONO_SRC_TRANSP 0x00002000
+#define SRC_IS_IN_COLOR 0x00000000
+#define SRC_IS_MONO 0x00001000
+#define SRC_USE_SRC_ADDR 0x00000000
+#define SRC_USE_BLTDATA 0x00000400
+#define BLT_TOP_TO_BOT 0x00000000
+#define BLT_BOT_TO_TOP 0x00000200
+#define BLT_LEFT_TO_RIGHT 0x00000000
+#define BLT_RIGHT_TO_LEFT 0x00000100
+#define BLT_ROP 0x000000FF
+#define BLT_PAT_ADDR 0x00040014
+#define BLT_SRC_ADDR 0x00040018
+#define BLT_DST_ADDR 0x0004001C
+#define BLT_DST_H_W 0x00040020
+#define BLT_DST_HEIGHT 0x1FFF0000
+#define BLT_DST_WIDTH 0x00001FFF
+#define SRCEXP_BG_COLOR 0x00040024
+#define SRCEXP_FG_COLOR 0x00040028
+#define BLTDATA 0x00050000
--
Ondrej Zary
^ permalink raw reply
* Hello
From: lisa hedstrand @ 2011-10-28 11:36 UTC (permalink / raw)
To: linux-fbdev
My name is Miss Lisa Please accept my apology if my mode of contacting you will in any way offend you. I am compelled to contact you via this medium because i needed a friend from that part of the world. We will get to know each other in details if my proposition accepted. l am a student in UK but originally from USA.
^ permalink raw reply
* [PATCH] fbtest: fix test011 with xpanstep or ypanstep greater than 1
From: Ondrej Zary @ 2011-10-27 20:31 UTC (permalink / raw)
To: linux-fbdev
Hello,
this patch fixes test011 in fbtest if framebuffer driver requires xpanstep or
ypanstep to be greater than 1. Without this, test011 fails on savagefb:
ioctl FBIOPAN_DISPLAY: Invalid argument
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
--- fbtest-orig/tests/test011.c 2011-10-27 22:20:47.000000000 +0200
+++ fbtest/tests/test011.c 2011-10-27 22:22:16.000000000 +0200
@@ -93,16 +93,25 @@ static int linegen_next(struct linegen *
return 1;
}
-static void move(u32 cx, u32 cy, u32 x1, u32 y1, u32 x2, u32 y2)
+static void move(u32 cx, u32 cy, u32 x1, u32 y1, u32 x2, u32 y2, u32 xpanstep, u32 ypanstep)
{
struct linegen gen;
u32 x, y;
static int cnt = 0;
+ if (xpanstep = 0)
+ xpanstep = 1;
+ if (ypanstep = 0)
+ ypanstep = 1;
+ x1 /= xpanstep;
+ x2 /= xpanstep;
+ y1 /= ypanstep;
+ y2 /= ypanstep;
+
linegen_init(&gen, x1, y1, x2, y2);
while (linegen_next(&gen, &x, &y)) {
fill_circle(cx+x, cy+y, 2, cnt & 4 ? black_pixel : white_pixel);
- fb_pan(x, y);
+ fb_pan(x * xpanstep, y * ypanstep);
wait_ms(SLEEP_MS);
cnt++;
}
@@ -137,29 +146,29 @@ static enum test_res test011_func(void)
dy = fb_fix.ypanstep ? fb_var.yres_virtual-fb_var.yres : 0;
/* move right */
- move(cx, cy, 0, 0, dx, 0);
+ move(cx, cy, 0, 0, dx, 0, fb_fix.xpanstep, fb_fix.ypanstep);
/* move down */
- move(cx, cy, dx, 0, dx, dy);
+ move(cx, cy, dx, 0, dx, dy, fb_fix.xpanstep, fb_fix.ypanstep);
/* move left */
- move(cx, cy, dx, dy, 0, dy);
+ move(cx, cy, dx, dy, 0, dy, fb_fix.xpanstep, fb_fix.ypanstep);
if (dx >= 2 && dy >= 2) {
/* move up and right */
- move(cx, cy, 0, dy, dx/2, 0);
+ move(cx, cy, 0, dy, dx/2, 0, fb_fix.xpanstep, fb_fix.ypanstep);
/* move right and down */
- move(cx, cy, dx/2, 0, dx, dy/2);
+ move(cx, cy, dx/2, 0, dx, dy/2, fb_fix.xpanstep, fb_fix.ypanstep);
/* move left and down */
- move(cx, cy, dx, dy/2, dx/2, dy);
+ move(cx, cy, dx, dy/2, dx/2, dy, fb_fix.xpanstep, fb_fix.ypanstep);
/* move up and left */
- move(cx, cy, dx/2, dy, 0, 0);
+ move(cx, cy, dx/2, dy, 0, 0, fb_fix.xpanstep, fb_fix.ypanstep);
} else {
/* move up */
- move(cx, cy, 0, dy, 0, 0);
+ move(cx, cy, 0, dy, 0, 0, fb_fix.xpanstep, fb_fix.ypanstep);
}
wait_for_key(10);
--
Ondrej Zary
^ permalink raw reply
* Re: fb_setcolreg(), CNVT_TOHW() and chan_to_field()
From: Rabin Vincent @ 2011-10-25 15:25 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20111025073349.GB6027@debian>
On Tue, Oct 25, 2011 at 01:15:41PM +0200, Geert Uytterhoeven wrote:
> On Tue, Oct 25, 2011 at 09:34, Rabin Vincent <rabin@rab.in> wrote:
> > I'm trying to figure out the best way to implement fb_setcolreg() for
> > FB_VISUAL_TRUECOLOR.
>
> FB_VISUAL_TRUECOLOR implies the colormap is read-only.
> Perhaps you meant FB_VISUAL_DIRECTCOLOR?
I was referring to the pseudo palette usage for FB_VISUAL_TRUECOLOR, which is
where most of the drivers use chan_to_field(), for example in s3c2410fb.c:
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
/* true-colour, use pseudo-palette */
if (regno < 16) {
u32 *pal = info->pseudo_palette;
val = chan_to_field(red, &info->var.red);
>
> > 14 or so drivers copy/paste the CNVT_TOHW from skeletonfb.c:
> >
> > #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
> > ...
> > red = CNVT_TOHW(red, info->var.red.length);
> >
> > Another 18 or so drivers copy/paste a chan_to_field() function which has
> > a straightforward shift:
> >
> > static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
> > {
> > chan &= 0xffff;
> > chan >>= 16 - bf->length;
> > return chan << bf->offset;
> > }
> > ...
> > val = chan_to_field(red, &info->var.red);
> >
> > Both methods return similar values, except that with CNVT_TOHW() the
> > extreme values seem to have a smaller range than the other values, while
> > with the chan_to_field() shift all the values have an equal range.
> >
> > What's the reason behind choosing one over the other? Could/should a
> > common function be provided for all the drivers to use?
>
> The idea is to use the full dynamic range of the 16-bit values. I.e. 'all ones'
> in the hardware-specific value should map to 'all ones' in the 16-bit expanded
> value. So the macros are preferred.
I'm not sure I follow. In the pseudo palette, where the bf->length is less
than 16, both CNVT_TOHW() and the plain shift return the same values for the
all-ones case.
^ permalink raw reply
* Re: fb_setcolreg(), CNVT_TOHW() and chan_to_field()
From: Geert Uytterhoeven @ 2011-10-25 11:15 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <20111025073349.GB6027@debian>
On Tue, Oct 25, 2011 at 09:34, Rabin Vincent <rabin@rab.in> wrote:
> I'm trying to figure out the best way to implement fb_setcolreg() for
> FB_VISUAL_TRUECOLOR.
FB_VISUAL_TRUECOLOR implies the colormap is read-only.
Perhaps you meant FB_VISUAL_DIRECTCOLOR?
> 14 or so drivers copy/paste the CNVT_TOHW from skeletonfb.c:
>
> #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
> ...
> red = CNVT_TOHW(red, info->var.red.length);
>
> Another 18 or so drivers copy/paste a chan_to_field() function which has
> a straightforward shift:
>
> static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
> {
> chan &= 0xffff;
> chan >>= 16 - bf->length;
> return chan << bf->offset;
> }
> ...
> val = chan_to_field(red, &info->var.red);
>
> Both methods return similar values, except that with CNVT_TOHW() the
> extreme values seem to have a smaller range than the other values, while
> with the chan_to_field() shift all the values have an equal range.
>
> What's the reason behind choosing one over the other? Could/should a
> common function be provided for all the drivers to use?
The idea is to use the full dynamic range of the 16-bit values. I.e. 'all ones'
in the hardware-specific value should map to 'all ones' in the 16-bit expanded
value. So the macros are preferred.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* fb_setcolreg(), CNVT_TOHW() and chan_to_field()
From: Rabin Vincent @ 2011-10-25 7:46 UTC (permalink / raw)
To: linux-fbdev
I'm trying to figure out the best way to implement fb_setcolreg() for
FB_VISUAL_TRUECOLOR.
14 or so drivers copy/paste the CNVT_TOHW from skeletonfb.c:
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
...
red = CNVT_TOHW(red, info->var.red.length);
Another 18 or so drivers copy/paste a chan_to_field() function which has
a straightforward shift:
static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
{
chan &= 0xffff;
chan >>= 16 - bf->length;
return chan << bf->offset;
}
...
val = chan_to_field(red, &info->var.red);
Both methods return similar values, except that with CNVT_TOHW() the
extreme values seem to have a smaller range than the other values, while
with the chan_to_field() shift all the values have an equal range.
What's the reason behind choosing one over the other? Could/should a
common function be provided for all the drivers to use?
^ permalink raw reply
* 群发软件+买家搜索机+最新广交会买家、海
From: 仅10元每天。 @ 2011-10-24 21:16 UTC (permalink / raw)
To: linux-fbdev
576k5Y+R6L2v5Lu2K+S5sOWutuaQnOe0ouacuisxMDnlsYrlub/kuqTkvJrkubDlrrbjgIHlsZXk
vJrkubDlrrbjgIHmtbflhbPmlbDmja4sQjJC6K+i55uY5Lmw5a62NTAw5LiH44CCDQoNCuS4gOWF
sTjkuKrljIUo5pWw5o2u5piv5YWo6KGM5Lia55qE77yM5oyJ54Wn6KGM5Lia5YiG5aW957G777yM
5bm25LiU5Y+v5Lul5oyJ54Wn5YWz6ZSu6K+N5p+l6K+i55qEKe+8miANCjHvvIwyMDEx5pil5a2j
MTA55bGK5bm/5Lqk5Lya5Lmw5a625pWw5o2u5bqT5paw6bKc5Ye654KJ77yM6LaF57qn5paw6bKc
5Lmw5a6277yM5paw6bKc5pWw5o2u77yM5a655piT5oiQ5Y2V77yBIA0KMu+8jOacgOaWsOWFqOeQ
g+S5sOWutuW6kyzlhbE0NTE2NjDmnaHmlbDmja7jgIIgDQoz77yMMjAwOOW5tCwyMDA55bm0LDIw
MTDlubQg5pil5a2jK+eni+Wto+W5v+S6pOS8muS5sOWutuWQjeW9le+8jDEwMyAxMDQgMTA1IDEw
NiAxMDcgMTA4IOWFseWFreWxiiDlhbExMjAuNuS4h+aVsOaNruOAgg0KNO+8jDIwMTDlubTlm73p
mYXkv4PplIDljY/kvJrvvIhQUEFJ77yJ5oiQ5ZGY5ZCN5Y2VIFBQQUkgTWVtYmVycyBEaXJlY3Rv
cnnvvIzpnZ7luLjph43opoHnmoTlpKfkubDlrrbjgIINCjXvvIwyMDEw5bm05Yiw6aaZ5riv6YeH
6LSt55qE5Zu95aSW5a6i5Lq65ZCN5b2VKOmmmea4r+i0uOWPkeWxgOaPkOS+mynvvIzlhbE3LjLk
uIfmlbDmja7vvIzotoXnuqfph43opoHnmoTkubDlrrbjgIINCjbvvIw2MC445LiH5p2h5pyA5paw
5Zu95aSWQjJC5Lmw5a626K+i55uY44CCDQo377yMMjAwOeW5tOa1t+WFs+aPkOWNleaVsOaNrnBp
ZXJz54mI5pWw5o2uIDHljYPkuIfjgIINCjjvvIznvqTlj5Hova/ku7bvvIznvqTlj5Hova/ku7bn
moTpg6jnvbLkuI7lronoo4XjgIINCg0K5YWxIDUwMOS4h+S4quS5sOWutu+8jOavj+S4quWdh+ac
iUVtYWlsLiANCg0K5L+d6K+B5q+P5aSp6YO95pyJ5Lmw5a625Zue5aSN44CCDQrkv53or4Hmr4/l
pKnpg73mnInkubDlrrblm57lpI3jgIINCg0K6KaB55qE5oqT57Sn6IGU57O7UVE6IDQ2NzY0Mzk3
NSAgIOaIluiAheeri+WNs+WbnuWkjemCrueusTogIDQ2NzY0Mzk3NUBxcS5jb20NCuimgeeahOaK
k+e0p+iBlOezu1FROiA0Njc2NDM5NzUgICDmiJbogIXnq4vljbPlm57lpI3pgq7nrrE6ICA0Njc2
NDM5NzVAcXEuY29tDQropoHnmoTmipPntKfogZTns7tRUTogNDY3NjQzOTc1ICAg5oiW6ICF56uL
5Y2z5Zue5aSN6YKu566xOiAgNDY3NjQzOTc1QHFxLmNvbQ0KDQoNCuivmuS/oeS4uuacrO+8jOWm
guaenOS4jeS/oeS7u+acrOS6uizlj6/ku6XotbDmt5jlrp3kuqTmmJMs5pS26LSn6aqM6K+B5ZCO
5YaN5LuY5qy+LOi/meaYr+WvueaCqOacgOWlveeahOS/nemanOS6huOAgiANCg0K5L+d6K+B5q+P
5aSp6YO95pyJ5Lmw5a625Zue5aSN44CCDQrkv53or4Hmr4/lpKnpg73mnInkubDlrrblm57lpI3j
gIINCuS/neivgeavj+WkqemDveacieS5sOWutuWbnuWkjeOAgg0KDQoNCg0KDQrlub/kuqTkvJrk
ubDlrrbmjInkuqflk4HnsbvliKvliIbnsbvvvIzliIbkuLrku6XkuIvlh6DnsbvvvJoNCjEg5Yqe
5YWs6K6+5aSHDQoyIOe8lue7h+WPiuiXpOmTgeW3peiJuuWTgQ0KMyDnjrvnkoMNCjQg6aSQ5Y6o
55So5YW3DQo1IOi9pui+hg0KNiDlpKflnovmnLrmorDlj4rorr7lpIcNCjcg55S15a2Q55S15rCU
DQo4IOeUteWtkOa2iOi0ueWTgQ0KOSDnurrnu4cNCjEwIOacjeijhQ0KMTEg5Liq5Lq65oqk55CG
DQoxMiDlt6XnqIvmnLrmorANCjEzIOW3peWFtw0KMTQg5YyW5belDQoxNSDorqHnrpfmnLrlj4rp
gJrorq8NCjE2IOWutuWxheeUqOWTgQ0KMTcg5a625bGF6KOF6aWwDQoxOCDlrrblhbcNCjE5IOWu
tueUqOeUteWZqA0KMjAg5bu6562R5Y+K6KOF6aWw5p2Q5paZDQoyMSDoioLml6XnlKjlk4ENCjIy
IOekvOWTgeWPiui1oOWTgQ0KMjMg5pGp5omY6L2mDQoyNCDmsb3ovabphY3ku7YNCjI1IOmjn+WT
gQ0KMjYg6Zm255O3DQoyNyDpk4Hnn7MNCjI4IOeOqeWFtw0KMjkg5Y2r5rW0DQozMCDkupTph5EN
CjMxIOWwj+Wei+acuuaisA0KMzIg6Z6LDQozMyDkvJHpl7LnlKjlk4ENCjM0IOWMu+eWlw0KMzUg
5rW05a6k5Lqn5ZOBDQozNiDlm63mnpcNCjM3IOeFp+aYjuS6p+WTgQ0KMzgg6ZKf6KGo55y86ZWc
DQozOSDoh6rooYzovaYNCjQwIOWMhQ0KDQoNCuS/neivgeavj+WkqemDveacieS5sOWutuWbnuWk
jeOAgg0K5L+d6K+B5q+P5aSp6YO95pyJ5Lmw5a625Zue5aSN44CCDQrkv53or4Hmr4/lpKnpg73m
nInkubDlrrblm57lpI3jgIINCuS/neivgeavj+WkqemDveacieS5sOWutuWbnuWkjeOAgg0K5L+d
6K+B5q+P5aSp6YO95pyJ5Lmw5a625Zue5aSN44CCDQo
^ permalink raw reply
* [PATCH 02/16] macfb: fix black and white modes
From: Finn Thain @ 2011-10-23 14:11 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: linux-m68k, Florian Tobias Schandinat, linux-fbdev
In-Reply-To: <20111023141108.856998818@telegraphics.com.au>
macfb won't init in black & white modes since fb_alloc_cmap() no longer works for zero cmap length. Fix this and also clean up a few printk's and some stylistic inconsistencies.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Index: linux-m68k/drivers/video/macfb.c
=================================--- linux-m68k.orig/drivers/video/macfb.c 2011-10-22 23:02:22.000000000 +1100
+++ linux-m68k/drivers/video/macfb.c 2011-10-23 00:50:51.000000000 +1100
@@ -592,12 +592,12 @@ static int __init macfb_init(void)
if (!fb_info.screen_base)
return -ENODEV;
- printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
- macfb_fix.smem_start, fb_info.screen_base,
- macfb_fix.smem_len / 1024);
- printk("macfb: mode is %dx%dx%d, linelength=%d\n",
- macfb_defined.xres, macfb_defined.yres,
- macfb_defined.bits_per_pixel, macfb_fix.line_length);
+ pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
+ macfb_fix.smem_start, fb_info.screen_base,
+ macfb_fix.smem_len / 1024);
+ pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
+ macfb_defined.xres, macfb_defined.yres,
+ macfb_defined.bits_per_pixel, macfb_fix.line_length);
/* Fill in the available video resolution */
macfb_defined.xres_virtual = macfb_defined.xres;
@@ -613,14 +613,10 @@ static int __init macfb_init(void)
switch (macfb_defined.bits_per_pixel) {
case 1:
- /*
- * XXX: I think this will catch any program that tries
- * to do FBIO_PUTCMAP when the visual is monochrome.
- */
macfb_defined.red.length = macfb_defined.bits_per_pixel;
macfb_defined.green.length = macfb_defined.bits_per_pixel;
macfb_defined.blue.length = macfb_defined.bits_per_pixel;
- video_cmap_len = 0;
+ video_cmap_len = 2;
macfb_fix.visual = FB_VISUAL_MONO01;
break;
case 2:
@@ -660,11 +656,10 @@ static int __init macfb_init(void)
macfb_fix.visual = FB_VISUAL_TRUECOLOR;
break;
default:
- video_cmap_len = 0;
- macfb_fix.visual = FB_VISUAL_MONO01;
- printk("macfb: unknown or unsupported bit depth: %d\n",
+ pr_err("macfb: unknown or unsupported bit depth: %d\n",
macfb_defined.bits_per_pixel);
- break;
+ err = -EINVAL;
+ goto fail_unmap;
}
/*
@@ -734,8 +729,8 @@ static int __init macfb_init(void)
case MAC_MODEL_Q950:
strcpy(macfb_fix.id, "DAFB");
macfb_setpalette = dafb_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -744,8 +739,8 @@ static int __init macfb_init(void)
case MAC_MODEL_LCII:
strcpy(macfb_fix.id, "V8");
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -758,8 +753,8 @@ static int __init macfb_init(void)
case MAC_MODEL_P600:
strcpy(macfb_fix.id, "Brazil");
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -773,10 +768,10 @@ static int __init macfb_init(void)
case MAC_MODEL_P520:
case MAC_MODEL_P550:
case MAC_MODEL_P460:
- macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "Sonora");
+ macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -786,10 +781,10 @@ static int __init macfb_init(void)
*/
case MAC_MODEL_IICI:
case MAC_MODEL_IISI:
- macfb_setpalette = rbv_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "RBV");
+ macfb_setpalette = rbv_setpalette;
rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -797,10 +792,10 @@ static int __init macfb_init(void)
*/
case MAC_MODEL_Q840:
case MAC_MODEL_C660:
- macfb_setpalette = civic_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "Civic");
+ macfb_setpalette = civic_setpalette;
civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
@@ -809,26 +804,26 @@ static int __init macfb_init(void)
* We think this may be like the LC II
*/
case MAC_MODEL_LC:
+ strcpy(macfb_fix.id, "LC");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
}
- strcpy(macfb_fix.id, "LC");
break;
/*
* We think this may be like the LC II
*/
case MAC_MODEL_CCL:
+ strcpy(macfb_fix.id, "Color Classic");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
}
- strcpy(macfb_fix.id, "Color Classic");
break;
/*
@@ -893,10 +888,10 @@ static int __init macfb_init(void)
case MAC_MODEL_PB270C:
case MAC_MODEL_PB280:
case MAC_MODEL_PB280C:
- macfb_setpalette = csc_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "CSC");
+ macfb_setpalette = csc_setpalette;
csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
default:
@@ -918,8 +913,9 @@ static int __init macfb_init(void)
if (err)
goto fail_dealloc;
- printk("fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ pr_info("fb%d: %s frame buffer device\n",
+ fb_info.node, fb_info.fix.id);
+
return 0;
fail_dealloc:
^ permalink raw reply
* lxfb_core: support 800x480 panel
From: pavel @ 2011-10-23 14:00 UTC (permalink / raw)
To: linux-geode, linux-fbdev, linux-kernel
(very old message; maybe it was fixed in the meantime)
I need something like this to support full resolution of internal LCD
panel on Kohjinsha subnotebook.
(Note: I basically made up the numbers, if someone knows how to
generate them properly, let me know. It somehow works even on external
display, but last few columns are missing.)
Signed-off-by: Pavel Machek <pavel@ucw.cz>
index 889cbe3..2c04a01 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -37,6 +37,9 @@ static int vt_switch;
*/
static struct fb_videomode geode_modedb[] __initdata = {
+ /* 800x480-?? */
+ { NULL, 60, 800, 480, 25131, 72, 32, 29, 1, 136, 6,
+ 0, FB_VMODE_NONINTERLACED, 0 },
/* 640x480-60 */
{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
^ permalink raw reply related
* [PATCH v2] GIO bus support for SGI IP22/28
From: Thomas Bogendoerfer @ 2011-10-20 22:19 UTC (permalink / raw)
To: linux-mips, linux-fbdev; +Cc: ralf, FlorianSchandinat
SGI IP22/IP28 machines have GIO busses for adding graphics and other
extension cards. This patch adds support for GIO driver/device
handling and converts the newport console driver to a GIO driver.
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
Changes to last version:
- use EXPORT_SYMBOL_GPL
- ChallengeS has only 2 slots
- use subsys_initcall for gio detection
Florian, the whole patch should go through the MIPS tree, if it's ok for
you.
arch/mips/include/asm/gio_device.h | 56 +++++
arch/mips/sgi-ip22/Makefile | 2 +-
arch/mips/sgi-ip22/ip22-gio.c | 414 +++++++++++++++++++++++++++++++++++
arch/mips/sgi-ip22/ip22-mc.c | 10 +-
arch/mips/sgi-ip22/ip22-setup.c | 21 --
drivers/video/console/newport_con.c | 61 ++++--
6 files changed, 518 insertions(+), 46 deletions(-)
diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h
new file mode 100644
index 0000000..5437c84
--- /dev/null
+++ b/arch/mips/include/asm/gio_device.h
@@ -0,0 +1,56 @@
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+struct gio_device_id {
+ __u8 id;
+};
+
+struct gio_device {
+ struct device dev;
+ struct resource resource;
+ unsigned int irq;
+ unsigned int slotno;
+
+ const char *name;
+ struct gio_device_id id;
+ unsigned id32:1;
+ unsigned gio64:1;
+};
+#define to_gio_device(d) container_of(d, struct gio_device, dev)
+
+struct gio_driver {
+ const char *name;
+ struct module *owner;
+ const struct gio_device_id *id_table;
+
+ int (*probe)(struct gio_device *, const struct gio_device_id *);
+ void (*remove)(struct gio_device *);
+ int (*suspend)(struct gio_device *, pm_message_t);
+ int (*resume)(struct gio_device *);
+ void (*shutdown)(struct gio_device *);
+
+ struct device_driver driver;
+};
+#define to_gio_driver(drv) container_of(drv, struct gio_driver, driver)
+
+extern const struct gio_device_id *gio_match_device(const struct gio_device_id *,
+ const struct gio_device *);
+extern struct gio_device *gio_dev_get(struct gio_device *);
+extern void gio_dev_put(struct gio_device *);
+
+extern int gio_device_register(struct gio_device *);
+extern void gio_device_unregister(struct gio_device *);
+extern void gio_release_dev(struct device *);
+
+static inline void gio_device_free(struct gio_device *dev)
+{
+ gio_release_dev(&dev->dev);
+}
+
+extern int gio_register_driver(struct gio_driver *);
+extern void gio_unregister_driver(struct gio_driver *);
+
+#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev)
+#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data))
+
+extern void gio_set_master(struct gio_device *);
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index cc53849..411cda9 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -4,7 +4,7 @@
#
obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \
- ip22-platform.o ip22-reset.o ip22-setup.o
+ ip22-platform.o ip22-reset.o ip22-setup.o ip22-gio.o
obj-$(CONFIG_SGI_IP22) += ip22-berr.o
obj-$(CONFIG_SGI_IP28) += ip28-berr.o
diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c
new file mode 100644
index 0000000..d841529
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-gio.c
@@ -0,0 +1,414 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include <asm/addrspace.h>
+#include <asm/paccess.h>
+#include <asm/gio_device.h>
+#include <asm/sgi/gio.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/ip22.h>
+
+static struct bus_type gio_bus;
+
+static struct {
+ const char *name;
+ __u8 id;
+} gio_name_table[] = {
+ { .name = "SGI Impact", .id = 0x10 },
+ { .name = "Phobos G160", .id = 0x35 },
+ /* fake IDs */
+ { .name = "SGI Newport", .id = 0x7e },
+ { .name = "SGI GR2/GR3", .id = 0x7f },
+};
+
+/**
+ * gio_match_device - Tell if an of_device structure has a matching
+ * gio_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct gio_device_id *gio_match_device(const struct gio_device_id *match,
+ const struct gio_device *dev)
+{
+ const struct gio_device_id *ids;
+
+ for (ids = match; ids->id != 0xff; ids++)
+ if (ids->id = dev->id.id)
+ return ids;
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gio_match_device);
+
+struct gio_device *gio_dev_get(struct gio_device *dev)
+{
+ struct device *tmp;
+
+ if (!dev)
+ return NULL;
+ tmp = get_device(&dev->dev);
+ if (tmp)
+ return to_gio_device(tmp);
+ else
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gio_dev_get);
+
+void gio_dev_put(struct gio_device *dev)
+{
+ if (dev)
+ put_device(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(gio_dev_put);
+
+static ssize_t dev_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gio_device *giodev;
+
+ giodev = to_gio_device(dev);
+ return sprintf(buf, "%s", giodev->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, dev_show_name, NULL);
+
+static ssize_t dev_show_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct gio_device *giodev;
+
+ giodev = to_gio_device(dev);
+ return sprintf(buf, "%x", giodev->id.id);
+}
+
+static DEVICE_ATTR(id, S_IRUGO, dev_show_id, NULL);
+
+/**
+ * gio_release_dev - free an gio device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this gio device are
+ * done.
+ */
+void gio_release_dev(struct device *dev)
+{
+ struct gio_device *giodev;
+
+ giodev = to_gio_device(dev);
+ kfree(giodev);
+}
+EXPORT_SYMBOL_GPL(gio_release_dev);
+
+int gio_device_register(struct gio_device *giodev)
+{
+ int rc;
+
+ giodev->dev.bus = &gio_bus;
+ rc = device_register(&giodev->dev);
+ if (rc)
+ return rc;
+
+ rc = device_create_file(&giodev->dev, &dev_attr_name);
+ if (rc)
+ goto err;
+ rc = device_create_file(&giodev->dev, &dev_attr_id);
+ if (rc)
+ goto err;
+
+ return 0;
+
+err:
+ device_unregister(&giodev->dev);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(gio_device_register);
+
+void gio_device_unregister(struct gio_device *giodev)
+{
+ device_remove_file(&giodev->dev, &dev_attr_id);
+ device_remove_file(&giodev->dev, &dev_attr_name);
+ device_unregister(&giodev->dev);
+}
+EXPORT_SYMBOL_GPL(gio_device_unregister);
+
+static int gio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *gio_drv = to_gio_driver(drv);
+
+ return gio_match_device(gio_drv->id_table, gio_dev) != NULL;
+}
+
+static int gio_device_probe(struct device *dev)
+{
+ int error = -ENODEV;
+ struct gio_driver *drv;
+ struct gio_device *gio_dev;
+ const struct gio_device_id *match;
+
+ drv = to_gio_driver(dev->driver);
+ gio_dev = to_gio_device(dev);
+
+ if (!drv->probe)
+ return error;
+
+ gio_dev_get(gio_dev);
+
+ match = gio_match_device(drv->id_table, gio_dev);
+ if (match)
+ error = drv->probe(gio_dev, match);
+ if (error)
+ gio_dev_put(gio_dev);
+
+ return error;
+}
+
+static int gio_device_remove(struct device *dev)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+
+ if (dev->driver && drv->remove)
+ drv->remove(gio_dev);
+ return 0;
+}
+
+static int gio_device_suspend(struct device *dev, pm_message_t state)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->suspend)
+ error = drv->suspend(gio_dev, state);
+ return error;
+}
+
+static int gio_device_resume(struct device *dev)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->resume)
+ error = drv->resume(gio_dev);
+ return error;
+}
+
+static void gio_device_shutdown(struct device *dev)
+{
+ struct gio_device *gio_dev = to_gio_device(dev);
+ struct gio_driver *drv = to_gio_driver(dev->driver);
+
+ if (dev->driver && drv->shutdown)
+ drv->shutdown(gio_dev);
+}
+
+int gio_register_driver(struct gio_driver *drv)
+{
+ /* initialize common driver fields */
+ if (!drv->driver.name)
+ drv->driver.name = drv->name;
+ if (!drv->driver.owner)
+ drv->driver.owner = drv->owner;
+ drv->driver.bus = &gio_bus;
+
+ /* register with core */
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(gio_register_driver);
+
+void gio_unregister_driver(struct gio_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(gio_unregister_driver);
+
+void gio_set_master(struct gio_device *dev)
+{
+ u32 tmp = sgimc->giopar;
+
+ switch (dev->slotno) {
+ case 0:
+ tmp |= SGIMC_GIOPAR_MASTERGFX;
+ break;
+ case 1:
+ tmp |= SGIMC_GIOPAR_MASTEREXP0;
+ break;
+ case 2:
+ tmp |= SGIMC_GIOPAR_MASTEREXP1;
+ break;
+ }
+ sgimc->giopar = tmp;
+}
+EXPORT_SYMBOL_GPL(gio_set_master);
+
+void ip22_gio_set_64bit(int slotno)
+{
+ u32 tmp = sgimc->giopar;
+
+ switch (slotno) {
+ case 0:
+ tmp |= SGIMC_GIOPAR_GFX64;
+ break;
+ case 1:
+ tmp |= SGIMC_GIOPAR_EXP064;
+ break;
+ case 2:
+ tmp |= SGIMC_GIOPAR_EXP164;
+ break;
+ }
+ sgimc->giopar = tmp;
+}
+
+static int ip22_gio_id(unsigned long addr, u32 *res)
+{
+ u8 tmp8;
+ u8 tmp16;
+ u32 tmp32;
+ u8 *ptr8;
+ u16 *ptr16;
+ u32 *ptr32;
+
+ ptr32 = (void *)CKSEG1ADDR(addr);
+ if (!get_dbe(tmp32, ptr32)) {
+ /*
+ * We got no DBE, but this doesn't mean anything.
+ * If GIO is pipelined (which can't be disabled
+ * for GFX slot) we don't get a DBE, but we see
+ * the transfer size as data. So we do an 8bit
+ * and a 16bit access and check whether the common
+ * data matches
+ */
+ ptr8 = (void *)CKSEG1ADDR(addr + 3);
+ get_dbe(tmp8, ptr8);
+ ptr16 = (void *)CKSEG1ADDR(addr + 2);
+ get_dbe(tmp16, ptr16);
+ if (tmp8 = (tmp16 & 0xff) &&
+ tmp8 = (tmp32 & 0xff) &&
+ tmp16 = (tmp32 & 0xffff)) {
+ *res = tmp32;
+ return 1;
+ }
+ }
+ return 0; /* nothing here */
+}
+
+#define HQ2_MYSTERY_OFFS 0x6A07C
+#define NEWPORT_USTATUS_OFFS 0xF133C
+
+static int ip22_is_gr2(unsigned long addr)
+{
+ u32 tmp;
+ u32 *ptr;
+
+ /* HQ2 only allows 32bit accesses */
+ ptr = (void *)CKSEG1ADDR(addr + HQ2_MYSTERY_OFFS);
+ if (!get_dbe(tmp, ptr)) {
+ if (tmp = 0xdeadbeef)
+ return 1;
+ }
+ return 0;
+}
+
+
+static void ip22_check_gio(int slotno, unsigned long addr)
+{
+ const char *name = "Unknown";
+ struct gio_device *gio_dev;
+ u32 tmp;
+ __u8 id;
+ int i;
+
+ /* first look for GR2/GR3 by checking mystery register */
+ if (ip22_is_gr2(addr))
+ tmp = 0x7f;
+ else {
+ if (!ip22_gio_id(addr, &tmp)) {
+ /*
+ * no GIO signature at start address of slot, but
+ * Newport doesn't have one, so let's check usea
+ * status register
+ */
+ if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp))
+ tmp = 0x7e;
+ else
+ tmp = 0;
+ }
+ }
+ if (tmp) {
+ id = GIO_ID(tmp);
+ if (tmp & GIO_32BIT_ID) {
+ if (tmp & GIO_64BIT_IFACE)
+ ip22_gio_set_64bit(slotno);
+ }
+ for (i = 0; i < ARRAY_SIZE(gio_name_table); i++) {
+ if (id = gio_name_table[i].id) {
+ name = gio_name_table[i].name;
+ break;
+ }
+ }
+ printk(KERN_INFO "GIO: slot %d : %s (id %x)\n",
+ slotno, name, id);
+ gio_dev = kzalloc(sizeof *gio_dev, GFP_KERNEL);
+ gio_dev->name = name;
+ gio_dev->slotno = slotno;
+ gio_dev->id.id = id;
+ gio_dev->resource.start = addr;
+ gio_dev->resource.end = addr + 0x3fffff;
+ gio_dev->resource.flags = IORESOURCE_MEM;
+ dev_set_name(&gio_dev->dev, "gio%d", slotno);
+ gio_device_register(gio_dev);
+ } else
+ printk(KERN_INFO "GIO: slot %d : Empty\n", slotno);
+}
+
+static struct bus_type gio_bus = {
+ .name = "gio",
+ .match = gio_bus_match,
+ .probe = gio_device_probe,
+ .remove = gio_device_remove,
+ .suspend = gio_device_suspend,
+ .resume = gio_device_resume,
+ .shutdown = gio_device_shutdown,
+};
+
+static struct resource gio_bus_resource = {
+ .start = GIO_SLOT_GFX_BASE,
+ .end = GIO_SLOT_GFX_BASE + 0x9fffff,
+ .name = "GIO Bus",
+ .flags = IORESOURCE_MEM,
+};
+
+int __init ip22_gio_init(void)
+{
+ unsigned int pbdma __maybe_unused;
+ int ret;
+
+ ret = bus_register(&gio_bus);
+ if (!ret) {
+ request_resource(&iomem_resource, &gio_bus_resource);
+ printk(KERN_INFO "GIO: Probing bus...\n");
+
+ if (ip22_is_fullhouse() ||
+ !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) {
+ /* Indigo2 and ChallengeS */
+ ip22_check_gio(0, GIO_SLOT_GFX_BASE);
+ ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
+ } else {
+ /* Indy */
+ ip22_check_gio(0, GIO_SLOT_GFX_BASE);
+ ip22_check_gio(1, GIO_SLOT_EXP0_BASE);
+ ip22_check_gio(2, GIO_SLOT_EXP1_BASE);
+ }
+ }
+ return ret;
+}
+
+subsys_initcall(ip22_gio_init);
+
diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c
index d22262e..75ada8a 100644
--- a/arch/mips/sgi-ip22/ip22-mc.c
+++ b/arch/mips/sgi-ip22/ip22-mc.c
@@ -139,11 +139,11 @@ void __init sgimc_init(void)
* zero.
*/
/* don't touch parity settings for IP28 */
-#ifndef CONFIG_SGI_IP28
tmp = sgimc->cpuctrl0;
- tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
- SGIMC_CCTRL0_R4KNOCHKPARR);
+#ifndef CONFIG_SGI_IP28
+ tmp |= SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM;
#endif
+ tmp |= SGIMC_CCTRL0_R4KNOCHKPARR;
sgimc->cpuctrl0 = tmp;
/* Step 3: Setup the MC write buffer depth, this is controlled
@@ -178,7 +178,8 @@ void __init sgimc_init(void)
*/
/* First the basic invariants across all GIO64 implementations. */
- tmp = SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
+ tmp = sgimc->giopar & SGIMC_GIOPAR_GFX64; /* keep gfx 64bit settings */
+ tmp |= SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */
tmp |= SGIMC_GIOPAR_ONEBUS; /* Only one physical GIO bus exists */
if (ip22_is_fullhouse()) {
@@ -193,7 +194,6 @@ void __init sgimc_init(void)
tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp[01] pipelined */
tmp |= SGIMC_GIOPAR_PLINEEXP1;
tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */
- tmp |= SGIMC_GIOPAR_GFX64; /* GFX at 64 bits */
}
} else {
/* Guiness specific settings. */
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 5e66213..c7bdfe4 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -26,9 +26,6 @@
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>
-unsigned long sgi_gfxaddr;
-EXPORT_SYMBOL_GPL(sgi_gfxaddr);
-
extern void ip22_be_init(void) __init;
void __init plat_mem_setup(void)
@@ -78,22 +75,4 @@ void __init plat_mem_setup(void)
prom_flags |= PROM_FLAG_USE_AS_CONSOLE;
add_preferred_console("arc", 0, NULL);
}
-
-#if defined(CONFIG_VT) && defined(CONFIG_SGI_NEWPORT_CONSOLE)
- {
- ULONG *gfxinfo;
- ULONG * (*__vec)(void) = (void *) (long)
- *((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20));
-
- gfxinfo = __vec();
- sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000
- && gfxinfo[1] <= 0xc0000000)
- ? gfxinfo[1] - 0xa0000000 : 0);
-
- /* newport addresses? */
- if (sgi_gfxaddr = 0x1f0f0000 || sgi_gfxaddr = 0x1f4f0000) {
- conswitchp = &newport_con;
- }
- }
-#endif
}
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 93317b5..628b7ec 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -25,14 +25,13 @@
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/gio_device.h>
+
#include <video/newport.h>
#include <linux/linux_logo.h>
#include <linux/font.h>
-
-extern unsigned long sgi_gfxaddr;
-
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
/* borrowed from fbcon.c */
@@ -304,12 +303,6 @@ static const char *newport_startup(void)
{
int i;
- if (!sgi_gfxaddr)
- return NULL;
-
- if (!npregs)
- npregs = (struct newport_regs *)/* ioremap cannot fail */
- ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
npregs->cset.config = NPORT_CFG_GD0;
if (newport_wait(npregs))
@@ -743,26 +736,56 @@ const struct consw newport_con = {
.con_save_screen = DUMMY
};
-#ifdef MODULE
-static int __init newport_console_init(void)
+static int newport_probe(struct gio_device *dev,
+ const struct gio_device_id *id)
{
- if (!sgi_gfxaddr)
- return 0;
+ unsigned long newport_addr;
- if (!npregs)
- npregs = (struct newport_regs *)/* ioremap cannot fail */
- ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
+ if (!dev->resource.start)
+ return -EINVAL;
+
+ if (npregs)
+ return -EBUSY; /* we only support one Newport as console */
+
+ newport_addr = dev->resource.start + 0xF0000;
+ if (!request_mem_region(newport_addr, 0x10000, "Newport"))
+ return -ENODEV;
+
+ npregs = (struct newport_regs *)/* ioremap cannot fail */
+ ioremap(newport_addr, sizeof(struct newport_regs));
return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
}
-module_init(newport_console_init);
-static void __exit newport_console_exit(void)
+static void newport_remove(struct gio_device *dev)
{
give_up_console(&newport_con);
iounmap((void *)npregs);
}
+
+static struct gio_device_id newport_ids[] = {
+ { .id = 0x7e },
+ { .id = 0xff }
+};
+
+static struct gio_driver newport_driver = {
+ .name = "newport",
+ .id_table = newport_ids,
+ .probe = newport_probe,
+ .remove = newport_remove,
+};
+
+int __init newport_console_init(void)
+{
+ return gio_register_driver(&newport_driver);
+}
+
+void __exit newport_console_exit(void)
+{
+ gio_unregister_driver(&newport_driver);
+}
+
+module_init(newport_console_init);
module_exit(newport_console_exit);
-#endif
MODULE_LICENSE("GPL");
^ permalink raw reply related
* Re: [PATCH 4/4] fbdev/cirrusfb: Add support for "64 MiB" version
From: Jeff Garzik @ 2011-10-20 17:03 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies, linux-kernel, Ingo Jürgensmann
In-Reply-To: <1319110945-25684-4-git-send-email-geert@linux-m68k.org>
On 10/20/2011 07:42 AM, Geert Uytterhoeven wrote:
> Some Village Tronic Picasso IV graphics cards identify as a 64 MiB Zorro
> device in Zorro III mode.
>
> While the total graphics memory size is the same on such cards, the offset
> of the graphics memory differs. Add a quirk to handle this.
>
> Based on src/sys/arch/amiga/dev/grf_cl.c from NetBSD.
>
> Signed-off-by: Geert Uytterhoeven<geert@linux-m68k.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
^ permalink raw reply
* Re: [PATCH 3/4] fbdev/cirrusfb: Add support for Picasso IV in Zorro
From: Jeff Garzik @ 2011-10-20 17:03 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies, linux-kernel, Ingo Jürgensmann
In-Reply-To: <1319110945-25684-3-git-send-email-geert@linux-m68k.org>
On 10/20/2011 07:42 AM, Geert Uytterhoeven wrote:
> In Zorro II mode, the Village Tronic Picasso IV graphics card shows up as
> either 2 or 3 Zorro devices:
> - One for the registers of the Cirrus Logic graphics chip,
> - One for the first bank of 2 MiB of graphics memory,
> - An optional one for the second bank of 2 MiB of graphics memory,
> if there was enough free Zorro II address space.
>
> Based on src/sys/arch/amiga/dev/grf_cl.c from NetBSD.
>
> Signed-off-by: Geert Uytterhoeven<geert@linux-m68k.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
^ permalink raw reply
* Re: [PATCH 2/4] fbdev/cirrusfb: Rewrite Zorro graphics card probing
From: Jeff Garzik @ 2011-10-20 17:03 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies, linux-kernel, Ingo Jürgensmann
In-Reply-To: <1319110945-25684-2-git-send-email-geert@linux-m68k.org>
On 10/20/2011 07:42 AM, Geert Uytterhoeven wrote:
> As indicated by commit a7f4d00a82feb5b311f765bf9522bc55bee0684f ("zorro:
> Defer device_register() until all devices have been identified"), cirrusfb
> crashes if zorro_find_device() cannot find an expected device.
>
> Rewrite the Zorro device probe code to make it more robust, easier to
> understand, and more extensible.
>
> Other logical changes:
> - For cards that show up as 2 Zorro devices, autoprobe graphics memory
> sizes based on the size of the Zorro device containing the graphics
> memory.
> Acording to the NetBSD sources, this is safe.
>
> Signed-off-by: Geert Uytterhoeven<geert@linux-m68k.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
^ permalink raw reply
* [PATCH 4/4] fbdev/cirrusfb: Add support for "64 MiB" version of Picasso IV
From: Geert Uytterhoeven @ 2011-10-20 11:42 UTC (permalink / raw)
To: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies
Cc: linux-kernel, Ingo Jürgensmann, Geert Uytterhoeven
In-Reply-To: <1319110945-25684-1-git-send-email-geert@linux-m68k.org>
Some Village Tronic Picasso IV graphics cards identify as a 64 MiB Zorro
device in Zorro III mode.
While the total graphics memory size is the same on such cards, the offset
of the graphics memory differs. Add a quirk to handle this.
Based on src/sys/arch/amiga/dev/grf_cl.c from NetBSD.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
--
Untested, due to lack of hardware
---
drivers/video/cirrusfb.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 816433f..6ea505c 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -314,7 +314,7 @@ static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
.type = BT_PICASSO4,
.regoffset = 0x00600000,
.ramsize = 4 * MB_,
- .ramoffset = 0x01000000,
+ .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
};
static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
@@ -2259,6 +2259,10 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
ramsize = zcl->ramsize;
if (ramsize) {
rambase = zorro_resource_start(z) + zcl->ramoffset;
+ if (zorro_resource_len(z) = 64 * MB_) {
+ /* Quirk for 64 MiB Picasso IV */
+ rambase += zcl->ramoffset;
+ }
} else {
struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
if (!ram || !zorro_resource_len(ram)) {
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/4] fbdev/cirrusfb: Add support for Picasso IV in Zorro II mode
From: Geert Uytterhoeven @ 2011-10-20 11:42 UTC (permalink / raw)
To: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies
Cc: linux-kernel, Ingo Jürgensmann, Geert Uytterhoeven
In-Reply-To: <1319110945-25684-1-git-send-email-geert@linux-m68k.org>
In Zorro II mode, the Village Tronic Picasso IV graphics card shows up as
either 2 or 3 Zorro devices:
- One for the registers of the Cirrus Logic graphics chip,
- One for the first bank of 2 MiB of graphics memory,
- An optional one for the second bank of 2 MiB of graphics memory,
if there was enough free Zorro II address space.
Based on src/sys/arch/amiga/dev/grf_cl.c from NetBSD.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
--
Untested, due to lack of hardware
---
drivers/video/cirrusfb.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 357139a..816433f 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -287,6 +287,7 @@ struct zorrocl {
/* If zero, use autoprobe on RAM device */
u32 ramoffset; /* Offset of video RAM in first Zorro device */
zorro_id ramid; /* Zorro ID of RAM device */
+ zorro_id ramid2; /* Zorro ID of optional second RAM device */
};
static const struct zorrocl zcl_sd64 __devinitconst = {
@@ -316,6 +317,13 @@ static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
.ramoffset = 0x01000000,
};
+static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
+ .type = BT_PICASSO4,
+ .regoffset = 0x10000,
+ .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
+ .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
+};
+
static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
{
@@ -333,6 +341,9 @@ static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
}, {
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
.driver_data = (unsigned long)&zcl_picasso4_z3,
+ }, {
+ .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
+ .driver_data = (unsigned long)&zcl_picasso4_z2,
},
{ 0 }
};
@@ -2257,6 +2268,16 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
}
rambase = zorro_resource_start(ram);
ramsize = zorro_resource_len(ram);
+ if (zcl->ramid2 &&
+ (ram = zorro_find_device(zcl->ramid2, NULL))) {
+ if (zorro_resource_start(ram) != rambase + ramsize) {
+ dev_warn(info->device,
+ "Skipping non-contiguous RAM at %pR\n",
+ &ram->resource);
+ } else {
+ ramsize += zorro_resource_len(ram);
+ }
+ }
}
dev_info(info->device,
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/4] fbdev/cirrusfb: Rewrite Zorro graphics card probing
From: Geert Uytterhoeven @ 2011-10-20 11:42 UTC (permalink / raw)
To: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies
Cc: linux-kernel, Ingo Jürgensmann, Geert Uytterhoeven
In-Reply-To: <1319110945-25684-1-git-send-email-geert@linux-m68k.org>
As indicated by commit a7f4d00a82feb5b311f765bf9522bc55bee0684f ("zorro:
Defer device_register() until all devices have been identified"), cirrusfb
crashes if zorro_find_device() cannot find an expected device.
Rewrite the Zorro device probe code to make it more robust, easier to
understand, and more extensible.
Other logical changes:
- For cards that show up as 2 Zorro devices, autoprobe graphics memory
sizes based on the size of the Zorro device containing the graphics
memory.
Acording to the NetBSD sources, this is safe.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
--
Untested, due to lack of hardware
---
drivers/video/cirrusfb.c | 241 ++++++++++++++++++++++-----------------------
1 files changed, 118 insertions(+), 123 deletions(-)
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 6df7c54..357139a 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -280,52 +280,63 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
#endif /* CONFIG_PCI */
#ifdef CONFIG_ZORRO
-static const struct zorro_device_id cirrusfb_zorro_table[] = {
+struct zorrocl {
+ enum cirrus_board type; /* Board type */
+ u32 regoffset; /* Offset of registers in first Zorro device */
+ u32 ramsize; /* Size of video RAM in first Zorro device */
+ /* If zero, use autoprobe on RAM device */
+ u32 ramoffset; /* Offset of video RAM in first Zorro device */
+ zorro_id ramid; /* Zorro ID of RAM device */
+};
+
+static const struct zorrocl zcl_sd64 __devinitconst = {
+ .type = BT_SD64,
+ .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
+};
+
+static const struct zorrocl zcl_piccolo __devinitconst = {
+ .type = BT_PICCOLO,
+ .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
+};
+
+static const struct zorrocl zcl_picasso __devinitconst = {
+ .type = BT_PICASSO,
+ .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
+};
+
+static const struct zorrocl zcl_spectrum __devinitconst = {
+ .type = BT_SPECTRUM,
+ .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
+};
+
+static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
+ .type = BT_PICASSO4,
+ .regoffset = 0x00600000,
+ .ramsize = 4 * MB_,
+ .ramoffset = 0x01000000,
+};
+
+
+static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
{
- .id = ZORRO_PROD_HELFRICH_SD64_RAM,
- .driver_data = BT_SD64,
+ .id = ZORRO_PROD_HELFRICH_SD64_REG,
+ .driver_data = (unsigned long)&zcl_sd64,
}, {
- .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
- .driver_data = BT_PICCOLO,
+ .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
+ .driver_data = (unsigned long)&zcl_piccolo,
}, {
- .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
- .driver_data = BT_PICASSO,
+ .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
+ .driver_data = (unsigned long)&zcl_picasso,
}, {
- .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
- .driver_data = BT_SPECTRUM,
+ .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
+ .driver_data = (unsigned long)&zcl_spectrum,
}, {
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
- .driver_data = BT_PICASSO4,
+ .driver_data = (unsigned long)&zcl_picasso4_z3,
},
{ 0 }
};
MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
-
-static const struct {
- zorro_id id2;
- unsigned long size;
-} cirrusfb_zorro_table2[] = {
- [BT_SD64] = {
- .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
- .size = 0x400000
- },
- [BT_PICCOLO] = {
- .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
- .size = 0x200000
- },
- [BT_PICASSO] = {
- .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
- .size = 0x200000
- },
- [BT_SPECTRUM] = {
- .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
- .size = 0x200000
- },
- [BT_PICASSO4] = {
- .id2 = 0,
- .size = 0x400000
- }
-};
#endif /* CONFIG_ZORRO */
#ifdef CIRRUSFB_DEBUG
@@ -1956,16 +1967,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info)
struct cirrusfb_info *cinfo = info->par;
struct zorro_dev *zdev = to_zorro_dev(info->device);
- zorro_release_device(zdev);
-
- if (cinfo->btype = BT_PICASSO4) {
- cinfo->regbase -= 0x600000;
- iounmap((void *)cinfo->regbase);
+ if (info->fix.smem_start > 16 * MB_)
iounmap(info->screen_base);
- } else {
- if (zorro_resource_start(zdev) > 0x01000000)
- iounmap(info->screen_base);
- }
+ if (info->fix.mmio_start > 16 * MB_)
+ iounmap(cinfo->regbase);
+
+ zorro_release_device(zdev);
}
#endif /* CONFIG_ZORRO */
@@ -2222,115 +2229,102 @@ static struct pci_driver cirrusfb_pci_driver = {
static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
const struct zorro_device_id *ent)
{
- struct cirrusfb_info *cinfo;
struct fb_info *info;
+ int error;
+ const struct zorrocl *zcl;
enum cirrus_board btype;
- struct zorro_dev *z2 = NULL;
- unsigned long board_addr, board_size, size;
- int ret;
-
- btype = ent->driver_data;
- if (cirrusfb_zorro_table2[btype].id2)
- z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
- size = cirrusfb_zorro_table2[btype].size;
+ unsigned long regbase, ramsize, rambase;
+ struct cirrusfb_info *cinfo;
info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
if (!info) {
printk(KERN_ERR "cirrusfb: could not allocate memory\n");
- ret = -ENOMEM;
- goto err_out;
+ return -ENOMEM;
}
- dev_info(info->device, "%s board detected\n",
- cirrusfb_board_info[btype].name);
-
- cinfo = info->par;
- cinfo->btype = btype;
-
- assert(z);
- assert(btype != BT_NONE);
+ zcl = (const struct zorrocl *)ent->driver_data;
+ btype = zcl->type;
+ regbase = zorro_resource_start(z) + zcl->regoffset;
+ ramsize = zcl->ramsize;
+ if (ramsize) {
+ rambase = zorro_resource_start(z) + zcl->ramoffset;
+ } else {
+ struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
+ if (!ram || !zorro_resource_len(ram)) {
+ dev_err(info->device, "No video RAM found\n");
+ error = -ENODEV;
+ goto err_release_fb;
+ }
+ rambase = zorro_resource_start(ram);
+ ramsize = zorro_resource_len(ram);
+ }
- board_addr = zorro_resource_start(z);
- board_size = zorro_resource_len(z);
- info->screen_size = size;
+ dev_info(info->device,
+ "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
+ cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
+ rambase);
if (!zorro_request_device(z, "cirrusfb")) {
- dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
- board_addr);
- ret = -EBUSY;
+ dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
+ error = -EBUSY;
goto err_release_fb;
}
- ret = -EIO;
-
- if (btype = BT_PICASSO4) {
- dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
-
- /* To be precise, for the P4 this is not the */
- /* begin of the board, but the begin of RAM. */
- /* for P4, map in its address space in 2 chunks (### TEST! ) */
- /* (note the ugly hardcoded 16M number) */
- cinfo->regbase = ioremap(board_addr, 16777216);
- if (!cinfo->regbase)
- goto err_release_region;
-
- dev_dbg(info->device, "Virtual address for board set to: $%p\n",
- cinfo->regbase);
- cinfo->regbase += 0x600000;
- info->fix.mmio_start = board_addr + 0x600000;
-
- info->fix.smem_start = board_addr + 16777216;
- info->screen_base = ioremap(info->fix.smem_start, 16777216);
- if (!info->screen_base)
- goto err_unmap_regbase;
- } else {
- dev_info(info->device, " REG at $%lx\n",
- (unsigned long) z2->resource.start);
-
- info->fix.smem_start = board_addr;
- if (board_addr > 0x01000000)
- info->screen_base = ioremap(board_addr, board_size);
- else
- info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
- if (!info->screen_base)
- goto err_release_region;
+ cinfo = info->par;
+ cinfo->btype = btype;
- /* set address for REG area of board */
- cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
- info->fix.mmio_start = z2->resource.start;
+ info->fix.mmio_start = regbase;
+ cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
+ : (caddr_t)ZTWO_VADDR(regbase);
+ if (!cinfo->regbase) {
+ dev_err(info->device, "Cannot map registers\n");
+ error = -EIO;
+ goto err_release_dev;
+ }
- dev_dbg(info->device, "Virtual address for board set to: $%p\n",
- cinfo->regbase);
+ info->fix.smem_start = rambase;
+ info->screen_size = ramsize;
+ info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
+ : (caddr_t)ZTWO_VADDR(rambase);
+ if (!info->screen_base) {
+ dev_err(info->device, "Cannot map video RAM\n");
+ error = -EIO;
+ goto err_unmap_reg;
}
+
cinfo->unmap = cirrusfb_zorro_unmap;
dev_info(info->device,
- "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
- board_size / MB_, board_addr);
-
- zorro_set_drvdata(z, info);
+ "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
+ ramsize / MB_, rambase);
/* MCLK select etc. */
if (cirrusfb_board_info[btype].init_sr1f)
vga_wseq(cinfo->regbase, CL_SEQR1F,
cirrusfb_board_info[btype].sr1f);
- ret = cirrusfb_register(info);
- if (!ret)
- return 0;
+ error = cirrusfb_register(info);
+ if (error) {
+ dev_err(info->device, "Failed to register device, error %d\n",
+ error);
+ goto err_unmap_ram;
+ }
- if (btype = BT_PICASSO4 || board_addr > 0x01000000)
+ zorro_set_drvdata(z, info);
+ return 0;
+
+err_unmap_ram:
+ if (rambase > 16 * MB_)
iounmap(info->screen_base);
-err_unmap_regbase:
- if (btype = BT_PICASSO4)
- iounmap(cinfo->regbase - 0x600000);
-err_release_region:
- release_region(board_addr, board_size);
+err_unmap_reg:
+ if (regbase > 16 * MB_)
+ iounmap(cinfo->regbase);
+err_release_dev:
+ zorro_release_device(z);
err_release_fb:
framebuffer_release(info);
-err_out:
- return ret;
+ return error;
}
void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
@@ -2338,6 +2332,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
struct fb_info *info = zorro_get_drvdata(z);
cirrusfb_cleanup(info);
+ zorro_set_drvdata(z, NULL);
}
static struct zorro_driver cirrusfb_zorro_driver = {
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/4] zorro: Rename Picasso IV Z2 "MEM" to "RAM" for consistency
From: Geert Uytterhoeven @ 2011-10-20 11:42 UTC (permalink / raw)
To: Florian Tobias Schandinat, linux-fbdev, linux-m68k,
Christian T. Steigies
Cc: linux-kernel, Ingo Jürgensmann, Geert Uytterhoeven
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
include/linux/zorro_ids.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/zorro_ids.h b/include/linux/zorro_ids.h
index 7e74908..74bc53b 100644
--- a/include/linux/zorro_ids.h
+++ b/include/linux/zorro_ids.h
@@ -360,8 +360,8 @@
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0)
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0)
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE ZORRO_ID(VILLAGE_TRONIC, 0x0D, 0)
-#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0)
-#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0)
+#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0)
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0)
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0)
#define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0)
--
1.7.0.4
^ permalink raw reply related
* Re:
From: Wayne Johnson @ 2011-10-20 0:40 UTC (permalink / raw)
To: linux-fbdev
--1006711009-1319071212=:21299
Content-transfer-encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
--1006711009-1319071212=:21299
Content-Disposition: attachment; filename="bn1840572.pdf"
Content-Transfer-Encoding: base64
Content-Type: application/pdf; charset=UTF-8; name="bn1840572.pdf"
Content-Length: 32299
JVBERi0xLjQKJf////8KMjMgMCBvYmoKPDwvTGVuZ3RoIDI0OTgKL1N1YnR5cGUgL1hNTAovVHlw
ZSAvTWV0YWRhdGEKPj4Kc3RyZWFtCjw/eHBhY2tldCBiZWdpbj0n77u/JyBpZD0nVzVNME1wQ2Vo
aUh6cmVTek5UY3prYzlkJz8+Cjx4OnhtcG1ldGEgeDp4bXB0az0iMy4xLTcwMSIgeG1sbnM6eD0i
YWRvYmU6bnM6bWV0YS8iPgogIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcv
MTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91
dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICA8eG1w
OkNyZWF0ZURhdGU+MjAxMS0xMC0yMFQwMDoxOTozOFo8L3htcDpDcmVhdGVEYXRlPgogICAgICA8
eG1wOkNyZWF0b3JUb29sPk5pdHJvIFBERiBQcm9mZXNzaW9uYWwgICg2LCAxLCAwLCAzMCk8L3ht
cDpDcmVhdG9yVG9vbD4KICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTEtMTAtMjBUMDA6MTk6Mzha
PC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxMS0xMC0yMFQwMDox
OTozOFo8L3htcDpNZXRhZGF0YURhdGU+CiAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgIDxyZGY6
RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxl
bWVudHMvMS4xLyI+CiAgICAgIDxkYzpmb3JtYXQ+YXBwbGljYXRpb24vcGRmPC9kYzpmb3JtYXQ+
CiAgICAgIDxkYzpjcmVhdG9yPgogICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgPHJkZjpsaT48
L3JkZjpsaT4KICAgICAgICA8L3JkZjpTZXE+CiAgICAgIDwvZGM6Y3JlYXRvcj4KICAgICAgPGRj
OnRpdGxlPgogICAgICAgIDxyZGY6QWx0PgogICAgICAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1k
ZWZhdWx0Ij48L3JkZjpsaT4KICAgICAgICA8L3JkZjpBbHQ+CiAgICAgIDwvZGM6dGl0bGU+CiAg
ICAgIDxkYzpkZXNjcmlwdGlvbj4KICAgICAgICA8cmRmOkFsdD4KICAgICAgICAgIDxyZGY6bGkg
eG1sOmxhbmc9IngtZGVmYXVsdCIvPgogICAgICAgIDwvcmRmOkFsdD4KICAgICAgPC9kYzpkZXNj
cmlwdGlvbj4KICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6
YWJvdXQ9IiIgeG1sbnM6cGRmPSJodHRwOi8vbnMuYWRvYmUuY29tL3BkZi8xLjMvIj4KICAgICAg
PHBkZjpLZXl3b3Jkcz48L3BkZjpLZXl3b3Jkcz4KICAgICAgPHBkZjpQcm9kdWNlcj5OaXRybyBQ
REYgUHJvZmVzc2lvbmFsICAoNiwgMSwgMCwgMzApPC9wZGY6UHJvZHVjZXI+CiAgICA8L3JkZjpE
ZXNjcmlwdGlvbj4KICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1N
PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4KICAgICAgPHhtcE1NOkRvY3VtZW50
SUQ+dXVpZDo3MWZhYTZmNS0zNjY4LTQ0ODYtYWE4My05M2MyYTc3MDMyMWY8L3htcE1NOkRvY3Vt
ZW50SUQ+CiAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgog
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQo8P3hwYWNr
ZXQgZW5kPSd3Jz8+CmVuZHN0cmVhbQplbmRvYmoKMjIgMCBvYmoKPDwvQ3JlYXRpb25EYXRlIChE
OjIwMTExMDIwMDAxOTM4WikKL0NyZWF0b3IgKP7/AE4AaQB0AHIAbwAgAFAARABGACAAUAByAG8A
ZgBlAHMAcwBpAG8AbgBhAGwAIAAgAFwoADYALAAgADEALAAgADAALAAgADMAMABcKSkKL01vZERh
dGUgKEQ6MjAxMTEwMjAwMDE5MzhaKQovUHJvZHVjZXIgKP7/AE4AaQB0AHIAbwAgAFAARABGACAA
UAByAG8AZgBlAHMAcwBpAG8AbgBhAGwAIAAgAFwoADYALAAgADEALAAgADAALAAgADMAMABcKSkK
Pj4KZW5kb2JqCjIxIDAgb2JqCjw8L0RlY29kZVBhcm1zIFtudWxsIF0KL0ZpbHRlciBbL0ZsYXRl
RGVjb2RlIF0KL0xlbmd0aCAzNgo+PgpzdHJlYW0KeNpiAAAAAP//YmBgaGBm0OI4IMCgcKIjAQAA
AP//AwAR0wNWCmVuZHN0cmVhbQplbmRvYmoKMjAgMCBvYmoKPDwvRGVjb2RlUGFybXMgW251bGwg
XQovRmlsdGVyIFsvRmxhdGVEZWNvZGUgXQovTGVuZ3RoIDcwCj4+CnN0cmVhbQp42mJgoBAw4pFj
YmDGKs4CxKxAzIYkxg6lORg4sejgwusGbiQ2DwMvmAYAAAD//+KD8vmhtABchSCDEAAAAP//AwAi
JQCsCmVuZHN0cmVhbQplbmRvYmoKMTkgMCBvYmoKPDwvRGVjb2RlUGFybXMgW251bGwgXQovRmls
dGVyIFsvRmxhdGVEZWNvZGUgXQovTGVuZ3RoIDg3MzYKL0xlbmd0aDEgMAo+PgpzdHJlYW0KeNos
Un1M1VUYft5zfueC48IfzQ+4agE2J1Jzslm5XOHHbBWu/Mz83BWRi3m9lyvGzRgCptQaLd2VBYoO
0YljpmNXJyw/p+Yf3aBsfTgHQluCa3nX5pgav9NDa8/e/X7POed93+d9zqmI7CzBONRAo7D4w4ps
7+Cz9wAcBjwrtoRLg95N0WX8TzK2l277aEvl4pa1QPoGYPzZQIl/893yUAaQy8BLAS743boU8kXk
zweCFdFYauur5AHyt7aFiv3BvMlTyTvJZwT90XCtM+yQ3yHPDkdKwrvW9L1N/gRIu2S6kcXwmZPI
cqYjE7D3GUNjX7fMDo3tj33VA2Zf+D+AdpyWMpzGZVyTJLPOoAtx3MIkLOJcVYihHh6s4cpnWEYY
rscky8YxC630oRUJnn0P1ejGRMm0w9iNvfo2s/YiHbmYj3cRQoMU2Z1Yh35nD15GEbYjLDV2tf3C
HrDHcQJd+pYdRRp8KCYS9i/zq72LF5lxEE3olwPjzqGQXWp4sgURNOv1jthS+4QKclBJDQ6WICFX
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
7JAJSchWPUKE+AoRYjubAbrHIan1iLluDhGTBp8AXCPoOFNFxJ4Rm89Nxb/z35hyiDo+7Z/OYktL
EsEdtdxWNnwKKrO5pAdfCn8PgsMAhUUtMfZhHhtiUn1PcMxjlo25MraQptQtoYkYTTIlNBadLCYp
/QUAAP//AwAmfYOqCmVuZHN0cmVhbQplbmRvYmoKMTggMCBvYmoKWzMyIDMyIDI3NyA0NiA0NiAy
NzcgNDcgNDcgMjc3IDU4IDU4IDI3NyA2MCA2MCA1ODMgNjIgNjIgNTgzIDY4IDY4IDcyMiA3MiA3
MiA3MjIgNzMgNzMgMjc3IDgzIDgzIDY2NiA5OCA5OCA1NTYgMTA0IDEwNCA1NTYgMTA1IDEwNSAy
MjIgMTA4IDEwOCAyMjIgMTEyIDExMiA1NTYgMTE2IDExNiAyNzcgMTIxIDEyMSA1MDAgMTIyIDEy
MiA1MDAgXQplbmRvYmoKMTcgMCBvYmoKPDwvRGVjb2RlUGFybXMgW251bGwgXQovRmlsdGVyIFsv
RmxhdGVEZWNvZGUgXQovTGVuZ3RoIDIyCj4+CnN0cmVhbQp42mIAAAAA//9iAAAAAP//AwAAAgAB
CmVuZHN0cmVhbQplbmRvYmoKMTYgMCBvYmoKPDwvRGVjb2RlUGFybXMgW251bGwgXQovRmlsdGVy
IFsvRmxhdGVEZWNvZGUgXQovTGVuZ3RoIDQ0NjUKL0xlbmd0aDEgMAo+PgpzdHJlYW0KeNosUn1M
1VUYfp5zDje6czjdqBhBlLWMSxtNMnKXRaumznDN7lVkNfkQuW1cuRkQzg8Iq63VCqWPO3H+EfnH
lQ8NbK25VZvoYnLVgoDmH7Q+VyzIVuuf7nl7RX9n53f2vOf9Os/ztu5pa8St6IJFZUN7a9H6FwKT
AI4Bt7y1K9EUTz6cuwnIXg1kzTY1790Vnl84DeSoC3bHGut27jg6qCBnt+K1MTX0ZU4GFH+k+N5Y
vLWjCWmn+CvFrrmloe6R65HImbiO43UdiSOBZVbxFcVFiT2NiZHe1ArFfwLBj92v6nQE+XoW2noU
AjJ3c//gD+qd3vuMiJnR6MjNfeOL6Hpv6R9h1Y0TOzGFOA7jA7Wt4SWkUInlap+CJViNMHrxMr5F
VK6p9W70YxEleBQx8ViBTngeQD8NjEaVYxKN6DFhG3LzIIpZagfYjQc1SwTv43Zc1ozFElQ8agpM
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
EeXa34AqWbLLpeaH5Mw/aWc2hiQQVax2dtY7X2b8GG88qKWk3/TzRXZ7K2Hj8tA8/HCwvvdFzBn8
cmxOmtmcPsAzqWU/j772s181mX2myd+aPMI7R1/3hbFrbDuiMHZIyX5RGRq7zjGtV4ZCTjiwcF0U
wElpDiziwHrB1Y0d4jZJjbm65uozXN7ijsg5f2JammnNMoNZZqCZQcksjBk+xSw9AtcMX3p8xdTf
wGzOZabuZtht/qexAjw2ynsJlUa+7YQofnZzeW5mwzPLKqDHRmXV9Mk/+3ZOOgj/sJEdiqxnCyv3
ktf2LCGzZ4scEueknyftUPz22p5jB0Leu0EjnQl3/RQubwRznAXkrEGx3HSOOSWzS7FSipVSLLft
6lg66zEt30FX4re41vfGcgUT2K9y2d1YuzjQ2bzPzavqwyKwO1jG0mQFy9z3KGTa6mx1yIRvGZlW
qQIuTebVPq8+sLvStIbL63YXTOe7wK5UOXljV0pFp+pUkdZdRTEKPSZQoCLAK+is6P+3j7gb0958
g/JD79ELSskI9DNVMZC3iIaJ8+dZjJ6Zmk4CUC8bZUYTxoLuVMyQIjAu00YxNKIboJP8BwAA//+C
iAEAAAD//wMADTdxlQplbmRzdHJlYW0KZW5kb2JqCjE1IDAgb2JqCltdCmVuZG9iagoxNCAwIG9i
ago8PC9CaXRzUGVyQ29tcG9uZW50IDEKL0NvbG9yU3BhY2UgMTIgMCBSCi9EZWNvZGVQYXJtcyBb
bnVsbCBdCi9GaWx0ZXIgWy9GbGF0ZURlY29kZSBdCi9IZWlnaHQgMTI3Ci9MZW5ndGggMzc1Nwov
U3VidHlwZSAvSW1hZ2UKL1R5cGUgL1hPYmplY3QKL1dpZHRoIDcxNwo+PgpzdHJlYW0KeNr6DwAA
AP//7Mw9TsMwFADgkbErEhK5BRSh0mtwAyZkoQxBCW0HpDL2ApV6AiSkDB7SKiNjttLiRIYFljqv
U15VxzFOStUODGFg41nvx7bep/8oVvpf3pPztqmj4vtaQFlDk4lJUk2b6JmzDVJLVrxcM7LcyWWo
SvtZ7tWSpZGL0sHK49sPWT7vjEIXejfXk5O1ypvX0Ph4fodx6x5RDMi4dfPU1X1m3bqHd6fWkll9
3V/mJ+N2Y7Dyjpn1UEeerGWBj0NMz2OwEwa4cIgdi6Cj3Rk4Zy/elMMluNqN7KkdI8FmOku9GvLS
y1BFzMNYXgBhAYd5Zjp3vFz5WUSjK6FH/kLlKiQCWKYjX/hC1pAxQKL4q8SJ7KbAJqHZNh0cqhTN
OOUk1SEVSm1k7HEq6C/k+eqgI7vi7aiSTf/ck78AAAD//+zVsU7DMBAG4IGBkY3yJAiEUB6EgZHR
Q4YONDVMTDxBi/IInUg6UFvQPawgqxyeGEJ6FZHiilNiXLokndKJhelk6fTpJPt+87V8xbL3g11v
JX/utJAxxnOS96aiokzBBKuZXP3CERHLJBMAHmeKiDgoMDaUTDFl28keyUOTUUEpxD37K8ffGFLO
ZgIFhLLPVE55HwYQIwh0smkhz/2Q01vkD6jwP5JuYJNu5mqEskwvJkMUeMYnbJaW6TGeJP6dHDr5
9bmF/Ljk3Gh25BvcQz0vrXbXp/EWZLX/cjmFYDG2TyA6VedmEetlj08hgofTVonUWCmqrzBsNHtb
Zl1ZP5v6Cstmr+Bbyo232UikDfn6/0/5Y/kHAAD//xo1edTkUZNHrskAAAAA//8aNXnU5FGTR67J
AAAAAP//lJhNaxNBGICVHnoqOXoQ2z8giKdaSpNfIqH00EtlhUBj3SZ7EMxJj3qp6R+olBLoWtbN
W8jBk9lbq2x33wbBFdrspIbsJH0zM04+mkZvwl5mGZ599+PwPPsfZMFx4Ik3Qno8scJuCkYn+yml
8u8n/sfGW2AYn+zWWMXAAx29T4zJEUwZqMKJyVI0vlw70spr3ZJpOmuH5FSpu51eHBom/EOeGKiC
iX9yPvZfpu9I3gow8ums1QODZHluHu0PlVsfnMbk0+1M10i9aRxmumYCUF14fVpqqNop5xuFxq/V
FqIq7T18NFtbrf2Q99dayPfnDq7OLza2H/efWOFCyRUJMdvfp9oLc/7eq4bdagwforBzyPf4s/IB
8uXEgqP4Zd0sqyOP8zX3LHrKsijNchxzN7/ii4sHLMvLnbfNMFqrNiXPBF6uImLO8k6W3PVPLG+G
Np0NyNfikKHnJ2Sto2c3laXTTzenLABLPD+NK7sAggrBd1mMBbSTwi6wLUpjJvQCFB5ULsmgJkfj
EyRFrMSXKmPw9IDcE5sM0eemZSBOkYUmo1/EAozIvpSxQJ4IAGZSkVkhBkygblDKinoU5zNWItGO
NcHgxSG53zlfwG+zyzfk53Pi88ydATm+IfdnRuS73oQcDcjRiJzpz6fOW8UviTxe/It8hbqr1TuJ
oOtUKoPIlEroYm3CoaiSZQFJcnQrBypiTb0ONf+3csFpE+i6TUAhk6qw2NTTDCbAePhNXffaGrnI
TvoIuk6lZH7bTITQ5R7AJlWpaIF+C5rcC4izr3od8p/iWpNNoqoynBi5g25I+WYPDE3uYzz6vUPt
uhVWPthbCDvRshTRSrRVz/UjC91ykquSa8FSnRwn7JxFBv+o1yGdCNt0y2TTjlpfqnvcBCfgRtzZ
YUHA/gAAAP//qrr/rhjs5t//H/5/WFGT37q//vCH73+YP/wT+2PP/0/uf0N14nv+2u+H/h/4Y/u9
vMKee5+8/I9oIH/vH93f/ezVid/7vx/+9+GP7fMPP6rbDz+Xv899+P7uPfKt++/zg9MzLMv9hGfD
58QNRNUTWdb9/QzP1eeJGoj6R2wp+ocfJvLBnromj9YpoyZjNfn+73/wdH8fXOf8BVd7t8FyQOZ+
2CjKXdj4CnQgZz88w+wHVmLfIdUVRC3U5L+Y+QsAAAD//2yYMWvbQBiGC4WsHjukJn+hk90SEv+O
EEIHD14SrmAau1YtDSH11owdTKw/kJYWt/Ygy0fSIVOjzU5Qravo4CGV7sDY5/Z0Uj/ZluuQwiG+
43QPnNDdc7xiYWUxdyteJjWr5JWtyOemvEvGXNzfBXzxxsqMpb/JMiIKV3Miuuhr8/SSvBh3ssz9
/GSq8A027mSug8xPkWeH0m1duriTrX1yy9vr2knqnHyJs+P+G+ZssESzufz04MS9jcoolb9grzOS
f8883gJ2wB2/aPSF0/wAgoUDsNm7VHq2SNND6bQ2G9joKW95ybzV9rlJmkY1rFgVukNFotkozc9K
jWFUOuNpnyo9yY1+MVbsH36qowLlOdSIBasj5OkFD4NJQUP7YJCCJ7Z9azQJBYgdlRQpO1JvU55o
NlStG6GSECxdHehDTw4LPrVn5D2MEOUa6oIfI6g9jDwCvgMxHQAZeUIFbUwiZQKjccJrSgzkRLNg
JzsmE3siB5h6so8W5Im9QtYWZGuF/OvhnPx07R/5Y4onmp2RHwD5em1OblH/x3pMHvdVhxA/BEsj
koMahG0PAWtPQmgwL5zNiN7JSHXi7FgRGor8RLMSVgCrgacUhkZs+ZIMZhe0YGxVHaL7Aal2KcFQ
11VS5zNyAC0k9dkqv0V9LybrYqSMVET8RLNS4CzccSTOejG5LovklLRj8sh65tDntEKqIFgN6k2V
7sLHNW+sis1fhXTnSg4c/l42GxxGsRxWb81Czk80Cz9X0yliCZYWhkl3gxHduyrFZE5qJsPkuCu+
smkEdUuy9obNjzq54zY9lqyzJYzz6W5QVlM1M86Ow0cXLBokmhUpdz+XUoRbVnjpiLUlZ4ZL/3si
3YmCf9/36lLA0V8AAAD//wJzf4Oz3m8iyjqUoWBEvQvPzN/PoxYD38HFy3ciTEYZCkbUu/Aewwd7
bCa/H61TRk3GCu7jNPn3b3iF8/d//W+E6t+Iuu49SvV0H9qrBKp4/xc2h5EPU/XvPtxk5AT7nyST
/4NMrqmx/1cnz48wGe5mpBz0G8bbj5D4h+zjv4jWACS3ApsUn3fv//H33rv7MFVgNT9+SdQAAAAA
//+EmUFrE0EUx/UgvVh6q4LafgLpzbaENJ/Dk972IDGUQGKzyU5BbD+EbfIRWpF2LZtkWgPNRbOe
moZtdgyB5pBsJ1KbSZ3MPN9WIxUpLjzYZeHHsizv9/77ntio0g9QXzt5ZT3Qx4J+7Vbad8kwcz81
u16dmV0DrBMyXJrZaQ0XyOvWTosePoxNmGhnsXbcV9ymWjbPjknfn6n2B7HJ3dgk9py6eZRKRfK7
gF3TKHV1NUX8TtRzSGevvsySuw2e0VgeEaVaMi9KYGLbpLaZF4bw3VSmaiourshVwp+eRdxl/+Ld
yQVOBa4RBL1QE0Vls/dCFeIQ8xVNA7NdoydzoodJq6dscM8DbrlyhCk1RqxOQzOxSeOqkJZfsG0L
LyjQgt1T1GhIw5PhvJEIuqiQNJSUw2yh6AsgvmImhJvSQJZFoDSWA0wgORynSIKQMOFRtHMcn0HW
fpExlGICxlQpE2NyqL0kkvf257/foQaSb7srsD8fkvMYajXW3hX51picRzIZeKtXZJ8/jwqnieTt
SbU6JvMy8+qo0kswZZZyLq26hhKcjoCGt4Q7h187VhavPT8c1LT2NXxmtiIXdYITARdlRsL/EARN
H65rw8WwuCK/9VClCtCcNOFKCyNySQ40hNtdh/Mt7xywLCQ7+P6RPPJHELC0oheuhTeQ7IPkaccC
K+EJi9mnzO7AZbhobaBKPch14xtiS1oNMIudlwFs8LK7UvOMaFdixcHvRPykLxTaOKObNbNZQDs3
O0je/ATyNBmJQslY5IvMOWKOCz9Yrm8XUaWHWk+3K8NnA1WECWv2UZtUWG57tLTQ1/eGGGzb5KAv
6NQBH2FKfaMjrWHERTuXpxUTlTYcfBsOKvCxP5hdp9nHNDv3J8Ne6v9l1Bsya+dvCY7P3XGvU+fq
P0nyhmQZCvc6+Xd74YUxeTQl/3HpteMnAAAA///Cwkfq8WIx+UH9aG01vE3+SwWTgQmnvB6+GOn7
dEi/9e//73+hCQneVQVXXH/vguXB4DaoJsTr5vr6f8j57TfYzc9/YjEZKPEXUSv/JmTyv38Iz8PG
hIEmf4XUmv9Q8ziwYP2OyM/3sa7H+fH7G6hOfNvfo6N/I07u+D8z+/YHb0BjwhXV8rL/rz9++LH9
TT1/j/3jwx9qbPsPV+TG799mZ7BhP0he/sPt97zb225UH8ZusvW7wvtvyvPevb9795z13433qu+B
x4TLLd7d/X/99Z239x/ve573/7bt++o55XvL19yv33h39+79IPn776Pvfd0OrGNt/wMAAAD//8ya
QUsCQRiGiQ4dOnjr2D/o7EHMnyKdvEgSQouabtC9P5DlXwgEDQYdyLt7K2TVwUPtQd0pxB1h3f36
vikqYooOHbotfPAMDOw8876MgYzybOTEAAOUYM1ZGKK5MroTdprzCO7dfcEdnEI3aniDoOagV3Ku
svQcGmwQ5qNGy7TRK0VORCtVkdyehxGVqrq5xeAZQbNdk5ymgDqRKDXhzqEwIrKOvIyFaMKfyelX
8lrONt/JVWDJmkfk9Gl/44M8fCPbnFU0ecNElpSaMUhf4NahxeIsalB3wrheCirH0cKmKTwAvYHC
qDqNRffQ1/OMXVaBiykazGRVJbJLZKYgywLQnTBGWgblAGXMLeHCEqVMRXDSiwUnMkXeWlk9omON
z8BWHjkRbyCM1VUupQKn5FSoEx7VpWtByS+27avFJYO81+lb/nLclrFo+X6R5nanFN6NpumZZyJr
J9qFoWX1/Ccln6/XmS3qhFlP3PhxKBPncLA6sfDSeDaRYntSkBE/GokEzeE2XO91d3rjXeM/+CUk
8k/fjsmt4tcnkvxe0cLkVv4XZG4i2//u5H8BAAD//xoSJgMAAAD//wMAEI/DSgplbmRzdHJlYW0K
ZW5kb2JqCjEzIDAgb2JqCjw8L0RlY29kZVBhcm1zIFtudWxsIF0KL0ZpbHRlciBbL0ZsYXRlRGVj
b2RlIF0KL0xlbmd0aCAyNgo+PgpzdHJlYW0KeNpiAAAAAP//YmD4//8/AAAA//8DAAYAAv4KZW5k
c3RyZWFtCmVuZG9iagoxMiAwIG9iagpbL0luZGV4ZWQgL0RldmljZVJHQiAxIDEzIDAgUiBdCmVu
ZG9iagoxMSAwIG9iago8PC9CYXNlRm9udCAvQXJpYWwKL0Rlc2NlbmRhbnRGb250cyBbMTAgMCBS
IF0KL0VuY29kaW5nIC9JZGVudGl0eS1ICi9OYW1lIC9GMgovU3VidHlwZSAvVHlwZTAKL1RvVW5p
Y29kZSAvSWRlbnRpdHktSAovVHlwZSAvRm9udAo+PgplbmRvYmoKMTAgMCBvYmoKPDwvQmFzZUZv
bnQgL0FyaWFsCi9DSURTeXN0ZW1JbmZvIDw8L09yZGVyaW5nIChJZGVudGl0eSkKL1JlZ2lzdHJ5
IChBZG9iZSkKL1N1cHBsZW1lbnQgMQo+PgovQ0lEVG9HSURNYXAgMjAgMCBSCi9Gb250RGVzY3Jp
cHRvciA5IDAgUgovU3VidHlwZSAvQ0lERm9udFR5cGUyCi9UeXBlIC9Gb250Ci9XIDE4IDAgUgo+
PgplbmRvYmoKOSAwIG9iago8PC9Bc2NlbnQgMTAwNQovQ0lEU2V0IDIxIDAgUgovQ2FwSGVpZ2h0
IDAKL0Rlc2NlbnQgLTMyNAovRmxhZ3MgMzIKL0ZvbnRCQm94IFstNjY0IC0zMjQgMjAwMCAxMDA1
IF0KL0ZvbnRGaWxlMiAxOSAwIFIKL0ZvbnROYW1lIC9BcmlhbAovSXRhbGljQW5nbGUgMAovU3Rl
bVYgMAovVHlwZSAvRm9udERlc2NyaXB0b3IKPj4KZW5kb2JqCjggMCBvYmoKPDwvRGVjb2RlUGFy
bXMgW251bGwgXQovRmlsdGVyIFsvRmxhdGVEZWNvZGUgXQovTGVuZ3RoIDMxMQo+PgpzdHJlYW0K
eNrMUT1PAzEMvTm/wmNvuNR2YidBiAGVj7JVnMSAWEBQkHpAERKiv54ktNIhYGNAUV7iF9vvyUE4
MQRLszaLvNcmsEXnnI8QKNqkicXDMKKVnSVUjQlWRgktInt0v/KjNitzAY9ZQ1woFIoA5pXERmVR
Dz+q3AxmOh+WBLOn7HFRfaIlRhSFN4PVfO6TBREJlNhydF4IQsLcWckxvNxW7cV/Sk/JRkJJCv3G
HPZmesyQbPISPEF/l7+lTIdGU5EQrCYKgaEfzOWkOWhdgS4WvOrPzFH/Fy6IbIoceewiRetYhPS7
i/u2k0nz2nZuh8+V2av36RZ10lxX+qGlXZ6tuCrEext3uZ/Vs+a02RTyvO0ox/P6BjnQ0blfarfw
dQAfAAAA//8iPtYCwakfAAAA//8DAHqml/0KZW5kc3RyZWFtCmVuZG9iago3IDAgb2JqCjw8L0Jh
c2VGb250IC9Db3VyaWVyTmV3Ci9EZXNjZW5kYW50Rm9udHMgWzYgMCBSIF0KL0VuY29kaW5nIC9J
ZGVudGl0eS1ICi9OYW1lIC9GMQovU3VidHlwZSAvVHlwZTAKL1RvVW5pY29kZSAvSWRlbnRpdHkt
SAovVHlwZSAvRm9udAo+PgplbmRvYmoKNiAwIG9iago8PC9CYXNlRm9udCAvQ291cmllck5ldwov
Q0lEU3lzdGVtSW5mbyA8PC9PcmRlcmluZyAoSWRlbnRpdHkpCi9SZWdpc3RyeSAoQWRvYmUpCi9T
dXBwbGVtZW50IDEKPj4KL0NJRFRvR0lETWFwIDE3IDAgUgovRm9udERlc2NyaXB0b3IgNSAwIFIK
L1N1YnR5cGUgL0NJREZvbnRUeXBlMgovVHlwZSAvRm9udAovVyAxNSAwIFIKPj4KZW5kb2JqCjUg
MCBvYmoKPDwvQXNjZW50IDEwMjAKL0NhcEhlaWdodCAwCi9EZXNjZW50IC02NzkKL0ZsYWdzIDMy
Ci9Gb250QkJveCBbLTEyMSAtNjc5IDYyMiAxMDIwIF0KL0ZvbnRGaWxlMiAxNiAwIFIKL0ZvbnRO
YW1lIC9Db3VyaWVyTmV3Ci9JdGFsaWNBbmdsZSAwCi9TdGVtViAwCi9UeXBlIC9Gb250RGVzY3Jp
cHRvcgo+PgplbmRvYmoKNCAwIG9iago8PC9Db250ZW50cyA4IDAgUgovTWVkaWFCb3ggWzAgMCA2
MTIuMjgzNDY1IDc5MC44NjYxNDIgXQovUGFyZW50IDEgMCBSCi9UeXBlIC9QYWdlCj4+CmVuZG9i
agozIDAgb2JqCjw8L0NvbG9yU3BhY2UgPDwvQ1MxIDEyIDAgUgo+PgovRm9udCA8PC9GMSA3IDAg
UgovRjIgMTEgMCBSCj4+Ci9YT2JqZWN0IDw8L0ltZzEgMTQgMCBSCj4+Cj4+CmVuZG9iagoyIDAg
b2JqCjw8L01ldGFkYXRhIDIzIDAgUgovT3BlbkFjdGlvbiBbNCAwIFIgL1hZWiAtMzI3NjggLTMy
NzY4IDEgXQovUGFnZUxheW91dCAvU2luZ2xlUGFnZQovUGFnZU1vZGUgL1VzZU5vbmUKL1BhZ2Vz
IDEgMCBSCi9UeXBlIC9DYXRhbG9nCi9WaWV3ZXJQcmVmZXJlbmNlcyA8PC9DZW50ZXJXaW5kb3cg
ZmFsc2UKL0RpcmVjdGlvbiAvTDJSCi9EaXNwbGF5RG9jVGl0bGUgZmFsc2UKL0ZpdFdpbmRvdyBm
YWxzZQovSGlkZU1lbnViYXIgZmFsc2UKL0hpZGVUb29sYmFyIGZhbHNlCi9IaWRlV2luZG93VUkg
ZmFsc2UKL05vbkZ1bGxTY3JlZW5QYWdlTW9kZSAvVXNlTm9uZQovUHJpbnRBcmVhIC9Dcm9wQm94
Ci9QcmludENsaXAgL0Nyb3BCb3gKL1ByaW50U2NhbGluZyAvQXBwRGVmYXVsdAovVmlld0FyZWEg
L0Nyb3BCb3gKL1ZpZXdDbGlwIC9Dcm9wQm94Cj4+Cj4+CmVuZG9iagoxIDAgb2JqCjw8L0NvdW50
IDEKL0tpZHMgWzQgMCBSIF0KL01lZGlhQm94IFswIDAgNTk1LjI3NTU5MSA4NDEuODg5NzY0IF0K
L1Jlc291cmNlcyAzIDAgUgovVHlwZSAvUGFnZXMKPj4KZW5kb2JqCnhyZWYNCjAgMjQNCjAwMDAw
MDAwMDAgNjU1MzUgZg0KMDAwMDAyMzE4MyAwMDAwMCBuDQowMDAwMDIyNzM5IDAwMDAwIG4NCjAw
MDAwMjI2MzEgMDAwMDAgbg0KMDAwMDAyMjUzMCAwMDAwMCBuDQowMDAwMDIyMzQyIDAwMDAwIG4N
CjAwMDAwMjIxNDAgMDAwMDAgbg0KMDAwMDAyMTk4OSAwMDAwMCBuDQowMDAwMDIxNTgzIDAwMDAw
IG4NCjAwMDAwMjEzODQgMDAwMDAgbg0KMDAwMDAyMTE4NiAwMDAwMCBuDQowMDAwMDIxMDM4IDAw
MDAwIG4NCjAwMDAwMjA5OTAgMDAwMDAgbg0KMDAwMDAyMDg2OSAwMDAwMCBuDQowMDAwMDE2OTIy
IDAwMDAwIG4NCjAwMDAwMTY5MDMgMDAwMDAgbg0KMDAwMDAxMjMzMCAwMDAwMCBuDQowMDAwMDEy
MjEzIDAwMDAwIG4NCjAwMDAwMTIwMDAgMDAwMDAgbg0KMDAwMDAwMzE1NiAwMDAwMCBuDQowMDAw
MDAyOTkxIDAwMDAwIG4NCjAwMDAwMDI4NjAgMDAwMDAgbg0KMDAwMDAwMjU5NSAwMDAwMCBuDQow
MDAwMDAwMDE1IDAwMDAwIG4NCnRyYWlsZXINCjw8L0lEIFsoFsP4ubwbSGi6mi5Cr0tFZUVlKSAo
eOBy/frUTDeS0erDJi6kg6SDKSBdCi9JbmZvIDIyIDAgUgovUm9vdCAyIDAgUgovU2l6ZSAyNAo+
Pg0Kc3RhcnR4cmVmDQoyMzI5Ng0KJSVFT0Y--1006711009-1319071212=:21299--
^ permalink raw reply
* RE: [RFC PATCH 0/3] fbdev driver for dm644x
From: Hadli, Manjunath @ 2011-10-19 11:40 UTC (permalink / raw)
To: linux-fbdev
Hello,
Can some one review this patches, so that I can issue a pull request.
Thanks.
Regards,
--Manju
On Mon, Sep 26, 2011 at 19:05:06, Hadli, Manjunath wrote:
> This patch series adds an fbdev driver for Texas Instruments Davinci SoC.The display subsystem consists of OSD and VENC, with OSD supporting 2 RGb planes and
> 2 video planes.
> http://focus.ti.com/general/docs/lit/
> getliterature.tsp?literatureNumber=sprue37d&fileType=pdf
>
> A good amount of the OSD and VENC enabling code is present in the kernel, and this patch series adds the fbdev interface.
>
> The fbdev driver exports 4 nodes representing each plane to the user - from fb0 to fb3.
>
> Manjunath Hadli (3):
> davinci: vpbe: enable vpbe for fbdev addition
> davinci: vpbe: add fbdev driver for dm644x
> davinci: vpbe: add build infrastructure for fbdev driver
>
> drivers/media/video/davinci/Kconfig | 13 +
> drivers/media/video/davinci/Makefile | 1 +
> drivers/media/video/davinci/vpbe_display.c | 6 +
> drivers/media/video/davinci/vpbe_fb.c | 2537 +++++++++++++++++++++++++++
> drivers/media/video/davinci/vpbe_fb.h | 66 +
> drivers/media/video/davinci/vpbe_fb_ioctl.h | 159 ++
> drivers/media/video/davinci/vpbe_osd.c | 793 +++++++++-
> drivers/media/video/davinci/vpbe_venc.c | 84 +
> include/media/davinci/vpbe_osd.h | 64 +-
> include/media/davinci/vpbe_venc.h | 21 +
> 10 files changed, 3735 insertions(+), 9 deletions(-) create mode 100644 drivers/media/video/davinci/vpbe_fb.c
> create mode 100644 drivers/media/video/davinci/vpbe_fb.h
> create mode 100644 drivers/media/video/davinci/vpbe_fb_ioctl.h
>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox