diff options
Diffstat (limited to 'drivers/video')
65 files changed, 2889 insertions, 1782 deletions
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 0b17824..2110556 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -308,7 +308,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * Pseudocolor: * uses offset = 0 && length = RAMDAC register width. * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC + * var->{color}.length contains width of DAC * cmap is not used * RAMDAC[X] is programmed to (red, green, blue) * Truecolor: diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 5a5c303..dabe804 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -400,9 +400,12 @@ config FB_SA1100 If you plan to use the LCD display with your SA-1100 system, say Y here. +config HAVE_FB_IMX + bool + config FB_IMX tristate "Motorola i.MX LCD support" - depends on FB && (ARCH_MX1 || ARCH_MX2) + depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -909,6 +912,18 @@ config FB_XVR2500 mostly initialized the card already. It is treated as a completely dumb framebuffer device. +config FB_XVR1000 + bool "Sun XVR-1000 support" + depends on SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-1000 and similar + graphics cards. The driver only works on sparc64 systems where + the system firmware has mostly initialized the card already. It + is treated as a completely dumb framebuffer device. + config FB_PVR2 tristate "NEC PowerVR 2 display support" depends on FB && SH_DREAMCAST @@ -1494,7 +1509,6 @@ config FB_VIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select I2C_ALGOBIT select I2C help @@ -1945,6 +1959,27 @@ config FB_S3C2410_DEBUG Turn on debugging messages. Note that you can set/unset at run time through sysfs +config FB_NUC900 + bool "NUC900 LCD framebuffer support" + depends on FB && ARCH_W90X900 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Nuvoton + NUC900 processor + +config GPM1040A0_320X240 + bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD" + depends on FB_NUC900 + +config FB_NUC900_DEBUG + bool "NUC900 lcd debug messages" + depends on FB_NUC900 + help + Turn on debugging messages. Note that you can set/unset at run time + through sysfs + config FB_SM501 tristate "Silicon Motion SM501 framebuffer support" depends on FB && MFD_SM501 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 4ecb30c..ddc2af2 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_FB_N411) += n411.o obj-$(CONFIG_FB_HGA) += hgafb.o obj-$(CONFIG_FB_XVR500) += sunxvr500.o obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o +obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o obj-$(CONFIG_FB_Q40) += q40fb.o @@ -129,6 +130,7 @@ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ obj-$(CONFIG_FB_MSM) += msm/ +obj-$(CONFIG_FB_NUC900) += nuc900fb.o # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 0bcc59e..43d7d50 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1221,7 +1221,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) printk("acornfb: freed %dK memory\n", mb_freed); } -static int __init acornfb_probe(struct platform_device *dev) +static int __devinit acornfb_probe(struct platform_device *dev) { unsigned long size; u_int h_sync, v_sync; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index c343169..01554d6 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -504,7 +504,7 @@ static struct fb_ops arcfb_ops = { .fb_ioctl = arcfb_ioctl, }; -static int __init arcfb_probe(struct platform_device *dev) +static int __devinit arcfb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 9fe90ce..e70bc22 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -140,7 +140,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc /* 3 <= m <= 257 */ if (m >= 3 && m <= 257) { - unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ? + unsigned new_error = Ftarget * n >= Fref * m ? ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n)); if (new_error < best_error) { best_n = n; @@ -152,7 +152,7 @@ static void asiliant_calc_dclk2(u32 *ppixclock, u8 *dclk2_m, u8 *dclk2_n, u8 *dc else if (m <= 1028) { /* remember there are still only 8-bits of precision in m, so * avoid over-optimistic error calculations */ - unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ? + unsigned new_error = Ftarget * n >= Fref * (m & ~3) ? ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n)); if (new_error < best_error) { best_n = n; diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c new file mode 100644 index 0000000..b8f705c --- /dev/null +++ b/drivers/video/backlight/88pm860x_bl.c @@ -0,0 +1,304 @@ +/* + * Backlight driver for Marvell Semiconductor 88PM8606 + * + * Copyright (C) 2009 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/i2c.h> +#include <linux/backlight.h> +#include <linux/mfd/88pm860x.h> + +#define MAX_BRIGHTNESS (0xFF) +#define MIN_BRIGHTNESS (0) + +#define CURRENT_MASK (0x1F << 1) + +struct pm860x_backlight_data { + struct pm860x_chip *chip; + struct i2c_client *i2c; + int current_brightness; + int port; + int pwm; + int iset; +}; + +static inline int wled_a(int port) +{ + int ret; + + ret = ((port - PM8606_BACKLIGHT1) << 1) + 2; + return ret; +} + +static inline int wled_b(int port) +{ + int ret; + + ret = ((port - PM8606_BACKLIGHT1) << 1) + 3; + return ret; +} + +/* WLED2 & WLED3 share the same IDC */ +static inline int wled_idc(int port) +{ + int ret; + + switch (port) { + case PM8606_BACKLIGHT1: + case PM8606_BACKLIGHT2: + ret = ((port - PM8606_BACKLIGHT1) << 1) + 3; + break; + case PM8606_BACKLIGHT3: + default: + ret = ((port - PM8606_BACKLIGHT2) << 1) + 3; + break; + } + return ret; +} + +static int pm860x_backlight_set(struct backlight_device *bl, int brightness) +{ + struct pm860x_backlight_data *data = bl_get_data(bl); + struct pm860x_chip *chip = data->chip; + unsigned char value; + int ret; + + if (brightness > MAX_BRIGHTNESS) + value = MAX_BRIGHTNESS; + else + value = brightness; + + ret = pm860x_reg_write(data->i2c, wled_a(data->port), value); + if (ret < 0) + goto out; + + if ((data->current_brightness == 0) && brightness) { + if (data->iset) { + ret = pm860x_set_bits(data->i2c, wled_idc(data->port), + CURRENT_MASK, data->iset); + if (ret < 0) + goto out; + } + if (data->pwm) { + ret = pm860x_set_bits(data->i2c, PM8606_PWM, + PM8606_PWM_FREQ_MASK, data->pwm); + if (ret < 0) + goto out; + } + if (brightness == MAX_BRIGHTNESS) { + /* set WLED_ON bit as 100% */ + ret = pm860x_set_bits(data->i2c, wled_b(data->port), + PM8606_WLED_ON, PM8606_WLED_ON); + } + } else { + if (brightness == MAX_BRIGHTNESS) { + /* set WLED_ON bit as 100% */ + ret = pm860x_set_bits(data->i2c, wled_b(data->port), + PM8606_WLED_ON, PM8606_WLED_ON); + } else { + /* clear WLED_ON bit since it's not 100% */ + ret = pm860x_set_bits(data->i2c, wled_b(data->port), + PM8606_WLED_ON, 0); + } + } + if (ret < 0) + goto out; + + dev_dbg(chip->dev, "set brightness %d\n", value); + data->current_brightness = value; + return 0; +out: + dev_dbg(chip->dev, "set brightness %d failure with return " + "value:%d\n", value, ret); + return ret; +} + +static int pm860x_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.state & BL_CORE_SUSPENDED) + brightness = 0; + + return pm860x_backlight_set(bl, brightness); +} + +static int pm860x_backlight_get_brightness(struct backlight_device *bl) +{ + struct pm860x_backlight_data *data = bl_get_data(bl); + struct pm860x_chip *chip = data->chip; + int ret; + + ret = pm860x_reg_read(data->i2c, wled_a(data->port)); + if (ret < 0) + goto out; + data->current_brightness = ret; + dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness); + return data->current_brightness; +out: + return -EINVAL; +} + +static struct backlight_ops pm860x_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = pm860x_backlight_update_status, + .get_brightness = pm860x_backlight_get_brightness, +}; + +static int __check_device(struct pm860x_backlight_pdata *pdata, char *name) +{ + struct pm860x_backlight_pdata *p = pdata; + int ret = -EINVAL; + + while (p && p->id) { + if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0)) + break; + + if (!strncmp(name, pm860x_backlight_name[p->flags], + MFD_NAME_SIZE)) { + ret = (int)p->flags; + break; + } + p++; + } + return ret; +} + +static int pm860x_backlight_probe(struct platform_device *pdev) +{ + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm860x_platform_data *pm860x_pdata; + struct pm860x_backlight_pdata *pdata = NULL; + struct pm860x_backlight_data *data; + struct backlight_device *bl; + struct resource *res; + unsigned char value; + char name[MFD_NAME_SIZE]; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (res == NULL) { + dev_err(&pdev->dev, "No I/O resource!\n"); + return -EINVAL; + } + + if (pdev->dev.parent->platform_data) { + pm860x_pdata = pdev->dev.parent->platform_data; + pdata = pm860x_pdata->backlight; + } + if (pdata == NULL) { + dev_err(&pdev->dev, "platform data isn't assigned to " + "backlight\n"); + return -EINVAL; + } + + data = kzalloc(sizeof(struct pm860x_backlight_data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + strncpy(name, res->name, MFD_NAME_SIZE); + data->chip = chip; + data->i2c = (chip->id == CHIP_PM8606) ? chip->client \ + : chip->companion; + data->current_brightness = MAX_BRIGHTNESS; + data->pwm = pdata->pwm; + data->iset = pdata->iset; + data->port = __check_device(pdata, name); + if (data->port < 0) { + dev_err(&pdev->dev, "wrong platform data is assigned"); + return -EINVAL; + } + + bl = backlight_device_register(name, &pdev->dev, data, + &pm860x_backlight_ops); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); + return PTR_ERR(bl); + } + bl->props.max_brightness = MAX_BRIGHTNESS; + bl->props.brightness = MAX_BRIGHTNESS; + + platform_set_drvdata(pdev, bl); + + /* Enable reference VSYS */ + ret = pm860x_reg_read(data->i2c, PM8606_VSYS); + if (ret < 0) + goto out; + if ((ret & PM8606_VSYS_EN) == 0) { + value = ret | PM8606_VSYS_EN; + ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value); + if (ret < 0) + goto out; + } + /* Enable reference OSC */ + ret = pm860x_reg_read(data->i2c, PM8606_MISC); + if (ret < 0) + goto out; + if ((ret & PM8606_MISC_OSC_EN) == 0) { + value = ret | PM8606_MISC_OSC_EN; + ret = pm860x_reg_write(data->i2c, PM8606_MISC, value); + if (ret < 0) + goto out; + } + /* read current backlight */ + ret = pm860x_backlight_get_brightness(bl); + if (ret < 0) + goto out; + + backlight_update_status(bl); + return 0; +out: + kfree(data); + return ret; +} + +static int pm860x_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct pm860x_backlight_data *data = bl_get_data(bl); + + backlight_device_unregister(bl); + kfree(data); + return 0; +} + +static struct platform_driver pm860x_backlight_driver = { + .driver = { + .name = "88pm860x-backlight", + .owner = THIS_MODULE, + }, + .probe = pm860x_backlight_probe, + .remove = pm860x_backlight_remove, +}; + +static int __init pm860x_backlight_init(void) +{ + return platform_driver_register(&pm860x_backlight_driver); +} +module_init(pm860x_backlight_init); + +static void __exit pm860x_backlight_exit(void) +{ + platform_driver_unregister(&pm860x_backlight_driver); +} +module_exit(pm860x_backlight_exit); + +MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606"); +MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:88pm860x-backlight"); diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 09bfa96..0c77fc6 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -212,6 +212,13 @@ config BACKLIGHT_DA903X If you have a LCD backlight connected to the WLED output of DA9030 or DA9034 WLED output, say Y here to enable this driver. +config BACKLIGHT_MAX8925 + tristate "Backlight driver for MAX8925" + depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925 + help + If you have a LCD backlight connected to the WLED output of MAX8925 + WLED output, say Y here to enable this driver. + config BACKLIGHT_MBP_NVIDIA tristate "MacBook Pro Nvidia Backlight Driver" depends on BACKLIGHT_CLASS_DEVICE && X86 @@ -262,3 +269,9 @@ config BACKLIGHT_ADP5520 To compile this driver as a module, choose M here: the module will be called adp5520_bl. +config BACKLIGHT_88PM860X + tristate "Backlight Driver for 88PM8606 using WLED" + depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X + help + Say Y to enable the backlight driver for Marvell 88PM8606. + diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 9a40554..6c704d4 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -22,10 +22,12 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o +obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o +obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c new file mode 100644 index 0000000..c267069 --- /dev/null +++ b/drivers/video/backlight/max8925_bl.c @@ -0,0 +1,200 @@ +/* + * Backlight driver for Maxim MAX8925 + * + * Copyright (C) 2009 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/i2c.h> +#include <linux/backlight.h> +#include <linux/mfd/max8925.h> + +#define MAX_BRIGHTNESS (0xff) +#define MIN_BRIGHTNESS (0) + +#define LWX_FREQ(x) (((x - 601) / 100) & 0x7) + +struct max8925_backlight_data { + struct max8925_chip *chip; + + int current_brightness; +}; + +static int max8925_backlight_set(struct backlight_device *bl, int brightness) +{ + struct max8925_backlight_data *data = bl_get_data(bl); + struct max8925_chip *chip = data->chip; + unsigned char value; + int ret; + + if (brightness > MAX_BRIGHTNESS) + value = MAX_BRIGHTNESS; + else + value = brightness; + + ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value); + if (ret < 0) + goto out; + + if (!data->current_brightness && brightness) + /* enable WLED output */ + ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1); + else if (!brightness) + /* disable WLED output */ + ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0); + if (ret < 0) + goto out; + dev_dbg(chip->dev, "set brightness %d\n", value); + data->current_brightness = value; + return 0; +out: + dev_dbg(chip->dev, "set brightness %d failure with return value:%d\n", + value, ret); + return ret; +} + +static int max8925_backlight_update_status(struct backlight_device *bl) +{ + int brightness = bl->props.brightness; + + if (bl->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + if (bl->props.state & BL_CORE_SUSPENDED) + brightness = 0; + + return max8925_backlight_set(bl, brightness); +} + +static int max8925_backlight_get_brightness(struct backlight_device *bl) +{ + struct max8925_backlight_data *data = bl_get_data(bl); + struct max8925_chip *chip = data->chip; + int ret; + + ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL); + if (ret < 0) + return -EINVAL; + data->current_brightness = ret; + dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness); + return ret; +} + +static struct backlight_ops max8925_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = max8925_backlight_update_status, + .get_brightness = max8925_backlight_get_brightness, +}; + +static int __devinit max8925_backlight_probe(struct platform_device *pdev) +{ + struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct max8925_platform_data *max8925_pdata; + struct max8925_backlight_pdata *pdata = NULL; + struct max8925_backlight_data *data; + struct backlight_device *bl; + struct resource *res; + char name[MAX8925_NAME_SIZE]; + unsigned char value; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (res == NULL) { + dev_err(&pdev->dev, "No I/O resource!\n"); + return -EINVAL; + } + + if (pdev->dev.parent->platform_data) { + max8925_pdata = pdev->dev.parent->platform_data; + pdata = max8925_pdata->backlight; + } + + if (!pdata) { + dev_err(&pdev->dev, "platform data isn't assigned to " + "backlight\n"); + return -EINVAL; + } + + data = kzalloc(sizeof(struct max8925_backlight_data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + strncpy(name, res->name, MAX8925_NAME_SIZE); + data->chip = chip; + data->current_brightness = 0; + + bl = backlight_device_register(name, &pdev->dev, data, + &max8925_backlight_ops); + if (IS_ERR(bl)) { + dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); + return PTR_ERR(bl); + } + bl->props.max_brightness = MAX_BRIGHTNESS; + bl->props.brightness = MAX_BRIGHTNESS; + + platform_set_drvdata(pdev, bl); + + value = 0; + if (pdata->lxw_scl) + value |= (1 << 7); + if (pdata->lxw_freq) + value |= (LWX_FREQ(pdata->lxw_freq) << 4); + if (pdata->dual_string) + value |= (1 << 1); + ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value); + if (ret < 0) + goto out; + + backlight_update_status(bl); + return 0; +out: + kfree(data); + return ret; +} + +static int __devexit max8925_backlight_remove(struct platform_device *pdev) +{ + struct backlight_device *bl = platform_get_drvdata(pdev); + struct max8925_backlight_data *data = bl_get_data(bl); + + backlight_device_unregister(bl); + kfree(data); + return 0; +} + +static struct platform_driver max8925_backlight_driver = { + .driver = { + .name = "max8925-backlight", + .owner = THIS_MODULE, + }, + .probe = max8925_backlight_probe, + .remove = __devexit_p(max8925_backlight_remove), +}; + +static int __init max8925_backlight_init(void) +{ + return platform_driver_register(&max8925_backlight_driver); +} +module_init(max8925_backlight_init); + +static void __exit max8925_backlight_exit(void) +{ + platform_driver_unregister(&max8925_backlight_driver); +}; +module_exit(max8925_backlight_exit); + +MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925"); +MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:max8925-backlight"); diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index e49ae5e..814312a 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -82,7 +82,6 @@ struct bfin_bf54xfb_info { unsigned char *fb_buffer; /* RGB Buffer */ dma_addr_t dma_handle; - int lq043_mmap; int lq043_open_cnt; int irq; spinlock_t lock; /* lock */ @@ -316,7 +315,6 @@ static int bfin_bf54x_fb_release(struct fb_info *info, int user) spin_lock(&fbi->lock); fbi->lq043_open_cnt--; - fbi->lq043_mmap = 0; if (fbi->lq043_open_cnt <= 0) { @@ -374,33 +372,6 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var, return 0; } -static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - - struct bfin_bf54xfb_info *fbi = info->par; - - if (fbi->lq043_mmap) - return -1; - - spin_lock(&fbi->lock); - fbi->lq043_mmap = 1; - spin_unlock(&fbi->lock); - - vma->vm_start = (unsigned long)(fbi->fb_buffer); - - vma->vm_end = vma->vm_start + info->fix.smem_len; - /* For those who don't understand how mmap works, go read - * Documentation/nommu-mmap.txt. - * For those that do, you will know that the VM_MAYSHARE flag - * must be set in the vma->vm_flags structure on noMMU - * Other flags can be set, and are documented in - * include/linux/mm.h - */ - vma->vm_flags |= VM_MAYSHARE | VM_SHARED; - - return 0; -} - int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { if (nocursor) @@ -452,7 +423,6 @@ static struct fb_ops bfin_bf54x_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_mmap = bfin_bf54x_fb_mmap, .fb_cursor = bfin_bf54x_fb_cursor, .fb_setcolreg = bfin_bf54x_fb_setcolreg, }; diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index b690c26..0387236 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c @@ -22,7 +22,6 @@ #include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> -#include <linux/dma-mapping.h> #include <asm/blackfin.h> #include <asm/irq.h> diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 2549c53..5653d08 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -87,7 +87,6 @@ struct bfin_t350mcqbfb_info { struct device *dev; unsigned char *fb_buffer; /* RGB Buffer */ dma_addr_t dma_handle; - int lq043_mmap; int lq043_open_cnt; int irq; spinlock_t lock; /* lock */ @@ -235,7 +234,6 @@ static int bfin_t350mcqb_fb_release(struct fb_info *info, int user) spin_lock(&fbi->lock); fbi->lq043_open_cnt--; - fbi->lq043_mmap = 0; if (fbi->lq043_open_cnt <= 0) { bfin_t350mcqb_disable_ppi(); @@ -293,32 +291,6 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var, return 0; } -static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - if (fbi->lq043_mmap) - return -1; - - spin_lock(&fbi->lock); - fbi->lq043_mmap = 1; - spin_unlock(&fbi->lock); - - vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET); - - vma->vm_end = vma->vm_start + info->fix.smem_len; - /* For those who don't understand how mmap works, go read - * Documentation/nommu-mmap.txt. - * For those that do, you will know that the VM_MAYSHARE flag - * must be set in the vma->vm_flags structure on noMMU - * Other flags can be set, and are documented in - * include/linux/mm.h - */ - vma->vm_flags |= VM_MAYSHARE | VM_SHARED; - - return 0; -} - int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { if (nocursor) @@ -370,7 +342,6 @@ static struct fb_ops bfin_t350mcqb_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_mmap = bfin_t350mcqb_fb_mmap, .fb_cursor = bfin_t350mcqb_fb_cursor, .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, }; diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c index df9ccb9..ebda687 100644 --- a/drivers/video/broadsheetfb.c +++ b/drivers/video/broadsheetfb.c @@ -29,11 +29,65 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/list.h> +#include <linux/firmware.h> #include <linux/uaccess.h> #include <video/broadsheetfb.h> -/* Display specific information */ +/* track panel specific parameters */ +struct panel_info { + int w; + int h; + u16 sdcfg; + u16 gdcfg; + u16 lutfmt; + u16 fsynclen; + u16 fendfbegin; + u16 lsynclen; + u16 lendlbegin; + u16 pixclk; +}; + +/* table of panel specific parameters to be indexed into by the board drivers */ +static struct panel_info panel_table[] = { + { /* standard 6" on TFT backplane */ + .w = 800, + .h = 600, + .sdcfg = (100 | (1 << 8) | (1 << 9)), + .gdcfg = 2, + .lutfmt = (4 | (1 << 7)), + .fsynclen = 4, + .fendfbegin = (10 << 8) | 4, + .lsynclen = 10, + .lendlbegin = (100 << 8) | 4, + .pixclk = 6, + }, + { /* custom 3.7" flexible on PET or steel */ + .w = 320, + .h = 240, + .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)), + .gdcfg = 3, + .lutfmt = (4 | (1 << 7)), + .fsynclen = 0, + .fendfbegin = (80 << 8) | 4, + .lsynclen = 10, + .lendlbegin = (80 << 8) | 20, + .pixclk = 14, + }, + { /* standard 9.7" on TFT backplane */ + .w = 1200, + .h = 825, + .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)), + .gdcfg = 2, + .lutfmt = (4 | (1 << 7)), + .fsynclen = 0, + .fendfbegin = (4 << 8) | 4, + .lsynclen = 4, + .lendlbegin = (60 << 8) | 10, + .pixclk = 3, + }, +}; + #define DPY_W 800 #define DPY_H 600 @@ -62,30 +116,30 @@ static struct fb_var_screeninfo broadsheetfb_var __devinitdata = { }; /* main broadsheetfb functions */ -static void broadsheet_issue_data(struct broadsheetfb_par *par, u16 data) +static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data) { par->board->set_ctl(par, BS_WR, 0); par->board->set_hdb(par, data); par->board->set_ctl(par, BS_WR, 1); } -static void broadsheet_issue_cmd(struct broadsheetfb_par *par, u16 data) +static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data) { par->board->set_ctl(par, BS_DC, 0); - broadsheet_issue_data(par, data); + broadsheet_gpio_issue_data(par, data); } -static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) +static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data) { par->board->wait_for_rdy(par); par->board->set_ctl(par, BS_CS, 0); - broadsheet_issue_cmd(par, data); + broadsheet_gpio_issue_cmd(par, data); par->board->set_ctl(par, BS_DC, 1); par->board->set_ctl(par, BS_CS, 1); } -static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, +static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, int argc, u16 *argv) { int i; @@ -93,15 +147,43 @@ static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, par->board->wait_for_rdy(par); par->board->set_ctl(par, BS_CS, 0); - broadsheet_issue_cmd(par, cmd); + broadsheet_gpio_issue_cmd(par, cmd); par->board->set_ctl(par, BS_DC, 1); for (i = 0; i < argc; i++) - broadsheet_issue_data(par, argv[i]); + broadsheet_gpio_issue_data(par, argv[i]); par->board->set_ctl(par, BS_CS, 1); } -static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, +static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, + int argc, u16 *argv) +{ + int i; + + par->board->mmio_write(par, BS_MMIO_CMD, cmd); + + for (i = 0; i < argc; i++) + par->board->mmio_write(par, BS_MMIO_DATA, argv[i]); +} + +static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) +{ + if (par->board->mmio_write) + par->board->mmio_write(par, BS_MMIO_CMD, data); + else + broadsheet_gpio_send_command(par, data); +} + +static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, + int argc, u16 *argv) +{ + if (par->board->mmio_write) + broadsheet_mmio_send_cmdargs(par, cmd, argc, argv); + else + broadsheet_gpio_send_cmdargs(par, cmd, argc, argv); +} + +static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size, u16 *data) { int i; @@ -121,7 +203,30 @@ static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, par->board->set_ctl(par, BS_CS, 1); } -static u16 broadsheet_get_data(struct broadsheetfb_par *par) +static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size, + u16 *data) +{ + int i; + u16 tmp; + + for (i = 0; i < size; i++) { + tmp = (data[i] & 0x0F) << 4; + tmp |= (data[i] & 0x0F00) << 4; + par->board->mmio_write(par, BS_MMIO_DATA, tmp); + } + +} + +static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, + u16 *data) +{ + if (par->board->mmio_write) + broadsheet_mmio_burst_write(par, size, data); + else + broadsheet_gpio_burst_write(par, size, data); +} + +static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par) { u16 res; /* wait for ready to go hi. (lo is busy) */ @@ -141,7 +246,16 @@ static u16 broadsheet_get_data(struct broadsheetfb_par *par) return res; } -static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, + +static u16 broadsheet_get_data(struct broadsheetfb_par *par) +{ + if (par->board->mmio_read) + return par->board->mmio_read(par); + else + return broadsheet_gpio_get_data(par); +} + +static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg, u16 data) { /* wait for ready to go hi. (lo is busy) */ @@ -150,44 +264,541 @@ static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, /* cs lo, dc lo for cmd, we lo for each data, db as usual */ par->board->set_ctl(par, BS_CS, 0); - broadsheet_issue_cmd(par, BS_CMD_WR_REG); + broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG); par->board->set_ctl(par, BS_DC, 1); - broadsheet_issue_data(par, reg); - broadsheet_issue_data(par, data); + broadsheet_gpio_issue_data(par, reg); + broadsheet_gpio_issue_data(par, data); par->board->set_ctl(par, BS_CS, 1); } +static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg, + u16 data) +{ + par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG); + par->board->mmio_write(par, BS_MMIO_DATA, reg); + par->board->mmio_write(par, BS_MMIO_DATA, data); + +} + +static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, + u16 data) +{ + if (par->board->mmio_write) + broadsheet_mmio_write_reg(par, reg, data); + else + broadsheet_gpio_write_reg(par, reg, data); +} + +static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg, + u32 data) +{ + broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF); + broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF); +} + + static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg) { - broadsheet_send_command(par, reg); - msleep(100); + broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, ®); + par->board->wait_for_rdy(par); return broadsheet_get_data(par); } +/* functions for waveform manipulation */ +static int is_broadsheet_pll_locked(struct broadsheetfb_par *par) +{ + return broadsheet_read_reg(par, 0x000A) & 0x0001; +} + +static int broadsheet_setup_plls(struct broadsheetfb_par *par) +{ + int retry_count = 0; + u16 tmp; + + /* disable arral saemipu mode */ + broadsheet_write_reg(par, 0x0006, 0x0000); + + broadsheet_write_reg(par, 0x0010, 0x0004); + broadsheet_write_reg(par, 0x0012, 0x5949); + broadsheet_write_reg(par, 0x0014, 0x0040); + broadsheet_write_reg(par, 0x0016, 0x0000); + + do { + if (retry_count++ > 100) + return -ETIMEDOUT; + mdelay(1); + } while (!is_broadsheet_pll_locked(par)); + + tmp = broadsheet_read_reg(par, 0x0006); + tmp &= ~0x1; + broadsheet_write_reg(par, 0x0006, tmp); + + return 0; +} + +static int broadsheet_setup_spi(struct broadsheetfb_par *par) +{ + + broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); + broadsheet_write_reg(par, 0x0208, 0x0001); + + return 0; +} + +static int broadsheet_setup_spiflash(struct broadsheetfb_par *par, + u16 *orig_sfmcd) +{ + + *orig_sfmcd = broadsheet_read_reg(par, 0x0204); + broadsheet_write_reg(par, 0x0208, 0); + broadsheet_write_reg(par, 0x0204, 0); + broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); + + return 0; +} + +static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par, + u16 reg, int bitnum, int val, + int timeout) +{ + u16 tmp; + + do { + tmp = broadsheet_read_reg(par, reg); + if (((tmp >> bitnum) & 1) == val) + return 0; + mdelay(1); + } while (timeout--); + + return -ETIMEDOUT; +} + +static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data) +{ + broadsheet_write_reg(par, 0x0202, (data | 0x100)); + + return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); +} + +static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data) +{ + int err; + u16 tmp; + + broadsheet_write_reg(par, 0x0202, 0); + + err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); + if (err) + return err; + + tmp = broadsheet_read_reg(par, 0x200); + + *data = tmp & 0xFF; + + return 0; +} + +static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par, + int timeout) +{ + u8 tmp; + int err; + + do { + broadsheet_write_reg(par, 0x0208, 1); + + err = broadsheet_spiflash_write_byte(par, 0x05); + if (err) + goto failout; + + err = broadsheet_spiflash_read_byte(par, &tmp); + if (err) + goto failout; + + broadsheet_write_reg(par, 0x0208, 0); + + if (!(tmp & 0x1)) + return 0; + + mdelay(5); + } while (timeout--); + + dev_err(par->info->device, "Timed out waiting for spiflash status\n"); + return -ETIMEDOUT; + +failout: + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par, + u8 op, u32 addr) +{ + int i; + u8 tmp; + int err; + + broadsheet_write_reg(par, 0x0208, 1); + + err = broadsheet_spiflash_write_byte(par, op); + if (err) + return err; + + for (i = 2; i >= 0; i--) { + tmp = ((addr >> (i * 8)) & 0xFF); + err = broadsheet_spiflash_write_byte(par, tmp); + if (err) + return err; + } + + return err; +} + +static int broadsheet_verify_spiflash(struct broadsheetfb_par *par, + int *flash_type) +{ + int err = 0; + u8 sig; + + err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000); + if (err) + goto failout; + + err = broadsheet_spiflash_read_byte(par, &sig); + if (err) + goto failout; + + if ((sig != 0x10) && (sig != 0x11)) { + dev_err(par->info->device, "Unexpected flash type\n"); + err = -EINVAL; + goto failout; + } + + *flash_type = sig; + +failout: + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par, + u16 *initial_sfmcd, int *flash_type) + +{ + int err; + + err = broadsheet_setup_plls(par); + if (err) + return err; + + broadsheet_write_reg(par, 0x0106, 0x0203); + + err = broadsheet_setup_spi(par); + if (err) + return err; + + err = broadsheet_setup_spiflash(par, initial_sfmcd); + if (err) + return err; + + return broadsheet_verify_spiflash(par, flash_type); +} + +static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par, + int mode) +{ + int err; + + broadsheet_write_reg(par, 0x0208, 1); + if (mode) + err = broadsheet_spiflash_write_byte(par, 0x06); + else + err = broadsheet_spiflash_write_byte(par, 0x04); + + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par, + int addr) +{ + int err; + + broadsheet_spiflash_write_control(par, 1); + + err = broadsheet_spiflash_op_on_address(par, 0xD8, addr); + + broadsheet_write_reg(par, 0x0208, 0); + + if (err) + return err; + + err = broadsheet_spiflash_wait_for_status(par, 1000); + + return err; +} + +static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par, + int addr, int size, char *data) +{ + int err; + int i; + + err = broadsheet_spiflash_op_on_address(par, 0x03, addr); + if (err) + goto failout; + + for (i = 0; i < size; i++) { + err = broadsheet_spiflash_read_byte(par, &data[i]); + if (err) + goto failout; + } + +failout: + broadsheet_write_reg(par, 0x0208, 0); + return err; +} + +#define BS_SPIFLASH_PAGE_SIZE 256 +static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par, + int addr, const char *data) +{ + int err; + int i; + + broadsheet_spiflash_write_control(par, 1); + + err = broadsheet_spiflash_op_on_address(par, 0x02, addr); + if (err) + goto failout; + + for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) { + err = broadsheet_spiflash_write_byte(par, data[i]); + if (err) + goto failout; + } + + broadsheet_write_reg(par, 0x0208, 0); + + err = broadsheet_spiflash_wait_for_status(par, 100); + +failout: + return err; +} + +static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par, + int addr, const char *data, int sector_size) +{ + int i; + int err; + + for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) { + err = broadsheet_spiflash_write_page(par, addr + i, &data[i]); + if (err) + return err; + } + return 0; +} + +/* + * The caller must guarantee that the data to be rewritten is entirely + * contained within this sector. That is, data_start_addr + data_len + * must be less than sector_start_addr + sector_size. + */ +static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par, + int sector_size, int data_start_addr, + int data_len, const char *data) +{ + int err; + char *sector_buffer; + int tail_start_addr; + int start_sector_addr; + + sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL); + if (!sector_buffer) + return -ENOMEM; + + /* the start address of the sector is the 0th byte of that sector */ + start_sector_addr = (data_start_addr / sector_size) * sector_size; + + /* + * check if there is head data that we need to readback into our sector + * buffer first + */ + if (data_start_addr != start_sector_addr) { + /* + * we need to read every byte up till the start address of our + * data and we put it into our sector buffer. + */ + err = broadsheet_spiflash_read_range(par, start_sector_addr, + data_start_addr, sector_buffer); + if (err) + return err; + } + + /* now we copy our data into the right place in the sector buffer */ + memcpy(sector_buffer + data_start_addr, data, data_len); + + /* + * now we check if there is a tail section of the sector that we need to + * readback. + */ + tail_start_addr = (data_start_addr + data_len) % sector_size; + + if (tail_start_addr) { + int tail_len; + + tail_len = sector_size - tail_start_addr; + + /* now we read this tail into our sector buffer */ + err = broadsheet_spiflash_read_range(par, tail_start_addr, + tail_len, sector_buffer + tail_start_addr); + if (err) + return err; + } + + /* if we got here we have the full sector that we want to rewrite. */ + + /* first erase the sector */ + err = broadsheet_spiflash_erase_sector(par, start_sector_addr); + if (err) + return err; + + /* now write it */ + err = broadsheet_spiflash_write_sector(par, start_sector_addr, + sector_buffer, sector_size); + return err; +} + +static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr, + const u8 *wfm, int bytecount, int flash_type) +{ + int sector_size; + int err; + int cur_addr; + int writecount; + int maxlen; + int offset = 0; + + switch (flash_type) { + case 0x10: + sector_size = 32*1024; + break; + case 0x11: + default: + sector_size = 64*1024; + break; + } + + while (bytecount) { + cur_addr = wfm_addr + offset; + maxlen = roundup(cur_addr, sector_size) - cur_addr; + writecount = min(bytecount, maxlen); + + err = broadsheet_spiflash_rewrite_sector(par, sector_size, + cur_addr, writecount, wfm + offset); + if (err) + return err; + + offset += writecount; + bytecount -= writecount; + } + + return 0; +} + +static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par, + const u8 *wfm, size_t wfm_size) +{ + int err = 0; + u16 initial_sfmcd = 0; + int flash_type = 0; + + err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type); + if (err) + goto failout; + + err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type); + +failout: + broadsheet_write_reg(par, 0x0204, initial_sfmcd); + return err; +} + +static ssize_t broadsheet_loadstore_waveform(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + int err; + struct fb_info *info = dev_get_drvdata(dev); + struct broadsheetfb_par *par = info->par; + const struct firmware *fw_entry; + + if (len < 1) + return -EINVAL; + + err = request_firmware(&fw_entry, "broadsheet.wbf", dev); + if (err < 0) { + dev_err(dev, "Failed to get broadsheet waveform\n"); + goto err_failed; + } + + /* try to enforce reasonable min max on waveform */ + if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) { + dev_err(dev, "Invalid waveform\n"); + err = -EINVAL; + goto err_failed; + } + + mutex_lock(&(par->io_lock)); + err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data, + fw_entry->size); + + mutex_unlock(&(par->io_lock)); + if (err < 0) { + dev_err(dev, "Failed to store broadsheet waveform\n"); + goto err_failed; + } + + dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size); + + return len; + +err_failed: + return err; +} +static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL, + broadsheet_loadstore_waveform); + +/* upper level functions that manipulate the display and other stuff */ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) { u16 args[5]; - - args[0] = DPY_W; - args[1] = DPY_H; - args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */ - args[3] = 2; /* gdrv cfg */ - args[4] = (4 | (1 << 7)); /* lut index format */ + int xres = par->info->var.xres; + int yres = par->info->var.yres; + + args[0] = panel_table[par->panel_index].w; + args[1] = panel_table[par->panel_index].h; + args[2] = panel_table[par->panel_index].sdcfg; + args[3] = panel_table[par->panel_index].gdcfg; + args[4] = panel_table[par->panel_index].lutfmt; broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); /* did the controller really set it? */ broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); - args[0] = 4; /* fsync len */ - args[1] = (10 << 8) | 4; /* fend/fbegin len */ - args[2] = 10; /* line sync len */ - args[3] = (100 << 8) | 4; /* line end/begin len */ - args[4] = 6; /* pixel clock cfg */ + args[0] = panel_table[par->panel_index].fsynclen; + args[1] = panel_table[par->panel_index].fendfbegin; + args[2] = panel_table[par->panel_index].lsynclen; + args[3] = panel_table[par->panel_index].lendlbegin; + args[4] = panel_table[par->panel_index].pixclk; broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); + broadsheet_write_reg32(par, 0x310, xres*yres*2); + /* setup waveform */ args[0] = 0x886; args[1] = 0; @@ -207,8 +818,9 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) args[0] = 0x154; broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); - broadsheet_burst_write(par, DPY_W*DPY_H/2, - (u16 *) par->info->screen_base); + broadsheet_burst_write(par, (panel_table[par->panel_index].w * + panel_table[par->panel_index].h)/2, + (u16 *) par->info->screen_base); broadsheet_send_command(par, BS_CMD_LD_IMG_END); @@ -222,6 +834,21 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) par->board->wait_for_rdy(par); } +static void __devinit broadsheet_identify(struct broadsheetfb_par *par) +{ + u16 rev, prc; + struct device *dev = par->info->device; + + rev = broadsheet_read_reg(par, BS_REG_REV); + prc = broadsheet_read_reg(par, BS_REG_PRC); + dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc); + + if (prc != 0x0047) + dev_warn(dev, "Unrecognized Broadsheet Product Code\n"); + if (rev != 0x0100) + dev_warn(dev, "Unrecognized Broadsheet Revision\n"); +} + static void __devinit broadsheet_init(struct broadsheetfb_par *par) { broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); @@ -236,6 +863,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, u16 args[5]; unsigned char *buf = (unsigned char *)par->info->screen_base; + mutex_lock(&(par->io_lock)); /* y1 must be a multiple of 4 so drop the lower bits */ y1 &= 0xFFFC; /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ @@ -265,6 +893,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); par->board->wait_for_rdy(par); + mutex_unlock(&(par->io_lock)); } @@ -272,13 +901,15 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) { u16 args[5]; + mutex_lock(&(par->io_lock)); args[0] = 0x3 << 4; broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); args[0] = 0x154; broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); - broadsheet_burst_write(par, DPY_W*DPY_H/2, - (u16 *) par->info->screen_base); + broadsheet_burst_write(par, (panel_table[par->panel_index].w * + panel_table[par->panel_index].h)/2, + (u16 *) par->info->screen_base); broadsheet_send_command(par, BS_CMD_LD_IMG_END); @@ -290,7 +921,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); par->board->wait_for_rdy(par); - + mutex_unlock(&(par->io_lock)); } /* this is called back from the deferred io workqueue */ @@ -436,6 +1067,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) unsigned char *videomemory; struct broadsheetfb_par *par; int i; + int dpyw, dpyh; + int panel_index; /* pick up board specific routines */ board = dev->dev.platform_data; @@ -450,7 +1083,24 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) if (!info) goto err; - videomemorysize = (DPY_W*DPY_H); + switch (board->get_panel_type()) { + case 37: + panel_index = 1; + break; + case 97: + panel_index = 2; + break; + case 6: + default: + panel_index = 0; + break; + } + + dpyw = panel_table[panel_index].w; + dpyh = panel_table[panel_index].h; + + videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); + videomemory = vmalloc(videomemorysize); if (!videomemory) goto err_fb_rel; @@ -460,16 +1110,25 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) info->screen_base = (char *)videomemory; info->fbops = &broadsheetfb_ops; + broadsheetfb_var.xres = dpyw; + broadsheetfb_var.yres = dpyh; + broadsheetfb_var.xres_virtual = dpyw; + broadsheetfb_var.yres_virtual = dpyh; info->var = broadsheetfb_var; + + broadsheetfb_fix.line_length = dpyw; info->fix = broadsheetfb_fix; info->fix.smem_len = videomemorysize; par = info->par; + par->panel_index = panel_index; par->info = info; par->board = board; par->write_reg = broadsheet_write_reg; par->read_reg = broadsheet_read_reg; init_waitqueue_head(&par->waitq); + mutex_init(&par->io_lock); + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; info->fbdefio = &broadsheetfb_defio; @@ -496,13 +1155,20 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) if (retval < 0) goto err_free_irq; + broadsheet_identify(par); + broadsheet_init(par); retval = register_framebuffer(info); if (retval < 0) goto err_free_irq; + platform_set_drvdata(dev, info); + retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform); + if (retval < 0) + goto err_unreg_fb; + printk(KERN_INFO "fb%d: Broadsheet frame buffer, using %dK of video memory\n", info->node, videomemorysize >> 10); @@ -510,6 +1176,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev) return 0; +err_unreg_fb: + unregister_framebuffer(info); err_free_irq: board->cleanup(par); err_cmap: @@ -530,6 +1198,8 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev) if (info) { struct broadsheetfb_par *par = info->par; + + device_remove_file(info->dev, &dev_attr_loadstore_waveform); unregister_framebuffer(info); fb_deferred_io_cleanup(info); par->board->cleanup(par); diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 108b89e..5eb61b5 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -287,7 +287,7 @@ static struct fb_ops cobalt_lcd_fbops = { .fb_cursor = cobalt_lcdfb_cursor, }; -static int __init cobalt_lcdfb_probe(struct platform_device *dev) +static int __devinit cobalt_lcdfb_probe(struct platform_device *dev) { struct fb_info *info; struct resource *res; diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index fc7d9bb..8e8f18d 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -37,6 +37,7 @@ config VGACON_SOFT_SCROLLBACK config VGACON_SOFT_SCROLLBACK_SIZE int "Scrollback Buffer Size (in KB)" depends on VGACON_SOFT_SCROLLBACK + range 1 1024 default "64" help Enter the amount of System RAM to allocate for the scrollback diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3681c6a..b0a3fa0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3025,6 +3025,20 @@ static int fbcon_fb_unregistered(struct fb_info *info) return 0; } +static void fbcon_remap_all(int idx) +{ + int i; + for (i = first_fb_vc; i <= last_fb_vc; i++) + set_con2fb_map(i, idx, 0); + + if (con_is_bound(&fb_con)) { + printk(KERN_INFO "fbcon: Remapping primary device, " + "fb%i, to tty %i-%i\n", idx, + first_fb_vc + 1, last_fb_vc + 1); + info_idx = idx; + } +} + #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY static void fbcon_select_primary(struct fb_info *info) { @@ -3225,6 +3239,10 @@ static int fbcon_event_notify(struct notifier_block *self, caps = event->data; fbcon_get_requirement(info, caps); break; + case FB_EVENT_REMAP_ALL_CONSOLE: + idx = info->node; + fbcon_remap_all(idx); + break; } done: return ret; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index cc4bbbe..182dd6f 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -112,7 +112,7 @@ static int vga_video_font_height; static int vga_scan_lines __read_mostly; static unsigned int vga_rolled_over; -int vgacon_text_mode_force = 0; +static int vgacon_text_mode_force; bool vgacon_text_force(void) { diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index d25df51..581d2db 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -210,7 +210,7 @@ static int __init efifb_setup(char *options) return 0; } -static int __init efifb_probe(struct platform_device *dev) +static int __devinit efifb_probe(struct platform_device *dev) { struct fb_info *info; int err; diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 2735b79..6d755bb 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -602,7 +602,7 @@ static int epson1355fb_remove(struct platform_device *dev) return 0; } -int __init epson1355fb_probe(struct platform_device *dev) +int __devinit epson1355fb_probe(struct platform_device *dev) { struct epson1355_par *default_par; struct fb_info *info; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 99bbd28..a15b44e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1513,7 +1513,6 @@ register_framebuffer(struct fb_info *fb_info) fb_info->fix.id, registered_fb[i]->fix.id); unregister_framebuffer(registered_fb[i]); - break; } } } diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 695fa01..5643a35 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1128,7 +1128,7 @@ static int __init gbefb_setup(char *options) return 0; } -static int __init gbefb_probe(struct platform_device *p_dev) +static int __devinit gbefb_probe(struct platform_device *p_dev) { int i, ret = 0; struct fb_info *info; diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 0129c04..db9b785 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = { * Initialization */ -static int __init hgafb_probe(struct platform_device *pdev) +static int __devinit hgafb_probe(struct platform_device *pdev) { struct fb_info *info; diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 73c83a8..bf78779 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -325,7 +325,7 @@ static struct fb_ops hitfb_ops = { .fb_imageblit = cfb_imageblit, }; -static int __init hitfb_probe(struct platform_device *dev) +static int __devinit hitfb_probe(struct platform_device *dev) { unsigned short lcdclor, ldr3, ldvndr; struct fb_info *info; diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index fabb0c5..8280a58 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -31,15 +31,6 @@ #define CARMINE_MEM_SIZE 0x8000000 #define DRV_NAME "mb862xxfb" -#if defined(CONFIG_LWMON5) -static struct mb862xx_gc_mode lwmon5_gc_mode = { - /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */ - { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 }, - /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */ - 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2 -}; -#endif - #if defined(CONFIG_SOCRATES) static struct mb862xx_gc_mode socrates_gc_mode = { /* Mode for Prime View PM070WL4 TFT LCD Panel */ @@ -600,10 +591,6 @@ static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, goto irqdisp; } -#if defined(CONFIG_LWMON5) - par->gc_mode = &lwmon5_gc_mode; -#endif - #if defined(CONFIG_SOCRATES) par->gc_mode = &socrates_gc_mode; #endif diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 01f77bc..afea9ab 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -693,7 +693,7 @@ static void __devinit setup_memc(struct fb_info *fbi) unsigned long tmp; int i; - /* FIXME: use platfrom specific parameters */ + /* FIXME: use platform specific parameters */ /* setup SDRAM controller */ write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS), diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 0129f1b..b895aae 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -893,7 +893,7 @@ const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var, } /** - * fb_add_videomode: adds videomode entry to modelist + * fb_add_videomode - adds videomode entry to modelist * @mode: videomode to add * @head: struct list_head of modelist * @@ -928,7 +928,7 @@ int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head) } /** - * fb_delete_videomode: removed videomode entry from modelist + * fb_delete_videomode - removed videomode entry from modelist * @mode: videomode to remove * @head: struct list_head of modelist * @@ -953,7 +953,7 @@ void fb_delete_videomode(const struct fb_videomode *mode, } /** - * fb_destroy_modelist: destroy modelist + * fb_destroy_modelist - destroy modelist * @head: struct list_head of modelist */ void fb_destroy_modelist(struct list_head *head) @@ -968,7 +968,7 @@ void fb_destroy_modelist(struct list_head *head) EXPORT_SYMBOL_GPL(fb_destroy_modelist); /** - * fb_videomode_to_modelist: convert mode array to mode list + * fb_videomode_to_modelist - convert mode array to mode list * @modedb: array of struct fb_videomode * @num: number of entries in array * @head: struct list_head of modelist diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c new file mode 100644 index 0000000..6bf0d46 --- /dev/null +++ b/drivers/video/nuc900fb.c @@ -0,0 +1,779 @@ +/* + * + * Copyright (c) 2009 Nuvoton technology corporation + * All rights reserved. + * + * 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. + * + * Description: + * Nuvoton LCD Controller Driver + * Author: + * Wang Qiang (rurality.linux@gmail.com) 2009/12/11 + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/workqueue.h> +#include <linux/wait.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/cpufreq.h> +#include <linux/io.h> +#include <linux/pm.h> +#include <linux/device.h> + +#include <mach/map.h> +#include <mach/regs-clock.h> +#include <mach/regs-ldm.h> +#include <mach/fb.h> +#include <mach/clkdev.h> + +#include "nuc900fb.h" + + +/* + * Initialize the nuc900 video (dual) buffer address + */ +static void nuc900fb_set_lcdaddr(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + void __iomem *regs = fbi->io; + unsigned long vbaddr1, vbaddr2; + + vbaddr1 = info->fix.smem_start; + vbaddr2 = info->fix.smem_start; + vbaddr2 += info->fix.line_length * info->var.yres; + + /* set frambuffer start phy addr*/ + writel(vbaddr1, regs + REG_LCM_VA_BADDR0); + writel(vbaddr2, regs + REG_LCM_VA_BADDR1); + + writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL); + writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE); +} + +/* + * calculate divider for lcd div + */ +static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi, + unsigned long pixclk) +{ + unsigned long clk = fbi->clk_rate; + unsigned long long div; + + /* pixclk is in picseconds. our clock is in Hz*/ + /* div = (clk * pixclk)/10^12 */ + div = (unsigned long long)clk * pixclk; + div >>= 12; + do_div(div, 625 * 625UL * 625); + + dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div); + + return div; +} + +/* + * Check the video params of 'var'. + */ +static int nuc900fb_check_var(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; + struct nuc900fb_display *display = NULL; + struct nuc900fb_display *default_display = mach_info->displays + + mach_info->default_display; + int i; + + dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info); + + /* validate x/y resolution */ + /* choose default mode if possible */ + if (var->xres == default_display->xres && + var->yres == default_display->yres && + var->bits_per_pixel == default_display->bpp) + display = default_display; + else + for (i = 0; i < mach_info->num_displays; i++) + if (var->xres == mach_info->displays[i].xres && + var->yres == mach_info->displays[i].yres && + var->bits_per_pixel == mach_info->displays[i].bpp) { + display = mach_info->displays + i; + break; + } + + if (display == NULL) { + printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + + /* it should be the same size as the display */ + var->xres_virtual = display->xres; + var->yres_virtual = display->yres; + var->height = display->height; + var->width = display->width; + + /* copy lcd settings */ + var->pixclock = display->pixclock; + var->left_margin = display->left_margin; + var->right_margin = display->right_margin; + var->upper_margin = display->upper_margin; + var->lower_margin = display->lower_margin; + var->vsync_len = display->vsync_len; + var->hsync_len = display->hsync_len; + + var->transp.offset = 0; + var->transp.length = 0; + + fbi->regs.lcd_dccs = display->dccs; + fbi->regs.lcd_device_ctrl = display->devctl; + fbi->regs.lcd_va_fbctrl = display->fbctrl; + fbi->regs.lcd_va_scale = display->scale; + + /* set R/G/B possions */ + switch (var->bits_per_pixel) { + case 1: + case 2: + case 4: + case 8: + default: + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + break; + case 12: + var->red.length = 4; + var->green.length = 4; + var->blue.length = 4; + var->red.offset = 8; + var->green.offset = 4; + var->blue.offset = 0; + break; + case 16: + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + break; + case 18: + var->red.length = 6; + var->green.length = 6; + var->blue.length = 6; + var->red.offset = 12; + var->green.offset = 6; + var->blue.offset = 0; + break; + case 32: + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + break; + } + + return 0; +} + +/* + * Calculate lcd register values from var setting & save into hw + */ +static void nuc900fb_calculate_lcd_regs(const struct fb_info *info, + struct nuc900fb_hw *regs) +{ + const struct fb_var_screeninfo *var = &info->var; + int vtt = var->height + var->upper_margin + var->lower_margin; + int htt = var->width + var->left_margin + var->right_margin; + int hsync = var->width + var->right_margin; + int vsync = var->height + var->lower_margin; + + regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) | + LCM_CRTC_SIZE_HTTVAL(htt); + regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) | + LCM_CRTC_DEND_HDENDVAL(var->width); + regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) | + LCM_CRTC_HR_SVAL(var->width + 1); + regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) | + LCM_CRTC_HSYNC_SVAL(hsync); + regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) | + LCM_CRTC_VR_SVAL(vsync); + +} + +/* + * Activate (set) the controller from the given framebuffer + * information + */ +static void nuc900fb_activate_var(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + void __iomem *regs = fbi->io; + struct fb_var_screeninfo *var = &info->var; + int clkdiv; + + clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1; + if (clkdiv < 0) + clkdiv = 0; + + nuc900fb_calculate_lcd_regs(info, &fbi->regs); + + /* set the new lcd registers*/ + + dev_dbg(fbi->dev, "new lcd register set:\n"); + dev_dbg(fbi->dev, "dccs = 0x%08x\n", fbi->regs.lcd_dccs); + dev_dbg(fbi->dev, "dev_ctl = 0x%08x\n", fbi->regs.lcd_device_ctrl); + dev_dbg(fbi->dev, "crtc_size = 0x%08x\n", fbi->regs.lcd_crtc_size); + dev_dbg(fbi->dev, "crtc_dend = 0x%08x\n", fbi->regs.lcd_crtc_dend); + dev_dbg(fbi->dev, "crtc_hr = 0x%08x\n", fbi->regs.lcd_crtc_hr); + dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync); + dev_dbg(fbi->dev, "crtc_vr = 0x%08x\n", fbi->regs.lcd_crtc_vr); + + writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL); + writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE); + writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND); + writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR); + writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC); + writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR); + + /* set lcd address pointers */ + nuc900fb_set_lcdaddr(info); + + writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS); +} + +/* + * Alters the hardware state. + * + */ +static int nuc900fb_set_par(struct fb_info *info) +{ + struct fb_var_screeninfo *var = &info->var; + + switch (var->bits_per_pixel) { + case 32: + case 24: + case 18: + case 16: + case 12: + info->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + info->fix.visual = FB_VISUAL_MONO01; + break; + default: + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + } + + info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; + + /* activate this new configuration */ + nuc900fb_activate_var(info); + return 0; +} + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int nuc900fb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + unsigned int val; + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + /* true-colour, use pseuo-palette */ + if (regno < 16) { + u32 *pal = info->pseudo_palette; + + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + pal[regno] = val; + } + break; + + default: + return 1; /* unknown type */ + } + return 0; +} + +/** + * nuc900fb_blank + * + */ +static int nuc900fb_blank(int blank_mode, struct fb_info *info) +{ + + return 0; +} + +static struct fb_ops nuc900fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = nuc900fb_check_var, + .fb_set_par = nuc900fb_set_par, + .fb_blank = nuc900fb_blank, + .fb_setcolreg = nuc900fb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + + +static inline void modify_gpio(void __iomem *reg, + unsigned long set, unsigned long mask) +{ + unsigned long tmp; + tmp = readl(reg) & ~mask; + writel(tmp | set, reg); +} + +/* + * Initialise LCD-related registers + */ +static int nuc900fb_init_registers(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data; + void __iomem *regs = fbi->io; + + /*reset the display engine*/ + writel(0, regs + REG_LCM_DCCS); + writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST, + regs + REG_LCM_DCCS); + ndelay(100); + writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST), + regs + REG_LCM_DCCS); + ndelay(100); + + writel(0, regs + REG_LCM_DEV_CTRL); + + /* config gpio output */ + modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir, + mach_info->gpio_dir_mask); + modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data, + mach_info->gpio_data_mask); + + return 0; +} + + +/* + * Alloc the SDRAM region of NUC900 for the frame buffer. + * The buffer should be a non-cached, non-buffered, memory region + * to allow palette and pixel writes without flushing the cache. + */ +static int __init nuc900fb_map_video_memory(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + dma_addr_t map_dma; + unsigned long map_size = PAGE_ALIGN(info->fix.smem_len); + + dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n", + fbi, map_size); + + info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, + &map_dma, GFP_KERNEL); + + if (!info->screen_base) + return -ENOMEM; + + memset(info->screen_base, 0x00, map_size); + info->fix.smem_start = map_dma; + + return 0; +} + +static inline void nuc900fb_unmap_video_memory(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), + info->screen_base, info->fix.smem_start); +} + +static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id) +{ + struct nuc900fb_info *fbi = dev_id; + void __iomem *regs = fbi->io; + void __iomem *irq_base = fbi->irq_base; + unsigned long lcdirq = readl(regs + REG_LCM_INT_CS); + + if (lcdirq & LCM_INT_CS_DISP_F_STATUS) { + writel(readl(irq_base) | 1<<30, irq_base); + + /* wait VA_EN low */ + if ((readl(regs + REG_LCM_DCCS) & + LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE) + while ((readl(regs + REG_LCM_DCCS) & + LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN) + ; + /* display_out-enable */ + writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN, + regs + REG_LCM_DCCS); + /* va-enable*/ + writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN, + regs + REG_LCM_DCCS); + } else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) { + writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base); + } else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) { + writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base); + } + + return IRQ_HANDLED; +} + +#ifdef CONFIG_CPU_FREQ + +static int nuc900fb_cpufreq_transition(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct nuc900fb_info *info; + struct fb_info *fbinfo; + long delta_f; + info = container_of(nb, struct nuc900fb_info, freq_transition); + fbinfo = platform_get_drvdata(to_platform_device(info->dev)); + + delta_f = info->clk_rate - clk_get_rate(info->clk); + + if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) || + (val == CPUFREQ_PRECHANGE && delta_f < 0)) { + info->clk_rate = clk_get_rate(info->clk); + nuc900fb_activate_var(fbinfo); + } + + return 0; +} + +static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi) +{ + fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition; + return cpufreq_register_notifier(&fbi->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +} + +static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi) +{ + cpufreq_unregister_notifier(&fbi->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +} +#else +static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb, + unsigned long val, void *data) +{ + return 0; +} + +static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi) +{ + return 0; +} + +static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info) +{ +} +#endif + +static char driver_name[] = "nuc900fb"; + +static int __devinit nuc900fb_probe(struct platform_device *pdev) +{ + struct nuc900fb_info *fbi; + struct nuc900fb_display *display; + struct fb_info *fbinfo; + struct nuc900fb_mach_info *mach_info; + struct resource *res; + int ret; + int irq; + int i; + int size; + + dev_dbg(&pdev->dev, "devinit\n"); + mach_info = pdev->dev.platform_data; + if (mach_info == NULL) { + dev_err(&pdev->dev, + "no platform data for lcd, cannot attach\n"); + return -EINVAL; + } + + if (mach_info->default_display > mach_info->num_displays) { + dev_err(&pdev->dev, + "default display No. is %d but only %d displays \n", + mach_info->default_display, mach_info->num_displays); + return -EINVAL; + } + + + display = mach_info->displays + mach_info->default_display; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no irq for device\n"); + return -ENOENT; + } + + fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev); + if (!fbinfo) + return -ENOMEM; + + platform_set_drvdata(pdev, fbinfo); + + fbi = fbinfo->par; + fbi->dev = &pdev->dev; + +#ifdef CONFIG_CPU_NUC950 + fbi->drv_type = LCDDRV_NUC950; +#endif + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + size = (res->end - res->start) + 1; + fbi->mem = request_mem_region(res->start, size, pdev->name); + if (fbi->mem == NULL) { + dev_err(&pdev->dev, "failed to alloc memory region\n"); + ret = -ENOENT; + goto free_fb; + } + + fbi->io = ioremap(res->start, size); + if (fbi->io == NULL) { + dev_err(&pdev->dev, "ioremap() of lcd registers failed\n"); + ret = -ENXIO; + goto release_mem_region; + } + + fbi->irq_base = fbi->io + REG_LCM_INT_CS; + + + /* Stop the LCD */ + writel(0, fbi->io + REG_LCM_DCCS); + + /* fill the fbinfo*/ + strcpy(fbinfo->fix.id, driver_name); + fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; + fbinfo->fix.type_aux = 0; + fbinfo->fix.xpanstep = 0; + fbinfo->fix.ypanstep = 0; + fbinfo->fix.ywrapstep = 0; + fbinfo->fix.accel = FB_ACCEL_NONE; + fbinfo->var.nonstd = 0; + fbinfo->var.activate = FB_ACTIVATE_NOW; + fbinfo->var.accel_flags = 0; + fbinfo->var.vmode = FB_VMODE_NONINTERLACED; + fbinfo->fbops = &nuc900fb_ops; + fbinfo->flags = FBINFO_FLAG_DEFAULT; + fbinfo->pseudo_palette = &fbi->pseudo_pal; + + ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED, + pdev->name, fbinfo); + if (ret) { + dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", + irq, ret); + ret = -EBUSY; + goto release_regs; + } + + nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2); + + fbi->clk = clk_get(&pdev->dev, NULL); + if (!fbi->clk || IS_ERR(fbi->clk)) { + printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); + ret = -ENOENT; + goto release_irq; + } + + clk_enable(fbi->clk); + dev_dbg(&pdev->dev, "got and enabled clock\n"); + + fbi->clk_rate = clk_get_rate(fbi->clk); + + /* calutate the video buffer size */ + for (i = 0; i < mach_info->num_displays; i++) { + unsigned long smem_len = mach_info->displays[i].xres; + smem_len *= mach_info->displays[i].yres; + smem_len *= mach_info->displays[i].bpp; + smem_len >>= 3; + if (fbinfo->fix.smem_len < smem_len) + fbinfo->fix.smem_len = smem_len; + } + + /* Initialize Video Memory */ + ret = nuc900fb_map_video_memory(fbinfo); + if (ret) { + printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret); + goto release_clock; + } + + dev_dbg(&pdev->dev, "got video memory\n"); + + fbinfo->var.xres = display->xres; + fbinfo->var.yres = display->yres; + fbinfo->var.bits_per_pixel = display->bpp; + + nuc900fb_init_registers(fbinfo); + + nuc900fb_check_var(&fbinfo->var, fbinfo); + + ret = nuc900fb_cpufreq_register(fbi); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register cpufreq\n"); + goto free_video_memory; + } + + ret = register_framebuffer(fbinfo); + if (ret) { + printk(KERN_ERR "failed to register framebuffer device: %d\n", + ret); + goto free_cpufreq; + } + + printk(KERN_INFO "fb%d: %s frame buffer device\n", + fbinfo->node, fbinfo->fix.id); + + return 0; + +free_cpufreq: + nuc900fb_cpufreq_deregister(fbi); +free_video_memory: + nuc900fb_unmap_video_memory(fbinfo); +release_clock: + clk_disable(fbi->clk); + clk_put(fbi->clk); +release_irq: + free_irq(irq, fbi); +release_regs: + iounmap(fbi->io); +release_mem_region: + release_mem_region((unsigned long)fbi->mem, size); +free_fb: + framebuffer_release(fbinfo); + return ret; +} + +/* + * shutdown the lcd controller + */ +static void nuc900fb_stop_lcd(struct fb_info *info) +{ + struct nuc900fb_info *fbi = info->par; + void __iomem *regs = fbi->io; + + writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN), + regs + REG_LCM_DCCS); +} + +/* + * Cleanup + */ +static int nuc900fb_remove(struct platform_device *pdev) +{ + struct fb_info *fbinfo = platform_get_drvdata(pdev); + struct nuc900fb_info *fbi = fbinfo->par; + int irq; + + nuc900fb_stop_lcd(fbinfo); + msleep(1); + + nuc900fb_unmap_video_memory(fbinfo); + + iounmap(fbi->io); + + irq = platform_get_irq(pdev, 0); + free_irq(irq, fbi); + + release_resource(fbi->mem); + kfree(fbi->mem); + + platform_set_drvdata(pdev, NULL); + framebuffer_release(fbinfo); + + return 0; +} + +#ifdef CONFIG_PM + +/* + * suspend and resume support for the lcd controller + */ + +static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state) +{ + struct fb_info *fbinfo = platform_get_drvdata(dev); + struct nuc900fb_info *info = fbinfo->par; + + nuc900fb_stop_lcd(); + msleep(1); + clk_disable(info->clk); + return 0; +} + +static int nuc900fb_resume(struct platform_device *dev) +{ + struct fb_info *fbinfo = platform_get_drvdata(dev); + struct nuc900fb_info *fbi = fbinfo->par; + + printk(KERN_INFO "nuc900fb resume\n"); + + clk_enable(fbi->clk); + msleep(1); + + nuc900fb_init_registers(fbinfo); + nuc900fb_activate_var(bfinfo); + + return 0; +} + +#else +#define nuc900fb_suspend NULL +#define nuc900fb_resume NULL +#endif + +static struct platform_driver nuc900fb_driver = { + .probe = nuc900fb_probe, + .remove = nuc900fb_remove, + .suspend = nuc900fb_suspend, + .resume = nuc900fb_resume, + .driver = { + .name = "nuc900-lcd", + .owner = THIS_MODULE, + }, +}; + +int __devinit nuc900fb_init(void) +{ + return platform_driver_register(&nuc900fb_driver); +} + +static void __exit nuc900fb_cleanup(void) +{ + platform_driver_unregister(&nuc900fb_driver); +} + +module_init(nuc900fb_init); +module_exit(nuc900fb_cleanup); + +MODULE_DESCRIPTION("Framebuffer driver for the NUC900"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h new file mode 100644 index 0000000..6c23aa3 --- /dev/null +++ b/drivers/video/nuc900fb.h @@ -0,0 +1,55 @@ +/* + * + * Copyright (c) 2009 Nuvoton technology corporation + * All rights reserved. + * + * 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. + * + * Auther: + * Wang Qiang(rurality.linux@gmail.com) 2009/12/16 + */ + +#ifndef __NUC900FB_H +#define __NUC900FB_H + +#include <mach/map.h> +#include <mach/fb.h> + +enum nuc900_lcddrv_type { + LCDDRV_NUC910, + LCDDRV_NUC930, + LCDDRV_NUC932, + LCDDRV_NUC950, + LCDDRV_NUC960, +}; + + +#define PALETTE_BUFFER_SIZE 256 +#define PALETTE_BUFF_CLEAR (0x80000000) /* entry is clear/invalid */ + +struct nuc900fb_info { + struct device *dev; + struct clk *clk; + + struct resource *mem; + void __iomem *io; + void __iomem *irq_base; + int drv_type; + struct nuc900fb_hw regs; + unsigned long clk_rate; + +#ifdef CONFIG_CPU_FREQ + struct notifier_block freq_transition; +#endif + + /* keep these registers in case we need to re-write palette */ + u32 palette_buffer[PALETTE_BUFFER_SIZE]; + u32 pseudo_pal[16]; +}; + +int nuc900fb_init(void); + +#endif /* __NUC900FB_H */ diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index a334839..9557f96 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c @@ -389,7 +389,7 @@ static int omap_lcdc_enable_plane(int plane, int enable) /* * Configure the LCD DMA for a palette load operation and do the palette * downloading synchronously. We don't use the frame+palette load mode of - * the controller, since the palette can always be downloaded seperately. + * the controller, since the palette can always be downloaded separately. */ static void load_palette(void) { diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 913142d..9acef00 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -341,7 +341,7 @@ static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, return manager_attr->store(manager, buf, size); } -static struct sysfs_ops manager_sysfs_ops = { +static const struct sysfs_ops manager_sysfs_ops = { .show = manager_attr_show, .store = manager_attr_store, }; diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 0c5bea2..aed3f31 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -320,7 +320,7 @@ static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, return overlay_attr->store(overlay, buf, size); } -static struct sysfs_ops overlay_sysfs_ops = { +static const struct sysfs_ops overlay_sysfs_ops = { .show = overlay_attr_show, .store = overlay_attr_store, }; diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 36436ee..27f93aa 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -896,7 +896,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green, * Pseudocolor: * uses offset = 0 && length = DAC register width. * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC + * var->{color}.length contains width of DAC * cmap is not used * DAC[X] is programmed to (red, green, blue) * Truecolor: diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 4beac1d..de40a62 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -85,7 +85,7 @@ static struct fb_ops q40fb_ops = { .fb_imageblit = cfb_imageblit, }; -static int __init q40fb_probe(struct platform_device *dev) +static int __devinit q40fb_probe(struct platform_device *dev) { struct fb_info *info; diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index 0deb0a8..7b63429 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -517,12 +517,12 @@ s1d13xxxfb_bitblt_copyarea(struct fb_info *info, const struct fb_copyarea *area) src = (sy * stride) + (bpp * sx); } - /* set source adress */ + /* set source address */ s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff)); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff); - /* set destination adress */ + /* set destination address */ s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff)); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff); s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index aac6612..2b094de 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -1004,12 +1004,12 @@ dealloc_fb: return ret; } -static int __init s3c2410fb_probe(struct platform_device *pdev) +static int __devinit s3c2410fb_probe(struct platform_device *pdev) { return s3c24xxfb_probe(pdev, DRV_S3C2410); } -static int __init s3c2412fb_probe(struct platform_device *pdev) +static int __devinit s3c2412fb_probe(struct platform_device *pdev) { return s3c24xxfb_probe(pdev, DRV_S3C2412); } diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index cdaa873..e8b76d6 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -1435,7 +1435,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) return fbi; } -static int __init sa1100fb_probe(struct platform_device *pdev) +static int __devinit sa1100fb_probe(struct platform_device *pdev) { struct sa1100fb_info *fbi; int ret, irq; diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index f860122..7a3a5e2 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -745,7 +745,7 @@ int __init sgivwfb_setup(char *options) /* * Initialisation */ -static int __init sgivwfb_probe(struct platform_device *dev) +static int __devinit sgivwfb_probe(struct platform_device *dev) { struct sgivw_par *par; struct fb_info *info; diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 8d7653e..bbd1dbf 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -943,7 +943,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { static int sh_mobile_lcdc_remove(struct platform_device *pdev); -static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) +static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) { struct fb_info *info; struct sh_mobile_lcdc_priv *priv; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 9d2b6bc..a531a0f 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1891,9 +1891,6 @@ static struct fb_ops sisfb_ops = { .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, -#ifdef CONFIG_FB_SOFT_CURSOR - .fb_cursor = soft_cursor, -#endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_ioctl, diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 35370d0..b7dc180 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -411,7 +411,7 @@ static int sm501fb_set_par_common(struct fb_info *info, struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; unsigned long pixclock; /* pixelclock in Hz */ - unsigned long sm501pixclock; /* pixelclock the 501 can achive in Hz */ + unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */ unsigned int mem_type; unsigned int clock_type; unsigned int head_addr; diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 609d0a5..79840f1 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1102,7 +1102,7 @@ static void sst_set_vidmod_ics(struct fb_info *info, const int bpp) * detect dac type * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset, * dram refresh disabled, FbiInit remaped. - * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ... + * TODO: mmh.. maybe i should put the "prerequisite" in the func ... */ diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c new file mode 100644 index 0000000..a8248c0 --- /dev/null +++ b/drivers/video/sunxvr1000.c @@ -0,0 +1,228 @@ +/* sunxvr1000.c: Sun XVR-1000 driver for sparc64 systems + * + * Copyright (C) 2010 David S. Miller (davem@davemloft.net) + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/of_device.h> + +struct gfb_info { + struct fb_info *info; + + char __iomem *fb_base; + unsigned long fb_base_phys; + + struct device_node *of_node; + + unsigned int width; + unsigned int height; + unsigned int depth; + unsigned int fb_size; + + u32 pseudo_palette[16]; +}; + +static int __devinit gfb_get_props(struct gfb_info *gp) +{ + gp->width = of_getintprop_default(gp->of_node, "width", 0); + gp->height = of_getintprop_default(gp->of_node, "height", 0); + gp->depth = of_getintprop_default(gp->of_node, "depth", 32); + + if (!gp->width || !gp->height) { + printk(KERN_ERR "gfb: Critical properties missing for %s\n", + gp->of_node->full_name); + return -EINVAL; + } + + return 0; +} + +static int gfb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + u32 value; + + if (regno < 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + + value = (blue << 16) | (green << 8) | red; + ((u32 *)info->pseudo_palette)[regno] = value; + } + + return 0; +} + +static struct fb_ops gfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = gfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __devinit gfb_set_fbinfo(struct gfb_info *gp) +{ + struct fb_info *info = gp->info; + struct fb_var_screeninfo *var = &info->var; + + info->flags = FBINFO_DEFAULT; + info->fbops = &gfb_ops; + info->screen_base = gp->fb_base; + info->screen_size = gp->fb_size; + + info->pseudo_palette = gp->pseudo_palette; + + /* Fill fix common fields */ + strlcpy(info->fix.id, "gfb", sizeof(info->fix.id)); + info->fix.smem_start = gp->fb_base_phys; + info->fix.smem_len = gp->fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + if (gp->depth == 32 || gp->depth == 24) + info->fix.visual = FB_VISUAL_TRUECOLOR; + else + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + + var->xres = gp->width; + var->yres = gp->height; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + var->bits_per_pixel = gp->depth; + + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + + if (fb_alloc_cmap(&info->cmap, 256, 0)) { + printk(KERN_ERR "gfb: Cannot allocate color map.\n"); + return -ENOMEM; + } + + return 0; +} + +static int __devinit gfb_probe(struct of_device *op, + const struct of_device_id *match) +{ + struct device_node *dp = op->node; + struct fb_info *info; + struct gfb_info *gp; + int err; + + info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev); + if (!info) { + printk(KERN_ERR "gfb: Cannot allocate fb_info\n"); + err = -ENOMEM; + goto err_out; + } + + gp = info->par; + gp->info = info; + gp->of_node = dp; + + gp->fb_base_phys = op->resource[6].start; + + err = gfb_get_props(gp); + if (err) + goto err_release_fb; + + /* Framebuffer length is the same regardless of resolution. */ + info->fix.line_length = 16384; + gp->fb_size = info->fix.line_length * gp->height; + + gp->fb_base = of_ioremap(&op->resource[6], 0, + gp->fb_size, "gfb fb"); + if (!gp->fb_base) + goto err_release_fb; + + err = gfb_set_fbinfo(gp); + if (err) + goto err_unmap_fb; + + printk("gfb: Found device at %s\n", dp->full_name); + + err = register_framebuffer(info); + if (err < 0) { + printk(KERN_ERR "gfb: Could not register framebuffer %s\n", + dp->full_name); + goto err_unmap_fb; + } + + dev_set_drvdata(&op->dev, info); + + return 0; + +err_unmap_fb: + of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size); + +err_release_fb: + framebuffer_release(info); + +err_out: + return err; +} + +static int __devexit gfb_remove(struct of_device *op) +{ + struct fb_info *info = dev_get_drvdata(&op->dev); + struct gfb_info *gp = info->par; + + unregister_framebuffer(info); + + iounmap(gp->fb_base); + + of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size); + + framebuffer_release(info); + + dev_set_drvdata(&op->dev, NULL); + + return 0; +} + +static const struct of_device_id gfb_match[] = { + { + .name = "SUNW,gfb", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ffb_match); + +static struct of_platform_driver gfb_driver = { + .name = "gfb", + .match_table = gfb_match, + .probe = gfb_probe, + .remove = __devexit_p(gfb_remove), +}; + +static int __init gfb_init(void) +{ + if (fb_get_options("gfb", NULL)) + return -ENODEV; + + return of_register_driver(&gfb_driver, &of_bus_type); +} + +static void __exit gfb_exit(void) +{ + of_unregister_driver(&gfb_driver); +} + +module_init(gfb_init); +module_exit(gfb_exit); + +MODULE_DESCRIPTION("framebuffer driver for Sun XVR-1000 graphics"); +MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index bd37ee1..ef4128c 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -226,7 +226,7 @@ static int __init vesafb_setup(char *options) return 0; } -static int __init vesafb_probe(struct platform_device *dev) +static int __devinit vesafb_probe(struct platform_device *dev) { struct fb_info *info; int i, err; diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 050d432..b8ab995 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -479,7 +479,7 @@ static int __init vfb_setup(char *options) * Initialisation */ -static int __init vfb_probe(struct platform_device *dev) +static int __devinit vfb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 5b29389..76d8dae 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1293,7 +1293,7 @@ static int vga16fb_setup(char *options) } #endif -static int __init vga16fb_probe(struct platform_device *dev) +static int __devinit vga16fb_probe(struct platform_device *dev) { struct fb_info *info; struct vga16fb_par *par; diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index e533b4b..eeed238 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_FB_VIA) += viafb.o -viafb-y :=viafbdev.o hw.o iface.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o +viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 474f428..8c06bd3 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -107,7 +107,6 @@ struct tmds_chip_information { int tmds_chip_name; int tmds_chip_slave_addr; - int dvi_panel_id; int data_mode; int output_interface; int i2c_port; @@ -142,14 +141,9 @@ struct tmds_setting_information { int iga_path; int h_active; int v_active; - int bpp; - int refresh_rate; - int get_dvi_size_method; int max_pixel_clock; - int dvi_panel_size; - int dvi_panel_hres; - int dvi_panel_vres; - int native_size; + int max_hres; + int max_vres; }; struct lvds_setting_information { @@ -160,7 +154,6 @@ struct lvds_setting_information { int refresh_rate; int get_lcd_size_method; int lcd_panel_id; - int lcd_panel_size; int lcd_panel_hres; int lcd_panel_vres; int display_method; diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index 67b3693..abe59b8 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -23,11 +23,10 @@ static void tmds_register_write(int index, u8 data); static int tmds_register_read(int index); static int tmds_register_read_bytes(int index, u8 *buff, int buff_len); -static int check_reduce_blanking_mode(int mode_index, - int refresh_rate); -static int dvi_get_panel_size_from_DDCv1(void); -static int dvi_get_panel_size_from_DDCv2(void); -static unsigned char dvi_get_panel_info(void); +static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting); +static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting); static int viafb_dvi_query_EDID(void); static int check_tmds_chip(int device_id_subaddr, int device_id) @@ -38,23 +37,24 @@ static int check_tmds_chip(int device_id_subaddr, int device_id) return FAIL; } -void viafb_init_dvi_size(void) +void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, + struct tmds_setting_information *tmds_setting) { DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); - DEBUG_MSG(KERN_INFO - "viaparinfo->tmds_setting_info->get_dvi_size_method %d\n", - viaparinfo->tmds_setting_info->get_dvi_size_method); - switch (viaparinfo->tmds_setting_info->get_dvi_size_method) { - case GET_DVI_SIZE_BY_SYSTEM_BIOS: + viafb_dvi_sense(); + switch (viafb_dvi_query_EDID()) { + case 1: + dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting); break; - case GET_DVI_SZIE_BY_HW_STRAPPING: + case 2: + dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting); break; - case GET_DVI_SIZE_BY_VGA_BIOS: default: - dvi_get_panel_info(); + printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n"); break; } + return; } @@ -189,42 +189,14 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) return 0; } -static int check_reduce_blanking_mode(int mode_index, - int refresh_rate) -{ - if (refresh_rate != 60) - return false; - - switch (mode_index) { - /* Following modes have reduce blanking mode. */ - case VIA_RES_1360X768: - case VIA_RES_1400X1050: - case VIA_RES_1440X900: - case VIA_RES_1600X900: - case VIA_RES_1680X1050: - case VIA_RES_1920X1080: - case VIA_RES_1920X1200: - break; - - default: - DEBUG_MSG(KERN_INFO - "This dvi mode %d have no reduce blanking mode!\n", - mode_index); - return false; - } - - return true; -} - /* DVI Set Mode */ -void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) +void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, + int set_iga) { - struct VideoModeTable *videoMode = NULL; + struct VideoModeTable *rb_mode; struct crt_mode_table *pDviTiming; unsigned long desirePixelClock, maxPixelClock; - int status = 0; - videoMode = viafb_get_modetbl_pointer(video_index); - pDviTiming = videoMode->crtc; + pDviTiming = mode->crtc; desirePixelClock = pDviTiming->clk / 1000000; maxPixelClock = (unsigned long)viaparinfo-> tmds_setting_info->max_pixel_clock; @@ -232,20 +204,14 @@ void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga) DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { - /*Check if reduce-blanking mode is exist */ - status = - check_reduce_blanking_mode(video_index, - pDviTiming->refresh_rate); - if (status) { - video_index += 100; /*Use reduce-blanking mode */ - videoMode = viafb_get_modetbl_pointer(video_index); - pDviTiming = videoMode->crtc; - DEBUG_MSG(KERN_INFO - "DVI use reduce blanking mode %d!!\n", - video_index); + rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, + mode->crtc[0].crtc.ver_addr); + if (rb_mode) { + mode = rb_mode; + pDviTiming = rb_mode->crtc; } } - viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga); + viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); viafb_set_output_path(DEVICE_DVI, set_iga, viaparinfo->chip_info->tmds_chip_info.output_interface); } @@ -350,25 +316,18 @@ static int viafb_dvi_query_EDID(void) return false; } -/* - * - * int dvi_get_panel_size_from_DDCv1(void) - * - * - Get Panel Size Using EDID1 Table - * - * Return Type: int - * - */ -static int dvi_get_panel_size_from_DDCv1(void) +/* Get Panel Size Using EDID1 Table */ +static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting) { - int i, max_h = 0, max_v = 0, tmp, restore; + int i, max_h = 0, tmp, restore; unsigned char rData; unsigned char EDID_DATA[18]; DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); - restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; + restore = tmds_chip->tmds_chip_slave_addr; + tmds_chip->tmds_chip_slave_addr = 0xA0; rData = tmds_register_read(0x23); if (rData & 0x3C) @@ -414,8 +373,8 @@ static int dvi_get_panel_size_from_DDCv1(void) /* The first two byte must be zero. */ if (EDID_DATA[3] == 0xFD) { /* To get max pixel clock. */ - viaparinfo->tmds_setting_info-> - max_pixel_clock = EDID_DATA[9] * 10; + tmds_setting->max_pixel_clock = + EDID_DATA[9] * 10; } } break; @@ -425,154 +384,88 @@ static int dvi_get_panel_size_from_DDCv1(void) } } + tmds_setting->max_hres = max_h; switch (max_h) { case 640: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_640X480; + tmds_setting->max_vres = 480; break; case 800: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_800X600; + tmds_setting->max_vres = 600; break; case 1024: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; + tmds_setting->max_vres = 768; break; case 1280: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1280X1024; + tmds_setting->max_vres = 1024; break; case 1400: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1400X1050; + tmds_setting->max_vres = 1050; break; case 1440: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1440X1050; + tmds_setting->max_vres = 1050; break; case 1600: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1600X1200; + tmds_setting->max_vres = 1200; break; case 1920: - if (max_v == 1200) { - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1920X1200; - } else { - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1920X1080; - } - + tmds_setting->max_vres = 1080; break; default: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; - DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d !\ - set default panel size.\n", max_h); + DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! " + "set default panel size.\n", max_h); break; } DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", - viaparinfo->tmds_setting_info->max_pixel_clock); - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; - return viaparinfo->tmds_setting_info->dvi_panel_size; + tmds_setting->max_pixel_clock); + tmds_chip->tmds_chip_slave_addr = restore; } -/* - * - * int dvi_get_panel_size_from_DDCv2(void) - * - * - Get Panel Size Using EDID2 Table - * - * Return Type: int - * - */ -static int dvi_get_panel_size_from_DDCv2(void) +/* Get Panel Size Using EDID2 Table */ +static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information + *tmds_chip, struct tmds_setting_information *tmds_setting) { - int HSize = 0, restore; + int restore; unsigned char R_Buffer[2]; DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n"); - restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2; + restore = tmds_chip->tmds_chip_slave_addr; + tmds_chip->tmds_chip_slave_addr = 0xA2; /* Horizontal: 0x76, 0x77 */ tmds_register_read_bytes(0x76, R_Buffer, 2); - HSize = R_Buffer[0]; - HSize += R_Buffer[1] << 8; + tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8); - switch (HSize) { + switch (tmds_setting->max_hres) { case 640: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_640X480; + tmds_setting->max_vres = 480; break; case 800: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_800X600; + tmds_setting->max_vres = 600; break; case 1024: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; + tmds_setting->max_vres = 768; break; case 1280: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1280X1024; + tmds_setting->max_vres = 1024; break; case 1400: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1400X1050; + tmds_setting->max_vres = 1050; break; case 1440: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1440X1050; + tmds_setting->max_vres = 1050; break; case 1600: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1600X1200; - break; - default: - viaparinfo->tmds_setting_info->dvi_panel_size = - VIA_RES_1024X768; - DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d!\ - set default panel size.\n", HSize); - break; - } - - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore; - return viaparinfo->tmds_setting_info->dvi_panel_size; -} - -/* - * - * unsigned char dvi_get_panel_info(void) - * - * - Get Panel Size - * - * Return Type: unsigned char - */ -static unsigned char dvi_get_panel_info(void) -{ - unsigned char dvipanelsize; - DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n"); - - viafb_dvi_sense(); - switch (viafb_dvi_query_EDID()) { - case 1: - dvi_get_panel_size_from_DDCv1(); - break; - case 2: - dvi_get_panel_size_from_DDCv2(); + tmds_setting->max_vres = 1200; break; default: + DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! " + "set default panel size.\n", tmds_setting->max_hres); break; } - DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n", - viaparinfo->tmds_setting_info->dvi_panel_size); - dvipanelsize = (unsigned char)(viaparinfo-> - tmds_setting_info->dvi_panel_size); - return dvipanelsize; + tmds_chip->tmds_chip_slave_addr = restore; } /* If Disable DVI, turn off pad */ diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index e1ec37f..0dffcfd 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h @@ -53,12 +53,13 @@ #define DEV_CONNECT_DVI 0x01 #define DEV_CONNECT_HDMI 0x02 -struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index); int viafb_dvi_sense(void); void viafb_dvi_disable(void); void viafb_dvi_enable(void); int viafb_tmds_trasmitter_identify(void); -void viafb_init_dvi_size(void); -void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga); +void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, + struct tmds_setting_information *tmds_setting); +void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, + int set_iga); #endif /* __DVI_H__ */ diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index b675cdb..1ee511b 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c @@ -23,15 +23,12 @@ int viafb_platform_epia_dvi = STATE_OFF; int viafb_device_lcd_dualedge = STATE_OFF; int viafb_bus_width = 12; int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI; -int viafb_memsize; int viafb_DeviceStatus = CRT_Device; int viafb_hotplug; int viafb_refresh = 60; int viafb_refresh1 = 60; int viafb_lcd_dsp_method = LCD_EXPANDSION; int viafb_lcd_mode = LCD_OPENLDI; -int viafb_bpp = 32; -int viafb_bpp1 = 32; int viafb_CRT_ON = 1; int viafb_DVI_ON; int viafb_LCD_ON ; @@ -42,8 +39,6 @@ int viafb_hotplug_Xres = 640; int viafb_hotplug_Yres = 480; int viafb_hotplug_bpp = 32; int viafb_hotplug_refresh = 60; -unsigned int viafb_second_offset; -int viafb_second_size; int viafb_primary_dev = None_Device; unsigned int viafb_second_xres = 640; unsigned int viafb_second_yres = 480; diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index d69d0ca..8d95d5f 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -35,7 +35,6 @@ #include "debug.h" -#include "iface.h" #include "viafbdev.h" #include "chip.h" #include "accel.h" @@ -68,8 +67,6 @@ extern int viafb_refresh; extern int viafb_refresh1; extern int viafb_lcd_dsp_method; extern int viafb_lcd_mode; -extern int viafb_bpp; -extern int viafb_bpp1; extern int viafb_CRT_ON; extern int viafb_hotplug_Xres; diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 3e083ff..f2583b1 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -524,7 +524,6 @@ static void dvi_patch_skew_dvp1(void); static void dvi_patch_skew_dvp_low(void); static void set_dvi_output_path(int set_iga, int output_interface); static void set_lcd_output_path(int set_iga, int output_interface); -static int search_mode_setting(int ModeInfoIndex); static void load_fix_bit_crtc_reg(void); static void init_gfx_chip_info(struct pci_dev *pdev, const struct pci_device_id *pdi); @@ -686,6 +685,84 @@ void viafb_set_secondary_pitch(u32 pitch) viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); } +void viafb_set_primary_color_depth(u8 depth) +{ + u8 value; + + DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth); + switch (depth) { + case 8: + value = 0x00; + break; + case 15: + value = 0x04; + break; + case 16: + value = 0x14; + break; + case 24: + value = 0x0C; + break; + case 30: + value = 0x08; + break; + default: + printk(KERN_WARNING "viafb_set_primary_color_depth: " + "Unsupported depth: %d\n", depth); + return; + } + + viafb_write_reg_mask(0x15, VIASR, value, 0x1C); +} + +void viafb_set_secondary_color_depth(u8 depth) +{ + u8 value; + + DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth); + switch (depth) { + case 8: + value = 0x00; + break; + case 16: + value = 0x40; + break; + case 24: + value = 0xC0; + break; + case 30: + value = 0x80; + break; + default: + printk(KERN_WARNING "viafb_set_secondary_color_depth: " + "Unsupported depth: %d\n", depth); + return; + } + + viafb_write_reg_mask(0x67, VIACR, value, 0xC0); +} + +static void set_color_register(u8 index, u8 red, u8 green, u8 blue) +{ + outb(0xFF, 0x3C6); /* bit mask of palette */ + outb(index, 0x3C8); + outb(red, 0x3C9); + outb(green, 0x3C9); + outb(blue, 0x3C9); +} + +void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue) +{ + viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01); + set_color_register(index, red, green, blue); +} + +void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue) +{ + viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01); + set_color_register(index, red, green, blue); +} + void viafb_set_output_path(int device, int set_iga, int output_interface) { switch (device) { @@ -710,11 +787,8 @@ static void set_crt_output_path(int set_iga) viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6); break; case IGA2: - case IGA1_IGA2: viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7); viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6); - if (set_iga == IGA1_IGA2) - viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); break; } } @@ -904,13 +978,6 @@ static void set_lcd_output_path(int set_iga, int output_interface) enable_second_display_channel(); break; - - case IGA1_IGA2: - viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3); - viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); - - disable_second_display_channel(); - break; } switch (output_interface) { @@ -987,49 +1054,6 @@ static void set_lcd_output_path(int set_iga, int output_interface) } } -/* Search Mode Index */ -static int search_mode_setting(int ModeInfoIndex) -{ - int i = 0; - - while ((i < NUM_TOTAL_MODETABLE) && - (ModeInfoIndex != CLE266Modes[i].ModeIndex)) - i++; - if (i >= NUM_TOTAL_MODETABLE) - i = 0; - return i; - -} - -struct VideoModeTable *viafb_get_modetbl_pointer(int Index) -{ - struct VideoModeTable *TmpTbl = NULL; - TmpTbl = &CLE266Modes[search_mode_setting(Index)]; - return TmpTbl; -} - -struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index) -{ - struct VideoModeTable *TmpTbl = NULL; - int i = 0; - while ((i < NUM_TOTAL_CEA_MODES) && - (Index != CEA_HDMI_Modes[i].ModeIndex)) - i++; - if ((i < NUM_TOTAL_CEA_MODES)) - TmpTbl = &CEA_HDMI_Modes[i]; - else { - /*Still use general timing if don't find CEA timing */ - i = 0; - while ((i < NUM_TOTAL_MODETABLE) && - (Index != CLE266Modes[i].ModeIndex)) - i++; - if (i >= NUM_TOTAL_MODETABLE) - i = 0; - TmpTbl = &CLE266Modes[i]; - } - return TmpTbl; -} - static void load_fix_bit_crtc_reg(void) { /* always set to 1 */ @@ -1121,15 +1145,13 @@ void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) struct io_register *reg = NULL; switch (set_iga) { - case IGA1_IGA2: case IGA1: reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); viafb_load_reg_num = fetch_count_reg. iga1_fetch_count_reg.reg_num; reg = fetch_count_reg.iga1_fetch_count_reg.reg; viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); - if (set_iga == IGA1) - break; + break; case IGA2: reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); viafb_load_reg_num = fetch_count_reg. @@ -1499,7 +1521,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) /* H.W. Reset : ON */ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA1) { /* Change D,N FOR VCLK */ switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_CLE266: @@ -1528,7 +1550,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) } } - if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA2) { /* Change D,N FOR LCK */ switch (viaparinfo->chip_info->gfx_chip_name) { case UNICHROME_CLE266: @@ -1557,12 +1579,12 @@ void viafb_set_vclock(u32 CLK, int set_iga) viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); /* Reset PLL */ - if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA1) { viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); } - if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) { + if (set_iga == IGA2) { viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0); viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0); } @@ -1805,47 +1827,15 @@ void viafb_load_crtc_timing(struct display_timing device_timing, viafb_lock_crt(); } -void viafb_set_color_depth(int bpp_byte, int set_iga) -{ - if (set_iga == IGA1) { - switch (bpp_byte) { - case MODE_8BPP: - viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E); - break; - case MODE_16BPP: - viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE); - break; - case MODE_32BPP: - viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE); - break; - } - } else { - switch (bpp_byte) { - case MODE_8BPP: - viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7); - break; - case MODE_16BPP: - viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7); - break; - case MODE_32BPP: - viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7); - break; - } - } -} - void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, - int mode_index, int bpp_byte, int set_iga) + struct VideoModeTable *video_mode, int bpp_byte, int set_iga) { - struct VideoModeTable *video_mode; struct display_timing crt_reg; int i; int index = 0; int h_addr, v_addr; u32 pll_D_N; - video_mode = &CLE266Modes[search_mode_setting(mode_index)]; - for (i = 0; i < video_mode->mode_array; i++) { index = i; @@ -1858,8 +1848,10 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, /* Mode 640x480 has border, but LCD/DFP didn't have border. */ /* So we would delete border. */ - if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480) - && (viaparinfo->crt_setting_info->refresh_rate == 60)) { + if ((viafb_LCD_ON | viafb_DVI_ON) + && video_mode->crtc[0].crtc.hor_addr == 640 + && video_mode->crtc[0].crtc.ver_addr == 480 + && viaparinfo->crt_setting_info->refresh_rate == 60) { /* The border is 8 pixels. */ crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; @@ -1912,9 +1904,6 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) viafb_load_FIFO_reg(set_iga, h_addr, v_addr); - /* load SR Register About Memory and Color part */ - viafb_set_color_depth(bpp_byte, set_iga); - pll_D_N = viafb_get_clk_value(crt_table[index].clk); DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N); viafb_set_vclock(pll_D_N, set_iga); @@ -1956,9 +1945,6 @@ void viafb_update_device_setting(int hres, int vres, viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; - viaparinfo->tmds_setting_info->bpp = bpp; - viaparinfo->tmds_setting_info->refresh_rate = - vmode_refresh; viaparinfo->lvds_setting_info->h_active = hres; viaparinfo->lvds_setting_info->v_active = vres; @@ -1975,9 +1961,6 @@ void viafb_update_device_setting(int hres, int vres, if (viaparinfo->tmds_setting_info->iga_path == IGA2) { viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; - viaparinfo->tmds_setting_info->bpp = bpp; - viaparinfo->tmds_setting_info->refresh_rate = - vmode_refresh; } if (viaparinfo->lvds_setting_info->iga_path == IGA2) { @@ -2076,9 +2059,8 @@ static void init_tmds_chip_info(void) DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); - viaparinfo->tmds_setting_info->get_dvi_size_method = - GET_DVI_SIZE_BY_VGA_BIOS; - viafb_init_dvi_size(); + viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info, + &viaparinfo->shared->tmds_setting_info); } static void init_lvds_chip_info(void) @@ -2195,28 +2177,19 @@ static void set_display_channel(void) } } -int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, - int vmode_index1, int hor_res1, int ver_res1, int video_bpp1) +int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, + struct VideoModeTable *vmode_tbl1, int video_bpp1) { int i, j; int port; u8 value, index, mask; - struct VideoModeTable *vmode_tbl; struct crt_mode_table *crt_timing; - struct VideoModeTable *vmode_tbl1 = NULL; struct crt_mode_table *crt_timing1 = NULL; - DEBUG_MSG(KERN_INFO "Set Mode!!\n"); - DEBUG_MSG(KERN_INFO - "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n", - vmode_index, hor_res, ver_res, video_bpp); - device_screen_off(); - vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)]; crt_timing = vmode_tbl->crtc; if (viafb_SAMM_ON == 1) { - vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)]; crt_timing1 = vmode_tbl1->crtc; } @@ -2267,12 +2240,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, outb(VPIT.SR[i - 1], VIASR + 1); } - viafb_set_primary_address(0); - viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); + viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); viafb_set_iga_path(); /* Write CRTC */ - viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1); + viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1); /* Write Graphic Controller */ for (i = 0; i < StdGR; i++) { @@ -2292,65 +2264,25 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, /* Update Patch Register */ - if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) - || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) { - for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { - if (res_patch_table[i].mode_index == vmode_index) { - for (j = 0; - j < res_patch_table[i].table_length; j++) { - index = - res_patch_table[i]. - io_reg_table[j].index; - port = - res_patch_table[i]. - io_reg_table[j].port; - value = - res_patch_table[i]. - io_reg_table[j].value; - mask = - res_patch_table[i]. - io_reg_table[j].mask; - viafb_write_reg_mask(index, port, value, - mask); - } - } - } - } - - if (viafb_SAMM_ON == 1) { - if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) - || (viaparinfo->chip_info->gfx_chip_name == - UNICHROME_K400)) { - for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) { - if (res_patch_table[i].mode_index == - vmode_index1) { - for (j = 0; - j < - res_patch_table[i]. - table_length; j++) { - index = - res_patch_table[i]. - io_reg_table[j].index; - port = - res_patch_table[i]. - io_reg_table[j].port; - value = - res_patch_table[i]. - io_reg_table[j].value; - mask = - res_patch_table[i]. - io_reg_table[j].mask; - viafb_write_reg_mask(index, - port, value, mask); - } - } - } + if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 + || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) + && vmode_tbl->crtc[0].crtc.hor_addr == 1024 + && vmode_tbl->crtc[0].crtc.ver_addr == 768) { + for (j = 0; j < res_patch_table[0].table_length; j++) { + index = res_patch_table[0].io_reg_table[j].index; + port = res_patch_table[0].io_reg_table[j].port; + value = res_patch_table[0].io_reg_table[j].value; + mask = res_patch_table[0].io_reg_table[j].mask; + viafb_write_reg_mask(index, port, value, mask); } } viafb_set_primary_pitch(viafbinfo->fix.line_length); viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length : viafbinfo->fix.line_length); + viafb_set_primary_color_depth(viaparinfo->depth); + viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth + : viaparinfo->depth); /* Update Refresh Rate Setting */ /* Clear On Screen */ @@ -2359,11 +2291,11 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, if (viafb_CRT_ON) { if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path == IGA2)) { - viafb_fill_crtc_timing(crt_timing1, vmode_index1, + viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, video_bpp1 / 8, viaparinfo->crt_setting_info->iga_path); } else { - viafb_fill_crtc_timing(crt_timing, vmode_index, + viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, viaparinfo->crt_setting_info->iga_path); } @@ -2373,7 +2305,7 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode to 8 alignment (1368),there is several pixels (2 pixels) on right side of screen. */ - if (hor_res % 8) { + if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { viafb_unlock_crt(); viafb_write_reg(CR02, VIACR, viafb_read_reg(VIACR, CR02) - 1); @@ -2384,14 +2316,14 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, if (viafb_DVI_ON) { if (viafb_SAMM_ON && (viaparinfo->tmds_setting_info->iga_path == IGA2)) { - viafb_dvi_set_mode(viafb_get_mode_index + viafb_dvi_set_mode(viafb_get_mode (viaparinfo->tmds_setting_info->h_active, viaparinfo->tmds_setting_info-> v_active), video_bpp1, viaparinfo-> tmds_setting_info->iga_path); } else { - viafb_dvi_set_mode(viafb_get_mode_index + viafb_dvi_set_mode(viafb_get_mode (viaparinfo->tmds_setting_info->h_active, viaparinfo-> tmds_setting_info->v_active), @@ -2445,8 +2377,8 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp, /* If set mode normally, save resolution information for hot-plug . */ if (!viafb_hotplug) { - viafb_hotplug_Xres = hor_res; - viafb_hotplug_Yres = ver_res; + viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; + viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; viafb_hotplug_bpp = video_bpp; viafb_hotplug_refresh = viafb_refresh; @@ -2706,13 +2638,11 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ /*According var's xres, yres fill var's other timing information*/ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, - int mode_index) + struct VideoModeTable *vmode_tbl) { - struct VideoModeTable *vmode_tbl = NULL; struct crt_mode_table *crt_timing = NULL; struct display_timing crt_reg; int i = 0, index = 0; - vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)]; crt_timing = vmode_tbl->crtc; for (i = 0; i < vmode_tbl->mode_array; i++) { index = i; @@ -2721,36 +2651,6 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, } crt_reg = crt_timing[index].crtc; - switch (var->bits_per_pixel) { - case 8: - var->red.offset = 0; - var->green.offset = 0; - var->blue.offset = 0; - var->red.length = 6; - var->green.length = 6; - var->blue.length = 6; - break; - case 16: - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - break; - case 32: - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - break; - default: - /* never happed, put here to keep consistent */ - break; - } - var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); var->left_margin = crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index b874d95..12ef32d 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -22,6 +22,7 @@ #ifndef __HW_H__ #define __HW_H__ +#include "viamode.h" #include "global.h" /*************************************************** @@ -862,8 +863,6 @@ struct pci_device_id_info { }; extern unsigned int viafb_second_virtual_xres; -extern unsigned int viafb_second_offset; -extern int viafb_second_size; extern int viafb_SAMM_ON; extern int viafb_dual_fb; extern int viafb_LCD2_ON; @@ -874,8 +873,9 @@ extern int viafb_hotplug; void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); void viafb_set_output_path(int device, int set_iga, int output_interface); + void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, - int mode_index, int bpp_byte, int set_iga); + struct VideoModeTable *video_mode, int bpp_byte, int set_iga); void viafb_set_vclock(u32 CLK, int set_iga); void viafb_load_reg(int timing_value, int viafb_load_reg_num, @@ -891,16 +891,15 @@ void viafb_lock_crt(void); void viafb_unlock_crt(void); void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); void viafb_write_regx(struct io_reg RegTable[], int ItemNum); -struct VideoModeTable *viafb_get_modetbl_pointer(int Index); u32 viafb_get_clk_value(int clk); void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); -void viafb_set_color_depth(int bpp_byte, int set_iga); void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ *p_gfx_dpa_setting); -int viafb_setmode(int vmode_index, int hor_res, int ver_res, - int video_bpp, int vmode_index1, int hor_res1, - int ver_res1, int video_bpp1); +int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, + struct VideoModeTable *vmode_tbl1, int video_bpp1); +void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, + struct VideoModeTable *vmode_tbl); void viafb_init_chip_info(struct pci_dev *pdev, const struct pci_device_id *pdi); void viafb_init_dac(int set_iga); @@ -915,6 +914,8 @@ void viafb_set_primary_address(u32 addr); void viafb_set_secondary_address(u32 addr); void viafb_set_primary_pitch(u32 pitch); void viafb_set_secondary_pitch(u32 pitch); +void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); +void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); #endif /* __HW_H__ */ diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c deleted file mode 100644 index 1570636..0000000 --- a/drivers/video/via/iface.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - - * 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, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "global.h" - -/* Get frame buffer size from VGA BIOS */ - -unsigned int viafb_get_memsize(void) -{ - unsigned int m; - - /* If memory size provided by user */ - if (viafb_memsize) - m = viafb_memsize * Mb; - else { - m = (unsigned int)viafb_read_reg(VIASR, SR39); - m = m * (4 * Mb); - - if ((m < (16 * Mb)) || (m > (64 * Mb))) - m = 16 * Mb; - } - DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb); - return m; -} - -/* Get Video Buffer Starting Physical Address(back door)*/ - -unsigned long viafb_get_videobuf_addr(void) -{ - struct pci_dev *pdev = NULL; - unsigned char sys_mem; - unsigned char video_mem; - unsigned long sys_mem_size; - unsigned long video_mem_size; - /*system memory = 256 MB, video memory 64 MB */ - unsigned long vmem_starting_adr = 0x0C000000; - - pdev = - (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID, - VIA_K800_BRIDGE_DID, NULL); - if (pdev != NULL) { - pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG, - &sys_mem); - pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG, - &video_mem); - video_mem = (video_mem & 0x70) >> 4; - sys_mem_size = ((unsigned long)sys_mem) << 24; - if (video_mem != 0) - video_mem_size = (1 << (video_mem)) * 1024 * 1024; - else - video_mem_size = 0; - - vmem_starting_adr = sys_mem_size - video_mem_size; - pci_dev_put(pdev); - } - - DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n", - vmem_starting_adr); - return vmem_starting_adr; -} diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h deleted file mode 100644 index 790ec3e..0000000 --- a/drivers/video/via/iface.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - - * 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, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __IFACE_H__ -#define __IFACE_H__ - -#define Kb (1024) -#define Mb (Kb*Kb) - -#define VIA_K800_BRIDGE_VID 0x1106 -#define VIA_K800_BRIDGE_DID 0x3204 - -#define VIA_K800_SYSTEM_MEMORY_REG 0x47 -#define VIA_K800_VIDEO_MEMORY_REG 0xA1 - -extern int viafb_memsize; -unsigned int viafb_get_memsize(void); -unsigned long viafb_get_videobuf_addr(void); - -#endif /* __IFACE_H__ */ diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 09353e2..1b1ccdc 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -22,25 +22,7 @@ #include "global.h" #include "lcdtbl.h" -static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = { - /* IGA2 Shadow Horizontal Total */ - {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } }, - /* IGA2 Shadow Horizontal Blank End */ - {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } }, - /* IGA2 Shadow Vertical Total */ - {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } }, - /* IGA2 Shadow Vertical Addressable Video */ - {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } }, - /* IGA2 Shadow Vertical Blank Start */ - {IGA2_SHADOW_VER_BLANK_START_REG_NUM, - {{CR72, 0, 7}, {CR74, 4, 6} } }, - /* IGA2 Shadow Vertical Blank End */ - {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } }, - /* IGA2 Shadow Vertical Sync Start */ - {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } }, - /* IGA2 Shadow Vertical Sync End */ - {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } } -}; +#define viafb_compact_res(x, y) (((x)<<16)|(y)) static struct _lcd_scaling_factor lcd_scaling_factor = { /* LCD Horizontal Scaling Factor Register */ @@ -59,16 +41,10 @@ static struct _lcd_scaling_factor lcd_scaling_factor_CLE = { static int check_lvds_chip(int device_id_subaddr, int device_id); static bool lvds_identify_integratedlvds(void); -static int fp_id_to_vindex(int panel_id); +static void fp_id_to_vindex(int panel_id); static int lvds_register_read(int index); static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, int panel_vres); -static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, - int panel_id); -static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, - int panel_id); -static void load_lcd_patch_regs(int set_hres, int set_vres, - int panel_id, int set_iga); static void via_pitch_alignment_patch_lcd( struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information @@ -98,8 +74,6 @@ static void check_diport_of_integrated_lvds( static struct display_timing lcd_centering_timging(struct display_timing mode_crt_reg, struct display_timing panel_crt_reg); -static void load_crtc_shadow_timing(struct display_timing mode_timing, - struct display_timing panel_timing); static void viafb_load_scaling_factor_for_p4m900(int set_hres, int set_vres, int panel_hres, int panel_vres); @@ -125,33 +99,24 @@ void viafb_init_lcd_size(void) break; case GET_LCD_SIZE_BY_VGA_BIOS: DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n"); - viaparinfo->lvds_setting_info->lcd_panel_size = - fp_id_to_vindex(viafb_lcd_panel_id); + fp_id_to_vindex(viafb_lcd_panel_id); DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", viaparinfo->lvds_setting_info->lcd_panel_id); - DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", - viaparinfo->lvds_setting_info->lcd_panel_size); break; case GET_LCD_SIZE_BY_USER_SETTING: DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n"); - viaparinfo->lvds_setting_info->lcd_panel_size = - fp_id_to_vindex(viafb_lcd_panel_id); + fp_id_to_vindex(viafb_lcd_panel_id); DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n", viaparinfo->lvds_setting_info->lcd_panel_id); - DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n", - viaparinfo->lvds_setting_info->lcd_panel_size); break; default: DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n"); viaparinfo->lvds_setting_info->lcd_panel_id = LCD_PANEL_ID1_800X600; - viaparinfo->lvds_setting_info->lcd_panel_size = - fp_id_to_vindex(LCD_PANEL_ID1_800X600); + fp_id_to_vindex(LCD_PANEL_ID1_800X600); } viaparinfo->lvds_setting_info2->lcd_panel_id = viaparinfo->lvds_setting_info->lcd_panel_id; - viaparinfo->lvds_setting_info2->lcd_panel_size = - viaparinfo->lvds_setting_info->lcd_panel_size; viaparinfo->lvds_setting_info2->lcd_panel_hres = viaparinfo->lvds_setting_info->lcd_panel_hres; viaparinfo->lvds_setting_info2->lcd_panel_vres = @@ -171,13 +136,13 @@ static bool lvds_identify_integratedlvds(void) if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = INTEGRATED_LVDS; - DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\ - (Internal LVDS + External LVDS)\n"); + DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! " + "(Internal LVDS + External LVDS)\n"); } else { viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = INTEGRATED_LVDS; - DEBUG_MSG(KERN_INFO "Not found external LVDS,\ - so can't support two dual channel LVDS!\n"); + DEBUG_MSG(KERN_INFO "Not found external LVDS, " + "so can't support two dual channel LVDS!\n"); } } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) { /* Two single channel LCD (Internal LVDS + Internal LVDS): */ @@ -185,8 +150,8 @@ static bool lvds_identify_integratedlvds(void) INTEGRATED_LVDS; viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name = INTEGRATED_LVDS; - DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\ - (Internal LVDS + Internal LVDS)\n"); + DEBUG_MSG(KERN_INFO "Support two single channel LVDS! " + "(Internal LVDS + Internal LVDS)\n"); } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) { /* If we have found external LVDS, just use it, otherwise, we will use internal LVDS as default. */ @@ -248,7 +213,7 @@ int viafb_lvds_trasmitter_identify(void) return FAIL; } -static int fp_id_to_vindex(int panel_id) +static void fp_id_to_vindex(int panel_id) { DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); @@ -264,7 +229,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID0_640X480; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_640X480; break; case 0x1: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; @@ -273,7 +237,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID1_800X600; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_800X600; break; case 0x2: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -282,7 +245,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1024X768; break; case 0x3: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -291,7 +253,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X768; break; case 0x4: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -300,7 +261,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID4_1280X1024; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X1024; break; case 0x5: viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; @@ -309,7 +269,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID5_1400X1050; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1400X1050; break; case 0x6: viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; @@ -318,7 +277,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID6_1600X1200; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1600X1200; break; case 0x8: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; @@ -327,7 +285,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_IDA_800X480; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_800X480; break; case 0x9: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -336,7 +293,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1024X768; break; case 0xA: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -345,7 +301,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1024X768; break; case 0xB: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -354,7 +309,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID2_1024X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1024X768; break; case 0xC: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -363,7 +317,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1280X768; break; case 0xD: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -372,7 +325,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID4_1280X1024; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1280X1024; break; case 0xE: viaparinfo->lvds_setting_info->lcd_panel_hres = 1400; @@ -381,7 +333,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID5_1400X1050; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1400X1050; break; case 0xF: viaparinfo->lvds_setting_info->lcd_panel_hres = 1600; @@ -390,7 +341,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID6_1600X1200; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1600X1200; break; case 0x10: viaparinfo->lvds_setting_info->lcd_panel_hres = 1366; @@ -399,7 +349,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID7_1366X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1368X768; break; case 0x11: viaparinfo->lvds_setting_info->lcd_panel_hres = 1024; @@ -408,7 +357,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID8_1024X600; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1024X600; break; case 0x12: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -417,7 +365,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X768; break; case 0x13: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -426,7 +373,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID9_1280X800; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_1280X800; break; case 0x14: viaparinfo->lvds_setting_info->lcd_panel_hres = 1360; @@ -435,7 +381,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_IDB_1360X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1360X768; break; case 0x15: viaparinfo->lvds_setting_info->lcd_panel_hres = 1280; @@ -444,7 +389,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID3_1280X768; viaparinfo->lvds_setting_info->device_lcd_dualedge = 1; viaparinfo->lvds_setting_info->LCDDithering = 0; - return VIA_RES_1280X768; break; case 0x16: viaparinfo->lvds_setting_info->lcd_panel_hres = 480; @@ -453,7 +397,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_IDC_480X640; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_480X640; break; default: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; @@ -462,7 +405,6 @@ static int fp_id_to_vindex(int panel_id) LCD_PANEL_ID1_800X600; viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; - return VIA_RES_800X600; } } @@ -573,284 +515,6 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, } } -static void load_lcd_k400_patch_tbl(int set_hres, int set_vres, - int panel_id) -{ - int vmode_index; - int reg_num = 0; - struct io_reg *lcd_patch_reg = NULL; - - vmode_index = viafb_get_mode_index(set_hres, set_vres); - switch (panel_id) { - /* LCD 800x600 */ - case LCD_PANEL_ID1_800X600: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6; - lcd_patch_reg = K400_LCD_RES_6X4_8X6; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6; - lcd_patch_reg = K400_LCD_RES_7X4_8X6; - break; - } - break; - - /* LCD 1024x768 */ - case LCD_PANEL_ID2_1024X768: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7; - lcd_patch_reg = K400_LCD_RES_6X4_10X7; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7; - lcd_patch_reg = K400_LCD_RES_7X4_10X7; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7; - lcd_patch_reg = K400_LCD_RES_8X6_10X7; - break; - } - break; - - /* LCD 1280x1024 */ - case LCD_PANEL_ID4_1280X1024: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10; - lcd_patch_reg = K400_LCD_RES_6X4_12X10; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10; - lcd_patch_reg = K400_LCD_RES_7X4_12X10; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10; - lcd_patch_reg = K400_LCD_RES_8X6_12X10; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10; - lcd_patch_reg = K400_LCD_RES_10X7_12X10; - break; - - } - break; - - /* LCD 1400x1050 */ - case LCD_PANEL_ID5_1400X1050: - switch (vmode_index) { - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10; - lcd_patch_reg = K400_LCD_RES_6X4_14X10; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10; - lcd_patch_reg = K400_LCD_RES_8X6_14X10; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10; - lcd_patch_reg = K400_LCD_RES_10X7_14X10; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X800: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10; - lcd_patch_reg = K400_LCD_RES_12X10_14X10; - break; - } - break; - - /* LCD 1600x1200 */ - case LCD_PANEL_ID6_1600X1200: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12; - lcd_patch_reg = K400_LCD_RES_6X4_16X12; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12; - lcd_patch_reg = K400_LCD_RES_7X4_16X12; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12; - lcd_patch_reg = K400_LCD_RES_8X6_16X12; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12; - lcd_patch_reg = K400_LCD_RES_10X7_16X12; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X800: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12; - lcd_patch_reg = K400_LCD_RES_12X10_16X12; - break; - } - break; - - /* LCD 1366x768 */ - case LCD_PANEL_ID7_1366X768: - switch (vmode_index) { - case VIA_RES_640X480: - reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7; - lcd_patch_reg = K400_LCD_RES_6X4_1366X7; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7; - lcd_patch_reg = K400_LCD_RES_7X4_1366X7; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7; - lcd_patch_reg = K400_LCD_RES_8X6_1366X7; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7; - lcd_patch_reg = K400_LCD_RES_10X7_1366X7; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X800: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7; - lcd_patch_reg = K400_LCD_RES_12X10_1366X7; - break; - } - break; - - /* LCD 1360x768 */ - case LCD_PANEL_IDB_1360X768: - break; - } - if (reg_num != 0) { - /* H.W. Reset : ON */ - viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - - viafb_write_regx(lcd_patch_reg, reg_num); - - /* H.W. Reset : OFF */ - viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); - - /* Reset PLL */ - viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); - viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); - - /* Fire! */ - outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); - } -} - -static void load_lcd_p880_patch_tbl(int set_hres, int set_vres, - int panel_id) -{ - int vmode_index; - int reg_num = 0; - struct io_reg *lcd_patch_reg = NULL; - - vmode_index = viafb_get_mode_index(set_hres, set_vres); - - switch (panel_id) { - case LCD_PANEL_ID5_1400X1050: - switch (vmode_index) { - case VIA_RES_640X480: - reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10; - lcd_patch_reg = P880_LCD_RES_6X4_14X10; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10; - lcd_patch_reg = P880_LCD_RES_8X6_14X10; - break; - } - break; - case LCD_PANEL_ID6_1600X1200: - switch (vmode_index) { - case VIA_RES_640X400: - case VIA_RES_640X480: - reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12; - lcd_patch_reg = P880_LCD_RES_6X4_16X12; - break; - case VIA_RES_720X480: - case VIA_RES_720X576: - reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12; - lcd_patch_reg = P880_LCD_RES_7X4_16X12; - break; - case VIA_RES_800X600: - reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12; - lcd_patch_reg = P880_LCD_RES_8X6_16X12; - break; - case VIA_RES_1024X768: - reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12; - lcd_patch_reg = P880_LCD_RES_10X7_16X12; - break; - case VIA_RES_1280X768: - case VIA_RES_1280X960: - case VIA_RES_1280X1024: - reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12; - lcd_patch_reg = P880_LCD_RES_12X10_16X12; - break; - } - break; - - } - if (reg_num != 0) { - /* H.W. Reset : ON */ - viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); - - viafb_write_regx(lcd_patch_reg, reg_num); - - /* H.W. Reset : OFF */ - viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); - - /* Reset PLL */ - viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1); - viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1); - - /* Fire! */ - outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc); - } -} - -static void load_lcd_patch_regs(int set_hres, int set_vres, - int panel_id, int set_iga) -{ - int vmode_index; - - vmode_index = viafb_get_mode_index(set_hres, set_vres); - - viafb_unlock_crt(); - - /* Patch for simultaneous & Expansion */ - if ((set_iga == IGA1_IGA2) && - (viaparinfo->lvds_setting_info->display_method == - LCD_EXPANDSION)) { - switch (viaparinfo->chip_info->gfx_chip_name) { - case UNICHROME_CLE266: - case UNICHROME_K400: - load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id); - break; - case UNICHROME_K800: - break; - case UNICHROME_PM800: - case UNICHROME_CN700: - case UNICHROME_CX700: - load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id); - } - } - - viafb_lock_crt(); -} - static void via_pitch_alignment_patch_lcd( struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information @@ -949,29 +613,25 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info) { - int video_index = plvds_setting_info->lcd_panel_size; int set_iga = plvds_setting_info->iga_path; int mode_bpp = plvds_setting_info->bpp; - int set_hres, set_vres; - int panel_hres, panel_vres; + int set_hres = plvds_setting_info->h_active; + int set_vres = plvds_setting_info->v_active; + int panel_hres = plvds_setting_info->lcd_panel_hres; + int panel_vres = plvds_setting_info->lcd_panel_vres; u32 pll_D_N; - int offset; struct display_timing mode_crt_reg, panel_crt_reg; struct crt_mode_table *panel_crt_table = NULL; - struct VideoModeTable *vmode_tbl = NULL; + struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, + panel_vres); DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); /* Get mode table */ mode_crt_reg = mode_crt_table->crtc; /* Get panel table Pointer */ - vmode_tbl = viafb_get_modetbl_pointer(video_index); panel_crt_table = vmode_tbl->crtc; panel_crt_reg = panel_crt_table->crtc; DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); - set_hres = plvds_setting_info->h_active; - set_vres = plvds_setting_info->v_active; - panel_hres = plvds_setting_info->lcd_panel_hres; - panel_vres = plvds_setting_info->lcd_panel_vres; if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); plvds_setting_info->vclk = panel_crt_table->clk; @@ -1001,54 +661,12 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, } } - if (set_iga == IGA1_IGA2) { - load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg); - /* Fill shadow registers */ - - switch (plvds_setting_info->lcd_panel_id) { - case LCD_PANEL_ID0_640X480: - offset = 80; - break; - case LCD_PANEL_ID1_800X600: - case LCD_PANEL_IDA_800X480: - offset = 110; - break; - case LCD_PANEL_ID2_1024X768: - offset = 150; - break; - case LCD_PANEL_ID3_1280X768: - case LCD_PANEL_ID4_1280X1024: - case LCD_PANEL_ID5_1400X1050: - case LCD_PANEL_ID9_1280X800: - offset = 190; - break; - case LCD_PANEL_ID6_1600X1200: - offset = 250; - break; - case LCD_PANEL_ID7_1366X768: - case LCD_PANEL_IDB_1360X768: - offset = 212; - break; - default: - offset = 140; - break; - } - - /* Offset for simultaneous */ - viafb_set_secondary_pitch(offset << 3); - DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n"); - viafb_load_fetch_count_reg(set_hres, 4, IGA2); - /* Fetch count for simultaneous */ - } else { /* SAMM */ - /* Fetch count for IGA2 only */ - viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); - - if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) - && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) - viafb_load_FIFO_reg(set_iga, set_hres, set_vres); + /* Fetch count for IGA2 only */ + viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); - viafb_set_color_depth(mode_bpp / 8, set_iga); - } + if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) + && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) + viafb_load_FIFO_reg(set_iga, set_hres, set_vres); fill_lcd_format(); @@ -1065,11 +683,6 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)) viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); - load_lcd_patch_regs(set_hres, set_vres, - plvds_setting_info->lcd_panel_id, set_iga); - - DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n"); - /* Patch for non 32bit alignment mode */ via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); } @@ -1283,8 +896,7 @@ void viafb_lcd_enable(void) viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); } - if ((viaparinfo->lvds_setting_info->iga_path == IGA1) - || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) { + if (viaparinfo->lvds_setting_info->iga_path == IGA1) { /* CRT path set to IGA2 */ viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40); /* IGA2 path disabled */ @@ -1476,210 +1088,6 @@ static struct display_timing lcd_centering_timging(struct display_timing return crt_reg; } -static void load_crtc_shadow_timing(struct display_timing mode_timing, - struct display_timing panel_timing) -{ - struct io_register *reg = NULL; - int i; - int viafb_load_reg_Num = 0; - int reg_value = 0; - - if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) { - /* Expansion */ - for (i = 12; i < 20; i++) { - switch (i) { - case H_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_HOR_TOTAL_SHADOW_FORMULA - (panel_timing.hor_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.hor_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; - break; - case H_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_HOR_BLANK_END_SHADOW_FORMULA - (panel_timing.hor_blank_start, - panel_timing.hor_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg; - break; - case V_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_VER_TOTAL_SHADOW_FORMULA - (panel_timing.ver_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; - break; - case V_ADDR_SHADOW_INDEX: - reg_value = - IGA2_VER_ADDR_SHADOW_FORMULA - (panel_timing.ver_addr); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_addr_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; - break; - case V_BLANK_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_START_SHADOW_FORMULA - (panel_timing.ver_blank_start); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg; - break; - case V_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_END_SHADOW_FORMULA - (panel_timing.ver_blank_start, - panel_timing.ver_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg; - break; - case V_SYNC_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_START_SHADOW_FORMULA - (panel_timing.ver_sync_start); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_sync_start_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_sync_start_shadow.reg; - break; - case V_SYNC_END_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_END_SHADOW_FORMULA - (panel_timing.ver_sync_start, - panel_timing.ver_sync_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_sync_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_sync_end_shadow.reg; - break; - } - viafb_load_reg(reg_value, - viafb_load_reg_Num, reg, VIACR); - } - } else { /* Centering */ - for (i = 12; i < 20; i++) { - switch (i) { - case H_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_HOR_TOTAL_SHADOW_FORMULA - (panel_timing.hor_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.hor_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.hor_total_shadow.reg; - break; - case H_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_HOR_BLANK_END_SHADOW_FORMULA - (panel_timing.hor_blank_start, - panel_timing.hor_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - hor_blank_end_shadow.reg; - break; - case V_TOTAL_SHADOW_INDEX: - reg_value = - IGA2_VER_TOTAL_SHADOW_FORMULA - (panel_timing.ver_total); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_total_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_total_shadow.reg; - break; - case V_ADDR_SHADOW_INDEX: - reg_value = - IGA2_VER_ADDR_SHADOW_FORMULA - (mode_timing.ver_addr); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_addr_shadow. - reg_num; - reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg; - break; - case V_BLANK_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_START_SHADOW_FORMULA - (mode_timing.ver_blank_start); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_start_shadow.reg; - break; - case V_BLANK_END_SHADOW_INDEX: - reg_value = - IGA2_VER_BLANK_END_SHADOW_FORMULA - (panel_timing.ver_blank_start, - panel_timing.ver_blank_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg_num; - reg = - iga2_shadow_crtc_reg. - ver_blank_end_shadow.reg; - break; - case V_SYNC_SATRT_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_START_SHADOW_FORMULA( - (panel_timing.ver_sync_start - - panel_timing.ver_blank_start) + - (panel_timing.ver_addr - - mode_timing.ver_addr) / 2 + - mode_timing.ver_addr); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_sync_start_shadow. - reg_num; - reg = - iga2_shadow_crtc_reg.ver_sync_start_shadow. - reg; - break; - case V_SYNC_END_SHADOW_INDEX: - reg_value = - IGA2_VER_SYNC_END_SHADOW_FORMULA( - (panel_timing.ver_sync_start - - panel_timing.ver_blank_start) + - (panel_timing.ver_addr - - mode_timing.ver_addr) / 2 + - mode_timing.ver_addr, - panel_timing.ver_sync_end); - viafb_load_reg_Num = - iga2_shadow_crtc_reg.ver_sync_end_shadow. - reg_num; - reg = - iga2_shadow_crtc_reg.ver_sync_end_shadow. - reg; - break; - } - viafb_load_reg(reg_value, - viafb_load_reg_Num, reg, VIACR); - } - } -} - bool viafb_lcd_get_mobile_state(bool *mobile) { unsigned char *romptr, *tableptr; diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 7cd03e2..d55aaa7 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -43,61 +43,6 @@ /* Video Memory Size */ #define VIDEO_MEMORY_SIZE_16M 0x1000000 -/* Definition Mode Index -*/ -#define VIA_RES_640X480 0 -#define VIA_RES_800X600 1 -#define VIA_RES_1024X768 2 -#define VIA_RES_1152X864 3 -#define VIA_RES_1280X1024 4 -#define VIA_RES_1600X1200 5 -#define VIA_RES_1440X1050 6 -#define VIA_RES_1280X768 7 -#define VIA_RES_1280X960 8 -#define VIA_RES_1920X1440 9 -#define VIA_RES_848X480 10 -#define VIA_RES_1400X1050 11 -#define VIA_RES_720X480 12 -#define VIA_RES_720X576 13 -#define VIA_RES_1024X512 14 -#define VIA_RES_856X480 15 -#define VIA_RES_1024X576 16 -#define VIA_RES_640X400 17 -#define VIA_RES_1280X720 18 -#define VIA_RES_1920X1080 19 -#define VIA_RES_800X480 20 -#define VIA_RES_1368X768 21 -#define VIA_RES_1024X600 22 -#define VIA_RES_1280X800 23 -#define VIA_RES_1680X1050 24 -#define VIA_RES_960X600 25 -#define VIA_RES_1000X600 26 -#define VIA_RES_1088X612 27 -#define VIA_RES_1152X720 28 -#define VIA_RES_1200X720 29 -#define VIA_RES_1280X600 30 -#define VIA_RES_1360X768 31 -#define VIA_RES_1366X768 32 -#define VIA_RES_1440X900 33 -#define VIA_RES_1600X900 34 -#define VIA_RES_1600X1024 35 -#define VIA_RES_1792X1344 36 -#define VIA_RES_1856X1392 37 -#define VIA_RES_1920X1200 38 -#define VIA_RES_2048X1536 39 -#define VIA_RES_480X640 40 - -/*Reduce Blanking*/ -#define VIA_RES_1360X768_RB 131 -#define VIA_RES_1440X900_RB 133 -#define VIA_RES_1400X1050_RB 111 -#define VIA_RES_1600X900_RB 134 -#define VIA_RES_1680X1050_RB 124 -#define VIA_RES_1920X1080_RB 119 -#define VIA_RES_1920X1200_RB 138 - -#define VIA_RES_INVALID 255 - /* standard VGA IO port */ #define VIARMisc 0x3CC @@ -118,7 +63,6 @@ /* Display path */ #define IGA1 1 #define IGA2 2 -#define IGA1_IGA2 3 /* Define Color Depth */ #define MODE_8BPP 1 diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index d53c3d5..aefdeee 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c @@ -239,15 +239,3 @@ void viafb_get_gamma_support_state(int bpp, unsigned int *support_state) else *support_state = CRT_Device | DVI_Device | LCD_Device; } - -int viafb_input_parameter_converter(int parameter_value) -{ - int result; - - if (parameter_value >= 1 && parameter_value <= 9) - result = 1 << (parameter_value - 1); - else - result = 1; - - return result; -} diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h index 2fd4552..1670ba8 100644 --- a/drivers/video/via/via_utility.h +++ b/drivers/video/via/via_utility.h @@ -30,6 +30,5 @@ bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres); void viafb_set_gamma_table(int bpp, unsigned int *gamma_table); void viafb_get_gamma_table(unsigned int *gamma_table); void viafb_get_gamma_support_state(int bpp, unsigned int *support_state); -int viafb_input_parameter_converter(int parameter_value); #endif /* __VIAUTILITY_H__ */ diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3028e7d..ce7783b 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -26,18 +26,22 @@ #include "global.h" -static struct fb_var_screeninfo default_var; static char *viafb_name = "Via"; static u32 pseudo_pal[17]; /* video mode */ -static char *viafb_mode = "640x480"; -static char *viafb_mode1 = "640x480"; +static char *viafb_mode; +static char *viafb_mode1; +static int viafb_bpp = 32; +static int viafb_bpp1 = 32; + +static unsigned int viafb_second_offset; +static int viafb_second_size; static int viafb_accel = 1; /* Added for specifying active devices.*/ -char *viafb_active_dev = ""; +char *viafb_active_dev; /*Added for specify lcd output port*/ char *viafb_lcd_port = ""; @@ -50,18 +54,78 @@ static void apply_second_mode_setting(struct fb_var_screeninfo *sec_var); static void retrieve_device_setting(struct viafb_ioctl_setting *setting_info); +static int viafb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info); static struct fb_ops viafb_ops; +static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth) +{ + var->grayscale = 0; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->nonstd = 0; + switch (depth) { + case 8: + var->bits_per_pixel = 8; + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + break; + case 15: + var->bits_per_pixel = 16; + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + break; + case 16: + var->bits_per_pixel = 16; + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + break; + case 24: + var->bits_per_pixel = 32; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + break; + case 30: + var->bits_per_pixel = 32; + var->red.offset = 20; + var->green.offset = 10; + var->blue.offset = 0; + var->red.length = 10; + var->green.length = 10; + var->blue.length = 10; + break; + } +} + static void viafb_update_fix(struct fb_info *info) { u32 bpp = info->var.bits_per_pixel; info->fix.visual = bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - info->fix.line_length = - ((info->var.xres_virtual + 7) & ~7) * bpp / 8; + info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; } static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, @@ -75,6 +139,7 @@ static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; + fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; @@ -97,9 +162,10 @@ static int viafb_release(struct fb_info *info, int user) static int viafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - int vmode_index, htotal, vtotal; + int htotal, vtotal, depth; + struct VideoModeTable *vmode_entry; struct viafb_par *ppar = info->par; - u32 long_refresh; + u32 long_refresh, line; DEBUG_MSG(KERN_INFO "viafb_check_var!\n"); /* Sanity check */ @@ -107,26 +173,36 @@ static int viafb_check_var(struct fb_var_screeninfo *var, if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) return -EINVAL; - vmode_index = viafb_get_mode_index(var->xres, var->yres); - if (vmode_index == VIA_RES_INVALID) { + vmode_entry = viafb_get_mode(var->xres, var->yres); + if (!vmode_entry) { DEBUG_MSG(KERN_INFO "viafb: Mode %dx%dx%d not supported!!\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } - if (24 == var->bits_per_pixel) - var->bits_per_pixel = 32; + depth = fb_get_color_depth(var, &info->fix); + if (!depth) + depth = var->bits_per_pixel; - if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && - var->bits_per_pixel != 32) + if (depth < 0 || depth > 32) return -EINVAL; + else if (!depth) + depth = 24; + else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1) + depth = 15; + else if (depth == 30) + depth = 30; + else if (depth <= 8) + depth = 8; + else if (depth <= 16) + depth = 16; + else + depth = 24; - if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F) - /*32 pixel alignment */ - var->xres_virtual = (var->xres_virtual + 31) & ~31; - if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > - ppar->memsize) + viafb_fill_var_color_info(var, depth); + line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; + if (line * var->yres_virtual > ppar->memsize) return -EINVAL; /* Based on var passed in to calculate the refresh, @@ -142,7 +218,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh); /* Adjust var according to our driver's own table */ - viafb_fill_var_timing_info(var, viafb_refresh, vmode_index); + viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); if (info->var.accel_flags & FB_ACCELF_TEXT && !ppar->shared->engine_mmio) info->var.accel_flags = 0; @@ -153,39 +229,45 @@ static int viafb_check_var(struct fb_var_screeninfo *var, static int viafb_set_par(struct fb_info *info) { struct viafb_par *viapar = info->par; - int vmode_index; - int vmode_index1 = 0; + struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); viapar->depth = fb_get_color_depth(&info->var, &info->fix); - viafb_update_device_setting(info->var.xres, info->var.yres, - info->var.bits_per_pixel, viafb_refresh, 0); + viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, + viafbinfo->var.bits_per_pixel, viafb_refresh, 0); - vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres); - - if (viafb_SAMM_ON == 1) { + vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); + if (viafb_dual_fb) { + vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres, + viafbinfo1->var.yres); + viafb_update_device_setting(viafbinfo1->var.xres, + viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, + viafb_refresh1, 1); + } else if (viafb_SAMM_ON == 1) { DEBUG_MSG(KERN_INFO "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", viafb_second_xres, viafb_second_yres, viafb_bpp1); - vmode_index1 = viafb_get_mode_index(viafb_second_xres, + vmode_entry1 = viafb_get_mode(viafb_second_xres, viafb_second_yres); - DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n", - vmode_index1); viafb_update_device_setting(viafb_second_xres, viafb_second_yres, viafb_bpp1, viafb_refresh1, 1); } - if (vmode_index != VIA_RES_INVALID) { + if (vmode_entry) { viafb_update_fix(info); - viafb_bpp = info->var.bits_per_pixel; + if (viafb_dual_fb && viapar->iga_path == IGA2) + viafb_bpp1 = info->var.bits_per_pixel; + else + viafb_bpp = info->var.bits_per_pixel; + if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; - viafb_setmode(vmode_index, info->var.xres, info->var.yres, - info->var.bits_per_pixel, vmode_index1, - viafb_second_xres, viafb_second_yres, viafb_bpp1); + viafb_setmode(vmode_entry, info->var.bits_per_pixel, + vmode_entry1, viafb_bpp1); + viafb_pan_display(&info->var, info); } return 0; @@ -195,234 +277,52 @@ static int viafb_set_par(struct fb_info *info) static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; - unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16; - DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n"); - if (regno >= cmap_entries) - return 1; - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { - /* - * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev. - */ - outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); - rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; - } - switch (info->var.bits_per_pixel) { - case 8: - outb(0x1A, 0x3C4); - sr1a = inb(0x3C5); - outb(0x1B, 0x3C4); - sr1b = inb(0x3C5); - outb(0x67, 0x3D4); - cr67 = inb(0x3D5); - outb(0x6A, 0x3D4); - cr6a = inb(0x3D5); - - /* Map the 3C6/7/8/9 to the IGA2 */ - outb(0x1A, 0x3C4); - outb(sr1a | 0x01, 0x3C5); - /* Second Display Engine colck always on */ - outb(0x1B, 0x3C4); - outb(sr1b | 0x80, 0x3C5); - /* Second Display Color Depth 8 */ - outb(0x67, 0x3D4); - outb(cr67 & 0x3F, 0x3D5); - outb(0x6A, 0x3D4); - /* Second Display Channel Reset CR6A[6]) */ - outb(cr6a & 0xBF, 0x3D5); - /* Second Display Channel Enable CR6A[7] */ - outb(cr6a | 0x80, 0x3D5); - /* Second Display Channel stop reset) */ - outb(cr6a | 0x40, 0x3D5); - - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - /* Write one register of IGA2 */ - outb(regno, 0x3C8); - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && - rev >= 15) { - shift = 8; - viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); - viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); - } else { - shift = 10; - viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); - viafb_write_reg_mask(SR15, VIASR, 0, BIT7); - } - outb(red >> shift, 0x3C9); - outb(green >> shift, 0x3C9); - outb(blue >> shift, 0x3C9); - - /* Map the 3C6/7/8/9 to the IGA1 */ - outb(0x1A, 0x3C4); - outb(sr1a & 0xFE, 0x3C5); - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - /* Write one register of IGA1 */ - outb(regno, 0x3C8); - outb(red >> shift, 0x3C9); - outb(green >> shift, 0x3C9); - outb(blue >> shift, 0x3C9); - - outb(0x1A, 0x3C4); - outb(sr1a, 0x3C5); - outb(0x1B, 0x3C4); - outb(sr1b, 0x3C5); - outb(0x67, 0x3D4); - outb(cr67, 0x3D5); - outb(0x6A, 0x3D4); - outb(cr6a, 0x3D5); - break; - case 16: - ((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) | - ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11); - break; - case 32: - ((u32 *) info->pseudo_palette)[regno] = - ((transp & 0xFF00) << 16) | - ((red & 0xFF00) << 8) | - ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); - break; - } - - return 0; + struct viafb_par *viapar = info->par; + u32 r, g, b; -} + if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { + if (regno > 255) + return -EINVAL; -/*CALLED BY: fb_set_cmap */ -/* fb_set_var, pass 256 colors */ -/*CALLED BY: fb_set_cmap */ -/* fbcon_set_palette, pass 16 colors */ -static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) -{ - u32 len = cmap->len; - u32 i; - u16 *pred = cmap->red; - u16 *pgreen = cmap->green; - u16 *pblue = cmap->blue; - u16 *ptransp = cmap->transp; - u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10; - if (len > 256) - return 1; - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) { - /* - * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip - * rev. - */ - outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8); - rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff; - } - switch (info->var.bits_per_pixel) { - case 8: - outb(0x1A, 0x3C4); - sr1a = inb(0x3C5); - outb(0x1B, 0x3C4); - sr1b = inb(0x3C5); - outb(0x67, 0x3D4); - cr67 = inb(0x3D5); - outb(0x6A, 0x3D4); - cr6a = inb(0x3D5); - /* Map the 3C6/7/8/9 to the IGA2 */ - outb(0x1A, 0x3C4); - outb(sr1a | 0x01, 0x3C5); - outb(0x1B, 0x3C4); - /* Second Display Engine colck always on */ - outb(sr1b | 0x80, 0x3C5); - outb(0x67, 0x3D4); - /* Second Display Color Depth 8 */ - outb(cr67 & 0x3F, 0x3D5); - outb(0x6A, 0x3D4); - /* Second Display Channel Reset CR6A[6]) */ - outb(cr6a & 0xBF, 0x3D5); - /* Second Display Channel Enable CR6A[7] */ - outb(cr6a | 0x80, 0x3D5); - /* Second Display Channel stop reset) */ - outb(cr6a | 0xC0, 0x3D5); - - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - outb(0x00, 0x3C8); - if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name && - rev >= 15) { - shift = 8; - viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5); - viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7); - } else { - shift = 10; - viafb_write_reg_mask(CR6A, VIACR, 0, BIT5); - viafb_write_reg_mask(SR15, VIASR, 0, BIT7); - } - for (i = 0; i < len; i++) { - outb((*(pred + i)) >> shift, 0x3C9); - outb((*(pgreen + i)) >> shift, 0x3C9); - outb((*(pblue + i)) >> shift, 0x3C9); - } + if (!viafb_dual_fb || viapar->iga_path == IGA1) + viafb_set_primary_color_register(regno, red >> 8, + green >> 8, blue >> 8); - outb(0x1A, 0x3C4); - /* Map the 3C6/7/8/9 to the IGA1 */ - outb(sr1a & 0xFE, 0x3C5); - /* Bit mask of palette */ - outb(0xFF, 0x3c6); - outb(0x00, 0x3C8); - for (i = 0; i < len; i++) { - outb((*(pred + i)) >> shift, 0x3C9); - outb((*(pgreen + i)) >> shift, 0x3C9); - outb((*(pblue + i)) >> shift, 0x3C9); - } + if (!viafb_dual_fb || viapar->iga_path == IGA2) + viafb_set_secondary_color_register(regno, red >> 8, + green >> 8, blue >> 8); + } else { + if (regno > 15) + return -EINVAL; - outb(0x1A, 0x3C4); - outb(sr1a, 0x3C5); - outb(0x1B, 0x3C4); - outb(sr1b, 0x3C5); - outb(0x67, 0x3D4); - outb(cr67, 0x3D5); - outb(0x6A, 0x3D4); - outb(cr6a, 0x3D5); - break; - case 16: - if (len > 17) - return 0; /* Because static u32 pseudo_pal[17]; */ - for (i = 0; i < len; i++) - ((u32 *) info->pseudo_palette)[i] = - (*(pred + i) & 0xF800) | - ((*(pgreen + i) & 0xFC00) >> 5) | - ((*(pblue + i) & 0xF800) >> 11); - break; - case 32: - if (len > 17) - return 0; - if (ptransp) { - for (i = 0; i < len; i++) - ((u32 *) info->pseudo_palette)[i] = - ((*(ptransp + i) & 0xFF00) << 16) | - ((*(pred + i) & 0xFF00) << 8) | - ((*(pgreen + i) & 0xFF00)) | - ((*(pblue + i) & 0xFF00) >> 8); - } else { - for (i = 0; i < len; i++) - ((u32 *) info->pseudo_palette)[i] = - 0x00000000 | - ((*(pred + i) & 0xFF00) << 8) | - ((*(pgreen + i) & 0xFF00)) | - ((*(pblue + i) & 0xFF00) >> 8); - } - break; + r = (red >> (16 - info->var.red.length)) + << info->var.red.offset; + b = (blue >> (16 - info->var.blue.length)) + << info->var.blue.offset; + g = (green >> (16 - info->var.green.length)) + << info->var.green.offset; + ((u32 *) info->pseudo_palette)[regno] = r | g | b; } + return 0; } static int viafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - unsigned int offset; - - DEBUG_MSG(KERN_INFO "viafb_pan_display!\n"); - - offset = (var->xoffset + (var->yoffset * var->xres_virtual)) * - var->bits_per_pixel / 16; + struct viafb_par *viapar = info->par; + u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) + * (var->bits_per_pixel / 8) + viapar->vram_addr; + + DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); + if (!viafb_dual_fb) { + viafb_set_primary_address(vram_addr); + viafb_set_secondary_address(vram_addr); + } else if (viapar->iga_path == IGA1) + viafb_set_primary_address(vram_addr); + else + viafb_set_secondary_address(vram_addr); - DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset); - viafb_set_primary_address(offset); return 0; } @@ -476,6 +376,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) u32 gpu32; DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); + printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n"); memset(&u, 0, sizeof(u)); switch (cmd) { @@ -1015,23 +916,6 @@ static int viafb_sync(struct fb_info *info) return 0; } -int viafb_get_mode_index(int hres, int vres) -{ - u32 i; - DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n"); - - for (i = 0; i < NUM_TOTAL_MODETABLE; i++) - if (CLE266Modes[i].mode_array && - CLE266Modes[i].crtc[0].crtc.hor_addr == hres && - CLE266Modes[i].crtc[0].crtc.ver_addr == vres) - break; - - if (i == NUM_TOTAL_MODETABLE) - return VIA_RES_INVALID; - - return CLE266Modes[i].ModeIndex; -} - static void check_available_device_to_enable(int device_id) { int device_num = 0; @@ -1330,7 +1214,7 @@ static void retrieve_device_setting(struct viafb_ioctl_setting setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode; } -static void parse_active_dev(void) +static int parse_active_dev(void) { viafb_CRT_ON = STATE_OFF; viafb_DVI_ON = STATE_OFF; @@ -1341,60 +1225,63 @@ static void parse_active_dev(void) IGA path to devices in SAMM case. */ /* Note: The previous of active_dev is primary device, and the following is secondary device. */ - if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) { + if (!viafb_active_dev) { + viafb_CRT_ON = STATE_ON; + viafb_SAMM_ON = STATE_OFF; + } else if (!strcmp(viafb_active_dev, "CRT+DVI")) { /* CRT+DVI */ viafb_CRT_ON = STATE_ON; viafb_DVI_ON = STATE_ON; viafb_primary_dev = CRT_Device; - } else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) { + } else if (!strcmp(viafb_active_dev, "DVI+CRT")) { /* DVI+CRT */ viafb_CRT_ON = STATE_ON; viafb_DVI_ON = STATE_ON; viafb_primary_dev = DVI_Device; - } else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) { + } else if (!strcmp(viafb_active_dev, "CRT+LCD")) { /* CRT+LCD */ viafb_CRT_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = CRT_Device; - } else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) { + } else if (!strcmp(viafb_active_dev, "LCD+CRT")) { /* LCD+CRT */ viafb_CRT_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = LCD_Device; - } else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) { + } else if (!strcmp(viafb_active_dev, "DVI+LCD")) { /* DVI+LCD */ viafb_DVI_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = DVI_Device; - } else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) { + } else if (!strcmp(viafb_active_dev, "LCD+DVI")) { /* LCD+DVI */ viafb_DVI_ON = STATE_ON; viafb_LCD_ON = STATE_ON; viafb_primary_dev = LCD_Device; - } else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) { + } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) { viafb_LCD_ON = STATE_ON; viafb_LCD2_ON = STATE_ON; viafb_primary_dev = LCD_Device; - } else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) { + } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) { viafb_LCD_ON = STATE_ON; viafb_LCD2_ON = STATE_ON; viafb_primary_dev = LCD2_Device; - } else if (!strncmp(viafb_active_dev, "CRT", 3)) { + } else if (!strcmp(viafb_active_dev, "CRT")) { /* CRT only */ viafb_CRT_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; - } else if (!strncmp(viafb_active_dev, "DVI", 3)) { + } else if (!strcmp(viafb_active_dev, "DVI")) { /* DVI only */ viafb_DVI_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; - } else if (!strncmp(viafb_active_dev, "LCD", 3)) { + } else if (!strcmp(viafb_active_dev, "LCD")) { /* LCD only */ viafb_LCD_ON = STATE_ON; viafb_SAMM_ON = STATE_OFF; - } else { - viafb_CRT_ON = STATE_ON; - viafb_SAMM_ON = STATE_OFF; - } + } else + return -EINVAL; + + return 0; } static int parse_port(char *opt_str, int *output_interface) @@ -1823,35 +1710,37 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("viafb", NULL); } -static void parse_mode(const char *str, u32 *xres, u32 *yres) +static int parse_mode(const char *str, u32 *xres, u32 *yres) { char *ptr; + if (!str) { + *xres = 640; + *yres = 480; + return 0; + } + *xres = simple_strtoul(str, &ptr, 10); if (ptr[0] != 'x') - goto out_default; + return -EINVAL; *yres = simple_strtoul(&ptr[1], &ptr, 10); if (ptr[0]) - goto out_default; - - return; + return -EINVAL; -out_default: - printk(KERN_WARNING "viafb received invalid mode string: %s\n", str); - *xres = 640; - *yres = 480; + return 0; } static int __devinit via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { u32 default_xres, default_yres; - int vmode_index; + struct VideoModeTable *vmode_entry; + struct fb_var_screeninfo default_var; u32 viafb_par_length; DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); - + memset(&default_var, 0, sizeof(default_var)); viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8); /* Allocate fb_info and ***_par here, also including some other needed @@ -1877,7 +1766,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, if (viafb_dual_fb) viafb_SAMM_ON = 1; - parse_active_dev(); parse_lcd_port(); parse_dvi_port(); @@ -1926,9 +1814,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, } parse_mode(viafb_mode, &default_xres, &default_yres); - vmode_index = viafb_get_mode_index(default_xres, default_yres); - DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); - + vmode_entry = viafb_get_mode(default_xres, default_yres); if (viafb_SAMM_ON == 1) { parse_mode(viafb_mode1, &viafb_second_xres, &viafb_second_yres); @@ -1947,19 +1833,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_second_virtual_yres = viafb_second_yres; } - switch (viafb_bpp) { - case 0 ... 8: - viafb_bpp = 8; - break; - case 9 ... 16: - viafb_bpp = 16; - break; - case 17 ... 32: - viafb_bpp = 32; - break; - default: - viafb_bpp = 8; - } default_var.xres = default_xres; default_var.yres = default_yres; switch (default_xres) { @@ -1972,8 +1845,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, } default_var.yres_virtual = default_yres; default_var.bits_per_pixel = viafb_bpp; - if (default_var.bits_per_pixel == 15) - default_var.bits_per_pixel = 16; default_var.pixclock = viafb_get_pixclock(default_xres, default_yres, viafb_refresh); default_var.left_margin = (default_xres >> 3) & 0xf8; @@ -1982,6 +1853,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, default_var.lower_margin = 4; default_var.hsync_len = default_var.left_margin; default_var.vsync_len = 4; + viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); + viafbinfo->var = default_var; if (viafb_dual_fb) { viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); @@ -2016,8 +1889,6 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, default_var.yres = viafb_second_yres; default_var.xres_virtual = viafb_second_virtual_xres; default_var.yres_virtual = viafb_second_virtual_yres; - if (viafb_bpp1 != viafb_bpp) - viafb_bpp1 = viafb_bpp; default_var.bits_per_pixel = viafb_bpp1; default_var.pixclock = viafb_get_pixclock(viafb_second_xres, viafb_second_yres, @@ -2037,9 +1908,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, &viafbinfo1->fix); } - viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); - viafb_check_var(&default_var, viafbinfo); - viafbinfo->var = default_var; + viafb_check_var(&viafbinfo->var, viafbinfo); viafb_update_fix(viafbinfo); viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, &viafbinfo->fix); @@ -2197,12 +2066,20 @@ static struct pci_driver viafb_driver = { static int __init viafb_init(void) { + u32 dummy; #ifndef MODULE char *option = NULL; if (fb_get_options("viafb", &option)) return -ENODEV; viafb_setup(option); #endif + if (parse_mode(viafb_mode, &dummy, &dummy) + || parse_mode(viafb_mode1, &dummy, &dummy) + || viafb_bpp < 0 || viafb_bpp > 32 + || viafb_bpp1 < 0 || viafb_bpp1 > 32 + || parse_active_dev()) + return -EINVAL; + printk(KERN_INFO "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", VERSION_MAJOR, VERSION_MINOR); @@ -2230,15 +2107,12 @@ static struct fb_ops viafb_ops = { .fb_cursor = viafb_cursor, .fb_ioctl = viafb_ioctl, .fb_sync = viafb_sync, - .fb_setcmap = viafb_setcmap, }; module_init(viafb_init); module_exit(viafb_exit); #ifdef MODULE -module_param(viafb_memsize, int, S_IRUSR); - module_param(viafb_mode, charp, S_IRUSR); MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)"); diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 0c94d24..61b5953 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -83,22 +83,16 @@ struct viafb_par { extern unsigned int viafb_second_virtual_yres; extern unsigned int viafb_second_virtual_xres; -extern unsigned int viafb_second_offset; -extern int viafb_second_size; extern int viafb_SAMM_ON; extern int viafb_dual_fb; extern int viafb_LCD2_ON; extern int viafb_LCD_ON; extern int viafb_DVI_ON; extern int viafb_hotplug; -extern int viafb_memsize; extern int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); -void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, - int mode_index); -int viafb_get_mode_index(int hres, int vres); u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, u8 index); diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index b74f8a6..af50e24 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -412,7 +412,7 @@ struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C}, }; struct patch_table res_patch_table[] = { - {VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768} + {ARRAY_SIZE(PM1024x768), PM1024x768} }; /* struct VPITTable { @@ -879,169 +879,151 @@ struct crt_mode_table CRTM2048x1536[] = { {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} } }; -/* Video Mode Table */ -/* struct VideoModeTable {*/ -/* int ModeIndex;*/ -/* struct crt_mode_table *crtc;*/ -/* int mode_array;*/ -/* };*/ -struct VideoModeTable CLE266Modes[] = { +struct VideoModeTable viafb_modes[] = { /* Display : 480x640 (GTF) */ - {VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)}, + {CRTM480x640, ARRAY_SIZE(CRTM480x640)}, /* Display : 640x480 */ - {VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)}, + {CRTM640x480, ARRAY_SIZE(CRTM640x480)}, /* Display : 720x480 (GTF) */ - {VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)}, + {CRTM720x480, ARRAY_SIZE(CRTM720x480)}, /* Display : 720x576 (GTF) */ - {VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)}, + {CRTM720x576, ARRAY_SIZE(CRTM720x576)}, /* Display : 800x600 */ - {VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)}, + {CRTM800x600, ARRAY_SIZE(CRTM800x600)}, /* Display : 800x480 (CVT) */ - {VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)}, + {CRTM800x480, ARRAY_SIZE(CRTM800x480)}, /* Display : 848x480 (CVT) */ - {VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)}, + {CRTM848x480, ARRAY_SIZE(CRTM848x480)}, /* Display : 852x480 (GTF) */ - {VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)}, + {CRTM852x480, ARRAY_SIZE(CRTM852x480)}, /* Display : 1024x512 (GTF) */ - {VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, + {CRTM1024x512, ARRAY_SIZE(CRTM1024x512)}, /* Display : 1024x600 */ - {VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, - - /* Display : 1024x576 (GTF) */ - /*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */ + {CRTM1024x600, ARRAY_SIZE(CRTM1024x600)}, /* Display : 1024x768 */ - {VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, + {CRTM1024x768, ARRAY_SIZE(CRTM1024x768)}, /* Display : 1152x864 */ - {VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, + {CRTM1152x864, ARRAY_SIZE(CRTM1152x864)}, /* Display : 1280x768 (GTF) */ - {VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, + {CRTM1280x768, ARRAY_SIZE(CRTM1280x768)}, /* Display : 960x600 (CVT) */ - {VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)}, + {CRTM960x600, ARRAY_SIZE(CRTM960x600)}, /* Display : 1000x600 (GTF) */ - {VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, + {CRTM1000x600, ARRAY_SIZE(CRTM1000x600)}, /* Display : 1024x576 (GTF) */ - {VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, + {CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, /* Display : 1088x612 (GTF) */ - {VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, + {CRTM1088x612, ARRAY_SIZE(CRTM1088x612)}, /* Display : 1152x720 (CVT) */ - {VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, + {CRTM1152x720, ARRAY_SIZE(CRTM1152x720)}, /* Display : 1200x720 (GTF) */ - {VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, + {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, /* Display : 1280x600 (GTF) */ - {VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, + {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, /* Display : 1280x800 (CVT) */ - {VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, - - /* Display : 1280x800 (GTF) */ - /*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */ + {CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, /* Display : 1280x960 */ - {VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, + {CRTM1280x960, ARRAY_SIZE(CRTM1280x960)}, /* Display : 1280x1024 */ - {VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, + {CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)}, /* Display : 1360x768 (CVT) */ - {VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, - - /* Display : 1360x768 (CVT Reduce Blanking) */ - {VIA_RES_1360X768_RB, CRTM1360x768_RB, - ARRAY_SIZE(CRTM1360x768_RB)}, + {CRTM1360x768, ARRAY_SIZE(CRTM1360x768)}, /* Display : 1366x768 */ - {VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, + {CRTM1366x768, ARRAY_SIZE(CRTM1366x768)}, /* Display : 1368x768 (GTF) */ - /*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */ - /* Display : 1368x768 (GTF) */ - {VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, + {CRTM1368x768, ARRAY_SIZE(CRTM1368x768)}, /* Display : 1440x900 (CVT) */ - {VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, - - /* Display : 1440x900 (CVT Reduce Blanking) */ - {VIA_RES_1440X900_RB, CRTM1440x900_RB, - ARRAY_SIZE(CRTM1440x900_RB)}, + {CRTM1440x900, ARRAY_SIZE(CRTM1440x900)}, /* Display : 1440x1050 (GTF) */ - {VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, - - /* Display : 1400x1050 (CVT Reduce Blanking) */ - {VIA_RES_1400X1050_RB, CRTM1400x1050_RB, - ARRAY_SIZE(CRTM1400x1050_RB)}, + {CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)}, /* Display : 1600x900 (CVT) */ - {VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, - - /* Display : 1600x900 (CVT Reduce Blanking) */ - {VIA_RES_1600X900_RB, CRTM1600x900_RB, - ARRAY_SIZE(CRTM1600x900_RB)}, + {CRTM1600x900, ARRAY_SIZE(CRTM1600x900)}, /* Display : 1600x1024 (GTF) */ - {VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, + {CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)}, /* Display : 1600x1200 */ - {VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, + {CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)}, /* Display : 1680x1050 (CVT) */ - {VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, - - /* Display : 1680x1050 (CVT Reduce Blanking) */ - {VIA_RES_1680X1050_RB, CRTM1680x1050_RB, - ARRAY_SIZE(CRTM1680x1050_RB)}, + {CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)}, /* Display : 1792x1344 (DMT) */ - {VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, + {CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)}, /* Display : 1856x1392 (DMT) */ - {VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, + {CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)}, /* Display : 1920x1440 */ - {VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, + {CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)}, /* Display : 2048x1536 */ - {VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, + {CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)}, /* Display : 1280x720 */ - {VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, + {CRTM1280x720, ARRAY_SIZE(CRTM1280x720)}, /* Display : 1920x1080 (CVT) */ - {VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, - - /* Display : 1920x1080 (CVT Reduce Blanking) */ - {VIA_RES_1920X1080_RB, CRTM1920x1080_RB, - ARRAY_SIZE(CRTM1920x1080_RB)}, + {CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)}, /* Display : 1920x1200 (CVT) */ - {VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, - - /* Display : 1920x1200 (CVT Reduce Blanking) */ - {VIA_RES_1920X1200_RB, CRTM1920x1200_RB, - ARRAY_SIZE(CRTM1920x1200_RB)}, + {CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)}, /* Display : 1400x1050 (CVT) */ - {VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} + {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)} }; + +struct VideoModeTable viafb_rb_modes[] = { + /* Display : 1360x768 (CVT Reduce Blanking) */ + {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)}, + + /* Display : 1440x900 (CVT Reduce Blanking) */ + {CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)}, + + /* Display : 1400x1050 (CVT Reduce Blanking) */ + {CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)}, + + /* Display : 1600x900 (CVT Reduce Blanking) */ + {CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)}, + + /* Display : 1680x1050 (CVT Reduce Blanking) */ + {CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)}, + + /* Display : 1920x1080 (CVT Reduce Blanking) */ + {CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)}, + + /* Display : 1920x1200 (CVT Reduce Blanking) */ + {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)} +}; + struct crt_mode_table CEAM1280x720[] = { {REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP, M1280X720_CEA_R60_VSP, @@ -1056,8 +1038,8 @@ struct crt_mode_table CEAM1920x1080[] = { }; struct VideoModeTable CEA_HDMI_Modes[] = { /* Display : 1280x720 */ - {VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, - {VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} + {CEAM1280x720, ARRAY_SIZE(CEAM1280x720)}, + {CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)} }; int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl); @@ -1069,4 +1051,28 @@ int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs); int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs); int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); -int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes); + + +struct VideoModeTable *viafb_get_mode(int hres, int vres) +{ + u32 i; + for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) + if (viafb_modes[i].mode_array && + viafb_modes[i].crtc[0].crtc.hor_addr == hres && + viafb_modes[i].crtc[0].crtc.ver_addr == vres) + return &viafb_modes[i]; + + return NULL; +} + +struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) +{ + u32 i; + for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) + if (viafb_rb_modes[i].mode_array && + viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && + viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) + return &viafb_rb_modes[i]; + + return NULL; +} diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index a9d6554..5b1ced8 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h @@ -32,13 +32,11 @@ struct VPITTable { }; struct VideoModeTable { - int ModeIndex; struct crt_mode_table *crtc; int mode_array; }; struct patch_table { - int mode_index; int table_length; struct io_reg *io_reg_table; }; @@ -59,13 +57,11 @@ extern int NUM_TOTAL_CX700_ModeXregs; extern int NUM_TOTAL_VX855_ModeXregs; extern int NUM_TOTAL_CLE266_ModeXregs; extern int NUM_TOTAL_PATCH_MODE; -extern int NUM_TOTAL_MODETABLE; /********************/ /* Mode Table */ /********************/ -extern struct VideoModeTable CLE266Modes[]; extern struct crt_mode_table CEAM1280x720[]; extern struct crt_mode_table CEAM1920x1080[]; extern struct VideoModeTable CEA_HDMI_Modes[]; @@ -81,4 +77,8 @@ extern struct io_reg CLE266_ModeXregs[]; extern struct io_reg PM1024x768[]; extern struct patch_table res_patch_table[]; extern struct VPITTable VPIT; + +struct VideoModeTable *viafb_get_mode(int hres, int vres); +struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); + #endif /* __VIAMODE_H__ */ diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index 2376f68..5d22395 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -628,7 +628,7 @@ static int w100fb_resume(struct platform_device *dev) #endif -int __init w100fb_probe(struct platform_device *pdev) +int __devinit w100fb_probe(struct platform_device *pdev) { int err = -EIO; struct w100fb_mach_info *inf; |