Commit 20de03da authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Linus Torvalds

i.MX31: fix framebuffer locking regressions

Recent framebuffer locking patches first made affected systems unbootable,
then the dead-lock has been fixed but as of 2.6.31-rc4 the framebuffer on
mx3 machines doesn't work. Fix this.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2d8dd38a
...@@ -669,7 +669,8 @@ static uint32_t bpp_to_pixfmt(int bpp) ...@@ -669,7 +669,8 @@ static uint32_t bpp_to_pixfmt(int bpp)
} }
static int mx3fb_blank(int blank, struct fb_info *fbi); static int mx3fb_blank(int blank, struct fb_info *fbi);
static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len); static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
bool lock);
static int mx3fb_unmap_video_memory(struct fb_info *fbi); static int mx3fb_unmap_video_memory(struct fb_info *fbi);
/** /**
...@@ -711,12 +712,7 @@ static void mx3fb_dma_done(void *arg) ...@@ -711,12 +712,7 @@ static void mx3fb_dma_done(void *arg)
complete(&mx3_fbi->flip_cmpl); complete(&mx3_fbi->flip_cmpl);
} }
/** static int __set_par(struct fb_info *fbi, bool lock)
* mx3fb_set_par() - set framebuffer parameters and change the operating mode.
* @fbi: framebuffer information pointer.
* @return: 0 on success or negative error code on failure.
*/
static int mx3fb_set_par(struct fb_info *fbi)
{ {
u32 mem_len; u32 mem_len;
struct ipu_di_signal_cfg sig_cfg; struct ipu_di_signal_cfg sig_cfg;
...@@ -727,10 +723,6 @@ static int mx3fb_set_par(struct fb_info *fbi) ...@@ -727,10 +723,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
struct idmac_video_param *video = &ichan->params.video; struct idmac_video_param *video = &ichan->params.video;
struct scatterlist *sg = mx3_fbi->sg; struct scatterlist *sg = mx3_fbi->sg;
dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
mutex_lock(&mx3_fbi->mutex);
/* Total cleanup */ /* Total cleanup */
if (mx3_fbi->txd) if (mx3_fbi->txd)
sdc_disable_channel(mx3_fbi); sdc_disable_channel(mx3_fbi);
...@@ -742,11 +734,9 @@ static int mx3fb_set_par(struct fb_info *fbi) ...@@ -742,11 +734,9 @@ static int mx3fb_set_par(struct fb_info *fbi)
if (fbi->fix.smem_start) if (fbi->fix.smem_start)
mx3fb_unmap_video_memory(fbi); mx3fb_unmap_video_memory(fbi);
if (mx3fb_map_video_memory(fbi, mem_len) < 0) { if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0)
mutex_unlock(&mx3_fbi->mutex);
return -ENOMEM; return -ENOMEM;
} }
}
sg_init_table(&sg[0], 1); sg_init_table(&sg[0], 1);
sg_init_table(&sg[1], 1); sg_init_table(&sg[1], 1);
...@@ -791,7 +781,6 @@ static int mx3fb_set_par(struct fb_info *fbi) ...@@ -791,7 +781,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
fbi->var.vsync_len, fbi->var.vsync_len,
fbi->var.lower_margin + fbi->var.lower_margin +
fbi->var.vsync_len, sig_cfg) != 0) { fbi->var.vsync_len, sig_cfg) != 0) {
mutex_unlock(&mx3_fbi->mutex);
dev_err(fbi->device, dev_err(fbi->device,
"mx3fb: Error initializing panel.\n"); "mx3fb: Error initializing panel.\n");
return -EINVAL; return -EINVAL;
...@@ -810,9 +799,30 @@ static int mx3fb_set_par(struct fb_info *fbi) ...@@ -810,9 +799,30 @@ static int mx3fb_set_par(struct fb_info *fbi)
if (mx3_fbi->blank == FB_BLANK_UNBLANK) if (mx3_fbi->blank == FB_BLANK_UNBLANK)
sdc_enable_channel(mx3_fbi); sdc_enable_channel(mx3_fbi);
return 0;
}
/**
* mx3fb_set_par() - set framebuffer parameters and change the operating mode.
* @fbi: framebuffer information pointer.
* @return: 0 on success or negative error code on failure.
*/
static int mx3fb_set_par(struct fb_info *fbi)
{
struct mx3fb_info *mx3_fbi = fbi->par;
struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
struct idmac_channel *ichan = mx3_fbi->idmac_channel;
int ret;
dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
mutex_lock(&mx3_fbi->mutex);
ret = __set_par(fbi, true);
mutex_unlock(&mx3_fbi->mutex); mutex_unlock(&mx3_fbi->mutex);
return 0; return ret;
} }
/** /**
...@@ -966,21 +976,11 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red, ...@@ -966,21 +976,11 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
return ret; return ret;
} }
/** static void __blank(int blank, struct fb_info *fbi)
* mx3fb_blank() - blank the display.
*/
static int mx3fb_blank(int blank, struct fb_info *fbi)
{ {
struct mx3fb_info *mx3_fbi = fbi->par; struct mx3fb_info *mx3_fbi = fbi->par;
struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
blank, fbi->screen_base, fbi->fix.smem_len);
if (mx3_fbi->blank == blank)
return 0;
mutex_lock(&mx3_fbi->mutex);
mx3_fbi->blank = blank; mx3_fbi->blank = blank;
switch (blank) { switch (blank) {
...@@ -999,6 +999,23 @@ static int mx3fb_blank(int blank, struct fb_info *fbi) ...@@ -999,6 +999,23 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
sdc_set_brightness(mx3fb, mx3fb->backlight_level); sdc_set_brightness(mx3fb, mx3fb->backlight_level);
break; break;
} }
}
/**
* mx3fb_blank() - blank the display.
*/
static int mx3fb_blank(int blank, struct fb_info *fbi)
{
struct mx3fb_info *mx3_fbi = fbi->par;
dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
blank, fbi->screen_base, fbi->fix.smem_len);
if (mx3_fbi->blank == blank)
return 0;
mutex_lock(&mx3_fbi->mutex);
__blank(blank, fbi);
mutex_unlock(&mx3_fbi->mutex); mutex_unlock(&mx3_fbi->mutex);
return 0; return 0;
...@@ -1198,6 +1215,7 @@ static int mx3fb_resume(struct platform_device *pdev) ...@@ -1198,6 +1215,7 @@ static int mx3fb_resume(struct platform_device *pdev)
* mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
* @fbi: framebuffer information pointer * @fbi: framebuffer information pointer
* @mem_len: length of mapped memory * @mem_len: length of mapped memory
* @lock: do not lock during initialisation
* @return: Error code indicating success or failure * @return: Error code indicating success or failure
* *
* This buffer is remapped into a non-cached, non-buffered, memory region to * This buffer is remapped into a non-cached, non-buffered, memory region to
...@@ -1205,7 +1223,8 @@ static int mx3fb_resume(struct platform_device *pdev) ...@@ -1205,7 +1223,8 @@ static int mx3fb_resume(struct platform_device *pdev)
* area is remapped, all virtual memory access to the video memory should occur * area is remapped, all virtual memory access to the video memory should occur
* at the new region. * at the new region.
*/ */
static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len) static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
bool lock)
{ {
int retval = 0; int retval = 0;
dma_addr_t addr; dma_addr_t addr;
...@@ -1221,9 +1240,11 @@ static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len) ...@@ -1221,9 +1240,11 @@ static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len)
goto err0; goto err0;
} }
if (lock)
mutex_lock(&fbi->mm_lock); mutex_lock(&fbi->mm_lock);
fbi->fix.smem_start = addr; fbi->fix.smem_start = addr;
fbi->fix.smem_len = mem_len; fbi->fix.smem_len = mem_len;
if (lock)
mutex_unlock(&fbi->mm_lock); mutex_unlock(&fbi->mm_lock);
dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
...@@ -1365,6 +1386,11 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) ...@@ -1365,6 +1386,11 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
init_completion(&mx3fbi->flip_cmpl); init_completion(&mx3fbi->flip_cmpl);
disable_irq(ichan->eof_irq); disable_irq(ichan->eof_irq);
dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
ret = __set_par(fbi, false);
if (ret < 0)
goto esetpar;
__blank(FB_BLANK_UNBLANK, fbi);
dev_info(dev, "registered, using mode %s\n", fb_mode); dev_info(dev, "registered, using mode %s\n", fb_mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment