Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+56 −30
Original line number Diff line number Diff line
@@ -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_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);

/**
@@ -711,12 +712,7 @@ static void mx3fb_dma_done(void *arg)
	complete(&mx3_fbi->flip_cmpl);
}

/**
 * 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)
static int __set_par(struct fb_info *fbi, bool lock)
{
	u32 mem_len;
	struct ipu_di_signal_cfg sig_cfg;
@@ -727,10 +723,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
	struct idmac_video_param *video = &ichan->params.video;
	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 */
	if (mx3_fbi->txd)
		sdc_disable_channel(mx3_fbi);
@@ -742,11 +734,9 @@ static int mx3fb_set_par(struct fb_info *fbi)
		if (fbi->fix.smem_start)
			mx3fb_unmap_video_memory(fbi);

		if (mx3fb_map_video_memory(fbi, mem_len) < 0) {
			mutex_unlock(&mx3_fbi->mutex);
		if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0)
			return -ENOMEM;
	}
	}

	sg_init_table(&sg[0], 1);
	sg_init_table(&sg[1], 1);
@@ -791,7 +781,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
				   fbi->var.vsync_len,
				   fbi->var.lower_margin +
				   fbi->var.vsync_len, sig_cfg) != 0) {
			mutex_unlock(&mx3_fbi->mutex);
			dev_err(fbi->device,
				"mx3fb: Error initializing panel.\n");
			return -EINVAL;
@@ -810,9 +799,30 @@ static int mx3fb_set_par(struct fb_info *fbi)
	if (mx3_fbi->blank == FB_BLANK_UNBLANK)
		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);

	return 0;
	return ret;
}

/**
@@ -966,21 +976,11 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
	return ret;
}

/**
 * mx3fb_blank() - blank the display.
 */
static int mx3fb_blank(int blank, struct fb_info *fbi)
static void __blank(int blank, struct fb_info *fbi)
{
	struct mx3fb_info *mx3_fbi = fbi->par;
	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;

	switch (blank) {
@@ -999,6 +999,23 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
		sdc_set_brightness(mx3fb, mx3fb->backlight_level);
		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);

	return 0;
@@ -1198,6 +1215,7 @@ static int mx3fb_resume(struct platform_device *pdev)
 * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
 * @fbi:	framebuffer information pointer
 * @mem_len:	length of mapped memory
 * @lock:	do not lock during initialisation
 * @return:	Error code indicating success or failure
 *
 * 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)
 * area is remapped, all virtual memory access to the video memory should occur
 * 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;
	dma_addr_t addr;
@@ -1221,9 +1240,11 @@ static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len)
		goto err0;
	}

	if (lock)
		mutex_lock(&fbi->mm_lock);
	fbi->fix.smem_start = addr;
	fbi->fix.smem_len = mem_len;
	if (lock)
		mutex_unlock(&fbi->mm_lock);

	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)
	init_completion(&mx3fbi->flip_cmpl);
	disable_irq(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);