mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
fbdev updates for 3.7
It includes:
- large updates for OMAP
- basic OMAP5 DSS support for DPI and DSI outputs
- large cleanups and restructuring
- some update to Exynos and da8xx-fb
- removal of the pnx4008 driver (arch removed)
- various other small patches
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.12 (GNU/Linux)
iQIcBAABAgAGBQJQdz+EAAoJECSVL5KnPj1PyiMP/R84rSfGUbDIh0Cr6g1Snk76
h2/1i19TuEgJAWH1q0lnwhqMC3yYmkA1Hz3ulT35KS+/L3IEgUosOESrxZIJhxHI
f55pk3v8dueN0rx3OhCknLT7hGpVsI4vSN+3yf9LetDp3qt8UVwKLFzVij1VF/MS
b1wA+RBe1IYMR0bB6pK0AgMZZiBkQMta5rKs5IfDDi8kMgMT4+V8l/iFmt2Ue833
VxdPw+3reKshBXKTkQt1Usv4JRtG7OgwpRmFhxOo+ag0dxPLeUe/3wZG54qfOywF
7jK+mnxmW8oZxLkGBvygrmzd40MH6H09N7i/IKVQ0GZoHgAqWWe7VvWahpg8LzwB
ynktwWZ3Va98p5u/BIafBr0ZOU30mPL8N0aqR3HU7H12Wq21HtwcF+ewiT4vnMc8
CKzt6VL0qY1tOOdzJzmICzvXGkbBGfj9YOUptJALCIa3bLwZodyQ/bKq8V/bHdTg
2yyUmVhVf/r5qLermjQN8TjFMpRf2SNwTUUYvhUNwZ4yZMVWZgjjhtAlGGFCA/Bs
qMRuNpbHMedhzNV4py418Xe3Hwg6TLPuWSWGJ67SG8hxsYy2hq7GebSsXXdC7xG9
N5DMpA88IQR2nLwkr/pslFqjRsUI6ULvIfxibHEoNjQ0GOY9f+hEWbdHBZPI+0Gv
Ea9d7nyhmYTZgvRcd9U0
=EJUS
-----END PGP SIGNATURE-----
Merge tag 'fbdev-updates-for-3.7' of git://github.com/schandinat/linux-2.6
Pull fbdev updates from Florian Tobias Schandinat:
"This includes:
- large updates for OMAP
- basic OMAP5 DSS support for DPI and DSI outputs
- large cleanups and restructuring
- some update to Exynos and da8xx-fb
- removal of the pnx4008 driver (arch removed)
- various other small patches"
Fix up some trivial conflicts (mostly just include line changes, but
also some due to the renaming of the deferred work functions by Tejun).
* tag 'fbdev-updates-for-3.7' of git://github.com/schandinat/linux-2.6: (193 commits)
gbefb: fix compile error
video: mark nuc900fb_map_video_memory as __devinit
video/mx3fb: set .owner to prevent module unloading while being used
video: exynos_dp: use clk_prepare_enable and clk_disable_unprepare
drivers/video/exynos/exynos_mipi_dsi.c: fix error return code
drivers/video/savage/savagefb_driver.c: fix error return code
video: s3c-fb: use clk_prepare_enable and clk_disable_unprepare
da8xx-fb: save and restore LCDC context across suspend/resume cycle
da8xx-fb: add pm_runtime support
video/udlfb: fix line counting in fb_write
OMAPDSS: add missing include for string.h
OMAPDSS: DISPC: Configure color conversion coefficients for writeback
OMAPDSS: DISPC: Add manager like functions for writeback
OMAPDSS: DISPC: Configure writeback FIFOs
OMAPDSS: DISPC: Configure writeback specific parameters in dispc_wb_setup()
OMAPDSS: DISPC: Configure overlay-like parameters in dispc_wb_setup
OMAPDSS: DISPC: Add function to set channel in for writeback
OMAPDSS: DISPC: Don't set chroma resampling bit for writeback
OMAPDSS: DISPC: Downscale chroma if plane is writeback
OMAPDSS: DISPC: Configure input and output sizes for writeback
...
This commit is contained in:
commit
5f76945a9c
127 changed files with 5347 additions and 4718 deletions
|
|
@ -2139,21 +2139,6 @@ config FB_UDL
|
|||
mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
|
||||
To compile as a module, choose M here: the module name is udlfb.
|
||||
|
||||
config FB_PNX4008_DUM
|
||||
tristate "Display Update Module support on Philips PNX4008 board"
|
||||
depends on FB && ARCH_PNX4008
|
||||
---help---
|
||||
Say Y here to enable support for PNX4008 Display Update Module (DUM)
|
||||
|
||||
config FB_PNX4008_DUM_RGB
|
||||
tristate "RGB Framebuffer support on Philips PNX4008 board"
|
||||
depends on FB_PNX4008_DUM
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
---help---
|
||||
Say Y here to enable support for PNX4008 RGB Framebuffer
|
||||
|
||||
config FB_IBM_GXT4500
|
||||
tristate "Framebuffer support for IBM GXT4500P adaptor"
|
||||
depends on FB && PPC
|
||||
|
|
|
|||
|
|
@ -127,8 +127,6 @@ obj-$(CONFIG_FB_S3C) += s3c-fb.o
|
|||
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
|
||||
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
|
||||
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
|
||||
obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
|
||||
obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
|
||||
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
|
||||
obj-$(CONFIG_FB_PS3) += ps3fb.o
|
||||
obj-$(CONFIG_FB_SM501) += sm501fb.o
|
||||
|
|
|
|||
|
|
@ -949,7 +949,6 @@ static int round_down_bpp = 1; /* for mode probing */
|
|||
|
||||
|
||||
static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
|
||||
static int amifb_inverse = 0;
|
||||
|
||||
static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
|
||||
static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
|
||||
|
|
@ -2355,7 +2354,6 @@ static int __init amifb_setup(char *options)
|
|||
if (!*this_opt)
|
||||
continue;
|
||||
if (!strcmp(this_opt, "inverse")) {
|
||||
amifb_inverse = 1;
|
||||
fb_invert_cmaps();
|
||||
} else if (!strcmp(this_opt, "ilbm"))
|
||||
amifb_ilbm = 1;
|
||||
|
|
|
|||
|
|
@ -552,6 +552,7 @@ static int __devinit arcfb_probe(struct platform_device *dev)
|
|||
"arcfb", info)) {
|
||||
printk(KERN_INFO
|
||||
"arcfb: Failed req IRQ %d\n", par->irq);
|
||||
retval = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -931,8 +931,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
|
||||
if (!info->screen_base)
|
||||
if (!info->screen_base) {
|
||||
ret = -ENOMEM;
|
||||
goto release_intmem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't clear the framebuffer -- someone may have set
|
||||
|
|
@ -960,6 +962,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
|
|||
sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
|
||||
if (!sinfo->mmio) {
|
||||
dev_err(dev, "cannot map LCDC registers\n");
|
||||
ret = -ENOMEM;
|
||||
goto release_mem;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -760,18 +760,20 @@ static int __devinit bfin_lq035_probe(struct platform_device *pdev)
|
|||
bfin_lq035_fb.flags = FBINFO_DEFAULT;
|
||||
|
||||
|
||||
bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
|
||||
bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev,
|
||||
sizeof(u32) * 16,
|
||||
GFP_KERNEL);
|
||||
if (bfin_lq035_fb.pseudo_palette == NULL) {
|
||||
pr_err("failed to allocate pseudo_palette\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_palette;
|
||||
goto out_table;
|
||||
}
|
||||
|
||||
if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
|
||||
pr_err("failed to allocate colormap (%d entries)\n",
|
||||
NBR_PALETTE);
|
||||
ret = -EFAULT;
|
||||
goto out_cmap;
|
||||
goto out_table;
|
||||
}
|
||||
|
||||
if (register_framebuffer(&bfin_lq035_fb) < 0) {
|
||||
|
|
@ -804,9 +806,6 @@ out_lcd:
|
|||
unregister_framebuffer(&bfin_lq035_fb);
|
||||
out_reg:
|
||||
fb_dealloc_cmap(&bfin_lq035_fb.cmap);
|
||||
out_cmap:
|
||||
kfree(bfin_lq035_fb.pseudo_palette);
|
||||
out_palette:
|
||||
out_table:
|
||||
dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
|
||||
fb_buffer = NULL;
|
||||
|
|
@ -834,7 +833,6 @@ static int __devexit bfin_lq035_remove(struct platform_device *pdev)
|
|||
free_dma(CH_PPI);
|
||||
|
||||
|
||||
kfree(bfin_lq035_fb.pseudo_palette);
|
||||
fb_dealloc_cmap(&bfin_lq035_fb.cmap);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -525,6 +525,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
|
|||
info = fbinfo->par;
|
||||
info->fb = fbinfo;
|
||||
info->dev = &pdev->dev;
|
||||
spin_lock_init(&info->lock);
|
||||
|
||||
platform_set_drvdata(pdev, fbinfo);
|
||||
|
||||
|
|
@ -601,7 +602,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
|
|||
|
||||
fbinfo->fbops = &bfin_bf54x_fb_ops;
|
||||
|
||||
fbinfo->pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
|
||||
fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
|
||||
GFP_KERNEL);
|
||||
if (!fbinfo->pseudo_palette) {
|
||||
printk(KERN_ERR DRIVER_NAME
|
||||
"Fail to allocate pseudo_palette\n");
|
||||
|
|
@ -616,7 +618,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
|
|||
"Fail to allocate colormap (%d entries)\n",
|
||||
BFIN_LCD_NBR_PALETTE_ENTRIES);
|
||||
ret = -EFAULT;
|
||||
goto out5;
|
||||
goto out4;
|
||||
}
|
||||
|
||||
if (request_ports(info)) {
|
||||
|
|
@ -671,8 +673,6 @@ out7:
|
|||
free_ports(info);
|
||||
out6:
|
||||
fb_dealloc_cmap(&fbinfo->cmap);
|
||||
out5:
|
||||
kfree(fbinfo->pseudo_palette);
|
||||
out4:
|
||||
dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
|
||||
info->dma_handle);
|
||||
|
|
@ -699,7 +699,6 @@ static int __devexit bfin_bf54x_remove(struct platform_device *pdev)
|
|||
dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
|
||||
info->dma_handle);
|
||||
|
||||
kfree(fbinfo->pseudo_palette);
|
||||
fb_dealloc_cmap(&fbinfo->cmap);
|
||||
|
||||
#ifndef NO_BL_SUPPORT
|
||||
|
|
|
|||
|
|
@ -577,6 +577,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
|
|||
info = fbinfo->par;
|
||||
info->fb = fbinfo;
|
||||
info->dev = &pdev->dev;
|
||||
spin_lock_init(&info->lock);
|
||||
|
||||
info->disp_info = pdev->dev.platform_data;
|
||||
|
||||
|
|
@ -853,17 +854,7 @@ static struct platform_driver bfin_lq035q1_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init bfin_lq035q1_driver_init(void)
|
||||
{
|
||||
return platform_driver_register(&bfin_lq035q1_driver);
|
||||
}
|
||||
module_init(bfin_lq035q1_driver_init);
|
||||
|
||||
static void __exit bfin_lq035q1_driver_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&bfin_lq035q1_driver);
|
||||
}
|
||||
module_exit(bfin_lq035q1_driver_cleanup);
|
||||
module_platform_driver(bfin_lq035q1_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -447,6 +447,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
|
|||
info = fbinfo->par;
|
||||
info->fb = fbinfo;
|
||||
info->dev = &pdev->dev;
|
||||
spin_lock_init(&info->lock);
|
||||
|
||||
platform_set_drvdata(pdev, fbinfo);
|
||||
|
||||
|
|
|
|||
|
|
@ -319,8 +319,10 @@ static int __devinit bw2_probe(struct platform_device *op)
|
|||
|
||||
info->screen_base = of_ioremap(&op->resource[0], 0,
|
||||
info->fix.smem_len, "bw2 ram");
|
||||
if (!info->screen_base)
|
||||
if (!info->screen_base) {
|
||||
err = -ENOMEM;
|
||||
goto out_unmap_regs;
|
||||
}
|
||||
|
||||
bw2_blank(FB_BLANK_UNBLANK, info);
|
||||
|
||||
|
|
|
|||
|
|
@ -398,7 +398,8 @@ static int __devinit cg3_probe(struct platform_device *op)
|
|||
goto out_unmap_screen;
|
||||
}
|
||||
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
err = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (err)
|
||||
goto out_unmap_screen;
|
||||
|
||||
fb_set_cmap(&info->cmap, info);
|
||||
|
|
|
|||
|
|
@ -348,7 +348,8 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
|
|||
}
|
||||
|
||||
info->screen_size = resource_size(res);
|
||||
info->screen_base = ioremap(res->start, info->screen_size);
|
||||
info->screen_base = devm_ioremap(&dev->dev, res->start,
|
||||
info->screen_size);
|
||||
info->fbops = &cobalt_lcd_fbops;
|
||||
info->fix = cobalt_lcdfb_fix;
|
||||
info->fix.smem_start = res->start;
|
||||
|
|
@ -359,7 +360,6 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
|
|||
|
||||
retval = register_framebuffer(info);
|
||||
if (retval < 0) {
|
||||
iounmap(info->screen_base);
|
||||
framebuffer_release(info);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -380,7 +380,6 @@ static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
|
|||
|
||||
info = platform_get_drvdata(dev);
|
||||
if (info) {
|
||||
iounmap(info->screen_base);
|
||||
unregister_framebuffer(info);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1092,7 +1092,7 @@ static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
|
|||
/*{*/ /* Char 124: '|' */
|
||||
0x44, /*= [ * ] */
|
||||
0x44, /*= [ * ] */
|
||||
0x00, /*= [ ] */
|
||||
0x44, /*= [ * ] */
|
||||
0x44, /*= [ * ] */
|
||||
0x44, /*= [ * ] */
|
||||
0x00, /*= [ ] */
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
|
|||
/*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
|
||||
/*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
|
||||
/*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
|
||||
/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
/*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
|
||||
/*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
|
||||
|
|
|
|||
|
|
@ -1804,8 +1804,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
|
||||
cfb->irq = dev->irq;
|
||||
cfb->region = pci_ioremap_bar(dev, 0);
|
||||
if (!cfb->region)
|
||||
if (!cfb->region) {
|
||||
err = -ENOMEM;
|
||||
goto failed_ioremap;
|
||||
}
|
||||
|
||||
cfb->regs = cfb->region + MMIO_OFFSET;
|
||||
cfb->fb.device = &dev->dev;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/console.h>
|
||||
|
|
@ -48,6 +50,7 @@
|
|||
#define LCD_PL_LOAD_DONE BIT(6)
|
||||
#define LCD_FIFO_UNDERFLOW BIT(5)
|
||||
#define LCD_SYNC_LOST BIT(2)
|
||||
#define LCD_FRAME_DONE BIT(0)
|
||||
|
||||
/* LCD DMA Control Register */
|
||||
#define LCD_DMA_BURST_SIZE(x) ((x) << 4)
|
||||
|
|
@ -86,6 +89,8 @@
|
|||
#define LCD_V2_LIDD_CLK_EN BIT(1)
|
||||
#define LCD_V2_CORE_CLK_EN BIT(0)
|
||||
#define LCD_V2_LPP_B10 26
|
||||
#define LCD_V2_TFT_24BPP_MODE BIT(25)
|
||||
#define LCD_V2_TFT_24BPP_UNPACK BIT(26)
|
||||
|
||||
/* LCD Raster Timing 2 Register */
|
||||
#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
|
||||
|
|
@ -135,6 +140,8 @@ static void __iomem *da8xx_fb_reg_base;
|
|||
static struct resource *lcdc_regs;
|
||||
static unsigned int lcd_revision;
|
||||
static irq_handler_t lcdc_irq_handler;
|
||||
static wait_queue_head_t frame_done_wq;
|
||||
static int frame_done_flag;
|
||||
|
||||
static inline unsigned int lcdc_read(unsigned int addr)
|
||||
{
|
||||
|
|
@ -156,7 +163,6 @@ struct da8xx_fb_par {
|
|||
unsigned int dma_end;
|
||||
struct clk *lcdc_clk;
|
||||
int irq;
|
||||
unsigned short pseudo_palette[16];
|
||||
unsigned int palette_sz;
|
||||
unsigned int pxl_clk;
|
||||
int blank;
|
||||
|
|
@ -175,6 +181,7 @@ struct da8xx_fb_par {
|
|||
unsigned int lcd_fck_rate;
|
||||
#endif
|
||||
void (*panel_power_ctrl)(int);
|
||||
u32 pseudo_palette[16];
|
||||
};
|
||||
|
||||
/* Variable Screen Information */
|
||||
|
|
@ -288,13 +295,26 @@ static inline void lcd_enable_raster(void)
|
|||
}
|
||||
|
||||
/* Disable the Raster Engine of the LCD Controller */
|
||||
static inline void lcd_disable_raster(void)
|
||||
static inline void lcd_disable_raster(bool wait_for_frame_done)
|
||||
{
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
reg = lcdc_read(LCD_RASTER_CTRL_REG);
|
||||
if (reg & LCD_RASTER_ENABLE)
|
||||
lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
|
||||
else
|
||||
/* return if already disabled */
|
||||
return;
|
||||
|
||||
if ((wait_for_frame_done == true) && (lcd_revision == LCD_VERSION_2)) {
|
||||
frame_done_flag = 0;
|
||||
ret = wait_event_interruptible_timeout(frame_done_wq,
|
||||
frame_done_flag != 0,
|
||||
msecs_to_jiffies(50));
|
||||
if (ret == 0)
|
||||
pr_err("LCD Controller timed out\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
|
||||
|
|
@ -321,7 +341,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
|
|||
} else {
|
||||
reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
|
||||
LCD_V2_END_OF_FRAME0_INT_ENA |
|
||||
LCD_V2_END_OF_FRAME1_INT_ENA;
|
||||
LCD_V2_END_OF_FRAME1_INT_ENA |
|
||||
LCD_FRAME_DONE;
|
||||
lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
|
||||
}
|
||||
reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
|
||||
|
|
@ -499,6 +520,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
if (bpp > 16 && lcd_revision == LCD_VERSION_1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set the Panel Width */
|
||||
/* Pixels per line = (PPL + 1)*16 */
|
||||
if (lcd_revision == LCD_VERSION_1) {
|
||||
|
|
@ -542,14 +566,19 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
|
|||
reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
|
||||
if (raster_order)
|
||||
reg |= LCD_RASTER_ORDER;
|
||||
lcdc_write(reg, LCD_RASTER_CTRL_REG);
|
||||
|
||||
par->palette_sz = 16 * 2;
|
||||
|
||||
switch (bpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 16:
|
||||
par->palette_sz = 16 * 2;
|
||||
break;
|
||||
case 24:
|
||||
reg |= LCD_V2_TFT_24BPP_MODE;
|
||||
case 32:
|
||||
reg |= LCD_V2_TFT_24BPP_UNPACK;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
|
|
@ -560,9 +589,12 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
lcdc_write(reg, LCD_RASTER_CTRL_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
|
||||
static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
unsigned blue, unsigned transp,
|
||||
struct fb_info *info)
|
||||
|
|
@ -578,13 +610,38 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
|
||||
return 1;
|
||||
|
||||
if (info->var.bits_per_pixel == 4) {
|
||||
if (regno > 15)
|
||||
return 1;
|
||||
if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->var.grayscale) {
|
||||
pal = regno;
|
||||
} else {
|
||||
switch (info->fix.visual) {
|
||||
case FB_VISUAL_TRUECOLOR:
|
||||
red = CNVT_TOHW(red, info->var.red.length);
|
||||
green = CNVT_TOHW(green, info->var.green.length);
|
||||
blue = CNVT_TOHW(blue, info->var.blue.length);
|
||||
break;
|
||||
case FB_VISUAL_PSEUDOCOLOR:
|
||||
switch (info->var.bits_per_pixel) {
|
||||
case 4:
|
||||
if (regno > 15)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->var.grayscale) {
|
||||
pal = regno;
|
||||
} else {
|
||||
red >>= 4;
|
||||
green >>= 8;
|
||||
blue >>= 12;
|
||||
|
||||
pal = red & 0x0f00;
|
||||
pal |= green & 0x00f0;
|
||||
pal |= blue & 0x000f;
|
||||
}
|
||||
if (regno == 0)
|
||||
pal |= 0x2000;
|
||||
palette[regno] = pal;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
red >>= 4;
|
||||
green >>= 8;
|
||||
blue >>= 12;
|
||||
|
|
@ -592,36 +649,36 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
pal = (red & 0x0f00);
|
||||
pal |= (green & 0x00f0);
|
||||
pal |= (blue & 0x000f);
|
||||
|
||||
if (palette[regno] != pal) {
|
||||
update_hw = 1;
|
||||
palette[regno] = pal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (regno == 0)
|
||||
pal |= 0x2000;
|
||||
palette[regno] = pal;
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (info->var.bits_per_pixel == 8) {
|
||||
red >>= 4;
|
||||
green >>= 8;
|
||||
blue >>= 12;
|
||||
/* Truecolor has hardware independent palette */
|
||||
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
|
||||
u32 v;
|
||||
|
||||
pal = (red & 0x0f00);
|
||||
pal |= (green & 0x00f0);
|
||||
pal |= (blue & 0x000f);
|
||||
if (regno > 15)
|
||||
return -EINVAL;
|
||||
|
||||
if (palette[regno] != pal) {
|
||||
update_hw = 1;
|
||||
palette[regno] = pal;
|
||||
v = (red << info->var.red.offset) |
|
||||
(green << info->var.green.offset) |
|
||||
(blue << info->var.blue.offset);
|
||||
|
||||
switch (info->var.bits_per_pixel) {
|
||||
case 16:
|
||||
((u16 *) (info->pseudo_palette))[regno] = v;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
((u32 *) (info->pseudo_palette))[regno] = v;
|
||||
break;
|
||||
}
|
||||
} else if ((info->var.bits_per_pixel == 16) && regno < 16) {
|
||||
red >>= (16 - info->var.red.length);
|
||||
red <<= info->var.red.offset;
|
||||
|
||||
green >>= (16 - info->var.green.length);
|
||||
green <<= info->var.green.offset;
|
||||
|
||||
blue >>= (16 - info->var.blue.length);
|
||||
blue <<= info->var.blue.offset;
|
||||
|
||||
par->pseudo_palette[regno] = red | green | blue;
|
||||
|
||||
if (palette[0] != 0x4000) {
|
||||
update_hw = 1;
|
||||
palette[0] = 0x4000;
|
||||
|
|
@ -634,11 +691,12 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#undef CNVT_TOHW
|
||||
|
||||
static void lcd_reset(struct da8xx_fb_par *par)
|
||||
{
|
||||
/* Disable the Raster if previously Enabled */
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(false);
|
||||
|
||||
/* DMA has to be disabled */
|
||||
lcdc_write(0, LCD_DMA_CTRL_REG);
|
||||
|
|
@ -734,7 +792,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
|
|||
u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
|
||||
|
||||
if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(false);
|
||||
lcdc_write(stat, LCD_MASKED_STAT_REG);
|
||||
lcd_enable_raster();
|
||||
} else if (stat & LCD_PL_LOAD_DONE) {
|
||||
|
|
@ -744,7 +802,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
|
|||
* interrupt via the following write to the status register. If
|
||||
* this is done after then one gets multiple PL done interrupts.
|
||||
*/
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(false);
|
||||
|
||||
lcdc_write(stat, LCD_MASKED_STAT_REG);
|
||||
|
||||
|
|
@ -775,6 +833,14 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
|
|||
par->vsync_flag = 1;
|
||||
wake_up_interruptible(&par->vsync_wait);
|
||||
}
|
||||
|
||||
/* Set only when controller is disabled and at the end of
|
||||
* active frame
|
||||
*/
|
||||
if (stat & BIT(0)) {
|
||||
frame_done_flag = 1;
|
||||
wake_up_interruptible(&frame_done_wq);
|
||||
}
|
||||
}
|
||||
|
||||
lcdc_write(0, LCD_END_OF_INT_IND_REG);
|
||||
|
|
@ -789,7 +855,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
|
|||
u32 reg_ras;
|
||||
|
||||
if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(false);
|
||||
lcdc_write(stat, LCD_STAT_REG);
|
||||
lcd_enable_raster();
|
||||
} else if (stat & LCD_PL_LOAD_DONE) {
|
||||
|
|
@ -799,7 +865,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
|
|||
* interrupt via the following write to the status register. If
|
||||
* this is done after then one gets multiple PL done interrupts.
|
||||
*/
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(false);
|
||||
|
||||
lcdc_write(stat, LCD_STAT_REG);
|
||||
|
||||
|
|
@ -842,6 +908,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
|
|||
{
|
||||
int err = 0;
|
||||
|
||||
if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
|
||||
return -EINVAL;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 1:
|
||||
case 8:
|
||||
|
|
@ -877,6 +946,26 @@ static int fb_check_var(struct fb_var_screeninfo *var,
|
|||
var->transp.length = 0;
|
||||
var->nonstd = 0;
|
||||
break;
|
||||
case 24:
|
||||
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->nonstd = 0;
|
||||
break;
|
||||
case 32:
|
||||
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->nonstd = 0;
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
|
@ -898,9 +987,10 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
|
|||
if (val == CPUFREQ_POSTCHANGE) {
|
||||
if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
|
||||
par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(true);
|
||||
lcd_calc_clk_divider(par);
|
||||
lcd_enable_raster();
|
||||
if (par->blank == FB_BLANK_UNBLANK)
|
||||
lcd_enable_raster();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -935,7 +1025,7 @@ static int __devexit fb_remove(struct platform_device *dev)
|
|||
if (par->panel_power_ctrl)
|
||||
par->panel_power_ctrl(0);
|
||||
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(true);
|
||||
lcdc_write(0, LCD_RASTER_CTRL_REG);
|
||||
|
||||
/* disable DMA */
|
||||
|
|
@ -948,8 +1038,8 @@ static int __devexit fb_remove(struct platform_device *dev)
|
|||
dma_free_coherent(NULL, par->vram_size, par->vram_virt,
|
||||
par->vram_phys);
|
||||
free_irq(par->irq, par);
|
||||
clk_disable(par->lcdc_clk);
|
||||
clk_put(par->lcdc_clk);
|
||||
pm_runtime_put_sync(&dev->dev);
|
||||
pm_runtime_disable(&dev->dev);
|
||||
framebuffer_release(info);
|
||||
iounmap(da8xx_fb_reg_base);
|
||||
release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
|
||||
|
|
@ -1051,7 +1141,7 @@ static int cfb_blank(int blank, struct fb_info *info)
|
|||
if (par->panel_power_ctrl)
|
||||
par->panel_power_ctrl(0);
|
||||
|
||||
lcd_disable_raster();
|
||||
lcd_disable_raster(true);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
|
@ -1183,9 +1273,9 @@ static int __devinit fb_probe(struct platform_device *device)
|
|||
ret = -ENODEV;
|
||||
goto err_ioremap;
|
||||
}
|
||||
ret = clk_enable(fb_clk);
|
||||
if (ret)
|
||||
goto err_clk_put;
|
||||
|
||||
pm_runtime_enable(&device->dev);
|
||||
pm_runtime_get_sync(&device->dev);
|
||||
|
||||
/* Determine LCD IP Version */
|
||||
switch (lcdc_read(LCD_PID_REG)) {
|
||||
|
|
@ -1213,7 +1303,7 @@ static int __devinit fb_probe(struct platform_device *device)
|
|||
if (i == ARRAY_SIZE(known_lcd_panels)) {
|
||||
dev_err(&device->dev, "GLCD: No valid panel found\n");
|
||||
ret = -ENODEV;
|
||||
goto err_clk_disable;
|
||||
goto err_pm_runtime_disable;
|
||||
} else
|
||||
dev_info(&device->dev, "GLCD: Found %s panel\n",
|
||||
fb_pdata->type);
|
||||
|
|
@ -1225,7 +1315,7 @@ static int __devinit fb_probe(struct platform_device *device)
|
|||
if (!da8xx_fb_info) {
|
||||
dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_clk_disable;
|
||||
goto err_pm_runtime_disable;
|
||||
}
|
||||
|
||||
par = da8xx_fb_info->par;
|
||||
|
|
@ -1356,8 +1446,10 @@ static int __devinit fb_probe(struct platform_device *device)
|
|||
|
||||
if (lcd_revision == LCD_VERSION_1)
|
||||
lcdc_irq_handler = lcdc_irq_handler_rev01;
|
||||
else
|
||||
else {
|
||||
init_waitqueue_head(&frame_done_wq);
|
||||
lcdc_irq_handler = lcdc_irq_handler_rev02;
|
||||
}
|
||||
|
||||
ret = request_irq(par->irq, lcdc_irq_handler, 0,
|
||||
DRIVER_NAME, par);
|
||||
|
|
@ -1385,11 +1477,9 @@ err_release_fb_mem:
|
|||
err_release_fb:
|
||||
framebuffer_release(da8xx_fb_info);
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable(fb_clk);
|
||||
|
||||
err_clk_put:
|
||||
clk_put(fb_clk);
|
||||
err_pm_runtime_disable:
|
||||
pm_runtime_put_sync(&device->dev);
|
||||
pm_runtime_disable(&device->dev);
|
||||
|
||||
err_ioremap:
|
||||
iounmap(da8xx_fb_reg_base);
|
||||
|
|
@ -1401,6 +1491,69 @@ err_request_mem:
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
struct lcdc_context {
|
||||
u32 clk_enable;
|
||||
u32 ctrl;
|
||||
u32 dma_ctrl;
|
||||
u32 raster_timing_0;
|
||||
u32 raster_timing_1;
|
||||
u32 raster_timing_2;
|
||||
u32 int_enable_set;
|
||||
u32 dma_frm_buf_base_addr_0;
|
||||
u32 dma_frm_buf_ceiling_addr_0;
|
||||
u32 dma_frm_buf_base_addr_1;
|
||||
u32 dma_frm_buf_ceiling_addr_1;
|
||||
u32 raster_ctrl;
|
||||
} reg_context;
|
||||
|
||||
static void lcd_context_save(void)
|
||||
{
|
||||
if (lcd_revision == LCD_VERSION_2) {
|
||||
reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG);
|
||||
reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG);
|
||||
}
|
||||
|
||||
reg_context.ctrl = lcdc_read(LCD_CTRL_REG);
|
||||
reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG);
|
||||
reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG);
|
||||
reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG);
|
||||
reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG);
|
||||
reg_context.dma_frm_buf_base_addr_0 =
|
||||
lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
|
||||
reg_context.dma_frm_buf_ceiling_addr_0 =
|
||||
lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
|
||||
reg_context.dma_frm_buf_base_addr_1 =
|
||||
lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
|
||||
reg_context.dma_frm_buf_ceiling_addr_1 =
|
||||
lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
|
||||
reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
static void lcd_context_restore(void)
|
||||
{
|
||||
if (lcd_revision == LCD_VERSION_2) {
|
||||
lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG);
|
||||
lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG);
|
||||
}
|
||||
|
||||
lcdc_write(reg_context.ctrl, LCD_CTRL_REG);
|
||||
lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG);
|
||||
lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG);
|
||||
lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG);
|
||||
lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG);
|
||||
lcdc_write(reg_context.dma_frm_buf_base_addr_0,
|
||||
LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
|
||||
lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0,
|
||||
LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
|
||||
lcdc_write(reg_context.dma_frm_buf_base_addr_1,
|
||||
LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
|
||||
lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1,
|
||||
LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
|
||||
lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG);
|
||||
return;
|
||||
}
|
||||
|
||||
static int fb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct fb_info *info = platform_get_drvdata(dev);
|
||||
|
|
@ -1411,8 +1564,9 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state)
|
|||
par->panel_power_ctrl(0);
|
||||
|
||||
fb_set_suspend(info, 1);
|
||||
lcd_disable_raster();
|
||||
clk_disable(par->lcdc_clk);
|
||||
lcd_disable_raster(true);
|
||||
lcd_context_save();
|
||||
pm_runtime_put_sync(&dev->dev);
|
||||
console_unlock();
|
||||
|
||||
return 0;
|
||||
|
|
@ -1423,11 +1577,14 @@ static int fb_resume(struct platform_device *dev)
|
|||
struct da8xx_fb_par *par = info->par;
|
||||
|
||||
console_lock();
|
||||
clk_enable(par->lcdc_clk);
|
||||
lcd_enable_raster();
|
||||
pm_runtime_get_sync(&dev->dev);
|
||||
lcd_context_restore();
|
||||
if (par->blank == FB_BLANK_UNBLANK) {
|
||||
lcd_enable_raster();
|
||||
|
||||
if (par->panel_power_ctrl)
|
||||
par->panel_power_ctrl(1);
|
||||
if (par->panel_power_ctrl)
|
||||
par->panel_power_ctrl(1);
|
||||
}
|
||||
|
||||
fb_set_suspend(info, 0);
|
||||
console_unlock();
|
||||
|
|
|
|||
|
|
@ -529,7 +529,8 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
|||
* any of the framebuffer registers.
|
||||
*/
|
||||
fbi->res = res;
|
||||
fbi->mmio_base = ioremap(res->start, resource_size(res));
|
||||
fbi->mmio_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!fbi->mmio_base) {
|
||||
err = -ENXIO;
|
||||
goto failed_resource;
|
||||
|
|
@ -553,20 +554,20 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
|||
if (err == 0) {
|
||||
dev_err(info->dev, "No suitable video mode found\n");
|
||||
err = -EINVAL;
|
||||
goto failed_mode;
|
||||
goto failed_resource;
|
||||
}
|
||||
|
||||
if (mach_info->setup) {
|
||||
err = mach_info->setup(pdev);
|
||||
if (err)
|
||||
goto failed_mode;
|
||||
goto failed_resource;
|
||||
}
|
||||
|
||||
err = ep93xxfb_check_var(&info->var, info);
|
||||
if (err)
|
||||
goto failed_check;
|
||||
|
||||
fbi->clk = clk_get(info->dev, NULL);
|
||||
fbi->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(fbi->clk)) {
|
||||
err = PTR_ERR(fbi->clk);
|
||||
fbi->clk = NULL;
|
||||
|
|
@ -578,19 +579,15 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
|||
|
||||
err = register_framebuffer(info);
|
||||
if (err)
|
||||
goto failed;
|
||||
goto failed_check;
|
||||
|
||||
dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
|
||||
info->var.xres, info->var.yres, info->var.bits_per_pixel);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
clk_put(fbi->clk);
|
||||
failed_check:
|
||||
if (fbi->mach_info->teardown)
|
||||
fbi->mach_info->teardown(pdev);
|
||||
failed_mode:
|
||||
iounmap(fbi->mmio_base);
|
||||
failed_resource:
|
||||
ep93xxfb_dealloc_videomem(info);
|
||||
failed_videomem:
|
||||
|
|
@ -609,8 +606,6 @@ static int __devexit ep93xxfb_remove(struct platform_device *pdev)
|
|||
|
||||
unregister_framebuffer(info);
|
||||
clk_disable(fbi->clk);
|
||||
clk_put(fbi->clk);
|
||||
iounmap(fbi->mmio_base);
|
||||
ep93xxfb_dealloc_videomem(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ static int exynos_dp_init_dp(struct exynos_dp_device *dp)
|
|||
|
||||
exynos_dp_swreset(dp);
|
||||
|
||||
exynos_dp_init_analog_param(dp);
|
||||
exynos_dp_init_interrupt(dp);
|
||||
|
||||
/* SW defined function Normal operation */
|
||||
exynos_dp_enable_sw_function(dp);
|
||||
|
||||
|
|
@ -260,7 +263,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
|
|||
|
||||
static void exynos_dp_link_start(struct exynos_dp_device *dp)
|
||||
{
|
||||
u8 buf[5];
|
||||
u8 buf[4];
|
||||
int lane;
|
||||
int lane_count;
|
||||
|
||||
|
|
@ -295,10 +298,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
|
|||
exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
|
||||
|
||||
/* Set RX training pattern */
|
||||
buf[0] = DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_1;
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_1);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
|
||||
|
|
@ -308,7 +311,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
|
|||
lane_count, buf);
|
||||
}
|
||||
|
||||
static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
|
||||
static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
|
||||
{
|
||||
int shift = (lane & 1) * 4;
|
||||
u8 link_value = link_status[lane>>1];
|
||||
|
|
@ -316,7 +319,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
|
|||
return (link_value >> shift) & 0xf;
|
||||
}
|
||||
|
||||
static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
|
||||
static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
|
||||
{
|
||||
int lane;
|
||||
u8 lane_status;
|
||||
|
|
@ -329,22 +332,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
|
||||
static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
|
||||
{
|
||||
int lane;
|
||||
u8 lane_align;
|
||||
u8 lane_status;
|
||||
|
||||
lane_align = link_status[2];
|
||||
lane_align = link_align[2];
|
||||
if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
lane_status = exynos_dp_get_lane_status(link_status, lane);
|
||||
lane_status = exynos_dp_get_lane_status(link_align, lane);
|
||||
lane_status &= DPCD_CHANNEL_EQ_BITS;
|
||||
if (lane_status != DPCD_CHANNEL_EQ_BITS)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -417,69 +421,17 @@ static unsigned int exynos_dp_get_lane_link_training(
|
|||
|
||||
static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
|
||||
{
|
||||
if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) {
|
||||
/* set to reduced bit rate */
|
||||
dp->link_train.link_rate = LINK_RATE_1_62GBPS;
|
||||
dev_err(dp->dev, "set to bandwidth %.2x\n",
|
||||
dp->link_train.link_rate);
|
||||
dp->link_train.lt_state = START;
|
||||
} else {
|
||||
exynos_dp_training_pattern_dis(dp);
|
||||
/* set enhanced mode if available */
|
||||
exynos_dp_set_enhanced_mode(dp);
|
||||
dp->link_train.lt_state = FAILED;
|
||||
}
|
||||
}
|
||||
exynos_dp_training_pattern_dis(dp);
|
||||
exynos_dp_set_enhanced_mode(dp);
|
||||
|
||||
static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
|
||||
u8 adjust_request[2])
|
||||
{
|
||||
int lane;
|
||||
int lane_count;
|
||||
u8 voltage_swing;
|
||||
u8 pre_emphasis;
|
||||
u8 training_lane;
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3 ||
|
||||
pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
}
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
}
|
||||
}
|
||||
|
||||
static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
|
||||
u8 voltage_swing)
|
||||
{
|
||||
int lane;
|
||||
int lane_count;
|
||||
|
||||
lane_count = dp->link_train.lane_count;
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3 ||
|
||||
dp->link_train.cr_loop[lane] == MAX_CR_LOOP)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
dp->link_train.lt_state = FAILED;
|
||||
}
|
||||
|
||||
static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
|
||||
{
|
||||
u8 data;
|
||||
u8 link_status[6];
|
||||
u8 link_status[2];
|
||||
int lane;
|
||||
int lane_count;
|
||||
u8 buf[5];
|
||||
|
||||
u8 adjust_request[2];
|
||||
u8 voltage_swing;
|
||||
|
|
@ -488,100 +440,154 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
|
|||
|
||||
usleep_range(100, 101);
|
||||
|
||||
exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
|
||||
6, link_status);
|
||||
lane_count = dp->link_train.lane_count;
|
||||
|
||||
exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
|
||||
2, link_status);
|
||||
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
|
||||
/* set training pattern 2 for EQ */
|
||||
exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
|
||||
|
||||
adjust_request[0] = link_status[4];
|
||||
adjust_request[1] = link_status[5];
|
||||
|
||||
exynos_dp_get_adjust_train(dp, adjust_request);
|
||||
|
||||
buf[0] = DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_2;
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
buf[0]);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
buf[lane] = dp->link_train.training_lane[lane];
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET + lane,
|
||||
buf[lane]);
|
||||
}
|
||||
dp->link_train.lt_state = EQUALIZER_TRAINING;
|
||||
} else {
|
||||
exynos_dp_read_byte_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
&data);
|
||||
adjust_request[0] = data;
|
||||
|
||||
exynos_dp_read_byte_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
|
||||
&data);
|
||||
adjust_request[1] = data;
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
training_lane = exynos_dp_get_lane_link_training(
|
||||
dp, lane);
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
|
||||
(DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
|
||||
dp->link_train.cr_loop[lane]++;
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
}
|
||||
|
||||
if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
} else {
|
||||
exynos_dp_get_adjust_train(dp, adjust_request);
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_2);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
buf[lane] = dp->link_train.training_lane[lane];
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET + lane,
|
||||
buf[lane]);
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
dp->link_train.training_lane);
|
||||
|
||||
dev_info(dp->dev, "Link Training Clock Recovery success\n");
|
||||
dp->link_train.lt_state = EQUALIZER_TRAINING;
|
||||
} else {
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
training_lane = exynos_dp_get_lane_link_training(
|
||||
dp, lane);
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3 ||
|
||||
pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
|
||||
dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
|
||||
if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
|
||||
voltage_swing) &&
|
||||
(DPCD_PRE_EMPHASIS_GET(training_lane) ==
|
||||
pre_emphasis)) {
|
||||
dp->link_train.cr_loop[lane]++;
|
||||
if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
|
||||
dev_err(dp->dev, "CR Max loop\n");
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
}
|
||||
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane], lane);
|
||||
}
|
||||
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
dp->link_train.training_lane);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reduce_link_rate:
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
|
||||
{
|
||||
u8 link_status[6];
|
||||
u8 link_status[2];
|
||||
u8 link_align[3];
|
||||
int lane;
|
||||
int lane_count;
|
||||
u8 buf[5];
|
||||
u32 reg;
|
||||
|
||||
u8 adjust_request[2];
|
||||
u8 voltage_swing;
|
||||
u8 pre_emphasis;
|
||||
u8 training_lane;
|
||||
|
||||
usleep_range(400, 401);
|
||||
|
||||
exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
|
||||
6, link_status);
|
||||
lane_count = dp->link_train.lane_count;
|
||||
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
|
||||
adjust_request[0] = link_status[4];
|
||||
adjust_request[1] = link_status[5];
|
||||
exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
|
||||
2, link_status);
|
||||
|
||||
if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) {
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
|
||||
link_align[0] = link_status[0];
|
||||
link_align[1] = link_status[1];
|
||||
|
||||
exynos_dp_read_byte_from_dpcd(dp,
|
||||
DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
|
||||
&link_align[2]);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
exynos_dp_read_bytes_from_dpcd(dp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
voltage_swing = exynos_dp_get_adjust_request_voltage(
|
||||
adjust_request, lane);
|
||||
pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
|
||||
adjust_request, lane);
|
||||
training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
|
||||
DPCD_PRE_EMPHASIS_SET(pre_emphasis);
|
||||
|
||||
if (voltage_swing == VOLTAGE_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_SWING_REACHED;
|
||||
if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
|
||||
training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
|
||||
|
||||
dp->link_train.training_lane[lane] = training_lane;
|
||||
}
|
||||
|
||||
if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
|
||||
/* traing pattern Set to Normal */
|
||||
exynos_dp_training_pattern_dis(dp);
|
||||
|
||||
|
|
@ -596,39 +602,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
|
|||
dp->link_train.lane_count = reg;
|
||||
dev_dbg(dp->dev, "final lane count = %.2x\n",
|
||||
dp->link_train.lane_count);
|
||||
|
||||
/* set enhanced mode if available */
|
||||
exynos_dp_set_enhanced_mode(dp);
|
||||
|
||||
dp->link_train.lt_state = FINISHED;
|
||||
} else {
|
||||
/* not all locked */
|
||||
dp->link_train.eq_loop++;
|
||||
|
||||
if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
} else {
|
||||
exynos_dp_get_adjust_train(dp, adjust_request);
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
buf[lane] = dp->link_train.training_lane[lane];
|
||||
exynos_dp_write_byte_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET + lane,
|
||||
buf[lane]);
|
||||
}
|
||||
dev_err(dp->dev, "EQ Max loop\n");
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++)
|
||||
exynos_dp_set_lane_link_training(dp,
|
||||
dp->link_train.training_lane[lane],
|
||||
lane);
|
||||
|
||||
exynos_dp_write_bytes_to_dpcd(dp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
dp->link_train.training_lane);
|
||||
}
|
||||
} else {
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
goto reduce_link_rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reduce_link_rate:
|
||||
exynos_dp_reduce_link_rate(dp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
|
||||
u8 *bandwidth)
|
||||
u8 *bandwidth)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
|
|
@ -641,7 +650,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
|
|||
}
|
||||
|
||||
static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
|
||||
u8 *lane_count)
|
||||
u8 *lane_count)
|
||||
{
|
||||
u8 data;
|
||||
|
||||
|
|
@ -693,13 +702,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
|
|||
static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
|
||||
{
|
||||
int retval = 0;
|
||||
int training_finished;
|
||||
|
||||
/* Turn off unnecessary lane */
|
||||
if (dp->link_train.lane_count == 1)
|
||||
exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
|
||||
|
||||
training_finished = 0;
|
||||
int training_finished = 0;
|
||||
|
||||
dp->link_train.lt_state = START;
|
||||
|
||||
|
|
@ -710,10 +713,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
|
|||
exynos_dp_link_start(dp);
|
||||
break;
|
||||
case CLOCK_RECOVERY:
|
||||
exynos_dp_process_clock_recovery(dp);
|
||||
retval = exynos_dp_process_clock_recovery(dp);
|
||||
if (retval)
|
||||
dev_err(dp->dev, "LT CR failed!\n");
|
||||
break;
|
||||
case EQUALIZER_TRAINING:
|
||||
exynos_dp_process_equalizer_training(dp);
|
||||
retval = exynos_dp_process_equalizer_training(dp);
|
||||
if (retval)
|
||||
dev_err(dp->dev, "LT EQ failed!\n");
|
||||
break;
|
||||
case FINISHED:
|
||||
training_finished = 1;
|
||||
|
|
@ -872,40 +879,33 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
|||
|
||||
dp->dev = &pdev->dev;
|
||||
|
||||
dp->clock = clk_get(&pdev->dev, "dp");
|
||||
dp->clock = devm_clk_get(&pdev->dev, "dp");
|
||||
if (IS_ERR(dp->clock)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
return PTR_ERR(dp->clock);
|
||||
}
|
||||
|
||||
clk_enable(dp->clock);
|
||||
clk_prepare_enable(dp->clock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "failed to get registers\n");
|
||||
ret = -EINVAL;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
dp->reg_base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!dp->reg_base) {
|
||||
dev_err(&pdev->dev, "failed to ioremap\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_clock;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dp->irq = platform_get_irq(pdev, 0);
|
||||
if (!dp->irq) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
ret = -ENODEV;
|
||||
goto err_clock;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
|
||||
"exynos-dp", dp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
goto err_clock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dp->video_info = pdata->video_info;
|
||||
|
|
@ -917,7 +917,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
|||
ret = exynos_dp_detect_hpd(dp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to detect hpd\n");
|
||||
goto err_clock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
exynos_dp_handle_edid(dp);
|
||||
|
|
@ -926,7 +926,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
|||
dp->video_info->link_rate);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to do link train\n");
|
||||
goto err_clock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
exynos_dp_enable_scramble(dp, 1);
|
||||
|
|
@ -940,17 +940,12 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
|||
ret = exynos_dp_config_video(dp, dp->video_info);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to config video\n");
|
||||
goto err_clock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dp);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clock:
|
||||
clk_put(dp->clock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit exynos_dp_remove(struct platform_device *pdev)
|
||||
|
|
@ -961,8 +956,7 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
|
|||
if (pdata && pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
|
||||
clk_disable(dp->clock);
|
||||
clk_put(dp->clock);
|
||||
clk_disable_unprepare(dp->clock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -977,7 +971,7 @@ static int exynos_dp_suspend(struct device *dev)
|
|||
if (pdata && pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
|
||||
clk_disable(dp->clock);
|
||||
clk_disable_unprepare(dp->clock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -991,7 +985,7 @@ static int exynos_dp_resume(struct device *dev)
|
|||
if (pdata && pdata->phy_init)
|
||||
pdata->phy_init();
|
||||
|
||||
clk_enable(dp->clock);
|
||||
clk_prepare_enable(dp->clock);
|
||||
|
||||
exynos_dp_init_dp(dp);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
|
|||
void exynos_dp_reset(struct exynos_dp_device *dp);
|
||||
void exynos_dp_swreset(struct exynos_dp_device *dp);
|
||||
void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
|
||||
u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
|
||||
enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
|
||||
void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
|
||||
enum analog_power_block block,
|
||||
|
|
@ -105,7 +105,7 @@ u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
|
|||
u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
|
||||
u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
|
||||
void exynos_dp_reset_macro(struct exynos_dp_device *dp);
|
||||
int exynos_dp_init_video(struct exynos_dp_device *dp);
|
||||
void exynos_dp_init_video(struct exynos_dp_device *dp);
|
||||
|
||||
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
|
||||
u32 color_depth,
|
||||
|
|
@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
|
|||
#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
|
||||
#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
|
||||
#define DPCD_ADDR_LANE0_1_STATUS 0x0202
|
||||
#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
|
||||
#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED 0x0204
|
||||
#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
|
||||
#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
|
||||
#define DPCD_ADDR_TEST_REQUEST 0x0218
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
|
|||
writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
|
||||
|
||||
reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
|
||||
TX_CUR1_2X | TX_CUR_8_MA;
|
||||
TX_CUR1_2X | TX_CUR_16_MA;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
|
||||
|
||||
reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
|
||||
|
|
@ -148,9 +148,6 @@ void exynos_dp_reset(struct exynos_dp_device *dp)
|
|||
writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
|
||||
|
||||
writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
|
||||
|
||||
exynos_dp_init_analog_param(dp);
|
||||
exynos_dp_init_interrupt(dp);
|
||||
}
|
||||
|
||||
void exynos_dp_swreset(struct exynos_dp_device *dp)
|
||||
|
|
@ -179,7 +176,7 @@ void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
|
|||
writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
|
||||
}
|
||||
|
||||
u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
|
||||
enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
|
|
@ -401,6 +398,7 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
|
|||
{
|
||||
int reg;
|
||||
int retval = 0;
|
||||
int timeout_loop = 0;
|
||||
|
||||
/* Enable AUX CH operation */
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
|
||||
|
|
@ -409,8 +407,15 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
|
|||
|
||||
/* Is AUX CH command reply received? */
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
|
||||
while (!(reg & RPLY_RECEIV))
|
||||
while (!(reg & RPLY_RECEIV)) {
|
||||
timeout_loop++;
|
||||
if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
|
||||
dev_err(dp->dev, "AUX CH command reply failed!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
|
||||
usleep_range(10, 11);
|
||||
}
|
||||
|
||||
/* Clear interrupt source for AUX CH command reply */
|
||||
writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
|
||||
|
|
@ -471,7 +476,8 @@ int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
|
|||
if (retval == 0)
|
||||
break;
|
||||
else
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
|
@ -511,7 +517,8 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
|
|||
if (retval == 0)
|
||||
break;
|
||||
else
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/* Read data buffer */
|
||||
|
|
@ -575,7 +582,8 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
|
|||
if (retval == 0)
|
||||
break;
|
||||
else
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
start_offset += cur_data_count;
|
||||
|
|
@ -632,7 +640,8 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
|
|||
if (retval == 0)
|
||||
break;
|
||||
else
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
for (cur_data_idx = 0; cur_data_idx < cur_data_count;
|
||||
|
|
@ -677,7 +686,7 @@ int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
|
|||
/* Start AUX transaction */
|
||||
retval = exynos_dp_start_aux_transaction(dp);
|
||||
if (retval != 0)
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -717,7 +726,8 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
|
|||
if (retval == 0)
|
||||
break;
|
||||
else
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/* Read data */
|
||||
|
|
@ -777,7 +787,9 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
|
|||
if (retval == 0)
|
||||
break;
|
||||
else
|
||||
dev_err(dp->dev, "Aux Transaction fail!\n");
|
||||
dev_dbg(dp->dev,
|
||||
"%s: Aux Transaction fail!\n",
|
||||
__func__);
|
||||
}
|
||||
/* Check if Rx sends defer */
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
|
||||
|
|
@ -883,7 +895,9 @@ void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
reg = level << PRE_EMPHASIS_SET_SHIFT;
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
|
||||
reg &= ~PRE_EMPHASIS_SET_MASK;
|
||||
reg |= level << PRE_EMPHASIS_SET_SHIFT;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
|
||||
}
|
||||
|
||||
|
|
@ -891,7 +905,9 @@ void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
reg = level << PRE_EMPHASIS_SET_SHIFT;
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
|
||||
reg &= ~PRE_EMPHASIS_SET_MASK;
|
||||
reg |= level << PRE_EMPHASIS_SET_SHIFT;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
|
||||
}
|
||||
|
||||
|
|
@ -899,7 +915,9 @@ void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
reg = level << PRE_EMPHASIS_SET_SHIFT;
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
|
||||
reg &= ~PRE_EMPHASIS_SET_MASK;
|
||||
reg |= level << PRE_EMPHASIS_SET_SHIFT;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
|
||||
}
|
||||
|
||||
|
|
@ -907,7 +925,9 @@ void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
reg = level << PRE_EMPHASIS_SET_SHIFT;
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
|
||||
reg &= ~PRE_EMPHASIS_SET_MASK;
|
||||
reg |= level << PRE_EMPHASIS_SET_SHIFT;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
|
||||
}
|
||||
|
||||
|
|
@ -994,7 +1014,7 @@ void exynos_dp_reset_macro(struct exynos_dp_device *dp)
|
|||
writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
|
||||
}
|
||||
|
||||
int exynos_dp_init_video(struct exynos_dp_device *dp)
|
||||
void exynos_dp_init_video(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
|
|
@ -1012,8 +1032,6 @@ int exynos_dp_init_video(struct exynos_dp_device *dp)
|
|||
|
||||
reg = VID_HRES_TH(2) | VID_VRES_TH(0);
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@
|
|||
#define PD_RING_OSC (0x1 << 6)
|
||||
#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4)
|
||||
#define TX_CUR1_2X (0x1 << 2)
|
||||
#define TX_CUR_8_MA (0x2 << 0)
|
||||
#define TX_CUR_16_MA (0x3 << 0)
|
||||
|
||||
/* EXYNOS_DP_TX_AMP_TUNING_CTL */
|
||||
#define CH3_AMP_400_MV (0x0 << 24)
|
||||
|
|
@ -285,6 +285,7 @@
|
|||
#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
|
||||
|
||||
/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
|
||||
#define PRE_EMPHASIS_SET_MASK (0x3 << 3)
|
||||
#define PRE_EMPHASIS_SET_SHIFT (3)
|
||||
|
||||
/* EXYNOS_DP_DEBUG_CTL */
|
||||
|
|
|
|||
|
|
@ -205,7 +205,8 @@ int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
|
||||
static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
|
||||
struct mipi_dsim_lcd_driver *lcd_drv)
|
||||
{
|
||||
struct mipi_dsim_ddi *dsim_ddi, *next;
|
||||
struct mipi_dsim_lcd_device *lcd_dev;
|
||||
|
|
@ -265,7 +266,8 @@ int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
|
|||
|
||||
}
|
||||
|
||||
struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
|
||||
static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
|
||||
struct mipi_dsim_device *dsim,
|
||||
const char *name)
|
||||
{
|
||||
struct mipi_dsim_ddi *dsim_ddi, *next;
|
||||
|
|
@ -373,6 +375,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
|
|||
dsim->clock = clk_get(&pdev->dev, "dsim0");
|
||||
if (IS_ERR(dsim->clock)) {
|
||||
dev_err(&pdev->dev, "failed to get dsim clock source\n");
|
||||
ret = -ENODEV;
|
||||
goto err_clock_get;
|
||||
}
|
||||
|
||||
|
|
@ -381,6 +384,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
|
|||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "failed to get io memory region\n");
|
||||
ret = -ENODEV;
|
||||
goto err_platform_get;
|
||||
}
|
||||
|
||||
|
|
@ -405,6 +409,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
|
|||
dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
|
||||
if (!dsim_ddi) {
|
||||
dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
|
||||
ret = -EINVAL;
|
||||
goto err_bind;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,11 +79,6 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
|
|||
struct mipi_dsim_device *dsim = dev_id;
|
||||
unsigned int intsrc, intmsk;
|
||||
|
||||
if (dsim == NULL) {
|
||||
dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
intsrc = exynos_mipi_dsi_read_interrupt(dsim);
|
||||
intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
|
||||
intmsk = ~intmsk & intsrc;
|
||||
|
|
@ -288,9 +283,6 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
|
|||
mutex_unlock(&dsim->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&dsim->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
|
||||
|
|
|
|||
|
|
@ -1501,8 +1501,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
|
|||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
|
||||
&dma_addr, GFP_DMA | __GFP_ZERO);
|
||||
data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
|
||||
&dma_addr, GFP_DMA | __GFP_ZERO);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->dma_addr = dma_addr;
|
||||
|
|
@ -1628,9 +1628,6 @@ error:
|
|||
|
||||
iounmap(data->diu_reg);
|
||||
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
|
||||
data->dma_addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1648,9 +1645,6 @@ static int fsl_diu_remove(struct platform_device *pdev)
|
|||
|
||||
iounmap(data->diu_reg);
|
||||
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
|
||||
data->dma_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/mtrr.h>
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
#include <asm/addrspace.h>
|
||||
#endif
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#include <video/gbe.h>
|
||||
|
|
@ -1156,7 +1156,8 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
|
|||
goto out_release_framebuffer;
|
||||
}
|
||||
|
||||
gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe));
|
||||
gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
|
||||
sizeof(struct sgi_gbe));
|
||||
if (!gbe) {
|
||||
printk(KERN_ERR "gbefb: couldn't map mmio region\n");
|
||||
ret = -ENXIO;
|
||||
|
|
@ -1170,12 +1171,13 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
|
|||
if (!gbe_tiles.cpu) {
|
||||
printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_unmap;
|
||||
goto out_release_mem_region;
|
||||
}
|
||||
|
||||
if (gbe_mem_phys) {
|
||||
/* memory was allocated at boot time */
|
||||
gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
|
||||
gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys,
|
||||
gbe_mem_size);
|
||||
if (!gbe_mem) {
|
||||
printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -1241,13 +1243,9 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
|
|||
out_gbe_unmap:
|
||||
if (gbe_dma_addr)
|
||||
dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
|
||||
else
|
||||
iounmap(gbe_mem);
|
||||
out_tiles_free:
|
||||
dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
|
||||
(void *)gbe_tiles.cpu, gbe_tiles.dma);
|
||||
out_unmap:
|
||||
iounmap(gbe);
|
||||
out_release_mem_region:
|
||||
release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
|
||||
out_release_framebuffer:
|
||||
|
|
@ -1264,12 +1262,9 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)
|
|||
gbe_turn_off();
|
||||
if (gbe_dma_addr)
|
||||
dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
|
||||
else
|
||||
iounmap(gbe_mem);
|
||||
dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
|
||||
(void *)gbe_tiles.cpu, gbe_tiles.dma);
|
||||
release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
|
||||
iounmap(gbe);
|
||||
gbefb_remove_sysfs(&p_dev->dev);
|
||||
framebuffer_release(info);
|
||||
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ static int __devinit hpfb_init_one(unsigned long phys_base,
|
|||
unsigned long virt_base)
|
||||
{
|
||||
unsigned long fboff, fb_width, fb_height, fb_start;
|
||||
int ret;
|
||||
|
||||
fb_regs = virt_base;
|
||||
fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB);
|
||||
|
|
@ -290,19 +291,29 @@ static int __devinit hpfb_init_one(unsigned long phys_base,
|
|||
fb_info.var = hpfb_defined;
|
||||
fb_info.screen_base = (char *)fb_start;
|
||||
|
||||
fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
|
||||
ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
|
||||
if (ret < 0)
|
||||
goto unmap_screen_base;
|
||||
|
||||
if (register_framebuffer(&fb_info) < 0) {
|
||||
fb_dealloc_cmap(&fb_info.cmap);
|
||||
iounmap(fb_info.screen_base);
|
||||
fb_info.screen_base = NULL;
|
||||
return 1;
|
||||
}
|
||||
ret = register_framebuffer(&fb_info);
|
||||
if (ret < 0)
|
||||
goto dealloc_cmap;
|
||||
|
||||
printk(KERN_INFO "fb%d: %s frame buffer device\n",
|
||||
fb_info.node, fb_info.fix.id);
|
||||
|
||||
return 0;
|
||||
|
||||
dealloc_cmap:
|
||||
fb_dealloc_cmap(&fb_info.cmap);
|
||||
|
||||
unmap_screen_base:
|
||||
if (fb_info.screen_base) {
|
||||
iounmap(fb_info.screen_base);
|
||||
fb_info.screen_base = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -345,6 +356,9 @@ static void __devexit hpfb_remove_one(struct dio_dev *d)
|
|||
if (d->scode >= DIOII_SCBASE)
|
||||
iounmap((void *)fb_regs);
|
||||
release_mem_region(d->resource.start, resource_size(&d->resource));
|
||||
fb_dealloc_cmap(&fb_info.cmap);
|
||||
if (fb_info.screen_base)
|
||||
iounmap(fb_info.screen_base);
|
||||
}
|
||||
|
||||
static struct dio_device_id hpfb_dio_tbl[] = {
|
||||
|
|
|
|||
|
|
@ -803,6 +803,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
|
|||
fbi->regs = ioremap(res->start, resource_size(res));
|
||||
if (fbi->regs == NULL) {
|
||||
dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
|
||||
ret = -ENOMEM;
|
||||
goto failed_ioremap;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -632,23 +632,10 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
|
|||
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;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
fb->fbops = &jzfb_ops;
|
||||
|
|
@ -657,27 +644,26 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
|
|||
jzfb = fb->par;
|
||||
jzfb->pdev = pdev;
|
||||
jzfb->pdata = pdata;
|
||||
jzfb->mem = mem;
|
||||
|
||||
jzfb->ldclk = clk_get(&pdev->dev, "lcd");
|
||||
jzfb->ldclk = devm_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");
|
||||
jzfb->lpclk = devm_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;
|
||||
goto err_framebuffer_release;
|
||||
}
|
||||
|
||||
jzfb->base = ioremap(mem->start, resource_size(mem));
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
jzfb->base = devm_request_and_ioremap(&pdev->dev, mem);
|
||||
if (!jzfb->base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
|
||||
ret = -EBUSY;
|
||||
goto err_put_lpclk;
|
||||
goto err_framebuffer_release;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, jzfb);
|
||||
|
|
@ -693,7 +679,7 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
|
|||
ret = jzfb_alloc_devmem(jzfb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to allocate video memory\n");
|
||||
goto err_iounmap;
|
||||
goto err_framebuffer_release;
|
||||
}
|
||||
|
||||
fb->fix = jzfb_fix;
|
||||
|
|
@ -734,16 +720,8 @@ err_free_devmem:
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -756,17 +734,11 @@ static int __devexit jzfb_remove(struct platform_device *pdev)
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -1052,12 +1052,14 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
|
|||
break;
|
||||
default:
|
||||
/* should never occur */
|
||||
ret = -EIO;
|
||||
goto rel_reg;
|
||||
}
|
||||
|
||||
par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
|
||||
if (par->fb_base == NULL) {
|
||||
dev_err(dev, "Cannot map framebuffer\n");
|
||||
ret = -EIO;
|
||||
goto rel_reg;
|
||||
}
|
||||
|
||||
|
|
@ -1073,11 +1075,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
|
|||
dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
|
||||
(unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
|
||||
|
||||
if (mb862xx_pci_gdc_init(par))
|
||||
ret = mb862xx_pci_gdc_init(par);
|
||||
if (ret)
|
||||
goto io_unmap;
|
||||
|
||||
if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
|
||||
DRV_NAME, (void *)par)) {
|
||||
ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
|
||||
DRV_NAME, (void *)par);
|
||||
if (ret) {
|
||||
dev_err(dev, "Cannot request irq\n");
|
||||
goto io_unmap;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <video/mbxfb.h>
|
||||
|
||||
|
|
@ -939,8 +938,9 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
|
|||
}
|
||||
mfbi->reg_phys_addr = mfbi->reg_res->start;
|
||||
|
||||
mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr,
|
||||
res_size(mfbi->reg_req));
|
||||
mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev,
|
||||
mfbi->reg_phys_addr,
|
||||
res_size(mfbi->reg_req));
|
||||
if (!mfbi->reg_virt_addr) {
|
||||
dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
|
||||
ret = -EINVAL;
|
||||
|
|
@ -948,12 +948,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
|
|||
}
|
||||
virt_base_2700 = mfbi->reg_virt_addr;
|
||||
|
||||
mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
|
||||
res_size(mfbi->fb_req));
|
||||
mfbi->fb_virt_addr = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr,
|
||||
res_size(mfbi->fb_req));
|
||||
if (!mfbi->fb_virt_addr) {
|
||||
dev_err(&dev->dev, "failed to ioremap frame buffer\n");
|
||||
ret = -EINVAL;
|
||||
goto err4;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
|
||||
|
|
@ -971,7 +971,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
|
|||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "fb_alloc_cmap failed\n");
|
||||
ret = -EINVAL;
|
||||
goto err5;
|
||||
goto err3;
|
||||
}
|
||||
|
||||
platform_set_drvdata(dev, fbi);
|
||||
|
|
@ -996,10 +996,6 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
|
|||
|
||||
err6:
|
||||
fb_dealloc_cmap(&fbi->cmap);
|
||||
err5:
|
||||
iounmap(mfbi->fb_virt_addr);
|
||||
err4:
|
||||
iounmap(mfbi->reg_virt_addr);
|
||||
err3:
|
||||
release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
|
||||
err2:
|
||||
|
|
@ -1026,10 +1022,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
|
|||
if (mfbi->platform_remove)
|
||||
mfbi->platform_remove(fbi);
|
||||
|
||||
if (mfbi->fb_virt_addr)
|
||||
iounmap(mfbi->fb_virt_addr);
|
||||
if (mfbi->reg_virt_addr)
|
||||
iounmap(mfbi->reg_virt_addr);
|
||||
|
||||
if (mfbi->reg_req)
|
||||
release_mem_region(mfbi->reg_req->start,
|
||||
res_size(mfbi->reg_req));
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sched.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/platform_data/video-msm_fb.h>
|
||||
#include "mddi_hw.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -189,8 +189,9 @@ static int mddi_nt35399_probe(struct platform_device *pdev)
|
|||
|
||||
int ret;
|
||||
|
||||
struct panel_info *panel = kzalloc(sizeof(struct panel_info),
|
||||
GFP_KERNEL);
|
||||
struct panel_info *panel = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct panel_info),
|
||||
GFP_KERNEL);
|
||||
|
||||
printk(KERN_DEBUG "%s: enter.\n", __func__);
|
||||
|
||||
|
|
@ -233,7 +234,6 @@ static int mddi_nt35399_remove(struct platform_device *pdev)
|
|||
struct panel_info *panel = platform_get_drvdata(pdev);
|
||||
|
||||
setup_vsync(panel, 0);
|
||||
kfree(panel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <linux/major.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <linux/platform_data/video-msm_fb.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/export.h>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#ifndef _MDP_HW_H_
|
||||
#define _MDP_HW_H_
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
#include <linux/platform_data/video-msm_fb.h>
|
||||
|
||||
struct mdp_info {
|
||||
|
|
|
|||
|
|
@ -1568,7 +1568,8 @@ static int mx3fb_remove(struct platform_device *dev)
|
|||
|
||||
static struct platform_driver mx3fb_driver = {
|
||||
.driver = {
|
||||
.name = MX3FB_NAME,
|
||||
.name = MX3FB_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = mx3fb_probe,
|
||||
.remove = mx3fb_remove,
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)
|
|||
* The buffer should be a non-cached, non-buffered, memory region
|
||||
* to allow palette and pixel writes without flushing the cache.
|
||||
*/
|
||||
static int __init nuc900fb_map_video_memory(struct fb_info *info)
|
||||
static int __devinit nuc900fb_map_video_memory(struct fb_info *info)
|
||||
{
|
||||
struct nuc900fb_info *fbi = info->par;
|
||||
dma_addr_t map_dma;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <plat/dma.h>
|
||||
#include "omapfb.h"
|
||||
|
||||
#define HWA742_REV_CODE_REG 0x0
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <plat/fpga.h>
|
||||
#include "omapfb.h"
|
||||
|
||||
static int palmte_panel_init(struct lcd_panel *panel,
|
||||
|
|
|
|||
|
|
@ -131,15 +131,6 @@ static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
|
|||
* LCD controller and LCD DMA
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
/* Lookup table to map elem size to elem type. */
|
||||
static const int dma_elem_type[] = {
|
||||
0,
|
||||
OMAP_DMA_DATA_TYPE_S8,
|
||||
OMAP_DMA_DATA_TYPE_S16,
|
||||
0,
|
||||
OMAP_DMA_DATA_TYPE_S32,
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocate resources needed for LCD controller and LCD DMA operations. Video
|
||||
* memory is allocated from system memory according to the virtual display
|
||||
|
|
|
|||
|
|
@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
|
|||
|
||||
mutex_lock(&md->mutex);
|
||||
|
||||
omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
|
||||
|
||||
r = omapdss_sdi_display_enable(dssdev);
|
||||
if (r) {
|
||||
pr_err("%s sdi enable failed\n", __func__);
|
||||
|
|
@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)
|
|||
static void acx_panel_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
omapdss_sdi_display_disable(dssdev);
|
||||
omapdss_sdi_set_timings(dssdev, timings);
|
||||
|
||||
dssdev->panel.timings = *timings;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = omapdss_sdi_display_enable(dssdev);
|
||||
if (r)
|
||||
dev_err(&dssdev->dev, "%s enable failed\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static int acx_panel_check_timings(struct omap_dss_device *dssdev,
|
||||
|
|
|
|||
|
|
@ -545,6 +545,8 @@ struct panel_drv_data {
|
|||
struct omap_dss_device *dssdev;
|
||||
|
||||
struct panel_config *panel_config;
|
||||
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static inline struct panel_generic_dpi_data
|
||||
|
|
@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
|
@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
|
|||
drv_data->dssdev = dssdev;
|
||||
drv_data->panel_config = panel_config;
|
||||
|
||||
mutex_init(&drv_data->lock);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, drv_data);
|
||||
|
||||
return 0;
|
||||
|
|
@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
|
|||
|
||||
static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
r = generic_dpi_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
err:
|
||||
mutex_unlock(&drv_data->lock);
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
generic_dpi_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
mutex_unlock(&drv_data->lock);
|
||||
}
|
||||
|
||||
static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
generic_dpi_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
|
||||
mutex_unlock(&drv_data->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
r = generic_dpi_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&drv_data->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
dpi_set_timings(dssdev, timings);
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, timings);
|
||||
|
||||
dssdev->panel.timings = *timings;
|
||||
|
||||
mutex_unlock(&drv_data->lock);
|
||||
}
|
||||
|
||||
static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
*timings = dssdev->panel.timings;
|
||||
|
||||
mutex_unlock(&drv_data->lock);
|
||||
}
|
||||
|
||||
static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
return dpi_check_timings(dssdev, timings);
|
||||
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
mutex_lock(&drv_data->lock);
|
||||
|
||||
r = dpi_check_timings(dssdev, timings);
|
||||
|
||||
mutex_unlock(&drv_data->lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver dpi_driver = {
|
||||
|
|
@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {
|
|||
.resume = generic_dpi_panel_resume,
|
||||
|
||||
.set_timings = generic_dpi_panel_set_timings,
|
||||
.get_timings = generic_dpi_panel_get_timings,
|
||||
.check_timings = generic_dpi_panel_check_timings,
|
||||
|
||||
.driver = {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
|
|
|||
|
|
@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
|
|||
BLIZZARD_SRC_WRITE_LCD :
|
||||
BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
|
||||
|
||||
omap_rfbi_configure(dssdev, 16, 8);
|
||||
omapdss_rfbi_set_pixel_size(dssdev, 16);
|
||||
omapdss_rfbi_set_data_lines(dssdev, 8);
|
||||
|
||||
omap_rfbi_configure(dssdev);
|
||||
|
||||
blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
|
||||
|
||||
omap_rfbi_configure(dssdev, 16, 16);
|
||||
omapdss_rfbi_set_pixel_size(dssdev, 16);
|
||||
omapdss_rfbi_set_data_lines(dssdev, 16);
|
||||
|
||||
omap_rfbi_configure(dssdev);
|
||||
}
|
||||
|
||||
static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
|
||||
|
|
@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
|
|||
goto err_plat_en;
|
||||
}
|
||||
|
||||
omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
|
||||
omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
|
||||
omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
|
||||
|
||||
r = omapdss_rfbi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err_rfbi_en;
|
||||
|
|
@ -477,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
|
|||
dssdev->panel.timings.y_res = 480;
|
||||
dssdev->ctrl.pixel_size = 16;
|
||||
dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
props.max_brightness = 127;
|
||||
|
|
@ -625,17 +638,25 @@ static int n8x0_panel_update(struct omap_dss_device *dssdev,
|
|||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
struct panel_drv_data *ddata = get_drv_data(dssdev);
|
||||
u16 dw, dh;
|
||||
|
||||
dev_dbg(&dssdev->dev, "update\n");
|
||||
|
||||
dw = dssdev->panel.timings.x_res;
|
||||
dh = dssdev->panel.timings.y_res;
|
||||
|
||||
if (x != 0 || y != 0 || w != dw || h != dh) {
|
||||
dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
|
||||
x, y, w, h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
rfbi_bus_lock();
|
||||
|
||||
omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
|
||||
|
||||
blizzard_ctrl_setup_update(dssdev, x, y, w, h);
|
||||
|
||||
omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL);
|
||||
omap_rfbi_update(dssdev, update_done, NULL);
|
||||
|
||||
mutex_unlock(&ddata->lock);
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
|
|
|||
|
|
@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
|
|||
* then only i2c commands can be successfully sent to dpp2600
|
||||
*/
|
||||
msleep(1000);
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable DPI\n");
|
||||
|
|
|
|||
|
|
@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,18 @@ struct taal_data {
|
|||
|
||||
struct omap_dss_device *dssdev;
|
||||
|
||||
/* panel specific HW info */
|
||||
struct panel_config *panel_config;
|
||||
|
||||
/* panel HW configuration from DT or platform data */
|
||||
int reset_gpio;
|
||||
int ext_te_gpio;
|
||||
|
||||
bool use_dsi_backlight;
|
||||
|
||||
struct omap_dsi_pin_config pin_config;
|
||||
|
||||
/* runtime variables */
|
||||
bool enabled;
|
||||
u8 rotate;
|
||||
bool mirror;
|
||||
|
|
@ -145,16 +157,8 @@ struct taal_data {
|
|||
bool ulps_enabled;
|
||||
unsigned ulps_timeout;
|
||||
struct delayed_work ulps_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 taal_ulps_work(struct work_struct *work);
|
||||
|
||||
|
|
@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
|
|||
static int taal_enter_ulps(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;
|
||||
|
||||
if (td->ulps_enabled)
|
||||
|
|
@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
|
||||
if (gpio_is_valid(td->ext_te_gpio))
|
||||
disable_irq(gpio_to_irq(td->ext_te_gpio));
|
||||
|
||||
omapdss_dsi_display_disable(dssdev, false, true);
|
||||
|
||||
|
|
@ -405,7 +409,6 @@ err:
|
|||
static int taal_exit_ulps(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;
|
||||
|
||||
if (!td->ulps_enabled)
|
||||
|
|
@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
|
|||
goto err2;
|
||||
}
|
||||
|
||||
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
|
||||
if (gpio_is_valid(td->ext_te_gpio))
|
||||
enable_irq(gpio_to_irq(td->ext_te_gpio));
|
||||
|
||||
taal_queue_ulps_work(dssdev);
|
||||
|
||||
|
|
@ -438,7 +442,8 @@ err2:
|
|||
|
||||
r = taal_panel_reset(dssdev);
|
||||
if (!r) {
|
||||
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
|
||||
if (gpio_is_valid(td->ext_te_gpio))
|
||||
enable_irq(gpio_to_irq(td->ext_te_gpio));
|
||||
td->ulps_enabled = false;
|
||||
}
|
||||
err1:
|
||||
|
|
@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = {
|
|||
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)
|
||||
if (!gpio_is_valid(td->reset_gpio))
|
||||
return;
|
||||
|
||||
gpio_set_value(panel_data->reset_gpio, 1);
|
||||
gpio_set_value(td->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);
|
||||
gpio_set_value(td->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);
|
||||
gpio_set_value(td->reset_gpio, 1);
|
||||
/* wait after releasing reset */
|
||||
if (td->panel_config->sleep.hw_reset)
|
||||
msleep(td->panel_config->sleep.hw_reset);
|
||||
}
|
||||
|
||||
static void taal_probe_pdata(struct taal_data *td,
|
||||
const struct nokia_dsi_panel_data *pdata)
|
||||
{
|
||||
td->reset_gpio = pdata->reset_gpio;
|
||||
|
||||
if (pdata->use_ext_te)
|
||||
td->ext_te_gpio = pdata->ext_te_gpio;
|
||||
else
|
||||
td->ext_te_gpio = -1;
|
||||
|
||||
td->esd_interval = pdata->esd_interval;
|
||||
td->ulps_timeout = pdata->ulps_timeout;
|
||||
|
||||
td->use_dsi_backlight = pdata->use_dsi_backlight;
|
||||
|
||||
td->pin_config = pdata->pin_config;
|
||||
}
|
||||
|
||||
static int taal_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
struct taal_data *td;
|
||||
struct backlight_device *bldev = NULL;
|
||||
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
|
||||
struct panel_config *panel_config = NULL;
|
||||
int r, i;
|
||||
const char *panel_name;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
||||
if (!panel_data || !panel_data->name) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL);
|
||||
if (!td)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, td);
|
||||
td->dssdev = dssdev;
|
||||
|
||||
if (dssdev->data) {
|
||||
const struct nokia_dsi_panel_data *pdata = dssdev->data;
|
||||
|
||||
taal_probe_pdata(td, pdata);
|
||||
|
||||
panel_name = pdata->name;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (panel_name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
|
||||
if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
|
||||
panel_config = &panel_configs[i];
|
||||
if (strcmp(panel_name, panel_configs[i].name) == 0) {
|
||||
td->panel_config = &panel_configs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!panel_config) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (!td->panel_config)
|
||||
return -EINVAL;
|
||||
|
||||
dssdev->panel.timings = panel_config->timings;
|
||||
dssdev->panel.timings = td->panel_config->timings;
|
||||
dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
|
||||
|
||||
td = kzalloc(sizeof(*td), GFP_KERNEL);
|
||||
if (!td) {
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
td->dssdev = dssdev;
|
||||
td->panel_config = panel_config;
|
||||
td->esd_interval = panel_data->esd_interval;
|
||||
td->ulps_enabled = false;
|
||||
td->ulps_timeout = panel_data->ulps_timeout;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
|
||||
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
|
||||
|
||||
mutex_init(&td->lock);
|
||||
|
||||
atomic_set(&td->do_update, 0);
|
||||
|
||||
if (gpio_is_valid(td->reset_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "taal rst");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to request reset gpio\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_is_valid(td->ext_te_gpio)) {
|
||||
r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio,
|
||||
GPIOF_IN, "taal irq");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "GPIO request failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio),
|
||||
taal_te_isr,
|
||||
IRQF_TRIGGER_RISING,
|
||||
"taal vsync", dssdev);
|
||||
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "IRQ request failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
INIT_DEFERRABLE_WORK(&td->te_timeout_work,
|
||||
taal_te_timeout_work_callback);
|
||||
|
||||
dev_dbg(&dssdev->dev, "Using GPIO TE\n");
|
||||
}
|
||||
|
||||
td->workqueue = create_singlethread_workqueue("taal_esd");
|
||||
if (td->workqueue == NULL) {
|
||||
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
|
||||
r = -ENOMEM;
|
||||
goto err_wq;
|
||||
return -ENOMEM;
|
||||
}
|
||||
INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work);
|
||||
INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, td);
|
||||
|
||||
if (gpio_is_valid(panel_data->reset_gpio)) {
|
||||
r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
|
||||
"taal rst");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to request reset gpio\n");
|
||||
goto err_rst_gpio;
|
||||
}
|
||||
}
|
||||
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
if (panel_data->use_dsi_backlight) {
|
||||
if (td->use_dsi_backlight) {
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = 255;
|
||||
|
||||
|
|
@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
taal_bl_update_status(bldev);
|
||||
}
|
||||
|
||||
if (panel_data->use_ext_te) {
|
||||
int gpio = panel_data->ext_te_gpio;
|
||||
|
||||
r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "GPIO request failed\n");
|
||||
goto err_gpio;
|
||||
}
|
||||
|
||||
r = request_irq(gpio_to_irq(gpio), taal_te_isr,
|
||||
IRQF_TRIGGER_RISING,
|
||||
"taal vsync", dssdev);
|
||||
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "IRQ request failed\n");
|
||||
gpio_free(gpio);
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
INIT_DEFERRABLE_WORK(&td->te_timeout_work,
|
||||
taal_te_timeout_work_callback);
|
||||
|
||||
dev_dbg(&dssdev->dev, "Using GPIO TE\n");
|
||||
}
|
||||
|
||||
r = omap_dsi_request_vc(dssdev, &td->channel);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to get virtual channel\n");
|
||||
|
|
@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
err_vc_id:
|
||||
omap_dsi_release_vc(dssdev, td->channel);
|
||||
err_req_vc:
|
||||
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:
|
||||
if (bldev != NULL)
|
||||
backlight_device_unregister(bldev);
|
||||
err_bl:
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_free(panel_data->reset_gpio);
|
||||
err_rst_gpio:
|
||||
destroy_workqueue(td->workqueue);
|
||||
err_wq:
|
||||
kfree(td);
|
||||
err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit 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");
|
||||
|
|
@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
|
|||
sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
|
||||
omap_dsi_release_vc(dssdev, td->channel);
|
||||
|
||||
if (panel_data->use_ext_te) {
|
||||
int gpio = panel_data->ext_te_gpio;
|
||||
free_irq(gpio_to_irq(gpio), dssdev);
|
||||
gpio_free(gpio);
|
||||
}
|
||||
|
||||
bldev = td->bldev;
|
||||
if (bldev != NULL) {
|
||||
bldev->props.power = FB_BLANK_POWERDOWN;
|
||||
|
|
@ -1040,26 +1042,31 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
|
|||
|
||||
/* reset, to be sure that the panel is in a valid state */
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_free(panel_data->reset_gpio);
|
||||
|
||||
kfree(td);
|
||||
}
|
||||
|
||||
static int taal_power_on(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);
|
||||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
||||
r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config);
|
||||
r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to configure DSI pins\n");
|
||||
goto err0;
|
||||
};
|
||||
|
||||
omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
|
||||
omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
|
||||
|
||||
r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
r = omapdss_dsi_display_enable(dssdev);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable DSI\n");
|
||||
|
|
@ -1356,7 +1363,6 @@ 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);
|
||||
|
|
@ -1380,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
|
||||
schedule_delayed_work(&td->te_timeout_work,
|
||||
msecs_to_jiffies(250));
|
||||
atomic_set(&td->do_update, 1);
|
||||
|
|
@ -1419,7 +1425,6 @@ 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;
|
||||
|
||||
if (enable)
|
||||
|
|
@ -1427,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
|||
else
|
||||
r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
|
||||
|
||||
if (!panel_data->use_ext_te)
|
||||
if (!gpio_is_valid(td->ext_te_gpio))
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
|
||||
if (td->panel_config->sleep.enable_te)
|
||||
|
|
@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)
|
|||
static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
u16 dw, dh;
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
|
||||
|
|
@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (rotate == 0 || rotate == 2) {
|
||||
dw = dssdev->panel.timings.x_res;
|
||||
dh = dssdev->panel.timings.y_res;
|
||||
} else {
|
||||
dw = dssdev->panel.timings.y_res;
|
||||
dh = dssdev->panel.timings.x_res;
|
||||
}
|
||||
|
||||
omapdss_dsi_set_size(dssdev, dw, dh);
|
||||
|
||||
td->rotate = rotate;
|
||||
|
||||
dsi_bus_unlock(dssdev);
|
||||
|
|
@ -1726,7 +1742,6 @@ 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;
|
||||
|
||||
|
|
@ -1773,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work)
|
|||
}
|
||||
/* Self-diagnostics result is also shown on TE GPIO line. We need
|
||||
* to re-enable TE after self diagnostics */
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
|
||||
r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
|
||||
if (r)
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
|
@ -116,8 +119,8 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
|||
}
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio)) {
|
||||
r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
|
||||
"tfp410 pd");
|
||||
r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio,
|
||||
GPIOF_OUT_INIT_LOW, "tfp410 pd");
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
|
||||
ddata->pd_gpio);
|
||||
|
|
@ -132,8 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
|||
if (!adapter) {
|
||||
dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
|
||||
i2c_bus_num);
|
||||
r = -EINVAL;
|
||||
goto err_i2c;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ddata->i2c_adapter = adapter;
|
||||
|
|
@ -142,10 +144,6 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
|||
dev_set_drvdata(&dssdev->dev, ddata);
|
||||
|
||||
return 0;
|
||||
err_i2c:
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_free(ddata->pd_gpio);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit tfp410_remove(struct omap_dss_device *dssdev)
|
||||
|
|
@ -157,9 +155,6 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)
|
|||
if (ddata->i2c_adapter)
|
||||
i2c_put_adapter(ddata->i2c_adapter);
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_free(ddata->pd_gpio);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, NULL);
|
||||
|
||||
mutex_unlock(&ddata->lock);
|
||||
|
|
@ -231,7 +226,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
|
|||
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
dpi_set_timings(dssdev, timings);
|
||||
omapdss_dpi_set_timings(dssdev, timings);
|
||||
dssdev->panel.timings = *timings;
|
||||
mutex_unlock(&ddata->lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
|
|||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
|
@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
|
|||
static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
dpi_set_timings(dssdev, timings);
|
||||
omapdss_dpi_set_timings(dssdev, timings);
|
||||
|
||||
dssdev->panel.timings = *timings;
|
||||
}
|
||||
|
||||
static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ config OMAP2_DSS_SDI
|
|||
|
||||
config OMAP2_DSS_DSI
|
||||
bool "DSI support"
|
||||
depends on ARCH_OMAP3 || ARCH_OMAP4
|
||||
depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
|
||||
default n
|
||||
help
|
||||
MIPI DSI (Display Serial Interface) support.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
|
||||
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
|
||||
manager.o overlay.o apply.o
|
||||
manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
|
||||
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
|
||||
|
|
|
|||
|
|
@ -111,9 +111,6 @@ static struct {
|
|||
struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
|
||||
struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
|
||||
|
||||
bool fifo_merge_dirty;
|
||||
bool fifo_merge;
|
||||
|
||||
bool irq_enabled;
|
||||
} dss_data;
|
||||
|
||||
|
|
@ -424,17 +421,25 @@ static void wait_pending_extra_info_updates(void)
|
|||
int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
struct mgr_priv_data *mp;
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
u32 irq;
|
||||
unsigned long flags;
|
||||
int r;
|
||||
int i;
|
||||
struct omap_dss_device *dssdev = mgr->device;
|
||||
|
||||
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (mgr_manual_update(mgr))
|
||||
if (mgr_manual_update(mgr)) {
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mp->enabled) {
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
|
|
@ -442,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|||
|
||||
irq = dispc_mgr_get_vsync_irq(mgr->id);
|
||||
|
||||
mp = get_mgr_priv(mgr);
|
||||
i = 0;
|
||||
while (1) {
|
||||
unsigned long flags;
|
||||
bool shadow_dirty, dirty;
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
|
@ -489,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
struct ovl_priv_data *op;
|
||||
struct omap_dss_device *dssdev;
|
||||
struct mgr_priv_data *mp;
|
||||
u32 irq;
|
||||
unsigned long flags;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
if (!ovl->manager)
|
||||
return 0;
|
||||
|
||||
dssdev = ovl->manager->device;
|
||||
mp = get_mgr_priv(ovl->manager);
|
||||
|
||||
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (ovl_manual_update(ovl))
|
||||
if (ovl_manual_update(ovl)) {
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mp->enabled) {
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
|
|
@ -514,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|||
op = get_ovl_priv(ovl);
|
||||
i = 0;
|
||||
while (1) {
|
||||
unsigned long flags;
|
||||
bool shadow_dirty, dirty;
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
|
@ -573,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
|
|||
|
||||
replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
|
||||
|
||||
r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings);
|
||||
r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
|
||||
if (r) {
|
||||
/*
|
||||
* We can't do much here, as this function can be called from
|
||||
|
|
@ -677,40 +688,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
|
|||
mp->shadow_extra_info_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_write_regs_common(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
int i;
|
||||
|
||||
if (!dss_data.fifo_merge_dirty)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct mgr_priv_data *mp;
|
||||
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (mp->enabled) {
|
||||
if (dss_data.fifo_merge_dirty) {
|
||||
dispc_enable_fifomerge(dss_data.fifo_merge);
|
||||
dss_data.fifo_merge_dirty = false;
|
||||
}
|
||||
|
||||
if (mp->updating)
|
||||
mp->shadow_info_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dss_write_regs(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
int i;
|
||||
|
||||
dss_write_regs_common();
|
||||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct mgr_priv_data *mp;
|
||||
|
|
@ -799,8 +781,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
|||
dss_mgr_write_regs(mgr);
|
||||
dss_mgr_write_regs_extra(mgr);
|
||||
|
||||
dss_write_regs_common();
|
||||
|
||||
mp->updating = true;
|
||||
|
||||
if (!dss_data.irq_enabled && need_isr())
|
||||
|
|
@ -984,20 +964,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
|
|||
op->extra_info_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_apply_fifo_merge(bool use_fifo_merge)
|
||||
{
|
||||
if (dss_data.fifo_merge == use_fifo_merge)
|
||||
return;
|
||||
|
||||
dss_data.fifo_merge = use_fifo_merge;
|
||||
dss_data.fifo_merge_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
|
||||
bool use_fifo_merge)
|
||||
static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
|
||||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
u32 fifo_low, fifo_high;
|
||||
bool use_fifo_merge = false;
|
||||
|
||||
if (!op->enabled && !op->enabling)
|
||||
return;
|
||||
|
|
@ -1008,8 +979,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
|
|||
dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
|
||||
}
|
||||
|
||||
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
|
||||
bool use_fifo_merge)
|
||||
static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct omap_overlay *ovl;
|
||||
struct mgr_priv_data *mp;
|
||||
|
|
@ -1020,10 +990,10 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
|
|||
return;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list)
|
||||
dss_ovl_setup_fifo(ovl, use_fifo_merge);
|
||||
dss_ovl_setup_fifo(ovl);
|
||||
}
|
||||
|
||||
static void dss_setup_fifos(bool use_fifo_merge)
|
||||
static void dss_setup_fifos(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
struct omap_overlay_manager *mgr;
|
||||
|
|
@ -1031,91 +1001,15 @@ static void dss_setup_fifos(bool use_fifo_merge)
|
|||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
dss_mgr_setup_fifos(mgr, use_fifo_merge);
|
||||
dss_mgr_setup_fifos(mgr);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_num_used_managers(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct mgr_priv_data *mp;
|
||||
int i;
|
||||
int enabled_mgrs;
|
||||
|
||||
enabled_mgrs = 0;
|
||||
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (!mp->enabled)
|
||||
continue;
|
||||
|
||||
enabled_mgrs++;
|
||||
}
|
||||
|
||||
return enabled_mgrs;
|
||||
}
|
||||
|
||||
static int get_num_used_overlays(void)
|
||||
{
|
||||
const int num_ovls = omap_dss_get_num_overlays();
|
||||
struct omap_overlay *ovl;
|
||||
struct ovl_priv_data *op;
|
||||
struct mgr_priv_data *mp;
|
||||
int i;
|
||||
int enabled_ovls;
|
||||
|
||||
enabled_ovls = 0;
|
||||
|
||||
for (i = 0; i < num_ovls; ++i) {
|
||||
ovl = omap_dss_get_overlay(i);
|
||||
op = get_ovl_priv(ovl);
|
||||
|
||||
if (!op->enabled && !op->enabling)
|
||||
continue;
|
||||
|
||||
mp = get_mgr_priv(ovl->manager);
|
||||
|
||||
if (!mp->enabled)
|
||||
continue;
|
||||
|
||||
enabled_ovls++;
|
||||
}
|
||||
|
||||
return enabled_ovls;
|
||||
}
|
||||
|
||||
static bool get_use_fifo_merge(void)
|
||||
{
|
||||
int enabled_mgrs = get_num_used_managers();
|
||||
int enabled_ovls = get_num_used_overlays();
|
||||
|
||||
if (!dss_has_feature(FEAT_FIFO_MERGE))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* In theory the only requirement for fifomerge is enabled_ovls <= 1.
|
||||
* However, if we have two managers enabled and set/unset the fifomerge,
|
||||
* we need to set the GO bits in particular sequence for the managers,
|
||||
* and wait in between.
|
||||
*
|
||||
* This is rather difficult as new apply calls can happen at any time,
|
||||
* so we simplify the problem by requiring also that enabled_mgrs <= 1.
|
||||
* In practice this shouldn't matter, because when only one overlay is
|
||||
* enabled, most likely only one output is enabled.
|
||||
*/
|
||||
|
||||
return enabled_mgrs <= 1 && enabled_ovls <= 1;
|
||||
}
|
||||
|
||||
int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
unsigned long flags;
|
||||
int r;
|
||||
bool fifo_merge;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
|
|
@ -1133,23 +1027,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* step 1: setup fifos/fifomerge before enabling the manager */
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
dss_setup_fifos();
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait until fifo config is in */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
/* step 2: enable the manager */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (!mgr_manual_update(mgr))
|
||||
mp->updating = true;
|
||||
|
||||
|
|
@ -1174,7 +1056,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
unsigned long flags;
|
||||
bool fifo_merge;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
|
|
@ -1189,16 +1070,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
|
|||
mp->updating = false;
|
||||
mp->enabled = false;
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
out:
|
||||
mutex_unlock(&apply_lock);
|
||||
}
|
||||
|
|
@ -1237,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
}
|
||||
|
||||
int dss_mgr_set_device(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev)
|
||||
int dss_mgr_set_output(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_output *output)
|
||||
{
|
||||
int r;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
if (dssdev->manager) {
|
||||
DSSERR("display '%s' already has a manager '%s'\n",
|
||||
dssdev->name, dssdev->manager->name);
|
||||
if (mgr->output) {
|
||||
DSSERR("manager %s is already connected to an output\n",
|
||||
mgr->name);
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((mgr->supported_displays & dssdev->type) == 0) {
|
||||
DSSERR("display '%s' does not support manager '%s'\n",
|
||||
dssdev->name, mgr->name);
|
||||
if ((mgr->supported_outputs & output->id) == 0) {
|
||||
DSSERR("output does not support manager %s\n",
|
||||
mgr->name);
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dssdev->manager = mgr;
|
||||
mgr->device = dssdev;
|
||||
output->manager = mgr;
|
||||
mgr->output = output;
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
|
|
@ -1269,40 +1142,46 @@ err:
|
|||
return r;
|
||||
}
|
||||
|
||||
int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
|
||||
int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
int r;
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
if (!mgr->device) {
|
||||
DSSERR("failed to unset display, display not set.\n");
|
||||
if (!mgr->output) {
|
||||
DSSERR("failed to unset output, output not set\n");
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow currently enabled displays to have the overlay manager
|
||||
* pulled out from underneath them
|
||||
*/
|
||||
if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (mp->enabled) {
|
||||
DSSERR("output can't be unset when manager is enabled\n");
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
mgr->device->manager = NULL;
|
||||
mgr->device = NULL;
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
mgr->output->manager = NULL;
|
||||
mgr->output = NULL;
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
err:
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
|
||||
struct omap_video_timings *timings)
|
||||
const struct omap_video_timings *timings)
|
||||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
|
|
@ -1311,24 +1190,22 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
|
|||
}
|
||||
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
struct omap_video_timings *timings)
|
||||
const struct omap_video_timings *timings)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (mp->updating) {
|
||||
DSSERR("cannot set timings for %s: manager needs to be disabled\n",
|
||||
mgr->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dss_apply_mgr_timings(mgr, timings);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
}
|
||||
|
||||
static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
|
||||
|
|
@ -1346,7 +1223,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
|||
unsigned long flags;
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
if (mp->enabled) {
|
||||
DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
|
||||
|
|
@ -1354,19 +1231,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
|||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
dss_apply_mgr_lcd_config(mgr, config);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
out:
|
||||
mutex_unlock(&apply_lock);
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
}
|
||||
|
||||
int dss_ovl_set_info(struct omap_overlay *ovl,
|
||||
|
|
@ -1483,6 +1350,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
|
|||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for pending extra_info updates to ensure the ovl is disabled */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
op->channel = -1;
|
||||
|
||||
ovl->manager = NULL;
|
||||
|
|
@ -1517,7 +1391,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
unsigned long flags;
|
||||
bool fifo_merge;
|
||||
int r;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
|
@ -1527,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
if (ovl->manager == NULL || ovl->manager->device == NULL) {
|
||||
if (ovl->manager == NULL || ovl->manager->output == NULL) {
|
||||
r = -EINVAL;
|
||||
goto err1;
|
||||
}
|
||||
|
|
@ -1543,22 +1416,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
goto err2;
|
||||
}
|
||||
|
||||
/* step 1: configure fifos/fifomerge for currently enabled ovls */
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for fifo configs to go in */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
/* step 2: enable the overlay */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
dss_setup_fifos();
|
||||
|
||||
op->enabling = false;
|
||||
dss_apply_ovl_enable(ovl, true);
|
||||
|
|
@ -1568,9 +1426,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
|||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for overlay to be enabled */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1586,7 +1441,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)
|
|||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
unsigned long flags;
|
||||
bool fifo_merge;
|
||||
int r;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
|
@ -1596,39 +1450,19 @@ int dss_ovl_disable(struct omap_overlay *ovl)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (ovl->manager == NULL || ovl->manager->device == NULL) {
|
||||
if (ovl->manager == NULL || ovl->manager->output == NULL) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* step 1: disable the overlay */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
dss_apply_ovl_enable(ovl, false);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for the overlay to be disabled */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
/* step 2: configure fifos/fifomerge */
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
fifo_merge = get_use_fifo_merge();
|
||||
dss_setup_fifos(fifo_merge);
|
||||
dss_apply_fifo_merge(fifo_merge);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
/* wait for fifo config to go in */
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
|
|
@ -57,6 +58,11 @@ bool dss_debug;
|
|||
module_param_named(debug, dss_debug, bool, 0644);
|
||||
#endif
|
||||
|
||||
const char *dss_get_default_display_name(void)
|
||||
{
|
||||
return core.default_display_name;
|
||||
}
|
||||
|
||||
/* REGULATORS */
|
||||
|
||||
struct regulator *dss_get_vdds_dsi(void)
|
||||
|
|
@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)
|
|||
int r;
|
||||
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
bool force;
|
||||
|
||||
DSSDBG("driver_probe: dev %s/%s, drv %s\n",
|
||||
dev_name(dev), dssdev->driver_name,
|
||||
dssdrv->driver.name);
|
||||
|
||||
dss_init_device(core.pdev, dssdev);
|
||||
|
||||
force = core.default_display_name &&
|
||||
strcmp(core.default_display_name, dssdev->name) == 0;
|
||||
dss_recheck_connections(dssdev, force);
|
||||
r = dss_init_device(core.pdev, dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = dssdrv->probe(dssdev);
|
||||
|
||||
|
|
@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
|
|||
EXPORT_SYMBOL(omap_dss_unregister_driver);
|
||||
|
||||
/* DEVICE */
|
||||
static void reset_device(struct device *dev, int check)
|
||||
{
|
||||
u8 *dev_p = (u8 *)dev;
|
||||
u8 *dev_end = dev_p + sizeof(*dev);
|
||||
void *saved_pdata;
|
||||
|
||||
saved_pdata = dev->platform_data;
|
||||
if (check) {
|
||||
/*
|
||||
* Check if there is any other setting than platform_data
|
||||
* in struct device; warn that these will be reset by our
|
||||
* init.
|
||||
*/
|
||||
dev->platform_data = NULL;
|
||||
while (dev_p < dev_end) {
|
||||
if (*dev_p) {
|
||||
WARN("%s: struct device fields will be "
|
||||
"discarded\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
dev_p++;
|
||||
}
|
||||
}
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->platform_data = saved_pdata;
|
||||
}
|
||||
|
||||
|
||||
static void omap_dss_dev_release(struct device *dev)
|
||||
{
|
||||
reset_device(dev, 0);
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
kfree(dssdev);
|
||||
}
|
||||
|
||||
int omap_dss_register_device(struct omap_dss_device *dssdev,
|
||||
struct device *parent, int disp_num)
|
||||
{
|
||||
WARN_ON(!dssdev->driver_name);
|
||||
static int disp_num_counter;
|
||||
|
||||
struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
|
||||
{
|
||||
struct omap_dss_device *dssdev;
|
||||
|
||||
dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
|
||||
if (!dssdev)
|
||||
return NULL;
|
||||
|
||||
reset_device(&dssdev->dev, 1);
|
||||
dssdev->dev.bus = &dss_bus_type;
|
||||
dssdev->dev.parent = parent;
|
||||
dssdev->dev.release = omap_dss_dev_release;
|
||||
dev_set_name(&dssdev->dev, "display%d", disp_num);
|
||||
return device_register(&dssdev->dev);
|
||||
dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
|
||||
|
||||
device_initialize(&dssdev->dev);
|
||||
|
||||
return dssdev;
|
||||
}
|
||||
|
||||
void omap_dss_unregister_device(struct omap_dss_device *dssdev)
|
||||
int dss_add_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return device_add(&dssdev->dev);
|
||||
}
|
||||
|
||||
void dss_put_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
put_device(&dssdev->dev);
|
||||
}
|
||||
|
||||
void dss_unregister_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
device_unregister(&dssdev->dev);
|
||||
}
|
||||
|
|
@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)
|
|||
static int dss_unregister_dss_dev(struct device *dev, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
omap_dss_unregister_device(dssdev);
|
||||
dss_unregister_device(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void omap_dss_unregister_child_devices(struct device *parent)
|
||||
void dss_unregister_child_devices(struct device *parent)
|
||||
{
|
||||
device_for_each_child(parent, NULL, dss_unregister_dss_dev);
|
||||
}
|
||||
|
||||
void dss_copy_device_pdata(struct omap_dss_device *dst,
|
||||
const struct omap_dss_device *src)
|
||||
{
|
||||
u8 *d = (u8 *)dst;
|
||||
u8 *s = (u8 *)src;
|
||||
size_t dsize = sizeof(struct device);
|
||||
|
||||
memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
|
||||
}
|
||||
|
||||
/* BUS */
|
||||
static int __init omap_dss_bus_register(void)
|
||||
{
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -36,6 +36,7 @@
|
|||
#define DISPC_CONTROL2 0x0238
|
||||
#define DISPC_CONFIG2 0x0620
|
||||
#define DISPC_DIVISOR 0x0804
|
||||
#define DISPC_GLOBAL_BUFFER 0x0800
|
||||
#define DISPC_CONTROL3 0x0848
|
||||
#define DISPC_CONFIG3 0x084C
|
||||
|
||||
|
|
@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
|
|||
return 0x014C;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0300;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0500;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -370,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0000;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0008;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -385,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0004;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x000C;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -404,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
|
|||
return 0x04BC;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0310;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0118;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -422,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
|
|||
return 0x04C0;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0314;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x011C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -451,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x000C;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x00A8;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -467,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0010;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0070;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -486,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
|
|||
return 0x04DC;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x032C;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0310;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -501,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0014;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x008C;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -517,6 +531,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0018;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0088;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -533,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x001C;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x00A4;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -549,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0020;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0098;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -598,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0024;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0090;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -617,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
|
|||
return 0x055C;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0424;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x290;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -633,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0028;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0094;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -651,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x002C;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0000;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -670,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
|
|||
return 0x0560;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0428;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0294;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -686,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0030;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0004;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -705,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
|
|||
return 0x0564;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x042C;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0298;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -722,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0034 + i * 0x8;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0010 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -742,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
|
|||
return 0x0568 + i * 0x8;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0430 + i * 0x8;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x02A0 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -759,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0038 + i * 0x8;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0014 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -779,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
|
|||
return 0x056C + i * 0x8;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0434 + i * 0x8;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x02A4 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
@ -795,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
|
|||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0074 + i * 0x4;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -814,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
|
|||
case OMAP_DSS_VIDEO2:
|
||||
return 0x00B4 + i * 0x4;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
case OMAP_DSS_WB:
|
||||
return 0x0050 + i * 0x4;
|
||||
default:
|
||||
BUG();
|
||||
|
|
@ -834,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
|
|||
return 0x05A8 + i * 0x4;
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0470 + i * 0x4;
|
||||
case OMAP_DSS_WB:
|
||||
return 0x02E0 + i * 0x4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->driver->disable(dssdev);
|
||||
dssdev->driver->set_timings(dssdev, &t);
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
@ -316,26 +320,117 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
|
|||
}
|
||||
EXPORT_SYMBOL(omapdss_default_get_timings);
|
||||
|
||||
void dss_init_device(struct platform_device *pdev,
|
||||
/*
|
||||
* Connect dssdev to a manager if the manager is free or if force is specified.
|
||||
* Connect all overlays to that manager if they are free or if force is
|
||||
* specified.
|
||||
*/
|
||||
static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
|
||||
{
|
||||
struct omap_dss_output *out;
|
||||
struct omap_overlay_manager *mgr;
|
||||
int i, r;
|
||||
|
||||
out = omapdss_get_output_from_dssdev(dssdev);
|
||||
|
||||
WARN_ON(dssdev->output);
|
||||
WARN_ON(out->device);
|
||||
|
||||
r = omapdss_output_set_device(out, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to connect output to new device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
mgr = omap_dss_get_overlay_manager(dssdev->channel);
|
||||
|
||||
if (mgr->output && !force)
|
||||
return 0;
|
||||
|
||||
if (mgr->output)
|
||||
mgr->unset_output(mgr);
|
||||
|
||||
r = mgr->set_output(mgr, out);
|
||||
if (r) {
|
||||
DSSERR("failed to connect manager to output of new device\n");
|
||||
|
||||
/* remove the output-device connection we just made */
|
||||
omapdss_output_unset_device(out);
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
||||
struct omap_overlay *ovl = omap_dss_get_overlay(i);
|
||||
|
||||
if (!ovl->manager || force) {
|
||||
if (ovl->manager)
|
||||
ovl->unset_manager(ovl);
|
||||
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to set initial overlay\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_uninit_connections(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->output) {
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
if (mgr)
|
||||
mgr->unset_output(mgr);
|
||||
|
||||
omapdss_output_unset_device(dssdev->output);
|
||||
}
|
||||
}
|
||||
|
||||
int dss_init_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct device_attribute *attr;
|
||||
int i;
|
||||
int r;
|
||||
int i, r;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
bool force;
|
||||
|
||||
force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
|
||||
dss_init_connections(dssdev, force);
|
||||
|
||||
/* create device sysfs files */
|
||||
i = 0;
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL) {
|
||||
r = device_create_file(&dssdev->dev, attr);
|
||||
if (r)
|
||||
if (r) {
|
||||
for (i = i - 2; i >= 0; i--) {
|
||||
attr = display_sysfs_attrs[i];
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
}
|
||||
|
||||
dss_uninit_connections(dssdev);
|
||||
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* create display? sysfs links */
|
||||
r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
|
||||
dev_name(&dssdev->dev));
|
||||
if (r)
|
||||
if (r) {
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL)
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
|
||||
dss_uninit_connections(dssdev);
|
||||
|
||||
DSSERR("failed to create sysfs display link\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dss_uninit_device(struct platform_device *pdev,
|
||||
|
|
@ -349,8 +444,7 @@ void dss_uninit_device(struct platform_device *pdev,
|
|||
while ((attr = display_sysfs_attrs[i++]) != NULL)
|
||||
device_remove_file(&dssdev->dev, attr);
|
||||
|
||||
if (dssdev->manager)
|
||||
dssdev->manager->unset_device(dssdev->manager);
|
||||
dss_uninit_connections(dssdev);
|
||||
}
|
||||
|
||||
static int dss_suspend_device(struct device *dev, void *data)
|
||||
|
|
|
|||
|
|
@ -29,17 +29,24 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static struct {
|
||||
struct regulator *vdds_dsi_reg;
|
||||
struct platform_device *dsidev;
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
struct omap_video_timings timings;
|
||||
struct dss_lcd_mgr_config mgr_config;
|
||||
int data_lines;
|
||||
|
||||
struct omap_dss_output output;
|
||||
} dpi;
|
||||
|
||||
static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
|
||||
|
|
@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
|
|||
|
||||
static int dpi_set_mode(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_video_timings *t = &dssdev->panel.timings;
|
||||
struct omap_video_timings *t = &dpi.timings;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
int lck_div = 0, pck_div = 0;
|
||||
unsigned long fck = 0;
|
||||
unsigned long pck;
|
||||
|
|
@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
|
|||
t->pixel_clock = pck;
|
||||
}
|
||||
|
||||
dss_mgr_set_timings(dssdev->manager, t);
|
||||
dss_mgr_set_timings(mgr, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
|
||||
|
||||
dpi.mgr_config.stallmode = false;
|
||||
dpi.mgr_config.fifohandcheck = false;
|
||||
|
||||
dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines;
|
||||
dpi.mgr_config.video_port_width = dpi.data_lines;
|
||||
|
||||
dpi.mgr_config.lcden_sig_polarity = 0;
|
||||
|
||||
dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config);
|
||||
dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
|
||||
}
|
||||
|
||||
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
int r;
|
||||
|
||||
if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
|
||||
mutex_lock(&dpi.lock);
|
||||
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
|
||||
DSSERR("no VDSS_DSI regulator\n");
|
||||
return -ENODEV;
|
||||
r = -ENODEV;
|
||||
goto err_no_reg;
|
||||
}
|
||||
|
||||
if (dssdev->manager == NULL) {
|
||||
DSSERR("failed to enable display: no manager\n");
|
||||
return -ENODEV;
|
||||
if (out == NULL || out->manager == NULL) {
|
||||
DSSERR("failed to enable display: no output/manager\n");
|
||||
r = -ENODEV;
|
||||
goto err_no_out_mgr;
|
||||
}
|
||||
|
||||
r = omap_dss_start_device(dssdev);
|
||||
|
|
@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err_start_dev;
|
||||
}
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
|
||||
r = regulator_enable(dpi.vdds_dsi_reg);
|
||||
if (r)
|
||||
goto err_reg_enable;
|
||||
|
|
@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err_get_dispc;
|
||||
|
||||
r = dss_dpi_select_source(dssdev->channel);
|
||||
if (r)
|
||||
goto err_src_sel;
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
r = dsi_runtime_get(dpi.dsidev);
|
||||
if (r)
|
||||
|
|
@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
mdelay(2);
|
||||
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
r = dss_mgr_enable(out->manager);
|
||||
if (r)
|
||||
goto err_mgr_enable;
|
||||
|
||||
mutex_unlock(&dpi.lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_mgr_enable:
|
||||
|
|
@ -227,20 +248,28 @@ err_dsi_pll_init:
|
|||
if (dpi_use_dsi_pll(dssdev))
|
||||
dsi_runtime_put(dpi.dsidev);
|
||||
err_get_dsi:
|
||||
err_src_sel:
|
||||
dispc_runtime_put();
|
||||
err_get_dispc:
|
||||
if (cpu_is_omap34xx())
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
|
||||
regulator_disable(dpi.vdds_dsi_reg);
|
||||
err_reg_enable:
|
||||
omap_dss_stop_device(dssdev);
|
||||
err_start_dev:
|
||||
err_no_out_mgr:
|
||||
err_no_reg:
|
||||
mutex_unlock(&dpi.lock);
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_display_enable);
|
||||
|
||||
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
mutex_lock(&dpi.lock);
|
||||
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
|
|
@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
|||
|
||||
dispc_runtime_put();
|
||||
|
||||
if (cpu_is_omap34xx())
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
|
||||
regulator_disable(dpi.vdds_dsi_reg);
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
|
||||
mutex_unlock(&dpi.lock);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_display_disable);
|
||||
|
||||
void dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
int r;
|
||||
|
||||
DSSDBG("dpi_set_timings\n");
|
||||
dssdev->panel.timings = *timings;
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return;
|
||||
|
||||
dpi_set_mode(dssdev);
|
||||
mutex_lock(&dpi.lock);
|
||||
|
||||
dispc_runtime_put();
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, timings);
|
||||
}
|
||||
dpi.timings = *timings;
|
||||
|
||||
mutex_unlock(&dpi.lock);
|
||||
}
|
||||
EXPORT_SYMBOL(dpi_set_timings);
|
||||
EXPORT_SYMBOL(omapdss_dpi_set_timings);
|
||||
|
||||
int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
int r;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
int lck_div, pck_div;
|
||||
unsigned long fck;
|
||||
unsigned long pck;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
|
||||
if (dss_mgr_check_timings(dssdev->manager, timings))
|
||||
if (dss_mgr_check_timings(mgr, timings))
|
||||
return -EINVAL;
|
||||
|
||||
if (timings->pixel_clock == 0)
|
||||
|
|
@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
|
|||
}
|
||||
EXPORT_SYMBOL(dpi_check_timings);
|
||||
|
||||
void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
|
||||
{
|
||||
mutex_lock(&dpi.lock);
|
||||
|
||||
dpi.data_lines = data_lines;
|
||||
|
||||
mutex_unlock(&dpi.lock);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
|
||||
|
||||
static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
|
||||
if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
|
||||
dpi.vdds_dsi_reg == NULL) {
|
||||
struct regulator *vdds_dsi;
|
||||
|
||||
vdds_dsi = dss_get_vdds_dsi();
|
||||
|
|
@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __init dpi_probe_pdata(struct platform_device *pdev)
|
||||
static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i, r;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
def_dssdev = NULL;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
|
@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
|
|||
if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
|
||||
continue;
|
||||
|
||||
r = dpi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
if (def_dssdev == NULL)
|
||||
def_dssdev = dssdev;
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
if (def_disp_name != NULL &&
|
||||
strcmp(dssdev->name, def_disp_name) == 0) {
|
||||
def_dssdev = dssdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return def_dssdev;
|
||||
}
|
||||
|
||||
static void __init dpi_probe_pdata(struct platform_device *dpidev)
|
||||
{
|
||||
struct omap_dss_device *plat_dssdev;
|
||||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
|
||||
plat_dssdev = dpi_find_dssdev(dpidev);
|
||||
|
||||
if (!plat_dssdev)
|
||||
return;
|
||||
|
||||
dssdev = dss_alloc_and_init_device(&dpidev->dev);
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
dss_copy_device_pdata(dssdev, plat_dssdev);
|
||||
|
||||
r = dpi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init dpi_init_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &dpi.output;
|
||||
|
||||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_DPI;
|
||||
out->type = OMAP_DISPLAY_TYPE_DPI;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
||||
static void __exit dpi_uninit_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &dpi.output;
|
||||
|
||||
dss_unregister_output(out);
|
||||
}
|
||||
|
||||
static int __init omap_dpi_probe(struct platform_device *pdev)
|
||||
{
|
||||
mutex_init(&dpi.lock);
|
||||
|
||||
dpi_init_output(pdev);
|
||||
|
||||
dpi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
|
@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
|
|||
|
||||
static int __exit omap_dpi_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
dpi_uninit_output(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -31,11 +31,11 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -65,6 +65,13 @@ struct dss_reg {
|
|||
static int dss_runtime_get(void);
|
||||
static void dss_runtime_put(void);
|
||||
|
||||
struct dss_features {
|
||||
u8 fck_div_max;
|
||||
u8 dss_fck_multiplier;
|
||||
const char *clk_name;
|
||||
int (*dpi_select_source)(enum omap_channel channel);
|
||||
};
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
|
|
@ -83,6 +90,8 @@ static struct {
|
|||
|
||||
bool ctx_valid;
|
||||
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
|
||||
|
||||
const struct dss_features *feat;
|
||||
} dss;
|
||||
|
||||
static const char * const dss_generic_clk_source_names[] = {
|
||||
|
|
@ -144,7 +153,7 @@ static void dss_restore_context(void)
|
|||
#undef SR
|
||||
#undef RR
|
||||
|
||||
void dss_sdi_init(u8 datapairs)
|
||||
void dss_sdi_init(int datapairs)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
|
|
@ -236,7 +245,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
|
|||
return dss_generic_clk_source_names[clk_src];
|
||||
}
|
||||
|
||||
|
||||
void dss_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
unsigned long dpll4_ck_rate;
|
||||
|
|
@ -259,18 +267,10 @@ void dss_dump_clocks(struct seq_file *s)
|
|||
|
||||
seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
|
||||
|
||||
if (cpu_is_omap3630() || cpu_is_omap44xx())
|
||||
seq_printf(s, "%s (%s) = %lu / %lu = %lu\n",
|
||||
fclk_name, fclk_real_name,
|
||||
dpll4_ck_rate,
|
||||
dpll4_ck_rate / dpll4_m4_ck_rate,
|
||||
fclk_rate);
|
||||
else
|
||||
seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
|
||||
fclk_name, fclk_real_name,
|
||||
dpll4_ck_rate,
|
||||
dpll4_ck_rate / dpll4_m4_ck_rate,
|
||||
fclk_rate);
|
||||
seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n",
|
||||
fclk_name, fclk_real_name, dpll4_ck_rate,
|
||||
dpll4_ck_rate / dpll4_m4_ck_rate,
|
||||
dss.feat->dss_fck_multiplier, fclk_rate);
|
||||
} else {
|
||||
seq_printf(s, "%s (%s) = %lu\n",
|
||||
fclk_name, fclk_real_name,
|
||||
|
|
@ -431,31 +431,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
|
|||
}
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo)
|
||||
{
|
||||
if (dss.dpll4_m4_ck) {
|
||||
unsigned long prate;
|
||||
u16 fck_div_max = 16;
|
||||
|
||||
if (cpu_is_omap3630() || cpu_is_omap44xx())
|
||||
fck_div_max = 32;
|
||||
|
||||
if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
|
||||
return -EINVAL;
|
||||
|
||||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
|
||||
cinfo->fck = prate / cinfo->fck_div;
|
||||
} else {
|
||||
if (cinfo->fck_div != 0)
|
||||
return -EINVAL;
|
||||
cinfo->fck = clk_get_rate(dss.dss_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo)
|
||||
{
|
||||
if (dss.dpll4_m4_ck) {
|
||||
|
|
@ -478,26 +453,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dss_get_clock_div(struct dss_clock_info *cinfo)
|
||||
{
|
||||
cinfo->fck = clk_get_rate(dss.dss_clk);
|
||||
|
||||
if (dss.dpll4_m4_ck) {
|
||||
unsigned long prate;
|
||||
|
||||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
|
||||
if (cpu_is_omap3630() || cpu_is_omap44xx())
|
||||
cinfo->fck_div = prate / (cinfo->fck);
|
||||
else
|
||||
cinfo->fck_div = prate / (cinfo->fck / 2);
|
||||
} else {
|
||||
cinfo->fck_div = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long dss_get_dpll4_rate(void)
|
||||
{
|
||||
if (dss.dpll4_m4_ck)
|
||||
|
|
@ -515,7 +470,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
|||
|
||||
unsigned long fck, max_dss_fck;
|
||||
|
||||
u16 fck_div, fck_div_max = 16;
|
||||
u16 fck_div;
|
||||
|
||||
int match = 0;
|
||||
int min_fck_per_pck;
|
||||
|
|
@ -525,9 +480,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
|||
max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
|
||||
|
||||
fck = clk_get_rate(dss.dss_clk);
|
||||
if (req_pck == dss.cache_req_pck &&
|
||||
((cpu_is_omap34xx() && prate == dss.cache_prate) ||
|
||||
dss.cache_dss_cinfo.fck == fck)) {
|
||||
if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
|
||||
dss.cache_dss_cinfo.fck == fck) {
|
||||
DSSDBG("dispc clock info found from cache.\n");
|
||||
*dss_cinfo = dss.cache_dss_cinfo;
|
||||
*dispc_cinfo = dss.cache_dispc_cinfo;
|
||||
|
|
@ -564,16 +518,10 @@ retry:
|
|||
|
||||
goto found;
|
||||
} else {
|
||||
if (cpu_is_omap3630() || cpu_is_omap44xx())
|
||||
fck_div_max = 32;
|
||||
|
||||
for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
|
||||
for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
|
||||
struct dispc_clock_info cur_dispc;
|
||||
|
||||
if (fck_div_max == 32)
|
||||
fck = prate / fck_div;
|
||||
else
|
||||
fck = prate / fck_div * 2;
|
||||
fck = prate / fck_div * dss.feat->dss_fck_multiplier;
|
||||
|
||||
if (fck > max_dss_fck)
|
||||
continue;
|
||||
|
|
@ -648,9 +596,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)
|
|||
REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
|
||||
}
|
||||
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
|
||||
{
|
||||
REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
|
||||
enum omap_display_type dp;
|
||||
dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
|
||||
|
||||
/* Complain about invalid selections */
|
||||
WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
|
||||
WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
|
||||
|
||||
/* Select only if we have options */
|
||||
if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
|
||||
REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
|
||||
}
|
||||
|
||||
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
|
||||
|
|
@ -661,9 +618,71 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
|
|||
if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
|
||||
return DSS_VENC_TV_CLK;
|
||||
|
||||
if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
|
||||
return DSS_HDMI_M_PCLK;
|
||||
|
||||
return REG_GET(DSS_CONTROL, 15, 15);
|
||||
}
|
||||
|
||||
static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
|
||||
{
|
||||
if (channel != OMAP_DSS_CHANNEL_LCD)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_dpi_select_source_omap4(enum omap_channel channel)
|
||||
{
|
||||
int val;
|
||||
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
val = 0;
|
||||
break;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
val = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_dpi_select_source_omap5(enum omap_channel channel)
|
||||
{
|
||||
int val;
|
||||
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
val = 1;
|
||||
break;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
val = 2;
|
||||
break;
|
||||
case OMAP_DSS_CHANNEL_LCD3:
|
||||
val = 3;
|
||||
break;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_dpi_select_source(enum omap_channel channel)
|
||||
{
|
||||
return dss.feat->dpi_select_source(channel);
|
||||
}
|
||||
|
||||
static int dss_get_clocks(void)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
|
@ -678,22 +697,11 @@ static int dss_get_clocks(void)
|
|||
|
||||
dss.dss_clk = clk;
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
clk = clk_get(NULL, "dpll4_m4_ck");
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("Failed to get dpll4_m4_ck\n");
|
||||
r = PTR_ERR(clk);
|
||||
goto err;
|
||||
}
|
||||
} else if (cpu_is_omap44xx()) {
|
||||
clk = clk_get(NULL, "dpll_per_m5x2_ck");
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("Failed to get dpll_per_m5x2_ck\n");
|
||||
r = PTR_ERR(clk);
|
||||
goto err;
|
||||
}
|
||||
} else { /* omap24xx */
|
||||
clk = NULL;
|
||||
clk = clk_get(NULL, dss.feat->clk_name);
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("Failed to get %s\n", dss.feat->clk_name);
|
||||
r = PTR_ERR(clk);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dss.dpll4_m4_ck = clk;
|
||||
|
|
@ -749,6 +757,71 @@ void dss_debug_dump_clocks(struct seq_file *s)
|
|||
}
|
||||
#endif
|
||||
|
||||
static const struct dss_features omap24xx_dss_feats __initconst = {
|
||||
.fck_div_max = 16,
|
||||
.dss_fck_multiplier = 2,
|
||||
.clk_name = NULL,
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
};
|
||||
|
||||
static const struct dss_features omap34xx_dss_feats __initconst = {
|
||||
.fck_div_max = 16,
|
||||
.dss_fck_multiplier = 2,
|
||||
.clk_name = "dpll4_m4_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
};
|
||||
|
||||
static const struct dss_features omap3630_dss_feats __initconst = {
|
||||
.fck_div_max = 32,
|
||||
.dss_fck_multiplier = 1,
|
||||
.clk_name = "dpll4_m4_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap2_omap3,
|
||||
};
|
||||
|
||||
static const struct dss_features omap44xx_dss_feats __initconst = {
|
||||
.fck_div_max = 32,
|
||||
.dss_fck_multiplier = 1,
|
||||
.clk_name = "dpll_per_m5x2_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap4,
|
||||
};
|
||||
|
||||
static const struct dss_features omap54xx_dss_feats __initconst = {
|
||||
.fck_div_max = 64,
|
||||
.dss_fck_multiplier = 1,
|
||||
.clk_name = "dpll_per_h12x2_ck",
|
||||
.dpi_select_source = &dss_dpi_select_source_omap5,
|
||||
};
|
||||
|
||||
static int __init dss_init_features(struct device *dev)
|
||||
{
|
||||
const struct dss_features *src;
|
||||
struct dss_features *dst;
|
||||
|
||||
dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
|
||||
if (!dst) {
|
||||
dev_err(dev, "Failed to allocate local DSS Features\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (cpu_is_omap24xx())
|
||||
src = &omap24xx_dss_feats;
|
||||
else if (cpu_is_omap34xx())
|
||||
src = &omap34xx_dss_feats;
|
||||
else if (cpu_is_omap3630())
|
||||
src = &omap3630_dss_feats;
|
||||
else if (cpu_is_omap44xx())
|
||||
src = &omap44xx_dss_feats;
|
||||
else if (soc_is_omap54xx())
|
||||
src = &omap54xx_dss_feats;
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
dss.feat = dst;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DSS HW IP initialisation */
|
||||
static int __init omap_dsshw_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
@ -758,6 +831,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
|
|||
|
||||
dss.pdev = pdev;
|
||||
|
||||
r = dss_init_features(&dss.pdev->dev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
|
||||
if (!dss_mem) {
|
||||
DSSERR("can't get IORESOURCE_MEM DSS\n");
|
||||
|
|
|
|||
|
|
@ -113,6 +113,17 @@ enum dss_dsi_content_type {
|
|||
DSS_DSI_CONTENT_GENERIC,
|
||||
};
|
||||
|
||||
enum dss_writeback_channel {
|
||||
DSS_WB_LCD1_MGR = 0,
|
||||
DSS_WB_LCD2_MGR = 1,
|
||||
DSS_WB_TV_MGR = 2,
|
||||
DSS_WB_OVL0 = 3,
|
||||
DSS_WB_OVL1 = 4,
|
||||
DSS_WB_OVL2 = 5,
|
||||
DSS_WB_OVL3 = 6,
|
||||
DSS_WB_LCD3_MGR = 7,
|
||||
};
|
||||
|
||||
struct dss_clock_info {
|
||||
/* rates that we get with dividers below */
|
||||
unsigned long fck;
|
||||
|
|
@ -175,6 +186,7 @@ struct seq_file;
|
|||
struct platform_device;
|
||||
|
||||
/* core */
|
||||
const char *dss_get_default_display_name(void);
|
||||
struct bus_type *dss_get_bus(void);
|
||||
struct regulator *dss_get_vdds_dsi(void);
|
||||
struct regulator *dss_get_vdds_sdi(void);
|
||||
|
|
@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
|
|||
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
|
||||
|
||||
int omap_dss_register_device(struct omap_dss_device *dssdev,
|
||||
struct device *parent, int disp_num);
|
||||
void omap_dss_unregister_device(struct omap_dss_device *dssdev);
|
||||
void omap_dss_unregister_child_devices(struct device *parent);
|
||||
struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
|
||||
int dss_add_device(struct omap_dss_device *dssdev);
|
||||
void dss_unregister_device(struct omap_dss_device *dssdev);
|
||||
void dss_unregister_child_devices(struct device *parent);
|
||||
void dss_put_device(struct omap_dss_device *dssdev);
|
||||
void dss_copy_device_pdata(struct omap_dss_device *dst,
|
||||
const struct omap_dss_device *src);
|
||||
|
||||
/* apply */
|
||||
void dss_apply_init(void);
|
||||
|
|
@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|||
int dss_mgr_set_device(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev);
|
||||
int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_set_output(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_output *output);
|
||||
int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
struct omap_video_timings *timings);
|
||||
const struct omap_video_timings *timings);
|
||||
void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
|
||||
|
|
@ -222,12 +240,17 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
|
|||
struct omap_overlay_manager *mgr);
|
||||
int dss_ovl_unset_manager(struct omap_overlay *ovl);
|
||||
|
||||
/* output */
|
||||
void dss_register_output(struct omap_dss_output *out);
|
||||
void dss_unregister_output(struct omap_dss_output *out);
|
||||
struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
|
||||
|
||||
/* display */
|
||||
int dss_suspend_all_devices(void);
|
||||
int dss_resume_all_devices(void);
|
||||
void dss_disable_all_devices(void);
|
||||
|
||||
void dss_init_device(struct platform_device *pdev,
|
||||
int dss_init_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
void dss_uninit_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
|
|
@ -254,22 +277,29 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
|
|||
return false;
|
||||
}
|
||||
|
||||
int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
|
||||
struct platform_device *pdev);
|
||||
void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
|
||||
|
||||
/* overlay */
|
||||
void dss_init_overlays(struct platform_device *pdev);
|
||||
void dss_uninit_overlays(struct platform_device *pdev);
|
||||
void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
|
||||
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
|
||||
int dss_ovl_simple_check(struct omap_overlay *ovl,
|
||||
const struct omap_overlay_info *info);
|
||||
int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
|
||||
const struct omap_video_timings *mgr_timings);
|
||||
bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
|
||||
enum omap_color_mode mode);
|
||||
int dss_overlay_kobj_init(struct omap_overlay *ovl,
|
||||
struct platform_device *pdev);
|
||||
void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
|
||||
|
||||
/* DSS */
|
||||
int dss_init_platform_driver(void) __init;
|
||||
void dss_uninit_platform_driver(void);
|
||||
|
||||
int dss_dpi_select_source(enum omap_channel channel);
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
|
||||
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
|
||||
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
|
||||
|
|
@ -279,7 +309,7 @@ void dss_dump_clocks(struct seq_file *s);
|
|||
void dss_debug_dump_clocks(struct seq_file *s);
|
||||
#endif
|
||||
|
||||
void dss_sdi_init(u8 datapairs);
|
||||
void dss_sdi_init(int datapairs);
|
||||
int dss_sdi_enable(void);
|
||||
void dss_sdi_disable(void);
|
||||
|
||||
|
|
@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
|
|||
void dss_set_dac_pwrdn_bgz(bool enable);
|
||||
|
||||
unsigned long dss_get_dpll4_rate(void);
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo);
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo);
|
||||
int dss_get_clock_div(struct dss_clock_info *cinfo);
|
||||
int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
|
||||
|
|
@ -427,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
|
|||
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
||||
u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
|
||||
bool manual_update);
|
||||
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
||||
bool replication, const struct omap_video_timings *mgr_timings);
|
||||
int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
||||
bool replication, const struct omap_video_timings *mgr_timings,
|
||||
bool mem_to_mem);
|
||||
int dispc_ovl_enable(enum omap_plane plane, bool enable);
|
||||
void dispc_ovl_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel);
|
||||
|
|
@ -457,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
|
|||
void dispc_mgr_setup(enum omap_channel channel,
|
||||
struct omap_overlay_manager_info *info);
|
||||
|
||||
u32 dispc_wb_get_framedone_irq(void);
|
||||
bool dispc_wb_go_busy(void);
|
||||
void dispc_wb_go(void);
|
||||
void dispc_wb_enable(bool enable);
|
||||
bool dispc_wb_is_enabled(void);
|
||||
void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
|
||||
int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
|
||||
bool mem_to_mem, const struct omap_video_timings *timings);
|
||||
|
||||
/* VENC */
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
int venc_init_platform_driver(void) __init;
|
||||
|
|
@ -469,6 +507,20 @@ static inline unsigned long venc_get_pixel_clock(void)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
|
||||
void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
|
||||
int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
|
||||
void omapdss_venc_set_type(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_venc_type type);
|
||||
void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
|
||||
bool invert_polarity);
|
||||
int venc_panel_init(void);
|
||||
void venc_panel_exit(void);
|
||||
|
||||
/* HDMI */
|
||||
#ifdef CONFIG_OMAP4_DSS_HDMI
|
||||
|
|
@ -484,7 +536,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
|
|||
#endif
|
||||
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
|
||||
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
|
||||
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
int omapdss_hdmi_read_edid(u8 *buf, int len);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ struct omap_dss_features {
|
|||
|
||||
const int num_mgrs;
|
||||
const int num_ovls;
|
||||
const int num_wbs;
|
||||
const enum omap_display_type *supported_displays;
|
||||
const enum omap_dss_output_id *supported_outputs;
|
||||
const enum omap_color_mode *supported_color_modes;
|
||||
const enum omap_overlay_caps *overlay_caps;
|
||||
const char * const *clksrc_names;
|
||||
|
|
@ -106,6 +108,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
|
|||
[FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
|
||||
};
|
||||
|
||||
static const struct dss_reg_field omap5_dss_reg_fields[] = {
|
||||
[FEAT_REG_FIRHINC] = { 12, 0 },
|
||||
[FEAT_REG_FIRVINC] = { 28, 16 },
|
||||
[FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
|
||||
[FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
|
||||
[FEAT_REG_FIFOSIZE] = { 15, 0 },
|
||||
[FEAT_REG_HORIZONTALACCU] = { 10, 0 },
|
||||
[FEAT_REG_VERTICALACCU] = { 26, 16 },
|
||||
[FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
|
||||
[FEAT_REG_DSIPLL_REGN] = { 8, 1 },
|
||||
[FEAT_REG_DSIPLL_REGM] = { 20, 9 },
|
||||
[FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
|
||||
[FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap2_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
|
||||
|
|
@ -144,6 +161,76 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
|
|||
OMAP_DISPLAY_TYPE_DSI,
|
||||
};
|
||||
|
||||
static const enum omap_display_type omap5_dss_supported_displays[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_DSI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
|
||||
OMAP_DISPLAY_TYPE_DSI,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
|
||||
OMAP_DSS_OUTPUT_DPI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI2,
|
||||
};
|
||||
|
||||
static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
|
||||
/* OMAP_DSS_CHANNEL_LCD */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_DIGIT */
|
||||
OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD2 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI1,
|
||||
|
||||
/* OMAP_DSS_CHANNEL_LCD3 */
|
||||
OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
|
||||
OMAP_DSS_OUTPUT_DSI2,
|
||||
};
|
||||
|
||||
static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
|
||||
|
|
@ -224,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
|
|||
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
|
||||
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
|
||||
OMAP_DSS_COLOR_RGBX32,
|
||||
|
||||
/* OMAP_DSS_WB */
|
||||
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
|
||||
OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
|
||||
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
|
||||
OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
|
||||
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
|
||||
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
|
||||
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
|
||||
OMAP_DSS_COLOR_RGBX32,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
0,
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE,
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE,
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE,
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA,
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE,
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA,
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
|
||||
/* OMAP_DSS_GFX */
|
||||
OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_ZORDER,
|
||||
OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
|
||||
OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO1 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO2 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
|
||||
/* OMAP_DSS_VIDEO3 */
|
||||
OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER,
|
||||
OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
|
||||
OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
|
||||
};
|
||||
|
||||
static const char * const omap2_dss_clk_source_names[] = {
|
||||
|
|
@ -298,6 +407,14 @@ static const char * const omap4_dss_clk_source_names[] = {
|
|||
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
|
||||
};
|
||||
|
||||
static const char * const omap5_dss_clk_source_names[] = {
|
||||
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
|
||||
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
|
||||
[OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
|
||||
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
|
||||
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap2_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 2, 255 },
|
||||
|
|
@ -326,6 +443,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
|
|
@ -341,6 +459,23 @@ static const struct dss_param_range omap4_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap5_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
|
||||
[FEAT_PARAM_DSS_PCD] = { 1, 255 },
|
||||
[FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
|
||||
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
|
|
@ -373,6 +508,26 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
|
|||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
FEAT_DPI_USES_VDDS_DSI,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id am35xx_dss_feat_list[] = {
|
||||
FEAT_LCDENABLEPOL,
|
||||
FEAT_LCDENABLESIGNAL,
|
||||
FEAT_PCKFREEENABLE,
|
||||
FEAT_FUNCGATED,
|
||||
FEAT_LINEBUFFERSPLIT,
|
||||
FEAT_ROWREPEATENABLE,
|
||||
FEAT_RESIZECONF,
|
||||
FEAT_DSI_PLL_FREQSEL,
|
||||
FEAT_DSI_REVERSE_TXCLKESC,
|
||||
FEAT_VENC_REQUIRES_TV_DAC_CLK,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FIXED_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap3630_dss_feat_list[] = {
|
||||
|
|
@ -447,6 +602,28 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
|
|||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap5_dss_feat_list[] = {
|
||||
FEAT_MGR_LCD2,
|
||||
FEAT_CORE_CLK_DIV,
|
||||
FEAT_LCD_CLK_SRC,
|
||||
FEAT_DSI_DCS_CMD_CONFIG_VC,
|
||||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_HDMI_CTS_SWMODE,
|
||||
FEAT_HDMI_AUDIO_USE_MCLK,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
FEAT_ATTR2,
|
||||
FEAT_CPR,
|
||||
FEAT_PRELOAD,
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
FEAT_DSI_PLL_SELFREQDCO,
|
||||
FEAT_DSI_PLL_REFSEL,
|
||||
FEAT_DSI_PHY_DCC,
|
||||
};
|
||||
|
||||
/* OMAP2 DSS Features */
|
||||
static const struct omap_dss_features omap2_dss_features = {
|
||||
.reg_fields = omap2_dss_reg_fields,
|
||||
|
|
@ -458,6 +635,7 @@ static const struct omap_dss_features omap2_dss_features = {
|
|||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap2_dss_supported_displays,
|
||||
.supported_outputs = omap2_dss_supported_outputs,
|
||||
.supported_color_modes = omap2_dss_supported_color_modes,
|
||||
.overlay_caps = omap2_dss_overlay_caps,
|
||||
.clksrc_names = omap2_dss_clk_source_names,
|
||||
|
|
@ -478,6 +656,31 @@ static const struct omap_dss_features omap3430_dss_features = {
|
|||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap3430_dss_supported_displays,
|
||||
.supported_outputs = omap3430_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3430_dss_overlay_caps,
|
||||
.clksrc_names = omap3_dss_clk_source_names,
|
||||
.dss_params = omap3_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
|
||||
/*
|
||||
* AM35xx DSS Features. This is basically OMAP3 DSS Features without the
|
||||
* vdds_dsi regulator.
|
||||
*/
|
||||
static const struct omap_dss_features am35xx_dss_features = {
|
||||
.reg_fields = omap3_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
|
||||
|
||||
.features = am35xx_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(am35xx_dss_feat_list),
|
||||
|
||||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap3430_dss_supported_displays,
|
||||
.supported_outputs = omap3430_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3430_dss_overlay_caps,
|
||||
.clksrc_names = omap3_dss_clk_source_names,
|
||||
|
|
@ -497,6 +700,7 @@ static const struct omap_dss_features omap3630_dss_features = {
|
|||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
.supported_displays = omap3630_dss_supported_displays,
|
||||
.supported_outputs = omap3630_dss_supported_outputs,
|
||||
.supported_color_modes = omap3_dss_supported_color_modes,
|
||||
.overlay_caps = omap3630_dss_overlay_caps,
|
||||
.clksrc_names = omap3_dss_clk_source_names,
|
||||
|
|
@ -517,7 +721,9 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
|
|||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.num_wbs = 1,
|
||||
.supported_displays = omap4_dss_supported_displays,
|
||||
.supported_outputs = omap4_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap4_dss_clk_source_names,
|
||||
|
|
@ -537,7 +743,9 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
|
|||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.num_wbs = 1,
|
||||
.supported_displays = omap4_dss_supported_displays,
|
||||
.supported_outputs = omap4_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap4_dss_clk_source_names,
|
||||
|
|
@ -557,7 +765,9 @@ static const struct omap_dss_features omap4_dss_features = {
|
|||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.num_wbs = 1,
|
||||
.supported_displays = omap4_dss_supported_displays,
|
||||
.supported_outputs = omap4_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap4_dss_clk_source_names,
|
||||
|
|
@ -567,6 +777,27 @@ static const struct omap_dss_features omap4_dss_features = {
|
|||
.burst_size_unit = 16,
|
||||
};
|
||||
|
||||
/* OMAP5 DSS Features */
|
||||
static const struct omap_dss_features omap5_dss_features = {
|
||||
.reg_fields = omap5_dss_reg_fields,
|
||||
.num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
|
||||
|
||||
.features = omap5_dss_feat_list,
|
||||
.num_features = ARRAY_SIZE(omap5_dss_feat_list),
|
||||
|
||||
.num_mgrs = 3,
|
||||
.num_ovls = 4,
|
||||
.supported_displays = omap5_dss_supported_displays,
|
||||
.supported_outputs = omap5_dss_supported_outputs,
|
||||
.supported_color_modes = omap4_dss_supported_color_modes,
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap5_dss_clk_source_names,
|
||||
.dss_params = omap5_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI)
|
||||
/* HDMI OMAP4 Functions*/
|
||||
static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
|
||||
|
|
@ -612,6 +843,11 @@ int dss_feat_get_num_ovls(void)
|
|||
return omap_current_dss_features->num_ovls;
|
||||
}
|
||||
|
||||
int dss_feat_get_num_wbs(void)
|
||||
{
|
||||
return omap_current_dss_features->num_wbs;
|
||||
}
|
||||
|
||||
unsigned long dss_feat_get_param_min(enum dss_range_param param)
|
||||
{
|
||||
return omap_current_dss_features->dss_params[param].min;
|
||||
|
|
@ -627,6 +863,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
|
|||
return omap_current_dss_features->supported_displays[channel];
|
||||
}
|
||||
|
||||
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
|
||||
{
|
||||
return omap_current_dss_features->supported_outputs[channel];
|
||||
}
|
||||
|
||||
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
|
||||
{
|
||||
return omap_current_dss_features->supported_color_modes[plane];
|
||||
|
|
@ -694,8 +935,13 @@ void dss_features_init(void)
|
|||
omap_current_dss_features = &omap2_dss_features;
|
||||
else if (cpu_is_omap3630())
|
||||
omap_current_dss_features = &omap3630_dss_features;
|
||||
else if (cpu_is_omap34xx())
|
||||
omap_current_dss_features = &omap3430_dss_features;
|
||||
else if (cpu_is_omap34xx()) {
|
||||
if (soc_is_am35xx()) {
|
||||
omap_current_dss_features = &am35xx_dss_features;
|
||||
} else {
|
||||
omap_current_dss_features = &omap3430_dss_features;
|
||||
}
|
||||
}
|
||||
else if (omap_rev() == OMAP4430_REV_ES1_0)
|
||||
omap_current_dss_features = &omap4430_es1_0_dss_features;
|
||||
else if (omap_rev() == OMAP4430_REV_ES2_0 ||
|
||||
|
|
@ -704,6 +950,8 @@ void dss_features_init(void)
|
|||
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
|
||||
else if (cpu_is_omap44xx())
|
||||
omap_current_dss_features = &omap4_dss_features;
|
||||
else if (soc_is_omap54xx())
|
||||
omap_current_dss_features = &omap5_dss_features;
|
||||
else
|
||||
DSSWARN("Unsupported OMAP version");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ enum dss_feat_id {
|
|||
FEAT_DSI_VC_OCP_WIDTH,
|
||||
FEAT_DSI_REVERSE_TXCLKESC,
|
||||
FEAT_DSI_GNQ,
|
||||
FEAT_DPI_USES_VDDS_DSI,
|
||||
FEAT_HDMI_CTS_SWMODE,
|
||||
FEAT_HDMI_AUDIO_USE_MCLK,
|
||||
FEAT_HANDLE_UV_SEPARATE,
|
||||
|
|
@ -64,6 +65,9 @@ enum dss_feat_id {
|
|||
/* An unknown HW bug causing the normal FIFO thresholds not to work */
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
FEAT_BURST_2D,
|
||||
FEAT_DSI_PLL_SELFREQDCO,
|
||||
FEAT_DSI_PLL_REFSEL,
|
||||
FEAT_DSI_PHY_DCC,
|
||||
};
|
||||
|
||||
/* DSS register field id */
|
||||
|
|
@ -91,6 +95,7 @@ enum dss_range_param {
|
|||
FEAT_PARAM_DSIPLL_REGM_DSI,
|
||||
FEAT_PARAM_DSIPLL_FINT,
|
||||
FEAT_PARAM_DSIPLL_LPDIV,
|
||||
FEAT_PARAM_DSI_FCK,
|
||||
FEAT_PARAM_DOWNSCALE,
|
||||
FEAT_PARAM_LINEWIDTH,
|
||||
FEAT_PARAM_MGR_WIDTH,
|
||||
|
|
@ -100,9 +105,11 @@ enum dss_range_param {
|
|||
/* DSS Feature Functions */
|
||||
int dss_feat_get_num_mgrs(void);
|
||||
int dss_feat_get_num_ovls(void);
|
||||
int dss_feat_get_num_wbs(void);
|
||||
unsigned long dss_feat_get_param_min(enum dss_range_param param);
|
||||
unsigned long dss_feat_get_param_max(enum dss_range_param param);
|
||||
enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
|
||||
enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
|
||||
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
|
||||
enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
|
||||
bool dss_feat_color_mode_supported(enum omap_plane plane,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "ti_hdmi.h"
|
||||
|
|
@ -61,6 +63,13 @@ static struct {
|
|||
struct hdmi_ip_data ip_data;
|
||||
|
||||
struct clk *sys_clk;
|
||||
struct regulator *vdda_hdmi_dac_reg;
|
||||
|
||||
int ct_cp_hpd_gpio;
|
||||
int ls_oe_gpio;
|
||||
int hpd_gpio;
|
||||
|
||||
struct omap_dss_output output;
|
||||
} hdmi;
|
||||
|
||||
/*
|
||||
|
|
@ -314,12 +323,47 @@ static void hdmi_runtime_put(void)
|
|||
|
||||
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
struct gpio gpios[] = {
|
||||
{ hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
|
||||
{ hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
|
||||
{ hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
|
||||
};
|
||||
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
dss_init_hdmi_ip_ops(&hdmi.ip_data);
|
||||
|
||||
if (hdmi.vdda_hdmi_dac_reg == NULL) {
|
||||
struct regulator *reg;
|
||||
|
||||
reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
|
||||
|
||||
if (IS_ERR(reg)) {
|
||||
DSSERR("can't get VDDA_HDMI_DAC regulator\n");
|
||||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
hdmi.vdda_hdmi_dac_reg = reg;
|
||||
}
|
||||
|
||||
r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("uninit_display\n");
|
||||
|
||||
gpio_free(hdmi.ct_cp_hpd_gpio);
|
||||
gpio_free(hdmi.ls_oe_gpio);
|
||||
gpio_free(hdmi.hpd_gpio);
|
||||
}
|
||||
|
||||
static const struct hdmi_config *hdmi_find_timing(
|
||||
const struct hdmi_config *timings_arr,
|
||||
int len)
|
||||
|
|
@ -459,32 +503,30 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
|
|||
static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
const struct hdmi_config *timing;
|
||||
struct omap_video_timings *p;
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
unsigned long phy;
|
||||
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 1);
|
||||
|
||||
/* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
|
||||
udelay(300);
|
||||
|
||||
r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
|
||||
if (r)
|
||||
goto err_vdac_enable;
|
||||
|
||||
r = hdmi_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
goto err_runtime_get;
|
||||
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
p = &dssdev->panel.timings;
|
||||
p = &hdmi.ip_data.cfg.timings;
|
||||
|
||||
DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
|
||||
dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
|
||||
|
||||
timing = hdmi_get_timings();
|
||||
if (timing == NULL) {
|
||||
/* HDMI code 4 corresponds to 640 * 480 VGA */
|
||||
hdmi.ip_data.cfg.cm.code = 4;
|
||||
/* DVI mode 1 corresponds to HDMI 0 to DVI */
|
||||
hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
|
||||
hdmi.ip_data.cfg = vesa_timings[0];
|
||||
} else {
|
||||
hdmi.ip_data.cfg = *timing;
|
||||
}
|
||||
phy = p->pixel_clock;
|
||||
|
||||
hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
|
||||
|
|
@ -495,13 +537,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|||
r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
|
||||
if (r) {
|
||||
DSSDBG("Failed to lock PLL\n");
|
||||
goto err;
|
||||
goto err_pll_enable;
|
||||
}
|
||||
|
||||
r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
|
||||
if (r) {
|
||||
DSSDBG("Failed to start PHY\n");
|
||||
goto err;
|
||||
goto err_phy_enable;
|
||||
}
|
||||
|
||||
hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
|
||||
|
|
@ -521,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|||
dispc_enable_gamma_table(0);
|
||||
|
||||
/* tv size */
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
dss_mgr_set_timings(mgr, p);
|
||||
|
||||
r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
|
||||
if (r)
|
||||
goto err_vid_enable;
|
||||
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
r = dss_mgr_enable(mgr);
|
||||
if (r)
|
||||
goto err_mgr_enable;
|
||||
|
||||
|
|
@ -537,20 +579,33 @@ err_mgr_enable:
|
|||
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
|
||||
err_vid_enable:
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
err_phy_enable:
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
err:
|
||||
err_pll_enable:
|
||||
hdmi_runtime_put();
|
||||
err_runtime_get:
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
err_vdac_enable:
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void hdmi_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
hdmi_runtime_put();
|
||||
|
||||
regulator_disable(hdmi.vdda_hdmi_dac_reg);
|
||||
|
||||
gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
||||
gpio_set_value(hdmi.ls_oe_gpio, 0);
|
||||
}
|
||||
|
||||
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
||||
|
|
@ -567,25 +622,22 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
|||
|
||||
}
|
||||
|
||||
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
|
||||
void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
struct hdmi_cm cm;
|
||||
const struct hdmi_config *t;
|
||||
|
||||
cm = hdmi_get_code(&dssdev->panel.timings);
|
||||
hdmi.ip_data.cfg.cm.code = cm.code;
|
||||
hdmi.ip_data.cfg.cm.mode = cm.mode;
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
int r;
|
||||
cm = hdmi_get_code(timings);
|
||||
hdmi.ip_data.cfg.cm = cm;
|
||||
|
||||
hdmi_power_off(dssdev);
|
||||
t = hdmi_get_timings();
|
||||
if (t != NULL)
|
||||
hdmi.ip_data.cfg = *t;
|
||||
|
||||
r = hdmi_power_on(dssdev);
|
||||
if (r)
|
||||
DSSERR("failed to power on device\n");
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
}
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
static void hdmi_dump_regs(struct seq_file *s)
|
||||
|
|
@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void)
|
|||
|
||||
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_hdmi_data *priv = dssdev->data;
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
int r = 0;
|
||||
|
||||
DSSDBG("ENTER hdmi_display_enable\n");
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->manager == NULL) {
|
||||
DSSERR("failed to enable display: no manager\n");
|
||||
if (out == NULL || out->manager == NULL) {
|
||||
DSSERR("failed to enable display: no output/manager\n");
|
||||
r = -ENODEV;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
|
||||
hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
|
||||
|
||||
r = omap_dss_start_device(dssdev);
|
||||
if (r) {
|
||||
|
|
@ -661,26 +713,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to enable GPIO's\n");
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
||||
r = hdmi_power_on(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to power on device\n");
|
||||
goto err2;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
err1:
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
|
|
@ -696,9 +737,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
|
|||
|
||||
hdmi_power_off(dssdev);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
|
@ -869,10 +907,14 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
|
|||
|
||||
#endif
|
||||
|
||||
static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
||||
static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int r, i;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
def_dssdev = NULL;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
|
@ -880,17 +922,76 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
|||
if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
|
||||
continue;
|
||||
|
||||
r = hdmi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
if (def_dssdev == NULL)
|
||||
def_dssdev = dssdev;
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
if (def_disp_name != NULL &&
|
||||
strcmp(dssdev->name, def_disp_name) == 0) {
|
||||
def_dssdev = dssdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return def_dssdev;
|
||||
}
|
||||
|
||||
static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_device *plat_dssdev;
|
||||
struct omap_dss_device *dssdev;
|
||||
struct omap_dss_hdmi_data *priv;
|
||||
int r;
|
||||
|
||||
plat_dssdev = hdmi_find_dssdev(pdev);
|
||||
|
||||
if (!plat_dssdev)
|
||||
return;
|
||||
|
||||
dssdev = dss_alloc_and_init_device(&pdev->dev);
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
dss_copy_device_pdata(dssdev, plat_dssdev);
|
||||
|
||||
priv = dssdev->data;
|
||||
|
||||
hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
|
||||
hdmi.ls_oe_gpio = priv->ls_oe_gpio;
|
||||
hdmi.hpd_gpio = priv->hpd_gpio;
|
||||
|
||||
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
||||
r = hdmi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init hdmi_init_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &hdmi.output;
|
||||
|
||||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_HDMI;
|
||||
out->type = OMAP_DISPLAY_TYPE_HDMI;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
||||
static void __exit hdmi_uninit_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &hdmi.output;
|
||||
|
||||
dss_unregister_output(out);
|
||||
}
|
||||
|
||||
/* HDMI HW IP initialisation */
|
||||
|
|
@ -929,23 +1030,37 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
|||
hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
|
||||
hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
|
||||
hdmi.ip_data.phy_offset = HDMI_PHY;
|
||||
|
||||
mutex_init(&hdmi.ip_data.lock);
|
||||
|
||||
hdmi_panel_init();
|
||||
|
||||
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
|
||||
|
||||
hdmi_init_output(pdev);
|
||||
|
||||
hdmi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit hdmi_remove_child(struct device *dev, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
hdmi_uninit_display(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
|
||||
|
||||
dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
hdmi_panel_exit();
|
||||
|
||||
hdmi_uninit_output(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
hdmi_put_clocks();
|
||||
|
|
|
|||
|
|
@ -41,17 +41,34 @@ static struct {
|
|||
|
||||
static int hdmi_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
/* Initialize default timings to VGA in DVI mode */
|
||||
const struct omap_video_timings default_timings = {
|
||||
.x_res = 640,
|
||||
.y_res = 480,
|
||||
.pixel_clock = 25175,
|
||||
.hsw = 96,
|
||||
.hfp = 16,
|
||||
.hbp = 48,
|
||||
.vsw = 2,
|
||||
.vfp = 11,
|
||||
.vbp = 31,
|
||||
|
||||
.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
|
||||
.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
|
||||
|
||||
.interlace = false,
|
||||
};
|
||||
|
||||
DSSDBG("ENTER hdmi_panel_probe\n");
|
||||
|
||||
dssdev->panel.timings = (struct omap_video_timings)
|
||||
{ 640, 480, 25175, 96, 16, 48, 2, 11, 31,
|
||||
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
|
||||
false,
|
||||
};
|
||||
dssdev->panel.timings = default_timings;
|
||||
|
||||
DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
|
||||
dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
|
||||
omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
|
||||
|
||||
r = omapdss_hdmi_display_enable(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to power on\n");
|
||||
|
|
@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
|
|||
*/
|
||||
hdmi_panel_audio_disable(dssdev);
|
||||
|
||||
omapdss_hdmi_display_set_timing(dssdev, timings);
|
||||
dssdev->panel.timings = *timings;
|
||||
omapdss_hdmi_display_set_timing(dssdev);
|
||||
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
|
|
|||
512
drivers/video/omap2/dss/manager-sysfs.c
Normal file
512
drivers/video/omap2/dss/manager-sysfs.c
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "MANAGER"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
|
||||
}
|
||||
|
||||
static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = mgr->get_device(mgr);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
|
||||
dssdev->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r = 0;
|
||||
size_t len = size;
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
int match(struct omap_dss_device *dssdev, void *data)
|
||||
{
|
||||
const char *str = data;
|
||||
return sysfs_streq(dssdev->name, str);
|
||||
}
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0)
|
||||
dssdev = omap_dss_find_device((void *)buf, match);
|
||||
|
||||
if (len > 0 && dssdev == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (dssdev)
|
||||
DSSDBG("display %s found\n", dssdev->name);
|
||||
|
||||
if (mgr->output) {
|
||||
r = mgr->unset_output(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to unset current output\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
if (dssdev) {
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
|
||||
/*
|
||||
* a registered device should have an output connected to it
|
||||
* already
|
||||
*/
|
||||
if (!out) {
|
||||
DSSERR("device has no output connected to it\n");
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
r = mgr->set_output(mgr, out);
|
||||
if (r) {
|
||||
DSSERR("failed to set manager output\n");
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to apply dispc config\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
put_device:
|
||||
if (dssdev)
|
||||
omap_dss_put_device(dssdev);
|
||||
|
||||
return r ? r : size;
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 color;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &color);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.default_color = color;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static const char *trans_key_type_str[] = {
|
||||
"gfx-destination",
|
||||
"video-source",
|
||||
};
|
||||
|
||||
static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
key_type = info.trans_key_type;
|
||||
BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
|
||||
for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
|
||||
key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
|
||||
if (sysfs_streq(buf, trans_key_type_str[key_type]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (key_type == ARRAY_SIZE(trans_key_type_str))
|
||||
return -EINVAL;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key_type = key_type;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 key_value;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &key_value);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key = key_value;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_show(
|
||||
struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.partial_alpha_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_store(
|
||||
struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.partial_alpha_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
if (info.cpr_enable == enable)
|
||||
return size;
|
||||
|
||||
info.cpr_enable = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d %d %d %d %d %d %d %d %d\n",
|
||||
info.cpr_coefs.rr,
|
||||
info.cpr_coefs.rg,
|
||||
info.cpr_coefs.rb,
|
||||
info.cpr_coefs.gr,
|
||||
info.cpr_coefs.gg,
|
||||
info.cpr_coefs.gb,
|
||||
info.cpr_coefs.br,
|
||||
info.cpr_coefs.bg,
|
||||
info.cpr_coefs.bb);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
struct omap_dss_cpr_coefs coefs;
|
||||
int r, i;
|
||||
s16 *arr;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
|
||||
&coefs.rr, &coefs.rg, &coefs.rb,
|
||||
&coefs.gr, &coefs.gg, &coefs.gb,
|
||||
&coefs.br, &coefs.bg, &coefs.bb) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
|
||||
coefs.gr, coefs.gg, coefs.gb,
|
||||
coefs.br, coefs.bg, coefs.bb };
|
||||
|
||||
for (i = 0; i < 9; ++i) {
|
||||
if (arr[i] < -512 || arr[i] > 511)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.cpr_coefs = coefs;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct manager_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay_manager *, char *);
|
||||
ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define MANAGER_ATTR(_name, _mode, _show, _store) \
|
||||
struct manager_attribute manager_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
|
||||
static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
|
||||
manager_display_show, manager_display_store);
|
||||
static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
|
||||
manager_default_color_show, manager_default_color_store);
|
||||
static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_type_show, manager_trans_key_type_store);
|
||||
static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_value_show, manager_trans_key_value_store);
|
||||
static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_enabled_show,
|
||||
manager_trans_key_enabled_store);
|
||||
static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_alpha_blending_enabled_show,
|
||||
manager_alpha_blending_enabled_store);
|
||||
static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_enable_show,
|
||||
manager_cpr_enable_store);
|
||||
static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_coef_show,
|
||||
manager_cpr_coef_store);
|
||||
|
||||
|
||||
static struct attribute *manager_sysfs_attrs[] = {
|
||||
&manager_attr_name.attr,
|
||||
&manager_attr_display.attr,
|
||||
&manager_attr_default_color.attr,
|
||||
&manager_attr_trans_key_type.attr,
|
||||
&manager_attr_trans_key_value.attr,
|
||||
&manager_attr_trans_key_enabled.attr,
|
||||
&manager_attr_alpha_blending_enabled.attr,
|
||||
&manager_attr_cpr_enable.attr,
|
||||
&manager_attr_cpr_coef.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->show(manager, buf);
|
||||
}
|
||||
|
||||
static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->store(manager, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops manager_sysfs_ops = {
|
||||
.show = manager_attr_show,
|
||||
.store = manager_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type manager_ktype = {
|
||||
.sysfs_ops = &manager_sysfs_ops,
|
||||
.default_attrs = manager_sysfs_attrs,
|
||||
};
|
||||
|
||||
int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
return kobject_init_and_add(&mgr->kobj, &manager_ktype,
|
||||
&pdev->dev.kobj, "manager%d", mgr->id);
|
||||
}
|
||||
|
||||
void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
kobject_del(&mgr->kobj);
|
||||
kobject_put(&mgr->kobj);
|
||||
}
|
||||
|
|
@ -36,463 +36,15 @@
|
|||
static int num_managers;
|
||||
static struct omap_overlay_manager *managers;
|
||||
|
||||
static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
|
||||
return mgr->output ? mgr->output->device : NULL;
|
||||
}
|
||||
|
||||
static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
mgr->device ? mgr->device->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r = 0;
|
||||
size_t len = size;
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
int match(struct omap_dss_device *dssdev, void *data)
|
||||
{
|
||||
const char *str = data;
|
||||
return sysfs_streq(dssdev->name, str);
|
||||
}
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0)
|
||||
dssdev = omap_dss_find_device((void *)buf, match);
|
||||
|
||||
if (len > 0 && dssdev == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (dssdev)
|
||||
DSSDBG("display %s found\n", dssdev->name);
|
||||
|
||||
if (mgr->device) {
|
||||
r = mgr->unset_device(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to unset display\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
if (dssdev) {
|
||||
r = mgr->set_device(mgr, dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to set manager\n");
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to apply dispc config\n");
|
||||
goto put_device;
|
||||
}
|
||||
}
|
||||
|
||||
put_device:
|
||||
if (dssdev)
|
||||
omap_dss_put_device(dssdev);
|
||||
|
||||
return r ? r : size;
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
|
||||
}
|
||||
|
||||
static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 color;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &color);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.default_color = color;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static const char *trans_key_type_str[] = {
|
||||
"gfx-destination",
|
||||
"video-source",
|
||||
};
|
||||
|
||||
static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
key_type = info.trans_key_type;
|
||||
BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
enum omap_dss_trans_key_type key_type;
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
|
||||
for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
|
||||
key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
|
||||
if (sysfs_streq(buf, trans_key_type_str[key_type]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (key_type == ARRAY_SIZE(trans_key_type_str))
|
||||
return -EINVAL;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key_type = key_type;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
u32 key_value;
|
||||
int r;
|
||||
|
||||
r = kstrtouint(buf, 0, &key_value);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_key = key_value;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.trans_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_show(
|
||||
struct omap_overlay_manager *mgr, char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.partial_alpha_enabled);
|
||||
}
|
||||
|
||||
static ssize_t manager_alpha_blending_enabled_store(
|
||||
struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
bool enable;
|
||||
int r;
|
||||
|
||||
WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.partial_alpha_enabled = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
if (info.cpr_enable == enable)
|
||||
return size;
|
||||
|
||||
info.cpr_enable = enable;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"%d %d %d %d %d %d %d %d %d\n",
|
||||
info.cpr_coefs.rr,
|
||||
info.cpr_coefs.rg,
|
||||
info.cpr_coefs.rb,
|
||||
info.cpr_coefs.gr,
|
||||
info.cpr_coefs.gg,
|
||||
info.cpr_coefs.gb,
|
||||
info.cpr_coefs.br,
|
||||
info.cpr_coefs.bg,
|
||||
info.cpr_coefs.bb);
|
||||
}
|
||||
|
||||
static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager_info info;
|
||||
struct omap_dss_cpr_coefs coefs;
|
||||
int r, i;
|
||||
s16 *arr;
|
||||
|
||||
if (!dss_has_feature(FEAT_CPR))
|
||||
return -ENODEV;
|
||||
|
||||
if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
|
||||
&coefs.rr, &coefs.rg, &coefs.rb,
|
||||
&coefs.gr, &coefs.gg, &coefs.gb,
|
||||
&coefs.br, &coefs.bg, &coefs.bb) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
|
||||
coefs.gr, coefs.gg, coefs.gb,
|
||||
coefs.br, coefs.bg, coefs.bb };
|
||||
|
||||
for (i = 0; i < 9; ++i) {
|
||||
if (arr[i] < -512 || arr[i] > 511)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mgr->get_manager_info(mgr, &info);
|
||||
|
||||
info.cpr_coefs = coefs;
|
||||
|
||||
r = mgr->set_manager_info(mgr, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct manager_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay_manager *, char *);
|
||||
ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define MANAGER_ATTR(_name, _mode, _show, _store) \
|
||||
struct manager_attribute manager_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
|
||||
static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
|
||||
manager_display_show, manager_display_store);
|
||||
static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
|
||||
manager_default_color_show, manager_default_color_store);
|
||||
static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_type_show, manager_trans_key_type_store);
|
||||
static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_value_show, manager_trans_key_value_store);
|
||||
static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_trans_key_enabled_show,
|
||||
manager_trans_key_enabled_store);
|
||||
static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
|
||||
manager_alpha_blending_enabled_show,
|
||||
manager_alpha_blending_enabled_store);
|
||||
static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_enable_show,
|
||||
manager_cpr_enable_store);
|
||||
static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
|
||||
manager_cpr_coef_show,
|
||||
manager_cpr_coef_store);
|
||||
|
||||
|
||||
static struct attribute *manager_sysfs_attrs[] = {
|
||||
&manager_attr_name.attr,
|
||||
&manager_attr_display.attr,
|
||||
&manager_attr_default_color.attr,
|
||||
&manager_attr_trans_key_type.attr,
|
||||
&manager_attr_trans_key_value.attr,
|
||||
&manager_attr_trans_key_enabled.attr,
|
||||
&manager_attr_alpha_blending_enabled.attr,
|
||||
&manager_attr_cpr_enable.attr,
|
||||
&manager_attr_cpr_coef.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->show(manager, buf);
|
||||
}
|
||||
|
||||
static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay_manager *manager;
|
||||
struct manager_attribute *manager_attr;
|
||||
|
||||
manager = container_of(kobj, struct omap_overlay_manager, kobj);
|
||||
manager_attr = container_of(attr, struct manager_attribute, attr);
|
||||
|
||||
if (!manager_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return manager_attr->store(manager, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops manager_sysfs_ops = {
|
||||
.show = manager_attr_show,
|
||||
.store = manager_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type manager_ktype = {
|
||||
.sysfs_ops = &manager_sysfs_ops,
|
||||
.default_attrs = manager_sysfs_attrs,
|
||||
};
|
||||
|
||||
static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
struct omap_dss_device *dssdev = mgr->get_device(mgr);
|
||||
u32 irq;
|
||||
int r;
|
||||
|
||||
|
|
@ -500,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC)
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
|
||||
irq = DISPC_IRQ_EVSYNC_ODD;
|
||||
else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI)
|
||||
else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
|
||||
irq = DISPC_IRQ_EVSYNC_EVEN;
|
||||
else
|
||||
irq = dispc_mgr_get_vsync_irq(mgr->id);
|
||||
|
|
@ -547,23 +99,24 @@ int dss_init_overlay_managers(struct platform_device *pdev)
|
|||
break;
|
||||
}
|
||||
|
||||
mgr->set_device = &dss_mgr_set_device;
|
||||
mgr->unset_device = &dss_mgr_unset_device;
|
||||
mgr->set_output = &dss_mgr_set_output;
|
||||
mgr->unset_output = &dss_mgr_unset_output;
|
||||
mgr->apply = &omap_dss_mgr_apply;
|
||||
mgr->set_manager_info = &dss_mgr_set_info;
|
||||
mgr->get_manager_info = &dss_mgr_get_info;
|
||||
mgr->wait_for_go = &dss_mgr_wait_for_go;
|
||||
mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
|
||||
mgr->get_device = &dss_mgr_get_device;
|
||||
|
||||
mgr->caps = 0;
|
||||
mgr->supported_displays =
|
||||
dss_feat_get_supported_displays(mgr->id);
|
||||
mgr->supported_outputs =
|
||||
dss_feat_get_supported_outputs(mgr->id);
|
||||
|
||||
INIT_LIST_HEAD(&mgr->overlays);
|
||||
|
||||
r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
|
||||
&pdev->dev.kobj, "manager%d", i);
|
||||
|
||||
r = dss_manager_kobj_init(mgr, pdev);
|
||||
if (r)
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
}
|
||||
|
|
@ -577,9 +130,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < num_managers; ++i) {
|
||||
struct omap_overlay_manager *mgr = &managers[i];
|
||||
|
||||
kobject_del(&mgr->kobj);
|
||||
kobject_put(&mgr->kobj);
|
||||
dss_manager_kobj_uninit(mgr);
|
||||
}
|
||||
|
||||
kfree(managers);
|
||||
|
|
|
|||
148
drivers/video/omap2/dss/output.c
Normal file
148
drivers/video/omap2/dss/output.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Texas Instruments Ltd
|
||||
* Author: Archit Taneja <archit@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
||||
static LIST_HEAD(output_list);
|
||||
static DEFINE_MUTEX(output_lock);
|
||||
|
||||
int omapdss_output_set_device(struct omap_dss_output *out,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
mutex_lock(&output_lock);
|
||||
|
||||
if (out->device) {
|
||||
DSSERR("output already has device %s connected to it\n",
|
||||
out->device->name);
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (out->type != dssdev->type) {
|
||||
DSSERR("output type and display type don't match\n");
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
out->device = dssdev;
|
||||
dssdev->output = out;
|
||||
|
||||
mutex_unlock(&output_lock);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&output_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_output_set_device);
|
||||
|
||||
int omapdss_output_unset_device(struct omap_dss_output *out)
|
||||
{
|
||||
int r;
|
||||
|
||||
mutex_lock(&output_lock);
|
||||
|
||||
if (!out->device) {
|
||||
DSSERR("output doesn't have a device connected to it\n");
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
DSSERR("device %s is not disabled, cannot unset device\n",
|
||||
out->device->name);
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
out->device->output = NULL;
|
||||
out->device = NULL;
|
||||
|
||||
mutex_unlock(&output_lock);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&output_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_output_unset_device);
|
||||
|
||||
void dss_register_output(struct omap_dss_output *out)
|
||||
{
|
||||
list_add_tail(&out->list, &output_list);
|
||||
}
|
||||
|
||||
void dss_unregister_output(struct omap_dss_output *out)
|
||||
{
|
||||
list_del(&out->list);
|
||||
}
|
||||
|
||||
struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
|
||||
{
|
||||
struct omap_dss_output *out;
|
||||
|
||||
list_for_each_entry(out, &output_list, list) {
|
||||
if (out->id == id)
|
||||
return out;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_output *out = NULL;
|
||||
enum omap_dss_output_id id;
|
||||
|
||||
switch (dssdev->type) {
|
||||
case OMAP_DISPLAY_TYPE_DPI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_DBI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_SDI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_VENC:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_HDMI:
|
||||
out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
|
||||
break;
|
||||
case OMAP_DISPLAY_TYPE_DSI:
|
||||
id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
|
||||
OMAP_DSS_OUTPUT_DSI2;
|
||||
out = omap_dss_get_output(id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
456
drivers/video/omap2/dss/overlay-sysfs.c
Normal file
456
drivers/video/omap2/dss/overlay-sysfs.c
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "OVERLAY"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ovl->manager ? ovl->manager->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int i, r;
|
||||
struct omap_overlay_manager *mgr = NULL;
|
||||
struct omap_overlay_manager *old_mgr;
|
||||
int len = size;
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0) {
|
||||
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
|
||||
if (sysfs_streq(buf, mgr->name))
|
||||
break;
|
||||
|
||||
mgr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0 && mgr == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mgr)
|
||||
DSSDBG("manager %s found\n", mgr->name);
|
||||
|
||||
if (mgr == ovl->manager)
|
||||
return size;
|
||||
|
||||
old_mgr = ovl->manager;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* detach old manager */
|
||||
if (old_mgr) {
|
||||
r = ovl->unset_manager(ovl);
|
||||
if (r) {
|
||||
DSSERR("detach failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = old_mgr->apply(old_mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mgr) {
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r) {
|
||||
DSSERR("Failed to attach overlay\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dispc_runtime_put();
|
||||
|
||||
return size;
|
||||
|
||||
err:
|
||||
dispc_runtime_put();
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.width, info.height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.pos_x, info.pos_y);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pos_x = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.pos_y = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.out_width, info.out_height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.out_width = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.out_height = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (enable)
|
||||
r = ovl->enable(ovl);
|
||||
else
|
||||
r = ovl->disable(ovl);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.global_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.global_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.pre_mult_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pre_mult_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 zorder;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &zorder);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.zorder = zorder;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct overlay_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay *, char *);
|
||||
ssize_t (*store)(struct omap_overlay *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define OVERLAY_ATTR(_name, _mode, _show, _store) \
|
||||
struct overlay_attribute overlay_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
|
||||
static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
|
||||
overlay_manager_show, overlay_manager_store);
|
||||
static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
|
||||
static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
|
||||
static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
|
||||
overlay_position_show, overlay_position_store);
|
||||
static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
|
||||
overlay_output_size_show, overlay_output_size_store);
|
||||
static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
|
||||
overlay_enabled_show, overlay_enabled_store);
|
||||
static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_global_alpha_show, overlay_global_alpha_store);
|
||||
static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_pre_mult_alpha_show,
|
||||
overlay_pre_mult_alpha_store);
|
||||
static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
|
||||
overlay_zorder_show, overlay_zorder_store);
|
||||
|
||||
static struct attribute *overlay_sysfs_attrs[] = {
|
||||
&overlay_attr_name.attr,
|
||||
&overlay_attr_manager.attr,
|
||||
&overlay_attr_input_size.attr,
|
||||
&overlay_attr_screen_width.attr,
|
||||
&overlay_attr_position.attr,
|
||||
&overlay_attr_output_size.attr,
|
||||
&overlay_attr_enabled.attr,
|
||||
&overlay_attr_global_alpha.attr,
|
||||
&overlay_attr_pre_mult_alpha.attr,
|
||||
&overlay_attr_zorder.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->show(overlay, buf);
|
||||
}
|
||||
|
||||
static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->store(overlay, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops overlay_sysfs_ops = {
|
||||
.show = overlay_attr_show,
|
||||
.store = overlay_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type overlay_ktype = {
|
||||
.sysfs_ops = &overlay_sysfs_ops,
|
||||
.default_attrs = overlay_sysfs_attrs,
|
||||
};
|
||||
|
||||
int dss_overlay_kobj_init(struct omap_overlay *ovl,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
|
||||
&pdev->dev.kobj, "overlay%d", ovl->id);
|
||||
}
|
||||
|
||||
void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
|
||||
{
|
||||
kobject_del(&ovl->kobj);
|
||||
kobject_put(&ovl->kobj);
|
||||
}
|
||||
|
|
@ -26,13 +26,11 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -40,417 +38,13 @@
|
|||
static int num_overlays;
|
||||
static struct omap_overlay *overlays;
|
||||
|
||||
static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
|
||||
static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
|
||||
return ovl->manager ?
|
||||
(ovl->manager->output ? ovl->manager->output->device : NULL) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
ovl->manager ? ovl->manager->name : "<none>");
|
||||
}
|
||||
|
||||
static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int i, r;
|
||||
struct omap_overlay_manager *mgr = NULL;
|
||||
struct omap_overlay_manager *old_mgr;
|
||||
int len = size;
|
||||
|
||||
if (buf[size-1] == '\n')
|
||||
--len;
|
||||
|
||||
if (len > 0) {
|
||||
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
|
||||
if (sysfs_streq(buf, mgr->name))
|
||||
break;
|
||||
|
||||
mgr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0 && mgr == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mgr)
|
||||
DSSDBG("manager %s found\n", mgr->name);
|
||||
|
||||
if (mgr == ovl->manager)
|
||||
return size;
|
||||
|
||||
old_mgr = ovl->manager;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* detach old manager */
|
||||
if (old_mgr) {
|
||||
r = ovl->unset_manager(ovl);
|
||||
if (r) {
|
||||
DSSERR("detach failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = old_mgr->apply(old_mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mgr) {
|
||||
r = ovl->set_manager(ovl, mgr);
|
||||
if (r) {
|
||||
DSSERR("Failed to attach overlay\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = mgr->apply(mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dispc_runtime_put();
|
||||
|
||||
return size;
|
||||
|
||||
err:
|
||||
dispc_runtime_put();
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.width, info.height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.pos_x, info.pos_y);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pos_x = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.pos_y = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
info.out_width, info.out_height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
char *last;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.out_width = simple_strtoul(buf, &last, 10);
|
||||
++last;
|
||||
if (last - buf >= size)
|
||||
return -EINVAL;
|
||||
|
||||
info.out_height = simple_strtoul(last, &last, 10);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
int r;
|
||||
bool enable;
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (enable)
|
||||
r = ovl->enable(ovl);
|
||||
else
|
||||
r = ovl->disable(ovl);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.global_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.global_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
info.pre_mult_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 alpha;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &alpha);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.pre_mult_alpha = alpha;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int r;
|
||||
u8 zorder;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
|
||||
return -ENODEV;
|
||||
|
||||
r = kstrtou8(buf, 0, &zorder);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.zorder = zorder;
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
struct overlay_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct omap_overlay *, char *);
|
||||
ssize_t (*store)(struct omap_overlay *, const char *, size_t);
|
||||
};
|
||||
|
||||
#define OVERLAY_ATTR(_name, _mode, _show, _store) \
|
||||
struct overlay_attribute overlay_attr_##_name = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
|
||||
static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
|
||||
overlay_manager_show, overlay_manager_store);
|
||||
static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
|
||||
static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
|
||||
static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
|
||||
overlay_position_show, overlay_position_store);
|
||||
static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
|
||||
overlay_output_size_show, overlay_output_size_store);
|
||||
static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
|
||||
overlay_enabled_show, overlay_enabled_store);
|
||||
static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_global_alpha_show, overlay_global_alpha_store);
|
||||
static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
|
||||
overlay_pre_mult_alpha_show,
|
||||
overlay_pre_mult_alpha_store);
|
||||
static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
|
||||
overlay_zorder_show, overlay_zorder_store);
|
||||
|
||||
static struct attribute *overlay_sysfs_attrs[] = {
|
||||
&overlay_attr_name.attr,
|
||||
&overlay_attr_manager.attr,
|
||||
&overlay_attr_input_size.attr,
|
||||
&overlay_attr_screen_width.attr,
|
||||
&overlay_attr_position.attr,
|
||||
&overlay_attr_output_size.attr,
|
||||
&overlay_attr_enabled.attr,
|
||||
&overlay_attr_global_alpha.attr,
|
||||
&overlay_attr_pre_mult_alpha.attr,
|
||||
&overlay_attr_zorder.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->show)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->show(overlay, buf);
|
||||
}
|
||||
|
||||
static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct omap_overlay *overlay;
|
||||
struct overlay_attribute *overlay_attr;
|
||||
|
||||
overlay = container_of(kobj, struct omap_overlay, kobj);
|
||||
overlay_attr = container_of(attr, struct overlay_attribute, attr);
|
||||
|
||||
if (!overlay_attr->store)
|
||||
return -ENOENT;
|
||||
|
||||
return overlay_attr->store(overlay, buf, size);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops overlay_sysfs_ops = {
|
||||
.show = overlay_attr_show,
|
||||
.store = overlay_attr_store,
|
||||
};
|
||||
|
||||
static struct kobj_type overlay_ktype = {
|
||||
.sysfs_ops = &overlay_sysfs_ops,
|
||||
.default_attrs = overlay_sysfs_attrs,
|
||||
};
|
||||
|
||||
int omap_dss_get_num_overlays(void)
|
||||
{
|
||||
return num_overlays;
|
||||
|
|
@ -507,97 +101,25 @@ void dss_init_overlays(struct platform_device *pdev)
|
|||
ovl->set_overlay_info = &dss_ovl_set_info;
|
||||
ovl->get_overlay_info = &dss_ovl_get_info;
|
||||
ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
|
||||
ovl->get_device = &dss_ovl_get_device;
|
||||
|
||||
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
|
||||
ovl->supported_modes =
|
||||
dss_feat_get_supported_color_modes(ovl->id);
|
||||
|
||||
r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
|
||||
&pdev->dev.kobj, "overlay%d", i);
|
||||
|
||||
r = dss_overlay_kobj_init(ovl, pdev);
|
||||
if (r)
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* connect overlays to the new device, if not already connected. if force
|
||||
* selected, connect always. */
|
||||
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
|
||||
{
|
||||
int i;
|
||||
struct omap_overlay_manager *lcd_mgr;
|
||||
struct omap_overlay_manager *tv_mgr;
|
||||
struct omap_overlay_manager *lcd2_mgr = NULL;
|
||||
struct omap_overlay_manager *lcd3_mgr = NULL;
|
||||
struct omap_overlay_manager *mgr = NULL;
|
||||
|
||||
lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
|
||||
tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
|
||||
if (dss_has_feature(FEAT_MGR_LCD3))
|
||||
lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
|
||||
if (dss_has_feature(FEAT_MGR_LCD2))
|
||||
lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
|
||||
|
||||
if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
|
||||
if (!lcd3_mgr->device || force) {
|
||||
if (lcd3_mgr->device)
|
||||
lcd3_mgr->unset_device(lcd3_mgr);
|
||||
lcd3_mgr->set_device(lcd3_mgr, dssdev);
|
||||
mgr = lcd3_mgr;
|
||||
}
|
||||
} else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
|
||||
if (!lcd2_mgr->device || force) {
|
||||
if (lcd2_mgr->device)
|
||||
lcd2_mgr->unset_device(lcd2_mgr);
|
||||
lcd2_mgr->set_device(lcd2_mgr, dssdev);
|
||||
mgr = lcd2_mgr;
|
||||
}
|
||||
} else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
|
||||
&& dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
|
||||
if (!lcd_mgr->device || force) {
|
||||
if (lcd_mgr->device)
|
||||
lcd_mgr->unset_device(lcd_mgr);
|
||||
lcd_mgr->set_device(lcd_mgr, dssdev);
|
||||
mgr = lcd_mgr;
|
||||
}
|
||||
}
|
||||
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
|
||||
|| dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
|
||||
if (!tv_mgr->device || force) {
|
||||
if (tv_mgr->device)
|
||||
tv_mgr->unset_device(tv_mgr);
|
||||
tv_mgr->set_device(tv_mgr, dssdev);
|
||||
mgr = tv_mgr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mgr) {
|
||||
dispc_runtime_get();
|
||||
|
||||
for (i = 0; i < dss_feat_get_num_ovls(); i++) {
|
||||
struct omap_overlay *ovl;
|
||||
ovl = omap_dss_get_overlay(i);
|
||||
if (!ovl->manager || force) {
|
||||
if (ovl->manager)
|
||||
ovl->unset_manager(ovl);
|
||||
ovl->set_manager(ovl, mgr);
|
||||
}
|
||||
}
|
||||
|
||||
dispc_runtime_put();
|
||||
}
|
||||
}
|
||||
|
||||
void dss_uninit_overlays(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_overlays; ++i) {
|
||||
struct omap_overlay *ovl = &overlays[i];
|
||||
|
||||
kobject_del(&ovl->kobj);
|
||||
kobject_put(&ovl->kobj);
|
||||
dss_overlay_kobj_uninit(ovl);
|
||||
}
|
||||
|
||||
kfree(overlays);
|
||||
|
|
|
|||
|
|
@ -111,6 +111,13 @@ static struct {
|
|||
struct omap_dss_device *dssdev[2];
|
||||
|
||||
struct semaphore bus_lock;
|
||||
|
||||
struct omap_video_timings timings;
|
||||
int pixel_size;
|
||||
int data_lines;
|
||||
struct rfbi_timings intf_timings;
|
||||
|
||||
struct omap_dss_output output;
|
||||
} rfbi;
|
||||
|
||||
static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
|
||||
|
|
@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
|
|||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_write_pixels);
|
||||
|
||||
static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
|
||||
u16 height, void (*callback)(void *data), void *data)
|
||||
static int rfbi_transfer_area(struct omap_dss_device *dssdev,
|
||||
void (*callback)(void *data), void *data)
|
||||
{
|
||||
u32 l;
|
||||
int r;
|
||||
struct omap_video_timings timings = {
|
||||
.hsw = 1,
|
||||
.hfp = 1,
|
||||
.hbp = 1,
|
||||
.vsw = 1,
|
||||
.vfp = 0,
|
||||
.vbp = 0,
|
||||
.x_res = width,
|
||||
.y_res = height,
|
||||
};
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
u16 width = rfbi.timings.x_res;
|
||||
u16 height = rfbi.timings.y_res;
|
||||
|
||||
/*BUG_ON(callback == 0);*/
|
||||
BUG_ON(rfbi.framedone_callback != NULL);
|
||||
|
||||
DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
|
||||
|
||||
dss_mgr_set_timings(dssdev->manager, &timings);
|
||||
dss_mgr_set_timings(mgr, &rfbi.timings);
|
||||
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
r = dss_mgr_enable(mgr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
|
@ -770,63 +770,46 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
|
||||
int data_lines)
|
||||
int omap_rfbi_configure(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
|
||||
return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
|
||||
rfbi.data_lines);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_configure);
|
||||
|
||||
int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h)
|
||||
int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
|
||||
void *data)
|
||||
{
|
||||
u16 dw, dh;
|
||||
struct omap_video_timings timings = {
|
||||
.hsw = 1,
|
||||
.hfp = 1,
|
||||
.hbp = 1,
|
||||
.vsw = 1,
|
||||
.vfp = 0,
|
||||
.vbp = 0,
|
||||
.x_res = *w,
|
||||
.y_res = *h,
|
||||
};
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
if (*x > dw || *y > dh)
|
||||
return -EINVAL;
|
||||
|
||||
if (*x + *w > dw)
|
||||
return -EINVAL;
|
||||
|
||||
if (*y + *h > dh)
|
||||
return -EINVAL;
|
||||
|
||||
if (*w == 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (*w == 0 || *h == 0)
|
||||
return -EINVAL;
|
||||
|
||||
dss_mgr_set_timings(dssdev->manager, &timings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_prepare_update);
|
||||
|
||||
int omap_rfbi_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h,
|
||||
void (*callback)(void *), void *data)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = rfbi_transfer_area(dssdev, w, h, callback, data);
|
||||
|
||||
return r;
|
||||
return rfbi_transfer_area(dssdev, callback, data);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_update);
|
||||
|
||||
void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
|
||||
{
|
||||
rfbi.timings.x_res = w;
|
||||
rfbi.timings.y_res = h;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_set_size);
|
||||
|
||||
void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
|
||||
{
|
||||
rfbi.pixel_size = pixel_size;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
|
||||
|
||||
void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
|
||||
{
|
||||
rfbi.data_lines = data_lines;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
|
||||
|
||||
void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
|
||||
struct rfbi_timings *timings)
|
||||
{
|
||||
rfbi.intf_timings = *timings;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
|
||||
|
||||
static void rfbi_dump_regs(struct seq_file *s)
|
||||
{
|
||||
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
|
||||
|
|
@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)
|
|||
|
||||
static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
struct dss_lcd_mgr_config mgr_config;
|
||||
|
||||
mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
|
||||
|
|
@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
|
|||
/* Do we need fifohandcheck for RFBI? */
|
||||
mgr_config.fifohandcheck = false;
|
||||
|
||||
mgr_config.video_port_width = dssdev->ctrl.pixel_size;
|
||||
mgr_config.video_port_width = rfbi.pixel_size;
|
||||
mgr_config.lcden_sig_polarity = 0;
|
||||
|
||||
dss_mgr_set_lcd_config(dssdev->manager, &mgr_config);
|
||||
dss_mgr_set_lcd_config(mgr, &mgr_config);
|
||||
|
||||
/*
|
||||
* Set rfbi.timings with default values, the x_res and y_res fields
|
||||
* are expected to be already configured by the panel driver via
|
||||
* omapdss_rfbi_set_size()
|
||||
*/
|
||||
rfbi.timings.hsw = 1;
|
||||
rfbi.timings.hfp = 1;
|
||||
rfbi.timings.hbp = 1;
|
||||
rfbi.timings.vsw = 1;
|
||||
rfbi.timings.vfp = 0;
|
||||
rfbi.timings.vbp = 0;
|
||||
|
||||
rfbi.timings.interlace = false;
|
||||
rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
|
||||
rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
|
||||
rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
|
||||
rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
|
||||
|
||||
dss_mgr_set_timings(mgr, &rfbi.timings);
|
||||
}
|
||||
|
||||
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
int r;
|
||||
|
||||
if (dssdev->manager == NULL) {
|
||||
DSSERR("failed to enable display: no manager\n");
|
||||
if (out == NULL || out->manager == NULL) {
|
||||
DSSERR("failed to enable display: no output/manager\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
rfbi_config_lcd_manager(dssdev);
|
||||
|
||||
rfbi_configure(dssdev->phy.rfbi.channel,
|
||||
dssdev->ctrl.pixel_size,
|
||||
dssdev->phy.rfbi.data_lines);
|
||||
|
||||
rfbi_set_timings(dssdev->phy.rfbi.channel,
|
||||
&dssdev->ctrl.rfbi_timings);
|
||||
rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
|
||||
rfbi.data_lines);
|
||||
|
||||
rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
|
|
@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
|
|||
static int __init rfbi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init rfbi_probe_pdata(struct platform_device *pdev)
|
||||
static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i, r;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
def_dssdev = NULL;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
|
@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
|
|||
if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
|
||||
continue;
|
||||
|
||||
r = rfbi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
if (def_dssdev == NULL)
|
||||
def_dssdev = dssdev;
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
if (def_disp_name != NULL &&
|
||||
strcmp(dssdev->name, def_disp_name) == 0) {
|
||||
def_dssdev = dssdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return def_dssdev;
|
||||
}
|
||||
|
||||
static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
|
||||
{
|
||||
struct omap_dss_device *plat_dssdev;
|
||||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
|
||||
plat_dssdev = rfbi_find_dssdev(rfbidev);
|
||||
|
||||
if (!plat_dssdev)
|
||||
return;
|
||||
|
||||
dssdev = dss_alloc_and_init_device(&rfbidev->dev);
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
dss_copy_device_pdata(dssdev, plat_dssdev);
|
||||
|
||||
r = rfbi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init rfbi_init_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &rfbi.output;
|
||||
|
||||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_DBI;
|
||||
out->type = OMAP_DISPLAY_TYPE_DBI;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
||||
static void __exit rfbi_uninit_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &rfbi.output;
|
||||
|
||||
dss_unregister_output(out);
|
||||
}
|
||||
|
||||
/* RFBI HW IP initialisation */
|
||||
|
|
@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
|
|||
|
||||
dss_debugfs_create_file("rfbi", rfbi_dump_regs);
|
||||
|
||||
rfbi_init_output(pdev);
|
||||
|
||||
rfbi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1031,8 +1089,12 @@ err_runtime_get:
|
|||
|
||||
static int __exit omap_rfbihw_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
rfbi_uninit_output(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include "dss.h"
|
||||
|
|
@ -34,10 +35,16 @@ static struct {
|
|||
struct regulator *vdds_sdi_reg;
|
||||
|
||||
struct dss_lcd_mgr_config mgr_config;
|
||||
struct omap_video_timings timings;
|
||||
int datapairs;
|
||||
|
||||
struct omap_dss_output output;
|
||||
} sdi;
|
||||
|
||||
static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
|
||||
|
||||
sdi.mgr_config.stallmode = false;
|
||||
|
|
@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
|
|||
sdi.mgr_config.video_port_width = 24;
|
||||
sdi.mgr_config.lcden_sig_polarity = 1;
|
||||
|
||||
dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config);
|
||||
dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
|
||||
}
|
||||
|
||||
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_video_timings *t = &dssdev->panel.timings;
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
struct omap_video_timings *t = &sdi.timings;
|
||||
struct dss_clock_info dss_cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
unsigned long pck;
|
||||
int r;
|
||||
|
||||
if (dssdev->manager == NULL) {
|
||||
DSSERR("failed to enable display: no manager\n");
|
||||
if (out == NULL || out->manager == NULL) {
|
||||
DSSERR("failed to enable display: no output/manager\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err_get_dispc;
|
||||
|
||||
/* 15.5.9.1.2 */
|
||||
dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
|
||||
|
||||
r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
|
||||
if (r)
|
||||
|
|
@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
}
|
||||
|
||||
|
||||
dss_mgr_set_timings(dssdev->manager, t);
|
||||
dss_mgr_set_timings(out->manager, t);
|
||||
|
||||
r = dss_set_clock_div(&dss_cinfo);
|
||||
if (r)
|
||||
|
|
@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
* need to care about the shadow register mechanism for pck-free. The
|
||||
* exact reason for this is unknown.
|
||||
*/
|
||||
dispc_mgr_set_clock_div(dssdev->manager->id,
|
||||
&sdi.mgr_config.clock_info);
|
||||
dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
|
||||
|
||||
dss_sdi_init(dssdev->phy.sdi.datapairs);
|
||||
dss_sdi_init(sdi.datapairs);
|
||||
r = dss_sdi_enable();
|
||||
if (r)
|
||||
goto err_sdi_enable;
|
||||
mdelay(2);
|
||||
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
r = dss_mgr_enable(out->manager);
|
||||
if (r)
|
||||
goto err_mgr_enable;
|
||||
|
||||
|
|
@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
|
|||
|
||||
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
dss_sdi_disable();
|
||||
|
||||
|
|
@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
|
|||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_display_disable);
|
||||
|
||||
void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
sdi.timings = *timings;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_set_timings);
|
||||
|
||||
void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
|
||||
{
|
||||
sdi.datapairs = datapairs;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
|
||||
|
||||
static int __init sdi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("SDI init\n");
|
||||
|
|
@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __init sdi_probe_pdata(struct platform_device *pdev)
|
||||
static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i, r;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
def_dssdev = NULL;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
|
@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
|
|||
if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
|
||||
continue;
|
||||
|
||||
r = sdi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
if (def_dssdev == NULL)
|
||||
def_dssdev = dssdev;
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
if (def_disp_name != NULL &&
|
||||
strcmp(dssdev->name, def_disp_name) == 0) {
|
||||
def_dssdev = dssdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return def_dssdev;
|
||||
}
|
||||
|
||||
static void __init sdi_probe_pdata(struct platform_device *sdidev)
|
||||
{
|
||||
struct omap_dss_device *plat_dssdev;
|
||||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
|
||||
plat_dssdev = sdi_find_dssdev(sdidev);
|
||||
|
||||
if (!plat_dssdev)
|
||||
return;
|
||||
|
||||
dssdev = dss_alloc_and_init_device(&sdidev->dev);
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
dss_copy_device_pdata(dssdev, plat_dssdev);
|
||||
|
||||
r = sdi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init sdi_init_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &sdi.output;
|
||||
|
||||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_SDI;
|
||||
out->type = OMAP_DISPLAY_TYPE_SDI;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
||||
static void __exit sdi_uninit_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &sdi.output;
|
||||
|
||||
dss_unregister_output(out);
|
||||
}
|
||||
|
||||
static int __init omap_sdi_probe(struct platform_device *pdev)
|
||||
{
|
||||
sdi_init_output(pdev);
|
||||
|
||||
sdi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
|
@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev)
|
|||
|
||||
static int __exit omap_sdi_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
sdi_uninit_output(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
|
@ -300,6 +299,12 @@ static struct {
|
|||
struct regulator *vdda_dac_reg;
|
||||
|
||||
struct clk *tv_dac_clk;
|
||||
|
||||
struct omap_video_timings timings;
|
||||
enum omap_dss_venc_type type;
|
||||
bool invert_polarity;
|
||||
|
||||
struct omap_dss_output output;
|
||||
} venc;
|
||||
|
||||
static inline void venc_write_reg(int idx, u32 val)
|
||||
|
|
@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config(
|
|||
|
||||
static int venc_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
u32 l;
|
||||
int r;
|
||||
|
||||
venc_reset();
|
||||
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
|
||||
r = venc_runtime_get();
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
dss_set_venc_output(dssdev->phy.venc.type);
|
||||
venc_reset();
|
||||
venc_write_config(venc_timings_to_config(&venc.timings));
|
||||
|
||||
dss_set_venc_output(venc.type);
|
||||
dss_set_dac_pwrdn_bgz(1);
|
||||
|
||||
l = 0;
|
||||
|
||||
if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
|
||||
if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
|
||||
l |= 1 << 1;
|
||||
else /* S-Video */
|
||||
l |= (1 << 0) | (1 << 2);
|
||||
|
||||
if (dssdev->phy.venc.invert_polarity == false)
|
||||
if (venc.invert_polarity == false)
|
||||
l |= 1 << 3;
|
||||
|
||||
venc_write_reg(VENC_OUTPUT_CONTROL, l);
|
||||
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
dss_mgr_set_timings(mgr, &venc.timings);
|
||||
|
||||
r = regulator_enable(venc.vdda_dac_reg);
|
||||
if (r)
|
||||
goto err;
|
||||
goto err1;
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
r = dss_mgr_enable(mgr);
|
||||
if (r)
|
||||
goto err;
|
||||
goto err2;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
err2:
|
||||
regulator_disable(venc.vdda_dac_reg);
|
||||
err1:
|
||||
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
|
||||
dss_set_dac_pwrdn_bgz(0);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
regulator_disable(venc.vdda_dac_reg);
|
||||
|
||||
venc_runtime_put();
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void venc_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_manager *mgr = dssdev->output->manager;
|
||||
|
||||
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
|
||||
dss_set_dac_pwrdn_bgz(0);
|
||||
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
dss_mgr_disable(mgr);
|
||||
|
||||
regulator_disable(venc.vdda_dac_reg);
|
||||
|
||||
venc_runtime_put();
|
||||
}
|
||||
|
||||
unsigned long venc_get_pixel_clock(void)
|
||||
|
|
@ -491,171 +498,83 @@ unsigned long venc_get_pixel_clock(void)
|
|||
return 13500000;
|
||||
}
|
||||
|
||||
static ssize_t display_output_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
const char *ret;
|
||||
struct omap_dss_output *out = dssdev->output;
|
||||
int r;
|
||||
|
||||
switch (dssdev->phy.venc.type) {
|
||||
case OMAP_DSS_VENC_TYPE_COMPOSITE:
|
||||
ret = "composite";
|
||||
break;
|
||||
case OMAP_DSS_VENC_TYPE_SVIDEO:
|
||||
ret = "svideo";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t display_output_type_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
enum omap_dss_venc_type new_type;
|
||||
|
||||
if (sysfs_streq("composite", buf))
|
||||
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
|
||||
else if (sysfs_streq("svideo", buf))
|
||||
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
|
||||
else
|
||||
return -EINVAL;
|
||||
DSSDBG("venc_display_enable\n");
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
if (dssdev->phy.venc.type != new_type) {
|
||||
dssdev->phy.venc.type = new_type;
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
venc_power_off(dssdev);
|
||||
venc_power_on(dssdev);
|
||||
}
|
||||
if (out == NULL || out->manager == NULL) {
|
||||
DSSERR("Failed to enable display: no output/manager\n");
|
||||
r = -ENODEV;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
|
||||
display_output_type_show, display_output_type_store);
|
||||
|
||||
/* driver */
|
||||
static int venc_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.timings = omap_dss_pal_timings;
|
||||
|
||||
return device_create_file(&dssdev->dev, &dev_attr_output_type);
|
||||
}
|
||||
|
||||
static void venc_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
device_remove_file(&dssdev->dev, &dev_attr_output_type);
|
||||
}
|
||||
|
||||
static int venc_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
DSSDBG("venc_enable_display\n");
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
r = omap_dss_start_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("failed to start device\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
r = -EINVAL;
|
||||
goto err1;
|
||||
}
|
||||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
|
||||
r = venc_runtime_get();
|
||||
if (r)
|
||||
goto err1;
|
||||
|
||||
r = venc_power_on(dssdev);
|
||||
if (r)
|
||||
goto err2;
|
||||
goto err1;
|
||||
|
||||
venc.wss_data = 0;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return 0;
|
||||
err2:
|
||||
venc_runtime_put();
|
||||
err1:
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void venc_panel_disable(struct omap_dss_device *dssdev)
|
||||
void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("venc_disable_display\n");
|
||||
DSSDBG("venc_display_disable\n");
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
|
||||
goto end;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
|
||||
/* suspended is the same as disabled with venc */
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
venc_power_off(dssdev);
|
||||
|
||||
venc_runtime_put();
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
end:
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
static int venc_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
venc_panel_disable(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int venc_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return venc_panel_enable(dssdev);
|
||||
}
|
||||
|
||||
static void venc_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
DSSDBG("venc_set_timings\n");
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
/* Reset WSS data when the TV standard changes. */
|
||||
if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
|
||||
if (memcmp(&venc.timings, timings, sizeof(*timings)))
|
||||
venc.wss_data = 0;
|
||||
|
||||
dssdev->panel.timings = *timings;
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
/* turn the venc off and on to get new timings to use */
|
||||
venc_panel_disable(dssdev);
|
||||
venc_panel_enable(dssdev);
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, timings);
|
||||
}
|
||||
venc.timings = *timings;
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
static int venc_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
DSSDBG("venc_check_timings\n");
|
||||
|
||||
|
|
@ -668,13 +587,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static u32 venc_get_wss(struct omap_dss_device *dssdev)
|
||||
u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
|
||||
{
|
||||
/* Invert due to VENC_L21_WC_CTL:INV=1 */
|
||||
return (venc.wss_data >> 8) ^ 0xfffff;
|
||||
}
|
||||
|
||||
static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
|
||||
int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
|
||||
{
|
||||
const struct venc_config *config;
|
||||
int r;
|
||||
|
|
@ -683,7 +602,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
|
|||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
config = venc_timings_to_config(&dssdev->panel.timings);
|
||||
config = venc_timings_to_config(&venc.timings);
|
||||
|
||||
/* Invert due to VENC_L21_WC_CTL:INV=1 */
|
||||
venc.wss_data = (wss ^ 0xfffff) << 8;
|
||||
|
|
@ -703,30 +622,25 @@ err:
|
|||
return r;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver venc_driver = {
|
||||
.probe = venc_panel_probe,
|
||||
.remove = venc_panel_remove,
|
||||
void omapdss_venc_set_type(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_venc_type type)
|
||||
{
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
.enable = venc_panel_enable,
|
||||
.disable = venc_panel_disable,
|
||||
.suspend = venc_panel_suspend,
|
||||
.resume = venc_panel_resume,
|
||||
venc.type = type;
|
||||
|
||||
.get_resolution = omapdss_default_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
.set_timings = venc_set_timings,
|
||||
.check_timings = venc_check_timings,
|
||||
void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
|
||||
bool invert_polarity)
|
||||
{
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
.get_wss = venc_get_wss,
|
||||
.set_wss = venc_set_wss,
|
||||
venc.invert_polarity = invert_polarity;
|
||||
|
||||
.driver = {
|
||||
.name = "venc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
/* driver end */
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
static int __init venc_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
|
|
@ -752,11 +666,6 @@ static void venc_dump_regs(struct seq_file *s)
|
|||
{
|
||||
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
|
||||
|
||||
if (cpu_is_omap44xx()) {
|
||||
seq_printf(s, "VENC currently disabled on OMAP44xx\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (venc_runtime_get())
|
||||
return;
|
||||
|
||||
|
|
@ -832,10 +741,14 @@ static void venc_put_clocks(void)
|
|||
clk_put(venc.tv_dac_clk);
|
||||
}
|
||||
|
||||
static void __init venc_probe_pdata(struct platform_device *pdev)
|
||||
static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int r, i;
|
||||
const char *def_disp_name = dss_get_default_display_name();
|
||||
struct omap_dss_device *def_dssdev;
|
||||
int i;
|
||||
|
||||
def_dssdev = NULL;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
|
@ -843,17 +756,69 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
|
|||
if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
|
||||
continue;
|
||||
|
||||
r = venc_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
if (def_dssdev == NULL)
|
||||
def_dssdev = dssdev;
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
if (def_disp_name != NULL &&
|
||||
strcmp(dssdev->name, def_disp_name) == 0) {
|
||||
def_dssdev = dssdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return def_dssdev;
|
||||
}
|
||||
|
||||
static void __init venc_probe_pdata(struct platform_device *vencdev)
|
||||
{
|
||||
struct omap_dss_device *plat_dssdev;
|
||||
struct omap_dss_device *dssdev;
|
||||
int r;
|
||||
|
||||
plat_dssdev = venc_find_dssdev(vencdev);
|
||||
|
||||
if (!plat_dssdev)
|
||||
return;
|
||||
|
||||
dssdev = dss_alloc_and_init_device(&vencdev->dev);
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
dss_copy_device_pdata(dssdev, plat_dssdev);
|
||||
|
||||
dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
|
||||
r = venc_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
|
||||
r = dss_add_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s register failed: %d\n", dssdev->name, r);
|
||||
dss_put_device(dssdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init venc_init_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &venc.output;
|
||||
|
||||
out->pdev = pdev;
|
||||
out->id = OMAP_DSS_OUTPUT_VENC;
|
||||
out->type = OMAP_DISPLAY_TYPE_VENC;
|
||||
|
||||
dss_register_output(out);
|
||||
}
|
||||
|
||||
static void __exit venc_uninit_output(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_output *out = &venc.output;
|
||||
|
||||
dss_unregister_output(out);
|
||||
}
|
||||
|
||||
/* VENC HW IP initialisation */
|
||||
|
|
@ -897,17 +862,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
|
|||
|
||||
venc_runtime_put();
|
||||
|
||||
r = omap_dss_register_driver(&venc_driver);
|
||||
r = venc_panel_init();
|
||||
if (r)
|
||||
goto err_reg_panel_driver;
|
||||
goto err_panel_init;
|
||||
|
||||
dss_debugfs_create_file("venc", venc_dump_regs);
|
||||
|
||||
venc_init_output(pdev);
|
||||
|
||||
venc_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg_panel_driver:
|
||||
err_panel_init:
|
||||
err_runtime_get:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
venc_put_clocks();
|
||||
|
|
@ -916,14 +883,16 @@ err_runtime_get:
|
|||
|
||||
static int __exit omap_venchw_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
if (venc.vdda_dac_reg != NULL) {
|
||||
regulator_put(venc.vdda_dac_reg);
|
||||
venc.vdda_dac_reg = NULL;
|
||||
}
|
||||
|
||||
omap_dss_unregister_driver(&venc_driver);
|
||||
venc_panel_exit();
|
||||
|
||||
venc_uninit_output(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
venc_put_clocks();
|
||||
|
|
@ -971,16 +940,10 @@ static struct platform_driver omap_venchw_driver = {
|
|||
|
||||
int __init venc_init_platform_driver(void)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
return 0;
|
||||
|
||||
return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
|
||||
}
|
||||
|
||||
void __exit venc_uninit_platform_driver(void)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
return;
|
||||
|
||||
platform_driver_unregister(&omap_venchw_driver);
|
||||
}
|
||||
|
|
|
|||
251
drivers/video/omap2/dss/venc_panel.c
Normal file
251
drivers/video/omap2/dss/venc_panel.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* VENC panel driver
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
||||
static struct {
|
||||
struct mutex lock;
|
||||
} venc_panel;
|
||||
|
||||
static ssize_t display_output_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
const char *ret;
|
||||
|
||||
switch (dssdev->phy.venc.type) {
|
||||
case OMAP_DSS_VENC_TYPE_COMPOSITE:
|
||||
ret = "composite";
|
||||
break;
|
||||
case OMAP_DSS_VENC_TYPE_SVIDEO:
|
||||
ret = "svideo";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t display_output_type_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
enum omap_dss_venc_type new_type;
|
||||
|
||||
if (sysfs_streq("composite", buf))
|
||||
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
|
||||
else if (sysfs_streq("svideo", buf))
|
||||
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&venc_panel.lock);
|
||||
|
||||
if (dssdev->phy.venc.type != new_type) {
|
||||
dssdev->phy.venc.type = new_type;
|
||||
omapdss_venc_set_type(dssdev, new_type);
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
omapdss_venc_display_disable(dssdev);
|
||||
omapdss_venc_display_enable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&venc_panel.lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
|
||||
display_output_type_show, display_output_type_store);
|
||||
|
||||
static int venc_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
/* set default timings to PAL */
|
||||
const struct omap_video_timings default_timings = {
|
||||
.x_res = 720,
|
||||
.y_res = 574,
|
||||
.pixel_clock = 13500,
|
||||
.hsw = 64,
|
||||
.hfp = 12,
|
||||
.hbp = 68,
|
||||
.vsw = 5,
|
||||
.vfp = 5,
|
||||
.vbp = 41,
|
||||
|
||||
.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
|
||||
.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
|
||||
|
||||
.interlace = true,
|
||||
};
|
||||
|
||||
mutex_init(&venc_panel.lock);
|
||||
|
||||
dssdev->panel.timings = default_timings;
|
||||
|
||||
return device_create_file(&dssdev->dev, &dev_attr_output_type);
|
||||
}
|
||||
|
||||
static void venc_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
device_remove_file(&dssdev->dev, &dev_attr_output_type);
|
||||
}
|
||||
|
||||
static int venc_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "venc_panel_enable\n");
|
||||
|
||||
mutex_lock(&venc_panel.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
|
||||
omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
|
||||
omapdss_venc_invert_vid_out_polarity(dssdev,
|
||||
dssdev->phy.venc.invert_polarity);
|
||||
|
||||
r = omapdss_venc_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
mutex_unlock(&venc_panel.lock);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
mutex_unlock(&venc_panel.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void venc_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "venc_panel_disable\n");
|
||||
|
||||
mutex_lock(&venc_panel.lock);
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
|
||||
goto end;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
|
||||
/* suspended is the same as disabled with venc */
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
omapdss_venc_display_disable(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
end:
|
||||
mutex_unlock(&venc_panel.lock);
|
||||
}
|
||||
|
||||
static int venc_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
venc_panel_disable(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int venc_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return venc_panel_enable(dssdev);
|
||||
}
|
||||
|
||||
static void venc_panel_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
|
||||
|
||||
mutex_lock(&venc_panel.lock);
|
||||
|
||||
omapdss_venc_set_timings(dssdev, timings);
|
||||
dssdev->panel.timings = *timings;
|
||||
|
||||
mutex_unlock(&venc_panel.lock);
|
||||
}
|
||||
|
||||
static int venc_panel_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
|
||||
|
||||
return omapdss_venc_check_timings(dssdev, timings);
|
||||
}
|
||||
|
||||
static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
|
||||
|
||||
return omapdss_venc_get_wss(dssdev);
|
||||
}
|
||||
|
||||
static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
|
||||
|
||||
return omapdss_venc_set_wss(dssdev, wss);
|
||||
}
|
||||
|
||||
static struct omap_dss_driver venc_driver = {
|
||||
.probe = venc_panel_probe,
|
||||
.remove = venc_panel_remove,
|
||||
|
||||
.enable = venc_panel_enable,
|
||||
.disable = venc_panel_disable,
|
||||
.suspend = venc_panel_suspend,
|
||||
.resume = venc_panel_resume,
|
||||
|
||||
.get_resolution = omapdss_default_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
|
||||
.set_timings = venc_panel_set_timings,
|
||||
.check_timings = venc_panel_check_timings,
|
||||
|
||||
.get_wss = venc_panel_get_wss,
|
||||
.set_wss = venc_panel_set_wss,
|
||||
|
||||
.driver = {
|
||||
.name = "venc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
int venc_panel_init(void)
|
||||
{
|
||||
return omap_dss_register_driver(&venc_driver);
|
||||
}
|
||||
|
||||
void venc_panel_exit(void)
|
||||
{
|
||||
omap_dss_unregister_driver(&venc_driver);
|
||||
}
|
||||
|
|
@ -599,6 +599,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_dss_device *display = fb2display(fbi);
|
||||
struct omap_overlay_manager *mgr;
|
||||
|
||||
union {
|
||||
struct omapfb_update_window_old uwnd_o;
|
||||
|
|
@ -786,12 +787,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
|
||||
case OMAPFB_WAITFORVSYNC:
|
||||
DBG("ioctl WAITFORVSYNC\n");
|
||||
if (!display) {
|
||||
if (!display && !display->output && !display->output->manager) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
r = display->manager->wait_for_vsync(display->manager);
|
||||
mgr = display->output->manager;
|
||||
|
||||
r = mgr->wait_for_vsync(mgr);
|
||||
break;
|
||||
|
||||
case OMAPFB_WAITFORGO:
|
||||
|
|
|
|||
|
|
@ -1593,6 +1593,20 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void omapfb_clear_fb(struct fb_info *fbi)
|
||||
{
|
||||
const struct fb_fillrect rect = {
|
||||
.dx = 0,
|
||||
.dy = 0,
|
||||
.width = fbi->var.xres_virtual,
|
||||
.height = fbi->var.yres_virtual,
|
||||
.color = 0,
|
||||
.rop = ROP_COPY,
|
||||
};
|
||||
|
||||
cfb_fillrect(fbi, &rect);
|
||||
}
|
||||
|
||||
int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
|
@ -1662,6 +1676,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
|||
goto err;
|
||||
}
|
||||
|
||||
omapfb_clear_fb(fbi);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
omapfb_free_fbmem(fbi);
|
||||
|
|
@ -1946,6 +1962,16 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
struct fb_info *fbi = fbdev->fbs[i];
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
if (ofbi->region->size == 0)
|
||||
continue;
|
||||
|
||||
omapfb_clear_fb(fbi);
|
||||
}
|
||||
|
||||
DBG("fb_infos initialized\n");
|
||||
|
||||
for (i = 0; i < fbdev->num_fbs; i++) {
|
||||
|
|
@ -2354,6 +2380,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
|||
struct omap_overlay *ovl;
|
||||
struct omap_dss_device *def_display;
|
||||
struct omap_dss_device *dssdev;
|
||||
struct omap_dss_device *ovl_device;
|
||||
|
||||
DBG("omapfb_probe\n");
|
||||
|
||||
|
|
@ -2427,8 +2454,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
|
|||
/* gfx overlay should be the default one. find a display
|
||||
* connected to that, and use it as default display */
|
||||
ovl = omap_dss_get_overlay(0);
|
||||
if (ovl->manager && ovl->manager->device) {
|
||||
def_display = ovl->manager->device;
|
||||
ovl_device = ovl->get_device(ovl);
|
||||
if (ovl_device) {
|
||||
def_display = ovl_device;
|
||||
} else {
|
||||
dev_warn(&pdev->dev, "cannot find default display\n");
|
||||
def_display = NULL;
|
||||
|
|
|
|||
|
|
@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
|
|||
|
||||
/* XXX: returns the display connected to first attached overlay */
|
||||
for (i = 0; i < ofbi->num_overlays; i++) {
|
||||
if (ofbi->overlays[i]->manager)
|
||||
return ofbi->overlays[i]->manager->device;
|
||||
struct omap_overlay *ovl = ofbi->overlays[i];
|
||||
|
||||
return ovl->get_device(ovl);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <asm/setup.h>
|
||||
|
||||
#include <plat/vram.h>
|
||||
#include <plat/dma.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
|
||||
|
|
@ -250,59 +249,6 @@ int omap_vram_reserve(unsigned long paddr, size_t size)
|
|||
}
|
||||
EXPORT_SYMBOL(omap_vram_reserve);
|
||||
|
||||
static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
|
||||
{
|
||||
struct completion *compl = data;
|
||||
complete(compl);
|
||||
}
|
||||
|
||||
static int _omap_vram_clear(u32 paddr, unsigned pages)
|
||||
{
|
||||
struct completion compl;
|
||||
unsigned elem_count;
|
||||
unsigned frame_count;
|
||||
int r;
|
||||
int lch;
|
||||
|
||||
init_completion(&compl);
|
||||
|
||||
r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
|
||||
_omap_vram_dma_cb,
|
||||
&compl, &lch);
|
||||
if (r) {
|
||||
pr_err("VRAM: request_dma failed for memory clear\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
elem_count = pages * PAGE_SIZE / 4;
|
||||
frame_count = 1;
|
||||
|
||||
omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
|
||||
elem_count, frame_count,
|
||||
OMAP_DMA_SYNC_ELEMENT,
|
||||
0, 0);
|
||||
|
||||
omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
|
||||
paddr, 0, 0);
|
||||
|
||||
omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
|
||||
|
||||
omap_start_dma(lch);
|
||||
|
||||
if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
|
||||
omap_stop_dma(lch);
|
||||
pr_err("VRAM: dma timeout while clearing memory\n");
|
||||
r = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
err:
|
||||
omap_free_dma(lch);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
|
||||
{
|
||||
struct vram_region *rm;
|
||||
|
|
@ -337,8 +283,6 @@ found:
|
|||
|
||||
*paddr = start;
|
||||
|
||||
_omap_vram_clear(start, pages);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
#
|
||||
# Makefile for the new PNX4008 framebuffer device driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o
|
||||
obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnxrgbfb.o
|
||||
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
/*
|
||||
* linux/drivers/video/pnx4008/dum.h
|
||||
*
|
||||
* Internal header for SDUM
|
||||
*
|
||||
* 2005 (c) Koninklijke Philips N.V. This file is licensed under
|
||||
* the terms of the GNU General Public License version 2. This program
|
||||
* is licensed "as is" without any warranty of any kind, whether express
|
||||
* or implied.
|
||||
*/
|
||||
|
||||
#ifndef __PNX008_DUM_H__
|
||||
#define __PNX008_DUM_H__
|
||||
|
||||
#include <mach/platform.h>
|
||||
|
||||
#define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE)
|
||||
#define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE)
|
||||
|
||||
/* DUM CFG ADDRESSES */
|
||||
#define DUM_CH_BASE_ADR (PNX4008_DUMCONF_VA_BASE + 0x00)
|
||||
#define DUM_CH_MIN_ADR (PNX4008_DUMCONF_VA_BASE + 0x00)
|
||||
#define DUM_CH_MAX_ADR (PNX4008_DUMCONF_VA_BASE + 0x04)
|
||||
#define DUM_CH_CONF_ADR (PNX4008_DUMCONF_VA_BASE + 0x08)
|
||||
#define DUM_CH_STAT_ADR (PNX4008_DUMCONF_VA_BASE + 0x0C)
|
||||
#define DUM_CH_CTRL_ADR (PNX4008_DUMCONF_VA_BASE + 0x10)
|
||||
|
||||
#define CH_MARG (0x100 / sizeof(u32))
|
||||
#define DUM_CH_MIN(i) (*((volatile u32 *)DUM_CH_MIN_ADR + (i) * CH_MARG))
|
||||
#define DUM_CH_MAX(i) (*((volatile u32 *)DUM_CH_MAX_ADR + (i) * CH_MARG))
|
||||
#define DUM_CH_CONF(i) (*((volatile u32 *)DUM_CH_CONF_ADR + (i) * CH_MARG))
|
||||
#define DUM_CH_STAT(i) (*((volatile u32 *)DUM_CH_STAT_ADR + (i) * CH_MARG))
|
||||
#define DUM_CH_CTRL(i) (*((volatile u32 *)DUM_CH_CTRL_ADR + (i) * CH_MARG))
|
||||
|
||||
#define DUM_CONF_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x00)
|
||||
#define DUM_CTRL_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x04)
|
||||
#define DUM_STAT_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x08)
|
||||
#define DUM_DECODE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x0C)
|
||||
#define DUM_COM_BASE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x10)
|
||||
#define DUM_SYNC_C_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x14)
|
||||
#define DUM_CLK_DIV_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x18)
|
||||
#define DUM_DIRTY_LOW_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x20)
|
||||
#define DUM_DIRTY_HIGH_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x24)
|
||||
#define DUM_FORMAT_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x28)
|
||||
#define DUM_WTCFG1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x30)
|
||||
#define DUM_RTCFG1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x34)
|
||||
#define DUM_WTCFG2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x38)
|
||||
#define DUM_RTCFG2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x3C)
|
||||
#define DUM_TCFG_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x40)
|
||||
#define DUM_OUTP_FORMAT1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x44)
|
||||
#define DUM_OUTP_FORMAT2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x48)
|
||||
#define DUM_SYNC_MODE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x4C)
|
||||
#define DUM_SYNC_OUT_C_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x50)
|
||||
|
||||
#define DUM_CONF (*(volatile u32 *)(DUM_CONF_ADR))
|
||||
#define DUM_CTRL (*(volatile u32 *)(DUM_CTRL_ADR))
|
||||
#define DUM_STAT (*(volatile u32 *)(DUM_STAT_ADR))
|
||||
#define DUM_DECODE (*(volatile u32 *)(DUM_DECODE_ADR))
|
||||
#define DUM_COM_BASE (*(volatile u32 *)(DUM_COM_BASE_ADR))
|
||||
#define DUM_SYNC_C (*(volatile u32 *)(DUM_SYNC_C_ADR))
|
||||
#define DUM_CLK_DIV (*(volatile u32 *)(DUM_CLK_DIV_ADR))
|
||||
#define DUM_DIRTY_LOW (*(volatile u32 *)(DUM_DIRTY_LOW_ADR))
|
||||
#define DUM_DIRTY_HIGH (*(volatile u32 *)(DUM_DIRTY_HIGH_ADR))
|
||||
#define DUM_FORMAT (*(volatile u32 *)(DUM_FORMAT_ADR))
|
||||
#define DUM_WTCFG1 (*(volatile u32 *)(DUM_WTCFG1_ADR))
|
||||
#define DUM_RTCFG1 (*(volatile u32 *)(DUM_RTCFG1_ADR))
|
||||
#define DUM_WTCFG2 (*(volatile u32 *)(DUM_WTCFG2_ADR))
|
||||
#define DUM_RTCFG2 (*(volatile u32 *)(DUM_RTCFG2_ADR))
|
||||
#define DUM_TCFG (*(volatile u32 *)(DUM_TCFG_ADR))
|
||||
#define DUM_OUTP_FORMAT1 (*(volatile u32 *)(DUM_OUTP_FORMAT1_ADR))
|
||||
#define DUM_OUTP_FORMAT2 (*(volatile u32 *)(DUM_OUTP_FORMAT2_ADR))
|
||||
#define DUM_SYNC_MODE (*(volatile u32 *)(DUM_SYNC_MODE_ADR))
|
||||
#define DUM_SYNC_OUT_C (*(volatile u32 *)(DUM_SYNC_OUT_C_ADR))
|
||||
|
||||
/* DUM SLAVE ADDRESSES */
|
||||
#define DUM_SLAVE_WRITE_ADR (PNX4008_DUM_MAINCFG_BASE + 0x0000000)
|
||||
#define DUM_SLAVE_READ1_I_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000000)
|
||||
#define DUM_SLAVE_READ1_R_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000004)
|
||||
#define DUM_SLAVE_READ2_I_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000008)
|
||||
#define DUM_SLAVE_READ2_R_ADR (PNX4008_DUM_MAINCFG_BASE + 0x100000C)
|
||||
|
||||
#define DUM_SLAVE_WRITE_W ((volatile u32 *)(DUM_SLAVE_WRITE_ADR))
|
||||
#define DUM_SLAVE_WRITE_HW ((volatile u16 *)(DUM_SLAVE_WRITE_ADR))
|
||||
#define DUM_SLAVE_READ1_I ((volatile u8 *)(DUM_SLAVE_READ1_I_ADR))
|
||||
#define DUM_SLAVE_READ1_R ((volatile u16 *)(DUM_SLAVE_READ1_R_ADR))
|
||||
#define DUM_SLAVE_READ2_I ((volatile u8 *)(DUM_SLAVE_READ2_I_ADR))
|
||||
#define DUM_SLAVE_READ2_R ((volatile u16 *)(DUM_SLAVE_READ2_R_ADR))
|
||||
|
||||
/* Sony display register addresses */
|
||||
#define DISP_0_REG (0x00)
|
||||
#define DISP_1_REG (0x01)
|
||||
#define DISP_CAL_REG (0x20)
|
||||
#define DISP_ID_REG (0x2A)
|
||||
#define DISP_XMIN_L_REG (0x30)
|
||||
#define DISP_XMIN_H_REG (0x31)
|
||||
#define DISP_YMIN_REG (0x32)
|
||||
#define DISP_XMAX_L_REG (0x34)
|
||||
#define DISP_XMAX_H_REG (0x35)
|
||||
#define DISP_YMAX_REG (0x36)
|
||||
#define DISP_SYNC_EN_REG (0x38)
|
||||
#define DISP_SYNC_RISE_L_REG (0x3C)
|
||||
#define DISP_SYNC_RISE_H_REG (0x3D)
|
||||
#define DISP_SYNC_FALL_L_REG (0x3E)
|
||||
#define DISP_SYNC_FALL_H_REG (0x3F)
|
||||
#define DISP_PIXEL_REG (0x0B)
|
||||
#define DISP_DUMMY1_REG (0x28)
|
||||
#define DISP_DUMMY2_REG (0x29)
|
||||
#define DISP_TIMING_REG (0x98)
|
||||
#define DISP_DUMP_REG (0x99)
|
||||
|
||||
/* Sony display constants */
|
||||
#define SONY_ID1 (0x22)
|
||||
#define SONY_ID2 (0x23)
|
||||
|
||||
/* Philips display register addresses */
|
||||
#define PH_DISP_ORIENT_REG (0x003)
|
||||
#define PH_DISP_YPOINT_REG (0x200)
|
||||
#define PH_DISP_XPOINT_REG (0x201)
|
||||
#define PH_DISP_PIXEL_REG (0x202)
|
||||
#define PH_DISP_YMIN_REG (0x406)
|
||||
#define PH_DISP_YMAX_REG (0x407)
|
||||
#define PH_DISP_XMIN_REG (0x408)
|
||||
#define PH_DISP_XMAX_REG (0x409)
|
||||
|
||||
/* Misc constants */
|
||||
#define NO_VALID_DISPLAY_FOUND (0)
|
||||
#define DISPLAY2_IS_NOT_CONNECTED (0)
|
||||
|
||||
/* register values */
|
||||
#define V_BAC_ENABLE (BIT(0))
|
||||
#define V_BAC_DISABLE_IDLE (BIT(1))
|
||||
#define V_BAC_DISABLE_TRIG (BIT(2))
|
||||
#define V_DUM_RESET (BIT(3))
|
||||
#define V_MUX_RESET (BIT(4))
|
||||
#define BAC_ENABLED (BIT(0))
|
||||
#define BAC_DISABLED 0
|
||||
|
||||
/* Sony LCD commands */
|
||||
#define V_LCD_STANDBY_OFF ((BIT(25)) | (0 << 16) | DISP_0_REG)
|
||||
#define V_LCD_USE_9BIT_BUS ((BIT(25)) | (2 << 16) | DISP_1_REG)
|
||||
#define V_LCD_SYNC_RISE_L ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_L_REG)
|
||||
#define V_LCD_SYNC_RISE_H ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_H_REG)
|
||||
#define V_LCD_SYNC_FALL_L ((BIT(25)) | (160 << 16) | DISP_SYNC_FALL_L_REG)
|
||||
#define V_LCD_SYNC_FALL_H ((BIT(25)) | (0 << 16) | DISP_SYNC_FALL_H_REG)
|
||||
#define V_LCD_SYNC_ENABLE ((BIT(25)) | (128 << 16) | DISP_SYNC_EN_REG)
|
||||
#define V_LCD_DISPLAY_ON ((BIT(25)) | (64 << 16) | DISP_0_REG)
|
||||
|
||||
enum {
|
||||
PAD_NONE,
|
||||
PAD_512,
|
||||
PAD_1024
|
||||
};
|
||||
|
||||
enum {
|
||||
RGB888,
|
||||
RGB666,
|
||||
RGB565,
|
||||
BGR565,
|
||||
ARGB1555,
|
||||
ABGR1555,
|
||||
ARGB4444,
|
||||
ABGR4444
|
||||
};
|
||||
|
||||
struct dum_setup {
|
||||
int sync_neg_edge;
|
||||
int round_robin;
|
||||
int mux_int;
|
||||
int synced_dirty_flag_int;
|
||||
int dirty_flag_int;
|
||||
int error_int;
|
||||
int pf_empty_int;
|
||||
int sf_empty_int;
|
||||
int bac_dis_int;
|
||||
u32 dirty_base_adr;
|
||||
u32 command_base_adr;
|
||||
u32 sync_clk_div;
|
||||
int sync_output;
|
||||
u32 sync_restart_val;
|
||||
u32 set_sync_high;
|
||||
u32 set_sync_low;
|
||||
};
|
||||
|
||||
struct dum_ch_setup {
|
||||
int disp_no;
|
||||
u32 xmin;
|
||||
u32 ymin;
|
||||
u32 xmax;
|
||||
u32 ymax;
|
||||
int xmirror;
|
||||
int ymirror;
|
||||
int rotate;
|
||||
u32 minadr;
|
||||
u32 maxadr;
|
||||
u32 dirtybuffer;
|
||||
int pad;
|
||||
int format;
|
||||
int hwdirty;
|
||||
int slave_trans;
|
||||
};
|
||||
|
||||
struct disp_window {
|
||||
u32 xmin_l;
|
||||
u32 xmin_h;
|
||||
u32 ymin;
|
||||
u32 xmax_l;
|
||||
u32 xmax_h;
|
||||
u32 ymax;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __PNX008_DUM_H__ */
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Philips Semiconductors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
#define QCIF_W (176)
|
||||
#define QCIF_H (144)
|
||||
|
||||
#define CIF_W (352)
|
||||
#define CIF_H (288)
|
||||
|
||||
#define LCD_X_RES 208
|
||||
#define LCD_Y_RES 320
|
||||
#define LCD_X_PAD 256
|
||||
#define LCD_BBP 4 /* Bytes Per Pixel */
|
||||
|
||||
#define DISP_MAX_X_SIZE (320)
|
||||
#define DISP_MAX_Y_SIZE (208)
|
||||
|
||||
#define RETURNVAL_BASE (0x400)
|
||||
|
||||
enum fb_ioctl_returntype {
|
||||
ENORESOURCESLEFT = RETURNVAL_BASE,
|
||||
ERESOURCESNOTFREED,
|
||||
EPROCNOTOWNER,
|
||||
EFBNOTOWNER,
|
||||
ECOPYFAILED,
|
||||
EIOREMAPFAILED,
|
||||
};
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
/*
|
||||
* drivers/video/pnx4008/pnxrgbfb.c
|
||||
*
|
||||
* PNX4008's framebuffer support
|
||||
*
|
||||
* Author: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
|
||||
* Based on Philips Semiconductors's code
|
||||
*
|
||||
* Copyrght (c) 2005 MontaVista Software, Inc.
|
||||
* Copyright (c) 2005 Philips Semiconductors
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "sdum.h"
|
||||
#include "fbcommon.h"
|
||||
|
||||
static u32 colreg[16];
|
||||
|
||||
static struct fb_var_screeninfo rgbfb_var __initdata = {
|
||||
.xres = LCD_X_RES,
|
||||
.yres = LCD_Y_RES,
|
||||
.xres_virtual = LCD_X_RES,
|
||||
.yres_virtual = LCD_Y_RES,
|
||||
.bits_per_pixel = 32,
|
||||
.red.offset = 16,
|
||||
.red.length = 8,
|
||||
.green.offset = 8,
|
||||
.green.length = 8,
|
||||
.blue.offset = 0,
|
||||
.blue.length = 8,
|
||||
.left_margin = 0,
|
||||
.right_margin = 0,
|
||||
.upper_margin = 0,
|
||||
.lower_margin = 0,
|
||||
.vmode = FB_VMODE_NONINTERLACED,
|
||||
};
|
||||
static struct fb_fix_screeninfo rgbfb_fix __initdata = {
|
||||
.id = "RGBFB",
|
||||
.line_length = LCD_X_RES * LCD_BBP,
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_TRUECOLOR,
|
||||
.xpanstep = 0,
|
||||
.ypanstep = 0,
|
||||
.ywrapstep = 0,
|
||||
.accel = FB_ACCEL_NONE,
|
||||
};
|
||||
|
||||
static int channel_owned;
|
||||
|
||||
static int no_cursor(struct fb_info *info, struct fb_cursor *cursor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rgbfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
u_int transp, struct fb_info *info)
|
||||
{
|
||||
if (regno > 15)
|
||||
return 1;
|
||||
|
||||
colreg[regno] = ((red & 0xff00) << 8) | (green & 0xff00) |
|
||||
((blue & 0xff00) >> 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
return pnx4008_sdum_mmap(info, vma, NULL);
|
||||
}
|
||||
|
||||
static struct fb_ops rgbfb_ops = {
|
||||
.fb_mmap = rgbfb_mmap,
|
||||
.fb_setcolreg = rgbfb_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
};
|
||||
|
||||
static int rgbfb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fb_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
if (info) {
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
framebuffer_release(info);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
pnx4008_free_dum_channel(channel_owned, pdev->id);
|
||||
pnx4008_set_dum_exit_notification(pdev->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit rgbfb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct dumchannel_uf chan_uf;
|
||||
int ret;
|
||||
char *option;
|
||||
|
||||
info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
|
||||
if (!info) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pnx4008_get_fb_addresses(FB_TYPE_RGB, (void **)&info->screen_base,
|
||||
(dma_addr_t *) &rgbfb_fix.smem_start,
|
||||
&rgbfb_fix.smem_len);
|
||||
|
||||
if ((ret = pnx4008_alloc_dum_channel(pdev->id)) < 0)
|
||||
goto err0;
|
||||
else {
|
||||
channel_owned = ret;
|
||||
chan_uf.channelnr = channel_owned;
|
||||
chan_uf.dirty = (u32 *) NULL;
|
||||
chan_uf.source = (u32 *) rgbfb_fix.smem_start;
|
||||
chan_uf.x_offset = 0;
|
||||
chan_uf.y_offset = 0;
|
||||
chan_uf.width = LCD_X_RES;
|
||||
chan_uf.height = LCD_Y_RES;
|
||||
|
||||
if ((ret = pnx4008_put_dum_channel_uf(chan_uf, pdev->id))< 0)
|
||||
goto err1;
|
||||
|
||||
if ((ret =
|
||||
pnx4008_set_dum_channel_sync(channel_owned, CONF_SYNC_ON,
|
||||
pdev->id)) < 0)
|
||||
goto err1;
|
||||
|
||||
if ((ret =
|
||||
pnx4008_set_dum_channel_dirty_detect(channel_owned,
|
||||
CONF_DIRTYDETECTION_ON,
|
||||
pdev->id)) < 0)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (!fb_get_options("pnxrgbfb", &option) && option &&
|
||||
!strcmp(option, "nocursor"))
|
||||
rgbfb_ops.fb_cursor = no_cursor;
|
||||
|
||||
info->node = -1;
|
||||
info->flags = FBINFO_FLAG_DEFAULT;
|
||||
info->fbops = &rgbfb_ops;
|
||||
info->fix = rgbfb_fix;
|
||||
info->var = rgbfb_var;
|
||||
info->screen_size = rgbfb_fix.smem_len;
|
||||
info->pseudo_palette = info->par;
|
||||
info->par = NULL;
|
||||
|
||||
ret = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (ret < 0)
|
||||
goto err1;
|
||||
|
||||
ret = register_framebuffer(info);
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
err1:
|
||||
pnx4008_free_dum_channel(channel_owned, pdev->id);
|
||||
err0:
|
||||
framebuffer_release(info);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver rgbfb_driver = {
|
||||
.driver = {
|
||||
.name = "pnx4008-rgbfb",
|
||||
},
|
||||
.probe = rgbfb_probe,
|
||||
.remove = rgbfb_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(rgbfb_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,861 +0,0 @@
|
|||
/*
|
||||
* drivers/video/pnx4008/sdum.c
|
||||
*
|
||||
* Display Update Master support
|
||||
*
|
||||
* Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
|
||||
* Vitaly Wool <vitalywool@gmail.com>
|
||||
* Based on Philips Semiconductors's code
|
||||
*
|
||||
* Copyrght (c) 2005-2006 MontaVista Software, Inc.
|
||||
* Copyright (c) 2005 Philips Semiconductors
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
* kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
#include "sdum.h"
|
||||
#include "fbcommon.h"
|
||||
#include "dum.h"
|
||||
|
||||
/* Framebuffers we have */
|
||||
|
||||
static struct pnx4008_fb_addr {
|
||||
int fb_type;
|
||||
long addr_offset;
|
||||
long fb_length;
|
||||
} fb_addr[] = {
|
||||
[0] = {
|
||||
FB_TYPE_YUV, 0, 0xB0000
|
||||
},
|
||||
[1] = {
|
||||
FB_TYPE_RGB, 0xB0000, 0x50000
|
||||
},
|
||||
};
|
||||
|
||||
static struct dum_data {
|
||||
u32 lcd_phys_start;
|
||||
u32 lcd_virt_start;
|
||||
u32 slave_phys_base;
|
||||
u32 *slave_virt_base;
|
||||
int fb_owning_channel[MAX_DUM_CHANNELS];
|
||||
struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS];
|
||||
} dum_data;
|
||||
|
||||
/* Different local helper functions */
|
||||
|
||||
static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup)
|
||||
{
|
||||
return (ch_setup->xmax - ch_setup->xmin + 1);
|
||||
}
|
||||
|
||||
static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup)
|
||||
{
|
||||
return (ch_setup->ymax - ch_setup->ymin + 1);
|
||||
}
|
||||
|
||||
static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup)
|
||||
{
|
||||
return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup));
|
||||
}
|
||||
|
||||
static u32 nof_bytes(struct dum_ch_setup *ch_setup)
|
||||
{
|
||||
u32 r = nof_pixels_dxy(ch_setup);
|
||||
switch (ch_setup->format) {
|
||||
case RGB888:
|
||||
case RGB666:
|
||||
r *= 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
r *= 2;
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static u32 build_command(int disp_no, u32 reg, u32 val)
|
||||
{
|
||||
return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) |
|
||||
(reg << 0));
|
||||
}
|
||||
|
||||
static u32 build_double_index(int disp_no, u32 val)
|
||||
{
|
||||
return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0));
|
||||
}
|
||||
|
||||
static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw)
|
||||
{
|
||||
dw->ymin = ch_setup->ymin;
|
||||
dw->ymax = ch_setup->ymax;
|
||||
dw->xmin_l = ch_setup->xmin & 0xFF;
|
||||
dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8;
|
||||
dw->xmax_l = ch_setup->xmax & 0xFF;
|
||||
dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8;
|
||||
}
|
||||
|
||||
static int put_channel(struct dumchannel chan)
|
||||
{
|
||||
int i = chan.channelnr;
|
||||
|
||||
if (i < 0 || i > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else {
|
||||
DUM_CH_MIN(i) = chan.dum_ch_min;
|
||||
DUM_CH_MAX(i) = chan.dum_ch_max;
|
||||
DUM_CH_CONF(i) = chan.dum_ch_conf;
|
||||
DUM_CH_CTRL(i) = chan.dum_ch_ctrl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear_channel(int channr)
|
||||
{
|
||||
struct dumchannel chan;
|
||||
|
||||
chan.channelnr = channr;
|
||||
chan.dum_ch_min = 0;
|
||||
chan.dum_ch_max = 0;
|
||||
chan.dum_ch_conf = 0;
|
||||
chan.dum_ch_ctrl = 0;
|
||||
|
||||
put_channel(chan);
|
||||
}
|
||||
|
||||
static int put_cmd_string(struct cmdstring cmds)
|
||||
{
|
||||
u16 *cmd_str_virtaddr;
|
||||
u32 *cmd_ptr0_virtaddr;
|
||||
u32 cmd_str_physaddr;
|
||||
|
||||
int i = cmds.channelnr;
|
||||
|
||||
if (i < 0 || i > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if ((cmd_ptr0_virtaddr =
|
||||
(int *)ioremap_nocache(DUM_COM_BASE,
|
||||
sizeof(int) * MAX_DUM_CHANNELS)) ==
|
||||
NULL)
|
||||
return -EIOREMAPFAILED;
|
||||
else {
|
||||
cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]);
|
||||
if ((cmd_str_virtaddr =
|
||||
(u16 *) ioremap_nocache(cmd_str_physaddr,
|
||||
sizeof(cmds))) == NULL) {
|
||||
iounmap(cmd_ptr0_virtaddr);
|
||||
return -EIOREMAPFAILED;
|
||||
} else {
|
||||
int t;
|
||||
for (t = 0; t < 8; t++)
|
||||
iowrite16(*((u16 *)&cmds.prestringlen + t),
|
||||
cmd_str_virtaddr + t);
|
||||
|
||||
for (t = 0; t < cmds.prestringlen / 2; t++)
|
||||
iowrite16(*((u16 *)&cmds.precmd + t),
|
||||
cmd_str_virtaddr + t + 8);
|
||||
|
||||
for (t = 0; t < cmds.poststringlen / 2; t++)
|
||||
iowrite16(*((u16 *)&cmds.postcmd + t),
|
||||
cmd_str_virtaddr + t + 8 +
|
||||
cmds.prestringlen / 2);
|
||||
|
||||
iounmap(cmd_ptr0_virtaddr);
|
||||
iounmap(cmd_str_virtaddr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup)
|
||||
{
|
||||
struct cmdstring cmds_c;
|
||||
struct cmdstring *cmds = &cmds_c;
|
||||
struct disp_window dw;
|
||||
int standard;
|
||||
u32 orientation = 0;
|
||||
struct dumchannel chan = { 0 };
|
||||
int ret;
|
||||
|
||||
if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) {
|
||||
standard = 0;
|
||||
|
||||
orientation = BIT(1); /* always set 9-bit-bus */
|
||||
if (ch_setup->xmirror)
|
||||
orientation |= BIT(4);
|
||||
if (ch_setup->ymirror)
|
||||
orientation |= BIT(3);
|
||||
if (ch_setup->rotate)
|
||||
orientation |= BIT(0);
|
||||
} else
|
||||
standard = 1;
|
||||
|
||||
cmds->channelnr = ch_no;
|
||||
|
||||
/* build command string header */
|
||||
if (standard) {
|
||||
cmds->prestringlen = 32;
|
||||
cmds->poststringlen = 0;
|
||||
} else {
|
||||
cmds->prestringlen = 48;
|
||||
cmds->poststringlen = 16;
|
||||
}
|
||||
|
||||
cmds->format =
|
||||
(u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format));
|
||||
cmds->reserved = 0x0;
|
||||
cmds->startaddr_low = (ch_setup->minadr & 0xFFFF);
|
||||
cmds->startaddr_high = (ch_setup->minadr >> 16);
|
||||
|
||||
if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0)
|
||||
&& (ch_setup->xmin == 0)
|
||||
&& (ch_setup->ymin == 0) && (ch_setup->xmax == 0)
|
||||
&& (ch_setup->ymax == 0)) {
|
||||
cmds->pixdatlen_low = 0;
|
||||
cmds->pixdatlen_high = 0;
|
||||
} else {
|
||||
u32 nbytes = nof_bytes(ch_setup);
|
||||
cmds->pixdatlen_low = (nbytes & 0xFFFF);
|
||||
cmds->pixdatlen_high = (nbytes >> 16);
|
||||
}
|
||||
|
||||
if (ch_setup->slave_trans)
|
||||
cmds->pixdatlen_high |= BIT(15);
|
||||
|
||||
/* build pre-string */
|
||||
build_disp_window(ch_setup, &dw);
|
||||
|
||||
if (standard) {
|
||||
cmds->precmd[0] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99);
|
||||
cmds->precmd[1] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
|
||||
dw.xmin_l);
|
||||
cmds->precmd[2] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
|
||||
dw.xmin_h);
|
||||
cmds->precmd[3] =
|
||||
build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
|
||||
cmds->precmd[4] =
|
||||
build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
|
||||
dw.xmax_l);
|
||||
cmds->precmd[5] =
|
||||
build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
|
||||
dw.xmax_h);
|
||||
cmds->precmd[6] =
|
||||
build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
|
||||
cmds->precmd[7] =
|
||||
build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
|
||||
} else {
|
||||
if (dw.xmin_l == ch_no)
|
||||
cmds->precmd[0] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
|
||||
0x99);
|
||||
else
|
||||
cmds->precmd[0] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
|
||||
ch_no);
|
||||
|
||||
cmds->precmd[1] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
|
||||
dw.xmin_l);
|
||||
cmds->precmd[2] =
|
||||
build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
|
||||
dw.xmin_h);
|
||||
cmds->precmd[3] =
|
||||
build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
|
||||
cmds->precmd[4] =
|
||||
build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
|
||||
dw.xmax_l);
|
||||
cmds->precmd[5] =
|
||||
build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
|
||||
dw.xmax_h);
|
||||
cmds->precmd[6] =
|
||||
build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
|
||||
cmds->precmd[7] =
|
||||
build_command(ch_setup->disp_no, DISP_1_REG, orientation);
|
||||
cmds->precmd[8] =
|
||||
build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
|
||||
cmds->precmd[9] =
|
||||
build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
|
||||
cmds->precmd[0xA] =
|
||||
build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
|
||||
cmds->precmd[0xB] =
|
||||
build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
|
||||
cmds->postcmd[0] =
|
||||
build_command(ch_setup->disp_no, DISP_1_REG, BIT(1));
|
||||
cmds->postcmd[1] =
|
||||
build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1);
|
||||
cmds->postcmd[2] =
|
||||
build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2);
|
||||
cmds->postcmd[3] =
|
||||
build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3);
|
||||
}
|
||||
|
||||
if ((ret = put_cmd_string(cmds_c)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
chan.channelnr = cmds->channelnr;
|
||||
chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr;
|
||||
chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr;
|
||||
chan.dum_ch_conf = 0x002;
|
||||
chan.dum_ch_ctrl = 0x04;
|
||||
|
||||
put_channel(chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer,
|
||||
u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h)
|
||||
{
|
||||
|
||||
struct dum_ch_setup k;
|
||||
int ret;
|
||||
|
||||
/* keep width & height within display area */
|
||||
if ((xpos + w) > DISP_MAX_X_SIZE)
|
||||
w = DISP_MAX_X_SIZE - xpos;
|
||||
|
||||
if ((ypos + h) > DISP_MAX_Y_SIZE)
|
||||
h = DISP_MAX_Y_SIZE - ypos;
|
||||
|
||||
/* assume 1 display only */
|
||||
k.disp_no = 0;
|
||||
k.xmin = xpos;
|
||||
k.ymin = ypos;
|
||||
k.xmax = xpos + (w - 1);
|
||||
k.ymax = ypos + (h - 1);
|
||||
|
||||
/* adjust min and max values if necessary */
|
||||
if (k.xmin > DISP_MAX_X_SIZE - 1)
|
||||
k.xmin = DISP_MAX_X_SIZE - 1;
|
||||
if (k.ymin > DISP_MAX_Y_SIZE - 1)
|
||||
k.ymin = DISP_MAX_Y_SIZE - 1;
|
||||
|
||||
if (k.xmax > DISP_MAX_X_SIZE - 1)
|
||||
k.xmax = DISP_MAX_X_SIZE - 1;
|
||||
if (k.ymax > DISP_MAX_Y_SIZE - 1)
|
||||
k.ymax = DISP_MAX_Y_SIZE - 1;
|
||||
|
||||
k.xmirror = 0;
|
||||
k.ymirror = 0;
|
||||
k.rotate = 0;
|
||||
k.minadr = (u32) frame_buffer;
|
||||
k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2));
|
||||
k.pad = PAD_1024;
|
||||
k.dirtybuffer = (u32) dirty_buffer;
|
||||
k.format = RGB888;
|
||||
k.hwdirty = 0;
|
||||
k.slave_trans = 0;
|
||||
|
||||
ret = dum_ch_setup(ch_no, &k);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lcd_reset(void)
|
||||
{
|
||||
u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE);
|
||||
|
||||
udelay(1);
|
||||
iowrite32(BIT(19), &dum_pio_base[2]);
|
||||
udelay(1);
|
||||
iowrite32(BIT(19), &dum_pio_base[1]);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static int dum_init(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
/* enable DUM clock */
|
||||
clk = clk_get(&pdev->dev, "dum_ck");
|
||||
if (IS_ERR(clk)) {
|
||||
printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n");
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
clk_set_rate(clk, 1);
|
||||
clk_put(clk);
|
||||
|
||||
DUM_CTRL = V_DUM_RESET;
|
||||
|
||||
/* set priority to "round-robin". All other params to "false" */
|
||||
DUM_CONF = BIT(9);
|
||||
|
||||
/* Display 1 */
|
||||
DUM_WTCFG1 = PNX4008_DUM_WT_CFG;
|
||||
DUM_RTCFG1 = PNX4008_DUM_RT_CFG;
|
||||
DUM_TCFG = PNX4008_DUM_T_CFG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dum_chan_init(void)
|
||||
{
|
||||
int i = 0, ch = 0;
|
||||
u32 *cmdptrs;
|
||||
u32 *cmdstrings;
|
||||
|
||||
DUM_COM_BASE =
|
||||
CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS;
|
||||
|
||||
if ((cmdptrs =
|
||||
(u32 *) ioremap_nocache(DUM_COM_BASE,
|
||||
sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL)
|
||||
return;
|
||||
|
||||
for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++)
|
||||
iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch,
|
||||
cmdptrs + ch);
|
||||
|
||||
for (ch = 0; ch < MAX_DUM_CHANNELS; ch++)
|
||||
clear_channel(ch);
|
||||
|
||||
/* Clear the cmdstrings */
|
||||
cmdstrings =
|
||||
(u32 *)ioremap_nocache(*cmdptrs,
|
||||
BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS);
|
||||
|
||||
if (!cmdstrings)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32);
|
||||
i++)
|
||||
iowrite32(0, cmdstrings + i);
|
||||
|
||||
iounmap((u32 *)cmdstrings);
|
||||
|
||||
out:
|
||||
iounmap((u32 *)cmdptrs);
|
||||
}
|
||||
|
||||
static void lcd_init(void)
|
||||
{
|
||||
lcd_reset();
|
||||
|
||||
DUM_OUTP_FORMAT1 = 0; /* RGB666 */
|
||||
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Interface exported to framebuffer drivers */
|
||||
|
||||
int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
|
||||
dma_addr_t *phys_addr, int *fb_length)
|
||||
{
|
||||
int i;
|
||||
int ret = -1;
|
||||
for (i = 0; i < ARRAY_SIZE(fb_addr); i++)
|
||||
if (fb_addr[i].fb_type == fb_type) {
|
||||
*virt_addr = (void *)(dum_data.lcd_virt_start +
|
||||
fb_addr[i].addr_offset);
|
||||
*phys_addr =
|
||||
dum_data.lcd_phys_start + fb_addr[i].addr_offset;
|
||||
*fb_length = fb_addr[i].fb_length;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_get_fb_addresses);
|
||||
|
||||
int pnx4008_alloc_dum_channel(int dev_id)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1))
|
||||
i++;
|
||||
|
||||
if (i == MAX_DUM_CHANNELS)
|
||||
return -ENORESOURCESLEFT;
|
||||
else {
|
||||
dum_data.fb_owning_channel[i] = dev_id;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_alloc_dum_channel);
|
||||
|
||||
int pnx4008_free_dum_channel(int channr, int dev_id)
|
||||
{
|
||||
if (channr < 0 || channr > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if (dum_data.fb_owning_channel[channr] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else {
|
||||
clear_channel(channr);
|
||||
dum_data.fb_owning_channel[channr] = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_free_dum_channel);
|
||||
|
||||
int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id)
|
||||
{
|
||||
int i = chan_uf.channelnr;
|
||||
int ret;
|
||||
|
||||
if (i < 0 || i > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if (dum_data.fb_owning_channel[i] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else if ((ret =
|
||||
display_open(chan_uf.channelnr, 0, chan_uf.dirty,
|
||||
chan_uf.source, chan_uf.y_offset,
|
||||
chan_uf.x_offset, chan_uf.height,
|
||||
chan_uf.width)) != 0)
|
||||
return ret;
|
||||
else {
|
||||
dum_data.chan_uf_store[i].dirty = chan_uf.dirty;
|
||||
dum_data.chan_uf_store[i].source = chan_uf.source;
|
||||
dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset;
|
||||
dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset;
|
||||
dum_data.chan_uf_store[i].width = chan_uf.width;
|
||||
dum_data.chan_uf_store[i].height = chan_uf.height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_put_dum_channel_uf);
|
||||
|
||||
int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id)
|
||||
{
|
||||
if (channr < 0 || channr > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if (dum_data.fb_owning_channel[channr] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else {
|
||||
if (val == CONF_SYNC_ON) {
|
||||
DUM_CH_CONF(channr) |= CONF_SYNCENABLE;
|
||||
DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK |
|
||||
DUM_CHANNEL_CFG_SYNC_MASK_SET;
|
||||
} else if (val == CONF_SYNC_OFF)
|
||||
DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_set_dum_channel_sync);
|
||||
|
||||
int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id)
|
||||
{
|
||||
if (channr < 0 || channr > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if (dum_data.fb_owning_channel[channr] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else {
|
||||
if (val == CONF_DIRTYDETECTION_ON)
|
||||
DUM_CH_CONF(channr) |= CONF_DIRTYENABLE;
|
||||
else if (val == CONF_DIRTYDETECTION_OFF)
|
||||
DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect);
|
||||
|
||||
#if 0 /* Functions not used currently, but likely to be used in future */
|
||||
|
||||
static int get_channel(struct dumchannel *p_chan)
|
||||
{
|
||||
int i = p_chan->channelnr;
|
||||
|
||||
if (i < 0 || i > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else {
|
||||
p_chan->dum_ch_min = DUM_CH_MIN(i);
|
||||
p_chan->dum_ch_max = DUM_CH_MAX(i);
|
||||
p_chan->dum_ch_conf = DUM_CH_CONF(i);
|
||||
p_chan->dum_ch_stat = DUM_CH_STAT(i);
|
||||
p_chan->dum_ch_ctrl = 0; /* WriteOnly control register */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id)
|
||||
{
|
||||
int i = p_chan_uf->channelnr;
|
||||
|
||||
if (i < 0 || i > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if (dum_data.fb_owning_channel[i] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else {
|
||||
p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty;
|
||||
p_chan_uf->source = dum_data.chan_uf_store[i].source;
|
||||
p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset;
|
||||
p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset;
|
||||
p_chan_uf->width = dum_data.chan_uf_store[i].width;
|
||||
p_chan_uf->height = dum_data.chan_uf_store[i].height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_get_dum_channel_uf);
|
||||
|
||||
int pnx4008_get_dum_channel_config(int channr, int dev_id)
|
||||
{
|
||||
int ret;
|
||||
struct dumchannel chan;
|
||||
|
||||
if (channr < 0 || channr > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
else if (dum_data.fb_owning_channel[channr] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else {
|
||||
chan.channelnr = channr;
|
||||
if ((ret = get_channel(&chan)) != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_get_dum_channel_config);
|
||||
|
||||
int pnx4008_force_update_dum_channel(int channr, int dev_id)
|
||||
{
|
||||
if (channr < 0 || channr > MAX_DUM_CHANNELS)
|
||||
return -EINVAL;
|
||||
|
||||
else if (dum_data.fb_owning_channel[channr] != dev_id)
|
||||
return -EFBNOTOWNER;
|
||||
else
|
||||
DUM_CH_CTRL(channr) = CTRL_SETDIRTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_force_update_dum_channel);
|
||||
|
||||
#endif
|
||||
|
||||
int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma,
|
||||
struct device *dev)
|
||||
{
|
||||
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
if (off < info->fix.smem_len) {
|
||||
vma->vm_pgoff += 1;
|
||||
return dma_mmap_writecombine(dev, vma,
|
||||
(void *)dum_data.lcd_virt_start,
|
||||
dum_data.lcd_phys_start,
|
||||
FB_DMA_SIZE);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_sdum_mmap);
|
||||
|
||||
int pnx4008_set_dum_exit_notification(int dev_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_DUM_CHANNELS; i++)
|
||||
if (dum_data.fb_owning_channel[i] == dev_id)
|
||||
return -ERESOURCESNOTFREED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pnx4008_set_dum_exit_notification);
|
||||
|
||||
/* Platform device driver for DUM */
|
||||
|
||||
static int sdum_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
int retval = 0;
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_get(0, "dum_ck");
|
||||
if (!IS_ERR(clk)) {
|
||||
clk_set_rate(clk, 0);
|
||||
clk_put(clk);
|
||||
} else
|
||||
retval = PTR_ERR(clk);
|
||||
|
||||
/* disable BAC */
|
||||
DUM_CTRL = V_BAC_DISABLE_IDLE;
|
||||
|
||||
/* LCD standby & turn off display */
|
||||
lcd_reset();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int sdum_resume(struct platform_device *pdev)
|
||||
{
|
||||
int retval = 0;
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_get(0, "dum_ck");
|
||||
if (!IS_ERR(clk)) {
|
||||
clk_set_rate(clk, 1);
|
||||
clk_put(clk);
|
||||
} else
|
||||
retval = PTR_ERR(clk);
|
||||
|
||||
/* wait for BAC disable */
|
||||
DUM_CTRL = V_BAC_DISABLE_TRIG;
|
||||
|
||||
while (DUM_CTRL & BAC_ENABLED)
|
||||
udelay(10);
|
||||
|
||||
/* re-init LCD */
|
||||
lcd_init();
|
||||
|
||||
/* enable BAC and reset MUX */
|
||||
DUM_CTRL = V_BAC_ENABLE;
|
||||
udelay(1);
|
||||
DUM_CTRL = V_MUX_RESET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit sdum_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0, i = 0;
|
||||
|
||||
/* map frame buffer */
|
||||
dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev,
|
||||
FB_DMA_SIZE,
|
||||
&dum_data.lcd_phys_start,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!dum_data.lcd_virt_start) {
|
||||
ret = -ENOMEM;
|
||||
goto out_3;
|
||||
}
|
||||
|
||||
/* map slave registers */
|
||||
dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE;
|
||||
dum_data.slave_virt_base =
|
||||
(u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32));
|
||||
|
||||
if (dum_data.slave_virt_base == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out_2;
|
||||
}
|
||||
|
||||
/* initialize DUM and LCD display */
|
||||
ret = dum_init(pdev);
|
||||
if (ret)
|
||||
goto out_1;
|
||||
|
||||
dum_chan_init();
|
||||
lcd_init();
|
||||
|
||||
DUM_CTRL = V_BAC_ENABLE;
|
||||
udelay(1);
|
||||
DUM_CTRL = V_MUX_RESET;
|
||||
|
||||
/* set decode address and sync clock divider */
|
||||
DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK;
|
||||
DUM_CLK_DIV = PNX4008_DUM_CLK_DIV;
|
||||
|
||||
for (i = 0; i < MAX_DUM_CHANNELS; i++)
|
||||
dum_data.fb_owning_channel[i] = -1;
|
||||
|
||||
/*setup wakeup interrupt */
|
||||
start_int_set_rising_edge(SE_DISP_SYNC_INT);
|
||||
start_int_ack(SE_DISP_SYNC_INT);
|
||||
start_int_umask(SE_DISP_SYNC_INT);
|
||||
|
||||
return 0;
|
||||
|
||||
out_1:
|
||||
iounmap((void *)dum_data.slave_virt_base);
|
||||
out_2:
|
||||
dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
|
||||
(void *)dum_data.lcd_virt_start,
|
||||
dum_data.lcd_phys_start);
|
||||
out_3:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sdum_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
start_int_mask(SE_DISP_SYNC_INT);
|
||||
|
||||
clk = clk_get(0, "dum_ck");
|
||||
if (!IS_ERR(clk)) {
|
||||
clk_set_rate(clk, 0);
|
||||
clk_put(clk);
|
||||
}
|
||||
|
||||
iounmap((void *)dum_data.slave_virt_base);
|
||||
|
||||
dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
|
||||
(void *)dum_data.lcd_virt_start,
|
||||
dum_data.lcd_phys_start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sdum_driver = {
|
||||
.driver = {
|
||||
.name = "pnx4008-sdum",
|
||||
},
|
||||
.probe = sdum_probe,
|
||||
.remove = sdum_remove,
|
||||
.suspend = sdum_suspend,
|
||||
.resume = sdum_resume,
|
||||
};
|
||||
|
||||
module_platform_driver(sdum_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Philips Semiconductors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
#define MAX_DUM_CHANNELS 64
|
||||
|
||||
#define RGB_MEM_WINDOW(x) (0x10000000 + (x)*0x00100000)
|
||||
|
||||
#define QCIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x30000: -1)
|
||||
#define CIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x60000: -1)
|
||||
|
||||
#define CTRL_SETDIRTY (0x00000001)
|
||||
#define CONF_DIRTYENABLE (0x00000020)
|
||||
#define CONF_SYNCENABLE (0x00000004)
|
||||
|
||||
#define DIRTY_ENABLED(conf) ((conf) & 0x0020)
|
||||
#define SYNC_ENABLED(conf) ((conf) & 0x0004)
|
||||
|
||||
/* Display 1 & 2 Write Timing Configuration */
|
||||
#define PNX4008_DUM_WT_CFG 0x00372000
|
||||
|
||||
/* Display 1 & 2 Read Timing Configuration */
|
||||
#define PNX4008_DUM_RT_CFG 0x00003A47
|
||||
|
||||
/* DUM Transit State Timing Configuration */
|
||||
#define PNX4008_DUM_T_CFG 0x1D /* 29 HCLK cycles */
|
||||
|
||||
/* DUM Sync count clock divider */
|
||||
#define PNX4008_DUM_CLK_DIV 0x02DD
|
||||
|
||||
/* Memory size for framebuffer, allocated through dma_alloc_writecombine().
|
||||
* Must be PAGE aligned
|
||||
*/
|
||||
#define FB_DMA_SIZE (PAGE_ALIGN(SZ_1M + PAGE_SIZE))
|
||||
|
||||
#define OFFSET_RGBBUFFER (0xB0000)
|
||||
#define OFFSET_YUVBUFFER (0x00000)
|
||||
|
||||
#define YUVBUFFER (lcd_video_start + OFFSET_YUVBUFFER)
|
||||
#define RGBBUFFER (lcd_video_start + OFFSET_RGBBUFFER)
|
||||
|
||||
#define CMDSTRING_BASEADDR (0x00C000) /* iram */
|
||||
#define BYTES_PER_CMDSTRING (0x80)
|
||||
#define NR_OF_CMDSTRINGS (64)
|
||||
|
||||
#define MAX_NR_PRESTRINGS (0x40)
|
||||
#define MAX_NR_POSTSTRINGS (0x40)
|
||||
|
||||
/* various mask definitions */
|
||||
#define DUM_CLK_ENABLE 0x01
|
||||
#define DUM_CLK_DISABLE 0
|
||||
#define DUM_DECODE_MASK 0x1FFFFFFF
|
||||
#define DUM_CHANNEL_CFG_MASK 0x01FF
|
||||
#define DUM_CHANNEL_CFG_SYNC_MASK 0xFFFE00FF
|
||||
#define DUM_CHANNEL_CFG_SYNC_MASK_SET 0x0CA00
|
||||
|
||||
#define SDUM_RETURNVAL_BASE (0x500)
|
||||
|
||||
#define CONF_SYNC_OFF (0x602)
|
||||
#define CONF_SYNC_ON (0x603)
|
||||
|
||||
#define CONF_DIRTYDETECTION_OFF (0x600)
|
||||
#define CONF_DIRTYDETECTION_ON (0x601)
|
||||
|
||||
struct dumchannel_uf {
|
||||
int channelnr;
|
||||
u32 *dirty;
|
||||
u32 *source;
|
||||
u32 x_offset;
|
||||
u32 y_offset;
|
||||
u32 width;
|
||||
u32 height;
|
||||
};
|
||||
|
||||
enum {
|
||||
FB_TYPE_YUV,
|
||||
FB_TYPE_RGB
|
||||
};
|
||||
|
||||
struct cmdstring {
|
||||
int channelnr;
|
||||
uint16_t prestringlen;
|
||||
uint16_t poststringlen;
|
||||
uint16_t format;
|
||||
uint16_t reserved;
|
||||
uint16_t startaddr_low;
|
||||
uint16_t startaddr_high;
|
||||
uint16_t pixdatlen_low;
|
||||
uint16_t pixdatlen_high;
|
||||
u32 precmd[MAX_NR_PRESTRINGS];
|
||||
u32 postcmd[MAX_NR_POSTSTRINGS];
|
||||
|
||||
};
|
||||
|
||||
struct dumchannel {
|
||||
int channelnr;
|
||||
int dum_ch_min;
|
||||
int dum_ch_max;
|
||||
int dum_ch_conf;
|
||||
int dum_ch_stat;
|
||||
int dum_ch_ctrl;
|
||||
};
|
||||
|
||||
int pnx4008_alloc_dum_channel(int dev_id);
|
||||
int pnx4008_free_dum_channel(int channr, int dev_id);
|
||||
|
||||
int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id);
|
||||
int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id);
|
||||
|
||||
int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id);
|
||||
int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id);
|
||||
|
||||
int pnx4008_force_dum_update_channel(int channr, int dev_id);
|
||||
|
||||
int pnx4008_get_dum_channel_config(int channr, int dev_id);
|
||||
|
||||
int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev);
|
||||
int pnx4008_set_dum_exit_notification(int dev_id);
|
||||
|
||||
int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
|
||||
dma_addr_t * phys_addr, int *fb_length);
|
||||
|
|
@ -1034,6 +1034,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
|
|||
if (status) {
|
||||
dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
|
||||
__func__, status);
|
||||
retval = -ENOMEM;
|
||||
goto err_close_device;
|
||||
}
|
||||
dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
|
||||
|
|
@ -1046,6 +1047,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
|
|||
dev_err(&dev->core,
|
||||
"%s: lv1_gpu_context_allocate failed: %d\n", __func__,
|
||||
status);
|
||||
retval = -ENOMEM;
|
||||
goto err_gpu_memory_free;
|
||||
}
|
||||
|
||||
|
|
@ -1053,6 +1055,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
|
|||
dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
|
||||
if (!dinfo) {
|
||||
dev_err(&dev->core, "%s: ioremap failed\n", __func__);
|
||||
retval = -ENOMEM;
|
||||
goto err_gpu_context_free;
|
||||
}
|
||||
|
||||
|
|
@ -1121,8 +1124,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
|
|||
}
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
|
||||
if (!info)
|
||||
if (!info) {
|
||||
retval = -ENOMEM;
|
||||
goto err_context_fb_close;
|
||||
}
|
||||
|
||||
par = info->par;
|
||||
par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <video/samsung_fimd.h>
|
||||
#include <mach/map.h>
|
||||
#include <plat/regs-fb-v4.h>
|
||||
#include <plat/fb.h>
|
||||
|
||||
/* This driver will export a number of framebuffer interfaces depending
|
||||
|
|
@ -1398,35 +1398,28 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
|
|||
|
||||
spin_lock_init(&sfb->slock);
|
||||
|
||||
sfb->bus_clk = clk_get(dev, "lcd");
|
||||
sfb->bus_clk = devm_clk_get(dev, "lcd");
|
||||
if (IS_ERR(sfb->bus_clk)) {
|
||||
dev_err(dev, "failed to get bus clock\n");
|
||||
ret = PTR_ERR(sfb->bus_clk);
|
||||
goto err_sfb;
|
||||
return PTR_ERR(sfb->bus_clk);
|
||||
}
|
||||
|
||||
clk_enable(sfb->bus_clk);
|
||||
clk_prepare_enable(sfb->bus_clk);
|
||||
|
||||
if (!sfb->variant.has_clksel) {
|
||||
sfb->lcd_clk = clk_get(dev, "sclk_fimd");
|
||||
sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd");
|
||||
if (IS_ERR(sfb->lcd_clk)) {
|
||||
dev_err(dev, "failed to get lcd clock\n");
|
||||
ret = PTR_ERR(sfb->lcd_clk);
|
||||
goto err_bus_clk;
|
||||
}
|
||||
|
||||
clk_enable(sfb->lcd_clk);
|
||||
clk_prepare_enable(sfb->lcd_clk);
|
||||
}
|
||||
|
||||
pm_runtime_enable(sfb->dev);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "failed to find registers\n");
|
||||
ret = -ENOENT;
|
||||
goto err_lcd_clk;
|
||||
}
|
||||
|
||||
sfb->regs = devm_request_and_ioremap(dev, res);
|
||||
if (!sfb->regs) {
|
||||
dev_err(dev, "failed to map registers\n");
|
||||
|
|
@ -1510,16 +1503,12 @@ err_pm_runtime:
|
|||
err_lcd_clk:
|
||||
pm_runtime_disable(sfb->dev);
|
||||
|
||||
if (!sfb->variant.has_clksel) {
|
||||
clk_disable(sfb->lcd_clk);
|
||||
clk_put(sfb->lcd_clk);
|
||||
}
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_disable_unprepare(sfb->lcd_clk);
|
||||
|
||||
err_bus_clk:
|
||||
clk_disable(sfb->bus_clk);
|
||||
clk_put(sfb->bus_clk);
|
||||
clk_disable_unprepare(sfb->bus_clk);
|
||||
|
||||
err_sfb:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1541,13 +1530,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
|
|||
if (sfb->windows[win])
|
||||
s3c_fb_release_win(sfb, sfb->windows[win]);
|
||||
|
||||
if (!sfb->variant.has_clksel) {
|
||||
clk_disable(sfb->lcd_clk);
|
||||
clk_put(sfb->lcd_clk);
|
||||
}
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_disable_unprepare(sfb->lcd_clk);
|
||||
|
||||
clk_disable(sfb->bus_clk);
|
||||
clk_put(sfb->bus_clk);
|
||||
clk_disable_unprepare(sfb->bus_clk);
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
pm_runtime_disable(sfb->dev);
|
||||
|
|
@ -1575,9 +1561,9 @@ static int s3c_fb_suspend(struct device *dev)
|
|||
}
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_disable(sfb->lcd_clk);
|
||||
clk_disable_unprepare(sfb->lcd_clk);
|
||||
|
||||
clk_disable(sfb->bus_clk);
|
||||
clk_disable_unprepare(sfb->bus_clk);
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
|
|
@ -1595,10 +1581,10 @@ static int s3c_fb_resume(struct device *dev)
|
|||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
clk_enable(sfb->bus_clk);
|
||||
clk_prepare_enable(sfb->bus_clk);
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_enable(sfb->lcd_clk);
|
||||
clk_prepare_enable(sfb->lcd_clk);
|
||||
|
||||
/* setup gpio and output polarity controls */
|
||||
pd->setup_gpio();
|
||||
|
|
@ -1654,9 +1640,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
|
|||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_disable(sfb->lcd_clk);
|
||||
clk_disable_unprepare(sfb->lcd_clk);
|
||||
|
||||
clk_disable(sfb->bus_clk);
|
||||
clk_disable_unprepare(sfb->bus_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1667,10 +1653,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
|
|||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb_platdata *pd = sfb->pdata;
|
||||
|
||||
clk_enable(sfb->bus_clk);
|
||||
clk_prepare_enable(sfb->bus_clk);
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_enable(sfb->lcd_clk);
|
||||
clk_prepare_enable(sfb->lcd_clk);
|
||||
|
||||
/* setup gpio and output polarity controls */
|
||||
pd->setup_gpio();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
* Driver based on skeletonfb.c, sa1100fb.c and others.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
|
|
@ -48,7 +50,11 @@ static int debug = 1;
|
|||
static int debug;
|
||||
#endif
|
||||
|
||||
#define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg);
|
||||
#define dprintk(msg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
pr_debug(msg); \
|
||||
} while (0)
|
||||
|
||||
/* useful functions */
|
||||
|
||||
|
|
@ -598,11 +604,11 @@ static int s3c2410fb_debug_store(struct device *dev,
|
|||
if (strnicmp(buf, "on", 2) == 0 ||
|
||||
strnicmp(buf, "1", 1) == 0) {
|
||||
debug = 1;
|
||||
printk(KERN_DEBUG "s3c2410fb: Debug On");
|
||||
dev_dbg(dev, "s3c2410fb: Debug On");
|
||||
} else if (strnicmp(buf, "off", 3) == 0 ||
|
||||
strnicmp(buf, "0", 1) == 0) {
|
||||
debug = 0;
|
||||
printk(KERN_DEBUG "s3c2410fb: Debug Off");
|
||||
dev_dbg(dev, "s3c2410fb: Debug Off");
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -921,7 +927,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
|
||||
info->clk = clk_get(NULL, "lcd");
|
||||
if (IS_ERR(info->clk)) {
|
||||
printk(KERN_ERR "failed to get lcd clock source\n");
|
||||
dev_err(&pdev->dev, "failed to get lcd clock source\n");
|
||||
ret = PTR_ERR(info->clk);
|
||||
goto release_irq;
|
||||
}
|
||||
|
|
@ -929,7 +935,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
clk_enable(info->clk);
|
||||
dprintk("got and enabled clock\n");
|
||||
|
||||
usleep_range(1000, 1000);
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
info->clk_rate = clk_get_rate(info->clk);
|
||||
|
||||
|
|
@ -947,7 +953,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
/* Initialize video memory */
|
||||
ret = s3c2410fb_map_video_memory(fbinfo);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
|
||||
dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
|
||||
ret = -ENOMEM;
|
||||
goto release_clock;
|
||||
}
|
||||
|
|
@ -970,7 +976,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
|
||||
ret = register_framebuffer(fbinfo);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "Failed to register framebuffer device: %d\n",
|
||||
dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n",
|
||||
ret);
|
||||
goto free_cpufreq;
|
||||
}
|
||||
|
|
@ -978,9 +984,9 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
/* create device files */
|
||||
ret = device_create_file(&pdev->dev, &dev_attr_debug);
|
||||
if (ret)
|
||||
printk(KERN_ERR "failed to add debug attribute\n");
|
||||
dev_err(&pdev->dev, "failed to add debug attribute\n");
|
||||
|
||||
printk(KERN_INFO "fb%d: %s frame buffer device\n",
|
||||
dev_info(&pdev->dev, "fb%d: %s frame buffer device\n",
|
||||
fbinfo->node, fbinfo->fix.id);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1028,7 +1034,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
|
|||
s3c2410fb_cpufreq_deregister(info);
|
||||
|
||||
s3c2410fb_lcd_enable(info, 0);
|
||||
usleep_range(1000, 1000);
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
s3c2410fb_unmap_video_memory(fbinfo);
|
||||
|
||||
|
|
@ -1065,7 +1071,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
|
|||
* the LCD DMA engine is not going to get back on the bus
|
||||
* before the clock goes off again (bjd) */
|
||||
|
||||
usleep_range(1000, 1000);
|
||||
usleep_range(1000, 1100);
|
||||
clk_disable(info->clk);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1077,7 +1083,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
|
|||
struct s3c2410fb_info *info = fbinfo->par;
|
||||
|
||||
clk_enable(info->clk);
|
||||
usleep_range(1000, 1000);
|
||||
usleep_range(1000, 1100);
|
||||
|
||||
s3c2410fb_init_registers(fbinfo);
|
||||
|
||||
|
|
@ -1134,8 +1140,8 @@ static void __exit s3c2410fb_cleanup(void)
|
|||
module_init(s3c2410fb_init);
|
||||
module_exit(s3c2410fb_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Arnaud Patard <[email protected]>, "
|
||||
"Ben Dooks <[email protected]>");
|
||||
MODULE_AUTHOR("Arnaud Patard <[email protected]>");
|
||||
MODULE_AUTHOR("Ben Dooks <[email protected]>");
|
||||
MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:s3c2410-lcd");
|
||||
|
|
|
|||
|
|
@ -2266,8 +2266,10 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
|
|||
lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
|
||||
info->var.yres_virtual = info->fix.smem_len/lpitch;
|
||||
|
||||
if (info->var.yres_virtual < info->var.yres)
|
||||
if (info->var.yres_virtual < info->var.yres) {
|
||||
err = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FB_SAVAGE_ACCEL)
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
|
|||
}
|
||||
#endif
|
||||
|
||||
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
|
||||
if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {
|
||||
printk(KERN_ERR "Could not find mode %x\n", ModeNo);
|
||||
return 65000;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,10 @@ static int __devinit gfb_probe(struct platform_device *op)
|
|||
|
||||
gp->fb_base = of_ioremap(&op->resource[6], 0,
|
||||
gp->fb_size, "gfb fb");
|
||||
if (!gp->fb_base)
|
||||
if (!gp->fb_base) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_fb;
|
||||
}
|
||||
|
||||
err = gfb_set_fbinfo(gp);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -181,8 +181,10 @@ static int __devinit s3d_pci_register(struct pci_dev *pdev,
|
|||
sp->fb_size = info->fix.line_length * sp->height;
|
||||
|
||||
sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size);
|
||||
if (!sp->fb_base)
|
||||
if (!sp->fb_base) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_pci;
|
||||
}
|
||||
|
||||
err = s3d_set_fbinfo(sp);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -298,8 +298,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
|
|||
goto err_release_fb;
|
||||
}
|
||||
ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
|
||||
if (!ep->ramdac)
|
||||
if (!ep->ramdac) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_pci1;
|
||||
}
|
||||
|
||||
ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
|
||||
ep->fb8_0_off -= ep->fb_base_reg;
|
||||
|
|
@ -343,8 +345,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
|
|||
ep->fb_size = info->fix.line_length * ep->height;
|
||||
|
||||
ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
|
||||
if (!ep->fb_base)
|
||||
if (!ep->fb_base) {
|
||||
err = -ENOMEM;
|
||||
goto err_release_pci0;
|
||||
}
|
||||
|
||||
err = e3d_set_fbinfo(ep);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -646,7 +646,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
|
|||
result = fb_sys_write(info, buf, count, ppos);
|
||||
|
||||
if (result > 0) {
|
||||
int start = max((int)(offset / info->fix.line_length) - 1, 0);
|
||||
int start = max((int)(offset / info->fix.line_length), 0);
|
||||
int lines = min((u32)((result / info->fix.line_length) + 1),
|
||||
(u32)info->var.yres);
|
||||
|
||||
|
|
|
|||
|
|
@ -659,6 +659,8 @@ static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
|
|||
task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
|
||||
task->t.buf_len = EDID_LENGTH;
|
||||
task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
if (!task->buf)
|
||||
return -ENOMEM;
|
||||
|
||||
err = uvesafb_exec(task);
|
||||
|
||||
|
|
|
|||
|
|
@ -1167,8 +1167,7 @@ void vmlfb_unregister_subsys(struct vml_sys *sys)
|
|||
list_for_each_entry_safe(entry, next, &global_has_mode, head) {
|
||||
printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");
|
||||
vmlfb_disable_pipe(entry);
|
||||
list_del(&entry->head);
|
||||
list_add_tail(&entry->head, &global_no_mode);
|
||||
list_move_tail(&entry->head, &global_no_mode);
|
||||
}
|
||||
mutex_unlock(&vml_mutex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/via-core.h>
|
||||
#include <asm/olpc.h>
|
||||
#include "via_clock.h"
|
||||
#include "global.h"
|
||||
#include "debug.h"
|
||||
|
|
@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config)
|
|||
printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
|
||||
}
|
||||
|
||||
static void noop_set_clock_state(u8 state)
|
||||
{
|
||||
}
|
||||
|
||||
void via_clock_init(struct via_clock *clock, int gfx_chip)
|
||||
{
|
||||
switch (gfx_chip) {
|
||||
|
|
@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
|
|||
break;
|
||||
|
||||
}
|
||||
|
||||
if (machine_is_olpc()) {
|
||||
/* The OLPC XO-1.5 cannot suspend/resume reliably if the
|
||||
* IGA1/IGA2 clocks are set as on or off (memory rot
|
||||
* occasionally happens during suspend under such
|
||||
* configurations).
|
||||
*
|
||||
* The only known stable scenario is to leave this bits as-is,
|
||||
* which in their default states are documented to enable the
|
||||
* clock only when it is needed.
|
||||
*/
|
||||
clock->set_primary_clock_state = noop_set_clock_state;
|
||||
clock->set_secondary_clock_state = noop_set_clock_state;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue