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
This commit is contained in:
commit
d4a7dbfdf1
28 changed files with 1039 additions and 303 deletions
|
@ -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.
|
||||
* p1022ds_valid_monitor_port: set the monitor port for sysfs
|
||||
*/
|
||||
ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
|
||||
enum fsl_diu_monitor_port
|
||||
p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
|
||||
{
|
||||
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
|
||||
*/
|
||||
int p1022ds_set_sysfs_monitor_port(int val)
|
||||
{
|
||||
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)
|
||||
enum fsl_diu_monitor_port
|
||||
mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
|
||||
/* Kickstart the panel */
|
||||
au1200_setpanel(panel);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
else if (strncmp(this_opt, "off", 3) == 0)
|
||||
return 1;
|
||||
/* Unsupported option */
|
||||
else {
|
||||
print_warn("Unsupported option \"%s\"", this_opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
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 (request == AU1XXX_PM_IDLE) {
|
||||
} else if (request == AU1XXX_PM_CLEANUP) {
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
#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");
|
||||
|
||||
|
|
579
drivers/video/grvga.c
Normal file
579
drivers/video/grvga.c
Normal file
|
@ -0,0 +1,579 @@
|
|||
/*
|
||||
* 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>
|
||||
|
|
Loading…
Reference in a new issue