[patch 0/9] PS3 Virtual Frame Buffer Device Driver patches for 2.6.24

STALE6890d

10 messages, 1 author, 2007-10-08 · open the first message on its own page

[patch 0/9] PS3 Virtual Frame Buffer Device Driver patches for 2.6.24

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:21

	Hi,

Here are some new patches for the PS3 Virtual Frame Buffer Device Driver
(ps3fb):
  [1] ps3fb: Convert from printk()/DPRINTK() to dev_*()/pr_*()
  [2] ps3fb: Do not print warnings on invalid frame numbers
  [3] ps3fb: Clean up includes
  [4] ps3fb: Make ps3fb_wait_for_vsync() and ps3fb_flip_ctl() static
  [5] ps3fb: Fix possible overlap of GPU command buffer and frame buffer
  [6] ps3fb: Use fb_info.par properly
  [7] ps3fb: Don't keep the borders for non-fullscreen modes in XDR memory
  [8] ps3fb: Add virtual screen and panning support
  [9] ps3fb: Enhance horizontal panning on firmware 1.90 and up

Please review, and queue for 2.6.24 if they're ok. Thanks!

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 1/9] ps3fb: Convert from printk()/DPRINTK() to dev_*()/pr_*()

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:22

From: Geert Uytterhoeven <redacted>

Convert ps3fb from printk()/DPRINTK() to dev_*()/pr_*()

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |  183 ++++++++++++++++++++++++++------------------------
 1 files changed, 96 insertions(+), 87 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -48,12 +48,6 @@
 
 #define DEVICE_NAME		"ps3fb"
 
-#ifdef PS3FB_DEBUG
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
 #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC	0x101
 #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP	0x102
 #define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP	0x600
@@ -316,7 +310,7 @@ static int ps3fb_get_res_table(u32 xres,
 		f = ps3fb_res[i].type;
 
 		if (!x) {
-			DPRINTK("ERROR: ps3fb_get_res_table()\n");
+			pr_debug("ERROR: ps3fb_get_res_table()\n");
 			return -1;
 		}
 
@@ -357,11 +351,11 @@ static unsigned int ps3fb_find_mode(cons
 			/* Full broadcast modes have the full mode bit set */
 			mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
 
-			DPRINTK("ps3fb_find_mode: mode %u\n", mode);
+			pr_debug("ps3fb_find_mode: mode %u\n", mode);
 			return mode;
 		}
 
-	DPRINTK("ps3fb_find_mode: mode not found\n");
+	pr_debug("ps3fb_find_mode: mode not found\n");
 	return 0;
 
 }
@@ -384,7 +378,7 @@ static const struct fb_videomode *ps3fb_
 	return &ps3fb_modedb[mode - 1];
 }
 
-static int ps3fb_sync(u32 frame)
+static int ps3fb_sync(struct fb_info *info, u32 frame)
 {
 	int i, status;
 	u32 xres, yres;
@@ -395,8 +389,8 @@ static int ps3fb_sync(u32 frame)
 	yres = ps3fb_res[i].yres;
 
 	if (frame > ps3fb.num_frames - 1) {
-		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
-		       __func__, frame);
+		dev_warn(info->device, "%s: invalid frame number (%u)\n",
+			 __func__, frame);
 		return -EINVAL;
 	}
 	offset = xres * yres * BPP * frame;
@@ -409,26 +403,26 @@ static int ps3fb_sync(u32 frame)
 					   (xres << 16) | yres,
 					   xres * BPP);	/* line_length */
 	if (status)
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
-		       __func__, status);
+		dev_err(info->device,
+			"%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+			__func__, status);
 #ifdef HEAD_A
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
 					   0, offset, 0, 0);
 	if (status)
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
-		       __func__, status);
+		dev_err(info->device,
+			"%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+			__func__, status);
 #endif
 #ifdef HEAD_B
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
 					   1, offset, 0, 0);
 	if (status)
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
-		       __func__, status);
+		dev_err(info->device,
+			"%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+			__func__, status);
 #endif
 	return 0;
 }
@@ -445,7 +439,7 @@ static int ps3fb_release(struct fb_info 
 	if (atomic_dec_and_test(&ps3fb.f_count)) {
 		if (atomic_read(&ps3fb.ext_flip)) {
 			atomic_set(&ps3fb.ext_flip, 0);
-			ps3fb_sync(0);	/* single buffer */
+			ps3fb_sync(info, 0);	/* single buffer */
 		}
 	}
 	return 0;
@@ -465,8 +459,10 @@ static int ps3fb_check_var(struct fb_var
 	int mode;
 	int i;
 
-	DPRINTK("var->xres:%u info->var.xres:%u\n", var->xres, info->var.xres);
-	DPRINTK("var->yres:%u info->var.yres:%u\n", var->yres, info->var.yres);
+	dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres,
+		info->var.xres);
+	dev_dbg(info->device, "var->yres:%u info->var.yres:%u\n", var->yres,
+		info->var.yres);
 
 	/* FIXME For now we do exact matches only */
 	mode = ps3fb_find_mode(var, &line_length);
@@ -487,7 +483,8 @@ static int ps3fb_check_var(struct fb_var
 	/* Virtual screen and panning are not supported */
 	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
 	    var->xoffset || var->yoffset) {
-		DPRINTK("Virtual screen and panning are not supported\n");
+		dev_dbg(info->device,
+			"Virtual screen and panning are not supported\n");
 		return -EINVAL;
 	}
 
@@ -502,7 +499,7 @@ static int ps3fb_check_var(struct fb_var
 	    var->blue.length > 8 || var->transp.length > 8 ||
 	    var->red.msb_right || var->green.msb_right ||
 	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
-		DPRINTK("We support ARGB8888 only\n");
+		dev_dbg(info->device, "We support ARGB8888 only\n");
 		return -EINVAL;
 	}
 
@@ -522,14 +519,14 @@ static int ps3fb_check_var(struct fb_var
 
 	/* Rotation is not supported */
 	if (var->rotate) {
-		DPRINTK("Rotation is not supported\n");
+		dev_dbg(info->device, "Rotation is not supported\n");
 		return -EINVAL;
 	}
 
 	/* Memory limit */
 	i = ps3fb_get_res_table(var->xres, var->yres, mode);
 	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb_videomemory.size) {
-		DPRINTK("Not enough memory\n");
+		dev_dbg(info->device, "Not enough memory\n");
 		return -ENOMEM;
 	}
 
@@ -549,7 +546,7 @@ static int ps3fb_set_par(struct fb_info 
 	int i;
 	unsigned long offset;
 
-	DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
+	dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n",
 		info->var.xres, info->var.xres_virtual,
 		info->var.yres, info->var.yres_virtual, info->var.pixclock);
 
@@ -623,8 +620,8 @@ static int ps3fb_mmap(struct fb_info *in
 			    size, vma->vm_page_prot))
 		return -EAGAIN;
 
-	printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
-	       vma->vm_start);
+	dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
+		offset, vma->vm_start);
 	return 0;
 }
 
@@ -636,7 +633,7 @@ static int ps3fb_blank(int blank, struct
 {
 	int retval;
 
-	DPRINTK("%s: blank:%d\n", __func__, blank);
+	dev_dbg(info->device, "%s: blank:%d\n", __func__, blank);
 	switch (blank) {
 	case FB_BLANK_POWERDOWN:
 	case FB_BLANK_HSYNC_SUSPEND:
@@ -705,7 +702,7 @@ static int ps3fb_ioctl(struct fb_info *i
 	case FBIOGET_VBLANK:
 		{
 			struct fb_vblank vblank;
-			DPRINTK("FBIOGET_VBLANK:\n");
+			dev_dbg(info->device, "FBIOGET_VBLANK:\n");
 			retval = ps3fb_get_vblank(&vblank);
 			if (retval)
 				break;
@@ -718,7 +715,7 @@ static int ps3fb_ioctl(struct fb_info *i
 	case FBIO_WAITFORVSYNC:
 		{
 			u32 crt;
-			DPRINTK("FBIO_WAITFORVSYNC:\n");
+			dev_dbg(info->device, "FBIO_WAITFORVSYNC:\n");
 			if (get_user(crt, (u32 __user *) arg))
 				break;
 
@@ -739,7 +736,7 @@ static int ps3fb_ioctl(struct fb_info *i
 				if (id > 0)
 					val = (val & ~PS3AV_MODE_MASK) | id;
 			}
-			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
+			dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
 			retval = -EINVAL;
 			old_mode = ps3fb_mode;
 			ps3fb_mode = val;
@@ -762,7 +759,7 @@ static int ps3fb_ioctl(struct fb_info *i
 
 	case PS3FB_IOCTL_GETMODE:
 		val = ps3av_get_mode();
-		DPRINTK("PS3FB_IOCTL_GETMODE:%x\n", val);
+		dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x\n", val);
 		if (!copy_to_user(argp, &val, sizeof(val)))
 			retval = 0;
 		break;
@@ -771,7 +768,7 @@ static int ps3fb_ioctl(struct fb_info *i
 		{
 			struct ps3fb_ioctl_res res;
 			int i = ps3fb.res_index;
-			DPRINTK("PS3FB_IOCTL_SCREENINFO:\n");
+			dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n");
 			res.xres = ps3fb_res[i].xres;
 			res.yres = ps3fb_res[i].yres;
 			res.xoff = ps3fb_res[i].xoff;
@@ -783,13 +780,13 @@ static int ps3fb_ioctl(struct fb_info *i
 		}
 
 	case PS3FB_IOCTL_ON:
-		DPRINTK("PS3FB_IOCTL_ON:\n");
+		dev_dbg(info->device, "PS3FB_IOCTL_ON:\n");
 		atomic_inc(&ps3fb.ext_flip);
 		retval = 0;
 		break;
 
 	case PS3FB_IOCTL_OFF:
-		DPRINTK("PS3FB_IOCTL_OFF:\n");
+		dev_dbg(info->device, "PS3FB_IOCTL_OFF:\n");
 		atomic_dec_if_positive(&ps3fb.ext_flip);
 		retval = 0;
 		break;
@@ -798,8 +795,8 @@ static int ps3fb_ioctl(struct fb_info *i
 		if (copy_from_user(&val, argp, sizeof(val)))
 			break;
 
-		DPRINTK("PS3FB_IOCTL_FSEL:%d\n", val);
-		retval = ps3fb_sync(val);
+		dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val);
+		retval = ps3fb_sync(info, val);
 		break;
 
 	default:
@@ -811,13 +808,15 @@ static int ps3fb_ioctl(struct fb_info *i
 
 static int ps3fbd(void *arg)
 {
+	struct fb_info *info = arg;
+
 	set_freezable();
 	while (!kthread_should_stop()) {
 		try_to_freeze();
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (ps3fb.is_kicked) {
 			ps3fb.is_kicked = 0;
-			ps3fb_sync(0);	/* single buffer */
+			ps3fb_sync(info, 0);	/* single buffer */
 		}
 		schedule();
 	}
@@ -826,14 +825,15 @@ static int ps3fbd(void *arg)
 
 static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
 {
+	struct device *dev = ptr;
 	u64 v1;
 	int status;
 	struct display_head *head = &ps3fb.dinfo->display_head[1];
 
 	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
-		       __func__, status);
+		dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__,
+			status);
 		return IRQ_NONE;
 	}
 
@@ -853,35 +853,35 @@ static irqreturn_t ps3fb_vsync_interrupt
 
 
 static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo,
-				struct ps3_system_bus_device *dev)
+				struct device *dev)
 {
 	int error;
 
-	DPRINTK("version_driver:%x\n", dinfo->version_driver);
-	DPRINTK("irq outlet:%x\n", dinfo->irq.irq_outlet);
-	DPRINTK("version_gpu:%x memory_size:%x ch:%x core_freq:%d mem_freq:%d\n",
+	dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver);
+	dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet);
+	dev_dbg(dev,
+		"version_gpu: %x memory_size: %x ch: %x core_freq: %d "
+		"mem_freq:%d\n",
 		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
 		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
 
 	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
-		printk(KERN_ERR "%s: version_driver err:%x\n", __func__,
-		       dinfo->version_driver);
+		dev_err(dev, "%s: version_driver err:%x\n", __func__,
+			dinfo->version_driver);
 		return -EINVAL;
 	}
 
 	error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
 				   &ps3fb.irq_no);
 	if (error) {
-		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__,
-		       error);
+		dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error);
 		return error;
 	}
 
 	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
 			    DEVICE_NAME, dev);
 	if (error) {
-		printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
-		       error);
+		dev_err(dev, "%s: request_irq failed %d\n", __func__, error);
 		ps3_irq_plug_destroy(ps3fb.irq_no);
 		return error;
 	}
@@ -891,18 +891,19 @@ static int ps3fb_vsync_settings(struct g
 	return 0;
 }
 
-static int ps3fb_xdr_settings(u64 xdr_lpar)
+static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev)
 {
 	int status;
 
 	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
 				       xdr_lpar, ps3fb_videomemory.size, 0);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
-		       __func__, status);
+		dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n",
+			__func__, status);
 		return -ENXIO;
 	}
-	DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
+	dev_dbg(dev,
+		"video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
 		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
 		virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size);
 
@@ -911,9 +912,9 @@ static int ps3fb_xdr_settings(u64 xdr_lp
 					   xdr_lpar, ps3fb_videomemory.size,
 					   GPU_IOIF, 0);
 	if (status) {
-		printk(KERN_ERR
-		       "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
-		       __func__, status);
+		dev_err(dev,
+			"%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+			__func__, status);
 		return -ENXIO;
 	}
 	return 0;
@@ -943,7 +944,7 @@ static struct fb_fix_screeninfo ps3fb_fi
 	.accel =	FB_ACCEL_NONE,
 };
 
-static int ps3fb_set_sync(void)
+static int ps3fb_set_sync(struct device *dev)
 {
 	int status;
 
@@ -952,8 +953,10 @@ static int ps3fb_set_sync(void)
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
 					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC "
-		       "failed: %d\n", __func__, status);
+		dev_err(dev,
+			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
+			"%d\n",
+			__func__, status);
 		return -1;
 	}
 #endif
@@ -963,8 +966,10 @@ static int ps3fb_set_sync(void)
 					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
 
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE "
-		       "failed: %d\n", __func__, status);
+		dev_err(dev,
+			"%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: "
+			"%d\n",
+			__func__, status);
 		return -1;
 	}
 #endif
@@ -988,18 +993,19 @@ static int __devinit ps3fb_probe(struct 
 
 	status = ps3_open_hv_device(dev);
 	if (status) {
-		printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__);
+		dev_err(&dev->core, "%s: ps3_open_hv_device failed\n",
+			__func__);
 		goto err;
 	}
 
 	if (!ps3fb_mode)
 		ps3fb_mode = ps3av_get_mode();
-	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+	dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode);
 
 	if (ps3fb_mode > 0 &&
 	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
 		ps3fb.res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);
-		DPRINTK("res_index:%d\n", ps3fb.res_index);
+		dev_dbg(&dev->core, "res_index:%d\n", ps3fb.res_index);
 	} else
 		ps3fb.res_index = GPU_RES_INDEX;
 
@@ -1008,43 +1014,44 @@ static int __devinit ps3fb_probe(struct 
 	init_waitqueue_head(&ps3fb.wait_vsync);
 	ps3fb.num_frames = 1;
 
-	ps3fb_set_sync();
+	ps3fb_set_sync(&dev->core);
 
 	/* get gpu context handle */
 	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
 					 &ps3fb.memory_handle, &ddr_lpar);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
-		       __func__, status);
+		dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
+			__func__, status);
 		goto err;
 	}
-	DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
+	dev_dbg(&dev->core, "ddr:lpar:0x%lx\n", ddr_lpar);
 
 	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
 					  &ps3fb.context_handle,
 					  &lpar_dma_control, &lpar_driver_info,
 					  &lpar_reports, &lpar_reports_size);
 	if (status) {
-		printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
-		       __func__, status);
+		dev_err(&dev->core,
+			"%s: lv1_gpu_context_attribute failed: %d\n", __func__,
+			status);
 		goto err_gpu_memory_free;
 	}
 
 	/* vsync interrupt */
 	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
 	if (!ps3fb.dinfo) {
-		printk(KERN_ERR "%s: ioremap failed\n", __func__);
+		dev_err(&dev->core, "%s: ioremap failed\n", __func__);
 		goto err_gpu_context_free;
 	}
 
-	retval = ps3fb_vsync_settings(ps3fb.dinfo, dev);
+	retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core);
 	if (retval)
 		goto err_iounmap_dinfo;
 
 	/* xdr frame buffer */
 	ps3fb.xdr_ea = ps3fb_videomemory.address;
 	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
-	retval = ps3fb_xdr_settings(xdr_lpar);
+	retval = ps3fb_xdr_settings(xdr_lpar, &dev->core);
 	if (retval)
 		goto err_free_irq;
 
@@ -1087,9 +1094,9 @@ static int __devinit ps3fb_probe(struct 
 
 	dev->core.driver_data = info;
 
-	printk(KERN_INFO
-	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
-	       info->node, ps3fb_videomemory.size >> 10);
+	dev_info(info->device, "%s %s, using %lu KiB of video memory\n",
+		 dev_driver_string(info->dev), info->dev->bus_id,
+		 ps3fb_videomemory.size >> 10);
 
 	task = kthread_run(ps3fbd, info, DEVICE_NAME);
 	if (IS_ERR(task)) {
@@ -1126,7 +1133,7 @@ static int ps3fb_shutdown(struct ps3_sys
 	int status;
 	struct fb_info *info = dev->core.driver_data;
 
-	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 
 	ps3fb_flip_ctl(0, &ps3fb);	/* flip off */
 	ps3fb.dinfo->irq.mask = 0;
@@ -1151,14 +1158,16 @@ static int ps3fb_shutdown(struct ps3_sys
 
 	status = lv1_gpu_context_free(ps3fb.context_handle);
 	if (status)
-		DPRINTK("lv1_gpu_context_free failed: %d\n", status);
+		dev_dbg(&dev->core, "lv1_gpu_context_free failed: %d\n",
+			status);
 
 	status = lv1_gpu_memory_free(ps3fb.memory_handle);
 	if (status)
-		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
+		dev_dbg(&dev->core, "lv1_gpu_memory_free failed: %d\n",
+			status);
 
 	ps3_close_hv_device(dev);
-	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
+	dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
 
 	return 0;
 }
@@ -1211,9 +1220,9 @@ static int __init ps3fb_init(void)
 
 static void __exit ps3fb_exit(void)
 {
-	DPRINTK(" -> %s:%d\n", __func__, __LINE__);
+	pr_debug(" -> %s:%d\n", __func__, __LINE__);
 	ps3_system_bus_driver_unregister(&ps3fb_driver);
-	DPRINTK(" <- %s:%d\n", __func__, __LINE__);
+	pr_debug(" <- %s:%d\n", __func__, __LINE__);
 }
 
 module_init(ps3fb_init);
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 2/9] ps3fb: Do not print warnings on invalid frame numbers

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:23

From: Geert Uytterhoeven <redacted>

ps3fb: Do not print warnings on invalid frame numbers, as this can be triggered
from user space.

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -389,8 +389,8 @@ static int ps3fb_sync(struct fb_info *in
 	yres = ps3fb_res[i].yres;
 
 	if (frame > ps3fb.num_frames - 1) {
-		dev_warn(info->device, "%s: invalid frame number (%u)\n",
-			 __func__, frame);
+		dev_dbg(info->device, "%s: invalid frame number (%u)\n",
+			__func__, frame);
 		return -EINVAL;
 	}
 	offset = xres * yres * BPP * frame;
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 3/9] ps3fb: Clean up includes

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:24

From: Geert Uytterhoeven <redacted>

ps3fb: Clean up includes
  
Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |   10 +---------
 1 files changed, 1 insertion(+), 9 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -22,22 +22,14 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
 #include <linux/ioctl.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
-
-#include <asm/uaccess.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <asm/time.h>
+#include <linux/uaccess.h>
 
 #include <asm/abs_addr.h>
 #include <asm/lv1call.h>
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 4/9] ps3fb: Make ps3fb_wait_for_vsync() and ps3fb_flip_ctl() static

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:25

From: Geert Uytterhoeven <redacted>

ps3fb: Make ps3fb_wait_for_vsync() and ps3fb_flip_ctl() static, as they're no
(longer) used outside ps3fb.

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -652,7 +652,7 @@ static int ps3fb_get_vblank(struct fb_vb
 	return 0;
 }
 
-int ps3fb_wait_for_vsync(u32 crtc)
+static int ps3fb_wait_for_vsync(u32 crtc)
 {
 	int ret;
 	u64 count;
@@ -667,9 +667,7 @@ int ps3fb_wait_for_vsync(u32 crtc)
 	return 0;
 }
 
-EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
-
-void ps3fb_flip_ctl(int on, void *data)
+static void ps3fb_flip_ctl(int on, void *data)
 {
 	struct ps3fb_priv *priv = data;
 	if (on)
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 5/9] ps3fb: Fix possible overlap of GPU command buffer and frame buffer

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:26

From: Geert Uytterhoeven <redacted>

ps3fb: In the case of non-fullscreen video modes, there was a partial overlap
of the GPU command buffer and the frame buffer. Fix and cleanup various issues
with overlap and alignment:
  - Move the GPU command buffer from the beginning to the end of video memory
  - Exclude the GPU command buffer from the actual frame buffer memory
  - Align the start of the virtual frame buffer to PAGE_SIZE instead of to 64
    KiB, and don't waste memory if it's already aligned (for fullscreen modes)
  - Take into account the alignment when checking memory requirements and
    maximum number of frames
  - Make sure fb_fix_screeninfo.smem_start always points to the virtual frame
    buffer start, so we don't have to compensate for that in ps3fb_mmap()

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |   66 +++++++++++++++++++++++++++++---------------------
 1 files changed, 39 insertions(+), 27 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -52,7 +52,7 @@
 #define L1GPU_DISPLAY_SYNC_VSYNC		2
 
 #define DDR_SIZE				(0)	/* used no ddr */
-#define GPU_OFFSET				(64 * 1024)
+#define GPU_CMD_BUF_SIZE			(64 * 1024)
 #define GPU_IOIF				(0x0d000000UL)
 
 #define PS3FB_FULL_MODE_BIT			0x80
@@ -117,6 +117,7 @@ struct ps3fb_priv {
 
 	u64 context_handle, memory_handle;
 	void *xdr_ea;
+	size_t xdr_size;
 	struct gpu_driver_info *dinfo;
 	u32 res_index;
 
@@ -280,9 +281,20 @@ static const struct fb_videomode ps3fb_m
 #define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */
 #define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */
 #define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */
-#define BPP	4		/* number of bytes per pixel */
-#define VP_OFF(i)	(WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
-#define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
+#define BPP		4			/* number of bytes per pixel */
+
+/* Start of the virtual frame buffer (relative to fullscreen ) */
+#define VP_OFF(i)	((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP)
+
+/*
+ * Start of the virtual frame buffer (relative to start of video memory)
+ * This is PAGE_SIZE aligned for easier mmap()
+ */
+#define VFB_OFF(i)	PAGE_ALIGN(VP_OFF(i))
+
+/* Start of the fullscreen frame buffer (relative to start of video memory) */
+#define FB_OFF(i)	(-VP_OFF(i) & ~PAGE_MASK)
+
 
 static int ps3fb_mode;
 module_param(ps3fb_mode, int, 0);
@@ -517,7 +529,8 @@ static int ps3fb_check_var(struct fb_var
 
 	/* Memory limit */
 	i = ps3fb_get_res_table(var->xres, var->yres, mode);
-	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb_videomemory.size) {
+	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP >
+	    ps3fb.xdr_size - VFB_OFF(i)) {
 		dev_dbg(info->device, "Not enough memory\n");
 		return -ENOMEM;
 	}
@@ -549,12 +562,13 @@ static int ps3fb_set_par(struct fb_info 
 	i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode);
 	ps3fb.res_index = i;
 
-	offset = FB_OFF(i) + VP_OFF(i);
-	info->fix.smem_len = ps3fb_videomemory.size - offset;
+	offset = VFB_OFF(i);
+	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea) + offset;
+	info->fix.smem_len = ps3fb.xdr_size - offset;
 	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
-	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+	memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
 
-	ps3fb.num_frames = ps3fb_videomemory.size/
+	ps3fb.num_frames = info->fix.smem_len/
 			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
 
 	/* Keep the special bits we cannot set using fb_var_screeninfo */
@@ -596,18 +610,13 @@ static int ps3fb_setcolreg(unsigned int 
 static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	unsigned long size, offset;
-	int i;
-
-	i = ps3fb_get_res_table(info->var.xres, info->var.yres, ps3fb_mode);
-	if (i == -1)
-		return -EINVAL;
 
 	size = vma->vm_end - vma->vm_start;
 	offset = vma->vm_pgoff << PAGE_SHIFT;
 	if (offset + size > info->fix.smem_len)
 		return -EINVAL;
 
-	offset += info->fix.smem_start + FB_OFF(i) + VP_OFF(i);
+	offset += info->fix.smem_start;
 	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
 			    size, vma->vm_page_prot))
 		return -EAGAIN;
@@ -899,8 +908,9 @@ static int ps3fb_xdr_settings(u64 xdr_lp
 
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
-					   xdr_lpar, ps3fb_videomemory.size,
-					   GPU_IOIF, 0);
+					   xdr_lpar + ps3fb.xdr_size,
+					   GPU_CMD_BUF_SIZE,
+					   GPU_IOIF + ps3fb.xdr_size, 0);
 	if (status) {
 		dev_err(dev,
 			"%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
@@ -1038,29 +1048,31 @@ static int __devinit ps3fb_probe(struct 
 	if (retval)
 		goto err_iounmap_dinfo;
 
-	/* xdr frame buffer */
+	/* XDR frame buffer */
 	ps3fb.xdr_ea = ps3fb_videomemory.address;
 	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
+
+	/* Clear memory to prevent kernel info leakage into userspace */
+	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+
+	/* The GPU command buffer is at the end of video memory */
+	ps3fb.xdr_size = ps3fb_videomemory.size - GPU_CMD_BUF_SIZE;
+
 	retval = ps3fb_xdr_settings(xdr_lpar, &dev->core);
 	if (retval)
 		goto err_free_irq;
 
-	/*
-	 * ps3fb must clear memory to prevent kernel info
-	 * leakage into userspace
-	 */
-	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
 	info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
 	if (!info)
 		goto err_free_irq;
 
-	offset = FB_OFF(ps3fb.res_index) + VP_OFF(ps3fb.res_index);
+	offset = VFB_OFF(ps3fb.res_index);
 	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
 	info->fbops = &ps3fb_ops;
 
 	info->fix = ps3fb_fix;
-	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
-	info->fix.smem_len = ps3fb_videomemory.size - offset;
+	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea) + offset;
+	info->fix.smem_len = ps3fb.xdr_size - offset;
 	info->pseudo_palette = info->par;
 	info->par = NULL;
 	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST;
@@ -1086,7 +1098,7 @@ static int __devinit ps3fb_probe(struct 
 
 	dev_info(info->device, "%s %s, using %lu KiB of video memory\n",
 		 dev_driver_string(info->dev), info->dev->bus_id,
-		 ps3fb_videomemory.size >> 10);
+		 ps3fb.xdr_size >> 10);
 
 	task = kthread_run(ps3fbd, info, DEVICE_NAME);
 	if (IS_ERR(task)) {
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 6/9] ps3fb: Use fb_info.par properly

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:27

From: Geert Uytterhoeven <redacted>

ps3fb: Use fb_info.par properly:
  o Move mode-specific fields into struct ps3fb_par
  o Allocate struct ps3fb_par using framebuffer_alloc()
  o Protect access to ps3fb_par in ps3fb_sync() using the console semaphore
    (this semaphore is already held when ps3fb_set_par() is called)
  o Avoid calling ps3av_set_video_mode() if the actual video mode hasn't
    changed

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |   92 ++++++++++++++++++++++++++++++--------------------
 1 files changed, 57 insertions(+), 35 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -119,12 +119,10 @@ struct ps3fb_priv {
 	void *xdr_ea;
 	size_t xdr_size;
 	struct gpu_driver_info *dinfo;
-	u32 res_index;
 
 	u64 vblank_count;	/* frame count */
 	wait_queue_head_t wait_vsync;
 
-	u32 num_frames;		/* num of frame buffers */
 	atomic_t ext_flip;	/* on/off flip with vsync */
 	atomic_t f_count;	/* fb_open count */
 	int is_blanked;
@@ -133,6 +131,13 @@ struct ps3fb_priv {
 };
 static struct ps3fb_priv ps3fb;
 
+struct ps3fb_par {
+	u32 pseudo_palette[16];
+	int mode_id, new_mode_id;
+	int res_index;
+	unsigned int num_frames;	/* num of frame buffers */
+};
+
 struct ps3fb_res_table {
 	u32 xres;
 	u32 yres;
@@ -361,18 +366,17 @@ static unsigned int ps3fb_find_mode(cons
 
 	pr_debug("ps3fb_find_mode: mode not found\n");
 	return 0;
-
 }
 
-static const struct fb_videomode *ps3fb_default_mode(void)
+static const struct fb_videomode *ps3fb_default_mode(int id)
 {
-	u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
+	u32 mode = id & PS3AV_MODE_MASK;
 	u32 flags;
 
 	if (mode < 1 || mode > 13)
 		return NULL;
 
-	flags = ps3fb_mode & ~PS3AV_MODE_MASK;
+	flags = id & ~PS3AV_MODE_MASK;
 
 	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
 		/* Full broadcast mode */
@@ -384,18 +388,22 @@ static const struct fb_videomode *ps3fb_
 
 static int ps3fb_sync(struct fb_info *info, u32 frame)
 {
-	int i, status;
+	struct ps3fb_par *par = info->par;
+	int i, status, error = 0;
 	u32 xres, yres;
 	u64 fb_ioif, offset;
 
-	i = ps3fb.res_index;
+	acquire_console_sem();
+
+	i = par->res_index;
 	xres = ps3fb_res[i].xres;
 	yres = ps3fb_res[i].yres;
 
-	if (frame > ps3fb.num_frames - 1) {
+	if (frame > par->num_frames - 1) {
 		dev_dbg(info->device, "%s: invalid frame number (%u)\n",
 			__func__, frame);
-		return -EINVAL;
+		error = -EINVAL;
+		goto out;
 	}
 	offset = xres * yres * BPP * frame;
 
@@ -428,7 +436,10 @@ static int ps3fb_sync(struct fb_info *in
 			"%s: lv1_gpu_context_attribute FLIP failed: %d\n",
 			__func__, status);
 #endif
-	return 0;
+
+out:
+	release_console_sem();
+	return error;
 }
 
 
@@ -547,6 +558,7 @@ static int ps3fb_check_var(struct fb_var
 
 static int ps3fb_set_par(struct fb_info *info)
 {
+	struct ps3fb_par *par = info->par;
 	unsigned int mode;
 	int i;
 	unsigned long offset;
@@ -560,7 +572,7 @@ static int ps3fb_set_par(struct fb_info 
 		return -EINVAL;
 
 	i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode);
-	ps3fb.res_index = i;
+	par->res_index = i;
 
 	offset = VFB_OFF(i);
 	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea) + offset;
@@ -568,14 +580,19 @@ static int ps3fb_set_par(struct fb_info 
 	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
 	memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
 
-	ps3fb.num_frames = info->fix.smem_len/
-			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+	par->num_frames = info->fix.smem_len/
+			  (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
 
 	/* Keep the special bits we cannot set using fb_var_screeninfo */
-	ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
+	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
 
-	if (ps3av_set_video_mode(ps3fb_mode))
-		return -EINVAL;
+	if (par->new_mode_id != par->mode_id) {
+		if (ps3av_set_video_mode(par->new_mode_id)) {
+			par->new_mode_id = par->mode_id;
+			return -EINVAL;
+		}
+		par->mode_id = par->new_mode_id;
+	}
 
 	return 0;
 }
@@ -694,7 +711,7 @@ static int ps3fb_ioctl(struct fb_info *i
 		       unsigned long arg)
 {
 	void __user *argp = (void __user *)arg;
-	u32 val, old_mode;
+	u32 val;
 	int retval = -EFAULT;
 
 	switch (cmd) {
@@ -724,6 +741,7 @@ static int ps3fb_ioctl(struct fb_info *i
 
 	case PS3FB_IOCTL_SETMODE:
 		{
+			struct ps3fb_par *par = info->par;
 			const struct fb_videomode *mode;
 			struct fb_var_screeninfo var;
 
@@ -737,9 +755,7 @@ static int ps3fb_ioctl(struct fb_info *i
 			}
 			dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
 			retval = -EINVAL;
-			old_mode = ps3fb_mode;
-			ps3fb_mode = val;
-			mode = ps3fb_default_mode();
+			mode = ps3fb_default_mode(val);
 			if (mode) {
 				var = info->var;
 				fb_videomode_to_var(&var, mode);
@@ -747,12 +763,11 @@ static int ps3fb_ioctl(struct fb_info *i
 				info->flags |= FBINFO_MISC_USEREVENT;
 				/* Force, in case only special bits changed */
 				var.activate |= FB_ACTIVATE_FORCE;
+				par->new_mode_id = val;
 				retval = fb_set_var(info, &var);
 				info->flags &= ~FBINFO_MISC_USEREVENT;
 				release_console_sem();
 			}
-			if (retval)
-				ps3fb_mode = old_mode;
 			break;
 		}
 
@@ -765,14 +780,15 @@ static int ps3fb_ioctl(struct fb_info *i
 
 	case PS3FB_IOCTL_SCREENINFO:
 		{
+			struct ps3fb_par *par = info->par;
 			struct ps3fb_ioctl_res res;
-			int i = ps3fb.res_index;
+			int i = par->res_index;
 			dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n");
 			res.xres = ps3fb_res[i].xres;
 			res.yres = ps3fb_res[i].yres;
 			res.xoff = ps3fb_res[i].xoff;
 			res.yoff = ps3fb_res[i].yoff;
-			res.num_frames = ps3fb.num_frames;
+			res.num_frames = par->num_frames;
 			if (!copy_to_user(argp, &res, sizeof(res)))
 				retval = 0;
 			break;
@@ -979,6 +995,7 @@ static int ps3fb_set_sync(struct device 
 static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
 {
 	struct fb_info *info;
+	struct ps3fb_par *par;
 	int retval = -ENOMEM;
 	u32 xres, yres;
 	u64 ddr_lpar = 0;
@@ -987,7 +1004,7 @@ static int __devinit ps3fb_probe(struct 
 	u64 lpar_reports = 0;
 	u64 lpar_reports_size = 0;
 	u64 xdr_lpar;
-	int status;
+	int status, res_index;
 	unsigned long offset;
 	struct task_struct *task;
 
@@ -1004,15 +1021,14 @@ static int __devinit ps3fb_probe(struct 
 
 	if (ps3fb_mode > 0 &&
 	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
-		ps3fb.res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);
-		dev_dbg(&dev->core, "res_index:%d\n", ps3fb.res_index);
+		res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);
+		dev_dbg(&dev->core, "res_index:%d\n", res_index);
 	} else
-		ps3fb.res_index = GPU_RES_INDEX;
+		res_index = GPU_RES_INDEX;
 
 	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
 	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
 	init_waitqueue_head(&ps3fb.wait_vsync);
-	ps3fb.num_frames = 1;
 
 	ps3fb_set_sync(&dev->core);
 
@@ -1062,19 +1078,24 @@ static int __devinit ps3fb_probe(struct 
 	if (retval)
 		goto err_free_irq;
 
-	info = framebuffer_alloc(sizeof(u32) * 16, &dev->core);
+	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
 	if (!info)
 		goto err_free_irq;
 
-	offset = VFB_OFF(ps3fb.res_index);
+	par = info->par;
+	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */
+	par->new_mode_id = ps3fb_mode;
+	par->res_index = res_index;
+	par->num_frames = 1;
+
+	offset = VFB_OFF(res_index);
 	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
 	info->fbops = &ps3fb_ops;
 
 	info->fix = ps3fb_fix;
 	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea) + offset;
 	info->fix.smem_len = ps3fb.xdr_size - offset;
-	info->pseudo_palette = info->par;
-	info->par = NULL;
+	info->pseudo_palette = par->pseudo_palette;
 	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST;
 
 	retval = fb_alloc_cmap(&info->cmap, 256, 0);
@@ -1082,7 +1103,8 @@ static int __devinit ps3fb_probe(struct 
 		goto err_framebuffer_release;
 
 	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
-			  ARRAY_SIZE(ps3fb_modedb), ps3fb_default_mode(), 32)) {
+			  ARRAY_SIZE(ps3fb_modedb),
+			  ps3fb_default_mode(par->new_mode_id), 32)) {
 		retval = -EINVAL;
 		goto err_fb_dealloc;
 	}
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 7/9] ps3fb: Dont keep the borders for non-fullscreen modes in XDR memory

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:28

From: Geert Uytterhoeven <redacted>

Don't keep the borders for non-fullscreen modes in XDR memory:
  - Extract ps3fb_sync_image()
  - Work around the alignment restrictions of L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT
    by using an offset with L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP
  - Only copy the visible part of the screen on every vblank
  - Always put the real frame buffer at the start of video memory
  - Clear fullscreen DDR memory on mode change

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |  131 ++++++++++++++++++++++++++++----------------------
 1 files changed, 75 insertions(+), 56 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -54,6 +54,7 @@
 #define DDR_SIZE				(0)	/* used no ddr */
 #define GPU_CMD_BUF_SIZE			(64 * 1024)
 #define GPU_IOIF				(0x0d000000UL)
+#define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)
 
 #define PS3FB_FULL_MODE_BIT			0x80
 
@@ -136,6 +137,10 @@ struct ps3fb_par {
 	int mode_id, new_mode_id;
 	int res_index;
 	unsigned int num_frames;	/* num of frame buffers */
+	unsigned int width;
+	unsigned int height;
+	unsigned long full_offset;	/* start of fullscreen DDR fb */
+	unsigned long fb_offset;	/* start of actual DDR fb */
 };
 
 struct ps3fb_res_table {
@@ -291,15 +296,6 @@ static const struct fb_videomode ps3fb_m
 /* Start of the virtual frame buffer (relative to fullscreen ) */
 #define VP_OFF(i)	((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP)
 
-/*
- * Start of the virtual frame buffer (relative to start of video memory)
- * This is PAGE_SIZE aligned for easier mmap()
- */
-#define VFB_OFF(i)	PAGE_ALIGN(VP_OFF(i))
-
-/* Start of the fullscreen frame buffer (relative to start of video memory) */
-#define FB_OFF(i)	(-VP_OFF(i) & ~PAGE_MASK)
-
 
 static int ps3fb_mode;
 module_param(ps3fb_mode, int, 0);
@@ -386,63 +382,72 @@ static const struct fb_videomode *ps3fb_
 	return &ps3fb_modedb[mode - 1];
 }
 
-static int ps3fb_sync(struct fb_info *info, u32 frame)
+static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
+			     u64 dst_offset, u64 src_offset, u32 width,
+			     u32 height, u64 line_length)
 {
-	struct ps3fb_par *par = info->par;
-	int i, status, error = 0;
-	u32 xres, yres;
-	u64 fb_ioif, offset;
-
-	acquire_console_sem();
-
-	i = par->res_index;
-	xres = ps3fb_res[i].xres;
-	yres = ps3fb_res[i].yres;
-
-	if (frame > par->num_frames - 1) {
-		dev_dbg(info->device, "%s: invalid frame number (%u)\n",
-			__func__, frame);
-		error = -EINVAL;
-		goto out;
-	}
-	offset = xres * yres * BPP * frame;
+	int status;
 
-	fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
-					   offset, fb_ioif,
+					   dst_offset, GPU_IOIF + src_offset,
 					   L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
-					   (xres << 16) | yres,
-					   xres * BPP);	/* line_length */
+					   (width << 16) | height,
+					   line_length);
 	if (status)
-		dev_err(info->device,
+		dev_err(dev,
 			"%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
 			__func__, status);
 #ifdef HEAD_A
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
-					   0, offset, 0, 0);
+					   0, frame_offset, 0, 0);
 	if (status)
-		dev_err(info->device,
-			"%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
 			__func__, status);
 #endif
 #ifdef HEAD_B
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
-					   1, offset, 0, 0);
+					   1, frame_offset, 0, 0);
 	if (status)
-		dev_err(info->device,
-			"%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
 			__func__, status);
 #endif
+}
+
+static int ps3fb_sync(struct fb_info *info, u32 frame)
+{
+	struct ps3fb_par *par = info->par;
+	int i, error = 0;
+	u32 xres, yres;
+	u64 line_length, base;
+
+	acquire_console_sem();
+
+	if (frame > par->num_frames - 1) {
+		dev_dbg(info->device, "%s: invalid frame number (%u)\n",
+			__func__, frame);
+		error = -EINVAL;
+		goto out;
+	}
+
+	i = par->res_index;
+	xres = ps3fb_res[i].xres;
+	yres = ps3fb_res[i].yres;
+
+	line_length = xres * BPP;
+	base = frame * yres * line_length;
+
+	ps3fb_sync_image(info->device, base + par->full_offset,
+			 base + par->fb_offset, base, par->width, par->height,
+			 line_length);
 
 out:
 	release_console_sem();
 	return error;
 }
 
-
 static int ps3fb_open(struct fb_info *info, int user)
 {
 	atomic_inc(&ps3fb.f_count);
@@ -472,7 +477,6 @@ static int ps3fb_check_var(struct fb_var
 {
 	u32 line_length;
 	int mode;
-	int i;
 
 	dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres,
 		info->var.xres);
@@ -539,9 +543,7 @@ static int ps3fb_check_var(struct fb_var
 	}
 
 	/* Memory limit */
-	i = ps3fb_get_res_table(var->xres, var->yres, mode);
-	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP >
-	    ps3fb.xdr_size - VFB_OFF(i)) {
+	if (var->yres * line_length > ps3fb.xdr_size) {
 		dev_dbg(info->device, "Not enough memory\n");
 		return -ENOMEM;
 	}
@@ -559,9 +561,9 @@ static int ps3fb_check_var(struct fb_var
 static int ps3fb_set_par(struct fb_info *info)
 {
 	struct ps3fb_par *par = info->par;
-	unsigned int mode;
+	unsigned int mode, lines, maxlines;
 	int i;
-	unsigned long offset;
+	unsigned long offset, dst;
 
 	dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n",
 		info->var.xres, info->var.xres_virtual,
@@ -574,11 +576,9 @@ static int ps3fb_set_par(struct fb_info 
 	i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode);
 	par->res_index = i;
 
-	offset = VFB_OFF(i);
-	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea) + offset;
-	info->fix.smem_len = ps3fb.xdr_size - offset;
-	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
-	memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
+	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
+	info->fix.smem_len = ps3fb.xdr_size;
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea;
 
 	par->num_frames = info->fix.smem_len/
 			  (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
@@ -586,6 +586,12 @@ static int ps3fb_set_par(struct fb_info 
 	/* Keep the special bits we cannot set using fb_var_screeninfo */
 	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
 
+	par->width = info->var.xres;
+	par->height = info->var.yres;
+	offset = VP_OFF(i);
+	par->fb_offset = GPU_ALIGN_UP(offset);
+	par->full_offset = par->fb_offset - offset;
+
 	if (par->new_mode_id != par->mode_id) {
 		if (ps3av_set_video_mode(par->new_mode_id)) {
 			par->new_mode_id = par->mode_id;
@@ -594,6 +600,21 @@ static int ps3fb_set_par(struct fb_info 
 		par->mode_id = par->new_mode_id;
 	}
 
+	/* Clear XDR frame buffer memory */
+	memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
+
+	/* Clear DDR frame buffer memory */
+	lines = ps3fb_res[i].yres * par->num_frames;
+	if (par->full_offset)
+		lines++;
+	maxlines = ps3fb.xdr_size / info->fix.line_length;
+	for (dst = 0; lines; dst += maxlines * info->fix.line_length) {
+		unsigned int l = min(lines, maxlines);
+		ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l,
+				 info->fix.line_length);
+		lines -= l;
+	}
+
 	return 0;
 }
 
@@ -1005,7 +1026,6 @@ static int __devinit ps3fb_probe(struct 
 	u64 lpar_reports_size = 0;
 	u64 xdr_lpar;
 	int status, res_index;
-	unsigned long offset;
 	struct task_struct *task;
 
 	status = ps3_open_hv_device(dev);
@@ -1088,13 +1108,12 @@ static int __devinit ps3fb_probe(struct 
 	par->res_index = res_index;
 	par->num_frames = 1;
 
-	offset = VFB_OFF(res_index);
-	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea;
 	info->fbops = &ps3fb_ops;
 
 	info->fix = ps3fb_fix;
-	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea) + offset;
-	info->fix.smem_len = ps3fb.xdr_size - offset;
+	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
+	info->fix.smem_len = ps3fb.xdr_size;
 	info->pseudo_palette = par->pseudo_palette;
 	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST;
 
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 8/9] ps3fb: Add virtual screen and panning support

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:29

From: Geert Uytterhoeven <redacted>

ps3fb: Add virtual screen and panning support:
  - The vertical virtual screen size is limited by the amount of memory
    reserved for ps3fb,
  - The horizontal virtual screen size is limited to the fullscreen width,
  - Advertise that we support panning, so fbcon will use it if the virtual
    screen is enabled.
    Enabling a virtual screen (using `fbset -vyres nnn') can speed up text
    console scrolling by a factor of 10-15, depending on the video mode.

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |   65 ++++++++++++++++++++++++++++++--------------------
 1 files changed, 40 insertions(+), 25 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -141,6 +141,7 @@ struct ps3fb_par {
 	unsigned int height;
 	unsigned long full_offset;	/* start of fullscreen DDR fb */
 	unsigned long fb_offset;	/* start of actual DDR fb */
+	unsigned long pan_offset;
 };
 
 struct ps3fb_res_table {
@@ -440,8 +441,8 @@ static int ps3fb_sync(struct fb_info *in
 	base = frame * yres * line_length;
 
 	ps3fb_sync_image(info->device, base + par->full_offset,
-			 base + par->fb_offset, base, par->width, par->height,
-			 line_length);
+			 base + par->fb_offset, base + par->pan_offset,
+			 par->width, par->height, line_length);
 
 out:
 	release_console_sem();
@@ -488,27 +489,23 @@ static int ps3fb_check_var(struct fb_var
 	if (!mode)
 		return -EINVAL;
 
-	/*
-	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
-	 */
-
-	if (var->vmode & FB_VMODE_CONUPDATE) {
-		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = info->var.xoffset;
-		var->yoffset = info->var.yoffset;
-	}
+	/* Virtual screen */
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
 
-	/* Virtual screen and panning are not supported */
-	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
-	    var->xoffset || var->yoffset) {
+	if (var->xres_virtual > line_length / BPP) {
 		dev_dbg(info->device,
-			"Virtual screen and panning are not supported\n");
+			"Horizontal virtual screen size too large\n");
 		return -EINVAL;
 	}
 
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;
+	if (var->xoffset + var->xres > var->xres_virtual ||
+	    var->yoffset + var->yres > var->yres_virtual) {
+		dev_dbg(info->device, "panning out-of-range\n");
+		return -EINVAL;
+	}
 
 	/* We support ARGB8888 only */
 	if (var->bits_per_pixel > 32 || var->grayscale ||
@@ -543,7 +540,7 @@ static int ps3fb_check_var(struct fb_var
 	}
 
 	/* Memory limit */
-	if (var->yres * line_length > ps3fb.xdr_size) {
+	if (var->yres_virtual * line_length > ps3fb.xdr_size) {
 		dev_dbg(info->device, "Not enough memory\n");
 		return -ENOMEM;
 	}
@@ -561,7 +558,7 @@ static int ps3fb_check_var(struct fb_var
 static int ps3fb_set_par(struct fb_info *info)
 {
 	struct ps3fb_par *par = info->par;
-	unsigned int mode, lines, maxlines;
+	unsigned int mode, line_length, lines, maxlines;
 	int i;
 	unsigned long offset, dst;
 
@@ -569,7 +566,7 @@ static int ps3fb_set_par(struct fb_info 
 		info->var.xres, info->var.xres_virtual,
 		info->var.yres, info->var.yres_virtual, info->var.pixclock);
 
-	mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
+	mode = ps3fb_find_mode(&info->var, &line_length);
 	if (!mode)
 		return -EINVAL;
 
@@ -578,6 +575,10 @@ static int ps3fb_set_par(struct fb_info 
 
 	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
 	info->fix.smem_len = ps3fb.xdr_size;
+	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
+	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
+	info->fix.line_length = line_length;
+
 	info->screen_base = (char __iomem *)ps3fb.xdr_ea;
 
 	par->num_frames = info->fix.smem_len/
@@ -591,6 +592,8 @@ static int ps3fb_set_par(struct fb_info 
 	offset = VP_OFF(i);
 	par->fb_offset = GPU_ALIGN_UP(offset);
 	par->full_offset = par->fb_offset - offset;
+	par->pan_offset = info->var.yoffset * line_length +
+			  info->var.xoffset * BPP;
 
 	if (par->new_mode_id != par->mode_id) {
 		if (ps3av_set_video_mode(par->new_mode_id)) {
@@ -607,11 +610,11 @@ static int ps3fb_set_par(struct fb_info 
 	lines = ps3fb_res[i].yres * par->num_frames;
 	if (par->full_offset)
 		lines++;
-	maxlines = ps3fb.xdr_size / info->fix.line_length;
-	for (dst = 0; lines; dst += maxlines * info->fix.line_length) {
+	maxlines = ps3fb.xdr_size / line_length;
+	for (dst = 0; lines; dst += maxlines * line_length) {
 		unsigned int l = min(lines, maxlines);
 		ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l,
-				 info->fix.line_length);
+				 line_length);
 		lines -= l;
 	}
 
@@ -641,6 +644,16 @@ static int ps3fb_setcolreg(unsigned int 
 	return 0;
 }
 
+static int ps3fb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct ps3fb_par *par = info->par;
+
+	par->pan_offset = var->yoffset * info->fix.line_length +
+			  var->xoffset * BPP;
+	return 0;
+}
+
     /*
      *  As we have a virtual frame buffer, we need our own mmap function
      */
@@ -965,6 +978,7 @@ static struct fb_ops ps3fb_ops = {
 	.fb_check_var	= ps3fb_check_var,
 	.fb_set_par	= ps3fb_set_par,
 	.fb_setcolreg	= ps3fb_setcolreg,
+	.fb_pan_display	= ps3fb_pan_display,
 	.fb_fillrect	= sys_fillrect,
 	.fb_copyarea	= sys_copyarea,
 	.fb_imageblit	= sys_imageblit,
@@ -1115,7 +1129,8 @@ static int __devinit ps3fb_probe(struct 
 	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
 	info->fix.smem_len = ps3fb.xdr_size;
 	info->pseudo_palette = par->pseudo_palette;
-	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST;
+	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
 
 	retval = fb_alloc_cmap(&info->cmap, 256, 0);
 	if (retval < 0)
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

[patch 9/9] ps3fb: Enhance horizontal panning on firmware 1.90 and up

From: Geert Uytterhoeven <hidden>
Date: 2007-10-08 16:14:30

From: Geert Uytterhoeven <redacted>

ps3fb: Enhance horizontal panning on firmware 1.90 and up:
  - On firmware 1.90 and up, L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT supports copying
    rectangles from XDR to DDR memory with different source and destination
    line lengths. Hence larger horizontal virtual resolutions can be supported
    (up to 16368 pixels).
  - As the actual frame buffer memory layout no longer matches the entries in
    ps3fb_res[], create fake struct ps3fb_ioctl_res data for the
    PS3FB_IOCTL_SCREENINFO ioctl, so user space applications that depend on it
    keep on working.

Signed-off-by: Geert Uytterhoeven <redacted>
---
 drivers/video/ps3fb.c |  103 +++++++++++++++++++++++++++++---------------------
 1 files changed, 61 insertions(+), 42 deletions(-)
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -55,6 +55,7 @@
 #define GPU_CMD_BUF_SIZE			(64 * 1024)
 #define GPU_IOIF				(0x0d000000UL)
 #define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)
+#define GPU_MAX_LINE_LENGTH			(65536 - 64)
 
 #define PS3FB_FULL_MODE_BIT			0x80
 
@@ -335,7 +336,7 @@ static int ps3fb_get_res_table(u32 xres,
 }
 
 static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
-				    u32 *line_length)
+				    u32 *ddr_line_length, u32 *xdr_line_length)
 {
 	unsigned int i, mode;
 
@@ -350,19 +351,30 @@ static unsigned int ps3fb_find_mode(cons
 		    var->upper_margin == ps3fb_modedb[i].upper_margin &&
 		    var->lower_margin == ps3fb_modedb[i].lower_margin &&
 		    var->sync == ps3fb_modedb[i].sync &&
-		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) {
-			/* Cropped broadcast modes use the full line_length */
-			*line_length =
-			    ps3fb_modedb[i < 10 ? i + 13 : i].xres * 4;
-			/* Full broadcast modes have the full mode bit set */
-			mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
-
-			pr_debug("ps3fb_find_mode: mode %u\n", mode);
-			return mode;
-		}
+		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode)
+			goto found;
 
 	pr_debug("ps3fb_find_mode: mode not found\n");
 	return 0;
+
+found:
+	/* Cropped broadcast modes use the full line length */
+	*ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP;
+
+	if (ps3_compare_firmware_version(1, 9, 0) >= 0) {
+		*xdr_line_length = GPU_ALIGN_UP(max(var->xres,
+						    var->xres_virtual) * BPP);
+		if (*xdr_line_length > GPU_MAX_LINE_LENGTH)
+			*xdr_line_length = GPU_MAX_LINE_LENGTH;
+	} else
+		*xdr_line_length = *ddr_line_length;
+
+	/* Full broadcast modes have the full mode bit set */
+	mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
+
+	pr_debug("ps3fb_find_mode: mode %u\n", mode);
+
+	return mode;
 }
 
 static const struct fb_videomode *ps3fb_default_mode(int id)
@@ -385,9 +397,15 @@ static const struct fb_videomode *ps3fb_
 
 static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
 			     u64 dst_offset, u64 src_offset, u32 width,
-			     u32 height, u64 line_length)
+			     u32 height, u32 dst_line_length,
+			     u32 src_line_length)
 {
 	int status;
+	u64 line_length;
+
+	line_length = dst_line_length;
+	if (src_line_length != dst_line_length)
+		line_length |= (u64)src_line_length << 32;
 
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
@@ -421,8 +439,8 @@ static int ps3fb_sync(struct fb_info *in
 {
 	struct ps3fb_par *par = info->par;
 	int i, error = 0;
-	u32 xres, yres;
-	u64 line_length, base;
+	u32 ddr_line_length, xdr_line_length;
+	u64 ddr_base, xdr_base;
 
 	acquire_console_sem();
 
@@ -434,15 +452,15 @@ static int ps3fb_sync(struct fb_info *in
 	}
 
 	i = par->res_index;
-	xres = ps3fb_res[i].xres;
-	yres = ps3fb_res[i].yres;
-
-	line_length = xres * BPP;
-	base = frame * yres * line_length;
-
-	ps3fb_sync_image(info->device, base + par->full_offset,
-			 base + par->fb_offset, base + par->pan_offset,
-			 par->width, par->height, line_length);
+	xdr_line_length = info->fix.line_length;
+	ddr_line_length = ps3fb_res[i].xres * BPP;
+	xdr_base = frame * info->var.yres_virtual * xdr_line_length;
+	ddr_base = frame * ps3fb_res[i].yres * ddr_line_length;
+
+	ps3fb_sync_image(info->device, ddr_base + par->full_offset,
+			 ddr_base + par->fb_offset, xdr_base + par->pan_offset,
+			 par->width, par->height, ddr_line_length,
+			 xdr_line_length);
 
 out:
 	release_console_sem();
@@ -476,7 +494,7 @@ static int ps3fb_release(struct fb_info 
 
 static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	u32 line_length;
+	u32 xdr_line_length, ddr_line_length;
 	int mode;
 
 	dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres,
@@ -485,7 +503,7 @@ static int ps3fb_check_var(struct fb_var
 		info->var.yres);
 
 	/* FIXME For now we do exact matches only */
-	mode = ps3fb_find_mode(var, &line_length);
+	mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
 	if (!mode)
 		return -EINVAL;
 
@@ -495,7 +513,7 @@ static int ps3fb_check_var(struct fb_var
 	if (var->yres_virtual < var->yres)
 		var->yres_virtual = var->yres;
 
-	if (var->xres_virtual > line_length / BPP) {
+	if (var->xres_virtual > xdr_line_length / BPP) {
 		dev_dbg(info->device,
 			"Horizontal virtual screen size too large\n");
 		return -EINVAL;
@@ -540,7 +558,7 @@ static int ps3fb_check_var(struct fb_var
 	}
 
 	/* Memory limit */
-	if (var->yres_virtual * line_length > ps3fb.xdr_size) {
+	if (var->yres_virtual * xdr_line_length > ps3fb.xdr_size) {
 		dev_dbg(info->device, "Not enough memory\n");
 		return -ENOMEM;
 	}
@@ -558,15 +576,16 @@ static int ps3fb_check_var(struct fb_var
 static int ps3fb_set_par(struct fb_info *info)
 {
 	struct ps3fb_par *par = info->par;
-	unsigned int mode, line_length, lines, maxlines;
+	unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
 	int i;
-	unsigned long offset, dst;
+	unsigned long offset;
+	u64 dst;
 
 	dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n",
 		info->var.xres, info->var.xres_virtual,
 		info->var.yres, info->var.yres_virtual, info->var.pixclock);
 
-	mode = ps3fb_find_mode(&info->var, &line_length);
+	mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length);
 	if (!mode)
 		return -EINVAL;
 
@@ -577,12 +596,13 @@ static int ps3fb_set_par(struct fb_info 
 	info->fix.smem_len = ps3fb.xdr_size;
 	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
 	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
-	info->fix.line_length = line_length;
+	info->fix.line_length = xdr_line_length;
 
 	info->screen_base = (char __iomem *)ps3fb.xdr_ea;
 
-	par->num_frames = info->fix.smem_len/
-			  (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+	par->num_frames = ps3fb.xdr_size /
+			  max(ps3fb_res[i].yres * ddr_line_length,
+			      info->var.yres_virtual * xdr_line_length);
 
 	/* Keep the special bits we cannot set using fb_var_screeninfo */
 	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
@@ -592,7 +612,7 @@ static int ps3fb_set_par(struct fb_info 
 	offset = VP_OFF(i);
 	par->fb_offset = GPU_ALIGN_UP(offset);
 	par->full_offset = par->fb_offset - offset;
-	par->pan_offset = info->var.yoffset * line_length +
+	par->pan_offset = info->var.yoffset * xdr_line_length +
 			  info->var.xoffset * BPP;
 
 	if (par->new_mode_id != par->mode_id) {
@@ -610,11 +630,11 @@ static int ps3fb_set_par(struct fb_info 
 	lines = ps3fb_res[i].yres * par->num_frames;
 	if (par->full_offset)
 		lines++;
-	maxlines = ps3fb.xdr_size / line_length;
-	for (dst = 0; lines; dst += maxlines * line_length) {
+	maxlines = ps3fb.xdr_size / ddr_line_length;
+	for (dst = 0; lines; dst += maxlines * ddr_line_length) {
 		unsigned int l = min(lines, maxlines);
 		ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l,
-				 line_length);
+				 ddr_line_length, ddr_line_length);
 		lines -= l;
 	}
 
@@ -816,12 +836,11 @@ static int ps3fb_ioctl(struct fb_info *i
 		{
 			struct ps3fb_par *par = info->par;
 			struct ps3fb_ioctl_res res;
-			int i = par->res_index;
 			dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n");
-			res.xres = ps3fb_res[i].xres;
-			res.yres = ps3fb_res[i].yres;
-			res.xoff = ps3fb_res[i].xoff;
-			res.yoff = ps3fb_res[i].yoff;
+			res.xres = info->fix.line_length / BPP;
+			res.yres = info->var.yres_virtual;
+			res.xoff = (res.xres - info->var.xres) / 2;
+			res.yoff = (res.yres - info->var.yres) / 2;
 			res.num_frames = par->num_frames;
 			if (!copy_to_user(argp, &res, sizeof(res)))
 				retval = 0;
-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village ������������������ Da Vincilaan 7-D1 ������������������ B-1935 Zaventem ������������������ Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 ������������������ B-1840 Londerzeel ������������������ Belgium	
VAT BE 0413.825.160 ������������������ RPR Brussels	
Fortis Bank Zaventem ������������������ Swift GEBABEBB08A ������������������ IBAN BE39001382358619

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help