All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Dooks <ben@simtec.co.uk>
To: linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v3 06/12] s3c-fb: Add wait for VSYNC ioctl
Date: Fri, 02 Jul 2010 11:37:00 +0000	[thread overview]
Message-ID: <4C2DCF5C.4020600@simtec.co.uk> (raw)
In-Reply-To: <1277712538-23188-7-git-send-email-p.osciak@samsung.com>

On 28/06/10 09:08, Pawel Osciak wrote:
> Add VSYNC interrupt support and an ioctl that allows waiting for it.
> Interrupts are turned on only when needed.
> 
> Signed-off-by: Pawel Osciak <p.osciak@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  arch/arm/plat-samsung/include/plat/regs-fb.h |    1 +
>  drivers/video/s3c-fb.c                       |  167 +++++++++++++++++++++++++-
>  2 files changed, 167 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
> index f454e32..5bcdd09 100644
> --- a/arch/arm/plat-samsung/include/plat/regs-fb.h
> +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
> @@ -298,6 +298,7 @@
>  #define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
>  
>  #define VIDINTCON0_FRAMESEL1			(1 << 13)
> +#define VIDINTCON0_FRAMESEL1_MASK		(0x3 << 13)
>  #define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 13)
>  #define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 13)
>  #define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 13)
> diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
> index 4f3680d..6131ebb 100644
> --- a/drivers/video/s3c-fb.c
> +++ b/drivers/video/s3c-fb.c
> @@ -21,6 +21,8 @@
>  #include <linux/clk.h>
>  #include <linux/fb.h>
>  #include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/interrupt.h>
>  
>  #include <mach/map.h>
>  #include <plat/regs-fb-v4.h>
> @@ -48,6 +50,11 @@
>  	__raw_writel(v, r); } while(0)
>  #endif /* FB_S3C_DEBUG_REGWRITE */
>  
> +/* irq_flags bits */
> +#define S3C_FB_VSYNC_IRQ_EN	0
> +
> +#define VSYNC_TIMEOUT_MSEC 50
> +
>  struct s3c_fb;
>  
>  #define VALID_BPP(x) (1 << ((x) - 1))
> @@ -156,6 +163,16 @@ struct s3c_fb_win {
>  };
>  
>  /**
> + * struct s3c_fb_vsync - vsync information
> + * @wait:	a queue for processes waiting for vsync
> + * @count:	vsync interrupt count
> + */
> +struct s3c_fb_vsync {
> +	wait_queue_head_t	wait;
> +	unsigned int		count;
> +};
> +
> +/**
>   * struct s3c_fb - overall hardware state of the hardware
>   * @dev: The device that we bound to, for printing, etc.
>   * @regs_res: The resource we claimed for the IO registers.
> @@ -165,6 +182,9 @@ struct s3c_fb_win {
>   * @enabled: A bitmask of enabled hardware windows.
>   * @pdata: The platform configuration data passed with the device.
>   * @windows: The hardware windows that have been claimed.
> + * @irq_no: IRQ line number
> + * @irq_flags: irq flags
> + * @vsync_info: VSYNC-related information (count, queues...)
>   */
>  struct s3c_fb {
>  	struct device		*dev;
> @@ -177,6 +197,10 @@ struct s3c_fb {
>  
>  	struct s3c_fb_platdata	*pdata;
>  	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
> +
> +	int			 irq_no;
> +	unsigned long		 irq_flags;
> +	struct s3c_fb_vsync	 vsync_info;
>  };
>  
>  /**
> @@ -801,6 +825,124 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
>  	return 0;
>  }
>  
> +/**
> + * s3c_fb_enable_irq() - enable framebuffer interrupts
> + * @sfb: main hardware state
> + */
> +static void s3c_fb_enable_irq(struct s3c_fb *sfb)
> +{
> +	void __iomem *regs = sfb->regs;
> +	u32 irq_ctrl_reg;
> +
> +	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
> +		/* IRQ disabled, enable it */
> +		irq_ctrl_reg = readl(regs + VIDINTCON0);
> +
> +		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
> +		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
> +
> +		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
> +		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
> +		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
> +		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
> +
> +		writel(irq_ctrl_reg, regs + VIDINTCON0);
> +	}
> +}

there should probably be some form of locking so that an irq
doesn't come through and disable this. possibly in the call
that queues the request to reduce the likelyhood of any races.

> +
> +/**
> + * s3c_fb_disable_irq() - disable framebuffer interrupts
> + * @sfb: main hardware state
> + */
> +static void s3c_fb_disable_irq(struct s3c_fb *sfb)
> +{
> +	void __iomem *regs = sfb->regs;
> +	u32 irq_ctrl_reg;
> +
> +	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
> +		/* IRQ enabled, disable it */
> +		irq_ctrl_reg = readl(regs + VIDINTCON0);
> +
> +		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
> +		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
> +
> +		writel(irq_ctrl_reg, regs + VIDINTCON0);
> +	}
> +}
> +
> +static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
> +{
> +	struct s3c_fb *sfb = dev_id;
> +	void __iomem  *regs = sfb->regs;
> +	u32 irq_sts_reg;
> +
> +	irq_sts_reg = readl(regs + VIDINTCON1);
> +
> +	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
> +
> +		/* VSYNC interrupt, accept it */
> +		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
> +
> +		sfb->vsync_info.count++;
> +		wake_up_interruptible(&sfb->vsync_info.wait);
> +	}
> +
> +	/* We only support waiting for VSYNC for now, so it's safe
> +	 * to always disable irqs here.
> +	 */
> +	s3c_fb_disable_irq(sfb);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
> + * @sfb: main hardware state
> + * @crtc: head index.
> + */
> +static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
> +{
> +	unsigned long count;
> +	int ret;
> +
> +	if (crtc != 0)
> +		return -ENODEV;
> +
> +	s3c_fb_enable_irq(sfb);
> +	count = sfb->vsync_info.count;

possibly doing count before enabling the irq.

> +	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
> +				       count != sfb->vsync_info.count,
> +				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
> +	if (ret = 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
> +			unsigned long arg)
> +{
> +	struct s3c_fb_win *win = info->par;
> +	struct s3c_fb *sfb = win->parent;
> +	int ret;
> +	u32 crtc;
> +
> +	switch (cmd) {
> +	case FBIO_WAITFORVSYNC:
> +		if (get_user(crtc, (u32 __user *)arg)) {
> +			ret = -EFAULT;
> +			break;
> +		}

can't find any info on what the argument is meant to be.

> +
> +		ret = s3c_fb_wait_for_vsync(sfb, crtc);
> +		break;
> +	default:
> +		ret = -ENOTTY;

Can someone else confirm this is the correct err?

> +	}
> +
> +	return ret;
> +}
> +
>  static struct fb_ops s3c_fb_ops = {
>  	.owner		= THIS_MODULE,
>  	.fb_check_var	= s3c_fb_check_var,
> @@ -811,6 +953,7 @@ static struct fb_ops s3c_fb_ops = {
>  	.fb_copyarea	= cfb_copyarea,
>  	.fb_imageblit	= cfb_imageblit,
>  	.fb_pan_display	= s3c_fb_pan_display,
> +	.fb_ioctl	= s3c_fb_ioctl,
>  };
>  
>  /**
> @@ -917,6 +1060,8 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
>  
>  	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
>  
> +	init_waitqueue_head(&sfb->vsync_info.wait);
> +
>  	palette_size = variant->palette_sz * 4;
>  
>  	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
> @@ -1096,6 +1241,20 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  		goto err_req_region;
>  	}
>  
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!res) {
> +		dev_err(dev, "failed to acquire irq resource\n");
> +		ret = -ENOENT;
> +		goto err_ioremap;
> +	}
> +	sfb->irq_no = res->start;
> +	ret = request_irq(sfb->irq_no, s3c_fb_irq,
> +			  0, "s3c_fb", sfb);
> +	if (ret) {
> +		dev_err(dev, "irq request failed\n");
> +		goto err_ioremap;
> +	}
> +
>  	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
>  
>  	/* setup gpio and output polarity controls */
> @@ -1130,7 +1289,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  			dev_err(dev, "failed to create window %d\n", win);
>  			for (; win >= 0; win--)
>  				s3c_fb_release_win(sfb, sfb->windows[win]);
> -			goto err_ioremap;
> +			goto err_irq;
>  		}
>  	}
>  
> @@ -1138,6 +1297,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  
>  	return 0;
>  
> +err_irq:
> +	free_irq(sfb->irq_no, sfb);
> +
>  err_ioremap:
>  	iounmap(sfb->regs);
>  
> @@ -1170,6 +1332,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
>  		if (sfb->windows[win])
>  			s3c_fb_release_win(sfb, sfb->windows[win]);
>  
> +	free_irq(sfb->irq_no, sfb);
> +
>  	iounmap(sfb->regs);
>  
>  	clk_disable(sfb->bus_clk);
> @@ -1370,6 +1534,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 __devinitdata = {
>  			[3] = 0x3000,
>  			[4] = 0x3400,
>  		},
> +
>  	},

oops, added whitespace.

>  	.win[0]	= &s3c_fb_data_64xx_wins[0],
>  	.win[1]	= &s3c_fb_data_64xx_wins[1],


WARNING: multiple messages have this Message-ID (diff)
From: Ben Dooks <ben@simtec.co.uk>
To: Pawel Osciak <p.osciak@samsung.com>
Cc: linux-fbdev@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, kyungmin.park@samsung.com,
	ben-linux@fluff.org, m.szyprowski@samsung.com
Subject: Re: [PATCH v3 06/12] s3c-fb: Add wait for VSYNC ioctl
Date: Fri, 02 Jul 2010 12:37:00 +0100	[thread overview]
Message-ID: <4C2DCF5C.4020600@simtec.co.uk> (raw)
In-Reply-To: <1277712538-23188-7-git-send-email-p.osciak@samsung.com>

On 28/06/10 09:08, Pawel Osciak wrote:
> Add VSYNC interrupt support and an ioctl that allows waiting for it.
> Interrupts are turned on only when needed.
> 
> Signed-off-by: Pawel Osciak <p.osciak@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  arch/arm/plat-samsung/include/plat/regs-fb.h |    1 +
>  drivers/video/s3c-fb.c                       |  167 +++++++++++++++++++++++++-
>  2 files changed, 167 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
> index f454e32..5bcdd09 100644
> --- a/arch/arm/plat-samsung/include/plat/regs-fb.h
> +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
> @@ -298,6 +298,7 @@
>  #define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
>  
>  #define VIDINTCON0_FRAMESEL1			(1 << 13)
> +#define VIDINTCON0_FRAMESEL1_MASK		(0x3 << 13)
>  #define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 13)
>  #define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 13)
>  #define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 13)
> diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
> index 4f3680d..6131ebb 100644
> --- a/drivers/video/s3c-fb.c
> +++ b/drivers/video/s3c-fb.c
> @@ -21,6 +21,8 @@
>  #include <linux/clk.h>
>  #include <linux/fb.h>
>  #include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/interrupt.h>
>  
>  #include <mach/map.h>
>  #include <plat/regs-fb-v4.h>
> @@ -48,6 +50,11 @@
>  	__raw_writel(v, r); } while(0)
>  #endif /* FB_S3C_DEBUG_REGWRITE */
>  
> +/* irq_flags bits */
> +#define S3C_FB_VSYNC_IRQ_EN	0
> +
> +#define VSYNC_TIMEOUT_MSEC 50
> +
>  struct s3c_fb;
>  
>  #define VALID_BPP(x) (1 << ((x) - 1))
> @@ -156,6 +163,16 @@ struct s3c_fb_win {
>  };
>  
>  /**
> + * struct s3c_fb_vsync - vsync information
> + * @wait:	a queue for processes waiting for vsync
> + * @count:	vsync interrupt count
> + */
> +struct s3c_fb_vsync {
> +	wait_queue_head_t	wait;
> +	unsigned int		count;
> +};
> +
> +/**
>   * struct s3c_fb - overall hardware state of the hardware
>   * @dev: The device that we bound to, for printing, etc.
>   * @regs_res: The resource we claimed for the IO registers.
> @@ -165,6 +182,9 @@ struct s3c_fb_win {
>   * @enabled: A bitmask of enabled hardware windows.
>   * @pdata: The platform configuration data passed with the device.
>   * @windows: The hardware windows that have been claimed.
> + * @irq_no: IRQ line number
> + * @irq_flags: irq flags
> + * @vsync_info: VSYNC-related information (count, queues...)
>   */
>  struct s3c_fb {
>  	struct device		*dev;
> @@ -177,6 +197,10 @@ struct s3c_fb {
>  
>  	struct s3c_fb_platdata	*pdata;
>  	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
> +
> +	int			 irq_no;
> +	unsigned long		 irq_flags;
> +	struct s3c_fb_vsync	 vsync_info;
>  };
>  
>  /**
> @@ -801,6 +825,124 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
>  	return 0;
>  }
>  
> +/**
> + * s3c_fb_enable_irq() - enable framebuffer interrupts
> + * @sfb: main hardware state
> + */
> +static void s3c_fb_enable_irq(struct s3c_fb *sfb)
> +{
> +	void __iomem *regs = sfb->regs;
> +	u32 irq_ctrl_reg;
> +
> +	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
> +		/* IRQ disabled, enable it */
> +		irq_ctrl_reg = readl(regs + VIDINTCON0);
> +
> +		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
> +		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
> +
> +		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
> +		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
> +		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
> +		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
> +
> +		writel(irq_ctrl_reg, regs + VIDINTCON0);
> +	}
> +}

there should probably be some form of locking so that an irq
doesn't come through and disable this. possibly in the call
that queues the request to reduce the likelyhood of any races.

> +
> +/**
> + * s3c_fb_disable_irq() - disable framebuffer interrupts
> + * @sfb: main hardware state
> + */
> +static void s3c_fb_disable_irq(struct s3c_fb *sfb)
> +{
> +	void __iomem *regs = sfb->regs;
> +	u32 irq_ctrl_reg;
> +
> +	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
> +		/* IRQ enabled, disable it */
> +		irq_ctrl_reg = readl(regs + VIDINTCON0);
> +
> +		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
> +		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
> +
> +		writel(irq_ctrl_reg, regs + VIDINTCON0);
> +	}
> +}
> +
> +static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
> +{
> +	struct s3c_fb *sfb = dev_id;
> +	void __iomem  *regs = sfb->regs;
> +	u32 irq_sts_reg;
> +
> +	irq_sts_reg = readl(regs + VIDINTCON1);
> +
> +	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
> +
> +		/* VSYNC interrupt, accept it */
> +		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
> +
> +		sfb->vsync_info.count++;
> +		wake_up_interruptible(&sfb->vsync_info.wait);
> +	}
> +
> +	/* We only support waiting for VSYNC for now, so it's safe
> +	 * to always disable irqs here.
> +	 */
> +	s3c_fb_disable_irq(sfb);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
> + * @sfb: main hardware state
> + * @crtc: head index.
> + */
> +static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
> +{
> +	unsigned long count;
> +	int ret;
> +
> +	if (crtc != 0)
> +		return -ENODEV;
> +
> +	s3c_fb_enable_irq(sfb);
> +	count = sfb->vsync_info.count;

possibly doing count before enabling the irq.

> +	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
> +				       count != sfb->vsync_info.count,
> +				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
> +	if (ret == 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
> +			unsigned long arg)
> +{
> +	struct s3c_fb_win *win = info->par;
> +	struct s3c_fb *sfb = win->parent;
> +	int ret;
> +	u32 crtc;
> +
> +	switch (cmd) {
> +	case FBIO_WAITFORVSYNC:
> +		if (get_user(crtc, (u32 __user *)arg)) {
> +			ret = -EFAULT;
> +			break;
> +		}

can't find any info on what the argument is meant to be.

> +
> +		ret = s3c_fb_wait_for_vsync(sfb, crtc);
> +		break;
> +	default:
> +		ret = -ENOTTY;

Can someone else confirm this is the correct err?

> +	}
> +
> +	return ret;
> +}
> +
>  static struct fb_ops s3c_fb_ops = {
>  	.owner		= THIS_MODULE,
>  	.fb_check_var	= s3c_fb_check_var,
> @@ -811,6 +953,7 @@ static struct fb_ops s3c_fb_ops = {
>  	.fb_copyarea	= cfb_copyarea,
>  	.fb_imageblit	= cfb_imageblit,
>  	.fb_pan_display	= s3c_fb_pan_display,
> +	.fb_ioctl	= s3c_fb_ioctl,
>  };
>  
>  /**
> @@ -917,6 +1060,8 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
>  
>  	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
>  
> +	init_waitqueue_head(&sfb->vsync_info.wait);
> +
>  	palette_size = variant->palette_sz * 4;
>  
>  	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
> @@ -1096,6 +1241,20 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  		goto err_req_region;
>  	}
>  
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!res) {
> +		dev_err(dev, "failed to acquire irq resource\n");
> +		ret = -ENOENT;
> +		goto err_ioremap;
> +	}
> +	sfb->irq_no = res->start;
> +	ret = request_irq(sfb->irq_no, s3c_fb_irq,
> +			  0, "s3c_fb", sfb);
> +	if (ret) {
> +		dev_err(dev, "irq request failed\n");
> +		goto err_ioremap;
> +	}
> +
>  	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
>  
>  	/* setup gpio and output polarity controls */
> @@ -1130,7 +1289,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  			dev_err(dev, "failed to create window %d\n", win);
>  			for (; win >= 0; win--)
>  				s3c_fb_release_win(sfb, sfb->windows[win]);
> -			goto err_ioremap;
> +			goto err_irq;
>  		}
>  	}
>  
> @@ -1138,6 +1297,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  
>  	return 0;
>  
> +err_irq:
> +	free_irq(sfb->irq_no, sfb);
> +
>  err_ioremap:
>  	iounmap(sfb->regs);
>  
> @@ -1170,6 +1332,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
>  		if (sfb->windows[win])
>  			s3c_fb_release_win(sfb, sfb->windows[win]);
>  
> +	free_irq(sfb->irq_no, sfb);
> +
>  	iounmap(sfb->regs);
>  
>  	clk_disable(sfb->bus_clk);
> @@ -1370,6 +1534,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 __devinitdata = {
>  			[3] = 0x3000,
>  			[4] = 0x3400,
>  		},
> +
>  	},

oops, added whitespace.

>  	.win[0]	= &s3c_fb_data_64xx_wins[0],
>  	.win[1]	= &s3c_fb_data_64xx_wins[1],

WARNING: multiple messages have this Message-ID (diff)
From: ben@simtec.co.uk (Ben Dooks)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 06/12] s3c-fb: Add wait for VSYNC ioctl
Date: Fri, 02 Jul 2010 12:37:00 +0100	[thread overview]
Message-ID: <4C2DCF5C.4020600@simtec.co.uk> (raw)
In-Reply-To: <1277712538-23188-7-git-send-email-p.osciak@samsung.com>

On 28/06/10 09:08, Pawel Osciak wrote:
> Add VSYNC interrupt support and an ioctl that allows waiting for it.
> Interrupts are turned on only when needed.
> 
> Signed-off-by: Pawel Osciak <p.osciak@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  arch/arm/plat-samsung/include/plat/regs-fb.h |    1 +
>  drivers/video/s3c-fb.c                       |  167 +++++++++++++++++++++++++-
>  2 files changed, 167 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
> index f454e32..5bcdd09 100644
> --- a/arch/arm/plat-samsung/include/plat/regs-fb.h
> +++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
> @@ -298,6 +298,7 @@
>  #define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
>  
>  #define VIDINTCON0_FRAMESEL1			(1 << 13)
> +#define VIDINTCON0_FRAMESEL1_MASK		(0x3 << 13)
>  #define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 13)
>  #define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 13)
>  #define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 13)
> diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
> index 4f3680d..6131ebb 100644
> --- a/drivers/video/s3c-fb.c
> +++ b/drivers/video/s3c-fb.c
> @@ -21,6 +21,8 @@
>  #include <linux/clk.h>
>  #include <linux/fb.h>
>  #include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/interrupt.h>
>  
>  #include <mach/map.h>
>  #include <plat/regs-fb-v4.h>
> @@ -48,6 +50,11 @@
>  	__raw_writel(v, r); } while(0)
>  #endif /* FB_S3C_DEBUG_REGWRITE */
>  
> +/* irq_flags bits */
> +#define S3C_FB_VSYNC_IRQ_EN	0
> +
> +#define VSYNC_TIMEOUT_MSEC 50
> +
>  struct s3c_fb;
>  
>  #define VALID_BPP(x) (1 << ((x) - 1))
> @@ -156,6 +163,16 @@ struct s3c_fb_win {
>  };
>  
>  /**
> + * struct s3c_fb_vsync - vsync information
> + * @wait:	a queue for processes waiting for vsync
> + * @count:	vsync interrupt count
> + */
> +struct s3c_fb_vsync {
> +	wait_queue_head_t	wait;
> +	unsigned int		count;
> +};
> +
> +/**
>   * struct s3c_fb - overall hardware state of the hardware
>   * @dev: The device that we bound to, for printing, etc.
>   * @regs_res: The resource we claimed for the IO registers.
> @@ -165,6 +182,9 @@ struct s3c_fb_win {
>   * @enabled: A bitmask of enabled hardware windows.
>   * @pdata: The platform configuration data passed with the device.
>   * @windows: The hardware windows that have been claimed.
> + * @irq_no: IRQ line number
> + * @irq_flags: irq flags
> + * @vsync_info: VSYNC-related information (count, queues...)
>   */
>  struct s3c_fb {
>  	struct device		*dev;
> @@ -177,6 +197,10 @@ struct s3c_fb {
>  
>  	struct s3c_fb_platdata	*pdata;
>  	struct s3c_fb_win	*windows[S3C_FB_MAX_WIN];
> +
> +	int			 irq_no;
> +	unsigned long		 irq_flags;
> +	struct s3c_fb_vsync	 vsync_info;
>  };
>  
>  /**
> @@ -801,6 +825,124 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
>  	return 0;
>  }
>  
> +/**
> + * s3c_fb_enable_irq() - enable framebuffer interrupts
> + * @sfb: main hardware state
> + */
> +static void s3c_fb_enable_irq(struct s3c_fb *sfb)
> +{
> +	void __iomem *regs = sfb->regs;
> +	u32 irq_ctrl_reg;
> +
> +	if (!test_and_set_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
> +		/* IRQ disabled, enable it */
> +		irq_ctrl_reg = readl(regs + VIDINTCON0);
> +
> +		irq_ctrl_reg |= VIDINTCON0_INT_ENABLE;
> +		irq_ctrl_reg |= VIDINTCON0_INT_FRAME;
> +
> +		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL0_MASK;
> +		irq_ctrl_reg |= VIDINTCON0_FRAMESEL0_VSYNC;
> +		irq_ctrl_reg &= ~VIDINTCON0_FRAMESEL1_MASK;
> +		irq_ctrl_reg |= VIDINTCON0_FRAMESEL1_NONE;
> +
> +		writel(irq_ctrl_reg, regs + VIDINTCON0);
> +	}
> +}

there should probably be some form of locking so that an irq
doesn't come through and disable this. possibly in the call
that queues the request to reduce the likelyhood of any races.

> +
> +/**
> + * s3c_fb_disable_irq() - disable framebuffer interrupts
> + * @sfb: main hardware state
> + */
> +static void s3c_fb_disable_irq(struct s3c_fb *sfb)
> +{
> +	void __iomem *regs = sfb->regs;
> +	u32 irq_ctrl_reg;
> +
> +	if (test_and_clear_bit(S3C_FB_VSYNC_IRQ_EN, &sfb->irq_flags)) {
> +		/* IRQ enabled, disable it */
> +		irq_ctrl_reg = readl(regs + VIDINTCON0);
> +
> +		irq_ctrl_reg &= ~VIDINTCON0_INT_FRAME;
> +		irq_ctrl_reg &= ~VIDINTCON0_INT_ENABLE;
> +
> +		writel(irq_ctrl_reg, regs + VIDINTCON0);
> +	}
> +}
> +
> +static irqreturn_t s3c_fb_irq(int irq, void *dev_id)
> +{
> +	struct s3c_fb *sfb = dev_id;
> +	void __iomem  *regs = sfb->regs;
> +	u32 irq_sts_reg;
> +
> +	irq_sts_reg = readl(regs + VIDINTCON1);
> +
> +	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
> +
> +		/* VSYNC interrupt, accept it */
> +		writel(VIDINTCON1_INT_FRAME, regs + VIDINTCON1);
> +
> +		sfb->vsync_info.count++;
> +		wake_up_interruptible(&sfb->vsync_info.wait);
> +	}
> +
> +	/* We only support waiting for VSYNC for now, so it's safe
> +	 * to always disable irqs here.
> +	 */
> +	s3c_fb_disable_irq(sfb);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/**
> + * s3c_fb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout
> + * @sfb: main hardware state
> + * @crtc: head index.
> + */
> +static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
> +{
> +	unsigned long count;
> +	int ret;
> +
> +	if (crtc != 0)
> +		return -ENODEV;
> +
> +	s3c_fb_enable_irq(sfb);
> +	count = sfb->vsync_info.count;

possibly doing count before enabling the irq.

> +	ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
> +				       count != sfb->vsync_info.count,
> +				       msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
> +	if (ret == 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
> +			unsigned long arg)
> +{
> +	struct s3c_fb_win *win = info->par;
> +	struct s3c_fb *sfb = win->parent;
> +	int ret;
> +	u32 crtc;
> +
> +	switch (cmd) {
> +	case FBIO_WAITFORVSYNC:
> +		if (get_user(crtc, (u32 __user *)arg)) {
> +			ret = -EFAULT;
> +			break;
> +		}

can't find any info on what the argument is meant to be.

> +
> +		ret = s3c_fb_wait_for_vsync(sfb, crtc);
> +		break;
> +	default:
> +		ret = -ENOTTY;

Can someone else confirm this is the correct err?

> +	}
> +
> +	return ret;
> +}
> +
>  static struct fb_ops s3c_fb_ops = {
>  	.owner		= THIS_MODULE,
>  	.fb_check_var	= s3c_fb_check_var,
> @@ -811,6 +953,7 @@ static struct fb_ops s3c_fb_ops = {
>  	.fb_copyarea	= cfb_copyarea,
>  	.fb_imageblit	= cfb_imageblit,
>  	.fb_pan_display	= s3c_fb_pan_display,
> +	.fb_ioctl	= s3c_fb_ioctl,
>  };
>  
>  /**
> @@ -917,6 +1060,8 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
>  
>  	dev_dbg(sfb->dev, "probing window %d, variant %p\n", win_no, variant);
>  
> +	init_waitqueue_head(&sfb->vsync_info.wait);
> +
>  	palette_size = variant->palette_sz * 4;
>  
>  	fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
> @@ -1096,6 +1241,20 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  		goto err_req_region;
>  	}
>  
> +	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (!res) {
> +		dev_err(dev, "failed to acquire irq resource\n");
> +		ret = -ENOENT;
> +		goto err_ioremap;
> +	}
> +	sfb->irq_no = res->start;
> +	ret = request_irq(sfb->irq_no, s3c_fb_irq,
> +			  0, "s3c_fb", sfb);
> +	if (ret) {
> +		dev_err(dev, "irq request failed\n");
> +		goto err_ioremap;
> +	}
> +
>  	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
>  
>  	/* setup gpio and output polarity controls */
> @@ -1130,7 +1289,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  			dev_err(dev, "failed to create window %d\n", win);
>  			for (; win >= 0; win--)
>  				s3c_fb_release_win(sfb, sfb->windows[win]);
> -			goto err_ioremap;
> +			goto err_irq;
>  		}
>  	}
>  
> @@ -1138,6 +1297,9 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
>  
>  	return 0;
>  
> +err_irq:
> +	free_irq(sfb->irq_no, sfb);
> +
>  err_ioremap:
>  	iounmap(sfb->regs);
>  
> @@ -1170,6 +1332,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
>  		if (sfb->windows[win])
>  			s3c_fb_release_win(sfb, sfb->windows[win]);
>  
> +	free_irq(sfb->irq_no, sfb);
> +
>  	iounmap(sfb->regs);
>  
>  	clk_disable(sfb->bus_clk);
> @@ -1370,6 +1534,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 __devinitdata = {
>  			[3] = 0x3000,
>  			[4] = 0x3400,
>  		},
> +
>  	},

oops, added whitespace.

>  	.win[0]	= &s3c_fb_data_64xx_wins[0],
>  	.win[1]	= &s3c_fb_data_64xx_wins[1],

  reply	other threads:[~2010-07-02 11:37 UTC|newest]

Thread overview: 99+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-06-28  8:08 [PATCH v3 0/12] Various s3c-fb updates Pawel Osciak
2010-06-28  8:08 ` Pawel Osciak
2010-06-28  8:08 ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer memory alloc failure Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02  9:51   ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer Ben Dooks
2010-07-02  9:51     ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer memory alloc failure Ben Dooks
2010-07-02  9:51     ` Ben Dooks
2010-07-02 12:56     ` [PATCH v3 01/12] s3c-fb: Fix various null references on Pawel Osciak
2010-07-02 12:56       ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer memory alloc failure Pawel Osciak
2010-07-02 12:56       ` Pawel Osciak
2010-07-06 16:16     ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer James Simmons
2010-07-06 16:16       ` [PATCH v3 01/12] s3c-fb: Fix various null references on framebuffer memory alloc failure James Simmons
2010-07-06 16:16       ` James Simmons
2010-06-28  8:08 ` [PATCH v3 02/12] s3c-fb: Correct FRAMESEL1 bitfield defines for Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 02/12] s3c-fb: Correct FRAMESEL1 bitfield defines for VIDINTCON0 register Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02 10:51   ` [PATCH v3 02/12] s3c-fb: Correct FRAMESEL1 bitfield defines for Ben Dooks
2010-07-02 10:51     ` [PATCH v3 02/12] s3c-fb: Correct FRAMESEL1 bitfield defines for VIDINTCON0 register Ben Dooks
2010-07-02 10:51     ` Ben Dooks
2010-06-28  8:08 ` [PATCH v3 03/12] s3c-fb: Separate S5PC100 and S5PV210 framebuffer Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 03/12] s3c-fb: Separate S5PC100 and S5PV210 framebuffer driver data structures Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02 11:12   ` [PATCH v3 03/12] s3c-fb: Separate S5PC100 and S5PV210 framebuffer Ben Dooks
2010-07-02 11:12     ` [PATCH v3 03/12] s3c-fb: Separate S5PC100 and S5PV210 framebuffer driver data structures Ben Dooks
2010-07-02 11:12     ` Ben Dooks
2010-07-02 13:05     ` [PATCH v3 03/12] s3c-fb: Separate S5PC100 and S5PV210 framebuffer Pawel Osciak
2010-07-02 13:05       ` [PATCH v3 03/12] s3c-fb: Separate S5PC100 and S5PV210 framebuffer driver data structures Pawel Osciak
2010-07-02 13:05       ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 04/12] s3c-fb: Add device name initialization Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02 11:13   ` Ben Dooks
2010-07-02 11:13     ` Ben Dooks
2010-07-02 11:13     ` Ben Dooks
2010-06-28  8:08 ` [PATCH v3 05/12] s3c-fb: Add support for display panning Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28 11:28   ` Maurus Cuelenaere
2010-06-28 11:28     ` Maurus Cuelenaere
2010-06-28 11:28     ` Maurus Cuelenaere
2010-07-02 11:25     ` Ben Dooks
2010-07-02 11:25       ` Ben Dooks
2010-07-02 11:25       ` Ben Dooks
2010-07-02 11:33       ` Maurus Cuelenaere
2010-07-02 11:33         ` Maurus Cuelenaere
2010-07-02 11:33         ` Maurus Cuelenaere
2010-07-02 11:52       ` Mark Brown
2010-07-02 11:52         ` Mark Brown
2010-07-02 11:52         ` Mark Brown
2010-07-02 11:24   ` Ben Dooks
2010-07-02 11:24     ` Ben Dooks
2010-07-02 11:24     ` Ben Dooks
2010-07-02 13:29     ` Pawel Osciak
2010-07-02 13:29       ` Pawel Osciak
2010-07-02 13:29       ` Pawel Osciak
2010-07-04 13:50       ` Jamie Lokier
2010-07-04 13:50         ` Jamie Lokier
2010-07-04 13:50         ` Jamie Lokier
2010-06-28  8:08 ` [PATCH v3 06/12] s3c-fb: Add wait for VSYNC ioctl Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02 11:37   ` Ben Dooks [this message]
2010-07-02 11:37     ` Ben Dooks
2010-07-02 11:37     ` Ben Dooks
2010-07-02 14:39     ` Pawel Osciak
2010-07-02 14:39       ` Pawel Osciak
2010-07-02 14:39       ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 07/12] s3c-fb: window 3 of 64xx+ does not have an osd_d Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 07/12] s3c-fb: window 3 of 64xx+ does not have an osd_d register Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 08/12] s3c-fb: Add SHADOWCON shadow register locking support Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 08/12] s3c-fb: Add SHADOWCON shadow register locking support for S5PV210 Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02 13:11   ` [PATCH v3 08/12] s3c-fb: Add SHADOWCON shadow register locking Ben Dooks
2010-07-02 13:11     ` [PATCH v3 08/12] s3c-fb: Add SHADOWCON shadow register locking support for S5PV210 Ben Dooks
2010-07-02 13:11     ` Ben Dooks
2010-07-02 14:45     ` [PATCH v3 08/12] s3c-fb: Add SHADOWCON shadow register locking Pawel Osciak
2010-07-02 14:45       ` [PATCH v3 08/12] s3c-fb: Add SHADOWCON shadow register locking support for S5PV210 Pawel Osciak
2010-07-02 14:45       ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 09/12] s3c-fb: Correct window osd size and alpha register Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 09/12] s3c-fb: Correct window osd size and alpha register handling Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-07-02 13:16   ` [PATCH v3 09/12] s3c-fb: Correct window osd size and alpha register Ben Dooks
2010-07-02 13:16     ` [PATCH v3 09/12] s3c-fb: Correct window osd size and alpha register handling Ben Dooks
2010-07-02 13:16     ` Ben Dooks
2010-07-02 14:53     ` [PATCH v3 09/12] s3c-fb: Correct window osd size and alpha Pawel Osciak
2010-07-02 14:53       ` [PATCH v3 09/12] s3c-fb: Correct window osd size and alpha register handling Pawel Osciak
2010-07-02 14:53       ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 10/12] s3c-fb: Protect window-specific registers during Pawel Osciak
2010-06-28  8:08   ` [PATCH v3 10/12] s3c-fb: Protect window-specific registers during updates Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 11/12] s3c-fb: fix section mismatch Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08 ` [PATCH v3 12/12] s3c-fb: Add support for DMA channel control on S5PV210 Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak
2010-06-28  8:08   ` Pawel Osciak

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=4C2DCF5C.4020600@simtec.co.uk \
    --to=ben@simtec.co.uk \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.