Commit d4a7dbfd authored by Florian Tobias Schandinat's avatar Florian Tobias Schandinat

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-3.x into fbdev-next

Conflicts:
	drivers/video/atmel_lcdfb.c
parents b5480ed7 fa514fbc
......@@ -66,8 +66,8 @@ struct fsl_diu_shared_fb {
bool in_use;
};
unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
int monitor_port)
u32 mpc512x_get_pixel_format(enum fsl_diu_monitor_port port,
unsigned int bits_per_pixel)
{
switch (bits_per_pixel) {
case 32:
......@@ -80,11 +80,12 @@ unsigned int mpc512x_get_pixel_format(unsigned int bits_per_pixel,
return 0x00000400;
}
void mpc512x_set_gamma_table(int monitor_port, char *gamma_table_base)
void mpc512x_set_gamma_table(enum fsl_diu_monitor_port port,
char *gamma_table_base)
{
}
void mpc512x_set_monitor_port(int monitor_port)
void mpc512x_set_monitor_port(enum fsl_diu_monitor_port port)
{
}
......@@ -182,14 +183,10 @@ void mpc512x_set_pixel_clock(unsigned int pixclock)
iounmap(ccm);
}
ssize_t mpc512x_show_monitor_port(int monitor_port, char *buf)
enum fsl_diu_monitor_port
mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
{
return sprintf(buf, "0 - 5121 LCD\n");
}
int mpc512x_set_sysfs_monitor_port(int val)
{
return 0;
return FSL_DIU_PORT_DVI;
}
static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
......@@ -332,8 +329,7 @@ void __init mpc512x_setup_diu(void)
diu_ops.set_gamma_table = mpc512x_set_gamma_table;
diu_ops.set_monitor_port = mpc512x_set_monitor_port;
diu_ops.set_pixel_clock = mpc512x_set_pixel_clock;
diu_ops.show_monitor_port = mpc512x_show_monitor_port;
diu_ops.set_sysfs_monitor_port = mpc512x_set_sysfs_monitor_port;
diu_ops.valid_monitor_port = mpc512x_valid_monitor_port;
diu_ops.release_bootmem = mpc512x_release_bootmem;
#endif
}
......
......@@ -93,8 +93,8 @@
* The Area Descriptor is a 32-bit value that determine which bits in each
* pixel are to be used for each color.
*/
static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
int monitor_port)
static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port,
unsigned int bits_per_pixel)
{
switch (bits_per_pixel) {
case 32:
......@@ -118,7 +118,8 @@ static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
* On some boards, the gamma table for some ports may need to be modified.
* This is not the case on the P1022DS, so we do nothing.
*/
static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
char *gamma_table_base)
{
}
......@@ -126,7 +127,7 @@ static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
* p1022ds_set_monitor_port: switch the output to a different monitor port
*
*/
static void p1022ds_set_monitor_port(int monitor_port)
static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
{
struct device_node *pixis_node;
void __iomem *pixis;
......@@ -145,19 +146,21 @@ static void p1022ds_set_monitor_port(int monitor_port)
}
brdcfg1 = pixis + 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */
switch (monitor_port) {
case 0: /* DVI */
switch (port) {
case FSL_DIU_PORT_DVI:
printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
/* Enable the DVI port, disable the DFP and the backlight */
clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
PX_BRDCFG1_DVIEN);
break;
case 1: /* Single link LVDS */
case FSL_DIU_PORT_LVDS:
printk(KERN_INFO "%s:%u\n", __func__, __LINE__);
/* Enable the DFP port, disable the DVI and the backlight */
clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
PX_BRDCFG1_DFPEN);
break;
default:
pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
pr_err("p1022ds: unsupported monitor port %i\n", port);
}
iounmap(pixis);
......@@ -214,23 +217,18 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
}
/**
* p1022ds_show_monitor_port: show the current monitor
*
* This function returns a string indicating whether the current monitor is
* set to DVI or LVDS.
*/
ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
{
return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
}
/**
* p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
* p1022ds_valid_monitor_port: set the monitor port for sysfs
*/
int p1022ds_set_sysfs_monitor_port(int val)
enum fsl_diu_monitor_port
p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
{
return val < 2 ? val : 0;
switch (port) {
case FSL_DIU_PORT_DVI:
case FSL_DIU_PORT_LVDS:
return port;
default:
return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
}
}
#endif
......@@ -305,8 +303,7 @@ static void __init p1022_ds_setup_arch(void)
diu_ops.set_gamma_table = p1022ds_set_gamma_table;
diu_ops.set_monitor_port = p1022ds_set_monitor_port;
diu_ops.set_pixel_clock = p1022ds_set_pixel_clock;
diu_ops.show_monitor_port = p1022ds_show_monitor_port;
diu_ops.set_sysfs_monitor_port = p1022ds_set_sysfs_monitor_port;
diu_ops.valid_monitor_port = p1022ds_valid_monitor_port;
#endif
#ifdef CONFIG_SMP
......
......@@ -152,10 +152,10 @@ machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
(c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
(c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
int monitor_port)
u32 mpc8610hpcd_get_pixel_format(enum fsl_diu_monitor_port port,
unsigned int bits_per_pixel)
{
static const unsigned long pixelformat[][3] = {
static const u32 pixelformat[][3] = {
{
MAKE_AD(3, 0, 2, 1, 3, 8, 8, 8, 8),
MAKE_AD(4, 2, 0, 1, 2, 8, 8, 8, 0),
......@@ -170,7 +170,8 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
unsigned int arch_monitor;
/* The DVI port is mis-wired on revision 1 of this board. */
arch_monitor = ((*pixis_arch == 0x01) && (monitor_port == 0))? 0 : 1;
arch_monitor =
((*pixis_arch == 0x01) && (port == FSL_DIU_PORT_DVI)) ? 0 : 1;
switch (bits_per_pixel) {
case 32:
......@@ -185,10 +186,11 @@ unsigned int mpc8610hpcd_get_pixel_format(unsigned int bits_per_pixel,
}
}
void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
void mpc8610hpcd_set_gamma_table(enum fsl_diu_monitor_port port,
char *gamma_table_base)
{
int i;
if (monitor_port == 2) { /* dual link LVDS */
if (port == FSL_DIU_PORT_DLVDS) {
for (i = 0; i < 256*3; i++)
gamma_table_base[i] = (gamma_table_base[i] << 2) |
((gamma_table_base[i] >> 6) & 0x03);
......@@ -199,17 +201,21 @@ void mpc8610hpcd_set_gamma_table(int monitor_port, char *gamma_table_base)
#define PX_BRDCFG0_DLINK (1 << 4)
#define PX_BRDCFG0_DIU_MASK (PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK)
void mpc8610hpcd_set_monitor_port(int monitor_port)
void mpc8610hpcd_set_monitor_port(enum fsl_diu_monitor_port port)
{
static const u8 bdcfg[] = {
PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK,
PX_BRDCFG0_DLINK,
0,
};
if (monitor_port < 3)
switch (port) {
case FSL_DIU_PORT_DVI:
clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
bdcfg[monitor_port]);
PX_BRDCFG0_DVISEL | PX_BRDCFG0_DLINK);
break;
case FSL_DIU_PORT_LVDS:
clrsetbits_8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK,
PX_BRDCFG0_DLINK);
break;
case FSL_DIU_PORT_DLVDS:
clrbits8(pixis_bdcfg0, PX_BRDCFG0_DIU_MASK);
break;
}
}
/**
......@@ -262,20 +268,10 @@ void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
iounmap(guts);
}
ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
{
return snprintf(buf, PAGE_SIZE,
"%c0 - DVI\n"
"%c1 - Single link LVDS\n"
"%c2 - Dual link LVDS\n",
monitor_port == 0 ? '*' : ' ',
monitor_port == 1 ? '*' : ' ',
monitor_port == 2 ? '*' : ' ');
}
int mpc8610hpcd_set_sysfs_monitor_port(int val)
enum fsl_diu_monitor_port
mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
{
return val < 3 ? val : 0;
return port;
}
#endif
......@@ -307,8 +303,7 @@ static void __init mpc86xx_hpcd_setup_arch(void)
diu_ops.set_gamma_table = mpc8610hpcd_set_gamma_table;
diu_ops.set_monitor_port = mpc8610hpcd_set_monitor_port;
diu_ops.set_pixel_clock = mpc8610hpcd_set_pixel_clock;
diu_ops.show_monitor_port = mpc8610hpcd_show_monitor_port;
diu_ops.set_sysfs_monitor_port = mpc8610hpcd_set_sysfs_monitor_port;
diu_ops.valid_monitor_port = mpc8610hpcd_valid_monitor_port;
#endif
pixis_node = of_find_compatible_node(NULL, NULL, "fsl,fpga-pixis");
......
......@@ -22,15 +22,24 @@ struct device_node;
extern void fsl_rstcr_restart(char *cmd);
#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
/* The different ports that the DIU can be connected to */
enum fsl_diu_monitor_port {
FSL_DIU_PORT_DVI, /* DVI */
FSL_DIU_PORT_LVDS, /* Single-link LVDS */
FSL_DIU_PORT_DLVDS /* Dual-link LVDS */
};
struct platform_diu_data_ops {
unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,
int monitor_port);
void (*set_gamma_table) (int monitor_port, char *gamma_table_base);
void (*set_monitor_port) (int monitor_port);
void (*set_pixel_clock) (unsigned int pixclock);
ssize_t (*show_monitor_port) (int monitor_port, char *buf);
int (*set_sysfs_monitor_port) (int val);
void (*release_bootmem) (void);
u32 (*get_pixel_format)(enum fsl_diu_monitor_port port,
unsigned int bpp);
void (*set_gamma_table)(enum fsl_diu_monitor_port port,
char *gamma_table_base);
void (*set_monitor_port)(enum fsl_diu_monitor_port port);
void (*set_pixel_clock)(unsigned int pixclock);
enum fsl_diu_monitor_port (*valid_monitor_port)
(enum fsl_diu_monitor_port port);
void (*release_bootmem)(void);
};
extern struct platform_diu_data_ops diu_ops;
......
......@@ -259,6 +259,15 @@ config FB_TILEBLITTING
comment "Frame buffer hardware drivers"
depends on FB
config FB_GRVGA
tristate "Aeroflex Gaisler framebuffer support"
depends on FB && SPARC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
---help---
This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler.
config FB_CIRRUS
tristate "Cirrus Logic support"
depends on FB && (ZORRO || PCI)
......@@ -1756,9 +1765,10 @@ config FB_AU1100
config FB_AU1200
bool "Au1200 LCD Driver"
depends on (FB = y) && MIPS && SOC_AU1200
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
help
This is the framebuffer driver for the AMD Au1200 SOC. It can drive
various panels and CRTs by passing in kernel cmd line option
......
......@@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_GRVGA) += grvga.o
obj-$(CONFIG_FB_PM2) += pm2fb.o
obj-$(CONFIG_FB_PM3) += pm3fb.o
......
......@@ -46,14 +46,6 @@
#include <asm/mach-au1x00/au1000.h>
#include "au1200fb.h"
#ifdef CONFIG_PM
#include <asm/mach-au1x00/au1xxx_pm.h>
#endif
#ifndef CONFIG_FB_AU1200_DEVS
#define CONFIG_FB_AU1200_DEVS 4
#endif
#define DRIVER_NAME "au1200fb"
#define DRIVER_DESC "LCD controller driver for AU1200 processors"
......@@ -150,7 +142,7 @@ struct au1200_lcd_iodata_t {
/* Private, per-framebuffer management information (independent of the panel itself) */
struct au1200fb_device {
struct fb_info fb_info; /* FB driver info record */
struct fb_info *fb_info; /* FB driver info record */
int plane;
unsigned char* fb_mem; /* FrameBuffer memory map */
......@@ -158,7 +150,6 @@ struct au1200fb_device {
dma_addr_t fb_phys;
};
static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
/********************************************************************/
/* LCD controller restrictions */
......@@ -171,10 +162,18 @@ static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
/* Default number of visible screen buffer to allocate */
#define AU1200FB_NBR_VIDEO_BUFFERS 1
/* Default maximum number of fb devices to create */
#define MAX_DEVICE_COUNT 4
/* Default window configuration entry to use (see windows[]) */
#define DEFAULT_WINDOW_INDEX 2
/********************************************************************/
static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT];
static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
static int window_index = 2; /* default is zero */
static int device_count = MAX_DEVICE_COUNT;
static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */
static int panel_index = 2; /* default is zero */
static struct window_settings *win;
static struct panel_settings *panel;
......@@ -205,12 +204,6 @@ struct window_settings {
extern int board_au1200fb_panel_init (void);
extern int board_au1200fb_panel_shutdown (void);
#ifdef CONFIG_PM
int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
au1xxx_request_t request, void *data);
au1xxx_power_dev_t *LCD_pm_dev;
#endif
/*
* Default window configurations
*/
......@@ -652,25 +645,6 @@ static struct panel_settings known_lcd_panels[] =
/********************************************************************/
#ifdef CONFIG_PM
static int set_brightness(unsigned int brightness)
{
unsigned int hi1, divider;
/* limit brightness pwm duty to >= 30/1600 */
if (brightness < 30) {
brightness = 30;
}
divider = (lcd->pwmdiv & 0x3FFFF) + 1;
hi1 = (lcd->pwmhi >> 16) + 1;
hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
lcd->pwmhi &= 0xFFFF;
lcd->pwmhi |= (hi1 << 16);
return brightness;
}
#endif /* CONFIG_PM */
static int winbpp (unsigned int winctrl1)
{
int bits = 0;
......@@ -712,8 +686,8 @@ static int fbinfo2index (struct fb_info *fb_info)
{
int i;
for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info))
for (i = 0; i < device_count; ++i) {
if (fb_info == _au1200fb_infos[i])
return i;
}
printk("au1200fb: ERROR: fbinfo2index failed!\n");
......@@ -962,7 +936,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev)
lcd->window[plane].winctrl2 = ( 0
| LCD_WINCTRL2_CKMODE_00
| LCD_WINCTRL2_DBM
| LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
| LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length)
| LCD_WINCTRL2_SCX_1
| LCD_WINCTRL2_SCY_1
) ;
......@@ -1050,7 +1024,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi)
static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *fbi)
{
struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
struct au1200fb_device *fbdev = fbi->par;
u32 pixclock;
int screen_size, plane;
......@@ -1142,7 +1116,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
*/
static int au1200fb_fb_set_par(struct fb_info *fbi)
{
struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
struct au1200fb_device *fbdev = fbi->par;
au1200fb_update_fbinfo(fbi);
au1200_setmode(fbdev);
......@@ -1246,11 +1220,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned int len;
unsigned long start=0, off;
struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
#ifdef CONFIG_PM
au1xxx_pm_access(LCD_pm_dev);
#endif
struct au1200fb_device *fbdev = info->par;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
return -EINVAL;
......@@ -1461,10 +1431,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
int plane;
int val;
#ifdef CONFIG_PM
au1xxx_pm_access(LCD_pm_dev);
#endif
plane = fbinfo2index(info);
print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
......@@ -1536,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = {
.fb_set_par = au1200fb_fb_set_par,
.fb_setcolreg = au1200fb_fb_setcolreg,
.fb_blank = au1200fb_fb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
.fb_read = fb_sys_read,
.fb_write = fb_sys_write,
.fb_sync = NULL,
.fb_ioctl = au1200fb_ioctl,
.fb_mmap = au1200fb_fb_mmap,
......@@ -1561,10 +1529,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id)
static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
{
struct fb_info *fbi = &fbdev->fb_info;
struct fb_info *fbi = fbdev->fb_info;
int bpp;
memset(fbi, 0, sizeof(struct fb_info));
fbi->fbops = &au1200fb_fb_ops;
bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
......@@ -1623,24 +1590,36 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
/* AU1200 LCD controller device driver */
static int au1200fb_drv_probe(struct platform_device *dev)
static int __devinit au1200fb_drv_probe(struct platform_device *dev)
{
struct au1200fb_device *fbdev;
struct fb_info *fbi = NULL;
unsigned long page;
int bpp, plane, ret;
int bpp, plane, ret, irq;
if (!dev)
return -EINVAL;
/* shut gcc up */
ret = 0;
fbdev = NULL;
/* Kickstart the panel */
au1200_setpanel(panel);
for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
for (plane = 0; plane < device_count; ++plane) {
bpp = winbpp(win->w[plane].mode_winctrl1);
if (win->w[plane].xres == 0)
win->w[plane].xres = panel->Xres;
if (win->w[plane].yres == 0)
win->w[plane].yres = panel->Yres;
fbdev = &_au1200fb_devices[plane];
memset(fbdev, 0, sizeof(struct au1200fb_device));
fbi = framebuffer_alloc(sizeof(struct au1200fb_device),
&dev->dev);
if (!fbi)
goto failed;
_au1200fb_infos[plane] = fbi;
fbdev = fbi->par;
fbdev->fb_info = fbi;
fbdev->plane = plane;
/* Allocate the framebuffer to the maximum screen size */
......@@ -1673,30 +1652,31 @@ static int au1200fb_drv_probe(struct platform_device *dev)
goto failed;
/* Register new framebuffer */
if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
ret = register_framebuffer(fbi);
if (ret < 0) {
print_err("cannot register new framebuffer");
goto failed;
}
au1200fb_fb_set_par(&fbdev->fb_info);
au1200fb_fb_set_par(fbi);
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
if (plane == 0)
if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
if (fb_prepare_logo(fbi, FB_ROTATE_UR)) {
/* Start display and show logo on boot */
fb_set_cmap(&fbdev->fb_info.cmap,
&fbdev->fb_info);
fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
fb_set_cmap(&fbi->cmap, fbi);
fb_show_logo(fbi, FB_ROTATE_UR);
}
#endif
}
/* Now hook interrupt too */
if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq,
IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) {
irq = platform_get_irq(dev, 0);
ret = request_irq(irq, au1200fb_handle_irq,
IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev);
if (ret) {
print_err("fail to request interrupt line %d (err: %d)",
AU1200_LCD_INT, ret);
irq, ret);
goto failed;
}
......@@ -1705,84 +1685,108 @@ static int au1200fb_drv_probe(struct platform_device *dev)
failed:
/* NOTE: This only does the current plane/window that failed; others are still active */
if (fbdev->fb_mem)
dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
fbdev->fb_mem, fbdev->fb_phys);
if (fbdev->fb_info.cmap.len != 0)
fb_dealloc_cmap(&fbdev->fb_info.cmap);
if (fbdev->fb_info.pseudo_palette)
kfree(fbdev->fb_info.pseudo_palette);
if (fbi) {
if (fbi->cmap.len != 0)
fb_dealloc_cmap(&fbi->cmap);
kfree(fbi->pseudo_palette);
}
if (plane == 0)
free_irq(AU1200_LCD_INT, (void*)dev);
return ret;
}
static int au1200fb_drv_remove(struct platform_device *dev)
static int __devexit au1200fb_drv_remove(struct platform_device *dev)
{
struct au1200fb_device *fbdev;
struct fb_info *fbi;
int plane;
if (!dev)
return -ENODEV;
/* Turn off the panel */
au1200_setpanel(NULL);
for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
{
fbdev = &_au1200fb_devices[plane];
for (plane = 0; plane < device_count; ++plane) {
fbi = _au1200fb_infos[plane];
fbdev = fbi->par;
/* Clean up all probe data */
unregister_framebuffer(&fbdev->fb_info);
unregister_framebuffer(fbi);
if (fbdev->fb_mem)
dma_free_noncoherent(&dev->dev,
PAGE_ALIGN(fbdev->fb_len),
fbdev->fb_mem, fbdev->fb_phys);
if (fbdev->fb_info.cmap.len != 0)
fb_dealloc_cmap(&fbdev->fb_info.cmap);
if (fbdev->fb_info.pseudo_palette)
kfree(fbdev->fb_info.pseudo_palette);
if (fbi->cmap.len != 0)
fb_dealloc_cmap(&fbi->cmap);
kfree(fbi->pseudo_palette);
framebuffer_release(fbi);
_au1200fb_infos[plane] = NULL;
}
free_irq(AU1200_LCD_INT, (void *)dev);
free_irq(platform_get_irq(dev, 0), (void *)dev);
return 0;
}
#ifdef CONFIG_PM
static int au1200fb_drv_suspend(struct platform_device *dev, u32 state)
static int au1200fb_drv_suspend(struct device *dev)
{
/* TODO */
au1200_setpanel(NULL);
lcd->outmask = 0;
au_sync();
return 0;
}
static int au1200fb_drv_resume(struct platform_device *dev)
static int au1200fb_drv_resume(struct device *dev)
{
/* TODO */
struct fb_info *fbi;
int i;
/* Kickstart the panel */
au1200_setpanel(panel);
for (i = 0; i < device_count; i++) {
fbi = _au1200fb_infos[i];
au1200fb_fb_set_par(fbi);
}
return 0;
}
static const struct dev_pm_ops au1200fb_pmops = {
.suspend = au1200fb_drv_suspend,
.resume = au1200fb_drv_resume,
.freeze = au1200fb_drv_suspend,
.thaw = au1200fb_drv_resume,
};
#define AU1200FB_PMOPS (&au1200fb_pmops)
#else
#define AU1200FB_PMOPS NULL
#endif /* CONFIG_PM */
static struct platform_driver au1200fb_driver = {
.driver = {
.name = "au1200-lcd",
.owner = THIS_MODULE,
.name = "au1200-lcd",
.owner = THIS_MODULE,
.pm = AU1200FB_PMOPS,
},
.probe = au1200fb_drv_probe,
.remove = au1200fb_drv_remove,
#ifdef CONFIG_PM
.suspend = au1200fb_drv_suspend,
.resume = au1200fb_drv_resume,
#endif
.remove = __devexit_p(au1200fb_drv_remove),
};
/*-------------------------------------------------------------------------*/
/* Kernel driver */
static void au1200fb_setup(void)
static int au1200fb_setup(void)
{
char* options = NULL;
char* this_opt;
char *options = NULL;
char *this_opt, *endptr;
int num_panels = ARRAY_SIZE(known_lcd_panels);
int panel_idx = -1;
......@@ -1827,70 +1831,42 @@ static void au1200fb_setup(void)
nohwcursor = 1;
}
/* Unsupported option */
else {
print_warn("Unsupported option \"%s\"", this_opt);
else if (strncmp(this_opt, "devices:", 8) == 0) {
this_opt += 8;
device_count = simple_strtol(this_opt,
&endptr, 0);
if ((device_count < 0) ||
(device_count > MAX_DEVICE_COUNT))
device_count = MAX_DEVICE_COUNT;
}
}
}
}
#ifdef CONFIG_PM
static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
au1xxx_request_t request, void *data) {
int retval = -1;
unsigned int d = 0;
unsigned int brightness = 0;
if (request == AU1XXX_PM_SLEEP) {
board_au1200fb_panel_shutdown();
}
else if (request == AU1XXX_PM_WAKEUP) {
if(dev->prev_state == SLEEP_STATE)
{
int plane;
au1200_setpanel(panel);
for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
struct au1200fb_device *fbdev;
fbdev = &_au1200fb_devices[plane];
au1200fb_fb_set_par(&fbdev->fb_info);
else if (strncmp(this_opt, "wincfg:", 7) == 0) {
this_opt += 7;
window_index = simple_strtol(this_opt,
&endptr, 0);
if ((window_index < 0) ||
(window_index >= ARRAY_SIZE(windows)))
window_index = DEFAULT_WINDOW_INDEX;
}
}
d = *((unsigned int*)data);
if(d <=10) brightness = 26;
else if(d<=20) brightness = 51;
else if(d<=30) brightness = 77;
else if(d<=40) brightness = 102;
else if(d<=50) brightness = 128;
else if(d<=60) brightness = 153;
else if(d<=70) brightness = 179;
else if(d<=80) brightness = 204;
else if(d<=90) brightness = 230;
else brightness = 255;
set_brightness(brightness);
} else if (request == AU1XXX_PM_GETSTATUS) {
return dev->cur_state;
} else if (request == AU1XXX_PM_ACCESS) {
if (dev->cur_state != SLEEP_STATE)
return retval;
else {
au1200_setpanel(panel);
else if (strncmp(this_opt, "off", 3) == 0)
return 1;
/* Unsupported option */
else {
print_warn("Unsupported option \"%s\"", this_opt);
}
}
} else if (request == AU1XXX_PM_IDLE) {
} else if (request == AU1XXX_PM_CLEANUP) {
}
return retval;
return 0;
}
#endif
static int __init au1200fb_init(void)
{
print_info("" DRIVER_DESC "");
/* Setup driver with options */
au1200fb_setup();
if (au1200fb_setup())
return -ENODEV;
/* Point to the panel selected */
panel = &known_lcd_panels[panel_index];
......@@ -1899,17 +1875,6 @@ static int __init au1200fb_init(void)
printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
/* Kickstart the panel, the framebuffers/windows come soon enough */
au1200_setpanel(panel);
#ifdef CONFIG_PM
LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
if ( LCD_pm_dev == NULL)
printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
else
printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
#endif
return platform_driver_register(&au1200fb_driver);
}
......
......@@ -7,7 +7,6 @@
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pm.h>
......
......@@ -7,7 +7,6 @@
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pm.h>
......
......@@ -32,11 +32,11 @@
#define CARMINEFB_DEFAULT_VIDEO_MODE 1
static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
module_param(fb_mode, uint, 444);
module_param(fb_mode, uint, 0444);
MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
static char *fb_mode_str;
module_param(fb_mode_str, charp, 444);
module_param(fb_mode_str, charp, 0444);
MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
/*
......@@ -46,7 +46,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
* 0b010 Display 1
*/
static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
module_param(fb_displays, int, 444);
module_param(fb_displays, int, 0444);
MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
struct carmine_hw {
......
......@@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
/*
* Parse user speficied options (`video=controlfb:')
* Parse user specified options (`video=controlfb:')
*/
static void __init control_setup(char *options)
{
......
......@@ -35,6 +35,9 @@
#define DRIVER_NAME "da8xx_lcdc"
#define LCD_VERSION_1 1
#define LCD_VERSION_2 2
/* LCD Status Register */
#define LCD_END_OF_FRAME1 BIT(9)
#define LCD_END_OF_FRAME0 BIT(8)
......@@ -49,7 +52,9 @@
#define LCD_DMA_BURST_4 0x2
#define LCD_DMA_BURST_8 0x3
#define LCD_DMA_BURST_16 0x4
#define LCD_END_OF_FRAME_INT_ENA BIT(2)
#define LCD_V1_END_OF_FRAME_INT_ENA BIT(2)
#define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8)
#define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9)
#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0)
/* LCD Control Register */
......@@ -65,12 +70,18 @@
#define LCD_MONO_8BIT_MODE BIT(9)
#define LCD_RASTER_ORDER BIT(8)
#define LCD_TFT_MODE BIT(7)
#define LCD_UNDERFLOW_INT_ENA BIT(6)
#define LCD_PL_ENABLE BIT(4)
#define LCD_V1_UNDERFLOW_INT_ENA BIT(6)
#define LCD_V2_UNDERFLOW_INT_ENA BIT(5)
#define LCD_V1_PL_INT_ENA BIT(4)
#define LCD_V2_PL_INT_ENA BIT(6)
#define LCD_MONOCHROME_MODE BIT(1)
#define LCD_RASTER_ENABLE BIT(0)
#define LCD_TFT_ALT_ENABLE BIT(23)
#define LCD_STN_565_ENABLE BIT(24)
#define LCD_V2_DMA_CLK_EN BIT(2)
#define LCD_V2_LIDD_CLK_EN BIT(1)
#define LCD_V2_CORE_CLK_EN BIT(0)
#define LCD_V2_LPP_B10 26
/* LCD Raster Timing 2 Register */
#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
......@@ -82,6 +93,7 @@
#define LCD_INVERT_FRAME_CLOCK BIT(20)
/* LCD Block */
#define LCD_PID_REG 0x0
#define LCD_CTRL_REG 0x4
#define LCD_STAT_REG 0x8
#define LCD_RASTER_CTRL_REG 0x28
......@@ -94,6 +106,17 @@
#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C
#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50
/* Interrupt Registers available only in Version 2 */
#define LCD_RAW_STAT_REG 0x58
#define LCD_MASKED_STAT_REG 0x5c
#define LCD_INT_ENABLE_SET_REG 0x60
#define LCD_INT_ENABLE_CLR_REG 0x64
#define LCD_END_OF_INT_IND_REG 0x68
/* Clock registers available only on Version 2 */
#define LCD_CLK_ENABLE_REG 0x6c
#define LCD_CLK_RESET_REG 0x70
#define LCD_NUM_BUFFERS 2
#define WSI_TIMEOUT 50
......@@ -105,6 +128,8 @@
static resource_size_t da8xx_fb_reg_base;
static struct resource *lcdc_regs;
static unsigned int lcd_revision;
static irq_handler_t lcdc_irq_handler;
static inline unsigned int lcdc_read(unsigned int addr)
{
......@@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
u32 end;
u32 reg_ras;
u32 reg_dma;
u32 reg_int;
/* init reg to clear PLM (loading mode) fields */
reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
......@@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
end = par->dma_end;
reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY);
reg_dma |= LCD_END_OF_FRAME_INT_ENA;
if (lcd_revision == LCD_VERSION_1) {
reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA;
} else {
reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
LCD_V2_END_OF_FRAME0_INT_ENA |
LCD_V2_END_OF_FRAME1_INT_ENA;
lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
}
reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
......@@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
end = start + par->palette_sz - 1;
reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY);
reg_ras |= LCD_PL_ENABLE;
if (lcd_revision == LCD_VERSION_1) {
reg_ras |= LCD_V1_PL_INT_ENA;
} else {
reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
LCD_V2_PL_INT_ENA;
lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
}
lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
......@@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width,
static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
{
u32 reg;
u32 reg_int;
reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE |
LCD_MONO_8BIT_MODE |
......@@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg)
}
/* enable additional interrupts here */
reg |= LCD_UNDERFLOW_INT_ENA;
if (lcd_revision == LCD_VERSION_1) {
reg |= LCD_V1_UNDERFLOW_INT_ENA;
} else {
reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
LCD_V2_UNDERFLOW_INT_ENA;
lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
}
lcdc_write(reg, LCD_RASTER_CTRL_REG);
......@@ -511,6 +558,9 @@ static void lcd_reset(struct da8xx_fb_par *par)
/* DMA has to be disabled */
lcdc_write(0, LCD_DMA_CTRL_REG);
lcdc_write(0, LCD_RASTER_CTRL_REG);
if (lcd_revision == LCD_VERSION_2)
lcdc_write(0, LCD_INT_ENABLE_SET_REG);
}
static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
......@@ -523,6 +573,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
/* Configure the LCD clock divisor. */
lcdc_write(LCD_CLK_DIVISOR(div) |
(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
if (lcd_revision == LCD_VERSION_2)
lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
}
static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
......@@ -583,7 +638,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
return 0;
}
static irqreturn_t lcdc_irq_handler(int irq, void *arg)
/* IRQ handler for version 2 of LCDC */
static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
{
struct da8xx_fb_par *par = arg;
u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
u32 reg_int;
if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
lcd_disable_raster();
lcdc_write(stat, LCD_MASKED_STAT_REG);
lcd_enable_raster();
} else if (stat & LCD_PL_LOAD_DONE) {
/*
* Must disable raster before changing state of any control bit.
* And also must be disabled before clearing the PL loading
* interrupt via the following write to the status register. If
* this is done after then one gets multiple PL done interrupts.
*/
lcd_disable_raster();
lcdc_write(stat, LCD_MASKED_STAT_REG);
/* Disable PL completion inerrupt */
reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) |
(LCD_V2_PL_INT_ENA);
lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG);
/* Setup and start data loading mode */
lcd_blit(LOAD_DATA, par);
} else {
lcdc_write(stat, LCD_MASKED_STAT_REG);
if (stat & LCD_END_OF_FRAME0) {
lcdc_write(par->dma_start,
LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
lcdc_write(par->dma_end,
LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
par->vsync_flag = 1;
wake_up_interruptible(&par->vsync_wait);
}
if (stat & LCD_END_OF_FRAME1) {
lcdc_write(par->dma_start,
LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
lcdc_write(par->dma_end,
LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
par->vsync_flag = 1;
wake_up_interruptible(&par->vsync_wait);
}
}
lcdc_write(0, LCD_END_OF_INT_IND_REG);
return IRQ_HANDLED;
}
/* IRQ handler for version 1 LCDC */
static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
{
struct da8xx_fb_par *par = arg;
u32 stat = lcdc_read(LCD_STAT_REG);
......@@ -606,7 +717,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg)
/* Disable PL completion inerrupt */
reg_ras = lcdc_read(LCD_RASTER_CTRL_REG);
reg_ras &= ~LCD_PL_ENABLE;
reg_ras &= ~LCD_V1_PL_INT_ENA;
lcdc_write(reg_ras, LCD_RASTER_CTRL_REG);
/* Setup and start data loading mode */
......@@ -945,6 +1056,22 @@ static int __devinit fb_probe(struct platform_device *device)
if (ret)
goto err_clk_put;
/* Determine LCD IP Version */
switch (lcdc_read(LCD_PID_REG)) {
case 0x4C100102:
lcd_revision = LCD_VERSION_1;
break;
case 0x4F200800:
lcd_revision = LCD_VERSION_2;
break;
default:
dev_warn(&device->dev, "Unknown PID Reg value 0x%x, "
"defaulting to LCD revision 1\n",
lcdc_read(LCD_PID_REG));
lcd_revision = LCD_VERSION_1;
break;
}
for (i = 0, lcdc_info = known_lcd_panels;
i < ARRAY_SIZE(known_lcd_panels);
i++, lcdc_info++) {
......@@ -1085,7 +1212,13 @@ static int __devinit fb_probe(struct platform_device *device)
}
#endif
ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par);
if (lcd_revision == LCD_VERSION_1)
lcdc_irq_handler = lcdc_irq_handler_rev01;
else
lcdc_irq_handler = lcdc_irq_handler_rev02;
ret = request_irq(par->irq, lcdc_irq_handler, 0,
DRIVER_NAME, par);
if (ret)
goto irq_freq;
return 0;
......
......@@ -223,8 +223,7 @@ void fb_deferred_io_cleanup(struct fb_info *info)
int i;
BUG_ON(!fbdefio);
cancel_delayed_work(&info->deferred_work);
flush_scheduled_work();
cancel_delayed_work_sync(&info->deferred_work);
/* clear out the mapping that we setup */
for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
......
......@@ -31,8 +31,6 @@
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/of_platform.h>
#include <sysdev/fsl_soc.h>
#include <linux/fsl-diu-fb.h>
#include "edid.h"
......@@ -183,7 +181,8 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = {
static char *fb_mode = "1024x768-32@60";
static unsigned long default_bpp = 32;
static int monitor_port;
static enum fsl_diu_monitor_port monitor_port;
static char *monitor_string;
#if defined(CONFIG_NOT_COHERENT_CACHE)
static u8 *coherence_data;
......@@ -201,7 +200,7 @@ struct fsl_diu_data {
void *dummy_aoi_virt;
unsigned int irq;
int fb_enabled;
int monitor_port;
enum fsl_diu_monitor_port monitor_port;
};
struct mfb_info {
......@@ -281,6 +280,37 @@ static struct diu_hw dr = {
static struct diu_pool pool;
/**
* fsl_diu_name_to_port - convert a port name to a monitor port enum
*
* Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns
* the enum fsl_diu_monitor_port that corresponds to that string.
*
* For compatibility with older versions, a number ("0", "1", or "2") is also
* supported.
*
* If the string is unknown, DVI is assumed.
*
* If the particular port is not supported by the platform, another port
* (platform-specific) is chosen instead.
*/
static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
{
enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI;
unsigned long val;
if (s) {
if (!strict_strtoul(s, 10, &val) && (val <= 2))
port = (enum fsl_diu_monitor_port) val;
else if (strncmp(s, "lvds", 4) == 0)
port = FSL_DIU_PORT_LVDS;
else if (strncmp(s, "dlvds", 5) == 0)
port = FSL_DIU_PORT_DLVDS;
}
return diu_ops.valid_monitor_port(port);
}
/**
* fsl_diu_alloc - allocate memory for the DIU
* @size: number of bytes to allocate
......@@ -831,9 +861,8 @@ static int fsl_diu_set_par(struct fb_info *info)
}
}
ad->pix_fmt =
diu_ops.get_pixel_format(var->bits_per_pixel,
machine_data->monitor_port);
ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port,
var->bits_per_pixel);
ad->addr = cpu_to_le32(info->fix.smem_start);
ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
var->xres_virtual) | mfbi->g_alpha;
......@@ -1439,16 +1468,12 @@ static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
static ssize_t store_monitor(struct device *device,
struct device_attribute *attr, const char *buf, size_t count)
{
int old_monitor_port;
unsigned long val;
enum fsl_diu_monitor_port old_monitor_port;
struct fsl_diu_data *machine_data =
container_of(attr, struct fsl_diu_data, dev_attr);
if (strict_strtoul(buf, 10, &val))
return 0;
old_monitor_port = machine_data->monitor_port;
machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val);
machine_data->monitor_port = fsl_diu_name_to_port(buf);
if (old_monitor_port != machine_data->monitor_port) {
/* All AOIs need adjust pixel format
......@@ -1468,7 +1493,17 @@ static ssize_t show_monitor(struct device *device,
{
struct fsl_diu_data *machine_data =
container_of(attr, struct fsl_diu_data, dev_attr);
return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
switch (machine_data->monitor_port) {
case FSL_DIU_PORT_DVI:
return sprintf(buf, "DVI\n");
case FSL_DIU_PORT_LVDS:
return sprintf(buf, "Single-link LVDS\n");
case FSL_DIU_PORT_DLVDS:
return sprintf(buf, "Dual-link LVDS\n");
}
return 0;
}
static int __devinit fsl_diu_probe(struct platform_device *ofdev)
......@@ -1692,8 +1727,7 @@ static int __init fsl_diu_setup(char *options)
if (!*opt)
continue;
if (!strncmp(opt, "monitor=", 8)) {
if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2))
monitor_port = val;
monitor_port = fsl_diu_name_to_port(opt + 8);
} else if (!strncmp(opt, "bpp=", 4)) {
if (!strict_strtoul(opt + 4, 10, &val))
default_bpp = val;
......@@ -1746,6 +1780,8 @@ static int __init fsl_diu_init(void)
if (fb_get_options("fslfb", &option))
return -ENODEV;
fsl_diu_setup(option);
#else
monitor_port = fsl_diu_name_to_port(monitor_string);
#endif
printk(KERN_INFO "Freescale DIU driver\n");
......@@ -1812,7 +1848,7 @@ MODULE_PARM_DESC(mode,
"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
module_param_named(bpp, default_bpp, ulong, 0);
MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
module_param_named(monitor, monitor_port, int, 0);
MODULE_PARM_DESC(monitor,
"Specify the monitor port (0, 1 or 2) if supported by the platform");
module_param_named(monitor, monitor_string, charp, 0);
MODULE_PARM_DESC(monitor, "Specify the monitor port "
"(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform");
/*
* Driver for Aeroflex Gaisler SVGACTRL framebuffer device.
*
* 2011 (c) Aeroflex Gaisler AB
*
* Full documentation of the core can be found here:
* http://www.gaisler.com/products/grlib/grip.pdf
*
* 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.
*
* Contributors: Kristoffer Glembo <kristoffer@gaisler.com>
*
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/io.h>
struct grvga_regs {
u32 status; /* 0x00 */
u32 video_length; /* 0x04 */
u32 front_porch; /* 0x08 */
u32 sync_length; /* 0x0C */
u32 line_length; /* 0x10 */
u32 fb_pos; /* 0x14 */
u32 clk_vector[4]; /* 0x18 */
u32 clut; /* 0x20 */
};
struct grvga_par {
struct grvga_regs *regs;
u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */
int clk_sel;
int fb_alloced; /* = 1 if framebuffer is allocated in main memory */
};
static const struct fb_videomode grvga_modedb[] = {
{
/* 640x480 @ 60 Hz */
NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2,
0, FB_VMODE_NONINTERLACED
}, {
/* 800x600 @ 60 Hz */
NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
0, FB_VMODE_NONINTERLACED
}, {
/* 800x600 @ 72 Hz */
NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
0, FB_VMODE_NONINTERLACED
}, {
/* 1024x768 @ 60 Hz */
NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
0, FB_VMODE_NONINTERLACED
}
};
static struct fb_fix_screeninfo grvga_fix __initdata = {
.id = "AG SVGACTRL",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.xpanstep = 0,
.ypanstep = 1,
.ywrapstep = 0,
.accel = FB_ACCEL_NONE,
};
static int grvga_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct grvga_par *par = info->par;
int i;
if (!var->xres)
var->xres = 1;
if (!var->yres)
var->yres = 1;
if (var->bits_per_pixel <= 8)
var->bits_per_pixel = 8;
else if (var->bits_per_pixel <= 16)
var->bits_per_pixel = 16;
else if (var->bits_per_pixel <= 24)
var->bits_per_pixel = 24;
else if (var->bits_per_pixel <= 32)
var->bits_per_pixel = 32;
else
return -EINVAL;
var->xres_virtual = var->xres;
var->yres_virtual = 2*var->yres;
if (info->fix.smem_len) {
if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len)
return -ENOMEM;
}
/* Which clocks that are available can be read out in these registers */
for (i = 0; i <= 3 ; i++) {
if (var->pixclock == par->regs->clk_vector[i])
break;
}
if (i <= 3)
par->clk_sel = i;
else
return -EINVAL;
switch (info->var.bits_per_pixel) {
case 8:
var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */
var->green = (struct fb_bitfield) {0, 8, 0};
var->blue = (struct fb_bitfield) {0, 8, 0};
var->transp = (struct fb_bitfield) {0, 0, 0};
break;
case 16:
var->red = (struct fb_bitfield) {11, 5, 0};
var->green = (struct fb_bitfield) {5, 6, 0};
var->blue = (struct fb_bitfield) {0, 5, 0};
var->transp = (struct fb_bitfield) {0, 0, 0};
break;
case 24:
case 32:
var->red = (struct fb_bitfield) {16, 8, 0};
var->green = (struct fb_bitfield) {8, 8, 0};
var->blue = (struct fb_bitfield) {0, 8, 0};
var->transp = (struct fb_bitfield) {24, 8, 0};
break;
default:
return -EINVAL;
}
return 0;
}
static int grvga_set_par(struct fb_info *info)
{
u32 func = 0;
struct grvga_par *par = info->par;
__raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1),
&par->regs->video_length);
__raw_writel((info->var.lower_margin << 16) | (info->var.right_margin),
&par->regs->front_porch);
__raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len),
&par->regs->sync_length);
__raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) |
(info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1),
&par->regs->line_length);
switch (info->var.bits_per_pixel) {
case 8:
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
func = 1;
break;
case 16:
info->fix.visual = FB_VISUAL_TRUECOLOR;
func = 2;
break;
case 24:
case 32:
info->fix.visual = FB_VISUAL_TRUECOLOR;
func = 3;
break;
default:
return -EINVAL;
}
__raw_writel((par->clk_sel << 6) | (func << 4) | 1,
&par->regs->status);
info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8;
return 0;
}
static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info)
{
struct grvga_par *par;
par = info->par;
if (regno >= 256) /* Size of CLUT */
return -EINVAL;
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
red = CNVT_TOHW(red, info->var.red.length);
green = CNVT_TOHW(green, info->var.green.length);
blue = CNVT_TOHW(blue, info->var.blue.length);
transp = CNVT_TOHW(transp, info->var.transp.length);
#undef CNVT_TOHW
/* In PSEUDOCOLOR we use the hardware CLUT */
if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
__raw_writel((regno << 24) | (red << 16) | (green << 8) | blue,
&par->regs->clut);
/* Truecolor uses the pseudo palette */
else if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 v;
if (regno >= 16)
return -EINVAL;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset) |
(transp << info->var.transp.offset);
((u32 *) (info->pseudo_palette))[regno] = v;
}
return 0;
}
static int grvga_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct grvga_par *par = info->par;
struct fb_fix_screeninfo *fix = &info->fix;
u32 base_addr;
if (var->xoffset != 0)
return -EINVAL;
base_addr = fix->smem_start + (var->yoffset * fix->line_length);
base_addr &= ~3UL;
/* Set framebuffer base address */
__raw_writel(base_addr,
&par->regs->fb_pos);
return 0;
}
static struct fb_ops grvga_ops = {
.owner = THIS_MODULE,
.fb_check_var = grvga_check_var,
.fb_set_par = grvga_set_par,
.fb_setcolreg = grvga_setcolreg,
.fb_pan_display = grvga_pan_display,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit
};
static int __init grvga_parse_custom(char *options,
struct fb_var_screeninfo *screendata)
{
char *this_opt;
int count = 0;
if (!options || !*options)
return -1;
while ((this_opt = strsep(&options, " ")) != NULL) {
if (!*this_opt)
continue;
switch (count) {
case 0:
screendata->pixclock = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 1:
screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 2:
screendata->right_margin = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 3:
screendata->hsync_len = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 4:
screendata->left_margin = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 5:
screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 6:
screendata->lower_margin = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 7:
screendata->vsync_len = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 8:
screendata->upper_margin = simple_strtoul(this_opt, NULL, 0);
count++;
break;
case 9:
screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0);
count++;
break;
default:
return -1;
}
}
screendata->activate = FB_ACTIVATE_NOW;
screendata->vmode = FB_VMODE_NONINTERLACED;
return 0;
}
static int __devinit grvga_probe(struct platform_device *dev)
{
struct fb_info *info;
int retval = -ENOMEM;
unsigned long virtual_start;
unsigned long grvga_fix_addr = 0;
unsigned long physical_start = 0;
unsigned long grvga_mem_size = 0;
struct grvga_par *par = NULL;
char *options = NULL, *mode_opt = NULL;
info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev);
if (!info) {
dev_err(&dev->dev, "framebuffer_alloc failed\n");
return -ENOMEM;
}
/* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>]
*
* If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters
* If address is left out, we allocate memory,
* if size is left out we only allocate enough to support the given mode.
*/
if (fb_get_options("grvga", &options)) {
retval = -ENODEV;
goto err;
}
if (!options || !*options)
options = "640x480-8@60";
while (1) {
char *this_opt = strsep(&options, ",");
if (!this_opt)
break;
if (!strncmp(this_opt, "custom", 6)) {
if (grvga_parse_custom(this_opt, &info->var) < 0) {
dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt);
retval = -EINVAL;
goto err1;
}
} else if (!strncmp(this_opt, "addr", 4))
grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16);
else if (!strncmp(this_opt, "size", 4))
grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0);
else
mode_opt = this_opt;
}
par = info->par;
info->fbops = &grvga_ops;
info->fix = grvga_fix;
info->pseudo_palette = par->color_palette;
info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
info->fix.smem_len = grvga_mem_size;
if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) {
dev_err(&dev->dev, "registers already mapped\n");
retval = -EBUSY;
goto err;
}
par->regs = of_ioremap(&dev->resource[0], 0,
resource_size(&dev->resource[0]),
"grlib-svgactrl regs");
if (!par->regs) {
dev_err(&dev->dev, "failed to map registers\n");
retval = -ENOMEM;
goto err1;
}
retval = fb_alloc_cmap(&info->cmap, 256, 0);
if (retval < 0) {
dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n");
retval = -ENOMEM;
goto err2;
}
if (mode_opt) {
retval = fb_find_mode(&info->var, info, mode_opt,
grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8);
if (!retval || retval == 4) {
retval = -EINVAL;
goto err3;
}
}
if (!grvga_mem_size)
grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8;
if (grvga_fix_addr) {
/* Got framebuffer base address from argument list */
physical_start = grvga_fix_addr;
if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) {
dev_err(&dev->dev, "failed to request memory region\n");
retval = -ENOMEM;
goto err3;
}
virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size);
if (!virtual_start) {
dev_err(&dev->dev, "error mapping framebuffer memory\n");
retval = -ENOMEM;
goto err4;
}
} else { /* Allocate frambuffer memory */
unsigned long page;
virtual_start = (unsigned long) __get_free_pages(GFP_DMA,
get_order(grvga_mem_size));
if (!virtual_start) {
dev_err(&dev->dev,
"unable to allocate framebuffer memory (%lu bytes)\n",
grvga_mem_size);
retval = -ENOMEM;
goto err3;
}
physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE);
/* Set page reserved so that mmap will work. This is necessary
* since we'll be remapping normal memory.
*/
for (page = virtual_start;
page < PAGE_ALIGN(virtual_start + grvga_mem_size);
page += PAGE_SIZE) {
SetPageReserved(virt_to_page(page));
}
par->fb_alloced = 1;
}
memset((unsigned long *) virtual_start, 0, grvga_mem_size);
info->screen_base = (char __iomem *) virtual_start;
info->fix.smem_start = physical_start;
info->fix.smem_len = grvga_mem_size;
dev_set_drvdata(&dev->dev, info);
dev_info(&dev->dev,
"Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n",
info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel,
grvga_mem_size >> 10, info->screen_base);
retval = register_framebuffer(info);
if (retval < 0) {
dev_err(&dev->dev, "failed to register framebuffer\n");
goto err4;
}
__raw_writel(physical_start, &par->regs->fb_pos);
__raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */
&par->regs->status);
return 0;
err4:
dev_set_drvdata(&dev->dev, NULL);
if (grvga_fix_addr) {
release_mem_region(physical_start, grvga_mem_size);
iounmap((void *)virtual_start);
} else
kfree((void *)virtual_start);
err3:
fb_dealloc_cmap(&info->cmap);
err2:
of_iounmap(&dev->resource[0], par->regs,
resource_size(&dev->resource[0]));
err1:
release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]));
err:
framebuffer_release(info);
return retval;
}
static int __devexit grvga_remove(struct platform_device *device)
{
struct fb_info *info = dev_get_drvdata(&device->dev);
struct grvga_par *par = info->par;
if (info) {
unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
of_iounmap(&device->resource[0], par->regs,
resource_size(&device->resource[0]));
release_mem_region(device->resource[0].start, resource_size(&device->resource[0]));
if (!par->fb_alloced) {
release_mem_region(info->fix.smem_start, info->fix.smem_len);
iounmap(info->screen_base);
} else
kfree((void *)info->screen_base);
framebuffer_release(info);
dev_set_drvdata(&device->dev, NULL);
}
return 0;
}
static struct of_device_id svgactrl_of_match[] = {
{
.name = "GAISLER_SVGACTRL",
},
{
.name = "01_063",
},
{},
};
MODULE_DEVICE_TABLE(of, svgactrl_of_match);
static struct platform_driver grvga_driver = {
.driver = {
.name = "grlib-svgactrl",
.owner = THIS_MODULE,
.of_match_table = svgactrl_of_match,
},
.probe = grvga_probe,
.remove = __devexit_p(grvga_remove),
};
static int __init grvga_init(void)
{
return platform_driver_register(&grvga_driver);
}
static void __exit grvga_exit(void)
{
platform_driver_unregister(&grvga_driver);
}
module_init(grvga_init);
module_exit(grvga_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Aeroflex Gaisler");
MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver");
......@@ -421,7 +421,8 @@ int mdp_probe(struct platform_device *pdev)
clk = clk_get(&pdev->dev, "mdp_clk");
if (IS_ERR(clk)) {
printk(KERN_INFO "mdp: failed to get mdp clk");
return PTR_ERR(clk);
ret = PTR_ERR(clk);
goto error_get_clk;
}
ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
......@@ -495,6 +496,7 @@ int mdp_probe(struct platform_device *pdev)
error_device_register:
free_irq(mdp->irq, mdp);
error_request_irq:
error_get_clk:
iounmap(mdp->base);
error_get_irq:
error_ioremap:
......
......@@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
/*
* Parse user speficied options (`video=platinumfb:')
* Parse user specified options (`video=platinumfb:')
*/
static int __init platinumfb_setup(char *options)
{
......
......@@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
#ifndef MODULE
/**
* Parse user speficied options.
* Parse user specified options.
*
* This is, comma-separated options following `video=pm2fb:'.
*/
......
......@@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options)
{
char *this_opt;
/* Parse user speficied options (`video=pm3fb:') */
/* Parse user specified options (`video=pm3fb:') */
if (!options || !*options)
return 0;
......
......@@ -31,8 +31,6 @@
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/miscdevice.h>
......
......@@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
unsigned long val, void *data)
{
struct cpufreq_freqs *freqs = data;
struct s3c2410fb_info *info;
struct fb_info *fbinfo;
long delta_f;
......
......@@ -1505,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = {
.resume = s3_pci_resume,
};
/* Parse user speficied options */
/* Parse user specified options */
#ifndef MODULE
static int __init s3fb_setup(char *options)
......
......@@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device;
*/
int __init xxxfb_setup(char *options)
{
/* Parse user speficied options (`video=xxxfb:') */
/* Parse user specified options (`video=xxxfb:') */
}
#endif /* MODULE */
......
......@@ -48,13 +48,22 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
/*
* There are many DisplayLink-based products, all with unique PIDs. We are able
* to support all volume ones (circa 2009) with a single driver, so we match
* globally on VID. TODO: Probe() needs to detect when we might be running
* "future" chips, and bail on those, so a compatible driver can match.
* There are many DisplayLink-based graphics products, all with unique PIDs.
* So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff)
* We also require a match on SubClass (0x00) and Protocol (0x00),
* which is compatible with all known USB 2.0 era graphics chips and firmware,
* but allows DisplayLink to increment those for any future incompatible chips
*/
static struct usb_device_id id_table[] = {
{.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
{.idVendor = 0x17e9,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS |
USB_DEVICE_ID_MATCH_INT_PROTOCOL,
},
{},
};
MODULE_DEVICE_TABLE(usb, id_table);
......@@ -1613,7 +1622,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
/* We don't register a new USB class. Our client interface is fbdev */
/* allocates framebuffer driver structure, not framebuffer memory */
info = framebuffer_alloc(0, &usbdev->dev);
info = framebuffer_alloc(0, &interface->dev);
if (!info) {
retval = -ENOMEM;
pr_err("framebuffer_alloc failed\n");
......
......@@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info,
/*
* Parse user speficied options (`video=valkyriefb:')
* Parse user specified options (`video=valkyriefb:')
*/
int __init valkyriefb_setup(char *options)
{
......
......@@ -28,6 +28,11 @@
#include <linux/types.h>
#define VIA_PITCH_SIZE (1<<3)
#define VIA_PITCH_MAX 0x3FF8
void via_set_primary_address(u32 addr);
void via_set_secondary_address(u32 addr);
void via_set_primary_pitch(u32 pitch);
......
......@@ -151,7 +151,8 @@ static void viafb_update_fix(struct fb_info *info)
info->fix.visual =
bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
VIA_PITCH_SIZE);
}
static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
......@@ -238,8 +239,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
depth = 24;
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)
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
VIA_PITCH_SIZE);
if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
return -EINVAL;
/* Based on var passed in to calculate the refresh,
......@@ -348,8 +353,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct viafb_par *viapar = info->par;
u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
* (var->bits_per_pixel / 8) + viapar->vram_addr;
u32 vram_addr = viapar->vram_addr
+ var->yoffset * info->fix.line_length
+ var->xoffset * info->var.bits_per_pixel / 8;
DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
if (!viafb_dual_fb) {
......
......@@ -23,7 +23,6 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment