GIT d28749036c341696a3ed984e74d69c5d8ab82a1e git://git.infradead.org/users/jcrouse/geode.git commit d28749036c341696a3ed984e74d69c5d8ab82a1e Author: Jordan Crouse Date: Tue Aug 8 09:47:59 2006 -0600 [PATCH] gxfb: Turn on the flatpanel power and data For Geode devices without a flatpanel aware BIOS, this enables the flatpanel power and data. Signed-off-by: Jordan Crouse commit 823c57b5623976191f8f8ae0c1df796f9ceb5c03 Author: Jordan Crouse Date: Mon Jul 31 16:45:08 2006 -0600 [PATCH] gxfb: Fixup flatpanel detection Use the right MSR and bits to detect if the GX is strapped for TFT or CRT Signed-off-by: Jordan Crouse commit 5eb7482c8215acacf9057c3c000dc277e9007f35 Author: Jordan Crouse Date: Mon Jul 31 16:29:05 2006 -0600 [PATCH] gxfb: Support command line options Add support for command line options for setting the mode and various settings. Signed-off-by: Jordan Crouse commit 69050de07c8c0bd68839c6c7f597173e20909a70 Author: Jordan Crouse Date: Sat Jul 15 16:35:37 2006 -0600 [PATCH] gxfb: Add timings for the OLPC LCD Add a mode for the OLPC LCD. Signed-off-by: Jordan Crouse commit 0deb997308c966687a10003dc1baeb97508f1b72 Author: Jordan Crouse Date: Sat Jul 15 16:29:13 2006 -0600 [PATCH] gxfb: Support flat panel timings Support TFT panels by correctly setting up the flat panel registers Signed-off-by: Jordan Crouse commit 2ffed2363d930ab54175429a97ac488ac5c3dbc0 Author: Jaya Kumar Date: Thu Jun 15 09:29:11 2006 -0600 [PATCH] ALSA: fix duplicate control creation in AC97 This patch conditions AC97 control creation by whether or not the codec is an AD18xx codec. This fixes the case where the default control would get created and then snd_ac97_mixer_build fails out when creation of ad18xx specific control would get attempted. This problem was found and debuged by Marcelo Tosatti. Signed-off-by: Jaya Kumar commit 8d34c3d87ebb69da5ce14e30547ed7f19b996abc Author: Jordan Crouse Date: Thu Jun 8 09:26:19 2006 -0600 [PATCH] gxfb: Fixups for the AMD Geode GX framebuffer driver We cannot assume that the BIOS will be correctly setting up the hardware, so set some bits in various display registers to enable video output. Allow an advanced user to specify a frambuffer size, rather then probing the BIOS. All of these fixes were prompted by the OLPC effort. Signed-off-by: Jordan Crouse commit 39e4ed94d034a7d5b9e62d835ce991b1a360b7cb Author: Jordan Crouse Date: Thu Jun 8 09:26:13 2006 -0600 [PATCH] scx200_acb: Use PCI I/O resource when appropriate On the CS5535 and CS5536, the I/O resource is allocated through PCI, so use that instead of using the MSR backdoor. Signed-off-by: Jordan Crouse commit 3207a3d778e68c1f9de1c546221ad6345fe7a6c2 Author: Jordan Crouse Date: Thu Jun 8 09:25:53 2006 -0600 [PATCH] Add a configuration option to avoid automatically probing VGA Some x86 implementations don't have a built in VGA / VESA BIOS. This configuration option (enabled when EMBEDDED is selected), allows us to avoid probing the VGA hardware during boot. This option also disables the VGA console option, which depends heavily on the VGA / VESA probing. Signed-off-by: Jordan Crouse commit f4f038f60ce939186f5347a8c02f06be4ec71c6b Author: Jordan Crouse Date: Fri Jun 2 11:12:03 2006 -0600 PATCH: crypto: Add CryptoAPI support for the Geode LX AES Module Add CryptoAPI support for the Geode LX hardware based AES encryption engine. Signed-off-by: Jordan Crouse commit e0dc167e4220d0441ac3fa31564e48d0c55ca32e Author: Jaya Kumar Date: Fri Apr 28 12:34:49 2006 +0200 PM support for cs5535audio [ALSA] PM support for cs5535audio Appended is my patch adding PM support to the cs5535audio driver. I also added the ac97 quirk but it's not yet confirmed which boards need to be in the quirk list. The patch also includes some Kconfig and misc cleanup. Signed-off-by: Jaya Kumar Signed-off-by: Takashi Iwai commit 7281703e0d862388f8a6d276864c92b2e96acc9a Author: Jordan Crouse Date: Mon May 15 20:54:51 2006 -0600 FB: Get the Geode GX frambuffer size from the BIOS Use the Geode GX BIOS virtual registers to get the actual size of the framebuffer. Signed-off-by: Jordan Crouse commit cbd556651c8511cda7659a5580e1484ee3e66f0d Author: Jordan Crouse Date: Mon May 15 15:11:27 2006 -0600 GEODE: Update and fixup the PCI IDs for the CS5535 Clean up redundant and poorly worded PCI IDs Signed-off-by: Jordan Crouse arch/i386/Kconfig | 9 + arch/i386/boot/setup.S | 5 drivers/crypto/Kconfig | 9 + drivers/crypto/Makefile | 1 drivers/crypto/geode-aes.c | 395 ++++++++++++++++++++++++++++++++++++++ drivers/crypto/geode-aes.h | 42 ++++ drivers/i2c/busses/scx200_acb.c | 2 drivers/video/Kconfig | 6 - drivers/video/console/Kconfig | 4 drivers/video/geode/Kconfig | 20 ++ drivers/video/geode/display_gx.c | 22 ++ drivers/video/geode/display_gx.h | 7 + drivers/video/geode/gxfb_core.c | 57 +++++ drivers/video/geode/video_gx.c | 107 +++++++++- drivers/video/geode/video_gx.h | 25 ++ include/linux/pci_ids.h | 5 16 files changed, 686 insertions(+), 30 deletions(-) diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index b2751ea..36d644f 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -737,6 +737,15 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. +config VGA_NOPROBE + bool "Don't probe VGA at boot" if EMBEDDED + default n + help + Saying Y here will cause the kernel to not probe VGA at boot time. + This will break everything that depends on the probed screen + data. Say N here unless you are absolutely sure this is what you + want. + source kernel/Kconfig.hz config KEXEC diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index d2b684c..d63bd9d 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -394,10 +394,13 @@ # Set the keyboard repeat rate to the ma xorw %bx, %bx int $0x16 +#ifndef CONFIG_VGA_NOPROBE + # Check for video adapter and its parameters and allow the # user to browse video modes. call video # NOTE: we need %ds pointing # to bootsector +#endif # Get hd0 data... xorw %ax, %ax @@ -1006,9 +1009,11 @@ gdt_48: .word gdt_end - gdt - 1 # gdt limit .word 0, 0 # gdt base (filled in later) +#ifndef CONFIG_VGA_NOPROBE # Include video setup & detection code #include "video.S" +#endif # Setup signature -- must be last setup_sig1: .word SIG1 diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 4263935..efc5c72 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -20,4 +20,13 @@ config CRYPTO_DEV_PADLOCK_AES help Use VIA PadLock for AES algorithm. +config CRYPTO_DEV_GEODE + tristate "Support for the Geode LX AES engine" + depends on CRYPTO && X86_32 + help + Say 'Y' here to use the AMD Geode LX processor on-board AES + engine for the CryptoAPI AES alogrithm. + + To compile this driver as a module, choose M here: the module + will be called geode-aes. endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 45426ca..9093ed0 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o +obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c new file mode 100644 index 0000000..90ccec4 --- /dev/null +++ b/drivers/crypto/geode-aes.c @@ -0,0 +1,395 @@ +/* CryptoAPI interface for the Geode LX hardware AES encryption module + * Copyright (C) 2004-2006, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "geode-aes.h" + +/* Register definitions */ + +#define AES_CTRLA_REG 0x0000 + +#define AES_CTRL_START 0x01 +#define AES_CTRL_DECRYPT 0x00 +#define AES_CTRL_ENCRYPT 0x02 +#define AES_CTRL_WRKEY 0x04 +#define AES_CTRL_DCA 0x08 +#define AES_CTRL_SCA 0x10 +#define AES_CTRL_CBC 0x20 + +#define AES_INTR_REG 0x0008 + +#define AES_INTRA_PENDING (1 << 16) +#define AES_INTRB_PENDING (1 << 17) + +#define AES_INTR_PENDING (AES_INTRA_PENDING | AES_INTRB_PENDING) +#define AES_INTR_MASK 0x07 + +#define AES_SOURCEA_REG 0x0010 +#define AES_DSTA_REG 0x0014 +#define AES_LENA_REG 0x0018 +#define AES_WRITEKEY0_REG 0x0030 +#define AES_WRITEIV0_REG 0x0040 + +/* Useful macros */ + +#define SET_KEY(key) _writefield(AES_WRITEKEY0_REG, key) +#define SET_IV(iv) _writefield(AES_WRITEIV0_REG, iv) +#define GET_IV(iv) _readfield(AES_WRITEIV0_REG, iv) + +/* Static structures */ + +static void __iomem * _iobase; +static DEFINE_MUTEX(emutex); + +static inline void AWRITE(unsigned long val, unsigned short reg) { +#ifdef DEBUG + printk("[AES] W [%x]=%x\n", reg, val); +#endif + iowrite32(val, _iobase + reg); +} + +static inline unsigned int AREAD(unsigned short reg) { + unsigned int val = ioread32(_iobase + reg); +#ifdef DEBUG + printk("[AES] R [%x]=%x\n", reg, val); +#endif + return val; +} + +/* Write a 128 bit field (either a writable key or IV) */ +static inline void +_writefield(u32 offset, void *value) +{ + int i; + for(i = 0; i < 4; i++) + AWRITE(((u32 *) value)[i], offset + (i * 4)); +} + +/* Read a 128 bit field (either a writable key or IV) */ +static inline void +_readfield(u32 offset, void *value) +{ + int i; + for(i = 0; i < 4; i++) + ((u32 *) value)[i] = AREAD(offset + (i * 4)); +} + +static void +_crypt(void *src, void *dst, int len, u32 flags) +{ + u32 status; + + AWRITE(__pa(src), AES_SOURCEA_REG); + AWRITE(__pa(dst), AES_DSTA_REG); + AWRITE(len, AES_LENA_REG); + + /* Start the operation */ + AWRITE(AES_CTRL_START | flags, AES_CTRLA_REG); + + /* According to the silicon developers, the status will only + * fail to clear on an catastrophic failure, so an infinite + * loop is valid here + */ + + do + status = AREAD(AES_INTR_REG); + while(!(status & AES_INTRA_PENDING)); + + /* Clear the event */ + AWRITE((status & 0xFF) | AES_INTRA_PENDING, AES_INTR_REG); +} + +unsigned int +geode_aes_crypt(struct geode_aes_op *op) +{ + u32 flags = 0; + + if (op->len == 0 || op->src == op->dst) + return 0; + + if (mutex_lock_interruptible(&emutex)) + return 0; + + if (op->mode == AES_MODE_CBC) { + flags |= AES_CTRL_CBC; + SET_IV(op->iv); + } + + if (op->flags & AES_FLAGS_USRKEY) { + flags |= AES_CTRL_WRKEY; + SET_KEY(op->key); + } + + if (op->flags & AES_FLAGS_COHERENT) + flags |= (AES_CTRL_DCA | AES_CTRL_SCA); + + if (op->dir == AES_DIR_ENCRYPT) + flags |= AES_CTRL_ENCRYPT; + + _crypt(op->src, op->dst, op->len, flags); + + if (op->mode == AES_MODE_CBC) + GET_IV(op->iv); + + mutex_unlock(&emutex); + return op->len; +} + +/* CRYPTO-API Functions */ + +static int +geode_aes_setkey(void *data, const u8 *key, unsigned int len, u32 *flags) +{ + + struct geode_aes_op *op = (struct geode_aes_op *) data; + + if (len != AES_KEY_LENGTH) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + memcpy(op->key, key, len); + return 0; +} + +static void +geode_aes_encrypt(void *ctx, u8 *out, const u8 *in) +{ + struct geode_aes_op *op = (struct geode_aes_op *) ctx; + + if ((out == NULL) || (in == NULL)) + return; + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_CBC; + op->flags = 0; + op->len = AES_MIN_BLOCK_SIZE; + op->dir = AES_DIR_ENCRYPT; + + geode_aes_crypt(op); +} + + +static void +geode_aes_decrypt(void *ctx, u8 *out, const u8 *in) +{ + struct geode_aes_op *op = (struct geode_aes_op *) ctx; + + if ((out == NULL) || (in == NULL)) + return; + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_CBC; + op->flags = 0; + op->len = AES_MIN_BLOCK_SIZE; + op->dir = AES_DIR_DECRYPT; + + geode_aes_crypt(op); +} + +static unsigned int +geode_aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_tfm_ctx(desc->tfm); + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_ECB; + op->flags = 0; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_ENCRYPT; + + return geode_aes_crypt(op); +} + +static unsigned int +geode_aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_tfm_ctx(desc->tfm); + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_ECB; + op->flags = 0; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_DECRYPT; + + return geode_aes_crypt(op); +} + +static unsigned int +geode_aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_tfm_ctx(desc->tfm); + unsigned int ret; + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_CBC; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_ENCRYPT; + + memcpy(op->iv, desc->info, AES_IV_LENGTH); + + ret = geode_aes_crypt(op); + + memcpy(desc->info, op->iv, AES_IV_LENGTH); + return ret; +} + +static unsigned int +geode_aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_tfm_ctx(desc->tfm); + unsigned int ret; + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_CBC; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_DECRYPT; + + memcpy(op->iv, desc->info, AES_IV_LENGTH); + + ret = geode_aes_crypt(op); + + memcpy(desc->info, op->iv, AES_IV_LENGTH); + return ret; +} + +static struct crypto_alg geode_aes_crypto = { + .cra_name = "aes", + .cra_driver_name = "geode-aes", + .cra_priority = 110, + .cra_alignmask = 15, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_MIN_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct geode_aes_op), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(geode_aes_crypto.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_KEY_LENGTH, + .cia_max_keysize = AES_KEY_LENGTH, + .cia_setkey = geode_aes_setkey, + .cia_encrypt = geode_aes_encrypt, + .cia_decrypt = geode_aes_decrypt, + .cia_encrypt_ecb = geode_aes_encrypt_ecb, + .cia_decrypt_ecb = geode_aes_decrypt_ecb, + .cia_encrypt_cbc = geode_aes_encrypt_cbc, + .cia_decrypt_cbc = geode_aes_decrypt_cbc, + } + } +}; + +static void +geode_aes_remove(struct pci_dev *dev) +{ + crypto_unregister_alg(&geode_aes_crypto); + + pci_iounmap(dev, _iobase); + _iobase = NULL; + + pci_release_regions(dev); + pci_disable_device(dev); + + mutex_destroy(&emutex); +} + + +static int +geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret; + + if ((ret = pci_enable_device(dev))) + return ret; + + if ((ret = pci_request_regions(dev, "geode-aes"))) + goto eenable; + + _iobase = pci_iomap(dev, 0, 0); + + if (_iobase == NULL) { + ret = -ENOMEM; + goto erequest; + } + + /* Clear any pending activity */ + AWRITE(AES_INTR_PENDING | AES_INTR_MASK, AES_INTR_REG); + + mutex_init(&emutex); + + ret = crypto_register_alg(&geode_aes_crypto); + + if (ret == 0) { + printk(KERN_NOTICE "geode-aes: GEODE AES engine enabled.\n"); + return 0; + } + + crypto_unregister_alg(&geode_aes_crypto); + + pci_iounmap(dev, _iobase); + + erequest: + pci_release_regions(dev); + + eenable: + pci_disable_device(dev); + + return ret; +} + +struct pci_device_id geode_aes_tbl[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, PCI_ANY_ID, PCI_ANY_ID} , + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, geode_aes_tbl); + +static struct pci_driver geode_aes_driver = { + name: "Geode LX AES", + id_table: geode_aes_tbl, + probe: geode_aes_probe, + remove: __devexit_p(geode_aes_remove) +}; + +static int __devinit +geode_aes_init(void) +{ + return pci_module_init(&geode_aes_driver); +} + +static void __devexit +geode_aes_exit(void) +{ + pci_unregister_driver(&geode_aes_driver); +} + +MODULE_AUTHOR("Advanced Micro Devices, Inc."); +MODULE_DESCRIPTION("Geode LX Hardware AES driver"); +MODULE_LICENSE("GPL"); + +module_init(geode_aes_init); +module_exit(geode_aes_exit); diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h new file mode 100644 index 0000000..97f9eee --- /dev/null +++ b/drivers/crypto/geode-aes.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2003-2006, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _GEODE_AES_H_ +#define _GEODE_AES_H_ + +#define AES_KEY_LENGTH 16 +#define AES_IV_LENGTH 16 + +#define AES_MIN_BLOCK_SIZE 16 + +#define AES_MODE_ECB 0 +#define AES_MODE_CBC 1 + +#define AES_DIR_DECRYPT 0 +#define AES_DIR_ENCRYPT 1 + +#define AES_FLAGS_USRKEY (1 << 0) +#define AES_FLAGS_COHERENT (1 << 1) + +struct geode_aes_op { + + void *src; + void *dst; + + u32 mode; + u32 dir; + u32 flags; + int len; + + u8 key[AES_KEY_LENGTH]; + u8 iv[AES_IV_LENGTH]; +}; + +unsigned int geode_aes_crypt(struct geode_aes_op *); + +#endif diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index eae9e81..278ce4b 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -622,8 +622,10 @@ static int __init scx200_acb_init(void) rc = scx200_scan_pci(); /* If at least one bus was created, init must succeed */ + if (scx200_acb_list) return 0; + return rc; } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 702eb93..c46e372 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -542,7 +542,7 @@ config FB_TGA config FB_VESA bool "VESA VGA graphics support" - depends on (FB = y) && X86 + depends on (FB = y) && X86 && !VGA_NOPROBE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -826,7 +826,7 @@ config FB_I810_I2C config FB_INTEL tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" - depends on FB && EXPERIMENTAL && PCI && X86 + depends on FB && EXPERIMENTAL && PCI && X86 && !VGA_NOPROBE select AGP select AGP_INTEL select FB_MODE_HELPERS @@ -1158,7 +1158,7 @@ config FB_SAVAGE_ACCEL config FB_SIS tristate "SiS/XGI display support" - depends on FB && PCI + depends on FB && PCI && !VGA_NOPROBE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 4444bef..0be8e3b 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -5,8 +5,8 @@ # menu "Console display driver support" config VGA_CONSOLE - bool "VGA text console" if EMBEDDED || !X86 - depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE + bool "VGA text console" if (EMBEDDED || !X86) + depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !VGA_NOPROBE default y help Saying Y here will allow you to use Linux in text mode through a diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 4e173ef..5704879 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -23,6 +23,26 @@ config FB_GEODE_GX If unsure, say N. +config FB_GEODE_GX_SET_FBSIZE + bool "Manually specify the Geode GX framebuffer size" + depends on FB_GEODE_GX + default n + ---help--- + If you want to manually specify the size of your GX framebuffer, + say Y here, otherwise say N to dynamically probe it. + + Say N unless you know what you are doing. + +config FB_GEODE_GX_FBSIZE + hex "Size of the GX framebuffer, in bytes" + depends on FB_GEODE_GX_SET_FBSIZE + default "0x1600000" + ---help--- + Specify the size of the GX framebuffer. Normally, you will + want this to be MB aligned. Common values are 0x80000 (8MB) + and 0x1600000 (16MB). Don't change this unless you know what + you are doing + config FB_GEODE_GX1 tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" depends on FB && FB_GEODE && EXPERIMENTAL diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c index 825c340..7faf62a 100644 --- a/drivers/video/geode/display_gx.c +++ b/drivers/video/geode/display_gx.c @@ -21,11 +21,26 @@ #include #include "geodefb.h" #include "display_gx.h" -int gx_frame_buffer_size(void) +#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE +unsigned int gx_frame_buffer_size(void) { + return CONFIG_FB_GEODE_GX_FBSIZE; +} +#else +unsigned int gx_frame_buffer_size(void) { - /* Assuming 16 MiB. */ - return 16*1024*1024; + unsigned int val; + + /* FB size is reported by a virtual register */ + /* Virtual register class = 0x02 */ + /* VG_MEM_SIZE(512Kb units) = 0x00 */ + + outw(0xFC53, 0xAC1C); + outw(0x0200, 0xAC1C); + + val = (unsigned int)(inw(0xAC1E)) & 0xFFl; + return (val << 19); } +#endif int gx_line_delta(int xres, int bpp) { @@ -81,6 +96,7 @@ static void gx_set_mode(struct fb_info * writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, par->dc_regs + DC_LINE_SIZE); + /* Enable graphics and video data and unmask address lines. */ dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h index 86c6233..0af33f3 100644 --- a/drivers/video/geode/display_gx.h +++ b/drivers/video/geode/display_gx.h @@ -11,11 +11,15 @@ #ifndef __DISPLAY_GX_H__ #define __DISPLAY_GX_H__ -int gx_frame_buffer_size(void); +unsigned int gx_frame_buffer_size(void); int gx_line_delta(int xres, int bpp); extern struct geode_dc_ops gx_dc_ops; +/* MSR that tells us if a TFT or CRT is attached */ +#define GLD_MSR_CONFIG 0xC0002001 +#define GLD_MSR_CONFIG_DM_FP 0x40 + /* Display controller registers */ #define DC_UNLOCK 0x00 @@ -93,4 +97,5 @@ #define DC_V_SYNC_TIMING 0x58 #define DC_PAL_ADDRESS 0x70 #define DC_PAL_DATA 0x74 +#define DC_GLIU0_MEM_OFFSET 0x84 #endif /* !__DISPLAY_GX1_H__ */ diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c index 0d3643f..1e20a3b 100644 --- a/drivers/video/geode/gxfb_core.c +++ b/drivers/video/geode/gxfb_core.c @@ -35,10 +35,10 @@ #include "geodefb.h" #include "display_gx.h" #include "video_gx.h" -static char mode_option[32] = "640x480-16@60"; +static char *mode_option; /* Modes relevant to the GX (taken from modedb.c) */ -static const struct fb_videomode __initdata gx_modedb[] = { +static const struct fb_videomode gx_modedb[] __initdata = { /* 640x480-60 VESA */ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -103,6 +103,9 @@ static const struct fb_videomode __initd { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, + { "OLPC-1", 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 } }; static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -240,6 +243,12 @@ static int __init gxfb_map_video_memory( if (!info->screen_base) return -ENOMEM; + /* Set the 16MB aligned base address of the graphics memory region + * in the display controller */ + + writel(info->fix.smem_start & 0xFF000000, + par->dc_regs + DC_GLIU0_MEM_OFFSET); + dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", info->fix.smem_len / 1024, info->fix.smem_start); @@ -302,6 +311,7 @@ static int __init gxfb_probe(struct pci_ struct geodefb_par *par; struct fb_info *info; int ret; + unsigned long val; info = gxfb_init_fbinfo(&pdev->dev); if (!info) @@ -317,6 +327,15 @@ static int __init gxfb_probe(struct pci_ goto err; } + /* Figure out if this is a TFT or CRT part */ + + rdmsrl(GLD_MSR_CONFIG, val); + + if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP) + par->enable_crt = 0; + else + par->enable_crt = 1; + ret = fb_find_mode(&info->var, info, mode_option, gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); if (ret == 0 || ret == 4) { @@ -325,7 +344,8 @@ static int __init gxfb_probe(struct pci_ goto err; } - /* Clear the frame buffer of garbage. */ + + /* Clear the frame buffer of garbage. */ memset_io(info->screen_base, 0, info->fix.smem_len); gxfb_check_var(&info->var, info); @@ -380,7 +400,7 @@ static void gxfb_remove(struct pci_dev * } static struct pci_device_id gxfb_id_table[] = { - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO, + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 }, { 0, } @@ -395,11 +415,34 @@ static struct pci_driver gxfb_driver = { .remove = gxfb_remove, }; +#ifndef MODULE +static int __init gxfb_setup(char *options) { + + char *opt; + + if (!options || !*options) + return 0; + + while((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + + mode_option = opt; + } + + return 0; +} +#endif + static int __init gxfb_init(void) { #ifndef MODULE - if (fb_get_options("gxfb", NULL)) + char *option = NULL; + + if (fb_get_options("gxfb", &option)) return -ENODEV; + + gxfb_setup(option); #endif return pci_register_driver(&gxfb_driver); } @@ -412,8 +455,8 @@ static void __exit gxfb_cleanup(void) module_init(gxfb_init); module_exit(gxfb_cleanup); -module_param_string(mode, mode_option, sizeof(mode_option), 0444); -MODULE_PARM_DESC(mode, "video mode (x[-][@])"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "video mode (x[-][@])"); MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c index 2b2a788..ed6a174 100644 --- a/drivers/video/geode/video_gx.c +++ b/drivers/video/geode/video_gx.c @@ -175,13 +175,88 @@ static void gx_set_dclk_frequency(struct } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); } +static void +gx_configure_tft(struct fb_info *info) { + + struct geodefb_par *par = info->par; + unsigned long val; + unsigned long fp; + + /* Set up the DF pad select MSR */ + + rdmsrl(GX_VP_MSR_PAD_SELECT, val); + val &= ~GX_VP_PAD_SELECT_MASK; + val |= GX_VP_PAD_SELECT_TFT; + wrmsrl(GX_VP_MSR_PAD_SELECT, val); + + /* Turn off the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp &= ~GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); + + /* Set timing 1 */ + + fp = readl(par->vid_regs + GX_FP_PT1); + fp &= GX_FP_PT1_VSIZE_MASK; + fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT; + writel(fp, par->vid_regs + GX_FP_PT1); + + /* Timing 2 */ + /* Set bits that are always on for TFT */ + + fp = 0x0F100000; + + /* Add sync polarity */ + + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + fp |= GX_FP_PT2_VSP; + + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + fp |= GX_FP_PT2_HSP; + + writel(fp, par->vid_regs + GX_FP_PT2); + + /* Set the dither control */ + writel(0x70, par->vid_regs + GX_FP_DFC); + + /* Enable the FP data and power (in case the BIOS didn't) */ + + fp = readl(par->vid_regs + GX_DCFG); + fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN; + writel(fp, par->vid_regs + GX_DCFG); + + /* Unblank the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp |= GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); +} + static void gx_configure_display(struct fb_info *info) { struct geodefb_par *par = info->par; - u32 dcfg, fp_pm; + u32 dcfg, misc; + + /* Set up the MISC register */ + + misc = readl(par->vid_regs + GX_MISC); + + /* Power up the DAC */ + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN); + + /* Disable gamma correction */ + misc |= GX_MISC_GAM_EN; + + writel(misc, par->vid_regs + GX_MISC); + /* Write the display configuration */ dcfg = readl(par->vid_regs + GX_DCFG); + /* Disable hsync and vsync */ + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); + writel(dcfg, par->vid_regs + GX_DCFG); + /* Clear bits from existing mode. */ dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL @@ -199,12 +274,19 @@ static void gx_configure_display(struct if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) dcfg |= GX_DCFG_CRT_VSYNC_POL; + /* Enable the display logic */ + /* Set up the DACS to blank normally */ + + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN; + + /* Enable the external DAC VREF? */ + writel(dcfg, par->vid_regs + GX_DCFG); - /* Power on flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + /* Set up the flat panel (if it is enabled) */ + + if (par->enable_crt == 0) + gx_configure_tft(info); } static int gx_blank_display(struct fb_info *info, int blank_mode) @@ -245,12 +327,15 @@ static int gx_blank_display(struct fb_in writel(dcfg, par->vid_regs + GX_DCFG); /* Power on/off flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - if (blank_mode == FB_BLANK_POWERDOWN) - fp_pm &= ~GX_FP_PM_P; - else - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + + if (par->enable_crt == 0) { + fp_pm = readl(par->vid_regs + GX_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~GX_FP_PM_P; + else + fp_pm |= GX_FP_PM_P; + writel(fp_pm, par->vid_regs + GX_FP_PM); + } return 0; } diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h index 2d9211f..ce28d8f 100644 --- a/drivers/video/geode/video_gx.h +++ b/drivers/video/geode/video_gx.h @@ -13,6 +13,11 @@ #define __VIDEO_GX_H__ extern struct geode_vid_ops gx_vid_ops; +/* GX Flatpanel control MSR */ +#define GX_VP_MSR_PAD_SELECT 0xC0002011 +#define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF +#define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF + /* Geode GX video processor registers */ #define GX_DCFG 0x0008 @@ -20,6 +25,8 @@ # define GX_DCFG_CRT_EN 0x00000001 # define GX_DCFG_HSYNC_EN 0x00000002 # define GX_DCFG_VSYNC_EN 0x00000004 # define GX_DCFG_DAC_BL_EN 0x00000008 +# define GX_DCFG_FP_PWR_EN 0x00000040 +# define GX_DCFG_FP_DATA_EN 0x00000080 # define GX_DCFG_CRT_HSYNC_POL 0x00000100 # define GX_DCFG_CRT_VSYNC_POL 0x00000200 # define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 @@ -28,10 +35,28 @@ # define GX_DCFG_VG_CK 0x00100000 # define GX_DCFG_GV_GAM 0x00200000 # define GX_DCFG_DAC_VREF 0x04000000 +/* Geode GX MISC video configuration */ + +#define GX_MISC 0x50 +#define GX_MISC_GAM_EN 0x00000001 +#define GX_MISC_DAC_PWRDN 0x00000400 +#define GX_MISC_A_PWRDN 0x00000800 + /* Geode GX flat panel display control registers */ + +#define GX_FP_PT1 0x0400 +#define GX_FP_PT1_VSIZE_MASK 0x7FF0000 +#define GX_FP_PT1_VSIZE_SHIFT 16 + +#define GX_FP_PT2 0x408 +#define GX_FP_PT2_VSP (1 << 23) +#define GX_FP_PT2_HSP (1 << 22) + #define GX_FP_PM 0x410 # define GX_FP_PM_P 0x01000000 +#define GX_FP_DFC 0x418 + /* Geode GX clock control MSRs */ #define MSR_GLCP_SYS_RSTPLL 0x4c000014 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 7a24915..99ed423 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -390,7 +390,7 @@ #define PCI_DEVICE_ID_NS_CS5535_ISA 0x00 #define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d #define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e #define PCI_DEVICE_ID_NS_CS5535_USB 0x002f -#define PCI_DEVICE_ID_NS_CS5535_VIDEO 0x0030 +#define PCI_DEVICE_ID_NS_GX_VIDEO 0x0030 #define PCI_DEVICE_ID_NS_SATURN 0x0035 #define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500 #define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501 @@ -403,8 +403,7 @@ #define PCI_DEVICE_ID_NS_SC1100_SMI 0x05 #define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515 #define PCI_DEVICE_ID_NS_87410 0xd001 -#define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE 0x0028 -#define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE 0x002b +#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE 0x0028 #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202