diff mbox

allow 32bpp framebuffers for cirrus drm

Message ID 1412711357-23299-1-git-send-email-zachr@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zach Reizner Oct. 7, 2014, 7:49 p.m. UTC
This patch allows framebuffers for cirrus to be created with
32bpp pixel formats provided that they do not violate certain
restrictions of the cirrus hardware.

Signed-off-by: Zach Reizner <zachr@google.com>
---
 drivers/gpu/drm/cirrus/cirrus_drv.h   |  2 ++
 drivers/gpu/drm/cirrus/cirrus_fbdev.c |  4 +++-
 drivers/gpu/drm/cirrus/cirrus_main.c  | 22 ++++++++++++++++++++--
 3 files changed, 25 insertions(+), 3 deletions(-)

Comments

Stéphane Marchesin Oct. 25, 2014, 1:31 a.m. UTC | #1
On Tue, Oct 7, 2014 at 12:49 PM, Zach Reizner <zachr@google.com> wrote:

> This patch allows framebuffers for cirrus to be created with
> 32bpp pixel formats provided that they do not violate certain
> restrictions of the cirrus hardware.
>
> Signed-off-by: Zach Reizner <zachr@google.com>
>

Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>

Dave, Adam: are you ok with this patch?

Stéphane



> ---
>  drivers/gpu/drm/cirrus/cirrus_drv.h   |  2 ++
>  drivers/gpu/drm/cirrus/cirrus_fbdev.c |  4 +++-
>  drivers/gpu/drm/cirrus/cirrus_main.c  | 22 ++++++++++++++++++++--
>  3 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h
> b/drivers/gpu/drm/cirrus/cirrus_drv.h
> index 401c890..fac475c 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> @@ -208,6 +208,8 @@ int cirrus_framebuffer_init(struct drm_device *dev,
>                             struct drm_mode_fb_cmd2 *mode_cmd,
>                             struct drm_gem_object *obj);
>
> +bool cirrus_check_framebuffer(int width, int height, int bpp, int pitch);
> +
>                                 /* cirrus_display.c */
>  int cirrus_modeset_init(struct cirrus_device *cdev);
>  void cirrus_modeset_fini(struct cirrus_device *cdev);
> diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
> b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
> index 2a135f2..4a0756c 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
> +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
> @@ -146,8 +146,10 @@ static int cirrusfb_create_object(struct cirrus_fbdev
> *afbdev,
>         int ret = 0;
>         drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
>
> -       if (bpp > 24)
> +       if (!cirrus_check_framebuffer(mode_cmd->width, mode_cmd->height,
> bpp,
> +                                     mode_cmd->pitches[0]))
>                 return -EINVAL;
> +
>         size = mode_cmd->pitches[0] * mode_cmd->height;
>         ret = cirrus_gem_create(dev, size, true, &gobj);
>         if (ret)
> diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c
> b/drivers/gpu/drm/cirrus/cirrus_main.c
> index 99c1983..029f9e9 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_main.c
> +++ b/drivers/gpu/drm/cirrus/cirrus_main.c
> @@ -55,8 +55,9 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
>         u32 bpp, depth;
>
>         drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
> -       /* cirrus can't handle > 24bpp framebuffers at all */
> -       if (bpp > 24)
> +
> +       if (!cirrus_check_framebuffer(mode_cmd->width, mode_cmd->height,
> +                                     bpp, mode_cmd->pitches[0]))
>                 return ERR_PTR(-EINVAL);
>
>         obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
> @@ -307,3 +308,20 @@ out_unlock:
>         return ret;
>
>  }
> +
> +bool cirrus_check_framebuffer(int width, int height, int bpp, int pitch)
> +{
> +       const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
> +       const int max_size = 0x400000; /* 4MB */
> +
> +       if (bpp > 32)
> +               return false;
> +
> +       if (pitch > max_pitch)
> +               return false;
> +
> +       if (pitch * height > max_size)
> +               return false;
> +
> +       return true;
> +}
> --
> 2.1.0.rc2.206.gedb03e5
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
Adam Jackson Oct. 27, 2014, 3 p.m. UTC | #2
On Fri, 2014-10-24 at 18:31 -0700, Stéphane Marchesin wrote:

> Dave, Adam: are you ok with this patch?

Seems like it doesn't go far enough?  You'd already need an "aware"
guest to have this work, since the chip actually being emulated didn't
have 32bpp.  The pitch check would prevent 1024x768x32 and larger from
working, which makes it sort of a weak win on its own.

Could we read the BAR size from the device instead of hardcoding 4M?
That alone would make 1920x1200x16 work; and then, if that pitch limit
isn't encoded into the register space representation, the aware guest
would have resolutions worth using at least be possible.

- ajax
Gerd Hoffmann Oct. 27, 2014, 3:30 p.m. UTC | #3
On Mo, 2014-10-27 at 11:00 -0400, Adam Jackson wrote:
> On Fri, 2014-10-24 at 18:31 -0700, Stéphane Marchesin wrote:
> 
> > Dave, Adam: are you ok with this patch?
> 
> Seems like it doesn't go far enough?  You'd already need an "aware"
> guest to have this work, since the chip actually being emulated didn't
> have 32bpp.  The pitch check would prevent 1024x768x32 and larger from
> working, which makes it sort of a weak win on its own.
> 
> Could we read the BAR size from the device instead of hardcoding 4M?
> That alone would make 1920x1200x16 work; and then, if that pitch limit
> isn't encoded into the register space representation, the aware guest
> would have resolutions worth using at least be possible.

How about stop using cirrus and go for 'qemu -vga std' instead?

Linux kernel 3.14+ comes with a modesetting driver for the qemu standard
vga (CONFIG_DRM_BOCHS).  Just switch over, and all your cirrus pain is
gone.

That is much better than trying use features the real cirrus hardware
never had, then praying that all qemu versions in the wild are actually
doing what you want qemu do.

cheers,
  Gerd

https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
Zach Reizner Oct. 27, 2014, 3:36 p.m. UTC | #4
Real cirrus did have 32bpp according to both the reference manual and
qemu's emulation of the hardware. The cirrus DRM driver even had the
modesetting code for 32bpp but the driver prevented the creation of 32bpp
framebuffers.

Best,
Zach

On Mon, Oct 27, 2014, 08:30 Gerd Hoffmann <kraxel@redhat.com> wrote:

> On Mo, 2014-10-27 at 11:00 -0400, Adam Jackson wrote:
> > On Fri, 2014-10-24 at 18:31 -0700, Stéphane Marchesin wrote:
> >
> > > Dave, Adam: are you ok with this patch?
> >
> > Seems like it doesn't go far enough?  You'd already need an "aware"
> > guest to have this work, since the chip actually being emulated didn't
> > have 32bpp.  The pitch check would prevent 1024x768x32 and larger from
> > working, which makes it sort of a weak win on its own.
> >
> > Could we read the BAR size from the device instead of hardcoding 4M?
> > That alone would make 1920x1200x16 work; and then, if that pitch limit
> > isn't encoded into the register space representation, the aware guest
> > would have resolutions worth using at least be possible.
>
> How about stop using cirrus and go for 'qemu -vga std' instead?
>
> Linux kernel 3.14+ comes with a modesetting driver for the qemu standard
> vga (CONFIG_DRM_BOCHS).  Just switch over, and all your cirrus pain is
> gone.
>
> That is much better than trying use features the real cirrus hardware
> never had, then praying that all qemu versions in the wild are actually
> doing what you want qemu do.
>
> cheers,
>   Gerd
>
> https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
>
>
Adam Jackson Oct. 27, 2014, 4:21 p.m. UTC | #5
On Mon, 2014-10-27 at 16:30 +0100, Gerd Hoffmann wrote:

> How about stop using cirrus and go for 'qemu -vga std' instead?
> 
> Linux kernel 3.14+ comes with a modesetting driver for the qemu standard
> vga (CONFIG_DRM_BOCHS).  Just switch over, and all your cirrus pain is
> gone.
> 
> That is much better than trying use features the real cirrus hardware
> never had, then praying that all qemu versions in the wild are actually
> doing what you want qemu do.

I was going to ask for a pci revision id bump at the same time, so the
guest could know.

I heartily agree, people should stop using cirrus.  And qemu should stop
defaulting to it.  Since neither has happened yet, enhancing the
emulation holds the promise of making the future better...

- ajax
Zach Reizner Oct. 27, 2014, 10:09 p.m. UTC | #6
ajax,
What do you mean by a pci revision id bump? Do you want it in qemu or the
kernel? Why is a revision bump needed when none of the behavior of the
cirrus device has changed?
I agree that reading the BAR size from the device would be an enhancement.
I'm working on the patch to include that now.
-Zach

On Mon Oct 27 2014 at 9:21:42 AM Adam Jackson <ajax@redhat.com> wrote:

> On Mon, 2014-10-27 at 16:30 +0100, Gerd Hoffmann wrote:
>
> > How about stop using cirrus and go for 'qemu -vga std' instead?
> >
> > Linux kernel 3.14+ comes with a modesetting driver for the qemu standard
> > vga (CONFIG_DRM_BOCHS).  Just switch over, and all your cirrus pain is
> > gone.
> >
> > That is much better than trying use features the real cirrus hardware
> > never had, then praying that all qemu versions in the wild are actually
> > doing what you want qemu do.
>
> I was going to ask for a pci revision id bump at the same time, so the
> guest could know.
>
> I heartily agree, people should stop using cirrus.  And qemu should stop
> defaulting to it.  Since neither has happened yet, enhancing the
> emulation holds the promise of making the future better...
>
> - ajax
>
>
Gerd Hoffmann Oct. 28, 2014, 9:09 a.m. UTC | #7
On Mo, 2014-10-27 at 22:09 +0000, Zachary Reizner wrote:
> ajax,
> What do you mean by a pci revision id bump? Do you want it in qemu or
> the kernel? Why is a revision bump needed when none of the behavior of
> the cirrus device has changed?

revision bump would be needed when adding a new interface (not present
in real hardware) to allow for larger pitches, so you could use 32bpp
with the default (1024x768) resolution.

>         I heartily agree, people should stop using cirrus.  And qemu
>         should stop
>         defaulting to it.  Since neither has happened yet, enhancing
>         the
>         emulation holds the promise of making the future better...

I'll try flip the default.  That is more sane than pimping up the cirrus
emulation.

cheers,
  Gerd
Zach Reizner Oct. 28, 2014, 5:04 p.m. UTC | #8
>
> revision bump would be needed when adding a new interface (not present
> in real hardware) to allow for larger pitches, so you could use 32bpp
> with the default (1024x768) resolution.
>
I did not change the pitch mechanism. The hardware is limited to less than
a 4KB pitch because of the registers, so I kept that limitation in the
driver. That means no revision bump is necessary.
Gerd Hoffmann Oct. 29, 2014, 11 a.m. UTC | #9
On Di, 2014-10-28 at 17:04 +0000, Zachary Reizner wrote:
>         revision bump would be needed when adding a new interface (not
>         present
>         in real hardware) to allow for larger pitches, so you could
>         use 32bpp
>         with the default (1024x768) resolution.
> I did not change the pitch mechanism.

Sure.  That was Adams idea to make the patch more useful.

> The hardware is limited to less than a 4KB pitch because of the
> registers, so I kept that limitation in the driver. That means no
> revision bump is necessary.

Yes, but it also implies that 32bpp will work on very low resolutions
only (excluding the default res of 1024x768).  I don't think the patch
is very useful because of that.  Nevertheless no objections to include
it from my side.

cheers,
  Gerd
diff mbox

Patch

diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 401c890..fac475c 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -208,6 +208,8 @@  int cirrus_framebuffer_init(struct drm_device *dev,
 			    struct drm_mode_fb_cmd2 *mode_cmd,
 			    struct drm_gem_object *obj);
 
+bool cirrus_check_framebuffer(int width, int height, int bpp, int pitch);
+
 				/* cirrus_display.c */
 int cirrus_modeset_init(struct cirrus_device *cdev);
 void cirrus_modeset_fini(struct cirrus_device *cdev);
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index 2a135f2..4a0756c 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -146,8 +146,10 @@  static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
 	int ret = 0;
 	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
 
-	if (bpp > 24)
+	if (!cirrus_check_framebuffer(mode_cmd->width, mode_cmd->height, bpp,
+				      mode_cmd->pitches[0]))
 		return -EINVAL;
+
 	size = mode_cmd->pitches[0] * mode_cmd->height;
 	ret = cirrus_gem_create(dev, size, true, &gobj);
 	if (ret)
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index 99c1983..029f9e9 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -55,8 +55,9 @@  cirrus_user_framebuffer_create(struct drm_device *dev,
 	u32 bpp, depth;
 
 	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
-	/* cirrus can't handle > 24bpp framebuffers at all */
-	if (bpp > 24)
+
+	if (!cirrus_check_framebuffer(mode_cmd->width, mode_cmd->height,
+				      bpp, mode_cmd->pitches[0]))
 		return ERR_PTR(-EINVAL);
 
 	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
@@ -307,3 +308,20 @@  out_unlock:
 	return ret;
 
 }
+
+bool cirrus_check_framebuffer(int width, int height, int bpp, int pitch)
+{
+	const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
+	const int max_size = 0x400000; /* 4MB */
+
+	if (bpp > 32)
+		return false;
+
+	if (pitch > max_pitch)
+		return false;
+
+	if (pitch * height > max_size)
+		return false;
+
+	return true;
+}