From: "Ville Syrjälä" <syrjala@sci.fi>
To: linux-fbdev-devel@lists.sourceforge.net
Subject: [PATCH] atyfb: vblank irq support
Date: Thu, 22 Jul 2004 21:49:37 +0300 [thread overview]
Message-ID: <20040722184937.GA11361@sci.fi> (raw)
[-- Attachment #1: Type: text/plain, Size: 323 bytes --]
This patch adds vblank interrupt support to atyfb. The added features are
FB_ACTIVATE_VBL flag for panning and FBIO_WAITFORVSYNC ioctl.
The code is basically copied from matroxfb. I've tested it on two laptops
(Mobility and LT Pro) using DirectFB.
--
Ville Syrjälä
syrjala@sci.fi
http://www.sci.fi/~syrjala/
[-- Attachment #2: atyfb-2.6-vblank_irq.patch --]
[-- Type: text/plain, Size: 9700 bytes --]
diff -urN linux/drivers/video/aty/atyfb.h linux/drivers/video/aty/atyfb.h
--- linux/drivers/video/aty/atyfb.h 2004-06-18 01:14:39.000000000 +0300
+++ linux/drivers/video/aty/atyfb.h 2004-07-22 21:08:19.000000000 +0300
@@ -3,6 +3,8 @@
*/
#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
/*
* Elements of the hardware specific atyfb_par structure
*/
@@ -33,6 +35,12 @@
#endif
};
+struct aty_interrupt {
+ wait_queue_head_t wait;
+ unsigned int count;
+ int pan_display;
+};
+
struct pll_info {
int pll_max;
int pll_min;
@@ -142,8 +150,8 @@
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
u8 mmaped;
- int open;
#endif
+ int open;
#ifdef CONFIG_FB_ATY_GENERIC_LCD
unsigned long bios_base_phys;
unsigned long bios_base;
@@ -166,6 +174,10 @@
#endif
unsigned long aux_start; /* auxiliary aperture */
unsigned long aux_size;
+ struct aty_interrupt vblank;
+ unsigned long irq_flags;
+ unsigned int irq;
+ spinlock_t int_lock;
};
/*
diff -urN linux/drivers/video/aty/atyfb_base.c linux/drivers/video/aty/atyfb_base.c
--- linux/drivers/video/aty/atyfb_base.c 2004-06-18 01:14:39.000000000 +0300
+++ linux/drivers/video/aty/atyfb_base.c 2004-07-22 21:26:36.633215432 +0300
@@ -62,6 +62,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -1441,7 +1444,6 @@
u32 bpp = info->var.bits_per_pixel;
par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
- aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
}
@@ -1451,26 +1453,103 @@
static int atyfb_open(struct fb_info *info, int user)
{
-#ifdef __sparc__
struct atyfb_par *par = (struct atyfb_par *) info->par;
if (user) {
par->open++;
+#ifdef __sparc__
par->mmaped = 0;
- }
#endif
+ }
return (0);
}
+static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp)
+{
+ struct atyfb_par *par = dev_id;
+ int handled = 0;
+ u32 int_cntl;
+
+ spin_lock(&par->int_lock);
+
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
+
+ if (int_cntl & CRTC_VBLANK_INT) {
+ /* clear interrupt */
+ aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);
+ par->vblank.count++;
+ if (par->vblank.pan_display) {
+ par->vblank.pan_display = 0;
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+ }
+ wake_up_interruptible(&par->vblank.wait);
+ handled = 1;
+ }
+
+ spin_unlock(&par->int_lock);
+
+ return IRQ_RETVAL(handled);
+}
+
+static int aty_enable_irq(struct atyfb_par *par, int reenable)
+{
+ u32 int_cntl;
+
+ if (!test_and_set_bit(0, &par->irq_flags)) {
+ if (request_irq(par->irq, aty_irq, SA_SHIRQ, "atyfb", par)) {
+ clear_bit(0, &par->irq_flags);
+ return -EINVAL;
+ }
+ spin_lock_irq(&par->int_lock);
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+ /* clear interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
+ /* enable interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
+ spin_unlock_irq(&par->int_lock);
+ } else if (reenable) {
+ spin_lock_irq(&par->int_lock);
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+ if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
+ printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);
+ /* re-enable interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );
+ }
+ spin_unlock_irq(&par->int_lock);
+ }
+
+ return 0;
+}
+
+static int aty_disable_irq(struct atyfb_par *par)
+{
+ u32 int_cntl;
+
+ if (test_and_clear_bit(0, &par->irq_flags)) {
+ if (par->vblank.pan_display) {
+ par->vblank.pan_display = 0;
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+ }
+ spin_lock_irq(&par->int_lock);
+ int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+ /* disable interrupt */
+ aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );
+ spin_unlock_irq(&par->int_lock);
+ free_irq(par->irq, par);
+ }
+
+ return 0;
+}
+
static int atyfb_release(struct fb_info *info, int user)
{
-#ifdef __sparc__
struct atyfb_par *par = (struct atyfb_par *) info->par;
if (user) {
par->open--;
mdelay(1);
wait_for_idle(par);
if (!par->open) {
+#ifdef __sparc__
int was_mmaped = par->mmaped;
par->mmaped = 0;
@@ -1495,9 +1574,10 @@
var.yres_virtual = var.yres;
}
}
+#endif
+ aty_disable_irq(par);
}
}
-#endif
return (0);
}
@@ -1524,10 +1604,50 @@
info->var.yoffset = yoffset;
if (par->asleep)
return 0;
+
set_off_pitch(par, info);
+ if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
+ par->vblank.pan_display = 1;
+ } else {
+ par->vblank.pan_display = 0;
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+ }
+
+ return 0;
+}
+
+static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
+{
+ struct aty_interrupt *vbl;
+ unsigned int count;
+ int ret;
+
+ switch (crtc) {
+ case 0:
+ vbl = &par->vblank;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ ret = aty_enable_irq(par, 0);
+ if (ret)
+ return ret;
+
+ count = vbl->count;
+ ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ aty_enable_irq(par, 1);
+ return -ETIMEDOUT;
+ }
+
return 0;
}
+
#ifdef DEBUG
#define ATYIO_CLKR 0x41545900 /* ATY\00 */
#define ATYIO_CLKW 0x41545901 /* ATY\01 */
@@ -1552,12 +1672,14 @@
#define ATYIO_FEATW 0x41545903 /* ATY\03 */
#endif
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, struct fb_info *info)
{
-#if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT))
struct atyfb_par *par = (struct atyfb_par *) info->par;
-#endif /* __sparc__ || DEBUG */
#ifdef __sparc__
struct fbtype fbtyp;
#endif
@@ -1575,6 +1697,18 @@
return -EFAULT;
break;
#endif /* __sparc__ */
+
+ case FBIO_WAITFORVSYNC:
+ {
+ u32 crtc;
+
+ if (get_user(crtc, (__u32 *) arg))
+ return -EFAULT;
+
+ return aty_waitforvblank(par, crtc);
+ }
+ break;
+
#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
case ATYIO_CLKR:
if (M64_HAS(INTEGRATED)) {
@@ -1771,6 +1905,7 @@
info->var.yoffset = atyfb_save.yoffset;
set_off_pitch(par, info);
}
+ aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
break;
}
}
@@ -2005,6 +2140,9 @@
int sense;
#endif
+ init_waitqueue_head(&par->vblank.wait);
+ spin_lock_init(&par->int_lock);
+
par->aty_cmap_regs =
(struct aty_cmap_regs *) (par->ati_regbase + 0xc0);
@@ -3207,6 +3345,8 @@
info->fix = atyfb_fix;
par->pci_id = aty_chips[i].pci_id;
+ par->irq = pdev->irq;
+
/* Reserve space */
par->res_start = rp->start;
par->res_size = rp->end - rp->start + 1;
@@ -3300,6 +3440,8 @@
info->fix = atyfb_fix;
+ par->irq = (unsigned int) -1; /* something invalid */
+
/*
* Map the video memory (physical address given) to somewhere in the
* kernel address space.
diff -urN linux/include/video/mach64.h linux/include/video/mach64.h
--- linux/include/video/mach64.h 2004-06-18 01:14:39.000000000 +0300
+++ linux/include/video/mach64.h 2004-07-13 19:52:39.000000000 +0300
@@ -630,10 +630,70 @@
#define CRTC_CUR_B_TEST 0x80000000
#define CRTC_CRNT_VLINE 0x07f00000
-#define CRTC_VBLANK 0x00000001
#define CRTC_PRESERVED_MASK 0x0001f000
+#define CRTC_VBLANK 0x00000001
+#define CRTC_VBLANK_INT_EN 0x00000002
+#define CRTC_VBLANK_INT 0x00000004
+#define CRTC_VBLANK_INT_AK CRTC_VBLANK_INT
+#define CRTC_VLINE_INT_EN 0x00000008
+#define CRTC_VLINE_INT 0x00000010
+#define CRTC_VLINE_INT_AK CRTC_VLINE_INT
+#define CRTC_VLINE_SYNC 0x00000020
+#define CRTC_FRAME 0x00000040
+#define SNAPSHOT_INT_EN 0x00000080
+#define SNAPSHOT_INT 0x00000100
+#define SNAPSHOT_INT_AK SNAPSHOT_INT
+#define I2C_INT_EN 0x00000200
+#define I2C_INT 0x00000400
+#define I2C_INT_AK I2C_INT
+#define CRTC2_VBLANK 0x00000800
+#define CRTC2_VBLANK_INT_EN 0x00001000
+#define CRTC2_VBLANK_INT 0x00002000
+#define CRTC2_VBLANK_INT_AK CRTC2_VBLANK_INT
+#define CRTC2_VLINE_INT_EN 0x00004000
+#define CRTC2_VLINE_INT 0x00008000
+#define CRTC2_VLINE_INT_AK CRTC2_VLINE_INT
+#define CAPBUF0_INT_EN 0x00010000
+#define CAPBUF0_INT 0x00020000
+#define CAPBUF0_INT_AK CAPBUF0_INT
+#define CAPBUF1_INT_EN 0x00040000
+#define CAPBUF1_INT 0x00080000
+#define CAPBUF1_INT_AK CAPBUF1_INT
+#define OVERLAY_EOF_INT_EN 0x00100000
+#define OVERLAY_EOF_INT 0x00200000
+#define OVERLAY_EOF_INT_AK OVERLAY_EOF_INT
+#define ONESHOT_CAP_INT_EN 0x00400000
+#define ONESHOT_CAP_INT 0x00800000
+#define ONESHOT_CAP_INT_AK ONESHOT_CAP_INT
+#define BUSMASTER_EOL_INT_EN 0x01000000
+#define BUSMASTER_EOL_INT 0x02000000
+#define BUSMASTER_EOL_INT_AK BUSMASTER_EOL_INT
+#define GP_INT_EN 0x04000000
+#define GP_INT 0x08000000
+#define GP_INT_AK GP_INT
+#define CRTC2_VLINE_SYNC 0x10000000
+#define SNAPSHOT2_INT_EN 0x20000000
+#define SNAPSHOT2_INT 0x40000000
+#define SNAPSHOT2_INT_AK SNAPSHOT2_INT
+#define VBLANK_BIT2_INT 0x80000000
+#define VBLANK_BIT2_INT_AK VBLANK_BIT2_INT
+
+#define CRTC_INT_EN_MASK (CRTC_VBLANK_INT_EN | \
+ CRTC_VLINE_INT_EN | \
+ SNAPSHOT_INT_EN | \
+ I2C_INT_EN | \
+ CRTC2_VBLANK_INT_EN | \
+ CRTC2_VLINE_INT_EN | \
+ CAPBUF0_INT_EN | \
+ CAPBUF1_INT_EN | \
+ OVERLAY_EOF_INT_EN | \
+ ONESHOT_CAP_INT_EN | \
+ BUSMASTER_EOL_INT_EN | \
+ GP_INT_EN | \
+ SNAPSHOT2_INT_EN)
+
/* DAC control values */
#define DAC_EXT_SEL_RS2 0x01
next reply other threads:[~2004-07-22 18:49 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-07-22 18:49 Ville Syrjälä [this message]
2004-07-24 23:12 ` [PATCH] atyfb: vblank irq support Alexander Kern
2004-07-25 0:03 ` Antonino A. Daplas
2004-07-25 18:36 ` Alexander Kern
2004-07-25 22:47 ` Antonino A. Daplas
2004-07-30 18:12 ` [Question] Colour management Alexander Kern
2004-07-31 10:26 ` Antonino A. Daplas
2004-07-31 13:31 ` Ville Syrjälä
2004-07-31 21:19 ` Antonino A. Daplas
2004-07-31 22:19 ` Alexander Kern
2004-07-31 23:37 ` Antonino A. Daplas
2004-07-31 22:18 ` Ville Syrjälä
2004-07-31 23:47 ` Antonino A. Daplas
2004-07-31 22:10 ` Ville Syrjälä
2004-08-01 1:03 ` Antonino A. Daplas
2004-07-25 10:16 ` [PATCH] atyfb: vblank irq support Ville Syrjälä
2004-07-25 18:29 ` Alexander Kern
2004-07-25 23:36 ` Ville Syrjälä
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040722184937.GA11361@sci.fi \
--to=syrjala@sci.fi \
--cc=linux-fbdev-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).