diff options
Diffstat (limited to 'packages/linux/linux-2.6.18/lcdc-wait-for-vsync.patch')
-rw-r--r-- | packages/linux/linux-2.6.18/lcdc-wait-for-vsync.patch | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/packages/linux/linux-2.6.18/lcdc-wait-for-vsync.patch b/packages/linux/linux-2.6.18/lcdc-wait-for-vsync.patch new file mode 100644 index 0000000000..7c1cd663cb --- /dev/null +++ b/packages/linux/linux-2.6.18/lcdc-wait-for-vsync.patch @@ -0,0 +1,152 @@ +--- + drivers/video/sidsafb.c | 68 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 61 insertions(+), 7 deletions(-) + +Index: linux-2.6.18-rc6-mm1/drivers/video/sidsafb.c +=================================================================== +--- linux-2.6.18-rc6-mm1.orig/drivers/video/sidsafb.c 2006-09-11 13:03:46.000000000 +0200 ++++ linux-2.6.18-rc6-mm1/drivers/video/sidsafb.c 2006-09-11 13:38:52.000000000 +0200 +@@ -11,6 +11,7 @@ + + #include <linux/config.h> + #include <linux/clk.h> ++#include <linux/completion.h> + #include <linux/kernel.h> + #include <linux/dma-mapping.h> + #include <linux/interrupt.h> +@@ -38,7 +39,8 @@ struct sidsafb_info { + struct fb_info * info; + void __iomem * regs; + unsigned long irq_base; +- wait_queue_head_t vsync_wait; ++ int wait_for_vsync; ++ struct completion vsync_complete; + unsigned int guard_time; + struct clk *hclk; + struct clk *pixclk; +@@ -169,6 +171,38 @@ static struct fb_fix_screeninfo sidsafb_ + .accel = FB_ACCEL_NONE, + }; + ++/* ++ * Let the user decide whether FBIOPAN_DISPLAY waits for the next ++ * vsync or not. ++ */ ++static ssize_t ++vsync_pan_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sidsafb_info *sinfo = info->par; ++ ++ return sprintf(buf, "%d\n", sinfo->wait_for_vsync); ++} ++ ++static ssize_t ++vsync_pan_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *info = dev_get_drvdata(dev); ++ struct sidsafb_info *sinfo = info->par; ++ unsigned long val; ++ ++ val = simple_strtoul(buf, NULL, 0); ++ if (val) ++ sinfo->wait_for_vsync = 1; ++ else ++ sinfo->wait_for_vsync = 0; ++ ++ return count; ++} ++ ++static DEVICE_ATTR(vsync_pan, 0644, vsync_pan_show, vsync_pan_store); ++ + static void sidsafb_update_dma(struct fb_info *info, + struct fb_var_screeninfo *var) + { +@@ -513,10 +547,25 @@ static int sidsafb_setcolreg(unsigned in + static int sidsafb_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info) + { ++ struct sidsafb_info *sinfo = info->par; ++ + pr_debug("sidsafb_pan_display\n"); + + sidsafb_update_dma(info, var); + ++ if (sinfo->wait_for_vsync) { ++ spin_lock_irq(&sinfo->lock); ++ lcdc_writel(sinfo, LCD_ICR, LCDC_BIT(LCD_ICR_EOFIC)); ++ lcdc_writel(sinfo, LCD_IER, LCDC_BIT(LCD_IER_EOFIE)); ++ init_completion(&sinfo->vsync_complete); ++ lcdc_readl(sinfo, LCD_IMR); ++ spin_unlock_irq(&sinfo->lock); ++ ++ wait_for_completion(&sinfo->vsync_complete); ++ ++ lcdc_writel(sinfo, LCD_IDR, LCDC_BIT(LCD_IDR_EOFID)); ++ } ++ + return 0; + } + +@@ -545,7 +594,7 @@ static irqreturn_t sidsafb_interrupt(int + + lcdc_writel(sinfo, LCD_ICR, LCDC_BIT(LCD_ICR_EOFIC)); + status &= ~LCDC_BIT(LCD_ISR_EOFIS); +- wake_up(&sinfo->vsync_wait); ++ complete(&sinfo->vsync_complete); + } + + if (status) { +@@ -600,8 +649,6 @@ static int __devinit sidsafb_set_fbinfo( + info->fbops = &sidsafb_ops; + info->pseudo_palette = sinfo->pseudo_palette; + +- init_waitqueue_head(&sinfo->vsync_wait); +- + return 0; + } + +@@ -700,18 +747,21 @@ static int __devinit sidsafb_probe(struc + goto unregister_irqs; + } + ++ platform_set_drvdata(pdev, info); ++ ret = device_create_file(&pdev->dev, &dev_attr_vsync_pan); ++ if (ret) ++ goto free_cmap; ++ + /* + * Tell the world that we're ready to go + */ + ret = register_framebuffer(info); + if (ret) +- goto free_cmap; ++ goto remove_attrs; + + printk("fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n", + info->node, info->fix.mmio_start, sinfo->regs, sinfo->irq_base); + +- platform_set_drvdata(pdev, info); +- + memset_io(info->screen_base, 0, info->fix.smem_len); + info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW; + ret = fb_set_var(info, &info->var); +@@ -724,6 +774,8 @@ static int __devinit sidsafb_probe(struc + return 0; + + ++remove_attrs: ++ device_remove_file(&pdev->dev, &dev_attr_vsync_pan); + free_cmap: + fb_dealloc_cmap(&info->cmap); + unregister_irqs: +@@ -761,6 +813,8 @@ static int __devexit sidsafb_remove(stru + /* TODO: Restore original state */ + unregister_framebuffer(info); + ++ device_remove_file(&pdev->dev, &dev_attr_vsync_pan); ++ + fb_dealloc_cmap(&info->cmap); + free_irq(sinfo->irq_base, info); + iounmap(sinfo->regs); |