#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 <asm/ps3.h>
#ifdef PS3FB_DEBUG
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args)
#else
#define DPRINTK(fmt, args...)
#endif
u64 context_handle, memory_handle;
void *xdr_ea;
struct gpu_driver_info *dinfo;
- struct semaphore sem;
u32 res_index;
u64 vblank_count; /* frame count */
atomic_t ext_flip; /* on/off flip with vsync */
atomic_t f_count; /* fb_open count */
int is_blanked;
+ int is_kicked;
+ struct task_struct *task;
};
static struct ps3fb_priv ps3fb;
#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)
-static int ps3fb_mode = 0;
+static int ps3fb_mode;
module_param(ps3fb_mode, bool, 0);
-static char *mode_option __initdata = NULL;
+static char *mode_option __initdata;
static int ps3fb_get_res_table(u32 xres, u32 yres)
if (frame > ps3fb.num_frames - 1) {
printk(KERN_WARNING "%s: invalid frame number (%u)\n",
- __FUNCTION__, frame);
+ __func__, frame);
return -EINVAL;
}
offset = xres * yres * BPP * frame;
(xres << 16) | yres,
xres * BPP); /* line_length */
if (status)
- printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
- __FUNCTION__, status);
+ printk(KERN_ERR
+ "%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",
- __FUNCTION__, status);
+ printk(KERN_ERR
+ "%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",
- __FUNCTION__, status);
+ printk(KERN_ERR
+ "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+ __func__, status);
#endif
return 0;
}
{
int retval;
- DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+ DPRINTK("%s: blank:%d\n", __func__, blank);
switch (blank) {
case FB_BLANK_POWERDOWN:
case FB_BLANK_HSYNC_SUSPEND:
void ps3fb_flip_ctl(int on)
{
- if (on) {
- if (atomic_read(&ps3fb.ext_flip) > 0) {
- atomic_dec(&ps3fb.ext_flip);
- }
- } else {
+ if (on)
+ atomic_dec_if_positive(&ps3fb.ext_flip);
+ else
atomic_inc(&ps3fb.ext_flip);
- }
}
EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
if (copy_from_user(&val, argp, sizeof(val)))
break;
+ if (!(val & PS3AV_MODE_MASK)) {
+ u32 id = ps3av_get_auto_mode(0);
+ if (id > 0)
+ val = (val & ~PS3AV_MODE_MASK) | id;
+ }
DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
retval = -EINVAL;
old_mode = ps3fb_mode;
case PS3FB_IOCTL_OFF:
DPRINTK("PS3FB_IOCTL_OFF:\n");
- if (atomic_read(&ps3fb.ext_flip) > 0)
- atomic_dec(&ps3fb.ext_flip);
+ atomic_dec_if_positive(&ps3fb.ext_flip);
retval = 0;
break;
static int ps3fbd(void *arg)
{
- daemonize("ps3fbd");
- for (;;) {
- down(&ps3fb.sem);
- if (atomic_read(&ps3fb.ext_flip) == 0)
+ 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 */
+ }
+ schedule();
}
return 0;
}
status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
if (status) {
printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
- __FUNCTION__, status);
+ __func__, status);
return IRQ_NONE;
}
if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
/* VSYNC */
ps3fb.vblank_count = head->vblank_count;
- if (!ps3fb.is_blanked)
- up(&ps3fb.sem);
+ if (ps3fb.task && !ps3fb.is_blanked &&
+ !atomic_read(&ps3fb.ext_flip)) {
+ ps3fb.is_kicked = 1;
+ wake_up_process(ps3fb.task);
+ }
wake_up_interruptible(&ps3fb.wait_vsync);
}
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", __FUNCTION__,
+ printk(KERN_ERR "%s: version_driver err:%x\n", __func__,
dinfo->version_driver);
return -EINVAL;
}
error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
&ps3fb.irq_no);
if (error) {
- printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+ printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__,
error);
return error;
}
error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
"ps3fb vsync", ps3fb.dev);
if (error) {
- printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+ printk(KERN_ERR "%s: request_irq failed %d\n", __func__,
error);
ps3_free_irq(ps3fb.irq_no);
return error;
xdr_lpar, ps3fb_videomemory.size, 0);
if (status) {
printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
- __FUNCTION__, status);
+ __func__, status);
return -ENXIO;
}
DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
xdr_lpar, ps3fb_videomemory.size,
GPU_IOIF, 0);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
- __FUNCTION__, status);
+ printk(KERN_ERR
+ "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+ __func__, status);
return -ENXIO;
}
return 0;
u64 xdr_lpar;
int status;
unsigned long offset;
+ struct task_struct *task;
/* 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",
- __FUNCTION__, status);
+ __func__, status);
goto err;
}
DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
&lpar_reports, &lpar_reports_size);
if (status) {
printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
- __FUNCTION__, status);
+ __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", __FUNCTION__);
+ printk(KERN_ERR "%s: ioremap failed\n", __func__);
goto err_gpu_context_free;
}
"fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
info->node, ps3fb_videomemory.size >> 10);
- kernel_thread(ps3fbd, info, CLONE_KERNEL);
+ task = kthread_run(ps3fbd, info, "ps3fbd");
+ if (IS_ERR(task)) {
+ retval = PTR_ERR(task);
+ goto err_unregister_framebuffer;
+ }
+
+ ps3fb.task = task;
+
return 0;
+err_unregister_framebuffer:
+ unregister_framebuffer(info);
err_fb_dealloc:
fb_dealloc_cmap(&info->cmap);
err_framebuffer_release:
{
int status;
+ if (ps3fb.task) {
+ struct task_struct *task = ps3fb.task;
+ ps3fb.task = NULL;
+ kthread_stop(task);
+ }
if (ps3fb.irq_no) {
free_irq(ps3fb.irq_no, ps3fb.dev);
ps3_free_irq(ps3fb.irq_no);
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",
- __FUNCTION__, status);
+ printk(KERN_ERR
+ "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+ __func__, status);
return -1;
}
#endif
1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
if (status) {
- printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
- __FUNCTION__, status);
+ printk(KERN_ERR
+ "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+ __func__, status);
return -1;
}
#endif
error = ps3av_dev_open();
if (error) {
- printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+ printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__);
goto err;
}
atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */
atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */
- init_MUTEX(&ps3fb.sem);
init_waitqueue_head(&ps3fb.wait_vsync);
ps3fb.num_frames = 1;