Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH 00/13] sa1100fb cleanups
From: Florian Tobias Schandinat @ 2012-02-19 22:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20120204093744.GQ889@n2100.arm.linux.org.uk>

Hi Russell,

On 02/04/2012 09:37 AM, Russell King - ARM Linux wrote:
> Here's another bunch of SA11x0 stuff - its framebuffer driver.  This
> set of patches fixes some section mismatch warnings, moves the board
> configuration out to the board files, converts the Shannon stuff to
> use gpiolib rather than poking at GPDR/GPSR/GPCR directly.
> 
> The function hooks for LCD and backlight power control are moved into
> the platform data passed from the board, eliminating the global function
> pointers.

This series looks good to me.
Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>

> This series will conflict with the previous series (in the case of
> Assabet, the conflict is quite large) so I'd prefer to keep this in my
> tree for the next merge window.

Sure, feel free to proceed with this series as you like.


Best regards,

Florian Tobias Schandinat

^ permalink raw reply

* [PATCH] i740fb: fix compile error when CONFIG_MTRR is not selected
From: Florian Tobias Schandinat @ 2012-02-19 21:33 UTC (permalink / raw)
  To: linux-fbdev
  Cc: linux-kernel, Florian Tobias Schandinat, Ondrej Zary,
	Stephen Rothwell, linux-next
In-Reply-To: <20120216162900.e2dd164732084f48e5b239f0@canb.auug.org.au>

Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
---
 drivers/video/i740fb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c
index 8be0302..fe574d8 100644
--- a/drivers/video/i740fb.c
+++ b/drivers/video/i740fb.c
@@ -1179,9 +1179,9 @@ static void __devexit i740fb_remove(struct pci_dev *dev)
 	struct fb_info *info = pci_get_drvdata(dev);
 
 	if (info) {
-#ifdef CONFIG_MTRR
 		struct i740fb_par *par = info->par;
 
+#ifdef CONFIG_MTRR
 		if (par->mtrr_reg >= 0) {
 			mtrr_del(par->mtrr_reg, 0, 0);
 			par->mtrr_reg = -1;
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 5/5] fbdev: s/#if CONFIG/#ifdef CONFIG/
From: Geert Uytterhoeven @ 2012-02-19 15:11 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-kernel, Geert Uytterhoeven, Florian Tobias Schandinat,
	linux-fbdev
In-Reply-To: <1329664319-3128-1-git-send-email-geert@linux-m68k.org>

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: linux-fbdev@vger.kernel.org
---
 drivers/video/au1100fb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index de9da67..4da1895 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -532,7 +532,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
 	for (page = (unsigned long)fbdev->fb_mem;
 	     page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len);
 	     page += PAGE_SIZE) {
-#if CONFIG_DMA_NONCOHERENT
+#ifdef CONFIG_DMA_NONCOHERENT
 		SetPageReserved(virt_to_page(CAC_ADDR((void *)page)));
 #else
 		SetPageReserved(virt_to_page(page));
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH] drivers/video/pxa168fb.c: use devm_ functions
From: Julia Lawall @ 2012-02-18 18:19 UTC (permalink / raw)
  To: Florian Tobias Schandinat; +Cc: kernel-janitors, linux-fbdev, linux-kernel

From: Julia Lawall <Julia.Lawall@lip6.fr>

The various devm_ functions allocate memory that is released when a driver
detaches.  This patch uses these functions for data that is allocated in
the probe function of a platform device and is only freed in the remove
function.

By using devm_ioremap, it also removes a potential memory leak, because
there was no call to iounmap in the probe function.

Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>

---
 drivers/video/pxa168fb.c |   15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 8384b94..f146089 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -21,6 +21,7 @@
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
@@ -670,7 +671,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
 	/*
 	 * Map LCD controller registers.
 	 */
-	fbi->reg_base = ioremap_nocache(res->start, resource_size(res));
+	fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start,
+					     resource_size(res));
 	if (fbi->reg_base = NULL) {
 		ret = -ENOMEM;
 		goto failed_free_info;
@@ -739,8 +741,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
 	/*
 	 * Register irq handler.
 	 */
-	ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED,
-					info->fix.id, fbi);
+	ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
+			       IRQF_SHARED, info->fix.id, fbi);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "unable to request IRQ\n");
 		ret = -ENXIO;
@@ -759,14 +761,12 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
 		ret = -ENXIO;
-		goto failed_free_irq;
+		goto failed_free_cmap;
 	}
 
 	platform_set_drvdata(pdev, fbi);
 	return 0;
 
-failed_free_irq:
-	free_irq(irq, fbi);
 failed_free_cmap:
 	fb_dealloc_cmap(&info->cmap);
 failed_free_clk:
@@ -808,13 +808,10 @@ static int __devexit pxa168fb_remove(struct platform_device *pdev)
 		fb_dealloc_cmap(&info->cmap);
 
 	irq = platform_get_irq(pdev, 0);
-	free_irq(irq, fbi);
 
 	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
 				info->screen_base, info->fix.smem_start);
 
-	iounmap(fbi->reg_base);
-
 	clk_disable(fbi->clk);
 	clk_put(fbi->clk);
 


^ permalink raw reply related

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Clark, Rob @ 2012-02-18 17:53 UTC (permalink / raw)
  To: Adam Jackson
  Cc: Laurent Pinchart, Tomasz Stanislawski, linux-fbdev, Sakari Ailus,
	Pawel Osciak, Magnus Damm, Marcus Lorentzon, dri-devel,
	Alexander Deucher, linux-media, Marek Szyprowski
In-Reply-To: <4F3EADAA.9090702@redhat.com>

On Fri, Feb 17, 2012 at 1:42 PM, Adam Jackson <ajax@redhat.com> wrote:
> On 2/16/12 6:25 PM, Laurent Pinchart wrote:
>
>>   Helper functions will be implemented in the subsystems to convert
>> between
>>   that generic structure and the various subsystem-specific structures.
>
>
> I guess.  I don't really see a reason not to unify the structs too, but then
> I don't have binary blobs to pretend to be ABI-compatible with.
>

this is just for where timing struct is exposed to userspace

BR,
-R

^ permalink raw reply

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Keith Packard @ 2012-02-18  0:56 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
	Marcus Lorentzon, Magnus Damm, dri-devel, Alexander Deucher,
	Rob Clark, Marek Szyprowski, linux-media
In-Reply-To: <1775349.d0yvHiVdjB@avalon>

<#part sign=pgpmime>
On Fri, 17 Feb 2012 00:25:51 +0100, Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote:

> ***  Synchronous pipeline changes ***
> 
>   Goal: Create an API to apply complex changes to a video pipeline atomically.
> 
>   Needed for complex camera use cases. On the DRM/KMS side, the approach is to
>   use one big ioctl to configure the whole pipeline.

This is the only credible approach for most desktop chips -- you must
have the whole configuration available before you can make any
commitment to supporting the requested modes.

>   One solution is a commit ioctl, through the media controller device, that
>   would be dispatched to entities internally with a prepare step and a commit
>   step.

The current plan for the i915 KMS code is to use a single ioctl -- the
application sends a buffer full of configuration commands down to the
kernel which can then figure out whether it can be supported or not.

The kernel will have to store the intermediate data until the commit
arrives anyways, and you still need a central authority in the kernel
controlling the final commit decision.

-- 
keith.packard@intel.com

^ permalink raw reply

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Adam Jackson @ 2012-02-17 19:42 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
	Magnus Damm, Marcus Lorentzon, dri-devel, Alexander Deucher,
	Rob Clark, linux-media, Marek Szyprowski
In-Reply-To: <1775349.d0yvHiVdjB@avalon>

On 2/16/12 6:25 PM, Laurent Pinchart wrote:

> ***  Common video mode data structure and EDID parser ***
>
>    Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
>
>    The DRM EDID parser is currently the most advanced implementation and will
>    be taken as a starting point.
>
>    Different subsystems use different data structures to describe video
>    mode/timing information:
>
>    - struct drm_mode_modeinfo in DRM/KMS
>    - struct fb_videomode in FBDEV
>    - struct v4l2_bt_timings in V4L2
>
>    A new common video mode/timing data structure (struct media_video_mode_info,
>    exact name is to be defined), not tied to any specific subsystem, is
>    required to share the EDID parser. That structure won't be exported to
>    userspace.
>
>    Helper functions will be implemented in the subsystems to convert between
>    that generic structure and the various subsystem-specific structures.

I guess.  I don't really see a reason not to unify the structs too, but 
then I don't have binary blobs to pretend to be ABI-compatible with.

>    The mode list is stored in the DRM connector in the EDID parser. A new mode
>    list data structure can be added, or a callback function can be used by the
>    parser to give modes one at a time to the caller.
>
>    3D needs to be taken into account (this is similar to interlacing).

Would also be pleasant if the new mode structure had a reasonable way of 
representing borders, we copied that mistake from xserver and have been 
regretting it.

>    Action points:
>    - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.

I'm totally in favor of this.  I've long loathed fbdev having such a 
broken parser, I just never got around to fixing it since we don't use 
fbdev in any real way.

The existing drm_edid.c needs a little detangling, DDC fetch and EDID 
parse should be better split.  Shouldn't be too terrible though.

Has the embedded world seen any adoption of DisplayID?  I wrote a fair 
bit of a parser for it at one point [1] but I've yet to find a machine 
that's required it.

> ***  Split KMS and GPU Drivers ***
>
>    Goal: Split KMS and GPU drivers with in kernel API inbetween.
>
>    In most (all ?) SoCs, the GPU and the display controller are separate
>    devices. Splitting them into separate drivers would allow reusing the GPU
>    driver with different devices (e.g. using a single common PowerVR kernel
>    module with different display controller drivers). The same approach can be
>    used on the desktop for the multi-GPU case and the USB display case.
>
>    - OMAP already separates the GPU and DSS drivers, but the GPU driver is some
>    kind of DSS plugin. This isn't a long-term approach.
>    - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
>    into  display subsystem since UMP, GPU has own memory management codes.
>
>    One of the biggest challenges would be to get GPU vendors to use this new
>    model. ARM could help here, by making the Mali kernel driver split from the
>    display controller drivers. Once one vendor jumps onboard, others could have
>    a bigger incentive to follow.

Honestly I want this for Intel already, given how identical Poulsbo's 
display block is to gen3.

> ***  HDMI CEC Support ***
>
>    Goal: Support HDMI CEC and offer a userspace API for applications.
>
>    A new kernel API is needed and must be usable by KMS, V4L2 and possibly
>    LIRC. There's ongoing effort from Cisco to implement HDMI CEC support. Given
>    their background, V4L2 is their initial target. A proposal is available at
>    http://www.mail-archive.com/linux-media@vger.kernel.org/msg29241.html with a
>    sample implementation at
>    http://git.linuxtv.org/hverkuil/cisco.git/shortlog/refs/heads/cobalt-
> mainline
>    (drivers/media/video/adv7604.c and ad9389b.c.
>
>    In order to avoid API duplication, a new CEC subsystem is probably needed.
>    CEC could be modeled as a bus, or as a network device. With the network
>    device approach, we could have both kernel and userspace protocol handlers.

I'm not a huge fan of userspace protocol for this.  Seems like it'd just 
give people more license to do their own subtly-incompatible things that 
only work between devices of the same vendor.  Interoperability is the 
_whole_ point of CEC.  (Yes I know every vendor tries to spin it as 
their own magical branded thing, but I'd appreciate it if they grew up.)

[1] - 
http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/modes/xf86DisplayIDModes.c

- ajax

^ permalink raw reply

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Laurent Pinchart @ 2012-02-17 18:49 UTC (permalink / raw)
  To: Semwal, Sumit
  Cc: Sakari Ailus, Jesse Barker, Jesse Barnes, Rob Clark, Pawel Osciak,
	Marek Szyprowski, Tomasz Stanislawski, Magnus Damm,
	Marcus Lorentzon, Alexander Deucher, linux-media, dri-devel,
	linux-fbdev
In-Reply-To: <CAB2ybb_-ULCsfS48u7HQiRDLG5y-X2rmyXvHBcCRtc=m-732hQ@mail.gmail.com>

Hi Sumit,

On Friday 17 February 2012 16:37:35 Semwal, Sumit wrote:
> On Fri, Feb 17, 2012 at 4:55 AM, Laurent Pinchart wrote: 
> > Hello everybody,
> > 
> > First of all, I would like to thank all the attendees for their
> > participation in the mini-summit that helped make the meeting a success.
> 
> <snip>
> 
> > ***  dma-buf Implementation in V4L2 ***
> > 
> >  Goal: Implement the dma-buf API in V4L2.
> > 
> >  Sumit Semwal has submitted patches to implement the dma-buf importer role
> > in videobuf2. Tomasz Stanislawski has then submitted incremental patches
> > to add exporter role support.
> > 
> >  Action points:
> >  - Create a git branch to host all the latest patches. Sumit will provide
> >    that.
> 
> Against my Action Item: I have created the following branch at my
> github (obviously, it is an RFC branch only)

That was very fast :-) Thank you for your work on this.

> tree: git://github.com/sumitsemwal/kernel-omap4.git
> branch: 3.3rc3-v4l2-dmabuf-RFCv1
> 
> As the name partially suggests, it is based out of:
> 3.3-rc3 +
> dmav6 [1] +
> some minor dma-buf updates [2] +
> my v4l2-as-importer RFC [3] +
> Tomasz' RFC for v4l2-as-exporter (and related patches) [4]
> 
> Since Tomasz' RFC had a patch-pair which first removed and then added
> drivers/media/video/videobuf2-dma-contig.c file, I 'combined' these
> into one - but since the patch-pair heavily refactored the file, I am
> not able to take responsibility of completeness / correctness of the
> same.

No worries. The branch's main purpose is to provide people with a starting 
point to use dma-buf, patch review will go through mailing lists anyway.

> [1]:
> http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/3.3
> -rc2-dma-v6 [2]: git://git.linaro.org/people/sumitsemwal/linux-3.x.git 'dev'
> branch [3]:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/4296
> 6/focusB968 [4]:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/4379
> 3

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Laurent Pinchart @ 2012-02-17 18:46 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
	Magnus Damm, Marcus Lorentzon, dri-devel, Alexander Deucher,
	Rob Clark, linux-media, Marek Szyprowski
In-Reply-To: <20120217095554.GA5511@phenom.ffwll.local>

Hi Daniel,

On Friday 17 February 2012 10:55:54 Daniel Vetter wrote:
> On Fri, Feb 17, 2012 at 12:25:51AM +0100, Laurent Pinchart wrote:
> > Hello everybody,
> > 
> > First of all, I would like to thank all the attendees for their
> > participation in the mini-summit that helped make the meeting a success.
> > 
> > Here are my consolidated notes that cover both the Linaro Connect meeting
> > and the ELC meeting. They're also available at
> > http://www.ideasonboard.org/media/meetings/.
> 
> Looks like you've been all really busy ;-)

I like to think so :-)

> A few quick comments below.

Thanks for your feedback.
 
> > Kernel Display and Video API Consolidation mini-summit at ELC 2012
> > ------------------------------------------------------------------
> 
> [snip]
> 
> > ***  Common video mode data structure and EDID parser ***
> > 
> >   Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
> >   
> >   The DRM EDID parser is currently the most advanced implementation and
> >   will
> >   be taken as a starting point.
> >   
> >   Different subsystems use different data structures to describe video
> >   mode/timing information:
> >   
> >   - struct drm_mode_modeinfo in DRM/KMS
> >   - struct fb_videomode in FBDEV
> >   - struct v4l2_bt_timings in V4L2
> >   
> >   A new common video mode/timing data structure (struct
> >   media_video_mode_info, exact name is to be defined), not tied to any
> >   specific subsystem, is required to share the EDID parser. That
> >   structure won't be exported to userspace.
> >   
> >   Helper functions will be implemented in the subsystems to convert
> >   between
> >   that generic structure and the various subsystem-specific structures.
> >   
> >   The mode list is stored in the DRM connector in the EDID parser. A new
> >   mode
> >   list data structure can be added, or a callback function can be used by
> >   the
> >   parser to give modes one at a time to the caller.
> >   
> >   3D needs to be taken into account (this is similar to interlacing).
> >   
> >   Action points:
> >   - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.
> 
> I think we should include kernel cmdline video mode parsing here, afaik
> kms and fbdev are rather similar (won't work if they're too different,
> obviously).

Good point. I'll add that to the notes and will look into it.

> [snip]
> 
> > ***  Central 4CC Documentation ***
> > 
> >   Goal: Define and document 4CCs in a central location to make sure 4CCs
> >   won't overlap or have different meanings for different subsystems.
> >   
> >   DRM and V4L2 define their own 4CCs:
> >   
> >   - include/drm/drm-fourccs.h
> >   - include/linux/videodev2.h
> >   
> >   A new header file will centralize the definitions, with a new
> >   cross-subsystem prefix. DRM and V4L2 4CCs will be redefined as aliases
> >   for
> >   the new centralized 4CCs.
> >   
> >   Colorspace (including both color matrix and Y/U/V ranges) should be
> >   shared as well. VDPAU (and VAAPI ?) pass the color matrix to userspace.
> >   The kernel API should not be more restrictive, but we just need a couple
> >   of presets in most cases. We can define a list of common presets, with a
> >   way to upload a custom matrix.
> >   
> >   Action points:
> >   - Start with the V4L2 documentation, create a shared header file. Sakari
> >   to work on a proposal.
> 
> I'm looking forward to the bikeshed discussion here ;-)
> </snide-remark>

I'm certainly going to NACK if we try to paint 4CCs in the wrong colorspace 
;-)
 
> > ***  Split KMS and GPU Drivers ***
> > 
> >   Goal: Split KMS and GPU drivers with in kernel API inbetween.
> >   
> >   In most (all ?) SoCs, the GPU and the display controller are separate
> >   devices. Splitting them into separate drivers would allow reusing the
> >   GPU driver with different devices (e.g. using a single common PowerVR
> >   kernel module with different display controller drivers). The same
> >   approach can be used on the desktop for the multi-GPU case and the USB
> >   display case.
> >   
> >   - OMAP already separates the GPU and DSS drivers, but the GPU driver is
> >   some kind of DSS plugin. This isn't a long-term approach.
> >   - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
> >   into  display subsystem since UMP, GPU has own memory management codes.
> >   
> >   One of the biggest challenges would be to get GPU vendors to use this
> >   new model. ARM could help here, by making the Mali kernel driver split
> >   from the display controller drivers. Once one vendor jumps onboard,
> >   others could have a bigger incentive to follow.
> >   
> >   Action points:
> >   - Rob planning to work on a reference implementation, as part of the
> >   sync object case. This is a pretty long term plan.
> >   
> >   - Jesse will handle the coordination with ARM for Mali.
> 
> Imo splitting up SoC drm drivers into separate drivers for the different
> blocks makes tons of sense. The one controlling the display subsystem
> would then also support kms, all the others would just support gem and
> share buffers with dma_buf (and maybe synchronize with some new-fangled
> sync objects). Otoh it doesn't make much sense to push this if we don't
> have at least one of the SoC ip block verndors on board. We can dream ...

That's the conclusion we came up to. ARM might be able to help here with Mali, 
and we could then try to sell the idea to other vendors when a reference 
implementation will be complete (or at least usable enough).

> [snip]
> 
> > ***  Sync objects ***
> > 
> >   Goal: Implement in-kernel support for buffer swapping, dependency
> >   system, sync objects, queue/dequeue userspace API (think EGLstream &
> >   EGLsync)
> >   
> >   This can be implemented in kernel-space (with direct communication
> >   between drivers to schedule buffers around), user-space (with ioctls to
> >   queue/dequeue buffers), or a mix of both. SoCs with direct sync object
> >   support at the hardware level between different IP blocks can be
> >   foreseen in the (near ?) future. A kernel-space API would then be
> >   needed.
> >   
> >   Sharing sync objects between subsystems could result in the creation of
> >   a cross-subsystem queue/dequeue API. Integration with dma_buf would make
> >   sense, a dma_buf_pool object would then likely be needed.
> >   
> >   If the SoC supports direct signaling between IP blocks, this could be
> >   considered (and implemented) as a pipeline configurable through the
> >   Media Controller API. However, applications will then need to be link-
> >   aware. Using sync/stream objects would offer a single API to userspace,
> >   regardless of whether the synchronization is handled by the CPU in
> >   kernel space or by the IP blocks directly.
> >   
> >   Sync objects are not always tied to buffers, they need to be implemented
> >   as stand-alone objects on the kernel side. However, when exposing the
> >   sync object to userspace in order to share it between devices, all
> >   current use cases involve dma-buf. The first implementation will thus not
> >   expose the sync objects explicitly to userspace, but associate them with
> >   a dma-buf. If sync objects with no associated dma-buf are later needed,
> >   an explicit userspace API can be added.
> >   
> >   eventfd is a possible candidate for sync object implementation.
> >   
> >   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=in
> >   clude/linux/eventfd.h
> >   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=D
> >   ocumentation/cgroups/cgroups.txt
> >   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=D
> >   ocumentation/cgroups/memory.txt
> >   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=D
> >   ocumentation/virtual/kvm/api.txt
> >   
> >   Action points:
> >   - TBD, will be on the agenda for the Graphics Summit @ELC2012.
> 
> I've already started discussing this a bit with Rob. I'm not sure whether
> implicitly associating a sync object with a dma_buf makes sense, afaik
> sync objects can be used rather independently from buffers. But this is a
> long-term feature, so we still have plenty of time to discuss this.

I think we need to work on this one step at a time. Associating a sync object 
with a dma_buf is probably not going to solve all our problems in the long 
term, but it might provide us with a first solution that doesn't require 
exposing the sync object API to userspace. I'm not saying we need to do this, 
but it could be a reasonable first step that would buy us some time while we 
sort out the sync object userspace API.

> [snip]
> 
> > *** 2D Kernel APIs ***
> > 
> >   Goal: Expose a 2D acceleration API to userspace for devices that support
> >   hardware-accelerated 2D rendering.
> >   
> >   If the hardware is based on a command stream, a userspace library is
> >   needed anyway to build the command stream. A 2D kernel API would then
> >   not be very useful. This could be split to a DRM device without a KMS
> >   interface.
> 
> Imo we should ditch this - fb accel doesn't belong into the kernel. Even
> on hw that still has a blitter for easy 2d accel without a complete 3d
> state setup necessary, it's not worth it. Chris Wilson from our team once
> played around with implementing fb accel in the kernel (i915 hw still has
> a blitter engine in the latest generations). He quickly noticed that to
> have decent speed, competitive with s/w rendering by the cpu he needs the
> entire batch and buffer management stuff from userspace. And to really
> beat the cpu, you need even more magic.
> 
> If you want fast 2d accel, use something like cairo.

Our conclusion on this is that we should not expose an explicit 2D 
acceleration API at the kernel level. If really needed, hardware 2D 
acceleration could be implemented as a DRM device to handle memory management, 
commands ring setup, synchronization, ... but I'm not even sure if that's 
worth it. I might not have conveyed it well in my notes.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Semwal, Sumit @ 2012-02-17 11:19 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sakari Ailus, Jesse Barker, Jesse Barnes, Rob Clark, Pawel Osciak,
	Marek Szyprowski, Tomasz Stanislawski, Magnus Damm,
	Marcus Lorentzon, Alexander Deucher, linux-media, dri-devel,
	linux-fbdev
In-Reply-To: <1775349.d0yvHiVdjB@avalon>

Hello Laurent, Everyone:


On Fri, Feb 17, 2012 at 4:55 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hello everybody,
>
> First of all, I would like to thank all the attendees for their participation
> in the mini-summit that helped make the meeting a success.
>
<snip>
> ***  dma-buf Implementation in V4L2 ***
>
>  Goal: Implement the dma-buf API in V4L2.
>
>  Sumit Semwal has submitted patches to implement the dma-buf importer role in
>  videobuf2. Tomasz Stanislawski has then submitted incremental patches to add
>  exporter role support.
>
>  Action points:
>  - Create a git branch to host all the latest patches. Sumit will provide
>    that.
>
>
Against my Action Item: I have created the following branch at my
github (obviously, it is an RFC branch only)

tree: git://github.com/sumitsemwal/kernel-omap4.git
branch: 3.3rc3-v4l2-dmabuf-RFCv1

As the name partially suggests, it is based out of:
3.3-rc3 +
dmav6 [1] +
some minor dma-buf updates [2] +
my v4l2-as-importer RFC [3] +
Tomasz' RFC for v4l2-as-exporter (and related patches) [4]

Since Tomasz' RFC had a patch-pair which first removed and then added
drivers/media/video/videobuf2-dma-contig.c file, I 'combined' these
into one - but since the patch-pair heavily refactored the file, I am
not able to take responsibility of completeness / correctness of the
same.

[1]: http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/3.3-rc2-dma-v6
[2]: git://git.linaro.org/people/sumitsemwal/linux-3.x.git 'dev' branch
[3]: http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/42966/focusB968
[4]: http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/43793

Best regards,
~Sumit.

^ permalink raw reply

* Re: Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Daniel Vetter @ 2012-02-17  9:55 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Tomasz Stanislawski, linux-fbdev, Sakari Ailus, Pawel Osciak,
	Magnus Damm, Marcus Lorentzon, dri-devel, Alexander Deucher,
	Rob Clark, linux-media, Marek Szyprowski
In-Reply-To: <1775349.d0yvHiVdjB@avalon>

On Fri, Feb 17, 2012 at 12:25:51AM +0100, Laurent Pinchart wrote:
> Hello everybody,
> 
> First of all, I would like to thank all the attendees for their participation 
> in the mini-summit that helped make the meeting a success.
> 
> Here are my consolidated notes that cover both the Linaro Connect meeting and 
> the ELC meeting. They're also available at 
> http://www.ideasonboard.org/media/meetings/.

Looks like you've been all really busy ;-) A few quick comments below.

> Kernel Display and Video API Consolidation mini-summit at ELC 2012
> ------------------------------------------------------------------

[snip]

> ***  Common video mode data structure and EDID parser ***
> 
>   Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.
> 
>   The DRM EDID parser is currently the most advanced implementation and will
>   be taken as a starting point.
> 
>   Different subsystems use different data structures to describe video
>   mode/timing information:
> 
>   - struct drm_mode_modeinfo in DRM/KMS
>   - struct fb_videomode in FBDEV
>   - struct v4l2_bt_timings in V4L2
> 
>   A new common video mode/timing data structure (struct media_video_mode_info,
>   exact name is to be defined), not tied to any specific subsystem, is
>   required to share the EDID parser. That structure won't be exported to
>   userspace.
> 
>   Helper functions will be implemented in the subsystems to convert between
>   that generic structure and the various subsystem-specific structures.
> 
>   The mode list is stored in the DRM connector in the EDID parser. A new mode
>   list data structure can be added, or a callback function can be used by the
>   parser to give modes one at a time to the caller.
> 
>   3D needs to be taken into account (this is similar to interlacing).
> 
>   Action points:
>   - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.

I think we should include kernel cmdline video mode parsing here, afaik
kms and fbdev are rather similar (won't work if they're too different,
obviously).

[snip]

> ***  Central 4CC Documentation ***
> 
>   Goal: Define and document 4CCs in a central location to make sure 4CCs won't
>   overlap or have different meanings for different subsystems.
> 
>   DRM and V4L2 define their own 4CCs:
> 
>   - include/drm/drm-fourccs.h
>   - include/linux/videodev2.h
> 
>   A new header file will centralize the definitions, with a new
>   cross-subsystem prefix. DRM and V4L2 4CCs will be redefined as aliases for
>   the new centralized 4CCs.
> 
>   Colorspace (including both color matrix and Y/U/V ranges) should be shared
>   as well. VDPAU (and VAAPI ?) pass the color matrix to userspace. The kernel
>   API should not be more restrictive, but we just need a couple of presets in
>   most cases. We can define a list of common presets, with a way to upload a
>   custom matrix.
> 
>   Action points:
>   - Start with the V4L2 documentation, create a shared header file. Sakari to
>     work on a proposal.

I'm looking forward to the bikeshed discussion here ;-)
</snide-remark>

> ***  Split KMS and GPU Drivers ***
> 
>   Goal: Split KMS and GPU drivers with in kernel API inbetween.
>  
>   In most (all ?) SoCs, the GPU and the display controller are separate
>   devices. Splitting them into separate drivers would allow reusing the GPU
>   driver with different devices (e.g. using a single common PowerVR kernel
>   module with different display controller drivers). The same approach can be
>   used on the desktop for the multi-GPU case and the USB display case.
> 
>   - OMAP already separates the GPU and DSS drivers, but the GPU driver is some
>   kind of DSS plugin. This isn't a long-term approach.
>   - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
>   into  display subsystem since UMP, GPU has own memory management codes.
> 
>   One of the biggest challenges would be to get GPU vendors to use this new
>   model. ARM could help here, by making the Mali kernel driver split from the
>   display controller drivers. Once one vendor jumps onboard, others could have
>   a bigger incentive to follow.
> 
>   Action points:
>   - Rob planning to work on a reference implementation, as part of the sync
>     object case. This is a pretty long term plan. 
>   - Jesse will handle the coordination with ARM for Mali.

Imo splitting up SoC drm drivers into separate drivers for the different
blocks makes tons of sense. The one controlling the display subsystem
would then also support kms, all the others would just support gem and
share buffers with dma_buf (and maybe synchronize with some new-fangled
sync objects). Otoh it doesn't make much sense to push this if we don't
have at least one of the SoC ip block verndors on board. We can dream ...

[snip]

> ***  Sync objects ***
> 
>   Goal: Implement in-kernel support for buffer swapping, dependency system,
>   sync objects, queue/dequeue userspace API (think EGLstream & EGLsync)
> 
>   This can be implemented in kernel-space (with direct communication between
>   drivers to schedule buffers around), user-space (with ioctls to
>   queue/dequeue buffers), or a mix of both. SoCs with direct sync object
>   support at the hardware level between different IP blocks can be foreseen in
>   the (near ?) future. A kernel-space API would then be needed.
> 
>   Sharing sync objects between subsystems could result in the creation of a
>   cross-subsystem queue/dequeue API. Integration with dma_buf would make
>   sense, a dma_buf_pool object would then likely be needed.
> 
>   If the SoC supports direct signaling between IP blocks, this could be
>   considered (and implemented) as a pipeline configurable through the Media
>   Controller API. However, applications will then need to be link-aware. Using
>   sync/stream objects would offer a single API to userspace, regardless of
>   whether the synchronization is handled by the CPU in kernel space or by the
>   IP blocks directly.
> 
>   Sync objects are not always tied to buffers, they need to be implemented as
>   stand-alone objects on the kernel side. However, when exposing the sync
>   object to userspace in order to share it between devices, all current use
>   cases involve dma-buf. The first implementation will thus not expose the
>   sync objects explicitly to userspace, but associate them with a dma-buf. If
>   sync objects with no associated dma-buf are later needed, an explicit
>   userspace API can be added.
> 
>   eventfd is a possible candidate for sync object implementation.
> 
>   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=include/linux/eventfd.h
>   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/cgroups.txt
>   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/memory.txt
>   http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/virtual/kvm/api.txt
> 
>   Action points:
>   - TBD, will be on the agenda for the Graphics Summit @ELC2012.

I've already started discussing this a bit with Rob. I'm not sure whether
implicitly associating a sync object with a dma_buf makes sense, afaik
sync objects can be used rather independently from buffers. But this is a
long-term feature, so we still have plenty of time to discuss this.

[snip]

> *** 2D Kernel APIs ***
> 
>   Goal: Expose a 2D acceleration API to userspace for devices that support
>   hardware-accelerated 2D rendering.
> 
>   If the hardware is based on a command stream, a userspace library is needed
>   anyway to build the command stream. A 2D kernel API would then not be very
>   useful. This could be split to a DRM device without a KMS interface.

Imo we should ditch this - fb accel doesn't belong into the kernel. Even
on hw that still has a blitter for easy 2d accel without a complete 3d
state setup necessary, it's not worth it. Chris Wilson from our team once
played around with implementing fb accel in the kernel (i915 hw still has
a blitter engine in the latest generations). He quickly noticed that to
have decent speed, competitive with s/w rendering by the cpu he needs the
entire batch and buffer management stuff from userspace. And to really
beat the cpu, you need even more magic.

If you want fast 2d accel, use something like cairo.

Cheers, Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply

* Re: [patch] viafb: NULL dereference on allocation failure in query_edid()
From: Florian Tobias Schandinat @ 2012-02-17  7:30 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20120217064501.GD3666@elgon.mountain>

On 02/17/2012 06:45 AM, Dan Carpenter wrote:
> We should handle the allocation here, if only to keep the static
> checkers happy.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Ah, thanks for noticing it and sorry that I introduced it in the first place.
Applied.


Thanks,

Florian Tobias Schandinat

> 
> diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
> index 03f7a41..754d450 100644
> --- a/drivers/video/via/via_aux_edid.c
> +++ b/drivers/video/via/via_aux_edid.c
> @@ -36,10 +36,13 @@ static void query_edid(struct via_aux_drv *drv)
>  	unsigned char edid[EDID_LENGTH];
>  	bool valid = false;
>  
> -	if (spec)
> +	if (spec) {
>  		fb_destroy_modedb(spec->modedb);
> -	else
> +	} else {
>  		spec = kmalloc(sizeof(*spec), GFP_KERNEL);
> +		if (!spec)
> +			return;
> +	}
>  
>  	spec->version = spec->revision = 0;
>  	if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
> 


^ permalink raw reply

* [patch] viafb: NULL dereference on allocation failure in query_edid()
From: Dan Carpenter @ 2012-02-17  6:45 UTC (permalink / raw)
  To: linux-fbdev

We should handle the allocation here, if only to keep the static
checkers happy.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
index 03f7a41..754d450 100644
--- a/drivers/video/via/via_aux_edid.c
+++ b/drivers/video/via/via_aux_edid.c
@@ -36,10 +36,13 @@ static void query_edid(struct via_aux_drv *drv)
 	unsigned char edid[EDID_LENGTH];
 	bool valid = false;
 
-	if (spec)
+	if (spec) {
 		fb_destroy_modedb(spec->modedb);
-	else
+	} else {
 		spec = kmalloc(sizeof(*spec), GFP_KERNEL);
+		if (!spec)
+			return;
+	}
 
 	spec->version = spec->revision = 0;
 	if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {

^ permalink raw reply related

* Kernel Display and Video API Consolidation mini-summit at ELC 2012 - Notes
From: Laurent Pinchart @ 2012-02-16 23:25 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sakari Ailus, Sumit Semwal, Jesse Barker, Jesse Barnes, Rob Clark,
	Pawel Osciak, Marek Szyprowski, Tomasz Stanislawski, Magnus Damm,
	Marcus Lorentzon, Alexander Deucher, linux-media, dri-devel,
	linux-fbdev
In-Reply-To: <1654816.MX2JJ87BEo@avalon>

Hello everybody,

First of all, I would like to thank all the attendees for their participation 
in the mini-summit that helped make the meeting a success.

Here are my consolidated notes that cover both the Linaro Connect meeting and 
the ELC meeting. They're also available at 
http://www.ideasonboard.org/media/meetings/.


Kernel Display and Video API Consolidation mini-summit at ELC 2012
------------------------------------------------------------------

***  Video Transmitter Drivers ***

  Goal: Sharing video transmitter drivers (i2c or 'IP block') between V4L and
  DRM.

  This is mostly useful for embedded systems. Transmitters can be used by both
  GPUs and direct video outputs. Having a single driver for external (or even
  internal) HDMI transmitters is desired to avoid code duplication between
  subsystems.

  - DRM/KMS implements support for transmitters as DRM encoders. Code is
    embedded in the main DRM/KMS driver.
  - V4L2 implements transmitter drivers as generic kernel objects called
    v4l2_subdev that implement a set of abstract operations.

  v4l2_subdev already solves (most of ?) the problem, but is specific to V4L2.
  The proposed approach is to create a media_video_entity (exact name to be
  defined) object similar to v4l2_subdev.

  Using that API should not be mandatory, especially on hardware where the
  transmitter and the display controller are deeply cross-dependent.

  How to instantiate the transmitter device and how to handle probe order
  needs to be solved, especially when DT binding come into play. The problem
  already exists to some extend in V4L2.

  The subdev API takes mbus formats as arguments, which is not handled by
  DRM/KMS. V4L2 media bus codes will then need to be shared.

  Action points:
  - Initially, mostly FBDEV (HDMI-on-DSI, Renesas) and V4L2 (TI hardware,
    Cisco). Hans + Laurent to work on a proposal.

***  Display Panel Drivers ***

  Goal: Sharing display panel drivers between display controllers from
  different vendors.

  Panels are connected to the display controller through a standard bus with a
  control channel (DSI and eDP are two major such buses). Various vendors have
  created proprietary interfaces for panel drivers:

  - TI on OMAP (drivers/video/omap2/displays).
  - Samsung on Exynos (drivers/video/exynos).
  - ST-Ericsson on MCDE (http://www.igloocommunity.org/gitweb/?p=kernel/igloo-
kernel.git;a=tree;f=drivers/video/mcde)
  - Renesas is working on a similar interface for SH Mobile.

  HDMI-on-DSI transmitters, while not panels per-se, can be supported through
  the same API.

  A Low level Linux Display Framework (https://lkml.org/lkml/2011/9/15/107)
  has been proposed and overlaps with this topic.

  For DSI, a possible abstraction level would be a DCS (Display Command Set)
  bus. Panels and/or HDMI-on-DSI transmitter drivers would be implemented as
  DCS drivers.

  Action points:
  - Marcus to work on a proposal for DCS-based panels (with Tomi Valkeinen and
    Morimoto-san).

***  Common video mode data structure and EDID parser ***

  Goal: Sharing an EDID parser between DRM/KMS, FBDEV and V4L2.

  The DRM EDID parser is currently the most advanced implementation and will
  be taken as a starting point.

  Different subsystems use different data structures to describe video
  mode/timing information:

  - struct drm_mode_modeinfo in DRM/KMS
  - struct fb_videomode in FBDEV
  - struct v4l2_bt_timings in V4L2

  A new common video mode/timing data structure (struct media_video_mode_info,
  exact name is to be defined), not tied to any specific subsystem, is
  required to share the EDID parser. That structure won't be exported to
  userspace.

  Helper functions will be implemented in the subsystems to convert between
  that generic structure and the various subsystem-specific structures.

  The mode list is stored in the DRM connector in the EDID parser. A new mode
  list data structure can be added, or a callback function can be used by the
  parser to give modes one at a time to the caller.

  3D needs to be taken into account (this is similar to interlacing).

  Action points:
  - Laurent to work on a proposal. The DRM/KMS EDID parser will be reused.
  
***  Shared in-kernel image/framebuffer object type ***

  Goal: Describe dma-buf content in a generic cross-subsystem way.

  Most formats can be described by 4CC, width, height and pitch. Strange
  hardware-specific formats might not be possible to describes completely
  generically.

  However, format negotiation goes through userspace anyway, so there should
  be no need for passing format information directly between drivers.

  Action points:
  - None, this task will not be worked on.

***  Central 4CC Documentation ***

  Goal: Define and document 4CCs in a central location to make sure 4CCs won't
  overlap or have different meanings for different subsystems.

  DRM and V4L2 define their own 4CCs:

  - include/drm/drm-fourccs.h
  - include/linux/videodev2.h

  A new header file will centralize the definitions, with a new
  cross-subsystem prefix. DRM and V4L2 4CCs will be redefined as aliases for
  the new centralized 4CCs.

  Colorspace (including both color matrix and Y/U/V ranges) should be shared
  as well. VDPAU (and VAAPI ?) pass the color matrix to userspace. The kernel
  API should not be more restrictive, but we just need a couple of presets in
  most cases. We can define a list of common presets, with a way to upload a
  custom matrix.

  Action points:
  - Start with the V4L2 documentation, create a shared header file. Sakari to
    work on a proposal.

***  Split KMS and GPU Drivers ***

  Goal: Split KMS and GPU drivers with in kernel API inbetween.
 
  In most (all ?) SoCs, the GPU and the display controller are separate
  devices. Splitting them into separate drivers would allow reusing the GPU
  driver with different devices (e.g. using a single common PowerVR kernel
  module with different display controller drivers). The same approach can be
  used on the desktop for the multi-GPU case and the USB display case.

  - OMAP already separates the GPU and DSS drivers, but the GPU driver is some
  kind of DSS plugin. This isn't a long-term approach.
  - Exynos also separates the GPU and FIMD drivers. It's hard to merge GPU
  into  display subsystem since UMP, GPU has own memory management codes.

  One of the biggest challenges would be to get GPU vendors to use this new
  model. ARM could help here, by making the Mali kernel driver split from the
  display controller drivers. Once one vendor jumps onboard, others could have
  a bigger incentive to follow.

  Action points:
  - Rob planning to work on a reference implementation, as part of the sync
    object case. This is a pretty long term plan. 
  - Jesse will handle the coordination with ARM for Mali.
  
***  HDMI CEC Support ***

  Goal: Support HDMI CEC and offer a userspace API for applications.

  A new kernel API is needed and must be usable by KMS, V4L2 and possibly
  LIRC. There's ongoing effort from Cisco to implement HDMI CEC support. Given
  their background, V4L2 is their initial target. A proposal is available at
  http://www.mail-archive.com/linux-media@vger.kernel.org/msg29241.html with a
  sample implementation at
  http://git.linuxtv.org/hverkuil/cisco.git/shortlog/refs/heads/cobalt-
mainline
  (drivers/media/video/adv7604.c and ad9389b.c.

  In order to avoid API duplication, a new CEC subsystem is probably needed.
  CEC could be modeled as a bus, or as a network device. With the network
  device approach, we could have both kernel and userspace protocol handlers.

  CEC devices need to be associated with HDMI connectors. The Media Controller
  API is a good candidate.

  Action points:
  - Hans is planning to push CEC support to mainline this year. Marcus can
    provide contact information for Per Persson (ST Ericsson).

***  Hardware Pipeline Configuration ***

  Goal: Create a central shared API to configure hardware pipelines on any
  display- or video-related device.

  Hardware pipeline configuration includes both link and format configuration.
  To handle complex pipelines, V4L2 created a userspace V4L2 subdev API that
  works in cooperation with the Media Controller API. Such an approach could
  be generalized to support DRM/KMS, FB and V4L2 devices with a single
  pipeline configuration API.

  However, DRM/KMS can configure a complete display pipeline directly, without
  any need for userspace to access formats on specific pads directly. There is
  thus no direct need (at least for today's hardware) to expose low-level
  pipeline configuration to userspace.

  For display devices, DRM/KMS is going to support configuration of multiple
  overlays/planes. fbdev support will be available "for free" on top of
  DRM/KMS for legacy applications and for fbcon. fbdev should probably not be
  extended to support multiple overlays/planes explicitly. Drivers and
  applications should implement and use KMS instead, and no new FB or V4L2
  frontend should be implemented in new display drivers.

  Implementing the Media Controller API in DRM/KMS is still useful to
  associate connectors with HDMI audio/CEC devices. More than that would
  probably be overkill.

  Action points:
  - Laurent to check the DRM/KMS API to make sure it fulfills all the V4L2
    needs. dma-buf importer role in DRM/KMS is one of the required features to
    implement use cases currently supported by V4L2 USERPTR.
  - Implement a proof-of-concept media controller API in DRM to expose the 
    pipeline topology to userspace. Sumit is working on dma-buf, could maybe
    help on this. Laurent will coordinate the effort.

***  Synchronous pipeline changes ***

  Goal: Create an API to apply complex changes to a video pipeline atomically.

  Needed for complex camera use cases. On the DRM/KMS side, the approach is to
  use one big ioctl to configure the whole pipeline.

  One solution is a commit ioctl, through the media controller device, that
  would be dispatched to entities internally with a prepare step and a commit
  step.

  Parameters to be committed need to be stored in a context. We can either use
  one cross-device context, or per-device contexts that would then need to be
  associated with the commit operation.

  Action points:
  - Sakari will provide a proof-of-concept and/or proposal if needed.

***  Sync objects ***

  Goal: Implement in-kernel support for buffer swapping, dependency system,
  sync objects, queue/dequeue userspace API (think EGLstream & EGLsync)

  This can be implemented in kernel-space (with direct communication between
  drivers to schedule buffers around), user-space (with ioctls to
  queue/dequeue buffers), or a mix of both. SoCs with direct sync object
  support at the hardware level between different IP blocks can be foreseen in
  the (near ?) future. A kernel-space API would then be needed.

  Sharing sync objects between subsystems could result in the creation of a
  cross-subsystem queue/dequeue API. Integration with dma_buf would make
  sense, a dma_buf_pool object would then likely be needed.

  If the SoC supports direct signaling between IP blocks, this could be
  considered (and implemented) as a pipeline configurable through the Media
  Controller API. However, applications will then need to be link-aware. Using
  sync/stream objects would offer a single API to userspace, regardless of
  whether the synchronization is handled by the CPU in kernel space or by the
  IP blocks directly.

  Sync objects are not always tied to buffers, they need to be implemented as
  stand-alone objects on the kernel side. However, when exposing the sync
  object to userspace in order to share it between devices, all current use
  cases involve dma-buf. The first implementation will thus not expose the
  sync objects explicitly to userspace, but associate them with a dma-buf. If
  sync objects with no associated dma-buf are later needed, an explicit
  userspace API can be added.

  eventfd is a possible candidate for sync object implementation.

  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=include/linux/eventfd.h
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/cgroups.txt
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/cgroups/memory.txt
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/virtual/kvm/api.txt

  Action points:
  - TBD, will be on the agenda for the Graphics Summit @ELC2012.

***  dma-buf Implementation in V4L2 ***

  Goal: Implement the dma-buf API in V4L2.

  Sumit Semwal has submitted patches to implement the dma-buf importer role in
  videobuf2. Tomasz Stanislawski has then submitted incremental patches to add
  exporter role support.

  Action points:
  - Create a git branch to host all the latest patches. Sumit will provide
    that.



Other points that have been briefly discussed
---------------------------------------------

***  Device Tree Aware 'Subdevice' Instantiation ***

  Goal: Design standard device tree bindings to instantiate "subdevices"
  (including the generic subdev-like video transmitters).

  U-Boot developers are working on automatic configuration using the device
  tree and want to support LCDs. Proposed patches are available at
  http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/122864/focus\x122881

  On a related note, kernel PWM proposed DT binding patches for backlight
  control are available at
  http://www.spinics.net/lists/linux-tegra/msg03988.html.

*** HDMI audio output ***

  Goal: Give applications a way to associate an HDMI connector with an ALSA
  HDMI audio device.

  This should be implemented with the Media Controller API.
 
*** 2D Kernel APIs ***

  Goal: Expose a 2D acceleration API to userspace for devices that support
  hardware-accelerated 2D rendering.

  If the hardware is based on a command stream, a userspace library is needed
  anyway to build the command stream. A 2D kernel API would then not be very
  useful. This could be split to a DRM device without a KMS interface.

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Cousson, Benoit @ 2012-02-16 10:16 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Kevin Hilman, Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <1329380536.1951.26.camel@deskari>

On 2/16/2012 9:22 AM, Tomi Valkeinen wrote:
> On Wed, 2012-02-15 at 11:59 -0800, Kevin Hilman wrote:
>> "Cousson, Benoit"<b-cousson@ti.com>  writes:
>
>>> Kevin,
>>>
>>> Do we still need to set the dev.parent to omap_device_parent?
>>
>> Nope.
>>
>>> I guess the default&platform_bus parent is good enough and
>>> potentially the DSS children should be able to overwrite that.
>>
>> Yes, now that we use PM domains, we don't need it.  I just sent a patch
>> to remove omap_device_parent.
>
> But it's still not possible to create a custom parent-child hierarchy
> with omap_devices. Or can I change the parent of a platform_device after
> it has been created? (doesn't sound very clean even if I can)

Nope, it has to be done before platform_device_add.

Thanks to Ohad patch [1] that Tony has just resent, you can use the 
internal omap_device API and thus will be able to change the parent 
before the registration.

Benoit

[1] ARM: OMAP: omap_device: Expose omap_device_{alloc, delete, register}

^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Tomi Valkeinen @ 2012-02-16  8:22 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Cousson, Benoit, Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <87fweb98bs.fsf@ti.com>

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]

On Wed, 2012-02-15 at 11:59 -0800, Kevin Hilman wrote:
> "Cousson, Benoit" <b-cousson@ti.com> writes:

> > Kevin,
> >
> > Do we still need to set the dev.parent to omap_device_parent?
> 
> Nope.
> 
> > I guess the default &platform_bus parent is good enough and
> > potentially the DSS children should be able to overwrite that.
> 
> Yes, now that we use PM domains, we don't need it.  I just sent a patch
> to remove omap_device_parent.

But it's still not possible to create a custom parent-child hierarchy
with omap_devices. Or can I change the parent of a platform_device after
it has been created? (doesn't sound very clean even if I can)

 Tomi


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH] fb_defio: add first_io callback
From: Heiko Stübner @ 2012-02-16  7:34 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <201112311145.47717.heiko@sntech.de>

Hi Florian,

Am Donnerstag, 16. Februar 2012, 03:27:25 schrieb Florian Tobias Schandinat:
> Hi Heiko,
> 
> sorry for the long delay.
no problem


> On 12/31/2011 10:45 AM, Heiko Stübner wrote:
> > With this optional callback the driver is notified when the first page
> > is entered into the pagelist and a new deferred_io call is scheduled.
> > 
> > A possible use-case for this is runtime-pm. In the first_io call
> > 
> > 	pm_runtime_get()
> > 
> > could be called, which starts an asynchronous runtime_resume of the
> > device. In the deferred_io callback a call to
> > 
> > 	pm_runtime_barrier()
> > 
> > makes the sure, the device is resumed by then and a
> > 
> > 	pm_runtime_put()
> > 
> > may put the device back to sleep.
> > 
> > Also, some SoCs may use the runtime-pm system to determine if they
> > are able to enter deeper idle states. Therefore it is necessary to
> > keep the use-count from the first written page until the conclusion
> > of the screen update, to prevent the system from going to sleep before
> > completing the pending update.
> > 
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> 
> while I consider this patch acceptable, I don't see any reason to apply it
> as long as there is no driver actually using it.
ok, so I will keep sitting on it until my driver for the AUO-K190x epd 
controller is ready for primetime and resubmit this patch in conjunction with 
it.

Heiko

^ permalink raw reply

* linux-next: build failure after merge of the final tree (fbdev tree related)
From: Stephen Rothwell @ 2012-02-16  5:29 UTC (permalink / raw)
  To: Florian Tobias Schandinat, linux-fbdev
  Cc: linux-next, linux-kernel, Ondrej Zary
In-Reply-To: <20110520163233.abcabd67.sfr@canb.auug.org.au>

[-- Attachment #1: Type: text/plain, Size: 504 bytes --]

Hi all,

After merging the final tree, today's linux-next build (powerpc
allyesconfig) failed like this:

drivers/video/i740fb.c: In function 'i740fb_remove':
drivers/video/i740fb.c:1192:7: error: 'par' undeclared (first use in this function)

Caused by commit 5350c65f4f15 ("Resurrect Intel740 driver: i740fb") from
the fbdev tree.  CONFIG_MTRR is not defined for this build ...

I have reverted that commit for today.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH] fb_defio: add first_io callback
From: Florian Tobias Schandinat @ 2012-02-16  2:27 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <201112311145.47717.heiko@sntech.de>

Hi Heiko,

sorry for the long delay.

On 12/31/2011 10:45 AM, Heiko Stübner wrote:
> With this optional callback the driver is notified when the first page
> is entered into the pagelist and a new deferred_io call is scheduled.
> 
> A possible use-case for this is runtime-pm. In the first_io call
> 	pm_runtime_get()
> could be called, which starts an asynchronous runtime_resume of the
> device. In the deferred_io callback a call to
> 	pm_runtime_barrier()
> makes the sure, the device is resumed by then and a
> 	pm_runtime_put()
> may put the device back to sleep.
> 
> Also, some SoCs may use the runtime-pm system to determine if they
> are able to enter deeper idle states. Therefore it is necessary to
> keep the use-count from the first written page until the conclusion
> of the screen update, to prevent the system from going to sleep before
> completing the pending update.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>

while I consider this patch acceptable, I don't see any reason to apply it as
long as there is no driver actually using it.


Best regards,

Florian Tobias Schandinat

> ---
>  drivers/video/fb_defio.c |    4 ++++
>  include/linux/fb.h       |    1 +
>  2 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
> index c27e153..070f26f 100644
> --- a/drivers/video/fb_defio.c
> +++ b/drivers/video/fb_defio.c
> @@ -107,6 +107,10 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
>  	/* protect against the workqueue changing the page list */
>  	mutex_lock(&fbdefio->lock);
>  
> +	/* first write in this cycle, notify the driver */
> +	if (fbdefio->first_io && list_empty(&fbdefio->pagelist))
> +		fbdefio->first_io(info);
> +
>  	/*
>  	 * We want the page to remain locked from ->page_mkwrite until
>  	 * the PTE is marked dirty to avoid page_mkclean() being called
> diff --git a/include/linux/fb.h b/include/linux/fb.h
> index 1d6836c..b86cd41 100644
> --- a/include/linux/fb.h
> +++ b/include/linux/fb.h
> @@ -602,6 +602,7 @@ struct fb_deferred_io {
>  	struct mutex lock; /* mutex that protects the page list */
>  	struct list_head pagelist; /* list of touched pages */
>  	/* callback */
> +	void (*first_io)(struct fb_info *info);
>  	void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
>  };
>  #endif


^ permalink raw reply

* Re: [PATCH v5] [resend] Resurrect Intel740 driver: i740fb
From: Florian Tobias Schandinat @ 2012-02-16  1:23 UTC (permalink / raw)
  To: Ondrej Zary
  Cc: linux-fbdev, Andrey Ulanov, Paul Mundt, Kernel development list
In-Reply-To: <201202101859.27975.linux@rainbow-software.org>

On 02/10/2012 05:59 PM, Ondrej Zary wrote:
> This is a resurrection of an old (like 2.4.19) out-of-tree driver for
> Intel740 graphics cards and adaptation for recent kernels. The old driver by
> Andrey Ulanov is located at: http://sourceforge.net/projects/i740fbdev/files/
> 
> This is a new driver based on skeletonfb, using most of the low level HW code
> from the old driver. The DDC code is completely new.
> 
> The driver was tested on two 8MB cards: Protac AG240D and Diamond Stealth II
> G460.
> 
> Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

Applied. Just for the record, checkpatch complained about

WARNING: simple_strtoul is obsolete, use kstrtoul instead
#1384: FILE: drivers/video/i740fb.c:1296:
+                       mtrr = simple_strtoul(opt + 5, NULL, 0);

Feel free to send another patch to fix it, if you like.


Thanks,

Florian Tobias Schandinat

> ---
> Changes in v5:
>  - fixed checkpatch problems
>  - added Kconfig dependency on FB_DDC
>  - cleaned up i740_calc_vclk()
>  - fixed SDRAM/SGRAM detection
>  - fixed wrong colors in 16bpp mode when neither 555 nor 565 specified
> 
> --- linux-3.2.1-orig/drivers/video/Kconfig	2012-01-12 20:42:45.000000000 +0100
> +++ linux-3.2.1/drivers/video/Kconfig	2012-01-23 20:52:32.000000000 +0100
> @@ -1123,6 +1123,18 @@ config FB_RIVA_BACKLIGHT
>  	help
>  	  Say Y here if you want to control the backlight of your display.
>  
> +config FB_I740
> +	tristate "Intel740 support (EXPERIMENTAL)"
> +	depends on EXPERIMENTAL && FB && PCI
> +	select FB_MODE_HELPERS
> +	select FB_CFB_FILLRECT
> +	select FB_CFB_COPYAREA
> +	select FB_CFB_IMAGEBLIT
> +	select VGASTATE
> +	select FB_DDC
> +	help
> +	  This driver supports graphics cards based on Intel740 chip.
> +
>  config FB_I810
>  	tristate "Intel 810/815 support (EXPERIMENTAL)"
>  	depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
> --- linux-3.2.1-orig/drivers/video/Makefile	2012-01-12 20:42:45.000000000 +0100
> +++ linux-3.2.1/drivers/video/Makefile	2012-01-23 20:52:32.000000000 +0100
> @@ -37,6 +37,7 @@ obj-$(CONFIG_FB_GRVGA)            += grv
>  obj-$(CONFIG_FB_PM2)              += pm2fb.o
>  obj-$(CONFIG_FB_PM3)		  += pm3fb.o
>  
> +obj-$(CONFIG_FB_I740)		  += i740fb.o
>  obj-$(CONFIG_FB_MATROX)		  += matrox/
>  obj-$(CONFIG_FB_RIVA)		  += riva/
>  obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
> --- /dev/null	2012-01-24 00:06:39.330222901 +0100
> +++ linux-3.2.1/drivers/video/i740fb.c	2012-01-24 00:01:54.000000000 +0100
> @@ -0,0 +1,1337 @@
> +/*
> + * i740fb - framebuffer driver for Intel740
> + * Copyright (c) 2011 Ondrej Zary
> + *
> + * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
> + * which was partially based on:
> + *  VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
> + *	and Petr Vandrovec <VANDROVE@vc.cvut.cz>
> + *  i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
> + *	Texas.
> + *  i740fb by Patrick LERDA, v0.9
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/delay.h>
> +#include <linux/fb.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/pci_ids.h>
> +#include <linux/i2c.h>
> +#include <linux/i2c-algo-bit.h>
> +#include <linux/console.h>
> +#include <video/vga.h>
> +
> +#ifdef CONFIG_MTRR
> +#include <asm/mtrr.h>
> +#endif
> +
> +#include "i740_reg.h"
> +
> +static char *mode_option __devinitdata;
> +
> +#ifdef CONFIG_MTRR
> +static int mtrr __devinitdata = 1;
> +#endif
> +
> +struct i740fb_par {
> +	unsigned char __iomem *regs;
> +	bool has_sgram;
> +#ifdef CONFIG_MTRR
> +	int mtrr_reg;
> +#endif
> +	bool ddc_registered;
> +	struct i2c_adapter ddc_adapter;
> +	struct i2c_algo_bit_data ddc_algo;
> +	u32 pseudo_palette[16];
> +	struct mutex open_lock;
> +	unsigned int ref_count;
> +
> +	u8 crtc[VGA_CRT_C];
> +	u8 atc[VGA_ATT_C];
> +	u8 gdc[VGA_GFX_C];
> +	u8 seq[VGA_SEQ_C];
> +	u8 misc;
> +	u8 vss;
> +
> +	/* i740 specific registers */
> +	u8 display_cntl;
> +	u8 pixelpipe_cfg0;
> +	u8 pixelpipe_cfg1;
> +	u8 pixelpipe_cfg2;
> +	u8 video_clk2_m;
> +	u8 video_clk2_n;
> +	u8 video_clk2_mn_msbs;
> +	u8 video_clk2_div_sel;
> +	u8 pll_cntl;
> +	u8 address_mapping;
> +	u8 io_cntl;
> +	u8 bitblt_cntl;
> +	u8 ext_vert_total;
> +	u8 ext_vert_disp_end;
> +	u8 ext_vert_sync_start;
> +	u8 ext_vert_blank_start;
> +	u8 ext_horiz_total;
> +	u8 ext_horiz_blank;
> +	u8 ext_offset;
> +	u8 interlace_cntl;
> +	u32 lmi_fifo_watermark;
> +	u8 ext_start_addr;
> +	u8 ext_start_addr_hi;
> +};
> +
> +#define DACSPEED8	203
> +#define DACSPEED16	163
> +#define DACSPEED24_SG	136
> +#define DACSPEED24_SD	128
> +#define DACSPEED32	86
> +
> +static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
> +	.id =		"i740fb",
> +	.type =		FB_TYPE_PACKED_PIXELS,
> +	.visual =	FB_VISUAL_TRUECOLOR,
> +	.xpanstep =	8,
> +	.ypanstep =	1,
> +	.accel =	FB_ACCEL_NONE,
> +};
> +
> +static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
> +{
> +	vga_mm_w(par->regs, port, val);
> +}
> +static inline u8 i740inb(struct i740fb_par *par, u16 port)
> +{
> +	return vga_mm_r(par->regs, port);
> +}
> +static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
> +{
> +	vga_mm_w_fast(par->regs, port, reg, val);
> +}
> +static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
> +{
> +	vga_mm_w(par->regs, port, reg);
> +	return vga_mm_r(par->regs, port+1);
> +}
> +static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
> +				   u8 val, u8 mask)
> +{
> +	vga_mm_w_fast(par->regs, port, reg, (val & mask)
> +		| (i740inreg(par, port, reg) & ~mask));
> +}
> +
> +#define REG_DDC_DRIVE	0x62
> +#define REG_DDC_STATE	0x63
> +#define DDC_SCL		(1 << 3)
> +#define DDC_SDA		(1 << 2)
> +
> +static void i740fb_ddc_setscl(void *data, int val)
> +{
> +	struct i740fb_par *par = data;
> +
> +	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
> +	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
> +}
> +
> +static void i740fb_ddc_setsda(void *data, int val)
> +{
> +	struct i740fb_par *par = data;
> +
> +	i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
> +	i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
> +}
> +
> +static int i740fb_ddc_getscl(void *data)
> +{
> +	struct i740fb_par *par = data;
> +
> +	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
> +
> +	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
> +}
> +
> +static int i740fb_ddc_getsda(void *data)
> +{
> +	struct i740fb_par *par = data;
> +
> +	i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
> +
> +	return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
> +}
> +
> +static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
> +{
> +	struct i740fb_par *par = info->par;
> +
> +	strlcpy(par->ddc_adapter.name, info->fix.id,
> +		sizeof(par->ddc_adapter.name));
> +	par->ddc_adapter.owner		= THIS_MODULE;
> +	par->ddc_adapter.class		= I2C_CLASS_DDC;
> +	par->ddc_adapter.algo_data	= &par->ddc_algo;
> +	par->ddc_adapter.dev.parent	= info->device;
> +	par->ddc_algo.setsda		= i740fb_ddc_setsda;
> +	par->ddc_algo.setscl		= i740fb_ddc_setscl;
> +	par->ddc_algo.getsda		= i740fb_ddc_getsda;
> +	par->ddc_algo.getscl		= i740fb_ddc_getscl;
> +	par->ddc_algo.udelay		= 10;
> +	par->ddc_algo.timeout		= 20;
> +	par->ddc_algo.data		= par;
> +
> +	i2c_set_adapdata(&par->ddc_adapter, par);
> +
> +	return i2c_bit_add_bus(&par->ddc_adapter);
> +}
> +
> +static int i740fb_open(struct fb_info *info, int user)
> +{
> +	struct i740fb_par *par = info->par;
> +
> +	mutex_lock(&(par->open_lock));
> +	par->ref_count++;
> +	mutex_unlock(&(par->open_lock));
> +
> +	return 0;
> +}
> +
> +static int i740fb_release(struct fb_info *info, int user)
> +{
> +	struct i740fb_par *par = info->par;
> +
> +	mutex_lock(&(par->open_lock));
> +	if (par->ref_count = 0) {
> +		printk(KERN_ERR "fb%d: release called with zero refcount\n",
> +			info->node);
> +		mutex_unlock(&(par->open_lock));
> +		return -EINVAL;
> +	}
> +
> +	par->ref_count--;
> +	mutex_unlock(&(par->open_lock));
> +
> +	return 0;
> +}
> +
> +static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
> +{
> +	/*
> +	 * Would like to calculate these values automatically, but a generic
> +	 * algorithm does not seem possible.  Note: These FIFO water mark
> +	 * values were tested on several cards and seem to eliminate the
> +	 * all of the snow and vertical banding, but fine adjustments will
> +	 * probably be required for other cards.
> +	 */
> +
> +	u32 wm;
> +
> +	switch (bpp) {
> +	case 8:
> +		if	(freq > 200)
> +			wm = 0x18120000;
> +		else if (freq > 175)
> +			wm = 0x16110000;
> +		else if (freq > 135)
> +			wm = 0x120E0000;
> +		else
> +			wm = 0x100D0000;
> +		break;
> +	case 15:
> +	case 16:
> +		if (par->has_sgram) {
> +			if	(freq > 140)
> +				wm = 0x2C1D0000;
> +			else if (freq > 120)
> +				wm = 0x2C180000;
> +			else if (freq > 100)
> +				wm = 0x24160000;
> +			else if (freq >  90)
> +				wm = 0x18120000;
> +			else if (freq >  50)
> +				wm = 0x16110000;
> +			else if (freq >  32)
> +				wm = 0x13100000;
> +			else
> +				wm = 0x120E0000;
> +		} else {
> +			if	(freq > 160)
> +				wm = 0x28200000;
> +			else if (freq > 140)
> +				wm = 0x2A1E0000;
> +			else if (freq > 130)
> +				wm = 0x2B1A0000;
> +			else if (freq > 120)
> +				wm = 0x2C180000;
> +			else if (freq > 100)
> +				wm = 0x24180000;
> +			else if (freq >  90)
> +				wm = 0x18120000;
> +			else if (freq >  50)
> +				wm = 0x16110000;
> +			else if (freq >  32)
> +				wm = 0x13100000;
> +			else
> +				wm = 0x120E0000;
> +		}
> +		break;
> +	case 24:
> +		if (par->has_sgram) {
> +			if	(freq > 130)
> +				wm = 0x31200000;
> +			else if (freq > 120)
> +				wm = 0x2E200000;
> +			else if (freq > 100)
> +				wm = 0x2C1D0000;
> +			else if (freq >  80)
> +				wm = 0x25180000;
> +			else if (freq >  64)
> +				wm = 0x24160000;
> +			else if (freq >  49)
> +				wm = 0x18120000;
> +			else if (freq >  32)
> +				wm = 0x16110000;
> +			else
> +				wm = 0x13100000;
> +		} else {
> +			if	(freq > 120)
> +				wm = 0x311F0000;
> +			else if (freq > 100)
> +				wm = 0x2C1D0000;
> +			else if (freq >  80)
> +				wm = 0x25180000;
> +			else if (freq >  64)
> +				wm = 0x24160000;
> +			else if (freq >  49)
> +				wm = 0x18120000;
> +			else if (freq >  32)
> +				wm = 0x16110000;
> +			else
> +				wm = 0x13100000;
> +		}
> +		break;
> +	case 32:
> +		if (par->has_sgram) {
> +			if	(freq >  80)
> +				wm = 0x2A200000;
> +			else if (freq >  60)
> +				wm = 0x281A0000;
> +			else if (freq >  49)
> +				wm = 0x25180000;
> +			else if (freq >  32)
> +				wm = 0x18120000;
> +			else
> +				wm = 0x16110000;
> +		} else {
> +			if	(freq >  80)
> +				wm = 0x29200000;
> +			else if (freq >  60)
> +				wm = 0x281A0000;
> +			else if (freq >  49)
> +				wm = 0x25180000;
> +			else if (freq >  32)
> +				wm = 0x18120000;
> +			else
> +				wm = 0x16110000;
> +		}
> +		break;
> +	}
> +
> +	return wm;
> +}
> +
> +/* clock calculation from i740fb by Patrick LERDA */
> +
> +#define I740_RFREQ		1000000
> +#define TARGET_MAX_N		30
> +#define I740_FFIX		(1 << 8)
> +#define I740_RFREQ_FIX		(I740_RFREQ / I740_FFIX)
> +#define I740_REF_FREQ		(6667 * I740_FFIX / 100)	/* 66.67 MHz */
> +#define I740_MAX_VCO_FREQ	(450 * I740_FFIX)		/* 450 MHz */
> +
> +static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
> +{
> +	const u32 err_max    = freq / (200  * I740_RFREQ / I740_FFIX);
> +	const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
> +	u32 err_best = 512 * I740_FFIX;
> +	u32 f_err, f_vco;
> +	int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
> +	int m, n;
> +
> +	p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
> +	d_best = 0;
> +	f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
> +	freq = freq / I740_RFREQ_FIX;
> +
> +	n = 2;
> +	do {
> +		n++;
> +		m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
> +
> +		if (m < 3)
> +			m = 3;
> +
> +		{
> +			u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
> +				 / n) + ((1 << p_best) / 2)) / (1 << p_best);
> +
> +			f_err = (freq - f_out);
> +
> +			if (abs(f_err) < err_max) {
> +				m_best = m;
> +				n_best = n;
> +				err_best = f_err;
> +			}
> +		}
> +	} while ((abs(f_err) >= err_target) &&
> +		 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
> +
> +	if (abs(f_err) < err_target) {
> +		m_best = m;
> +		n_best = n;
> +	}
> +
> +	par->video_clk2_m = (m_best - 2) & 0xFF;
> +	par->video_clk2_n = (n_best - 2) & 0xFF;
> +	par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
> +				 | (((m_best - 2) >> 8) & VCO_M_MSBS));
> +	par->video_clk2_div_sel > +		((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
> +}
> +
> +static int i740fb_decode_var(const struct fb_var_screeninfo *var,
> +			     struct i740fb_par *par, struct fb_info *info)
> +{
> +	/*
> +	 * Get the video params out of 'var'.
> +	 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
> +	 */
> +
> +	u32 xres, right, hslen, left, xtotal;
> +	u32 yres, lower, vslen, upper, ytotal;
> +	u32 vxres, xoffset, vyres, yoffset;
> +	u32 bpp, base, dacspeed24, mem;
> +	u8 r7;
> +	int i;
> +
> +	dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
> +		  var->xres, var->yres, var->xres_virtual, var->xres_virtual);
> +	dev_dbg(info->device, "	xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
> +		  var->xoffset, var->yoffset, var->bits_per_pixel,
> +		  var->grayscale);
> +	dev_dbg(info->device, "	activate: %i, nonstd: %i, vmode: %i\n",
> +		  var->activate, var->nonstd, var->vmode);
> +	dev_dbg(info->device, "	pixclock: %i, hsynclen:%i, vsynclen:%i\n",
> +		  var->pixclock, var->hsync_len, var->vsync_len);
> +	dev_dbg(info->device, "	left: %i, right: %i, up:%i, lower:%i\n",
> +		  var->left_margin, var->right_margin, var->upper_margin,
> +		  var->lower_margin);
> +
> +
> +	bpp = var->bits_per_pixel;
> +	switch (bpp) {
> +	case 1 ... 8:
> +		bpp = 8;
> +		if ((1000000 / var->pixclock) > DACSPEED8) {
> +			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
> +				1000000 / var->pixclock, DACSPEED8);
> +			return -EINVAL;
> +		}
> +		break;
> +	case 9 ... 15:
> +		bpp = 15;
> +	case 16:
> +		if ((1000000 / var->pixclock) > DACSPEED16) {
> +			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
> +				1000000 / var->pixclock, DACSPEED16);
> +			return -EINVAL;
> +		}
> +		break;
> +	case 17 ... 24:
> +		bpp = 24;
> +		dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
> +		if ((1000000 / var->pixclock) > dacspeed24) {
> +			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
> +				1000000 / var->pixclock, dacspeed24);
> +			return -EINVAL;
> +		}
> +		break;
> +	case 25 ... 32:
> +		bpp = 32;
> +		if ((1000000 / var->pixclock) > DACSPEED32) {
> +			dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
> +				1000000 / var->pixclock, DACSPEED32);
> +			return -EINVAL;
> +		}
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	xres = ALIGN(var->xres, 8);
> +	vxres = ALIGN(var->xres_virtual, 16);
> +	if (vxres < xres)
> +		vxres = xres;
> +
> +	xoffset = ALIGN(var->xoffset, 8);
> +	if (xres + xoffset > vxres)
> +		xoffset = vxres - xres;
> +
> +	left = ALIGN(var->left_margin, 8);
> +	right = ALIGN(var->right_margin, 8);
> +	hslen = ALIGN(var->hsync_len, 8);
> +
> +	yres = var->yres;
> +	vyres = var->yres_virtual;
> +	if (yres > vyres)
> +		vyres = yres;
> +
> +	yoffset = var->yoffset;
> +	if (yres + yoffset > vyres)
> +		yoffset = vyres - yres;
> +
> +	lower = var->lower_margin;
> +	vslen = var->vsync_len;
> +	upper = var->upper_margin;
> +
> +	mem = vxres * vyres * ((bpp + 1) / 8);
> +	if (mem > info->screen_size) {
> +		dev_err(info->device, "not enough video memory (%d KB requested, %ld KB avaliable)\n",
> +			mem >> 10, info->screen_size >> 10);
> +		return -ENOMEM;
> +	}
> +
> +	if (yoffset + yres > vyres)
> +		yoffset = vyres - yres;
> +
> +	xtotal = xres + right + hslen + left;
> +	ytotal = yres + lower + vslen + upper;
> +
> +	par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
> +	par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
> +	par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
> +	par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
> +	par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
> +		| ((((xres + right + hslen) >> 3) & 0x20) << 2);
> +	par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
> +		| 0x80;
> +
> +	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
> +
> +	r7 = 0x10;	/* disable linecompare */
> +	if (ytotal & 0x100)
> +		r7 |= 0x01;
> +	if (ytotal & 0x200)
> +		r7 |= 0x20;
> +
> +	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
> +	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
> +	if (var->vmode & FB_VMODE_DOUBLE)
> +		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
> +	par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
> +	par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
> +	par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
> +	par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
> +	par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
> +	if ((yres-1) & 0x100)
> +		r7 |= 0x02;
> +	if ((yres-1) & 0x200)
> +		r7 |= 0x40;
> +
> +	par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
> +	par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
> +	if ((yres + lower - 1) & 0x100)
> +		r7 |= 0x0C;
> +	if ((yres + lower - 1) & 0x200) {
> +		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
> +		r7 |= 0x80;
> +	}
> +
> +	/* disabled IRQ */
> +	par->crtc[VGA_CRTC_V_SYNC_END] > +		((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
> +	/* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
> +	par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
> +
> +	par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
> +	par->crtc[VGA_CRTC_MODE] = 0xC3 ;
> +	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
> +	par->crtc[VGA_CRTC_OVERFLOW] = r7;
> +
> +	par->vss = 0x00;	/* 3DA */
> +
> +	for (i = 0x00; i < 0x10; i++)
> +		par->atc[i] = i;
> +	par->atc[VGA_ATC_MODE] = 0x81;
> +	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
> +	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
> +	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
> +
> +	par->misc = 0xC3;
> +	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
> +		par->misc &= ~0x40;
> +	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
> +		par->misc &= ~0x80;
> +
> +	par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
> +	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
> +	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
> +	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
> +
> +	par->gdc[VGA_GFX_SR_VALUE] = 0x00;
> +	par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
> +	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
> +	par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
> +	par->gdc[VGA_GFX_PLANE_READ] = 0;
> +	par->gdc[VGA_GFX_MODE] = 0x02;
> +	par->gdc[VGA_GFX_MISC] = 0x05;
> +	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
> +	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
> +
> +	base = (yoffset * vxres + (xoffset & ~7)) >> 2;
> +	switch (bpp) {
> +	case 8:
> +		par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
> +		par->ext_offset = vxres >> 11;
> +		par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
> +		par->bitblt_cntl = COLEXP_8BPP;
> +		break;
> +	case 15: /* 0rrrrrgg gggbbbbb */
> +	case 16: /* rrrrrggg gggbbbbb */
> +		par->pixelpipe_cfg1 = (var->green.length = 6) ?
> +			DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
> +		par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
> +		par->ext_offset = vxres >> 10;
> +		par->bitblt_cntl = COLEXP_16BPP;
> +		base *= 2;
> +		break;
> +	case 24:
> +		par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
> +		par->ext_offset = (vxres * 3) >> 11;
> +		par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
> +		par->bitblt_cntl = COLEXP_24BPP;
> +		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
> +		base *= 3;
> +		break;
> +	case 32:
> +		par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
> +		par->ext_offset = vxres >> 9;
> +		par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
> +		par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
> +		base *= 4;
> +		break;
> +	}
> +
> +	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
> +	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
> +	par->ext_start_addr > +		((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
> +	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
> +
> +	par->pixelpipe_cfg0 = DAC_8_BIT;
> +
> +	par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
> +	par->io_cntl = EXTENDED_CRTC_CNTL;
> +	par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
> +	par->display_cntl = HIRES_MODE;
> +
> +	/* Set the MCLK freq */
> +	par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
> +
> +	/* Calculate the extended CRTC regs */
> +	par->ext_vert_total = (ytotal - 2) >> 8;
> +	par->ext_vert_disp_end = (yres - 1) >> 8;
> +	par->ext_vert_sync_start = (yres + lower) >> 8;
> +	par->ext_vert_blank_start = (yres + lower) >> 8;
> +	par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
> +	par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
> +
> +	par->interlace_cntl = INTERLACE_DISABLE;
> +
> +	/* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
> +	par->atc[VGA_ATC_OVERSCAN] = 0;
> +
> +	/* Calculate VCLK that most closely matches the requested dot clock */
> +	i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
> +
> +	/* Since we program the clocks ourselves, always use VCLK2. */
> +	par->misc |= 0x0C;
> +
> +	/* Calculate the FIFO Watermark and Burst Length. */
> +	par->lmi_fifo_watermark > +		i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
> +
> +	return 0;
> +}
> +
> +static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
> +{
> +	switch (var->bits_per_pixel) {
> +	case 8:
> +		var->red.offset	= var->green.offset = var->blue.offset = 0;
> +		var->red.length	= var->green.length = var->blue.length = 8;
> +		break;
> +	case 16:
> +		switch (var->green.length) {
> +		default:
> +		case 5:
> +			var->red.offset = 10;
> +			var->green.offset = 5;
> +			var->blue.offset = 0;
> +			var->red.length	= 5;
> +			var->green.length = 5;
> +			var->blue.length = 5;
> +			break;
> +		case 6:
> +			var->red.offset = 11;
> +			var->green.offset = 5;
> +			var->blue.offset = 0;
> +			var->red.length = var->blue.length = 5;
> +			break;
> +		}
> +		break;
> +	case 24:
> +		var->red.offset = 16;
> +		var->green.offset = 8;
> +		var->blue.offset = 0;
> +		var->red.length	= var->green.length = var->blue.length = 8;
> +		break;
> +	case 32:
> +		var->transp.offset = 24;
> +		var->red.offset = 16;
> +		var->green.offset = 8;
> +		var->blue.offset = 0;
> +		var->transp.length = 8;
> +		var->red.length = var->green.length = var->blue.length = 8;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (var->xres > var->xres_virtual)
> +		var->xres_virtual = var->xres;
> +
> +	if (var->yres > var->yres_virtual)
> +		var->yres_virtual = var->yres;
> +
> +	if (info->monspecs.hfmax && info->monspecs.vfmax &&
> +	    info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void vga_protect(struct i740fb_par *par)
> +{
> +	/* disable the display */
> +	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
> +
> +	i740inb(par, 0x3DA);
> +	i740outb(par, VGA_ATT_W, 0x00);	/* enable pallete access */
> +}
> +
> +static void vga_unprotect(struct i740fb_par *par)
> +{
> +	/* reenable display */
> +	i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
> +
> +	i740inb(par, 0x3DA);
> +	i740outb(par, VGA_ATT_W, 0x20);	/* disable pallete access */
> +}
> +
> +static int i740fb_set_par(struct fb_info *info)
> +{
> +	struct i740fb_par *par = info->par;
> +	u32 itemp;
> +	int i;
> +
> +	i = i740fb_decode_var(&info->var, par, info);
> +	if (i)
> +		return i;
> +
> +	memset(info->screen_base, 0, info->screen_size);
> +
> +	vga_protect(par);
> +
> +	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
> +
> +	mdelay(1);
> +
> +	i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
> +	i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
> +	i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
> +	i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
> +
> +	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
> +			par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
> +
> +	i740inb(par, 0x3DA);
> +	i740outb(par, 0x3C0, 0x00);
> +
> +	/* update misc output register */
> +	i740outb(par, VGA_MIS_W, par->misc | 0x01);
> +
> +	/* synchronous reset on */
> +	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
> +	/* write sequencer registers */
> +	i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
> +			par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
> +	for (i = 2; i < VGA_SEQ_C; i++)
> +		i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
> +
> +	/* synchronous reset off */
> +	i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
> +
> +	/* deprotect CRT registers 0-7 */
> +	i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
> +			par->crtc[VGA_CRTC_V_SYNC_END]);
> +
> +	/* write CRT registers */
> +	for (i = 0; i < VGA_CRT_C; i++)
> +		i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
> +
> +	/* write graphics controller registers */
> +	for (i = 0; i < VGA_GFX_C; i++)
> +		i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
> +
> +	/* write attribute controller registers */
> +	for (i = 0; i < VGA_ATT_C; i++) {
> +		i740inb(par, VGA_IS1_RC);		/* reset flip-flop */
> +		i740outb(par, VGA_ATT_IW, i);
> +		i740outb(par, VGA_ATT_IW, par->atc[i]);
> +	}
> +
> +	i740inb(par, VGA_IS1_RC);
> +	i740outb(par, VGA_ATT_IW, 0x20);
> +
> +	i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
> +	i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
> +	i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
> +			par->ext_vert_sync_start);
> +	i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
> +			par->ext_vert_blank_start);
> +	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
> +	i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
> +	i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
> +	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
> +	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
> +
> +	i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
> +			par->interlace_cntl, INTERLACE_ENABLE);
> +	i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
> +	i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
> +	i740outreg_mask(par, XRX, DISPLAY_CNTL,
> +			par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
> +	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
> +	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
> +
> +	i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
> +
> +	i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
> +			par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
> +
> +	itemp = readl(par->regs + FWATER_BLC);
> +	itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
> +	itemp |= par->lmi_fifo_watermark;
> +	writel(itemp, par->regs + FWATER_BLC);
> +
> +	i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
> +
> +	i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
> +	i740outreg_mask(par, XRX, IO_CTNL,
> +			par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
> +
> +	if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
> +		i740outb(par, VGA_PEL_MSK, 0xFF);
> +		i740outb(par, VGA_PEL_IW, 0x00);
> +		for (i = 0; i < 256; i++) {
> +			itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
> +			i740outb(par, VGA_PEL_D, itemp);
> +			i740outb(par, VGA_PEL_D, itemp);
> +			i740outb(par, VGA_PEL_D, itemp);
> +		}
> +	}
> +
> +	/* Wait for screen to stabilize. */
> +	mdelay(50);
> +	vga_unprotect(par);
> +
> +	info->fix.line_length > +			info->var.xres_virtual * info->var.bits_per_pixel / 8;
> +	if (info->var.bits_per_pixel = 8)
> +		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
> +	else
> +		info->fix.visual = FB_VISUAL_TRUECOLOR;
> +
> +	return 0;
> +}
> +
> +static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
> +			   unsigned blue, unsigned transp,
> +			   struct fb_info *info)
> +{
> +	u32 r, g, b;
> +
> +	dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
> +		regno, red, green, blue, transp, info->var.bits_per_pixel);
> +
> +	switch (info->fix.visual) {
> +	case FB_VISUAL_PSEUDOCOLOR:
> +		if (regno >= 256)
> +			return -EINVAL;
> +		i740outb(info->par, VGA_PEL_IW, regno);
> +		i740outb(info->par, VGA_PEL_D, red >> 8);
> +		i740outb(info->par, VGA_PEL_D, green >> 8);
> +		i740outb(info->par, VGA_PEL_D, blue >> 8);
> +		break;
> +	case FB_VISUAL_TRUECOLOR:
> +		if (regno >= 16)
> +			return -EINVAL;
> +		r = (red >> (16 - info->var.red.length))
> +			<< info->var.red.offset;
> +		b = (blue >> (16 - info->var.blue.length))
> +			<< info->var.blue.offset;
> +		g = (green >> (16 - info->var.green.length))
> +			<< info->var.green.offset;
> +		((u32 *) info->pseudo_palette)[regno] = r | g | b;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int i740fb_pan_display(struct fb_var_screeninfo *var,
> +				 struct fb_info *info)
> +{
> +	struct i740fb_par *par = info->par;
> +	u32 base = (var->yoffset * info->var.xres_virtual
> +		 + (var->xoffset & ~7)) >> 2;
> +
> +	dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
> +		var->xoffset, var->yoffset, base);
> +
> +	switch (info->var.bits_per_pixel) {
> +	case 8:
> +		break;
> +	case 15:
> +	case 16:
> +		base *= 2;
> +		break;
> +	case 24:
> +		/*
> +		 * The last bit does not seem to have any effect on the start
> +		 * address register in 24bpp mode, so...
> +		 */
> +		base &= 0xFFFFFFFE; /* ...ignore the last bit. */
> +		base *= 3;
> +		break;
> +	case 32:
> +		base *= 4;
> +		break;
> +	}
> +
> +	par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
> +	par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >>  8;
> +	par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
> +	par->ext_start_addr > +			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
> +
> +	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO,  base & 0x000000FF);
> +	i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
> +			(base & 0x0000FF00) >> 8);
> +	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
> +			(base & 0x3FC00000) >> 22);
> +	i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
> +			((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
> +
> +	return 0;
> +}
> +
> +static int i740fb_blank(int blank_mode, struct fb_info *info)
> +{
> +	struct i740fb_par *par = info->par;
> +
> +	unsigned char SEQ01;
> +	int DPMSSyncSelect;
> +
> +	switch (blank_mode) {
> +	case FB_BLANK_UNBLANK:
> +	case FB_BLANK_NORMAL:
> +		SEQ01 = 0x00;
> +		DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
> +		break;
> +	case FB_BLANK_VSYNC_SUSPEND:
> +		SEQ01 = 0x20;
> +		DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
> +		break;
> +	case FB_BLANK_HSYNC_SUSPEND:
> +		SEQ01 = 0x20;
> +		DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
> +		break;
> +	case FB_BLANK_POWERDOWN:
> +		SEQ01 = 0x20;
> +		DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +	/* Turn the screen on/off */
> +	i740outb(par, SRX, 0x01);
> +	SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
> +	i740outb(par, SRX, 0x01);
> +	i740outb(par, SRX + 1, SEQ01);
> +
> +	/* Set the DPMS mode */
> +	i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
> +
> +	/* Let fbcon do a soft blank for us */
> +	return (blank_mode = FB_BLANK_NORMAL) ? 1 : 0;
> +}
> +
> +static struct fb_ops i740fb_ops = {
> +	.owner		= THIS_MODULE,
> +	.fb_open	= i740fb_open,
> +	.fb_release	= i740fb_release,
> +	.fb_check_var	= i740fb_check_var,
> +	.fb_set_par	= i740fb_set_par,
> +	.fb_setcolreg	= i740fb_setcolreg,
> +	.fb_blank	= i740fb_blank,
> +	.fb_pan_display	= i740fb_pan_display,
> +	.fb_fillrect	= cfb_fillrect,
> +	.fb_copyarea	= cfb_copyarea,
> +	.fb_imageblit	= cfb_imageblit,
> +};
> +
> +/* ------------------------------------------------------------------------- */
> +
> +static int __devinit i740fb_probe(struct pci_dev *dev,
> +				  const struct pci_device_id *ent)
> +{
> +	struct fb_info *info;
> +	struct i740fb_par *par;
> +	int ret, tmp;
> +	bool found = false;
> +	u8 *edid;
> +
> +	info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
> +	if (!info) {
> +		dev_err(&(dev->dev), "cannot allocate framebuffer\n");
> +		return -ENOMEM;
> +	}
> +
> +	par = info->par;
> +	mutex_init(&par->open_lock);
> +
> +	info->var.activate = FB_ACTIVATE_NOW;
> +	info->var.bits_per_pixel = 8;
> +	info->fbops = &i740fb_ops;
> +	info->pseudo_palette = par->pseudo_palette;
> +
> +	ret = pci_enable_device(dev);
> +	if (ret) {
> +		dev_err(info->device, "cannot enable PCI device\n");
> +		goto err_enable_device;
> +	}
> +
> +	ret = pci_request_regions(dev, info->fix.id);
> +	if (ret) {
> +		dev_err(info->device, "error requesting regions\n");
> +		goto err_request_regions;
> +	}
> +
> +	info->screen_base = pci_ioremap_bar(dev, 0);
> +	if (!info->screen_base) {
> +		dev_err(info->device, "error remapping base\n");
> +		ret = -ENOMEM;
> +		goto err_ioremap_1;
> +	}
> +
> +	par->regs = pci_ioremap_bar(dev, 1);
> +	if (!par->regs) {
> +		dev_err(info->device, "error remapping MMIO\n");
> +		ret = -ENOMEM;
> +		goto err_ioremap_2;
> +	}
> +
> +	/* detect memory size */
> +	if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
> +							= DRAM_ROW_1_SDRAM)
> +		i740outb(par, XRX, DRAM_ROW_BNDRY_1);
> +	else
> +		i740outb(par, XRX, DRAM_ROW_BNDRY_0);
> +	info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
> +	/* detect memory type */
> +	tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
> +	par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
> +			   (tmp & DRAM_RAS_PRECHARGE));
> +
> +	printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
> +		pci_name(dev), info->screen_size >> 10,
> +		par->has_sgram ? "SGRAM" : "SDRAM");
> +
> +	info->fix = i740fb_fix;
> +	info->fix.mmio_start = pci_resource_start(dev, 1);
> +	info->fix.mmio_len = pci_resource_len(dev, 1);
> +	info->fix.smem_start = pci_resource_start(dev, 0);
> +	info->fix.smem_len = info->screen_size;
> +	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
> +
> +	if (i740fb_setup_ddc_bus(info) = 0) {
> +		par->ddc_registered = true;
> +		edid = fb_ddc_read(&par->ddc_adapter);
> +		if (edid) {
> +			fb_edid_to_monspecs(edid, &info->monspecs);
> +			kfree(edid);
> +			if (!info->monspecs.modedb)
> +				dev_err(info->device,
> +					"error getting mode database\n");
> +			else {
> +				const struct fb_videomode *m;
> +
> +				fb_videomode_to_modelist(
> +					info->monspecs.modedb,
> +					info->monspecs.modedb_len,
> +					&info->modelist);
> +				m = fb_find_best_display(&info->monspecs,
> +							 &info->modelist);
> +				if (m) {
> +					fb_videomode_to_var(&info->var, m);
> +					/* fill all other info->var's fields */
> +					if (!i740fb_check_var(&info->var, info))
> +						found = true;
> +				}
> +			}
> +		}
> +	}
> +
> +	if (!mode_option && !found)
> +		mode_option = "640x480-8@60";
> +
> +	if (mode_option) {
> +		ret = fb_find_mode(&info->var, info, mode_option,
> +				   info->monspecs.modedb,
> +				   info->monspecs.modedb_len,
> +				   NULL, info->var.bits_per_pixel);
> +		if (!ret || ret = 4) {
> +			dev_err(info->device, "mode %s not found\n",
> +				mode_option);
> +			ret = -EINVAL;
> +		}
> +	}
> +
> +	fb_destroy_modedb(info->monspecs.modedb);
> +	info->monspecs.modedb = NULL;
> +
> +	/* maximize virtual vertical size for fast scrolling */
> +	info->var.yres_virtual = info->fix.smem_len * 8 /
> +			(info->var.bits_per_pixel * info->var.xres_virtual);
> +
> +	if (ret = -EINVAL)
> +		goto err_find_mode;
> +
> +	ret = fb_alloc_cmap(&info->cmap, 256, 0);
> +	if (ret) {
> +		dev_err(info->device, "cannot allocate colormap\n");
> +		goto err_alloc_cmap;
> +	}
> +
> +	ret = register_framebuffer(info);
> +	if (ret) {
> +		dev_err(info->device, "error registering framebuffer\n");
> +		goto err_reg_framebuffer;
> +	}
> +
> +	printk(KERN_INFO "fb%d: %s frame buffer device\n",
> +		info->node, info->fix.id);
> +	pci_set_drvdata(dev, info);
> +#ifdef CONFIG_MTRR
> +	if (mtrr) {
> +		par->mtrr_reg = -1;
> +		par->mtrr_reg = mtrr_add(info->fix.smem_start,
> +				info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
> +	}
> +#endif
> +	return 0;
> +
> +err_reg_framebuffer:
> +	fb_dealloc_cmap(&info->cmap);
> +err_alloc_cmap:
> +err_find_mode:
> +	if (par->ddc_registered)
> +		i2c_del_adapter(&par->ddc_adapter);
> +	pci_iounmap(dev, par->regs);
> +err_ioremap_2:
> +	pci_iounmap(dev, info->screen_base);
> +err_ioremap_1:
> +	pci_release_regions(dev);
> +err_request_regions:
> +/*	pci_disable_device(dev); */
> +err_enable_device:
> +	framebuffer_release(info);
> +	return ret;
> +}
> +
> +static void __devexit i740fb_remove(struct pci_dev *dev)
> +{
> +	struct fb_info *info = pci_get_drvdata(dev);
> +
> +	if (info) {
> +#ifdef CONFIG_MTRR
> +		struct i740fb_par *par = info->par;
> +
> +		if (par->mtrr_reg >= 0) {
> +			mtrr_del(par->mtrr_reg, 0, 0);
> +			par->mtrr_reg = -1;
> +		}
> +#endif
> +		unregister_framebuffer(info);
> +		fb_dealloc_cmap(&info->cmap);
> +		if (par->ddc_registered)
> +			i2c_del_adapter(&par->ddc_adapter);
> +		pci_iounmap(dev, par->regs);
> +		pci_iounmap(dev, info->screen_base);
> +		pci_release_regions(dev);
> +/*		pci_disable_device(dev); */
> +		pci_set_drvdata(dev, NULL);
> +		framebuffer_release(info);
> +	}
> +}
> +
> +#ifdef CONFIG_PM
> +static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
> +{
> +	struct fb_info *info = pci_get_drvdata(dev);
> +	struct i740fb_par *par = info->par;
> +
> +	/* don't disable console during hibernation and wakeup from it */
> +	if (state.event = PM_EVENT_FREEZE || state.event = PM_EVENT_PRETHAW)
> +		return 0;
> +
> +	console_lock();
> +	mutex_lock(&(par->open_lock));
> +
> +	/* do nothing if framebuffer is not active */
> +	if (par->ref_count = 0) {
> +		mutex_unlock(&(par->open_lock));
> +		console_unlock();
> +		return 0;
> +	}
> +
> +	fb_set_suspend(info, 1);
> +
> +	pci_save_state(dev);
> +	pci_disable_device(dev);
> +	pci_set_power_state(dev, pci_choose_state(dev, state));
> +
> +	mutex_unlock(&(par->open_lock));
> +	console_unlock();
> +
> +	return 0;
> +}
> +
> +static int i740fb_resume(struct pci_dev *dev)
> +{
> +	struct fb_info *info = pci_get_drvdata(dev);
> +	struct i740fb_par *par = info->par;
> +
> +	console_lock();
> +	mutex_lock(&(par->open_lock));
> +
> +	if (par->ref_count = 0)
> +		goto fail;
> +
> +	pci_set_power_state(dev, PCI_D0);
> +	pci_restore_state(dev);
> +	if (pci_enable_device(dev))
> +		goto fail;
> +
> +	i740fb_set_par(info);
> +	fb_set_suspend(info, 0);
> +
> +fail:
> +	mutex_unlock(&(par->open_lock));
> +	console_unlock();
> +	return 0;
> +}
> +#else
> +#define i740fb_suspend NULL
> +#define i740fb_resume NULL
> +#endif /* CONFIG_PM */
> +
> +#define I740_ID_PCI 0x00d1
> +#define I740_ID_AGP 0x7800
> +
> +static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
> +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
> +	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
> +	{ 0 }
> +};
> +MODULE_DEVICE_TABLE(pci, i740fb_id_table);
> +
> +static struct pci_driver i740fb_driver = {
> +	.name		= "i740fb",
> +	.id_table	= i740fb_id_table,
> +	.probe		= i740fb_probe,
> +	.remove		= __devexit_p(i740fb_remove),
> +	.suspend	= i740fb_suspend,
> +	.resume		= i740fb_resume,
> +};
> +
> +#ifndef MODULE
> +static int  __init i740fb_setup(char *options)
> +{
> +	char *opt;
> +
> +	if (!options || !*options)
> +		return 0;
> +
> +	while ((opt = strsep(&options, ",")) != NULL) {
> +		if (!*opt)
> +			continue;
> +#ifdef CONFIG_MTRR
> +		else if (!strncmp(opt, "mtrr:", 5))
> +			mtrr = simple_strtoul(opt + 5, NULL, 0);
> +#endif
> +		else
> +			mode_option = opt;
> +	}
> +
> +	return 0;
> +}
> +#endif
> +
> +int __init i740fb_init(void)
> +{
> +#ifndef MODULE
> +	char *option = NULL;
> +
> +	if (fb_get_options("i740fb", &option))
> +		return -ENODEV;
> +	i740fb_setup(option);
> +#endif
> +
> +	return pci_register_driver(&i740fb_driver);
> +}
> +
> +static void __exit i740fb_exit(void)
> +{
> +	pci_unregister_driver(&i740fb_driver);
> +}
> +
> +module_init(i740fb_init);
> +module_exit(i740fb_exit);
> +
> +MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("fbdev driver for Intel740");
> +
> +module_param(mode_option, charp, 0444);
> +MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
> +
> +#ifdef CONFIG_MTRR
> +module_param(mtrr, int, 0444);
> +MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
> +#endif
> --- /dev/null	2012-01-24 00:06:39.330222901 +0100
> +++ linux-3.2.1/drivers/video/i740_reg.h	2012-01-23 22:55:57.000000000 +0100
> @@ -0,0 +1,309 @@
> +/**************************************************************************
> +
> +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
> +All Rights Reserved.
> +
> +Permission is hereby granted, free of charge, to any person obtaining a
> +copy of this software and associated documentation files (the
> +"Software"), to deal in the Software without restriction, including
> +without limitation the rights to use, copy, modify, merge, publish,
> +distribute, sub license, and/or sell copies of the Software, and to
> +permit persons to whom the Software is furnished to do so, subject to
> +the following conditions:
> +
> +The above copyright notice and this permission notice (including the
> +next paragraph) shall be included in all copies or substantial portions
> +of the Software.
> +
> +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
> +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
> +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> +
> +**************************************************************************/
> +
> +/*
> + * Authors:
> + *   Kevin E. Martin <kevin@precisioninsight.com>
> + */
> +
> +/* I/O register offsets */
> +#define SRX VGA_SEQ_I
> +#define GRX VGA_GFX_I
> +#define ARX VGA_ATT_IW
> +#define XRX 0x3D6
> +#define MRX 0x3D2
> +
> +/* VGA Color Palette Registers */
> +#define DACMASK		0x3C6
> +#define DACSTATE	0x3C7
> +#define DACRX		0x3C7
> +#define DACWX		0x3C8
> +#define DACDATA		0x3C9
> +
> +/* CRT Controller Registers (CRX) */
> +#define START_ADDR_HI		0x0C
> +#define START_ADDR_LO		0x0D
> +#define VERT_SYNC_END		0x11
> +#define EXT_VERT_TOTAL		0x30
> +#define EXT_VERT_DISPLAY	0x31
> +#define EXT_VERT_SYNC_START	0x32
> +#define EXT_VERT_BLANK_START	0x33
> +#define EXT_HORIZ_TOTAL		0x35
> +#define EXT_HORIZ_BLANK		0x39
> +#define EXT_START_ADDR		0x40
> +#define EXT_START_ADDR_ENABLE	0x80
> +#define EXT_OFFSET		0x41
> +#define EXT_START_ADDR_HI	0x42
> +#define INTERLACE_CNTL		0x70
> +#define INTERLACE_ENABLE	0x80
> +#define INTERLACE_DISABLE	0x00
> +
> +/* Miscellaneous Output Register */
> +#define MSR_R		0x3CC
> +#define MSR_W		0x3C2
> +#define IO_ADDR_SELECT	0x01
> +
> +#define MDA_BASE	0x3B0
> +#define CGA_BASE	0x3D0
> +
> +/* System Configuration Extension Registers (XRX) */
> +#define IO_CTNL		0x09
> +#define EXTENDED_ATTR_CNTL	0x02
> +#define EXTENDED_CRTC_CNTL	0x01
> +
> +#define ADDRESS_MAPPING	0x0A
> +#define PACKED_MODE_ENABLE	0x04
> +#define LINEAR_MODE_ENABLE	0x02
> +#define PAGE_MAPPING_ENABLE	0x01
> +
> +#define BITBLT_CNTL	0x20
> +#define COLEXP_MODE		0x30
> +#define COLEXP_8BPP		0x00
> +#define COLEXP_16BPP		0x10
> +#define COLEXP_24BPP		0x20
> +#define COLEXP_RESERVED		0x30
> +#define CHIP_RESET		0x02
> +#define BITBLT_STATUS		0x01
> +
> +#define DISPLAY_CNTL	0x40
> +#define VGA_WRAP_MODE		0x02
> +#define VGA_WRAP_AT_256KB	0x00
> +#define VGA_NO_WRAP		0x02
> +#define GUI_MODE		0x01
> +#define STANDARD_VGA_MODE	0x00
> +#define HIRES_MODE		0x01
> +
> +#define DRAM_ROW_TYPE	0x50
> +#define DRAM_ROW_0		0x07
> +#define DRAM_ROW_0_SDRAM	0x00
> +#define DRAM_ROW_0_EMPTY	0x07
> +#define DRAM_ROW_1		0x38
> +#define DRAM_ROW_1_SDRAM	0x00
> +#define DRAM_ROW_1_EMPTY	0x38
> +#define DRAM_ROW_CNTL_LO 0x51
> +#define DRAM_CAS_LATENCY	0x10
> +#define DRAM_RAS_TIMING		0x08
> +#define DRAM_RAS_PRECHARGE	0x04
> +#define DRAM_ROW_CNTL_HI 0x52
> +#define DRAM_EXT_CNTL	0x53
> +#define DRAM_REFRESH_RATE	0x03
> +#define DRAM_REFRESH_DISABLE	0x00
> +#define DRAM_REFRESH_60HZ	0x01
> +#define DRAM_REFRESH_FAST_TEST	0x02
> +#define DRAM_REFRESH_RESERVED	0x03
> +#define DRAM_TIMING	0x54
> +#define DRAM_ROW_BNDRY_0 0x55
> +#define DRAM_ROW_BNDRY_1 0x56
> +
> +#define DPMS_SYNC_SELECT 0x61
> +#define VSYNC_CNTL		0x08
> +#define VSYNC_ON		0x00
> +#define VSYNC_OFF		0x08
> +#define HSYNC_CNTL		0x02
> +#define HSYNC_ON		0x00
> +#define HSYNC_OFF		0x02
> +
> +#define PIXPIPE_CONFIG_0 0x80
> +#define DAC_8_BIT		0x80
> +#define DAC_6_BIT		0x00
> +#define HW_CURSOR_ENABLE	0x10
> +#define EXTENDED_PALETTE	0x01
> +
> +#define PIXPIPE_CONFIG_1 0x81
> +#define DISPLAY_COLOR_MODE	0x0F
> +#define DISPLAY_VGA_MODE	0x00
> +#define DISPLAY_8BPP_MODE	0x02
> +#define DISPLAY_15BPP_MODE	0x04
> +#define DISPLAY_16BPP_MODE	0x05
> +#define DISPLAY_24BPP_MODE	0x06
> +#define DISPLAY_32BPP_MODE	0x07
> +
> +#define PIXPIPE_CONFIG_2 0x82
> +#define DISPLAY_GAMMA_ENABLE	0x08
> +#define DISPLAY_GAMMA_DISABLE	0x00
> +#define OVERLAY_GAMMA_ENABLE	0x04
> +#define OVERLAY_GAMMA_DISABLE	0x00
> +
> +#define CURSOR_CONTROL	0xA0
> +#define CURSOR_ORIGIN_SCREEN	0x00
> +#define CURSOR_ORIGIN_DISPLAY	0x10
> +#define CURSOR_MODE		0x07
> +#define CURSOR_MODE_DISABLE	0x00
> +#define CURSOR_MODE_32_4C_AX	0x01
> +#define CURSOR_MODE_128_2C	0x02
> +#define CURSOR_MODE_128_1C	0x03
> +#define CURSOR_MODE_64_3C	0x04
> +#define CURSOR_MODE_64_4C_AX	0x05
> +#define CURSOR_MODE_64_4C	0x06
> +#define CURSOR_MODE_RESERVED	0x07
> +#define CURSOR_BASEADDR_LO 0xA2
> +#define CURSOR_BASEADDR_HI 0xA3
> +#define CURSOR_X_LO	0xA4
> +#define CURSOR_X_HI	0xA5
> +#define CURSOR_X_POS		0x00
> +#define CURSOR_X_NEG		0x80
> +#define CURSOR_Y_LO	0xA6
> +#define CURSOR_Y_HI	0xA7
> +#define CURSOR_Y_POS		0x00
> +#define CURSOR_Y_NEG		0x80
> +
> +#define VCLK2_VCO_M	0xC8
> +#define VCLK2_VCO_N	0xC9
> +#define VCLK2_VCO_MN_MSBS 0xCA
> +#define VCO_N_MSBS		0x30
> +#define VCO_M_MSBS		0x03
> +#define VCLK2_VCO_DIV_SEL 0xCB
> +#define POST_DIV_SELECT		0x70
> +#define POST_DIV_1		0x00
> +#define POST_DIV_2		0x10
> +#define POST_DIV_4		0x20
> +#define POST_DIV_8		0x30
> +#define POST_DIV_16		0x40
> +#define POST_DIV_32		0x50
> +#define VCO_LOOP_DIV_BY_4M	0x00
> +#define VCO_LOOP_DIV_BY_16M	0x04
> +#define REF_CLK_DIV_BY_5	0x02
> +#define REF_DIV_4		0x00
> +#define REF_DIV_1		0x01
> +
> +#define PLL_CNTL	0xCE
> +#define PLL_MEMCLK_SEL		0x03
> +#define PLL_MEMCLK__66667KHZ	0x00
> +#define PLL_MEMCLK__75000KHZ	0x01
> +#define PLL_MEMCLK__88889KHZ	0x02
> +#define PLL_MEMCLK_100000KHZ	0x03
> +
> +/* Multimedia Extension Registers (MRX) */
> +#define ACQ_CNTL_1	0x02
> +#define ACQ_CNTL_2	0x03
> +#define FRAME_CAP_MODE		0x01
> +#define CONT_CAP_MODE		0x00
> +#define SINGLE_CAP_MODE		0x01
> +#define ACQ_CNTL_3	0x04
> +#define COL_KEY_CNTL_1		0x3C
> +#define BLANK_DISP_OVERLAY	0x20
> +
> +/* FIFOs */
> +#define LP_FIFO		0x1000
> +#define HP_FIFO		0x2000
> +#define INSTPNT		0x3040
> +#define LP_FIFO_COUNT	0x3040
> +#define HP_FIFO_COUNT	0x3041
> +
> +/* FIFO Commands */
> +#define CLIENT		0xE0000000
> +#define CLIENT_2D	0x60000000
> +
> +/* Command Parser Mode Register */
> +#define COMPARS		0x3038
> +#define TWO_D_INST_DISABLE		0x08
> +#define THREE_D_INST_DISABLE		0x04
> +#define STATE_VAR_UPDATE_DISABLE	0x02
> +#define PAL_STIP_DISABLE		0x01
> +
> +/* Interrupt Control Registers */
> +#define IER		0x3030
> +#define IIR		0x3032
> +#define IMR		0x3034
> +#define ISR		0x3036
> +#define VMIINTB_EVENT		0x2000
> +#define GPIO4_INT		0x1000
> +#define DISP_FLIP_EVENT		0x0800
> +#define DVD_PORT_DMA		0x0400
> +#define DISP_VBLANK		0x0200
> +#define FIFO_EMPTY_DMA_DONE	0x0100
> +#define INST_PARSER_ERROR	0x0080
> +#define USER_DEFINED		0x0040
> +#define BREAKPOINT		0x0020
> +#define DISP_HORIZ_COUNT	0x0010
> +#define DISP_VSYNC		0x0008
> +#define CAPTURE_HORIZ_COUNT	0x0004
> +#define CAPTURE_VSYNC		0x0002
> +#define THREE_D_PIPE_FLUSHED	0x0001
> +
> +/* FIFO Watermark and Burst Length Control Register */
> +#define FWATER_BLC	0x00006000
> +#define LMI_BURST_LENGTH	0x7F000000
> +#define LMI_FIFO_WATERMARK	0x003F0000
> +#define AGP_BURST_LENGTH	0x00007F00
> +#define AGP_FIFO_WATERMARK	0x0000003F
> +
> +/* BitBLT Registers */
> +#define SRC_DST_PITCH	0x00040000
> +#define DST_PITCH		0x1FFF0000
> +#define SRC_PITCH		0x00001FFF
> +#define COLEXP_BG_COLOR	0x00040004
> +#define COLEXP_FG_COLOR	0x00040008
> +#define MONO_SRC_CNTL	0x0004000C
> +#define MONO_USE_COLEXP		0x00000000
> +#define MONO_USE_SRCEXP		0x08000000
> +#define MONO_DATA_ALIGN		0x07000000
> +#define MONO_BIT_ALIGN		0x01000000
> +#define MONO_BYTE_ALIGN		0x02000000
> +#define MONO_WORD_ALIGN		0x03000000
> +#define MONO_DWORD_ALIGN	0x04000000
> +#define MONO_QWORD_ALIGN	0x05000000
> +#define MONO_SRC_INIT_DSCRD	0x003F0000
> +#define MONO_SRC_RIGHT_CLIP	0x00003F00
> +#define MONO_SRC_LEFT_CLIP	0x0000003F
> +#define BITBLT_CONTROL	0x00040010
> +#define BLTR_STATUS		0x80000000
> +#define DYN_DEPTH		0x03000000
> +#define DYN_DEPTH_8BPP		0x00000000
> +#define DYN_DEPTH_16BPP		0x01000000
> +#define DYN_DEPTH_24BPP		0x02000000
> +#define DYN_DEPTH_32BPP		0x03000000	/* Unimplemented on the i740 */
> +#define DYN_DEPTH_ENABLE	0x00800000
> +#define PAT_VERT_ALIGN		0x00700000
> +#define SOLID_PAT_SELECT	0x00080000
> +#define PAT_IS_IN_COLOR		0x00000000
> +#define PAT_IS_MONO		0x00040000
> +#define MONO_PAT_TRANSP		0x00020000
> +#define COLOR_TRANSP_ROP	0x00000000
> +#define COLOR_TRANSP_DST	0x00008000
> +#define COLOR_TRANSP_EQ		0x00000000
> +#define COLOR_TRANSP_NOT_EQ	0x00010000
> +#define COLOR_TRANSP_ENABLE	0x00004000
> +#define MONO_SRC_TRANSP		0x00002000
> +#define SRC_IS_IN_COLOR		0x00000000
> +#define SRC_IS_MONO		0x00001000
> +#define SRC_USE_SRC_ADDR	0x00000000
> +#define SRC_USE_BLTDATA		0x00000400
> +#define BLT_TOP_TO_BOT		0x00000000
> +#define BLT_BOT_TO_TOP		0x00000200
> +#define BLT_LEFT_TO_RIGHT	0x00000000
> +#define BLT_RIGHT_TO_LEFT	0x00000100
> +#define BLT_ROP			0x000000FF
> +#define BLT_PAT_ADDR	0x00040014
> +#define BLT_SRC_ADDR	0x00040018
> +#define BLT_DST_ADDR	0x0004001C
> +#define BLT_DST_H_W	0x00040020
> +#define BLT_DST_HEIGHT		0x1FFF0000
> +#define BLT_DST_WIDTH		0x00001FFF
> +#define SRCEXP_BG_COLOR	0x00040024
> +#define SRCEXP_FG_COLOR	0x00040028
> +#define BLTDATA		0x00050000
> 
> 
> 


^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Kevin Hilman @ 2012-02-15 19:59 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Tomi Valkeinen, Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3BAD41.1020102@ti.com>

"Cousson, Benoit" <b-cousson@ti.com> writes:

> + Kevin
>
> On 2/15/2012 1:51 PM, Tomi Valkeinen wrote:
>> On Wed, 2012-02-15 at 13:35 +0100, Cousson, Benoit wrote:
>>
>>> I think that changing the device creation to change the dev->parent
>>> should be pretty straightforward.
>>
>> That's not possible with the current kernel, right?
>>
>> We are now using omap_device_build() (in arch/arm/mach-omap2/display.c)
>> to build the dss devices. Looking at the omap_device.c, the parent will
>> always forcibly set to omap_device_parent. It'd be nice to be able to
>> construct the device child-parent relationship the same way with both DT
>> and non-DT cases.
>
> I guess this should not be needed anymore since now the whole PM
> runtime stuff is handled using pm_domain.
>
> int omap_device_register(struct platform_device *pdev)
> {
> 	pr_debug("omap_device: %s: registering\n", pdev->name);
>
> 	pdev->dev.parent = &omap_device_parent;
> 	pdev->dev.pm_domain = &omap_device_pm_domain;
> 	return platform_device_add(pdev);
> }
>
>
> Kevin,
>
> Do we still need to set the dev.parent to omap_device_parent?

Nope.

> I guess the default &platform_bus parent is good enough and
> potentially the DSS children should be able to overwrite that.

Yes, now that we use PM domains, we don't need it.  I just sent a patch
to remove omap_device_parent.

Kevin

>> Or can I create only the dss_core with omap_device_build(), and create
>> the rest normally with platform device functions, and make dss_core the
>> parent of the rest? But are the hwmods then handled correctly?
>
> You can, the only issue if you create a regular platform device is
> that you will miss the automatic pm_runtime support along with the
> hwmod device creation mechanism + clock / PM.
>
> I think we can add an extra parameter to allow changing the
> omap_device parent during omap_device_build.

^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Cousson, Benoit @ 2012-02-15 13:04 UTC (permalink / raw)
  To: Tomi Valkeinen, Hilman, Kevin
  Cc: Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <1329310317.1892.60.camel@deskari>

+ Kevin

On 2/15/2012 1:51 PM, Tomi Valkeinen wrote:
> On Wed, 2012-02-15 at 13:35 +0100, Cousson, Benoit wrote:
>
>> I think that changing the device creation to change the dev->parent
>> should be pretty straightforward.
>
> That's not possible with the current kernel, right?
>
> We are now using omap_device_build() (in arch/arm/mach-omap2/display.c)
> to build the dss devices. Looking at the omap_device.c, the parent will
> always forcibly set to omap_device_parent. It'd be nice to be able to
> construct the device child-parent relationship the same way with both DT
> and non-DT cases.

I guess this should not be needed anymore since now the whole PM runtime 
stuff is handled using pm_domain.

int omap_device_register(struct platform_device *pdev)
{
	pr_debug("omap_device: %s: registering\n", pdev->name);

	pdev->dev.parent = &omap_device_parent;
	pdev->dev.pm_domain = &omap_device_pm_domain;
	return platform_device_add(pdev);
}


Kevin,

Do we still need to set the dev.parent to omap_device_parent?
I guess the default &platform_bus parent is good enough and potentially 
the DSS children should be able to overwrite that.

> Or can I create only the dss_core with omap_device_build(), and create
> the rest normally with platform device functions, and make dss_core the
> parent of the rest? But are the hwmods then handled correctly?

You can, the only issue if you create a regular platform device is that 
you will miss the automatic pm_runtime support along with the hwmod 
device creation mechanism + clock / PM.

I think we can add an extra parameter to allow changing the omap_device 
parent during omap_device_build.

Regards,
Benoit

^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Tomi Valkeinen @ 2012-02-15 12:51 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Archit Taneja, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3BA6A2.60604@ti.com>

[-- Attachment #1: Type: text/plain, Size: 759 bytes --]

On Wed, 2012-02-15 at 13:35 +0100, Cousson, Benoit wrote:

> I think that changing the device creation to change the dev->parent 
> should be pretty straightforward.

That's not possible with the current kernel, right?

We are now using omap_device_build() (in arch/arm/mach-omap2/display.c)
to build the dss devices. Looking at the omap_device.c, the parent will
always forcibly set to omap_device_parent. It'd be nice to be able to
construct the device child-parent relationship the same way with both DT
and non-DT cases.

Or can I create only the dss_core with omap_device_build(), and create
the rest normally with platform device functions, and make dss_core the
parent of the rest? But are the hwmods then handled correctly?

 Tomi


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Cousson, Benoit @ 2012-02-15 12:35 UTC (permalink / raw)
  To: Archit Taneja; +Cc: Tomi Valkeinen, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3B9E8F.1020002@ti.com>

On 2/15/2012 1:01 PM, Archit Taneja wrote:
> On Tuesday 14 February 2012 09:11 PM, Cousson, Benoit wrote:
>> On 2/14/2012 2:30 PM, Archit Taneja wrote:
>>> Hi,
>>>
>>> On Tuesday 14 February 2012 06:45 PM, Tomi Valkeinen wrote:
>>>> On Tue, 2012-02-14 at 13:58 +0100, Cousson, Benoit wrote:
>>>>> Hi Tomi,
>>>>
>>>>>> Benoit, do you think we'll get the MODULEMODE mess cleaned up in the
>>>>>> hwmod/clk framework at some point, and the drivers could do without
>>>>>> these kinds of hacks? =)
>>>>>
>>>>> The best way to fix that for my point of view is to go to device tree
>>>>> or/and to consider the DSS as the parent of all the DSS modules.
>>>>> pm_runtime will then always ensure that the parent is enabled before
>>>>> any
>>>>> of the child are used.
>>>>
>>>> Ah, right. Sounds fine to me.
>>>>
>>>> But is that a proper "fix"? Are we sure the MODULEMODE will then always
>>>> be handled correctly? Isn't the core problem still there, it just
>>>> doesn't happen with the setup anymore?
>>>>
>>>> I mean, if we have these special requirements regarding MODULEMODE, and
>>>> the code doesn't really know about it, would it get broken easily with
>>>> restructuring/changes?
>>>>
>>>> And no, I don't have any clear idea why/how it would break, but I have
>>>> just gotten the impression that the MODULEMODE is not handled quite
>>>> properly (and so we have these current problems), and having
>>>> dss_core as
>>>> the parent of other dss modules doesn't really fix that in any way.
>>>
>>> I agree with that.
>>>
>>> In the current approach, we have multiple platform devices for DSS, and
>>> all of them belong to the same clock domain, and the clock domain has
>>> just one MODULEMODE bit field.
>>>
>>> When shutting off a platform device(by calling pm_runtime_put()), hwmod
>>> enables/disables MODULEMODE without taking into mind that other active
>>> platform devices may still need it. So, for example, if we have 2
>>> platform devices, say dss and dispc, and we have code like:
>>>
>>> dispc_foo()
>>> {
>>> pm_runtime_get(dispc_pdev);
>>> ...
>>> ...
>>> pm_runtime_put(dispc_pdev);
>>> }
>>>
>>> dss_foo()
>>> {
>>> pm_runtime_get(dss_pdev);
>>> ...
>>> ...
>>> dispc_foo(); /* MODULEMODE off after this */
>>> ...
>>> ...
>>> pm_runtime_put(dss_pdev);
>>> }
>>>
>>> This will lead to the situation of one platform device disabling
>>> MODULEMODE even though other platform devices need it.
>>>
>>> This may not be resolved in device tree either. We would need to have
>>> some use count mechanism for these bits, or attach MODULEMODE only to
>>> one platform device, and don't give others control to enable/disable it.
>>
>> And this is exactly what the pm_runtime will provide. The fmwk already
>> handles reference counting.
>> Moreover the dev->parent will increment the power.child_count and thus
>> ensure that the parent is always enabled if at least one child is active.
>>
>> By initializing the dev->parent of each DSS modules to the dss_core, it
>> will ensure that the power dependency is managed properly.
>
> Yes, a parent/child relation will ensure the required dependencies. It
> sounds good!
>
> How do we take care of things in the meanwhile? With the current way of
> representing modulemode as a slave clock, the disabling sequence gets
> messed up. In arch/arm/mach-omap2/omap_hwmod.c:
>
> static int _disable_clocks(struct omap_hwmod *oh)
> {
> ...
> disable mainclk;
> disable slave clocks;
> ...
> }
>
> For DSS, mainclk is the DSS_FCLK opt clock, and slave clock is
> modulemode bits. We need the opposite sequence to happen here to cleanly
> disable DSS.

Yes, but as you pointed out the current clocks mapping in the DSS is a 
hack that should not be done like that in theory.
As soon as the devices can handle the dependency, we will be able to fix 
the clock mapping in the hwmod data and handle properly the module mode 
only from the dss_core hwmod only.

But I think you have to change the driver first, otherwise it will break 
the DSS. We did that hack previously because it was the only way to 
enable the DSS properly, knowing that disabling it with that method will 
be impossible.

I think that changing the device creation to change the dev->parent 
should be pretty straightforward.

Regards,
Benoit

^ permalink raw reply

* Re: [PATCH v2] OMAPDSS: HACK: Ensure DSS clock domain gets out of idle when HDMI is enabled
From: Archit Taneja @ 2012-02-15 12:13 UTC (permalink / raw)
  To: Cousson, Benoit; +Cc: Tomi Valkeinen, linux-omap, linux, linux-fbdev
In-Reply-To: <4F3A809E.3070508@ti.com>

On Tuesday 14 February 2012 09:11 PM, Cousson, Benoit wrote:
> On 2/14/2012 2:30 PM, Archit Taneja wrote:
>> Hi,
>>
>> On Tuesday 14 February 2012 06:45 PM, Tomi Valkeinen wrote:
>>> On Tue, 2012-02-14 at 13:58 +0100, Cousson, Benoit wrote:
>>>> Hi Tomi,
>>>
>>>>> Benoit, do you think we'll get the MODULEMODE mess cleaned up in the
>>>>> hwmod/clk framework at some point, and the drivers could do without
>>>>> these kinds of hacks? =)
>>>>
>>>> The best way to fix that for my point of view is to go to device tree
>>>> or/and to consider the DSS as the parent of all the DSS modules.
>>>> pm_runtime will then always ensure that the parent is enabled before
>>>> any
>>>> of the child are used.
>>>
>>> Ah, right. Sounds fine to me.
>>>
>>> But is that a proper "fix"? Are we sure the MODULEMODE will then always
>>> be handled correctly? Isn't the core problem still there, it just
>>> doesn't happen with the setup anymore?
>>>
>>> I mean, if we have these special requirements regarding MODULEMODE, and
>>> the code doesn't really know about it, would it get broken easily with
>>> restructuring/changes?
>>>
>>> And no, I don't have any clear idea why/how it would break, but I have
>>> just gotten the impression that the MODULEMODE is not handled quite
>>> properly (and so we have these current problems), and having dss_core as
>>> the parent of other dss modules doesn't really fix that in any way.
>>
>> I agree with that.
>>
>> In the current approach, we have multiple platform devices for DSS, and
>> all of them belong to the same clock domain, and the clock domain has
>> just one MODULEMODE bit field.
>>
>> When shutting off a platform device(by calling pm_runtime_put()), hwmod
>> enables/disables MODULEMODE without taking into mind that other active
>> platform devices may still need it. So, for example, if we have 2
>> platform devices, say dss and dispc, and we have code like:
>>
>> dispc_foo()
>> {
>> pm_runtime_get(dispc_pdev);
>> ...
>> ...
>> pm_runtime_put(dispc_pdev);
>> }
>>
>> dss_foo()
>> {
>> pm_runtime_get(dss_pdev);
>> ...
>> ...
>> dispc_foo(); /* MODULEMODE off after this */
>> ...
>> ...
>> pm_runtime_put(dss_pdev);
>> }
>>
>> This will lead to the situation of one platform device disabling
>> MODULEMODE even though other platform devices need it.
>>
>> This may not be resolved in device tree either. We would need to have
>> some use count mechanism for these bits, or attach MODULEMODE only to
>> one platform device, and don't give others control to enable/disable it.
>
> And this is exactly what the pm_runtime will provide. The fmwk already
> handles reference counting.
> Moreover the dev->parent will increment the power.child_count and thus
> ensure that the parent is always enabled if at least one child is active.
>
> By initializing the dev->parent of each DSS modules to the dss_core, it
> will ensure that the power dependency is managed properly.

Yes, a parent/child relation will ensure the required dependencies. It 
sounds good!

How do we take care of things in the meanwhile? With the current way of 
representing modulemode as a slave clock, the disabling sequence gets 
messed up. In arch/arm/mach-omap2/omap_hwmod.c:

static int _disable_clocks(struct omap_hwmod *oh)
{
	...
	disable mainclk;
	disable slave clocks;
	...
}

For DSS, mainclk is the DSS_FCLK opt clock, and slave clock is 
modulemode bits. We need the opposite sequence to happen here to cleanly 
disable DSS.

Any suggestions?

Thanks,
Archit

>
> Regards,
> Benoit
>
>


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox