Merge branch 'fbdev-next' of git://github.com/schandinat/linux-2.6

* 'fbdev-next' of git://github.com/schandinat/linux-2.6: (270 commits)
  video: platinumfb: Add __devexit_p at necessary place
  drivers/video: fsl-diu-fb: merge diu_pool into fsl_diu_data
  drivers/video: fsl-diu-fb: merge diu_hw into fsl_diu_data
  drivers/video: fsl-diu-fb: only DIU modes 0 and 1 are supported
  drivers/video: fsl-diu-fb: remove unused panel operating mode support
  drivers/video: fsl-diu-fb: use an enum for the AOI index
  drivers/video: fsl-diu-fb: add several new video modes
  drivers/video: fsl-diu-fb: remove broken screen blanking support
  drivers/video: fsl-diu-fb: move some definitions out of the header file
  drivers/video: fsl-diu-fb: fix some ioctls
  video: da8xx-fb: Increased resolution configuration of revised LCDC IP
  OMAPDSS: picodlp: add missing #include <linux/module.h>
  fb: fix au1100fb bitrot.
  mx3fb: fix NULL pointer dereference in screen blanking.
  video: irq: Remove IRQF_DISABLED
  smscufx: change edid data to u8 instead of char
  OMAPDSS: DISPC: zorder support for DSS overlays
  OMAPDSS: DISPC: VIDEO3 pipeline support
  OMAPDSS/OMAP_VOUT: Fix incorrect OMAP3-alpha compatibility setting
  video/omap: fix build dependencies
  ...

Fix up conflicts in:
 - drivers/staging/xgifb/XGI_main_26.c
	Changes to XGIfb_pan_var()
 - drivers/video/omap/{lcd_apollon.c,lcd_ldp.c,lcd_overo.c}
	Removed (or in the case of apollon.c, merged into the generic
	DSS panel in drivers/video/omap2/displays/panel-generic-dpi.c)
This commit is contained in:
Linus Torvalds 2011-10-30 15:30:01 -07:00
commit acff987d94
163 changed files with 12023 additions and 7620 deletions

View file

@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
|| var->xoffset)
return -EINVAL;
} else {
if (var->xoffset + var->xres > info->var.xres_virtual ||
var->yoffset + var->yres > info->var.yres_virtual)
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
}
info->var.xoffset = var->xoffset;

View file

@ -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
@ -2027,7 +2037,7 @@ config FB_TMIO_ACCELL
config FB_S3C
tristate "Samsung S3C framebuffer support"
depends on FB && S3C_DEV_FB
depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@ -2110,6 +2120,22 @@ config FB_SM501
If unsure, say N.
config FB_SMSCUFX
tristate "SMSC UFX6000/7000 USB Framebuffer support"
depends on FB && USB
select FB_MODE_HELPERS
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
select FB_DEFERRED_IO
---help---
This is a kernel framebuffer driver for SMSC UFX USB devices.
Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000
(USB 3.0) devices.
To compile as a module, choose M here: the module name is smscufx.
config FB_UDL
tristate "Displaylink USB Framebuffer support"
depends on FB && USB

View file

@ -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
@ -127,6 +128,7 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
obj-$(CONFIG_FB_PS3) += ps3fb.o
obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_UDL) += udlfb.o
obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o
obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o

View file

@ -850,9 +850,10 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
u_int y_bottom = var->yoffset;
if (!(var->vmode & FB_VMODE_YWRAP))
y_bottom += var->yres;
y_bottom += info->var.yres;
BUG_ON(y_bottom > var->yres_virtual);
if (y_bottom > info->var.yres_virtual)
return -EINVAL;
acornfb_update_dma(info, var);

View file

@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info
unsigned int offset;
/* Calculate the offset */
if (var->bits_per_pixel == 0) {
offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
if (info->var.bits_per_pixel == 0) {
offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+ (var->xoffset / 2);
offset = offset >> 2;
} else {
offset = (var->yoffset * info->fix.line_length) +
(var->xoffset * var->bits_per_pixel / 8);
offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3);
(var->xoffset * info->var.bits_per_pixel / 8);
offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3);
}
/* Set the offset */

View file

@ -39,7 +39,8 @@
| FBINFO_HWACCEL_YPAN)
static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
struct fb_var_screeninfo *var)
struct fb_var_screeninfo *var,
struct fb_info *info)
{
}
@ -50,14 +51,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
| FBINFO_HWACCEL_YPAN)
static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
struct fb_var_screeninfo *var)
struct fb_var_screeninfo *var,
struct fb_info *info)
{
u32 dma2dcfg;
u32 pixeloff;
pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
dma2dcfg = (info->var.xres_virtual - info->var.xres)
* info->var.bits_per_pixel / 8;
dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
@ -249,14 +252,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info,
unsigned long dma_addr;
dma_addr = (fix->smem_start + var->yoffset * fix->line_length
+ var->xoffset * var->bits_per_pixel / 8);
+ var->xoffset * info->var.bits_per_pixel / 8);
dma_addr &= ~3UL;
/* Set framebuffer DMA base address and pixel offset */
lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
atmel_lcdfb_update_dma2d(sinfo, var);
atmel_lcdfb_update_dma2d(sinfo, var, info);
}
static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)

View file

@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
{
struct radeonfb_info *rinfo = info->par;
if ((var->xoffset + var->xres > var->xres_virtual)
|| (var->yoffset + var->yres > var->yres_virtual))
return -EINVAL;
if ((var->xoffset + info->var.xres > info->var.xres_virtual)
|| (var->yoffset + info->var.yres > info->var.yres_virtual))
return -EINVAL;
if (rinfo->asleep)
return 0;
radeon_fifo_wait(2);
OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)
* var->bits_per_pixel / 8) & ~7);
OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length +
var->xoffset * info->var.bits_per_pixel / 8) & ~7);
return 0;
}

View file

@ -110,12 +110,6 @@ static struct fb_var_screeninfo au1100fb_var __devinitdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
static struct au1100fb_drv_info drv_info;
static int nocursor = 0;
module_param(nocursor, int, 0644);
MODULE_PARM_DESC(nocursor, "cursor enable/disable");
/* fb_blank
* Blank the screen. Depending on the mode, the screen will be
* activated with the backlight color, or desactivated
@ -132,7 +126,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
/* Turn on panel */
fbdev->regs->lcd_control |= LCD_CONTROL_GO;
#ifdef CONFIG_MIPS_PB1100
if (drv_info.panel_idx == 1) {
if (fbdev->panel_idx == 1) {
au_writew(au_readw(PB1100_G_CONTROL)
| (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
PB1100_G_CONTROL);
@ -147,7 +141,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
/* Turn off panel */
fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
#ifdef CONFIG_MIPS_PB1100
if (drv_info.panel_idx == 1) {
if (fbdev->panel_idx == 1) {
au_writew(au_readw(PB1100_G_CONTROL)
& ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD),
PB1100_G_CONTROL);
@ -428,17 +422,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
return 0;
}
/* fb_cursor
* Used to disable cursor drawing...
*/
int au1100fb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
if (nocursor)
return 0;
else
return -EINVAL; /* just to force soft_cursor() call */
}
static struct fb_ops au1100fb_ops =
{
.owner = THIS_MODULE,
@ -450,13 +433,53 @@ static struct fb_ops au1100fb_ops =
.fb_imageblit = cfb_imageblit,
.fb_rotate = au1100fb_fb_rotate,
.fb_mmap = au1100fb_fb_mmap,
.fb_cursor = au1100fb_fb_cursor,
};
/*-------------------------------------------------------------------------*/
/* AU1100 LCD controller device driver */
static int au1100fb_setup(struct au1100fb_device *fbdev)
{
char *this_opt, *options;
int num_panels = ARRAY_SIZE(known_lcd_panels);
if (num_panels <= 0) {
print_err("No LCD panels supported by driver!");
return -ENODEV;
}
if (fb_get_options(DRIVER_NAME, &options))
return -ENODEV;
if (!options)
return -ENODEV;
while ((this_opt = strsep(&options, ",")) != NULL) {
/* Panel option */
if (!strncmp(this_opt, "panel:", 6)) {
int i;
this_opt += 6;
for (i = 0; i < num_panels; i++) {
if (!strncmp(this_opt, known_lcd_panels[i].name,
strlen(this_opt))) {
fbdev->panel = &known_lcd_panels[i];
fbdev->panel_idx = i;
break;
}
}
if (i >= num_panels) {
print_warn("Panel '%s' not supported!", this_opt);
return -ENODEV;
}
}
/* Unsupported option */
else
print_warn("Unsupported option \"%s\"", this_opt);
}
print_info("Panel=%s", fbdev->panel->name);
return 0;
}
static int __devinit au1100fb_drv_probe(struct platform_device *dev)
{
@ -465,22 +488,21 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
unsigned long page;
u32 sys_clksrc;
if (!dev)
return -EINVAL;
/* Allocate new device private */
if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL);
if (!fbdev) {
print_err("fail to allocate device private record");
return -ENOMEM;
}
fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
if (au1100fb_setup(fbdev))
goto failed;
platform_set_drvdata(dev, (void *)fbdev);
/* Allocate region for our registers and map them */
if (!(regs_res = platform_get_resource(to_platform_device(dev),
IORESOURCE_MEM, 0))) {
regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!regs_res) {
print_err("fail to retrieve registers resource");
return -EFAULT;
}
@ -500,13 +522,11 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
print_dbg("Register memory map at %p", fbdev->regs);
print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
/* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len),
fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
&fbdev->fb_phys, GFP_KERNEL);
if (!fbdev->fb_mem) {
print_err("fail to allocate frambuffer (size: %dK))",
@ -525,7 +545,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
page += PAGE_SIZE) {
#if CONFIG_DMA_NONCOHERENT
SetPageReserved(virt_to_page(CAC_ADDR(page)));
SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
#else
SetPageReserved(virt_to_page(page));
#endif
@ -578,7 +598,8 @@ failed:
release_mem_region(fbdev->regs_phys, fbdev->regs_len);
}
if (fbdev->fb_mem) {
dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys);
dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
fbdev->fb_phys);
}
if (fbdev->info.cmap.len != 0) {
fb_dealloc_cmap(&fbdev->info.cmap);
@ -608,7 +629,8 @@ int au1100fb_drv_remove(struct platform_device *dev)
release_mem_region(fbdev->regs_phys, fbdev->regs_len);
dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys);
dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem,
fbdev->fb_phys);
fb_dealloc_cmap(&fbdev->info.cmap);
kfree(fbdev->info.pseudo_palette);
@ -675,101 +697,18 @@ static struct platform_driver au1100fb_driver = {
.resume = au1100fb_drv_resume,
};
/*-------------------------------------------------------------------------*/
/* Kernel driver */
int au1100fb_setup(char *options)
static int __init au1100fb_load(void)
{
char* this_opt;
int num_panels = ARRAY_SIZE(known_lcd_panels);
char* mode = NULL;
int panel_idx = 0;
if (num_panels <= 0) {
print_err("No LCD panels supported by driver!");
return -EFAULT;
}
if (options) {
while ((this_opt = strsep(&options,",")) != NULL) {
/* Panel option */
if (!strncmp(this_opt, "panel:", 6)) {
int i;
this_opt += 6;
for (i = 0; i < num_panels; i++) {
if (!strncmp(this_opt,
known_lcd_panels[i].name,
strlen(this_opt))) {
panel_idx = i;
break;
}
}
if (i >= num_panels) {
print_warn("Panel %s not supported!", this_opt);
}
}
if (!strncmp(this_opt, "nocursor", 8)) {
this_opt += 8;
nocursor = 1;
print_info("Cursor disabled");
}
/* Mode option (only option that start with digit) */
else if (isdigit(this_opt[0])) {
mode = kstrdup(this_opt, GFP_KERNEL);
if (!mode) {
print_err("memory allocation failed");
return -ENOMEM;
}
}
/* Unsupported option */
else {
print_warn("Unsupported option \"%s\"", this_opt);
}
}
}
drv_info.panel_idx = panel_idx;
drv_info.opt_mode = mode;
print_info("Panel=%s Mode=%s",
known_lcd_panels[drv_info.panel_idx].name,
drv_info.opt_mode ? drv_info.opt_mode : "default");
return 0;
}
int __init au1100fb_init(void)
{
char* options;
int ret;
print_info("" DRIVER_DESC "");
memset(&drv_info, 0, sizeof(drv_info));
if (fb_get_options(DRIVER_NAME, &options))
return -ENODEV;
/* Setup driver with options */
ret = au1100fb_setup(options);
if (ret < 0) {
print_err("Fail to setup driver");
return ret;
}
return platform_driver_register(&au1100fb_driver);
}
void __exit au1100fb_cleanup(void)
static void __exit au1100fb_unload(void)
{
platform_driver_unregister(&au1100fb_driver);
kfree(drv_info.opt_mode);
}
module_init(au1100fb_init);
module_exit(au1100fb_cleanup);
module_init(au1100fb_load);
module_exit(au1100fb_unload);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

View file

@ -108,6 +108,7 @@ struct au1100fb_device {
unsigned char* fb_mem; /* FrameBuffer memory map */
size_t fb_len;
dma_addr_t fb_phys;
int panel_idx;
};
/********************************************************************/
@ -364,11 +365,6 @@ static struct au1100fb_panel known_lcd_panels[] =
},
};
struct au1100fb_drv_info {
int panel_idx;
char *opt_mode;
};
/********************************************************************/
/* Inline helpers */

View file

@ -46,18 +46,10 @@
#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"
#define DEBUG 1
#define DEBUG 0
#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
@ -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_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);
}

View file

@ -7,7 +7,6 @@
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pm.h>

View file

@ -7,7 +7,6 @@
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pm.h>

View file

@ -633,7 +633,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
goto out7;
}
if (request_irq(info->irq, bfin_bf54x_irq_error, IRQF_DISABLED,
if (request_irq(info->irq, bfin_bf54x_irq_error, 0,
"PPI ERROR", info) < 0) {
printk(KERN_ERR DRIVER_NAME
": unable to request PPI ERROR IRQ\n");

View file

@ -695,7 +695,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
goto out7;
}
ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED,
ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0,
DRIVER_NAME" PPI ERROR", info);
if (ret < 0) {
dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");

View file

@ -529,7 +529,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
goto out7;
}
ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED,
ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0,
"PPI ERROR", info);
if (ret < 0) {
printk(KERN_ERR DRIVER_NAME

View file

@ -481,7 +481,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
goto out_4;
}
if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED,
if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0,
"PPI ERROR", fbdev) < 0) {
dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
ret = -EFAULT;

View file

@ -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 {

View file

@ -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)
{

View file

@ -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);
@ -413,18 +460,43 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
/* Set the Panel Width */
/* Pixels per line = (PPL + 1)*16 */
/*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/
width &= 0x3f0;
if (lcd_revision == LCD_VERSION_1) {
/*
* 0x3F in bits 4..9 gives max horizontal resolution = 1024
* pixels.
*/
width &= 0x3f0;
} else {
/*
* 0x7F in bits 4..10 gives max horizontal resolution = 2048
* pixels.
*/
width &= 0x7f0;
}
reg = lcdc_read(LCD_RASTER_TIMING_0_REG);
reg &= 0xfffffc00;
reg |= ((width >> 4) - 1) << 4;
if (lcd_revision == LCD_VERSION_1) {
reg |= ((width >> 4) - 1) << 4;
} else {
width = (width >> 4) - 1;
reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3);
}
lcdc_write(reg, LCD_RASTER_TIMING_0_REG);
/* Set the Panel Height */
/* Set bits 9:0 of Lines Per Pixel */
reg = lcdc_read(LCD_RASTER_TIMING_1_REG);
reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00);
lcdc_write(reg, LCD_RASTER_TIMING_1_REG);
/* Set bit 10 of Lines Per Pixel */
if (lcd_revision == LCD_VERSION_2) {
reg = lcdc_read(LCD_RASTER_TIMING_2_REG);
reg |= ((height - 1) & 0x400) << 16;
lcdc_write(reg, LCD_RASTER_TIMING_2_REG);
}
/* Set the Raster Order of the Frame Buffer */
reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
if (raster_order)
@ -511,6 +583,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 +598,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 +663,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 +742,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 */
@ -877,8 +1013,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
start = fix->smem_start +
new_var.yoffset * fix->line_length +
new_var.xoffset * var->bits_per_pixel / 8;
end = start + var->yres * fix->line_length - 1;
new_var.xoffset * fbi->var.bits_per_pixel / 8;
end = start + fbi->var.yres * fix->line_length - 1;
par->dma_start = start;
par->dma_end = end;
}
@ -945,6 +1081,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 +1237,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;

View file

@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var,
|| var->xoffset)
return -EINVAL;
} else {
if (var->xoffset + var->xres > info->var.xres_virtual ||
var->yoffset + var->yres > info->var.yres_virtual)
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
}
info->var.xoffset = var->xoffset;

View file

@ -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) {

View file

@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state)
{
struct fb_event event;
if (!lock_fb_info(info))
return;
event.info = info;
if (state) {
fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state)
info->state = FBINFO_STATE_RUNNING;
fb_notifier_call_chain(FB_EVENT_RESUME, &event);
}
unlock_fb_info(info);
}
/**

View file

@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
return num;
}
static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
int ver, int rev)
{
int xres, yres = 0, refresh, ratio, i;
@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
ratio = (block[1] & 0xc0) >> 6;
switch (ratio) {
case 0:
yres = xres;
/* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
if (ver < 1 || (ver == 1 && rev < 3))
yres = xres;
else
yres = (xres * 10)/16;
break;
case 1:
yres = (xres * 3)/4;
@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
}
static int get_dst_timing(unsigned char *block,
struct fb_videomode *mode)
struct fb_videomode *mode, int ver, int rev)
{
int j, num = 0;
for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
num += get_std_timing(block, &mode[num]);
num += get_std_timing(block, &mode[num], ver, rev);
return num;
}
@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
struct fb_videomode *mode, *m;
unsigned char *block;
int num = 0, i, first = 1;
int ver, rev;
ver = edid[EDID_STRUCT_VERSION];
rev = edid[EDID_STRUCT_REVISION];
mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
if (mode == NULL)
@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
DPRINTK(" Standard Timings\n");
block = edid + STD_TIMING_DESCRIPTIONS_START;
for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
num += get_std_timing(block, &mode[num]);
num += get_std_timing(block, &mode[num], ver, rev);
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
num += get_dst_timing(block + 5, &mode[num]);
num += get_dst_timing(block + 5, &mode[num], ver, rev);
}
/* Yikes, EDID data is totally useless */

View file

@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device,
state = simple_strtoul(buf, &last, 0);
if (!lock_fb_info(fb_info))
return -ENODEV;
console_lock();
fb_set_suspend(fb_info, (int)state);
console_unlock();
unlock_fb_info(fb_info);
return count;
}

File diff suppressed because it is too large Load diff

View file

@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
static int g364fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
if (var->xoffset || var->yoffset + var->yres > var->yres_virtual)
if (var->xoffset ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
*(unsigned int *) TOP_REG = var->yoffset * var->xres;
*(unsigned int *) TOP_REG = var->yoffset * info->var.xres;
return 0;
}

579
drivers/video/grvga.c Normal file
View 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");

View file

@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var,
if (var->xoffset & 7)
return -EINVAL;
if (var->xoffset + var->xres > var->xres_virtual ||
var->yoffset + var->yres > var->yres_virtual)
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset);

View file

@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var,
var->xoffset)
return -EINVAL;
} else {
if (var->xoffset + var->xres > info->var.xres_virtual
|| var->yoffset + var->yres > info->var.yres_virtual
if (var->xoffset + info->var.xres > info->var.xres_virtual
|| var->yoffset + info->var.yres > info->var.yres_virtual
|| var->yoffset % 8)
return -EINVAL;
}

View file

@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
{
struct imstt_par *par = info->par;
__u32 off = var->yoffset * (info->fix.line_length >> 3)
+ ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
+ ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3);
write_reg_le32(par->dc_regs, SSR, off);
}

View file

@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
xoffset = ROUND_DOWN_TO(var->xoffset, 8);
yoffset = var->yoffset;
if ((xoffset + var->xres > var->xres_virtual) ||
(yoffset + var->yres > var->yres_virtual))
if ((xoffset + info->var.xres > info->var.xres_virtual) ||
(yoffset + info->var.yres > info->var.yres_virtual))
return -EINVAL;
offset = (yoffset * dinfo->pitch) +
(xoffset * var->bits_per_pixel) / 8;
(xoffset * info->var.bits_per_pixel) / 8;
offset += dinfo->fb.offset << 12;

View file

@ -23,7 +23,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap)
u32 reg;
do {
udelay(1);
udelay(10);
reg = inreg(i2c, GC_I2C_BCR);
if (reg & (I2C_INT | I2C_BER))
break;

View file

@ -278,7 +278,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var,
reg = pack(var->yoffset, var->xoffset);
outreg(disp, GC_L0WY_L0WX, reg);
reg = pack(var->yres_virtual, var->xres_virtual);
reg = pack(info->var.yres_virtual, info->var.xres_virtual);
outreg(disp, GC_L0WH_L0WW, reg);
return 0;
}
@ -737,7 +737,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
if (mb862xx_gdc_init(par))
goto io_unmap;
if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED,
if (request_irq(par->irq, mb862xx_intr, 0,
DRV_NAME, (void *)par)) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;
@ -1073,7 +1073,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
if (mb862xx_pci_gdc_init(par))
goto io_unmap;
if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED,
if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
DRV_NAME, (void *)par)) {
dev_err(dev, "Cannot request irq\n");
goto io_unmap;

View file

@ -491,55 +491,56 @@ EXPORT_SYMBOL(vesa_modes);
static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
const struct fb_videomode *mode, unsigned int bpp)
{
int err = 0;
int err = 0;
DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname",
mode->xres, mode->yres, bpp, mode->refresh);
var->xres = mode->xres;
var->yres = mode->yres;
var->xres_virtual = mode->xres;
var->yres_virtual = mode->yres;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = bpp;
var->activate |= FB_ACTIVATE_TEST;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
var->hsync_len = mode->hsync_len;
var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode;
if (info->fbops->fb_check_var)
err = info->fbops->fb_check_var(var, info);
var->activate &= ~FB_ACTIVATE_TEST;
return err;
DPRINTK("Trying mode %s %dx%d-%d@%d\n",
mode->name ? mode->name : "noname",
mode->xres, mode->yres, bpp, mode->refresh);
var->xres = mode->xres;
var->yres = mode->yres;
var->xres_virtual = mode->xres;
var->yres_virtual = mode->yres;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = bpp;
var->activate |= FB_ACTIVATE_TEST;
var->pixclock = mode->pixclock;
var->left_margin = mode->left_margin;
var->right_margin = mode->right_margin;
var->upper_margin = mode->upper_margin;
var->lower_margin = mode->lower_margin;
var->hsync_len = mode->hsync_len;
var->vsync_len = mode->vsync_len;
var->sync = mode->sync;
var->vmode = mode->vmode;
if (info->fbops->fb_check_var)
err = info->fbops->fb_check_var(var, info);
var->activate &= ~FB_ACTIVATE_TEST;
return err;
}
/**
* fb_find_mode - finds a valid video mode
* @var: frame buffer user defined part of display
* @info: frame buffer info structure
* @mode_option: string video mode to find
* @db: video mode database
* @dbsize: size of @db
* @default_mode: default video mode to fall back to
* @default_bpp: default color depth in bits per pixel
* fb_find_mode - finds a valid video mode
* @var: frame buffer user defined part of display
* @info: frame buffer info structure
* @mode_option: string video mode to find
* @db: video mode database
* @dbsize: size of @db
* @default_mode: default video mode to fall back to
* @default_bpp: default color depth in bits per pixel
*
* Finds a suitable video mode, starting with the specified mode
* in @mode_option with fallback to @default_mode. If
* @default_mode fails, all modes in the video mode database will
* be tried.
* Finds a suitable video mode, starting with the specified mode
* in @mode_option with fallback to @default_mode. If
* @default_mode fails, all modes in the video mode database will
* be tried.
*
* Valid mode specifiers for @mode_option:
* Valid mode specifiers for @mode_option:
*
* <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
* <name>[-<bpp>][@<refresh>]
* <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
* <name>[-<bpp>][@<refresh>]
*
* with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
* <name> a string.
* with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
* <name> a string.
*
* If 'M' is present after yres (and before refresh/bpp if present),
* the function will compute the timings using VESA(tm) Coordinated
@ -551,12 +552,12 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
*
* 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
*
* NOTE: The passed struct @var is _not_ cleared! This allows you
* to supply values for e.g. the grayscale and accel_flags fields.
* NOTE: The passed struct @var is _not_ cleared! This allows you
* to supply values for e.g. the grayscale and accel_flags fields.
*
* Returns zero for failure, 1 if using specified @mode_option,
* 2 if using specified @mode_option with an ignored refresh rate,
* 3 if default mode is used, 4 if fall back to any valid mode.
* Returns zero for failure, 1 if using specified @mode_option,
* 2 if using specified @mode_option with an ignored refresh rate,
* 3 if default mode is used, 4 if fall back to any valid mode.
*
*/
@ -566,198 +567,203 @@ int fb_find_mode(struct fb_var_screeninfo *var,
const struct fb_videomode *default_mode,
unsigned int default_bpp)
{
int i;
int i;
/* Set up defaults */
if (!db) {
db = modedb;
dbsize = ARRAY_SIZE(modedb);
}
if (!default_mode)
default_mode = &db[0];
if (!default_bpp)
default_bpp = 8;
/* Did the user specify a video mode? */
if (!mode_option)
mode_option = fb_mode_option;
if (mode_option) {
const char *name = mode_option;
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
u32 best, diff, tdiff;
for (i = namelen-1; i >= 0; i--) {
switch (name[i]) {
case '@':
namelen = i;
if (!refresh_specified && !bpp_specified &&
!yres_specified) {
refresh = simple_strtol(&name[i+1], NULL, 10);
refresh_specified = 1;
if (cvt || rb)
cvt = 0;
} else
goto done;
break;
case '-':
namelen = i;
if (!bpp_specified && !yres_specified) {
bpp = simple_strtol(&name[i+1], NULL, 10);
bpp_specified = 1;
if (cvt || rb)
cvt = 0;
} else
goto done;
break;
case 'x':
if (!yres_specified) {
yres = simple_strtol(&name[i+1], NULL, 10);
yres_specified = 1;
} else
goto done;
break;
case '0' ... '9':
break;
case 'M':
if (!yres_specified)
cvt = 1;
break;
case 'R':
if (!cvt)
rb = 1;
break;
case 'm':
if (!cvt)
margins = 1;
break;
case 'i':
if (!cvt)
interlace = 1;
break;
default:
goto done;
}
}
if (i < 0 && yres_specified) {
xres = simple_strtol(name, NULL, 10);
res_specified = 1;
}
done:
if (cvt) {
struct fb_videomode cvt_mode;
int ret;
DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
(refresh) ? refresh : 60, (rb) ? " reduced blanking" :
"", (margins) ? " with margins" : "", (interlace) ?
" interlaced" : "");
memset(&cvt_mode, 0, sizeof(cvt_mode));
cvt_mode.xres = xres;
cvt_mode.yres = yres;
cvt_mode.refresh = (refresh) ? refresh : 60;
if (interlace)
cvt_mode.vmode |= FB_VMODE_INTERLACED;
else
cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
DPRINTK("modedb CVT: CVT mode ok\n");
return 1;
}
DPRINTK("CVT mode invalid, getting mode from database\n");
/* Set up defaults */
if (!db) {
db = modedb;
dbsize = ARRAY_SIZE(modedb);
}
DPRINTK("Trying specified video mode%s %ix%i\n",
refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
if (!default_mode)
default_mode = &db[0];
if (!refresh_specified) {
/*
* If the caller has provided a custom mode database and a
* valid monspecs structure, we look for the mode with the
* highest refresh rate. Otherwise we play it safe it and
* try to find a mode with a refresh rate closest to the
* standard 60 Hz.
*/
if (db != modedb &&
info->monspecs.vfmin && info->monspecs.vfmax &&
info->monspecs.hfmin && info->monspecs.hfmax &&
info->monspecs.dclkmax) {
refresh = 1000;
} else {
refresh = 60;
if (!default_bpp)
default_bpp = 8;
/* Did the user specify a video mode? */
if (!mode_option)
mode_option = fb_mode_option;
if (mode_option) {
const char *name = mode_option;
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
int margins = 0;
u32 best, diff, tdiff;
for (i = namelen-1; i >= 0; i--) {
switch (name[i]) {
case '@':
namelen = i;
if (!refresh_specified && !bpp_specified &&
!yres_specified) {
refresh = simple_strtol(&name[i+1], NULL,
10);
refresh_specified = 1;
if (cvt || rb)
cvt = 0;
} else
goto done;
break;
case '-':
namelen = i;
if (!bpp_specified && !yres_specified) {
bpp = simple_strtol(&name[i+1], NULL,
10);
bpp_specified = 1;
if (cvt || rb)
cvt = 0;
} else
goto done;
break;
case 'x':
if (!yres_specified) {
yres = simple_strtol(&name[i+1], NULL,
10);
yres_specified = 1;
} else
goto done;
break;
case '0' ... '9':
break;
case 'M':
if (!yres_specified)
cvt = 1;
break;
case 'R':
if (!cvt)
rb = 1;
break;
case 'm':
if (!cvt)
margins = 1;
break;
case 'i':
if (!cvt)
interlace = 1;
break;
default:
goto done;
}
}
}
if (i < 0 && yres_specified) {
xres = simple_strtol(name, NULL, 10);
res_specified = 1;
}
done:
if (cvt) {
struct fb_videomode cvt_mode;
int ret;
diff = -1;
best = -1;
for (i = 0; i < dbsize; i++) {
if ((name_matches(db[i], name, namelen) ||
(res_specified && res_matches(db[i], xres, yres))) &&
!fb_try_mode(var, info, &db[i], bpp)) {
if (refresh_specified && db[i].refresh == refresh) {
DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
(refresh) ? refresh : 60,
(rb) ? " reduced blanking" : "",
(margins) ? " with margins" : "",
(interlace) ? " interlaced" : "");
memset(&cvt_mode, 0, sizeof(cvt_mode));
cvt_mode.xres = xres;
cvt_mode.yres = yres;
cvt_mode.refresh = (refresh) ? refresh : 60;
if (interlace)
cvt_mode.vmode |= FB_VMODE_INTERLACED;
else
cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
DPRINTK("modedb CVT: CVT mode ok\n");
return 1;
}
DPRINTK("CVT mode invalid, getting mode from database\n");
}
DPRINTK("Trying specified video mode%s %ix%i\n",
refresh_specified ? "" : " (ignoring refresh rate)",
xres, yres);
if (!refresh_specified) {
/*
* If the caller has provided a custom mode database and
* a valid monspecs structure, we look for the mode with
* the highest refresh rate. Otherwise we play it safe
* it and try to find a mode with a refresh rate closest
* to the standard 60 Hz.
*/
if (db != modedb &&
info->monspecs.vfmin && info->monspecs.vfmax &&
info->monspecs.hfmin && info->monspecs.hfmax &&
info->monspecs.dclkmax) {
refresh = 1000;
} else {
refresh = 60;
}
}
diff = -1;
best = -1;
for (i = 0; i < dbsize; i++) {
if ((name_matches(db[i], name, namelen) ||
(res_specified && res_matches(db[i], xres, yres))) &&
!fb_try_mode(var, info, &db[i], bpp)) {
if (refresh_specified && db[i].refresh == refresh)
return 1;
if (abs(db[i].refresh - refresh) < diff) {
diff = abs(db[i].refresh - refresh);
best = i;
}
}
}
}
if (best != -1) {
fb_try_mode(var, info, &db[best], bpp);
return (refresh_specified) ? 2 : 1;
}
if (best != -1) {
fb_try_mode(var, info, &db[best], bpp);
return (refresh_specified) ? 2 : 1;
}
diff = 2 * (xres + yres);
best = -1;
DPRINTK("Trying best-fit modes\n");
for (i = 0; i < dbsize; i++) {
DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
if (!fb_try_mode(var, info, &db[i], bpp)) {
tdiff = abs(db[i].xres - xres) +
abs(db[i].yres - yres);
diff = 2 * (xres + yres);
best = -1;
DPRINTK("Trying best-fit modes\n");
for (i = 0; i < dbsize; i++) {
DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres);
if (!fb_try_mode(var, info, &db[i], bpp)) {
tdiff = abs(db[i].xres - xres) +
abs(db[i].yres - yres);
/*
* Penalize modes with resolutions smaller
* than requested.
*/
if (xres > db[i].xres || yres > db[i].yres)
tdiff += xres + yres;
/*
* Penalize modes with resolutions smaller
* than requested.
*/
if (xres > db[i].xres || yres > db[i].yres)
tdiff += xres + yres;
if (diff > tdiff) {
diff = tdiff;
best = i;
if (diff > tdiff) {
diff = tdiff;
best = i;
}
}
}
if (best != -1) {
fb_try_mode(var, info, &db[best], bpp);
return 5;
}
}
if (best != -1) {
fb_try_mode(var, info, &db[best], bpp);
return 5;
}
}
DPRINTK("Trying default video mode\n");
if (!fb_try_mode(var, info, default_mode, default_bpp))
return 3;
DPRINTK("Trying default video mode\n");
if (!fb_try_mode(var, info, default_mode, default_bpp))
return 3;
DPRINTK("Trying all modes\n");
for (i = 0; i < dbsize; i++)
if (!fb_try_mode(var, info, &db[i], default_bpp))
return 4;
DPRINTK("Trying all modes\n");
for (i = 0; i < dbsize; i++)
if (!fb_try_mode(var, info, &db[i], default_bpp))
return 4;
DPRINTK("No valid mode found\n");
return 0;
DPRINTK("No valid mode found\n");
return 0;
}
/**

View file

@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev)
mddi->int_enable = 0;
mddi_writel(mddi->int_enable, INTEN);
ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi",
ret = request_irq(mddi->irq, mddi_isr, 0, "mddi",
&mddi->client_data);
if (ret) {
printk(KERN_ERR "mddi: failed to request enable irq!\n");

View file

@ -421,10 +421,11 @@ 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);
ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
if (ret)
goto error_request_irq;
disable_irq(mdp->irq);
@ -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:

View file

@ -382,6 +382,9 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
uint32_t enabled;
unsigned long flags;
if (mx3_fbi->txd == NULL)
return;
spin_lock_irqsave(&mx3fb->lock, flags);
enabled = sdc_fb_uninit(mx3_fbi);
@ -986,9 +989,19 @@ static void __blank(int blank, struct fb_info *fbi)
{
struct mx3fb_info *mx3_fbi = fbi->par;
struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
int was_blank = mx3_fbi->blank;
mx3_fbi->blank = blank;
/* Attention!
* Do not call sdc_disable_channel() for a channel that is disabled
* already! This will result in a kernel NULL pointer dereference
* (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are
* handled equally by this driver.
*/
if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK)
return;
switch (blank) {
case FB_BLANK_POWERDOWN:
case FB_BLANK_VSYNC_SUSPEND:
@ -1062,15 +1075,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var,
y_bottom = var->yoffset;
if (!(var->vmode & FB_VMODE_YWRAP))
y_bottom += var->yres;
y_bottom += fbi->var.yres;
if (y_bottom > fbi->var.yres_virtual)
return -EINVAL;
mutex_lock(&mx3_fbi->mutex);
offset = (var->yoffset * var->xres_virtual + var->xoffset) *
(var->bits_per_pixel / 8);
offset = var->yoffset * fbi->fix.line_length
+ var->xoffset * (fbi->var.bits_per_pixel / 8);
base = fbi->fix.smem_start + offset;
dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",

View file

@ -39,6 +39,7 @@
* the required value in the imx_fb_videomode structure.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/clk.h>

View file

@ -1185,8 +1185,8 @@ static int neofb_pan_display(struct fb_var_screeninfo *var,
DBG("neofb_update_start");
Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;
Base *= (var->bits_per_pixel + 7) / 8;
Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
Base *= (info->var.bits_per_pixel + 7) / 8;
neoUnlock();

View file

@ -39,7 +39,6 @@
#include <mach/regs-clock.h>
#include <mach/regs-ldm.h>
#include <mach/fb.h>
#include <mach/clkdev.h>
#include "nuc900fb.h"
@ -588,7 +587,7 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev)
fbinfo->flags = FBINFO_FLAG_DEFAULT;
fbinfo->pseudo_palette = &fbi->pseudo_pal;
ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED,
ret = request_irq(irq, nuc900fb_irqhandler, 0,
pdev->name, fbinfo);
if (ret) {
dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",

View file

@ -9,35 +9,6 @@ config FB_OMAP
help
Frame buffer driver for OMAP based boards.
config FB_OMAP_LCD_VGA
bool "Use LCD in VGA mode"
depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP
help
Set LCD resolution as VGA (640 X 480).
Default resolution without this option is QVGA(320 X 240).
Please take a look at drivers/video/omap/lcd_ldp.c file
for lcd driver code.
choice
depends on FB_OMAP && MACH_OVERO
prompt "Screen resolution"
default FB_OMAP_079M3R
help
Selected desired screen resolution
config FB_OMAP_031M3R
boolean "640 x 480 @ 60 Hz Reduced blanking"
config FB_OMAP_048M3R
boolean "800 x 600 @ 60 Hz Reduced blanking"
config FB_OMAP_079M3R
boolean "1024 x 768 @ 60 Hz Reduced blanking"
config FB_OMAP_092M9R
boolean "1280 x 720 @ 60 Hz Reduced blanking"
endchoice
config FB_OMAP_LCDC_EXTERNAL
bool "External LCD controller support"
depends on FB_OMAP

View file

@ -17,7 +17,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o
objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o
objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o
objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o
@ -26,14 +25,7 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o
objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o
objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o
objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o
objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o
objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o
objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o
objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o
objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o
objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o
omapfb-objs := $(objs-yy)

View file

@ -1,203 +0,0 @@
/*
* LCD panel support for the TI 2430SDP board
*
* Copyright (C) 2007 MontaVista
* Author: Hunyue Yau <hyau@mvista.com>
*
* Derived from drivers/video/omap/lcd-apollon.c
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/i2c/twl.h>
#include <plat/mux.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91
#define SDP2430_LCD_PANEL_ENABLE_GPIO 154
#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24
#define SDP3430_LCD_PANEL_ENABLE_GPIO 28
static unsigned backlight_gpio;
static unsigned enable_gpio;
#define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */
#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
#define ENABLE_VAUX2_DEDICATED 0x09
#define ENABLE_VAUX2_DEV_GRP 0x20
#define ENABLE_VAUX3_DEDICATED 0x03
#define ENABLE_VAUX3_DEV_GRP 0x20
#define ENABLE_VPLL2_DEDICATED 0x05
#define ENABLE_VPLL2_DEV_GRP 0xE0
#define TWL4030_VPLL2_DEV_GRP 0x33
#define TWL4030_VPLL2_DEDICATED 0x36
#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
static int sdp2430_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
if (machine_is_omap_3430sdp()) {
enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO;
backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO;
} else {
enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO;
backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO;
}
gpio_request(enable_gpio, "LCD enable"); /* LCD panel */
gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */
gpio_direction_output(enable_gpio, 0);
gpio_direction_output(backlight_gpio, 0);
return 0;
}
static void sdp2430_panel_cleanup(struct lcd_panel *panel)
{
gpio_free(backlight_gpio);
gpio_free(enable_gpio);
}
static int sdp2430_panel_enable(struct lcd_panel *panel)
{
u8 ded_val, ded_reg;
u8 grp_val, grp_reg;
if (machine_is_omap_3430sdp()) {
ded_reg = TWL4030_VAUX3_DEDICATED;
ded_val = ENABLE_VAUX3_DEDICATED;
grp_reg = TWL4030_VAUX3_DEV_GRP;
grp_val = ENABLE_VAUX3_DEV_GRP;
if (omap_rev() > OMAP3430_REV_ES1_0) {
t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
TWL4030_VPLL2_DEDICATED);
t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
TWL4030_VPLL2_DEV_GRP);
}
} else {
ded_reg = TWL4030_VAUX2_DEDICATED;
ded_val = ENABLE_VAUX2_DEDICATED;
grp_reg = TWL4030_VAUX2_DEV_GRP;
grp_val = ENABLE_VAUX2_DEV_GRP;
}
gpio_set_value(enable_gpio, 1);
gpio_set_value(backlight_gpio, 1);
if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg))
return -EIO;
if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg))
return -EIO;
return 0;
}
static void sdp2430_panel_disable(struct lcd_panel *panel)
{
gpio_set_value(enable_gpio, 0);
gpio_set_value(backlight_gpio, 0);
if (omap_rev() > OMAP3430_REV_ES1_0) {
t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
msleep(4);
}
}
static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
struct lcd_panel sdp2430_panel = {
.name = "sdp2430",
.config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
OMAP_LCDC_INV_HSYNC,
.bpp = 16,
.data_lines = 16,
.x_res = 240,
.y_res = 320,
.hsw = 3, /* hsync_len (4) - 1 */
.hfp = 3, /* right_margin (4) - 1 */
.hbp = 39, /* left_margin (40) - 1 */
.vsw = 1, /* vsync_len (2) - 1 */
.vfp = 2, /* lower_margin */
.vbp = 7, /* upper_margin (8) - 1 */
.pixel_clock = LCD_PIXCLOCK_MAX,
.init = sdp2430_panel_init,
.cleanup = sdp2430_panel_cleanup,
.enable = sdp2430_panel_enable,
.disable = sdp2430_panel_disable,
.get_caps = sdp2430_panel_get_caps,
};
static int sdp2430_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&sdp2430_panel);
return 0;
}
static int sdp2430_panel_remove(struct platform_device *pdev)
{
return 0;
}
static int sdp2430_panel_suspend(struct platform_device *pdev,
pm_message_t mesg)
{
return 0;
}
static int sdp2430_panel_resume(struct platform_device *pdev)
{
return 0;
}
struct platform_driver sdp2430_panel_driver = {
.probe = sdp2430_panel_probe,
.remove = sdp2430_panel_remove,
.suspend = sdp2430_panel_suspend,
.resume = sdp2430_panel_resume,
.driver = {
.name = "sdp2430_lcd",
.owner = THIS_MODULE,
},
};
static int __init sdp2430_panel_drv_init(void)
{
return platform_driver_register(&sdp2430_panel_driver);
}
static void __exit sdp2430_panel_drv_exit(void)
{
platform_driver_unregister(&sdp2430_panel_driver);
}
module_init(sdp2430_panel_drv_init);
module_exit(sdp2430_panel_drv_exit);

View file

@ -1,136 +0,0 @@
/*
* LCD panel support for the Samsung OMAP2 Apollon board
*
* Copyright (C) 2005,2006 Samsung Electronics
* Author: Kyungmin Park <kyungmin.park@samsung.com>
*
* Derived from drivers/video/omap/lcd-h4.c
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/gpio.h>
#include "omapfb.h"
/* #define USE_35INCH_LCD 1 */
static int apollon_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
return 0;
}
static void apollon_panel_cleanup(struct lcd_panel *panel)
{
}
static int apollon_panel_enable(struct lcd_panel *panel)
{
return 0;
}
static void apollon_panel_disable(struct lcd_panel *panel)
{
}
static unsigned long apollon_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
struct lcd_panel apollon_panel = {
.name = "apollon",
.config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
OMAP_LCDC_INV_HSYNC,
.bpp = 16,
.data_lines = 18,
#ifdef USE_35INCH_LCD
.x_res = 240,
.y_res = 320,
.hsw = 2,
.hfp = 3,
.hbp = 9,
.vsw = 4,
.vfp = 3,
.vbp = 5,
#else
.x_res = 480,
.y_res = 272,
.hsw = 41,
.hfp = 2,
.hbp = 2,
.vsw = 10,
.vfp = 2,
.vbp = 2,
#endif
.pixel_clock = 6250,
.init = apollon_panel_init,
.cleanup = apollon_panel_cleanup,
.enable = apollon_panel_enable,
.disable = apollon_panel_disable,
.get_caps = apollon_panel_get_caps,
};
static int apollon_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&apollon_panel);
return 0;
}
static int apollon_panel_remove(struct platform_device *pdev)
{
return 0;
}
static int apollon_panel_suspend(struct platform_device *pdev,
pm_message_t mesg)
{
return 0;
}
static int apollon_panel_resume(struct platform_device *pdev)
{
return 0;
}
struct platform_driver apollon_panel_driver = {
.probe = apollon_panel_probe,
.remove = apollon_panel_remove,
.suspend = apollon_panel_suspend,
.resume = apollon_panel_resume,
.driver = {
.name = "apollon_lcd",
.owner = THIS_MODULE,
},
};
static int __init apollon_panel_drv_init(void)
{
return platform_driver_register(&apollon_panel_driver);
}
static void __exit apollon_panel_drv_exit(void)
{
platform_driver_unregister(&apollon_panel_driver);
}
module_init(apollon_panel_drv_init);
module_exit(apollon_panel_drv_exit);

View file

@ -1,117 +0,0 @@
/*
* LCD panel support for the TI OMAP H4 board
*
* Copyright (C) 2004 Nokia Corporation
* Author: Imre Deak <imre.deak@nokia.com>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include "omapfb.h"
static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
{
return 0;
}
static void h4_panel_cleanup(struct lcd_panel *panel)
{
}
static int h4_panel_enable(struct lcd_panel *panel)
{
return 0;
}
static void h4_panel_disable(struct lcd_panel *panel)
{
}
static unsigned long h4_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static struct lcd_panel h4_panel = {
.name = "h4",
.config = OMAP_LCDC_PANEL_TFT,
.bpp = 16,
.data_lines = 16,
.x_res = 240,
.y_res = 320,
.pixel_clock = 6250,
.hsw = 15,
.hfp = 15,
.hbp = 60,
.vsw = 1,
.vfp = 1,
.vbp = 1,
.init = h4_panel_init,
.cleanup = h4_panel_cleanup,
.enable = h4_panel_enable,
.disable = h4_panel_disable,
.get_caps = h4_panel_get_caps,
};
static int h4_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&h4_panel);
return 0;
}
static int h4_panel_remove(struct platform_device *pdev)
{
return 0;
}
static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
return 0;
}
static int h4_panel_resume(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver h4_panel_driver = {
.probe = h4_panel_probe,
.remove = h4_panel_remove,
.suspend = h4_panel_suspend,
.resume = h4_panel_resume,
.driver = {
.name = "lcd_h4",
.owner = THIS_MODULE,
},
};
static int __init h4_panel_drv_init(void)
{
return platform_driver_register(&h4_panel_driver);
}
static void __exit h4_panel_drv_cleanup(void)
{
platform_driver_unregister(&h4_panel_driver);
}
module_init(h4_panel_drv_init);
module_exit(h4_panel_drv_cleanup);

View file

@ -1,201 +0,0 @@
/*
* LCD panel support for the TI LDP board
*
* Copyright (C) 2007 WindRiver
* Author: Stanley Miao <stanley.miao@windriver.com>
*
* Derived from drivers/video/omap/lcd-2430sdp.c
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/i2c/twl.h>
#include <asm/gpio.h>
#include <plat/mux.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES)
#define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES)
#define LCD_PANEL_RESET_GPIO 55
#define LCD_PANEL_QVGA_GPIO 56
#ifdef CONFIG_FB_OMAP_LCD_VGA
#define LCD_XRES 480
#define LCD_YRES 640
#define LCD_PIXCLOCK_MAX 41700
#else
#define LCD_XRES 240
#define LCD_YRES 320
#define LCD_PIXCLOCK_MAX 185186
#endif
#define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
#define ENABLE_VAUX2_DEDICATED 0x09
#define ENABLE_VAUX2_DEV_GRP 0x20
#define ENABLE_VAUX3_DEDICATED 0x03
#define ENABLE_VAUX3_DEV_GRP 0x20
#define ENABLE_VPLL2_DEDICATED 0x05
#define ENABLE_VPLL2_DEV_GRP 0xE0
#define TWL4030_VPLL2_DEV_GRP 0x33
#define TWL4030_VPLL2_DEDICATED 0x36
#define t2_out(c, r, v) twl_i2c_write_u8(c, r, v)
static int ldp_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset");
gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga");
gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel");
gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight");
gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0);
gpio_direction_output(LCD_PANEL_RESET_GPIO, 0);
gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
#ifdef CONFIG_FB_OMAP_LCD_VGA
gpio_set_value(LCD_PANEL_QVGA_GPIO, 0);
#else
gpio_set_value(LCD_PANEL_QVGA_GPIO, 1);
#endif
gpio_set_value(LCD_PANEL_RESET_GPIO, 1);
return 0;
}
static void ldp_panel_cleanup(struct lcd_panel *panel)
{
gpio_free(LCD_PANEL_BACKLIGHT_GPIO);
gpio_free(LCD_PANEL_ENABLE_GPIO);
gpio_free(LCD_PANEL_QVGA_GPIO);
gpio_free(LCD_PANEL_RESET_GPIO);
}
static int ldp_panel_enable(struct lcd_panel *panel)
{
if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED,
TWL4030_VPLL2_DEDICATED))
return -EIO;
if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP,
TWL4030_VPLL2_DEV_GRP))
return -EIO;
gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1);
gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1);
if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED,
TWL4030_VAUX3_DEDICATED))
return -EIO;
if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP,
TWL4030_VAUX3_DEV_GRP))
return -EIO;
return 0;
}
static void ldp_panel_disable(struct lcd_panel *panel)
{
gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0);
gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0);
t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED);
t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP);
msleep(4);
}
static unsigned long ldp_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
struct lcd_panel ldp_panel = {
.name = "ldp",
.config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
OMAP_LCDC_INV_HSYNC,
.bpp = 16,
.data_lines = 18,
.x_res = LCD_XRES,
.y_res = LCD_YRES,
.hsw = 3, /* hsync_len (4) - 1 */
.hfp = 3, /* right_margin (4) - 1 */
.hbp = 39, /* left_margin (40) - 1 */
.vsw = 1, /* vsync_len (2) - 1 */
.vfp = 2, /* lower_margin */
.vbp = 7, /* upper_margin (8) - 1 */
.pixel_clock = LCD_PIXCLOCK_MAX,
.init = ldp_panel_init,
.cleanup = ldp_panel_cleanup,
.enable = ldp_panel_enable,
.disable = ldp_panel_disable,
.get_caps = ldp_panel_get_caps,
};
static int ldp_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&ldp_panel);
return 0;
}
static int ldp_panel_remove(struct platform_device *pdev)
{
return 0;
}
static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg)
{
return 0;
}
static int ldp_panel_resume(struct platform_device *pdev)
{
return 0;
}
struct platform_driver ldp_panel_driver = {
.probe = ldp_panel_probe,
.remove = ldp_panel_remove,
.suspend = ldp_panel_suspend,
.resume = ldp_panel_resume,
.driver = {
.name = "ldp_lcd",
.owner = THIS_MODULE,
},
};
static int __init ldp_panel_drv_init(void)
{
return platform_driver_register(&ldp_panel_driver);
}
static void __exit ldp_panel_drv_exit(void)
{
platform_driver_unregister(&ldp_panel_driver);
}
module_init(ldp_panel_drv_init);
module_exit(ldp_panel_drv_exit);

View file

@ -1,130 +0,0 @@
/*
* LCD panel support for the TI OMAP3 Beagle board
*
* Author: Koen Kooi <koen@openembedded.org>
*
* Derived from drivers/video/omap/lcd-omap3evm.c
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/i2c/twl.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_ENABLE_GPIO 170
static int omap3beagle_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable");
return 0;
}
static void omap3beagle_panel_cleanup(struct lcd_panel *panel)
{
gpio_free(LCD_PANEL_ENABLE_GPIO);
}
static int omap3beagle_panel_enable(struct lcd_panel *panel)
{
gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
return 0;
}
static void omap3beagle_panel_disable(struct lcd_panel *panel)
{
gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
}
static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
struct lcd_panel omap3beagle_panel = {
.name = "omap3beagle",
.config = OMAP_LCDC_PANEL_TFT,
.bpp = 16,
.data_lines = 24,
.x_res = 1024,
.y_res = 768,
.hsw = 3, /* hsync_len (4) - 1 */
.hfp = 3, /* right_margin (4) - 1 */
.hbp = 39, /* left_margin (40) - 1 */
.vsw = 1, /* vsync_len (2) - 1 */
.vfp = 2, /* lower_margin */
.vbp = 7, /* upper_margin (8) - 1 */
.pixel_clock = 64000,
.init = omap3beagle_panel_init,
.cleanup = omap3beagle_panel_cleanup,
.enable = omap3beagle_panel_enable,
.disable = omap3beagle_panel_disable,
.get_caps = omap3beagle_panel_get_caps,
};
static int omap3beagle_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&omap3beagle_panel);
return 0;
}
static int omap3beagle_panel_remove(struct platform_device *pdev)
{
return 0;
}
static int omap3beagle_panel_suspend(struct platform_device *pdev,
pm_message_t mesg)
{
return 0;
}
static int omap3beagle_panel_resume(struct platform_device *pdev)
{
return 0;
}
struct platform_driver omap3beagle_panel_driver = {
.probe = omap3beagle_panel_probe,
.remove = omap3beagle_panel_remove,
.suspend = omap3beagle_panel_suspend,
.resume = omap3beagle_panel_resume,
.driver = {
.name = "omap3beagle_lcd",
.owner = THIS_MODULE,
},
};
static int __init omap3beagle_panel_drv_init(void)
{
return platform_driver_register(&omap3beagle_panel_driver);
}
static void __exit omap3beagle_panel_drv_exit(void)
{
platform_driver_unregister(&omap3beagle_panel_driver);
}
module_init(omap3beagle_panel_drv_init);
module_exit(omap3beagle_panel_drv_exit);

View file

@ -1,193 +0,0 @@
/*
* LCD panel support for the TI OMAP3 EVM board
*
* Author: Steve Sakoman <steve@sakoman.com>
*
* Derived from drivers/video/omap/lcd-apollon.c
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/i2c/twl.h>
#include <plat/mux.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_PANEL_ENABLE_GPIO 153
#define LCD_PANEL_LR 2
#define LCD_PANEL_UD 3
#define LCD_PANEL_INI 152
#define LCD_PANEL_QVGA 154
#define LCD_PANEL_RESB 155
#define ENABLE_VDAC_DEDICATED 0x03
#define ENABLE_VDAC_DEV_GRP 0x20
#define ENABLE_VPLL2_DEDICATED 0x05
#define ENABLE_VPLL2_DEV_GRP 0xE0
#define TWL_LED_LEDEN 0x00
#define TWL_PWMA_PWMAON 0x00
#define TWL_PWMA_PWMAOFF 0x01
static unsigned int bklight_level;
static int omap3evm_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
gpio_request(LCD_PANEL_LR, "LCD lr");
gpio_request(LCD_PANEL_UD, "LCD ud");
gpio_request(LCD_PANEL_INI, "LCD ini");
gpio_request(LCD_PANEL_RESB, "LCD resb");
gpio_request(LCD_PANEL_QVGA, "LCD qvga");
gpio_direction_output(LCD_PANEL_RESB, 1);
gpio_direction_output(LCD_PANEL_INI, 1);
gpio_direction_output(LCD_PANEL_QVGA, 0);
gpio_direction_output(LCD_PANEL_LR, 1);
gpio_direction_output(LCD_PANEL_UD, 1);
twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN);
twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON);
twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF);
bklight_level = 100;
return 0;
}
static void omap3evm_panel_cleanup(struct lcd_panel *panel)
{
gpio_free(LCD_PANEL_QVGA);
gpio_free(LCD_PANEL_RESB);
gpio_free(LCD_PANEL_INI);
gpio_free(LCD_PANEL_UD);
gpio_free(LCD_PANEL_LR);
}
static int omap3evm_panel_enable(struct lcd_panel *panel)
{
gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0);
return 0;
}
static void omap3evm_panel_disable(struct lcd_panel *panel)
{
gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1);
}
static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
static int omap3evm_bklight_setlevel(struct lcd_panel *panel,
unsigned int level)
{
u8 c;
if ((level >= 0) && (level <= 100)) {
c = (125 * (100 - level)) / 100 + 2;
twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF);
bklight_level = level;
}
return 0;
}
static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel)
{
return bklight_level;
}
static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel)
{
return 100;
}
struct lcd_panel omap3evm_panel = {
.name = "omap3evm",
.config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC |
OMAP_LCDC_INV_HSYNC,
.bpp = 16,
.data_lines = 18,
.x_res = 480,
.y_res = 640,
.hsw = 3, /* hsync_len (4) - 1 */
.hfp = 3, /* right_margin (4) - 1 */
.hbp = 39, /* left_margin (40) - 1 */
.vsw = 1, /* vsync_len (2) - 1 */
.vfp = 2, /* lower_margin */
.vbp = 7, /* upper_margin (8) - 1 */
.pixel_clock = 26000,
.init = omap3evm_panel_init,
.cleanup = omap3evm_panel_cleanup,
.enable = omap3evm_panel_enable,
.disable = omap3evm_panel_disable,
.get_caps = omap3evm_panel_get_caps,
.set_bklight_level = omap3evm_bklight_setlevel,
.get_bklight_level = omap3evm_bklight_getlevel,
.get_bklight_max = omap3evm_bklight_getmaxlevel,
};
static int omap3evm_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&omap3evm_panel);
return 0;
}
static int omap3evm_panel_remove(struct platform_device *pdev)
{
return 0;
}
static int omap3evm_panel_suspend(struct platform_device *pdev,
pm_message_t mesg)
{
return 0;
}
static int omap3evm_panel_resume(struct platform_device *pdev)
{
return 0;
}
struct platform_driver omap3evm_panel_driver = {
.probe = omap3evm_panel_probe,
.remove = omap3evm_panel_remove,
.suspend = omap3evm_panel_suspend,
.resume = omap3evm_panel_resume,
.driver = {
.name = "omap3evm_lcd",
.owner = THIS_MODULE,
},
};
static int __init omap3evm_panel_drv_init(void)
{
return platform_driver_register(&omap3evm_panel_driver);
}
static void __exit omap3evm_panel_drv_exit(void)
{
platform_driver_unregister(&omap3evm_panel_driver);
}
module_init(omap3evm_panel_drv_init);
module_exit(omap3evm_panel_drv_exit);

View file

@ -1,180 +0,0 @@
/*
* LCD panel support for the Gumstix Overo
*
* Author: Steve Sakoman <steve@sakoman.com>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c/twl.h>
#include <asm/gpio.h>
#include <plat/mux.h>
#include <asm/mach-types.h>
#include "omapfb.h"
#define LCD_ENABLE 144
static int overo_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) &&
(gpio_direction_output(LCD_ENABLE, 1) == 0))
gpio_export(LCD_ENABLE, 0);
else
printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n");
return 0;
}
static void overo_panel_cleanup(struct lcd_panel *panel)
{
gpio_free(LCD_ENABLE);
}
static int overo_panel_enable(struct lcd_panel *panel)
{
gpio_set_value(LCD_ENABLE, 1);
return 0;
}
static void overo_panel_disable(struct lcd_panel *panel)
{
gpio_set_value(LCD_ENABLE, 0);
}
static unsigned long overo_panel_get_caps(struct lcd_panel *panel)
{
return 0;
}
struct lcd_panel overo_panel = {
.name = "overo",
.config = OMAP_LCDC_PANEL_TFT,
.bpp = 16,
.data_lines = 24,
#if defined CONFIG_FB_OMAP_031M3R
/* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
.x_res = 640,
.y_res = 480,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 7,
.pixel_clock = 23500,
#elif defined CONFIG_FB_OMAP_048M3R
/* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */
.x_res = 800,
.y_res = 600,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 11,
.pixel_clock = 35500,
#elif defined CONFIG_FB_OMAP_079M3R
/* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
.x_res = 1024,
.y_res = 768,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 15,
.pixel_clock = 56000,
#elif defined CONFIG_FB_OMAP_092M9R
/* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */
.x_res = 1280,
.y_res = 720,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 5,
.vbp = 13,
.pixel_clock = 64000,
#else
/* use 640 x 480 if no config option */
/* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
.x_res = 640,
.y_res = 480,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 7,
.pixel_clock = 23500,
#endif
.init = overo_panel_init,
.cleanup = overo_panel_cleanup,
.enable = overo_panel_enable,
.disable = overo_panel_disable,
.get_caps = overo_panel_get_caps,
};
static int overo_panel_probe(struct platform_device *pdev)
{
omapfb_register_panel(&overo_panel);
return 0;
}
static int overo_panel_remove(struct platform_device *pdev)
{
/* omapfb does not have unregister_panel */
return 0;
}
static struct platform_driver overo_panel_driver = {
.probe = overo_panel_probe,
.remove = overo_panel_remove,
.driver = {
.name = "overo_lcd",
.owner = THIS_MODULE,
},
};
static int __init overo_panel_drv_init(void)
{
return platform_driver_register(&overo_panel_driver);
}
static void __exit overo_panel_drv_exit(void)
{
platform_driver_unregister(&overo_panel_driver);
}
module_init(overo_panel_drv_init);
module_exit(overo_panel_drv_exit);

View file

@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI
Supports LCD Panel used in TI SDP3430 and EVM boards,
OMAP3517 EVM boards and CM-T35.
config PANEL_DVI
tristate "DVI output"
depends on OMAP2_DSS_DPI
help
Driver for external monitors, connected via DVI. The driver uses i2c
to read EDID information from the monitor.
config PANEL_LGPHILIPS_LB035Q02
tristate "LG.Philips LB035Q02 LCD Panel"
depends on OMAP2_DSS_DPI && SPI
@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS_DPI
select BACKLIGHT_CLASS_DEVICE
depends on BACKLIGHT_CLASS_DEVICE
help
LCD Panel used in TI's SDP3430 and EVM boards
config PANEL_NEC_NL8048HL11_01B
tristate "NEC NL8048HL11-01B Panel"
depends on OMAP2_DSS_DPI
depends on SPI
depends on BACKLIGHT_CLASS_DEVICE
help
This NEC NL8048HL11-01B panel is TFT LCD
used in the Zoom2/3/3630 sdp boards.
config PANEL_PICODLP
tristate "TI PICO DLP mini-projector"
depends on OMAP2_DSS && I2C
help
A mini-projector used in TI's SDP4430 and EVM boards
For more info please visit http://www.dlp.com/projector/
config PANEL_TAAL
tristate "Taal DSI Panel"
depends on OMAP2_DSS_DSI
depends on BACKLIGHT_CLASS_DEVICE
help
Taal DSI command mode panel from TPO.
@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1
config PANEL_ACX565AKM
tristate "ACX565AKM Panel"
depends on OMAP2_DSS_SDI && SPI
select BACKLIGHT_CLASS_DEVICE
depends on BACKLIGHT_CLASS_DEVICE
help
This is the LCD panel used on Nokia N900
config PANEL_N8X0
tristate "N8X0 Panel"
depends on OMAP2_DSS_RFBI && SPI
depends on BACKLIGHT_CLASS_DEVICE
help
This is the LCD panel used on Nokia N8x0
endmenu

View file

@ -1,8 +1,11 @@
obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
obj-$(CONFIG_PANEL_DVI) += panel-dvi.o
obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o

View file

@ -0,0 +1,363 @@
/*
* DVI output support
*
* Copyright (C) 2011 Texas Instruments Inc
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <video/omapdss.h>
#include <linux/i2c.h>
#include <drm/drm_edid.h>
#include <video/omap-panel-dvi.h>
static const struct omap_video_timings panel_dvi_default_timings = {
.x_res = 640,
.y_res = 480,
.pixel_clock = 23500,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 7,
};
struct panel_drv_data {
struct omap_dss_device *dssdev;
struct mutex lock;
};
static inline struct panel_dvi_platform_data
*get_pdata(const struct omap_dss_device *dssdev)
{
return dssdev->data;
}
static int panel_dvi_power_on(struct omap_dss_device *dssdev)
{
struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
int r;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
r = omapdss_dpi_display_enable(dssdev);
if (r)
goto err0;
if (pdata->platform_enable) {
r = pdata->platform_enable(dssdev);
if (r)
goto err1;
}
return 0;
err1:
omapdss_dpi_display_disable(dssdev);
err0:
return r;
}
static void panel_dvi_power_off(struct omap_dss_device *dssdev)
{
struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return;
if (pdata->platform_disable)
pdata->platform_disable(dssdev);
omapdss_dpi_display_disable(dssdev);
}
static int panel_dvi_probe(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata;
ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
dssdev->panel.timings = panel_dvi_default_timings;
dssdev->panel.config = OMAP_DSS_LCD_TFT;
ddata->dssdev = dssdev;
mutex_init(&ddata->lock);
dev_set_drvdata(&dssdev->dev, ddata);
return 0;
}
static void __exit panel_dvi_remove(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
dev_set_drvdata(&dssdev->dev, NULL);
mutex_unlock(&ddata->lock);
kfree(ddata);
}
static int panel_dvi_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ddata->lock);
r = panel_dvi_power_on(dssdev);
if (r == 0)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ddata->lock);
return r;
}
static void panel_dvi_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
panel_dvi_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
mutex_unlock(&ddata->lock);
}
static int panel_dvi_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
panel_dvi_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&ddata->lock);
return 0;
}
static int panel_dvi_resume(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ddata->lock);
r = panel_dvi_power_on(dssdev);
if (r == 0)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ddata->lock);
return r;
}
static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
dpi_set_timings(dssdev, timings);
mutex_unlock(&ddata->lock);
}
static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
mutex_lock(&ddata->lock);
*timings = dssdev->panel.timings;
mutex_unlock(&ddata->lock);
}
static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&ddata->lock);
r = dpi_check_timings(dssdev, timings);
mutex_unlock(&ddata->lock);
return r;
}
static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
unsigned char *buf, u16 count, u8 offset)
{
int r, retries;
for (retries = 3; retries > 0; retries--) {
struct i2c_msg msgs[] = {
{
.addr = DDC_ADDR,
.flags = 0,
.len = 1,
.buf = &offset,
}, {
.addr = DDC_ADDR,
.flags = I2C_M_RD,
.len = count,
.buf = buf,
}
};
r = i2c_transfer(adapter, msgs, 2);
if (r == 2)
return 0;
if (r != -EAGAIN)
break;
}
return r < 0 ? r : -EIO;
}
static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
u8 *edid, int len)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
struct i2c_adapter *adapter;
int r, l, bytes_read;
mutex_lock(&ddata->lock);
if (pdata->i2c_bus_num == 0) {
r = -ENODEV;
goto err;
}
adapter = i2c_get_adapter(pdata->i2c_bus_num);
if (!adapter) {
dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
pdata->i2c_bus_num);
r = -EINVAL;
goto err;
}
l = min(EDID_LENGTH, len);
r = panel_dvi_ddc_read(adapter, edid, l, 0);
if (r)
goto err;
bytes_read = l;
/* if there are extensions, read second block */
if (len > EDID_LENGTH && edid[0x7e] > 0) {
l = min(EDID_LENGTH, len - EDID_LENGTH);
r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH,
l, EDID_LENGTH);
if (r)
goto err;
bytes_read += l;
}
mutex_unlock(&ddata->lock);
return bytes_read;
err:
mutex_unlock(&ddata->lock);
return r;
}
static bool panel_dvi_detect(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
struct i2c_adapter *adapter;
unsigned char out;
int r;
mutex_lock(&ddata->lock);
if (pdata->i2c_bus_num == 0)
goto out;
adapter = i2c_get_adapter(pdata->i2c_bus_num);
if (!adapter)
goto out;
r = panel_dvi_ddc_read(adapter, &out, 1, 0);
mutex_unlock(&ddata->lock);
return r == 0;
out:
mutex_unlock(&ddata->lock);
return true;
}
static struct omap_dss_driver panel_dvi_driver = {
.probe = panel_dvi_probe,
.remove = __exit_p(panel_dvi_remove),
.enable = panel_dvi_enable,
.disable = panel_dvi_disable,
.suspend = panel_dvi_suspend,
.resume = panel_dvi_resume,
.set_timings = panel_dvi_set_timings,
.get_timings = panel_dvi_get_timings,
.check_timings = panel_dvi_check_timings,
.read_edid = panel_dvi_read_edid,
.detect = panel_dvi_detect,
.driver = {
.name = "dvi",
.owner = THIS_MODULE,
},
};
static int __init panel_dvi_init(void)
{
return omap_dss_register_driver(&panel_dvi_driver);
}
static void __exit panel_dvi_exit(void)
{
omap_dss_unregister_driver(&panel_dvi_driver);
}
module_init(panel_dvi_init);
module_exit(panel_dvi_exit);
MODULE_LICENSE("GPL");

View file

@ -58,30 +58,6 @@ struct panel_config {
/* Panel configurations */
static struct panel_config generic_dpi_panels[] = {
/* Generic Panel */
{
{
.x_res = 640,
.y_res = 480,
.pixel_clock = 23500,
.hfp = 48,
.hsw = 32,
.hbp = 80,
.vfp = 3,
.vsw = 4,
.vbp = 7,
},
.acbi = 0x0,
.acb = 0x0,
.config = OMAP_DSS_LCD_TFT,
.power_on_delay = 0,
.power_off_delay = 0,
.name = "generic",
},
/* Sharp LQ043T1DG01 */
{
{
@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "powertip_ph480272t",
},
/* Innolux AT070TN83 */
{
{
.x_res = 800,
.y_res = 480,
.pixel_clock = 40000,
.hsw = 48,
.hfp = 1,
.hbp = 1,
.vsw = 3,
.vfp = 12,
.vbp = 25,
},
.acbi = 0x0,
.acb = 0x28,
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS,
.power_on_delay = 0,
.power_off_delay = 0,
.name = "innolux_at070tn83",
},
/* NEC NL2432DR22-11B */
{
{
.x_res = 240,
.y_res = 320,
.pixel_clock = 5400,
.hsw = 3,
.hfp = 3,
.hbp = 39,
.vsw = 1,
.vfp = 2,
.vbp = 7,
},
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS,
.name = "nec_nl2432dr22-11b",
},
/* Unknown panel used in OMAP H4 */
{
{
.x_res = 240,
.y_res = 320,
.pixel_clock = 6250,
.hsw = 15,
.hfp = 15,
.hbp = 60,
.vsw = 1,
.vfp = 1,
.vbp = 1,
},
.config = OMAP_DSS_LCD_TFT,
.name = "h4",
},
/* Unknown panel used in Samsung OMAP2 Apollon */
{
{
.x_res = 480,
.y_res = 272,
.pixel_clock = 6250,
.hsw = 41,
.hfp = 2,
.hbp = 2,
.vsw = 10,
.vfp = 2,
.vbp = 2,
},
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS,
.name = "apollon",
},
};
struct panel_drv_data {

View file

@ -0,0 +1,747 @@
/* #define DEBUG */
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/backlight.h>
#include <linux/fb.h>
#include <video/omapdss.h>
#include <video/omap-panel-n8x0.h>
#define BLIZZARD_REV_CODE 0x00
#define BLIZZARD_CONFIG 0x02
#define BLIZZARD_PLL_DIV 0x04
#define BLIZZARD_PLL_LOCK_RANGE 0x06
#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
#define BLIZZARD_PLL_MODE 0x0c
#define BLIZZARD_CLK_SRC 0x0e
#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
#define BLIZZARD_MEM_BANK0_STATUS 0x14
#define BLIZZARD_PANEL_CONFIGURATION 0x28
#define BLIZZARD_HDISP 0x2a
#define BLIZZARD_HNDP 0x2c
#define BLIZZARD_VDISP0 0x2e
#define BLIZZARD_VDISP1 0x30
#define BLIZZARD_VNDP 0x32
#define BLIZZARD_HSW 0x34
#define BLIZZARD_VSW 0x38
#define BLIZZARD_DISPLAY_MODE 0x68
#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
#define BLIZZARD_POWER_SAVE 0xE6
#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
/* Data source select */
/* For S1D13745 */
#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
/* For S1D13744 */
#define BLIZZARD_SRC_WRITE_LCD 0x00
#define BLIZZARD_SRC_BLT_LCD 0x06
#define BLIZZARD_COLOR_RGB565 0x01
#define BLIZZARD_COLOR_YUV420 0x09
#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
#define MIPID_CMD_READ_DISP_ID 0x04
#define MIPID_CMD_READ_RED 0x06
#define MIPID_CMD_READ_GREEN 0x07
#define MIPID_CMD_READ_BLUE 0x08
#define MIPID_CMD_READ_DISP_STATUS 0x09
#define MIPID_CMD_RDDSDR 0x0F
#define MIPID_CMD_SLEEP_IN 0x10
#define MIPID_CMD_SLEEP_OUT 0x11
#define MIPID_CMD_DISP_OFF 0x28
#define MIPID_CMD_DISP_ON 0x29
static struct panel_drv_data {
struct mutex lock;
struct omap_dss_device *dssdev;
struct spi_device *spidev;
struct backlight_device *bldev;
int blizzard_ver;
} s_drv_data;
static inline
struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
{
return dssdev->data;
}
static inline
struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
{
return &s_drv_data;
}
static inline void blizzard_cmd(u8 cmd)
{
omap_rfbi_write_command(&cmd, 1);
}
static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
{
omap_rfbi_write_command(&cmd, 1);
omap_rfbi_write_data(buf, len);
}
static inline void blizzard_read(u8 cmd, u8 *buf, int len)
{
omap_rfbi_write_command(&cmd, 1);
omap_rfbi_read_data(buf, len);
}
static u8 blizzard_read_reg(u8 cmd)
{
u8 data;
blizzard_read(cmd, &data, 1);
return data;
}
static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
int x, int y, int w, int h)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
u8 tmp[18];
int x_end, y_end;
x_end = x + w - 1;
y_end = y + h - 1;
tmp[0] = x;
tmp[1] = x >> 8;
tmp[2] = y;
tmp[3] = y >> 8;
tmp[4] = x_end;
tmp[5] = x_end >> 8;
tmp[6] = y_end;
tmp[7] = y_end >> 8;
/* scaling? */
tmp[8] = x;
tmp[9] = x >> 8;
tmp[10] = y;
tmp[11] = y >> 8;
tmp[12] = x_end;
tmp[13] = x_end >> 8;
tmp[14] = y_end;
tmp[15] = y_end >> 8;
tmp[16] = BLIZZARD_COLOR_RGB565;
if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
else
tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
BLIZZARD_SRC_WRITE_LCD :
BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
omap_rfbi_configure(dssdev, 16, 8);
blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
omap_rfbi_configure(dssdev, 16, 16);
}
static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
int wlen, u8 *rbuf, int rlen)
{
struct spi_message m;
struct spi_transfer *x, xfer[4];
u16 w;
int r;
spi_message_init(&m);
memset(xfer, 0, sizeof(xfer));
x = &xfer[0];
cmd &= 0xff;
x->tx_buf = &cmd;
x->bits_per_word = 9;
x->len = 2;
spi_message_add_tail(x, &m);
if (wlen) {
x++;
x->tx_buf = wbuf;
x->len = wlen;
x->bits_per_word = 9;
spi_message_add_tail(x, &m);
}
if (rlen) {
x++;
x->rx_buf = &w;
x->len = 1;
spi_message_add_tail(x, &m);
if (rlen > 1) {
/* Arrange for the extra clock before the first
* data bit.
*/
x->bits_per_word = 9;
x->len = 2;
x++;
x->rx_buf = &rbuf[1];
x->len = rlen - 1;
spi_message_add_tail(x, &m);
}
}
r = spi_sync(spi, &m);
if (r < 0)
dev_dbg(&spi->dev, "spi_sync %d\n", r);
if (rlen)
rbuf[0] = w & 0xff;
}
static inline void mipid_cmd(struct spi_device *spi, int cmd)
{
mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
}
static inline void mipid_write(struct spi_device *spi,
int reg, const u8 *buf, int len)
{
mipid_transfer(spi, reg, buf, len, NULL, 0);
}
static inline void mipid_read(struct spi_device *spi,
int reg, u8 *buf, int len)
{
mipid_transfer(spi, reg, NULL, 0, buf, len);
}
static void set_data_lines(struct spi_device *spi, int data_lines)
{
u16 par;
switch (data_lines) {
case 16:
par = 0x150;
break;
case 18:
par = 0x160;
break;
case 24:
par = 0x170;
break;
}
mipid_write(spi, 0x3a, (u8 *)&par, 2);
}
static void send_init_string(struct spi_device *spi)
{
u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
}
static void send_display_on(struct spi_device *spi)
{
mipid_cmd(spi, MIPID_CMD_DISP_ON);
}
static void send_display_off(struct spi_device *spi)
{
mipid_cmd(spi, MIPID_CMD_DISP_OFF);
}
static void send_sleep_out(struct spi_device *spi)
{
mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
msleep(120);
}
static void send_sleep_in(struct spi_device *spi)
{
mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
msleep(50);
}
static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
{
int r;
struct panel_n8x0_data *bdata = get_board_data(dssdev);
struct panel_drv_data *ddata = get_drv_data(dssdev);
struct spi_device *spi = ddata->spidev;
u8 rev, conf;
u8 display_id[3];
const char *panel_name;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
return 0;
gpio_direction_output(bdata->ctrl_pwrdown, 1);
if (bdata->platform_enable) {
r = bdata->platform_enable(dssdev);
if (r)
goto err_plat_en;
}
r = omapdss_rfbi_display_enable(dssdev);
if (r)
goto err_rfbi_en;
rev = blizzard_read_reg(BLIZZARD_REV_CODE);
conf = blizzard_read_reg(BLIZZARD_CONFIG);
switch (rev & 0xfc) {
case 0x9c:
ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
break;
case 0xa4:
ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
break;
default:
dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
r = -ENODEV;
goto err_inv_chip;
}
/* panel */
gpio_direction_output(bdata->panel_reset, 1);
mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
display_id[0], display_id[1], display_id[2]);
switch (display_id[0]) {
case 0x45:
panel_name = "lph8923";
break;
case 0x83:
panel_name = "ls041y3";
break;
default:
dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
display_id[0]);
r = -ENODEV;
goto err_inv_panel;
}
dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
panel_name, display_id[1]);
send_sleep_out(spi);
send_init_string(spi);
set_data_lines(spi, 24);
send_display_on(spi);
return 0;
err_inv_panel:
/*
* HACK: we should turn off the panel here, but there is some problem
* with the initialization sequence, and we fail to init the panel if we
* have turned it off
*/
/* gpio_direction_output(bdata->panel_reset, 0); */
err_inv_chip:
omapdss_rfbi_display_disable(dssdev);
err_rfbi_en:
if (bdata->platform_disable)
bdata->platform_disable(dssdev);
err_plat_en:
gpio_direction_output(bdata->ctrl_pwrdown, 0);
return r;
}
static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
{
struct panel_n8x0_data *bdata = get_board_data(dssdev);
struct panel_drv_data *ddata = get_drv_data(dssdev);
struct spi_device *spi = ddata->spidev;
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return;
send_display_off(spi);
send_sleep_in(spi);
if (bdata->platform_disable)
bdata->platform_disable(dssdev);
/*
* HACK: we should turn off the panel here, but there is some problem
* with the initialization sequence, and we fail to init the panel if we
* have turned it off
*/
/* gpio_direction_output(bdata->panel_reset, 0); */
gpio_direction_output(bdata->ctrl_pwrdown, 0);
omapdss_rfbi_display_disable(dssdev);
}
static const struct rfbi_timings n8x0_panel_timings = {
.cs_on_time = 0,
.we_on_time = 9000,
.we_off_time = 18000,
.we_cycle_time = 36000,
.re_on_time = 9000,
.re_off_time = 27000,
.re_cycle_time = 36000,
.access_time = 27000,
.cs_off_time = 36000,
.cs_pulse_width = 0,
};
static int n8x0_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
struct panel_n8x0_data *bdata = get_board_data(dssdev);
struct panel_drv_data *ddata = get_drv_data(dssdev);
int r;
int level;
mutex_lock(&ddata->lock);
if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
dev->props.power == FB_BLANK_UNBLANK)
level = dev->props.brightness;
else
level = 0;
dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
if (!bdata->set_backlight)
r = -EINVAL;
else
r = bdata->set_backlight(dssdev, level);
mutex_unlock(&ddata->lock);
return r;
}
static int n8x0_bl_get_intensity(struct backlight_device *dev)
{
if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
dev->props.power == FB_BLANK_UNBLANK)
return dev->props.brightness;
return 0;
}
static const struct backlight_ops n8x0_bl_ops = {
.get_brightness = n8x0_bl_get_intensity,
.update_status = n8x0_bl_update_status,
};
static int n8x0_panel_probe(struct omap_dss_device *dssdev)
{
struct panel_n8x0_data *bdata = get_board_data(dssdev);
struct panel_drv_data *ddata;
struct backlight_device *bldev;
struct backlight_properties props;
int r;
dev_dbg(&dssdev->dev, "probe\n");
if (!bdata)
return -EINVAL;
s_drv_data.dssdev = dssdev;
ddata = &s_drv_data;
mutex_init(&ddata->lock);
dssdev->panel.config = OMAP_DSS_LCD_TFT;
dssdev->panel.timings.x_res = 800;
dssdev->panel.timings.y_res = 480;
dssdev->ctrl.pixel_size = 16;
dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
memset(&props, 0, sizeof(props));
props.max_brightness = 127;
props.type = BACKLIGHT_PLATFORM;
bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
dssdev, &n8x0_bl_ops, &props);
if (IS_ERR(bldev)) {
r = PTR_ERR(bldev);
dev_err(&dssdev->dev, "register backlight failed\n");
return r;
}
ddata->bldev = bldev;
bldev->props.fb_blank = FB_BLANK_UNBLANK;
bldev->props.power = FB_BLANK_UNBLANK;
bldev->props.brightness = 127;
n8x0_bl_update_status(bldev);
return 0;
}
static void n8x0_panel_remove(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
struct backlight_device *bldev;
dev_dbg(&dssdev->dev, "remove\n");
bldev = ddata->bldev;
bldev->props.power = FB_BLANK_POWERDOWN;
n8x0_bl_update_status(bldev);
backlight_device_unregister(bldev);
dev_set_drvdata(&dssdev->dev, NULL);
}
static int n8x0_panel_enable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "enable\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
r = n8x0_panel_power_on(dssdev);
rfbi_bus_unlock();
if (r) {
mutex_unlock(&ddata->lock);
return r;
}
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ddata->lock);
return 0;
}
static void n8x0_panel_disable(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
dev_dbg(&dssdev->dev, "disable\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
n8x0_panel_power_off(dssdev);
rfbi_bus_unlock();
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
mutex_unlock(&ddata->lock);
}
static int n8x0_panel_suspend(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
dev_dbg(&dssdev->dev, "suspend\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
n8x0_panel_power_off(dssdev);
rfbi_bus_unlock();
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&ddata->lock);
return 0;
}
static int n8x0_panel_resume(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "resume\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
r = n8x0_panel_power_on(dssdev);
rfbi_bus_unlock();
if (r) {
mutex_unlock(&ddata->lock);
return r;
}
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
mutex_unlock(&ddata->lock);
return 0;
}
static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
*timings = dssdev->panel.timings;
}
static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
*xres = dssdev->panel.timings.x_res;
*yres = dssdev->panel.timings.y_res;
}
static void update_done(void *data)
{
rfbi_bus_unlock();
}
static int n8x0_panel_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
dev_dbg(&dssdev->dev, "update\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
blizzard_ctrl_setup_update(dssdev, x, y, w, h);
omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
mutex_unlock(&ddata->lock);
return 0;
}
static int n8x0_panel_sync(struct omap_dss_device *dssdev)
{
struct panel_drv_data *ddata = get_drv_data(dssdev);
dev_dbg(&dssdev->dev, "sync\n");
mutex_lock(&ddata->lock);
rfbi_bus_lock();
rfbi_bus_unlock();
mutex_unlock(&ddata->lock);
return 0;
}
static struct omap_dss_driver n8x0_panel_driver = {
.probe = n8x0_panel_probe,
.remove = n8x0_panel_remove,
.enable = n8x0_panel_enable,
.disable = n8x0_panel_disable,
.suspend = n8x0_panel_suspend,
.resume = n8x0_panel_resume,
.update = n8x0_panel_update,
.sync = n8x0_panel_sync,
.get_resolution = n8x0_panel_get_resolution,
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
.get_timings = n8x0_panel_get_timings,
.driver = {
.name = "n8x0_panel",
.owner = THIS_MODULE,
},
};
/* PANEL */
static int mipid_spi_probe(struct spi_device *spi)
{
dev_dbg(&spi->dev, "mipid_spi_probe\n");
spi->mode = SPI_MODE_0;
s_drv_data.spidev = spi;
return 0;
}
static int mipid_spi_remove(struct spi_device *spi)
{
dev_dbg(&spi->dev, "mipid_spi_remove\n");
return 0;
}
static struct spi_driver mipid_spi_driver = {
.driver = {
.name = "lcd_mipid",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = mipid_spi_probe,
.remove = __devexit_p(mipid_spi_remove),
};
static int __init n8x0_panel_drv_init(void)
{
int r;
r = spi_register_driver(&mipid_spi_driver);
if (r) {
pr_err("n8x0_panel: spi driver registration failed\n");
return r;
}
r = omap_dss_register_driver(&n8x0_panel_driver);
if (r) {
pr_err("n8x0_panel: dss driver registration failed\n");
spi_unregister_driver(&mipid_spi_driver);
return r;
}
return 0;
}
static void __exit n8x0_panel_drv_exit(void)
{
spi_unregister_driver(&mipid_spi_driver);
omap_dss_unregister_driver(&n8x0_panel_driver);
}
module_init(n8x0_panel_drv_init);
module_exit(n8x0_panel_drv_exit);
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,594 @@
/*
* picodlp panel driver
* picodlp_i2c_driver: i2c_client driver
*
* Copyright (C) 2009-2011 Texas Instruments
* Author: Mythri P K <mythripk@ti.com>
* Mayuresh Janorkar <mayur@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <video/omapdss.h>
#include <video/omap-panel-picodlp.h>
#include "panel-picodlp.h"
struct picodlp_data {
struct mutex lock;
struct i2c_client *picodlp_i2c_client;
};
static struct i2c_board_info picodlp_i2c_board_info = {
I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
};
struct picodlp_i2c_data {
struct mutex xfer_lock;
};
static struct i2c_device_id picodlp_i2c_id[] = {
{ "picodlp_i2c_driver", 0 },
};
struct picodlp_i2c_command {
u8 reg;
u32 value;
};
static struct omap_video_timings pico_ls_timings = {
.x_res = 864,
.y_res = 480,
.hsw = 7,
.hfp = 11,
.hbp = 7,
.pixel_clock = 19200,
.vsw = 2,
.vfp = 3,
.vbp = 14,
};
static inline struct picodlp_panel_data
*get_panel_data(const struct omap_dss_device *dssdev)
{
return (struct picodlp_panel_data *) dssdev->data;
}
static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
{
u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
struct i2c_msg msg[2];
mutex_lock(&picodlp_i2c_data->xfer_lock);
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 2;
msg[0].buf = read_cmd;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = 4;
msg[1].buf = data;
i2c_transfer(client->adapter, msg, 2);
mutex_unlock(&picodlp_i2c_data->xfer_lock);
return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
}
static int picodlp_i2c_write_block(struct i2c_client *client,
u8 *data, int len)
{
struct i2c_msg msg;
int i, r, msg_count = 1;
struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
if (len < 1 || len > 32) {
dev_err(&client->dev,
"too long syn_write_block len %d\n", len);
return -EIO;
}
mutex_lock(&picodlp_i2c_data->xfer_lock);
msg.addr = client->addr;
msg.flags = 0;
msg.len = len;
msg.buf = data;
r = i2c_transfer(client->adapter, &msg, msg_count);
mutex_unlock(&picodlp_i2c_data->xfer_lock);
/*
* i2c_transfer returns:
* number of messages sent in case of success
* a negative error number in case of failure
*/
if (r != msg_count)
goto err;
/* In case of success */
for (i = 0; i < len; i++)
dev_dbg(&client->dev,
"addr %x bw 0x%02x[%d]: 0x%02x\n",
client->addr, data[0] + i, i, data[i]);
return 0;
err:
dev_err(&client->dev, "picodlp_i2c_write error\n");
return r;
}
static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
{
u8 data[5];
int i;
data[0] = reg;
for (i = 1; i < 5; i++)
data[i] = (value >> (32 - (i) * 8)) & 0xFF;
return picodlp_i2c_write_block(client, data, 5);
}
static int picodlp_i2c_write_array(struct i2c_client *client,
const struct picodlp_i2c_command commands[],
int count)
{
int i, r = 0;
for (i = 0; i < count; i++) {
r = picodlp_i2c_write(client, commands[i].reg,
commands[i].value);
if (r)
return r;
}
return r;
}
static int picodlp_wait_for_dma_done(struct i2c_client *client)
{
u8 trial = 100;
do {
msleep(1);
if (!trial--)
return -ETIMEDOUT;
} while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
return 0;
}
/**
* picodlp_i2c_init: i2c_initialization routine
* client: i2c_client for communication
*
* return
* 0 : Success, no error
* error code : Failure
*/
static int picodlp_i2c_init(struct i2c_client *client)
{
int r;
static const struct picodlp_i2c_command init_cmd_set1[] = {
{SOFT_RESET, 1},
{DMD_PARK_TRIGGER, 1},
{MISC_REG, 5},
{SEQ_CONTROL, 0},
{SEQ_VECTOR, 0x100},
{DMD_BLOCK_COUNT, 7},
{DMD_VCC_CONTROL, 0x109},
{DMD_PARK_PULSE_COUNT, 0xA},
{DMD_PARK_PULSE_WIDTH, 0xB},
{DMD_PARK_DELAY, 0x2ED},
{DMD_SHADOW_ENABLE, 0},
{FLASH_OPCODE, 0xB},
{FLASH_DUMMY_BYTES, 1},
{FLASH_ADDR_BYTES, 3},
{PBC_CONTROL, 0},
{FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
{FLASH_READ_BYTES, CMT_LUT_0_SIZE},
{CMT_SPLASH_LUT_START_ADDR, 0},
{CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
{PBC_CONTROL, 1},
};
static const struct picodlp_i2c_command init_cmd_set2[] = {
{PBC_CONTROL, 0},
{CMT_SPLASH_LUT_DEST_SELECT, 0},
{PBC_CONTROL, 0},
{FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
{FLASH_READ_BYTES, SEQUENCE_0_SIZE},
{SEQ_RESET_LUT_START_ADDR, 0},
{SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
{PBC_CONTROL, 1},
};
static const struct picodlp_i2c_command init_cmd_set3[] = {
{PBC_CONTROL, 0},
{SEQ_RESET_LUT_DEST_SELECT, 0},
{PBC_CONTROL, 0},
{FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
{FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
{SEQ_RESET_LUT_START_ADDR, 0},
{SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
{PBC_CONTROL, 1},
};
static const struct picodlp_i2c_command init_cmd_set4[] = {
{PBC_CONTROL, 0},
{SEQ_RESET_LUT_DEST_SELECT, 0},
{SDC_ENABLE, 1},
{AGC_CTRL, 7},
{CCA_C1A, 0x100},
{CCA_C1B, 0x0},
{CCA_C1C, 0x0},
{CCA_C2A, 0x0},
{CCA_C2B, 0x100},
{CCA_C2C, 0x0},
{CCA_C3A, 0x0},
{CCA_C3B, 0x0},
{CCA_C3C, 0x100},
{CCA_C7A, 0x100},
{CCA_C7B, 0x100},
{CCA_C7C, 0x100},
{CCA_ENABLE, 1},
{CPU_IF_MODE, 1},
{SHORT_FLIP, 1},
{CURTAIN_CONTROL, 0},
{DMD_PARK_TRIGGER, 0},
{R_DRIVE_CURRENT, 0x298},
{G_DRIVE_CURRENT, 0x298},
{B_DRIVE_CURRENT, 0x298},
{RGB_DRIVER_ENABLE, 7},
{SEQ_CONTROL, 0},
{ACTGEN_CONTROL, 0x10},
{SEQUENCE_MODE, SEQ_LOCK},
{DATA_FORMAT, RGB888},
{INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
{INPUT_SOURCE, PARALLEL_RGB},
{CPU_IF_SYNC_METHOD, 1},
{SEQ_CONTROL, 1}
};
r = picodlp_i2c_write_array(client, init_cmd_set1,
ARRAY_SIZE(init_cmd_set1));
if (r)
return r;
r = picodlp_wait_for_dma_done(client);
if (r)
return r;
r = picodlp_i2c_write_array(client, init_cmd_set2,
ARRAY_SIZE(init_cmd_set2));
if (r)
return r;
r = picodlp_wait_for_dma_done(client);
if (r)
return r;
r = picodlp_i2c_write_array(client, init_cmd_set3,
ARRAY_SIZE(init_cmd_set3));
if (r)
return r;
r = picodlp_wait_for_dma_done(client);
if (r)
return r;
r = picodlp_i2c_write_array(client, init_cmd_set4,
ARRAY_SIZE(init_cmd_set4));
if (r)
return r;
return 0;
}
static int picodlp_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct picodlp_i2c_data *picodlp_i2c_data;
picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
if (!picodlp_i2c_data)
return -ENOMEM;
mutex_init(&picodlp_i2c_data->xfer_lock);
i2c_set_clientdata(client, picodlp_i2c_data);
return 0;
}
static int picodlp_i2c_remove(struct i2c_client *client)
{
struct picodlp_i2c_data *picodlp_i2c_data =
i2c_get_clientdata(client);
kfree(picodlp_i2c_data);
return 0;
}
static struct i2c_driver picodlp_i2c_driver = {
.driver = {
.name = "picodlp_i2c_driver",
},
.probe = picodlp_i2c_probe,
.remove = picodlp_i2c_remove,
.id_table = picodlp_i2c_id,
};
static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
{
int r, trial = 100;
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
if (dssdev->platform_enable) {
r = dssdev->platform_enable(dssdev);
if (r)
return r;
}
gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
msleep(1);
gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
if (!trial--) {
dev_err(&dssdev->dev, "emu_done signal not"
" going high\n");
return -ETIMEDOUT;
}
msleep(5);
}
/*
* As per dpp2600 programming guide,
* it is required to sleep for 1000ms after emu_done signal goes high
* then only i2c commands can be successfully sent to dpp2600
*/
msleep(1000);
r = omapdss_dpi_display_enable(dssdev);
if (r) {
dev_err(&dssdev->dev, "failed to enable DPI\n");
goto err1;
}
r = picodlp_i2c_init(picod->picodlp_i2c_client);
if (r)
goto err;
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
return r;
err:
omapdss_dpi_display_disable(dssdev);
err1:
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
return r;
}
static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
{
struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
omapdss_dpi_display_disable(dssdev);
gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
if (dssdev->platform_disable)
dssdev->platform_disable(dssdev);
}
static int picodlp_panel_probe(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod;
struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
struct i2c_adapter *adapter;
struct i2c_client *picodlp_i2c_client;
int r = 0, picodlp_adapter_id;
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF |
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS;
dssdev->panel.acb = 0x0;
dssdev->panel.timings = pico_ls_timings;
picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
if (!picod)
return -ENOMEM;
mutex_init(&picod->lock);
picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
adapter = i2c_get_adapter(picodlp_adapter_id);
if (!adapter) {
dev_err(&dssdev->dev, "can't get i2c adapter\n");
r = -ENODEV;
goto err;
}
picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
if (!picodlp_i2c_client) {
dev_err(&dssdev->dev, "can't add i2c device::"
" picodlp_i2c_client is NULL\n");
r = -ENODEV;
goto err;
}
picod->picodlp_i2c_client = picodlp_i2c_client;
dev_set_drvdata(&dssdev->dev, picod);
return r;
err:
kfree(picod);
return r;
}
static void picodlp_panel_remove(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
i2c_unregister_device(picod->picodlp_i2c_client);
dev_set_drvdata(&dssdev->dev, NULL);
dev_dbg(&dssdev->dev, "removing picodlp panel\n");
kfree(picod);
}
static int picodlp_panel_enable(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
int r;
dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
mutex_lock(&picod->lock);
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
mutex_unlock(&picod->lock);
return -EINVAL;
}
r = picodlp_panel_power_on(dssdev);
mutex_unlock(&picod->lock);
return r;
}
static void picodlp_panel_disable(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
mutex_lock(&picod->lock);
/* Turn off DLP Power */
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
picodlp_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
mutex_unlock(&picod->lock);
dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
}
static int picodlp_panel_suspend(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
mutex_lock(&picod->lock);
/* Turn off DLP Power */
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
mutex_unlock(&picod->lock);
dev_err(&dssdev->dev, "unable to suspend picodlp panel,"
" panel is not ACTIVE\n");
return -EINVAL;
}
picodlp_panel_power_off(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
mutex_unlock(&picod->lock);
dev_dbg(&dssdev->dev, "suspending picodlp panel\n");
return 0;
}
static int picodlp_panel_resume(struct omap_dss_device *dssdev)
{
struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
int r;
mutex_lock(&picod->lock);
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
mutex_unlock(&picod->lock);
dev_err(&dssdev->dev, "unable to resume picodlp panel,"
" panel is not ACTIVE\n");
return -EINVAL;
}
r = picodlp_panel_power_on(dssdev);
mutex_unlock(&picod->lock);
dev_dbg(&dssdev->dev, "resuming picodlp panel\n");
return r;
}
static void picodlp_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres)
{
*xres = dssdev->panel.timings.x_res;
*yres = dssdev->panel.timings.y_res;
}
static struct omap_dss_driver picodlp_driver = {
.probe = picodlp_panel_probe,
.remove = picodlp_panel_remove,
.enable = picodlp_panel_enable,
.disable = picodlp_panel_disable,
.get_resolution = picodlp_get_resolution,
.suspend = picodlp_panel_suspend,
.resume = picodlp_panel_resume,
.driver = {
.name = "picodlp_panel",
.owner = THIS_MODULE,
},
};
static int __init picodlp_init(void)
{
int r = 0;
r = i2c_add_driver(&picodlp_i2c_driver);
if (r) {
printk(KERN_WARNING "picodlp_i2c_driver" \
" registration failed\n");
return r;
}
r = omap_dss_register_driver(&picodlp_driver);
if (r)
i2c_del_driver(&picodlp_i2c_driver);
return r;
}
static void __exit picodlp_exit(void)
{
i2c_del_driver(&picodlp_i2c_driver);
omap_dss_unregister_driver(&picodlp_driver);
}
module_init(picodlp_init);
module_exit(picodlp_exit);
MODULE_AUTHOR("Mythri P K <[email protected]>");
MODULE_DESCRIPTION("picodlp driver");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,288 @@
/*
* Header file required by picodlp panel driver
*
* Copyright (C) 2009-2011 Texas Instruments
* Author: Mythri P K <mythripk@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H
#define __OMAP2_DISPLAY_PANEL_PICODLP_H
/* Commands used for configuring picodlp panel */
#define MAIN_STATUS 0x03
#define PBC_CONTROL 0x08
#define INPUT_SOURCE 0x0B
#define INPUT_RESOLUTION 0x0C
#define DATA_FORMAT 0x0D
#define IMG_ROTATION 0x0E
#define LONG_FLIP 0x0F
#define SHORT_FLIP 0x10
#define TEST_PAT_SELECT 0x11
#define R_DRIVE_CURRENT 0x12
#define G_DRIVE_CURRENT 0x13
#define B_DRIVE_CURRENT 0x14
#define READ_REG_SELECT 0x15
#define RGB_DRIVER_ENABLE 0x16
#define CPU_IF_MODE 0x18
#define FRAME_RATE 0x19
#define CPU_IF_SYNC_METHOD 0x1A
#define CPU_IF_SOF 0x1B
#define CPU_IF_EOF 0x1C
#define CPU_IF_SLEEP 0x1D
#define SEQUENCE_MODE 0x1E
#define SOFT_RESET 0x1F
#define FRONT_END_RESET 0x21
#define AUTO_PWR_ENABLE 0x22
#define VSYNC_LINE_DELAY 0x23
#define CPU_PI_HORIZ_START 0x24
#define CPU_PI_VERT_START 0x25
#define CPU_PI_HORIZ_WIDTH 0x26
#define CPU_PI_VERT_HEIGHT 0x27
#define PIXEL_MASK_CROP 0x28
#define CROP_FIRST_LINE 0x29
#define CROP_LAST_LINE 0x2A
#define CROP_FIRST_PIXEL 0x2B
#define CROP_LAST_PIXEL 0x2C
#define DMD_PARK_TRIGGER 0x2D
#define MISC_REG 0x30
/* AGC registers */
#define AGC_CTRL 0x50
#define AGC_CLIPPED_PIXS 0x55
#define AGC_BRIGHT_PIXS 0x56
#define AGC_BG_PIXS 0x57
#define AGC_SAFETY_MARGIN 0x17
/* Color Coordinate Adjustment registers */
#define CCA_ENABLE 0x5E
#define CCA_C1A 0x5F
#define CCA_C1B 0x60
#define CCA_C1C 0x61
#define CCA_C2A 0x62
#define CCA_C2B 0x63
#define CCA_C2C 0x64
#define CCA_C3A 0x65
#define CCA_C3B 0x66
#define CCA_C3C 0x67
#define CCA_C7A 0x71
#define CCA_C7B 0x72
#define CCA_C7C 0x73
/**
* DLP Pico Processor 2600 comes with flash
* We can do DMA operations from flash for accessing Look Up Tables
*/
#define DMA_STATUS 0x100
#define FLASH_ADDR_BYTES 0x74
#define FLASH_DUMMY_BYTES 0x75
#define FLASH_WRITE_BYTES 0x76
#define FLASH_READ_BYTES 0x77
#define FLASH_OPCODE 0x78
#define FLASH_START_ADDR 0x79
#define FLASH_DUMMY2 0x7A
#define FLASH_WRITE_DATA 0x7B
#define TEMPORAL_DITH_DISABLE 0x7E
#define SEQ_CONTROL 0x82
#define SEQ_VECTOR 0x83
/* DMD is Digital Micromirror Device */
#define DMD_BLOCK_COUNT 0x84
#define DMD_VCC_CONTROL 0x86
#define DMD_PARK_PULSE_COUNT 0x87
#define DMD_PARK_PULSE_WIDTH 0x88
#define DMD_PARK_DELAY 0x89
#define DMD_SHADOW_ENABLE 0x8E
#define SEQ_STATUS 0x8F
#define FLASH_CLOCK_CONTROL 0x98
#define DMD_PARK 0x2D
#define SDRAM_BIST_ENABLE 0x46
#define DDR_DRIVER_STRENGTH 0x9A
#define SDC_ENABLE 0x9D
#define SDC_BUFF_SWAP_DISABLE 0xA3
#define CURTAIN_CONTROL 0xA6
#define DDR_BUS_SWAP_ENABLE 0xA7
#define DMD_TRC_ENABLE 0xA8
#define DMD_BUS_SWAP_ENABLE 0xA9
#define ACTGEN_ENABLE 0xAE
#define ACTGEN_CONTROL 0xAF
#define ACTGEN_HORIZ_BP 0xB0
#define ACTGEN_VERT_BP 0xB1
/* Look Up Table access */
#define CMT_SPLASH_LUT_START_ADDR 0xFA
#define CMT_SPLASH_LUT_DEST_SELECT 0xFB
#define CMT_SPLASH_LUT_DATA 0xFC
#define SEQ_RESET_LUT_START_ADDR 0xFD
#define SEQ_RESET_LUT_DEST_SELECT 0xFE
#define SEQ_RESET_LUT_DATA 0xFF
/* Input source definitions */
#define PARALLEL_RGB 0
#define INT_TEST_PATTERN 1
#define SPLASH_SCREEN 2
#define CPU_INTF 3
#define BT656 4
/* Standard input resolution definitions */
#define QWVGA_LANDSCAPE 3 /* (427h*240v) */
#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */
#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */
/* Standard data format definitions */
#define RGB565 0
#define RGB666 1
#define RGB888 2
/* Test Pattern definitions */
#define TPG_CHECKERBOARD 0
#define TPG_BLACK 1
#define TPG_WHITE 2
#define TPG_RED 3
#define TPG_BLUE 4
#define TPG_GREEN 5
#define TPG_VLINES_BLACK 6
#define TPG_HLINES_BLACK 7
#define TPG_VLINES_ALT 8
#define TPG_HLINES_ALT 9
#define TPG_DIAG_LINES 10
#define TPG_GREYRAMP_VERT 11
#define TPG_GREYRAMP_HORIZ 12
#define TPG_ANSI_CHECKERBOARD 13
/* sequence mode definitions */
#define SEQ_FREE_RUN 0
#define SEQ_LOCK 1
/* curtain color definitions */
#define CURTAIN_BLACK 0
#define CURTAIN_RED 1
#define CURTAIN_GREEN 2
#define CURTAIN_BLUE 3
#define CURTAIN_YELLOW 4
#define CURTAIN_MAGENTA 5
#define CURTAIN_CYAN 6
#define CURTAIN_WHITE 7
/* LUT definitions */
#define CMT_LUT_NONE 0
#define CMT_LUT_GREEN 1
#define CMT_LUT_RED 2
#define CMT_LUT_BLUE 3
#define CMT_LUT_ALL 4
#define SPLASH_LUT 5
#define SEQ_LUT_NONE 0
#define SEQ_DRC_LUT_0 1
#define SEQ_DRC_LUT_1 2
#define SEQ_DRC_LUT_2 3
#define SEQ_DRC_LUT_3 4
#define SEQ_SEQ_LUT 5
#define SEQ_DRC_LUT_ALL 6
#define WPC_PROGRAM_LUT 7
#define BITSTREAM_START_ADDR 0x00000000
#define BITSTREAM_SIZE 0x00040000
#define WPC_FW_0_START_ADDR 0x00040000
#define WPC_FW_0_SIZE 0x00000ce8
#define SEQUENCE_0_START_ADDR 0x00044000
#define SEQUENCE_0_SIZE 0x00001000
#define SEQUENCE_1_START_ADDR 0x00045000
#define SEQUENCE_1_SIZE 0x00000d10
#define SEQUENCE_2_START_ADDR 0x00046000
#define SEQUENCE_2_SIZE 0x00000d10
#define SEQUENCE_3_START_ADDR 0x00047000
#define SEQUENCE_3_SIZE 0x00000d10
#define SEQUENCE_4_START_ADDR 0x00048000
#define SEQUENCE_4_SIZE 0x00000d10
#define SEQUENCE_5_START_ADDR 0x00049000
#define SEQUENCE_5_SIZE 0x00000d10
#define SEQUENCE_6_START_ADDR 0x0004a000
#define SEQUENCE_6_SIZE 0x00000d10
#define CMT_LUT_0_START_ADDR 0x0004b200
#define CMT_LUT_0_SIZE 0x00000600
#define CMT_LUT_1_START_ADDR 0x0004b800
#define CMT_LUT_1_SIZE 0x00000600
#define CMT_LUT_2_START_ADDR 0x0004be00
#define CMT_LUT_2_SIZE 0x00000600
#define CMT_LUT_3_START_ADDR 0x0004c400
#define CMT_LUT_3_SIZE 0x00000600
#define CMT_LUT_4_START_ADDR 0x0004ca00
#define CMT_LUT_4_SIZE 0x00000600
#define CMT_LUT_5_START_ADDR 0x0004d000
#define CMT_LUT_5_SIZE 0x00000600
#define CMT_LUT_6_START_ADDR 0x0004d600
#define CMT_LUT_6_SIZE 0x00000600
#define DRC_TABLE_0_START_ADDR 0x0004dc00
#define DRC_TABLE_0_SIZE 0x00000100
#define SPLASH_0_START_ADDR 0x0004dd00
#define SPLASH_0_SIZE 0x00032280
#define SEQUENCE_7_START_ADDR 0x00080000
#define SEQUENCE_7_SIZE 0x00000d10
#define SEQUENCE_8_START_ADDR 0x00081800
#define SEQUENCE_8_SIZE 0x00000d10
#define SEQUENCE_9_START_ADDR 0x00083000
#define SEQUENCE_9_SIZE 0x00000d10
#define CMT_LUT_7_START_ADDR 0x0008e000
#define CMT_LUT_7_SIZE 0x00000600
#define CMT_LUT_8_START_ADDR 0x0008e800
#define CMT_LUT_8_SIZE 0x00000600
#define CMT_LUT_9_START_ADDR 0x0008f000
#define CMT_LUT_9_SIZE 0x00000600
#define SPLASH_1_START_ADDR 0x0009a000
#define SPLASH_1_SIZE 0x00032280
#define SPLASH_2_START_ADDR 0x000cd000
#define SPLASH_2_SIZE 0x00032280
#define SPLASH_3_START_ADDR 0x00100000
#define SPLASH_3_SIZE 0x00032280
#define OPT_SPLASH_0_START_ADDR 0x00134000
#define OPT_SPLASH_0_SIZE 0x000cb100
#endif

View file

@ -35,26 +35,12 @@
#include <video/omapdss.h>
#include <video/omap-panel-nokia-dsi.h>
#include <video/mipi_display.h>
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
#define DCS_READ_NUM_ERRORS 0x05
#define DCS_READ_POWER_MODE 0x0a
#define DCS_READ_MADCTL 0x0b
#define DCS_READ_PIXEL_FORMAT 0x0c
#define DCS_RDDSDR 0x0f
#define DCS_SLEEP_IN 0x10
#define DCS_SLEEP_OUT 0x11
#define DCS_DISPLAY_OFF 0x28
#define DCS_DISPLAY_ON 0x29
#define DCS_COLUMN_ADDR 0x2a
#define DCS_PAGE_ADDR 0x2b
#define DCS_MEMORY_WRITE 0x2c
#define DCS_TEAR_OFF 0x34
#define DCS_TEAR_ON 0x35
#define DCS_MEM_ACC_CTRL 0x36
#define DCS_PIXEL_FORMAT 0x3a
#define DCS_BRIGHTNESS 0x51
#define DCS_CTRL_DISPLAY 0x53
#define DCS_WRITE_CABC 0x55
@ -222,8 +208,6 @@ struct taal_data {
struct delayed_work te_timeout_work;
bool use_dsi_bl;
bool cabc_broken;
unsigned cabc_mode;
@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td)
hw_guard_wait(td);
cmd = DCS_SLEEP_IN;
cmd = MIPI_DCS_ENTER_SLEEP_MODE;
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
if (r)
return r;
@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td)
hw_guard_wait(td);
r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE);
if (r)
return r;
@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
u8 mode;
int b5, b6, b7;
r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode);
if (r)
return r;
@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
mode &= ~((1<<7) | (1<<6) | (1<<5));
mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode);
}
static int taal_set_update_window(struct taal_data *td,
@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td,
u16 y2 = y + h - 1;
u8 buf[5];
buf[0] = DCS_COLUMN_ADDR;
buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
buf[1] = (x1 >> 8) & 0xff;
buf[2] = (x1 >> 0) & 0xff;
buf[3] = (x2 >> 8) & 0xff;
@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td,
if (r)
return r;
buf[0] = DCS_PAGE_ADDR;
buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
buf[1] = (y1 >> 8) & 0xff;
buf[2] = (y1 >> 0) & 0xff;
buf[3] = (y2 >> 8) & 0xff;
@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
int level;
@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev)
mutex_lock(&td->lock);
if (td->use_dsi_bl) {
if (td->enabled) {
dsi_bus_lock(dssdev);
if (td->enabled) {
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (!r)
r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
r = taal_wake_up(dssdev);
if (!r)
r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
dsi_bus_unlock(dssdev);
} else {
r = 0;
}
dsi_bus_unlock(dssdev);
} else {
if (!panel_data->set_backlight)
r = -EINVAL;
else
r = panel_data->set_backlight(dssdev, level);
r = 0;
}
mutex_unlock(&td->lock);
@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
{
struct backlight_properties props;
struct taal_data *td;
struct backlight_device *bldev;
struct backlight_device *bldev = NULL;
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
struct panel_config *panel_config = NULL;
int r, i;
@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
dssdev->panel.config = OMAP_DSS_LCD_TFT;
dssdev->panel.timings = panel_config->timings;
dssdev->ctrl.pixel_size = 24;
dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
td = kzalloc(sizeof(*td), GFP_KERNEL);
if (!td) {
@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
/* if no platform set_backlight() defined, presume DSI backlight
* control */
memset(&props, 0, sizeof(struct backlight_properties));
if (!panel_data->set_backlight)
td->use_dsi_bl = true;
if (td->use_dsi_bl)
if (panel_data->use_dsi_backlight) {
memset(&props, 0, sizeof(struct backlight_properties));
props.max_brightness = 255;
else
props.max_brightness = 127;
props.type = BACKLIGHT_RAW;
bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
dssdev, &taal_bl_ops, &props);
if (IS_ERR(bldev)) {
r = PTR_ERR(bldev);
goto err_bl;
}
props.type = BACKLIGHT_RAW;
bldev = backlight_device_register(dev_name(&dssdev->dev),
&dssdev->dev, dssdev, &taal_bl_ops, &props);
if (IS_ERR(bldev)) {
r = PTR_ERR(bldev);
goto err_bl;
}
td->bldev = bldev;
td->bldev = bldev;
bldev->props.fb_blank = FB_BLANK_UNBLANK;
bldev->props.power = FB_BLANK_UNBLANK;
if (td->use_dsi_bl)
bldev->props.fb_blank = FB_BLANK_UNBLANK;
bldev->props.power = FB_BLANK_UNBLANK;
bldev->props.brightness = 255;
else
bldev->props.brightness = 127;
taal_bl_update_status(bldev);
taal_bl_update_status(bldev);
}
if (panel_data->use_ext_te) {
int gpio = panel_data->ext_te_gpio;
@ -1067,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
gpio_direction_input(gpio);
r = request_irq(gpio_to_irq(gpio), taal_te_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING,
IRQF_TRIGGER_RISING,
"taal vsync", dssdev);
if (r) {
@ -1111,7 +1078,8 @@ err_irq:
if (panel_data->use_ext_te)
gpio_free(panel_data->ext_te_gpio);
err_gpio:
backlight_device_unregister(bldev);
if (bldev != NULL)
backlight_device_unregister(bldev);
err_bl:
destroy_workqueue(td->workqueue);
err_wq:
@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
}
bldev = td->bldev;
bldev->props.power = FB_BLANK_POWERDOWN;
taal_bl_update_status(bldev);
backlight_device_unregister(bldev);
if (bldev != NULL) {
bldev->props.power = FB_BLANK_POWERDOWN;
taal_bl_update_status(bldev);
backlight_device_unregister(bldev);
}
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
if (r)
goto err;
r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT,
MIPI_DCS_PIXEL_FMT_24BIT);
if (r)
goto err;
@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
goto err;
}
r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON);
if (r)
goto err;
@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int r;
r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
if (!r)
r = taal_sleep_in(td);
@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
int r;
if (enable)
r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
else
r = taal_dcs_write_0(td, DCS_TEAR_OFF);
r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
if (!panel_data->use_ext_te)
omapdss_dsi_enable_te(dssdev, enable);
@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2);
if (r) {
dev_err(&dssdev->dev, "failed to read Taal status\n");
goto err;
@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
/* Self-diagnostics result is also shown on TE GPIO line. We need
* to re-enable TE after self diagnostics */
if (td->te_enabled && panel_data->use_ext_te) {
r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
if (r)
goto err;
}

View file

@ -1,5 +1,5 @@
menuconfig OMAP2_DSS
tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
tristate "OMAP2+ Display Subsystem support"
depends on ARCH_OMAP2PLUS
help
OMAP2+ Display Subsystem support.

View file

@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
hdmi_omap4_panel.o
hdmi_panel.o ti_hdmi_4xxx_ip.o

View file

@ -144,6 +144,10 @@ static int dss_initialize_debugfs(void)
#ifdef CONFIG_OMAP2_DSS_VENC
debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
&venc_dump_regs, &dss_debug_fops);
#endif
#ifdef CONFIG_OMAP4_DSS_HDMI
debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
&hdmi_dump_regs, &dss_debug_fops);
#endif
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
return 0x00BC;
case OMAP_DSS_VIDEO2:
return 0x014C;
case OMAP_DSS_VIDEO3:
return 0x0300;
default:
BUG();
}
@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0000;
case OMAP_DSS_VIDEO3:
return 0x0008;
default:
BUG();
}
@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0004;
case OMAP_DSS_VIDEO3:
return 0x000C;
default:
BUG();
}
@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
return 0x0544;
case OMAP_DSS_VIDEO2:
return 0x04BC;
case OMAP_DSS_VIDEO3:
return 0x0310;
default:
BUG();
}
@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
return 0x0548;
case OMAP_DSS_VIDEO2:
return 0x04C0;
case OMAP_DSS_VIDEO3:
return 0x0314;
default:
BUG();
}
@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0008;
case OMAP_DSS_VIDEO3:
return 0x009C;
default:
BUG();
}
@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x000C;
case OMAP_DSS_VIDEO3:
return 0x00A8;
default:
BUG();
}
@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0010;
case OMAP_DSS_VIDEO3:
return 0x0070;
default:
BUG();
}
@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
return 0x0568;
case OMAP_DSS_VIDEO2:
return 0x04DC;
case OMAP_DSS_VIDEO3:
return 0x032C;
default:
BUG();
}
@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0014;
case OMAP_DSS_VIDEO3:
return 0x008C;
default:
BUG();
}
@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0018;
case OMAP_DSS_VIDEO3:
return 0x0088;
default:
BUG();
}
@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x001C;
case OMAP_DSS_VIDEO3:
return 0x00A4;
default:
BUG();
}
@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0020;
case OMAP_DSS_VIDEO3:
return 0x0098;
default:
BUG();
}
@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
return 0x0034;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
case OMAP_DSS_VIDEO3:
BUG();
default:
BUG();
@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
return 0x0038;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
case OMAP_DSS_VIDEO3:
BUG();
default:
BUG();
@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0024;
case OMAP_DSS_VIDEO3:
return 0x0090;
default:
BUG();
}
@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
return 0x0580;
case OMAP_DSS_VIDEO2:
return 0x055C;
case OMAP_DSS_VIDEO3:
return 0x0424;
default:
BUG();
}
@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0028;
case OMAP_DSS_VIDEO3:
return 0x0094;
default:
BUG();
}
@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x002C;
case OMAP_DSS_VIDEO3:
return 0x0000;
default:
BUG();
}
@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
return 0x0584;
case OMAP_DSS_VIDEO2:
return 0x0560;
case OMAP_DSS_VIDEO3:
return 0x0428;
default:
BUG();
}
@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0030;
case OMAP_DSS_VIDEO3:
return 0x0004;
default:
BUG();
}
@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
return 0x0588;
case OMAP_DSS_VIDEO2:
return 0x0564;
case OMAP_DSS_VIDEO3:
return 0x042C;
default:
BUG();
}
@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0034 + i * 0x8;
case OMAP_DSS_VIDEO3:
return 0x0010 + i * 0x8;
default:
BUG();
}
@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
return 0x058C + i * 0x8;
case OMAP_DSS_VIDEO2:
return 0x0568 + i * 0x8;
case OMAP_DSS_VIDEO3:
return 0x0430 + i * 0x8;
default:
BUG();
}
@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0038 + i * 0x8;
case OMAP_DSS_VIDEO3:
return 0x0014 + i * 0x8;
default:
BUG();
}
@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
return 0x0590 + i * 8;
case OMAP_DSS_VIDEO2:
return 0x056C + i * 0x8;
case OMAP_DSS_VIDEO3:
return 0x0434 + i * 0x8;
default:
BUG();
}
@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
case OMAP_DSS_VIDEO3:
return 0x0074 + i * 0x4;
default:
BUG();
@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
return 0x0124 + i * 0x4;
case OMAP_DSS_VIDEO2:
return 0x00B4 + i * 0x4;
case OMAP_DSS_VIDEO3:
return 0x0050 + i * 0x4;
default:
BUG();
}
@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
return 0x05CC + i * 0x4;
case OMAP_DSS_VIDEO2:
return 0x05A8 + i * 0x4;
case OMAP_DSS_VIDEO3:
return 0x0470 + i * 0x4;
default:
BUG();
}
@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
return 0x0174;
case OMAP_DSS_VIDEO2:
return 0x00E8;
case OMAP_DSS_VIDEO3:
return 0x00A0;
default:
BUG();
}

View file

@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev,
const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
int r, enabled;
int r;
bool enabled;
r = kstrtoint(buf, 0, &enabled);
r = strtobool(buf, &enabled);
if (r)
return r;
enabled = !!enabled;
if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
if (enabled) {
r = dssdev->driver->enable(dssdev);
@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
int te, r;
int r;
bool te;
if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
return -ENOENT;
r = kstrtoint(buf, 0, &te);
r = strtobool(buf, &te);
if (r)
return r;
te = !!te;
r = dssdev->driver->enable_te(dssdev, te);
if (r)
return r;
@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
int mirror, r;
int r;
bool mirror;
if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
return -ENOENT;
r = kstrtoint(buf, 0, &mirror);
r = strtobool(buf, &mirror);
if (r)
return r;
mirror = !!mirror;
r = dssdev->driver->set_mirror(dssdev, mirror);
if (r)
return r;
@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
return 16;
case OMAP_DISPLAY_TYPE_DBI:
case OMAP_DISPLAY_TYPE_DSI:
if (dssdev->ctrl.pixel_size == 24)
return 24;
else
return 16;
case OMAP_DISPLAY_TYPE_DSI:
if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16)
return 24;
else
return 16;
case OMAP_DISPLAY_TYPE_VENC:
case OMAP_DISPLAY_TYPE_SDI:
case OMAP_DISPLAY_TYPE_HDMI:
@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
bpp = 24;
break;
case OMAP_DISPLAY_TYPE_DBI:
case OMAP_DISPLAY_TYPE_DSI:
bpp = dssdev->ctrl.pixel_size;
break;
case OMAP_DISPLAY_TYPE_DSI:
bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
break;
default:
BUG();
}

View file

@ -82,9 +82,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
return r;
}
*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
*lck_div = dispc_cinfo.lck_div;
@ -109,7 +111,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
if (r)
return r;
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
return r;
@ -129,7 +131,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
bool is_tft;
int r = 0;
dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
@ -153,7 +155,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
t->pixel_clock = pck;
}
dispc_set_lcd_timings(dssdev->manager->id, t);
dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
return 0;
}
@ -164,11 +166,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev)
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
dispc_set_parallel_interface_mode(dssdev->manager->id,
OMAP_DSS_PARALLELMODE_BYPASS);
dispc_set_lcd_display_type(dssdev->manager->id, is_tft ?
dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
dispc_mgr_enable_stallmode(dssdev->manager->id, false);
dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ?
OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
dispc_set_tft_data_lines(dssdev->manager->id,
dispc_mgr_set_tft_data_lines(dssdev->manager->id,
dssdev->phy.dpi.data_lines);
}
@ -176,6 +179,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
{
int r;
if (dssdev->manager == NULL) {
DSSERR("failed to enable display: no manager\n");
return -ENODEV;
}
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@ -277,7 +285,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
}
dpi_set_mode(dssdev);
dispc_go(dssdev->manager->id);
dispc_mgr_go(dssdev->manager->id);
dispc_runtime_put();
dss_runtime_put();

File diff suppressed because it is too large Load diff

View file

@ -639,6 +639,17 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
}
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
{
enum omap_display_type displays;
displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
return DSS_VENC_TV_CLK;
return REG_GET(DSS_CONTROL, 15, 15);
}
static int dss_get_clocks(void)
{
struct clk *clk;
@ -691,11 +702,6 @@ static void dss_put_clocks(void)
clk_put(dss.dss_clk);
}
struct clk *dss_get_ick(void)
{
return clk_get(&dss.pdev->dev, "ick");
}
int dss_runtime_get(void)
{
int r;
@ -824,13 +830,11 @@ static int omap_dsshw_remove(struct platform_device *pdev)
static int dss_runtime_suspend(struct device *dev)
{
dss_save_context();
clk_disable(dss.dss_clk);
return 0;
}
static int dss_runtime_resume(struct device *dev)
{
clk_enable(dss.dss_clk);
dss_restore_context();
return 0;
}

View file

@ -97,10 +97,10 @@ extern unsigned int dss_debug;
#define FLD_MOD(orig, val, start, end) \
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
enum omap_parallel_interface_mode {
OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
OMAP_DSS_PARALLELMODE_DSI,
enum dss_io_pad_mode {
DSS_IO_PAD_MODE_RESET,
DSS_IO_PAD_MODE_RFBI,
DSS_IO_PAD_MODE_BYPASS,
};
enum dss_hdmi_venc_clk_source_select {
@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select {
DSS_HDMI_M_PCLK = 1,
};
enum dss_dsi_content_type {
DSS_DSI_CONTENT_DCS,
DSS_DSI_CONTENT_GENERIC,
};
struct dss_clock_info {
/* rates that we get with dividers below */
unsigned long fck;
@ -150,16 +155,6 @@ struct dsi_clock_info {
bool use_sys_clk;
};
/* HDMI PLL structure */
struct hdmi_pll_info {
u16 regn;
u16 regm;
u32 regmf;
u16 regm2;
u16 regsd;
u16 dcofreq;
};
struct seq_file;
struct platform_device;
@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void);
int dss_runtime_get(void);
void dss_runtime_put(void);
struct clk *dss_get_ick(void);
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
int dsi_init_display(struct omap_dss_device *display);
void dsi_irq_handler(void);
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
int dsi_pll_set_clock_div(struct platform_device *dsidev,
struct dsi_clock_info *cinfo);
@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev)
static inline void dsi_runtime_put(struct platform_device *dsidev)
{
}
static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
{
WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
return 0;
}
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
{
WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@ -385,90 +386,71 @@ void dispc_disable_sidle(void);
void dispc_lcd_enable_signal_polarity(bool act_high);
void dispc_lcd_enable_signal(bool enable);
void dispc_pck_free_enable(bool enable);
void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
void dispc_set_digit_size(u16 width, u16 height);
u32 dispc_get_plane_fifo_size(enum omap_plane plane);
void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
void dispc_enable_fifomerge(bool enable);
u32 dispc_get_burst_size(enum omap_plane plane);
void dispc_enable_cpr(enum omap_channel channel, bool enable);
void dispc_set_cpr_coef(enum omap_channel channel,
struct omap_dss_cpr_coefs *coefs);
void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
void dispc_set_channel_out(enum omap_plane plane,
enum omap_channel channel_out);
void dispc_enable_gamma_table(bool enable);
int dispc_setup_plane(enum omap_plane plane,
u32 paddr, u16 screen_width,
u16 pos_x, u16 pos_y,
u16 width, u16 height,
u16 out_width, u16 out_height,
enum omap_color_mode color_mode,
bool ilace,
enum omap_dss_rotation_type rotation_type,
u8 rotation, bool mirror,
u8 global_alpha, u8 pre_mult_alpha,
enum omap_channel channel,
u32 puv_addr);
bool dispc_go_busy(enum omap_channel channel);
void dispc_go(enum omap_channel channel);
void dispc_enable_channel(enum omap_channel channel, bool enable);
bool dispc_is_channel_enabled(enum omap_channel channel);
int dispc_enable_plane(enum omap_plane plane, bool enable);
void dispc_enable_replication(enum omap_plane plane, bool enable);
void dispc_set_parallel_interface_mode(enum omap_channel channel,
enum omap_parallel_interface_mode mode);
void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
void dispc_set_lcd_display_type(enum omap_channel channel,
enum omap_lcd_display_type type);
void dispc_set_loadmode(enum omap_dss_load_mode mode);
void dispc_set_default_color(enum omap_channel channel, u32 color);
u32 dispc_get_default_color(enum omap_channel channel);
void dispc_set_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type type,
u32 trans_key);
void dispc_get_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type *type,
u32 *trans_key);
void dispc_enable_trans_key(enum omap_channel ch, bool enable);
void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
bool dispc_trans_key_enabled(enum omap_channel ch);
bool dispc_alpha_blending_enabled(enum omap_channel ch);
bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
void dispc_set_lcd_timings(enum omap_channel channel,
struct omap_video_timings *timings);
unsigned long dispc_fclk_rate(void);
unsigned long dispc_lclk_rate(enum omap_channel channel);
unsigned long dispc_pclk_rate(enum omap_channel channel);
void dispc_set_pol_freq(enum omap_channel channel,
enum omap_panel_config config, u8 acbi, u8 acb);
void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
struct dispc_clock_info *cinfo);
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
struct dispc_clock_info *cinfo);
int dispc_set_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
int dispc_get_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
u32 dispc_ovl_get_burst_size(enum omap_plane plane);
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
bool ilace, enum omap_channel channel, bool replication,
u32 fifo_low, u32 fifo_high);
int dispc_ovl_enable(enum omap_plane plane, bool enable);
void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable);
void dispc_mgr_set_cpr_coef(enum omap_channel channel,
struct omap_dss_cpr_coefs *coefs);
bool dispc_mgr_go_busy(enum omap_channel channel);
void dispc_mgr_go(enum omap_channel channel);
void dispc_mgr_enable(enum omap_channel channel, bool enable);
bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
enum omap_lcd_display_type type);
void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
u32 dispc_mgr_get_default_color(enum omap_channel channel);
void dispc_mgr_set_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type type,
u32 trans_key);
void dispc_mgr_get_trans_key(enum omap_channel ch,
enum omap_dss_trans_key_type *type,
u32 *trans_key);
void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
void dispc_mgr_set_lcd_timings(enum omap_channel channel,
struct omap_video_timings *timings);
void dispc_mgr_set_pol_freq(enum omap_channel channel,
enum omap_panel_config config, u8 acbi, u8 acb);
unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
int dispc_mgr_set_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
int dispc_mgr_get_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
/* VENC */
#ifdef CONFIG_OMAP2_DSS_VENC
int venc_init_platform_driver(void);
void venc_uninit_platform_driver(void);
void venc_dump_regs(struct seq_file *s);
int venc_init_display(struct omap_dss_device *display);
unsigned long venc_get_pixel_clock(void);
#else
static inline int venc_init_platform_driver(void)
{
@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void)
static inline void venc_uninit_platform_driver(void)
{
}
static inline unsigned long venc_get_pixel_clock(void)
{
WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
return 0;
}
#endif
/* HDMI */
@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void)
int hdmi_init_platform_driver(void);
void hdmi_uninit_platform_driver(void);
int hdmi_init_display(struct omap_dss_device *dssdev);
unsigned long hdmi_get_pixel_clock(void);
void hdmi_dump_regs(struct seq_file *s);
#else
static inline int hdmi_init_display(struct omap_dss_device *dssdev)
{
@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void)
static inline void hdmi_uninit_platform_driver(void)
{
}
static inline unsigned long hdmi_get_pixel_clock(void)
{
WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
return 0;
}
#endif
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings);
int omapdss_hdmi_read_edid(u8 *buf, int len);
bool omapdss_hdmi_detect(void);
int hdmi_panel_init(void);
void hdmi_panel_exit(void);

View file

@ -47,6 +47,7 @@ struct omap_dss_features {
const int num_ovls;
const enum omap_display_type *supported_displays;
const enum omap_color_mode *supported_color_modes;
const enum omap_overlay_caps *overlay_caps;
const char * const *clksrc_names;
const struct dss_param_range *dss_params;
@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
OMAP_DSS_COLOR_RGBX32,
/* OMAP_DSS_VIDEO3 */
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
OMAP_DSS_COLOR_RGBX32,
};
static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
/* OMAP_DSS_GFX */
0,
/* OMAP_DSS_VIDEO1 */
OMAP_DSS_OVL_CAP_SCALE,
/* OMAP_DSS_VIDEO2 */
OMAP_DSS_OVL_CAP_SCALE,
};
static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
/* OMAP_DSS_GFX */
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
/* OMAP_DSS_VIDEO1 */
OMAP_DSS_OVL_CAP_SCALE,
/* OMAP_DSS_VIDEO2 */
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
};
static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
/* OMAP_DSS_GFX */
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
/* OMAP_DSS_VIDEO1 */
OMAP_DSS_OVL_CAP_SCALE,
/* OMAP_DSS_VIDEO2 */
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
};
static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
/* OMAP_DSS_GFX */
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
OMAP_DSS_OVL_CAP_ZORDER,
/* OMAP_DSS_VIDEO1 */
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
/* OMAP_DSS_VIDEO2 */
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
/* OMAP_DSS_VIDEO3 */
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
};
static const char * const omap2_dss_clk_source_names[] = {
@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = {
static const struct dss_param_range omap2_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
[FEAT_PARAM_DSS_PCD] = { 2, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 },
[FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
[FEAT_PARAM_DOWNSCALE] = { 1, 2 },
};
static const struct dss_param_range omap3_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
[FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
};
static const struct dss_param_range omap4_dss_param_range[] = {
[FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
};
/* OMAP2 DSS Features */
@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = {
.num_ovls = 3,
.supported_displays = omap2_dss_supported_displays,
.supported_color_modes = omap2_dss_supported_color_modes,
.overlay_caps = omap2_dss_overlay_caps,
.clksrc_names = omap2_dss_clk_source_names,
.dss_params = omap2_dss_param_range,
.buffer_size_unit = 1,
@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
FEAT_LCDENABLEPOL |
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
FEAT_FIR_COEF_V,
FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
.num_mgrs = 2,
.num_ovls = 3,
.supported_displays = omap3430_dss_supported_displays,
.supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3430_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.buffer_size_unit = 1,
@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
FEAT_LCDENABLEPOL |
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
FEAT_FIR_COEF_V,
FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER,
.num_mgrs = 2,
.num_ovls = 3,
.supported_displays = omap3630_dss_supported_displays,
.supported_color_modes = omap3_dss_supported_color_modes,
.overlay_caps = omap3630_dss_overlay_caps,
.clksrc_names = omap3_dss_clk_source_names,
.dss_params = omap3_dss_param_range,
.buffer_size_unit = 1,
@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_MGR_LCD2 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V |
FEAT_ALPHA_FREE_ZORDER,
.num_mgrs = 3,
.num_ovls = 3,
.num_ovls = 4,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.buffer_size_unit = 16,
@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = {
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_MGR_LCD2 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
FEAT_PRELOAD | FEAT_FIR_COEF_V,
FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
.num_mgrs = 3,
.num_ovls = 3,
.num_ovls = 4,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap4_dss_supported_color_modes,
.overlay_caps = omap4_dss_overlay_caps,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
.buffer_size_unit = 16,
.burst_size_unit = 16,
};
#if defined(CONFIG_OMAP4_DSS_HDMI)
/* HDMI OMAP4 Functions*/
static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
.video_configure = ti_hdmi_4xxx_basic_configure,
.phy_enable = ti_hdmi_4xxx_phy_enable,
.phy_disable = ti_hdmi_4xxx_phy_disable,
.read_edid = ti_hdmi_4xxx_read_edid,
.detect = ti_hdmi_4xxx_detect,
.pll_enable = ti_hdmi_4xxx_pll_enable,
.pll_disable = ti_hdmi_4xxx_pll_disable,
.video_enable = ti_hdmi_4xxx_wp_video_start,
.dump_wrapper = ti_hdmi_4xxx_wp_dump,
.dump_core = ti_hdmi_4xxx_core_dump,
.dump_pll = ti_hdmi_4xxx_pll_dump,
.dump_phy = ti_hdmi_4xxx_phy_dump,
};
void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
{
if (cpu_is_omap44xx())
ip_data->ops = &omap4_hdmi_functions;
}
#endif
/* Functions returning values related to a DSS feature */
int dss_feat_get_num_mgrs(void)
{
@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
return omap_current_dss_features->supported_color_modes[plane];
}
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
{
return omap_current_dss_features->overlay_caps[plane];
}
bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode)
{

View file

@ -20,16 +20,17 @@
#ifndef __OMAP2_DSS_FEATURES_H
#define __OMAP2_DSS_FEATURES_H
#if defined(CONFIG_OMAP4_DSS_HDMI)
#include "ti_hdmi.h"
#endif
#define MAX_DSS_MANAGERS 3
#define MAX_DSS_OVERLAYS 3
#define MAX_DSS_OVERLAYS 4
#define MAX_DSS_LCD_MANAGERS 2
#define MAX_NUM_DSI 2
/* DSS has feature id */
enum dss_feat_id {
FEAT_GLOBAL_ALPHA = 1 << 0,
FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
FEAT_PRE_MULT_ALPHA = 1 << 2,
FEAT_LCDENABLEPOL = 1 << 3,
FEAT_LCDENABLESIGNAL = 1 << 4,
FEAT_PCKFREEENABLE = 1 << 5,
@ -55,6 +56,8 @@ enum dss_feat_id {
FEAT_CPR = 1 << 23,
FEAT_PRELOAD = 1 << 24,
FEAT_FIR_COEF_V = 1 << 25,
FEAT_ALPHA_FIXED_ZORDER = 1 << 26,
FEAT_ALPHA_FREE_ZORDER = 1 << 27,
};
/* DSS register field id */
@ -75,12 +78,14 @@ enum dss_feat_reg_field {
enum dss_range_param {
FEAT_PARAM_DSS_FCK,
FEAT_PARAM_DSS_PCD,
FEAT_PARAM_DSIPLL_REGN,
FEAT_PARAM_DSIPLL_REGM,
FEAT_PARAM_DSIPLL_REGM_DISPC,
FEAT_PARAM_DSIPLL_REGM_DSI,
FEAT_PARAM_DSIPLL_FINT,
FEAT_PARAM_DSIPLL_LPDIV,
FEAT_PARAM_DOWNSCALE,
};
/* DSS Feature Functions */
@ -90,6 +95,7 @@ unsigned long dss_feat_get_param_min(enum dss_range_param param);
unsigned long dss_feat_get_param_max(enum dss_range_param param);
enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode);
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void); /* in bytes */
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
void dss_features_init(void);
#if defined(CONFIG_OMAP4_DSS_HDMI)
void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/*
* hdmi_omap4_panel.c
* hdmi_panel.c
*
* HDMI library support functions for TI OMAP4 processors.
*
@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/module.h>
#include <video/omapdss.h>
#include <linux/slab.h>
#include "dss.h"
@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev)
dssdev->panel.config = OMAP_DSS_LCD_TFT |
OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
/*
* Initialize the timings to 640 * 480
* This is only for framebuffer update not for TV timing setting
* Setting TV timing will be done only on enable
*/
dssdev->panel.timings.x_res = 640;
dssdev->panel.timings.y_res = 480;
dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31};
DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
dssdev->panel.timings.x_res,
@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
mutex_lock(&hdmi.hdmi_lock);
dssdev->panel.timings = *timings;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
/* turn the hdmi off and on to get new timings to use */
omapdss_hdmi_display_disable(dssdev);
omapdss_hdmi_display_set_timing(dssdev);
}
omapdss_hdmi_display_set_timing(dssdev);
mutex_unlock(&hdmi.hdmi_lock);
}
@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
mutex_lock(&hdmi.hdmi_lock);
r = omapdss_hdmi_display_check_timing(dssdev, timings);
if (r) {
DSSERR("Timing cannot be applied\n");
goto err;
mutex_unlock(&hdmi.hdmi_lock);
return r;
}
static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
{
int r;
mutex_lock(&hdmi.hdmi_lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
r = omapdss_hdmi_display_enable(dssdev);
if (r)
goto err;
}
r = omapdss_hdmi_read_edid(buf, len);
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
omapdss_hdmi_display_disable(dssdev);
err:
mutex_unlock(&hdmi.hdmi_lock);
return r;
}
static bool hdmi_detect(struct omap_dss_device *dssdev)
{
int r;
mutex_lock(&hdmi.hdmi_lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
r = omapdss_hdmi_display_enable(dssdev);
if (r)
goto err;
}
r = omapdss_hdmi_detect();
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED ||
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
omapdss_hdmi_display_disable(dssdev);
err:
mutex_unlock(&hdmi.hdmi_lock);
return r;
}
@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = {
.get_timings = hdmi_get_timings,
.set_timings = hdmi_set_timings,
.check_timings = hdmi_check_timings,
.read_edid = hdmi_read_edid,
.detect = hdmi_detect,
.driver = {
.name = "hdmi_panel",
.owner = THIS_MODULE,

View file

@ -106,7 +106,7 @@ put_device:
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color);
}
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
u32 color;
int r;
if (sscanf(buf, "%d", &color) != 1)
return -EINVAL;
r = kstrtouint(buf, 0, &color);
if (r)
return r;
mgr->get_manager_info(mgr, &info);
@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key);
}
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
u32 key_value;
int r;
if (sscanf(buf, "%d", &key_value) != 1)
return -EINVAL;
r = kstrtouint(buf, 0, &key_value);
if (r)
return r;
mgr->get_manager_info(mgr, &info);
@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
const char *buf, size_t size)
{
struct omap_overlay_manager_info info;
int enable;
bool enable;
int r;
if (sscanf(buf, "%d", &enable) != 1)
return -EINVAL;
r = strtobool(buf, &enable);
if (r)
return r;
mgr->get_manager_info(mgr, &info);
info.trans_enabled = enable ? true : false;
info.trans_enabled = enable;
r = mgr->set_manager_info(mgr, &info);
if (r)
@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
static ssize_t manager_alpha_blending_enabled_show(
struct omap_overlay_manager *mgr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
return snprintf(buf, PAGE_SIZE, "%d\n",
mgr->info.partial_alpha_enabled);
}
static ssize_t manager_alpha_blending_enabled_store(
@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store(
const char *buf, size_t size)
{
struct omap_overlay_manager_info info;
int enable;
bool enable;
int r;
if (sscanf(buf, "%d", &enable) != 1)
return -EINVAL;
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
r = strtobool(buf, &enable);
if (r)
return r;
mgr->get_manager_info(mgr, &info);
info.alpha_enabled = enable ? true : false;
info.partial_alpha_enabled = enable;
r = mgr->set_manager_info(mgr, &info);
if (r)
@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
const char *buf, size_t size)
{
struct omap_overlay_manager_info info;
int v;
int r;
bool enable;
if (!dss_has_feature(FEAT_CPR))
return -ENODEV;
r = kstrtoint(buf, 0, &v);
r = strtobool(buf, &enable);
if (r)
return r;
enable = !!v;
mgr->get_manager_info(mgr, &info);
if (info.cpr_enable == enable)
@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
return -EINVAL;
}
/*
* Don't allow currently enabled displays to have the overlay manager
* pulled out from underneath them
*/
if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED)
return -EINVAL;
mgr->device->manager = NULL;
mgr->device = NULL;
mgr->device_changed = true;
@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane)
{
struct overlay_cache_data *c;
struct manager_cache_data *mc;
struct omap_overlay_info *oi;
struct omap_overlay_info *oi, new_oi;
struct omap_overlay_manager_info *mi;
u16 outw, outh;
u16 x, y, w, h;
@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane)
oi = &c->info;
if (!c->enabled) {
dispc_enable_plane(plane, 0);
dispc_ovl_enable(plane, 0);
return 0;
}
@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane)
/* If the overlay is outside the update region, disable it */
if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
x, y, outw, outh)) {
dispc_enable_plane(plane, 0);
dispc_ovl_enable(plane, 0);
return 0;
}
@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane)
}
}
r = dispc_setup_plane(plane,
paddr,
oi->screen_width,
x, y,
w, h,
outw, outh,
oi->color_mode,
c->ilace,
oi->rotation_type,
oi->rotation,
oi->mirror,
oi->global_alpha,
oi->pre_mult_alpha,
c->channel,
oi->p_uv_addr);
new_oi = *oi;
/* update new_oi members which could have been possibly updated */
new_oi.pos_x = x;
new_oi.pos_y = y;
new_oi.width = w;
new_oi.height = h;
new_oi.out_width = outw;
new_oi.out_height = outh;
new_oi.paddr = paddr;
r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
c->replication, c->fifo_low, c->fifo_high);
if (r) {
/* this shouldn't happen */
DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
dispc_enable_plane(plane, 0);
DSSERR("dispc_ovl_setup failed for ovl %d\n", plane);
dispc_ovl_enable(plane, 0);
return r;
}
dispc_enable_replication(plane, c->replication);
dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
dispc_enable_plane(plane, 1);
dispc_ovl_enable(plane, 1);
return 0;
}
@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel)
/* picking info from the cache */
mi = &dss_cache.manager_cache[channel].info;
dispc_set_default_color(channel, mi->default_color);
dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
dispc_enable_trans_key(channel, mi->trans_enabled);
dispc_enable_alpha_blending(channel, mi->alpha_enabled);
dispc_mgr_set_default_color(channel, mi->default_color);
dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
dispc_mgr_enable_trans_key(channel, mi->trans_enabled);
dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);
if (dss_has_feature(FEAT_CPR)) {
dispc_enable_cpr(channel, mi->cpr_enable);
dispc_set_cpr_coef(channel, &mi->cpr_coefs);
dispc_mgr_enable_cpr(channel, mi->cpr_enable);
dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);
}
}
@ -992,7 +998,7 @@ static int configure_dispc(void)
busy = false;
for (i = 0; i < num_mgrs; i++) {
mgr_busy[i] = dispc_go_busy(i);
mgr_busy[i] = dispc_mgr_go_busy(i);
mgr_go[i] = false;
}
@ -1053,7 +1059,7 @@ static int configure_dispc(void)
* always be turned off after frame, and new settings will be
* taken in to use at next update */
if (!mc->manual_update)
dispc_go(i);
dispc_mgr_go(i);
}
if (busy)
@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
u32 irq_mask;
for (i = 0; i < num_mgrs; i++)
mgr_busy[i] = dispc_go_busy(i);
mgr_busy[i] = dispc_mgr_go_busy(i);
spin_lock(&dss_cache.lock);
@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask)
/* re-read busy flags */
for (i = 0; i < num_mgrs; i++)
mgr_busy[i] = dispc_go_busy(i);
mgr_busy[i] = dispc_mgr_go_busy(i);
/* keep running as long as there are busy managers, so that
* we can collect overlay-applied information */
@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
ovl = omap_dss_get_overlay(i);
if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
continue;
oc = &dss_cache.overlay_cache[ovl->id];
if (ovl->manager_changed) {
ovl->manager_changed = false;
ovl->info_dirty = true;
}
if (!overlay_enabled(ovl)) {
if (oc->enabled) {
oc->enabled = false;
@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
list_for_each_entry(mgr, &manager_list, list) {
struct omap_dss_device *dssdev;
if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
continue;
mc = &dss_cache.manager_cache[mgr->id];
if (mgr->device_changed) {
@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
ovl = omap_dss_get_overlay(i);
if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
continue;
oc = &dss_cache.overlay_cache[ovl->id];
if (!oc->enabled)
@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
dssdev = ovl->manager->device;
size = dispc_get_plane_fifo_size(ovl->id);
size = dispc_ovl_get_fifo_size(ovl->id);
if (use_fifomerge)
size *= 3;
burst_size = dispc_get_burst_size(ovl->id);
burst_size = dispc_ovl_get_burst_size(ovl->id);
switch (dssdev->type) {
case OMAP_DISPLAY_TYPE_DPI:
@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
static int dss_check_manager(struct omap_overlay_manager *mgr)
{
/* OMAP supports only graphics source transparency color key and alpha
* blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
return -EINVAL;
if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
/*
* OMAP3 supports only graphics source transparency color key
* and alpha blending simultaneously. See TRM 15.4.2.4.2.2
* Alpha Mode
*/
if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled
&& mgr->info.trans_key_type !=
OMAP_DSS_COLOR_KEY_GFX_DST)
return -EINVAL;
}
return 0;
}
@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
static int dss_mgr_enable(struct omap_overlay_manager *mgr)
{
dispc_enable_channel(mgr->id, 1);
dispc_mgr_enable(mgr->id, 1);
return 0;
}
static int dss_mgr_disable(struct omap_overlay_manager *mgr)
{
dispc_enable_channel(mgr->id, 0);
dispc_mgr_enable(mgr->id, 0);
return 0;
}
@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
mgr->enable = &dss_mgr_enable;
mgr->disable = &dss_mgr_disable;
mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
mgr->caps = 0;
mgr->supported_displays =
dss_feat_get_supported_displays(mgr->id);
@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev)
}
}
#ifdef L4_EXAMPLE
{
int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
{
DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
return 0;
}
struct omap_overlay_manager *mgr;
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
BUG_ON(mgr == NULL);
mgr->name = "l4";
mgr->supported_displays =
OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
mgr->set_device = &omap_dss_set_device;
mgr->unset_device = &omap_dss_unset_device;
mgr->apply = &omap_dss_mgr_apply_l4;
mgr->set_manager_info = &omap_dss_mgr_set_info;
mgr->get_manager_info = &omap_dss_mgr_get_info;
dss_overlay_setup_l4_manager(mgr);
omap_dss_add_overlay_manager(mgr);
r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
&pdev->dev.kobj, "managerl4");
if (r)
DSSERR("failed to create sysfs file\n");
}
#endif
return 0;
}

View file

@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
size_t size)
{
int r, enable;
int r;
bool enable;
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
r = kstrtoint(buf, 0, &enable);
r = strtobool(buf, &enable);
if (r)
return r;
info.enabled = !!enable;
info.enabled = enable;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
return -ENODEV;
r = kstrtou8(buf, 0, &alpha);
@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
ovl->get_overlay_info(ovl, &info);
/* Video1 plane does not support global alpha
* to always make it 255 completely opaque
*/
if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
ovl->id == OMAP_DSS_VIDEO1)
info.global_alpha = 255;
else
info.global_alpha = alpha;
info.global_alpha = alpha;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
u8 alpha;
struct omap_overlay_info info;
if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
return -ENODEV;
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
ovl->get_overlay_info(ovl, &info);
/* only GFX and Video2 plane support pre alpha multiplied
* set zero for Video1 plane
*/
if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
ovl->id == OMAP_DSS_VIDEO1)
info.pre_mult_alpha = 0;
else
info.pre_mult_alpha = alpha;
info.pre_mult_alpha = alpha;
r = ovl->set_overlay_info(ovl, &info);
if (r)
return r;
if (ovl->manager) {
r = ovl->manager->apply(ovl->manager);
if (r)
return r;
}
return size;
}
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
}
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
const char *buf, size_t size)
{
int r;
u8 zorder;
struct omap_overlay_info info;
if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
return -ENODEV;
r = kstrtou8(buf, 0, &zorder);
if (r)
return r;
ovl->get_overlay_info(ovl, &info);
info.zorder = zorder;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
overlay_pre_mult_alpha_show,
overlay_pre_mult_alpha_store);
static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
overlay_zorder_show, overlay_zorder_store);
static struct attribute *overlay_sysfs_attrs[] = {
&overlay_attr_name.attr,
@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = {
&overlay_attr_enabled.attr,
&overlay_attr_global_alpha.attr,
&overlay_attr_pre_mult_alpha.attr,
&overlay_attr_zorder.attr,
NULL
};
@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
struct omap_overlay_info *info;
u16 outw, outh;
u16 dw, dh;
int i;
if (!dssdev)
return 0;
@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
return -EINVAL;
}
if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
if (info->zorder < 0 || info->zorder > 3) {
DSSERR("zorder out of range: %d\n",
info->zorder);
return -EINVAL;
}
/*
* Check that zorder doesn't match with zorder of any other
* overlay which is enabled and is also connected to the same
* manager
*/
for (i = 0; i < omap_dss_get_num_overlays(); i++) {
struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
if (tmp_ovl->id != ovl->id &&
tmp_ovl->manager == ovl->manager &&
tmp_ovl->info.enabled == true &&
tmp_ovl->info.zorder == info->zorder) {
DSSERR("%s and %s have same zorder: %d\n",
ovl->name, tmp_ovl->name, info->zorder);
return -EINVAL;
}
}
}
return 0;
}
@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
}
ovl->manager = mgr;
ovl->manager_changed = true;
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
* Userspace workaround for this is to update the LCD after disabling
* the overlay, but before moving the overlay to TV.
*/
dispc_set_channel_out(ovl->id, mgr->id);
return 0;
}
static int omap_dss_unset_manager(struct omap_overlay *ovl)
{
int r;
if (!ovl->manager) {
DSSERR("failed to detach overlay: manager not set\n");
return -EINVAL;
@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl)
return -EINVAL;
}
r = ovl->wait_for_go(ovl);
if (r)
return r;
ovl->manager = NULL;
ovl->manager_changed = true;
return 0;
}
@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev)
case 0:
ovl->name = "gfx";
ovl->id = OMAP_DSS_GFX;
ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
ovl->info.global_alpha = 255;
ovl->info.zorder = 0;
break;
case 1:
ovl->name = "vid1";
ovl->id = OMAP_DSS_VIDEO1;
ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
OMAP_DSS_OVL_CAP_DISPC;
ovl->info.global_alpha = 255;
ovl->info.zorder =
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
break;
case 2:
ovl->name = "vid2";
ovl->id = OMAP_DSS_VIDEO2;
ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
OMAP_DSS_OVL_CAP_DISPC;
ovl->info.global_alpha = 255;
ovl->info.zorder =
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
break;
case 3:
ovl->name = "vid3";
ovl->id = OMAP_DSS_VIDEO3;
ovl->info.global_alpha = 255;
ovl->info.zorder =
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
break;
}
@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev)
ovl->get_overlay_info = &dss_ovl_get_overlay_info;
ovl->wait_for_go = &dss_ovl_wait_for_go;
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
ovl->supported_modes =
dss_feat_get_supported_color_modes(ovl->id);

View file

@ -309,9 +309,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
dispc_set_lcd_size(dssdev->manager->id, width, height);
dispc_mgr_set_lcd_size(dssdev->manager->id, width, height);
dispc_enable_channel(dssdev->manager->id, true);
dispc_mgr_enable(dssdev->manager->id, true);
rfbi.framedone_callback = callback;
rfbi.framedone_callback_data = data;
@ -783,10 +783,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
if (*w == 0 || *h == 0)
return -EINVAL;
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
dss_setup_partial_planes(dssdev, x, y, w, h, true);
dispc_set_lcd_size(dssdev->manager->id, *w, *h);
}
dss_setup_partial_planes(dssdev, x, y, w, h, true);
dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
return 0;
}
@ -796,22 +794,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h,
void (*callback)(void *), void *data)
{
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
rfbi_transfer_area(dssdev, w, h, callback, data);
} else {
struct omap_overlay *ovl;
void __iomem *addr;
int scr_width;
ovl = dssdev->manager->overlays[0];
scr_width = ovl->info.screen_width;
addr = ovl->info.vaddr;
omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
callback(data);
}
rfbi_transfer_area(dssdev, w, h, callback, data);
return 0;
}
EXPORT_SYMBOL(omap_rfbi_update);
@ -860,6 +843,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
if (dssdev->manager == NULL) {
DSSERR("failed to enable display: no manager\n");
return -ENODEV;
}
r = rfbi_runtime_get();
if (r)
return r;
@ -877,13 +865,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
goto err1;
}
dispc_set_lcd_display_type(dssdev->manager->id,
dispc_mgr_set_lcd_display_type(dssdev->manager->id,
OMAP_DSS_LCD_DISPLAY_TFT);
dispc_set_parallel_interface_mode(dssdev->manager->id,
OMAP_DSS_PARALLELMODE_RFBI);
dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI);
dispc_mgr_enable_stallmode(dssdev->manager->id, true);
dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
rfbi_configure(dssdev->phy.rfbi.channel,
dssdev->ctrl.pixel_size,
@ -952,10 +940,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
msleep(10);
if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
clk = dss_get_ick();
else
clk = clk_get(&pdev->dev, "ick");
clk = clk_get(&pdev->dev, "ick");
if (IS_ERR(clk)) {
DSSERR("can't get ick\n");
r = PTR_ERR(clk);

View file

@ -35,13 +35,13 @@ static struct {
static void sdi_basic_init(struct omap_dss_device *dssdev)
{
dispc_set_parallel_interface_mode(dssdev->manager->id,
OMAP_DSS_PARALLELMODE_BYPASS);
dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS);
dispc_mgr_enable_stallmode(dssdev->manager->id, false);
dispc_set_lcd_display_type(dssdev->manager->id,
dispc_mgr_set_lcd_display_type(dssdev->manager->id,
OMAP_DSS_LCD_DISPLAY_TFT);
dispc_set_tft_data_lines(dssdev->manager->id, 24);
dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24);
dispc_lcd_enable_signal_polarity(1);
}
@ -55,6 +55,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
unsigned long pck;
int r;
if (dssdev->manager == NULL) {
DSSERR("failed to enable display: no manager\n");
return -ENODEV;
}
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@ -78,7 +83,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
/* 15.5.9.1.2 */
dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
dssdev->panel.acbi, dssdev->panel.acb);
r = dss_calc_clock_div(1, t->pixel_clock * 1000,
@ -101,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
}
dispc_set_lcd_timings(dssdev->manager->id, t);
dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
r = dss_set_clock_div(&dss_cinfo);
if (r)
goto err_set_dss_clock_div;
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
goto err_set_dispc_clock_div;

View file

@ -0,0 +1,138 @@
/*
* ti_hdmi.h
*
* HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor.
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TI_HDMI_H
#define _TI_HDMI_H
struct hdmi_ip_data;
enum hdmi_pll_pwr {
HDMI_PLLPWRCMD_ALLOFF = 0,
HDMI_PLLPWRCMD_PLLONLY = 1,
HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
};
enum hdmi_core_hdmi_dvi {
HDMI_DVI = 0,
HDMI_HDMI = 1
};
enum hdmi_clk_refsel {
HDMI_REFSEL_PCLK = 0,
HDMI_REFSEL_REF1 = 1,
HDMI_REFSEL_REF2 = 2,
HDMI_REFSEL_SYSCLK = 3
};
struct hdmi_video_timings {
u16 x_res;
u16 y_res;
/* Unit: KHz */
u32 pixel_clock;
u16 hsw;
u16 hfp;
u16 hbp;
u16 vsw;
u16 vfp;
u16 vbp;
};
/* HDMI timing structure */
struct hdmi_timings {
struct hdmi_video_timings timings;
int vsync_pol;
int hsync_pol;
};
struct hdmi_cm {
int code;
int mode;
};
struct hdmi_config {
struct hdmi_timings timings;
u16 interlace;
struct hdmi_cm cm;
};
/* HDMI PLL structure */
struct hdmi_pll_info {
u16 regn;
u16 regm;
u32 regmf;
u16 regm2;
u16 regsd;
u16 dcofreq;
enum hdmi_clk_refsel refsel;
};
struct ti_hdmi_ip_ops {
void (*video_configure)(struct hdmi_ip_data *ip_data);
int (*phy_enable)(struct hdmi_ip_data *ip_data);
void (*phy_disable)(struct hdmi_ip_data *ip_data);
int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len);
bool (*detect)(struct hdmi_ip_data *ip_data);
int (*pll_enable)(struct hdmi_ip_data *ip_data);
void (*pll_disable)(struct hdmi_ip_data *ip_data);
void (*video_enable)(struct hdmi_ip_data *ip_data, bool start);
void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s);
void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s);
void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
};
struct hdmi_ip_data {
void __iomem *base_wp; /* HDMI wrapper */
unsigned long core_sys_offset;
unsigned long core_av_offset;
unsigned long pll_offset;
unsigned long phy_offset;
const struct ti_hdmi_ip_ops *ops;
struct hdmi_config cfg;
struct hdmi_pll_info pll_data;
};
int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
* hdmi.h
* ti_hdmi_4xxx_ip.h
*
* HDMI driver definition for TI OMAP4 processors.
* HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors.
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
*
@ -18,202 +18,177 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _OMAP4_DSS_HDMI_H_
#define _OMAP4_DSS_HDMI_H_
#ifndef _HDMI_TI_4xxx_H_
#define _HDMI_TI_4xxx_H_
#include <linux/string.h>
#include <video/omapdss.h>
#define HDMI_WP 0x0
#define HDMI_CORE_SYS 0x400
#define HDMI_CORE_AV 0x900
#define HDMI_PLLCTRL 0x200
#define HDMI_PHY 0x300
struct hdmi_reg { u16 idx; };
#define HDMI_REG(idx) ((const struct hdmi_reg) { idx })
#include "ti_hdmi.h"
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
#include <sound/soc.h>
#include <sound/pcm_params.h>
#endif
/* HDMI Wrapper */
#define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx)
#define HDMI_WP_REVISION HDMI_WP_REG(0x0)
#define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10)
#define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24)
#define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28)
#define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40)
#define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C)
#define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50)
#define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60)
#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68)
#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C)
#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70)
#define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80)
#define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84)
#define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88)
#define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C)
#define HDMI_WP_REVISION 0x0
#define HDMI_WP_SYSCONFIG 0x10
#define HDMI_WP_IRQSTATUS_RAW 0x24
#define HDMI_WP_IRQSTATUS 0x28
#define HDMI_WP_PWR_CTRL 0x40
#define HDMI_WP_IRQENABLE_SET 0x2C
#define HDMI_WP_VIDEO_CFG 0x50
#define HDMI_WP_VIDEO_SIZE 0x60
#define HDMI_WP_VIDEO_TIMING_H 0x68
#define HDMI_WP_VIDEO_TIMING_V 0x6C
#define HDMI_WP_WP_CLK 0x70
#define HDMI_WP_AUDIO_CFG 0x80
#define HDMI_WP_AUDIO_CFG2 0x84
#define HDMI_WP_AUDIO_CTRL 0x88
#define HDMI_WP_AUDIO_DATA 0x8C
/* HDMI IP Core System */
#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx)
#define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0)
#define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8)
#define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC)
#define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10)
#define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14)
#define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20)
#define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24)
#define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124)
#define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128)
#define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0)
#define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4)
#define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8)
#define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC)
#define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0)
#define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4)
#define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208)
#define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8)
#define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC)
#define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0)
#define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8)
#define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC)
#define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0)
#define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4)
#define HDMI_CORE_SYS_VND_IDL 0x0
#define HDMI_CORE_SYS_DEV_IDL 0x8
#define HDMI_CORE_SYS_DEV_IDH 0xC
#define HDMI_CORE_SYS_DEV_REV 0x10
#define HDMI_CORE_SYS_SRST 0x14
#define HDMI_CORE_CTRL1 0x20
#define HDMI_CORE_SYS_SYS_STAT 0x24
#define HDMI_CORE_SYS_VID_ACEN 0x124
#define HDMI_CORE_SYS_VID_MODE 0x128
#define HDMI_CORE_SYS_INTR_STATE 0x1C0
#define HDMI_CORE_SYS_INTR1 0x1C4
#define HDMI_CORE_SYS_INTR2 0x1C8
#define HDMI_CORE_SYS_INTR3 0x1CC
#define HDMI_CORE_SYS_INTR4 0x1D0
#define HDMI_CORE_SYS_UMASK1 0x1D4
#define HDMI_CORE_SYS_TMDS_CTRL 0x208
#define HDMI_CORE_SYS_DE_DLY 0xC8
#define HDMI_CORE_SYS_DE_CTRL 0xCC
#define HDMI_CORE_SYS_DE_TOP 0xD0
#define HDMI_CORE_SYS_DE_CNTL 0xD8
#define HDMI_CORE_SYS_DE_CNTH 0xDC
#define HDMI_CORE_SYS_DE_LINL 0xE0
#define HDMI_CORE_SYS_DE_LINH_1 0xE4
#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
/* HDMI DDC E-DID */
#define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC)
#define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8)
#define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4)
#define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC)
#define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0)
#define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4)
#define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0)
#define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8)
#define HDMI_CORE_DDC_CMD 0x3CC
#define HDMI_CORE_DDC_STATUS 0x3C8
#define HDMI_CORE_DDC_ADDR 0x3B4
#define HDMI_CORE_DDC_OFFSET 0x3BC
#define HDMI_CORE_DDC_COUNT1 0x3C0
#define HDMI_CORE_DDC_COUNT2 0x3C4
#define HDMI_CORE_DDC_DATA 0x3D0
#define HDMI_CORE_DDC_SEGM 0x3B8
/* HDMI IP Core Audio Video */
#define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx)
#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC)
#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4)
#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8)
#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC)
#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100)
#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104)
#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108)
#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C)
#define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110)
#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15)
#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190)
#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
#define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210)
#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10)
#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290)
#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300)
#define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31)
#define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380)
#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31)
#define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4)
#define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8)
#define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC)
#define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10)
#define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14)
#define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18)
#define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C)
#define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20)
#define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24)
#define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28)
#define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C)
#define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50)
#define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54)
#define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60)
#define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64)
#define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C)
#define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70)
#define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74)
#define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78)
#define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C)
#define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80)
#define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84)
#define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88)
#define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C)
#define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90)
#define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC)
#define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0)
#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC)
#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0)
#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4)
#define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0)
#define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4)
#define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8)
#define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC)
#define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100)
#define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104)
#define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108)
#define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C)
#define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180)
#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184)
#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188)
#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C)
#define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200)
#define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204)
#define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208)
#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C)
#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280)
#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284)
#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288)
#define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C)
#define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C)
#define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC)
#define HDMI_CORE_AV_HDMI_CTRL 0xBC
#define HDMI_CORE_AV_DPD 0xF4
#define HDMI_CORE_AV_PB_CTRL1 0xF8
#define HDMI_CORE_AV_PB_CTRL2 0xFC
#define HDMI_CORE_AV_AVI_TYPE 0x100
#define HDMI_CORE_AV_AVI_VERS 0x104
#define HDMI_CORE_AV_AVI_LEN 0x108
#define HDMI_CORE_AV_AVI_CHSUM 0x10C
#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
#define HDMI_CORE_AV_ACR_CTRL 0x4
#define HDMI_CORE_AV_FREQ_SVAL 0x8
#define HDMI_CORE_AV_N_SVAL1 0xC
#define HDMI_CORE_AV_N_SVAL2 0x10
#define HDMI_CORE_AV_N_SVAL3 0x14
#define HDMI_CORE_AV_CTS_SVAL1 0x18
#define HDMI_CORE_AV_CTS_SVAL2 0x1C
#define HDMI_CORE_AV_CTS_SVAL3 0x20
#define HDMI_CORE_AV_CTS_HVAL1 0x24
#define HDMI_CORE_AV_CTS_HVAL2 0x28
#define HDMI_CORE_AV_CTS_HVAL3 0x2C
#define HDMI_CORE_AV_AUD_MODE 0x50
#define HDMI_CORE_AV_SPDIF_CTRL 0x54
#define HDMI_CORE_AV_HW_SPDIF_FS 0x60
#define HDMI_CORE_AV_SWAP_I2S 0x64
#define HDMI_CORE_AV_SPDIF_ERTH 0x6C
#define HDMI_CORE_AV_I2S_IN_MAP 0x70
#define HDMI_CORE_AV_I2S_IN_CTRL 0x74
#define HDMI_CORE_AV_I2S_CHST0 0x78
#define HDMI_CORE_AV_I2S_CHST1 0x7C
#define HDMI_CORE_AV_I2S_CHST2 0x80
#define HDMI_CORE_AV_I2S_CHST4 0x84
#define HDMI_CORE_AV_I2S_CHST5 0x88
#define HDMI_CORE_AV_ASRC 0x8C
#define HDMI_CORE_AV_I2S_IN_LEN 0x90
#define HDMI_CORE_AV_HDMI_CTRL 0xBC
#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0
#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC
#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0
#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4
#define HDMI_CORE_AV_TEST_TXCTRL 0xF0
#define HDMI_CORE_AV_DPD 0xF4
#define HDMI_CORE_AV_PB_CTRL1 0xF8
#define HDMI_CORE_AV_PB_CTRL2 0xFC
#define HDMI_CORE_AV_AVI_TYPE 0x100
#define HDMI_CORE_AV_AVI_VERS 0x104
#define HDMI_CORE_AV_AVI_LEN 0x108
#define HDMI_CORE_AV_AVI_CHSUM 0x10C
#define HDMI_CORE_AV_SPD_TYPE 0x180
#define HDMI_CORE_AV_SPD_VERS 0x184
#define HDMI_CORE_AV_SPD_LEN 0x188
#define HDMI_CORE_AV_SPD_CHSUM 0x18C
#define HDMI_CORE_AV_AUDIO_TYPE 0x200
#define HDMI_CORE_AV_AUDIO_VERS 0x204
#define HDMI_CORE_AV_AUDIO_LEN 0x208
#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
#define HDMI_CORE_AV_MPEG_TYPE 0x280
#define HDMI_CORE_AV_MPEG_VERS 0x284
#define HDMI_CORE_AV_MPEG_LEN 0x288
#define HDMI_CORE_AV_MPEG_CHSUM 0x28C
#define HDMI_CORE_AV_CP_BYTE1 0x37C
#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC
#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
/* PLL */
#define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx)
#define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0)
#define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4)
#define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8)
#define PLLCTRL_CFG1 HDMI_PLL_REG(0xC)
#define PLLCTRL_CFG2 HDMI_PLL_REG(0x10)
#define PLLCTRL_CFG3 HDMI_PLL_REG(0x14)
#define PLLCTRL_CFG4 HDMI_PLL_REG(0x20)
#define PLLCTRL_PLL_CONTROL 0x0
#define PLLCTRL_PLL_STATUS 0x4
#define PLLCTRL_PLL_GO 0x8
#define PLLCTRL_CFG1 0xC
#define PLLCTRL_CFG2 0x10
#define PLLCTRL_CFG3 0x14
#define PLLCTRL_CFG4 0x20
/* HDMI PHY */
#define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx)
#define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0)
#define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4)
#define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8)
#define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC)
#define HDMI_TXPHY_TX_CTRL 0x0
#define HDMI_TXPHY_DIGITAL_CTRL 0x4
#define HDMI_TXPHY_POWER_CTRL 0x8
#define HDMI_TXPHY_PAD_CFG_CTRL 0xC
/* HDMI EDID Length */
#define HDMI_EDID_MAX_LENGTH 256
#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
#define OMAP_HDMI_TIMINGS_NB 34
#define REG_FLD_MOD(idx, val, start, end) \
hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end))
#define REG_GET(idx, start, end) \
FLD_GET(hdmi_read_reg(idx), start, end)
/* HDMI timing structure */
struct hdmi_timings {
struct omap_video_timings timings;
int vsync_pol;
int hsync_pol;
};
#define REG_FLD_MOD(base, idx, val, start, end) \
hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
val, start, end))
#define REG_GET(base, idx, start, end) \
FLD_GET(hdmi_read_reg(base, idx), start, end)
enum hdmi_phy_pwr {
HDMI_PHYPWRCMD_OFF = 0,
@ -221,20 +196,6 @@ enum hdmi_phy_pwr {
HDMI_PHYPWRCMD_TXON = 2
};
enum hdmi_pll_pwr {
HDMI_PLLPWRCMD_ALLOFF = 0,
HDMI_PLLPWRCMD_PLLONLY = 1,
HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
};
enum hdmi_clk_refsel {
HDMI_REFSEL_PCLK = 0,
HDMI_REFSEL_REF1 = 1,
HDMI_REFSEL_REF2 = 2,
HDMI_REFSEL_SYSCLK = 3
};
enum hdmi_core_inputbus_width {
HDMI_INPUT_8BIT = 0,
HDMI_INPUT_10BIT = 1,
@ -263,11 +224,6 @@ enum hdmi_core_packet_mode {
HDMI_PACKETMODE48BITPERPIXEL = 7
};
enum hdmi_core_hdmi_dvi {
HDMI_DVI = 0,
HDMI_HDMI = 1
};
enum hdmi_core_tclkselclkmult {
HDMI_FPLL05IDCK = 0,
HDMI_FPLL10IDCK = 1,
@ -495,40 +451,40 @@ struct hdmi_core_video_config {
* details about infoframe databytes
*/
struct hdmi_core_infoframe_avi {
/* Y0, Y1 rgb,yCbCr */
u8 db1_format;
/* Y0, Y1 rgb,yCbCr */
/* A0 Active information Present */
u8 db1_active_info;
/* A0 Active information Present */
/* B0, B1 Bar info data valid */
u8 db1_bar_info_dv;
/* B0, B1 Bar info data valid */
/* S0, S1 scan information */
u8 db1_scan_info;
/* S0, S1 scan information */
/* C0, C1 colorimetry */
u8 db2_colorimetry;
/* C0, C1 colorimetry */
/* M0, M1 Aspect ratio (4:3, 16:9) */
u8 db2_aspect_ratio;
/* M0, M1 Aspect ratio (4:3, 16:9) */
/* R0...R3 Active format aspect ratio */
u8 db2_active_fmt_ar;
/* R0...R3 Active format aspect ratio */
/* ITC IT content. */
u8 db3_itc;
/* ITC IT content. */
/* EC0, EC1, EC2 Extended colorimetry */
u8 db3_ec;
/* EC0, EC1, EC2 Extended colorimetry */
/* Q1, Q0 Quantization range */
u8 db3_q_range;
/* Q1, Q0 Quantization range */
/* SC1, SC0 Non-uniform picture scaling */
u8 db3_nup_scaling;
/* SC1, SC0 Non-uniform picture scaling */
/* VIC0..6 Video format identification */
u8 db4_videocode;
/* VIC0..6 Video format identification */
/* PR0..PR3 Pixel repetition factor */
u8 db5_pixel_repeat;
/* PR0..PR3 Pixel repetition factor */
/* Line number end of top bar */
u16 db6_7_line_eoftop;
/* Line number end of top bar */
/* Line number start of bottom bar */
u16 db8_9_line_sofbottom;
/* Line number start of bottom bar */
/* Pixel number end of left bar */
u16 db10_11_pixel_eofleft;
/* Pixel number end of left bar */
/* Pixel number start of right bar */
u16 db12_13_pixel_sofright;
/* Pixel number start of right bar */
};
/*
* Refer to section 8.2 in HDMI 1.3 specification for
@ -568,17 +524,6 @@ struct hdmi_video_interface {
int tm; /* Timing mode */
};
struct hdmi_cm {
int code;
int mode;
};
struct hdmi_config {
struct hdmi_timings timings;
u16 interlace;
struct hdmi_cm cm;
};
struct hdmi_audio_format {
enum hdmi_stereo_channels stereo_channels;
u8 active_chnnls_msk;
@ -628,4 +573,21 @@ struct hdmi_core_audio_config {
bool en_parallel_aud_input;
bool en_spdif;
};
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai);
int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
u32 sample_freq, u32 *n, u32 *cts);
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_infoframe_audio *info_aud);
void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
struct hdmi_core_audio_config *cfg);
void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
struct hdmi_audio_dma *aud_dma);
void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
struct hdmi_audio_format *aud_fmt);
#endif
#endif

View file

@ -295,7 +295,6 @@ static struct {
u32 wss_data;
struct regulator *vdda_dac_reg;
struct clk *tv_clk;
struct clk *tv_dac_clk;
} venc;
@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev)
regulator_disable(venc.vdda_dac_reg);
}
unsigned long venc_get_pixel_clock(void)
{
/* VENC Pixel Clock in Mhz */
return 13500000;
}
/* driver */
static int venc_panel_probe(struct omap_dss_device *dssdev)
@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev)
{
struct clk *clk;
clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
DSSERR("can't get fck\n");
return PTR_ERR(clk);
}
venc.tv_clk = clk;
if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
if (cpu_is_omap34xx() || cpu_is_omap3630())
clk = clk_get(&pdev->dev, "dss_96m_fck");
else
clk = clk_get(&pdev->dev, "tv_dac_clk");
clk = clk_get(&pdev->dev, "tv_dac_clk");
if (IS_ERR(clk)) {
DSSERR("can't get tv_dac_clk\n");
clk_put(venc.tv_clk);
return PTR_ERR(clk);
}
} else {
@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev)
static void venc_put_clocks(void)
{
if (venc.tv_clk)
clk_put(venc.tv_clk);
if (venc.tv_dac_clk)
clk_put(venc.tv_dac_clk);
}
@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev)
{
if (venc.tv_dac_clk)
clk_disable(venc.tv_dac_clk);
clk_disable(venc.tv_clk);
dispc_runtime_put();
dss_runtime_put();
@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev)
if (r < 0)
goto err_get_dispc;
clk_enable(venc.tv_clk);
if (venc.tv_dac_clk)
clk_enable(venc.tv_dac_clk);

View file

@ -1,5 +1,5 @@
menuconfig FB_OMAP2
tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
tristate "OMAP2+ frame buffer support"
depends on FB && OMAP2_DSS
select OMAP2_VRAM

View file

@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
static void omapfb_calc_addr(const struct omapfb_info *ofbi,
const struct fb_var_screeninfo *var,
const struct fb_fix_screeninfo *fix,
int rotation, u32 *paddr, void __iomem **vaddr)
int rotation, u32 *paddr)
{
u32 data_start_p;
void __iomem *data_start_v;
int offset;
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
data_start_v = NULL;
} else {
else
data_start_p = omapfb_get_region_paddr(ofbi);
data_start_v = omapfb_get_region_vaddr(ofbi);
}
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
offset = calc_rotation_offset_vrfb(var, fix, rotation);
@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
offset = calc_rotation_offset_dma(var, fix, rotation);
data_start_p += offset;
data_start_v += offset;
if (offset)
DBG("offset %d, %d = %d\n",
var->xoffset, var->yoffset, offset);
DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
DBG("paddr %x\n", data_start_p);
*paddr = data_start_p;
*vaddr = data_start_v;
}
/* setup overlay according to the fb */
@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
struct fb_fix_screeninfo *fix = &fbi->fix;
enum omap_color_mode mode = 0;
u32 data_start_p = 0;
void __iomem *data_start_v = NULL;
struct omap_overlay_info info;
int xres, yres;
int screen_width;
@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
}
if (ofbi->region->size)
omapfb_calc_addr(ofbi, var, fix, rotation,
&data_start_p, &data_start_v);
omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p);
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
mirror = ofbi->mirror;
info.paddr = data_start_p;
info.vaddr = data_start_v;
info.screen_width = screen_width;
info.width = xres;
info.height = yres;
@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
return r;
}
static void fb_videomode_to_omap_timings(struct fb_videomode *m,
struct omap_video_timings *t)
{
t->x_res = m->xres;
t->y_res = m->yres;
t->pixel_clock = PICOS2KHZ(m->pixclock);
t->hsw = m->hsync_len;
t->hfp = m->right_margin;
t->hbp = m->left_margin;
t->vsw = m->vsync_len;
t->vfp = m->lower_margin;
t->vbp = m->upper_margin;
}
static int omapfb_find_best_mode(struct omap_dss_device *display,
struct omap_video_timings *timings)
{
struct fb_monspecs *specs;
u8 *edid;
int r, i, best_xres, best_idx, len;
if (!display->driver->read_edid)
return -ENODEV;
len = 0x80 * 2;
edid = kmalloc(len, GFP_KERNEL);
r = display->driver->read_edid(display, edid, len);
if (r < 0)
goto err1;
specs = kzalloc(sizeof(*specs), GFP_KERNEL);
fb_edid_to_monspecs(edid, specs);
if (edid[126] > 0)
fb_edid_add_monspecs(edid + 0x80, specs);
best_xres = 0;
best_idx = -1;
for (i = 0; i < specs->modedb_len; ++i) {
struct fb_videomode *m;
struct omap_video_timings t;
m = &specs->modedb[i];
if (m->pixclock == 0)
continue;
/* skip repeated pixel modes */
if (m->xres == 2880 || m->xres == 1440)
continue;
fb_videomode_to_omap_timings(m, &t);
r = display->driver->check_timings(display, &t);
if (r == 0 && best_xres < m->xres) {
best_xres = m->xres;
best_idx = i;
}
}
if (best_xres == 0) {
r = -ENOENT;
goto err2;
}
fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings);
r = 0;
err2:
fb_destroy_modedb(specs->modedb);
kfree(specs);
err1:
kfree(edid);
return r;
}
static int omapfb_init_display(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev)
omap_dss_get_device(dssdev);
if (!dssdev->driver) {
dev_err(&pdev->dev, "no driver for display\n");
r = -ENODEV;
dev_warn(&pdev->dev, "no driver for display: %s\n",
dssdev->name);
omap_dss_put_device(dssdev);
continue;
}
d = &fbdev->displays[fbdev->num_displays++];
@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev)
for (i = 0; i < fbdev->num_managers; i++)
fbdev->managers[i] = omap_dss_get_overlay_manager(i);
/* gfx overlay should be the default one. find a display
* connected to that, and use it as default display */
ovl = omap_dss_get_overlay(0);
if (ovl->manager && ovl->manager->device) {
def_display = ovl->manager->device;
} else {
dev_warn(&pdev->dev, "cannot find default display\n");
def_display = NULL;
}
if (def_mode && strlen(def_mode) > 0) {
if (omapfb_parse_def_modes(fbdev))
dev_warn(&pdev->dev, "cannot parse default modes\n");
} else if (def_display && def_display->driver->set_timings &&
def_display->driver->check_timings) {
struct omap_video_timings t;
r = omapfb_find_best_mode(def_display, &t);
if (r == 0)
def_display->driver->set_timings(def_display, &t);
}
r = omapfb_create_framebuffers(fbdev);
@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev)
DBG("mgr->apply'ed\n");
/* gfx overlay should be the default one. find a display
* connected to that, and use it as default display */
ovl = omap_dss_get_overlay(0);
if (ovl->manager && ovl->manager->device) {
def_display = ovl->manager->device;
} else {
dev_warn(&pdev->dev, "cannot find default display\n");
def_display = NULL;
}
if (def_display) {
r = omapfb_init_display(fbdev, def_display);
if (r) {

View file

@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev,
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
int mirror;
bool mirror;
int r;
struct fb_var_screeninfo new_var;
r = kstrtoint(buf, 0, &mirror);
r = strtobool(buf, &mirror);
if (r)
return r;
mirror = !!mirror;
if (!lock_fb_info(fbi))
return -ENODEV;

View file

@ -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)
{
@ -683,7 +683,7 @@ static struct platform_driver platinum_driver =
.of_match_table = platinumfb_match,
},
.probe = platinumfb_probe,
.remove = platinumfb_remove,
.remove = __devexit_p(platinumfb_remove),
};
static int __init platinumfb_init(void)

View file

@ -973,8 +973,8 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
{
struct pm2fb_par *p = info->par;
u32 base;
u32 depth = (var->bits_per_pixel + 7) & ~7;
u32 xres = (var->xres + 31) & ~31;
u32 depth = (info->var.bits_per_pixel + 7) & ~7;
u32 xres = (info->var.xres + 31) & ~31;
depth = (depth > 32) ? 32 : depth;
base = to3264(var->yoffset * xres + var->xoffset, depth, 1);
@ -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:'.
*/

View file

@ -1147,9 +1147,9 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct pm3_par *par = info->par;
const u32 xres = (var->xres + 31) & ~31;
const u32 xres = (info->var.xres + 31) & ~31;
par->base = pm3fb_shift_bpp(var->bits_per_pixel,
par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
(var->yoffset * xres)
+ var->xoffset);
PM3_WAIT(par, 1);
@ -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;

View file

@ -1082,7 +1082,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
}
retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
IRQF_DISABLED, DEVICE_NAME, &dev->core);
0, DEVICE_NAME, &dev->core);
if (retval) {
dev_err(&dev->core, "%s: request_irq failed %d\n", __func__,
retval);

View file

@ -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>
@ -678,7 +676,7 @@ pxa3xx_gcu_probe(struct platform_device *dev)
}
ret = request_irq(irq, pxa3xx_gcu_handle_irq,
IRQF_DISABLED, DRV_NAME, priv);
0, DRV_NAME, priv);
if (ret) {
dev_err(&dev->dev, "request_irq failed\n");
ret = -EBUSY;

View file

@ -2191,7 +2191,7 @@ static int __devinit pxafb_probe(struct platform_device *dev)
goto failed_free_mem;
}
ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
if (ret) {
dev_err(&dev->dev, "request_irq failed: %d\n", ret);
ret = -EBUSY;

View file

@ -81,6 +81,7 @@ struct s3c_fb;
* @palette: Address of palette memory, or 0 if none.
* @has_prtcon: Set if has PRTCON register.
* @has_shadowcon: Set if has SHADOWCON register.
* @has_clksel: Set if VIDCON0 register has CLKSEL bit.
*/
struct s3c_fb_variant {
unsigned int is_2443:1;
@ -98,6 +99,7 @@ struct s3c_fb_variant {
unsigned int has_prtcon:1;
unsigned int has_shadowcon:1;
unsigned int has_clksel:1;
};
/**
@ -186,6 +188,7 @@ struct s3c_fb_vsync {
* @dev: The device that we bound to, for printing, etc.
* @regs_res: The resource we claimed for the IO registers.
* @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
* @lcd_clk: The clk (sclk) feeding pixclk.
* @regs: The mapped hardware registers.
* @variant: Variant information for this hardware.
* @enabled: A bitmask of enabled hardware windows.
@ -200,6 +203,7 @@ struct s3c_fb {
struct device *dev;
struct resource *regs_res;
struct clk *bus_clk;
struct clk *lcd_clk;
void __iomem *regs;
struct s3c_fb_variant variant;
@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
*/
static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
{
unsigned long clk = clk_get_rate(sfb->bus_clk);
unsigned long clk;
unsigned long long tmp;
unsigned int result;
if (sfb->variant.has_clksel)
clk = clk_get_rate(sfb->bus_clk);
else
clk = clk_get_rate(sfb->lcd_clk);
tmp = (unsigned long long)clk;
tmp *= pixclk;
@ -883,7 +892,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
}
}
/* Offset in bytes to the end of the displayed area */
end_boff = start_boff + var->yres * info->fix.line_length;
end_boff = start_boff + info->var.yres * info->fix.line_length;
/* Temporarily turn off per-vsync update from shadow registers until
* both start and end addresses are updated to prevent corruption */
@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
clk_enable(sfb->bus_clk);
if (!sfb->variant.has_clksel) {
sfb->lcd_clk = clk_get(dev, "sclk_fimd");
if (IS_ERR(sfb->lcd_clk)) {
dev_err(dev, "failed to get lcd clock\n");
ret = PTR_ERR(sfb->lcd_clk);
goto err_bus_clk;
}
clk_enable(sfb->lcd_clk);
}
pm_runtime_enable(sfb->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "failed to find registers\n");
ret = -ENOENT;
goto err_clk;
goto err_lcd_clk;
}
sfb->regs_res = request_mem_region(res->start, resource_size(res),
@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
if (!sfb->regs_res) {
dev_err(dev, "failed to claim register region\n");
ret = -ENOENT;
goto err_clk;
goto err_lcd_clk;
}
sfb->regs = ioremap(res->start, resource_size(res));
@ -1450,7 +1470,13 @@ err_ioremap:
err_req_region:
release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
err_clk:
err_lcd_clk:
if (!sfb->variant.has_clksel) {
clk_disable(sfb->lcd_clk);
clk_put(sfb->lcd_clk);
}
err_bus_clk:
clk_disable(sfb->bus_clk);
clk_put(sfb->bus_clk);
@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
iounmap(sfb->regs);
if (!sfb->variant.has_clksel) {
clk_disable(sfb->lcd_clk);
clk_put(sfb->lcd_clk);
}
clk_disable(sfb->bus_clk);
clk_put(sfb->bus_clk);
@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev)
s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
}
if (!sfb->variant.has_clksel)
clk_disable(sfb->lcd_clk);
clk_disable(sfb->bus_clk);
return 0;
}
@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev)
clk_enable(sfb->bus_clk);
if (!sfb->variant.has_clksel)
clk_enable(sfb->lcd_clk);
/* setup gpio and output polarity controls */
pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
}
if (!sfb->variant.has_clksel)
clk_disable(sfb->lcd_clk);
clk_disable(sfb->bus_clk);
return 0;
}
@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev)
clk_enable(sfb->bus_clk);
if (!sfb->variant.has_clksel)
clk_enable(sfb->lcd_clk);
/* setup gpio and output polarity controls */
pd->setup_gpio();
writel(pd->vidcon1, sfb->regs + VIDCON1);
@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = {
},
.has_prtcon = 1,
.has_clksel = 1,
},
.win[0] = &s3c_fb_data_64xx_wins[0],
.win[1] = &s3c_fb_data_64xx_wins[1],
@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
},
.has_prtcon = 1,
.has_clksel = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
@ -1794,6 +1839,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
};
static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
.variant = {
.nr_windows = 5,
.vidtcon = VIDTCON0,
.wincon = WINCON(0),
.winmap = WINxMAP(0),
.keycon = WKEYCON,
.osd = VIDOSD_BASE,
.osd_stride = 16,
.buf_start = VIDW_BUF_START(0),
.buf_size = VIDW_BUF_SIZE(0),
.buf_end = VIDW_BUF_END(0),
.palette = {
[0] = 0x2400,
[1] = 0x2800,
[2] = 0x2c00,
[3] = 0x3000,
[4] = 0x3400,
},
.has_shadowcon = 1,
.has_clksel = 1,
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
.win[2] = &s3c_fb_data_s5p_wins[2],
.win[3] = &s3c_fb_data_s5p_wins[3],
.win[4] = &s3c_fb_data_s5p_wins[4],
};
static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
.variant = {
.nr_windows = 5,
.vidtcon = VIDTCON0,
@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
[0] = 0x400,
[1] = 0x800,
},
.has_clksel = 1,
},
.win[0] = &(struct s3c_fb_win_variant) {
.palette_sz = 256,
@ -1859,6 +1936,30 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = {
},
};
static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
.variant = {
.nr_windows = 3,
.vidtcon = VIDTCON0,
.wincon = WINCON(0),
.winmap = WINxMAP(0),
.keycon = WKEYCON,
.osd = VIDOSD_BASE,
.osd_stride = 16,
.buf_start = VIDW_BUF_START(0),
.buf_size = VIDW_BUF_SIZE(0),
.buf_end = VIDW_BUF_END(0),
.palette = {
[0] = 0x2400,
[1] = 0x2800,
[2] = 0x2c00,
},
},
.win[0] = &s3c_fb_data_s5p_wins[0],
.win[1] = &s3c_fb_data_s5p_wins[1],
.win[2] = &s3c_fb_data_s5p_wins[2],
};
static struct platform_device_id s3c_fb_driver_ids[] = {
{
.name = "s3c-fb",
@ -1869,9 +1970,15 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
}, {
.name = "s5pv210-fb",
.driver_data = (unsigned long)&s3c_fb_data_s5pv210,
}, {
.name = "exynos4-fb",
.driver_data = (unsigned long)&s3c_fb_data_exynos4,
}, {
.name = "s3c2443-fb",
.driver_data = (unsigned long)&s3c_fb_data_s3c2443,
}, {
.name = "s5p64x0-fb",
.driver_data = (unsigned long)&s3c_fb_data_s5p64x0,
},
{},
};

View file

@ -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;
@ -911,7 +910,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
for (i = 0; i < 256; i++)
info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);
ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info);
if (ret) {
dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
ret = -EBUSY;

View file

@ -1019,12 +1019,13 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
unsigned int offset;
/* Calculate the offset */
if (var->bits_per_pixel == 0) {
offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
if (info->var.bits_per_pixel == 0) {
offset = (var->yoffset / 16) * (info->var.xres_virtual / 2)
+ (var->xoffset / 2);
offset = offset >> 2;
} else {
offset = (var->yoffset * info->fix.line_length) +
(var->xoffset * var->bits_per_pixel / 8);
(var->xoffset * info->var.bits_per_pixel / 8);
offset = offset >> 2;
}
@ -1504,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)

View file

@ -1457,8 +1457,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
if (ret)
goto failed;
ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED,
"LCD", fbi);
ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
goto failed;

View file

@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r
vgaHWProtect(par, 0);
}
static void savagefb_update_start(struct savagefb_par *par,
struct fb_var_screeninfo *var)
static void savagefb_update_start(struct savagefb_par *par, int base)
{
int base;
base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
* ((var->bits_per_pixel+7) / 8)) >> 2;
/* now program the start address registers */
/* program the start address registers */
vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
vga_out8(0x3d4, 0x69, par);
@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct savagefb_par *par = info->par;
int base;
savagefb_update_start(par, var);
base = (var->yoffset * info->fix.line_length
+ (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2;
savagefb_update_start(par, base);
return 0;
}

View file

@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
static void sh_hdmi_edid_work_fn(struct work_struct *work)
{
struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
struct fb_info *info;
struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
struct sh_mobile_lcdc_chan *ch;
int ret;
@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
mutex_lock(&hdmi->mutex);
info = hdmi->info;
if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
struct fb_info *info = hdmi->info;
unsigned long parent_rate = 0, hdmi_rate;
ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
ch = info->par;
console_lock();
if (lock_fb_info(info)) {
console_lock();
/* HDMI plug in */
if (!sh_hdmi_must_reconfigure(hdmi) &&
info->state == FBINFO_STATE_RUNNING) {
/*
* First activation with the default monitor - just turn
* on, if we run a resume here, the logo disappears
*/
if (lock_fb_info(info)) {
/* HDMI plug in */
if (!sh_hdmi_must_reconfigure(hdmi) &&
info->state == FBINFO_STATE_RUNNING) {
/*
* First activation with the default monitor - just turn
* on, if we run a resume here, the logo disappears
*/
info->var.width = hdmi->var.width;
info->var.height = hdmi->var.height;
sh_hdmi_display_on(hdmi, info);
unlock_fb_info(info);
} else {
/* New monitor or have to wake up */
fb_set_suspend(info, 0);
}
} else {
/* New monitor or have to wake up */
fb_set_suspend(info, 0);
}
console_unlock();
console_unlock();
unlock_fb_info(info);
}
} else {
ret = 0;
if (!hdmi->info)
if (!info)
goto out;
hdmi->monspec.modedb_len = 0;
fb_destroy_modedb(hdmi->monspec.modedb);
hdmi->monspec.modedb = NULL;
console_lock();
if (lock_fb_info(info)) {
console_lock();
/* HDMI disconnect */
fb_set_suspend(hdmi->info, 1);
/* HDMI disconnect */
fb_set_suspend(info, 1);
console_unlock();
console_unlock();
unlock_fb_info(info);
}
}
out:

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv;
struct fb_info;
struct backlight_device;
/*
* struct sh_mobile_lcdc_chan - LCDC display channel
*
* @base_addr_y: Frame buffer viewport base address (luma component)
* @base_addr_c: Frame buffer viewport base address (chroma component)
* @pitch: Frame buffer line pitch
*/
struct sh_mobile_lcdc_chan {
struct sh_mobile_lcdc_priv *lcdc;
unsigned long *reg_offs;
@ -25,7 +32,6 @@ struct sh_mobile_lcdc_chan {
unsigned long enabled; /* ME and SE in LDCNT2R */
struct sh_mobile_lcdc_chan_cfg cfg;
u32 pseudo_palette[PALETTE_NR];
unsigned long saved_ch_regs[NR_CH_REGS];
struct fb_info *info;
struct backlight_device *bl;
dma_addr_t dma_handle;
@ -40,6 +46,10 @@ struct sh_mobile_lcdc_chan {
int blank_status;
struct mutex open_lock; /* protects the use counter */
int meram_enabled;
unsigned long base_addr_y;
unsigned long base_addr_c;
unsigned int pitch;
};
#endif

View file

@ -12,29 +12,103 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include "sh_mobile_meram.h"
#include <video/sh_mobile_meram.h>
/* meram registers */
#define MExxCTL 0x0
#define MExxBSIZE 0x4
#define MExxMNCF 0x8
#define MExxSARA 0x10
#define MExxSARB 0x14
#define MExxSBSIZE 0x18
#define MEVCR1 0x4
#define MEVCR1_RST (1 << 31)
#define MEVCR1_WD (1 << 30)
#define MEVCR1_AMD1 (1 << 29)
#define MEVCR1_AMD0 (1 << 28)
#define MEQSEL1 0x40
#define MEQSEL2 0x44
#define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \
((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16))
#define MERAM_MExxBSIZE_VAL(a, b, c) \
(((a) << 28) | ((b) << 16) | (c))
#define MExxCTL 0x400
#define MExxCTL_BV (1 << 31)
#define MExxCTL_BSZ_SHIFT 28
#define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT)
#define MExxCTL_MSAR_SHIFT 16
#define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT)
#define MExxCTL_NXT_SHIFT 11
#define MExxCTL_WD1 (1 << 10)
#define MExxCTL_WD0 (1 << 9)
#define MExxCTL_WS (1 << 8)
#define MExxCTL_CB (1 << 7)
#define MExxCTL_WBF (1 << 6)
#define MExxCTL_WF (1 << 5)
#define MExxCTL_RF (1 << 4)
#define MExxCTL_CM (1 << 3)
#define MExxCTL_MD_READ (1 << 0)
#define MExxCTL_MD_WRITE (2 << 0)
#define MExxCTL_MD_ICB_WB (3 << 0)
#define MExxCTL_MD_ICB (4 << 0)
#define MExxCTL_MD_FB (7 << 0)
#define MExxCTL_MD_MASK (7 << 0)
#define MExxBSIZE 0x404
#define MExxBSIZE_RCNT_SHIFT 28
#define MExxBSIZE_YSZM1_SHIFT 16
#define MExxBSIZE_XSZM1_SHIFT 0
#define MExxMNCF 0x408
#define MExxMNCF_KWBNM_SHIFT 28
#define MExxMNCF_KRBNM_SHIFT 24
#define MExxMNCF_BNM_SHIFT 16
#define MExxMNCF_XBV (1 << 15)
#define MExxMNCF_CPL_YCBCR444 (1 << 12)
#define MExxMNCF_CPL_YCBCR420 (2 << 12)
#define MExxMNCF_CPL_YCBCR422 (3 << 12)
#define MExxMNCF_CPL_MSK (3 << 12)
#define MExxMNCF_BL (1 << 2)
#define MExxMNCF_LNM_SHIFT 0
#define MExxSARA 0x410
#define MExxSARB 0x414
#define MExxSBSIZE 0x418
#define MExxSBSIZE_HDV (1 << 31)
#define MExxSBSIZE_HSZ16 (0 << 28)
#define MExxSBSIZE_HSZ32 (1 << 28)
#define MExxSBSIZE_HSZ64 (2 << 28)
#define MExxSBSIZE_HSZ128 (3 << 28)
#define MExxSBSIZE_SBSIZZ_SHIFT 0
#define MEVCR1 0x4
#define MEACTS 0x10
#define MEQSEL1 0x40
#define MEQSEL2 0x44
#define MERAM_MExxCTL_VAL(next, addr) \
((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
(((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
#define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
(((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
((xszm1) << MExxBSIZE_XSZM1_SHIFT))
#define SH_MOBILE_MERAM_ICB_NUM 32
static unsigned long common_regs[] = {
MEVCR1,
MEQSEL1,
MEQSEL2,
};
#define CMN_REGS_SIZE ARRAY_SIZE(common_regs)
static unsigned long icb_regs[] = {
MExxCTL,
MExxBSIZE,
MExxMNCF,
MExxSARA,
MExxSARB,
MExxSBSIZE,
};
#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
struct sh_mobile_meram_priv {
void __iomem *base;
struct mutex lock;
unsigned long used_icb;
int used_meram_cache_regions;
unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
unsigned long cmn_saved_regs[CMN_REGS_SIZE];
unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM];
};
/* settings */
#define MERAM_SEC_LINE 15
@ -44,8 +118,7 @@
* MERAM/ICB access functions
*/
#define MERAM_ICB_OFFSET(base, idx, off) \
((base) + (0x400 + ((idx) * 0x20) + (off)))
#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
static inline void meram_write_icb(void __iomem *base, int idx, int off,
unsigned long val)
@ -280,17 +353,18 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
/*
* Set MERAM for framebuffer
*
* 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode
* we also chain the cache_icb and the marker_icb.
* we also split the allocated MERAM buffer between two ICBs.
*/
meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
MERAM_MExxCTL_VAL(0x70f, icb->marker_icb,
icb->meram_offset));
MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) |
MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
MExxCTL_MD_FB);
meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
MERAM_MExxCTL_VAL(0x70f, icb->cache_icb,
icb->meram_offset +
icb->meram_size / 2));
MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset +
icb->meram_size / 2) |
MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
MExxCTL_MD_FB);
return 0;
}
@ -299,8 +373,10 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv,
struct sh_mobile_meram_icb *icb)
{
/* disable ICB */
meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0);
meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0);
meram_write_icb(priv->base, icb->cache_icb, MExxCTL,
MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
meram_write_icb(priv->base, icb->marker_icb, MExxCTL,
MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
icb->cache_unit = 0;
}
@ -337,24 +413,22 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
xres, yres, (!pixelformat) ? "yuv" : "rgb",
base_addr_y, base_addr_c);
mutex_lock(&priv->lock);
/* we can't handle wider than 8192px */
if (xres > 8192) {
dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
error = -EINVAL;
goto err;
}
if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
dev_err(&pdev->dev, "no more ICB available.");
error = -EINVAL;
goto err;
return -EINVAL;
}
/* do we have at least one ICB config? */
if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
dev_err(&pdev->dev, "at least one ICB is required.");
return -EINVAL;
}
mutex_lock(&priv->lock);
if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) {
dev_err(&pdev->dev, "no more ICB available.");
error = -EINVAL;
goto err;
}
@ -460,6 +534,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata,
return 0;
}
static int sh_mobile_meram_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
int k, j;
for (k = 0; k < CMN_REGS_SIZE; k++)
priv->cmn_saved_regs[k] = meram_read_reg(priv->base,
common_regs[k]);
for (j = 0; j < 32; j++) {
if (!test_bit(j, &priv->used_icb))
continue;
for (k = 0; k < ICB_REGS_SIZE; k++) {
priv->icb_saved_regs[j * ICB_REGS_SIZE + k] =
meram_read_icb(priv->base, j, icb_regs[k]);
/* Reset ICB on resume */
if (icb_regs[k] == MExxCTL)
priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |=
MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
}
}
return 0;
}
static int sh_mobile_meram_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
int k, j;
for (j = 0; j < 32; j++) {
if (!test_bit(j, &priv->used_icb))
continue;
for (k = 0; k < ICB_REGS_SIZE; k++) {
meram_write_icb(priv->base, j, icb_regs[k],
priv->icb_saved_regs[j * ICB_REGS_SIZE + k]);
}
}
for (k = 0; k < CMN_REGS_SIZE; k++)
meram_write_reg(priv->base, common_regs[k],
priv->cmn_saved_regs[k]);
return 0;
}
static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = {
.runtime_suspend = sh_mobile_meram_runtime_suspend,
.runtime_resume = sh_mobile_meram_runtime_resume,
};
static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
.module = THIS_MODULE,
.meram_register = sh_mobile_meram_register,
@ -513,7 +638,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
/* initialize ICB addressing mode */
if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
meram_write_reg(priv->base, MEVCR1, 1 << 29);
meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
pm_runtime_enable(&pdev->dev);
dev_info(&pdev->dev, "sh_mobile_meram initialized.");
@ -530,6 +657,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev)
{
struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
if (priv->base)
iounmap(priv->base);
@ -544,6 +673,7 @@ static struct platform_driver sh_mobile_meram_driver = {
.driver = {
.name = "sh_mobile_meram",
.owner = THIS_MODULE,
.pm = &sh_mobile_meram_dev_pm_ops,
},
.probe = sh_mobile_meram_probe,
.remove = sh_mobile_meram_remove,

View file

@ -1,41 +0,0 @@
#ifndef __sh_mobile_meram_h__
#define __sh_mobile_meram_h__
#include <linux/mutex.h>
#include <video/sh_mobile_meram.h>
/*
* MERAM private
*/
#define MERAM_ICB_Y 0x1
#define MERAM_ICB_C 0x2
/* MERAM cache size */
#define SH_MOBILE_MERAM_ICB_NUM 32
#define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16)
#define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff)
struct sh_mobile_meram_priv {
void __iomem *base;
struct mutex lock;
unsigned long used_icb;
int used_meram_cache_regions;
unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM];
};
int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg,
int xres,
int yres,
unsigned int base_addr,
int yuv_mode,
int *marker_icb,
int *out_pitch);
void sh_mobile_meram_free_icb(int marker_icb);
#define SH_MOBILE_MERAM_START(ind, ab) \
(0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24))
#endif /* !__sh_mobile_meram_h__ */

View file

@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
}
static int
sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info,
struct fb_var_screeninfo *var)
{
if(var->xoffset > (var->xres_virtual - var->xres)) {
return -EINVAL;
}
if(var->yoffset > (var->yres_virtual - var->yres)) {
return -EINVAL;
}
ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
ivideo->current_base = var->yoffset * info->var.xres_virtual
+ var->xoffset;
/* calculate base bpp dep. */
switch(var->bits_per_pixel) {
switch (info->var.bits_per_pixel) {
case 32:
break;
case 16:
@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
int err;
if(var->xoffset > (var->xres_virtual - var->xres))
if (var->vmode & FB_VMODE_YWRAP)
return -EINVAL;
if(var->yoffset > (var->yres_virtual - var->yres))
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
if(var->vmode & FB_VMODE_YWRAP)
return -EINVAL;
if(var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
if((err = sisfb_pan_var(ivideo, var)) < 0)
err = sisfb_pan_var(ivideo, info, var);
if (err < 0)
return err;
info->var.xoffset = var->xoffset;

View file

@ -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 */

Some files were not shown because too many files have changed in this diff Show more