[Bug 85667] GPU lockup when playing H264 video with vlc on Radeon 3850HD and R600_uvd.bin loaded

2014-10-31 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=85667

--- Comment #1 from Arthur Marsh  ---
Created attachment 108747
  --> https://bugs.freedesktop.org/attachment.cgi?id=108747=edit
full dmesg output

Another crash with a different file, possibly same encoding using vlc from
Debian unstable for playback, this time with the full dmesg output.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141031/b56f0dd9/attachment.html>


[PATCH 00/72] staging imx-drm new features and fixes

2014-10-31 Thread Fabio Estevam
Hi Steve,

On Fri, Oct 31, 2014 at 8:53 PM, Steve Longerbeam  
wrote:
> Hi, this affects only Freescale imx IPU and imx-drm staging drivers,
> except for two patches that affect drm core (patch 53 and 63, see below).
>
> New features for imx-drm staging driver:
>
> - Support for multi-display (HDMI and LVDS).
> - Support for global alpha and color-key properties for overlay plane.
> - Support for gamma correction.
> - The imx-drm crtc devices moved to device tree.
> - Support for defining custom display interface pixel mappings in the
>   device tree.
> - Implements encoder DPMS for LVDS.
> - YUV planar pixel formats supported for DRM framebuffers.
> - DDC support added for LVDS.
> - Page flip handling moved to imx plane driver and implemented with
>   IPU double-buffering.
> - Support page-flip in the overlay plane (patch 53 affects drm core).
> - Add support for parsing pixel clock edge select (patch 63 affects drm core).
> - Add LVDS connection detect via drm_probe_ddc().
> - Implement crtc mode_set_base using plane page-flip.
>
>
> Fixed issues:
>
> - HDMI and LVDS now use different PLL clock roots (part of multi-display
>   support).
> - Use counter added to IPU DC enable/disable (part of multi-display
>   support).
> - Fixed some HDMI timing issues.
> - Wider range of supported DI pixel clocks generated (all EDID modes
>   reported from HDMI displays now work).
> - Fix separate primary plane objects.
> - HDMI must select DI pre clock as DI clock parent during encoder prepare
>   (LVDS may have switched DI clock to LDB parent, part of multi-display
>   support).
> - Assign correct DMFC burst size.
> - Resolve some DI synchronous display error cases.
>
>
>
> George G. Davis (1):
>   ARM: dts: imx6qdl-sabreauto: Add HDMI device
>
> Jiada Wang (1):
>   gpu: ipu-v3: fix HDMI timing issues
>
> Steve Longerbeam (70):
>   ARM: dts: imx6qdl-sabrelite: Add HDMI device
>   ARM: dts: imx6qdl: Create imx-drm crtc nodes
>   ARM: i.MX6: use pll2_pfd0_352m as clock root of ipu_di
>   ARM: i.MX6: select pll3_usb_otg for ldb_di for rev 1.0 chip
>   gpu: ipu-cpmem: Add ipu_cpmem_set_uv_offset()
>   gpu: ipu-v3: Add ipu_dp_set_chroma_key()
>   gpu: ipu-v3: Add ipu_dp_set_gamma_correction()
>   gpu: ipu-v3: Add support for dynamic DC interface pixel maps
>   gpu: ipu-v3: Add ipu_dc_uninit_sync()
>   gpu: ipu-v3: Pass struct ipu_dc to enable/disable
>   gpu: ipu-v3: Add ipu_dp_uninit_channel()
>   gpu: ipu-v3: Pass struct ipu_dp to enable/disable
>   gpu: ipu-v3: Implement use counter for ipu_dc_enable(),
> ipu_dc_disable()
>   gpu: ipu-v3: Add DMFC/DP/DC/DI module enable/disable debug
>   gpu: ipu-v3: Add ipu_di_uninit_sync_panel()
>   gpu: ipu-v3: Split out DI clock enable/disable
>   gpu: ipu-v3: Protect more CM reg access with IPU lock
>   gpu: ipu-v3: Move DI waveform counter enable/disable to ipu-di
>   gpu: ipu-v3: Update DP sync SRM always in ipu_dp_enable_channel()
>   gpu: ipu-v3: Fix indent/ws in ipu-dmfc
>   gpu: ipu-v3: Allow burstsize of 20 in ipu_dmfc_setup_channel()
>   gpu: ipu-v3: Remove ipu_dmfc_init_channel()
>   gpu: ipu-v3: Consolidate mutex lock in ipu_dmfc_alloc_bandwidth()
>   gpu: ipu-v3: Enumerate the DC channel names
>   gpu: ipu-di: Move ipu pointer init
>   gpu: ipu-di: Add and improve debug/error messages
>   gpu: ipu-v3: Change signal names in struct ipu_di_signal_cfg
>   gpu: ipu-v3: Remove IPU client registration
>   gpu: ipu-di: Set rate of DI pre clock
>   gpu: ipu-v3: Add RGB666 interface pixel map
>   gpu: ipu-cpmem: Pass drm fourcc to ipu_cpmem_set_yuv_*
>   gpu: ipu-v3: Add ipu_drm_fourcc_is_planar()
>   gpu: ipu-v3: Add IDMA channel linking support
>   gpu: ipu-cpmem: Support YVU422
>   gpu: ipu-cpmem: Add ipu_cpmem_get_burstsize()
>   imx-drm: Crtcs moved to device tree
>   imx-drm: hdmi: optimize i2c write wait
>   imx-drm: parallel-display: Support RGB666 pixel fmt
>   imx-drm: imx-ldb: Add debug to connector/encoder entry points
>   imx-drm: imx-ldb: Implement imx_ldb_encoder_dpms()
>   imx-drm: parallel-display: Fix typo when setting mode type
>   imx-drm: ipuv3-plane: Fix planar formats
>   imx-drm: ipuv3-plane: Allow YUV space for background plane
>   imx-drm: ipuv3-plane: Add more supported pixel formats
>   imx-drm: ipuv3-plane: Implement global alpha and colorkey properties
>   imx-drm: hdmi: rework irq request/free
>   imx-drm: imx-ldb: Add DDC support
>   imx-drm: Fix separate primary plane objects
>   imx-drm: Move page flip handling to plane driver
>   imx-drm: Reset ipu unit pointers to NULL on errors
>   drm: implement page flipping support for planes
>   imx-drm: ipuv3-plane: Assign page_flip method to drm_plane_funcs
>   imx-drm: Implement DRM gamma set
>   imx-drm: Implement custom ioctl to set gamma
>   imx-drm: Add support for interface pixel maps
>   imx-drm: parallel-display: Add interface-pix-map DT property
>   imx-drm: hdmi: set DI clock source to DI pre clock
>   imx-drm: ipuv3-crtc: Set the crtc device name
>   imx-drm: hdmi: Save ipu/di mux for 

[Bug 82889] [drm:si_dpm_set_power_state] *ERROR* si_disable_ulv failed

2014-10-31 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=82889

--- Comment #24 from Alex Deucher  ---
(In reply to sean darcy from comment #23)
> I've a kaveri a8-7100. After this patch, is there a way to reenable ulv
> without rebuilding drm?

This patch and bug have nothing to do with Kaveri.  It's specifically related
Southern Islands GPUs.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141031/f0ed9f3e/attachment.html>


[PATCH 1/3] drm: Add a note to drm_property_create() about property lifetime

2014-10-31 Thread Daniel Vetter
On Fri, Oct 31, 2014 at 02:39:11PM +, Damien Lespiau wrote:
> Cc: Chandra Konduru 
> Cc: Daniel Vetter 
> Signed-off-by: Damien Lespiau 

On the entire series:

Reviewed-by: Daniel Vetter 

Merged into topic/core-stuff for shepherding until it lands in drm-next.
-Daniel

> ---
>  drivers/gpu/drm/drm_crtc.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 4081d7a..0f3c24c 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -3417,6 +3417,10 @@ void drm_fb_release(struct drm_file *priv)
>   * object with drm_object_attach_property. The returned property object must 
> be
>   * freed with drm_property_destroy.
>   *
> + * Note that the DRM core keeps a per-device list of properties and that, if
> + * drm_mode_config_cleanup() is called, it will destroy all properties 
> created
> + * by the driver.
> + *
>   * Returns:
>   * A pointer to the newly created property on success, NULL on failure.
>   */
> -- 
> 1.8.3.1
> 
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH] drm/vmwgfx: fix lock breakage

2014-10-31 Thread Daniel Vetter
On Thu, Oct 30, 2014 at 01:39:04PM -0400, Rob Clark wrote:
> After:
> 
> commit d059f652e73c35678d28d4cd09ab2cec89696af9
> Author: Daniel Vetter 
> AuthorDate: Fri Jul 25 18:07:40 2014 +0200
> 
> drm: Handle legacy per-crtc locking with full acquire ctx
> 
> drm_mode_cursor_common() was switched to use drm_modeset_(un)lock_crtc()
> which uses full aquire ctx.  So dropping/reaquiring the lock via
> drm_modeset_(un)lock() directly isn't the right thing to do, as lockdep
> kindly points out.
> 
> The 'FIXME's about sorting out whether vmwgfx *really* needs to lock-all
> for cursor updates still apply.
> 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c 
> b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index d2bc2b0..8fc1e38 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -187,7 +187,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct 
> drm_file *file_priv,
>* can do this since the caller in the drm core doesn't check anything
>* which is protected by any looks.
>*/
> - drm_modeset_unlock(>mutex);
> + drm_modeset_unlock_crtc(crtc);
>   drm_modeset_lock_all(dev_priv->dev);

Oh right this is simpler, but it also grabs a new acquire context. So not
too terribly fair really, but otoh neither was the old one.

Reviewed-by: Daniel Vetter 
>  
>   /* A lot of the code assumes this */
> @@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct 
> drm_file *file_priv,
>   ret = 0;
>  out:
>   drm_modeset_unlock_all(dev_priv->dev);
> - drm_modeset_lock(>mutex, NULL);
> + drm_modeset_lock_crtc(crtc);
>  
>   return ret;
>  }
> @@ -273,7 +273,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, 
> int y)
>* can do this since the caller in the drm core doesn't check anything
>* which is protected by any looks.
>*/
> - drm_modeset_unlock(>mutex);
> + drm_modeset_unlock_crtc(crtc);
>   drm_modeset_lock_all(dev_priv->dev);
>  
>   vmw_cursor_update_position(dev_priv, shown,
> @@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, 
> int y)
>  du->cursor_y + du->hotspot_y);
>  
>   drm_modeset_unlock_all(dev_priv->dev);
> - drm_modeset_lock(>mutex, NULL);
> + drm_modeset_lock_crtc(crtc);
>  
>   return 0;
>  }
> -- 
> 1.9.3
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


Modesetting lock changes breaks vmwgfx since 3.18-rc1

2014-10-31 Thread Daniel Vetter
On Thu, Oct 30, 2014 at 03:41:31PM +0100, Thomas Hellstrom wrote:
> Hi!
> 
> Details in
> 
> https://bugzilla.redhat.com/show_bug.cgi?id=1155825
> 
> Can whoever broke the driver please make an effort to fix it up?
> 
> Daniel, You've been named as a suspect. I'm not sure if that is true.

Yeah the recent locking frobbing didn't account for the FIXME comment in
vmwgfx. Might be good to address that long-term to get vmwgfx more in line
with everyone else again - I simply don't understand the interactions well
enough to make that call. There's two of those in total.

Can we just remove them perhaps? The question is whether you can do the
cursor operation just with the per-crtc lock as protection, or whether
there's any shared resources and you need the full exclusion provided by
modeset_lock_all. If the crtc locking is good enough then we could rip
this out in both function and be done.

Note that this FIXME has been in vmwgfx since almost two years now.

If that's not possible then I have a major kludge of a hack in my atomic
helpers branch which will keep this alive for a bit longer. It ain't
pretty though.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[Bug 82889] [drm:si_dpm_set_power_state] *ERROR* si_disable_ulv failed

2014-10-31 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=82889

--- Comment #23 from sean darcy  ---
I've a kaveri a8-7100. After this patch, is there a way to reenable ulv without
rebuilding drm?

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141031/42d0207c/attachment.html>


[PATCH 1/3] drm: Pull drm_crtc.h into the kerneldoc template

2014-10-31 Thread Daniel Vetter
On Fri, Oct 31, 2014 at 07:25:08AM -0400, Sean Paul wrote:
> On Wed, Oct 29, 2014 at 5:12 AM, Daniel Vetter  
> wrote:
> > While writing atomic docs I've noticed that I don't get any errors
> > for my screw-ups in drm_crtc.h. Fix this immediately.
> >
> > This just does the bare minimum to get starts, lots of stuff isn't
> > properly documented yet unfortunately.
> >
> > Signed-off-by: Daniel Vetter 
> 
> 
> Small spelling nit below, not sure if you want to fix it in this patch.

Fixed locally, I'll resend the entire pile with the atomic patches again.
> 
> Reviewed-by: Sean Paul 

Thanks for your review.
-Daniel

> 
> 
> > ---
> >  Documentation/DocBook/drm.tmpl |  4 
> >  include/drm/drm_crtc.h | 26 +-
> >  2 files changed, 17 insertions(+), 13 deletions(-)
> >
> > diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
> > index be35bc328b77..89829ae58e97 100644
> > --- a/Documentation/DocBook/drm.tmpl
> > +++ b/Documentation/DocBook/drm.tmpl
> > @@ -1827,6 +1827,10 @@ void intel_crt_init(struct drm_device *dev)
> >  !Edrivers/gpu/drm/drm_crtc.c
> >  
> >  
> > +  KMS Data Structures
> > +!Iinclude/drm/drm_crtc.h
> > +
> > +
> >KMS Locking
> >  !Pdrivers/gpu/drm/drm_modeset_lock.c kms locking
> >  !Iinclude/drm/drm_modeset_lock.h
> > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> > index 44c57d2a64ec..21a15850a4d5 100644
> > --- a/include/drm/drm_crtc.h
> > +++ b/include/drm/drm_crtc.h
> > @@ -142,7 +142,7 @@ struct drm_framebuffer_funcs {
> > int (*create_handle)(struct drm_framebuffer *fb,
> >  struct drm_file *file_priv,
> >  unsigned int *handle);
> > -   /**
> > +   /*
> >  * Optinal callback for the dirty fb ioctl.
> 
> Couldn't hurt to add an extra 'o' here while you're at it.
> 
> >  *
> >  * Userspace can notify the driver via this callback
> > @@ -226,7 +226,7 @@ struct drm_plane;
> >  struct drm_bridge;
> >
> >  /**
> > - * drm_crtc_funcs - control CRTCs for a given device
> > + * struct drm_crtc_funcs - control CRTCs for a given device
> >   * @save: save CRTC state
> >   * @restore: restore CRTC state
> >   * @reset: reset CRTC after state has been invalidated (e.g. resume)
> > @@ -290,7 +290,7 @@ struct drm_crtc_funcs {
> >  };
> >
> >  /**
> > - * drm_crtc - central CRTC control structure
> > + * struct drm_crtc - central CRTC control structure
> >   * @dev: parent DRM device
> >   * @head: list management
> >   * @mutex: per-CRTC locking
> > @@ -322,7 +322,7 @@ struct drm_crtc {
> > struct device_node *port;
> > struct list_head head;
> >
> > -   /**
> > +   /*
> >  * crtc mutex
> >  *
> >  * This provides a read lock for the overall crtc state (mode, dpms
> > @@ -377,7 +377,7 @@ struct drm_crtc {
> >
> >
> >  /**
> > - * drm_connector_funcs - control connectors on a given device
> > + * struct drm_connector_funcs - control connectors on a given device
> >   * @dpms: set power state (see drm_crtc_funcs above)
> >   * @save: save connector state
> >   * @restore: restore connector state
> > @@ -414,7 +414,7 @@ struct drm_connector_funcs {
> >  };
> >
> >  /**
> > - * drm_encoder_funcs - encoder controls
> > + * struct drm_encoder_funcs - encoder controls
> >   * @reset: reset state (e.g. at init or resume time)
> >   * @destroy: cleanup and free associated data
> >   *
> > @@ -428,7 +428,7 @@ struct drm_encoder_funcs {
> >  #define DRM_CONNECTOR_MAX_ENCODER 3
> >
> >  /**
> > - * drm_encoder - central DRM encoder structure
> > + * struct drm_encoder - central DRM encoder structure
> >   * @dev: parent DRM device
> >   * @head: list management
> >   * @base: base KMS object
> > @@ -472,7 +472,7 @@ struct drm_encoder {
> >  #define MAX_ELD_BYTES  128
> >
> >  /**
> > - * drm_connector - central DRM connector control structure
> > + * struct drm_connector - central DRM connector control structure
> >   * @dev: parent DRM device
> >   * @kdev: kernel device for sysfs attributes
> >   * @attr: sysfs attributes
> > @@ -566,7 +566,7 @@ struct drm_connector {
> >  };
> >
> >  /**
> > - * drm_plane_funcs - driver plane control functions
> > + * struct drm_plane_funcs - driver plane control functions
> >   * @update_plane: update the plane configuration
> >   * @disable_plane: shut down the plane
> >   * @destroy: clean up plane resources
> > @@ -594,7 +594,7 @@ enum drm_plane_type {
> >  };
> >
> >  /**
> > - * drm_plane - central DRM plane control structure
> > + * struct drm_plane - central DRM plane control structure
> >   * @dev: DRM device this plane belongs to
> >   * @head: for list management
> >   * @base: base mode object
> > @@ -632,7 +632,7 @@ struct drm_plane {
> >  };
> >
> >  /**
> > - * drm_bridge_funcs - drm_bridge control functions
> > + * struct drm_bridge_funcs - drm_bridge control functions
> >   * @attach: Called during 

[PATCH 3/5] drm/ttm: Use only DRM_MM_SEARCH_BELOW for TTM_PL_FLAG_TOPDOWN

2014-10-31 Thread Daniel Vetter
On Thu, Oct 30, 2014 at 04:07:05PM +0100, Thomas Hellstrom wrote:
> On 10/28/2014 12:10 PM, Daniel Vetter wrote:
> > On Tue, Oct 28, 2014 at 06:35:04PM +0900, Michel Dänzer wrote:
> >> From: Michel Dänzer 
> >>
> >> DRM_MM_SEARCH_BEST gets the smallest hole which can fit the BO. That seems
> >> against the idea of TTM_PL_FLAG_TOPDOWN:
> >>
> >> * The smallest hole may be in the overall bottom of the area
> >> * If the hole isn't much larger than the BO, it doesn't make much
> >>   difference whether the BO is placed at the bottom or at the top of the
> >>   hole
> >>
> >> Signed-off-by: Michel Dänzer 
> > tbh I think SEARCH_BEST is pretty much always a bad idea - it rips apart
> > allocations from the same execbuf, and usually those get recycled around
> > the same time. Which means you'll just fragment your mm even more if you
> > try to find the best hole instead of just picking one and the stuffing the
> > entire execbuf into it. So imo we might as well just kill it.
> >
> > Another one that I've advertised a bunch of times already is the scan
> > roaster in drm_mm.c: Currently ttm just evicts until there's a big enough
> > hole, which is fairly awful if you have quasi-segmented memory like with
> > top-down/bottom-up schemes and different ranges for different units. With
> > the roaster you just walk the lru and build up potential holes until
> > there's a suitable one, and then only evict those buffers. Which means if
> > you have a certain range of memory under very high pressure (e.g. the 256M
> > which uvd can use or whatever it is), then you wont thrash all the other
> > vram too.
> >
> > Cheers, Daniel
> >
> And I think I've commented each time why that is currently not possible
> or at least worthile with TTM ;).
> 
> Although the idea is great, even if you make a nice list of suitable
> buffers to evict, as soon as you drop the LRU spinlock, that list is
> invalid. Worse, while you start evicting your list, other processes may
> steal part of the hole you've created.
> 
> As some point we should perhaps figure out how to protect each managed
> area with a separate mutex, but that would create trouble if, for
> example, evicting from VRAM to managed GART.

Yeah, you need to do the entire scanning/evicting under the lru lock,
which means you need to jump over all the buffers you can't immediately
trylock. Which also means that you need a slowpath fallback that rips out
everything in case the buffer doesn't fit anywhere. Wrt the lru lock you
need to at least overwrite the generic placement/eviction code since you
need to a bit more logic and state-keeping for drm_mm than what's
currently exposed in the super-generic ttm managed area allocator (which
apparently could also manage an idr). But shouldn't be more fuzz than a
new vfunc with the current code as default implementation.

For lru lock recursion (due to vram->gtt eviction or similar) I guess
either rework stuff to allow the entire eviction process under lru. Or
keep the drm_mm allocations on some separate list until you've evicted
everything (dropping the lock meanwhile) and the mass-free the entire list
under the lru lock and immediately do your allocation.

I'm not sure whether the long hold times for the lru lock really would be
a problem (they'll happen even when you drop it for actual eviction since
walking the lru lists is costly when you jump over lots of buffers that
don't get you towards your goal), since evicting all buffers is probably
going to thrash the system much worse anyway. And for the worst case a
regular sched for lru lock contention or preemption should prevent
interactivity disasters for parallel cmd submission.

So yeah some details to take care of, but I don't think there's anything
insurmountable. It's just that I don't have time (nor justification) for
it. And it will be indeed quite a bit of work to get going.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH 00/72] staging imx-drm new features and fixes

2014-10-31 Thread Steve Longerbeam
On 10/31/2014 05:09 PM, Fabio Estevam wrote:
> Hi Steve,
>
> On Fri, Oct 31, 2014 at 8:53 PM, Steve Longerbeam  
> wrote:
>> Hi, this affects only Freescale imx IPU and imx-drm staging drivers,
>> except for two patches that affect drm core (patch 53 and 63, see below).
>>
>> New features for imx-drm staging driver:
>>
>> - Support for multi-display (HDMI and LVDS).
>> - Support for global alpha and color-key properties for overlay plane.
>> - Support for gamma correction.
>> - The imx-drm crtc devices moved to device tree.
>> - Support for defining custom display interface pixel mappings in the
>>   device tree.
>> - Implements encoder DPMS for LVDS.
>> - YUV planar pixel formats supported for DRM framebuffers.
>> - DDC support added for LVDS.
>> - Page flip handling moved to imx plane driver and implemented with
>>   IPU double-buffering.
>> - Support page-flip in the overlay plane (patch 53 affects drm core).
>> - Add support for parsing pixel clock edge select (patch 63 affects drm 
>> core).
>> - Add LVDS connection detect via drm_probe_ddc().
>> - Implement crtc mode_set_base using plane page-flip.
>>
>>
>> Fixed issues:
>>
>> - HDMI and LVDS now use different PLL clock roots (part of multi-display
>>   support).
>> - Use counter added to IPU DC enable/disable (part of multi-display
>>   support).
>> - Fixed some HDMI timing issues.
>> - Wider range of supported DI pixel clocks generated (all EDID modes
>>   reported from HDMI displays now work).
>> - Fix separate primary plane objects.
>> - HDMI must select DI pre clock as DI clock parent during encoder prepare
>>   (LVDS may have switched DI clock to LDB parent, part of multi-display
>>   support).
>> - Assign correct DMFC burst size.
>> - Resolve some DI synchronous display error cases.
>>
>>
>>
>> George G. Davis (1):
>>   ARM: dts: imx6qdl-sabreauto: Add HDMI device
>>
>> Jiada Wang (1):
>>   gpu: ipu-v3: fix HDMI timing issues
>>
>> Steve Longerbeam (70):
>>   ARM: dts: imx6qdl-sabrelite: Add HDMI device
>>   ARM: dts: imx6qdl: Create imx-drm crtc nodes
>>   ARM: i.MX6: use pll2_pfd0_352m as clock root of ipu_di
>>   ARM: i.MX6: select pll3_usb_otg for ldb_di for rev 1.0 chip
>>   gpu: ipu-cpmem: Add ipu_cpmem_set_uv_offset()
>>   gpu: ipu-v3: Add ipu_dp_set_chroma_key()
>>   gpu: ipu-v3: Add ipu_dp_set_gamma_correction()
>>   gpu: ipu-v3: Add support for dynamic DC interface pixel maps
>>   gpu: ipu-v3: Add ipu_dc_uninit_sync()
>>   gpu: ipu-v3: Pass struct ipu_dc to enable/disable
>>   gpu: ipu-v3: Add ipu_dp_uninit_channel()
>>   gpu: ipu-v3: Pass struct ipu_dp to enable/disable
>>   gpu: ipu-v3: Implement use counter for ipu_dc_enable(),
>> ipu_dc_disable()
>>   gpu: ipu-v3: Add DMFC/DP/DC/DI module enable/disable debug
>>   gpu: ipu-v3: Add ipu_di_uninit_sync_panel()
>>   gpu: ipu-v3: Split out DI clock enable/disable
>>   gpu: ipu-v3: Protect more CM reg access with IPU lock
>>   gpu: ipu-v3: Move DI waveform counter enable/disable to ipu-di
>>   gpu: ipu-v3: Update DP sync SRM always in ipu_dp_enable_channel()
>>   gpu: ipu-v3: Fix indent/ws in ipu-dmfc
>>   gpu: ipu-v3: Allow burstsize of 20 in ipu_dmfc_setup_channel()
>>   gpu: ipu-v3: Remove ipu_dmfc_init_channel()
>>   gpu: ipu-v3: Consolidate mutex lock in ipu_dmfc_alloc_bandwidth()
>>   gpu: ipu-v3: Enumerate the DC channel names
>>   gpu: ipu-di: Move ipu pointer init
>>   gpu: ipu-di: Add and improve debug/error messages
>>   gpu: ipu-v3: Change signal names in struct ipu_di_signal_cfg
>>   gpu: ipu-v3: Remove IPU client registration
>>   gpu: ipu-di: Set rate of DI pre clock
>>   gpu: ipu-v3: Add RGB666 interface pixel map
>>   gpu: ipu-cpmem: Pass drm fourcc to ipu_cpmem_set_yuv_*
>>   gpu: ipu-v3: Add ipu_drm_fourcc_is_planar()
>>   gpu: ipu-v3: Add IDMA channel linking support
>>   gpu: ipu-cpmem: Support YVU422
>>   gpu: ipu-cpmem: Add ipu_cpmem_get_burstsize()
>>   imx-drm: Crtcs moved to device tree
>>   imx-drm: hdmi: optimize i2c write wait
>>   imx-drm: parallel-display: Support RGB666 pixel fmt
>>   imx-drm: imx-ldb: Add debug to connector/encoder entry points
>>   imx-drm: imx-ldb: Implement imx_ldb_encoder_dpms()
>>   imx-drm: parallel-display: Fix typo when setting mode type
>>   imx-drm: ipuv3-plane: Fix planar formats
>>   imx-drm: ipuv3-plane: Allow YUV space for background plane
>>   imx-drm: ipuv3-plane: Add more supported pixel formats
>>   imx-drm: ipuv3-plane: Implement global alpha and colorkey properties
>>   imx-drm: hdmi: rework irq request/free
>>   imx-drm: imx-ldb: Add DDC support
>>   imx-drm: Fix separate primary plane objects
>>   imx-drm: Move page flip handling to plane driver
>>   imx-drm: Reset ipu unit pointers to NULL on errors
>>   drm: implement page flipping support for planes
>>   imx-drm: ipuv3-plane: Assign page_flip method to drm_plane_funcs
>>   imx-drm: Implement DRM gamma set
>>   imx-drm: Implement custom ioctl to set gamma
>>   imx-drm: Add support for interface pixel maps
>>   imx-drm: parallel-display: Add interface-pix-map 

[PATCH v3 0/9] Renesas R-Car DU HDMI support

2014-10-31 Thread Simon Horman
On Thu, Oct 30, 2014 at 01:40:34PM +0200, Laurent Pinchart wrote:
> Hi Simon,
> 
> On Thursday 30 October 2014 20:29:22 Simon Horman wrote:
> > 2014/10/30 20:05 "Laurent Pinchart" :
> > > On Tuesday 28 October 2014 15:30:05 Dave Airlie wrote:
> > >>> The last patch instantiates the HDMI encoder in the Koelsch board DT
> > >>> file and connects it to the DU output.
> > >>> 
> > >>> The patch series depends on Koelsch DU DT enablement (scheduled for
> > >>> merge in v3.19-rc1). Dave, I'd like to get this merged in v3.19-rc1, how
> > >>> would you like to proceed ? Could it go through Simon's Renesas tree ?
> > >>> There's a small risk of conflict in drivers/gpu/drm/drm_edid.c,
> > >>> include/drm/drm_edid.h, drivers/gpu/drm/i2c/Kconfig and
> > >>> drivers/gpu/drm/i2c/Makefile. Simon, could you alternatively provide a
> > >>> stable branch with the required dependencies ?
> > >> 
> > >> I'd probably like to take the drm patches into drm-next first, then
> > >> maybe get a stable branch from Simon I could use to base the rest on.
> > > 
> > > Simon, I believe that would be the dt-du-for-v3.19 branch of
> > > git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git
> > > 
> > > Is it correct ?
> > 
> > Sorry I shuffled things around a bit and what you need should now be in the
> > dt-for-v3.19 branch. I hope what is there now is stable. But I'd appreciate
> > it if you could wait a few more days.
> 
> Sure, no problem. Could you please let me know when I can use it ?

Of course, will do.


[RFC] drm: Add utility function to check for edp1.4

2014-10-31 Thread Daniel Vetter
On Wed, Oct 29, 2014 at 02:42:29PM +0100, Thierry Reding wrote:
> On Wed, Oct 22, 2014 at 11:45:23AM +0530, sonika.jindal at intel.com wrote:
> > From: Sonika Jindal 
> > 
> > v2: Reading DP_EDP_REV, only when DISPLAY_CONTROL_CAPABLE field is set 
> > (Satheesh)
> > 
> > v3: Moving the utility function to drm_dp_helper (Daniel)
> > 
> > Signed-off-by: Sonika Jindal 
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c |   15 +++
> >  include/drm/drm_dp_helper.h |2 ++
> >  2 files changed, 17 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c 
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 08e33b8..a54a760 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -768,3 +768,18 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux)
> > i2c_del_adapter(>ddc);
> >  }
> >  EXPORT_SYMBOL(drm_dp_aux_unregister);
> > +
> > +bool drm_dp_is_edp_v1_4(struct drm_dp_aux *aux, const u8 
> > dpcd[DP_RECEIVER_CAP_SIZE])
> 
> I'd prefer if this didn't take a dpcd argument but rather directly
> accessed the DP_EDP_CONFIGURATION_CAP register so that it can be used
> directly rather than rely on the driver to have read a dpcd block in the
> appropriate format.

The idea is that you'd grab the DPCD field anyway since it's needed all
over the place. We have a pile of helpers already that take exactly this
block and decode parts of it. So I think this makes sense - dp aux is fast
but not entirely free, so caching seems useful.

It's a bit strange then that this helper reads more code, but I guess you
really only care about the edp_rev field if you want the edp revision, and
with your interface suggestion I don't think we'd ever need to read this
again.

So for me the input fields make sense. I agree that for the output of the
function an enum with all the edp revisions is better.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH V7 03/12] drm/bridge: Add helper functions for drm_bridge

2014-10-31 Thread Daniel Vetter
On Wed, Oct 29, 2014 at 10:09:04AM +0100, Andrzej Hajda wrote:
> On 10/29/2014 08:58 AM, Daniel Vetter wrote:
> > On Tue, Oct 28, 2014 at 04:05:34PM +0100, Thierry Reding wrote:
> >> On Tue, Oct 28, 2014 at 08:16:44PM +0530, Ajay kumar wrote:
> >>> On Tue, Oct 28, 2014 at 8:11 PM, Thierry Reding
> >>>  wrote:
>  On Tue, Oct 28, 2014 at 03:19:36PM +0100, Daniel Vetter wrote:
> > On Tue, Oct 28, 2014 at 1:28 PM, Ajay kumar  
> > wrote:
> >> On Tue, Oct 28, 2014 at 3:31 PM, Daniel Vetter  
> >> wrote:
>  [...]
> >>> Hm, if you do this can you pls also update drm_panel accordingly? It
> >>> shouldn't be a lot of fuzz and would make things around drm+dt more
> >>> consistent.
> >> Are you talking about using struct device_node instead of struct 
> >> device?
> >> I guess you have misplaced the comment under the wrong section!
> >
> > Yeah, that should have been one up ;-)
> 
>  Like I said earlier, I don't think dropping struct device * in favour of
>  struct device_node * is a good idea.
> >>> I am not sure about drm_panel.
> >>> But, I am not really doing anything with the struct device pointer in
> >>> case of bridge.
> >>> So, just wondering if it is really needed?
> >>
> >> I think it's useful to have it just to send the right message. DRM panel
> >> and DRM bridge aren't specific to device tree. They are completely
> >> generic and can work with any type of device, whether it was
> >> instantiated from the device tree or some other infrastructure. Dropping
> >> struct device * will make it effectively useless on anything but DT. I
> >> don't think we should strive for that, even if only DT-enabled platforms
> >> currently use them.
> > 
> > See my other reply, but I now think we should put neither into drm
> > structures. This "find me the driver structures for this device" problem
> > looks really generic, and it has nothing to do with the drm structures and
> > concepts like bridges/panels at all. It shouldn't be in there at all.
> > 
> > Adding it looks very much like reintroducing the drm midlayer that we just
> > finally made obsolete, just not at the top-level (struct drm_device) but
> > at a bunch of leaf nodes. I expect all the same issues though. And I'm
> > definitely not looking to de-midlayer more stuff that we're just adding.
> > 
> > Imo this should be solved as a separate helper thing, maybe in the driver
> > core akin to the component helpers from Russell.
> > -Daniel
> > 
> 
> As I understand you want something generic to look for panels, bridges,
> whatever and, like components, it should allow to safe hot plug/unplug.
> I have proposed such thing few months ago [1]. Have you looked at it?
> 
> [1]: https://lkml.org/lkml/2014/4/30/345

Yeah I think I've looked but wasn't convinced. I do agree though that we
should definitely aim for something in the driver core. Since if Greg
doesn't like it it's not suddenly better if we just hide it in the drm
subsystem. This really smells like a generic issue - after all we already
have a two implementations with bridges already.

So maybe we need to augment the component framework with the possibility
to add additional devices later on at runtime, or something similar. Not
really sure since I don't have actual practice with these issues since
i915 doesn't (yet) have these problems.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH V7 03/12] drm/bridge: Add helper functions for drm_bridge

2014-10-31 Thread Daniel Vetter
On Wed, Oct 29, 2014 at 10:16:49AM +0100, Thierry Reding wrote:
> On Wed, Oct 29, 2014 at 08:51:27AM +0100, Daniel Vetter wrote:
> > On Tue, Oct 28, 2014 at 03:29:47PM +0100, Thierry Reding wrote:
> > > On Mon, Oct 27, 2014 at 11:20:31PM +0100, Daniel Vetter wrote:
> > > > On Mon, Oct 27, 2014 at 8:58 PM, Sean Paul  
> > > > wrote:
> > > > >>> @@ -660,8 +662,11 @@ struct drm_bridge_funcs {
> > > > >>>   * @driver_private: pointer to the bridge driver's internal context
> > > > >>>   */
> > > > >>>  struct drm_bridge {
> > > > >>> - struct drm_device *dev;
> > > > >>> + struct device *dev;
> > > > >>
> > > > >> Please don't rename the ->dev pointer into drm. Because _all_ the 
> > > > >> other
> > > > >> drm structures still call it ->dev. Also, can't we use struct 
> > > > >> device_node
> > > > >> here like we do in the of helpers Russell added? See 7e435aad38083
> > > > >>
> > > > >
> > > > > I think this is modeled after the naming in drm_panel, FWIW. However,
> > > > > seems reasonable to keep the device_node instead.
> > > > 
> > > > Hm, indeed. Tbh I vote to rename drm_panel->drm to ->dev and like with
> > > > drm_crtc drop the struct device and go directly to a struct
> > > > device_node. Since we don't really need the sturct device, the only
> > > > thing we care about is the of_node. For added bonus wrap an #ifdef
> > > > CONFIG_OF around all the various struct device_node in drm_foo.h.
> > > > Should be all fairly simple to pull off with cocci.
> > > > 
> > > > Thierry?
> > > 
> > > The struct device * is in DRM panel because there's nothing device tree
> > > specific about the concept. Having a struct device_node * instead would
> > > indicate that it can only be used with a device tree, whereas the
> > > framework doesn't care the tiniest bit what type of device we have.
> > > 
> > > While the trend clearly is to use more device tree, I don't think we
> > > should make it impossible for anybody else to use these frameworks.
> > > 
> > > There are other advantages to keeping a struct device *, like having
> > > access to the proper device and its name. Also you get access to the
> > > device_node * via dev->of_node anyway. I don't see any advantage in
> > > switching to just a struct device_node *, only disadvantages.
> > 
> > Well the idea is to make the lookup key specific, and conditional on
> > #CONFIG_OF. If there's going to be another neat way to enumerate platform
> > devices then I think we should add that, too. Or maybe we should have a
> > void *platform_data or so.
> > 
> > The reason I really don't want a struct device * in core drm structures is
> > that two releases down the road people will have found tons of really
> > great ways to abuse them and re-create a midlayer. DRM core really should
> > only care about the sw objects and not be hw specific at all. Heck there's
> > not even an requirement to have any piece of actual hw, you could write a
> > completely fake drm driver (for e.g. testing like the new v4l driver).
> > 
> > Tbh I wonder a bit why we even have this registery embedded into the core
> > drm objects. Essentially the only thing you're doing is a list that maps
> > some platform specific key onto some subsystem specific driver structure
> > or fails the lookup. So instead of putting all these low-level details
> > into drm core structures can't we just have a generic hashtable/list for
> > this, plus some static inline helpers that cast the void * you get into
> > the one you want?
> > 
> > I also get the feeling that this really should be in the driver core (like
> > the component helpers), and that we should think a lot harder about
> > lifetimes and refcounting (see my other reply on that).
> 
> Yes, that sounds very useful indeed. Also see my reply to yours. =)

Just replying here with some of the irc discussions we've had. Since
drm_bridge/panel isn't a core drm interface object exposed to userspace
it's less critical. I still think that wasting a few brain cycles to have
a clear separation between the abstract interface object and how to bind
and unbind the pieces together is worthwhile, even though the cost when
getting it wrong is much less severe than in the case of a mandatory piece
of core infrastructure.

I think in general the recent armsoc motivated drm infrastructure lacks a
bit in attention to these details. E.g. the cma helpers are built into the
drm.ko module, but clearly are auxilliary library code. So they should be
pulled out and the headers clean up, so that we have a clear separation
between core and helpers. Otherwise someone will sooner or later screw up
and insert a helper depency into the core, and then we've started with the
midlayer mess. Same goes with drm_bridge/panel, which didn't even bother
to have separate headers from the core modeset header drm_crtc.h.

So would be great if someone could invest a bit of time into cleaning this
up. Writing proper api docs also helps a lot with achieving a clean and
sensible split ;-)

[PATCH V7 03/12] drm/bridge: Add helper functions for drm_bridge

2014-10-31 Thread Daniel Vetter
On Thu, Oct 30, 2014 at 10:09:28AM +, Russell King - ARM Linux wrote:
> On Thu, Oct 30, 2014 at 11:01:02AM +0100, Andrzej Hajda wrote:
> > On 10/29/2014 10:14 AM, Thierry Reding wrote:
> > > On Wed, Oct 29, 2014 at 09:57:02AM +0100, Daniel Vetter wrote:
> > >> I think we nee try_get_module for the code and kref on the actual data
> > >> structures.
> > > 
> > > Agreed, that should do the trick. We'd probably need some sort of logic
> > > to also make operations return something like -ENODEV when the
> > > underlying device has disappeared. I think David had introduced
> > > something similar for DRM device not so long ago?
> > 
> > If the underlying device disappears it would be good to receive
> > notification anyway to trigger DRM HPD event. And if we have the
> > notification, we can release references to the device smoothly. We do
> > not need to play tricky games with krefs, zombie data and module
> > refcounting.
> 
> Any solution which thinks it needs to lock modules into the core is
> fundamentally broken.  It totally misses the point.
> 
> While you can lock a module into the core using try_get_module(), that
> doesn't stop the device itself being unbound from a driver.  Soo many
> people have fallen into that trap.  They write their device driver,
> along with some kind of framework which they make use try_get_module().
> They think its safe.  When you then echo the device name into the
> driver's unbind sysfs file, all hell breaks loose and the kernel oopses.
> 
> try_get_module is /totally/ useless for ensuring that things stick around.
> 
> The reality is that you can't make devices stick around.  Once that
> remove callback from the driver layer is called, that's it, the device
> _is_ going away whether you like it or not.  You can't stop it.  It's
> no good returning -EBUSY, because the remove return code is ignored.
> 
> What's more scarey is when you consider that in a real hotplug
> situation, when the remove callback is called, the device has
> /already/ gone.
> 
> So please, stop thinking that try_get_module() has some magic solution.
> Any "solution" to device lifetimes using try_get_module() totally misses
> the problem, and is just mere obfuscation and actually a bug in itself.

We need proper refcounting ofc, but we also need to make sure that as long
as the thing is around the text section for the final unref (at least
that) doesn't go poof. I'd prefer if the framework takes care of that
detail and drivers could just supply a THIS_MODULE at the right place.

But fully agree on your overall point that try_get_module alone is pure
snake oil.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[Bugzilla] Your account dri-devel@lists.freedesktop.org is being impersonated

2014-10-31 Thread bugzilla-dae...@freedesktop.org
ajax at nwnk dot net  has used the 'sudo' feature to 
access 
Bugzilla using your account.

ajax at nwnk dot net  provided the following reason for 
doing this:
seeing if i can set email prefs (mareko wants the New: gone from bz emails)

If you feel that this action was inappropriate, please contact 
sitewranglers at lists.freedesktop.org.  For more information on this feature, 
visit .


[Bug 85696] [regression] r600g+nine: Bioshock shader failure after 7b1c0cbc90d456384b0950ad21faa3c61a6b43ff

2014-10-31 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=85696

David Heidelberg (okias)  changed:

   What|Removed |Added

Summary|[regression] r600g+nine:|[regression] r600g+nine:
   |Bioshock shader failure |Bioshock shader failure
   |after recent changes|after
   ||7b1c0cbc90d456384b0950ad21f
   ||aa3c61a6b43ff

-- 
You are receiving this mail because:
You are the assignee for the bug.
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141031/04b800e6/attachment.html>


[PATCH V7 03/12] drm/bridge: Add helper functions for drm_bridge

2014-10-31 Thread Daniel Vetter
On Wed, Oct 29, 2014 at 10:14:37AM +0100, Thierry Reding wrote:
> On Wed, Oct 29, 2014 at 09:57:02AM +0100, Daniel Vetter wrote:
> > That makes the entire thing a bit non-trivial, which is why I think it
> > would be better as some generic helper. Which then gets embedded or
> > instantiated for specific cases, like dt_panel or dt_bridge.
> > Or maybe even acpi_bridge, who knows ;-)
> 
> I worry a little about type safety. How will this generic helper know
> what registry to look in for? Or conversely, if all these resources are
> added to a single registry how do you know that they're of the correct
> type? Failing to ensure this could cause situations where you're asking
> for a panel and get a bridge in return because you've wrongly wired it
> up in device tree for example.
> 
> But perhaps if both the registry and the device parts are turned into
> helpers we could still have a single core implementation and then
> instantiate that for each type, something roughly like this:
> 
>   struct registry {
>   struct list_head list;
>   struct mutex lock;
>   };
> 
>   struct registry_record {
>   struct list_head list;
>   struct module *owner;
>   struct kref *ref;
> 
>   struct device *dev;
>   };
> 
>   int registry_add(struct registry *registry, struct registry_record 
> *record)
>   {
>   ...
>   try_module_get(record->owner);
>   ...
>   }
> 
>   struct registry_record *registry_find_by_of_node(struct registry 
> *registry,
>struct device_node *np)
>   {
>   ...
>   kref_get(...);
>   ...
>   }
> 
> That way it should be possible to embed these into other structures,
> like so:
> 
>   struct drm_panel {
>   struct registry_record record;
>   ...
>   };
> 
>   static struct registry drm_panels;
> 
>   int drm_panel_add(struct drm_panel *panel)
>   {
>   return registry_add(_panels, >record);
>   }
> 
>   struct drm_panel *of_drm_panel_find(struct device_node *np)
>   {
>   struct registry_record *record;
> 
>   record = registry_find_by_of_node(_panels, np);
> 
>   return container_of(record, struct drm_panel, record);
>   }
> 
> Is that what you had in mind?

Yeah I've thought that we should instantiate using macros even, so that we
have per-type registries. So you'd smash the usual set of
DECLARE/DEFINE_AUX_DEV_REGISTRY into headers/source files, and they'd take
a (name, key, value) tripled. For the example here(of_drm_panel, struct
device_node *, struct drm_panel *) or similar. I might be hand-waving over
a few too many details though ;-)

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH 72/72] imx-drm: ipuv3-plane: Enable 8 burst locking

2014-10-31 Thread Steve Longerbeam
Enable 8 burst locking in the primary and overlay plane
idmac channels. This seems to improve some cases of data
starvation errors to the DI.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index c012c4e..5849b30 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -273,6 +273,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
 fb->pitches[0], crtc_h);

ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
+   ipu_idmac_lock_enable(ipu_plane->ipu_ch, 8);

burstsize = ipu_cpmem_get_burstsize(ipu_plane->ipu_ch);

-- 
1.7.9.5



[PATCH 71/72] imx-drm: ipuv3-crtc: Disable overlay plane during crtc disable

2014-10-31 Thread Steve Longerbeam
If the overlay exists and is enabled, it must be disabled before
stopping the DI, otherwise DI synchronous display errors are the
result.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-crtc.c |8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 7d5b691..b49d1b2 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -138,6 +138,14 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
if (!ipu_crtc->enabled)
return;

+   /*
+* If the overlay exists and is enabled, it must be disabled
+* before stopping the DI, otherwise DI synchronous display
+* errors are the result.
+*/
+   if (ipu_crtc->have_overlay && ipu_crtc->plane[1].enabled)
+   ipu_plane_disable(_crtc->plane[1]);
+
/* Stop DC channel and DI before IDMAC */
ipu_dc_disable_channel(ipu_crtc->dc);
ipu_di_disable(ipu_crtc->di);
-- 
1.7.9.5



[PATCH 70/72] imx-drm: Cancel pending page flip events at preclose

2014-10-31 Thread Steve Longerbeam
At preclose, destroy page flip events that are pending on every
plane.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |   15 +--
 drivers/staging/imx-drm/imx-drm.h  |2 ++
 drivers/staging/imx-drm/ipuv3-crtc.c   |   13 +
 drivers/staging/imx-drm/ipuv3-plane.c  |   22 ++
 drivers/staging/imx-drm/ipuv3-plane.h  |2 ++
 5 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index b31d291..b2cc77b 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -213,13 +213,24 @@ static void imx_drm_disable_vblank(struct drm_device 
*drm, int pipe)
 static void imx_drm_driver_preclose(struct drm_device *drm,
struct drm_file *file)
 {
+   struct imx_drm_device *imxdrm = drm->dev_private;
+   struct imx_drm_crtc_helper_funcs *helpers;
+   struct imx_drm_crtc *imx_drm_crtc;
int pipe;

if (!file->is_master)
return;

-   for (pipe = 0; pipe < MAX_PIPES; pipe++)
-   imx_drm_disable_vblank(drm, pipe);
+   for (pipe = 0; pipe < MAX_PIPES; pipe++) {
+   imx_drm_crtc = imxdrm->crtc[pipe_to_crtc_id(pipe)];
+   if (!imx_drm_crtc)
+   continue;
+   helpers = _drm_crtc->imx_drm_helper_funcs;
+   if (!helpers->cancel_page_flip)
+   continue;
+
+   helpers->cancel_page_flip(imx_drm_crtc->crtc, file, pipe);
+   }
 }

 static const struct file_operations imx_drm_driver_fops = {
diff --git a/drivers/staging/imx-drm/imx-drm.h 
b/drivers/staging/imx-drm/imx-drm.h
index 24b889a..8ffcc0a 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -21,6 +21,8 @@ int imx_drm_overlay_plane_pipe(struct imx_drm_crtc *crtc);
 struct imx_drm_crtc_helper_funcs {
int (*enable_vblank)(struct drm_crtc *crtc, int pipe);
void (*disable_vblank)(struct drm_crtc *crtc, int pipe);
+   void (*cancel_page_flip)(struct drm_crtc *crtc, struct drm_file *file,
+int pipe);
int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
 u32 pix_fmt, struct ipu_dc_if_map *pix_map,
 int hsync_pin, int vsync_pin);
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 179b764..7d5b691 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -398,6 +398,18 @@ static void ipu_disable_vblank(struct drm_crtc *crtc, int 
pipe)
ipu_plane_disable_vblank(ipu_plane);
 }

+static void ipu_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file,
+int pipe)
+{
+   struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+   struct ipu_plane *ipu_plane = pipe_to_plane(ipu_crtc, pipe);
+
+   if (!ipu_plane)
+   return;
+
+   ipu_plane_cancel_page_flip(ipu_plane, file);
+}
+
 static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
 u32 pixfmt, struct ipu_dc_if_map *pixmap,
 int hsync_pin, int vsync_pin)
@@ -435,6 +447,7 @@ static int ipu_gamma_set(struct drm_crtc *crtc, bool 
enable, u32 *m, u32 *b)
 static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
.enable_vblank = ipu_enable_vblank,
.disable_vblank = ipu_disable_vblank,
+   .cancel_page_flip = ipu_cancel_page_flip,
.set_interface_pix_fmt = ipu_set_interface_pix_fmt,
.gamma_set = ipu_gamma_set,
.crtc_funcs = _crtc_funcs,
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index aa10ae7..c012c4e 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -150,6 +150,28 @@ void ipu_plane_disable_vblank(struct ipu_plane *ipu_plane)
ipu_plane->newfb = NULL;
 }

+void ipu_plane_cancel_page_flip(struct ipu_plane *ipu_plane,
+   struct drm_file *file)
+{
+   struct drm_device *drm = ipu_plane->base.dev;
+   struct drm_pending_vblank_event *event;
+   unsigned long flags;
+
+   /*
+* Destroy the pending vertical blanking event associated with the
+* pending page flip, if any, and disable vertical blanking interrupts.
+*/
+   spin_lock_irqsave(>event_lock, flags);
+   event = ipu_plane->page_flip_event;
+   if (event && event->base.file_priv == file) {
+   ipu_plane->page_flip_event = NULL;
+   ipu_plane->newfb = NULL;
+   event->base.destroy(>base);
+   drm_vblank_put(drm, ipu_plane->pipe);
+   }
+   spin_unlock_irqrestore(>event_lock, flags);
+}
+
 int 

[PATCH 69/72] imx-drm: ipuv3-crtc: Implement mode_set_base

2014-10-31 Thread Steve Longerbeam
Implement the mode_set_base drm_crtc_helper callback. DRM core calls
this method when there is a SetCrtc request but only the framebuffer
and/or the x/y scanout position in the framebuffer has changed and no
other video mode parameters have changed.

So mode_set_base is similar to a page flip except that there is no
page flip event handling. So ipu_crtc_mode_set_base() simply calls
ipu_plane_page_flip() with a NULL event pointer. A reference on the
vblank interrupt will be acquired and then released when the flip
completes, as in a normal page flip.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-crtc.c |   12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 53241fd..179b764 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -174,6 +174,17 @@ static int ipu_crtc_page_flip(struct drm_crtc *crtc,
return ipu_plane_page_flip(crtc->primary, fb, event, page_flip_flags);
 }

+static int ipu_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+   struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+
+   ipu_crtc->plane[0].x = x;
+   ipu_crtc->plane[0].y = y;
+
+   return ipu_plane_page_flip(crtc->primary, crtc->primary->fb, NULL, 0);
+}
+
 /*
  * Normally the DRM Gamma API is used to program a color LUT that contains
  * gamma-corrected pixel values for red, green, and blue input pixel values
@@ -358,6 +369,7 @@ static void ipu_crtc_commit(struct drm_crtc *crtc)

 static struct drm_crtc_helper_funcs ipu_helper_funcs = {
.dpms = ipu_crtc_dpms,
+   .mode_set_base = ipu_crtc_mode_set_base,
.mode_fixup = ipu_crtc_mode_fixup,
.mode_set = ipu_crtc_mode_set,
.prepare = ipu_crtc_prepare,
-- 
1.7.9.5



[PATCH 68/72] imx-drm: imx-ldb: Use DDC probe as connection detect

2014-10-31 Thread Steve Longerbeam
If a ddc node was specified in the device tree, use it in
imx_ldb_connector_detect() to probe the ddc with drm_probe_ddc(), if
the result is success, we know there is a display connected so return
connected status. Otherwise (no ddc specified in DT) we just have to
assume connected status.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-ldb.c |   24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/imx-drm/imx-ldb.c 
b/drivers/staging/imx-drm/imx-ldb.c
index 615e090..319eedb 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -92,10 +92,32 @@ struct imx_ldb {
 #define imx_ldb_entry_dbg(ch)  \
imx_ldb_dbg((ch), "%s\n", __func__)

+/*
+ * Use the result of ddc probe to detect LVDS display presence
+ * if a ddc DT node was specified.
+ */
 static enum drm_connector_status imx_ldb_connector_detect(
struct drm_connector *connector, bool force)
 {
-   return connector_status_connected;
+   struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
+   enum drm_connector_status status;
+
+   if (imx_ldb_ch->ddc) {
+   if (drm_probe_ddc(imx_ldb_ch->ddc)) {
+   status = connector_status_connected;
+   imx_ldb_dbg(imx_ldb_ch,
+   "ddc probe success, connected\n");
+   } else {
+   status = connector_status_disconnected;
+   imx_ldb_dbg(imx_ldb_ch,
+   "ddc probe failed, disconnected\n");
+   }
+   } else {
+   status = connector_status_connected;
+   imx_ldb_dbg(imx_ldb_ch, "no ddc, assuming connected\n");
+   }
+
+   return status;
 }

 static int imx_ldb_connector_get_modes(struct drm_connector *connector)
-- 
1.7.9.5



[PATCH 67/72] imx-drm: ipuv3-crtc: Disable fb on crtc unbind

2014-10-31 Thread Steve Longerbeam
Call ipu_fb_disable() in the crtc unbind method, in case the
crtc has been left enabled.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-crtc.c |2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 65fe429..53241fd 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -637,6 +637,8 @@ static void ipu_drm_unbind(struct device *dev, struct 
device *master,
 {
struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);

+   ipu_fb_disable(ipu_crtc);
+
imx_drm_remove_crtc(ipu_crtc->imx_crtc);

ipu_plane_put_resources(_crtc->plane[0]);
-- 
1.7.9.5



[PATCH 66/72] imx-drm: parallel-display: Add all defined of video modes

2014-10-31 Thread Steve Longerbeam
Instead of assuming only a single defined display-timing node in the
device tree, assume there can be multiple modes and register all of
them in imx_pd_connector_get_modes().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/parallel-display.c |   48 +++-
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/imx-drm/parallel-display.c 
b/drivers/staging/imx-drm/parallel-display.c
index e0b0b56..11ae35d 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -25,8 +25,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
-#include 
+#include 

 #include "imx-drm.h"

@@ -41,8 +42,7 @@ struct imx_parallel_display {
int edid_len;
u32 interface_pix_fmt;
struct ipu_dc_if_map *interface_map;
-   int mode_valid;
-   struct drm_display_mode mode;
+   struct display_timings *timings;
struct drm_panel *panel;
 };

@@ -55,7 +55,7 @@ static enum drm_connector_status imx_pd_connector_detect(
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
 {
struct imx_parallel_display *imxpd = con_to_imxpd(connector);
-   struct device_node *np = imxpd->dev->of_node;
+   struct display_timings *timings = imxpd->timings;
int num_modes = 0;

if (imxpd->panel && imxpd->panel->funcs &&
@@ -70,27 +70,26 @@ static int imx_pd_connector_get_modes(struct drm_connector 
*connector)
num_modes = drm_add_edid_modes(connector, imxpd->edid);
}

-   if (imxpd->mode_valid) {
-   struct drm_display_mode *mode = drm_mode_create(connector->dev);
+   if (timings) {
+   struct drm_display_mode *mode;
+   struct videomode vm;
+   int i;

-   if (!mode)
-   return -EINVAL;
-   drm_mode_copy(mode, >mode);
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_probed_add(connector, mode);
-   num_modes++;
-   }
+   for (i = 0; i < timings->num_timings; i++) {
+   if (videomode_from_timings(timings, , i))
+   break;

-   if (np) {
-   struct drm_display_mode *mode = drm_mode_create(connector->dev);
+   mode = drm_mode_create(connector->dev);
+   drm_display_mode_from_videomode(, mode);

-   if (!mode)
-   return -EINVAL;
-   of_get_drm_display_mode(np, >mode, OF_USE_NATIVE_MODE);
-   drm_mode_copy(mode, >mode);
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_probed_add(connector, mode);
-   num_modes++;
+   mode->type = DRM_MODE_TYPE_DRIVER;
+   if (i == timings->native_mode)
+   mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+   drm_mode_set_name(mode);
+   drm_mode_probed_add(connector, mode);
+   num_modes++;
+   }
}

return num_modes;
@@ -223,6 +222,8 @@ static int imx_pd_bind(struct device *dev, struct device 
*master, void *data)
if (edidp)
imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL);

+   imxpd->timings = of_get_display_timings(np);
+
ret = of_property_read_string(np, "interface-pix-fmt", );
if (!ret) {
if (!strcmp(fmt, "rgb24"))
@@ -282,6 +283,9 @@ static void imx_pd_unbind(struct device *dev, struct device 
*master,

imxpd->encoder.funcs->destroy(>encoder);
imxpd->connector.funcs->destroy(>connector);
+
+   if (imxpd->timings)
+   display_timings_release(imxpd->timings);
 }

 static const struct component_ops imx_pd_ops = {
-- 
1.7.9.5



[PATCH 65/72] imx-drm: imx-ldb: Add all defined of video modes

2014-10-31 Thread Steve Longerbeam
Instead of assuming only a single defined display-timing node in the
device tree, assume there can be multiple modes and register all of
them in imx_ldb_connector_get_modes().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-ldb.c |   46 ++---
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-ldb.c 
b/drivers/staging/imx-drm/imx-ldb.c
index 53d9d82..615e090 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -28,7 +28,9 @@
 #include 
 #include 
 #include 
-#include 
+#include 
+#include 
+#include 
 #include 
 #include 

@@ -65,8 +67,7 @@ struct imx_ldb_channel {
int chno;
void *edid;
int edid_len;
-   struct drm_display_mode mode;
-   int mode_valid;
+   struct display_timings *timings;
 };

 struct bus_mux {
@@ -100,6 +101,7 @@ static enum drm_connector_status imx_ldb_connector_detect(
 static int imx_ldb_connector_get_modes(struct drm_connector *connector)
 {
struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
+   struct display_timings *timings = imx_ldb_ch->timings;
int num_modes = 0;

imx_ldb_entry_dbg(imx_ldb_ch);
@@ -113,16 +115,26 @@ static int imx_ldb_connector_get_modes(struct 
drm_connector *connector)
num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid);
}

-   if (imx_ldb_ch->mode_valid) {
+   if (timings) {
struct drm_display_mode *mode;
+   struct videomode vm;
+   int i;

-   mode = drm_mode_create(connector->dev);
-   if (!mode)
-   return -EINVAL;
-   drm_mode_copy(mode, _ldb_ch->mode);
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-   drm_mode_probed_add(connector, mode);
-   num_modes++;
+   for (i = 0; i < timings->num_timings; i++) {
+   if (videomode_from_timings(timings, , i))
+   break;
+
+   mode = drm_mode_create(connector->dev);
+   drm_display_mode_from_videomode(, mode);
+
+   mode->type = DRM_MODE_TYPE_DRIVER;
+   if (i == timings->native_mode)
+   mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+   drm_mode_set_name(mode);
+   drm_mode_probed_add(connector, mode);
+   num_modes++;
+   }
}

return num_modes;
@@ -568,16 +580,11 @@ static int imx_ldb_bind(struct device *dev, struct device 
*master, void *data)
channel->edid = kmemdup(edidp,
channel->edid_len,
GFP_KERNEL);
-   } else {
-   /* fallback to display-timings node */
-   ret = of_get_drm_display_mode(child,
- >mode,
- 0);
-   if (!ret)
-   channel->mode_valid = 1;
}
}

+   channel->timings = of_get_display_timings(child);
+
ret = of_property_read_u32(child, "fsl,data-width", );
if (ret)
datawidth = 0;
@@ -639,6 +646,9 @@ static void imx_ldb_unbind(struct device *dev, struct 
device *master,
channel->encoder.funcs->destroy(>encoder);

i2c_put_adapter(channel->ddc);
+
+   if (channel->timings)
+   display_timings_release(channel->timings);
}
 }

-- 
1.7.9.5



[PATCH 64/72] imx-drm: ipuv3-crtc: Use DRM mode flags to configure pixel clock polarity

2014-10-31 Thread Steve Longerbeam
Previously, pixel clock polarity was hardcoded and wasn't configurable.
This patch adds support to configure the pixel clock polarity from the
DRM mode flags.

Signed-off-by: Mohsin Kazmi 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-crtc.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 316e5bf..65fe429 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -291,9 +291,10 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
sig_cfg.hsync_pol = 1;
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
sig_cfg.vsync_pol = 1;
+   if (mode->flags & DRM_MODE_FLAG_PCLK)
+   sig_cfg.clk_pol = 1;

sig_cfg.enable_pol = 1;
-   sig_cfg.clk_pol = 0;
sig_cfg.width = mode->hdisplay;
sig_cfg.height = mode->vdisplay;
sig_cfg.pixel_fmt = out_pixel_fmt;
-- 
1.7.9.5



[PATCH 63/72] drm_modes: videomode: add pos/neg pixel clock polarity flag

2014-10-31 Thread Steve Longerbeam
Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/drm/drm_modes.c |4 
 include/uapi/drm/drm_mode.h |4 
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index d1b7d20..5016099 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -611,6 +611,10 @@ void drm_display_mode_from_videomode(const struct 
videomode *vm,
dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
dmode->flags |= DRM_MODE_FLAG_DBLCLK;
+   if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
+   dmode->flags |= DRM_MODE_FLAG_PCLK;
+   else if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+   dmode->flags |= DRM_MODE_FLAG_NCLK;
drm_mode_set_name(dmode);
 }
 EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 8d98cd0..d5d045c 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -72,6 +72,10 @@
 #define  DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH(6<<14)
 #define  DRM_MODE_FLAG_3D_TOP_AND_BOTTOM   (7<<14)
 #define  DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF(8<<14)
+/* drive data on rising pixclk edge */
+#define DRM_MODE_FLAG_PCLK (1<<19)
+/* drive data on falling pixclk edge */
+#define DRM_MODE_FLAG_NCLK (1<<20)


 /* DPMS flags */
-- 
1.7.9.5



[PATCH 62/72] imx-drm: ipuv3-plane: Assign correct dmfc burst size

2014-10-31 Thread Steve Longerbeam
According to the imx6 reference manual, the DMFC channel's
burstsize must match the corresponding IDMAC channel's burstsize,
so make sure to pass the IDMAC channel burstsize to
ipu_dmfc_alloc_bandwidth(). We need to move ipu_dmfc_alloc_bandwidth()
to after the channel is setup, in order to first initialize the
channel burstsize, before retrieving it with ipu_cpmem_get_burstsize().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |   20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 61d47e9..aa10ae7 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -159,7 +159,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
 {
struct device *dev = ipu_plane->base.dev->dev;
bool is_bg = (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_BG);
-   int ret;
+   int burstsize, ret;

/* no scaling */
if (src_w != crtc_w || src_h != crtc_h)
@@ -238,14 +238,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
}
}

-   ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
-   calc_bandwidth(crtc_w, crtc_h,
-  calc_vref(mode)), crtc_w, 64);
-   if (ret) {
-   dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
-   return ret;
-   }
-
ipu_cpmem_zero(ipu_plane->ipu_ch);
ipu_cpmem_set_resolution(ipu_plane->ipu_ch, src_w, src_h);
ret = ipu_cpmem_set_fmt(ipu_plane->ipu_ch, fb->pixel_format);
@@ -260,6 +252,16 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,

ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);

+   burstsize = ipu_cpmem_get_burstsize(ipu_plane->ipu_ch);
+
+   ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
+   calc_bandwidth(crtc_w, crtc_h,
+  calc_vref(mode)), crtc_w, burstsize);
+   if (ret) {
+   dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
+   return ret;
+   }
+
/* enable double-buffering */
ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, true);

-- 
1.7.9.5



[PATCH 61/72] imx-drm: hdmi: Save ipu/di mux for later iomux setup

2014-10-31 Thread Steve Longerbeam
Store the ipu/di mux in struct imx_hdmi during imx_hdmi_encoder_prepare().
imx_hdmi_encoder_commit() can then use the mux when setting the iomux
instead of looking it up again via imx_drm_encoder_get_mux_id().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-hdmi.c |9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index d97fa18..2503237 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -124,6 +124,7 @@ struct imx_hdmi {
struct hdmi_data_info hdmi_data;
int vic;
int irq;
+   int mux;

u8 edid[HDMI_EDID_LEN];
bool cable_plugin;
@@ -1454,12 +1455,13 @@ static void imx_hdmi_encoder_dpms(struct drm_encoder 
*encoder, int mode)
 static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder)
 {
struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
-   int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
+
+   hdmi->mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);

imx_hdmi_poweroff(hdmi);

/* set DI clock mux to DI pre clock mux */
-   clk_set_parent(hdmi->di_sel[mux], hdmi->di_pre_sel[mux]);
+   clk_set_parent(hdmi->di_sel[hdmi->mux], hdmi->di_pre_sel[hdmi->mux]);

imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24, NULL);
 }
@@ -1467,9 +1469,8 @@ static void imx_hdmi_encoder_prepare(struct drm_encoder 
*encoder)
 static void imx_hdmi_encoder_commit(struct drm_encoder *encoder)
 {
struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
-   int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);

-   imx_hdmi_set_ipu_di_mux(hdmi, mux);
+   imx_hdmi_set_ipu_di_mux(hdmi, hdmi->mux);

imx_hdmi_poweron(hdmi);
 }
-- 
1.7.9.5



[PATCH 60/72] imx-drm: ipuv3-crtc: Set the crtc device name

2014-10-31 Thread Steve Longerbeam
Set the i.mx crtc device name to a more meaningful crtc[0-3], which
matches the device tree phandle names.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-crtc.c |   10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index bd158d6..316e5bf 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -80,6 +80,7 @@ struct ipu_crtc {
struct device   *ipu_dev; /* our ipu */
struct ipu_soc  *ipu;
struct device_node  *port;/* our port */
+   int id;   /* this crtc's id */

const struct ipu_channels *ch;

@@ -545,7 +546,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 struct drm_device *drm)
 {
struct device_node *np = ipu_crtc->dev->of_node;
-   int id, primary_pipe, overlay_pipe;
+   int primary_pipe, overlay_pipe;
int ret;

ret = ipu_get_resources(ipu_crtc, np);
@@ -563,7 +564,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
goto err_put_resources;
}

-   id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
+   ipu_crtc->id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
primary_pipe = imx_drm_primary_plane_pipe(ipu_crtc->imx_crtc);

ret = ipu_plane_init(_crtc->plane[0], drm,
@@ -571,7 +572,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 primary_pipe,
 ipu_crtc->ch->dma[0],
 ipu_crtc->ch->dp[0],
-BIT(id), true);
+BIT(ipu_crtc->id), true);
if (ret) {
dev_err(ipu_crtc->dev, "init primary plane failed with %d\n",
ret);
@@ -593,7 +594,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
 overlay_pipe,
 ipu_crtc->ch->dma[1],
 ipu_crtc->ch->dp[1],
-BIT(id), false);
+BIT(ipu_crtc->id), false);

ipu_crtc->have_overlay = ret ? false : true;
}
@@ -625,6 +626,7 @@ static int ipu_drm_bind(struct device *dev, struct device 
*master, void *data)
return ret;

dev_set_drvdata(dev, ipu_crtc);
+   dev_set_name(dev, "crtc%d", ipu_crtc->id);

return 0;
 }
-- 
1.7.9.5



[PATCH 59/72] imx-drm: hdmi: set DI clock source to DI pre clock

2014-10-31 Thread Steve Longerbeam
If DI is firstly bound to ldb and then re-bound to HDMI,
DI clock source will still be routed to LDB clock by ldb driver.
In HDMI driver's encoder_prepare, we have to set DI clock source to
the parent di_pre clock mux to ensure we are having correct clock
chain to drive HDMI display.

Signed-off-by: Steve Longerbeam 
Signed-off-by: Jiada Wang 
---
 arch/arm/boot/dts/imx6dl.dtsi  |8 
 arch/arm/boot/dts/imx6q.dtsi   |   12 
 arch/arm/boot/dts/imx6qdl.dtsi |3 ---
 drivers/staging/imx-drm/imx-hdmi.c |   32 +++-
 4 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 05af0f4..7d1a1bf 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -104,6 +104,14 @@

  {
compatible = "fsl,imx6dl-hdmi";
+   clocks = < IMX6QDL_CLK_HDMI_IAHB>, < IMX6QDL_CLK_HDMI_ISFR>,
+< IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
+< IMX6QDL_CLK_IPU1_DI1_PRE_SEL>,
+< IMX6QDL_CLK_IPU1_DI0_SEL>,
+< IMX6QDL_CLK_IPU1_DI1_SEL>;
+   clock-names = "iahb", "isfr",
+ "di0_pre_sel", "di1_pre_sel",
+ "di0_sel", "di1_sel";
 };

  {
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 9d1f88c..7d0a7bc 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -235,6 +235,18 @@

  {
compatible = "fsl,imx6q-hdmi";
+   clocks = < IMX6QDL_CLK_HDMI_IAHB>, < IMX6QDL_CLK_HDMI_ISFR>,
+< IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
+< IMX6QDL_CLK_IPU1_DI1_PRE_SEL>,
+< IMX6QDL_CLK_IPU2_DI0_PRE_SEL>,
+< IMX6QDL_CLK_IPU2_DI1_PRE_SEL>,
+< IMX6QDL_CLK_IPU1_DI0_SEL>,
+< IMX6QDL_CLK_IPU1_DI1_SEL>,
+< IMX6QDL_CLK_IPU2_DI0_SEL>,
+< IMX6QDL_CLK_IPU2_DI1_SEL>;
+   clock-names = "iahb", "isfr",
+ "di0_pre_sel", "di1_pre_sel", "di2_pre_sel", 
"di3_pre_sel",
+ "di0_sel", "di1_sel", "di2_sel", "di3_sel";

port at 2 {
reg = <2>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 13d6b50..4e3a3e8 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -810,9 +810,6 @@
reg = <0x0012 0x9000>;
interrupts = <0 115 0x04>;
gpr = <>;
-   clocks = < IMX6QDL_CLK_HDMI_IAHB>,
-< IMX6QDL_CLK_HDMI_ISFR>;
-   clock-names = "iahb", "isfr";
status = "disabled";

port at 0 {
diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index 4ef1c0a..d97fa18 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -118,6 +118,8 @@ struct imx_hdmi {
struct device *dev;
struct clk *isfr_clk;
struct clk *iahb_clk;
+   struct clk *di_pre_sel[4];
+   struct clk *di_sel[4];

struct hdmi_data_info hdmi_data;
int vic;
@@ -1452,8 +1454,13 @@ static void imx_hdmi_encoder_dpms(struct drm_encoder 
*encoder, int mode)
 static void imx_hdmi_encoder_prepare(struct drm_encoder *encoder)
 {
struct imx_hdmi *hdmi = container_of(encoder, struct imx_hdmi, encoder);
+   int mux = imx_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);

imx_hdmi_poweroff(hdmi);
+
+   /* set DI clock mux to DI pre clock mux */
+   clk_set_parent(hdmi->di_sel[mux], hdmi->di_pre_sel[mux]);
+
imx_drm_panel_format(encoder, V4L2_PIX_FMT_RGB24, NULL);
 }

@@ -1593,7 +1600,7 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)
struct device_node *ddc_node;
struct imx_hdmi *hdmi;
struct resource *iores;
-   int ret;
+   int i, ret;

hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
@@ -1629,6 +1636,29 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)
if (IS_ERR(hdmi->regmap))
return PTR_ERR(hdmi->regmap);

+   for (i = 0; i < 4; i++) {
+   char clkname[16];
+
+   sprintf(clkname, "di%d_pre_sel", i);
+   hdmi->di_pre_sel[i] = devm_clk_get(hdmi->dev, clkname);
+   if (IS_ERR(hdmi->di_pre_sel[i])) {
+   ret = PTR_ERR(hdmi->di_pre_sel[i]);
+   hdmi->di_pre_sel[i] = NULL;
+   break;
+   }
+
+   sprintf(clkname, "di%d_sel", i);
+   hdmi->di_sel[i] = devm_clk_get(hdmi->dev, clkname);
+   if (IS_ERR(hdmi->di_sel[i])) {
+   ret = PTR_ERR(hdmi->di_sel[i]);
+ 

[PATCH 58/72] imx-drm: parallel-display: Add interface-pix-map DT property

2014-10-31 Thread Steve Longerbeam
Define a new devicetree property "interface-pix-map" for use by
i.MX DRM display drivers. This property defines a DI interface
pixel bus mapping. Implement the parsing of this property in the
parallel display driver, and pass on the mapping to
imx_drm_panel_format().

See Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
for a complete description of this property.

Signed-off-by: Steve Longerbeam 
---
 .../bindings/staging/imx-drm/fsl-imx-drm.txt   |   43 ++--
 drivers/staging/imx-drm/parallel-display.c |   25 +++-
 2 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt 
b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
index e75f0e5..a9146f8 100644
--- a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+++ b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
@@ -59,9 +59,26 @@ Parallel display support
 Required properties:
 - compatible: Should be "fsl,imx-parallel-display"
 Optional properties:
-- interface_pix_fmt: How this display is connected to the
-  display interface. Currently supported types: "rgb24", "rgb565", "bgr666"
-  and "lvds666".
+- interface-pix-map: Defines a pixel mapping onto the 24-bit IPU
+  Display Interface bus to the display. Internally the IPU represents
+  pixels in either RGB24 or YUV444 format. This property tells the IPU how
+  to map those RGB24 or YUV444 pixels onto the display interface bus.
+  The data format is as follows:
+
+  interface-pix-map = ;
+
+  where:
+   c0, c1, c2: are the color components (c0 = B/V, c1 = G/U, c2 = R/Y)
+   src-mask: is the mask of component source bits to be forwarded
+ to the DI bus
+   dest-msb: defines where to place those component bits on the
+ 24-bit DI bus, represented as the MSBit on the bus.
+
+- interface-pix-fmt: A name given to the pixel format sent to the display.
+  The following are names with pre-defined pixel mappings that do not
+  require an explicit interface-pix-map property: "rgb24", "rgb565", "rgb666"
+
 - edid: verbatim EDID data block describing attached display.
 - ddc: phandle describing the i2c bus handling the display data
   channel
@@ -81,3 +98,23 @@ display at di0 {
};
};
 };
+
+Pixel map examples:
+
+This example defines a new format named "bgr565" using a pixel map:
+
+display at di0 {
+   compatible = "fsl,imx-parallel-display";
+   edid = [edid-data];
+   interface-pix-fmt = "bgr565";
+   interface-pix-map = <15 0xf8 10 0xfc 4 0xf8>;
+};
+
+This example defines an unnamed format where an rgb666 format is shifted
+up by 6 bits on the DI bus:
+
+display at di0 {
+   compatible = "fsl,imx-parallel-display";
+   edid = [edid-data];
+   interface-pix-map = <11 0xfc 17 0xfc 23 0xfc>;
+};
diff --git a/drivers/staging/imx-drm/parallel-display.c 
b/drivers/staging/imx-drm/parallel-display.c
index 667a9b3..e0b0b56 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 

 #include "imx-drm.h"

@@ -39,6 +40,7 @@ struct imx_parallel_display {
void *edid;
int edid_len;
u32 interface_pix_fmt;
+   struct ipu_dc_if_map *interface_map;
int mode_valid;
struct drm_display_mode mode;
struct drm_panel *panel;
@@ -123,7 +125,8 @@ static void imx_pd_encoder_prepare(struct drm_encoder 
*encoder)
 {
struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);

-   imx_drm_panel_format(encoder, imxpd->interface_pix_fmt, NULL);
+   imx_drm_panel_format(encoder, imxpd->interface_pix_fmt,
+imxpd->interface_map);
 }

 static void imx_pd_encoder_commit(struct drm_encoder *encoder)
@@ -208,8 +211,9 @@ static int imx_pd_bind(struct device *dev, struct device 
*master, void *data)
struct device_node *panel_node;
const u8 *edidp;
struct imx_parallel_display *imxpd;
-   int ret;
+   struct ipu_dc_if_map interface_map;
const char *fmt;
+   int ret;

imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
if (!imxpd)
@@ -239,6 +243,23 @@ static int imx_pd_bind(struct device *dev, struct device 
*master, void *data)
}
}

+   ret = of_property_read_u32_array(np, "interface-pix-map",
+(u32 *)_map,
+sizeof(interface_map) / sizeof(u32));
+   if (!ret) {
+   imxpd->interface_map =
+   devm_kmalloc(dev, sizeof(imxpd->interface_map),
+GFP_KERNEL);
+   if (!imxpd->interface_map)
+   return -ENOMEM;
+   *imxpd->interface_map = interface_map;
+   }
+
+   if (!imxpd->interface_pix_fmt && 

[PATCH 57/72] imx-drm: Add support for interface pixel maps

2014-10-31 Thread Steve Longerbeam
Adds the framework that allows encoder/connector drivers to create
a new interface pixel mapping passed to imx_drm_panel_format(). The
crtc driver will then pass this pointer on to ipu_dc_init_sync() which
sets up the new mapping in the DC.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |   19 ++-
 drivers/staging/imx-drm/imx-drm.h  |   12 +---
 drivers/staging/imx-drm/imx-hdmi.c |3 +--
 drivers/staging/imx-drm/imx-ldb.c  |2 +-
 drivers/staging/imx-drm/imx-tve.c  |5 ++---
 drivers/staging/imx-drm/ipuv3-crtc.c   |   11 ---
 drivers/staging/imx-drm/ipuv3-plane.c  |2 +-
 drivers/staging/imx-drm/parallel-display.c |2 +-
 8 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index 4c85fd3..b31d291 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -136,7 +136,9 @@ static struct imx_drm_crtc *imx_drm_find_crtc_by_id(struct 
drm_device *drm,
 }

 int imx_drm_panel_format_pins(struct drm_encoder *encoder,
-   u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
+ u32 interface_pix_fmt,
+ struct ipu_dc_if_map *interface_pix_map,
+ int hsync_pin, int vsync_pin)
 {
struct imx_drm_crtc_helper_funcs *helper;
struct imx_drm_crtc *imx_crtc;
@@ -148,15 +150,22 @@ int imx_drm_panel_format_pins(struct drm_encoder *encoder,
helper = _crtc->imx_drm_helper_funcs;
if (helper->set_interface_pix_fmt)
return helper->set_interface_pix_fmt(encoder->crtc,
-   encoder->encoder_type, interface_pix_fmt,
-   hsync_pin, vsync_pin);
+encoder->encoder_type,
+interface_pix_fmt,
+interface_pix_map,
+hsync_pin, vsync_pin);
return 0;
 }
 EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);

-int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
+int imx_drm_panel_format(struct drm_encoder *encoder,
+u32 interface_pix_fmt,
+struct ipu_dc_if_map *interface_pix_map)
 {
-   return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
+   return imx_drm_panel_format_pins(encoder,
+interface_pix_fmt,
+interface_pix_map,
+2, 3);
 }
 EXPORT_SYMBOL_GPL(imx_drm_panel_format);

diff --git a/drivers/staging/imx-drm/imx-drm.h 
b/drivers/staging/imx-drm/imx-drm.h
index 0bb4735..24b889a 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -1,6 +1,8 @@
 #ifndef _IMX_DRM_H_
 #define _IMX_DRM_H_

+#include 
+
 struct device_node;
 struct drm_crtc;
 struct drm_connector;
@@ -20,7 +22,8 @@ struct imx_drm_crtc_helper_funcs {
int (*enable_vblank)(struct drm_crtc *crtc, int pipe);
void (*disable_vblank)(struct drm_crtc *crtc, int pipe);
int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
-   u32 pix_fmt, int hsync_pin, int vsync_pin);
+u32 pix_fmt, struct ipu_dc_if_map *pix_map,
+int hsync_pin, int vsync_pin);
int (*gamma_set)(struct drm_crtc *crtc, bool enable, u32 *m, u32 *b);
const struct drm_crtc_helper_funcs *crtc_helper_funcs;
const struct drm_crtc_funcs *crtc_funcs;
@@ -41,9 +44,12 @@ void imx_drm_mode_config_init(struct drm_device *drm);
 struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);

 int imx_drm_panel_format_pins(struct drm_encoder *encoder,
-   u32 interface_pix_fmt, int hsync_pin, int vsync_pin);
+ u32 interface_pix_fmt,
+ struct ipu_dc_if_map *interface_pix_map,
+ int hsync_pin, int vsync_pin);
 int imx_drm_panel_format(struct drm_encoder *encoder,
-   u32 interface_pix_fmt);
+u32 interface_pix_fmt,
+struct ipu_dc_if_map *interface_pix_map);

 int imx_drm_encoder_get_mux_id(struct device_node *node,
struct drm_encoder *encoder);
diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index db3906f..4ef1c0a 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -27,7 +27,6 @@
 #include 
 #include 
 #include 
-#include 

 #include "imx-hdmi.h"
 #include "imx-drm.h"
@@ -1455,7 +1454,7 @@ static void imx_hdmi_encoder_prepare(struct 

[PATCH 56/72] imx-drm: Implement custom ioctl to set gamma

2014-10-31 Thread Steve Longerbeam
Implement i.MX specific ioctl to set gamma directly using slope and
y-intercept values that define the piecewise linear gamma correction
curve.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |   40 +++-
 drivers/staging/imx-drm/imx-drm.h  |3 +--
 drivers/staging/imx-drm/ipuv3-crtc.c   |9 +++
 include/uapi/drm/imx_drm.h |   30 
 4 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 include/uapi/drm/imx_drm.h

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index 084ed53..4c85fd3 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 

 #include "imx-drm.h"

@@ -122,6 +123,18 @@ static struct imx_drm_crtc *imx_drm_find_crtc(struct 
drm_crtc *crtc)
return NULL;
 }

+static struct imx_drm_crtc *imx_drm_find_crtc_by_id(struct drm_device *drm,
+   u32 crtc_id)
+{
+   struct drm_crtc *crtc;
+
+   crtc = drm_crtc_find(drm, crtc_id);
+   if (!crtc)
+   return NULL;
+
+   return imx_drm_find_crtc(crtc);
+}
+
 int imx_drm_panel_format_pins(struct drm_encoder *encoder,
u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
 {
@@ -537,8 +550,33 @@ int imx_drm_encoder_get_mux_id(struct device_node *node,
 }
 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);

+static int drm_imx_set_gamma_ioctl(struct drm_device *drm, void *data,
+  struct drm_file *file_priv)
+{
+   struct drm_imx_gamma *g = data;
+   struct imx_drm_crtc_helper_funcs *helper;
+   struct imx_drm_crtc *imx_crtc;
+   int ret = -EINVAL;
+
+   if (!drm_core_check_feature(drm, DRIVER_MODESET))
+   return -ENODEV;
+
+   drm_modeset_lock_all(drm);
+
+   imx_crtc = imx_drm_find_crtc_by_id(drm, g->crtc_id);
+   if (!imx_crtc)
+   goto out_unlock;
+
+   helper = _crtc->imx_drm_helper_funcs;
+   ret = helper->gamma_set(imx_crtc->crtc, g->enable, g->m, g->b);
+
+out_unlock:
+   drm_modeset_unlock_all(drm);
+   return ret;
+}
+
 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
-   /* none so far */
+   DRM_IOCTL_DEF_DRV(IMX_SET_GAMMA, drm_imx_set_gamma_ioctl, DRM_AUTH),
 };

 static struct drm_driver imx_drm_driver = {
diff --git a/drivers/staging/imx-drm/imx-drm.h 
b/drivers/staging/imx-drm/imx-drm.h
index bf6b06b..0bb4735 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -21,6 +21,7 @@ struct imx_drm_crtc_helper_funcs {
void (*disable_vblank)(struct drm_crtc *crtc, int pipe);
int (*set_interface_pix_fmt)(struct drm_crtc *crtc, u32 encoder_type,
u32 pix_fmt, int hsync_pin, int vsync_pin);
+   int (*gamma_set)(struct drm_crtc *crtc, bool enable, u32 *m, u32 *b);
const struct drm_crtc_helper_funcs *crtc_helper_funcs;
const struct drm_crtc_funcs *crtc_funcs;
 };
@@ -52,6 +53,4 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
 void imx_drm_connector_destroy(struct drm_connector *connector);
 void imx_drm_encoder_destroy(struct drm_encoder *encoder);

-#define DRM_IMX_GAMMA_SIZE 16
-
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 4f2ba40..8d7c998 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 

 #include 
 #include "imx-drm.h"
@@ -405,10 +406,18 @@ static int ipu_set_interface_pix_fmt(struct drm_crtc 
*crtc, u32 encoder_type,
return 0;
 }

+static int ipu_gamma_set(struct drm_crtc *crtc, bool enable, u32 *m, u32 *b)
+{
+   struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+
+   return ipu_plane_gamma_set(_crtc->plane[0], true, m, b);
+}
+
 static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
.enable_vblank = ipu_enable_vblank,
.disable_vblank = ipu_disable_vblank,
.set_interface_pix_fmt = ipu_set_interface_pix_fmt,
+   .gamma_set = ipu_gamma_set,
.crtc_funcs = _crtc_funcs,
.crtc_helper_funcs = _helper_funcs,
 };
diff --git a/include/uapi/drm/imx_drm.h b/include/uapi/drm/imx_drm.h
new file mode 100644
index 000..b0a03d6
--- /dev/null
+++ b/include/uapi/drm/imx_drm.h
@@ -0,0 +1,30 @@
+/*
+ * include/uapi/drm/imx_drm.h
+ *
+ * Copyright (C) 2013-2014 Mentor Graphics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __IMX_DRM_H__
+#define __IMX_DRM_H__
+
+#include 
+
+#define DRM_IMX_GAMMA_SIZE 16
+struct drm_imx_gamma {
+   bool enable;
+   uint32_t 

[PATCH 55/72] imx-drm: Implement DRM gamma set

2014-10-31 Thread Steve Longerbeam
Implement the DRM gamma set API. This API expects that the adapter
will use a gamma-corrected CLUT, but the CLUT on i.MX6 is insufficient
for that purpose.

But the i.MX6 does support gamma correction via a set of registers
that define a piecewise linear approximation to a luminance
gamma correction curve, which is what this implementation uses.

The input gamma-corrected luminance values to ipu_drm_gamma_set() must
be in a specific format defined in the i.MX6 reference manual.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |3 +-
 drivers/staging/imx-drm/imx-drm.h  |2 +
 drivers/staging/imx-drm/ipuv3-crtc.c   |   85 
 drivers/staging/imx-drm/ipuv3-plane.c  |   10 
 drivers/staging/imx-drm/ipuv3-plane.h  |3 ++
 5 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index e0178d6..084ed53 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -387,7 +387,8 @@ int imx_drm_add_crtc(struct drm_device *drm, struct 
drm_crtc *crtc,

*new_crtc = imx_drm_crtc;

-   ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
+   ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc,
+  DRM_IMX_GAMMA_SIZE);
if (ret)
goto err_register;

diff --git a/drivers/staging/imx-drm/imx-drm.h 
b/drivers/staging/imx-drm/imx-drm.h
index ec084fe..bf6b06b 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -52,4 +52,6 @@ int imx_drm_encoder_parse_of(struct drm_device *drm,
 void imx_drm_connector_destroy(struct drm_connector *connector);
 void imx_drm_encoder_destroy(struct drm_encoder *encoder);

+#define DRM_IMX_GAMMA_SIZE 16
+
 #endif /* _IMX_DRM_H_ */
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 3040f8e..4f2ba40 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -171,10 +171,95 @@ static int ipu_crtc_page_flip(struct drm_crtc *crtc,
return ipu_plane_page_flip(crtc->primary, fb, event, page_flip_flags);
 }

+/*
+ * Normally the DRM Gamma API is used to program a color LUT that contains
+ * gamma-corrected pixel values for red, green, and blue input pixel values
+ * (normally in the range 0 to 255).
+ *
+ * However the i.MX6 LUT is only 256 entries, so it only supports 8 bpp
+ * indexed pixel format. Therefore if the i.MX6 LUT were used to implement
+ * gamma correction, th DRM framebuffer would have to use 8 bpp indexed pixel
+ * format which is insufficient for most use cases. To support a gamma
+ * correcting LUT with full RGB24 or YUV444 pixel formats, there would have
+ * to be 3 separate 256-entry LUTs for each color component.
+ *
+ * But the i.MX6 does support gamma correction via a set of registers that
+ * define a piecewise linear approximation to a luminance gamma correction
+ * curve. This function uses this approach.
+ *
+ * The input pixel values to this function must be in a specific format
+ * according to the i.MX6 reference manual (see Table 37-28 in the
+ * Rev. 1 TRM, dated 04/2013). This info is reprinted here:
+ *
+ * "The required Gamma correction slope for a specific display should be
+ * provided by the display manufacture. This information can be provided
+ * in various forms, as graph or formula. The gamma correction input pixel
+ * level (Gin) should be normalized to a maximum of 383. The gamma correction
+ * output pixel level (Gout) should be normalized to a maximum of 255. Then
+ * the following data should be collected:
+ *
+ * Table 37-28. Gamma correction values
+ *   Gin   Gout
+ *   ---   -
+ * 0   Gout0
+ * 2   Gout1
+ * 4   Gout2
+ * 8   Gout3
+ *16   Gout4
+ *32   Gout5
+ *64   Gout6
+ *96   Gout7
+ *   128   Gout8
+ *   160   Gout9
+ *   192   Gout10
+ *   224   Gout11
+ *   256   Gout12
+ *   288   Gout13
+ *   320   Gout14
+ *   352   Gout15"
+ *
+ *
+ * The 16 Gout values must be placed in the input lum[] array. The green
+ * and blue input arrays are ignored.
+ *
+ * The gamma register values are then computed according to Table 37-29
+ * in the Rev. 1 TRM.
+ */
+static void ipu_crtc_gamma_set(struct drm_crtc *crtc,
+  u16 *lum, u16 *g_unused, u16 *b_unused,
+  uint32_t start, uint32_t size)
+{
+   struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
+   u32 m[DRM_IMX_GAMMA_SIZE], b[DRM_IMX_GAMMA_SIZE];
+   int i;
+
+   if (size != DRM_IMX_GAMMA_SIZE)
+   return;
+
+   for (i = 0; i < size; i++) {
+   if (i == 0) {
+   b[0] = lum[0];
+   m[0] = 16 * (lum[1] - lum[0]);
+   } else if (i == 15) {
+   b[15] = lum[15];
+   m[15] = 255 - 

[PATCH 54/72] imx-drm: ipuv3-plane: Assign page_flip method to drm_plane_funcs

2014-10-31 Thread Steve Longerbeam
Assign ipu_plane_page_flip to new drm_plane_funcs->page_flip method.
This allows page flip operation in both the primary and overlay planes.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 3a1ebfe..3293e84 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -555,6 +555,7 @@ static struct drm_plane_funcs ipu_plane_funcs = {
.disable_plane  = ipu_disable_plane,
.destroy= ipu_plane_destroy,
.set_property   = ipu_plane_set_property,
+   .page_flip  = ipu_plane_page_flip,
 };

 int ipu_plane_init(struct ipu_plane *ipu_plane, struct drm_device *drm,
-- 
1.7.9.5



[PATCH 53/72] drm: implement page flipping support for planes

2014-10-31 Thread Steve Longerbeam
Planes like crtcs would benefit from having page flip event support.
With planes page flip it is now possible to synchronize changing a
framebuffer used by an overlay (or even cursor) plane with vertical
sync events.

A page flip in the primary plane is equivalent to a crtc page flip,
which suggests this ioctl could deprecate the crtc page flip ioctl
at some point in the future.

Signed-off-by: Steve Longerbeam 
Signed-off-by: Dmitry Eremin-Solenikov 
---
 drivers/gpu/drm/drm_crtc.c  |  241 +--
 drivers/gpu/drm/drm_ioctl.c |1 +
 include/drm/drm_crtc.h  |   11 ++
 include/uapi/drm/drm.h  |1 +
 include/uapi/drm/drm_mode.h |8 ++
 5 files changed, 164 insertions(+), 98 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e79c8d3..53b5f87 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2445,6 +2445,142 @@ int drm_mode_setplane(struct drm_device *dev, void 
*data,
 plane_req->src_w, plane_req->src_h);
 }

+int drm_mode_plane_page_flip_ioctl(struct drm_device *dev,
+  void *data, struct drm_file *file_priv)
+{
+   struct drm_mode_plane_page_flip *page_flip = data;
+   struct drm_plane *plane;
+   struct drm_crtc *crtc;
+   struct drm_framebuffer *fb = NULL;
+   struct drm_pending_vblank_event *e = NULL;
+   unsigned long flags;
+   bool is_primary;
+   int ret;
+
+   if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
+   page_flip->reserved != 0)
+   return -EINVAL;
+
+   if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) &&
+   !dev->mode_config.async_page_flip)
+   return -EINVAL;
+
+   plane = drm_plane_find(dev, page_flip->plane_id);
+   if (!plane)
+   return -ENOENT;
+
+   is_primary = (plane->type == DRM_PLANE_TYPE_PRIMARY);
+
+   drm_modeset_lock_all(dev);
+
+   if (plane->crtc == NULL || plane->fb == NULL) {
+   /* The crtc and/or framebuffer is currently unbound,
+* presumably due to a hotplug event, that userspace
+* has not yet discovered.
+*/
+   ret = -EBUSY;
+   goto out;
+   }
+   crtc = plane->crtc;
+
+   if ((is_primary && crtc->funcs->page_flip == NULL) ||
+   plane->funcs->page_flip == NULL) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
+   if (!fb) {
+   ret = -ENOENT;
+   goto out;
+   }
+
+   /*
+* If this is the primary plane (equivalent to a crtc page flip),
+* verify that the fb is valid for the bound crtc's viewport.
+* For overlay or cursor planes, the plane's page_flip op should
+* check that the fb is valid.
+*/
+   if (is_primary) {
+   ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y,
+ >mode, fb);
+   if (ret)
+   goto out;
+   }
+
+   if (plane->fb->pixel_format != fb->pixel_format) {
+   DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer 
format.\n");
+   ret = -EINVAL;
+   goto out;
+   }
+
+   if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+   ret = -ENOMEM;
+   spin_lock_irqsave(>event_lock, flags);
+   if (file_priv->event_space < sizeof(e->event)) {
+   spin_unlock_irqrestore(>event_lock, flags);
+   goto out;
+   }
+   file_priv->event_space -= sizeof(e->event);
+   spin_unlock_irqrestore(>event_lock, flags);
+
+   e = kzalloc(sizeof(*e), GFP_KERNEL);
+   if (e == NULL) {
+   spin_lock_irqsave(>event_lock, flags);
+   file_priv->event_space += sizeof(e->event);
+   spin_unlock_irqrestore(>event_lock, flags);
+   goto out;
+   }
+
+   e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
+   e->event.base.length = sizeof(e->event);
+   e->event.user_data = page_flip->user_data;
+   e->base.event = >event.base;
+   e->base.file_priv = file_priv;
+   e->base.destroy =
+   (void (*) (struct drm_pending_event *)) kfree;
+   }
+
+   plane->old_fb = plane->fb;
+
+   /* for now use crtc page_flip op, if this is the primary plane */
+   if (is_primary)
+   ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
+   else
+   ret = plane->funcs->page_flip(plane, fb, e, page_flip->flags);
+
+   if (ret) {
+   if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+   

[PATCH 52/72] imx-drm: Reset ipu unit pointers to NULL on errors

2014-10-31 Thread Steve Longerbeam
In the crtc and plane drivers it is possible the ipu unit pointers
could be left at error pointer values. Reset them to NULL on errors
to prevent this. Also ipu_put_resources() should reset the units to
NULL after releasing them.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-crtc.c  |   11 +--
 drivers/staging/imx-drm/ipuv3-plane.c |   15 ---
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 423b004..3040f8e 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -375,13 +375,18 @@ dev_put:

 static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
 {
-   if (!IS_ERR_OR_NULL(ipu_crtc->dc))
+   if (!IS_ERR_OR_NULL(ipu_crtc->dc)) {
ipu_dc_put(ipu_crtc->dc);
-   if (!IS_ERR_OR_NULL(ipu_crtc->di))
+   ipu_crtc->dc = NULL;
+   }
+   if (!IS_ERR_OR_NULL(ipu_crtc->di)) {
ipu_di_put(ipu_crtc->di);
+   ipu_crtc->di = NULL;
+   }
if (!IS_ERR_OR_NULL(ipu_crtc->ipu_dev)) {
module_put(ipu_crtc->ipu_dev->driver->owner);
put_device(ipu_crtc->ipu_dev);
+   ipu_crtc->ipu_dev = NULL;
}
 }

@@ -411,6 +416,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
ipu_crtc->di = ipu_di_get(ipu_crtc->ipu, di);
if (IS_ERR(ipu_crtc->di)) {
ret = PTR_ERR(ipu_crtc->di);
+   ipu_crtc->di = NULL;
goto err_out;
}

@@ -425,6 +431,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
ipu_crtc->dc = ipu_dc_get(ipu_crtc->ipu, ipu_crtc->ch->dc);
if (IS_ERR(ipu_crtc->dc)) {
ret = PTR_ERR(ipu_crtc->dc);
+   ipu_crtc->dc = NULL;
goto err_out;
}

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 76ac178..3a1ebfe 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -285,12 +285,18 @@ void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
  ipu_plane->irq, ipu_plane);
ipu_plane->irq = 0;
}
-   if (!IS_ERR_OR_NULL(ipu_plane->dp))
+   if (!IS_ERR_OR_NULL(ipu_plane->dp)) {
ipu_dp_put(ipu_plane->dp);
-   if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
+   ipu_plane->dp = NULL;
+   }
+   if (!IS_ERR_OR_NULL(ipu_plane->dmfc)) {
ipu_dmfc_put(ipu_plane->dmfc);
-   if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
+   ipu_plane->dmfc = NULL;
+   }
+   if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch)) {
ipu_idmac_put(ipu_plane->ipu_ch);
+   ipu_plane->ipu_ch = NULL;
+   }
 }

 int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
@@ -300,6 +306,7 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
if (IS_ERR(ipu_plane->ipu_ch)) {
ret = PTR_ERR(ipu_plane->ipu_ch);
+   ipu_plane->ipu_ch = NULL;
DRM_ERROR("failed to get idmac channel: %d\n", ret);
return ret;
}
@@ -307,6 +314,7 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
if (IS_ERR(ipu_plane->dmfc)) {
ret = PTR_ERR(ipu_plane->dmfc);
+   ipu_plane->dmfc = NULL;
DRM_ERROR("failed to get dmfc: ret %d\n", ret);
goto err_out;
}
@@ -315,6 +323,7 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
if (IS_ERR(ipu_plane->dp)) {
ret = PTR_ERR(ipu_plane->dp);
+   ipu_plane->dp = NULL;
DRM_ERROR("failed to get dp flow: %d\n", ret);
goto err_out;
}
-- 
1.7.9.5



[PATCH 51/72] imx-drm: Move page flip handling to plane driver

2014-10-31 Thread Steve Longerbeam
Move page flip handling and associated vblank handling to the
plane driver. This paves the way to allow page flipping in not
just the primary plane but the overlay plane as well.

To do this the primary and overlay planes are assigned a pipe value
suitable for passing to the drm core vblank methods (drm_vblank_get,
put,handle).

We modify imx-drm core slightly to make room for primary and overlay
pipe id's when assigning the crtc pipe. So crtc 0 has a primary pipe
value of 0 and overlay pipe value 1, crtc 1 has primary pipe value 2
and overlay pipe value 3, etc. imx_drm_crtc_id() returns the primary
pipe divided by 2 as an id value to form possible crtc masks.

The drm core vblank sees these planes as additional crtcs (pipes) and
does not need significant changes.

The plane driver implements page flip using idmac double-buffering.
Without double-buffering, a page flip operation changes the idmac
channel buffer base address while the buffer is still active. This
is not recommended according to the reference manual.

With double-buffering, a page-flip can set the base of the inactive
buffer before switching to it using buffer-ready control.

Note that for the synchronous display channels, the buffer ready signal can
be driven either by the ARM core writing to the buffer ready registers,
or by the DI.

When the ARM core does not drive ping-pong buffer ready selection at
every EOF, the DI will drive buffer ready, triggered by a timer located
in the DI. The IPU's FSU unit will quickly settle on a single buffer and
then remain at that buffer, the DI driving buffer ready at that buffer.

If the ARM core (the plane driver) then selects the other (inactive)
buffer, the FSU switches to it and then remains at this buffer, the DI
again taking over buffer ready signalling at the new buffer, until the
ARM core makes the next buffer selection.

So we take advantage of this behaviour and use buffer selection to
switch to the other buffer when we want to flip to another DRM
framebuffer for page-flip.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |   86 +
 drivers/staging/imx-drm/imx-drm.h  |   10 +-
 drivers/staging/imx-drm/ipuv3-crtc.c   |  111 --
 drivers/staging/imx-drm/ipuv3-plane.c  |  158 
 drivers/staging/imx-drm/ipuv3-plane.h  |   21 -
 5 files changed, 252 insertions(+), 134 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index 59200ff..e0178d6 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -28,6 +28,7 @@
 #include "imx-drm.h"

 #define MAX_CRTC   4
+#define MAX_PIPES  (2 * MAX_CRTC)

 struct imx_drm_crtc;

@@ -53,12 +54,29 @@ struct imx_drm_crtc {
 static int legacyfb_depth = 16;
 module_param(legacyfb_depth, int, 0444);

+static inline int pipe_to_crtc_id(int pipe)
+{
+   return pipe >> 1;
+}
+
 int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
 {
-   return crtc->pipe;
+   return pipe_to_crtc_id(crtc->pipe);
 }
 EXPORT_SYMBOL_GPL(imx_drm_crtc_id);

+int imx_drm_primary_plane_pipe(struct imx_drm_crtc *crtc)
+{
+   return crtc->pipe;
+}
+EXPORT_SYMBOL_GPL(imx_drm_primary_plane_pipe);
+
+int imx_drm_overlay_plane_pipe(struct imx_drm_crtc *crtc)
+{
+   return crtc->pipe + 1;
+}
+EXPORT_SYMBOL_GPL(imx_drm_overlay_plane_pipe);
+
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
 #if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
@@ -129,30 +147,16 @@ int imx_drm_panel_format(struct drm_encoder *encoder, u32 
interface_pix_fmt)
 }
 EXPORT_SYMBOL_GPL(imx_drm_panel_format);

-int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
-{
-   return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
-}
-EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
-
-void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
-{
-   drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
-}
-EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
-
-void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
-{
-   drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
-}
-EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
-
-static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
+static int imx_drm_enable_vblank(struct drm_device *drm, int pipe)
 {
struct imx_drm_device *imxdrm = drm->dev_private;
-   struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
+   struct imx_drm_crtc *imx_drm_crtc;
int ret;

+   if (pipe >= MAX_PIPES)
+   return -EINVAL;
+
+   imx_drm_crtc = imxdrm->crtc[pipe_to_crtc_id(pipe)];
if (!imx_drm_crtc)
return -EINVAL;

@@ -160,35 +164,40 @@ static int imx_drm_enable_vblank(struct drm_device *drm, 
int crtc)
return -ENOSYS;

ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(
-   imx_drm_crtc->crtc);
+   

[PATCH 50/72] imx-drm: Fix separate primary plane objects

2014-10-31 Thread Steve Longerbeam
drm_crtc_init() will create a primary plane object, while imx-drm also
creates its own, thus two primary planes are separately created, and
can cause difficult bugs to track down in the future.

Fix by using drm_crtc_init_with_planes() instead of drm_crtc_init(),
so that we can hand drm our own primary plane object, thus crtc->primary
and ipu_crtc->plane[0].base now are the same object.

To do this we need to statically declare the primary and overlay
planes in the crtc driver, to avoid a chicken-before-the-egg problem,
the primary plane must exist when imx_drm_add_crtc() is called but
before ipu_plane_init().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |3 +-
 drivers/staging/imx-drm/imx-drm.h  |1 +
 drivers/staging/imx-drm/ipuv3-crtc.c   |   54 ++--
 drivers/staging/imx-drm/ipuv3-plane.c  |   32 +--
 drivers/staging/imx-drm/ipuv3-plane.h  |6 ++--
 5 files changed, 45 insertions(+), 51 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index e5ec010..59200ff 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -342,6 +342,7 @@ err_kms:
  * imx_drm_add_crtc - add a new crtc
  */
 int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
+   struct drm_plane *primary,
struct imx_drm_crtc **new_crtc,
const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
struct device_node *port)
@@ -380,7 +381,7 @@ int imx_drm_add_crtc(struct drm_device *drm, struct 
drm_crtc *crtc,
drm_crtc_helper_add(crtc,
imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);

-   drm_crtc_init(drm, crtc,
+   drm_crtc_init_with_planes(drm, crtc, primary, NULL,
imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);

return 0;
diff --git a/drivers/staging/imx-drm/imx-drm.h 
b/drivers/staging/imx-drm/imx-drm.h
index 7453ae0..3a30f16 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -24,6 +24,7 @@ struct imx_drm_crtc_helper_funcs {
 };

 int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
+   struct drm_plane *primary,
struct imx_drm_crtc **new_crtc,
const struct imx_drm_crtc_helper_funcs *imx_helper_funcs,
struct device_node *port);
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 5a60017..593261f 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -84,7 +84,8 @@ struct ipu_crtc {
const struct ipu_channels *ch;

/* plane[0] is the full plane, plane[1] is the partial plane */
-   struct ipu_plane*plane[2];
+   struct ipu_planeplane[2];
+   boolhave_overlay; /* we have a partial plane */

struct ipu_dc   *dc;
struct ipu_di   *di;
@@ -106,7 +107,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
return;

ipu_dc_enable(ipu_crtc->dc);
-   ipu_plane_enable(ipu_crtc->plane[0]);
+   ipu_plane_enable(_crtc->plane[0]);
/* Start DC channel and DI after IDMAC */
ipu_dc_enable_channel(ipu_crtc->dc);
ipu_di_enable(ipu_crtc->di);
@@ -123,7 +124,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
/* Stop DC channel and DI before IDMAC */
ipu_dc_disable_channel(ipu_crtc->dc);
ipu_di_disable(ipu_crtc->di);
-   ipu_plane_disable(ipu_crtc->plane[0]);
+   ipu_plane_disable(_crtc->plane[0]);
ipu_dc_disable(ipu_crtc->dc);
ipu_di_disable_clock(ipu_crtc->di);

@@ -241,7 +242,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
return ret;
}

-   return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode,
+   return ipu_plane_mode_set(_crtc->plane[0], crtc, mode,
  crtc->primary->fb,
  0, 0, mode->hdisplay, mode->vdisplay,
  x, y, mode->hdisplay, mode->vdisplay);
@@ -267,7 +268,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
imx_drm_handle_vblank(ipu_crtc->imx_crtc);

if (ipu_crtc->newfb) {
-   struct ipu_plane *plane = ipu_crtc->plane[0];
+   struct ipu_plane *plane = _crtc->plane[0];

ipu_crtc->newfb = NULL;
ipu_plane_set_base(plane, ipu_crtc->base.primary->fb,
@@ -474,20 +475,27 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
return ret;
}

-   ret = imx_drm_add_crtc(drm, _crtc->base, _crtc->imx_crtc,
-  _crtc_helper_funcs, ipu_crtc->port);
+   ret = imx_drm_add_crtc(drm, _crtc->base, _crtc->plane[0].base,
+  

[PATCH 49/72] imx-drm: imx-ldb: Add DDC support

2014-10-31 Thread Steve Longerbeam
Add support for reading EDID over Display Data Channel. If no DDC
adapter is available, falls back to hardcoded EDID or display-timings
node as before.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-ldb.c |   39 +
 1 file changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-ldb.c 
b/drivers/staging/imx-drm/imx-ldb.c
index 1eb632f..6c16cf2 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -61,6 +61,7 @@ struct imx_ldb_channel {
struct drm_connector connector;
struct drm_encoder encoder;
struct device_node *child;
+   struct i2c_adapter *ddc;
int chno;
void *edid;
int edid_len;
@@ -103,6 +104,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector 
*connector)

imx_ldb_entry_dbg(imx_ldb_ch);

+   if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
+   imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
+
if (imx_ldb_ch->edid) {
drm_mode_connector_update_edid_property(connector,
imx_ldb_ch->edid);
@@ -529,6 +533,7 @@ static int imx_ldb_bind(struct device *dev, struct device 
*master, void *data)

for_each_child_of_node(np, child) {
struct imx_ldb_channel *channel;
+   struct device_node *ddc_node;

ret = of_property_read_u32(child, "reg", );
if (ret || i < 0 || i > 1)
@@ -547,14 +552,30 @@ static int imx_ldb_bind(struct device *dev, struct device 
*master, void *data)
channel->chno = i;
channel->child = child;

-   edidp = of_get_property(child, "edid", >edid_len);
-   if (edidp) {
-   channel->edid = kmemdup(edidp, channel->edid_len,
-   GFP_KERNEL);
-   } else {
-   ret = of_get_drm_display_mode(child, >mode, 0);
-   if (!ret)
-   channel->mode_valid = 1;
+   ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
+   if (ddc_node) {
+   channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
+   of_node_put(ddc_node);
+   }
+
+   if (!channel->ddc) {
+   /* if no DDC available, fallback to hardcoded EDID */
+   dev_dbg(dev, "no ddc available\n");
+
+   edidp = of_get_property(child, "edid",
+   >edid_len);
+   if (edidp) {
+   channel->edid = kmemdup(edidp,
+   channel->edid_len,
+   GFP_KERNEL);
+   } else {
+   /* fallback to display-timings node */
+   ret = of_get_drm_display_mode(child,
+ >mode,
+ 0);
+   if (!ret)
+   channel->mode_valid = 1;
+   }
}

ret = of_property_read_u32(child, "fsl,data-width", );
@@ -616,6 +637,8 @@ static void imx_ldb_unbind(struct device *dev, struct 
device *master,

channel->connector.funcs->destroy(>connector);
channel->encoder.funcs->destroy(>encoder);
+
+   i2c_put_adapter(channel->ddc);
}
 }

-- 
1.7.9.5



[PATCH 48/72] imx-drm: hdmi: rework irq request/free

2014-10-31 Thread Steve Longerbeam
Rearrange how HDMI driver requests and frees irq. Currently the driver
has two problems:

1) if imx_hdmi_register() fails, irq still can trigger and cause oops
2) irq is enabled too early, before all fields are initialized, so
triggered irq can cause oops.

Fix by moving irq request and activation to very end of imx_hdmi_bind(),
especially after imx_hdmi_register(). Then there's no possible way there
could be a (spurious) interrupt after a failed imx_hdmi_register() but
before the irq is freed.

Signed-off-by: Dmitry Eremin-Solenikov 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-hdmi.c |   33 +++--
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index 801a3eb..db3906f 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -122,6 +122,7 @@ struct imx_hdmi {

struct hdmi_data_info hdmi_data;
int vic;
+   int irq;

u8 edid[HDMI_EDID_LEN];
bool cable_plugin;
@@ -1593,7 +1594,7 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)
struct device_node *ddc_node;
struct imx_hdmi *hdmi;
struct resource *iores;
-   int ret, irq;
+   int ret;

hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
if (!hdmi)
@@ -1620,16 +1621,6 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)
dev_dbg(hdmi->dev, "no ddc property found\n");
}

-   irq = platform_get_irq(pdev, 0);
-   if (irq < 0)
-   return irq;
-
-   ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq,
-   imx_hdmi_irq, IRQF_SHARED,
-   dev_name(dev), hdmi);
-   if (ret)
-   return ret;
-
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdmi->regs = devm_ioremap_resource(dev, iores);
if (IS_ERR(hdmi->regs))
@@ -1685,6 +1676,10 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)
 */
hdmi_init_clk_regenerator(hdmi);

+   ret = imx_hdmi_register(drm, hdmi);
+   if (ret)
+   goto err_isfr;
+
/*
 * Configure registers related to HDMI interrupt
 * generation before registering IRQ.
@@ -1694,14 +1689,21 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)
/* Clear Hotplug interrupts */
hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);

-   ret = imx_hdmi_fb_registered(hdmi);
-   if (ret)
+   ret = platform_get_irq(pdev, 0);
+   if (ret < 0)
goto err_iahb;
+   hdmi->irq = ret;

-   ret = imx_hdmi_register(drm, hdmi);
+   ret = devm_request_threaded_irq(dev, hdmi->irq, imx_hdmi_hardirq,
+   imx_hdmi_irq, IRQF_SHARED,
+   dev_name(dev), hdmi);
if (ret)
goto err_iahb;

+   ret = imx_hdmi_fb_registered(hdmi);
+   if (ret)
+   goto err_irq;
+
/* Unmute interrupts */
hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);

@@ -1709,6 +1711,8 @@ static int imx_hdmi_bind(struct device *dev, struct 
device *master, void *data)

return 0;

+err_irq:
+   devm_free_irq(dev, hdmi->irq, hdmi);
 err_iahb:
clk_disable_unprepare(hdmi->iahb_clk);
 err_isfr:
@@ -1724,6 +1728,7 @@ static void imx_hdmi_unbind(struct device *dev, struct 
device *master,

/* Disable all interrupts */
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+   devm_free_irq(dev, hdmi->irq, hdmi);

hdmi->connector.funcs->destroy(>connector);
hdmi->encoder.funcs->destroy(>encoder);
-- 
1.7.9.5



[PATCH 47/72] imx-drm: ipuv3-plane: Implement global alpha and colorkey properties

2014-10-31 Thread Steve Longerbeam
Add support for setting global alpha and colorkey in foreground planes
using plane properties. Background planes can also support these
properties if the background plane is initialized as not private.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |  144 +++--
 drivers/staging/imx-drm/ipuv3-plane.h |7 ++
 2 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 5818249..1572c80 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -104,6 +104,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
   uint32_t src_w, uint32_t src_h)
 {
struct device *dev = ipu_plane->base.dev->dev;
+   bool is_bg = (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_BG);
int ret;

/* no scaling */
@@ -156,7 +157,6 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
ret);
return ret;
}
-   ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1);
break;
case IPU_DP_FLOW_SYNC_FG:
ipu_dp_setup_channel(ipu_plane->dp,
@@ -166,6 +166,24 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
break;
}

+   if (ipu_plane->dp) {
+   ret = ipu_dp_set_global_alpha(ipu_plane->dp,
+ ipu_plane->global_alpha_en,
+ ipu_plane->global_alpha, is_bg);
+   if (ret) {
+   dev_err(dev, "set global alpha failed with %d\n", ret);
+   return ret;
+   }
+
+   ret = ipu_dp_set_chroma_key(ipu_plane->dp,
+   ipu_plane->colorkey_en,
+   ipu_plane->colorkey);
+   if (ret) {
+   dev_err(dev, "set colorkey failed with %d\n", ret);
+   return ret;
+   }
+   }
+
ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
calc_bandwidth(crtc_w, crtc_h,
   calc_vref(mode)), crtc_w, 64);
@@ -329,13 +347,86 @@ static void ipu_plane_destroy(struct drm_plane *plane)
kfree(ipu_plane);
 }

+static int ipu_plane_set_global_alpha(struct ipu_plane *ipu_plane,
+ u32 global_alpha)
+{
+   bool is_bg = (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_BG);
+   bool global_alpha_en;
+
+   if (!ipu_plane->dp)
+   return -EINVAL;
+
+   global_alpha_en = ((global_alpha & (1 << 8)) != 0);
+   global_alpha &= ~(1 << 8);
+
+   if (ipu_plane->global_alpha_en == global_alpha_en &&
+   ipu_plane->global_alpha == global_alpha)
+   return 0;
+
+   ipu_plane->global_alpha_en = global_alpha_en;
+   ipu_plane->global_alpha = global_alpha;
+
+   if (!ipu_plane->enabled)
+   return 0;
+
+   return ipu_dp_set_global_alpha(ipu_plane->dp,
+  ipu_plane->global_alpha_en,
+  ipu_plane->global_alpha, is_bg);
+}
+
+static int ipu_plane_set_colorkey(struct ipu_plane *ipu_plane,
+ u32 colorkey)
+{
+   bool colorkey_en;
+
+   if (!ipu_plane->dp)
+   return -EINVAL;
+
+   colorkey_en = ((colorkey & (1 << 24)) != 0);
+   colorkey &= ~(1 << 24);
+
+   if (ipu_plane->colorkey_en == colorkey_en &&
+   ipu_plane->colorkey == colorkey)
+   return 0;
+
+   ipu_plane->colorkey_en = colorkey_en;
+   ipu_plane->colorkey = colorkey;
+
+   if (!ipu_plane->enabled)
+   return 0;
+
+   return ipu_dp_set_chroma_key(ipu_plane->dp,
+ipu_plane->colorkey_en,
+ipu_plane->colorkey);
+}
+
+static int ipu_plane_set_property(struct drm_plane *plane,
+ struct drm_property *property,
+ uint64_t value)
+{
+   struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+   int ret;
+
+   DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+   if (property == ipu_plane->global_alpha_prop)
+   ret = ipu_plane_set_global_alpha(ipu_plane, value);
+   else if (property == ipu_plane->colorkey_prop)
+   ret = ipu_plane_set_colorkey(ipu_plane, value);
+   else
+   ret = -EINVAL;
+
+   return ret;
+}
+
 static struct drm_plane_funcs ipu_plane_funcs = {
.update_plane   = ipu_update_plane,
.disable_plane  = ipu_disable_plane,
.destroy= ipu_plane_destroy,
+   .set_property   = ipu_plane_set_property,
 };


[PATCH 46/72] imx-drm: ipuv3-plane: Add more supported pixel formats

2014-10-31 Thread Steve Longerbeam
Report more supported formats to drm core via ipu_plane_formats[].

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index cbd300b..5818249 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -29,10 +29,18 @@ static const uint32_t ipu_plane_formats[] = {
DRM_FORMAT_XRGB,
DRM_FORMAT_ABGR,
DRM_FORMAT_XBGR,
+   DRM_FORMAT_RGB565,
+   DRM_FORMAT_RGB888,
+   DRM_FORMAT_BGR888,
DRM_FORMAT_YUYV,
+   DRM_FORMAT_UYVY,
DRM_FORMAT_YVYU,
DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420,
+   DRM_FORMAT_YUV422,
+   DRM_FORMAT_YVU422,
+   DRM_FORMAT_NV12,
+   DRM_FORMAT_NV16,
 };

 int ipu_plane_irq(struct ipu_plane *ipu_plane)
-- 
1.7.9.5



[PATCH 45/72] imx-drm: ipuv3-plane: Allow YUV space for background plane

2014-10-31 Thread Steve Longerbeam
A background plane was assuming the framebuffer pixel format was
RGB by passing IPUV3_COLORSPACE_RGB to ipu_dp_setup_channel(). Fix
by passing the actual colorspace of the framebuffer's pixel format.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index edfa72a..cbd300b 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -140,7 +140,7 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
switch (ipu_plane->dp_flow) {
case IPU_DP_FLOW_SYNC_BG:
ret = ipu_dp_setup_channel(ipu_plane->dp,
-   IPUV3_COLORSPACE_RGB,
+   ipu_drm_fourcc_to_colorspace(fb->pixel_format),
IPUV3_COLORSPACE_RGB);
if (ret) {
dev_err(dev,
-- 
1.7.9.5



[PATCH 44/72] imx-drm: ipuv3-plane: Fix planar formats

2014-10-31 Thread Steve Longerbeam
During a mode set the U/V plane strides and buffer offsets
for planar pixel formats were not being configured in cpmem.
Fix by calling ipu_cpmem_set_yuv_planar() for planar formats.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/ipuv3-plane.c |4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 365cdfe..edfa72a 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -174,6 +174,10 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
fb->pixel_format);
return ret;
}
+   if (ipu_drm_fourcc_is_planar(fb->pixel_format))
+   ipu_cpmem_set_yuv_planar(ipu_plane->ipu_ch, fb->pixel_format,
+fb->pitches[0], crtc_h);
+
ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);

ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
-- 
1.7.9.5



[PATCH 43/72] imx-drm: parallel-display: Fix typo when setting mode type

2014-10-31 Thread Steve Longerbeam
Comma expression is used to set mode type
"mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,"
which is a typo, replace it with ";".

Signed-off-by: Jiada Wang 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/parallel-display.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/imx-drm/parallel-display.c 
b/drivers/staging/imx-drm/parallel-display.c
index 5f7d4ee..49f8308 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -74,7 +74,7 @@ static int imx_pd_connector_get_modes(struct drm_connector 
*connector)
if (!mode)
return -EINVAL;
drm_mode_copy(mode, >mode);
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
num_modes++;
}
@@ -86,7 +86,7 @@ static int imx_pd_connector_get_modes(struct drm_connector 
*connector)
return -EINVAL;
of_get_drm_display_mode(np, >mode, OF_USE_NATIVE_MODE);
drm_mode_copy(mode, >mode);
-   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+   mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, mode);
num_modes++;
}
-- 
1.7.9.5



[PATCH 42/72] imx-drm: imx-ldb: Implement imx_ldb_encoder_dpms()

2014-10-31 Thread Steve Longerbeam
Implement imx_ldb_encoder_dpms(). Two new functions are created
to share poweroff and poweron code. imx_ldb_poweroff() is called
by encoder dpms, prepare, and disable. imx_ldb_poweron() is called
by encoder dpms and commit.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-ldb.c |  139 +
 1 file changed, 79 insertions(+), 60 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-ldb.c 
b/drivers/staging/imx-drm/imx-ldb.c
index 73ff379..1eb632f 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -132,11 +132,86 @@ static struct drm_encoder *imx_ldb_connector_best_encoder(
return _ldb_ch->encoder;
 }

+static void imx_ldb_poweroff(struct imx_ldb_channel *imx_ldb_ch)
+{
+   struct imx_ldb *ldb = imx_ldb_ch->ldb;
+   int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
+   int chno = imx_ldb_ch->chno;
+
+   if ((chno == 0 && (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0) ||
+   (chno == 1 && (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0))
+   return;
+
+   ldb->ldb_ctrl &= (chno == 0) ?
+   ~LDB_CH0_MODE_EN_MASK : ~LDB_CH1_MODE_EN_MASK;
+
+   regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
+
+   if (dual) {
+   clk_disable_unprepare(ldb->clk[0]);
+   clk_disable_unprepare(ldb->clk[1]);
+   } else
+   clk_disable_unprepare(ldb->clk[chno]);
+}
+
+static void imx_ldb_poweron(struct imx_ldb_channel *imx_ldb_ch)
+{
+   struct imx_ldb *ldb = imx_ldb_ch->ldb;
+   int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
+   int chno = imx_ldb_ch->chno;
+   int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child,
+_ldb_ch->encoder);
+
+   if ((chno == 0 && (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK)) ||
+   (chno == 1 && (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK)))
+   return;
+
+   if (dual) {
+   clk_prepare_enable(ldb->clk[0]);
+   clk_prepare_enable(ldb->clk[1]);
+   } else
+   clk_prepare_enable(ldb->clk[chno]);
+
+   if (chno == 0 || dual) {
+   ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
+   if (mux == 0 || ldb->lvds_mux)
+   ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
+   else if (mux == 1)
+   ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1;
+   }
+   if (chno == 1 || dual) {
+   ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
+   if (mux == 1 || ldb->lvds_mux)
+   ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1;
+   else if (mux == 0)
+   ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0;
+   }
+
+   if (ldb->lvds_mux) {
+   const struct bus_mux *lvds_mux = NULL;
+
+   if (chno == 0)
+   lvds_mux = >lvds_mux[0];
+   else if (chno == 1)
+   lvds_mux = >lvds_mux[1];
+
+   regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask,
+  mux << lvds_mux->shift);
+   }
+
+   regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
+}
+
 static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);

imx_ldb_dbg(imx_ldb_ch, "%s: %s\n", __func__, mode ? "OFF" : "ON");
+
+   if (mode)
+   imx_ldb_poweroff(imx_ldb_ch);
+   else
+   imx_ldb_poweron(imx_ldb_ch);
 }

 static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -186,6 +261,8 @@ static void imx_ldb_encoder_prepare(struct drm_encoder 
*encoder)

imx_ldb_entry_dbg(imx_ldb_ch);

+   imx_ldb_poweroff(imx_ldb_ch);
+
if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
/* dual channel LVDS mode */
serial_clk = 3500UL * mode->clock;
@@ -218,45 +295,10 @@ static void imx_ldb_encoder_prepare(struct drm_encoder 
*encoder)
 static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
 {
struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
-   struct imx_ldb *ldb = imx_ldb_ch->ldb;
-   int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
-   int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);

imx_ldb_entry_dbg(imx_ldb_ch);

-   if (dual) {
-   clk_prepare_enable(ldb->clk[0]);
-   clk_prepare_enable(ldb->clk[1]);
-   }
-
-   if (imx_ldb_ch == >channel[0] || dual) {
-   ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
-   if (mux == 0 || ldb->lvds_mux)
-   ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
-   else if (mux == 1)
-   ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1;
-   }
-   if (imx_ldb_ch == >channel[1] || dual) {
-   ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
-   if 

[PATCH 41/72] imx-drm: imx-ldb: Add debug to connector/encoder entry points

2014-10-31 Thread Steve Longerbeam
Add some debug macros for the important encoder and connector
callbacks.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-ldb.c |   36 +++-
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-ldb.c 
b/drivers/staging/imx-drm/imx-ldb.c
index 4662e00..73ff379 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -85,6 +85,11 @@ struct imx_ldb {
const struct bus_mux *lvds_mux;
 };

+#define imx_ldb_dbg(ch, fmt, args...)  \
+   dev_dbg((ch)->ldb->dev, "lvds%d: " fmt, (ch)->chno, ##args)
+#define imx_ldb_entry_dbg(ch)  \
+   imx_ldb_dbg((ch), "%s\n", __func__)
+
 static enum drm_connector_status imx_ldb_connector_detect(
struct drm_connector *connector, bool force)
 {
@@ -96,6 +101,8 @@ static int imx_ldb_connector_get_modes(struct drm_connector 
*connector)
struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
int num_modes = 0;

+   imx_ldb_entry_dbg(imx_ldb_ch);
+
if (imx_ldb_ch->edid) {
drm_mode_connector_update_edid_property(connector,
imx_ldb_ch->edid);
@@ -127,6 +134,9 @@ static struct drm_encoder *imx_ldb_connector_best_encoder(

 static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
+   struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
+
+   imx_ldb_dbg(imx_ldb_ch, "%s: %s\n", __func__, mode ? "OFF" : "ON");
 }

 static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -139,22 +149,22 @@ static bool imx_ldb_encoder_mode_fixup(struct drm_encoder 
*encoder,
 static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
unsigned long serial_clk, unsigned long di_clk)
 {
+   struct imx_ldb_channel *imx_ldb_ch = >channel[chno];
int ret;

-   dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
-   clk_get_rate(ldb->clk_pll[chno]), serial_clk);
+   imx_ldb_dbg(imx_ldb_ch, "%s: now: %ld want: %ld\n", __func__,
+   clk_get_rate(ldb->clk_pll[chno]), serial_clk);
clk_set_rate(ldb->clk_pll[chno], serial_clk);

-   dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
-   clk_get_rate(ldb->clk_pll[chno]));
+   imx_ldb_dbg(imx_ldb_ch, "%s after: %ld\n", __func__,
+   clk_get_rate(ldb->clk_pll[chno]));

-   dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
-   clk_get_rate(ldb->clk[chno]),
-   (long int)di_clk);
+   imx_ldb_dbg(imx_ldb_ch, "%s: now: %ld want: %ld\n", __func__,
+   clk_get_rate(ldb->clk[chno]), (long int)di_clk);
clk_set_rate(ldb->clk[chno], di_clk);

-   dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
-   clk_get_rate(ldb->clk[chno]));
+   imx_ldb_dbg(imx_ldb_ch, "%s after: %ld\n", __func__,
+   clk_get_rate(ldb->clk[chno]));

/* set display clock mux to LDB input clock */
ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]);
@@ -174,6 +184,8 @@ static void imx_ldb_encoder_prepare(struct drm_encoder 
*encoder)
unsigned long di_clk = mode->clock * 1000;
int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);

+   imx_ldb_entry_dbg(imx_ldb_ch);
+
if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
/* dual channel LVDS mode */
serial_clk = 3500UL * mode->clock;
@@ -210,6 +222,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder 
*encoder)
int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);

+   imx_ldb_entry_dbg(imx_ldb_ch);
+
if (dual) {
clk_prepare_enable(ldb->clk[0]);
clk_prepare_enable(ldb->clk[1]);
@@ -253,6 +267,8 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder 
*encoder,
struct imx_ldb *ldb = imx_ldb_ch->ldb;
int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;

+   imx_ldb_entry_dbg(imx_ldb_ch);
+
if (mode->clock > 17) {
dev_warn(ldb->dev,
 "%s: mode exceeds 170 MHz pixel clock\n", __func__);
@@ -282,6 +298,8 @@ static void imx_ldb_encoder_disable(struct drm_encoder 
*encoder)
struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
struct imx_ldb *ldb = imx_ldb_ch->ldb;

+   imx_ldb_entry_dbg(imx_ldb_ch);
+
/*
 * imx_ldb_encoder_disable is called by
 * drm_helper_disable_unused_functions without
-- 
1.7.9.5



[PATCH 40/72] imx-drm: parallel-display: Support RGB666 pixel fmt

2014-10-31 Thread Steve Longerbeam
Add a clause to imx-pd driver to use 18-bit output if driver is told so.

Signed-off-by: Dmitry Eremin-Solenikov 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/parallel-display.c |7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/staging/imx-drm/parallel-display.c 
b/drivers/staging/imx-drm/parallel-display.c
index 015a454..5f7d4ee 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -230,6 +230,13 @@ static int imx_pd_bind(struct device *dev, struct device 
*master, void *data)
else if (!strcmp(fmt, "lvds666"))
imxpd->interface_pix_fmt =
v4l2_fourcc('L', 'V', 'D', '6');
+   else if (!strcmp(fmt, "rgb18"))
+   imxpd->interface_pix_fmt =
+   v4l2_fourcc('R', 'G', 'B', 'H');
+   else {
+   dev_err(dev, "Unsupported interface pix_fmt!\n");
+   return -EINVAL;
+   }
}

panel_node = of_parse_phandle(np, "fsl,panel", 0);
-- 
1.7.9.5



[PATCH 39/72] imx-drm: hdmi: optimize i2c write wait

2014-10-31 Thread Steve Longerbeam
A wait of around 50 ~ 100 micro seconds seems to be enough to allow
I2C Master PHY done, so instead of wait 1000 usec at each time
of register check, wait 100 usec is more appropriate.

Signed-off-by: Jiada Wang 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-hdmi.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-hdmi.c 
b/drivers/staging/imx-drm/imx-hdmi.c
index aaec6b2..801a3eb 100644
--- a/drivers/staging/imx-drm/imx-hdmi.c
+++ b/drivers/staging/imx-drm/imx-hdmi.c
@@ -655,12 +655,12 @@ static inline void hdmi_phy_test_dout(struct imx_hdmi 
*hdmi,
hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
 }

-static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec)
+static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int husec)
 {
while ((hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) {
-   if (msec-- == 0)
+   if (husec-- == 0)
return false;
-   udelay(1000);
+   udelay(100);
}
return true;
 }
-- 
1.7.9.5



[PATCH 38/72] imx-drm: Crtcs moved to device tree

2014-10-31 Thread Steve Longerbeam
The crtcs are now nodes in the device tree, and the encoder endpoints
fall under the crtc port.

ipu_client_platformdata is no longer needed and is gone. The crtc
retrieves the following required parameters from its node:

- ipu phandle.
- di number.
- the port endpoints.

Optionally, "dual-plane" can be specified to configure the crtc device
with a foreground plane. If not given, the crtc will have only a
single plane.

The DC and IDMAC channels can be inferred from the dual-plane parameter.
In table form, the channel usage is:

 Background Plane   Foreground Plane Single Plane
     
Flow TypeIDMAC   DC   DP IDMAC   DP   IDMAC   DC
--  ---  --- -  ---   -  ---
Sync  23 50   27 1 28 1
Async 24 62   29 3 41 2

Async flows are included in the above table but async displays are
not yet supported by the crtc and plane drivers.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/imx-drm/imx-drm-core.c |   28 +++--
 drivers/staging/imx-drm/ipuv3-crtc.c   |  204 +++-
 2 files changed, 162 insertions(+), 70 deletions(-)

diff --git a/drivers/staging/imx-drm/imx-drm-core.c 
b/drivers/staging/imx-drm/imx-drm-core.c
index 9cb222e..e5ec010 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -591,37 +591,43 @@ static const struct component_master_ops imx_drm_ops = {

 static int imx_drm_platform_probe(struct platform_device *pdev)
 {
-   struct device_node *ep, *port, *remote;
+   struct device_node *ep, *crtc, *port, *remote;
struct component_match *match = NULL;
int ret;
int i;

/*
-* Bind the IPU display interface ports first, so that
-* imx_drm_encoder_parse_of called from encoder .bind callbacks
-* works as expected.
+* Bind the crtcs first, so that imx_drm_encoder_parse_of called
+* from encoder .bind callbacks works as expected.
 */
for (i = 0; ; i++) {
-   port = of_parse_phandle(pdev->dev.of_node, "ports", i);
-   if (!port)
+   crtc = of_parse_phandle(pdev->dev.of_node, "crtcs", i);
+   if (!crtc)
break;

-   component_match_add(>dev, , compare_of, port);
+   component_match_add(>dev, , compare_of, crtc);
}

if (i == 0) {
-   dev_err(>dev, "missing 'ports' property\n");
+   dev_err(>dev, "missing 'crtcs' property\n");
return -ENODEV;
}

/* Then bind all encoders */
for (i = 0; ; i++) {
-   port = of_parse_phandle(pdev->dev.of_node, "ports", i);
-   if (!port)
+   crtc = of_parse_phandle(pdev->dev.of_node, "crtcs", i);
+   if (!crtc)
break;

+   port = of_get_child_by_name(crtc, "port");
+   if (!port) {
+   dev_warn(>dev, "%s has no port\n", crtc->name);
+   continue;
+   }
+
for_each_child_of_node(port, ep) {
remote = of_graph_get_remote_port_parent(ep);
+
if (!remote || !of_device_is_available(remote)) {
of_node_put(remote);
continue;
@@ -635,7 +641,7 @@ static int imx_drm_platform_probe(struct platform_device 
*pdev)
component_match_add(>dev, , compare_of, 
remote);
of_node_put(remote);
}
-   of_node_put(port);
+   of_node_put(crtc);
}

ret = dma_set_coherent_mask(>dev, DMA_BIT_MASK(32));
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 8b4440a..5a60017 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -36,10 +36,52 @@

 #define DRIVER_DESC"i.MX IPUv3 Graphics"

+struct ipu_channels {
+   int dma[2]; /* BG, FG */
+   int dp[2];  /* BG, FG */
+   int dc;
+};
+
+#define NO_DP -1
+
+static const struct ipu_channels sync_dual_plane = {
+   .dma = { IPUV3_CHANNEL_MEM_BG_SYNC, IPUV3_CHANNEL_MEM_FG_SYNC },
+   .dp  = { IPU_DP_FLOW_SYNC_BG, IPU_DP_FLOW_SYNC_FG },
+   .dc  = IPU_DC_CHANNEL_DP_SYNC,
+};
+static const struct ipu_channels sync_single_plane = {
+   .dma = { IPUV3_CHANNEL_MEM_DC_SYNC, },
+   .dp  = { NO_DP, NO_DP },
+   .dc  = IPU_DC_CHANNEL_SYNC,
+};
+
+/*
+ * This driver does not yet support async flows for "smart" displays,
+ * but keep this around for future reference. The crtc nodes could in
+ * future add an "async" property.
+ */
+#if 0
+static const struct ipu_channels async_dual_plane = {
+   .dma = { 

[PATCH 37/72] gpu: ipu-cpmem: Add ipu_cpmem_get_burstsize()

2014-10-31 Thread Steve Longerbeam
Adds ipu_cpmem_get_burstsize().

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-cpmem.c |6 ++
 include/video/imx-ipu-v3.h |1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c
index b05a5e8..7afea0a 100644
--- a/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -275,6 +275,12 @@ void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id)
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_axi_id);

+int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch)
+{
+   return ipu_ch_param_read_field(ch, IPU_FIELD_NPB) + 1;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_get_burstsize);
+
 void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize)
 {
ipu_ch_param_write_field(ch, IPU_FIELD_NPB, burstsize - 1);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index df4cc5d..3c7f6f3 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -201,6 +201,7 @@ void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int 
bufnum, dma_addr_t buf);
 void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off);
 void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride);
 void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id);
+int ipu_cpmem_get_burstsize(struct ipuv3_channel *ch);
 void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize);
 void ipu_cpmem_set_block_mode(struct ipuv3_channel *ch);
 void ipu_cpmem_set_rotation(struct ipuv3_channel *ch,
-- 
1.7.9.5



[PATCH 36/72] gpu: ipu-cpmem: Support YVU422

2014-10-31 Thread Steve Longerbeam
Add simple hooks to support YVU422 in cpmem.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-cpmem.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c
index a53b242..b05a5e8 100644
--- a/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -413,6 +413,7 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
break;
case DRM_FORMAT_YVU420:
+   case DRM_FORMAT_YVU422:
ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, (stride / 2) - 1);
ipu_ch_param_write_field(ch, IPU_FIELD_UBO, v_offset / 8);
ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8);
@@ -443,6 +444,7 @@ void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, u32 
drm_fourcc,
  u_offset, v_offset);
break;
case DRM_FORMAT_YUV422:
+   case DRM_FORMAT_YVU422:
uv_stride = stride / 2;
u_offset = stride * height;
v_offset = u_offset + (uv_stride * height);
@@ -627,6 +629,7 @@ int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct 
ipu_image *image)
  u_offset, v_offset);
break;
case DRM_FORMAT_YUV422:
+   case DRM_FORMAT_YVU422:
offset = Y_OFFSET(pix, image->rect.left, image->rect.top);
u_offset = U2_OFFSET(pix, image->rect.left,
 image->rect.top) - offset;
-- 
1.7.9.5



[PATCH 35/72] gpu: ipu-v3: Add IDMA channel linking support

2014-10-31 Thread Steve Longerbeam
Adds functions to link and unlink IDMAC source channels to sink
channels.

So far the following links are supported:

IPUV3_CHANNEL_IC_PRP_ENC_MEM -> IPUV3_CHANNEL_MEM_ROT_ENC
PUV3_CHANNEL_IC_PRP_VF_MEM   -> IPUV3_CHANNEL_MEM_ROT_VF
IPUV3_CHANNEL_IC_PP_MEM  -> IPUV3_CHANNEL_MEM_ROT_PP

More links can be added to the idmac_link_info[] array.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-common.c |  112 +++
 include/video/imx-ipu-v3.h  |3 ++
 2 files changed, 115 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index b1f0feb..ce1de54 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -755,6 +755,118 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, 
bool vdi)
 }
 EXPORT_SYMBOL_GPL(ipu_set_ic_src_mux);

+
+/* IDMAC Channel Linking */
+
+struct idmac_link_reg_info {
+   int chno;
+   u32 reg;
+   int shift;
+   int bits;
+   u32 sel;
+};
+
+struct idmac_link_info {
+   struct idmac_link_reg_info src;
+   struct idmac_link_reg_info sink;
+};
+
+static const struct idmac_link_info idmac_link_info[] = {
+   {
+   .src  = { 20, IPU_FS_PROC_FLOW1,  0, 4, 7 },
+   .sink = { 45, IPU_FS_PROC_FLOW2,  0, 4, 1 },
+   }, {
+   .src =  { 21, IPU_FS_PROC_FLOW1,  8, 4, 8 },
+   .sink = { 46, IPU_FS_PROC_FLOW2,  4, 4, 1 },
+   }, {
+   .src =  { 22, IPU_FS_PROC_FLOW1, 16, 4, 5 },
+   .sink = { 47, IPU_FS_PROC_FLOW2, 12, 4, 3 },
+   },
+};
+
+static const struct idmac_link_info *find_idmac_link_info(
+   struct ipuv3_channel *src, struct ipuv3_channel *sink)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(idmac_link_info); i++) {
+   if (src->num == idmac_link_info[i].src.chno &&
+   sink->num == idmac_link_info[i].sink.chno)
+   return _link_info[i];
+   }
+
+   return NULL;
+}
+
+/*
+ * Links an IDMAC source channel to a sink channel.
+ */
+int ipu_idmac_link(struct ipuv3_channel *src, struct ipuv3_channel *sink)
+{
+   struct ipu_soc *ipu = src->ipu;
+   const struct idmac_link_info *link;
+   u32 src_reg, sink_reg, src_mask, sink_mask;
+   unsigned long flags;
+
+   link = find_idmac_link_info(src, sink);
+   if (!link)
+   return -EINVAL;
+
+   src_mask = ((1 << link->src.bits) - 1) << link->src.shift;
+   sink_mask = ((1 << link->sink.bits) - 1) << link->sink.shift;
+
+   spin_lock_irqsave(>lock, flags);
+
+   src_reg = ipu_cm_read(ipu, link->src.reg);
+   sink_reg = ipu_cm_read(ipu, link->sink.reg);
+
+   src_reg &= ~src_mask;
+   src_reg |= (link->src.sel << link->src.shift);
+
+   sink_reg &= ~sink_mask;
+   sink_reg |= (link->sink.sel << link->sink.shift);
+
+   ipu_cm_write(ipu, src_reg, link->src.reg);
+   ipu_cm_write(ipu, sink_reg, link->sink.reg);
+
+   spin_unlock_irqrestore(>lock, flags);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_link);
+
+/*
+ * Unlinks IDMAC source and sink channels.
+ */
+int ipu_idmac_unlink(struct ipuv3_channel *src, struct ipuv3_channel *sink)
+{
+   struct ipu_soc *ipu = src->ipu;
+   const struct idmac_link_info *link;
+   u32 src_reg, sink_reg, src_mask, sink_mask;
+   unsigned long flags;
+
+   link = find_idmac_link_info(src, sink);
+   if (!link)
+   return -EINVAL;
+
+   src_mask = ((1 << link->src.bits) - 1) << link->src.shift;
+   sink_mask = ((1 << link->sink.bits) - 1) << link->sink.shift;
+
+   spin_lock_irqsave(>lock, flags);
+
+   src_reg = ipu_cm_read(ipu, link->src.reg);
+   sink_reg = ipu_cm_read(ipu, link->sink.reg);
+
+   src_reg &= ~src_mask;
+   sink_reg &= ~sink_mask;
+
+   ipu_cm_write(ipu, src_reg, link->src.reg);
+   ipu_cm_write(ipu, sink_reg, link->sink.reg);
+
+   spin_unlock_irqrestore(>lock, flags);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_unlink);
+
 struct ipu_devtype {
const char *name;
unsigned long cm_ofs;
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index f48ded6..df4cc5d 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -129,6 +129,7 @@ enum ipu_channel_irq {
 #define IPUV3_CHANNEL_ROT_VF_MEM   49
 #define IPUV3_CHANNEL_ROT_PP_MEM   50
 #define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA51
+#define IPUV3_NUM_CHANNELS 64

 int ipu_map_irq(struct ipu_soc *ipu, int irq);
 int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
@@ -171,6 +172,8 @@ int ipu_idmac_get_current_buffer(struct ipuv3_channel 
*channel);
 bool ipu_idmac_buffer_is_ready(struct ipuv3_channel *channel, u32 buf_num);
 void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
 void ipu_idmac_clear_buffer(struct ipuv3_channel 

[PATCH 34/72] gpu: ipu-v3: Add ipu_drm_fourcc_is_planar()

2014-10-31 Thread Steve Longerbeam
Adds ipu_drm_fourcc_is_planar(), which is equivalent to
ipu_pixelformat_is_planar() but accepts a drm fourcc format.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-common.c |   18 ++
 include/video/imx-ipu-v3.h  |1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index ebafcf2..b1f0feb 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -153,6 +153,24 @@ bool ipu_pixelformat_is_planar(u32 pixelformat)
 }
 EXPORT_SYMBOL_GPL(ipu_pixelformat_is_planar);

+bool ipu_drm_fourcc_is_planar(u32 drm_fourcc)
+{
+   switch (drm_fourcc) {
+   case DRM_FORMAT_YUV420:
+   case DRM_FORMAT_YVU420:
+   case DRM_FORMAT_YUV422:
+   case DRM_FORMAT_YVU422:
+   case DRM_FORMAT_NV12:
+   case DRM_FORMAT_NV21:
+   case DRM_FORMAT_NV16:
+   case DRM_FORMAT_NV61:
+   return true;
+   }
+
+   return false;
+}
+EXPORT_SYMBOL_GPL(ipu_drm_fourcc_is_planar);
+
 enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code)
 {
switch (mbus_code & 0xf000) {
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 5aaa08d..f48ded6 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -380,6 +380,7 @@ enum ipu_color_space ipu_pixelformat_to_colorspace(u32 
pixelformat);
 enum ipu_color_space ipu_mbus_code_to_colorspace(u32 mbus_code);
 int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat);
 bool ipu_pixelformat_is_planar(u32 pixelformat);
+bool ipu_drm_fourcc_is_planar(u32 drm_fourcc);
 int ipu_degrees_to_rot_mode(enum ipu_rotate_mode *mode, int degrees,
bool hflip, bool vflip);
 int ipu_rot_mode_to_degrees(int *degrees, enum ipu_rotate_mode mode,
-- 
1.7.9.5



[PATCH 33/72] gpu: ipu-cpmem: Pass drm fourcc to ipu_cpmem_set_yuv_*

2014-10-31 Thread Steve Longerbeam
Pass a drm pixel format fourcc to ipu_cpmem_set_yuv_interleaved(),
ipu_cpmem_set_yuv_planar_full(), and ipu_cpmem_set_yuv_planar(),
instead of a v4l2 pixel format. The remaining cpmem API that still
accepts a v4l2 format is now only ipu_cpmem_set_image(), since this
function is called by v4l2 drivers.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-cpmem.c |   83 +---
 include/video/imx-ipu-v3.h |6 +--
 2 files changed, 46 insertions(+), 43 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c
index 2c93e9c..a53b242 100644
--- a/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -384,15 +384,15 @@ int ipu_cpmem_set_format_passthrough(struct ipuv3_channel 
*ch, int width)
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_passthrough);

-void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 pixel_format)
+void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel *ch, u32 drm_fourcc)
 {
-   switch (pixel_format) {
-   case V4L2_PIX_FMT_UYVY:
+   switch (drm_fourcc) {
+   case DRM_FORMAT_UYVY:
ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0xA);/* pix fmt */
ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
break;
-   case V4L2_PIX_FMT_YUYV:
+   case DRM_FORMAT_YUYV:
ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); /* bits/pixel */
ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0x8);/* pix fmt */
ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);/* burst size */
@@ -402,23 +402,23 @@ void ipu_cpmem_set_yuv_interleaved(struct ipuv3_channel 
*ch, u32 pixel_format)
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_interleaved);

 void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch,
-  u32 pixel_format, int stride,
+  u32 drm_fourcc, int stride,
   int u_offset, int v_offset)
 {
-   switch (pixel_format) {
-   case V4L2_PIX_FMT_YUV420:
-   case V4L2_PIX_FMT_YUV422P:
+   switch (drm_fourcc) {
+   case DRM_FORMAT_YUV420:
+   case DRM_FORMAT_YUV422:
ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, (stride / 2) - 1);
ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8);
break;
-   case V4L2_PIX_FMT_YVU420:
+   case DRM_FORMAT_YVU420:
ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, (stride / 2) - 1);
ipu_ch_param_write_field(ch, IPU_FIELD_UBO, v_offset / 8);
ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8);
break;
-   case V4L2_PIX_FMT_NV12:
-   case V4L2_PIX_FMT_NV16:
+   case DRM_FORMAT_NV12:
+   case DRM_FORMAT_NV16:
ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, stride - 1);
ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8);
ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8);
@@ -427,32 +427,32 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel 
*ch,
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);

-void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
- u32 pixel_format, int stride, int height)
+void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, u32 drm_fourcc,
+ int stride, int height)
 {
int u_offset, v_offset;
int uv_stride = 0;

-   switch (pixel_format) {
-   case V4L2_PIX_FMT_YUV420:
-   case V4L2_PIX_FMT_YVU420:
+   switch (drm_fourcc) {
+   case DRM_FORMAT_YUV420:
+   case DRM_FORMAT_YVU420:
uv_stride = stride / 2;
u_offset = stride * height;
v_offset = u_offset + (uv_stride * height / 2);
-   ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride,
+   ipu_cpmem_set_yuv_planar_full(ch, drm_fourcc, stride,
  u_offset, v_offset);
break;
-   case V4L2_PIX_FMT_YUV422P:
+   case DRM_FORMAT_YUV422:
uv_stride = stride / 2;
u_offset = stride * height;
v_offset = u_offset + (uv_stride * height);
-   ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride,
+   ipu_cpmem_set_yuv_planar_full(ch, drm_fourcc, stride,
  u_offset, v_offset);
break;
-   case V4L2_PIX_FMT_NV12:
-   case V4L2_PIX_FMT_NV16:
+   case DRM_FORMAT_NV12:
+   case DRM_FORMAT_NV16:
u_offset = stride * height;
-   ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride,
+   ipu_cpmem_set_yuv_planar_full(ch, 

[PATCH 32/72] gpu: ipu-v3: Add RGB666 interface pixel map

2014-10-31 Thread Steve Longerbeam
Adds RGB666 to the pre-loaded interface pixel maps.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dc.c |4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 23b6e2c..955adab 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -102,6 +102,10 @@ static struct ipu_dc_if_map predef_maps[] = {
.v4l2_fmt = v4l2_fourcc('G', 'B', 'R', '3'),
}, {
.src_mask = {0xfc, 0xfc, 0xfc},
+   .dest_msb = {5, 11, 17},
+   .v4l2_fmt = v4l2_fourcc('R', 'G', 'B', 'H'),
+   }, {
+   .src_mask = {0xfc, 0xfc, 0xfc},
.dest_msb = {17, 11, 5},
.v4l2_fmt = V4L2_PIX_FMT_BGR666,
}, {
-- 
1.7.9.5



[PATCH 31/72] gpu: ipu-di: Set rate of DI pre clock

2014-10-31 Thread Steve Longerbeam
This patch sets the rate of the DI pre clock to support a much wider
range of pixel clock frequencies.

It does this by calculating two values for the pre-clk rate: a
rate that is a whole integer multiple of the pixel clock, and a rate
that is a half-integer multiple. It then programs whichever rate
comes closest to generating the desired pixel clock, and uses the
corresponding integer or half-integer divider.

The reason only whole or half integer DI dividers are used is because
of a chip bug in the fractional part of DI Base Sync Clock Gen 0 register
(see discussion in FSL community site at
https://community.freescale.com/thread/308577).

Quoting from that thread:

"Pixel IPU clock for Display has high jitter and does not have 50% duty cycle.
This is expected behavior, when the clock divider is set to a value that is not
an integer. When the divider is set to a non-integer value, the average
frequency of the clock will be correct, but the clock will jitter."

According to our experimentation, only 0x8 for the fractional part seems
to generate clock waveforms that are tolerated by most displays (this
hasn't been proved officially).

Signed-off-by: Steve Longerbeam 
Signed-off-by: Jiada Wang 
---
 drivers/gpu/ipu-v3/ipu-di.c |  145 +--
 1 file changed, 111 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index b306f07..8da9c9f 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -398,12 +398,105 @@ static void ipu_di_sync_config_noninterlaced(struct 
ipu_di *di,
ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
 }

-static void ipu_di_config_clock(struct ipu_di *di,
-   const struct ipu_di_signal_cfg *sig)
+
+/*
+ * We need to use the DI divider. We should really have a flag here
+ * indicating whether the bridge can cope with a fractional divider
+ * or not.
+ *
+ * For now, assume the chip bug exists in the fractional divider
+ * which causes bad DI pixel clock waveforms for all values of the
+ * fractional part other than 0 (no fraction) or 0x8 (0.5). So this
+ * function returns a divider with only 0x0 or 0x8 in the fractional
+ * part.
+ *
+ * This function reprograms the clock rate of the parent-parent of
+ * the DI clock in order to get as close as possible to the requested
+ * pixel clock. It calculates two values for the parent-parent rate: a
+ * rate that is a whole integer multiple of the pixel clock, and a rate
+ * that is a half-integer multiple. It then programs whichever rate
+ * comes closest to generating the desired rate, and returns the
+ * corresponding integer or half-integer divider (times 16).
+ */
+static int set_di_pre_clk_rate(struct ipu_di *di,
+  const struct ipu_di_signal_cfg *sig)
+{
+   struct clk *di_pre_clk;
+   unsigned long pre_clk_N_round, pre_clk_N_0_5_round;
+   unsigned long pre_clk_N, pre_clk_N_0_5;
+   unsigned long pixclk_N, pixclk_N_0_5;
+   unsigned div_N, div_N_0_5, error_N, error_N_0_5;
+   int ret;
+
+   di_pre_clk = clk_get_parent(clk_get_parent(di->clk_di));
+   if (IS_ERR(di_pre_clk)) {
+   dev_err(di->ipu->dev, "failed to get di_pre clock\n");
+   return PTR_ERR(di_pre_clk);
+   }
+
+   /*
+* calc pre_clk_N and pre_clk_N_0_5, which are an integer multiple
+* and half-integer multiple of sig->pixelclock, respectively.
+*/
+   pre_clk_N = sig->pixelclock;
+   pre_clk_N_round = clk_round_rate(di_pre_clk, pre_clk_N);
+   pre_clk_N *= (pre_clk_N_round / pre_clk_N);
+   pre_clk_N_0_5 = pre_clk_N + sig->pixelclock / 2;
+
+   if (pre_clk_N < pre_clk_N_round)
+   pre_clk_N += sig->pixelclock;
+   if (pre_clk_N_0_5 < pre_clk_N_round)
+   pre_clk_N_0_5 += sig->pixelclock;
+
+   /*
+* now get the rounded pre_clk_N and pre_clk_N_0_5, i.e. what the
+* pre-clk can actually generate.
+*/
+   pre_clk_N_round = clk_round_rate(di_pre_clk, pre_clk_N);
+   pre_clk_N_0_5_round = clk_round_rate(di_pre_clk, pre_clk_N_0_5);
+
+   /*
+* finally we can determine whether the integer multiple or
+* half-integer multiple pre-clk comes closest to generating
+* the desired pixel clock. Set pre-clk rate to whichever comes
+* closest.
+*/
+   div_N = (pre_clk_N_round << 4) / sig->pixelclock;
+   div_N = (div_N + 0x8) & ~0xf; /* round to nearest int */
+   pixclk_N = (pre_clk_N_round << 4) / div_N;
+
+   div_N_0_5 = (pre_clk_N_0_5_round << 4) / sig->pixelclock;
+   div_N_0_5 = (div_N_0_5 + 0x4) & ~0x7; /* round to nearest half-int */
+   pixclk_N_0_5 = (pre_clk_N_0_5_round << 4) / div_N_0_5;
+
+   error_N = pixclk_N / (sig->pixelclock / 1000);
+   error_N_0_5 = pixclk_N_0_5 / (sig->pixelclock / 1000);
+
+   if (abs(error_N - 1000) < abs(error_N_0_5 - 1000)) {
+

[PATCH 30/72] gpu: ipu-v3: Remove IPU client registration

2014-10-31 Thread Steve Longerbeam
The IPU client devices have been moved to the device tree, so
remove platform registration of those devices. As a result,
platform data (struct ipu_client_platformdata) is no longer
needed, the client data is retrieved from the device nodes.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-common.c |  114 ---
 include/video/imx-ipu-v3.h  |9 
 2 files changed, 123 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 5004f71..ebafcf2 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -990,110 +990,6 @@ static void ipu_submodules_exit(struct ipu_soc *ipu)
ipu_cpmem_exit(ipu);
 }

-static int platform_remove_devices_fn(struct device *dev, void *unused)
-{
-   struct platform_device *pdev = to_platform_device(dev);
-
-   platform_device_unregister(pdev);
-
-   return 0;
-}
-
-static void platform_device_unregister_children(struct platform_device *pdev)
-{
-   device_for_each_child(>dev, NULL, platform_remove_devices_fn);
-}
-
-struct ipu_platform_reg {
-   struct ipu_client_platformdata pdata;
-   const char *name;
-   int reg_offset;
-};
-
-static const struct ipu_platform_reg client_reg[] = {
-   {
-   .pdata = {
-   .di = 0,
-   .dc = 5,
-   .dp = IPU_DP_FLOW_SYNC_BG,
-   .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
-   .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
-   },
-   .name = "imx-ipuv3-crtc",
-   }, {
-   .pdata = {
-   .di = 1,
-   .dc = 1,
-   .dp = -EINVAL,
-   .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
-   .dma[1] = -EINVAL,
-   },
-   .name = "imx-ipuv3-crtc",
-   }, {
-   .pdata = {
-   .csi = 0,
-   .dma[0] = IPUV3_CHANNEL_CSI0,
-   .dma[1] = -EINVAL,
-   },
-   .reg_offset = IPU_CM_CSI0_REG_OFS,
-   .name = "imx-ipuv3-camera",
-   }, {
-   .pdata = {
-   .csi = 1,
-   .dma[0] = IPUV3_CHANNEL_CSI1,
-   .dma[1] = -EINVAL,
-   },
-   .reg_offset = IPU_CM_CSI1_REG_OFS,
-   .name = "imx-ipuv3-camera",
-   },
-};
-
-static DEFINE_MUTEX(ipu_client_id_mutex);
-static int ipu_client_id;
-
-static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
-{
-   struct device *dev = ipu->dev;
-   unsigned i;
-   int id, ret;
-
-   mutex_lock(_client_id_mutex);
-   id = ipu_client_id;
-   ipu_client_id += ARRAY_SIZE(client_reg);
-   mutex_unlock(_client_id_mutex);
-
-   for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
-   const struct ipu_platform_reg *reg = _reg[i];
-   struct platform_device *pdev;
-   struct resource res;
-
-   if (reg->reg_offset) {
-   memset(, 0, sizeof(res));
-   res.flags = IORESOURCE_MEM;
-   res.start = ipu_base + ipu->devtype->cm_ofs + 
reg->reg_offset;
-   res.end = res.start + PAGE_SIZE - 1;
-   pdev = platform_device_register_resndata(dev, reg->name,
-   id++, , 1, >pdata, sizeof(reg->pdata));
-   } else {
-   pdev = platform_device_register_data(dev, reg->name,
-   id++, >pdata, sizeof(reg->pdata));
-   }
-
-   if (IS_ERR(pdev)) {
-   ret = PTR_ERR(pdev);
-   goto err_register;
-   }
-   }
-
-   return 0;
-
-err_register:
-   platform_device_unregister_children(to_platform_device(dev));
-
-   return ret;
-}
-
-
 static int ipu_irq_init(struct ipu_soc *ipu)
 {
struct irq_chip_generic *gc;
@@ -1318,19 +1214,10 @@ static int ipu_probe(struct platform_device *pdev)
if (ret)
goto failed_submodules_init;

-   ret = ipu_add_client_devices(ipu, ipu_base);
-   if (ret) {
-   dev_err(>dev, "adding client devices failed with %d\n",
-   ret);
-   goto failed_add_clients;
-   }
-
dev_info(>dev, "%s probed\n", devtype->name);

return 0;

-failed_add_clients:
-   ipu_submodules_exit(ipu);
 failed_submodules_init:
 out_failed_reset:
ipu_irq_exit(ipu);
@@ -1343,7 +1230,6 @@ static int ipu_remove(struct platform_device *pdev)
 {
struct ipu_soc *ipu = platform_get_drvdata(pdev);

-   platform_device_unregister_children(pdev);
ipu_submodules_exit(ipu);
ipu_irq_exit(ipu);

diff --git a/include/video/imx-ipu-v3.h 

[PATCH 29/72] gpu: ipu-v3: Change signal names in struct ipu_di_signal_cfg

2014-10-31 Thread Steve Longerbeam
This patch changes signal names in struct ipu_di_signal_cfg
as per the industry standard names, and renames fields that
were using CamelCase.

Signed-off-by: Deepak Das 
Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-di.c  |   68 +-
 drivers/staging/imx-drm/ipuv3-crtc.c |   16 
 include/video/imx-ipu-v3.h   |   16 
 3 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 47615ce..b306f07 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -207,10 +207,10 @@ static void ipu_di_sync_config(struct ipu_di *di, struct 
di_sync_config *config,
 static void ipu_di_sync_config_interlaced(struct ipu_di *di,
struct ipu_di_signal_cfg *sig)
 {
-   u32 h_total = sig->width + sig->h_sync_width +
-   sig->h_start_width + sig->h_end_width;
-   u32 v_total = sig->height + sig->v_sync_width +
-   sig->v_start_width + sig->v_end_width;
+   u32 h_total = sig->width + sig->h_sync_len +
+   sig->h_back_porch + sig->h_front_porch;
+   u32 v_total = sig->height + sig->v_sync_len +
+   sig->v_back_porch + sig->v_front_porch;
u32 reg;
struct di_sync_config cfg[] = {
{
@@ -229,7 +229,7 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di,
}, {
.run_count = v_total / 2 - 1,
.run_src = DI_SYNC_HSYNC,
-   .offset_count = sig->v_start_width,
+   .offset_count = sig->v_back_porch,
.offset_src = DI_SYNC_HSYNC,
.repeat_count = 2,
.cnt_clr_src = DI_SYNC_VSYNC,
@@ -249,7 +249,7 @@ static void ipu_di_sync_config_interlaced(struct ipu_di *di,
.cnt_clr_src = DI_SYNC_VSYNC,
}, {
.run_src = DI_SYNC_CLK,
-   .offset_count = sig->h_start_width,
+   .offset_count = sig->h_back_porch,
.offset_src = DI_SYNC_CLK,
.repeat_count = sig->width,
.cnt_clr_src = 5,
@@ -277,10 +277,10 @@ static void ipu_di_sync_config_interlaced(struct ipu_di 
*di,
 static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
struct ipu_di_signal_cfg *sig, int div)
 {
-   u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width +
-   sig->h_end_width;
-   u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width +
-   sig->v_end_width;
+   u32 h_total = sig->width + sig->h_sync_len + sig->h_back_porch +
+   sig->h_front_porch;
+   u32 v_total = sig->height + sig->v_sync_len + sig->v_back_porch +
+   sig->v_front_porch;
struct di_sync_config cfg[] = {
{
/* 1: INT_HSYNC */
@@ -294,25 +294,25 @@ static void ipu_di_sync_config_noninterlaced(struct 
ipu_di *di,
.offset_src = DI_SYNC_CLK,
.cnt_polarity_gen_en = 1,
.cnt_polarity_trigger_src = DI_SYNC_CLK,
-   .cnt_down = sig->h_sync_width * 2,
+   .cnt_down = sig->h_sync_len * 2,
} , {
/* PIN3: VSYNC */
.run_count = v_total - 1,
.run_src = DI_SYNC_INT_HSYNC,
.cnt_polarity_gen_en = 1,
.cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
-   .cnt_down = sig->v_sync_width * 2,
+   .cnt_down = sig->v_sync_len * 2,
} , {
/* 4: Line Active */
.run_src = DI_SYNC_HSYNC,
-   .offset_count = sig->v_sync_width + sig->v_start_width,
+   .offset_count = sig->v_sync_len + sig->v_back_porch,
.offset_src = DI_SYNC_HSYNC,
.repeat_count = sig->height,
.cnt_clr_src = DI_SYNC_VSYNC,
} , {
/* 5: Pixel Active, referenced by DC */
.run_src = DI_SYNC_CLK,
-   .offset_count = sig->h_sync_width + sig->h_start_width,
+   .offset_count = sig->h_sync_len + sig->h_back_porch,
.offset_src = DI_SYNC_CLK,
.repeat_count = sig->width,
.cnt_clr_src = 5, /* Line Active */
@@ -339,7 +339,7 @@ static void ipu_di_sync_config_noninterlaced(struct ipu_di 
*di,
} , {
/* 3: Line Active */
.run_src = DI_SYNC_INT_HSYNC,
-   .offset_count = sig->v_sync_width + sig->v_start_width,
+  

[PATCH 28/72] gpu: ipu-di: Add and improve debug/error messages

2014-10-31 Thread Steve Longerbeam
Add a couple error messages to ipu_di_init() for better IPU
load/unload debug. Add more debug messages.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-di.c |   30 --
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 70bf594..47615ce 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -172,7 +172,7 @@ static void ipu_di_sync_config(struct ipu_di *di, struct 
di_sync_config *config,
(c->repeat_count >= 0x1000) ||
(c->cnt_up >= 0x400) ||
(c->cnt_down >= 0x400)) {
-   dev_err(di->ipu->dev, "DI%d counters out of range.\n",
+   dev_err(di->ipu->dev, "di%d counters out of range.\n",
di->id);
return;
}
@@ -459,8 +459,10 @@ static void ipu_di_config_clock(struct ipu_di *di,

error = rate / (sig->pixelclock / 1000);

-   dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider 
%u, error %d.%u%%\n",
-   rate, div, (signed)(error - 1000) / 10, error % 10);
+   dev_dbg(di->ipu->dev,
+   "di%d: IPU clock can give %lu with divider %u, error 
%d.%u%%\n",
+   di->id, rate, div, (signed)(error - 1000) / 10,
+   error % 10);

/* Allow a 1% error */
if (error < 1010 && error >= 990) {
@@ -503,7 +505,9 @@ static void ipu_di_config_clock(struct ipu_di *di,
val |= DI_GEN_DI_CLK_EXT;
ipu_di_write(di, val, DI_GENERAL);

-   dev_dbg(di->ipu->dev, "Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
+   dev_dbg(di->ipu->dev,
+   "di%d: Want %luHz IPU %luHz DI %luHz using %s, %luHz\n",
+   di->id,
sig->pixelclock,
clk_get_rate(di->clk_ipu),
clk_get_rate(di->clk_di),
@@ -528,10 +532,12 @@ static void adapt_panel_to_ipu_restricitions(struct 
ipu_di *di,
sig->v_end_width = 2;
sig->v_sync_width = sig->v_sync_width - diff;
} else
-   dev_warn(di->ipu->dev, "failed to adapt timing\n");
+   dev_warn(di->ipu->dev,
+"di%d: failed to adapt timing\n", di->id);

dev_warn(di->ipu->dev,
-"timing adapted due to IPU restrictions\n");
+"di%d: timing adapted due to IPU restrictions\n",
+di->id);
}
 }

@@ -541,7 +547,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct 
ipu_di_signal_cfg *sig)
u32 di_gen, vsync_cnt;
u32 div;

-   dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
+   dev_dbg(di->ipu->dev, "di%d: panel size = %d x %d\n",
di->id, sig->width, sig->height);

if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
@@ -549,7 +555,9 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct 
ipu_di_signal_cfg *sig)

adapt_panel_to_ipu_restricitions(di, sig);

-   dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
+   dev_dbg(di->ipu->dev,
+   "di%d: Clocks: IPU %luHz DI %luHz Needed %luHz\n",
+   di->id,
clk_get_rate(di->clk_ipu),
clk_get_rate(di->clk_di),
sig->pixelclock);
@@ -762,8 +770,10 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, 
int id,
ipu->di_priv[id] = di;

di->clk_di = devm_clk_get(dev, id ? "di1" : "di0");
-   if (IS_ERR(di->clk_di))
+   if (IS_ERR(di->clk_di)) {
+   dev_err(dev, "di%d: could not get clock\n", id);
return PTR_ERR(di->clk_di);
+   }

di->ipu = ipu;
di->module = module;
@@ -775,7 +785,7 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, 
int id,

ipu_di_write(di, 0x10, DI_BS_CLKGEN0);

-   dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
+   dev_dbg(dev, "di%d: base: 0x%08lx remapped to %p\n",
id, base, di->base);
di->inuse = false;

-- 
1.7.9.5



[PATCH 27/72] gpu: ipu-di: Move ipu pointer init

2014-10-31 Thread Steve Longerbeam
Move the init of di->ipu pointer to near top of ipu_di_init().

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-di.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 5686969..70bf594 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -765,6 +765,7 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, 
int id,
if (IS_ERR(di->clk_di))
return PTR_ERR(di->clk_di);

+   di->ipu = ipu;
di->module = module;
di->id = id;
di->clk_ipu = clk_ipu;
@@ -777,7 +778,6 @@ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, 
int id,
dev_dbg(dev, "DI%d base: 0x%08lx remapped to %p\n",
id, base, di->base);
di->inuse = false;
-   di->ipu = ipu;

return 0;
 }
-- 
1.7.9.5



[PATCH 26/72] gpu: ipu-v3: Enumerate the DC channel names

2014-10-31 Thread Steve Longerbeam
Define the names of the DC channels, and reference them in ipu-dc.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dc.c |6 ++
 include/video/imx-ipu-v3.h  |7 +++
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 6a3e429..23b6e2c 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -83,8 +83,6 @@
 #define DC_WR_CH_CONF_PROG_DI_ID   (1 << 2)
 #define DC_WR_CH_CONF_PROG_DISP_ID(i)  (((i) & 0x1) << 3)

-#define IPU_DC_NUM_CHANNELS10
-
 struct ipu_dc_priv;

 /* some pre-defined maps */
@@ -394,9 +392,9 @@ void ipu_dc_disable_channel(struct ipu_dc *dc)
u32 val;

/* TODO: Handle MEM_FG_SYNC differently from MEM_BG_SYNC */
-   if (dc->chno == 1)
+   if (dc->chno == IPU_DC_CHANNEL_SYNC)
irq = priv->dc_irq;
-   else if (dc->chno == 5)
+   else if (dc->chno == IPU_DC_CHANNEL_DP_SYNC)
irq = priv->dp_irq;
else
return;
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 0eb7468..d2f621d 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -239,6 +239,13 @@ struct ipu_dc_if_map {
u32 v4l2_fmt;
 };

+#define IPU_DC_CHANNEL_DP_SYNC   5 /* sync main+aux planes */
+#define IPU_DC_CHANNEL_SYNC  1 /* sync single plane (no DP) */
+#define IPU_DC_CHANNEL_DP_ASYNC  6 /* async main+aux planes */
+#define IPU_DC_CHANNEL_ASYNC 2 /* async single plane (no DP) */
+#define IPU_DC_CHANNEL_READ  0 /* DC read channel */
+#define IPU_DC_NUM_CHANNELS 10
+
 struct ipu_dc;
 struct ipu_di;
 struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel);
-- 
1.7.9.5



[PATCH 25/72] gpu: ipu-v3: Consolidate mutex lock in ipu_dmfc_alloc_bandwidth()

2014-10-31 Thread Steve Longerbeam
The dmfc mutex was being acquired in ipu_dmfc_free_bandwidth(), freed,
then immediately re-acquired in ipu_dmfc_alloc_bandwidth(). Acquire
the lock once at the beginning of ipu_dmfc_alloc_bandwidth().

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dmfc.c |   19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 6ef4932..1823004 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -283,7 +283,7 @@ static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int 
slots)
return -EBUSY;
 }

-void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
+static void dmfc_free_bandwidth(struct dmfc_channel *dmfc)
 {
struct ipu_dmfc_priv *priv = dmfc->priv;
int i;
@@ -291,10 +291,8 @@ void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
dmfc->slots, dmfc->segment);

-   mutex_lock(>mutex);
-
if (!dmfc->slots)
-   goto out;
+   return;

dmfc->slotmask = 0;
dmfc->slots = 0;
@@ -320,7 +318,14 @@ void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
   priv->channels[i].segment,
   priv->channels[i].burstsize);
}
-out:
+}
+
+void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
+{
+   struct ipu_dmfc_priv *priv = dmfc->priv;
+
+   mutex_lock(>mutex);
+   dmfc_free_bandwidth(dmfc);
mutex_unlock(>mutex);
 }
 EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
@@ -337,10 +342,10 @@ int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
"dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
bandwidth_pixel_per_second / 100, dmfc->data->ipu_channel);

-   ipu_dmfc_free_bandwidth(dmfc);
-
mutex_lock(>mutex);

+   dmfc_free_bandwidth(dmfc);
+
if (slots > 8) {
ret = -EBUSY;
goto out;
-- 
1.7.9.5



[PATCH 24/72] gpu: ipu-v3: Remove ipu_dmfc_init_channel()

2014-10-31 Thread Steve Longerbeam
The function ipu_dmfc_init_channel() sets the "WAIT4EOT" mode according
to the line width and the DMFC channel's FIFO size (the slots parameter).
But this can only happen after slots has been calculated in
ipu_dmfc_alloc_bandwidth().

Fix by renaming ipu_dmfc_init_channel() to a static dmfc_set_wait_eot()
which is called at the end of ipu_dmfc_alloc_bandwidth(), after slots
has been calculated.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dmfc.c |   41 +
 drivers/staging/imx-drm/ipuv3-plane.c |8 +--
 include/video/imx-ipu-v3.h|3 +--
 3 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 37a0e41..6ef4932 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -176,6 +176,21 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
 }
 EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);

+static void dmfc_set_wait_eot(struct dmfc_channel *dmfc, int width)
+{
+   struct ipu_dmfc_priv *priv = dmfc->priv;
+   u32 dmfc_gen1;
+
+   dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
+
+   if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
+   dmfc_gen1 |= 1 << dmfc->data->eot_shift;
+   else
+   dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
+
+   writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
+}
+
 static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
  int segment, int burstsize)
 {
@@ -312,7 +327,7 @@ EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);

 int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
 unsigned long bandwidth_pixel_per_second,
-int burstsize)
+int width, int burstsize)
 {
struct ipu_dmfc_priv *priv = dmfc->priv;
int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
@@ -347,7 +362,11 @@ int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
goto out;
}

-   ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
+   ret = ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
+   if (ret)
+   goto out;
+
+   dmfc_set_wait_eot(dmfc, width);

 out:
mutex_unlock(>mutex);
@@ -356,24 +375,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);

-int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
-{
-   struct ipu_dmfc_priv *priv = dmfc->priv;
-   u32 dmfc_gen1;
-
-   dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
-
-   if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
-   dmfc_gen1 |= 1 << dmfc->data->eot_shift;
-   else
-   dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
-
-   writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
-
-   return 0;
-}
-EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
-
 struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
 {
struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 798125e..365cdfe 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -158,15 +158,9 @@ int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct 
drm_crtc *crtc,
break;
}

-   ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
-   if (ret) {
-   dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
-   return ret;
-   }
-
ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
calc_bandwidth(crtc_w, crtc_h,
-  calc_vref(mode)), 64);
+  calc_vref(mode)), crtc_w, 64);
if (ret) {
dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
return ret;
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 31b6fde..0eb7468 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -271,9 +271,8 @@ struct dmfc_channel;
 int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc);
 void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc);
 int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
-   unsigned long bandwidth_mbs, int burstsize);
+   unsigned long bandwidth, int width, int burstsize);
 void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc);
-int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width);
 struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel);
 void ipu_dmfc_put(struct dmfc_channel *dmfc);

-- 
1.7.9.5



[PATCH 23/72] gpu: ipu-v3: Allow burstsize of 20 in ipu_dmfc_setup_channel()

2014-10-31 Thread Steve Longerbeam
IDMAC channels can have a burtsize of 20 pixels, so allow for that in
ipu_dmfc_setup_channel().

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dmfc.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 307020e..37a0e41 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -207,6 +207,7 @@ static int ipu_dmfc_setup_channel(struct dmfc_channel 
*dmfc, int slots,
case 16:
field |= DMFC_BURSTSIZE_16;
break;
+   case 20:
case 32:
field |= DMFC_BURSTSIZE_32;
break;
-- 
1.7.9.5



[PATCH 22/72] gpu: ipu-v3: Fix indent/ws in ipu-dmfc

2014-10-31 Thread Steve Longerbeam
Cleanup indentation and whitespace in ipu-dmfc.c. No functional
changes.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dmfc.c |   30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 9ab9c87..307020e 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -125,6 +125,7 @@ struct ipu_dmfc_priv {
 int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
 {
struct ipu_dmfc_priv *priv = dmfc->priv;
+
mutex_lock(>mutex);

if (!priv->use_count) {
@@ -176,14 +177,14 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
 EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);

 static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
-   int segment, int burstsize)
+ int segment, int burstsize)
 {
struct ipu_dmfc_priv *priv = dmfc->priv;
u32 val, field;

dev_dbg(priv->dev,
-   "dmfc: using %d slots starting from segment %d for IPU 
channel %d\n",
-   slots, segment, dmfc->data->ipu_channel);
+   "dmfc: using %d slots starting from segment %d for IPU channel 
%d\n",
+   slots, segment, dmfc->data->ipu_channel);

switch (slots) {
case 1:
@@ -235,7 +236,7 @@ static int ipu_dmfc_setup_channel(struct dmfc_channel 
*dmfc, int slots,
 }

 static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
-   unsigned long bandwidth)
+  unsigned long bandwidth)
 {
int slots = 1;

@@ -272,7 +273,7 @@ void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
int i;

dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
-   dmfc->slots, dmfc->segment);
+   dmfc->slots, dmfc->segment);

mutex_lock(>mutex);

@@ -299,9 +300,9 @@ void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
if (priv->channels[i].slots > 0)
ipu_dmfc_setup_channel(>channels[i],
-   priv->channels[i].slots,
-   priv->channels[i].segment,
-   priv->channels[i].burstsize);
+  priv->channels[i].slots,
+  priv->channels[i].segment,
+  priv->channels[i].burstsize);
}
 out:
mutex_unlock(>mutex);
@@ -309,15 +310,16 @@ out:
 EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);

 int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
-   unsigned long bandwidth_pixel_per_second, int burstsize)
+unsigned long bandwidth_pixel_per_second,
+int burstsize)
 {
struct ipu_dmfc_priv *priv = dmfc->priv;
int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
int segment = -1, ret = 0;

-   dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU 
channel %d\n",
-   bandwidth_pixel_per_second / 100,
-   dmfc->data->ipu_channel);
+   dev_dbg(priv->dev,
+   "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
+   bandwidth_pixel_per_second / 100, dmfc->data->ipu_channel);

ipu_dmfc_free_bandwidth(dmfc);

@@ -390,7 +392,7 @@ void ipu_dmfc_put(struct dmfc_channel *dmfc)
 EXPORT_SYMBOL_GPL(ipu_dmfc_put);

 int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
-   struct clk *ipu_clk)
+ struct clk *ipu_clk)
 {
struct ipu_dmfc_priv *priv;
int i;
@@ -425,7 +427,7 @@ int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, 
unsigned long base,
priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8;

dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
-   priv->bandwidth_per_slot / 100);
+   priv->bandwidth_per_slot / 100);

writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
-- 
1.7.9.5



[PATCH 21/72] gpu: ipu-v3: Update DP sync SRM always in ipu_dp_enable_channel()

2014-10-31 Thread Steve Longerbeam
In Freescale kernels, when a DP channel is enabled, the DP sync
SRM is updated for both background and foreground DP channels. Do
the same.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dp.c |   11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index d918596..a31b4a5 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -388,14 +388,13 @@ int ipu_dp_enable_channel(struct ipu_dp *dp)
struct ipu_dp_priv *priv = flow->priv;
u32 reg;

-   if (!dp->foreground)
-   return 0;
-
mutex_lock(>mutex);

-   reg = readl(flow->base + DP_COM_CONF);
-   reg |= DP_COM_CONF_FG_EN;
-   writel(reg, flow->base + DP_COM_CONF);
+   if (dp->foreground) {
+   reg = readl(flow->base + DP_COM_CONF);
+   reg |= DP_COM_CONF_FG_EN;
+   writel(reg, flow->base + DP_COM_CONF);
+   }

ipu_srm_dp_sync_update(priv->ipu);

-- 
1.7.9.5



[PATCH 20/72] gpu: ipu-v3: Move DI waveform counter enable/disable to ipu-di

2014-10-31 Thread Steve Longerbeam
Move the DI waveform counter enable/disable out of
ipu_module_enable()/disable(). This should be carried out
when enabling/disabling the DI pixel clock.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-common.c |   37 +++--
 drivers/gpu/ipu-v3/ipu-di.c |   13 -
 drivers/gpu/ipu-v3/ipu-prv.h|1 +
 3 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index d3af206..5004f71 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -59,6 +59,25 @@ void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
 }
 EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);

+void ipu_enable_di_counter(struct ipu_soc *ipu, int di, bool enable)
+{
+   unsigned long flags;
+   u32 val, mask;
+
+   mask = di ? IPU_DI1_COUNTER_RELEASE : IPU_DI0_COUNTER_RELEASE;
+
+   spin_lock_irqsave(>lock, flags);
+
+   val = ipu_cm_read(ipu, IPU_DISP_GEN);
+   if (enable)
+   val |= mask;
+   else
+   val &= ~mask;
+   ipu_cm_write(ipu, val, IPU_DISP_GEN);
+
+   spin_unlock_irqrestore(>lock, flags);
+}
+
 enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
 {
switch (drm_fourcc) {
@@ -407,15 +426,6 @@ int ipu_module_enable(struct ipu_soc *ipu, u32 mask)

spin_lock_irqsave(>lock, lock_flags);

-   val = ipu_cm_read(ipu, IPU_DISP_GEN);
-
-   if (mask & IPU_CONF_DI0_EN)
-   val |= IPU_DI0_COUNTER_RELEASE;
-   if (mask & IPU_CONF_DI1_EN)
-   val |= IPU_DI1_COUNTER_RELEASE;
-
-   ipu_cm_write(ipu, val, IPU_DISP_GEN);
-
val = ipu_cm_read(ipu, IPU_CONF);
val |= mask;
ipu_cm_write(ipu, val, IPU_CONF);
@@ -437,15 +447,6 @@ int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
val &= ~mask;
ipu_cm_write(ipu, val, IPU_CONF);

-   val = ipu_cm_read(ipu, IPU_DISP_GEN);
-
-   if (mask & IPU_CONF_DI0_EN)
-   val &= ~IPU_DI0_COUNTER_RELEASE;
-   if (mask & IPU_CONF_DI1_EN)
-   val &= ~IPU_DI1_COUNTER_RELEASE;
-
-   ipu_cm_write(ipu, val, IPU_DISP_GEN);
-
spin_unlock_irqrestore(>lock, lock_flags);

return 0;
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 7ab19a3..5686969 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -670,7 +670,16 @@ EXPORT_SYMBOL_GPL(ipu_di_enable);

 int ipu_di_enable_clock(struct ipu_di *di)
 {
-   return clk_prepare_enable(di->clk_di_pixel);
+   int ret;
+
+   ret = clk_prepare_enable(di->clk_di_pixel);
+   if (ret)
+   return ret;
+
+   ipu_enable_di_counter(di->ipu, di->id, true);
+
+   return 0;
+
 }
 EXPORT_SYMBOL_GPL(ipu_di_enable_clock);

@@ -687,6 +696,8 @@ EXPORT_SYMBOL_GPL(ipu_di_disable);

 int ipu_di_disable_clock(struct ipu_di *di)
 {
+   ipu_enable_di_counter(di->ipu, di->id, false);
+
clk_disable_unprepare(di->clk_di_pixel);

return 0;
diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h
index bfb1e8a..7797894 100644
--- a/drivers/gpu/ipu-v3/ipu-prv.h
+++ b/drivers/gpu/ipu-v3/ipu-prv.h
@@ -184,6 +184,7 @@ static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 
value,
 }

 void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
+void ipu_enable_di_counter(struct ipu_soc *ipu, int di, bool enable);

 int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
 int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
-- 
1.7.9.5



[PATCH 19/72] gpu: ipu-v3: Protect more CM reg access with IPU lock

2014-10-31 Thread Steve Longerbeam
Some cm_reg accesses were not being protected by the IPU spin lock.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-common.c |   22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index f707d25..d3af206 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -46,11 +46,16 @@ static inline void ipu_cm_write(struct ipu_soc *ipu, u32 
value, unsigned offset)

 void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
 {
+   unsigned long flags;
u32 val;

+   spin_lock_irqsave(>lock, flags);
+
val = ipu_cm_read(ipu, IPU_SRM_PRI2);
val |= 0x8;
ipu_cm_write(ipu, val, IPU_SRM_PRI2);
+
+   spin_unlock_irqrestore(>lock, flags);
 }
 EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);

@@ -451,8 +456,17 @@ int ipu_idmac_get_current_buffer(struct ipuv3_channel 
*channel)
 {
struct ipu_soc *ipu = channel->ipu;
unsigned int chno = channel->num;
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(>lock, flags);

-   return (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ? 1 
: 0;
+   ret = (ipu_cm_read(ipu, IPU_CHA_CUR_BUF(chno)) & idma_mask(chno)) ?
+   1 : 0;
+
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_get_current_buffer);

@@ -569,10 +583,14 @@ EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);

 int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms)
 {
-   unsigned long timeout;
+   unsigned long flags, timeout;

timeout = jiffies + msecs_to_jiffies(ms);
+
+   spin_lock_irqsave(>lock, flags);
ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32));
+   spin_unlock_irqrestore(>lock, flags);
+
while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32 {
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
-- 
1.7.9.5



[PATCH 18/72] gpu: ipu-v3: Split out DI clock enable/disable

2014-10-31 Thread Steve Longerbeam
DI clock enable/disable is moved out of ipu_di_enable() and ipu_di_disable()
and into (new) ipu_di_enable_clock() and ipu_di_disable_clock(). So
ipu_di_enable() and ipu_di_disable() are now pure module enable/disable.

The purpose of this change is to more closely emulate the display mode
setting sequence in FSL kernels, which enable and disable the DI
clock as the very last steps during legacy fbdev set_par().

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-di.c  |   20 +---
 drivers/staging/imx-drm/ipuv3-crtc.c |2 ++
 include/video/imx-ipu-v3.h   |2 ++
 3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 9841419..7ab19a3 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -659,14 +659,8 @@ EXPORT_SYMBOL(ipu_di_uninit_sync_panel);

 int ipu_di_enable(struct ipu_di *di)
 {
-   int ret;
-
WARN_ON(IS_ERR(di->clk_di_pixel));

-   ret = clk_prepare_enable(di->clk_di_pixel);
-   if (ret)
-   return ret;
-
dev_dbg(di->ipu->dev, "DI%d enable\n", di->id);
ipu_module_enable(di->ipu, di->module);

@@ -674,6 +668,12 @@ int ipu_di_enable(struct ipu_di *di)
 }
 EXPORT_SYMBOL_GPL(ipu_di_enable);

+int ipu_di_enable_clock(struct ipu_di *di)
+{
+   return clk_prepare_enable(di->clk_di_pixel);
+}
+EXPORT_SYMBOL_GPL(ipu_di_enable_clock);
+
 int ipu_di_disable(struct ipu_di *di)
 {
WARN_ON(IS_ERR(di->clk_di_pixel));
@@ -681,11 +681,17 @@ int ipu_di_disable(struct ipu_di *di)
dev_dbg(di->ipu->dev, "DI%d disable\n", di->id);
ipu_module_disable(di->ipu, di->module);

+   return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_disable);
+
+int ipu_di_disable_clock(struct ipu_di *di)
+{
clk_disable_unprepare(di->clk_di_pixel);

return 0;
 }
-EXPORT_SYMBOL_GPL(ipu_di_disable);
+EXPORT_SYMBOL_GPL(ipu_di_disable_clock);

 int ipu_di_get_num(struct ipu_di *di)
 {
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 7053619..be24cb9 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -68,6 +68,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
/* Start DC channel and DI after IDMAC */
ipu_dc_enable_channel(ipu_crtc->dc);
ipu_di_enable(ipu_crtc->di);
+   ipu_di_enable_clock(ipu_crtc->di);

ipu_crtc->enabled = 1;
 }
@@ -82,6 +83,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
ipu_di_disable(ipu_crtc->di);
ipu_plane_disable(ipu_crtc->plane[0]);
ipu_dc_disable(ipu_crtc->dc);
+   ipu_di_disable_clock(ipu_crtc->di);

ipu_crtc->enabled = 0;
 }
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 01ab5e0..31b6fde 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -257,7 +257,9 @@ void ipu_dc_disable(struct ipu_dc *dc);
 struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp);
 void ipu_di_put(struct ipu_di *);
 int ipu_di_disable(struct ipu_di *);
+int ipu_di_disable_clock(struct ipu_di *di);
 int ipu_di_enable(struct ipu_di *);
+int ipu_di_enable_clock(struct ipu_di *di);
 int ipu_di_get_num(struct ipu_di *);
 int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig);
 void ipu_di_uninit_sync_panel(struct ipu_di *di);
-- 
1.7.9.5



[PATCH 17/72] gpu: ipu-v3: Add ipu_di_uninit_sync_panel()

2014-10-31 Thread Steve Longerbeam
Adds ipu_di_uninit_sync_panel() which tears down ipu_di_init_sync_panel().

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-di.c |   18 ++
 include/video/imx-ipu-v3.h  |1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 35ee345..9841419 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -639,6 +639,24 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct 
ipu_di_signal_cfg *sig)
 }
 EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);

+void ipu_di_uninit_sync_panel(struct ipu_di *di)
+{
+   u32 reg, di_gen;
+
+   mutex_lock(_mutex);
+
+   di_gen = ipu_di_read(di, DI_GENERAL);
+   di_gen |= 0x3ff | DI_GEN_POLARITY_DISP_CLK;
+   ipu_di_write(di, di_gen, DI_GENERAL);
+
+   reg = ipu_di_read(di, DI_POL);
+   reg |= 0x3ff;
+   ipu_di_write(di, reg, DI_POL);
+
+   mutex_unlock(_mutex);
+}
+EXPORT_SYMBOL(ipu_di_uninit_sync_panel);
+
 int ipu_di_enable(struct ipu_di *di)
 {
int ret;
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 1665a17..01ab5e0 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -260,6 +260,7 @@ int ipu_di_disable(struct ipu_di *);
 int ipu_di_enable(struct ipu_di *);
 int ipu_di_get_num(struct ipu_di *);
 int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig);
+void ipu_di_uninit_sync_panel(struct ipu_di *di);

 /*
  * IPU Display Multi FIFO Controller (dmfc) functions
-- 
1.7.9.5



[PATCH 16/72] gpu: ipu-v3: Add DMFC/DP/DC/DI module enable/disable debug

2014-10-31 Thread Steve Longerbeam
Add debug messages when these modules are globally disabled or enabled
in the IPU_CONF register.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dc.c   |8 ++--
 drivers/gpu/ipu-v3/ipu-di.c   |2 ++
 drivers/gpu/ipu-v3/ipu-dmfc.c |5 -
 drivers/gpu/ipu-v3/ipu-dp.c   |8 ++--
 4 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 79879e7..6a3e429 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -348,8 +348,10 @@ void ipu_dc_enable(struct ipu_dc *dc)

mutex_lock(>mutex);

-   if (!priv->use_count)
+   if (!priv->use_count) {
+   dev_dbg(priv->dev, "DC enable\n");
ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
+   }

priv->use_count++;

@@ -420,8 +422,10 @@ void ipu_dc_disable(struct ipu_dc *dc)
mutex_lock(>mutex);

priv->use_count--;
-   if (!priv->use_count)
+   if (!priv->use_count) {
+   dev_dbg(priv->dev, "DC disable\n");
ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
+   }

if (priv->use_count < 0)
priv->use_count = 0;
diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index 2fafb63..35ee345 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -649,6 +649,7 @@ int ipu_di_enable(struct ipu_di *di)
if (ret)
return ret;

+   dev_dbg(di->ipu->dev, "DI%d enable\n", di->id);
ipu_module_enable(di->ipu, di->module);

return 0;
@@ -659,6 +660,7 @@ int ipu_di_disable(struct ipu_di *di)
 {
WARN_ON(IS_ERR(di->clk_di_pixel));

+   dev_dbg(di->ipu->dev, "DI%d disable\n", di->id);
ipu_module_disable(di->ipu, di->module);

clk_disable_unprepare(di->clk_di_pixel);
diff --git a/drivers/gpu/ipu-v3/ipu-dmfc.c b/drivers/gpu/ipu-v3/ipu-dmfc.c
index 042c395..9ab9c87 100644
--- a/drivers/gpu/ipu-v3/ipu-dmfc.c
+++ b/drivers/gpu/ipu-v3/ipu-dmfc.c
@@ -127,8 +127,10 @@ int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
struct ipu_dmfc_priv *priv = dmfc->priv;
mutex_lock(>mutex);

-   if (!priv->use_count)
+   if (!priv->use_count) {
+   dev_dbg(priv->dev, "DMFC enable\n");
ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
+   }

priv->use_count++;

@@ -162,6 +164,7 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)

if (!priv->use_count) {
ipu_dmfc_wait_fifos(priv);
+   dev_dbg(priv->dev, "DMFC disable\n");
ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
}

diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index 89173e5..d918596 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -369,8 +369,10 @@ int ipu_dp_enable(struct ipu_dp *dp)

mutex_lock(>mutex);

-   if (!priv->use_count)
+   if (!priv->use_count) {
+   dev_dbg(priv->dev, "DP enable\n");
ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
+   }

priv->use_count++;

@@ -441,8 +443,10 @@ void ipu_dp_disable(struct ipu_dp *dp)

priv->use_count--;

-   if (!priv->use_count)
+   if (!priv->use_count) {
+   dev_dbg(priv->dev, "DP disable\n");
ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
+   }

if (priv->use_count < 0)
priv->use_count = 0;
-- 
1.7.9.5



[PATCH 15/72] gpu: ipu-v3: fix HDMI timing issues

2014-10-31 Thread Steve Longerbeam
From: Jiada Wang 

On some monitors, with high resolution(1920x1080), HDMI is not working,
some resolution have pixel column truncation problem
(shows 1280x1022 instead of 1280x1024), which will result in really strange
picture on some monitors.

This Patch aims to fix these HDMI timing issues.

Signed-off-by: Jiada Wang 
Signed-off-by: Deepak Das 
---
 drivers/gpu/ipu-v3/ipu-di.c |   30 +-
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
index c490ba4..2fafb63 100644
--- a/drivers/gpu/ipu-v3/ipu-di.c
+++ b/drivers/gpu/ipu-v3/ipu-di.c
@@ -511,12 +511,35 @@ static void ipu_di_config_clock(struct ipu_di *di,
clk_get_rate(di->clk_di_pixel) / (clkgen0 >> 4));
 }

+/*
+ * This function is called to adapt synchronous LCD panel to
+ * IPU restriction.
+ */
+static void adapt_panel_to_ipu_restricitions(struct ipu_di *di,
+struct ipu_di_signal_cfg *sig)
+{
+   if (sig->v_end_width < 2) {
+   uint16_t diff = 2 - sig->v_end_width;
+
+   if (sig->v_start_width >= diff) {
+   sig->v_end_width = 2;
+   sig->v_start_width -= diff;
+   } else if (sig->v_sync_width > diff) {
+   sig->v_end_width = 2;
+   sig->v_sync_width = sig->v_sync_width - diff;
+   } else
+   dev_warn(di->ipu->dev, "failed to adapt timing\n");
+
+   dev_warn(di->ipu->dev,
+"timing adapted due to IPU restrictions\n");
+   }
+}
+
 int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 {
u32 reg;
u32 di_gen, vsync_cnt;
u32 div;
-   u32 h_total, v_total;

dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d\n",
di->id, sig->width, sig->height);
@@ -524,10 +547,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct 
ipu_di_signal_cfg *sig)
if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
return -EINVAL;

-   h_total = sig->width + sig->h_sync_width + sig->h_start_width +
-   sig->h_end_width;
-   v_total = sig->height + sig->v_sync_width + sig->v_start_width +
-   sig->v_end_width;
+   adapt_panel_to_ipu_restricitions(di, sig);

dev_dbg(di->ipu->dev, "Clocks: IPU %luHz DI %luHz Needed %luHz\n",
clk_get_rate(di->clk_ipu),
-- 
1.7.9.5



[PATCH 14/72] gpu: ipu-v3: Implement use counter for ipu_dc_enable(), ipu_dc_disable()

2014-10-31 Thread Steve Longerbeam
The functions ipu_dc_enable() and ipu_dc_disable() enable/disable the DC
globally in the IPU_CONF register, but the DC is used by multiple clients
on different DC channels. So make sure to only disable/enable the DC
globally based on a use counter.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dc.c |   21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index f53fce5..79879e7 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -144,6 +144,7 @@ struct ipu_dc_priv {
struct completion   comp;
int dc_irq;
int dp_irq;
+   int use_count;
 };

 /* forward references */
@@ -345,7 +346,14 @@ void ipu_dc_enable(struct ipu_dc *dc)
 {
struct ipu_dc_priv *priv = dc->priv;

-   ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
+   mutex_lock(>mutex);
+
+   if (!priv->use_count)
+   ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
+
+   priv->use_count++;
+
+   mutex_unlock(>mutex);
 }
 EXPORT_SYMBOL_GPL(ipu_dc_enable);

@@ -409,7 +417,16 @@ void ipu_dc_disable(struct ipu_dc *dc)
 {
struct ipu_dc_priv *priv = dc->priv;

-   ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
+   mutex_lock(>mutex);
+
+   priv->use_count--;
+   if (!priv->use_count)
+   ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
+
+   if (priv->use_count < 0)
+   priv->use_count = 0;
+
+   mutex_unlock(>mutex);
 }
 EXPORT_SYMBOL_GPL(ipu_dc_disable);

-- 
1.7.9.5



[PATCH 13/72] gpu: ipu-v3: Pass struct ipu_dp to enable/disable

2014-10-31 Thread Steve Longerbeam
Pass the pointer to DP channel to ipu_dp_enable() and ipu_dp_disable(),
to be more consistent with the other ipu-dp APIs.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dp.c   |   10 ++
 drivers/staging/imx-drm/ipuv3-plane.c |4 ++--
 include/video/imx-ipu-v3.h|4 ++--
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index 626f738..89173e5 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -362,9 +362,10 @@ void ipu_dp_uninit_channel(struct ipu_dp *dp)
 }
 EXPORT_SYMBOL_GPL(ipu_dp_uninit_channel);

-int ipu_dp_enable(struct ipu_soc *ipu)
+int ipu_dp_enable(struct ipu_dp *dp)
 {
-   struct ipu_dp_priv *priv = ipu->dp_priv;
+   struct ipu_flow *flow = to_flow(dp);
+   struct ipu_dp_priv *priv = flow->priv;

mutex_lock(>mutex);

@@ -431,9 +432,10 @@ void ipu_dp_disable_channel(struct ipu_dp *dp)
 }
 EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);

-void ipu_dp_disable(struct ipu_soc *ipu)
+void ipu_dp_disable(struct ipu_dp *dp)
 {
-   struct ipu_dp_priv *priv = ipu->dp_priv;
+   struct ipu_flow *flow = to_flow(dp);
+   struct ipu_dp_priv *priv = flow->priv;

mutex_lock(>mutex);

diff --git a/drivers/staging/imx-drm/ipuv3-plane.c 
b/drivers/staging/imx-drm/ipuv3-plane.c
index 944962b..798125e 100644
--- a/drivers/staging/imx-drm/ipuv3-plane.c
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -236,7 +236,7 @@ err_out:
 void ipu_plane_enable(struct ipu_plane *ipu_plane)
 {
if (ipu_plane->dp)
-   ipu_dp_enable(ipu_plane->ipu);
+   ipu_dp_enable(ipu_plane->dp);
ipu_dmfc_enable_channel(ipu_plane->dmfc);
ipu_idmac_enable_channel(ipu_plane->ipu_ch);
if (ipu_plane->dp)
@@ -256,7 +256,7 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane)
ipu_idmac_disable_channel(ipu_plane->ipu_ch);
ipu_dmfc_disable_channel(ipu_plane->dmfc);
if (ipu_plane->dp)
-   ipu_dp_disable(ipu_plane->ipu);
+   ipu_dp_disable(ipu_plane->dp);
 }

 /*
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 567ac41..1665a17 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -286,10 +286,10 @@ void ipu_dmfc_put(struct dmfc_channel *dmfc);

 struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow);
 void ipu_dp_put(struct ipu_dp *);
-int ipu_dp_enable(struct ipu_soc *ipu);
+int ipu_dp_enable(struct ipu_dp *dp);
 int ipu_dp_enable_channel(struct ipu_dp *dp);
 void ipu_dp_disable_channel(struct ipu_dp *dp);
-void ipu_dp_disable(struct ipu_soc *ipu);
+void ipu_dp_disable(struct ipu_dp *dp);
 int ipu_dp_setup_channel(struct ipu_dp *dp,
enum ipu_color_space in, enum ipu_color_space out);
 void ipu_dp_uninit_channel(struct ipu_dp *dp);
-- 
1.7.9.5



[PATCH 12/72] gpu: ipu-v3: Add ipu_dp_uninit_channel()

2014-10-31 Thread Steve Longerbeam
Adds the function ipu_dp_uninit_channel() which tears down
ipu_dp_setup_channel().

Signed-off-by: Steve Longerbeam 
Signed-off-by: Muzaffar Mahmood 
---
 drivers/gpu/ipu-v3/ipu-dp.c |   18 ++
 include/video/imx-ipu-v3.h  |1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index 472acd6..626f738 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -302,6 +302,16 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
writel(reg, flow->base + DP_COM_CONF);
 }

+static void ipu_dp_csc_disable(struct ipu_flow *flow)
+{
+   writel(0, flow->base + DP_CSC_A_0);
+   writel(0, flow->base + DP_CSC_A_1);
+   writel(0, flow->base + DP_CSC_A_2);
+   writel(0, flow->base + DP_CSC_A_3);
+   writel(0, flow->base + DP_CSC_0);
+   writel(0, flow->base + DP_CSC_1);
+}
+
 int ipu_dp_setup_channel(struct ipu_dp *dp,
enum ipu_color_space in,
enum ipu_color_space out)
@@ -344,6 +354,14 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
 }
 EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);

+void ipu_dp_uninit_channel(struct ipu_dp *dp)
+{
+   struct ipu_flow *flow = to_flow(dp);
+
+   ipu_dp_csc_disable(flow);
+}
+EXPORT_SYMBOL_GPL(ipu_dp_uninit_channel);
+
 int ipu_dp_enable(struct ipu_soc *ipu)
 {
struct ipu_dp_priv *priv = ipu->dp_priv;
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 36309b9..567ac41 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -292,6 +292,7 @@ void ipu_dp_disable_channel(struct ipu_dp *dp);
 void ipu_dp_disable(struct ipu_soc *ipu);
 int ipu_dp_setup_channel(struct ipu_dp *dp,
enum ipu_color_space in, enum ipu_color_space out);
+void ipu_dp_uninit_channel(struct ipu_dp *dp);
 int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
 int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
bool bg_chan);
-- 
1.7.9.5



[PATCH 11/72] gpu: ipu-v3: Pass struct ipu_dc to enable/disable

2014-10-31 Thread Steve Longerbeam
Pass the pointer to DC channel to ipu_dc_enable() and ipu_dc_disable(),
to be more consistent with the other ipu-dc APIs.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dc.c  |   12 
 drivers/staging/imx-drm/ipuv3-crtc.c |8 ++--
 include/video/imx-ipu-v3.h   |4 ++--
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 6992f84..f53fce5 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -341,9 +341,11 @@ void ipu_dc_uninit_sync(struct ipu_dc *dc)
 }
 EXPORT_SYMBOL_GPL(ipu_dc_uninit_sync);

-void ipu_dc_enable(struct ipu_soc *ipu)
+void ipu_dc_enable(struct ipu_dc *dc)
 {
-   ipu_module_enable(ipu, IPU_CONF_DC_EN);
+   struct ipu_dc_priv *priv = dc->priv;
+
+   ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
 }
 EXPORT_SYMBOL_GPL(ipu_dc_enable);

@@ -403,9 +405,11 @@ void ipu_dc_disable_channel(struct ipu_dc *dc)
 }
 EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);

-void ipu_dc_disable(struct ipu_soc *ipu)
+void ipu_dc_disable(struct ipu_dc *dc)
 {
-   ipu_module_disable(ipu, IPU_CONF_DC_EN);
+   struct ipu_dc_priv *priv = dc->priv;
+
+   ipu_module_disable(priv->ipu, IPU_CONF_DC_EN);
 }
 EXPORT_SYMBOL_GPL(ipu_dc_disable);

diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c 
b/drivers/staging/imx-drm/ipuv3-crtc.c
index 25c0231..7053619 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -60,12 +60,10 @@ struct ipu_crtc {

 static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
 {
-   struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
-
if (ipu_crtc->enabled)
return;

-   ipu_dc_enable(ipu);
+   ipu_dc_enable(ipu_crtc->dc);
ipu_plane_enable(ipu_crtc->plane[0]);
/* Start DC channel and DI after IDMAC */
ipu_dc_enable_channel(ipu_crtc->dc);
@@ -76,8 +74,6 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)

 static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
 {
-   struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
-
if (!ipu_crtc->enabled)
return;

@@ -85,7 +81,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
ipu_dc_disable_channel(ipu_crtc->dc);
ipu_di_disable(ipu_crtc->di);
ipu_plane_disable(ipu_crtc->plane[0]);
-   ipu_dc_disable(ipu);
+   ipu_dc_disable(ipu_crtc->dc);

ipu_crtc->enabled = 0;
 }
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 758c773..36309b9 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -246,10 +246,10 @@ void ipu_dc_put(struct ipu_dc *dc);
 int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
 u32 pixel_fmt, struct ipu_dc_if_map *new_map, u32 width);
 void ipu_dc_uninit_sync(struct ipu_dc *dc);
-void ipu_dc_enable(struct ipu_soc *ipu);
+void ipu_dc_enable(struct ipu_dc *dc);
 void ipu_dc_enable_channel(struct ipu_dc *dc);
 void ipu_dc_disable_channel(struct ipu_dc *dc);
-void ipu_dc_disable(struct ipu_soc *ipu);
+void ipu_dc_disable(struct ipu_dc *dc);

 /*
  * IPU Display Interface (di) functions
-- 
1.7.9.5



[PATCH 10/72] gpu: ipu-v3: Add ipu_dc_uninit_sync()

2014-10-31 Thread Steve Longerbeam
Adds the function ipu_dc_uninit_sync() which tears down
ipu_dc_init_sync().

Signed-off-by: Steve Longerbeam 
Signed-off-by: Muzaffar Mahmood 
---
 drivers/gpu/ipu-v3/ipu-dc.c |   14 ++
 include/video/imx-ipu-v3.h  |1 +
 2 files changed, 15 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 36c7c57..6992f84 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -327,6 +327,20 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, 
bool interlaced,
 }
 EXPORT_SYMBOL_GPL(ipu_dc_init_sync);

+void ipu_dc_uninit_sync(struct ipu_dc *dc)
+{
+   dc_link_event(dc, DC_EVT_NL, 0, 0);
+   dc_link_event(dc, DC_EVT_EOL, 0, 0);
+   dc_link_event(dc, DC_EVT_NEW_DATA, 0, 0);
+   dc_link_event(dc, DC_EVT_NF, 0, 0);
+   dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
+   dc_link_event(dc, DC_EVT_EOF, 0, 0);
+   dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
+   dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
+   dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_uninit_sync);
+
 void ipu_dc_enable(struct ipu_soc *ipu)
 {
ipu_module_enable(ipu, IPU_CONF_DC_EN);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index 032948b5..758c773 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -245,6 +245,7 @@ struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel);
 void ipu_dc_put(struct ipu_dc *dc);
 int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
 u32 pixel_fmt, struct ipu_dc_if_map *new_map, u32 width);
+void ipu_dc_uninit_sync(struct ipu_dc *dc);
 void ipu_dc_enable(struct ipu_soc *ipu);
 void ipu_dc_enable_channel(struct ipu_dc *dc);
 void ipu_dc_disable_channel(struct ipu_dc *dc);
-- 
1.7.9.5



[PATCH 09/72] gpu: ipu-v3: Add support for dynamic DC interface pixel maps

2014-10-31 Thread Steve Longerbeam
Adds support to ipu-dc to dynamically create new display interface
pixel mappings.

The mappings are formally defined by a struct ipu_dc_if_map, which is
passed to ipu_dc_init_sync().

The ipu-dc maintains a list of the currently programmed mappings.
Some mappings are pre-loaded at probe time (RGB24, BGR24, GBR24,
RGB565, BGR666, and "LVDS666").

If the map pointer to ipu_dc_init_sync() is not NULL, a new mapping
is created, otherwise previously loaded mappings will be searched based
on the passed pixel_fmt.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dc.c  |  248 ++
 drivers/staging/imx-drm/ipuv3-crtc.c |2 +-
 include/video/imx-ipu-v3.h   |   23 +++-
 3 files changed, 184 insertions(+), 89 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c
index 2326c75..36c7c57 100644
--- a/drivers/gpu/ipu-v3/ipu-dc.c
+++ b/drivers/gpu/ipu-v3/ipu-dc.c
@@ -26,6 +26,7 @@

 #define DC_MAP_CONF_PTR(n) (0x108 + ((n) & ~0x1) * 2)
 #define DC_MAP_CONF_VAL(n) (0x144 + ((n) & ~0x1) * 2)
+#define DC_MAX_MAPS24

 #define DC_EVT_NF  0
 #define DC_EVT_NL  1
@@ -86,13 +87,40 @@

 struct ipu_dc_priv;

-enum ipu_dc_map {
-   IPU_DC_MAP_RGB24,
-   IPU_DC_MAP_RGB565,
-   IPU_DC_MAP_GBR24, /* TVEv2 */
-   IPU_DC_MAP_BGR666,
-   IPU_DC_MAP_LVDS666,
-   IPU_DC_MAP_BGR24,
+/* some pre-defined maps */
+static struct ipu_dc_if_map predef_maps[] = {
+   {
+   .src_mask = {0xff, 0xff, 0xff},
+   .dest_msb = {7, 15, 23},
+   .v4l2_fmt = V4L2_PIX_FMT_RGB24,
+   }, {
+   .src_mask = {0xf8, 0xfc, 0xf8},
+   .dest_msb = {4, 10, 15},
+   .v4l2_fmt = V4L2_PIX_FMT_RGB565,
+   }, {
+   /* V4L2_PIX_FMT_GBR24, for TVEv2 */
+   .src_mask = {0xff, 0xff, 0xff},
+   .dest_msb = {23, 7, 15},
+   .v4l2_fmt = v4l2_fourcc('G', 'B', 'R', '3'),
+   }, {
+   .src_mask = {0xfc, 0xfc, 0xfc},
+   .dest_msb = {17, 11, 5},
+   .v4l2_fmt = V4L2_PIX_FMT_BGR666,
+   }, {
+   .src_mask = {0xfc, 0xfc, 0xfc},
+   .dest_msb = {21, 13, 5},
+   .v4l2_fmt = v4l2_fourcc('L', 'V', 'D', '6'),
+   }, {
+   .src_mask = {0xff, 0xff, 0xff},
+   .dest_msb = {23, 15, 7},
+   .v4l2_fmt = V4L2_PIX_FMT_BGR24,
+   },
+};
+
+struct dc_if_map_priv {
+   struct ipu_dc_if_map map;
+   int mapnr;
+   struct list_head list;
 };

 struct ipu_dc {
@@ -110,12 +138,20 @@ struct ipu_dc_priv {
struct ipu_soc  *ipu;
struct device   *dev;
struct ipu_dc   channels[IPU_DC_NUM_CHANNELS];
+   struct list_headmap_list;
+   int next_map;
struct mutexmutex;
struct completion   comp;
int dc_irq;
int dp_irq;
 };

+/* forward references */
+static void ipu_dc_map_config(struct ipu_dc_priv *priv,
+ struct dc_if_map_priv *map);
+static void ipu_dc_map_clear(struct ipu_dc_priv *priv,
+struct dc_if_map_priv *map);
+
 static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
 {
u32 reg;
@@ -146,39 +182,91 @@ static void dc_write_tmpl(struct ipu_dc *dc, int word, 
u32 opcode, u32 operand,
writel(reg2, priv->dc_tmpl_reg + word * 8 + 4);
 }

-static int ipu_pixfmt_to_map(u32 fmt)
+static inline bool identical_mapping(struct ipu_dc_if_map *map1,
+struct ipu_dc_if_map *map2)
 {
-   switch (fmt) {
-   case V4L2_PIX_FMT_RGB24:
-   return IPU_DC_MAP_RGB24;
-   case V4L2_PIX_FMT_RGB565:
-   return IPU_DC_MAP_RGB565;
-   case IPU_PIX_FMT_GBR24:
-   return IPU_DC_MAP_GBR24;
-   case V4L2_PIX_FMT_BGR666:
-   return IPU_DC_MAP_BGR666;
-   case v4l2_fourcc('L', 'V', 'D', '6'):
-   return IPU_DC_MAP_LVDS666;
-   case V4L2_PIX_FMT_BGR24:
-   return IPU_DC_MAP_BGR24;
-   default:
-   return -EINVAL;
+   int i;
+
+   for (i = 0; i < 3; i++) {
+   if (map1->src_mask[i] != map2->src_mask[i] ||
+   map1->dest_msb[i] != map2->dest_msb[i])
+   return false;
+   }
+
+   return true;
+}
+
+/* priv->mutex held when calling */
+static struct dc_if_map_priv *ipu_dc_new_map(struct ipu_dc_priv *priv,
+struct ipu_dc_if_map *new_map)
+{
+   struct dc_if_map_priv *entry;
+
+   /* first search for an existing map that matches */
+   list_for_each_entry(entry, >map_list, list) {
+   if (identical_mapping(>map, new_map))
+   return entry;
+   }
+
+   if 

[PATCH 08/72] gpu: ipu-v3: Add ipu_dp_set_gamma_correction()

2014-10-31 Thread Steve Longerbeam
Adds the function ipu_dp_set_gamma_correction(), which programs the
piecewise linear curve that approximates a gamma correction curve.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dp.c |   46 +++
 include/video/imx-ipu-v3.h  |2 ++
 2 files changed, 48 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index e4026f1..472acd6 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -29,6 +29,8 @@
 #define DP_COM_CONF0x0
 #define DP_GRAPH_WIND_CTRL 0x0004
 #define DP_FG_POS  0x0008
+#define DP_GAMMA_C(i)  (0x0014 + ((i) / 2) * 4)
+#define DP_GAMMA_S(i)  (0x0034 + ((i) / 4) * 4)
 #define DP_CSC_A_0 0x0044
 #define DP_CSC_A_1 0x0048
 #define DP_CSC_A_2 0x004C
@@ -45,6 +47,8 @@
 #define DP_COM_CONF_CSC_DEF_FG (3 << 8)
 #define DP_COM_CONF_CSC_DEF_BG (2 << 8)
 #define DP_COM_CONF_CSC_DEF_BOTH   (1 << 8)
+#define DP_COM_CONF_GAMMA_EN   (1 << 12)
+#define DP_COM_CONF_GAMMA_YUV_EN   (1 << 13)

 #define IPUV3_NUM_FLOWS3

@@ -208,6 +212,48 @@ int ipu_dp_set_chroma_key(struct ipu_dp *dp, bool enable, 
u32 color_key)
 }
 EXPORT_SYMBOL(ipu_dp_set_chroma_key);

+/*
+ * Programs a piecewise linear curve that approximates the gamma curve.
+ * Sixteen lines in the curve must be provided, that is, m[] and b[]
+ * must each have sixteen entries, where m[] and b[] contain the slope
+ * and y-intercept of each line respectively.
+ */
+int ipu_dp_set_gamma_correction(struct ipu_dp *dp, bool enable, u32 *m, u32 *b)
+{
+   struct ipu_flow *flow = to_flow(dp);
+   struct ipu_dp_priv *priv = flow->priv;
+   u32 reg;
+   int i;
+
+   mutex_lock(>mutex);
+
+   for (i = 0; i < 16; i += 2)
+   writel((b[i] & 0x1ff) | ((b[i + 1] & 0x1ff) << 16),
+  flow->base + DP_GAMMA_C(i));
+   for (i = 0; i < 16; i += 4)
+   writel((m[i] & 0xff) | ((m[i + 1] & 0xff) << 8) |
+  ((m[i + 2] & 0xff) << 16) | ((m[i + 3] & 0xff) << 24),
+  flow->base + DP_GAMMA_S(i));
+
+   reg = readl(flow->base + DP_COM_CONF);
+   if (enable) {
+   if (flow->out_cs == IPUV3_COLORSPACE_YUV)
+   reg |= DP_COM_CONF_GAMMA_YUV_EN;
+   else
+   reg &= ~DP_COM_CONF_GAMMA_YUV_EN;
+   reg |= DP_COM_CONF_GAMMA_EN;
+   } else
+   reg &= ~DP_COM_CONF_GAMMA_EN;
+   writel(reg, flow->base + DP_COM_CONF);
+
+   ipu_srm_dp_sync_update(priv->ipu);
+
+   mutex_unlock(>mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL(ipu_dp_set_gamma_correction);
+
 int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
 {
struct ipu_flow *flow = to_flow(dp);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index e878343..6fa86c7 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -274,6 +274,8 @@ int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 
y_pos);
 int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
bool bg_chan);
 int ipu_dp_set_chroma_key(struct ipu_dp *dp, bool enable, u32 color_key);
+int ipu_dp_set_gamma_correction(struct ipu_dp *dp, bool enable,
+   u32 *m, u32 *b);

 /*
  * IPU CMOS Sensor Interface (csi) functions
-- 
1.7.9.5



[PATCH 07/72] gpu: ipu-v3: Add ipu_dp_set_chroma_key()

2014-10-31 Thread Steve Longerbeam
Adds the function ipu_dp_set_chroma_key(), which sets up a color key
value for a DP foreground plane.

ipu_dp_set_chroma_key() accepts a color key value in RGB24 format.
If the combiner unit colorspace is YUV, the key must be converted
to YUV444, using the same CSC coefficients as programmed in the DP.
So pull out the CSC coefficients from ipu_dp_csc_init() to make
them available to rgb24_to_yuv444() that converts to color key.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-dp.c |  121 ---
 include/video/imx-ipu-v3.h  |1 +
 2 files changed, 103 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c
index 98686ed..e4026f1 100644
--- a/drivers/gpu/ipu-v3/ipu-dp.c
+++ b/drivers/gpu/ipu-v3/ipu-dp.c
@@ -84,6 +84,52 @@ static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
return container_of(dp, struct ipu_flow, background);
 }

+static const int rgb2yuv_coeff[5][3] = {
+   { 0x0099, 0x012d, 0x003a },
+   { 0x03a9, 0x0356, 0x0100 },
+   { 0x0100, 0x0329, 0x03d6 },
+   { 0x, 0x0200, 0x0200 }, /* B0, B1, B2 */
+   { 0x2,0x2,0x2 },/* S0, S1, S2 */
+};
+
+static const int yuv2rgb_coeff[5][3] = {
+   { 0x0095, 0x, 0x00cc },
+   { 0x0095, 0x03ce, 0x0398 },
+   { 0x0095, 0x00ff, 0x },
+   { 0x3e42, 0x010a, 0x3dd6 }, /* B0,B1,B2 */
+   { 0x1,0x1,0x1 },/* S0,S1,S2 */
+};
+
+/*
+ * This is used to convert an RGB24 color key to YUV444, using
+ * the same CSC coefficients as programmed in the DP.
+ */
+static u32 rgb24_to_yuv444(u32 rgb24)
+{
+   u32 red, green, blue;
+   int i, c[3];
+
+   red   = (rgb24 >> 16) & 0xff;
+   green = (rgb24 >>  8) & 0xff;
+   blue  = (rgb24 >>  0) & 0xff;
+
+   for (i = 0; i < 3; i++) {
+   c[i] = red * rgb2yuv_coeff[i][0];
+   c[i] += green * rgb2yuv_coeff[i][1];
+   c[i] += blue * rgb2yuv_coeff[i][2];
+   c[i] /= 16;
+   c[i] += rgb2yuv_coeff[3][i] * 4;
+   c[i] += 8;
+   c[i] /= 16;
+   if (c[i] < 0)
+   c[i] = 0;
+   if (c[i] > 255)
+   c[i] = 255;
+   }
+
+   return (c[0] << 16) | (c[1] << 8) | c[2];
+}
+
 int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
u8 alpha, bool bg_chan)
 {
@@ -120,6 +166,48 @@ int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
 }
 EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);

+/*
+ * The input color_key must always be RGB24. It will be converted to
+ * YUV444 if the pixel format to the Combining unit is YUV space.
+ */
+int ipu_dp_set_chroma_key(struct ipu_dp *dp, bool enable, u32 color_key)
+{
+   struct ipu_flow *flow = to_flow(dp);
+   struct ipu_dp_priv *priv = flow->priv;
+   enum ipu_color_space combiner_cs;
+   u32 reg;
+
+   mutex_lock(>mutex);
+
+   if (flow->foreground.in_cs == flow->background.in_cs)
+   combiner_cs = flow->foreground.in_cs;
+   else
+   combiner_cs = flow->out_cs;
+
+   if (combiner_cs == IPUV3_COLORSPACE_YUV)
+   color_key = rgb24_to_yuv444(color_key);
+
+   color_key &= 0x00ff;
+
+   if (enable) {
+   reg = readl(flow->base + DP_GRAPH_WIND_CTRL) & ~0x00FFL;
+   writel(reg | color_key, flow->base + DP_GRAPH_WIND_CTRL);
+
+   reg = readl(flow->base + DP_COM_CONF);
+   writel(reg | DP_COM_CONF_GWCKE, flow->base + DP_COM_CONF);
+   } else {
+   reg = readl(flow->base + DP_COM_CONF);
+   writel(reg & ~DP_COM_CONF_GWCKE, flow->base + DP_COM_CONF);
+   }
+
+   ipu_srm_dp_sync_update(priv->ipu);
+
+   mutex_unlock(>mutex);
+
+   return 0;
+}
+EXPORT_SYMBOL(ipu_dp_set_chroma_key);
+
 int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
 {
struct ipu_flow *flow = to_flow(dp);
@@ -138,6 +226,7 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
enum ipu_color_space out,
u32 place)
 {
+   const int (*c)[3];
u32 reg;

reg = readl(flow->base + DP_COM_CONF);
@@ -148,25 +237,19 @@ static void ipu_dp_csc_init(struct ipu_flow *flow,
return;
}

-   if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
-   writel(0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
-   writel(0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
-   writel(0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
-   writel(0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
-   writel(0x3d6 | (0x << 16) | (2 << 30),
-   flow->base + DP_CSC_0);
-   writel(0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
-   flow->base + DP_CSC_1);
-   } else {
-   

[PATCH 06/72] gpu: ipu-cpmem: Add ipu_cpmem_set_uv_offset()

2014-10-31 Thread Steve Longerbeam
Adds ipu_cpmem_set_uv_offset(), to set planar U/V offsets.

Signed-off-by: Steve Longerbeam 
---
 drivers/gpu/ipu-v3/ipu-cpmem.c |7 +++
 include/video/imx-ipu-v3.h |1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c
index 3bf05bc..2c93e9c 100644
--- a/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ b/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -253,6 +253,13 @@ void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int 
bufnum, dma_addr_t buf)
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_buffer);

+void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off)
+{
+   ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_off / 8);
+   ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_off / 8);
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_uv_offset);
+
 void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride)
 {
ipu_ch_param_write_field(ch, IPU_FIELD_SO, 1);
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index c74bf4a..03cda50 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -195,6 +195,7 @@ void ipu_cpmem_set_resolution(struct ipuv3_channel *ch, int 
xres, int yres);
 void ipu_cpmem_set_stride(struct ipuv3_channel *ch, int stride);
 void ipu_cpmem_set_high_priority(struct ipuv3_channel *ch);
 void ipu_cpmem_set_buffer(struct ipuv3_channel *ch, int bufnum, dma_addr_t 
buf);
+void ipu_cpmem_set_uv_offset(struct ipuv3_channel *ch, u32 u_off, u32 v_off);
 void ipu_cpmem_interlaced_scan(struct ipuv3_channel *ch, int stride);
 void ipu_cpmem_set_axi_id(struct ipuv3_channel *ch, u32 id);
 void ipu_cpmem_set_burstsize(struct ipuv3_channel *ch, int burstsize);
-- 
1.7.9.5



[PATCH 05/72] ARM: i.MX6: select pll3_usb_otg for ldb_di for rev 1.0 chip

2014-10-31 Thread Steve Longerbeam
Select pll3_usb_otg for ldb_di clock for rev 1.0 chips.

Signed-off-by: Jiada Wang 
Signed-off-by: Steve Longerbeam 
---
 arch/arm/mach-imx/clk-imx6q.c |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 86b58fc..68064a6 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -481,6 +481,9 @@ static void __init imx6q_clocks_init(struct device_node 
*ccm_node)
cpu_is_imx6dl()) {
clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+   } else {
+   clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], 
clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+   clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], 
clk[IMX6QDL_CLK_PLL3_USB_OTG]);
}

clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], 
clk[IMX6QDL_CLK_PLL2_PFD0_352M]);
-- 
1.7.9.5



[PATCH 04/72] ARM: i.MX6: use pll2_pfd0_352m as clock root of ipu_di

2014-10-31 Thread Steve Longerbeam
AS pll5_video_div has already been used as clock root for ldb_di,
so use pll2_pfd0_352m as clock root of ipu_di for HDMI.

Signed-off-by: Jiada Wang 
Signed-off-by: Steve Longerbeam 
---
 arch/arm/mach-imx/clk-imx6q.c |8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 4e79da7..86b58fc 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -483,10 +483,10 @@ static void __init imx6q_clocks_init(struct device_node 
*ccm_node)
clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
}

-   clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-   clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-   clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-   clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], 
clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
+   clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL], 
clk[IMX6QDL_CLK_PLL2_PFD0_352M]);
+   clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL], 
clk[IMX6QDL_CLK_PLL2_PFD0_352M]);
+   clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL], 
clk[IMX6QDL_CLK_PLL2_PFD0_352M]);
+   clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], 
clk[IMX6QDL_CLK_PLL2_PFD0_352M]);
clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI0_SEL], 
clk[IMX6QDL_CLK_IPU1_DI0_PRE]);
clk_set_parent(clk[IMX6QDL_CLK_IPU1_DI1_SEL], 
clk[IMX6QDL_CLK_IPU1_DI1_PRE]);
clk_set_parent(clk[IMX6QDL_CLK_IPU2_DI0_SEL], 
clk[IMX6QDL_CLK_IPU2_DI0_PRE]);
-- 
1.7.9.5



[PATCH 03/72] ARM: dts: imx6qdl: Create imx-drm crtc nodes

2014-10-31 Thread Steve Longerbeam
Create imx-drm crtc device nodes. Each crtc node requires the following
parameters:

- parent ipu phandle.
- di number.
- port endpoints.

Optionally the node can specify a "dual-plane" boolean parameter
to configure the crtc device with a foreground plane. If not given,
the crtc will have only a single plane.

The crtc port lists the endpoints to the remote encoder endpoints.
These endpoints were moved out of the ipu nodes, since they more
logically now belong to the crtc nodes.

As a result, the display-subsystem node should enumerate its crtcs
instead of the former ipu ports.

Signed-off-by: Steve Longerbeam 
---
 arch/arm/boot/dts/imx6dl.dtsi  |2 +-
 arch/arm/boot/dts/imx6q.dtsi   |  116 --
 arch/arm/boot/dts/imx6qdl.dtsi |  122 +---
 3 files changed, 127 insertions(+), 113 deletions(-)

diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index b453e0e..05af0f4 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -98,7 +98,7 @@

display-subsystem {
compatible = "fsl,imx-display-subsystem";
-   ports = <_di0>, <_di1>;
+   crtcs = <>, <>;
};
 };

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index e9f3646..9d1f88c 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -140,6 +140,59 @@
};
};

+   crtc2: crtc at 2 {
+   compatible = "fsl,imx-ipuv3-crtc";
+   ipu = <>;
+   di = <0>;
+   dual-plane;
+
+   port {
+   crtc2_disp0: endpoint at 0 {
+   };
+
+   crtc2_hdmi: endpoint at 1 {
+   remote-endpoint = <_mux_2>;
+   };
+
+   crtc2_mipi: endpoint at 2 {
+   };
+
+   crtc2_lvds0: endpoint at 3 {
+   remote-endpoint = <_mux_2>;
+   };
+
+   crtc2_lvds1: endpoint at 4 {
+   remote-endpoint = <_mux_2>;
+   };
+   };
+   };
+
+   crtc3: crtc at 3 {
+   compatible = "fsl,imx-ipuv3-crtc";
+   ipu = <>;
+   di = <1>;
+
+   port {
+   crtc3_disp0: endpoint at 0 {
+   };
+
+   crtc3_hdmi: endpoint at 1 {
+   remote-endpoint = <_mux_3>;
+   };
+
+   crtc3_mipi: endpoint at 2 {
+   };
+
+   crtc3_lvds0: endpoint at 3 {
+   remote-endpoint = <_mux_3>;
+   };
+
+   crtc3_lvds1: endpoint at 4 {
+   remote-endpoint = <_mux_3>;
+   };
+   };
+   };
+
sata: sata at 0220 {
compatible = "fsl,imx6q-ahci";
reg = <0x0220 0x4000>;
@@ -171,57 +224,12 @@
ipu2_csi1: port at 1 {
reg = <1>;
};
-
-   ipu2_di0: port at 2 {
-   #address-cells = <1>;
-   #size-cells = <0>;
-   reg = <2>;
-
-   ipu2_di0_disp0: endpoint at 0 {
-   };
-
-   ipu2_di0_hdmi: endpoint at 1 {
-   remote-endpoint = <_mux_2>;
-   };
-
-   ipu2_di0_mipi: endpoint at 2 {
-   };
-
-   ipu2_di0_lvds0: endpoint at 3 {
-   remote-endpoint = <_mux_2>;
-   };
-
-   ipu2_di0_lvds1: endpoint at 4 {
-   remote-endpoint = <_mux_2>;
-   };
-   };
-
-   ipu2_di1: port at 3 {
-   #address-cells = <1>;
-   #size-cells = <0>;
-   reg = <3>;
-
-   ipu2_di1_hdmi: endpoint at 1 {
-   remote-endpoint = <_mux_3>;
-   };
-
-

[PATCH 02/72] ARM: dts: imx6qdl-sabreauto: Add HDMI device

2014-10-31 Thread Steve Longerbeam
From: "George G. Davis" 

Signed-off-by: George G. Davis 
---
 arch/arm/boot/dts/imx6qdl-sabreauto.dtsi |5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi 
b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 009abd6..1bb3ead 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -182,6 +182,11 @@
};
 };

+ {
+   ddc-i2c-bus = <>;
+   status = "okay";
+};
+
  {
pinctrl-names = "default";
pinctrl-0 = <_hog>;
-- 
1.7.9.5



[PATCH 01/72] ARM: dts: imx6qdl-sabrelite: Add HDMI device

2014-10-31 Thread Steve Longerbeam
Adds hdmi with DDC on i2c2.

Signed-off-by: Steve Longerbeam 
---
 arch/arm/boot/dts/imx6qdl-sabrelite.dtsi |   19 +++
 1 file changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi 
b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 0a36129..577e4fd 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -173,6 +173,11 @@
status = "okay";
 };

+ {
+   ddc-i2c-bus = <>;
+   status = "okay";
+};
+
  {
clock-frequency = <10>;
pinctrl-names = "default";
@@ -188,6 +193,13 @@
};
 };

+ {
+   status = "okay";
+   clock-frequency = <10>;
+   pinctrl-names = "default";
+   pinctrl-0 = <_i2c2>;
+};
+
  {
pinctrl-names = "default";
pinctrl-0 = <_hog>;
@@ -265,6 +277,13 @@
>;
};

+   pinctrl_i2c2: i2c2grp {
+   fsl,pins = <
+   MX6QDL_PAD_KEY_COL3__I2C2_SCL   
0x4001b8b1
+   MX6QDL_PAD_KEY_ROW3__I2C2_SDA   
0x4001b8b1
+   >;
+   };
+
pinctrl_pwm1: pwm1grp {
fsl,pins = <
MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
-- 
1.7.9.5



[PATCH 00/72] staging imx-drm new features and fixes

2014-10-31 Thread Steve Longerbeam
Hi, this affects only Freescale imx IPU and imx-drm staging drivers,
except for two patches that affect drm core (patch 53 and 63, see below).

New features for imx-drm staging driver:

- Support for multi-display (HDMI and LVDS).
- Support for global alpha and color-key properties for overlay plane.
- Support for gamma correction.
- The imx-drm crtc devices moved to device tree.
- Support for defining custom display interface pixel mappings in the
  device tree.
- Implements encoder DPMS for LVDS.
- YUV planar pixel formats supported for DRM framebuffers.
- DDC support added for LVDS.
- Page flip handling moved to imx plane driver and implemented with
  IPU double-buffering.
- Support page-flip in the overlay plane (patch 53 affects drm core).
- Add support for parsing pixel clock edge select (patch 63 affects drm core).
- Add LVDS connection detect via drm_probe_ddc().
- Implement crtc mode_set_base using plane page-flip.


Fixed issues:

- HDMI and LVDS now use different PLL clock roots (part of multi-display
  support).
- Use counter added to IPU DC enable/disable (part of multi-display
  support).
- Fixed some HDMI timing issues.
- Wider range of supported DI pixel clocks generated (all EDID modes
  reported from HDMI displays now work).
- Fix separate primary plane objects.
- HDMI must select DI pre clock as DI clock parent during encoder prepare
  (LVDS may have switched DI clock to LDB parent, part of multi-display
  support).
- Assign correct DMFC burst size.
- Resolve some DI synchronous display error cases.



George G. Davis (1):
  ARM: dts: imx6qdl-sabreauto: Add HDMI device

Jiada Wang (1):
  gpu: ipu-v3: fix HDMI timing issues

Steve Longerbeam (70):
  ARM: dts: imx6qdl-sabrelite: Add HDMI device
  ARM: dts: imx6qdl: Create imx-drm crtc nodes
  ARM: i.MX6: use pll2_pfd0_352m as clock root of ipu_di
  ARM: i.MX6: select pll3_usb_otg for ldb_di for rev 1.0 chip
  gpu: ipu-cpmem: Add ipu_cpmem_set_uv_offset()
  gpu: ipu-v3: Add ipu_dp_set_chroma_key()
  gpu: ipu-v3: Add ipu_dp_set_gamma_correction()
  gpu: ipu-v3: Add support for dynamic DC interface pixel maps
  gpu: ipu-v3: Add ipu_dc_uninit_sync()
  gpu: ipu-v3: Pass struct ipu_dc to enable/disable
  gpu: ipu-v3: Add ipu_dp_uninit_channel()
  gpu: ipu-v3: Pass struct ipu_dp to enable/disable
  gpu: ipu-v3: Implement use counter for ipu_dc_enable(),
ipu_dc_disable()
  gpu: ipu-v3: Add DMFC/DP/DC/DI module enable/disable debug
  gpu: ipu-v3: Add ipu_di_uninit_sync_panel()
  gpu: ipu-v3: Split out DI clock enable/disable
  gpu: ipu-v3: Protect more CM reg access with IPU lock
  gpu: ipu-v3: Move DI waveform counter enable/disable to ipu-di
  gpu: ipu-v3: Update DP sync SRM always in ipu_dp_enable_channel()
  gpu: ipu-v3: Fix indent/ws in ipu-dmfc
  gpu: ipu-v3: Allow burstsize of 20 in ipu_dmfc_setup_channel()
  gpu: ipu-v3: Remove ipu_dmfc_init_channel()
  gpu: ipu-v3: Consolidate mutex lock in ipu_dmfc_alloc_bandwidth()
  gpu: ipu-v3: Enumerate the DC channel names
  gpu: ipu-di: Move ipu pointer init
  gpu: ipu-di: Add and improve debug/error messages
  gpu: ipu-v3: Change signal names in struct ipu_di_signal_cfg
  gpu: ipu-v3: Remove IPU client registration
  gpu: ipu-di: Set rate of DI pre clock
  gpu: ipu-v3: Add RGB666 interface pixel map
  gpu: ipu-cpmem: Pass drm fourcc to ipu_cpmem_set_yuv_*
  gpu: ipu-v3: Add ipu_drm_fourcc_is_planar()
  gpu: ipu-v3: Add IDMA channel linking support
  gpu: ipu-cpmem: Support YVU422
  gpu: ipu-cpmem: Add ipu_cpmem_get_burstsize()
  imx-drm: Crtcs moved to device tree
  imx-drm: hdmi: optimize i2c write wait
  imx-drm: parallel-display: Support RGB666 pixel fmt
  imx-drm: imx-ldb: Add debug to connector/encoder entry points
  imx-drm: imx-ldb: Implement imx_ldb_encoder_dpms()
  imx-drm: parallel-display: Fix typo when setting mode type
  imx-drm: ipuv3-plane: Fix planar formats
  imx-drm: ipuv3-plane: Allow YUV space for background plane
  imx-drm: ipuv3-plane: Add more supported pixel formats
  imx-drm: ipuv3-plane: Implement global alpha and colorkey properties
  imx-drm: hdmi: rework irq request/free
  imx-drm: imx-ldb: Add DDC support
  imx-drm: Fix separate primary plane objects
  imx-drm: Move page flip handling to plane driver
  imx-drm: Reset ipu unit pointers to NULL on errors
  drm: implement page flipping support for planes
  imx-drm: ipuv3-plane: Assign page_flip method to drm_plane_funcs
  imx-drm: Implement DRM gamma set
  imx-drm: Implement custom ioctl to set gamma
  imx-drm: Add support for interface pixel maps
  imx-drm: parallel-display: Add interface-pix-map DT property
  imx-drm: hdmi: set DI clock source to DI pre clock
  imx-drm: ipuv3-crtc: Set the crtc device name
  imx-drm: hdmi: Save ipu/di mux for later iomux setup
  imx-drm: ipuv3-plane: Assign correct dmfc burst size
  drm_modes: videomode: add pos/neg pixel clock polarity flag
  imx-drm: ipuv3-crtc: Use DRM mode flags to configure pixel clock
polarity
  imx-drm: imx-ldb: Add all defined of video modes
  imx-drm: 

[PATCH 15/15] drm/panel: Add Sharp LQ101R1SX01 support

2014-10-31 Thread Thierry Reding
tor_disable should be enough.

Done.

> > +static int sharp_panel_probe(struct mipi_dsi_device *dsi)
> > +{
> > +   struct mipi_dsi_device *secondary = NULL;
> > +   struct sharp_panel *sharp;
> > +   struct device_node *np;
> > +   int err;
> > +
> > +   dsi->lanes = 4;
> > +   dsi->format = MIPI_DSI_FMT_RGB888;
> > +   dsi->mode_flags = 0;
> > +
> > +   /* Find DSI-LINK1 */
> > +   np = of_parse_phandle(dsi->dev.of_node, "link2", 0);
> > +   if (np) {
> > +   secondary = of_find_mipi_dsi_device_by_node(np);
> > +   of_node_put(np);
> > +
> > +   if (!secondary)
> > +   return -EPROBE_DEFER;
> > +   }
> > +
> > +   sharp = devm_kzalloc(>dev, sizeof(*sharp), GFP_KERNEL);
> > +   if (!sharp)
> > +   return -ENOMEM;
> 
> Do we really need this for LINK2 device? You can just check if
> mipi_dsi_get_drvdata
> is not null to distinguish them, I suppose.

Done.

> > +static int sharp_panel_remove(struct mipi_dsi_device *dsi)
> > +{
> > +   struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
> > +   int err;
> > +
> > +   /* only detach from host for the DSI-LINK2 interface */
> > +   if (!sharp->link2) {
> > +   mipi_dsi_detach(dsi);
> 
> There is no locking mechanism here, so it is possible that
> everything can crash if someone unbind driver from LINK2 and then try to
> enable the panel.

I don't think so. Since we're not doing anything with the DSI-LINK2
device anymore it's irrelevant whether it is bound to the driver or
not.

> > +   return 0;
> > +   }
> > +
> > +   err = sharp_panel_disable(>base);
> > +   if (err < 0)
> > +   dev_err(>dev, "failed to disable panel: %d\n", err);
> 
> IMHO calling mipi_dsi_detach below should cause connector to call panel
> disable and unprepare so the call above seems to me unnecessary.

I don't think the connector has any business doing anything with the
panel on mipi_dsi_detach(). I suppose we could implement something like
that as part of drm_panel_detach(), but that's not the case today, so
this simply follows what every other panel has done so far.

> > +
> > +   err = mipi_dsi_detach(dsi);
> > +   if (err < 0)
> > +   dev_err(>dev, "failed to detach from DSI host: %d\n", err);
> > +
> > +   drm_panel_detach(>base);
> 
> drm_panel_attach is called from tegra_dsi_host_attach,
> wouldn't be more 'symmetrical' to call drm_panel_detach from
> tegra_dsi_host_detach :)

No, it's not called from tegra_dsi_host_attach(), it's called as part of
the DSI output initialization at DRM load time.

drm_panel_detach() really needs to be called from two places: when the
panel driver is unloaded and when the connector is unloaded. It seems
like this is another area where we may have to put more thought into how
to handle it more uniformly across drivers.

Thierry
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20141031/a8398dbe/attachment.sig>


[PATCH 3/3] drm/gma500: Don't destroy DRM properties in the driver

2014-10-31 Thread Damien Lespiau
When drm properties are created, they are added to mode_config.property_list
which is then used in drm_mode_config_cleanup() to destroy every single
property created by the driver.

Cc: Patrik Jakobsson 
Signed-off-by: Damien Lespiau 
---
 drivers/gpu/drm/gma500/psb_intel_sdvo.c | 49 -
 1 file changed, 49 deletions(-)

diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c 
b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 0be96fd..58529ce 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1631,57 +1631,8 @@ static int psb_intel_sdvo_get_modes(struct drm_connector 
*connector)
return !list_empty(>probed_modes);
 }

-static void
-psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
-{
-   struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = 
to_psb_intel_sdvo_connector(connector);
-   struct drm_device *dev = connector->dev;
-
-   if (psb_intel_sdvo_connector->left)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->left);
-   if (psb_intel_sdvo_connector->right)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->right);
-   if (psb_intel_sdvo_connector->top)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->top);
-   if (psb_intel_sdvo_connector->bottom)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->bottom);
-   if (psb_intel_sdvo_connector->hpos)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->hpos);
-   if (psb_intel_sdvo_connector->vpos)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->vpos);
-   if (psb_intel_sdvo_connector->saturation)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->saturation);
-   if (psb_intel_sdvo_connector->contrast)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->contrast);
-   if (psb_intel_sdvo_connector->hue)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->hue);
-   if (psb_intel_sdvo_connector->sharpness)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness);
-   if (psb_intel_sdvo_connector->flicker_filter)
-   drm_property_destroy(dev, 
psb_intel_sdvo_connector->flicker_filter);
-   if (psb_intel_sdvo_connector->flicker_filter_2d)
-   drm_property_destroy(dev, 
psb_intel_sdvo_connector->flicker_filter_2d);
-   if (psb_intel_sdvo_connector->flicker_filter_adaptive)
-   drm_property_destroy(dev, 
psb_intel_sdvo_connector->flicker_filter_adaptive);
-   if (psb_intel_sdvo_connector->tv_luma_filter)
-   drm_property_destroy(dev, 
psb_intel_sdvo_connector->tv_luma_filter);
-   if (psb_intel_sdvo_connector->tv_chroma_filter)
-   drm_property_destroy(dev, 
psb_intel_sdvo_connector->tv_chroma_filter);
-   if (psb_intel_sdvo_connector->dot_crawl)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl);
-   if (psb_intel_sdvo_connector->brightness)
-   drm_property_destroy(dev, psb_intel_sdvo_connector->brightness);
-}
-
 static void psb_intel_sdvo_destroy(struct drm_connector *connector)
 {
-   struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = 
to_psb_intel_sdvo_connector(connector);
-
-   if (psb_intel_sdvo_connector->tv_format)
-   drm_property_destroy(connector->dev,
-psb_intel_sdvo_connector->tv_format);
-
-   psb_intel_sdvo_destroy_enhance_property(connector);
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
-- 
1.8.3.1



[PATCH 2/3] drm/i915: Don't destroy DRM properties in the driver

2014-10-31 Thread Damien Lespiau
When drm properties are created, they are added to mode_config.property_list,
which is then used in drm_mode_config_cleanup() to destroy every single
property created by the driver.

Cc: Chandra Konduru 
Cc: Daniel Vetter 
Signed-off-by: Damien Lespiau 
---
 drivers/gpu/drm/i915/intel_sdvo.c | 47 ---
 1 file changed, 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index 9350edd..6d7a277 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1991,57 +1991,10 @@ static int intel_sdvo_get_modes(struct drm_connector 
*connector)
return !list_empty(>probed_modes);
 }

-static void
-intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
-{
-   struct intel_sdvo_connector *intel_sdvo_connector = 
to_intel_sdvo_connector(connector);
-   struct drm_device *dev = connector->dev;
-
-   if (intel_sdvo_connector->left)
-   drm_property_destroy(dev, intel_sdvo_connector->left);
-   if (intel_sdvo_connector->right)
-   drm_property_destroy(dev, intel_sdvo_connector->right);
-   if (intel_sdvo_connector->top)
-   drm_property_destroy(dev, intel_sdvo_connector->top);
-   if (intel_sdvo_connector->bottom)
-   drm_property_destroy(dev, intel_sdvo_connector->bottom);
-   if (intel_sdvo_connector->hpos)
-   drm_property_destroy(dev, intel_sdvo_connector->hpos);
-   if (intel_sdvo_connector->vpos)
-   drm_property_destroy(dev, intel_sdvo_connector->vpos);
-   if (intel_sdvo_connector->saturation)
-   drm_property_destroy(dev, intel_sdvo_connector->saturation);
-   if (intel_sdvo_connector->contrast)
-   drm_property_destroy(dev, intel_sdvo_connector->contrast);
-   if (intel_sdvo_connector->hue)
-   drm_property_destroy(dev, intel_sdvo_connector->hue);
-   if (intel_sdvo_connector->sharpness)
-   drm_property_destroy(dev, intel_sdvo_connector->sharpness);
-   if (intel_sdvo_connector->flicker_filter)
-   drm_property_destroy(dev, intel_sdvo_connector->flicker_filter);
-   if (intel_sdvo_connector->flicker_filter_2d)
-   drm_property_destroy(dev, 
intel_sdvo_connector->flicker_filter_2d);
-   if (intel_sdvo_connector->flicker_filter_adaptive)
-   drm_property_destroy(dev, 
intel_sdvo_connector->flicker_filter_adaptive);
-   if (intel_sdvo_connector->tv_luma_filter)
-   drm_property_destroy(dev, intel_sdvo_connector->tv_luma_filter);
-   if (intel_sdvo_connector->tv_chroma_filter)
-   drm_property_destroy(dev, 
intel_sdvo_connector->tv_chroma_filter);
-   if (intel_sdvo_connector->dot_crawl)
-   drm_property_destroy(dev, intel_sdvo_connector->dot_crawl);
-   if (intel_sdvo_connector->brightness)
-   drm_property_destroy(dev, intel_sdvo_connector->brightness);
-}
-
 static void intel_sdvo_destroy(struct drm_connector *connector)
 {
struct intel_sdvo_connector *intel_sdvo_connector = 
to_intel_sdvo_connector(connector);

-   if (intel_sdvo_connector->tv_format)
-   drm_property_destroy(connector->dev,
-intel_sdvo_connector->tv_format);
-
-   intel_sdvo_destroy_enhance_property(connector);
drm_connector_cleanup(connector);
kfree(intel_sdvo_connector);
 }
-- 
1.8.3.1



[PATCH 1/3] drm: Add a note to drm_property_create() about property lifetime

2014-10-31 Thread Damien Lespiau
Cc: Chandra Konduru 
Cc: Daniel Vetter 
Signed-off-by: Damien Lespiau 
---
 drivers/gpu/drm/drm_crtc.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 4081d7a..0f3c24c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3417,6 +3417,10 @@ void drm_fb_release(struct drm_file *priv)
  * object with drm_object_attach_property. The returned property object must be
  * freed with drm_property_destroy.
  *
+ * Note that the DRM core keeps a per-device list of properties and that, if
+ * drm_mode_config_cleanup() is called, it will destroy all properties created
+ * by the driver.
+ *
  * Returns:
  * A pointer to the newly created property on success, NULL on failure.
  */
-- 
1.8.3.1



[PATCH 9/9] drm/exynos: remove leftover hdmi function declarations

2014-10-31 Thread Gustavo Padovan
From: Gustavo Padovan 

They are not implemented anywhere, so wipe them out.

Signed-off-by: Gustavo Padovan 
---
 drivers/gpu/drm/exynos/exynos_drm_drv.h | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index e762cbb..262a459 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -294,17 +294,6 @@ int exynos_drm_device_subdrv_remove(struct drm_device 
*dev);
 int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file);
 void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file);

-/*
- * this function registers exynos drm hdmi platform device. It ensures only one
- * instance of the device is created.
- */
-int exynos_platform_device_hdmi_register(void);
-
-/*
- * this function unregisters exynos drm hdmi platform device if it exists.
- */
-void exynos_platform_device_hdmi_unregister(void);
-
 #ifdef CONFIG_DRM_EXYNOS_IPP
 int exynos_platform_device_ipp_register(void);
 void exynos_platform_device_ipp_unregister(void);
-- 
1.9.3



[PATCH 8/9] drm/exynos: update documentation to reflect code changes

2014-10-31 Thread Gustavo Padovan
From: Gustavo Padovan 

Description of the @create_connector callback was missing,
and the @manager was no longer needed.

Signed-off-by: Gustavo Padovan 
---
 drivers/gpu/drm/exynos/exynos_drm_drv.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index f77e6aa..e762cbb 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -110,6 +110,7 @@ struct exynos_drm_overlay {
  * Exynos DRM Display Structure.
  * - this structure is common to analog tv, digital tv and lcd panel.
  *
+ * @create_connector: initialize and register a new connector
  * @remove: cleans up the display for removal
  * @mode_fixup: fix mode data comparing to hw specific display mode.
  * @mode_set: convert drm_display_mode to hw specific display mode and
@@ -262,8 +263,6 @@ struct exynos_drm_private {
  * @dev: pointer to device object for subdrv device driver.
  * @drm_dev: pointer to drm_device and this pointer would be set
  * when sub driver calls exynos_drm_subdrv_register().
- * @manager: subdrv has its own manager to control a hardware appropriately
- * and we can access a hardware drawing on this manager.
  * @probe: this callback would be called by exynos drm driver after
  * subdrv is registered to it.
  * @remove: this callback is used to release resources created
-- 
1.9.3



[PATCH 7/9] drm/exynos: Save up space using bool var as bitfields

2014-10-31 Thread Gustavo Padovan
From: Gustavo Padovan 

Save a few bytes by compiling them all in the same byte.

Signed-off-by: Gustavo Padovan 
---
 drivers/gpu/drm/exynos/exynos_drm_drv.h | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 9e4a7e1..f77e6aa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -66,10 +66,10 @@ enum exynos_drm_output_type {
  * @dma_addr: array of bus(accessed by dma) address to the memory region
  *   allocated for a overlay.
  * @zpos: order of overlay layer(z position).
- * @default_win: a window to be enabled.
- * @color_key: color key on or off.
  * @index_color: if using color key feature then this value would be used
  * as index color.
+ * @default_win: a window to be enabled.
+ * @color_key: color key on or off.
  * @local_path: in case of lcd type, local path mode on or off.
  * @transparency: transparency on or off.
  * @activated: activated or not.
@@ -97,13 +97,13 @@ struct exynos_drm_overlay {
uint32_t pixel_format;
dma_addr_t dma_addr[MAX_FB_BUFFER];
int zpos;
-
-   bool default_win;
-   bool color_key;
unsigned int index_color;
-   bool local_path;
-   bool transparency;
-   bool activated;
+
+   bool default_win:1;
+   bool color_key:1;
+   bool local_path:1;
+   bool transparency:1;
+   bool activated:1;
 };

 /*
-- 
1.9.3



[PATCH 6/9] drm/exynos: remove unused wait_for macro

2014-10-31 Thread Gustavo Padovan
From: Gustavo Padovan 

This is a leftover, all code using this macro have been removed/
changed already.

Signed-off-by: Gustavo Padovan 
---
 drivers/gpu/drm/exynos/exynos_drm_drv.h | 14 --
 1 file changed, 14 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 7806981..9e4a7e1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -23,20 +23,6 @@
 #define MAX_FB_BUFFER  4
 #define DEFAULT_ZPOS   -1

-#define _wait_for(COND, MS) ({ \
-   unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);   \
-   int ret__ = 0;  \
-   while (!(COND)) {   \
-   if (time_after(jiffies, timeout__)) {   \
-   ret__ = -ETIMEDOUT; \
-   break;  \
-   }   \
-   }   \
-   ret__;  \
-})
-
-#define wait_for(COND, MS) _wait_for(COND, MS)
-
 /* This enumerates device type. */
 enum exynos_drm_device_type {
EXYNOS_DEVICE_TYPE_NONE,
-- 
1.9.3



[PATCH 5/9] drm/exynos: Replace repeated declarations by #include "exynos_drm_drv.h"

2014-10-31 Thread Gustavo Padovan
From: Gustavo Padovan 

Re-declare struct is not a good practice, let's use the original
drm and exynos declarations.

Signed-off-by: Gustavo Padovan 
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.h | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h 
b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 690dcdd..e353d35 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -15,10 +15,7 @@
 #ifndef _EXYNOS_DRM_CRTC_H_
 #define _EXYNOS_DRM_CRTC_H_

-struct drm_device;
-struct drm_crtc;
-struct exynos_drm_manager;
-struct exynos_drm_overlay;
+#include "exynos_drm_drv.h"

 int exynos_drm_crtc_create(struct exynos_drm_manager *manager);
 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
-- 
1.9.3



  1   2   >