1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-24 18:31:53 +02:00

jz4740_fb: Disable lcd when it's blanked.

This commit is contained in:
Lars-Peter Clausen 2009-12-07 08:48:19 +01:00
parent bcdf5a8733
commit 6f76581889
3 changed files with 135 additions and 15 deletions

View File

@ -55,12 +55,14 @@ static int gpm940b0_set_power(struct lcd_device *lcd, int power)
switch (power) {
case FB_BLANK_UNBLANK:
mdelay(20);
gpm940b0->enabled = 1;
gpm940b0_power_enable(gpm940b0);
break;
default:
gpm940b0->enabled = 0;
gpm940b0_power_disable(gpm940b0);
mdelay(20);
break;
}
return 0;

View File

@ -21,6 +21,9 @@
#include <linux/jz4740_fb.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/mach-jz4740/gpio.h>
#define JZ_REG_LCD_CFG 0x00
#define JZ_REG_LCD_VSYNC 0x04
@ -98,6 +101,8 @@
#define JZ_LCD_SYNC_MASK 0x3ff
#define JZ_LCD_STATE_DISABLED BIT(0)
struct jzfb_framedesc {
uint32_t next;
uint32_t addr;
@ -120,7 +125,11 @@ struct jzfb {
dma_addr_t vidmem_phys;
struct jzfb_framedesc *framedesc;
struct clk *ldclk;
struct clk *lpclk;
uint32_t pseudo_palette[16];
unsigned is_enabled:1;
};
static struct fb_fix_screeninfo jzfb_fix __devinitdata = {
@ -133,8 +142,23 @@ static struct fb_fix_screeninfo jzfb_fix __devinitdata = {
.accel = FB_ACCEL_NONE,
};
const static struct jz_gpio_bulk_request jz_lcd_pins[] = {
JZ_GPIO_BULK_PIN(LCD_PCLK),
JZ_GPIO_BULK_PIN(LCD_HSYNC),
JZ_GPIO_BULK_PIN(LCD_VSYNC),
JZ_GPIO_BULK_PIN(LCD_DATA0),
JZ_GPIO_BULK_PIN(LCD_DATA1),
JZ_GPIO_BULK_PIN(LCD_DATA2),
JZ_GPIO_BULK_PIN(LCD_DATA3),
JZ_GPIO_BULK_PIN(LCD_DATA4),
JZ_GPIO_BULK_PIN(LCD_DATA5),
JZ_GPIO_BULK_PIN(LCD_DATA6),
JZ_GPIO_BULK_PIN(LCD_DATA7),
};
int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
unsigned transp, struct fb_info *fb)
unsigned transp, struct fb_info *fb)
{
((uint32_t*)fb->pseudo_palette)[regno] = red << 16 | green << 8 | blue;
return 0;
@ -142,14 +166,14 @@ int jzfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
static int jzfb_get_controller_bpp(struct jzfb *jzfb)
{
switch(jzfb->pdata->bpp) {
case 18:
case 24:
return 32;
break;
default:
return jzfb->pdata->bpp;
}
switch(jzfb->pdata->bpp) {
case 18:
case 24:
return 32;
break;
default:
return jzfb->pdata->bpp;
}
}
static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
@ -159,7 +183,7 @@ static int jzfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
int i;
if (fb->var.bits_per_pixel != jzfb_get_controller_bpp(jzfb) &&
fb->var.bits_per_pixel != jzfb->pdata->bpp)
fb->var.bits_per_pixel != jzfb->pdata->bpp)
return -EINVAL;
for (i = 0; i < jzfb->pdata->num_modes; ++i, ++mode) {
@ -278,6 +302,50 @@ static int jzfb_set_par(struct fb_info *info)
return 0;
}
static int jzfb_blank(int blank_mode, struct fb_info *info)
{
struct jzfb* jzfb = info->par;
uint32_t ctrl = readl(jzfb->base + JZ_REG_LCD_CTRL);
switch (blank_mode) {
case FB_BLANK_UNBLANK:
if (jzfb->is_enabled)
return 0;
jz_gpio_bulk_resume(jz_lcd_pins, ARRAY_SIZE(jz_lcd_pins));
clk_enable(jzfb->ldclk);
clk_enable(jzfb->lpclk);
writel(0, jzfb->base + JZ_REG_LCD_STATE);
writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
ctrl |= JZ_LCD_CTRL_ENABLE;
ctrl &= ~JZ_LCD_CTRL_DISABLE;
writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
jzfb->is_enabled = 1;
break;
default:
if (!jzfb->is_enabled)
return 0;
ctrl |= JZ_LCD_CTRL_DISABLE;
writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
do {
ctrl = readl(jzfb->base + JZ_REG_LCD_STATE);
} while (!(ctrl & JZ_LCD_STATE_DISABLED));
clk_disable(jzfb->lpclk);
clk_disable(jzfb->ldclk);
jz_gpio_bulk_suspend(jz_lcd_pins, ARRAY_SIZE(jz_lcd_pins));
jzfb->is_enabled = 0;
break;
}
return 0;
}
static int jzfb_alloc_vidmem(struct jzfb *jzfb)
{
@ -299,16 +367,16 @@ static int jzfb_alloc_vidmem(struct jzfb *jzfb)
jzfb->devmem_size = devmem_size;
jzfb->devmem = dma_alloc_coherent(&jzfb->pdev->dev,
PAGE_ALIGN(devmem_size),
&jzfb->devmem_phys, GFP_KERNEL);
PAGE_ALIGN(devmem_size),
&jzfb->devmem_phys, GFP_KERNEL);
if (!jzfb->devmem) {
return -ENOMEM;
}
for (page = jzfb->vidmem;
page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
page += PAGE_SIZE) {
page < jzfb->vidmem + PAGE_ALIGN(jzfb->vidmem_size);
page += PAGE_SIZE) {
SetPageReserved(virt_to_page(page));
}
@ -339,7 +407,7 @@ static struct fb_ops jzfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = jzfb_check_var,
.fb_set_par = jzfb_set_par,
/* .fb_blank = jzfb_blank,*/
.fb_blank = jzfb_blank,
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
@ -390,6 +458,24 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
jzfb->pdata = pdata;
jzfb->mem = mem;
jzfb->ldclk = clk_get(&pdev->dev, "lcd");
jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk");
jzfb->is_enabled = 1;
if (IS_ERR(jzfb->ldclk)) {
ret = PTR_ERR(jzfb->ldclk);
dev_err(&pdev->dev, "Faild to get device clock: %d\n", ret);
goto err_framebuffer_release;
}
if (IS_ERR(jzfb->lpclk)) {
ret = PTR_ERR(jzfb->ldclk);
dev_err(&pdev->dev, "Faild to get pixel clock: %d\n", ret);
goto err_framebuffer_release;
}
jzfb->base = ioremap(mem->start, resource_size(mem));
if (!jzfb->base) {
@ -428,6 +514,8 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
jzfb_set_par(fb);
writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
jz_gpio_bulk_request(jz_lcd_pins, ARRAY_SIZE(jz_lcd_pins));
ret = register_framebuffer(fb);
if (ret) {
dev_err(&pdev->dev, "Failed to register framebuffer: %d\n", ret);
@ -450,6 +538,7 @@ static int __devexit jzfb_remove(struct platform_device *pdev)
{
struct jzfb *jzfb = platform_get_drvdata(pdev);
jz_gpio_bulk_free(jz_lcd_pins, ARRAY_SIZE(jz_lcd_pins));
iounmap(jzfb->base);
release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
jzfb_free_devmem(jzfb);

View File

@ -0,0 +1,29 @@
--- a/drivers/video/fbmem.c 2009-10-05 13:18:19.000000000 +0200
+++ b/drivers/video/fbmem.c 2009-12-03 05:08:15.000000000 +0100
@@ -997,12 +997,12 @@
int
fb_blank(struct fb_info *info, int blank)
{
- int ret = -EINVAL;
+ int ret = 0;
if (blank > FB_BLANK_POWERDOWN)
blank = FB_BLANK_POWERDOWN;
- if (info->fbops->fb_blank)
+ if (info->fbops->fb_blank && blank == FB_BLANK_UNBLANK)
ret = info->fbops->fb_blank(blank, info);
if (!ret) {
@@ -1013,6 +1013,10 @@
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
}
+ if (info->fbops->fb_blank && blank != FB_BLANK_UNBLANK)
+ ret = info->fbops->fb_blank(blank, info);
+
+
return ret;
}