mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge commit 'v2.6.36-rc3' into x86/memblock
Conflicts: arch/x86/kernel/trampoline.c mm/memblock.c Merge reason: Resolve the conflicts, update to latest upstream. Signed-off-by: Ingo Molnar <[email protected]>
This commit is contained in:
commit
daab7fc734
8185 changed files with 510523 additions and 574313 deletions
|
|
@ -1505,7 +1505,7 @@ config FB_SIS_315
|
|||
|
||||
config FB_VIA
|
||||
tristate "VIA UniChrome (Pro) and Chrome9 display support"
|
||||
depends on FB && PCI
|
||||
depends on FB && PCI && X86
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
|
|
@ -1871,6 +1871,7 @@ config FB_MBX_DEBUG
|
|||
config FB_FSL_DIU
|
||||
tristate "Freescale DIU framebuffer support"
|
||||
depends on FB && FSL_SOC
|
||||
select FB_MODE_HELPERS
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
|
|
@ -1895,6 +1896,13 @@ config FB_W100
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config SH_MIPI_DSI
|
||||
tristate
|
||||
depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
|
||||
|
||||
config SH_LCD_MIPI_DSI
|
||||
bool
|
||||
|
||||
config FB_SH_MOBILE_LCDC
|
||||
tristate "SuperH Mobile LCDC framebuffer support"
|
||||
depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
|
||||
|
|
@ -1903,9 +1911,17 @@ config FB_SH_MOBILE_LCDC
|
|||
select FB_SYS_IMAGEBLIT
|
||||
select FB_SYS_FOPS
|
||||
select FB_DEFERRED_IO
|
||||
select SH_MIPI_DSI if SH_LCD_MIPI_DSI
|
||||
---help---
|
||||
Frame buffer driver for the on-chip SH-Mobile LCD controller.
|
||||
|
||||
config FB_SH_MOBILE_HDMI
|
||||
tristate "SuperH Mobile HDMI controller support"
|
||||
depends on FB_SH_MOBILE_LCDC
|
||||
select FB_MODE_HELPERS
|
||||
---help---
|
||||
Driver for the on-chip SH-Mobile HDMI controller.
|
||||
|
||||
config FB_TMIO
|
||||
tristate "Toshiba Mobile IO FrameBuffer support"
|
||||
depends on FB && MFD_CORE
|
||||
|
|
@ -1930,7 +1946,7 @@ config FB_TMIO_ACCELL
|
|||
|
||||
config FB_S3C
|
||||
tristate "Samsung S3C framebuffer support"
|
||||
depends on FB && ARCH_S3C64XX
|
||||
depends on FB && S3C_DEV_FB
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
|
|
@ -2229,6 +2245,15 @@ config FB_BROADSHEET
|
|||
and could also have been called by other names when coupled with
|
||||
a bridge adapter.
|
||||
|
||||
config FB_JZ4740
|
||||
tristate "JZ4740 LCD framebuffer support"
|
||||
depends on FB && MACH_JZ4740
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
help
|
||||
Framebuffer support for the JZ4740 SoC.
|
||||
|
||||
source "drivers/video/omap/Kconfig"
|
||||
source "drivers/video/omap2/Kconfig"
|
||||
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
|
|||
obj-$(CONFIG_FB_PS3) += ps3fb.o
|
||||
obj-$(CONFIG_FB_SM501) += sm501fb.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
|
||||
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
|
||||
obj-$(CONFIG_FB_OMAP) += omap/
|
||||
obj-y += omap2/
|
||||
|
|
@ -131,6 +133,7 @@ obj-$(CONFIG_FB_CARMINE) += carminefb.o
|
|||
obj-$(CONFIG_FB_MB862XX) += mb862xx/
|
||||
obj-$(CONFIG_FB_MSM) += msm/
|
||||
obj-$(CONFIG_FB_NUC900) += nuc900fb.o
|
||||
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
|
||||
|
||||
# Platform or fallback drivers go here
|
||||
obj-$(CONFIG_FB_UVESA) += uvesafb.o
|
||||
|
|
|
|||
|
|
@ -80,7 +80,10 @@ static void clcdfb_disable(struct clcd_fb *fb)
|
|||
/*
|
||||
* Disable CLCD clock source.
|
||||
*/
|
||||
clk_disable(fb->clk);
|
||||
if (fb->clk_enabled) {
|
||||
fb->clk_enabled = false;
|
||||
clk_disable(fb->clk);
|
||||
}
|
||||
}
|
||||
|
||||
static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
|
||||
|
|
@ -88,7 +91,10 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
|
|||
/*
|
||||
* Enable the CLCD clock source.
|
||||
*/
|
||||
clk_enable(fb->clk);
|
||||
if (!fb->clk_enabled) {
|
||||
fb->clk_enabled = true;
|
||||
clk_enable(fb->clk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bring up by first enabling..
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Backlight control code for Sharp Zaurus SL-5500
|
||||
*
|
||||
* Copyright 2005 John Lenz <lenz@cs.wisc.edu>
|
||||
* Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-)
|
||||
* Maintainer: Pavel Machek <pavel@ucw.cz> (unless John wants to :-)
|
||||
* GPL v2
|
||||
*
|
||||
* This driver assumes single CPU. That's okay, because collie is
|
||||
|
|
@ -246,6 +246,6 @@ static void __exit locomolcd_exit(void)
|
|||
module_init(locomolcd_init);
|
||||
module_exit(locomolcd_exit);
|
||||
|
||||
MODULE_AUTHOR("John Lenz <[email protected]>, Pavel Machek <pavel@suse.cz>");
|
||||
MODULE_AUTHOR("John Lenz <[email protected]>, Pavel Machek <pavel@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Collie LCD driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
|
||||
static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
struct fb_info *info;
|
||||
|
|
@ -350,7 +350,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit bw2_remove(struct of_device *op)
|
||||
static int __devexit bw2_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct bw2_par *par = info->par;
|
||||
|
|
@ -390,12 +390,12 @@ static int __init bw2_init(void)
|
|||
if (fb_get_options("bw2fb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&bw2_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&bw2_driver);
|
||||
}
|
||||
|
||||
static void __exit bw2_exit(void)
|
||||
{
|
||||
of_unregister_driver(&bw2_driver);
|
||||
of_unregister_platform_driver(&bw2_driver);
|
||||
}
|
||||
|
||||
module_init(bw2_init);
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ static int init_hardware(struct carmine_hw *hw)
|
|||
u32 loops;
|
||||
u32 ret;
|
||||
|
||||
/* Initalize Carmine */
|
||||
/* Initialize Carmine */
|
||||
/* Sets internal clock */
|
||||
c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
|
||||
CARMINE_DFLT_IP_CLOCK_ENABLE);
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
|
|||
{ .size = 0 }
|
||||
};
|
||||
|
||||
static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
|
||||
struct cg14_par *par)
|
||||
{
|
||||
if (par->regs)
|
||||
|
|
@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
|
|||
info->screen_base, info->fix.smem_len);
|
||||
}
|
||||
|
||||
static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
|
||||
static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
struct fb_info *info;
|
||||
|
|
@ -570,7 +570,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit cg14_remove(struct of_device *op)
|
||||
static int __devexit cg14_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct cg14_par *par = info->par;
|
||||
|
|
@ -610,12 +610,12 @@ static int __init cg14_init(void)
|
|||
if (fb_get_options("cg14fb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&cg14_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&cg14_driver);
|
||||
}
|
||||
|
||||
static void __exit cg14_exit(void)
|
||||
{
|
||||
of_unregister_driver(&cg14_driver);
|
||||
of_unregister_platform_driver(&cg14_driver);
|
||||
}
|
||||
|
||||
module_init(cg14_init);
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit cg3_probe(struct of_device *op,
|
||||
static int __devinit cg3_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
|
|
@ -433,7 +433,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit cg3_remove(struct of_device *op)
|
||||
static int __devexit cg3_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct cg3_par *par = info->par;
|
||||
|
|
@ -477,12 +477,12 @@ static int __init cg3_init(void)
|
|||
if (fb_get_options("cg3fb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&cg3_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&cg3_driver);
|
||||
}
|
||||
|
||||
static void __exit cg3_exit(void)
|
||||
{
|
||||
of_unregister_driver(&cg3_driver);
|
||||
of_unregister_platform_driver(&cg3_driver);
|
||||
}
|
||||
|
||||
module_init(cg3_init);
|
||||
|
|
|
|||
|
|
@ -718,7 +718,7 @@ static void __devinit cg6_chip_init(struct fb_info *info)
|
|||
sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
|
||||
}
|
||||
|
||||
static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
|
||||
struct cg6_par *par)
|
||||
{
|
||||
if (par->fbc)
|
||||
|
|
@ -737,7 +737,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
|
|||
info->fix.smem_len);
|
||||
}
|
||||
|
||||
static int __devinit cg6_probe(struct of_device *op,
|
||||
static int __devinit cg6_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
|
|
@ -827,7 +827,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit cg6_remove(struct of_device *op)
|
||||
static int __devexit cg6_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct cg6_par *par = info->par;
|
||||
|
|
@ -870,12 +870,12 @@ static int __init cg6_init(void)
|
|||
if (fb_get_options("cg6fb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&cg6_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&cg6_driver);
|
||||
}
|
||||
|
||||
static void __exit cg6_exit(void)
|
||||
{
|
||||
of_unregister_driver(&cg6_driver);
|
||||
of_unregister_platform_driver(&cg6_driver);
|
||||
}
|
||||
|
||||
module_init(cg6_init);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ menu "Console display driver support"
|
|||
|
||||
config VGA_CONSOLE
|
||||
bool "VGA text console" if EMBEDDED || !X86
|
||||
depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BLACKFIN && !AVR32 && !MN10300
|
||||
depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER)
|
||||
default y
|
||||
help
|
||||
Saying Y here will allow you to use Linux in text mode through a
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
/*
|
||||
* Accelerated handlers.
|
||||
*/
|
||||
static inline void update_attr(u8 *dst, u8 *src, int attribute,
|
||||
static void update_attr(u8 *dst, u8 *src, int attribute,
|
||||
struct vc_data *vc)
|
||||
{
|
||||
int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
|
||||
|
|
|
|||
|
|
@ -283,10 +283,11 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
|
|||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
||||
return (info->state != FBINFO_STATE_RUNNING ||
|
||||
vc->vc_mode != KD_TEXT || ops->graphics);
|
||||
vc->vc_mode != KD_TEXT || ops->graphics) &&
|
||||
!vt_force_oops_output(vc);
|
||||
}
|
||||
|
||||
static inline int get_color(struct vc_data *vc, struct fb_info *info,
|
||||
static int get_color(struct vc_data *vc, struct fb_info *info,
|
||||
u16 c, int is_fg)
|
||||
{
|
||||
int depth = fb_get_color_depth(&info->var, &info->fix);
|
||||
|
|
@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|||
if (p->userfont)
|
||||
charcnt = FNTCHARCNT(p->fontdata);
|
||||
|
||||
vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT);
|
||||
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
|
||||
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
|
||||
if (charcnt == 256) {
|
||||
|
|
@ -2342,6 +2344,30 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_debug_enter(struct vc_data *vc)
|
||||
{
|
||||
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
||||
ops->save_graphics = ops->graphics;
|
||||
ops->graphics = 0;
|
||||
if (info->fbops->fb_debug_enter)
|
||||
info->fbops->fb_debug_enter(info);
|
||||
fbcon_set_palette(vc, color_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_debug_leave(struct vc_data *vc)
|
||||
{
|
||||
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
||||
ops->graphics = ops->save_graphics;
|
||||
if (info->fbops->fb_debug_leave)
|
||||
info->fbops->fb_debug_leave(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
|
||||
{
|
||||
u8 *fontdata = vc->vc_font.data;
|
||||
|
|
@ -3276,6 +3302,8 @@ static const struct consw fb_con = {
|
|||
.con_screen_pos = fbcon_screen_pos,
|
||||
.con_getxy = fbcon_getxy,
|
||||
.con_resize = fbcon_resize,
|
||||
.con_debug_enter = fbcon_debug_enter,
|
||||
.con_debug_leave = fbcon_debug_leave,
|
||||
};
|
||||
|
||||
static struct notifier_block fbcon_event_notifier = {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ struct fbcon_ops {
|
|||
int cursor_reset;
|
||||
int blank_state;
|
||||
int graphics;
|
||||
int save_graphics; /* for debug enter/leave */
|
||||
int flags;
|
||||
int rotate;
|
||||
int cur_rotate;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
* Rotation 270 degrees
|
||||
*/
|
||||
|
||||
static inline void ccw_update_attr(u8 *dst, u8 *src, int attribute,
|
||||
static void ccw_update_attr(u8 *dst, u8 *src, int attribute,
|
||||
struct vc_data *vc)
|
||||
{
|
||||
int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
* Rotation 90 degrees
|
||||
*/
|
||||
|
||||
static inline void cw_update_attr(u8 *dst, u8 *src, int attribute,
|
||||
static void cw_update_attr(u8 *dst, u8 *src, int attribute,
|
||||
struct vc_data *vc)
|
||||
{
|
||||
int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
* Rotation 180 degrees
|
||||
*/
|
||||
|
||||
static inline void ud_update_attr(u8 *dst, u8 *src, int attribute,
|
||||
static void ud_update_attr(u8 *dst, u8 *src, int attribute,
|
||||
struct vc_data *vc)
|
||||
{
|
||||
int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
|
||||
|
|
|
|||
|
|
@ -1108,7 +1108,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
|
|||
charmap += 4 * cmapsz;
|
||||
#endif
|
||||
|
||||
unlock_kernel();
|
||||
spin_lock_irq(&vga_lock);
|
||||
/* First, the Sequencer */
|
||||
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
|
||||
|
|
@ -1192,7 +1191,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
|
|||
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
|
||||
}
|
||||
spin_unlock_irq(&vga_lock);
|
||||
lock_kernel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <video/vga.h>
|
||||
|
||||
static struct fb_var_screeninfo efifb_defined __initdata = {
|
||||
static struct fb_var_screeninfo efifb_defined __devinitdata = {
|
||||
.activate = FB_ACTIVATE_NOW,
|
||||
.height = -1,
|
||||
.width = -1,
|
||||
|
|
@ -27,7 +27,7 @@ static struct fb_var_screeninfo efifb_defined __initdata = {
|
|||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo efifb_fix __initdata = {
|
||||
static struct fb_fix_screeninfo efifb_fix __devinitdata = {
|
||||
.id = "EFI VGA",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
|
|
@ -59,7 +59,7 @@ static struct efifb_dmi_info {
|
|||
int stride;
|
||||
int width;
|
||||
int height;
|
||||
} dmi_list[] = {
|
||||
} dmi_list[] __initdata = {
|
||||
[M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 },
|
||||
[M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */
|
||||
[M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 },
|
||||
|
|
@ -83,7 +83,7 @@ static int set_system(const struct dmi_system_id *id);
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
|
||||
&dmi_list[enumid] }
|
||||
|
||||
static struct dmi_system_id __initdata dmi_system_table[] = {
|
||||
static const struct dmi_system_id dmi_system_table[] __initconst = {
|
||||
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
|
||||
/* At least one of these two will be right; maybe both? */
|
||||
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
|
||||
|
|
|
|||
|
|
@ -1362,6 +1362,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
|
|||
vma->vm_pgoff = off >> PAGE_SHIFT;
|
||||
/* This is an IO map - tell maydump to skip this VMA */
|
||||
vma->vm_flags |= VM_IO | VM_RESERVED;
|
||||
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
|
||||
fb_pgprotect(file, vma, off);
|
||||
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot))
|
||||
|
|
@ -1786,7 +1787,7 @@ static int ofonly __read_mostly;
|
|||
int fb_get_options(char *name, char **option)
|
||||
{
|
||||
char *opt, *options = NULL;
|
||||
int opt_len, retval = 0;
|
||||
int retval = 0;
|
||||
int name_len = strlen(name), i;
|
||||
|
||||
if (name_len && ofonly && strncmp(name, "offb", 4))
|
||||
|
|
@ -1796,8 +1797,7 @@ int fb_get_options(char *name, char **option)
|
|||
for (i = 0; i < FB_MAX; i++) {
|
||||
if (video_options[i] == NULL)
|
||||
continue;
|
||||
opt_len = strlen(video_options[i]);
|
||||
if (!opt_len)
|
||||
if (!video_options[i][0])
|
||||
continue;
|
||||
opt = video_options[i];
|
||||
if (!strncmp(name, opt, name_len) &&
|
||||
|
|
|
|||
|
|
@ -893,7 +893,7 @@ static void ffb_init_fix(struct fb_info *info)
|
|||
info->fix.accel = FB_ACCEL_SUN_CREATOR;
|
||||
}
|
||||
|
||||
static int __devinit ffb_probe(struct of_device *op,
|
||||
static int __devinit ffb_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
|
|
@ -1023,7 +1023,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit ffb_remove(struct of_device *op)
|
||||
static int __devexit ffb_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct ffb_par *par = info->par;
|
||||
|
|
@ -1067,12 +1067,12 @@ static int __init ffb_init(void)
|
|||
if (fb_get_options("ffb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&ffb_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&ffb_driver);
|
||||
}
|
||||
|
||||
static void __exit ffb_exit(void)
|
||||
{
|
||||
of_unregister_driver(&ffb_driver);
|
||||
of_unregister_platform_driver(&ffb_driver);
|
||||
}
|
||||
|
||||
module_init(ffb_init);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
#include <linux/of_platform.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include "fsl-diu-fb.h"
|
||||
#include <linux/fsl-diu-fb.h>
|
||||
#include "edid.h"
|
||||
|
||||
/*
|
||||
* These parameters give default parameters
|
||||
|
|
@ -217,6 +218,7 @@ struct mfb_info {
|
|||
int x_aoi_d; /* aoi display x offset to physical screen */
|
||||
int y_aoi_d; /* aoi display y offset to physical screen */
|
||||
struct fsl_diu_data *parent;
|
||||
u8 *edid_data;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -317,6 +319,17 @@ static void fsl_diu_free(void *virt, size_t size)
|
|||
free_pages_exact(virt, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for failed writing desc register of planes.
|
||||
* Needed with MPC5121 DIU rev 2.0 silicon.
|
||||
*/
|
||||
void wr_reg_wa(u32 *reg, u32 val)
|
||||
{
|
||||
do {
|
||||
out_be32(reg, val);
|
||||
} while (in_be32(reg) != val);
|
||||
}
|
||||
|
||||
static int fsl_diu_enable_panel(struct fb_info *info)
|
||||
{
|
||||
struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
|
||||
|
|
@ -330,7 +343,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
|
|||
switch (mfbi->index) {
|
||||
case 0: /* plane 0 */
|
||||
if (hw->desc[0] != ad->paddr)
|
||||
out_be32(&hw->desc[0], ad->paddr);
|
||||
wr_reg_wa(&hw->desc[0], ad->paddr);
|
||||
break;
|
||||
case 1: /* plane 1 AOI 0 */
|
||||
cmfbi = machine_data->fsl_diu_info[2]->par;
|
||||
|
|
@ -340,7 +353,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
|
|||
cpu_to_le32(cmfbi->ad->paddr);
|
||||
else
|
||||
ad->next_ad = 0;
|
||||
out_be32(&hw->desc[1], ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], ad->paddr);
|
||||
}
|
||||
break;
|
||||
case 3: /* plane 2 AOI 0 */
|
||||
|
|
@ -351,14 +364,14 @@ static int fsl_diu_enable_panel(struct fb_info *info)
|
|||
cpu_to_le32(cmfbi->ad->paddr);
|
||||
else
|
||||
ad->next_ad = 0;
|
||||
out_be32(&hw->desc[2], ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], ad->paddr);
|
||||
}
|
||||
break;
|
||||
case 2: /* plane 1 AOI 1 */
|
||||
pmfbi = machine_data->fsl_diu_info[1]->par;
|
||||
ad->next_ad = 0;
|
||||
if (hw->desc[1] == machine_data->dummy_ad->paddr)
|
||||
out_be32(&hw->desc[1], ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], ad->paddr);
|
||||
else /* AOI0 open */
|
||||
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
|
||||
break;
|
||||
|
|
@ -366,7 +379,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
|
|||
pmfbi = machine_data->fsl_diu_info[3]->par;
|
||||
ad->next_ad = 0;
|
||||
if (hw->desc[2] == machine_data->dummy_ad->paddr)
|
||||
out_be32(&hw->desc[2], ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], ad->paddr);
|
||||
else /* AOI0 was open */
|
||||
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
|
||||
break;
|
||||
|
|
@ -390,27 +403,24 @@ static int fsl_diu_disable_panel(struct fb_info *info)
|
|||
switch (mfbi->index) {
|
||||
case 0: /* plane 0 */
|
||||
if (hw->desc[0] != machine_data->dummy_ad->paddr)
|
||||
out_be32(&hw->desc[0],
|
||||
machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
|
||||
break;
|
||||
case 1: /* plane 1 AOI 0 */
|
||||
cmfbi = machine_data->fsl_diu_info[2]->par;
|
||||
if (cmfbi->count > 0) /* AOI1 is open */
|
||||
out_be32(&hw->desc[1], cmfbi->ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
|
||||
/* move AOI1 to the first */
|
||||
else /* AOI1 was closed */
|
||||
out_be32(&hw->desc[1],
|
||||
machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
|
||||
/* close AOI 0 */
|
||||
break;
|
||||
case 3: /* plane 2 AOI 0 */
|
||||
cmfbi = machine_data->fsl_diu_info[4]->par;
|
||||
if (cmfbi->count > 0) /* AOI1 is open */
|
||||
out_be32(&hw->desc[2], cmfbi->ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
|
||||
/* move AOI1 to the first */
|
||||
else /* AOI1 was closed */
|
||||
out_be32(&hw->desc[2],
|
||||
machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
|
||||
/* close AOI 0 */
|
||||
break;
|
||||
case 2: /* plane 1 AOI 1 */
|
||||
|
|
@ -421,7 +431,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
|
|||
/* AOI0 is open, must be the first */
|
||||
pmfbi->ad->next_ad = 0;
|
||||
} else /* AOI1 is the first in the chain */
|
||||
out_be32(&hw->desc[1], machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
|
||||
/* close AOI 1 */
|
||||
break;
|
||||
case 4: /* plane 2 AOI 1 */
|
||||
|
|
@ -432,7 +442,7 @@ static int fsl_diu_disable_panel(struct fb_info *info)
|
|||
/* AOI0 is open, must be the first */
|
||||
pmfbi->ad->next_ad = 0;
|
||||
} else /* AOI1 is the first in the chain */
|
||||
out_be32(&hw->desc[2], machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
|
||||
/* close AOI 1 */
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1100,6 +1110,10 @@ static int fsl_diu_open(struct fb_info *info, int user)
|
|||
struct mfb_info *mfbi = info->par;
|
||||
int res = 0;
|
||||
|
||||
/* free boot splash memory on first /dev/fb0 open */
|
||||
if (!mfbi->index && diu_ops.release_bootmem)
|
||||
diu_ops.release_bootmem();
|
||||
|
||||
spin_lock(&diu_lock);
|
||||
mfbi->count++;
|
||||
if (mfbi->count == 1) {
|
||||
|
|
@ -1173,18 +1187,30 @@ static int __devinit install_fb(struct fb_info *info)
|
|||
int rc;
|
||||
struct mfb_info *mfbi = info->par;
|
||||
const char *aoi_mode, *init_aoi_mode = "320x240";
|
||||
struct fb_videomode *db = fsl_diu_mode_db;
|
||||
unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
|
||||
int has_default_mode = 1;
|
||||
|
||||
if (init_fbinfo(info))
|
||||
return -EINVAL;
|
||||
|
||||
if (mfbi->index == 0) /* plane 0 */
|
||||
if (mfbi->index == 0) { /* plane 0 */
|
||||
if (mfbi->edid_data) {
|
||||
/* Now build modedb from EDID */
|
||||
fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
|
||||
fb_videomode_to_modelist(info->monspecs.modedb,
|
||||
info->monspecs.modedb_len,
|
||||
&info->modelist);
|
||||
db = info->monspecs.modedb;
|
||||
dbsize = info->monspecs.modedb_len;
|
||||
}
|
||||
aoi_mode = fb_mode;
|
||||
else
|
||||
} else {
|
||||
aoi_mode = init_aoi_mode;
|
||||
}
|
||||
pr_debug("mode used = %s\n", aoi_mode);
|
||||
rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
|
||||
ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp);
|
||||
|
||||
rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize,
|
||||
&fsl_diu_default_mode, default_bpp);
|
||||
switch (rc) {
|
||||
case 1:
|
||||
pr_debug("using mode specified in @mode\n");
|
||||
|
|
@ -1202,10 +1228,50 @@ static int __devinit install_fb(struct fb_info *info)
|
|||
default:
|
||||
pr_debug("rc = %d\n", rc);
|
||||
pr_debug("failed to find mode\n");
|
||||
return -EINVAL;
|
||||
/*
|
||||
* For plane 0 we continue and look into
|
||||
* driver's internal modedb.
|
||||
*/
|
||||
if (mfbi->index == 0 && mfbi->edid_data)
|
||||
has_default_mode = 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!has_default_mode) {
|
||||
rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
|
||||
ARRAY_SIZE(fsl_diu_mode_db),
|
||||
&fsl_diu_default_mode,
|
||||
default_bpp);
|
||||
if (rc > 0 && rc < 5)
|
||||
has_default_mode = 1;
|
||||
}
|
||||
|
||||
/* Still not found, use preferred mode from database if any */
|
||||
if (!has_default_mode && info->monspecs.modedb) {
|
||||
struct fb_monspecs *specs = &info->monspecs;
|
||||
struct fb_videomode *modedb = &specs->modedb[0];
|
||||
|
||||
/*
|
||||
* Get preferred timing. If not found,
|
||||
* first mode in database will be used.
|
||||
*/
|
||||
if (specs->misc & FB_MISC_1ST_DETAIL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < specs->modedb_len; i++) {
|
||||
if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
|
||||
modedb = &specs->modedb[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info->var.bits_per_pixel = default_bpp;
|
||||
fb_videomode_to_var(&info->var, modedb);
|
||||
}
|
||||
|
||||
pr_debug("xres_virtual %d\n", info->var.xres_virtual);
|
||||
pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
|
||||
|
||||
|
|
@ -1244,6 +1310,9 @@ static void uninstall_fb(struct fb_info *info)
|
|||
if (!mfbi->registered)
|
||||
return;
|
||||
|
||||
if (mfbi->index == 0)
|
||||
kfree(mfbi->edid_data);
|
||||
|
||||
unregister_framebuffer(info);
|
||||
unmap_video_memory(info);
|
||||
if (&info->cmap)
|
||||
|
|
@ -1324,7 +1393,7 @@ static void free_irq_local(int irq)
|
|||
* Power management hooks. Note that we won't be called from IRQ context,
|
||||
* unlike the blank functions above, so we may sleep.
|
||||
*/
|
||||
static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state)
|
||||
static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
|
||||
{
|
||||
struct fsl_diu_data *machine_data;
|
||||
|
||||
|
|
@ -1334,7 +1403,7 @@ static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fsl_diu_resume(struct of_device *ofdev)
|
||||
static int fsl_diu_resume(struct platform_device *ofdev)
|
||||
{
|
||||
struct fsl_diu_data *machine_data;
|
||||
|
||||
|
|
@ -1418,7 +1487,7 @@ static ssize_t show_monitor(struct device *device,
|
|||
return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
|
||||
}
|
||||
|
||||
static int __devinit fsl_diu_probe(struct of_device *ofdev,
|
||||
static int __devinit fsl_diu_probe(struct platform_device *ofdev,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
|
|
@ -1427,6 +1496,7 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
|
|||
int ret, i, error = 0;
|
||||
struct resource res;
|
||||
struct fsl_diu_data *machine_data;
|
||||
int diu_mode;
|
||||
|
||||
machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
|
||||
if (!machine_data)
|
||||
|
|
@ -1443,6 +1513,17 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
|
|||
mfbi = machine_data->fsl_diu_info[i]->par;
|
||||
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
|
||||
mfbi->parent = machine_data;
|
||||
|
||||
if (mfbi->index == 0) {
|
||||
const u8 *prop;
|
||||
int len;
|
||||
|
||||
/* Get EDID */
|
||||
prop = of_get_property(np, "edid", &len);
|
||||
if (prop && len == EDID_LENGTH)
|
||||
mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
|
|
@ -1463,7 +1544,9 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
|
|||
goto error2;
|
||||
}
|
||||
|
||||
out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU anyway*/
|
||||
diu_mode = in_be32(&dr.diu_reg->diu_mode);
|
||||
if (diu_mode != MFB_MODE1)
|
||||
out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */
|
||||
|
||||
/* Get the IRQ of the DIU */
|
||||
machine_data->irq = irq_of_parse_and_map(np, 0);
|
||||
|
|
@ -1511,7 +1594,13 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
|
|||
machine_data->dummy_ad->offset_xyd = 0;
|
||||
machine_data->dummy_ad->next_ad = 0;
|
||||
|
||||
out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
|
||||
/*
|
||||
* Let DIU display splash screen if it was pre-initialized
|
||||
* by the bootloader, set dummy area descriptor otherwise.
|
||||
*/
|
||||
if (diu_mode != MFB_MODE1)
|
||||
out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr);
|
||||
|
||||
out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr);
|
||||
out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr);
|
||||
|
||||
|
|
@ -1578,7 +1667,7 @@ error2:
|
|||
}
|
||||
|
||||
|
||||
static int fsl_diu_remove(struct of_device *ofdev)
|
||||
static int fsl_diu_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct fsl_diu_data *machine_data;
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
* Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* Freescale DIU Frame Buffer device driver
|
||||
*
|
||||
* Authors: Hongjun Chen <hong-jun.chen@freescale.com>
|
||||
* Paul Widmer <paul.widmer@freescale.com>
|
||||
* Srikanth Srinivasan <srikanth.srinivasan@freescale.com>
|
||||
* York Sun <yorksun@freescale.com>
|
||||
*
|
||||
* Based on imxfb.c Copyright (C) 2004 S.Hauer, Pengutronix
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FSL_DIU_FB_H__
|
||||
#define __FSL_DIU_FB_H__
|
||||
|
||||
/* Arbitrary threshold to determine the allocation method
|
||||
* See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
|
||||
*/
|
||||
#define MEM_ALLOC_THRESHOLD (1024*768*4+32)
|
||||
/* Minimum value that the pixel clock can be set to in pico seconds
|
||||
* This is determined by platform clock/3 where the minimum platform
|
||||
* clock is 533MHz. This gives 5629 pico seconds.
|
||||
*/
|
||||
#define MIN_PIX_CLK 5629
|
||||
#define MAX_PIX_CLK 96096
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct mfb_alpha {
|
||||
int enable;
|
||||
int alpha;
|
||||
};
|
||||
|
||||
struct mfb_chroma_key {
|
||||
int enable;
|
||||
__u8 red_max;
|
||||
__u8 green_max;
|
||||
__u8 blue_max;
|
||||
__u8 red_min;
|
||||
__u8 green_min;
|
||||
__u8 blue_min;
|
||||
};
|
||||
|
||||
struct aoi_display_offset {
|
||||
int x_aoi_d;
|
||||
int y_aoi_d;
|
||||
};
|
||||
|
||||
#define MFB_SET_CHROMA_KEY _IOW('M', 1, struct mfb_chroma_key)
|
||||
#define MFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t)
|
||||
#define MFB_SET_BRIGHTNESS _IOW('M', 3, __u8)
|
||||
|
||||
#define MFB_SET_ALPHA 0x80014d00
|
||||
#define MFB_GET_ALPHA 0x40014d00
|
||||
#define MFB_SET_AOID 0x80084d04
|
||||
#define MFB_GET_AOID 0x40084d04
|
||||
#define MFB_SET_PIXFMT 0x80014d08
|
||||
#define MFB_GET_PIXFMT 0x40014d08
|
||||
|
||||
#define FBIOGET_GWINFO 0x46E0
|
||||
#define FBIOPUT_GWINFO 0x46E1
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/*
|
||||
* These are the fields of area descriptor(in DDR memory) for every plane
|
||||
*/
|
||||
struct diu_ad {
|
||||
/* Word 0(32-bit) in DDR memory */
|
||||
/* __u16 comp; */
|
||||
/* __u16 pixel_s:2; */
|
||||
/* __u16 pallete:1; */
|
||||
/* __u16 red_c:2; */
|
||||
/* __u16 green_c:2; */
|
||||
/* __u16 blue_c:2; */
|
||||
/* __u16 alpha_c:3; */
|
||||
/* __u16 byte_f:1; */
|
||||
/* __u16 res0:3; */
|
||||
|
||||
__be32 pix_fmt; /* hard coding pixel format */
|
||||
|
||||
/* Word 1(32-bit) in DDR memory */
|
||||
__le32 addr;
|
||||
|
||||
/* Word 2(32-bit) in DDR memory */
|
||||
/* __u32 delta_xs:11; */
|
||||
/* __u32 res1:1; */
|
||||
/* __u32 delta_ys:11; */
|
||||
/* __u32 res2:1; */
|
||||
/* __u32 g_alpha:8; */
|
||||
__le32 src_size_g_alpha;
|
||||
|
||||
/* Word 3(32-bit) in DDR memory */
|
||||
/* __u32 delta_xi:11; */
|
||||
/* __u32 res3:5; */
|
||||
/* __u32 delta_yi:11; */
|
||||
/* __u32 res4:3; */
|
||||
/* __u32 flip:2; */
|
||||
__le32 aoi_size;
|
||||
|
||||
/* Word 4(32-bit) in DDR memory */
|
||||
/*__u32 offset_xi:11;
|
||||
__u32 res5:5;
|
||||
__u32 offset_yi:11;
|
||||
__u32 res6:5;
|
||||
*/
|
||||
__le32 offset_xyi;
|
||||
|
||||
/* Word 5(32-bit) in DDR memory */
|
||||
/*__u32 offset_xd:11;
|
||||
__u32 res7:5;
|
||||
__u32 offset_yd:11;
|
||||
__u32 res8:5; */
|
||||
__le32 offset_xyd;
|
||||
|
||||
|
||||
/* Word 6(32-bit) in DDR memory */
|
||||
__u8 ckmax_r;
|
||||
__u8 ckmax_g;
|
||||
__u8 ckmax_b;
|
||||
__u8 res9;
|
||||
|
||||
/* Word 7(32-bit) in DDR memory */
|
||||
__u8 ckmin_r;
|
||||
__u8 ckmin_g;
|
||||
__u8 ckmin_b;
|
||||
__u8 res10;
|
||||
/* __u32 res10:8; */
|
||||
|
||||
/* Word 8(32-bit) in DDR memory */
|
||||
__le32 next_ad;
|
||||
|
||||
/* Word 9(32-bit) in DDR memory, just for 64-bit aligned */
|
||||
__u32 paddr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* DIU register map */
|
||||
struct diu {
|
||||
__be32 desc[3];
|
||||
__be32 gamma;
|
||||
__be32 pallete;
|
||||
__be32 cursor;
|
||||
__be32 curs_pos;
|
||||
__be32 diu_mode;
|
||||
__be32 bgnd;
|
||||
__be32 bgnd_wb;
|
||||
__be32 disp_size;
|
||||
__be32 wb_size;
|
||||
__be32 wb_mem_addr;
|
||||
__be32 hsyn_para;
|
||||
__be32 vsyn_para;
|
||||
__be32 syn_pol;
|
||||
__be32 thresholds;
|
||||
__be32 int_status;
|
||||
__be32 int_mask;
|
||||
__be32 colorbar[8];
|
||||
__be32 filling;
|
||||
__be32 plut;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct diu_hw {
|
||||
struct diu *diu_reg;
|
||||
spinlock_t reg_lock;
|
||||
|
||||
__u32 mode; /* DIU operation mode */
|
||||
};
|
||||
|
||||
struct diu_addr {
|
||||
__u8 __iomem *vaddr; /* Virtual address */
|
||||
dma_addr_t paddr; /* Physical address */
|
||||
__u32 offset;
|
||||
};
|
||||
|
||||
struct diu_pool {
|
||||
struct diu_addr ad;
|
||||
struct diu_addr gamma;
|
||||
struct diu_addr pallete;
|
||||
struct diu_addr cursor;
|
||||
};
|
||||
|
||||
#define FSL_DIU_BASE_OFFSET 0x2C000 /* Offset of DIU */
|
||||
#define INT_LCDC 64 /* DIU interrupt number */
|
||||
|
||||
#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
|
||||
/* 1 for plane 0, 2 for plane 1&2 each */
|
||||
|
||||
/* Minimum X and Y resolutions */
|
||||
#define MIN_XRES 64
|
||||
#define MIN_YRES 64
|
||||
|
||||
/* HW cursor parameters */
|
||||
#define MAX_CURS 32
|
||||
|
||||
/* Modes of operation of DIU */
|
||||
#define MFB_MODE0 0 /* DIU off */
|
||||
#define MFB_MODE1 1 /* All three planes output to display */
|
||||
#define MFB_MODE2 2 /* Plane 1 to display, planes 2+3 written back*/
|
||||
#define MFB_MODE3 3 /* All three planes written back to memory */
|
||||
#define MFB_MODE4 4 /* Color bar generation */
|
||||
|
||||
/* INT_STATUS/INT_MASK field descriptions */
|
||||
#define INT_VSYNC 0x01 /* Vsync interrupt */
|
||||
#define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */
|
||||
#define INT_UNDRUN 0x04 /* Under run exception interrupt */
|
||||
#define INT_PARERR 0x08 /* Display parameters error interrupt */
|
||||
#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
|
||||
|
||||
/* Panels'operation modes */
|
||||
#define MFB_TYPE_OUTPUT 0 /* Panel output to display */
|
||||
#define MFB_TYPE_OFF 1 /* Panel off */
|
||||
#define MFB_TYPE_WB 2 /* Panel written back to memory */
|
||||
#define MFB_TYPE_TEST 3 /* Panel generate color bar */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __FSL_DIU_FB_H__ */
|
||||
|
|
@ -368,7 +368,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int __init igafb_init(void)
|
||||
static int __init igafb_init(void)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct pci_dev *pdev;
|
||||
|
|
@ -531,6 +531,7 @@ int __init igafb_init(void)
|
|||
iounmap(info->screen_base);
|
||||
kfree(par->mmap_map);
|
||||
kfree(info);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
|
|
@ -556,7 +557,7 @@ int __init igafb_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int __init igafb_setup(char *options)
|
||||
static int __init igafb_setup(char *options)
|
||||
{
|
||||
char *this_opt;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@
|
|||
*/
|
||||
#define DEBUG_VAR 1
|
||||
|
||||
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || \
|
||||
(defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) && \
|
||||
defined(CONFIG_FB_IMX_MODULE))
|
||||
#define PWMR_BACKLIGHT_AVAILABLE
|
||||
#endif
|
||||
|
||||
#define DRIVER_NAME "imx-fb"
|
||||
|
||||
#define LCDC_SSA 0x00
|
||||
|
|
@ -175,7 +181,9 @@ struct imxfb_info {
|
|||
|
||||
struct imx_fb_videomode *mode;
|
||||
int num_modes;
|
||||
#ifdef PWMR_BACKLIGHT_AVAILABLE
|
||||
struct backlight_device *bl;
|
||||
#endif
|
||||
|
||||
void (*lcd_power)(int);
|
||||
void (*backlight_power)(int);
|
||||
|
|
@ -450,8 +458,7 @@ static int imxfb_set_par(struct fb_info *info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef PWMR_BACKLIGHT_AVAILABLE
|
||||
static int imxfb_bl_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct imxfb_info *fbi = bl_get_data(bl);
|
||||
|
|
@ -516,6 +523,7 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi)
|
|||
if (fbi->bl)
|
||||
backlight_device_unregister(fbi->bl);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void imxfb_enable_controller(struct imxfb_info *fbi)
|
||||
{
|
||||
|
|
@ -647,6 +655,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
|
|||
fbi->regs + LCDC_SIZE);
|
||||
|
||||
writel(fbi->pcr, fbi->regs + LCDC_PCR);
|
||||
#ifndef PWMR_BACKLIGHT_AVAILABLE
|
||||
writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
|
||||
#endif
|
||||
writel(fbi->lscr1, fbi->regs + LCDC_LSCR1);
|
||||
writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
|
||||
|
||||
|
|
@ -847,7 +858,9 @@ static int __init imxfb_probe(struct platform_device *pdev)
|
|||
|
||||
imxfb_enable_controller(fbi);
|
||||
fbi->pdev = pdev;
|
||||
#ifdef PWMR_BACKLIGHT_AVAILABLE
|
||||
imxfb_init_backlight(fbi);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -885,7 +898,9 @@ static int __devexit imxfb_remove(struct platform_device *pdev)
|
|||
|
||||
imxfb_disable_controller(fbi);
|
||||
|
||||
#ifdef PWMR_BACKLIGHT_AVAILABLE
|
||||
imxfb_exit_backlight(fbi);
|
||||
#endif
|
||||
unregister_framebuffer(info);
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
|
|
|
|||
847
drivers/video/jz4740_fb.c
Normal file
847
drivers/video/jz4740_fb.c
Normal file
|
|
@ -0,0 +1,847 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
|
||||
* JZ4740 SoC LCD framebuffer driver
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <asm/mach-jz4740/jz4740_fb.h>
|
||||
#include <asm/mach-jz4740/gpio.h>
|
||||
|
||||
#define JZ_REG_LCD_CFG 0x00
|
||||
#define JZ_REG_LCD_VSYNC 0x04
|
||||
#define JZ_REG_LCD_HSYNC 0x08
|
||||
#define JZ_REG_LCD_VAT 0x0C
|
||||
#define JZ_REG_LCD_DAH 0x10
|
||||
#define JZ_REG_LCD_DAV 0x14
|
||||
#define JZ_REG_LCD_PS 0x18
|
||||
#define JZ_REG_LCD_CLS 0x1C
|
||||
#define JZ_REG_LCD_SPL 0x20
|
||||
#define JZ_REG_LCD_REV 0x24
|
||||
#define JZ_REG_LCD_CTRL 0x30
|
||||
#define JZ_REG_LCD_STATE 0x34
|
||||
#define JZ_REG_LCD_IID 0x38
|
||||
#define JZ_REG_LCD_DA0 0x40
|
||||
#define JZ_REG_LCD_SA0 0x44
|
||||
#define JZ_REG_LCD_FID0 0x48
|
||||
#define JZ_REG_LCD_CMD0 0x4C
|
||||
#define JZ_REG_LCD_DA1 0x50
|
||||
#define JZ_REG_LCD_SA1 0x54
|
||||
#define JZ_REG_LCD_FID1 0x58
|
||||
#define JZ_REG_LCD_CMD1 0x5C
|
||||
|
||||
#define JZ_LCD_CFG_SLCD BIT(31)
|
||||
#define JZ_LCD_CFG_PS_DISABLE BIT(23)
|
||||
#define JZ_LCD_CFG_CLS_DISABLE BIT(22)
|
||||
#define JZ_LCD_CFG_SPL_DISABLE BIT(21)
|
||||
#define JZ_LCD_CFG_REV_DISABLE BIT(20)
|
||||
#define JZ_LCD_CFG_HSYNCM BIT(19)
|
||||
#define JZ_LCD_CFG_PCLKM BIT(18)
|
||||
#define JZ_LCD_CFG_INV BIT(17)
|
||||
#define JZ_LCD_CFG_SYNC_DIR BIT(16)
|
||||
#define JZ_LCD_CFG_PS_POLARITY BIT(15)
|
||||
#define JZ_LCD_CFG_CLS_POLARITY BIT(14)
|
||||
#define JZ_LCD_CFG_SPL_POLARITY BIT(13)
|
||||
#define JZ_LCD_CFG_REV_POLARITY BIT(12)
|
||||
#define JZ_LCD_CFG_HSYNC_ACTIVE_LOW BIT(11)
|
||||
#define JZ_LCD_CFG_PCLK_FALLING_EDGE BIT(10)
|
||||
#define JZ_LCD_CFG_DE_ACTIVE_LOW BIT(9)
|
||||
#define JZ_LCD_CFG_VSYNC_ACTIVE_LOW BIT(8)
|
||||
#define JZ_LCD_CFG_18_BIT BIT(7)
|
||||
#define JZ_LCD_CFG_PDW (BIT(5) | BIT(4))
|
||||
#define JZ_LCD_CFG_MODE_MASK 0xf
|
||||
|
||||
#define JZ_LCD_CTRL_BURST_4 (0x0 << 28)
|
||||
#define JZ_LCD_CTRL_BURST_8 (0x1 << 28)
|
||||
#define JZ_LCD_CTRL_BURST_16 (0x2 << 28)
|
||||
#define JZ_LCD_CTRL_RGB555 BIT(27)
|
||||
#define JZ_LCD_CTRL_OFUP BIT(26)
|
||||
#define JZ_LCD_CTRL_FRC_GRAYSCALE_16 (0x0 << 24)
|
||||
#define JZ_LCD_CTRL_FRC_GRAYSCALE_4 (0x1 << 24)
|
||||
#define JZ_LCD_CTRL_FRC_GRAYSCALE_2 (0x2 << 24)
|
||||
#define JZ_LCD_CTRL_PDD_MASK (0xff << 16)
|
||||
#define JZ_LCD_CTRL_EOF_IRQ BIT(13)
|
||||
#define JZ_LCD_CTRL_SOF_IRQ BIT(12)
|
||||
#define JZ_LCD_CTRL_OFU_IRQ BIT(11)
|
||||
#define JZ_LCD_CTRL_IFU0_IRQ BIT(10)
|
||||
#define JZ_LCD_CTRL_IFU1_IRQ BIT(9)
|
||||
#define JZ_LCD_CTRL_DD_IRQ BIT(8)
|
||||
#define JZ_LCD_CTRL_QDD_IRQ BIT(7)
|
||||
#define JZ_LCD_CTRL_REVERSE_ENDIAN BIT(6)
|
||||
#define JZ_LCD_CTRL_LSB_FISRT BIT(5)
|
||||
#define JZ_LCD_CTRL_DISABLE BIT(4)
|
||||
#define JZ_LCD_CTRL_ENABLE BIT(3)
|
||||
#define JZ_LCD_CTRL_BPP_1 0x0
|
||||
#define JZ_LCD_CTRL_BPP_2 0x1
|
||||
#define JZ_LCD_CTRL_BPP_4 0x2
|
||||
#define JZ_LCD_CTRL_BPP_8 0x3
|
||||
#define JZ_LCD_CTRL_BPP_15_16 0x4
|
||||
#define JZ_LCD_CTRL_BPP_18_24 0x5
|
||||
|
||||
#define JZ_LCD_CMD_SOF_IRQ BIT(15)
|
||||
#define JZ_LCD_CMD_EOF_IRQ BIT(16)
|
||||
#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
|
||||
|
||||
#define JZ_LCD_SYNC_MASK 0x3ff
|
||||
|
||||
#define JZ_LCD_STATE_DISABLED BIT(0)
|
||||
|
||||
struct jzfb_framedesc {
|
||||
uint32_t next;
|
||||
uint32_t addr;
|
||||
uint32_t id;
|
||||
uint32_t cmd;
|
||||
} __packed;
|
||||
|
||||
struct jzfb {
|
||||
struct fb_info *fb;
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
struct resource *mem;
|
||||
struct jz4740_fb_platform_data *pdata;
|
||||
|
||||
size_t vidmem_size;
|
||||
void *vidmem;
|
||||
dma_addr_t vidmem_phys;
|
||||
struct jzfb_framedesc *framedesc;
|
||||
dma_addr_t framedesc_phys;
|
||||
|
||||
struct clk *ldclk;
|
||||
struct clk *lpclk;
|
||||
|
||||
unsigned is_enabled:1;
|
||||
struct mutex lock;
|
||||
|
||||
uint32_t pseudo_palette[16];
|
||||
};
|
||||
|
||||
static const struct fb_fix_screeninfo jzfb_fix __devinitdata = {
|
||||
.id = "JZ4740 FB",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_TRUECOLOR,
|
||||
.xpanstep = 0,
|
||||
.ypanstep = 0,
|
||||
.ywrapstep = 0,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
};
|
||||
|
||||
static const struct jz_gpio_bulk_request jz_lcd_ctrl_pins[] = {
|
||||
JZ_GPIO_BULK_PIN(LCD_PCLK),
|
||||
JZ_GPIO_BULK_PIN(LCD_HSYNC),
|
||||
JZ_GPIO_BULK_PIN(LCD_VSYNC),
|
||||
JZ_GPIO_BULK_PIN(LCD_DE),
|
||||
JZ_GPIO_BULK_PIN(LCD_PS),
|
||||
JZ_GPIO_BULK_PIN(LCD_REV),
|
||||
JZ_GPIO_BULK_PIN(LCD_CLS),
|
||||
JZ_GPIO_BULK_PIN(LCD_SPL),
|
||||
};
|
||||
|
||||
static const struct jz_gpio_bulk_request jz_lcd_data_pins[] = {
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA0),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA1),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA2),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA3),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA4),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA5),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA6),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA7),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA8),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA9),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA10),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA11),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA12),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA13),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA14),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA15),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA16),
|
||||
JZ_GPIO_BULK_PIN(LCD_DATA17),
|
||||
};
|
||||
|
||||
static unsigned int jzfb_num_ctrl_pins(struct jzfb *jzfb)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
switch (jzfb->pdata->lcd_type) {
|
||||
case JZ_LCD_TYPE_GENERIC_16_BIT:
|
||||
num = 4;
|
||||
break;
|
||||
case JZ_LCD_TYPE_GENERIC_18_BIT:
|
||||
num = 4;
|
||||
break;
|
||||
case JZ_LCD_TYPE_8BIT_SERIAL:
|
||||
num = 3;
|
||||
break;
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_1:
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_2:
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_3:
|
||||
num = 8;
|
||||
break;
|
||||
default:
|
||||
num = 0;
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static unsigned int jzfb_num_data_pins(struct jzfb *jzfb)
|
||||
{
|
||||
unsigned int num;
|
||||
|
||||
switch (jzfb->pdata->lcd_type) {
|
||||
case JZ_LCD_TYPE_GENERIC_16_BIT:
|
||||
num = 16;
|
||||
break;
|
||||
case JZ_LCD_TYPE_GENERIC_18_BIT:
|
||||
num = 18;
|
||||
break;
|
||||
case JZ_LCD_TYPE_8BIT_SERIAL:
|
||||
num = 8;
|
||||
break;
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_1:
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_2:
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_3:
|
||||
if (jzfb->pdata->bpp == 18)
|
||||
num = 18;
|
||||
else
|
||||
num = 16;
|
||||
break;
|
||||
default:
|
||||
num = 0;
|
||||
break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Based on CNVT_TOHW macro from skeletonfb.c */
|
||||
static inline uint32_t jzfb_convert_color_to_hw(unsigned val,
|
||||
struct fb_bitfield *bf)
|
||||
{
|
||||
return (((val << bf->length) + 0x7FFF - val) >> 16) << bf->offset;
|
||||
}
|
||||
|
||||
static int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
unsigned blue, unsigned transp, struct fb_info *fb)
|
||||
{
|
||||
uint32_t color;
|
||||
|
||||
if (regno >= 16)
|
||||
return -EINVAL;
|
||||
|
||||
color = jzfb_convert_color_to_hw(red, &fb->var.red);
|
||||
color |= jzfb_convert_color_to_hw(green, &fb->var.green);
|
||||
color |= jzfb_convert_color_to_hw(blue, &fb->var.blue);
|
||||
color |= jzfb_convert_color_to_hw(transp, &fb->var.transp);
|
||||
|
||||
((uint32_t *)(fb->pseudo_palette))[regno] = color;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jzfb_get_controller_bpp(struct jzfb *jzfb)
|
||||
{
|
||||
switch (jzfb->pdata->bpp) {
|
||||
case 18:
|
||||
case 24:
|
||||
return 32;
|
||||
case 15:
|
||||
return 16;
|
||||
default:
|
||||
return jzfb->pdata->bpp;
|
||||
}
|
||||
}
|
||||
|
||||
static struct fb_videomode *jzfb_get_mode(struct jzfb *jzfb,
|
||||
struct fb_var_screeninfo *var)
|
||||
{
|
||||
size_t i;
|
||||
struct fb_videomode *mode = jzfb->pdata->modes;
|
||||
|
||||
for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
|
||||
if (mode->xres == var->xres && mode->yres == var->yres)
|
||||
return mode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
|
||||
{
|
||||
struct jzfb *jzfb = fb->par;
|
||||
struct fb_videomode *mode;
|
||||
|
||||
if (var->bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
|
||||
var->bits_per_pixel != jzfb->pdata->bpp)
|
||||
return -EINVAL;
|
||||
|
||||
mode = jzfb_get_mode(jzfb, var);
|
||||
if (mode == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fb_videomode_to_var(var, mode);
|
||||
|
||||
switch (jzfb->pdata->bpp) {
|
||||
case 8:
|
||||
break;
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->red.length = 5;
|
||||
var->green.offset = 6;
|
||||
var->green.length = 5;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 5;
|
||||
break;
|
||||
case 16:
|
||||
var->red.offset = 11;
|
||||
var->red.length = 5;
|
||||
var->green.offset = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 5;
|
||||
break;
|
||||
case 18:
|
||||
var->red.offset = 16;
|
||||
var->red.length = 6;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 6;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 6;
|
||||
var->bits_per_pixel = 32;
|
||||
break;
|
||||
case 32:
|
||||
case 24:
|
||||
var->transp.offset = 24;
|
||||
var->transp.length = 8;
|
||||
var->red.offset = 16;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 8;
|
||||
var->bits_per_pixel = 32;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jzfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct jzfb *jzfb = info->par;
|
||||
struct jz4740_fb_platform_data *pdata = jzfb->pdata;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct fb_videomode *mode;
|
||||
uint16_t hds, vds;
|
||||
uint16_t hde, vde;
|
||||
uint16_t ht, vt;
|
||||
uint32_t ctrl;
|
||||
uint32_t cfg;
|
||||
unsigned long rate;
|
||||
|
||||
mode = jzfb_get_mode(jzfb, var);
|
||||
if (mode == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mode == info->mode)
|
||||
return 0;
|
||||
|
||||
info->mode = mode;
|
||||
|
||||
hds = mode->hsync_len + mode->left_margin;
|
||||
hde = hds + mode->xres;
|
||||
ht = hde + mode->right_margin;
|
||||
|
||||
vds = mode->vsync_len + mode->upper_margin;
|
||||
vde = vds + mode->yres;
|
||||
vt = vde + mode->lower_margin;
|
||||
|
||||
ctrl = JZ_LCD_CTRL_OFUP | JZ_LCD_CTRL_BURST_16;
|
||||
|
||||
switch (pdata->bpp) {
|
||||
case 1:
|
||||
ctrl |= JZ_LCD_CTRL_BPP_1;
|
||||
break;
|
||||
case 2:
|
||||
ctrl |= JZ_LCD_CTRL_BPP_2;
|
||||
break;
|
||||
case 4:
|
||||
ctrl |= JZ_LCD_CTRL_BPP_4;
|
||||
break;
|
||||
case 8:
|
||||
ctrl |= JZ_LCD_CTRL_BPP_8;
|
||||
break;
|
||||
case 15:
|
||||
ctrl |= JZ_LCD_CTRL_RGB555; /* Falltrough */
|
||||
case 16:
|
||||
ctrl |= JZ_LCD_CTRL_BPP_15_16;
|
||||
break;
|
||||
case 18:
|
||||
case 24:
|
||||
case 32:
|
||||
ctrl |= JZ_LCD_CTRL_BPP_18_24;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cfg = pdata->lcd_type & 0xf;
|
||||
|
||||
if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT))
|
||||
cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW;
|
||||
|
||||
if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
|
||||
cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
|
||||
|
||||
if (pdata->pixclk_falling_edge)
|
||||
cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
|
||||
|
||||
if (pdata->date_enable_active_low)
|
||||
cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
|
||||
|
||||
if (pdata->lcd_type == JZ_LCD_TYPE_GENERIC_18_BIT)
|
||||
cfg |= JZ_LCD_CFG_18_BIT;
|
||||
|
||||
if (mode->pixclock) {
|
||||
rate = PICOS2KHZ(mode->pixclock) * 1000;
|
||||
mode->refresh = rate / vt / ht;
|
||||
} else {
|
||||
if (pdata->lcd_type == JZ_LCD_TYPE_8BIT_SERIAL)
|
||||
rate = mode->refresh * (vt + 2 * mode->xres) * ht;
|
||||
else
|
||||
rate = mode->refresh * vt * ht;
|
||||
|
||||
mode->pixclock = KHZ2PICOS(rate / 1000);
|
||||
}
|
||||
|
||||
mutex_lock(&jzfb->lock);
|
||||
if (!jzfb->is_enabled)
|
||||
clk_enable(jzfb->ldclk);
|
||||
else
|
||||
ctrl |= JZ_LCD_CTRL_ENABLE;
|
||||
|
||||
switch (pdata->lcd_type) {
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_1:
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_2:
|
||||
case JZ_LCD_TYPE_SPECIAL_TFT_3:
|
||||
writel(pdata->special_tft_config.spl, jzfb->base + JZ_REG_LCD_SPL);
|
||||
writel(pdata->special_tft_config.cls, jzfb->base + JZ_REG_LCD_CLS);
|
||||
writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_PS);
|
||||
writel(pdata->special_tft_config.ps, jzfb->base + JZ_REG_LCD_REV);
|
||||
break;
|
||||
default:
|
||||
cfg |= JZ_LCD_CFG_PS_DISABLE;
|
||||
cfg |= JZ_LCD_CFG_CLS_DISABLE;
|
||||
cfg |= JZ_LCD_CFG_SPL_DISABLE;
|
||||
cfg |= JZ_LCD_CFG_REV_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
writel(mode->hsync_len, jzfb->base + JZ_REG_LCD_HSYNC);
|
||||
writel(mode->vsync_len, jzfb->base + JZ_REG_LCD_VSYNC);
|
||||
|
||||
writel((ht << 16) | vt, jzfb->base + JZ_REG_LCD_VAT);
|
||||
|
||||
writel((hds << 16) | hde, jzfb->base + JZ_REG_LCD_DAH);
|
||||
writel((vds << 16) | vde, jzfb->base + JZ_REG_LCD_DAV);
|
||||
|
||||
writel(cfg, jzfb->base + JZ_REG_LCD_CFG);
|
||||
|
||||
writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
|
||||
|
||||
if (!jzfb->is_enabled)
|
||||
clk_disable(jzfb->ldclk);
|
||||
|
||||
mutex_unlock(&jzfb->lock);
|
||||
|
||||
clk_set_rate(jzfb->lpclk, rate);
|
||||
clk_set_rate(jzfb->ldclk, rate * 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jzfb_enable(struct jzfb *jzfb)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
|
||||
clk_enable(jzfb->ldclk);
|
||||
|
||||
jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
|
||||
jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
|
||||
|
||||
writel(0, jzfb->base + JZ_REG_LCD_STATE);
|
||||
|
||||
writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
|
||||
|
||||
ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
|
||||
ctrl |= JZ_LCD_CTRL_ENABLE;
|
||||
ctrl &= ~JZ_LCD_CTRL_DISABLE;
|
||||
writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
|
||||
}
|
||||
|
||||
static void jzfb_disable(struct jzfb *jzfb)
|
||||
{
|
||||
uint32_t ctrl;
|
||||
|
||||
ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
|
||||
ctrl |= JZ_LCD_CTRL_DISABLE;
|
||||
writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
|
||||
do {
|
||||
ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
|
||||
} while (!(ctrl & JZ_LCD_STATE_DISABLED));
|
||||
|
||||
jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
|
||||
jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
|
||||
|
||||
clk_disable(jzfb->ldclk);
|
||||
}
|
||||
|
||||
static int jzfb_blank(int blank_mode, struct fb_info *info)
|
||||
{
|
||||
struct jzfb *jzfb = info->par;
|
||||
|
||||
switch (blank_mode) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
mutex_lock(&jzfb->lock);
|
||||
if (jzfb->is_enabled) {
|
||||
mutex_unlock(&jzfb->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jzfb_enable(jzfb);
|
||||
jzfb->is_enabled = 1;
|
||||
|
||||
mutex_unlock(&jzfb->lock);
|
||||
break;
|
||||
default:
|
||||
mutex_lock(&jzfb->lock);
|
||||
if (!jzfb->is_enabled) {
|
||||
mutex_unlock(&jzfb->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jzfb_disable(jzfb);
|
||||
jzfb->is_enabled = 0;
|
||||
|
||||
mutex_unlock(&jzfb->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jzfb_alloc_devmem(struct jzfb *jzfb)
|
||||
{
|
||||
int max_videosize = 0;
|
||||
struct fb_videomode *mode = jzfb->pdata->modes;
|
||||
void *page;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < jzfb->pdata->num_modes; ++mode, ++i) {
|
||||
if (max_videosize < mode->xres * mode->yres)
|
||||
max_videosize = mode->xres * mode->yres;
|
||||
}
|
||||
|
||||
max_videosize *= jzfb_get_controller_bpp(jzfb) >> 3;
|
||||
|
||||
jzfb->framedesc = dma_alloc_coherent(&jzfb->pdev->dev,
|
||||
sizeof(*jzfb->framedesc),
|
||||
&jzfb->framedesc_phys, GFP_KERNEL);
|
||||
|
||||
if (!jzfb->framedesc)
|
||||
return -ENOMEM;
|
||||
|
||||
jzfb->vidmem_size = PAGE_ALIGN(max_videosize);
|
||||
jzfb->vidmem = dma_alloc_coherent(&jzfb->pdev->dev,
|
||||
jzfb->vidmem_size,
|
||||
&jzfb->vidmem_phys, GFP_KERNEL);
|
||||
|
||||
if (!jzfb->vidmem)
|
||||
goto err_free_framedesc;
|
||||
|
||||
for (page = jzfb->vidmem;
|
||||
page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
|
||||
page += PAGE_SIZE) {
|
||||
SetPageReserved(virt_to_page(page));
|
||||
}
|
||||
|
||||
jzfb->framedesc->next = jzfb->framedesc_phys;
|
||||
jzfb->framedesc->addr = jzfb->vidmem_phys;
|
||||
jzfb->framedesc->id = 0xdeafbead;
|
||||
jzfb->framedesc->cmd = 0;
|
||||
jzfb->framedesc->cmd |= max_videosize / 4;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_framedesc:
|
||||
dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
|
||||
jzfb->framedesc, jzfb->framedesc_phys);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void jzfb_free_devmem(struct jzfb *jzfb)
|
||||
{
|
||||
dma_free_coherent(&jzfb->pdev->dev, jzfb->vidmem_size,
|
||||
jzfb->vidmem, jzfb->vidmem_phys);
|
||||
dma_free_coherent(&jzfb->pdev->dev, sizeof(*jzfb->framedesc),
|
||||
jzfb->framedesc, jzfb->framedesc_phys);
|
||||
}
|
||||
|
||||
static struct fb_ops jzfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = jzfb_check_var,
|
||||
.fb_set_par = jzfb_set_par,
|
||||
.fb_blank = jzfb_blank,
|
||||
.fb_fillrect = sys_fillrect,
|
||||
.fb_copyarea = sys_copyarea,
|
||||
.fb_imageblit = sys_imageblit,
|
||||
.fb_setcolreg = jzfb_setcolreg,
|
||||
};
|
||||
|
||||
static int __devinit jzfb_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct jzfb *jzfb;
|
||||
struct fb_info *fb;
|
||||
struct jz4740_fb_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct resource *mem;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "Missing platform data\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "Failed to get register memory resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
|
||||
if (!mem) {
|
||||
dev_err(&pdev->dev, "Failed to request register memory region\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
|
||||
if (!fb) {
|
||||
dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_release_mem_region;
|
||||
}
|
||||
|
||||
fb->fbops = &jzfb_ops;
|
||||
fb->flags = FBINFO_DEFAULT;
|
||||
|
||||
jzfb = fb->par;
|
||||
jzfb->pdev = pdev;
|
||||
jzfb->pdata = pdata;
|
||||
jzfb->mem = mem;
|
||||
|
||||
jzfb->ldclk = clk_get(&pdev->dev, "lcd");
|
||||
if (IS_ERR(jzfb->ldclk)) {
|
||||
ret = PTR_ERR(jzfb->ldclk);
|
||||
dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
|
||||
goto err_framebuffer_release;
|
||||
}
|
||||
|
||||
jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
|
||||
if (IS_ERR(jzfb->lpclk)) {
|
||||
ret = PTR_ERR(jzfb->lpclk);
|
||||
dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
|
||||
goto err_put_ldclk;
|
||||
}
|
||||
|
||||
jzfb->base = ioremap(mem->start, resource_size(mem));
|
||||
if (!jzfb->base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
|
||||
ret = -EBUSY;
|
||||
goto err_put_lpclk;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, jzfb);
|
||||
|
||||
mutex_init(&jzfb->lock);
|
||||
|
||||
fb_videomode_to_modelist(pdata->modes, pdata->num_modes,
|
||||
&fb->modelist);
|
||||
fb_videomode_to_var(&fb->var, pdata->modes);
|
||||
fb->var.bits_per_pixel = pdata->bpp;
|
||||
jzfb_check_var(&fb->var, fb);
|
||||
|
||||
ret = jzfb_alloc_devmem(jzfb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to allocate video memory\n");
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
fb->fix = jzfb_fix;
|
||||
fb->fix.line_length = fb->var.bits_per_pixel * fb->var.xres / 8;
|
||||
fb->fix.mmio_start = mem->start;
|
||||
fb->fix.mmio_len = resource_size(mem);
|
||||
fb->fix.smem_start = jzfb->vidmem_phys;
|
||||
fb->fix.smem_len = fb->fix.line_length * fb->var.yres;
|
||||
fb->screen_base = jzfb->vidmem;
|
||||
fb->pseudo_palette = jzfb->pseudo_palette;
|
||||
|
||||
fb_alloc_cmap(&fb->cmap, 256, 0);
|
||||
|
||||
clk_enable(jzfb->ldclk);
|
||||
jzfb->is_enabled = 1;
|
||||
|
||||
writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
|
||||
|
||||
fb->mode = NULL;
|
||||
jzfb_set_par(fb);
|
||||
|
||||
jz_gpio_bulk_request(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
|
||||
jz_gpio_bulk_request(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
|
||||
|
||||
ret = register_framebuffer(fb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
|
||||
goto err_free_devmem;
|
||||
}
|
||||
|
||||
jzfb->fb = fb;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_devmem:
|
||||
jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
|
||||
jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
|
||||
|
||||
fb_dealloc_cmap(&fb->cmap);
|
||||
jzfb_free_devmem(jzfb);
|
||||
err_iounmap:
|
||||
iounmap(jzfb->base);
|
||||
err_put_lpclk:
|
||||
clk_put(jzfb->lpclk);
|
||||
err_put_ldclk:
|
||||
clk_put(jzfb->ldclk);
|
||||
err_framebuffer_release:
|
||||
framebuffer_release(fb);
|
||||
err_release_mem_region:
|
||||
release_mem_region(mem->start, resource_size(mem));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit jzfb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct jzfb *jzfb = platform_get_drvdata(pdev);
|
||||
|
||||
jzfb_blank(FB_BLANK_POWERDOWN, jzfb->fb);
|
||||
|
||||
jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
|
||||
jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
|
||||
|
||||
iounmap(jzfb->base);
|
||||
release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
|
||||
|
||||
fb_dealloc_cmap(&jzfb->fb->cmap);
|
||||
jzfb_free_devmem(jzfb);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
clk_put(jzfb->lpclk);
|
||||
clk_put(jzfb->ldclk);
|
||||
|
||||
framebuffer_release(jzfb->fb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int jzfb_suspend(struct device *dev)
|
||||
{
|
||||
struct jzfb *jzfb = dev_get_drvdata(dev);
|
||||
|
||||
acquire_console_sem();
|
||||
fb_set_suspend(jzfb->fb, 1);
|
||||
release_console_sem();
|
||||
|
||||
mutex_lock(&jzfb->lock);
|
||||
if (jzfb->is_enabled)
|
||||
jzfb_disable(jzfb);
|
||||
mutex_unlock(&jzfb->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jzfb_resume(struct device *dev)
|
||||
{
|
||||
struct jzfb *jzfb = dev_get_drvdata(dev);
|
||||
clk_enable(jzfb->ldclk);
|
||||
|
||||
mutex_lock(&jzfb->lock);
|
||||
if (jzfb->is_enabled)
|
||||
jzfb_enable(jzfb);
|
||||
mutex_unlock(&jzfb->lock);
|
||||
|
||||
acquire_console_sem();
|
||||
fb_set_suspend(jzfb->fb, 0);
|
||||
release_console_sem();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops jzfb_pm_ops = {
|
||||
.suspend = jzfb_suspend,
|
||||
.resume = jzfb_resume,
|
||||
.poweroff = jzfb_suspend,
|
||||
.restore = jzfb_resume,
|
||||
};
|
||||
|
||||
#define JZFB_PM_OPS (&jzfb_pm_ops)
|
||||
|
||||
#else
|
||||
#define JZFB_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver jzfb_driver = {
|
||||
.probe = jzfb_probe,
|
||||
.remove = __devexit_p(jzfb_remove),
|
||||
.driver = {
|
||||
.name = "jz4740-fb",
|
||||
.pm = JZFB_PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init jzfb_init(void)
|
||||
{
|
||||
return platform_driver_register(&jzfb_driver);
|
||||
}
|
||||
module_init(jzfb_init);
|
||||
|
||||
static void __exit jzfb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&jzfb_driver);
|
||||
}
|
||||
module_exit(jzfb_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");
|
||||
MODULE_DESCRIPTION("JZ4740 SoC LCD framebuffer driver");
|
||||
MODULE_ALIAS("platform:jz4740-fb");
|
||||
|
|
@ -529,7 +529,7 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
|
|||
var->transp.length = 0;
|
||||
}
|
||||
|
||||
static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
|
||||
struct leo_par *par)
|
||||
{
|
||||
if (par->lc_ss0_usr)
|
||||
|
|
@ -547,7 +547,7 @@ static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
|
|||
of_iounmap(&op->resource[0], info->screen_base, 0x800000);
|
||||
}
|
||||
|
||||
static int __devinit leo_probe(struct of_device *op,
|
||||
static int __devinit leo_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
|
|
@ -637,7 +637,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit leo_remove(struct of_device *op)
|
||||
static int __devexit leo_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct leo_par *par = info->par;
|
||||
|
|
@ -677,12 +677,12 @@ static int __init leo_init(void)
|
|||
if (fb_get_options("leofb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&leo_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&leo_driver);
|
||||
}
|
||||
|
||||
static void __exit leo_exit(void)
|
||||
{
|
||||
of_unregister_driver(&leo_driver);
|
||||
of_unregister_platform_driver(&leo_driver);
|
||||
}
|
||||
|
||||
module_init(leo_init);
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
|
|||
};
|
||||
|
||||
i2c_new_probed_device(&m2info->maven.adapter,
|
||||
&maven_info, addr_list);
|
||||
&maven_info, addr_list, NULL);
|
||||
}
|
||||
}
|
||||
return m2info;
|
||||
|
|
|
|||
|
|
@ -151,13 +151,13 @@ static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
|
|||
static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
|
||||
#if defined(__alpha__) || defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* memcpy_toio works for us if:
|
||||
* iowrite32_rep works for us if:
|
||||
* (1) Copies data as 32bit quantities, not byte after byte,
|
||||
* (2) Performs LE ordered stores, and
|
||||
* (3) It copes with unaligned source (destination is guaranteed to be page
|
||||
* aligned and length is guaranteed to be multiple of 4).
|
||||
*/
|
||||
memcpy_toio(va.vaddr, src, len);
|
||||
iowrite32_rep(va.vaddr, src, len >> 2);
|
||||
#else
|
||||
u_int32_t __iomem* addr = va.vaddr;
|
||||
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
|
||||
static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev,
|
||||
const struct of_device_id *id)
|
||||
{
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
|
|
@ -669,7 +669,7 @@ fbrel:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev)
|
||||
static int __devexit of_platform_mb862xx_remove(struct platform_device *ofdev)
|
||||
{
|
||||
struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
|
||||
struct mb862xxfb_par *par = fbi->par;
|
||||
|
|
|
|||
|
|
@ -187,10 +187,8 @@ static void mddi_wait_interrupt(struct mddi_info *mddi, uint32_t intmask);
|
|||
|
||||
static void mddi_handle_rev_data_avail(struct mddi_info *mddi)
|
||||
{
|
||||
union mddi_rev *rev = mddi->rev_data;
|
||||
uint32_t rev_data_count;
|
||||
uint32_t rev_crc_err_count;
|
||||
int i;
|
||||
struct reg_read_info *ri;
|
||||
size_t prev_offset;
|
||||
uint16_t length;
|
||||
|
|
@ -670,7 +668,7 @@ static int __init mddi_rev_data_setup(struct mddi_info *mddi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init mddi_probe(struct platform_device *pdev)
|
||||
static int __devinit mddi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_mddi_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct mddi_info *mddi = &mddi_info[pdev->id];
|
||||
|
|
|
|||
|
|
@ -258,7 +258,6 @@ int get_img(struct mdp_img *img, struct fb_info *info,
|
|||
{
|
||||
int put_needed, ret = 0;
|
||||
struct file *file;
|
||||
unsigned long vstart;
|
||||
|
||||
file = fget_light(img->memory_id, &put_needed);
|
||||
if (file == NULL)
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/pci-bridge.h>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/gpio.h>
|
||||
#include <plat/mux.h>
|
||||
|
||||
#include "omapfb.h"
|
||||
|
||||
|
|
@ -34,8 +33,6 @@
|
|||
static int apollon_panel_init(struct lcd_panel *panel,
|
||||
struct omapfb_device *fbdev)
|
||||
{
|
||||
/* configure LCD PWR_EN */
|
||||
omap_cfg_reg(M21_242X_GPIO11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
|
|||
r = omapdss_sdi_display_enable(dssdev);
|
||||
if (r) {
|
||||
pr_err("%s sdi enable failed\n", __func__);
|
||||
return r;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
/*FIXME tweak me */
|
||||
|
|
@ -633,6 +633,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
|
|||
return acx565akm_bl_update_status(md->bl_dev);
|
||||
fail:
|
||||
omapdss_sdi_display_disable(dssdev);
|
||||
fail_unlock:
|
||||
mutex_unlock(&md->mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,13 @@
|
|||
#include <linux/fb.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
#include <plat/nokia-dsi-panel.h>
|
||||
|
||||
/* DSI Virtual channel. Hardcoded for now. */
|
||||
#define TCH 0
|
||||
|
|
@ -62,11 +63,136 @@
|
|||
#define DCS_GET_ID2 0xdb
|
||||
#define DCS_GET_ID3 0xdc
|
||||
|
||||
/* #define TAAL_USE_ESD_CHECK */
|
||||
#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
|
||||
|
||||
static irqreturn_t taal_te_isr(int irq, void *data);
|
||||
static void taal_te_timeout_work_callback(struct work_struct *work);
|
||||
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
|
||||
|
||||
struct panel_regulator {
|
||||
struct regulator *regulator;
|
||||
const char *name;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
};
|
||||
|
||||
static void free_regulators(struct panel_regulator *regulators, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
/* disable/put in reverse order */
|
||||
regulator_disable(regulators[n - i - 1].regulator);
|
||||
regulator_put(regulators[n - i - 1].regulator);
|
||||
}
|
||||
}
|
||||
|
||||
static int init_regulators(struct omap_dss_device *dssdev,
|
||||
struct panel_regulator *regulators, int n)
|
||||
{
|
||||
int r, i, v;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
struct regulator *reg;
|
||||
|
||||
reg = regulator_get(&dssdev->dev, regulators[i].name);
|
||||
if (IS_ERR(reg)) {
|
||||
dev_err(&dssdev->dev, "failed to get regulator %s\n",
|
||||
regulators[i].name);
|
||||
r = PTR_ERR(reg);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* FIXME: better handling of fixed vs. variable regulators */
|
||||
v = regulator_get_voltage(reg);
|
||||
if (v < regulators[i].min_uV || v > regulators[i].max_uV) {
|
||||
r = regulator_set_voltage(reg, regulators[i].min_uV,
|
||||
regulators[i].max_uV);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev,
|
||||
"failed to set regulator %s voltage\n",
|
||||
regulators[i].name);
|
||||
regulator_put(reg);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
r = regulator_enable(reg);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable regulator %s\n",
|
||||
regulators[i].name);
|
||||
regulator_put(reg);
|
||||
goto err;
|
||||
}
|
||||
|
||||
regulators[i].regulator = reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free_regulators(regulators, i);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct panel_config - panel configuration
|
||||
* @name: panel name
|
||||
* @type: panel type
|
||||
* @timings: panel resolution
|
||||
* @sleep: various panel specific delays, passed to msleep() if non-zero
|
||||
* @reset_sequence: reset sequence timings, passed to udelay() if non-zero
|
||||
* @regulators: array of panel regulators
|
||||
* @num_regulators: number of regulators in the array
|
||||
*/
|
||||
struct panel_config {
|
||||
const char *name;
|
||||
int type;
|
||||
|
||||
struct omap_video_timings timings;
|
||||
|
||||
struct {
|
||||
unsigned int sleep_in;
|
||||
unsigned int sleep_out;
|
||||
unsigned int hw_reset;
|
||||
unsigned int enable_te;
|
||||
} sleep;
|
||||
|
||||
struct {
|
||||
unsigned int high;
|
||||
unsigned int low;
|
||||
} reset_sequence;
|
||||
|
||||
struct panel_regulator *regulators;
|
||||
int num_regulators;
|
||||
};
|
||||
|
||||
enum {
|
||||
PANEL_TAAL,
|
||||
};
|
||||
|
||||
static struct panel_config panel_configs[] = {
|
||||
{
|
||||
.name = "taal",
|
||||
.type = PANEL_TAAL,
|
||||
.timings = {
|
||||
.x_res = 864,
|
||||
.y_res = 480,
|
||||
},
|
||||
.sleep = {
|
||||
.sleep_in = 5,
|
||||
.sleep_out = 5,
|
||||
.hw_reset = 5,
|
||||
.enable_te = 100, /* possible panel bug */
|
||||
},
|
||||
.reset_sequence = {
|
||||
.high = 10,
|
||||
.low = 10,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct taal_data {
|
||||
struct mutex lock;
|
||||
|
||||
|
|
@ -84,8 +210,15 @@ struct taal_data {
|
|||
bool mirror;
|
||||
|
||||
bool te_enabled;
|
||||
bool use_ext_te;
|
||||
struct completion te_completion;
|
||||
|
||||
atomic_t do_update;
|
||||
struct {
|
||||
u16 x;
|
||||
u16 y;
|
||||
u16 w;
|
||||
u16 h;
|
||||
} update_region;
|
||||
struct delayed_work te_timeout_work;
|
||||
|
||||
bool use_dsi_bl;
|
||||
|
||||
|
|
@ -96,8 +229,16 @@ struct taal_data {
|
|||
|
||||
struct workqueue_struct *esd_wq;
|
||||
struct delayed_work esd_work;
|
||||
|
||||
struct panel_config *panel_config;
|
||||
};
|
||||
|
||||
static inline struct nokia_dsi_panel_data
|
||||
*get_panel_data(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
return (struct nokia_dsi_panel_data *) dssdev->data;
|
||||
}
|
||||
|
||||
static void taal_esd_work(struct work_struct *work);
|
||||
|
||||
static void hw_guard_start(struct taal_data *td, int guard_msec)
|
||||
|
|
@ -159,7 +300,8 @@ static int taal_sleep_in(struct taal_data *td)
|
|||
|
||||
hw_guard_start(td, 120);
|
||||
|
||||
msleep(5);
|
||||
if (td->panel_config->sleep.sleep_in)
|
||||
msleep(td->panel_config->sleep.sleep_in);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -176,7 +318,8 @@ static int taal_sleep_out(struct taal_data *td)
|
|||
|
||||
hw_guard_start(td, 120);
|
||||
|
||||
msleep(5);
|
||||
if (td->panel_config->sleep.sleep_out)
|
||||
msleep(td->panel_config->sleep.sleep_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -279,6 +422,7 @@ 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;
|
||||
|
||||
|
|
@ -290,24 +434,26 @@ static int taal_bl_update_status(struct backlight_device *dev)
|
|||
|
||||
dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->use_dsi_bl) {
|
||||
if (td->enabled) {
|
||||
dsi_bus_lock();
|
||||
r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
|
||||
dsi_bus_unlock();
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
} else {
|
||||
if (!dssdev->set_backlight)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->set_backlight(dssdev, level);
|
||||
if (r)
|
||||
return r;
|
||||
if (!panel_data->set_backlight)
|
||||
r = -EINVAL;
|
||||
else
|
||||
r = panel_data->set_backlight(dssdev, level);
|
||||
}
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_bl_get_intensity(struct backlight_device *dev)
|
||||
|
|
@ -344,16 +490,6 @@ static void taal_get_resolution(struct omap_dss_device *dssdev,
|
|||
}
|
||||
}
|
||||
|
||||
static irqreturn_t taal_te_isr(int irq, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = data;
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
complete_all(&td->te_completion);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static ssize_t taal_num_errors_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -362,6 +498,8 @@ static ssize_t taal_num_errors_show(struct device *dev,
|
|||
u8 errors;
|
||||
int r;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->enabled) {
|
||||
dsi_bus_lock();
|
||||
r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
|
||||
|
|
@ -370,6 +508,8 @@ static ssize_t taal_num_errors_show(struct device *dev,
|
|||
r = -ENODEV;
|
||||
}
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
|
@ -384,6 +524,8 @@ static ssize_t taal_hw_revision_show(struct device *dev,
|
|||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->enabled) {
|
||||
dsi_bus_lock();
|
||||
r = taal_get_id(&id1, &id2, &id3);
|
||||
|
|
@ -392,6 +534,8 @@ static ssize_t taal_hw_revision_show(struct device *dev,
|
|||
r = -ENODEV;
|
||||
}
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
|
@ -441,6 +585,8 @@ static ssize_t store_cabc_mode(struct device *dev,
|
|||
if (i == ARRAY_SIZE(cabc_modes))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->enabled) {
|
||||
dsi_bus_lock();
|
||||
if (!td->cabc_broken)
|
||||
|
|
@ -450,6 +596,8 @@ static ssize_t store_cabc_mode(struct device *dev,
|
|||
|
||||
td->cabc_mode = i;
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
@ -488,47 +636,93 @@ static struct attribute_group taal_attr_group = {
|
|||
.attrs = taal_attrs,
|
||||
};
|
||||
|
||||
static void taal_hw_reset(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
|
||||
if (panel_data->reset_gpio == -1)
|
||||
return;
|
||||
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
if (td->panel_config->reset_sequence.high)
|
||||
udelay(td->panel_config->reset_sequence.high);
|
||||
/* reset the panel */
|
||||
gpio_set_value(panel_data->reset_gpio, 0);
|
||||
/* assert reset */
|
||||
if (td->panel_config->reset_sequence.low)
|
||||
udelay(td->panel_config->reset_sequence.low);
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
/* wait after releasing reset */
|
||||
if (td->panel_config->sleep.hw_reset)
|
||||
msleep(td->panel_config->sleep.hw_reset);
|
||||
}
|
||||
|
||||
static int taal_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct taal_data *td;
|
||||
struct backlight_device *bldev;
|
||||
int r;
|
||||
|
||||
const struct omap_video_timings taal_panel_timings = {
|
||||
.x_res = 864,
|
||||
.y_res = 480,
|
||||
};
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
struct panel_config *panel_config = NULL;
|
||||
int r, i;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
||||
if (!panel_data || !panel_data->name) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
|
||||
if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
|
||||
panel_config = &panel_configs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!panel_config) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT;
|
||||
dssdev->panel.timings = taal_panel_timings;
|
||||
dssdev->panel.timings = panel_config->timings;
|
||||
dssdev->ctrl.pixel_size = 24;
|
||||
|
||||
td = kzalloc(sizeof(*td), GFP_KERNEL);
|
||||
if (!td) {
|
||||
r = -ENOMEM;
|
||||
goto err0;
|
||||
goto err;
|
||||
}
|
||||
td->dssdev = dssdev;
|
||||
td->panel_config = panel_config;
|
||||
|
||||
mutex_init(&td->lock);
|
||||
|
||||
atomic_set(&td->do_update, 0);
|
||||
|
||||
r = init_regulators(dssdev, panel_config->regulators,
|
||||
panel_config->num_regulators);
|
||||
if (r)
|
||||
goto err_reg;
|
||||
|
||||
td->esd_wq = create_singlethread_workqueue("taal_esd");
|
||||
if (td->esd_wq == NULL) {
|
||||
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
|
||||
r = -ENOMEM;
|
||||
goto err1;
|
||||
goto err_wq;
|
||||
}
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, td);
|
||||
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
/* if no platform set_backlight() defined, presume DSI backlight
|
||||
* control */
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
if (!dssdev->set_backlight)
|
||||
if (!panel_data->set_backlight)
|
||||
td->use_dsi_bl = true;
|
||||
|
||||
if (td->use_dsi_bl)
|
||||
|
|
@ -539,7 +733,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
&taal_bl_ops, &props);
|
||||
if (IS_ERR(bldev)) {
|
||||
r = PTR_ERR(bldev);
|
||||
goto err2;
|
||||
goto err_bl;
|
||||
}
|
||||
|
||||
td->bldev = bldev;
|
||||
|
|
@ -553,13 +747,13 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
|
||||
taal_bl_update_status(bldev);
|
||||
|
||||
if (dssdev->phy.dsi.ext_te) {
|
||||
int gpio = dssdev->phy.dsi.ext_te_gpio;
|
||||
if (panel_data->use_ext_te) {
|
||||
int gpio = panel_data->ext_te_gpio;
|
||||
|
||||
r = gpio_request(gpio, "taal irq");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "GPIO request failed\n");
|
||||
goto err3;
|
||||
goto err_gpio;
|
||||
}
|
||||
|
||||
gpio_direction_input(gpio);
|
||||
|
|
@ -571,49 +765,52 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
if (r) {
|
||||
dev_err(&dssdev->dev, "IRQ request failed\n");
|
||||
gpio_free(gpio);
|
||||
goto err3;
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
init_completion(&td->te_completion);
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
|
||||
taal_te_timeout_work_callback);
|
||||
|
||||
td->use_ext_te = true;
|
||||
dev_dbg(&dssdev->dev, "Using GPIO TE\n");
|
||||
}
|
||||
|
||||
r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to create sysfs files\n");
|
||||
goto err4;
|
||||
goto err_sysfs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err4:
|
||||
if (td->use_ext_te) {
|
||||
int gpio = dssdev->phy.dsi.ext_te_gpio;
|
||||
free_irq(gpio_to_irq(gpio), dssdev);
|
||||
gpio_free(gpio);
|
||||
}
|
||||
err3:
|
||||
err_sysfs:
|
||||
if (panel_data->use_ext_te)
|
||||
free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
|
||||
err_irq:
|
||||
if (panel_data->use_ext_te)
|
||||
gpio_free(panel_data->ext_te_gpio);
|
||||
err_gpio:
|
||||
backlight_device_unregister(bldev);
|
||||
err2:
|
||||
cancel_delayed_work_sync(&td->esd_work);
|
||||
err_bl:
|
||||
destroy_workqueue(td->esd_wq);
|
||||
err1:
|
||||
err_wq:
|
||||
free_regulators(panel_config->regulators, panel_config->num_regulators);
|
||||
err_reg:
|
||||
kfree(td);
|
||||
err0:
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void taal_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
struct backlight_device *bldev;
|
||||
|
||||
dev_dbg(&dssdev->dev, "remove\n");
|
||||
|
||||
sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
|
||||
|
||||
if (td->use_ext_te) {
|
||||
int gpio = dssdev->phy.dsi.ext_te_gpio;
|
||||
if (panel_data->use_ext_te) {
|
||||
int gpio = panel_data->ext_te_gpio;
|
||||
free_irq(gpio_to_irq(gpio), dssdev);
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
|
@ -623,9 +820,15 @@ static void taal_remove(struct omap_dss_device *dssdev)
|
|||
taal_bl_update_status(bldev);
|
||||
backlight_device_unregister(bldev);
|
||||
|
||||
cancel_delayed_work_sync(&td->esd_work);
|
||||
cancel_delayed_work(&td->esd_work);
|
||||
destroy_workqueue(td->esd_wq);
|
||||
|
||||
/* reset, to be sure that the panel is in a valid state */
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
free_regulators(td->panel_config->regulators,
|
||||
td->panel_config->num_regulators);
|
||||
|
||||
kfree(td);
|
||||
}
|
||||
|
||||
|
|
@ -635,23 +838,14 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* it seems we have to wait a bit until taal is ready */
|
||||
msleep(5);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = omapdss_dsi_display_enable(dssdev);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable DSI\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
omapdss_dsi_vc_enable_hs(TCH, false);
|
||||
|
||||
r = taal_sleep_out(td);
|
||||
|
|
@ -662,34 +856,47 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
/* on early revisions CABC is broken */
|
||||
if (id2 == 0x00 || id2 == 0xff || id2 == 0x81)
|
||||
/* on early Taal revisions CABC is broken */
|
||||
if (td->panel_config->type == PANEL_TAAL &&
|
||||
(id2 == 0x00 || id2 == 0xff || id2 == 0x81))
|
||||
td->cabc_broken = true;
|
||||
|
||||
taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
|
||||
taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */
|
||||
r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
|
||||
r = taal_dcs_write_1(DCS_CTRL_DISPLAY,
|
||||
(1<<2) | (1<<5)); /* BL | BCTRL */
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
taal_set_addr_mode(td->rotate, td->mirror);
|
||||
if (!td->cabc_broken)
|
||||
taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
|
||||
r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
taal_dcs_write_0(DCS_DISPLAY_ON);
|
||||
r = taal_set_addr_mode(td->rotate, td->mirror);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (!td->cabc_broken) {
|
||||
r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = taal_dcs_write_0(DCS_DISPLAY_ON);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = _taal_enable_te(dssdev, td->te_enabled);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
#ifdef TAAL_USE_ESD_CHECK
|
||||
queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
|
||||
#endif
|
||||
|
||||
td->enabled = 1;
|
||||
|
||||
if (!td->intro_printed) {
|
||||
dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n",
|
||||
id1, id2, id3);
|
||||
dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n",
|
||||
td->panel_config->name, id1, id2, id3);
|
||||
if (td->cabc_broken)
|
||||
dev_info(&dssdev->dev,
|
||||
"old Taal version, CABC disabled\n");
|
||||
|
|
@ -698,46 +905,44 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
|
||||
omapdss_dsi_vc_enable_hs(TCH, true);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_err(&dssdev->dev, "error while enabling panel, issuing HW reset\n");
|
||||
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
omapdss_dsi_display_disable(dssdev);
|
||||
err0:
|
||||
dsi_bus_unlock();
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void taal_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
dsi_bus_lock();
|
||||
r = taal_dcs_write_0(DCS_DISPLAY_OFF);
|
||||
if (!r) {
|
||||
r = taal_sleep_in(td);
|
||||
/* HACK: wait a bit so that the message goes through */
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
cancel_delayed_work(&td->esd_work);
|
||||
|
||||
taal_dcs_write_0(DCS_DISPLAY_OFF);
|
||||
taal_sleep_in(td);
|
||||
|
||||
/* wait a bit so that the message goes through */
|
||||
msleep(10);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev,
|
||||
"error disabling panel, issuing HW reset\n");
|
||||
taal_hw_reset(dssdev);
|
||||
}
|
||||
|
||||
omapdss_dsi_display_disable(dssdev);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
td->enabled = 0;
|
||||
|
||||
dsi_bus_unlock();
|
||||
}
|
||||
|
||||
static int taal_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "enable\n");
|
||||
|
|
@ -749,10 +954,19 @@ static int taal_enable(struct omap_dss_device *dssdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = taal_power_on(dssdev);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (panel_data->use_esd_check)
|
||||
queue_delayed_work(td->esd_wq, &td->esd_work,
|
||||
TAAL_ESD_CHECK_PERIOD);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
|
@ -772,9 +986,15 @@ static void taal_disable(struct omap_dss_device *dssdev)
|
|||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
cancel_delayed_work(&td->esd_work);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
taal_power_off(dssdev);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
|
@ -794,7 +1014,14 @@ static int taal_suspend(struct omap_dss_device *dssdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
cancel_delayed_work(&td->esd_work);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
taal_power_off(dssdev);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
|
@ -808,6 +1035,7 @@ err:
|
|||
static int taal_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "resume\n");
|
||||
|
|
@ -819,8 +1047,20 @@ static int taal_resume(struct omap_dss_device *dssdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = taal_power_on(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
if (r) {
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
} else {
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
if (panel_data->use_esd_check)
|
||||
queue_delayed_work(td->esd_wq, &td->esd_work,
|
||||
TAAL_ESD_CHECK_PERIOD);
|
||||
}
|
||||
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
|
|
@ -837,10 +1077,52 @@ static void taal_framedone_cb(int err, void *data)
|
|||
dsi_bus_unlock();
|
||||
}
|
||||
|
||||
static irqreturn_t taal_te_isr(int irq, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = data;
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int old;
|
||||
int r;
|
||||
|
||||
old = atomic_cmpxchg(&td->do_update, 1, 0);
|
||||
|
||||
if (old) {
|
||||
cancel_delayed_work(&td->te_timeout_work);
|
||||
|
||||
r = omap_dsi_update(dssdev, TCH,
|
||||
td->update_region.x,
|
||||
td->update_region.y,
|
||||
td->update_region.w,
|
||||
td->update_region.h,
|
||||
taal_framedone_cb, dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
err:
|
||||
dev_err(&dssdev->dev, "start update failed\n");
|
||||
dsi_bus_unlock();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void taal_te_timeout_work_callback(struct work_struct *work)
|
||||
{
|
||||
struct taal_data *td = container_of(work, struct taal_data,
|
||||
te_timeout_work.work);
|
||||
struct omap_dss_device *dssdev = td->dssdev;
|
||||
|
||||
dev_err(&dssdev->dev, "TE not received for 250ms!\n");
|
||||
|
||||
atomic_set(&td->do_update, 0);
|
||||
dsi_bus_unlock();
|
||||
}
|
||||
|
||||
static int taal_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
|
||||
|
|
@ -853,7 +1135,7 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
goto err;
|
||||
}
|
||||
|
||||
r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h);
|
||||
r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
|
|
@ -861,10 +1143,21 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
r = omap_dsi_update(dssdev, TCH, x, y, w, h,
|
||||
taal_framedone_cb, dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
td->update_region.x = x;
|
||||
td->update_region.y = y;
|
||||
td->update_region.w = w;
|
||||
td->update_region.h = h;
|
||||
barrier();
|
||||
schedule_delayed_work(&td->te_timeout_work,
|
||||
msecs_to_jiffies(250));
|
||||
atomic_set(&td->do_update, 1);
|
||||
} else {
|
||||
r = omap_dsi_update(dssdev, TCH, x, y, w, h,
|
||||
taal_framedone_cb, dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* note: no bus_unlock here. unlock is in framedone_cb */
|
||||
mutex_unlock(&td->lock);
|
||||
|
|
@ -894,20 +1187,19 @@ static int taal_sync(struct omap_dss_device *dssdev)
|
|||
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
int r;
|
||||
|
||||
td->te_enabled = enable;
|
||||
|
||||
if (enable)
|
||||
r = taal_dcs_write_1(DCS_TEAR_ON, 0);
|
||||
else
|
||||
r = taal_dcs_write_0(DCS_TEAR_OFF);
|
||||
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
if (!panel_data->use_ext_te)
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
|
||||
/* XXX for some reason, DSI TE breaks if we don't wait here.
|
||||
* Panel bug? Needs more studying */
|
||||
msleep(100);
|
||||
if (td->panel_config->sleep.enable_te)
|
||||
msleep(td->panel_config->sleep.enable_te);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
@ -918,10 +1210,26 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
|||
int r;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->te_enabled == enable)
|
||||
goto end;
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = _taal_enable_te(dssdev, enable);
|
||||
if (td->enabled) {
|
||||
r = _taal_enable_te(dssdev, enable);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
td->te_enabled = enable;
|
||||
|
||||
dsi_bus_unlock();
|
||||
end:
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock();
|
||||
mutex_unlock(&td->lock);
|
||||
|
||||
|
|
@ -948,6 +1256,10 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
|||
dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->rotate == rotate)
|
||||
goto end;
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
if (td->enabled) {
|
||||
|
|
@ -959,6 +1271,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
|||
td->rotate = rotate;
|
||||
|
||||
dsi_bus_unlock();
|
||||
end:
|
||||
mutex_unlock(&td->lock);
|
||||
return 0;
|
||||
err:
|
||||
|
|
@ -987,6 +1300,10 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
|
|||
dev_dbg(&dssdev->dev, "mirror %d\n", enable);
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (td->mirror == enable)
|
||||
goto end;
|
||||
|
||||
dsi_bus_lock();
|
||||
if (td->enabled) {
|
||||
r = taal_set_addr_mode(td->rotate, enable);
|
||||
|
|
@ -997,6 +1314,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
|
|||
td->mirror = enable;
|
||||
|
||||
dsi_bus_unlock();
|
||||
end:
|
||||
mutex_unlock(&td->lock);
|
||||
return 0;
|
||||
err:
|
||||
|
|
@ -1024,23 +1342,30 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
|
|||
int r;
|
||||
|
||||
mutex_lock(&td->lock);
|
||||
|
||||
if (!td->enabled) {
|
||||
r = -ENODEV;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = taal_dcs_read_1(DCS_GET_ID1, &id1);
|
||||
if (r)
|
||||
goto err;
|
||||
goto err2;
|
||||
r = taal_dcs_read_1(DCS_GET_ID2, &id2);
|
||||
if (r)
|
||||
goto err;
|
||||
goto err2;
|
||||
r = taal_dcs_read_1(DCS_GET_ID3, &id3);
|
||||
if (r)
|
||||
goto err;
|
||||
goto err2;
|
||||
|
||||
dsi_bus_unlock();
|
||||
mutex_unlock(&td->lock);
|
||||
return 0;
|
||||
err:
|
||||
err2:
|
||||
dsi_bus_unlock();
|
||||
err1:
|
||||
mutex_unlock(&td->lock);
|
||||
return r;
|
||||
}
|
||||
|
|
@ -1128,6 +1453,7 @@ static void taal_esd_work(struct work_struct *work)
|
|||
struct taal_data *td = container_of(work, struct taal_data,
|
||||
esd_work.work);
|
||||
struct omap_dss_device *dssdev = td->dssdev;
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
u8 state1, state2;
|
||||
int r;
|
||||
|
||||
|
|
@ -1168,7 +1494,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->use_ext_te && td->te_enabled) {
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
r = taal_dcs_write_1(DCS_TEAR_ON, 0);
|
||||
if (r)
|
||||
goto err;
|
||||
|
|
@ -1184,6 +1510,7 @@ err:
|
|||
dev_err(&dssdev->dev, "performing LCD reset\n");
|
||||
|
||||
taal_power_off(dssdev);
|
||||
taal_hw_reset(dssdev);
|
||||
taal_power_on(dssdev);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
|
|
|||
|
|
@ -73,8 +73,12 @@ static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
|
|||
|
||||
static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS;
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT |
|
||||
OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS |
|
||||
OMAP_DSS_LCD_IPC |
|
||||
OMAP_DSS_LCD_ONOFF;
|
||||
|
||||
dssdev->panel.timings = toppoly_tdo_panel_timings;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hardirq.h>
|
||||
|
||||
#include <plat/sram.h>
|
||||
#include <plat/clock.h>
|
||||
|
|
@ -335,7 +336,7 @@ void dispc_save_context(void)
|
|||
void dispc_restore_context(void)
|
||||
{
|
||||
RR(SYSCONFIG);
|
||||
RR(IRQENABLE);
|
||||
/*RR(IRQENABLE);*/
|
||||
/*RR(CONTROL);*/
|
||||
RR(CONFIG);
|
||||
RR(DEFAULT_COLOR0);
|
||||
|
|
@ -472,6 +473,15 @@ void dispc_restore_context(void)
|
|||
|
||||
/* enable last, because LCD & DIGIT enable are here */
|
||||
RR(CONTROL);
|
||||
|
||||
/* clear spurious SYNC_LOST_DIGIT interrupts */
|
||||
dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
|
||||
|
||||
/*
|
||||
* enable last so IRQs won't trigger before
|
||||
* the context is fully restored
|
||||
*/
|
||||
RR(IRQENABLE);
|
||||
}
|
||||
|
||||
#undef SR
|
||||
|
|
@ -3019,7 +3029,7 @@ void dispc_fake_vsync_irq(void)
|
|||
u32 irqstatus = DISPC_IRQ_VSYNC;
|
||||
int i;
|
||||
|
||||
local_irq_disable();
|
||||
WARN_ON(!in_interrupt());
|
||||
|
||||
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
||||
struct omap_dispc_isr_data *isr_data;
|
||||
|
|
@ -3031,8 +3041,6 @@ void dispc_fake_vsync_irq(void)
|
|||
if (isr_data->mask & irqstatus)
|
||||
isr_data->isr(isr_data->arg, irqstatus);
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ static ssize_t display_upd_mode_store(struct device *dev,
|
|||
int val, r;
|
||||
enum omap_dss_update_mode mode;
|
||||
|
||||
if (!dssdev->driver->set_update_mode)
|
||||
return -EINVAL;
|
||||
|
||||
val = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
switch (val) {
|
||||
|
|
@ -343,7 +346,6 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
|
|||
case OMAP_DISPLAY_TYPE_VENC:
|
||||
case OMAP_DISPLAY_TYPE_SDI:
|
||||
return 24;
|
||||
return 24;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,14 @@ struct dsi_reg { u16 idx; };
|
|||
#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
|
||||
#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
|
||||
#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
|
||||
#define DSI_CIO_IRQ_ERROR_MASK \
|
||||
(DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
|
||||
DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
|
||||
DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \
|
||||
DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3)
|
||||
|
||||
#define DSI_DT_DCS_SHORT_WRITE_0 0x05
|
||||
#define DSI_DT_DCS_SHORT_WRITE_1 0x15
|
||||
|
|
@ -232,13 +240,15 @@ static struct
|
|||
unsigned pll_locked;
|
||||
|
||||
struct completion bta_completion;
|
||||
void (*bta_callback)(void);
|
||||
|
||||
int update_channel;
|
||||
struct dsi_update_region update_region;
|
||||
|
||||
bool te_enabled;
|
||||
|
||||
struct work_struct framedone_work;
|
||||
struct workqueue_struct *workqueue;
|
||||
|
||||
void (*framedone_callback)(int, void *);
|
||||
void *framedone_data;
|
||||
|
||||
|
|
@ -509,9 +519,13 @@ void dsi_irq_handler(void)
|
|||
dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
|
||||
#endif
|
||||
|
||||
if (vcstatus & DSI_VC_IRQ_BTA)
|
||||
if (vcstatus & DSI_VC_IRQ_BTA) {
|
||||
complete(&dsi.bta_completion);
|
||||
|
||||
if (dsi.bta_callback)
|
||||
dsi.bta_callback();
|
||||
}
|
||||
|
||||
if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
|
||||
DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
|
||||
i, vcstatus);
|
||||
|
|
@ -536,8 +550,12 @@ void dsi_irq_handler(void)
|
|||
/* flush posted write */
|
||||
dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
|
||||
|
||||
DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
|
||||
print_irq_status_cio(ciostatus);
|
||||
if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
|
||||
DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
|
||||
print_irq_status_cio(ciostatus);
|
||||
} else if (debug_irq) {
|
||||
print_irq_status_cio(ciostatus);
|
||||
}
|
||||
}
|
||||
|
||||
dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
|
||||
|
|
@ -584,11 +602,8 @@ static void _dsi_initialize_irq(void)
|
|||
for (i = 0; i < 4; ++i)
|
||||
dsi_write_reg(DSI_VC_IRQENABLE(i), l);
|
||||
|
||||
/* XXX zonda responds incorrectly, causing control error:
|
||||
Exit from LP-ESC mode to LP11 uses wrong transition states on the
|
||||
data lines LP0 and LN0. */
|
||||
dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
|
||||
-1 & (~DSI_CIO_IRQ_ERRCONTROL2));
|
||||
l = DSI_CIO_IRQ_ERROR_MASK;
|
||||
dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
|
||||
}
|
||||
|
||||
static u32 dsi_get_errors(void)
|
||||
|
|
@ -1098,6 +1113,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
|
|||
if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
|
||||
DSSERR("PLL not coming out of reset.\n");
|
||||
r = -ENODEV;
|
||||
dispc_pck_free_enable(0);
|
||||
goto err1;
|
||||
}
|
||||
|
||||
|
|
@ -1740,42 +1756,52 @@ static void dsi_vc_initial_config(int channel)
|
|||
dsi.vc[channel].mode = DSI_VC_MODE_L4;
|
||||
}
|
||||
|
||||
static void dsi_vc_config_l4(int channel)
|
||||
static int dsi_vc_config_l4(int channel)
|
||||
{
|
||||
if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
DSSDBGF("%d", channel);
|
||||
|
||||
dsi_vc_enable(channel, 0);
|
||||
|
||||
if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
|
||||
/* VC_BUSY */
|
||||
if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) {
|
||||
DSSERR("vc(%d) busy when trying to config for L4\n", channel);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
|
||||
|
||||
dsi_vc_enable(channel, 1);
|
||||
|
||||
dsi.vc[channel].mode = DSI_VC_MODE_L4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsi_vc_config_vp(int channel)
|
||||
static int dsi_vc_config_vp(int channel)
|
||||
{
|
||||
if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
DSSDBGF("%d", channel);
|
||||
|
||||
dsi_vc_enable(channel, 0);
|
||||
|
||||
if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */
|
||||
/* VC_BUSY */
|
||||
if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) {
|
||||
DSSERR("vc(%d) busy when trying to config for VP\n", channel);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
|
||||
|
||||
dsi_vc_enable(channel, 1);
|
||||
|
||||
dsi.vc[channel].mode = DSI_VC_MODE_VP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1854,19 +1880,19 @@ static u16 dsi_vc_flush_receive_data(int channel)
|
|||
u32 val;
|
||||
u8 dt;
|
||||
val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
|
||||
DSSDBG("\trawval %#08x\n", val);
|
||||
DSSERR("\trawval %#08x\n", val);
|
||||
dt = FLD_GET(val, 5, 0);
|
||||
if (dt == DSI_DT_RX_ACK_WITH_ERR) {
|
||||
u16 err = FLD_GET(val, 23, 8);
|
||||
dsi_show_rx_ack_with_err(err);
|
||||
} else if (dt == DSI_DT_RX_SHORT_READ_1) {
|
||||
DSSDBG("\tDCS short response, 1 byte: %#x\n",
|
||||
DSSERR("\tDCS short response, 1 byte: %#x\n",
|
||||
FLD_GET(val, 23, 8));
|
||||
} else if (dt == DSI_DT_RX_SHORT_READ_2) {
|
||||
DSSDBG("\tDCS short response, 2 byte: %#x\n",
|
||||
DSSERR("\tDCS short response, 2 byte: %#x\n",
|
||||
FLD_GET(val, 23, 8));
|
||||
} else if (dt == DSI_DT_RX_DCS_LONG_READ) {
|
||||
DSSDBG("\tDCS long response, len %d\n",
|
||||
DSSERR("\tDCS long response, len %d\n",
|
||||
FLD_GET(val, 23, 8));
|
||||
dsi_vc_flush_long_data(channel);
|
||||
} else {
|
||||
|
|
@ -2087,6 +2113,13 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len)
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
|
||||
DSSERR("rx fifo not empty after write, dumping data:\n");
|
||||
dsi_vc_flush_receive_data(channel);
|
||||
r = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
|
||||
|
|
@ -2233,11 +2266,12 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data)
|
|||
}
|
||||
EXPORT_SYMBOL(dsi_vc_dcs_read_1);
|
||||
|
||||
int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data)
|
||||
int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2)
|
||||
{
|
||||
u8 buf[2];
|
||||
int r;
|
||||
|
||||
r = dsi_vc_dcs_read(channel, dcs_cmd, (u8 *)data, 2);
|
||||
r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
|
@ -2245,231 +2279,122 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data)
|
|||
if (r != 2)
|
||||
return -EIO;
|
||||
|
||||
*data1 = buf[0];
|
||||
*data2 = buf[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dsi_vc_dcs_read_2);
|
||||
|
||||
int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
|
||||
{
|
||||
int r;
|
||||
r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
|
||||
return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
|
||||
len, 0);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dsi_vc_send_bta_sync(channel);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
|
||||
|
||||
static void dsi_set_lp_rx_timeout(unsigned long ns)
|
||||
static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16)
|
||||
{
|
||||
u32 r;
|
||||
unsigned x4, x16;
|
||||
unsigned long fck;
|
||||
unsigned long ticks;
|
||||
unsigned long total_ticks;
|
||||
u32 r;
|
||||
|
||||
BUG_ON(ticks > 0x1fff);
|
||||
|
||||
/* ticks in DSI_FCK */
|
||||
|
||||
fck = dsi_fclk_rate();
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000;
|
||||
x4 = 0;
|
||||
x16 = 0;
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
|
||||
x4 = 1;
|
||||
x16 = 0;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
|
||||
x4 = 0;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
|
||||
x4 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
DSSWARN("LP_TX_TO over limit, setting it to max\n");
|
||||
ticks = 0x1fff;
|
||||
x4 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
r = dsi_read_reg(DSI_TIMING2);
|
||||
r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
|
||||
r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */
|
||||
r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */
|
||||
r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */
|
||||
r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */
|
||||
r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
|
||||
dsi_write_reg(DSI_TIMING2, r);
|
||||
|
||||
DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n",
|
||||
(ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
|
||||
(fck / 1000 / 1000),
|
||||
ticks, x4 ? " x4" : "", x16 ? " x16" : "");
|
||||
total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
|
||||
|
||||
DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n",
|
||||
total_ticks,
|
||||
ticks, x4 ? " x4" : "", x16 ? " x16" : "",
|
||||
(total_ticks * 1000) / (fck / 1000 / 1000));
|
||||
}
|
||||
|
||||
static void dsi_set_ta_timeout(unsigned long ns)
|
||||
static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16)
|
||||
{
|
||||
u32 r;
|
||||
unsigned x8, x16;
|
||||
unsigned long fck;
|
||||
unsigned long ticks;
|
||||
unsigned long total_ticks;
|
||||
u32 r;
|
||||
|
||||
BUG_ON(ticks > 0x1fff);
|
||||
|
||||
/* ticks in DSI_FCK */
|
||||
fck = dsi_fclk_rate();
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000;
|
||||
x8 = 0;
|
||||
x16 = 0;
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 8;
|
||||
x8 = 1;
|
||||
x16 = 0;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
|
||||
x8 = 0;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16);
|
||||
x8 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
DSSWARN("TA_TO over limit, setting it to max\n");
|
||||
ticks = 0x1fff;
|
||||
x8 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
r = dsi_read_reg(DSI_TIMING1);
|
||||
r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
|
||||
r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */
|
||||
r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */
|
||||
r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */
|
||||
r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */
|
||||
r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
|
||||
dsi_write_reg(DSI_TIMING1, r);
|
||||
|
||||
DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n",
|
||||
(ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) /
|
||||
(fck / 1000 / 1000),
|
||||
ticks, x8 ? " x8" : "", x16 ? " x16" : "");
|
||||
total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
|
||||
|
||||
DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n",
|
||||
total_ticks,
|
||||
ticks, x8 ? " x8" : "", x16 ? " x16" : "",
|
||||
(total_ticks * 1000) / (fck / 1000 / 1000));
|
||||
}
|
||||
|
||||
static void dsi_set_stop_state_counter(unsigned long ns)
|
||||
static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16)
|
||||
{
|
||||
u32 r;
|
||||
unsigned x4, x16;
|
||||
unsigned long fck;
|
||||
unsigned long ticks;
|
||||
unsigned long total_ticks;
|
||||
u32 r;
|
||||
|
||||
BUG_ON(ticks > 0x1fff);
|
||||
|
||||
/* ticks in DSI_FCK */
|
||||
|
||||
fck = dsi_fclk_rate();
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000;
|
||||
x4 = 0;
|
||||
x16 = 0;
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
|
||||
x4 = 1;
|
||||
x16 = 0;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
|
||||
x4 = 0;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
|
||||
x4 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
DSSWARN("STOP_STATE_COUNTER_IO over limit, "
|
||||
"setting it to max\n");
|
||||
ticks = 0x1fff;
|
||||
x4 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
r = dsi_read_reg(DSI_TIMING1);
|
||||
r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
|
||||
r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */
|
||||
r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */
|
||||
r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */
|
||||
r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */
|
||||
r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
|
||||
dsi_write_reg(DSI_TIMING1, r);
|
||||
|
||||
DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n",
|
||||
(ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
|
||||
(fck / 1000 / 1000),
|
||||
ticks, x4 ? " x4" : "", x16 ? " x16" : "");
|
||||
total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
|
||||
|
||||
DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n",
|
||||
total_ticks,
|
||||
ticks, x4 ? " x4" : "", x16 ? " x16" : "",
|
||||
(total_ticks * 1000) / (fck / 1000 / 1000));
|
||||
}
|
||||
|
||||
static void dsi_set_hs_tx_timeout(unsigned long ns)
|
||||
static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16)
|
||||
{
|
||||
u32 r;
|
||||
unsigned x4, x16;
|
||||
unsigned long fck;
|
||||
unsigned long ticks;
|
||||
unsigned long total_ticks;
|
||||
u32 r;
|
||||
|
||||
BUG_ON(ticks > 0x1fff);
|
||||
|
||||
/* ticks in TxByteClkHS */
|
||||
|
||||
fck = dsi_get_txbyteclkhs();
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000;
|
||||
x4 = 0;
|
||||
x16 = 0;
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
|
||||
x4 = 1;
|
||||
x16 = 0;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
|
||||
x4 = 0;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
|
||||
x4 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
if (ticks > 0x1fff) {
|
||||
DSSWARN("HS_TX_TO over limit, setting it to max\n");
|
||||
ticks = 0x1fff;
|
||||
x4 = 1;
|
||||
x16 = 1;
|
||||
}
|
||||
|
||||
r = dsi_read_reg(DSI_TIMING2);
|
||||
r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
|
||||
r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */
|
||||
r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */
|
||||
r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */
|
||||
r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */
|
||||
r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
|
||||
dsi_write_reg(DSI_TIMING2, r);
|
||||
|
||||
DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n",
|
||||
(ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) /
|
||||
(fck / 1000 / 1000),
|
||||
ticks, x4 ? " x4" : "", x16 ? " x16" : "");
|
||||
total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
|
||||
|
||||
DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n",
|
||||
total_ticks,
|
||||
ticks, x4 ? " x4" : "", x16 ? " x16" : "",
|
||||
(total_ticks * 1000) / (fck / 1000 / 1000));
|
||||
}
|
||||
static int dsi_proto_config(struct omap_dss_device *dssdev)
|
||||
{
|
||||
|
|
@ -2487,10 +2412,10 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
|
|||
DSI_FIFO_SIZE_32);
|
||||
|
||||
/* XXX what values for the timeouts? */
|
||||
dsi_set_stop_state_counter(1000);
|
||||
dsi_set_ta_timeout(6400000);
|
||||
dsi_set_lp_rx_timeout(48000);
|
||||
dsi_set_hs_tx_timeout(1000000);
|
||||
dsi_set_stop_state_counter(0x1000, false, false);
|
||||
dsi_set_ta_timeout(0x1fff, true, true);
|
||||
dsi_set_lp_rx_timeout(0x1fff, true, true);
|
||||
dsi_set_hs_tx_timeout(0x1fff, true, true);
|
||||
|
||||
switch (dssdev->ctrl.pixel_size) {
|
||||
case 16:
|
||||
|
|
@ -2759,6 +2684,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
|
|||
unsigned packet_payload;
|
||||
unsigned packet_len;
|
||||
u32 l;
|
||||
int r;
|
||||
const unsigned channel = dsi.update_channel;
|
||||
/* line buffer is 1024 x 24bits */
|
||||
/* XXX: for some reason using full buffer size causes considerable TX
|
||||
|
|
@ -2809,8 +2735,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
|
|||
|
||||
dsi_perf_mark_start();
|
||||
|
||||
schedule_delayed_work(&dsi.framedone_timeout_work,
|
||||
r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work,
|
||||
msecs_to_jiffies(250));
|
||||
BUG_ON(r == 0);
|
||||
|
||||
dss_start_update(dssdev);
|
||||
|
||||
|
|
@ -2834,107 +2761,108 @@ static void dsi_te_timeout(unsigned long arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void dsi_handle_framedone(int error)
|
||||
{
|
||||
const int channel = dsi.update_channel;
|
||||
|
||||
cancel_delayed_work(&dsi.framedone_timeout_work);
|
||||
|
||||
dsi_vc_disable_bta_irq(channel);
|
||||
|
||||
/* SIDLEMODE back to smart-idle */
|
||||
dispc_enable_sidle();
|
||||
|
||||
dsi.bta_callback = NULL;
|
||||
|
||||
if (dsi.te_enabled) {
|
||||
/* enable LP_RX_TO again after the TE */
|
||||
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
|
||||
}
|
||||
|
||||
/* RX_FIFO_NOT_EMPTY */
|
||||
if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
|
||||
DSSERR("Received error during frame transfer:\n");
|
||||
dsi_vc_flush_receive_data(channel);
|
||||
if (!error)
|
||||
error = -EIO;
|
||||
}
|
||||
|
||||
dsi.framedone_callback(error, dsi.framedone_data);
|
||||
|
||||
if (!error)
|
||||
dsi_perf_show("DISPC");
|
||||
}
|
||||
|
||||
static void dsi_framedone_timeout_work_callback(struct work_struct *work)
|
||||
{
|
||||
int r;
|
||||
const int channel = dsi.update_channel;
|
||||
/* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
|
||||
* 250ms which would conflict with this timeout work. What should be
|
||||
* done is first cancel the transfer on the HW, and then cancel the
|
||||
* possibly scheduled framedone work. However, cancelling the transfer
|
||||
* on the HW is buggy, and would probably require resetting the whole
|
||||
* DSI */
|
||||
|
||||
DSSERR("Framedone not received for 250ms!\n");
|
||||
|
||||
/* SIDLEMODE back to smart-idle */
|
||||
dispc_enable_sidle();
|
||||
|
||||
if (dsi.te_enabled) {
|
||||
/* enable LP_RX_TO again after the TE */
|
||||
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
|
||||
}
|
||||
|
||||
/* Send BTA after the frame. We need this for the TE to work, as TE
|
||||
* trigger is only sent for BTAs without preceding packet. Thus we need
|
||||
* to BTA after the pixel packets so that next BTA will cause TE
|
||||
* trigger.
|
||||
*
|
||||
* This is not needed when TE is not in use, but we do it anyway to
|
||||
* make sure that the transfer has been completed. It would be more
|
||||
* optimal, but more complex, to wait only just before starting next
|
||||
* transfer. */
|
||||
r = dsi_vc_send_bta_sync(channel);
|
||||
if (r)
|
||||
DSSERR("BTA after framedone failed\n");
|
||||
|
||||
/* RX_FIFO_NOT_EMPTY */
|
||||
if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
|
||||
DSSERR("Received error during frame transfer:\n");
|
||||
dsi_vc_flush_receive_data(channel);
|
||||
}
|
||||
|
||||
dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data);
|
||||
dsi_handle_framedone(-ETIMEDOUT);
|
||||
}
|
||||
|
||||
static void dsi_framedone_irq_callback(void *data, u32 mask)
|
||||
static void dsi_framedone_bta_callback(void)
|
||||
{
|
||||
/* Note: We get FRAMEDONE when DISPC has finished sending pixels and
|
||||
* turns itself off. However, DSI still has the pixels in its buffers,
|
||||
* and is sending the data.
|
||||
*/
|
||||
|
||||
/* SIDLEMODE back to smart-idle */
|
||||
dispc_enable_sidle();
|
||||
|
||||
schedule_work(&dsi.framedone_work);
|
||||
}
|
||||
|
||||
static void dsi_handle_framedone(void)
|
||||
{
|
||||
int r;
|
||||
const int channel = dsi.update_channel;
|
||||
|
||||
DSSDBG("FRAMEDONE\n");
|
||||
|
||||
if (dsi.te_enabled) {
|
||||
/* enable LP_RX_TO again after the TE */
|
||||
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
|
||||
}
|
||||
|
||||
/* Send BTA after the frame. We need this for the TE to work, as TE
|
||||
* trigger is only sent for BTAs without preceding packet. Thus we need
|
||||
* to BTA after the pixel packets so that next BTA will cause TE
|
||||
* trigger.
|
||||
*
|
||||
* This is not needed when TE is not in use, but we do it anyway to
|
||||
* make sure that the transfer has been completed. It would be more
|
||||
* optimal, but more complex, to wait only just before starting next
|
||||
* transfer. */
|
||||
r = dsi_vc_send_bta_sync(channel);
|
||||
if (r)
|
||||
DSSERR("BTA after framedone failed\n");
|
||||
|
||||
/* RX_FIFO_NOT_EMPTY */
|
||||
if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
|
||||
DSSERR("Received error during frame transfer:\n");
|
||||
dsi_vc_flush_receive_data(channel);
|
||||
}
|
||||
dsi_handle_framedone(0);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
|
||||
dispc_fake_vsync_irq();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dsi_framedone_work_callback(struct work_struct *work)
|
||||
static void dsi_framedone_irq_callback(void *data, u32 mask)
|
||||
{
|
||||
DSSDBGF();
|
||||
const int channel = dsi.update_channel;
|
||||
int r;
|
||||
|
||||
cancel_delayed_work_sync(&dsi.framedone_timeout_work);
|
||||
/* Note: We get FRAMEDONE when DISPC has finished sending pixels and
|
||||
* turns itself off. However, DSI still has the pixels in its buffers,
|
||||
* and is sending the data.
|
||||
*/
|
||||
|
||||
dsi_handle_framedone();
|
||||
if (dsi.te_enabled) {
|
||||
/* enable LP_RX_TO again after the TE */
|
||||
REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
|
||||
}
|
||||
|
||||
dsi_perf_show("DISPC");
|
||||
/* Send BTA after the frame. We need this for the TE to work, as TE
|
||||
* trigger is only sent for BTAs without preceding packet. Thus we need
|
||||
* to BTA after the pixel packets so that next BTA will cause TE
|
||||
* trigger.
|
||||
*
|
||||
* This is not needed when TE is not in use, but we do it anyway to
|
||||
* make sure that the transfer has been completed. It would be more
|
||||
* optimal, but more complex, to wait only just before starting next
|
||||
* transfer.
|
||||
*
|
||||
* Also, as there's no interrupt telling when the transfer has been
|
||||
* done and the channel could be reconfigured, the only way is to
|
||||
* busyloop until TE_SIZE is zero. With BTA we can do this
|
||||
* asynchronously.
|
||||
* */
|
||||
|
||||
dsi.framedone_callback(0, dsi.framedone_data);
|
||||
dsi.bta_callback = dsi_framedone_bta_callback;
|
||||
|
||||
barrier();
|
||||
|
||||
dsi_vc_enable_bta_irq(channel);
|
||||
|
||||
r = dsi_vc_send_bta(channel);
|
||||
if (r) {
|
||||
DSSERR("BTA after framedone failed\n");
|
||||
dsi_handle_framedone(-EIO);
|
||||
}
|
||||
}
|
||||
|
||||
int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h)
|
||||
u16 *x, u16 *y, u16 *w, u16 *h,
|
||||
bool enlarge_update_area)
|
||||
{
|
||||
u16 dw, dh;
|
||||
|
||||
|
|
@ -2958,7 +2886,8 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
|
|||
dsi_perf_mark_setup();
|
||||
|
||||
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h);
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h,
|
||||
enlarge_update_area);
|
||||
dispc_set_lcd_size(*w, *h);
|
||||
}
|
||||
|
||||
|
|
@ -2973,6 +2902,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
|
|||
{
|
||||
dsi.update_channel = channel;
|
||||
|
||||
/* OMAP DSS cannot send updates of odd widths.
|
||||
* omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
|
||||
* here to make sure we catch erroneous updates. Otherwise we'll only
|
||||
* see rather obscure HW error happening, as DSS halts. */
|
||||
BUG_ON(x % 2 == 1);
|
||||
|
||||
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
|
||||
dsi.framedone_callback = callback;
|
||||
dsi.framedone_data = data;
|
||||
|
|
@ -2985,7 +2920,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
|
|||
|
||||
dsi_update_screen_dispc(dssdev, x, y, w, h);
|
||||
} else {
|
||||
dsi_update_screen_l4(dssdev, x, y, w, h);
|
||||
int r;
|
||||
|
||||
r = dsi_update_screen_l4(dssdev, x, y, w, h);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dsi_perf_show("L4");
|
||||
callback(0, data);
|
||||
}
|
||||
|
|
@ -3048,8 +2988,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
|
|||
cinfo.regm3 = dssdev->phy.dsi.div.regm3;
|
||||
cinfo.regm4 = dssdev->phy.dsi.div.regm4;
|
||||
r = dsi_calc_clock_rates(&cinfo);
|
||||
if (r)
|
||||
if (r) {
|
||||
DSSERR("Failed to calc dsi clocks\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dsi_pll_set_clock_div(&cinfo);
|
||||
if (r) {
|
||||
|
|
@ -3147,6 +3089,13 @@ err0:
|
|||
|
||||
static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
|
||||
{
|
||||
/* disable interface */
|
||||
dsi_if_enable(0);
|
||||
dsi_vc_enable(0, 0);
|
||||
dsi_vc_enable(1, 0);
|
||||
dsi_vc_enable(2, 0);
|
||||
dsi_vc_enable(3, 0);
|
||||
|
||||
dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
||||
dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
||||
dsi_complexio_uninit();
|
||||
|
|
@ -3257,7 +3206,7 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
|
|||
burst_size_bytes = 16 * 32 / 8;
|
||||
|
||||
*fifo_high = fifo_size - burst_size_bytes;
|
||||
*fifo_low = fifo_size - burst_size_bytes * 8;
|
||||
*fifo_low = fifo_size - burst_size_bytes * 2;
|
||||
}
|
||||
|
||||
int dsi_init_display(struct omap_dss_device *dssdev)
|
||||
|
|
@ -3274,6 +3223,18 @@ int dsi_init_display(struct omap_dss_device *dssdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void dsi_wait_dsi1_pll_active(void)
|
||||
{
|
||||
if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
|
||||
DSSERR("DSI1 PLL clock not active\n");
|
||||
}
|
||||
|
||||
void dsi_wait_dsi2_pll_active(void)
|
||||
{
|
||||
if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
|
||||
DSSERR("DSI2 PLL clock not active\n");
|
||||
}
|
||||
|
||||
int dsi_init(struct platform_device *pdev)
|
||||
{
|
||||
u32 rev;
|
||||
|
|
@ -3292,7 +3253,10 @@ int dsi_init(struct platform_device *pdev)
|
|||
mutex_init(&dsi.lock);
|
||||
sema_init(&dsi.bus_lock, 1);
|
||||
|
||||
INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback);
|
||||
dsi.workqueue = create_singlethread_workqueue("dsi");
|
||||
if (dsi.workqueue == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work,
|
||||
dsi_framedone_timeout_work_callback);
|
||||
|
||||
|
|
@ -3328,6 +3292,7 @@ int dsi_init(struct platform_device *pdev)
|
|||
err2:
|
||||
iounmap(dsi.base);
|
||||
err1:
|
||||
destroy_workqueue(dsi.workqueue);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -3335,6 +3300,8 @@ void dsi_exit(void)
|
|||
{
|
||||
iounmap(dsi.base);
|
||||
|
||||
destroy_workqueue(dsi.workqueue);
|
||||
|
||||
DSSDBG("omap_dsi_exit\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,6 +265,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
|
|||
|
||||
b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
|
||||
|
||||
if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
|
||||
dsi_wait_dsi1_pll_active();
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
|
||||
|
||||
dss.dispc_clk_source = clk_src;
|
||||
|
|
@ -279,6 +282,9 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
|
|||
|
||||
b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
|
||||
|
||||
if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
|
||||
dsi_wait_dsi2_pll_active();
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
|
||||
|
||||
dss.dsi_clk_source = clk_src;
|
||||
|
|
|
|||
|
|
@ -199,7 +199,8 @@ int dss_init_overlay_managers(struct platform_device *pdev);
|
|||
void dss_uninit_overlay_managers(struct platform_device *pdev);
|
||||
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
|
||||
void dss_setup_partial_planes(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h);
|
||||
u16 *x, u16 *y, u16 *w, u16 *h,
|
||||
bool enlarge_update_area);
|
||||
void dss_start_update(struct omap_dss_device *dssdev);
|
||||
|
||||
/* overlay */
|
||||
|
|
@ -281,6 +282,8 @@ void dsi_pll_uninit(void);
|
|||
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
|
||||
u32 fifo_size, enum omap_burst_size *burst_size,
|
||||
u32 *fifo_low, u32 *fifo_high);
|
||||
void dsi_wait_dsi1_pll_active(void);
|
||||
void dsi_wait_dsi2_pll_active(void);
|
||||
#else
|
||||
static inline int dsi_init(struct platform_device *pdev)
|
||||
{
|
||||
|
|
@ -289,6 +292,12 @@ static inline int dsi_init(struct platform_device *pdev)
|
|||
static inline void dsi_exit(void)
|
||||
{
|
||||
}
|
||||
static inline void dsi_wait_dsi1_pll_active(void)
|
||||
{
|
||||
}
|
||||
static inline void dsi_wait_dsi2_pll_active(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* DPI */
|
||||
|
|
|
|||
|
|
@ -440,6 +440,10 @@ struct manager_cache_data {
|
|||
|
||||
/* manual update region */
|
||||
u16 x, y, w, h;
|
||||
|
||||
/* enlarge the update area if the update area contains scaled
|
||||
* overlays */
|
||||
bool enlarge_update_area;
|
||||
};
|
||||
|
||||
static struct {
|
||||
|
|
@ -525,7 +529,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|||
int i;
|
||||
struct omap_dss_device *dssdev = mgr->device;
|
||||
|
||||
if (!dssdev)
|
||||
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
|
||||
|
|
@ -596,11 +600,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|||
int r;
|
||||
int i;
|
||||
|
||||
if (!ovl->manager || !ovl->manager->device)
|
||||
if (!ovl->manager)
|
||||
return 0;
|
||||
|
||||
dssdev = ovl->manager->device;
|
||||
|
||||
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
|
||||
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
|
||||
channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
|
@ -718,6 +725,7 @@ static int configure_overlay(enum omap_plane plane)
|
|||
u16 x, y, w, h;
|
||||
u32 paddr;
|
||||
int r;
|
||||
u16 orig_w, orig_h, orig_outw, orig_outh;
|
||||
|
||||
DSSDBGF("%d", plane);
|
||||
|
||||
|
|
@ -738,8 +746,16 @@ static int configure_overlay(enum omap_plane plane)
|
|||
outh = c->out_height == 0 ? c->height : c->out_height;
|
||||
paddr = c->paddr;
|
||||
|
||||
orig_w = w;
|
||||
orig_h = h;
|
||||
orig_outw = outw;
|
||||
orig_outh = outh;
|
||||
|
||||
if (c->manual_update && mc->do_manual_update) {
|
||||
unsigned bpp;
|
||||
unsigned scale_x_m = w, scale_x_d = outw;
|
||||
unsigned scale_y_m = h, scale_y_d = outh;
|
||||
|
||||
/* 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)) {
|
||||
|
|
@ -770,38 +786,47 @@ static int configure_overlay(enum omap_plane plane)
|
|||
BUG();
|
||||
}
|
||||
|
||||
if (dispc_is_overlay_scaled(c)) {
|
||||
/* If the overlay is scaled, the update area has
|
||||
* already been enlarged to cover the whole overlay. We
|
||||
* only need to adjust x/y here */
|
||||
x = c->pos_x - mc->x;
|
||||
y = c->pos_y - mc->y;
|
||||
if (mc->x > c->pos_x) {
|
||||
x = 0;
|
||||
outw -= (mc->x - c->pos_x);
|
||||
paddr += (mc->x - c->pos_x) *
|
||||
scale_x_m / scale_x_d * bpp / 8;
|
||||
} else {
|
||||
if (mc->x > c->pos_x) {
|
||||
x = 0;
|
||||
w -= (mc->x - c->pos_x);
|
||||
paddr += (mc->x - c->pos_x) * bpp / 8;
|
||||
} else {
|
||||
x = c->pos_x - mc->x;
|
||||
}
|
||||
x = c->pos_x - mc->x;
|
||||
}
|
||||
|
||||
if (mc->y > c->pos_y) {
|
||||
y = 0;
|
||||
h -= (mc->y - c->pos_y);
|
||||
paddr += (mc->y - c->pos_y) * c->screen_width *
|
||||
bpp / 8;
|
||||
} else {
|
||||
y = c->pos_y - mc->y;
|
||||
}
|
||||
if (mc->y > c->pos_y) {
|
||||
y = 0;
|
||||
outh -= (mc->y - c->pos_y);
|
||||
paddr += (mc->y - c->pos_y) *
|
||||
scale_y_m / scale_y_d *
|
||||
c->screen_width * bpp / 8;
|
||||
} else {
|
||||
y = c->pos_y - mc->y;
|
||||
}
|
||||
|
||||
if (mc->w < (x+w))
|
||||
w -= (x+w) - (mc->w);
|
||||
if (mc->w < (x + outw))
|
||||
outw -= (x + outw) - (mc->w);
|
||||
|
||||
if (mc->h < (y+h))
|
||||
h -= (y+h) - (mc->h);
|
||||
if (mc->h < (y + outh))
|
||||
outh -= (y + outh) - (mc->h);
|
||||
|
||||
outw = w;
|
||||
outh = h;
|
||||
w = w * outw / orig_outw;
|
||||
h = h * outh / orig_outh;
|
||||
|
||||
/* YUV mode overlay's input width has to be even and the
|
||||
* algorithm above may adjust the width to be odd.
|
||||
*
|
||||
* Here we adjust the width if needed, preferring to increase
|
||||
* the width if the original width was bigger.
|
||||
*/
|
||||
if ((w & 1) &&
|
||||
(c->color_mode == OMAP_DSS_COLOR_YUV2 ||
|
||||
c->color_mode == OMAP_DSS_COLOR_UYVY)) {
|
||||
if (orig_w > w)
|
||||
w += 1;
|
||||
else
|
||||
w -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -960,7 +985,7 @@ static void make_even(u16 *x, u16 *w)
|
|||
/* Configure dispc for partial update. Return possibly modified update
|
||||
* area */
|
||||
void dss_setup_partial_planes(struct omap_dss_device *dssdev,
|
||||
u16 *xi, u16 *yi, u16 *wi, u16 *hi)
|
||||
u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
|
||||
{
|
||||
struct overlay_cache_data *oc;
|
||||
struct manager_cache_data *mc;
|
||||
|
|
@ -969,6 +994,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
|
|||
int i;
|
||||
u16 x, y, w, h;
|
||||
unsigned long flags;
|
||||
bool area_changed;
|
||||
|
||||
x = *xi;
|
||||
y = *yi;
|
||||
|
|
@ -989,73 +1015,91 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
|
|||
|
||||
spin_lock_irqsave(&dss_cache.lock, flags);
|
||||
|
||||
/* We need to show the whole overlay if it is scaled. So look for
|
||||
* those, and make the update area larger if found.
|
||||
* Also mark the overlay cache dirty */
|
||||
for (i = 0; i < num_ovls; ++i) {
|
||||
unsigned x1, y1, x2, y2;
|
||||
unsigned outw, outh;
|
||||
/*
|
||||
* Execute the outer loop until the inner loop has completed
|
||||
* once without increasing the update area. This will ensure that
|
||||
* all scaled overlays end up completely within the update area.
|
||||
*/
|
||||
do {
|
||||
area_changed = false;
|
||||
|
||||
oc = &dss_cache.overlay_cache[i];
|
||||
/* We need to show the whole overlay if it is scaled. So look
|
||||
* for those, and make the update area larger if found.
|
||||
* Also mark the overlay cache dirty */
|
||||
for (i = 0; i < num_ovls; ++i) {
|
||||
unsigned x1, y1, x2, y2;
|
||||
unsigned outw, outh;
|
||||
|
||||
if (oc->channel != mgr->id)
|
||||
continue;
|
||||
oc = &dss_cache.overlay_cache[i];
|
||||
|
||||
oc->dirty = true;
|
||||
if (oc->channel != mgr->id)
|
||||
continue;
|
||||
|
||||
if (!oc->enabled)
|
||||
continue;
|
||||
oc->dirty = true;
|
||||
|
||||
if (!dispc_is_overlay_scaled(oc))
|
||||
continue;
|
||||
if (!enlarge_update_area)
|
||||
continue;
|
||||
|
||||
outw = oc->out_width == 0 ? oc->width : oc->out_width;
|
||||
outh = oc->out_height == 0 ? oc->height : oc->out_height;
|
||||
if (!oc->enabled)
|
||||
continue;
|
||||
|
||||
/* is the overlay outside the update region? */
|
||||
if (!rectangle_intersects(x, y, w, h,
|
||||
oc->pos_x, oc->pos_y,
|
||||
outw, outh))
|
||||
continue;
|
||||
if (!dispc_is_overlay_scaled(oc))
|
||||
continue;
|
||||
|
||||
/* if the overlay totally inside the update region? */
|
||||
if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
|
||||
x, y, w, h))
|
||||
continue;
|
||||
outw = oc->out_width == 0 ?
|
||||
oc->width : oc->out_width;
|
||||
outh = oc->out_height == 0 ?
|
||||
oc->height : oc->out_height;
|
||||
|
||||
if (x > oc->pos_x)
|
||||
x1 = oc->pos_x;
|
||||
else
|
||||
x1 = x;
|
||||
/* is the overlay outside the update region? */
|
||||
if (!rectangle_intersects(x, y, w, h,
|
||||
oc->pos_x, oc->pos_y,
|
||||
outw, outh))
|
||||
continue;
|
||||
|
||||
if (y > oc->pos_y)
|
||||
y1 = oc->pos_y;
|
||||
else
|
||||
y1 = y;
|
||||
/* if the overlay totally inside the update region? */
|
||||
if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
|
||||
x, y, w, h))
|
||||
continue;
|
||||
|
||||
if ((x + w) < (oc->pos_x + outw))
|
||||
x2 = oc->pos_x + outw;
|
||||
else
|
||||
x2 = x + w;
|
||||
if (x > oc->pos_x)
|
||||
x1 = oc->pos_x;
|
||||
else
|
||||
x1 = x;
|
||||
|
||||
if ((y + h) < (oc->pos_y + outh))
|
||||
y2 = oc->pos_y + outh;
|
||||
else
|
||||
y2 = y + h;
|
||||
if (y > oc->pos_y)
|
||||
y1 = oc->pos_y;
|
||||
else
|
||||
y1 = y;
|
||||
|
||||
x = x1;
|
||||
y = y1;
|
||||
w = x2 - x1;
|
||||
h = y2 - y1;
|
||||
if ((x + w) < (oc->pos_x + outw))
|
||||
x2 = oc->pos_x + outw;
|
||||
else
|
||||
x2 = x + w;
|
||||
|
||||
make_even(&x, &w);
|
||||
if ((y + h) < (oc->pos_y + outh))
|
||||
y2 = oc->pos_y + outh;
|
||||
else
|
||||
y2 = y + h;
|
||||
|
||||
DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
|
||||
x = x1;
|
||||
y = y1;
|
||||
w = x2 - x1;
|
||||
h = y2 - y1;
|
||||
|
||||
make_even(&x, &w);
|
||||
|
||||
DSSDBG("changing upd area due to ovl(%d) "
|
||||
"scaling %d,%d %dx%d\n",
|
||||
i, x, y, w, h);
|
||||
}
|
||||
|
||||
area_changed = true;
|
||||
}
|
||||
} while (area_changed);
|
||||
|
||||
mc = &dss_cache.manager_cache[mgr->id];
|
||||
mc->do_manual_update = true;
|
||||
mc->enlarge_update_area = enlarge_update_area;
|
||||
mc->x = x;
|
||||
mc->y = y;
|
||||
mc->w = w;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
|
|||
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
|
||||
if (strncmp(buf, mgr->name, len) == 0)
|
||||
if (sysfs_streq(buf, mgr->name))
|
||||
break;
|
||||
|
||||
mgr = NULL;
|
||||
|
|
|
|||
|
|
@ -886,7 +886,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
|||
return -EINVAL;
|
||||
|
||||
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h);
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h, true);
|
||||
dispc_set_lcd_size(*w, *h);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,12 +34,37 @@
|
|||
|
||||
#include "omapfb.h"
|
||||
|
||||
static u8 get_mem_idx(struct omapfb_info *ofbi)
|
||||
{
|
||||
if (ofbi->id == ofbi->region->id)
|
||||
return 0;
|
||||
|
||||
return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
|
||||
}
|
||||
|
||||
static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
|
||||
u8 mem_idx)
|
||||
{
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
|
||||
if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
|
||||
mem_idx &= OMAPFB_MEM_IDX_MASK;
|
||||
else
|
||||
mem_idx = ofbi->id;
|
||||
|
||||
if (mem_idx >= fbdev->num_fbs)
|
||||
return NULL;
|
||||
|
||||
return &fbdev->regions[mem_idx];
|
||||
}
|
||||
|
||||
static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_overlay *ovl;
|
||||
struct omap_overlay_info info;
|
||||
struct omap_overlay_info old_info;
|
||||
struct omapfb2_mem_region *old_rg, *new_rg;
|
||||
int r = 0;
|
||||
|
||||
DBG("omapfb_setup_plane\n");
|
||||
|
|
@ -52,36 +77,106 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
|||
/* XXX uses only the first overlay */
|
||||
ovl = ofbi->overlays[0];
|
||||
|
||||
if (pi->enabled && !ofbi->region.size) {
|
||||
old_rg = ofbi->region;
|
||||
new_rg = get_mem_region(ofbi, pi->mem_idx);
|
||||
if (!new_rg) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Take the locks in a specific order to keep lockdep happy */
|
||||
if (old_rg->id < new_rg->id) {
|
||||
omapfb_get_mem_region(old_rg);
|
||||
omapfb_get_mem_region(new_rg);
|
||||
} else if (new_rg->id < old_rg->id) {
|
||||
omapfb_get_mem_region(new_rg);
|
||||
omapfb_get_mem_region(old_rg);
|
||||
} else
|
||||
omapfb_get_mem_region(old_rg);
|
||||
|
||||
if (pi->enabled && !new_rg->size) {
|
||||
/*
|
||||
* This plane's memory was freed, can't enable it
|
||||
* until it's reallocated.
|
||||
*/
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
goto put_mem;
|
||||
}
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
ovl->get_overlay_info(ovl, &old_info);
|
||||
|
||||
info.pos_x = pi->pos_x;
|
||||
info.pos_y = pi->pos_y;
|
||||
info.out_width = pi->out_width;
|
||||
info.out_height = pi->out_height;
|
||||
info.enabled = pi->enabled;
|
||||
if (old_rg != new_rg) {
|
||||
ofbi->region = new_rg;
|
||||
set_fb_fix(fbi);
|
||||
}
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
goto out;
|
||||
if (pi->enabled) {
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
|
||||
pi->out_width, pi->out_height);
|
||||
if (r)
|
||||
goto out;
|
||||
goto undo;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
if (!info.enabled) {
|
||||
info.enabled = pi->enabled;
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
goto undo;
|
||||
}
|
||||
} else {
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.enabled = pi->enabled;
|
||||
info.pos_x = pi->pos_x;
|
||||
info.pos_y = pi->pos_y;
|
||||
info.out_width = pi->out_width;
|
||||
info.out_height = pi->out_height;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
goto undo;
|
||||
}
|
||||
|
||||
out:
|
||||
if (r)
|
||||
dev_err(fbdev->dev, "setup_plane failed\n");
|
||||
if (ovl->manager)
|
||||
ovl->manager->apply(ovl->manager);
|
||||
|
||||
/* Release the locks in a specific order to keep lockdep happy */
|
||||
if (old_rg->id > new_rg->id) {
|
||||
omapfb_put_mem_region(old_rg);
|
||||
omapfb_put_mem_region(new_rg);
|
||||
} else if (new_rg->id > old_rg->id) {
|
||||
omapfb_put_mem_region(new_rg);
|
||||
omapfb_put_mem_region(old_rg);
|
||||
} else
|
||||
omapfb_put_mem_region(old_rg);
|
||||
|
||||
return 0;
|
||||
|
||||
undo:
|
||||
if (old_rg != new_rg) {
|
||||
ofbi->region = old_rg;
|
||||
set_fb_fix(fbi);
|
||||
}
|
||||
|
||||
ovl->set_overlay_info(ovl, &old_info);
|
||||
put_mem:
|
||||
/* Release the locks in a specific order to keep lockdep happy */
|
||||
if (old_rg->id > new_rg->id) {
|
||||
omapfb_put_mem_region(old_rg);
|
||||
omapfb_put_mem_region(new_rg);
|
||||
} else if (new_rg->id > old_rg->id) {
|
||||
omapfb_put_mem_region(new_rg);
|
||||
omapfb_put_mem_region(old_rg);
|
||||
} else
|
||||
omapfb_put_mem_region(old_rg);
|
||||
out:
|
||||
dev_err(fbdev->dev, "setup_plane failed\n");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -92,8 +187,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
|||
if (ofbi->num_overlays != 1) {
|
||||
memset(pi, 0, sizeof(*pi));
|
||||
} else {
|
||||
struct omap_overlay_info *ovli;
|
||||
struct omap_overlay *ovl;
|
||||
struct omap_overlay_info *ovli;
|
||||
|
||||
ovl = ofbi->overlays[0];
|
||||
ovli = &ovl->info;
|
||||
|
|
@ -103,6 +198,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
|||
pi->enabled = ovli->enabled;
|
||||
pi->channel_out = 0; /* xxx */
|
||||
pi->mirror = 0;
|
||||
pi->mem_idx = get_mem_idx(ofbi);
|
||||
pi->out_width = ovli->out_width;
|
||||
pi->out_height = ovli->out_height;
|
||||
}
|
||||
|
|
@ -115,7 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
|||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omapfb2_mem_region *rg;
|
||||
int r, i;
|
||||
int r = 0, i;
|
||||
size_t size;
|
||||
|
||||
if (mi->type > OMAPFB_MEMTYPE_MAX)
|
||||
|
|
@ -123,22 +219,44 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
|||
|
||||
size = PAGE_ALIGN(mi->size);
|
||||
|
||||
rg = &ofbi->region;
|
||||
rg = ofbi->region;
|
||||
|
||||
for (i = 0; i < ofbi->num_overlays; i++) {
|
||||
if (ofbi->overlays[i]->info.enabled)
|
||||
return -EBUSY;
|
||||
down_write_nested(&rg->lock, rg->id);
|
||||
atomic_inc(&rg->lock_count);
|
||||
|
||||
if (atomic_read(&rg->map_count)) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
|
||||
int j;
|
||||
|
||||
if (ofbi2->region != rg)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < ofbi2->num_overlays; j++) {
|
||||
if (ofbi2->overlays[j]->info.enabled) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rg->size != size || rg->type != mi->type) {
|
||||
r = omapfb_realloc_fbmem(fbi, size, mi->type);
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "realloc fbmem failed\n");
|
||||
return r;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
atomic_dec(&rg->lock_count);
|
||||
up_write(&rg->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
||||
|
|
@ -146,12 +264,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
|||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_mem_region *rg;
|
||||
|
||||
rg = &ofbi->region;
|
||||
rg = omapfb_get_mem_region(ofbi->region);
|
||||
memset(mi, 0, sizeof(*mi));
|
||||
|
||||
mi->size = rg->size;
|
||||
mi->type = rg->type;
|
||||
|
||||
omapfb_put_mem_region(rg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -490,6 +610,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
struct omapfb_vram_info vram_info;
|
||||
struct omapfb_tearsync_info tearsync_info;
|
||||
struct omapfb_display_info display_info;
|
||||
u32 crt;
|
||||
} p;
|
||||
|
||||
int r = 0;
|
||||
|
|
@ -648,6 +769,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
r = -EFAULT;
|
||||
break;
|
||||
|
||||
case FBIO_WAITFORVSYNC:
|
||||
if (get_user(p.crt, (__u32 __user *)arg)) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (p.crt != 0) {
|
||||
r = -ENODEV;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case OMAPFB_WAITFORVSYNC:
|
||||
DBG("ioctl WAITFORVSYNC\n");
|
||||
if (!display) {
|
||||
|
|
@ -738,7 +870,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!display->driver->enable_te) {
|
||||
if (!display || !display->driver->enable_te) {
|
||||
r = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ static void fill_fb(struct fb_info *fbi)
|
|||
|
||||
static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
|
||||
{
|
||||
const struct vrfb *vrfb = &ofbi->region.vrfb;
|
||||
const struct vrfb *vrfb = &ofbi->region->vrfb;
|
||||
unsigned offset;
|
||||
|
||||
switch (rot) {
|
||||
|
|
@ -185,27 +185,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
|
|||
static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
|
||||
{
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
return ofbi->region.vrfb.paddr[rot]
|
||||
return ofbi->region->vrfb.paddr[rot]
|
||||
+ omapfb_get_vrfb_offset(ofbi, rot);
|
||||
} else {
|
||||
return ofbi->region.paddr;
|
||||
return ofbi->region->paddr;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
|
||||
{
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
|
||||
return ofbi->region.vrfb.paddr[0];
|
||||
return ofbi->region->vrfb.paddr[0];
|
||||
else
|
||||
return ofbi->region.paddr;
|
||||
return ofbi->region->paddr;
|
||||
}
|
||||
|
||||
static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
|
||||
{
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
|
||||
return ofbi->region.vrfb.vaddr[0];
|
||||
return ofbi->region->vrfb.vaddr[0];
|
||||
else
|
||||
return ofbi->region.vaddr;
|
||||
return ofbi->region->vaddr;
|
||||
}
|
||||
|
||||
static struct omapfb_colormode omapfb_colormodes[] = {
|
||||
|
|
@ -450,7 +450,7 @@ static int check_vrfb_fb_size(unsigned long region_size,
|
|||
static int check_fb_size(const struct omapfb_info *ofbi,
|
||||
struct fb_var_screeninfo *var)
|
||||
{
|
||||
unsigned long max_frame_size = ofbi->region.size;
|
||||
unsigned long max_frame_size = ofbi->region->size;
|
||||
int bytespp = var->bits_per_pixel >> 3;
|
||||
unsigned long line_size = var->xres_virtual * bytespp;
|
||||
|
||||
|
|
@ -497,7 +497,7 @@ static int check_fb_size(const struct omapfb_info *ofbi,
|
|||
static int setup_vrfb_rotation(struct fb_info *fbi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_mem_region *rg = &ofbi->region;
|
||||
struct omapfb2_mem_region *rg = ofbi->region;
|
||||
struct vrfb *vrfb = &rg->vrfb;
|
||||
struct fb_var_screeninfo *var = &fbi->var;
|
||||
struct fb_fix_screeninfo *fix = &fbi->fix;
|
||||
|
|
@ -558,9 +558,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
|
|||
return r;
|
||||
|
||||
/* used by open/write in fbmem.c */
|
||||
fbi->screen_base = ofbi->region.vrfb.vaddr[0];
|
||||
fbi->screen_base = ofbi->region->vrfb.vaddr[0];
|
||||
|
||||
fix->smem_start = ofbi->region.vrfb.paddr[0];
|
||||
fix->smem_start = ofbi->region->vrfb.paddr[0];
|
||||
|
||||
switch (var->nonstd) {
|
||||
case OMAPFB_COLOR_YUV422:
|
||||
|
|
@ -599,7 +599,7 @@ void set_fb_fix(struct fb_info *fbi)
|
|||
struct fb_fix_screeninfo *fix = &fbi->fix;
|
||||
struct fb_var_screeninfo *var = &fbi->var;
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_mem_region *rg = &ofbi->region;
|
||||
struct omapfb2_mem_region *rg = ofbi->region;
|
||||
|
||||
DBG("set_fb_fix\n");
|
||||
|
||||
|
|
@ -668,8 +668,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
|
|||
|
||||
DBG("check_fb_var %d\n", ofbi->id);
|
||||
|
||||
if (ofbi->region.size == 0)
|
||||
return 0;
|
||||
WARN_ON(!atomic_read(&ofbi->region->lock_count));
|
||||
|
||||
r = fb_mode_to_dss_mode(var, &mode);
|
||||
if (r) {
|
||||
|
|
@ -684,13 +683,14 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
|
|||
}
|
||||
}
|
||||
|
||||
if (var->rotate < 0 || var->rotate > 3)
|
||||
if (var->rotate > 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (check_fb_res_bounds(var))
|
||||
return -EINVAL;
|
||||
|
||||
if (check_fb_size(ofbi, var))
|
||||
/* When no memory is allocated ignore the size check */
|
||||
if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
|
||||
return -EINVAL;
|
||||
|
||||
if (var->xres + var->xoffset > var->xres_virtual)
|
||||
|
|
@ -822,9 +822,43 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
|
|||
return offset;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u32 data_start_p;
|
||||
void __iomem *data_start_v;
|
||||
int offset;
|
||||
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
|
||||
data_start_v = NULL;
|
||||
} 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);
|
||||
else
|
||||
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);
|
||||
|
||||
*paddr = data_start_p;
|
||||
*vaddr = data_start_v;
|
||||
}
|
||||
|
||||
/* setup overlay according to the fb */
|
||||
static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
|
||||
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
|
||||
u16 posx, u16 posy, u16 outw, u16 outh)
|
||||
{
|
||||
int r = 0;
|
||||
|
|
@ -832,9 +866,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
|
|||
struct fb_var_screeninfo *var = &fbi->var;
|
||||
struct fb_fix_screeninfo *fix = &fbi->fix;
|
||||
enum omap_color_mode mode = 0;
|
||||
int offset;
|
||||
u32 data_start_p;
|
||||
void __iomem *data_start_v;
|
||||
u32 data_start_p = 0;
|
||||
void __iomem *data_start_v = NULL;
|
||||
struct omap_overlay_info info;
|
||||
int xres, yres;
|
||||
int screen_width;
|
||||
|
|
@ -842,6 +875,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
|
|||
int rotation = var->rotate;
|
||||
int i;
|
||||
|
||||
WARN_ON(!atomic_read(&ofbi->region->lock_count));
|
||||
|
||||
for (i = 0; i < ofbi->num_overlays; i++) {
|
||||
if (ovl != ofbi->overlays[i])
|
||||
continue;
|
||||
|
|
@ -861,28 +896,9 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
|
|||
yres = var->yres;
|
||||
}
|
||||
|
||||
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
|
||||
data_start_v = NULL;
|
||||
} 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);
|
||||
else
|
||||
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);
|
||||
if (ofbi->region->size)
|
||||
omapfb_calc_addr(ofbi, var, fix, rotation,
|
||||
&data_start_p, &data_start_v);
|
||||
|
||||
r = fb_mode_to_dss_mode(var, &mode);
|
||||
if (r) {
|
||||
|
|
@ -954,12 +970,14 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
|
|||
fill_fb(fbi);
|
||||
#endif
|
||||
|
||||
WARN_ON(!atomic_read(&ofbi->region->lock_count));
|
||||
|
||||
for (i = 0; i < ofbi->num_overlays; i++) {
|
||||
ovl = ofbi->overlays[i];
|
||||
|
||||
DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
|
||||
|
||||
if (ofbi->region.size == 0) {
|
||||
if (ofbi->region->size == 0) {
|
||||
/* the fb is not available. disable the overlay */
|
||||
omapfb_overlay_enable(ovl, 0);
|
||||
if (!init && ovl->manager)
|
||||
|
|
@ -1007,36 +1025,48 @@ err:
|
|||
* DO NOT MODIFY PAR */
|
||||
static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
int r;
|
||||
|
||||
DBG("check_var(%d)\n", FB2OFB(fbi)->id);
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
r = check_fb_var(fbi, var);
|
||||
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* set the video mode according to info->var */
|
||||
static int omapfb_set_par(struct fb_info *fbi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
int r;
|
||||
|
||||
DBG("set_par(%d)\n", FB2OFB(fbi)->id);
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
set_fb_fix(fbi);
|
||||
|
||||
r = setup_vrfb_rotation(fbi);
|
||||
if (r)
|
||||
return r;
|
||||
goto out;
|
||||
|
||||
r = omapfb_apply_changes(fbi, 0);
|
||||
|
||||
out:
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omapfb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *fbi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct fb_var_screeninfo new_var;
|
||||
int r;
|
||||
|
||||
|
|
@ -1052,23 +1082,31 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
|
|||
|
||||
fbi->var = new_var;
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
r = omapfb_apply_changes(fbi, 0);
|
||||
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void mmap_user_open(struct vm_area_struct *vma)
|
||||
{
|
||||
struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
|
||||
struct omapfb2_mem_region *rg = vma->vm_private_data;
|
||||
|
||||
atomic_inc(&ofbi->map_count);
|
||||
omapfb_get_mem_region(rg);
|
||||
atomic_inc(&rg->map_count);
|
||||
omapfb_put_mem_region(rg);
|
||||
}
|
||||
|
||||
static void mmap_user_close(struct vm_area_struct *vma)
|
||||
{
|
||||
struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
|
||||
struct omapfb2_mem_region *rg = vma->vm_private_data;
|
||||
|
||||
atomic_dec(&ofbi->map_count);
|
||||
omapfb_get_mem_region(rg);
|
||||
atomic_dec(&rg->map_count);
|
||||
omapfb_put_mem_region(rg);
|
||||
}
|
||||
|
||||
static struct vm_operations_struct mmap_user_ops = {
|
||||
|
|
@ -1080,9 +1118,11 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
|
|||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct fb_fix_screeninfo *fix = &fbi->fix;
|
||||
struct omapfb2_mem_region *rg;
|
||||
unsigned long off;
|
||||
unsigned long start;
|
||||
u32 len;
|
||||
int r = -EINVAL;
|
||||
|
||||
if (vma->vm_end - vma->vm_start == 0)
|
||||
return 0;
|
||||
|
|
@ -1090,12 +1130,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
|
|||
return -EINVAL;
|
||||
off = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
rg = omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
start = omapfb_get_region_paddr(ofbi);
|
||||
len = fix->smem_len;
|
||||
if (off >= len)
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
if ((vma->vm_end - vma->vm_start + off) > len)
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
|
||||
off += start;
|
||||
|
||||
|
|
@ -1105,13 +1147,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
|
|||
vma->vm_flags |= VM_IO | VM_RESERVED;
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
vma->vm_ops = &mmap_user_ops;
|
||||
vma->vm_private_data = ofbi;
|
||||
vma->vm_private_data = rg;
|
||||
if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot)) {
|
||||
r = -EAGAIN;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* vm_ops.open won't be called for mmap itself. */
|
||||
atomic_inc(&ofbi->map_count);
|
||||
atomic_inc(&rg->map_count);
|
||||
|
||||
omapfb_put_mem_region(rg);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Store a single color palette entry into a pseudo palette or the hardware
|
||||
|
|
@ -1154,11 +1208,6 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
|
|||
if (r != 0)
|
||||
break;
|
||||
|
||||
if (regno < 0) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (regno < 16) {
|
||||
u16 pal;
|
||||
pal = ((red >> (16 - var->red.length)) <<
|
||||
|
|
@ -1217,6 +1266,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
|
|||
int do_update = 0;
|
||||
int r = 0;
|
||||
|
||||
if (!display)
|
||||
return -EINVAL;
|
||||
|
||||
omapfb_lock(fbdev);
|
||||
|
||||
switch (blank) {
|
||||
|
|
@ -1300,7 +1352,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
|
|||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omapfb2_mem_region *rg;
|
||||
|
||||
rg = &ofbi->region;
|
||||
rg = ofbi->region;
|
||||
|
||||
WARN_ON(atomic_read(&rg->map_count));
|
||||
|
||||
if (rg->paddr)
|
||||
if (omap_vram_free(rg->paddr, rg->size))
|
||||
|
|
@ -1355,8 +1409,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
|
|||
void __iomem *vaddr;
|
||||
int r;
|
||||
|
||||
rg = &ofbi->region;
|
||||
memset(rg, 0, sizeof(*rg));
|
||||
rg = ofbi->region;
|
||||
|
||||
rg->paddr = 0;
|
||||
rg->vaddr = NULL;
|
||||
memset(&rg->vrfb, 0, sizeof rg->vrfb);
|
||||
rg->size = 0;
|
||||
rg->type = 0;
|
||||
rg->alloc = false;
|
||||
rg->map = false;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
|
|
@ -1609,7 +1670,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
|
|||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
|
||||
struct omapfb2_mem_region *rg;
|
||||
rg = &ofbi->region;
|
||||
rg = ofbi->region;
|
||||
|
||||
DBG("region%d phys %08x virt %p size=%lu\n",
|
||||
i,
|
||||
|
|
@ -1626,7 +1687,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
|||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_dss_device *display = fb2display(fbi);
|
||||
struct omapfb2_mem_region *rg = &ofbi->region;
|
||||
struct omapfb2_mem_region *rg = ofbi->region;
|
||||
unsigned long old_size = rg->size;
|
||||
unsigned long old_paddr = rg->paddr;
|
||||
int old_type = rg->type;
|
||||
|
|
@ -1709,7 +1770,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
|
|||
fbi->flags = FBINFO_FLAG_DEFAULT;
|
||||
fbi->pseudo_palette = fbdev->pseudo_palette;
|
||||
|
||||
if (ofbi->region.size == 0) {
|
||||
if (ofbi->region->size == 0) {
|
||||
clear_fb_info(fbi);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1871,6 +1932,10 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
|||
ofbi->fbdev = fbdev;
|
||||
ofbi->id = i;
|
||||
|
||||
ofbi->region = &fbdev->regions[i];
|
||||
ofbi->region->id = i;
|
||||
init_rwsem(&ofbi->region->lock);
|
||||
|
||||
/* assign these early, so that fb alloc can use them */
|
||||
ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
|
||||
OMAP_DSS_ROT_DMA;
|
||||
|
|
@ -1900,7 +1965,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
|||
|
||||
/* setup fb_infos */
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
r = omapfb_fb_init(fbdev, fbdev->fbs[i]);
|
||||
struct fb_info *fbi = fbdev->fbs[i];
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
r = omapfb_fb_init(fbdev, fbi);
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "failed to setup fb_info\n");
|
||||
return r;
|
||||
|
|
@ -1921,20 +1992,19 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
|||
DBG("framebuffers registered\n");
|
||||
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
r = omapfb_apply_changes(fbdev->fbs[i], 1);
|
||||
struct fb_info *fbi = fbdev->fbs[i];
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
r = omapfb_apply_changes(fbi, 1);
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "failed to change mode\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("create sysfs for fbs\n");
|
||||
r = omapfb_create_sysfs(fbdev);
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "failed to create sysfs entries\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Enable fb0 */
|
||||
if (fbdev->num_fbs > 0) {
|
||||
struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
|
||||
|
|
@ -1968,11 +2038,11 @@ static int omapfb_mode_to_timings(const char *mode_str,
|
|||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
if (strcmp(mode_str, "pal") == 0) {
|
||||
*timings = omap_dss_pal_timings;
|
||||
*bpp = 0;
|
||||
*bpp = 24;
|
||||
return 0;
|
||||
} else if (strcmp(mode_str, "ntsc") == 0) {
|
||||
*timings = omap_dss_ntsc_timings;
|
||||
*bpp = 0;
|
||||
*bpp = 24;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -2220,6 +2290,13 @@ static int omapfb_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
DBG("create sysfs for fbs\n");
|
||||
r = omapfb_create_sysfs(fbdev);
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "failed to create sysfs entries\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev,
|
|||
{
|
||||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_mem_region *rg;
|
||||
enum omap_dss_rotation_type rot_type;
|
||||
int r;
|
||||
|
||||
|
|
@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev,
|
|||
if (rot_type == ofbi->rotation_type)
|
||||
goto out;
|
||||
|
||||
if (ofbi->region.size) {
|
||||
rg = omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
if (rg->size) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
goto put_region;
|
||||
}
|
||||
|
||||
ofbi->rotation_type = rot_type;
|
||||
|
|
@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev,
|
|||
* Since the VRAM for this FB is not allocated at the moment we don't
|
||||
* need to do any further parameter checking at this point.
|
||||
*/
|
||||
put_region:
|
||||
omapfb_put_mem_region(rg);
|
||||
out:
|
||||
unlock_fb_info(fbi);
|
||||
|
||||
|
|
@ -97,7 +102,7 @@ static ssize_t store_mirror(struct device *dev,
|
|||
{
|
||||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
bool mirror;
|
||||
unsigned long mirror;
|
||||
int r;
|
||||
struct fb_var_screeninfo new_var;
|
||||
|
||||
|
|
@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev,
|
|||
|
||||
ofbi->mirror = mirror;
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
memcpy(&new_var, &fbi->var, sizeof(new_var));
|
||||
r = check_fb_var(fbi, &new_var);
|
||||
if (r)
|
||||
|
|
@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev,
|
|||
|
||||
r = count;
|
||||
out:
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
unlock_fb_info(fbi);
|
||||
|
||||
return r;
|
||||
|
|
@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
DBG("detaching %d\n", ofbi->overlays[i]->id);
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
omapfb_overlay_enable(ovl, 0);
|
||||
|
||||
if (ovl->manager)
|
||||
ovl->manager->apply(ovl->manager);
|
||||
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
for (t = i + 1; t < ofbi->num_overlays; t++) {
|
||||
ofbi->rotation[t-1] = ofbi->rotation[t];
|
||||
ofbi->overlays[t-1] = ofbi->overlays[t];
|
||||
|
|
@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
|
|||
}
|
||||
|
||||
if (added) {
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
r = omapfb_apply_changes(fbi, 0);
|
||||
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev,
|
|||
for (i = 0; i < num_ovls; ++i)
|
||||
ofbi->rotation[i] = rotation[i];
|
||||
|
||||
omapfb_get_mem_region(ofbi->region);
|
||||
|
||||
r = omapfb_apply_changes(fbi, 0);
|
||||
|
||||
omapfb_put_mem_region(ofbi->region);
|
||||
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
|
|
@ -408,7 +431,7 @@ static ssize_t show_size(struct device *dev,
|
|||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
|
||||
return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
|
||||
}
|
||||
|
||||
static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
||||
|
|
@ -416,6 +439,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
|||
{
|
||||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omapfb2_mem_region *rg;
|
||||
unsigned long size;
|
||||
int r;
|
||||
int i;
|
||||
|
|
@ -425,15 +450,33 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
|||
if (!lock_fb_info(fbi))
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ofbi->num_overlays; i++) {
|
||||
if (ofbi->overlays[i]->info.enabled) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
rg = ofbi->region;
|
||||
|
||||
down_write_nested(&rg->lock, rg->id);
|
||||
atomic_inc(&rg->lock_count);
|
||||
|
||||
if (atomic_read(&rg->map_count)) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
|
||||
int j;
|
||||
|
||||
if (ofbi2->region != rg)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < ofbi2->num_overlays; j++) {
|
||||
if (ofbi2->overlays[j]->info.enabled) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (size != ofbi->region.size) {
|
||||
r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
|
||||
if (size != ofbi->region->size) {
|
||||
r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
|
||||
if (r) {
|
||||
dev_err(dev, "realloc fbmem failed\n");
|
||||
goto out;
|
||||
|
|
@ -442,6 +485,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
r = count;
|
||||
out:
|
||||
atomic_dec(&rg->lock_count);
|
||||
up_write(&rg->lock);
|
||||
|
||||
unlock_fb_info(fbi);
|
||||
|
||||
return r;
|
||||
|
|
@ -453,7 +499,7 @@ static ssize_t show_phys(struct device *dev,
|
|||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
|
||||
return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
|
||||
}
|
||||
|
||||
static ssize_t show_virt(struct device *dev,
|
||||
|
|
@ -462,7 +508,7 @@ static ssize_t show_virt(struct device *dev,
|
|||
struct fb_info *fbi = dev_get_drvdata(dev);
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
|
||||
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
|
||||
}
|
||||
|
||||
static struct device_attribute omapfb_attrs[] = {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#define DEBUG
|
||||
#endif
|
||||
|
||||
#include <linux/rwsem.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
@ -44,6 +46,7 @@ extern unsigned int omapfb_debug;
|
|||
#define OMAPFB_MAX_OVL_PER_FB 3
|
||||
|
||||
struct omapfb2_mem_region {
|
||||
int id;
|
||||
u32 paddr;
|
||||
void __iomem *vaddr;
|
||||
struct vrfb vrfb;
|
||||
|
|
@ -51,13 +54,15 @@ struct omapfb2_mem_region {
|
|||
u8 type; /* OMAPFB_PLANE_MEM_* */
|
||||
bool alloc; /* allocated by the driver */
|
||||
bool map; /* kernel mapped by the driver */
|
||||
atomic_t map_count;
|
||||
struct rw_semaphore lock;
|
||||
atomic_t lock_count;
|
||||
};
|
||||
|
||||
/* appended to fb_info */
|
||||
struct omapfb_info {
|
||||
int id;
|
||||
struct omapfb2_mem_region region;
|
||||
atomic_t map_count;
|
||||
struct omapfb2_mem_region *region;
|
||||
int num_overlays;
|
||||
struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
|
||||
struct omapfb2_device *fbdev;
|
||||
|
|
@ -76,6 +81,7 @@ struct omapfb2_device {
|
|||
|
||||
unsigned num_fbs;
|
||||
struct fb_info *fbs[10];
|
||||
struct omapfb2_mem_region regions[10];
|
||||
|
||||
unsigned num_displays;
|
||||
struct omap_dss_device *displays[10];
|
||||
|
|
@ -117,6 +123,9 @@ int omapfb_update_window(struct fb_info *fbi,
|
|||
int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
|
||||
struct fb_var_screeninfo *var);
|
||||
|
||||
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
|
||||
u16 posx, u16 posy, u16 outw, u16 outh);
|
||||
|
||||
/* find the display connected to this fb, if any */
|
||||
static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
|
||||
{
|
||||
|
|
@ -148,8 +157,24 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
|
|||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
if (info.enabled == enable)
|
||||
return 0;
|
||||
info.enabled = enable;
|
||||
return ovl->set_overlay_info(ovl, &info);
|
||||
}
|
||||
|
||||
static inline struct omapfb2_mem_region *
|
||||
omapfb_get_mem_region(struct omapfb2_mem_region *rg)
|
||||
{
|
||||
down_read_nested(&rg->lock, rg->id);
|
||||
atomic_inc(&rg->lock_count);
|
||||
return rg;
|
||||
}
|
||||
|
||||
static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
|
||||
{
|
||||
atomic_dec(&rg->lock_count);
|
||||
up_read(&rg->lock);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
|
|||
info->fix.accel = FB_ACCEL_SUN_CGTHREE;
|
||||
}
|
||||
|
||||
static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
|
||||
static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
struct fb_info *info;
|
||||
|
|
@ -326,7 +326,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit p9100_remove(struct of_device *op)
|
||||
static int __devexit p9100_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct p9100_par *par = info->par;
|
||||
|
|
@ -367,12 +367,12 @@ static int __init p9100_init(void)
|
|||
if (fb_get_options("p9100fb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&p9100_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&p9100_driver);
|
||||
}
|
||||
|
||||
static void __exit p9100_exit(void)
|
||||
{
|
||||
of_unregister_driver(&p9100_driver);
|
||||
of_unregister_platform_driver(&p9100_driver);
|
||||
}
|
||||
|
||||
module_init(p9100_init);
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ static int __init platinumfb_setup(char *options)
|
|||
#define invalidate_cache(addr)
|
||||
#endif
|
||||
|
||||
static int __devinit platinumfb_probe(struct of_device* odev,
|
||||
static int __devinit platinumfb_probe(struct platform_device* odev,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = odev->dev.of_node;
|
||||
|
|
@ -646,7 +646,7 @@ static int __devinit platinumfb_probe(struct of_device* odev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int __devexit platinumfb_remove(struct of_device* odev)
|
||||
static int __devexit platinumfb_remove(struct platform_device* odev)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&odev->dev);
|
||||
struct fb_info_platinum *pinfo = info->par;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
505
drivers/video/sh_mipi_dsi.c
Normal file
505
drivers/video/sh_mipi_dsi.c
Normal file
|
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* Renesas SH-mobile MIPI DSI support
|
||||
*
|
||||
* Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
#include <video/sh_mipi_dsi.h>
|
||||
#include <video/sh_mobile_lcdc.h>
|
||||
|
||||
#define CMTSRTCTR 0x80d0
|
||||
#define CMTSRTREQ 0x8070
|
||||
|
||||
#define DSIINTE 0x0060
|
||||
|
||||
/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
|
||||
#define MAX_SH_MIPI_DSI 2
|
||||
|
||||
struct sh_mipi {
|
||||
void __iomem *base;
|
||||
struct clk *dsit_clk;
|
||||
struct clk *dsip_clk;
|
||||
};
|
||||
|
||||
static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
|
||||
|
||||
/* Protect the above array */
|
||||
static DEFINE_MUTEX(array_lock);
|
||||
|
||||
static struct sh_mipi *sh_mipi_by_handle(int handle)
|
||||
{
|
||||
if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
|
||||
return NULL;
|
||||
|
||||
return mipi_dsi[handle];
|
||||
}
|
||||
|
||||
static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
|
||||
u8 cmd, u8 param)
|
||||
{
|
||||
u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
|
||||
int cnt = 100;
|
||||
|
||||
/* transmit a short packet to LCD panel */
|
||||
iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */
|
||||
iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */
|
||||
|
||||
while ((ioread32(mipi->base + 0x8070) & 1) && --cnt)
|
||||
udelay(1);
|
||||
|
||||
return cnt ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
|
||||
-EINVAL : (c) - 1)
|
||||
|
||||
static int sh_mipi_dcs(int handle, u8 cmd)
|
||||
{
|
||||
struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
|
||||
if (!mipi)
|
||||
return -ENODEV;
|
||||
return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
|
||||
}
|
||||
|
||||
static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
|
||||
{
|
||||
struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
|
||||
if (!mipi)
|
||||
return -ENODEV;
|
||||
return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
|
||||
param);
|
||||
}
|
||||
|
||||
static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
|
||||
{
|
||||
/*
|
||||
* enable LCDC data tx, transition to LPS after completion of each HS
|
||||
* packet
|
||||
*/
|
||||
iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */
|
||||
}
|
||||
|
||||
static void sh_mipi_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_mipi *mipi = platform_get_drvdata(pdev);
|
||||
|
||||
sh_mipi_dsi_enable(mipi, false);
|
||||
}
|
||||
|
||||
static void mipi_display_on(void *arg, struct fb_info *info)
|
||||
{
|
||||
struct sh_mipi *mipi = arg;
|
||||
|
||||
sh_mipi_dsi_enable(mipi, true);
|
||||
}
|
||||
|
||||
static void mipi_display_off(void *arg)
|
||||
{
|
||||
struct sh_mipi *mipi = arg;
|
||||
|
||||
sh_mipi_dsi_enable(mipi, false);
|
||||
}
|
||||
|
||||
static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
||||
struct sh_mipi_dsi_info *pdata)
|
||||
{
|
||||
void __iomem *base = mipi->base;
|
||||
struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
|
||||
u32 pctype, datatype, pixfmt;
|
||||
u32 linelength;
|
||||
bool yuv;
|
||||
|
||||
/* Select data format */
|
||||
switch (pdata->data_format) {
|
||||
case MIPI_RGB888:
|
||||
pctype = 0;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_cfg.xres * 3;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_RGB565:
|
||||
pctype = 1;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_cfg.xres * 2;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_RGB666_LP:
|
||||
pctype = 2;
|
||||
datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_cfg.xres * 3;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_RGB666:
|
||||
pctype = 3;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
|
||||
linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_BGR888:
|
||||
pctype = 8;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_cfg.xres * 3;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_BGR565:
|
||||
pctype = 9;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_cfg.xres * 2;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_BGR666_LP:
|
||||
pctype = 0xa;
|
||||
datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
|
||||
linelength = ch->lcd_cfg.xres * 3;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_BGR666:
|
||||
pctype = 0xb;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
|
||||
linelength = (ch->lcd_cfg.xres * 18 + 7) / 8;
|
||||
yuv = false;
|
||||
break;
|
||||
case MIPI_YUYV:
|
||||
pctype = 4;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_cfg.xres * 2;
|
||||
yuv = true;
|
||||
break;
|
||||
case MIPI_UYVY:
|
||||
pctype = 5;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
|
||||
linelength = ch->lcd_cfg.xres * 2;
|
||||
yuv = true;
|
||||
break;
|
||||
case MIPI_YUV420_L:
|
||||
pctype = 6;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
|
||||
linelength = (ch->lcd_cfg.xres * 12 + 7) / 8;
|
||||
yuv = true;
|
||||
break;
|
||||
case MIPI_YUV420:
|
||||
pctype = 7;
|
||||
datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
|
||||
pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
|
||||
/* Length of U/V line */
|
||||
linelength = (ch->lcd_cfg.xres + 1) / 2;
|
||||
yuv = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((yuv && ch->interface_type != YUV422) ||
|
||||
(!yuv && ch->interface_type != RGB24))
|
||||
return -EINVAL;
|
||||
|
||||
/* reset DSI link */
|
||||
iowrite32(0x00000001, base); /* SYSCTRL */
|
||||
/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
|
||||
udelay(50);
|
||||
iowrite32(0x00000000, base); /* SYSCTRL */
|
||||
|
||||
/* setup DSI link */
|
||||
|
||||
/*
|
||||
* Default = ULPS enable |
|
||||
* Contention detection enabled |
|
||||
* EoT packet transmission enable |
|
||||
* CRC check enable |
|
||||
* ECC check enable
|
||||
* additionally enable first two lanes
|
||||
*/
|
||||
iowrite32(0x00003703, base + 0x04); /* SYSCONF */
|
||||
/*
|
||||
* T_wakeup = 0x7000
|
||||
* T_hs-trail = 3
|
||||
* T_hs-prepare = 3
|
||||
* T_clk-trail = 3
|
||||
* T_clk-prepare = 2
|
||||
*/
|
||||
iowrite32(0x70003332, base + 0x08); /* TIMSET */
|
||||
/* no responses requested */
|
||||
iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */
|
||||
/* request response to packets of type 0x28 */
|
||||
iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */
|
||||
/* High-speed transmission timeout, default 0xffffffff */
|
||||
iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */
|
||||
/* LP reception timeout, default 0xffffffff */
|
||||
iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */
|
||||
/* Turn-around timeout, default 0xffffffff */
|
||||
iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */
|
||||
/* Peripheral reset timeout, default 0xffffffff */
|
||||
iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */
|
||||
/* Enable timeout counters */
|
||||
iowrite32(0x00000f00, base + 0x30); /* DSICTRL */
|
||||
/* Interrupts not used, disable all */
|
||||
iowrite32(0, base + DSIINTE);
|
||||
/* DSI-Tx bias on */
|
||||
iowrite32(0x00000001, base + 0x70); /* PHYCTRL */
|
||||
udelay(200);
|
||||
/* Deassert resets, power on, set multiplier */
|
||||
iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */
|
||||
|
||||
/* setup l-bridge */
|
||||
|
||||
/*
|
||||
* Enable transmission of all packets,
|
||||
* transmit LPS after each HS packet completion
|
||||
*/
|
||||
iowrite32(0x00000006, base + 0x8000); /* DTCTR */
|
||||
/* VSYNC width = 2 (<< 17) */
|
||||
iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */
|
||||
/*
|
||||
* Non-burst mode with sync pulses: VSE and HSE are output,
|
||||
* HSA period allowed, no commands in LP
|
||||
*/
|
||||
iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */
|
||||
/*
|
||||
* 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
|
||||
* sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default
|
||||
* (unused, since VMCTR2[HSABM] = 0)
|
||||
*/
|
||||
iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */
|
||||
|
||||
msleep(5);
|
||||
|
||||
/* setup LCD panel */
|
||||
|
||||
/* cf. drivers/video/omap/lcd_mipid.c */
|
||||
sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
|
||||
msleep(120);
|
||||
/*
|
||||
* [7] - Page Address Mode
|
||||
* [6] - Column Address Mode
|
||||
* [5] - Page / Column Address Mode
|
||||
* [4] - Display Device Line Refresh Order
|
||||
* [3] - RGB/BGR Order
|
||||
* [2] - Display Data Latch Data Order
|
||||
* [1] - Flip Horizontal
|
||||
* [0] - Flip Vertical
|
||||
*/
|
||||
sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
|
||||
/* cf. set_data_lines() */
|
||||
sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
|
||||
pixfmt << 4);
|
||||
sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init sh_mipi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_mipi *mipi;
|
||||
struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
unsigned long rate, f_current;
|
||||
int idx = pdev->id, ret;
|
||||
char dsip_clk[] = "dsi.p_clk";
|
||||
|
||||
if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&array_lock);
|
||||
if (idx < 0)
|
||||
for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
|
||||
;
|
||||
|
||||
if (idx == ARRAY_SIZE(mipi_dsi)) {
|
||||
ret = -EBUSY;
|
||||
goto efindslot;
|
||||
}
|
||||
|
||||
mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
|
||||
if (!mipi) {
|
||||
ret = -ENOMEM;
|
||||
goto ealloc;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
|
||||
dev_err(&pdev->dev, "MIPI register region already claimed\n");
|
||||
ret = -EBUSY;
|
||||
goto ereqreg;
|
||||
}
|
||||
|
||||
mipi->base = ioremap(res->start, resource_size(res));
|
||||
if (!mipi->base) {
|
||||
ret = -ENOMEM;
|
||||
goto emap;
|
||||
}
|
||||
|
||||
mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
|
||||
if (IS_ERR(mipi->dsit_clk)) {
|
||||
ret = PTR_ERR(mipi->dsit_clk);
|
||||
goto eclktget;
|
||||
}
|
||||
|
||||
f_current = clk_get_rate(mipi->dsit_clk);
|
||||
/* 80MHz required by the datasheet */
|
||||
rate = clk_round_rate(mipi->dsit_clk, 80000000);
|
||||
if (rate > 0 && rate != f_current)
|
||||
ret = clk_set_rate(mipi->dsit_clk, rate);
|
||||
else
|
||||
ret = rate;
|
||||
if (ret < 0)
|
||||
goto esettrate;
|
||||
|
||||
dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
|
||||
|
||||
sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
|
||||
mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
|
||||
if (IS_ERR(mipi->dsip_clk)) {
|
||||
ret = PTR_ERR(mipi->dsip_clk);
|
||||
goto eclkpget;
|
||||
}
|
||||
|
||||
f_current = clk_get_rate(mipi->dsip_clk);
|
||||
/* Between 10 and 50MHz */
|
||||
rate = clk_round_rate(mipi->dsip_clk, 24000000);
|
||||
if (rate > 0 && rate != f_current)
|
||||
ret = clk_set_rate(mipi->dsip_clk, rate);
|
||||
else
|
||||
ret = rate;
|
||||
if (ret < 0)
|
||||
goto esetprate;
|
||||
|
||||
dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
|
||||
|
||||
msleep(10);
|
||||
|
||||
ret = clk_enable(mipi->dsit_clk);
|
||||
if (ret < 0)
|
||||
goto eclkton;
|
||||
|
||||
ret = clk_enable(mipi->dsip_clk);
|
||||
if (ret < 0)
|
||||
goto eclkpon;
|
||||
|
||||
mipi_dsi[idx] = mipi;
|
||||
|
||||
ret = sh_mipi_setup(mipi, pdata);
|
||||
if (ret < 0)
|
||||
goto emipisetup;
|
||||
|
||||
mutex_unlock(&array_lock);
|
||||
platform_set_drvdata(pdev, mipi);
|
||||
|
||||
/* Set up LCDC callbacks */
|
||||
pdata->lcd_chan->board_cfg.board_data = mipi;
|
||||
pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
|
||||
pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
|
||||
|
||||
return 0;
|
||||
|
||||
emipisetup:
|
||||
mipi_dsi[idx] = NULL;
|
||||
clk_disable(mipi->dsip_clk);
|
||||
eclkpon:
|
||||
clk_disable(mipi->dsit_clk);
|
||||
eclkton:
|
||||
esetprate:
|
||||
clk_put(mipi->dsip_clk);
|
||||
eclkpget:
|
||||
esettrate:
|
||||
clk_put(mipi->dsit_clk);
|
||||
eclktget:
|
||||
iounmap(mipi->base);
|
||||
emap:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
ereqreg:
|
||||
kfree(mipi);
|
||||
ealloc:
|
||||
efindslot:
|
||||
mutex_unlock(&array_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __exit sh_mipi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct sh_mipi *mipi = platform_get_drvdata(pdev);
|
||||
int i, ret;
|
||||
|
||||
mutex_lock(&array_lock);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
|
||||
;
|
||||
|
||||
if (i == ARRAY_SIZE(mipi_dsi)) {
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
ret = 0;
|
||||
mipi_dsi[i] = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&array_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
pdata->lcd_chan->board_cfg.display_on = NULL;
|
||||
pdata->lcd_chan->board_cfg.display_off = NULL;
|
||||
pdata->lcd_chan->board_cfg.board_data = NULL;
|
||||
|
||||
clk_disable(mipi->dsip_clk);
|
||||
clk_disable(mipi->dsit_clk);
|
||||
clk_put(mipi->dsit_clk);
|
||||
clk_put(mipi->dsip_clk);
|
||||
iounmap(mipi->base);
|
||||
if (res)
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(mipi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sh_mipi_driver = {
|
||||
.remove = __exit_p(sh_mipi_remove),
|
||||
.shutdown = sh_mipi_shutdown,
|
||||
.driver = {
|
||||
.name = "sh-mipi-dsi",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sh_mipi_init(void)
|
||||
{
|
||||
return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
|
||||
}
|
||||
module_init(sh_mipi_init);
|
||||
|
||||
static void __exit sh_mipi_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sh_mipi_driver);
|
||||
}
|
||||
module_exit(sh_mipi_exit);
|
||||
|
||||
MODULE_AUTHOR("Guennadi Liakhovetski <[email protected]>");
|
||||
MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
1028
drivers/video/sh_mobile_hdmi.c
Normal file
1028
drivers/video/sh_mobile_hdmi.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -56,6 +56,7 @@ static int lcdc_shared_regs[] = {
|
|||
/* per-channel registers */
|
||||
enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
|
||||
LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
|
||||
LDHAJR,
|
||||
NR_CH_REGS };
|
||||
|
||||
static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
|
||||
|
|
@ -74,6 +75,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
|
|||
[LDVLNR] = 0x450,
|
||||
[LDVSYNR] = 0x454,
|
||||
[LDPMR] = 0x460,
|
||||
[LDHAJR] = 0x4a0,
|
||||
};
|
||||
|
||||
static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
|
||||
|
|
@ -137,6 +139,7 @@ struct sh_mobile_lcdc_priv {
|
|||
struct clk *dot_clk;
|
||||
unsigned long lddckr;
|
||||
struct sh_mobile_lcdc_chan ch[2];
|
||||
struct notifier_block notifier;
|
||||
unsigned long saved_shared_regs[NR_SHARED_REGS];
|
||||
int started;
|
||||
};
|
||||
|
|
@ -404,6 +407,56 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
|
|||
lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */
|
||||
}
|
||||
|
||||
static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
|
||||
{
|
||||
struct fb_var_screeninfo *var = &ch->info->var;
|
||||
unsigned long h_total, hsync_pos;
|
||||
u32 tmp;
|
||||
|
||||
tmp = ch->ldmt1r_value;
|
||||
tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
|
||||
tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
|
||||
lcdc_write_chan(ch, LDMT1R, tmp);
|
||||
|
||||
/* setup SYS bus */
|
||||
lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
|
||||
lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
|
||||
|
||||
/* horizontal configuration */
|
||||
h_total = var->xres + var->hsync_len +
|
||||
var->left_margin + var->right_margin;
|
||||
tmp = h_total / 8; /* HTCN */
|
||||
tmp |= (var->xres / 8) << 16; /* HDCN */
|
||||
lcdc_write_chan(ch, LDHCNR, tmp);
|
||||
|
||||
hsync_pos = var->xres + var->right_margin;
|
||||
tmp = hsync_pos / 8; /* HSYNP */
|
||||
tmp |= (var->hsync_len / 8) << 16; /* HSYNW */
|
||||
lcdc_write_chan(ch, LDHSYNR, tmp);
|
||||
|
||||
/* vertical configuration */
|
||||
tmp = var->yres + var->vsync_len +
|
||||
var->upper_margin + var->lower_margin; /* VTLN */
|
||||
tmp |= var->yres << 16; /* VDLN */
|
||||
lcdc_write_chan(ch, LDVLNR, tmp);
|
||||
|
||||
tmp = var->yres + var->lower_margin; /* VSYNP */
|
||||
tmp |= var->vsync_len << 16; /* VSYNW */
|
||||
lcdc_write_chan(ch, LDVSYNR, tmp);
|
||||
|
||||
/* Adjust horizontal synchronisation for HDMI */
|
||||
tmp = ((var->xres & 7) << 24) |
|
||||
((h_total & 7) << 16) |
|
||||
((var->hsync_len & 7) << 8) |
|
||||
hsync_pos;
|
||||
lcdc_write_chan(ch, LDHAJR, tmp);
|
||||
}
|
||||
|
||||
static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
||||
{
|
||||
struct sh_mobile_lcdc_chan *ch;
|
||||
|
|
@ -470,49 +523,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
if (!ch->enabled)
|
||||
continue;
|
||||
|
||||
tmp = ch->ldmt1r_value;
|
||||
tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
|
||||
tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
|
||||
tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
|
||||
lcdc_write_chan(ch, LDMT1R, tmp);
|
||||
|
||||
/* setup SYS bus */
|
||||
lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r);
|
||||
lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r);
|
||||
|
||||
/* horizontal configuration */
|
||||
tmp = lcd_cfg->xres + lcd_cfg->hsync_len;
|
||||
tmp += lcd_cfg->left_margin;
|
||||
tmp += lcd_cfg->right_margin;
|
||||
tmp /= 8; /* HTCN */
|
||||
tmp |= (lcd_cfg->xres / 8) << 16; /* HDCN */
|
||||
lcdc_write_chan(ch, LDHCNR, tmp);
|
||||
|
||||
tmp = lcd_cfg->xres;
|
||||
tmp += lcd_cfg->right_margin;
|
||||
tmp /= 8; /* HSYNP */
|
||||
tmp |= (lcd_cfg->hsync_len / 8) << 16; /* HSYNW */
|
||||
lcdc_write_chan(ch, LDHSYNR, tmp);
|
||||
sh_mobile_lcdc_geometry(ch);
|
||||
|
||||
/* power supply */
|
||||
lcdc_write_chan(ch, LDPMR, 0);
|
||||
|
||||
/* vertical configuration */
|
||||
tmp = lcd_cfg->yres + lcd_cfg->vsync_len;
|
||||
tmp += lcd_cfg->upper_margin;
|
||||
tmp += lcd_cfg->lower_margin; /* VTLN */
|
||||
tmp |= lcd_cfg->yres << 16; /* VDLN */
|
||||
lcdc_write_chan(ch, LDVLNR, tmp);
|
||||
|
||||
tmp = lcd_cfg->yres;
|
||||
tmp += lcd_cfg->lower_margin; /* VSYNP */
|
||||
tmp |= lcd_cfg->vsync_len << 16; /* VSYNW */
|
||||
lcdc_write_chan(ch, LDVSYNR, tmp);
|
||||
|
||||
board_cfg = &ch->cfg.board_cfg;
|
||||
if (board_cfg->setup_sys)
|
||||
ret = board_cfg->setup_sys(board_cfg->board_data, ch,
|
||||
|
|
@ -577,7 +592,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
|
||||
board_cfg = &ch->cfg.board_cfg;
|
||||
if (board_cfg->display_on)
|
||||
board_cfg->display_on(board_cfg->board_data);
|
||||
board_cfg->display_on(board_cfg->board_data, ch->info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -943,6 +958,62 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
|
|||
.runtime_resume = sh_mobile_lcdc_runtime_resume,
|
||||
};
|
||||
|
||||
static int sh_mobile_lcdc_notify(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct fb_event *event = data;
|
||||
struct fb_info *info = event->info;
|
||||
struct sh_mobile_lcdc_chan *ch = info->par;
|
||||
struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
|
||||
struct fb_var_screeninfo *var;
|
||||
|
||||
if (&ch->lcdc->notifier != nb)
|
||||
return 0;
|
||||
|
||||
dev_dbg(info->dev, "%s(): action = %lu, data = %p\n",
|
||||
__func__, action, event->data);
|
||||
|
||||
switch(action) {
|
||||
case FB_EVENT_SUSPEND:
|
||||
if (board_cfg->display_off)
|
||||
board_cfg->display_off(board_cfg->board_data);
|
||||
pm_runtime_put(info->device);
|
||||
break;
|
||||
case FB_EVENT_RESUME:
|
||||
var = &info->var;
|
||||
|
||||
/* HDMI must be enabled before LCDC configuration */
|
||||
if (board_cfg->display_on)
|
||||
board_cfg->display_on(board_cfg->board_data, ch->info);
|
||||
|
||||
/* Check if the new display is not in our modelist */
|
||||
if (ch->info->modelist.next &&
|
||||
!fb_match_mode(var, &ch->info->modelist)) {
|
||||
struct fb_videomode mode;
|
||||
int ret;
|
||||
|
||||
/* Can we handle this display? */
|
||||
if (var->xres > ch->cfg.lcd_cfg.xres ||
|
||||
var->yres > ch->cfg.lcd_cfg.yres)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Add to the modelist */
|
||||
fb_var_to_videomode(&mode, var);
|
||||
ret = fb_add_videomode(&mode, &ch->info->modelist);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(info->device);
|
||||
|
||||
sh_mobile_lcdc_geometry(ch);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_mobile_lcdc_remove(struct platform_device *pdev);
|
||||
|
||||
static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
||||
|
|
@ -1020,15 +1091,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
priv->base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!priv->base)
|
||||
goto err1;
|
||||
|
||||
error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "unable to setup clocks\n");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
struct fb_var_screeninfo *var;
|
||||
struct fb_videomode *lcd_cfg;
|
||||
cfg = &priv->ch[i].cfg;
|
||||
|
||||
priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
|
||||
|
|
@ -1039,22 +1114,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
info = priv->ch[i].info;
|
||||
var = &info->var;
|
||||
lcd_cfg = &cfg->lcd_cfg;
|
||||
info->fbops = &sh_mobile_lcdc_ops;
|
||||
info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
|
||||
info->var.yres = cfg->lcd_cfg.yres;
|
||||
var->xres = var->xres_virtual = lcd_cfg->xres;
|
||||
var->yres = lcd_cfg->yres;
|
||||
/* Default Y virtual resolution is 2x panel size */
|
||||
info->var.yres_virtual = info->var.yres * 2;
|
||||
info->var.width = cfg->lcd_size_cfg.width;
|
||||
info->var.height = cfg->lcd_size_cfg.height;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp);
|
||||
var->yres_virtual = var->yres * 2;
|
||||
var->width = cfg->lcd_size_cfg.width;
|
||||
var->height = cfg->lcd_size_cfg.height;
|
||||
var->activate = FB_ACTIVATE_NOW;
|
||||
var->left_margin = lcd_cfg->left_margin;
|
||||
var->right_margin = lcd_cfg->right_margin;
|
||||
var->upper_margin = lcd_cfg->upper_margin;
|
||||
var->lower_margin = lcd_cfg->lower_margin;
|
||||
var->hsync_len = lcd_cfg->hsync_len;
|
||||
var->vsync_len = lcd_cfg->vsync_len;
|
||||
var->sync = lcd_cfg->sync;
|
||||
var->pixclock = lcd_cfg->pixclock;
|
||||
|
||||
error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
info->fix = sh_mobile_lcdc_fix;
|
||||
info->fix.line_length = cfg->lcd_cfg.xres * (cfg->bpp / 8);
|
||||
info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8);
|
||||
info->fix.smem_len = info->fix.line_length *
|
||||
info->var.yres_virtual;
|
||||
var->yres_virtual;
|
||||
|
||||
buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len,
|
||||
&priv->ch[i].dma_handle, GFP_KERNEL);
|
||||
|
|
@ -1119,10 +1205,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
|||
ch->cfg.bpp);
|
||||
|
||||
/* deferred io mode: disable clock to save power */
|
||||
if (info->fbdefio)
|
||||
if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
|
||||
sh_mobile_lcdc_clk_off(priv);
|
||||
}
|
||||
|
||||
/* Failure ignored */
|
||||
priv->notifier.notifier_call = sh_mobile_lcdc_notify;
|
||||
fb_register_client(&priv->notifier);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
sh_mobile_lcdc_remove(pdev);
|
||||
|
|
@ -1136,6 +1226,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
|
|||
struct fb_info *info;
|
||||
int i;
|
||||
|
||||
fb_unregister_client(&priv->notifier);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
|
||||
if (priv->ch[i].info && priv->ch[i].info->dev)
|
||||
unregister_framebuffer(priv->ch[i].info);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit gfb_probe(struct of_device *op,
|
||||
static int __devinit gfb_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
|
|
@ -172,7 +172,7 @@ err_out:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit gfb_remove(struct of_device *op)
|
||||
static int __devexit gfb_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct gfb_info *gp = info->par;
|
||||
|
|
@ -213,12 +213,12 @@ static int __init gfb_init(void)
|
|||
if (fb_get_options("gfb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&gfb_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&gfb_driver);
|
||||
}
|
||||
|
||||
static void __exit gfb_exit(void)
|
||||
{
|
||||
of_unregister_driver(&gfb_driver);
|
||||
of_unregister_platform_driver(&gfb_driver);
|
||||
}
|
||||
|
||||
module_init(gfb_init);
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ tcx_init_fix(struct fb_info *info, int linebytes)
|
|||
info->fix.accel = FB_ACCEL_SUN_TCX;
|
||||
}
|
||||
|
||||
static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
|
||||
struct tcx_par *par)
|
||||
{
|
||||
if (par->tec)
|
||||
|
|
@ -362,7 +362,7 @@ static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
|
|||
info->screen_base, info->fix.smem_len);
|
||||
}
|
||||
|
||||
static int __devinit tcx_probe(struct of_device *op,
|
||||
static int __devinit tcx_probe(struct platform_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
|
|
@ -486,7 +486,7 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit tcx_remove(struct of_device *op)
|
||||
static int __devexit tcx_remove(struct platform_device *op)
|
||||
{
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct tcx_par *par = info->par;
|
||||
|
|
@ -526,12 +526,12 @@ static int __init tcx_init(void)
|
|||
if (fb_get_options("tcxfb", NULL))
|
||||
return -ENODEV;
|
||||
|
||||
return of_register_driver(&tcx_driver, &of_bus_type);
|
||||
return of_register_platform_driver(&tcx_driver);
|
||||
}
|
||||
|
||||
static void __exit tcx_exit(void)
|
||||
{
|
||||
of_unregister_driver(&tcx_driver);
|
||||
of_unregister_platform_driver(&tcx_driver);
|
||||
}
|
||||
|
||||
module_init(tcx_init);
|
||||
|
|
|
|||
|
|
@ -1571,8 +1571,8 @@ out_err_iobase:
|
|||
if (default_par->mtrr_handle >= 0)
|
||||
mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
|
||||
info->fix.smem_len);
|
||||
release_mem_region(pci_resource_start(pdev, 2),
|
||||
pci_resource_len(pdev, 2));
|
||||
release_region(pci_resource_start(pdev, 2),
|
||||
pci_resource_len(pdev, 2));
|
||||
out_err_screenbase:
|
||||
if (info->screen_base)
|
||||
iounmap(info->screen_base);
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ tgafb_set_par(struct fb_info *info)
|
|||
TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
|
||||
TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
|
||||
|
||||
/* Initalise RAMDAC. */
|
||||
/* Initialise RAMDAC. */
|
||||
if (tga_type == TGA_TYPE_8PLANE && tga_bus_pci) {
|
||||
|
||||
/* Init BT485 RAMDAC registers. */
|
||||
|
|
|
|||
|
|
@ -1977,8 +1977,7 @@ static void __devexit uvesafb_exit(void)
|
|||
|
||||
module_exit(uvesafb_exit);
|
||||
|
||||
#define param_get_scroll NULL
|
||||
static int param_set_scroll(const char *val, struct kernel_param *kp)
|
||||
static int param_set_scroll(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
ypan = 0;
|
||||
|
||||
|
|
@ -1993,7 +1992,9 @@ static int param_set_scroll(const char *val, struct kernel_param *kp)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct kernel_param_ops param_ops_scroll = {
|
||||
.set = param_set_scroll,
|
||||
};
|
||||
#define param_check_scroll(name, p) __param_check(name, p, void)
|
||||
|
||||
module_param_named(scroll, ypan, scroll, 0);
|
||||
|
|
|
|||
|
|
@ -160,7 +160,6 @@ struct lvds_setting_information {
|
|||
int v_active;
|
||||
int bpp;
|
||||
int refresh_rate;
|
||||
int get_lcd_size_method;
|
||||
int lcd_panel_id;
|
||||
int lcd_panel_hres;
|
||||
int lcd_panel_vres;
|
||||
|
|
|
|||
|
|
@ -23,143 +23,341 @@
|
|||
#include "global.h"
|
||||
|
||||
static struct pll_map pll_value[] = {
|
||||
{CLK_25_175M, CLE266_PLL_25_175M, K800_PLL_25_175M,
|
||||
CX700_25_175M, VX855_25_175M},
|
||||
{CLK_29_581M, CLE266_PLL_29_581M, K800_PLL_29_581M,
|
||||
CX700_29_581M, VX855_29_581M},
|
||||
{CLK_26_880M, CLE266_PLL_26_880M, K800_PLL_26_880M,
|
||||
CX700_26_880M, VX855_26_880M},
|
||||
{CLK_31_490M, CLE266_PLL_31_490M, K800_PLL_31_490M,
|
||||
CX700_31_490M, VX855_31_490M},
|
||||
{CLK_31_500M, CLE266_PLL_31_500M, K800_PLL_31_500M,
|
||||
CX700_31_500M, VX855_31_500M},
|
||||
{CLK_31_728M, CLE266_PLL_31_728M, K800_PLL_31_728M,
|
||||
CX700_31_728M, VX855_31_728M},
|
||||
{CLK_32_668M, CLE266_PLL_32_668M, K800_PLL_32_668M,
|
||||
CX700_32_668M, VX855_32_668M},
|
||||
{CLK_36_000M, CLE266_PLL_36_000M, K800_PLL_36_000M,
|
||||
CX700_36_000M, VX855_36_000M},
|
||||
{CLK_40_000M, CLE266_PLL_40_000M, K800_PLL_40_000M,
|
||||
CX700_40_000M, VX855_40_000M},
|
||||
{CLK_41_291M, CLE266_PLL_41_291M, K800_PLL_41_291M,
|
||||
CX700_41_291M, VX855_41_291M},
|
||||
{CLK_43_163M, CLE266_PLL_43_163M, K800_PLL_43_163M,
|
||||
CX700_43_163M, VX855_43_163M},
|
||||
{CLK_45_250M, CLE266_PLL_45_250M, K800_PLL_45_250M,
|
||||
CX700_45_250M, VX855_45_250M},
|
||||
{CLK_46_000M, CLE266_PLL_46_000M, K800_PLL_46_000M,
|
||||
CX700_46_000M, VX855_46_000M},
|
||||
{CLK_46_996M, CLE266_PLL_46_996M, K800_PLL_46_996M,
|
||||
CX700_46_996M, VX855_46_996M},
|
||||
{CLK_48_000M, CLE266_PLL_48_000M, K800_PLL_48_000M,
|
||||
CX700_48_000M, VX855_48_000M},
|
||||
{CLK_48_875M, CLE266_PLL_48_875M, K800_PLL_48_875M,
|
||||
CX700_48_875M, VX855_48_875M},
|
||||
{CLK_49_500M, CLE266_PLL_49_500M, K800_PLL_49_500M,
|
||||
CX700_49_500M, VX855_49_500M},
|
||||
{CLK_52_406M, CLE266_PLL_52_406M, K800_PLL_52_406M,
|
||||
CX700_52_406M, VX855_52_406M},
|
||||
{CLK_52_977M, CLE266_PLL_52_977M, K800_PLL_52_977M,
|
||||
CX700_52_977M, VX855_52_977M},
|
||||
{CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M,
|
||||
CX700_56_250M, VX855_56_250M},
|
||||
{CLK_57_275M, 0, 0, 0, VX855_57_275M},
|
||||
{CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M,
|
||||
CX700_60_466M, VX855_60_466M},
|
||||
{CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M,
|
||||
CX700_61_500M, VX855_61_500M},
|
||||
{CLK_65_000M, CLE266_PLL_65_000M, K800_PLL_65_000M,
|
||||
CX700_65_000M, VX855_65_000M},
|
||||
{CLK_65_178M, CLE266_PLL_65_178M, K800_PLL_65_178M,
|
||||
CX700_65_178M, VX855_65_178M},
|
||||
{CLK_66_750M, CLE266_PLL_66_750M, K800_PLL_66_750M,
|
||||
CX700_66_750M, VX855_66_750M},
|
||||
{CLK_68_179M, CLE266_PLL_68_179M, K800_PLL_68_179M,
|
||||
CX700_68_179M, VX855_68_179M},
|
||||
{CLK_69_924M, CLE266_PLL_69_924M, K800_PLL_69_924M,
|
||||
CX700_69_924M, VX855_69_924M},
|
||||
{CLK_70_159M, CLE266_PLL_70_159M, K800_PLL_70_159M,
|
||||
CX700_70_159M, VX855_70_159M},
|
||||
{CLK_72_000M, CLE266_PLL_72_000M, K800_PLL_72_000M,
|
||||
CX700_72_000M, VX855_72_000M},
|
||||
{CLK_78_750M, CLE266_PLL_78_750M, K800_PLL_78_750M,
|
||||
CX700_78_750M, VX855_78_750M},
|
||||
{CLK_80_136M, CLE266_PLL_80_136M, K800_PLL_80_136M,
|
||||
CX700_80_136M, VX855_80_136M},
|
||||
{CLK_83_375M, CLE266_PLL_83_375M, K800_PLL_83_375M,
|
||||
CX700_83_375M, VX855_83_375M},
|
||||
{CLK_83_950M, CLE266_PLL_83_950M, K800_PLL_83_950M,
|
||||
CX700_83_950M, VX855_83_950M},
|
||||
{CLK_84_750M, CLE266_PLL_84_750M, K800_PLL_84_750M,
|
||||
CX700_84_750M, VX855_84_750M},
|
||||
{CLK_85_860M, CLE266_PLL_85_860M, K800_PLL_85_860M,
|
||||
CX700_85_860M, VX855_85_860M},
|
||||
{CLK_88_750M, CLE266_PLL_88_750M, K800_PLL_88_750M,
|
||||
CX700_88_750M, VX855_88_750M},
|
||||
{CLK_94_500M, CLE266_PLL_94_500M, K800_PLL_94_500M,
|
||||
CX700_94_500M, VX855_94_500M},
|
||||
{CLK_97_750M, CLE266_PLL_97_750M, K800_PLL_97_750M,
|
||||
CX700_97_750M, VX855_97_750M},
|
||||
{CLK_101_000M, CLE266_PLL_101_000M, K800_PLL_101_000M,
|
||||
CX700_101_000M, VX855_101_000M},
|
||||
{CLK_106_500M, CLE266_PLL_106_500M, K800_PLL_106_500M,
|
||||
CX700_106_500M, VX855_106_500M},
|
||||
{CLK_108_000M, CLE266_PLL_108_000M, K800_PLL_108_000M,
|
||||
CX700_108_000M, VX855_108_000M},
|
||||
{CLK_113_309M, CLE266_PLL_113_309M, K800_PLL_113_309M,
|
||||
CX700_113_309M, VX855_113_309M},
|
||||
{CLK_118_840M, CLE266_PLL_118_840M, K800_PLL_118_840M,
|
||||
CX700_118_840M, VX855_118_840M},
|
||||
{CLK_119_000M, CLE266_PLL_119_000M, K800_PLL_119_000M,
|
||||
CX700_119_000M, VX855_119_000M},
|
||||
{CLK_121_750M, CLE266_PLL_121_750M, K800_PLL_121_750M,
|
||||
CX700_121_750M, 0},
|
||||
{CLK_125_104M, CLE266_PLL_125_104M, K800_PLL_125_104M,
|
||||
CX700_125_104M, 0},
|
||||
{CLK_133_308M, CLE266_PLL_133_308M, K800_PLL_133_308M,
|
||||
CX700_133_308M, 0},
|
||||
{CLK_135_000M, CLE266_PLL_135_000M, K800_PLL_135_000M,
|
||||
CX700_135_000M, VX855_135_000M},
|
||||
{CLK_136_700M, CLE266_PLL_136_700M, K800_PLL_136_700M,
|
||||
CX700_136_700M, VX855_136_700M},
|
||||
{CLK_138_400M, CLE266_PLL_138_400M, K800_PLL_138_400M,
|
||||
CX700_138_400M, VX855_138_400M},
|
||||
{CLK_146_760M, CLE266_PLL_146_760M, K800_PLL_146_760M,
|
||||
CX700_146_760M, VX855_146_760M},
|
||||
{CLK_153_920M, CLE266_PLL_153_920M, K800_PLL_153_920M,
|
||||
CX700_153_920M, VX855_153_920M},
|
||||
{CLK_156_000M, CLE266_PLL_156_000M, K800_PLL_156_000M,
|
||||
CX700_156_000M, VX855_156_000M},
|
||||
{CLK_157_500M, CLE266_PLL_157_500M, K800_PLL_157_500M,
|
||||
CX700_157_500M, VX855_157_500M},
|
||||
{CLK_162_000M, CLE266_PLL_162_000M, K800_PLL_162_000M,
|
||||
CX700_162_000M, VX855_162_000M},
|
||||
{CLK_187_000M, CLE266_PLL_187_000M, K800_PLL_187_000M,
|
||||
CX700_187_000M, VX855_187_000M},
|
||||
{CLK_193_295M, CLE266_PLL_193_295M, K800_PLL_193_295M,
|
||||
CX700_193_295M, VX855_193_295M},
|
||||
{CLK_202_500M, CLE266_PLL_202_500M, K800_PLL_202_500M,
|
||||
CX700_202_500M, VX855_202_500M},
|
||||
{CLK_204_000M, CLE266_PLL_204_000M, K800_PLL_204_000M,
|
||||
CX700_204_000M, VX855_204_000M},
|
||||
{CLK_218_500M, CLE266_PLL_218_500M, K800_PLL_218_500M,
|
||||
CX700_218_500M, VX855_218_500M},
|
||||
{CLK_234_000M, CLE266_PLL_234_000M, K800_PLL_234_000M,
|
||||
CX700_234_000M, VX855_234_000M},
|
||||
{CLK_267_250M, CLE266_PLL_267_250M, K800_PLL_267_250M,
|
||||
CX700_267_250M, VX855_267_250M},
|
||||
{CLK_297_500M, CLE266_PLL_297_500M, K800_PLL_297_500M,
|
||||
CX700_297_500M, VX855_297_500M},
|
||||
{CLK_74_481M, CLE266_PLL_74_481M, K800_PLL_74_481M,
|
||||
CX700_74_481M, VX855_74_481M},
|
||||
{CLK_172_798M, CLE266_PLL_172_798M, K800_PLL_172_798M,
|
||||
CX700_172_798M, VX855_172_798M},
|
||||
{CLK_122_614M, CLE266_PLL_122_614M, K800_PLL_122_614M,
|
||||
CX700_122_614M, VX855_122_614M},
|
||||
{CLK_74_270M, CLE266_PLL_74_270M, K800_PLL_74_270M,
|
||||
CX700_74_270M, 0},
|
||||
{CLK_148_500M, CLE266_PLL_148_500M, K800_PLL_148_500M,
|
||||
CX700_148_500M, VX855_148_500M}
|
||||
{25175000,
|
||||
{99, 7, 3},
|
||||
{85, 3, 4}, /* ignoring bit difference: 0x00008000 */
|
||||
{141, 5, 4},
|
||||
{141, 5, 4} },
|
||||
{29581000,
|
||||
{33, 4, 2},
|
||||
{66, 2, 4}, /* ignoring bit difference: 0x00808000 */
|
||||
{166, 5, 4}, /* ignoring bit difference: 0x00008000 */
|
||||
{165, 5, 4} },
|
||||
{26880000,
|
||||
{15, 4, 1},
|
||||
{30, 2, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{150, 5, 4},
|
||||
{150, 5, 4} },
|
||||
{31500000,
|
||||
{53, 3, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{141, 4, 4}, /* ignoring bit difference: 0x00008000 */
|
||||
{176, 5, 4},
|
||||
{176, 5, 4} },
|
||||
{31728000,
|
||||
{31, 7, 1},
|
||||
{177, 5, 4}, /* ignoring bit difference: 0x00008000 */
|
||||
{177, 5, 4},
|
||||
{142, 4, 4} },
|
||||
{32688000,
|
||||
{73, 4, 3},
|
||||
{146, 4, 4}, /* ignoring bit difference: 0x00008000 */
|
||||
{183, 5, 4},
|
||||
{146, 4, 4} },
|
||||
{36000000,
|
||||
{101, 5, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{161, 4, 4}, /* ignoring bit difference: 0x00008000 */
|
||||
{202, 5, 4},
|
||||
{161, 4, 4} },
|
||||
{40000000,
|
||||
{89, 4, 3},
|
||||
{89, 4, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{112, 5, 3},
|
||||
{112, 5, 3} },
|
||||
{41291000,
|
||||
{23, 4, 1},
|
||||
{69, 3, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{115, 5, 3},
|
||||
{115, 5, 3} },
|
||||
{43163000,
|
||||
{121, 5, 3},
|
||||
{121, 5, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{121, 5, 3},
|
||||
{121, 5, 3} },
|
||||
{45250000,
|
||||
{127, 5, 3},
|
||||
{127, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{127, 5, 3},
|
||||
{127, 5, 3} },
|
||||
{46000000,
|
||||
{90, 7, 2},
|
||||
{103, 4, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{129, 5, 3},
|
||||
{103, 4, 3} },
|
||||
{46996000,
|
||||
{105, 4, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{131, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{131, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{105, 4, 3} },
|
||||
{48000000,
|
||||
{67, 20, 0},
|
||||
{134, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{134, 5, 3},
|
||||
{134, 5, 3} },
|
||||
{48875000,
|
||||
{99, 29, 0},
|
||||
{82, 3, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{82, 3, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{137, 5, 3} },
|
||||
{49500000,
|
||||
{83, 6, 2},
|
||||
{83, 3, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{138, 5, 3},
|
||||
{83, 3, 3} },
|
||||
{52406000,
|
||||
{117, 4, 3},
|
||||
{117, 4, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{117, 4, 3},
|
||||
{88, 3, 3} },
|
||||
{52977000,
|
||||
{37, 5, 1},
|
||||
{148, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{148, 5, 3},
|
||||
{148, 5, 3} },
|
||||
{56250000,
|
||||
{55, 7, 1}, /* ignoring bit difference: 0x00008000 */
|
||||
{126, 4, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{157, 5, 3},
|
||||
{157, 5, 3} },
|
||||
{57275000,
|
||||
{0, 0, 0},
|
||||
{2, 2, 0},
|
||||
{2, 2, 0},
|
||||
{157, 5, 3} }, /* ignoring bit difference: 0x00808000 */
|
||||
{60466000,
|
||||
{76, 9, 1},
|
||||
{169, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{169, 5, 3}, /* FIXED: old = {72, 2, 3} */
|
||||
{169, 5, 3} },
|
||||
{61500000,
|
||||
{86, 20, 0},
|
||||
{172, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{172, 5, 3},
|
||||
{172, 5, 3} },
|
||||
{65000000,
|
||||
{109, 6, 2}, /* ignoring bit difference: 0x00008000 */
|
||||
{109, 3, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{109, 3, 3},
|
||||
{109, 3, 3} },
|
||||
{65178000,
|
||||
{91, 5, 2},
|
||||
{182, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{109, 3, 3},
|
||||
{182, 5, 3} },
|
||||
{66750000,
|
||||
{75, 4, 2},
|
||||
{150, 4, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{150, 4, 3},
|
||||
{112, 3, 3} },
|
||||
{68179000,
|
||||
{19, 4, 0},
|
||||
{114, 3, 3}, /* ignoring bit difference: 0x00008000 */
|
||||
{190, 5, 3},
|
||||
{191, 5, 3} },
|
||||
{69924000,
|
||||
{83, 17, 0},
|
||||
{195, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{195, 5, 3},
|
||||
{195, 5, 3} },
|
||||
{70159000,
|
||||
{98, 20, 0},
|
||||
{196, 5, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{196, 5, 3},
|
||||
{195, 5, 3} },
|
||||
{72000000,
|
||||
{121, 24, 0},
|
||||
{161, 4, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{161, 4, 3},
|
||||
{161, 4, 3} },
|
||||
{78750000,
|
||||
{33, 3, 1},
|
||||
{66, 3, 2}, /* ignoring bit difference: 0x00008000 */
|
||||
{110, 5, 2},
|
||||
{110, 5, 2} },
|
||||
{80136000,
|
||||
{28, 5, 0},
|
||||
{68, 3, 2}, /* ignoring bit difference: 0x00008000 */
|
||||
{112, 5, 2},
|
||||
{112, 5, 2} },
|
||||
{83375000,
|
||||
{93, 2, 3},
|
||||
{93, 4, 2}, /* ignoring bit difference: 0x00800000 */
|
||||
{93, 4, 2}, /* ignoring bit difference: 0x00800000 */
|
||||
{117, 5, 2} },
|
||||
{83950000,
|
||||
{41, 7, 0},
|
||||
{117, 5, 2}, /* ignoring bit difference: 0x00008000 */
|
||||
{117, 5, 2},
|
||||
{117, 5, 2} },
|
||||
{84750000,
|
||||
{118, 5, 2},
|
||||
{118, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{118, 5, 2},
|
||||
{118, 5, 2} },
|
||||
{85860000,
|
||||
{84, 7, 1},
|
||||
{120, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{120, 5, 2},
|
||||
{118, 5, 2} },
|
||||
{88750000,
|
||||
{31, 5, 0},
|
||||
{124, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{174, 7, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{124, 5, 2} },
|
||||
{94500000,
|
||||
{33, 5, 0},
|
||||
{132, 5, 2}, /* ignoring bit difference: 0x00008000 */
|
||||
{132, 5, 2},
|
||||
{132, 5, 2} },
|
||||
{97750000,
|
||||
{82, 6, 1},
|
||||
{137, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{137, 5, 2},
|
||||
{137, 5, 2} },
|
||||
{101000000,
|
||||
{127, 9, 1},
|
||||
{141, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{141, 5, 2},
|
||||
{141, 5, 2} },
|
||||
{106500000,
|
||||
{119, 4, 2},
|
||||
{119, 4, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{119, 4, 2},
|
||||
{149, 5, 2} },
|
||||
{108000000,
|
||||
{121, 4, 2},
|
||||
{121, 4, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{151, 5, 2},
|
||||
{151, 5, 2} },
|
||||
{113309000,
|
||||
{95, 12, 0},
|
||||
{95, 3, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{95, 3, 2},
|
||||
{159, 5, 2} },
|
||||
{118840000,
|
||||
{83, 5, 1},
|
||||
{166, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{166, 5, 2},
|
||||
{166, 5, 2} },
|
||||
{119000000,
|
||||
{108, 13, 0},
|
||||
{133, 4, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{133, 4, 2},
|
||||
{167, 5, 2} },
|
||||
{121750000,
|
||||
{85, 5, 1},
|
||||
{170, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{68, 2, 2},
|
||||
{0, 0, 0} },
|
||||
{125104000,
|
||||
{53, 6, 0}, /* ignoring bit difference: 0x00008000 */
|
||||
{106, 3, 2}, /* ignoring bit difference: 0x00008000 */
|
||||
{175, 5, 2},
|
||||
{0, 0, 0} },
|
||||
{135000000,
|
||||
{94, 5, 1},
|
||||
{28, 3, 0}, /* ignoring bit difference: 0x00804000 */
|
||||
{151, 4, 2},
|
||||
{189, 5, 2} },
|
||||
{136700000,
|
||||
{115, 12, 0},
|
||||
{191, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{191, 5, 2},
|
||||
{191, 5, 2} },
|
||||
{138400000,
|
||||
{87, 9, 0},
|
||||
{116, 3, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{116, 3, 2},
|
||||
{194, 5, 2} },
|
||||
{146760000,
|
||||
{103, 5, 1},
|
||||
{206, 5, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{206, 5, 2},
|
||||
{206, 5, 2} },
|
||||
{153920000,
|
||||
{86, 8, 0},
|
||||
{86, 4, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{86, 4, 1},
|
||||
{86, 4, 1} }, /* FIXED: old = {84, 2, 1} */
|
||||
{156000000,
|
||||
{109, 5, 1},
|
||||
{109, 5, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{109, 5, 1},
|
||||
{108, 5, 1} },
|
||||
{157500000,
|
||||
{55, 5, 0}, /* ignoring bit difference: 0x00008000 */
|
||||
{22, 2, 0}, /* ignoring bit difference: 0x00802000 */
|
||||
{110, 5, 1},
|
||||
{110, 5, 1} },
|
||||
{162000000,
|
||||
{113, 5, 1},
|
||||
{113, 5, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{113, 5, 1},
|
||||
{113, 5, 1} },
|
||||
{187000000,
|
||||
{118, 9, 0},
|
||||
{131, 5, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{131, 5, 1},
|
||||
{131, 5, 1} },
|
||||
{193295000,
|
||||
{108, 8, 0},
|
||||
{81, 3, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{135, 5, 1},
|
||||
{135, 5, 1} },
|
||||
{202500000,
|
||||
{99, 7, 0},
|
||||
{85, 3, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{142, 5, 1},
|
||||
{142, 5, 1} },
|
||||
{204000000,
|
||||
{100, 7, 0},
|
||||
{143, 5, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{143, 5, 1},
|
||||
{143, 5, 1} },
|
||||
{218500000,
|
||||
{92, 6, 0},
|
||||
{153, 5, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{153, 5, 1},
|
||||
{153, 5, 1} },
|
||||
{234000000,
|
||||
{98, 6, 0},
|
||||
{98, 3, 1}, /* ignoring bit difference: 0x00008000 */
|
||||
{98, 3, 1},
|
||||
{164, 5, 1} },
|
||||
{267250000,
|
||||
{112, 6, 0},
|
||||
{112, 3, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{187, 5, 1},
|
||||
{187, 5, 1} },
|
||||
{297500000,
|
||||
{102, 5, 0}, /* ignoring bit difference: 0x00008000 */
|
||||
{166, 4, 1}, /* ignoring bit difference: 0x00008000 */
|
||||
{208, 5, 1},
|
||||
{208, 5, 1} },
|
||||
{74481000,
|
||||
{26, 5, 0},
|
||||
{125, 3, 3}, /* ignoring bit difference: 0x00808000 */
|
||||
{208, 5, 3},
|
||||
{209, 5, 3} },
|
||||
{172798000,
|
||||
{121, 5, 1},
|
||||
{121, 5, 1}, /* ignoring bit difference: 0x00808000 */
|
||||
{121, 5, 1},
|
||||
{121, 5, 1} },
|
||||
{122614000,
|
||||
{60, 7, 0},
|
||||
{137, 4, 2}, /* ignoring bit difference: 0x00808000 */
|
||||
{137, 4, 2},
|
||||
{172, 5, 2} },
|
||||
{74270000,
|
||||
{83, 8, 1},
|
||||
{208, 5, 3},
|
||||
{208, 5, 3},
|
||||
{0, 0, 0} },
|
||||
{148500000,
|
||||
{83, 8, 0},
|
||||
{208, 5, 2},
|
||||
{166, 4, 2},
|
||||
{208, 5, 2} }
|
||||
};
|
||||
|
||||
static struct fifo_depth_select display_fifo_depth_reg = {
|
||||
|
|
@ -1360,40 +1558,70 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
|
|||
|
||||
}
|
||||
|
||||
static u32 cle266_encode_pll(struct pll_config pll)
|
||||
{
|
||||
return (pll.multiplier << 8)
|
||||
| (pll.rshift << 6)
|
||||
| pll.divisor;
|
||||
}
|
||||
|
||||
static u32 k800_encode_pll(struct pll_config pll)
|
||||
{
|
||||
return ((pll.divisor - 2) << 16)
|
||||
| (pll.rshift << 10)
|
||||
| (pll.multiplier - 2);
|
||||
}
|
||||
|
||||
static u32 vx855_encode_pll(struct pll_config pll)
|
||||
{
|
||||
return (pll.divisor << 16)
|
||||
| (pll.rshift << 10)
|
||||
| pll.multiplier;
|
||||
}
|
||||
|
||||
u32 viafb_get_clk_value(int clk)
|
||||
{
|
||||
int i;
|
||||
u32 value = 0;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) {
|
||||
if (clk == pll_value[i].clk) {
|
||||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
case UNICHROME_K400:
|
||||
return pll_value[i].cle266_pll;
|
||||
while (i < NUM_TOTAL_PLL_TABLE && clk != pll_value[i].clk)
|
||||
i++;
|
||||
|
||||
case UNICHROME_K800:
|
||||
case UNICHROME_PM800:
|
||||
case UNICHROME_CN700:
|
||||
return pll_value[i].k800_pll;
|
||||
if (i == NUM_TOTAL_PLL_TABLE) {
|
||||
printk(KERN_WARNING "viafb_get_clk_value: PLL lookup failed!");
|
||||
} else {
|
||||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
case UNICHROME_K400:
|
||||
value = cle266_encode_pll(pll_value[i].cle266_pll);
|
||||
break;
|
||||
|
||||
case UNICHROME_CX700:
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_VX800:
|
||||
return pll_value[i].cx700_pll;
|
||||
case UNICHROME_VX855:
|
||||
return pll_value[i].vx855_pll;
|
||||
}
|
||||
case UNICHROME_K800:
|
||||
case UNICHROME_PM800:
|
||||
case UNICHROME_CN700:
|
||||
value = k800_encode_pll(pll_value[i].k800_pll);
|
||||
break;
|
||||
|
||||
case UNICHROME_CX700:
|
||||
case UNICHROME_CN750:
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_VX800:
|
||||
value = k800_encode_pll(pll_value[i].cx700_pll);
|
||||
break;
|
||||
|
||||
case UNICHROME_VX855:
|
||||
value = vx855_encode_pll(pll_value[i].vx855_pll);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_MSG(KERN_INFO "Can't find match PLL value\n\n");
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Set VCLK*/
|
||||
void viafb_set_vclock(u32 CLK, int set_iga)
|
||||
void viafb_set_vclock(u32 clk, int set_iga)
|
||||
{
|
||||
/* H.W. Reset : ON */
|
||||
viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
|
||||
|
|
@ -1403,26 +1631,23 @@ void viafb_set_vclock(u32 CLK, int set_iga)
|
|||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
case UNICHROME_K400:
|
||||
viafb_write_reg(SR46, VIASR, CLK / 0x100);
|
||||
viafb_write_reg(SR47, VIASR, CLK % 0x100);
|
||||
via_write_reg(VIASR, SR46, (clk & 0x00FF));
|
||||
via_write_reg(VIASR, SR47, (clk & 0xFF00) >> 8);
|
||||
break;
|
||||
|
||||
case UNICHROME_K800:
|
||||
case UNICHROME_PM800:
|
||||
case UNICHROME_CN700:
|
||||
case UNICHROME_CX700:
|
||||
case UNICHROME_CN750:
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
viafb_write_reg(SR44, VIASR, CLK / 0x10000);
|
||||
DEBUG_MSG(KERN_INFO "\nSR44=%x", CLK / 0x10000);
|
||||
viafb_write_reg(SR45, VIASR, (CLK & 0xFFFF) / 0x100);
|
||||
DEBUG_MSG(KERN_INFO "\nSR45=%x",
|
||||
(CLK & 0xFFFF) / 0x100);
|
||||
viafb_write_reg(SR46, VIASR, CLK % 0x100);
|
||||
DEBUG_MSG(KERN_INFO "\nSR46=%x", CLK % 0x100);
|
||||
via_write_reg(VIASR, SR44, (clk & 0x0000FF));
|
||||
via_write_reg(VIASR, SR45, (clk & 0x00FF00) >> 8);
|
||||
via_write_reg(VIASR, SR46, (clk & 0xFF0000) >> 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1432,22 +1657,23 @@ void viafb_set_vclock(u32 CLK, int set_iga)
|
|||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
case UNICHROME_K400:
|
||||
viafb_write_reg(SR44, VIASR, CLK / 0x100);
|
||||
viafb_write_reg(SR45, VIASR, CLK % 0x100);
|
||||
via_write_reg(VIASR, SR44, (clk & 0x00FF));
|
||||
via_write_reg(VIASR, SR45, (clk & 0xFF00) >> 8);
|
||||
break;
|
||||
|
||||
case UNICHROME_K800:
|
||||
case UNICHROME_PM800:
|
||||
case UNICHROME_CN700:
|
||||
case UNICHROME_CX700:
|
||||
case UNICHROME_CN750:
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
viafb_write_reg(SR4A, VIASR, CLK / 0x10000);
|
||||
viafb_write_reg(SR4B, VIASR, (CLK & 0xFFFF) / 0x100);
|
||||
viafb_write_reg(SR4C, VIASR, CLK % 0x100);
|
||||
via_write_reg(VIASR, SR4A, (clk & 0x0000FF));
|
||||
via_write_reg(VIASR, SR4B, (clk & 0x00FF00) >> 8);
|
||||
via_write_reg(VIASR, SR4C, (clk & 0xFF0000) >> 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1791,8 +2017,6 @@ void viafb_init_chip_info(int chip_type)
|
|||
viafb_set_iga_path();
|
||||
|
||||
viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
|
||||
viaparinfo->lvds_setting_info->get_lcd_size_method =
|
||||
GET_LCD_SIZE_BY_USER_SETTING;
|
||||
viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
|
||||
viaparinfo->lvds_setting_info2->display_method =
|
||||
viaparinfo->lvds_setting_info->display_method;
|
||||
|
|
@ -1946,13 +2170,6 @@ static void init_tmds_chip_info(void)
|
|||
|
||||
static void init_lvds_chip_info(void)
|
||||
{
|
||||
if (viafb_lcd_panel_id > LCD_PANEL_ID_MAXIMUM)
|
||||
viaparinfo->lvds_setting_info->get_lcd_size_method =
|
||||
GET_LCD_SIZE_BY_VGA_BIOS;
|
||||
else
|
||||
viaparinfo->lvds_setting_info->get_lcd_size_method =
|
||||
GET_LCD_SIZE_BY_USER_SETTING;
|
||||
|
||||
viafb_lvds_trasmitter_identify();
|
||||
viafb_init_lcd_size();
|
||||
viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
|
||||
|
|
|
|||
|
|
@ -700,12 +700,18 @@ struct _lcd_scaling_factor {
|
|||
struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
|
||||
};
|
||||
|
||||
struct pll_config {
|
||||
u16 multiplier;
|
||||
u8 divisor;
|
||||
u8 rshift;
|
||||
};
|
||||
|
||||
struct pll_map {
|
||||
u32 clk;
|
||||
u32 cle266_pll;
|
||||
u32 k800_pll;
|
||||
u32 cx700_pll;
|
||||
u32 vx855_pll;
|
||||
struct pll_config cle266_pll;
|
||||
struct pll_config k800_pll;
|
||||
struct pll_config cx700_pll;
|
||||
struct pll_config vx855_pll;
|
||||
};
|
||||
|
||||
struct rgbLUT {
|
||||
|
|
|
|||
|
|
@ -35,11 +35,9 @@
|
|||
#define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */
|
||||
#define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */
|
||||
#define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */
|
||||
#define VIAFB_SET_DEVICE 0x5649410A
|
||||
#define VIAFB_GET_DEVICE 0x5649410B
|
||||
#define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */
|
||||
#define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */
|
||||
#define VIAFB_SET_DEVICE_INFO 0x56494114
|
||||
#define VIAFB_GET_DEVICE_INFO 0x56494115
|
||||
|
||||
#define VIAFB_GET_DEVICE_SUPPORT 0x56494118
|
||||
|
|
@ -50,7 +48,6 @@
|
|||
#define VIAFB_GET_GAMMA_LUT 0x56494124
|
||||
#define VIAFB_SET_GAMMA_LUT 0x56494125
|
||||
#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126
|
||||
#define VIAFB_SET_SECOND_MODE 0x56494129
|
||||
#define VIAFB_SYNC_SURFACE 0x56494130
|
||||
#define VIAFB_GET_DRIVER_CAPS 0x56494131
|
||||
#define VIAFB_GET_IGA_SCALING_INFO 0x56494132
|
||||
|
|
|
|||
|
|
@ -75,8 +75,6 @@ static void check_diport_of_integrated_lvds(
|
|||
static struct display_timing lcd_centering_timging(struct display_timing
|
||||
mode_crt_reg,
|
||||
struct display_timing panel_crt_reg);
|
||||
static void viafb_load_scaling_factor_for_p4m900(int set_hres,
|
||||
int set_vres, int panel_hres, int panel_vres);
|
||||
|
||||
static int check_lvds_chip(int device_id_subaddr, int device_id)
|
||||
{
|
||||
|
|
@ -89,33 +87,8 @@ static int check_lvds_chip(int device_id_subaddr, int device_id)
|
|||
void viafb_init_lcd_size(void)
|
||||
{
|
||||
DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
|
||||
DEBUG_MSG(KERN_INFO
|
||||
"viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
|
||||
viaparinfo->lvds_setting_info->get_lcd_size_method);
|
||||
|
||||
switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
|
||||
case GET_LCD_SIZE_BY_SYSTEM_BIOS:
|
||||
break;
|
||||
case GET_LCD_SZIE_BY_HW_STRAPPING:
|
||||
break;
|
||||
case GET_LCD_SIZE_BY_VGA_BIOS:
|
||||
DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
|
||||
fp_id_to_vindex(viafb_lcd_panel_id);
|
||||
DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
|
||||
viaparinfo->lvds_setting_info->lcd_panel_id);
|
||||
break;
|
||||
case GET_LCD_SIZE_BY_USER_SETTING:
|
||||
DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
|
||||
fp_id_to_vindex(viafb_lcd_panel_id);
|
||||
DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
|
||||
viaparinfo->lvds_setting_info->lcd_panel_id);
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
|
||||
viaparinfo->lvds_setting_info->lcd_panel_id =
|
||||
LCD_PANEL_ID1_800X600;
|
||||
fp_id_to_vindex(LCD_PANEL_ID1_800X600);
|
||||
}
|
||||
fp_id_to_vindex(viafb_lcd_panel_id);
|
||||
viaparinfo->lvds_setting_info2->lcd_panel_id =
|
||||
viaparinfo->lvds_setting_info->lcd_panel_id;
|
||||
viaparinfo->lvds_setting_info2->lcd_panel_hres =
|
||||
|
|
@ -437,14 +410,9 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
|
|||
|
||||
/* LCD Scaling Enable */
|
||||
viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
|
||||
if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
|
||||
viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
|
||||
panel_hres, panel_vres);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if expansion for horizontal */
|
||||
if (set_hres != panel_hres) {
|
||||
if (set_hres < panel_hres) {
|
||||
/* Load Horizontal Scaling Factor */
|
||||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
|
|
@ -464,6 +432,10 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
|
|||
case UNICHROME_CX700:
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_CN750:
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
reg_value =
|
||||
K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
|
||||
/* Horizontal scaling enabled */
|
||||
|
|
@ -483,7 +455,7 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
|
|||
}
|
||||
|
||||
/* Check if expansion for vertical */
|
||||
if (set_vres != panel_vres) {
|
||||
if (set_vres < panel_vres) {
|
||||
/* Load Vertical Scaling Factor */
|
||||
switch (viaparinfo->chip_info->gfx_chip_name) {
|
||||
case UNICHROME_CLE266:
|
||||
|
|
@ -503,6 +475,10 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
|
|||
case UNICHROME_CX700:
|
||||
case UNICHROME_K8M890:
|
||||
case UNICHROME_P4M890:
|
||||
case UNICHROME_P4M900:
|
||||
case UNICHROME_CN750:
|
||||
case UNICHROME_VX800:
|
||||
case UNICHROME_VX855:
|
||||
reg_value =
|
||||
K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
|
||||
/* Vertical scaling enabled */
|
||||
|
|
@ -648,9 +624,8 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
|
|||
(mode_crt_reg, panel_crt_reg), IGA1);
|
||||
} else {
|
||||
/* Expansion */
|
||||
if ((plvds_setting_info->display_method ==
|
||||
LCD_EXPANDSION) & ((set_hres != panel_hres)
|
||||
|| (set_vres != panel_vres))) {
|
||||
if (plvds_setting_info->display_method == LCD_EXPANDSION
|
||||
&& (set_hres < panel_hres || set_vres < panel_vres)) {
|
||||
/* expansion timing IGA2 loaded panel set timing*/
|
||||
viafb_load_crtc_timing(panel_crt_reg, IGA2);
|
||||
DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
|
||||
|
|
@ -1139,69 +1114,3 @@ bool viafb_lcd_get_mobile_state(bool *mobile)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void viafb_load_scaling_factor_for_p4m900(int set_hres,
|
||||
int set_vres, int panel_hres, int panel_vres)
|
||||
{
|
||||
int h_scaling_factor;
|
||||
int v_scaling_factor;
|
||||
u8 cra2 = 0;
|
||||
u8 cr77 = 0;
|
||||
u8 cr78 = 0;
|
||||
u8 cr79 = 0;
|
||||
u8 cr9f = 0;
|
||||
/* Check if expansion for horizontal */
|
||||
if (set_hres < panel_hres) {
|
||||
/* Load Horizontal Scaling Factor */
|
||||
|
||||
/* For VIA_K8M800 or later chipsets. */
|
||||
h_scaling_factor =
|
||||
K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
|
||||
/* HSCaleFactor[1:0] at CR9F[1:0] */
|
||||
cr9f = h_scaling_factor & 0x0003;
|
||||
/* HSCaleFactor[9:2] at CR77[7:0] */
|
||||
cr77 = (h_scaling_factor & 0x03FC) >> 2;
|
||||
/* HSCaleFactor[11:10] at CR79[5:4] */
|
||||
cr79 = (h_scaling_factor & 0x0C00) >> 10;
|
||||
cr79 <<= 4;
|
||||
|
||||
/* Horizontal scaling enabled */
|
||||
cra2 = 0xC0;
|
||||
|
||||
DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
|
||||
h_scaling_factor);
|
||||
} else {
|
||||
/* Horizontal scaling disabled */
|
||||
cra2 = 0x00;
|
||||
}
|
||||
|
||||
/* Check if expansion for vertical */
|
||||
if (set_vres < panel_vres) {
|
||||
/* Load Vertical Scaling Factor */
|
||||
|
||||
/* For VIA_K8M800 or later chipsets. */
|
||||
v_scaling_factor =
|
||||
K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
|
||||
|
||||
/* Vertical scaling enabled */
|
||||
cra2 |= 0x08;
|
||||
/* VSCaleFactor[0] at CR79[3] */
|
||||
cr79 |= ((v_scaling_factor & 0x0001) << 3);
|
||||
/* VSCaleFactor[8:1] at CR78[7:0] */
|
||||
cr78 |= (v_scaling_factor & 0x01FE) >> 1;
|
||||
/* VSCaleFactor[10:9] at CR79[7:6] */
|
||||
cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
|
||||
|
||||
DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
|
||||
v_scaling_factor);
|
||||
} else {
|
||||
/* Vertical scaling disabled */
|
||||
cra2 |= 0x00;
|
||||
}
|
||||
|
||||
viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
|
||||
viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
|
||||
viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
|
||||
viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
|
||||
viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@
|
|||
#define VT3271_DEVICE_ID_REG 0x02
|
||||
#define VT3271_DEVICE_ID 0x71
|
||||
|
||||
#define GET_LCD_SIZE_BY_SYSTEM_BIOS 0x01
|
||||
#define GET_LCD_SIZE_BY_VGA_BIOS 0x02
|
||||
#define GET_LCD_SZIE_BY_HW_STRAPPING 0x03
|
||||
#define GET_LCD_SIZE_BY_USER_SETTING 0x04
|
||||
|
||||
/* Definition DVI Panel ID*/
|
||||
/* Resolution: 640x480, Channel: single, Dithering: Enable */
|
||||
#define LCD_PANEL_ID0_640X480 0x00
|
||||
|
|
|
|||
|
|
@ -631,7 +631,6 @@
|
|||
#define CLK_25_175M 25175000
|
||||
#define CLK_26_880M 26880000
|
||||
#define CLK_29_581M 29581000
|
||||
#define CLK_31_490M 31490000
|
||||
#define CLK_31_500M 31500000
|
||||
#define CLK_31_728M 31728000
|
||||
#define CLK_32_668M 32688000
|
||||
|
|
@ -676,7 +675,6 @@
|
|||
#define CLK_119_000M 119000000
|
||||
#define CLK_121_750M 121750000 /* 121.704MHz */
|
||||
#define CLK_125_104M 125104000
|
||||
#define CLK_133_308M 133308000
|
||||
#define CLK_135_000M 135000000
|
||||
#define CLK_136_700M 136700000
|
||||
#define CLK_138_400M 138400000
|
||||
|
|
@ -699,313 +697,6 @@
|
|||
#define CLK_172_798M 172798000
|
||||
#define CLK_122_614M 122614000
|
||||
|
||||
/* CLE266 PLL value
|
||||
*/
|
||||
#define CLE266_PLL_25_175M 0x0000C763
|
||||
#define CLE266_PLL_26_880M 0x0000440F
|
||||
#define CLE266_PLL_29_581M 0x00008421
|
||||
#define CLE266_PLL_31_490M 0x00004721
|
||||
#define CLE266_PLL_31_500M 0x0000C3B5
|
||||
#define CLE266_PLL_31_728M 0x0000471F
|
||||
#define CLE266_PLL_32_668M 0x0000C449
|
||||
#define CLE266_PLL_36_000M 0x0000C5E5
|
||||
#define CLE266_PLL_40_000M 0x0000C459
|
||||
#define CLE266_PLL_41_291M 0x00004417
|
||||
#define CLE266_PLL_43_163M 0x0000C579
|
||||
#define CLE266_PLL_45_250M 0x0000C57F /* 45.46MHz */
|
||||
#define CLE266_PLL_46_000M 0x0000875A
|
||||
#define CLE266_PLL_46_996M 0x0000C4E9
|
||||
#define CLE266_PLL_48_000M 0x00001443
|
||||
#define CLE266_PLL_48_875M 0x00001D63
|
||||
#define CLE266_PLL_49_500M 0x00008653
|
||||
#define CLE266_PLL_52_406M 0x0000C475
|
||||
#define CLE266_PLL_52_977M 0x00004525
|
||||
#define CLE266_PLL_56_250M 0x000047B7
|
||||
#define CLE266_PLL_60_466M 0x0000494C
|
||||
#define CLE266_PLL_61_500M 0x00001456
|
||||
#define CLE266_PLL_65_000M 0x000086ED
|
||||
#define CLE266_PLL_65_178M 0x0000855B
|
||||
#define CLE266_PLL_66_750M 0x0000844B /* 67.116MHz */
|
||||
#define CLE266_PLL_68_179M 0x00000413
|
||||
#define CLE266_PLL_69_924M 0x00001153
|
||||
#define CLE266_PLL_70_159M 0x00001462
|
||||
#define CLE266_PLL_72_000M 0x00001879
|
||||
#define CLE266_PLL_74_270M 0x00004853
|
||||
#define CLE266_PLL_78_750M 0x00004321
|
||||
#define CLE266_PLL_80_136M 0x0000051C
|
||||
#define CLE266_PLL_83_375M 0x0000C25D
|
||||
#define CLE266_PLL_83_950M 0x00000729
|
||||
#define CLE266_PLL_84_750M 0x00008576 /* 84.537MHz */
|
||||
#define CLE266_PLL_85_860M 0x00004754
|
||||
#define CLE266_PLL_88_750M 0x0000051F
|
||||
#define CLE266_PLL_94_500M 0x00000521
|
||||
#define CLE266_PLL_97_750M 0x00004652
|
||||
#define CLE266_PLL_101_000M 0x0000497F
|
||||
#define CLE266_PLL_106_500M 0x00008477 /* 106.491463 MHz */
|
||||
#define CLE266_PLL_108_000M 0x00008479
|
||||
#define CLE266_PLL_113_309M 0x00000C5F
|
||||
#define CLE266_PLL_118_840M 0x00004553
|
||||
#define CLE266_PLL_119_000M 0x00000D6C
|
||||
#define CLE266_PLL_121_750M 0x00004555 /* 121.704MHz */
|
||||
#define CLE266_PLL_125_104M 0x000006B5
|
||||
#define CLE266_PLL_133_308M 0x0000465F
|
||||
#define CLE266_PLL_135_000M 0x0000455E
|
||||
#define CLE266_PLL_136_700M 0x00000C73
|
||||
#define CLE266_PLL_138_400M 0x00000957
|
||||
#define CLE266_PLL_146_760M 0x00004567
|
||||
#define CLE266_PLL_148_500M 0x00000853
|
||||
#define CLE266_PLL_153_920M 0x00000856
|
||||
#define CLE266_PLL_156_000M 0x0000456D
|
||||
#define CLE266_PLL_157_500M 0x000005B7
|
||||
#define CLE266_PLL_162_000M 0x00004571
|
||||
#define CLE266_PLL_187_000M 0x00000976
|
||||
#define CLE266_PLL_193_295M 0x0000086C
|
||||
#define CLE266_PLL_202_500M 0x00000763
|
||||
#define CLE266_PLL_204_000M 0x00000764
|
||||
#define CLE266_PLL_218_500M 0x0000065C
|
||||
#define CLE266_PLL_234_000M 0x00000662
|
||||
#define CLE266_PLL_267_250M 0x00000670
|
||||
#define CLE266_PLL_297_500M 0x000005E6
|
||||
#define CLE266_PLL_74_481M 0x0000051A
|
||||
#define CLE266_PLL_172_798M 0x00004579
|
||||
#define CLE266_PLL_122_614M 0x0000073C
|
||||
|
||||
/* K800 PLL value
|
||||
*/
|
||||
#define K800_PLL_25_175M 0x00539001
|
||||
#define K800_PLL_26_880M 0x001C8C80
|
||||
#define K800_PLL_29_581M 0x00409080
|
||||
#define K800_PLL_31_490M 0x006F9001
|
||||
#define K800_PLL_31_500M 0x008B9002
|
||||
#define K800_PLL_31_728M 0x00AF9003
|
||||
#define K800_PLL_32_668M 0x00909002
|
||||
#define K800_PLL_36_000M 0x009F9002
|
||||
#define K800_PLL_40_000M 0x00578C02
|
||||
#define K800_PLL_41_291M 0x00438C01
|
||||
#define K800_PLL_43_163M 0x00778C03
|
||||
#define K800_PLL_45_250M 0x007D8C83 /* 45.46MHz */
|
||||
#define K800_PLL_46_000M 0x00658C02
|
||||
#define K800_PLL_46_996M 0x00818C83
|
||||
#define K800_PLL_48_000M 0x00848C83
|
||||
#define K800_PLL_48_875M 0x00508C81
|
||||
#define K800_PLL_49_500M 0x00518C01
|
||||
#define K800_PLL_52_406M 0x00738C02
|
||||
#define K800_PLL_52_977M 0x00928C83
|
||||
#define K800_PLL_56_250M 0x007C8C02
|
||||
#define K800_PLL_60_466M 0x00A78C83
|
||||
#define K800_PLL_61_500M 0x00AA8C83
|
||||
#define K800_PLL_65_000M 0x006B8C01
|
||||
#define K800_PLL_65_178M 0x00B48C83
|
||||
#define K800_PLL_66_750M 0x00948C82 /* 67.116MHz */
|
||||
#define K800_PLL_68_179M 0x00708C01
|
||||
#define K800_PLL_69_924M 0x00C18C83
|
||||
#define K800_PLL_70_159M 0x00C28C83
|
||||
#define K800_PLL_72_000M 0x009F8C82
|
||||
#define K800_PLL_74_270M 0x00ce0c03
|
||||
#define K800_PLL_78_750M 0x00408801
|
||||
#define K800_PLL_80_136M 0x00428801
|
||||
#define K800_PLL_83_375M 0x005B0882
|
||||
#define K800_PLL_83_950M 0x00738803
|
||||
#define K800_PLL_84_750M 0x00748883 /* 84.477MHz */
|
||||
#define K800_PLL_85_860M 0x00768883
|
||||
#define K800_PLL_88_750M 0x007A8883
|
||||
#define K800_PLL_94_500M 0x00828803
|
||||
#define K800_PLL_97_750M 0x00878883
|
||||
#define K800_PLL_101_000M 0x008B8883
|
||||
#define K800_PLL_106_500M 0x00758882 /* 106.491463 MHz */
|
||||
#define K800_PLL_108_000M 0x00778882
|
||||
#define K800_PLL_113_309M 0x005D8881
|
||||
#define K800_PLL_118_840M 0x00A48883
|
||||
#define K800_PLL_119_000M 0x00838882
|
||||
#define K800_PLL_121_750M 0x00A88883 /* 121.704MHz */
|
||||
#define K800_PLL_125_104M 0x00688801
|
||||
#define K800_PLL_133_308M 0x005D8801
|
||||
#define K800_PLL_135_000M 0x001A4081
|
||||
#define K800_PLL_136_700M 0x00BD8883
|
||||
#define K800_PLL_138_400M 0x00728881
|
||||
#define K800_PLL_146_760M 0x00CC8883
|
||||
#define K800_PLL_148_500M 0x00ce0803
|
||||
#define K800_PLL_153_920M 0x00548482
|
||||
#define K800_PLL_156_000M 0x006B8483
|
||||
#define K800_PLL_157_500M 0x00142080
|
||||
#define K800_PLL_162_000M 0x006F8483
|
||||
#define K800_PLL_187_000M 0x00818483
|
||||
#define K800_PLL_193_295M 0x004F8481
|
||||
#define K800_PLL_202_500M 0x00538481
|
||||
#define K800_PLL_204_000M 0x008D8483
|
||||
#define K800_PLL_218_500M 0x00978483
|
||||
#define K800_PLL_234_000M 0x00608401
|
||||
#define K800_PLL_267_250M 0x006E8481
|
||||
#define K800_PLL_297_500M 0x00A48402
|
||||
#define K800_PLL_74_481M 0x007B8C81
|
||||
#define K800_PLL_172_798M 0x00778483
|
||||
#define K800_PLL_122_614M 0x00878882
|
||||
|
||||
/* PLL for VT3324 */
|
||||
#define CX700_25_175M 0x008B1003
|
||||
#define CX700_26_719M 0x00931003
|
||||
#define CX700_26_880M 0x00941003
|
||||
#define CX700_29_581M 0x00A49003
|
||||
#define CX700_31_490M 0x00AE1003
|
||||
#define CX700_31_500M 0x00AE1003
|
||||
#define CX700_31_728M 0x00AF1003
|
||||
#define CX700_32_668M 0x00B51003
|
||||
#define CX700_36_000M 0x00C81003
|
||||
#define CX700_40_000M 0x006E0C03
|
||||
#define CX700_41_291M 0x00710C03
|
||||
#define CX700_43_163M 0x00770C03
|
||||
#define CX700_45_250M 0x007D0C03 /* 45.46MHz */
|
||||
#define CX700_46_000M 0x007F0C03
|
||||
#define CX700_46_996M 0x00818C83
|
||||
#define CX700_48_000M 0x00840C03
|
||||
#define CX700_48_875M 0x00508C81
|
||||
#define CX700_49_500M 0x00880C03
|
||||
#define CX700_52_406M 0x00730C02
|
||||
#define CX700_52_977M 0x00920C03
|
||||
#define CX700_56_250M 0x009B0C03
|
||||
#define CX700_60_466M 0x00460C00
|
||||
#define CX700_61_500M 0x00AA0C03
|
||||
#define CX700_65_000M 0x006B0C01
|
||||
#define CX700_65_178M 0x006B0C01
|
||||
#define CX700_66_750M 0x00940C02 /*67.116MHz */
|
||||
#define CX700_68_179M 0x00BC0C03
|
||||
#define CX700_69_924M 0x00C10C03
|
||||
#define CX700_70_159M 0x00C20C03
|
||||
#define CX700_72_000M 0x009F0C02
|
||||
#define CX700_74_270M 0x00CE0C03
|
||||
#define CX700_74_481M 0x00CE0C03
|
||||
#define CX700_78_750M 0x006C0803
|
||||
#define CX700_80_136M 0x006E0803
|
||||
#define CX700_83_375M 0x005B0882
|
||||
#define CX700_83_950M 0x00730803
|
||||
#define CX700_84_750M 0x00740803 /* 84.537Mhz */
|
||||
#define CX700_85_860M 0x00760803
|
||||
#define CX700_88_750M 0x00AC8885
|
||||
#define CX700_94_500M 0x00820803
|
||||
#define CX700_97_750M 0x00870803
|
||||
#define CX700_101_000M 0x008B0803
|
||||
#define CX700_106_500M 0x00750802
|
||||
#define CX700_108_000M 0x00950803
|
||||
#define CX700_113_309M 0x005D0801
|
||||
#define CX700_118_840M 0x00A40803
|
||||
#define CX700_119_000M 0x00830802
|
||||
#define CX700_121_750M 0x00420800 /* 121.704MHz */
|
||||
#define CX700_125_104M 0x00AD0803
|
||||
#define CX700_133_308M 0x00930802
|
||||
#define CX700_135_000M 0x00950802
|
||||
#define CX700_136_700M 0x00BD0803
|
||||
#define CX700_138_400M 0x00720801
|
||||
#define CX700_146_760M 0x00CC0803
|
||||
#define CX700_148_500M 0x00a40802
|
||||
#define CX700_153_920M 0x00540402
|
||||
#define CX700_156_000M 0x006B0403
|
||||
#define CX700_157_500M 0x006C0403
|
||||
#define CX700_162_000M 0x006F0403
|
||||
#define CX700_172_798M 0x00770403
|
||||
#define CX700_187_000M 0x00810403
|
||||
#define CX700_193_295M 0x00850403
|
||||
#define CX700_202_500M 0x008C0403
|
||||
#define CX700_204_000M 0x008D0403
|
||||
#define CX700_218_500M 0x00970403
|
||||
#define CX700_234_000M 0x00600401
|
||||
#define CX700_267_250M 0x00B90403
|
||||
#define CX700_297_500M 0x00CE0403
|
||||
#define CX700_122_614M 0x00870802
|
||||
|
||||
/* PLL for VX855 */
|
||||
#define VX855_22_000M 0x007B1005
|
||||
#define VX855_25_175M 0x008D1005
|
||||
#define VX855_26_719M 0x00961005
|
||||
#define VX855_26_880M 0x00961005
|
||||
#define VX855_27_000M 0x00971005
|
||||
#define VX855_29_581M 0x00A51005
|
||||
#define VX855_29_829M 0x00641003
|
||||
#define VX855_31_490M 0x00B01005
|
||||
#define VX855_31_500M 0x00B01005
|
||||
#define VX855_31_728M 0x008E1004
|
||||
#define VX855_32_668M 0x00921004
|
||||
#define VX855_36_000M 0x00A11004
|
||||
#define VX855_40_000M 0x00700C05
|
||||
#define VX855_41_291M 0x00730C05
|
||||
#define VX855_43_163M 0x00790C05
|
||||
#define VX855_45_250M 0x007F0C05 /* 45.46MHz */
|
||||
#define VX855_46_000M 0x00670C04
|
||||
#define VX855_46_996M 0x00690C04
|
||||
#define VX855_48_000M 0x00860C05
|
||||
#define VX855_48_875M 0x00890C05
|
||||
#define VX855_49_500M 0x00530C03
|
||||
#define VX855_52_406M 0x00580C03
|
||||
#define VX855_52_977M 0x00940C05
|
||||
#define VX855_56_250M 0x009D0C05
|
||||
#define VX855_57_275M 0x009D8C85 /* Used by XO panel */
|
||||
#define VX855_60_466M 0x00A90C05
|
||||
#define VX855_61_500M 0x00AC0C05
|
||||
#define VX855_65_000M 0x006D0C03
|
||||
#define VX855_65_178M 0x00B60C05
|
||||
#define VX855_66_750M 0x00700C03 /*67.116MHz */
|
||||
#define VX855_67_295M 0x00BC0C05
|
||||
#define VX855_68_179M 0x00BF0C05
|
||||
#define VX855_68_369M 0x00BF0C05
|
||||
#define VX855_69_924M 0x00C30C05
|
||||
#define VX855_70_159M 0x00C30C05
|
||||
#define VX855_72_000M 0x00A10C04
|
||||
#define VX855_73_023M 0x00CC0C05
|
||||
#define VX855_74_481M 0x00D10C05
|
||||
#define VX855_78_750M 0x006E0805
|
||||
#define VX855_79_466M 0x006F0805
|
||||
#define VX855_80_136M 0x00700805
|
||||
#define VX855_81_627M 0x00720805
|
||||
#define VX855_83_375M 0x00750805
|
||||
#define VX855_83_527M 0x00750805
|
||||
#define VX855_83_950M 0x00750805
|
||||
#define VX855_84_537M 0x00760805
|
||||
#define VX855_84_750M 0x00760805 /* 84.537Mhz */
|
||||
#define VX855_85_500M 0x00760805 /* 85.909080 MHz*/
|
||||
#define VX855_85_860M 0x00760805
|
||||
#define VX855_85_909M 0x00760805
|
||||
#define VX855_88_750M 0x007C0805
|
||||
#define VX855_89_489M 0x007D0805
|
||||
#define VX855_94_500M 0x00840805
|
||||
#define VX855_96_648M 0x00870805
|
||||
#define VX855_97_750M 0x00890805
|
||||
#define VX855_101_000M 0x008D0805
|
||||
#define VX855_106_500M 0x00950805
|
||||
#define VX855_108_000M 0x00970805
|
||||
#define VX855_110_125M 0x00990805
|
||||
#define VX855_112_000M 0x009D0805
|
||||
#define VX855_113_309M 0x009F0805
|
||||
#define VX855_115_000M 0x00A10805
|
||||
#define VX855_118_840M 0x00A60805
|
||||
#define VX855_119_000M 0x00A70805
|
||||
#define VX855_121_750M 0x00AA0805 /* 121.704MHz */
|
||||
#define VX855_122_614M 0x00AC0805
|
||||
#define VX855_126_266M 0x00B10805
|
||||
#define VX855_130_250M 0x00B60805 /* 130.250 */
|
||||
#define VX855_135_000M 0x00BD0805
|
||||
#define VX855_136_700M 0x00BF0805
|
||||
#define VX855_137_750M 0x00C10805
|
||||
#define VX855_138_400M 0x00C20805
|
||||
#define VX855_144_300M 0x00CA0805
|
||||
#define VX855_146_760M 0x00CE0805
|
||||
#define VX855_148_500M 0x00D00805
|
||||
#define VX855_153_920M 0x00540402
|
||||
#define VX855_156_000M 0x006C0405
|
||||
#define VX855_156_867M 0x006E0405
|
||||
#define VX855_157_500M 0x006E0405
|
||||
#define VX855_162_000M 0x00710405
|
||||
#define VX855_172_798M 0x00790405
|
||||
#define VX855_187_000M 0x00830405
|
||||
#define VX855_193_295M 0x00870405
|
||||
#define VX855_202_500M 0x008E0405
|
||||
#define VX855_204_000M 0x008F0405
|
||||
#define VX855_218_500M 0x00990405
|
||||
#define VX855_229_500M 0x00A10405
|
||||
#define VX855_234_000M 0x00A40405
|
||||
#define VX855_267_250M 0x00BB0405
|
||||
#define VX855_297_500M 0x00D00405
|
||||
#define VX855_339_500M 0x00770005
|
||||
#define VX855_340_772M 0x00770005
|
||||
|
||||
|
||||
/* Definition CRTC Timing Index */
|
||||
#define H_TOTAL_INDEX 0
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ static inline int viafb_mmio_read(int reg)
|
|||
*/
|
||||
static u32 viafb_enabled_ints;
|
||||
|
||||
static void viafb_int_init(void)
|
||||
static void __devinit viafb_int_init(void)
|
||||
{
|
||||
viafb_enabled_ints = 0;
|
||||
|
||||
|
|
@ -489,7 +489,7 @@ out_unmap:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev)
|
||||
static void via_pci_teardown_mmio(struct viafb_dev *vdev)
|
||||
{
|
||||
iounmap(vdev->fbmem);
|
||||
iounmap(vdev->engine_mmio);
|
||||
|
|
@ -548,7 +548,7 @@ static int __devinit via_setup_subdevs(struct viafb_dev *vdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit via_teardown_subdevs(void)
|
||||
static void via_teardown_subdevs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -613,22 +613,24 @@ static void __devexit via_pci_remove(struct pci_dev *pdev)
|
|||
static struct pci_device_id via_pci_table[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
|
||||
.driver_data = UNICHROME_CLE266 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
|
||||
.driver_data = UNICHROME_PM800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
|
||||
.driver_data = UNICHROME_K400 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
|
||||
.driver_data = UNICHROME_K800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
|
||||
.driver_data = UNICHROME_PM800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN700_DID),
|
||||
.driver_data = UNICHROME_CN700 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
|
||||
.driver_data = UNICHROME_K8M890 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
|
||||
.driver_data = UNICHROME_CX700 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
|
||||
.driver_data = UNICHROME_P4M900 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
|
||||
.driver_data = UNICHROME_CN750 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
|
||||
.driver_data = UNICHROME_K8M890 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
|
||||
.driver_data = UNICHROME_P4M890 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
|
||||
.driver_data = UNICHROME_P4M900 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
|
||||
.driver_data = UNICHROME_VX800 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ struct viafb_gpio_cfg {
|
|||
struct gpio_chip gpio_chip;
|
||||
struct viafb_dev *vdev;
|
||||
struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS];
|
||||
char *gpio_names[VIAFB_NUM_GPIOS];
|
||||
const char *gpio_names[VIAFB_NUM_GPIOS];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ char *viafb_active_dev;
|
|||
char *viafb_lcd_port = "";
|
||||
char *viafb_dvi_port = "";
|
||||
|
||||
static void viafb_set_device(struct device_t active_dev);
|
||||
static int apply_device_setting(struct viafb_ioctl_setting setting_info,
|
||||
struct fb_info *info);
|
||||
static void apply_second_mode_setting(struct fb_var_screeninfo
|
||||
*sec_var);
|
||||
static void retrieve_device_setting(struct viafb_ioctl_setting
|
||||
*setting_info);
|
||||
static int viafb_pan_display(struct fb_var_screeninfo *var,
|
||||
|
|
@ -221,9 +216,9 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
|
|||
|
||||
/* Adjust var according to our driver's own table */
|
||||
viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry);
|
||||
if (info->var.accel_flags & FB_ACCELF_TEXT &&
|
||||
if (var->accel_flags & FB_ACCELF_TEXT &&
|
||||
!ppar->shared->vdev->engine_mmio)
|
||||
info->var.accel_flags = 0;
|
||||
var->accel_flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -234,6 +229,7 @@ static int viafb_set_par(struct fb_info *info)
|
|||
struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
|
||||
DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
|
||||
|
||||
viafb_update_fix(info);
|
||||
viapar->depth = fb_get_color_depth(&info->var, &info->fix);
|
||||
viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
|
||||
viafbinfo->var.bits_per_pixel, viafb_refresh, 0);
|
||||
|
|
@ -257,7 +253,6 @@ static int viafb_set_par(struct fb_info *info)
|
|||
}
|
||||
|
||||
if (vmode_entry) {
|
||||
viafb_update_fix(info);
|
||||
if (viafb_dual_fb && viapar->iga_path == IGA2)
|
||||
viafb_bpp1 = info->var.bits_per_pixel;
|
||||
else
|
||||
|
|
@ -478,13 +473,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
|
|||
if (gpu32 & LCD_Device)
|
||||
viafb_lcd_disable();
|
||||
break;
|
||||
case VIAFB_SET_DEVICE:
|
||||
if (copy_from_user(&u.active_dev, (void *)argp,
|
||||
sizeof(u.active_dev)))
|
||||
return -EFAULT;
|
||||
viafb_set_device(u.active_dev);
|
||||
viafb_set_par(info);
|
||||
break;
|
||||
case VIAFB_GET_DEVICE:
|
||||
u.active_dev.crt = viafb_CRT_ON;
|
||||
u.active_dev.dvi = viafb_DVI_ON;
|
||||
|
|
@ -527,21 +515,6 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
|
|||
|
||||
break;
|
||||
|
||||
case VIAFB_SET_DEVICE_INFO:
|
||||
if (copy_from_user(&u.viafb_setting,
|
||||
argp, sizeof(u.viafb_setting)))
|
||||
return -EFAULT;
|
||||
if (apply_device_setting(u.viafb_setting, info) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
|
||||
case VIAFB_SET_SECOND_MODE:
|
||||
if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var)))
|
||||
return -EFAULT;
|
||||
apply_second_mode_setting(&u.sec_var);
|
||||
break;
|
||||
|
||||
case VIAFB_GET_DEVICE_INFO:
|
||||
|
||||
retrieve_device_setting(&u.viafb_setting);
|
||||
|
|
@ -913,112 +886,6 @@ static int viafb_sync(struct fb_info *info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void check_available_device_to_enable(int device_id)
|
||||
{
|
||||
int device_num = 0;
|
||||
|
||||
/* Initialize: */
|
||||
viafb_CRT_ON = STATE_OFF;
|
||||
viafb_DVI_ON = STATE_OFF;
|
||||
viafb_LCD_ON = STATE_OFF;
|
||||
viafb_LCD2_ON = STATE_OFF;
|
||||
viafb_DeviceStatus = None_Device;
|
||||
|
||||
if ((device_id & CRT_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
|
||||
viafb_CRT_ON = STATE_ON;
|
||||
device_num++;
|
||||
viafb_DeviceStatus |= CRT_Device;
|
||||
}
|
||||
|
||||
if ((device_id & DVI_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
|
||||
viafb_DVI_ON = STATE_ON;
|
||||
device_num++;
|
||||
viafb_DeviceStatus |= DVI_Device;
|
||||
}
|
||||
|
||||
if ((device_id & LCD_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
|
||||
viafb_LCD_ON = STATE_ON;
|
||||
device_num++;
|
||||
viafb_DeviceStatus |= LCD_Device;
|
||||
}
|
||||
|
||||
if ((device_id & LCD2_Device) && (device_num < MAX_ACTIVE_DEV_NUM)) {
|
||||
viafb_LCD2_ON = STATE_ON;
|
||||
device_num++;
|
||||
viafb_DeviceStatus |= LCD2_Device;
|
||||
}
|
||||
|
||||
if (viafb_DeviceStatus == None_Device) {
|
||||
/* Use CRT as default active device: */
|
||||
viafb_CRT_ON = STATE_ON;
|
||||
viafb_DeviceStatus = CRT_Device;
|
||||
}
|
||||
DEBUG_MSG(KERN_INFO "Device Status:%x", viafb_DeviceStatus);
|
||||
}
|
||||
|
||||
static void viafb_set_device(struct device_t active_dev)
|
||||
{
|
||||
/* Check available device to enable: */
|
||||
int device_id = None_Device;
|
||||
if (active_dev.crt)
|
||||
device_id |= CRT_Device;
|
||||
if (active_dev.dvi)
|
||||
device_id |= DVI_Device;
|
||||
if (active_dev.lcd)
|
||||
device_id |= LCD_Device;
|
||||
|
||||
check_available_device_to_enable(device_id);
|
||||
|
||||
/* Check property of LCD: */
|
||||
if (viafb_LCD_ON) {
|
||||
if (active_dev.lcd_dsp_cent) {
|
||||
viaparinfo->lvds_setting_info->display_method =
|
||||
viafb_lcd_dsp_method = LCD_CENTERING;
|
||||
} else {
|
||||
viaparinfo->lvds_setting_info->display_method =
|
||||
viafb_lcd_dsp_method = LCD_EXPANDSION;
|
||||
}
|
||||
|
||||
if (active_dev.lcd_mode == LCD_SPWG) {
|
||||
viaparinfo->lvds_setting_info->lcd_mode =
|
||||
viafb_lcd_mode = LCD_SPWG;
|
||||
} else {
|
||||
viaparinfo->lvds_setting_info->lcd_mode =
|
||||
viafb_lcd_mode = LCD_OPENLDI;
|
||||
}
|
||||
|
||||
if (active_dev.lcd_panel_id <= LCD_PANEL_ID_MAXIMUM) {
|
||||
viafb_lcd_panel_id = active_dev.lcd_panel_id;
|
||||
viafb_init_lcd_size();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check property of mode: */
|
||||
if (!active_dev.xres1)
|
||||
viafb_second_xres = 640;
|
||||
else
|
||||
viafb_second_xres = active_dev.xres1;
|
||||
if (!active_dev.yres1)
|
||||
viafb_second_yres = 480;
|
||||
else
|
||||
viafb_second_yres = active_dev.yres1;
|
||||
if (active_dev.bpp != 0)
|
||||
viafb_bpp = active_dev.bpp;
|
||||
if (active_dev.bpp1 != 0)
|
||||
viafb_bpp1 = active_dev.bpp1;
|
||||
if (active_dev.refresh != 0)
|
||||
viafb_refresh = active_dev.refresh;
|
||||
if (active_dev.refresh1 != 0)
|
||||
viafb_refresh1 = active_dev.refresh1;
|
||||
if ((active_dev.samm == STATE_OFF) || (active_dev.samm == STATE_ON))
|
||||
viafb_SAMM_ON = active_dev.samm;
|
||||
viafb_primary_dev = active_dev.primary_dev;
|
||||
|
||||
via_set_primary_address(0);
|
||||
via_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
|
||||
viafb_set_iga_path();
|
||||
}
|
||||
|
||||
static int get_primary_device(void)
|
||||
{
|
||||
int primary_device = 0;
|
||||
|
|
@ -1060,124 +927,6 @@ static int get_primary_device(void)
|
|||
return primary_device;
|
||||
}
|
||||
|
||||
static void apply_second_mode_setting(struct fb_var_screeninfo
|
||||
*sec_var)
|
||||
{
|
||||
u32 htotal, vtotal, long_refresh;
|
||||
|
||||
htotal = sec_var->xres + sec_var->left_margin +
|
||||
sec_var->right_margin + sec_var->hsync_len;
|
||||
vtotal = sec_var->yres + sec_var->upper_margin +
|
||||
sec_var->lower_margin + sec_var->vsync_len;
|
||||
if ((sec_var->xres_virtual * (sec_var->bits_per_pixel >> 3)) & 0x1F) {
|
||||
/*Is 32 bytes alignment? */
|
||||
/*32 pixel alignment */
|
||||
sec_var->xres_virtual = (sec_var->xres_virtual + 31) & ~31;
|
||||
}
|
||||
|
||||
htotal = sec_var->xres + sec_var->left_margin +
|
||||
sec_var->right_margin + sec_var->hsync_len;
|
||||
vtotal = sec_var->yres + sec_var->upper_margin +
|
||||
sec_var->lower_margin + sec_var->vsync_len;
|
||||
long_refresh = 1000000000UL / sec_var->pixclock * 1000;
|
||||
long_refresh /= (htotal * vtotal);
|
||||
|
||||
viafb_second_xres = sec_var->xres;
|
||||
viafb_second_yres = sec_var->yres;
|
||||
viafb_second_virtual_xres = sec_var->xres_virtual;
|
||||
viafb_second_virtual_yres = sec_var->yres_virtual;
|
||||
viafb_bpp1 = sec_var->bits_per_pixel;
|
||||
viafb_refresh1 = viafb_get_refresh(sec_var->xres, sec_var->yres,
|
||||
long_refresh);
|
||||
}
|
||||
|
||||
static int apply_device_setting(struct viafb_ioctl_setting setting_info,
|
||||
struct fb_info *info)
|
||||
{
|
||||
int need_set_mode = 0;
|
||||
DEBUG_MSG(KERN_INFO "apply_device_setting\n");
|
||||
|
||||
if (setting_info.device_flag) {
|
||||
need_set_mode = 1;
|
||||
check_available_device_to_enable(setting_info.device_status);
|
||||
}
|
||||
|
||||
/* Unlock LCD's operation according to LCD flag
|
||||
and check if the setting value is valid. */
|
||||
/* If the value is valid, apply the new setting value to the device. */
|
||||
if (viafb_LCD_ON) {
|
||||
if (setting_info.lcd_operation_flag & OP_LCD_CENTERING) {
|
||||
need_set_mode = 1;
|
||||
if (setting_info.lcd_attributes.display_center) {
|
||||
/* Centering */
|
||||
viaparinfo->lvds_setting_info->display_method =
|
||||
LCD_CENTERING;
|
||||
viafb_lcd_dsp_method = LCD_CENTERING;
|
||||
viaparinfo->lvds_setting_info2->display_method =
|
||||
viafb_lcd_dsp_method = LCD_CENTERING;
|
||||
} else {
|
||||
/* expandsion */
|
||||
viaparinfo->lvds_setting_info->display_method =
|
||||
LCD_EXPANDSION;
|
||||
viafb_lcd_dsp_method = LCD_EXPANDSION;
|
||||
viaparinfo->lvds_setting_info2->display_method =
|
||||
LCD_EXPANDSION;
|
||||
viafb_lcd_dsp_method = LCD_EXPANDSION;
|
||||
}
|
||||
}
|
||||
|
||||
if (setting_info.lcd_operation_flag & OP_LCD_MODE) {
|
||||
need_set_mode = 1;
|
||||
if (setting_info.lcd_attributes.lcd_mode ==
|
||||
LCD_SPWG) {
|
||||
viaparinfo->lvds_setting_info->lcd_mode =
|
||||
viafb_lcd_mode = LCD_SPWG;
|
||||
} else {
|
||||
viaparinfo->lvds_setting_info->lcd_mode =
|
||||
viafb_lcd_mode = LCD_OPENLDI;
|
||||
}
|
||||
viaparinfo->lvds_setting_info2->lcd_mode =
|
||||
viaparinfo->lvds_setting_info->lcd_mode;
|
||||
}
|
||||
|
||||
if (setting_info.lcd_operation_flag & OP_LCD_PANEL_ID) {
|
||||
need_set_mode = 1;
|
||||
if (setting_info.lcd_attributes.panel_id <=
|
||||
LCD_PANEL_ID_MAXIMUM) {
|
||||
viafb_lcd_panel_id =
|
||||
setting_info.lcd_attributes.panel_id;
|
||||
viafb_init_lcd_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != (setting_info.samm_status & OP_SAMM)) {
|
||||
setting_info.samm_status =
|
||||
setting_info.samm_status & (~OP_SAMM);
|
||||
if (setting_info.samm_status == 0
|
||||
|| setting_info.samm_status == 1) {
|
||||
viafb_SAMM_ON = setting_info.samm_status;
|
||||
|
||||
if (viafb_SAMM_ON)
|
||||
viafb_primary_dev = setting_info.primary_device;
|
||||
|
||||
via_set_primary_address(0);
|
||||
via_set_secondary_address(viafb_SAMM_ON ?
|
||||
viafb_second_offset : 0);
|
||||
viafb_set_iga_path();
|
||||
}
|
||||
need_set_mode = 1;
|
||||
}
|
||||
|
||||
if (!need_set_mode) {
|
||||
;
|
||||
} else {
|
||||
viafb_set_iga_path();
|
||||
viafb_set_par(info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void retrieve_device_setting(struct viafb_ioctl_setting
|
||||
*setting_info)
|
||||
{
|
||||
|
|
@ -1776,10 +1525,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
|
|||
parse_lcd_port();
|
||||
parse_dvi_port();
|
||||
|
||||
/* for dual-fb must viafb_SAMM_ON=1 and viafb_dual_fb=1 */
|
||||
if (!viafb_SAMM_ON)
|
||||
viafb_dual_fb = 0;
|
||||
|
||||
viafb_init_chip_info(vdev->chip_type);
|
||||
/*
|
||||
* The framebuffer will have been successfully mapped by
|
||||
|
|
@ -1823,30 +1568,13 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
|
|||
parse_mode(viafb_mode1, &viafb_second_xres,
|
||||
&viafb_second_yres);
|
||||
|
||||
if (0 == viafb_second_virtual_xres) {
|
||||
switch (viafb_second_xres) {
|
||||
case 1400:
|
||||
viafb_second_virtual_xres = 1408;
|
||||
break;
|
||||
default:
|
||||
viafb_second_virtual_xres = viafb_second_xres;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 == viafb_second_virtual_yres)
|
||||
viafb_second_virtual_yres = viafb_second_yres;
|
||||
viafb_second_virtual_xres = viafb_second_xres;
|
||||
viafb_second_virtual_yres = viafb_second_yres;
|
||||
}
|
||||
|
||||
default_var.xres = default_xres;
|
||||
default_var.yres = default_yres;
|
||||
switch (default_xres) {
|
||||
case 1400:
|
||||
default_var.xres_virtual = 1408;
|
||||
break;
|
||||
default:
|
||||
default_var.xres_virtual = default_xres;
|
||||
break;
|
||||
}
|
||||
default_var.xres_virtual = default_xres;
|
||||
default_var.yres_virtual = default_yres;
|
||||
default_var.bits_per_pixel = viafb_bpp;
|
||||
default_var.pixclock =
|
||||
|
|
|
|||
|
|
@ -726,7 +726,9 @@ static int __devinit vt8623_pci_probe(struct pci_dev *dev, const struct pci_devi
|
|||
|
||||
/* Prepare startup mode */
|
||||
|
||||
kparam_block_sysfs_write(mode_option);
|
||||
rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
|
||||
kparam_unblock_sysfs_write(mode_option);
|
||||
if (! ((rc == 1) || (rc == 2))) {
|
||||
rc = -EINVAL;
|
||||
dev_err(info->device, "mode %s not found\n", mode_option);
|
||||
|
|
|
|||
|
|
@ -858,9 +858,9 @@ unsigned long w100fb_gpio_read(int port)
|
|||
void w100fb_gpio_write(int port, unsigned long value)
|
||||
{
|
||||
if (port==W100_GPIO_PORT_A)
|
||||
value = writel(value, remapped_regs + mmGPIO_DATA);
|
||||
writel(value, remapped_regs + mmGPIO_DATA);
|
||||
else
|
||||
value = writel(value, remapped_regs + mmGPIO_DATA2);
|
||||
writel(value, remapped_regs + mmGPIO_DATA2);
|
||||
}
|
||||
EXPORT_SYMBOL(w100fb_gpio_read);
|
||||
EXPORT_SYMBOL(w100fb_gpio_write);
|
||||
|
|
|
|||
|
|
@ -684,7 +684,7 @@ static struct xenbus_driver xenfb_driver = {
|
|||
|
||||
static int __init xenfb_init(void)
|
||||
{
|
||||
if (!xen_domain())
|
||||
if (!xen_pv_domain())
|
||||
return -ENODEV;
|
||||
|
||||
/* Nothing to do if running in dom0. */
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ static int xilinxfb_release(struct device *dev)
|
|||
*/
|
||||
|
||||
static int __devinit
|
||||
xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
|
||||
xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
|
||||
{
|
||||
const u32 *prop;
|
||||
u32 *p;
|
||||
|
|
@ -477,7 +477,7 @@ xilinxfb_of_probe(struct of_device *op, const struct of_device_id *match)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __devexit xilinxfb_of_remove(struct of_device *op)
|
||||
static int __devexit xilinxfb_of_remove(struct platform_device *op)
|
||||
{
|
||||
return xilinxfb_release(&op->dev);
|
||||
}
|
||||
|
|
@ -485,6 +485,8 @@ static int __devexit xilinxfb_of_remove(struct of_device *op)
|
|||
/* Match table for of_platform binding */
|
||||
static struct of_device_id xilinxfb_of_match[] __devinitdata = {
|
||||
{ .compatible = "xlnx,xps-tft-1.00.a", },
|
||||
{ .compatible = "xlnx,xps-tft-2.00.a", },
|
||||
{ .compatible = "xlnx,xps-tft-2.01.a", },
|
||||
{ .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", },
|
||||
{ .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", },
|
||||
{},
|
||||
|
|
|
|||
Loading…
Reference in a new issue