[PATCH v4 1/2] drm: bridge: Add sii902x driver

2016-06-01 Thread Daniel Vetter
On Wed, Jun 01, 2016 at 06:03:37PM +0200, Boris Brezillon wrote:
> On Tue, 17 May 2016 08:47:11 +0200
> Daniel Vetter  wrote:
> 
> > > +static struct drm_encoder *sii902x_best_encoder(struct drm_connector 
> > > *connector)
> > > +{
> > > + struct sii902x *sii902x = connector_to_sii902x(connector);
> > > +
> > > + return sii902x->bridge.encoder;
> > > +}  
> > 
> > drm_atomic_helper_best_encoder should do exactly this for you. If you feel
> > board pimp the atomic helpers to call that one by default to even remove
> > the vfunc assingment line ;-)
> 
> Just to be sure, is that what you had in mind?

Exactly, I'll pick this one up for drm-misc. btw if you're even more
motivated, you can go through all drivers with a static mapping from
connector to encoder, and nuke those functions. Since if it's just a
static mapping, the only way to do it is like the helper does.

Thanks, Daniel
> 
> --->8---
> From d218b7ea16ca35452b3174c83a207ecd406e5c88 Mon Sep 17 00:00:00 2001
> From: Boris Brezillon 
> Date: Wed, 1 Jun 2016 17:57:18 +0200
> Subject: [PATCH] drm: atomic: Handle funcs->best_encoder == NULL case
> 
> Fallback drm_atomic_helper_best_encoder() is funcs->best_encoder() is NULL
> so that DRM drivers can leave this hook unassigned if they know they want
> to use drm_atomic_helper_best_encoder().
> 
> Signed-off-by: Boris Brezillon 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index ddfa0d1..f6a3350 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -110,8 +110,10 @@ static int handle_conflicting_encoders(struct 
> drm_atomic_state *state,
>  
>   if (funcs->atomic_best_encoder)
>   new_encoder = funcs->atomic_best_encoder(connector, 
> conn_state);
> - else
> + else if (funcs->best_encoder)
>   new_encoder = funcs->best_encoder(connector);
> + else
> + new_encoder = drm_atomic_helper_best_encoder(connector);
>  
>   if (new_encoder) {
>   if (encoder_mask & (1 << 
> drm_encoder_index(new_encoder))) {
> 
> 
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[RFT v3] drm: use late_initcall() for amdkfd and radeon

2016-06-01 Thread Luis R. Rodriguez
On Tue, May 31, 2016 at 09:04:53PM +0200, Daniel Vetter wrote:
> On Tue, May 31, 2016 at 06:58:34PM +0200, Luis R. Rodriguez wrote:
> > On Sun, May 29, 2016 at 08:27:07PM +0200, Daniel Vetter wrote:
> > > On Fri, May 27, 2016 at 3:18 AM, Luis R. Rodriguez  
> > > wrote:
> > > > To get KFD support in radeon we need the following
> > > > initialization to happen in this order, their
> > > > respective driver file that has its init routine
> > > > listed next to it:
> > > >
> > > > 0. AMD IOMMUv1:arch/x86/kernel/pci-dma.c
> > > > 1. AMD IOMMUv2:drivers/iommu/amd_iommu_v2.c
> > > > 2. AMD KFD:drivers/gpu/drm/amd/amdkfd/kfd_module.c
> > > > 3. AMD Radeon: drivers/gpu/drm/radeon/radeon_drv.c
> > > >
> > > > Order is rather implicit, but these drivers can currently
> > > > only do so much given the amount of leg room available.
> > > > Below are the respective init routines and how they are
> > > > initialized:
> > > >
> > > > arch/x86/kernel/pci-dma.c   rootfs_initcall(pci_iommu_init);
> > > > drivers/iommu/amd_iommu_v2.cmodule_init(amd_iommu_v2_init);
> > > > drivers/gpu/drm/amd/amdkfd/kfd_module.c module_init(kfd_module_init);
> > > > drivers/gpu/drm/radeon/radeon_drv.c module_init(radeon_init);
> > > >
> > > > When a driver is built-in module_init() folds to use
> > > > device_initcall(), and we have the following possible
> > > > orders:
> > > >
> > > > #define pure_initcall(fn)__define_initcall(fn, 0)
> > > > #define core_initcall(fn)__define_initcall(fn, 1)
> > > > #define postcore_initcall(fn)__define_initcall(fn, 2)
> > > > #define arch_initcall(fn)__define_initcall(fn, 3)
> > > > #define subsys_initcall(fn)  __define_initcall(fn, 4)
> > > > #define fs_initcall(fn)  __define_initcall(fn, 5)
> > > > -
> > > > #define rootfs_initcall(fn)  __define_initcall(fn, rootfs)
> > > > #define device_initcall(fn)  __define_initcall(fn, 6)
> > > > #define late_initcall(fn)__define_initcall(fn, 7)
> > > >
> > > > Since we start off from rootfs_initcall(), it gives us 3 more
> > > > levels of leg room to play with for order semantics, this isn't
> > > > enough to address all required levels of dependencies, this
> > > > is specially true given that AMD-KFD needs to be loaded before
> > > > the radeon driver -- -but this it not enforced by symbols.
> > > > If the AMD-KFD driver is not loaded prior to the radeon driver
> > > > because otherwise the radeon driver will not initialize the
> > > > AMD-KFD driver and you get no KFD functionality in userspace.
> > > >
> > > > Commit 1bacc894c227fad8a7 ("drivers: Move iommu/ before gpu/ in
> > > > Makefile") works around some of the possibe races between
> > > > the AMD IOMMU v2 and GPU drivers by changing the link order.
> > > > This is fragile, however its the bets we can do, given that
> > > > making the GPU drivers use late_initcall() would also implicate
> > > > a similar race between them. That possible race is fortunatley
> > > > addressed given that the drm Makefile currently has amdkfd
> > > > linked prior to radeon:
> > > >
> > > > drivers/gpu/drm/Makefile
> > > > ...
> > > > obj-$(CONFIG_HSA_AMD) += amd/amdkfd/
> > > > obj-$(CONFIG_DRM_RADEON)+= radeon/
> > > > ...
> > > >
> > > > Changing amdkfd and radeon to late_initcall() however is
> > > > still the right call in orde to annotate explicitly a
> > > > delayed dependency requirement between the GPU drivers
> > > > and the IOMMUs.
> > > >
> > > > We can't address the fragile nature of the link order
> > > > right now, but in the future that might be possible.
> > > >
> > > > Signed-off-by: Luis R. Rodriguez 
> > > > ---
> > > >
> > > > Please note, the changes to drivers/Makefile are just
> > > > for the sake of forcing the possible race to occur,
> > > > if this works well the actual [PATCH] submission will
> > > > skip those changes as its pointless to remove those
> > > > work arounds as it stands, due to the limited nature
> > > > of the levels available for addressing requirements.
> > > >
> > > > Also, if you are aware of further dependency hell
> > > > things like these -- please do let me know as I am
> > > > interested in looking at addressing them.
> > > 
> > > This should be fixed with -EPROBE_DEFER instead. Frobbing initcall
> > > levels should then just be done as an optimization to avoid too much
> > > reprobing.
> > 
> > radeon already uses -EPROBE_DEFER but it assumes that amdkfd *is* loaded 
> > first,
> > and only if it is already loaded can it count on getting -EPROBE_DEFER. The
> > radeon driver will defer probe *iff* kgd2kfd_init() returns -EPROBE_DEFER,
> > which only happens when amdkfd_init_completed is no longer 0. If radeon
> > gets linked first though the symbol fetch for kgd2kfd_init() will make it as
> > not-present though.

I did some more homework and I no longer believe this was the 

[PATCH 02/11] dma-buf/fence: add fence_array fences v6

2016-06-01 Thread Sumit Semwal
Hi Christian, Gustavo,

Thanks for these patches.

On 1 June 2016 at 20:55, Gustavo Padovan  wrote:
> 2016-06-01 Christian König :
>
>> From: Gustavo Padovan 
>>
>> struct fence_collection inherits from struct fence and carries a
>> collection of fences that needs to be waited together.
>>
>> It is useful to translate a sync_file to a fence to remove the complexity
>> of dealing with sync_files on DRM drivers. So even if there are many
>> fences in the sync_file that needs to waited for a commit to happen,
>> they all get added to the fence_collection and passed for DRM use as
>> a standard struct fence.
>>
>> That means that no changes needed to any driver besides supporting fences.
>>
>> fence_collection's fence doesn't belong to any timeline context, so
>> fence_is_later() and fence_later() are not meant to be called with
>> fence_collections fences.
>>
>> v2: Comments by Daniel Vetter:
>>   - merge fence_collection_init() and fence_collection_add()
>>   - only add callbacks at ->enable_signalling()
>>   - remove fence_collection_put()
>>   - check for type on to_fence_collection()
>>   - adjust fence_is_later() and fence_later() to WARN_ON() if they
>>   are used with collection fences.
>>
>> v3: - Initialize fence_cb.node at fence init.
>>
>> Comments by Chris Wilson:
>>   - return "unbound" on fence_collection_get_timeline_name()
>>   - don't stop adding callbacks if one fails
>>   - remove redundant !! on fence_collection_enable_signaling()
>>   - remove redundant () on fence_collection_signaled
>>   - use fence_default_wait() instead
>>
>> v4 (chk): Rework, simplification and cleanup:
>>   - Drop FENCE_NO_CONTEXT handling, always allocate a context.
>>   - Rename to fence_array.
>>   - Return fixed driver name.
>>   - Register only one callback at a time.
>>   - Document that create function takes ownership of array.
>>
>> v5 (chk): More work and fixes:
>>   - Avoid deadlocks by adding all callbacks at once again.
>>   - Stop trying to remove the callbacks.
>>   - Provide context and sequence number for the array fence.
>>
>> v6 (chk): Fixes found during testing
>>   - Fix stupid typo in _enable_signaling().
>>
>> Signed-off-by: Gustavo Padovan 
>> Signed-off-by: Christian König 
>> ---
>>  drivers/dma-buf/Makefile  |   2 +-
>>  drivers/dma-buf/fence-array.c | 127 
>> ++
>>  include/linux/fence-array.h   |  72 
>>  3 files changed, 200 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/dma-buf/fence-array.c
>>  create mode 100644 include/linux/fence-array.h
>
> This is working fine to me. Once the commit message is fixed:
>
> Reviewed-by: Gustavo Padovan 
>
> You need to Cc Sumit here to decide who is picking these patches.
> It would be better to get them through the drm trees so we would need
> his Ack at least.
>
+1 on the commit message consistency change; post that, please feel
free to add my
Acked-by: Sumit Semwal 

for the 3 dma-buf/fences patches and request to take them via DRM tree
as rightly suggested by Gustavo.

> Gustavo

BR,
Sumit.


[RFC PATCH 3/4] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-06-01 Thread Chanwoo Choi
Hi Lin,

This patch include the two features as following:
- Monitor the ddr load
- Control the ddr's clock with ondemand governor based on load

The "Monitor the ddr load" has the specific the address in SoC.
Namely, it is separate the module.
So, I implemented the devfreq-event framework[1] which was merged.

It is right method to separate two feature from your device driver.
You can refer to patch[2][3]. The patch[2] show how to implement the
"monitor the ddr load"
by using Devfreq-Event framework and the patch[3] include the method
how to implement the rk3399 dmc driver.

[1] Devfreq-Event framework
- 
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=f262f28c147051e7aa6daaf4fb5996833ffadff4

[2] Exynos Noc probe driver by using Devfreq-Event framework
- 
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=0179a913875a8b39eaf5b848c876439a3a4650af

[3] Exynos Busfreq driver using the devfreq-evnet framework to get the
monitored data
- 
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=0722249ac1f3dcc3af9e9d7ed89792a68f00

If you have more information and help, please let me know. I'll help you.

Thanks,
Chanwoo Choi

On Wed, Jun 1, 2016 at 6:35 PM, Lin Huang  wrote:
> there is dfi controller on rk3399 platform, it can monitor
> ddr load, register this controller to devfreq framework, and
> default to use simple_ondeamnd policy, and do ddr frequency
> scaling base on this result.
>
> Signed-off-by: Lin Huang 
> ---
>  drivers/devfreq/Kconfig |   2 +-
>  drivers/devfreq/Makefile|   1 +
>  drivers/devfreq/rockchip/Kconfig|  14 +
>  drivers/devfreq/rockchip/Makefile   |   2 +
>  drivers/devfreq/rockchip/rk3399_dmc.c   | 438 
> 
>  drivers/devfreq/rockchip/rockchip_dmc.c | 132 ++
>  include/soc/rockchip/rockchip_dmc.h |  44 
>  7 files changed, 632 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/devfreq/rockchip/Kconfig
>  create mode 100644 drivers/devfreq/rockchip/Makefile
>  create mode 100644 drivers/devfreq/rockchip/rk3399_dmc.c
>  create mode 100644 drivers/devfreq/rockchip/rockchip_dmc.c
>  create mode 100644 include/soc/rockchip/rockchip_dmc.h
>
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index 78dac0e..a883744 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -101,5 +101,5 @@ config ARM_TEGRA_DEVFREQ
>   operating frequencies and voltages with OPP support.
>
>  source "drivers/devfreq/event/Kconfig"
> -
> +source "drivers/devfreq/rockchip/Kconfig"
>  endif # PM_DEVFREQ
> diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
> index 09f11d9..48e2ae6 100644
> --- a/drivers/devfreq/Makefile
> +++ b/drivers/devfreq/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o
>  # DEVFREQ Drivers
>  obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
>  obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o
> +obj-$(CONFIG_ARCH_ROCKCHIP)+= rockchip/
>
>  # DEVFREQ Event Drivers
>  obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
> diff --git a/drivers/devfreq/rockchip/Kconfig 
> b/drivers/devfreq/rockchip/Kconfig
> new file mode 100644
> index 000..617b5fe
> --- /dev/null
> +++ b/drivers/devfreq/rockchip/Kconfig
> @@ -0,0 +1,14 @@
> +config ARM_ROCKCHIP_DMC_DEVFREQ
> +   tristate "ARM ROCKCHIP DMC DEVFREQ Driver"
> +   depends on ARCH_ROCKCHIP
> +   help
> + This adds the DEVFREQ driver framework for the rockchip dmc.
> +
> +config ARM_RK3399_DMC_DEVFREQ
> +   tristate "ARM RK3399 DMC DEVFREQ Driver"
> +   depends on ARM_ROCKCHIP_DMC_DEVFREQ
> +   select PM_OPP
> +   select DEVFREQ_GOV_SIMPLE_ONDEMAND
> +   help
> + This adds the DEVFREQ driver for the RK3399 dmc. It sets the 
> frequency
> + for the memory controller and reads the usage counts from hardware.
> diff --git a/drivers/devfreq/rockchip/Makefile 
> b/drivers/devfreq/rockchip/Makefile
> new file mode 100644
> index 000..caca525
> --- /dev/null
> +++ b/drivers/devfreq/rockchip/Makefile
> @@ -0,0 +1,2 @@
> +obj-$(CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ) += rockchip_dmc.o
> +obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
> diff --git a/drivers/devfreq/rockchip/rk3399_dmc.c 
> b/drivers/devfreq/rockchip/rk3399_dmc.c
> new file mode 100644
> index 000..4907d38
> --- /dev/null
> +++ b/drivers/devfreq/rockchip/rk3399_dmc.c
> @@ -0,0 +1,438 @@
> +/*
> + * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
> + * Author: Lin Huang 
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of 

[BISECTED] 0955c1250e oops at drm_connector_cleanup+0x5c/0x1d0

2016-06-01 Thread George Spelvin
With 6e86d58be3, I get working X.  With 0955c1250e ("drm/crtc: take
references to connectors used in a modeset. (v2)"), startx produces a
kernel oops and a blank screen.

4.7-rc1 with 0955c1250e reverted also works, which seems definitive.

The oops is:

[  212.149973] nouveau :02:00.0: DRM: DDC responded, but no EDID for VGA-1
[  213.842270] BUG: unable to handle kernel NULL pointer dereference at 
0008
[  213.842283] IP: [] drm_connector_cleanup+0x5c/0x1d0
[  213.842290] PGD 41779c067 PUD 0 
[  213.842294] Oops: 0002 [#1] SMP 
[  213.842297] Modules linked in: nfsd lockd grace sunrpc via_velocity 
x86_pkg_temp_thermal input_leds crc32_pclmul crc32c_intel led_class [last 
unloaded: twofish_common]
[  213.842313] CPU: 0 PID: 5362 Comm: Xorg Not tainted 
4.6.0-rc3-00678-g0955c125 #541
[  213.842317] Hardware name: Gigabyte Technology Co., Ltd. To be filled by 
O.E.M./X79-UP4, BIOS F7 03/19/2014
[  213.842320] task: 880420c42580 ti: 880417404000 task.ti: 
880417404000
[  213.842324] RIP: 0010:[]  [] 
drm_connector_cleanup+0x5c/0x1d0
[  213.842329] RSP: 0018:880417407c08  EFLAGS: 00010206
[  213.842331] RAX:  RBX: 8800b9d79000 RCX: ea0010acde00
[  213.842511] RDX: dead0200 RSI: 88042b881078 RDI: 0007
[  213.842982] RBP: 88042b96e800 R08: 88042b881078 R09: 000180080007
[  213.843459] R10: ea0010ae2000 R11: 88042d803301 R12: 8800b9d79078
[  213.843929] R13: dead0200 R14: dead0100 R15: 
[  213.844414] FS:  () GS:88043fc0(0063) 
knlGS:f708b880
[  213.844896] CS:  0010 DS: 002b ES: 002b CR0: 80050033
[  213.845369] CR2: 0008 CR3: 000417796000 CR4: 001406f0
[  213.845557] Stack:
[  213.845557]  8800b9d79000 0001 88042b4e3000 
8800b9d79000
[  213.845557]  88042b881000 0001 813fda8c 
88042b96eb88
[  213.845557]  81328557 880420c42580 88042c271190 
8800b9d79000
[  213.845557] Call Trace:
[  213.845557]  [] ? nouveau_connector_destroy+0x2c/0x50
[  213.845557]  [] ? drm_crtc_helper_set_config+0xa17/0xce0
[  213.845557]  [] ? nouveau_crtc_set_config+0x4c/0x110
[  213.845557]  [] ? drm_mode_set_config_internal+0x5c/0x110
[  213.845557]  [] ? drm_mode_setcrtc+0x42c/0x540
[  213.845557]  [] ? drm_ioctl+0x12c/0x4e0
[  213.845557]  [] ? drm_mode_setplane+0x1c0/0x1c0
[  213.845557]  [] ? nouveau_drm_ioctl+0x61/0xb0
[  213.845557]  [] ? nouveau_compat_ioctl+0xb/0x20
[  213.845557]  [] ? compat_SyS_ioctl+0x95/0x1890
[  213.845557]  [] ? SyS_write+0x3d/0x90
[  213.845557]  [] ? do_fast_syscall_32+0x8d/0x140
[  213.845557]  [] ? entry_SYSENTER_compat+0x4f/0x5e
[  213.845557] Code: 48 8b 73 78 4c 8d 63 78 49 be 00 01 00 00 00 00 ad de 49 
bd 00 02 00 00 00 00 ad de 48 8b 06 4c 39 e6 49 89 c7 74 2b 48 8b 56 08 <48> 89 
50 08 48 89 02 4c 89 36 4c 89 6e 08 48 8b 3b e8 5e 2b 00 
[  213.845557] RIP  [] drm_connector_cleanup+0x5c/0x1d0
[  213.845557]  RSP 
[  213.845557] CR2: 0008
[  213.858256] ---[ end trace e4f18a1100ceeb21 ]---

One interesting detail I noticed during bisection, but didn't stop to
investigate in detail, is that it sometimes the display doesn't come
back after a reboot (!).

Userland is 32-bit, on a 64-bit kernel.  The GPU is an old nVidia one
that's not doing anything more complex then VLC.

02:00.0 VGA compatible controller [0300]: NVIDIA Corporation GT216 [GeForce 
210] [10de:0a23] (rev a2)


This is a personal machine, so it's easy to test patches, modulo
saving all my work in progress before rebooting.


[RFC PATCH 3/4] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-06-01 Thread MyungJoo Ham
On Wed, Jun 1, 2016 at 6:35 PM, Lin Huang  wrote:
> there is dfi controller on rk3399 platform, it can monitor
> ddr load, register this controller to devfreq framework, and
> default to use simple_ondeamnd policy, and do ddr frequency
> scaling base on this result.
>
> Signed-off-by: Lin Huang 
> ---
>  drivers/devfreq/Kconfig |   2 +-
>  drivers/devfreq/Makefile|   1 +
>  drivers/devfreq/rockchip/Kconfig|  14 +
>  drivers/devfreq/rockchip/Makefile   |   2 +
>  drivers/devfreq/rockchip/rk3399_dmc.c   | 438 
> 
>  drivers/devfreq/rockchip/rockchip_dmc.c | 132 ++
>  include/soc/rockchip/rockchip_dmc.h |  44 
>  7 files changed, 632 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/devfreq/rockchip/Kconfig
>  create mode 100644 drivers/devfreq/rockchip/Makefile
>  create mode 100644 drivers/devfreq/rockchip/rk3399_dmc.c
>  create mode 100644 drivers/devfreq/rockchip/rockchip_dmc.c
>  create mode 100644 include/soc/rockchip/rockchip_dmc.h
>
> +
> +   /* check the rate we get whether correct */
> +   dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk);
> +   if (dmcfreq->rate != target_rate) {
> +   dev_err(dev, "get wrong ddr frequency, Request freq %lu,\
> +   Current freq %lu\n", target_rate, dmcfreq->rate);
> +   regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt,
> + dmcfreq->volt);

Why do you need to check this and
more importantly, why do you assume that dmvfreq->volt
will be safe in this case? (what if the new dmcfreq->rate is
larger than the old dmcfreq->rate after clk_get_rate?)
Note that you didn't update dmcfreq->volt after clk_get_rate()


> +EXPORT_SYMBOL_GPL(dmc_event);
> +EXPORT_SYMBOL_GPL(rockchip_dmc_enabled);
> +EXPORT_SYMBOL_GPL(rockchip_dmc_enable);
> +EXPORT_SYMBOL_GPL(rockchip_dmc_disable);
> +EXPORT_SYMBOL_GPL(dmc_register_notifier);
> +EXPORT_SYMBOL_GPL(dmc_unregister_notifier);
> +EXPORT_SYMBOL_GPL(rockchip_dmc_get);
> +EXPORT_SYMBOL_GPL(rockchip_dmc_put);

Do you really need to export all these device driver specific
functions? Looks like a design flaw here.



Cheers,
MyungJoo


-- 
MyungJoo Ham, Ph.D.
S/W R&D Center, Samsung Electronics


[Nouveau] [PATCH 4/4] drm/nouveau/acpi: fix lockup with PCIe runtime PM

2016-06-01 Thread Lukas Wunner
On Wed, Jun 01, 2016 at 06:51:51PM +0200, Peter Wu wrote:
> On Tue, May 31, 2016 at 02:20:26PM +0200, Lukas Wunner wrote:
> > On Mon, May 30, 2016 at 06:13:51PM +0200, Peter Wu wrote:
> > > Do you have any suggestions for the case where the pcieport driver
> > > refuses to put the bridge in D3 (because the BIOS is too old)? In that
> > > case the nouveau driver needs to fallback to the DSM method (but not
> > > when runtime PM is deliberately disabled by writing control=on).
> > 
> > The BIOS cut-off date is meant to avoid issues when suspending ports
> > on older chipsets. However if the port is used for an Optimus GPU
> > and we can clearly identify that, and there's a _PR3 method provided,
> > it's probably safe to say that the port is *intended* to be suspended.
> > 
> > So you may want to consider amending pci_bridge_d3_possible() to
> > allow D3 for such ports regardless of the BIOS date, as I've done
> > for Thunderbolt in this commit:
> > https://github.com/l1k/linux/commit/3cb8549cd4e5
> 
> Then we have heuristics based on BIOS year, on whether it is TB or not,
> and next to it whether it is an Optimus laptop? Maybe the PCI core needs
> to export a function that allows drivers to override the detection if
> this becomes more common.

Well I consider the TB and Optimus whitelisting as a stop-gap until
the BIOS date is lowered. Rafael wrote:

Some time around when machines with Windows 10 started to ship should be
relatively safe.
I guess we can just pick a reasonable date in the initial patch and then
try to move it back to the past subsequently and see if that breaks things
for anyone.

Source: http://permalink.gmane.org/gmane.linux.power-management.general/75133

> 
> > Not sure how to uniquely identify such ports though. Perhaps check
> > if there's a device in slot 0 below the port which has
> > (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
> > (pdev->vendor == PCI_VENDOR_ID_NVIDIA ||
> >  pdev->vendor == PCI_VENDOR_ID_ATI)
> 
> Seems fragile, there are desktop setups satisfying this match.

Of course, I didn't mean this to be used as is, you'd have to augment
this with checks e.g. for presence of _PR3 and (if possible) Optimus,
but I'm not familiar enough with Optimus to write down working code
for it, I'm only familiar with apple-gmux switching.

Best regards,

Lukas


[PATCH 4/4] drm/nouveau/acpi: fix lockup with PCIe runtime PM

2016-06-01 Thread Peter Wu
On Wed, Jun 01, 2016 at 12:28:47PM +0300, Mika Westerberg wrote:
> On Tue, May 31, 2016 at 01:02:31PM +0200, Peter Wu wrote:
> > On Tue, May 31, 2016 at 11:43:56AM +0300, Mika Westerberg wrote:
> > > On Mon, May 30, 2016 at 06:13:51PM +0200, Peter Wu wrote:
> > > > Do you have any suggestions for the case where the pcieport driver
> > > > refuses to put the bridge in D3 (because the BIOS is too old)? In that
> > > > case the nouveau driver needs to fallback to the DSM method (but not
> > > > when runtime PM is deliberately disabled by writing control=on).
> > > 
> > > Do you know what Windows does then? I think we should do the same if
> > > possible.
> > 
> > If the BIOS is too old, then it probably does not have _PR3 objects nor
> > calls to _OSI("Windows 2013"). See below.
> > 
> > > If user has disabled runtime PM from the root port deliberately, there
> > > might be good reason to do so. Why we want to fallback to something that
> > > could cause problems? I mean _DSM on such systems is probably not that
> > > much tested because everybody runs Windows 8+ and using standard ACPI
> > > power resources.
> > 
> > I agree that when runtime PM on the root port is disabled (control=on),
> > then there should be no fallback to DSM. For devices without _PR3 it is
> > clear that DSM will always be used (if available).
> > 
> > In other cases (where _PR3 is available) we can distinguish:
> >  - pre-Windows 8 machines. I have never seen this combination. Firmware
> >writers seems to prefer sticking to reference code which did not use
> >power resources before.
> >  - Machines targeting Windows 8 or newer. (Note that there exist
> >machines with Windows 8 support that do not have _PR3, DSM is used in
> >that case.)
> > 
> > If Windows 7 is running on a Windows 8 machine, PR3 will not be used
> > anyway. If the Linux kernel claims support for Windows 8, but does not
> > use PR3, then we are probably approaching an untested area. So far
> > firmware seems fine with using *only* DSM *or* PR3, but at least my
> > laptop gets confused when you use both at the same time.
> > 
> > The latter happens on pci/pm (8b71f565) without other patches:
> > 
> >  1. nouveau invokes _DSM and _PS3, device is put in D3cold.
> >  2. pcieport driver calls PG00._OFF (PG00 is returned by _PR3).
> >  3. Wake up Nvidia device (e.g. by power=on).
> >  4. This will trigger PG00._ON (via pcieport) and _PS0 (via nouveau).
> >  5. Nvidia card is not really ready (observed via "restoring config
> > space at offset ... (was 0x, writing ...)", a soft lockup
> > and RCU stall after that requiring a reboot to recover).
> > 
> > nouveau could be patched not to invoke DSM when PR3 is detected
> > (proposal is ready) but will keep the device powered on in these cases:
> >  - nouveau is patched, but pci/pm patches are not.
> >  - PR3 is supported but due to the cutoff date (2015) it is not used.
> >  - Boot option pcie_port_pm=off.
> >  - runtime PM is disabled for pcieport (should be fine).
> 
> Since using only _DSM has been the only method to power down the card
> currently inńLinux (even if the root port has had _PR3), and it has been
> working fine, why not stick with that when _DSM is supported?

Maybe it is not really working, people have been reporting memory
corruption[1] for example on certain Lenovo models that was gone after
hacking the bbswitch module to disable the root port:

https://bugs.freedesktop.org/show_bug.cgi?id=78530
https://github.com/Bumblebee-Project/bbswitch/issues/78
https://github.com/Bumblebee-Project/bbswitch/issues/115

I'll try to solicit some feedback from the affected people on these
patch series, whether it solves their memory corruption issue.

Dave also said "This fixes GPU auto powerdown on the Lenovo W541," when
he added PR3 support in https://patchwork.freedesktop.org/patch/76313/
So apparently it did not work with just DSM.

> In other words, something like this:
> 
>   nouveau_dsm_pci_probe()
>   {
>   ...
>   if (retval & (NOUVEAU_DSM_HAS_OPT | NOUVEAU_DSM_HAS_MUX)) {
>   /*
>* We have custom _DSM method to power down the card so
>* prevent the PCI core from transitioning the
>* card into D3cold.
>*/
>   pci_d3cold_disable(pdev);
>   }
>   }
> 
> (Not sure about those flags above, though).
> 
> Yes, it does not follow Windows 8+ but if it works... ;-)
> 
> > There is a wealth of acpidumps on Launchpad bug 752542
> > (https://bugs.launchpad.net/bugs/752542). Search for example for
> > comments in early 2015 or before, those will likely be machine from 2014
> > or before.
> > 
> > Interesting to see is the _PR3 method of a HP Envy TS 15 (11/20/2014):
> > 
> > Method (_PR3, 0, NotSerialized) {
> > If (\_OSI ("Windows 2013")) {
> > Return (Package (0x01) {
> > 

[Nouveau] [PATCH 4/4] drm/nouveau/acpi: fix lockup with PCIe runtime PM

2016-06-01 Thread Peter Wu
On Tue, May 31, 2016 at 02:20:26PM +0200, Lukas Wunner wrote:
> On Mon, May 30, 2016 at 06:13:51PM +0200, Peter Wu wrote:
> > Do you have any suggestions for the case where the pcieport driver
> > refuses to put the bridge in D3 (because the BIOS is too old)? In that
> > case the nouveau driver needs to fallback to the DSM method (but not
> > when runtime PM is deliberately disabled by writing control=on).
> 
> The BIOS cut-off date is meant to avoid issues when suspending ports
> on older chipsets. However if the port is used for an Optimus GPU
> and we can clearly identify that, and there's a _PR3 method provided,
> it's probably safe to say that the port is *intended* to be suspended.
> 
> So you may want to consider amending pci_bridge_d3_possible() to
> allow D3 for such ports regardless of the BIOS date, as I've done
> for Thunderbolt in this commit:
> https://github.com/l1k/linux/commit/3cb8549cd4e5

Then we have heuristics based on BIOS year, on whether it is TB or not,
and next to it whether it is an Optimus laptop? Maybe the PCI core needs
to export a function that allows drivers to override the detection if
this becomes more common.

> Not sure how to uniquely identify such ports though. Perhaps check
> if there's a device in slot 0 below the port which has
>   (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
>   (pdev->vendor == PCI_VENDOR_ID_NVIDIA ||
>pdev->vendor == PCI_VENDOR_ID_ATI)

Seems fragile, there are desktop setups satisfying this match.
-- 
Kind regards,
Peter Wu
https://lekensteyn.nl


[GIT PULL] imx-drm: LVDS updates and some cleanup

2016-06-01 Thread Philipp Zabel
Hi Dave,

this tag contains support for pixel clock polarity configuration,
LVDS panel EDID reading via DDC, video mode selection via native-mode
DT property, UYVY/YUYV plane support, and some cleanups.

regards
Philipp

The following changes since commit 1a695a905c18548062509178b98bc91e67510864:

  Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)

are available in the git repository at:

  git://git.pengutronix.de/git/pza/linux.git tags/imx-drm-next-2016-06-01

for you to fetch changes up to 151787ba0562fd70e7b669a1b5a398875e4fc8e7:

  drm/imx: plane: Don't set plane->crtc in ipu_plane_update() (2016-05-30 
09:14:00 +0200)


imx-drm updates

- add support for reading LVDS panel EDID over DDC
- enable UYVY/VYUY support
- add support for pixel clock polarity configuration
- honor the native-mode DT property for LVDS
- various fixes and cleanups


Akshay Bhat (1):
  dt-bindings: imx: ldb: Add ddc-i2c-bus property

Liu Ying (2):
  drm/imx: ipuv3-plane: Constify ipu_plane_funcs
  drm/imx: plane: Don't set plane->crtc in ipu_plane_update()

Lothar Waßmann (2):
  drm/imx: parallel-display: remove dead code
  drm/imx: imx-ldb: honor 'native-mode' property when selecting video mode 
from DT

Philipp Zabel (4):
  drm/imx: imx-ldb: use of_graph_get_endpoint_by_regs helper
  drm/imx: parallel-display: use of_graph_get_endpoint_by_regs helper
  drm/imx: ipuv3-plane: enable UYVY and VYUY formats
  drm/imx: use bus_flags for pixel clock polarity

Steve Longerbeam (1):
  drm/imx: imx-ldb: Add DDC support

 .../devicetree/bindings/display/imx/ldb.txt|  1 +
 drivers/gpu/drm/imx/imx-drm-core.c | 13 ++--
 drivers/gpu/drm/imx/imx-drm.h  |  7 +-
 drivers/gpu/drm/imx/imx-ldb.c  | 78 +++---
 drivers/gpu/drm/imx/imx-tve.c  |  6 +-
 drivers/gpu/drm/imx/ipuv3-crtc.c   | 10 ++-
 drivers/gpu/drm/imx/ipuv3-plane.c  |  5 +-
 drivers/gpu/drm/imx/parallel-display.c | 40 ---
 8 files changed, 94 insertions(+), 66 deletions(-)


[GIT PULL] drm/mediatek: MT8173 DSI and DPI fixes

2016-06-01 Thread Philipp Zabel
Hi Dave,

this tag contains two fixes, one each for an oversight in the DPI and
DSI driver, respectively.

regards
Philipp

The following changes since commit 1a695a905c18548062509178b98bc91e67510864:

  Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)

are available in the git repository at:

  git://git.pengutronix.de/git/pza/linux.git tags/mediatek-drm-fixes-2016-06-01

for you to fetch changes up to 2ea9f31799adce35d8c9a0bb3bc1d2b515702c6f:

  drm/mediatek: mtk_dsi: Remove spurious drm_connector_unregister (2016-06-01 
16:09:56 +0200)


mediatek-drm fixes

- remove an invalid, unreachable error message and NULL pointer dereference
- remove a spurious drm_connector_unregister call from the DSI driver


Philipp Zabel (2):
  drm/mediatek: mtk_dpi: remove invalid error message
  drm/mediatek: mtk_dsi: Remove spurious drm_connector_unregister

 drivers/gpu/drm/mediatek/mtk_dpi.c | 5 -
 drivers/gpu/drm/mediatek/mtk_dsi.c | 4 +---
 2 files changed, 1 insertion(+), 8 deletions(-)


[PATCH 4/4] drm/amdgpu: modify sdma start sequence

2016-06-01 Thread Alex Deucher
From: Monk Liu 

should fist halt engine, and then doing the register
programing, and later unhalt engine, and finally run
ring_test.

this help fix reloading driver hang issue of SDMA
ring

original sequence is wrong for it programing engine
after unhalt, which will lead to fault behavior when
doing driver reloading after unloaded.

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/cik_sdma.c  |  9 +++--
 drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c |  8 ++--
 drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 15 +++
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c 
b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 76f73ab..0079916 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -448,7 +448,12 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);

ring->ready = true;
+   }
+
+   cik_sdma_enable(adev, true);

+   for (i = 0; i < adev->sdma.num_instances; i++) {
+   ring = &adev->sdma.instance[i].ring;
r = amdgpu_ring_test_ring(ring);
if (r) {
ring->ready = false;
@@ -531,8 +536,8 @@ static int cik_sdma_start(struct amdgpu_device *adev)
if (r)
return r;

-   /* unhalt the MEs */
-   cik_sdma_enable(adev, true);
+   /* halt the engine before programing */
+   cik_sdma_enable(adev, false);

/* start the gfx rings and rlc compute queues */
r = cik_sdma_gfx_resume(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index e11a374..f6014b0 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -491,7 +491,11 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);

ring->ready = true;
+   }

+   sdma_v2_4_enable(adev, true);
+   for (i = 0; i < adev->sdma.num_instances; i++) {
+   ring = &adev->sdma.instance[i].ring;
r = amdgpu_ring_test_ring(ring);
if (r) {
ring->ready = false;
@@ -582,8 +586,8 @@ static int sdma_v2_4_start(struct amdgpu_device *adev)
return -EINVAL;
}

-   /* unhalt the MEs */
-   sdma_v2_4_enable(adev, true);
+   /* halt the engine before programing */
+   sdma_v2_4_enable(adev, false);

/* start the gfx rings and rlc compute queues */
r = sdma_v2_4_gfx_resume(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 585d8fe..33605d4 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -713,7 +713,15 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);

ring->ready = true;
+   }

+   /* unhalt the MEs */
+   sdma_v3_0_enable(adev, true);
+   /* enable sdma ring preemption */
+   sdma_v3_0_ctx_switch_enable(adev, true);
+
+   for (i = 0; i < adev->sdma.num_instances; i++) {
+   ring = &adev->sdma.instance[i].ring;
r = amdgpu_ring_test_ring(ring);
if (r) {
ring->ready = false;
@@ -806,10 +814,9 @@ static int sdma_v3_0_start(struct amdgpu_device *adev)
}
}

-   /* unhalt the MEs */
-   sdma_v3_0_enable(adev, true);
-   /* enable sdma ring preemption */
-   sdma_v3_0_ctx_switch_enable(adev, true);
+   /* disble sdma engine before programing it */
+   sdma_v3_0_ctx_switch_enable(adev, false);
+   sdma_v3_0_enable(adev, false);

/* start the gfx rings and rlc compute queues */
r = sdma_v3_0_gfx_resume(adev);
-- 
2.5.5



[PATCH 3/4] drm/amdgpu: init more register for sdma

2016-06-01 Thread Alex Deucher
From: Monk Liu 

This help fix reloading driver hang issue of SDMA
ring

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/cik_sdma.c  | 2 ++
 drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 2 ++
 drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c 
b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index 518dca4..76f73ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -419,6 +419,8 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
/* Initialize the ring buffer's read and write pointers */
WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+   WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+   WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);

/* set the wb address whether it's enabled or not */
WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index f4c3130..e11a374 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -461,6 +461,8 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
/* Initialize the ring buffer's read and write pointers */
WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+   WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+   WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);

/* set the wb address whether it's enabled or not */
WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c 
b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 31d99b00..585d8fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -672,6 +672,8 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
/* Initialize the ring buffer's read and write pointers */
WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+   WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+   WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);

/* set the wb address whether it's enabled or not */
WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
-- 
2.5.5



[PATCH 2/4] drm/amdgpu: clear SA bo when created

2016-06-01 Thread Alex Deucher
From: Monk Liu 

This help fix reloading driver hang issue of SDMA
ring

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
index 8bf84ef..48618ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
@@ -115,6 +115,7 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
return r;
}
r = amdgpu_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr);
+   memset(sa_manager->cpu_ptr, 0, sa_manager->size);
amdgpu_bo_unreserve(sa_manager->bo);
return r;
 }
-- 
2.5.5



[PATCH 1/4] drm/amdgpu: clear RB at ring init

2016-06-01 Thread Alex Deucher
From: Monk Liu 

This help fix reloading driver hang issue of SDMA
ring.

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 3b02272..a4b3f44 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -310,6 +310,9 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct 
amdgpu_ring *ring,
}
r = amdgpu_bo_kmap(ring->ring_obj,
   (void **)&ring->ring);
+
+   memset((void *)ring->ring, 0, ring->ring_size);
+
amdgpu_bo_unreserve(ring->ring_obj);
if (r) {
dev_err(adev->dev, "(%d) ring map failed\n", r);
-- 
2.5.5



[PATCH 0/4] Fix SDMA after module reload

2016-06-01 Thread Alex Deucher
This patch set fixes SDMA after module reload.

Monk Liu (4):
  drm/amdgpu: clear RB at ring init
  drm/amdgpu: clear SA bo when created
  drm/amdgpu: init more register for sdma
  drm/amdgpu: modify sdma start sequence

 drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c |  3 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c   |  1 +
 drivers/gpu/drm/amd/amdgpu/cik_sdma.c| 11 +--
 drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c   | 10 --
 drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c   | 17 +
 5 files changed, 34 insertions(+), 8 deletions(-)

-- 
2.5.5



[Bug 88458] The monitor turns off when playing starcraft 2 in wine

2016-06-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=88458

--- Comment #6 from Jaakko Niemi  ---
(In reply to Jaakko Niemi from comment #5)
> I can repro this reliably.
> 
> [AMD/ATI] Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
> Kernel 4.6 drm-next, LLVM 3.8
> 
> These days I just get hung screen, audio keeps playing on background, I can
> ssh in and reboot. 
> 
> This happens only with SC2, I don't see problems with other games. Typically
> I don't even get halfway through campaign mission, sometimes I get crash
> when the game is playing video (assuming it's done through the engine...).
> 
> --

Oh, and Mesa is 12.0 rc1.

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


[Bug 88458] The monitor turns off when playing starcraft 2 in wine

2016-06-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=88458

--- Comment #5 from Jaakko Niemi  ---
I can repro this reliably.

[AMD/ATI] Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
Kernel 4.6 drm-next, LLVM 3.8

These days I just get hung screen, audio keeps playing on background, I can ssh
in and reboot. 

This happens only with SC2, I don't see problems with other games. Typically I
don't even get halfway through campaign mission, sometimes I get crash when the
game is playing video (assuming it's done through the engine...).

--

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


[PATCH 23/27] drm/sun4i: Use lockless gem BO free callback

2016-06-01 Thread Maxime Ripard
On Mon, May 30, 2016 at 07:53:15PM +0200, Daniel Vetter wrote:
> No dev->struct_mutex anywhere to be seen.
> 
> Cc: Maxime Ripard 
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/gpu/drm/sun4i/sun4i_drv.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
> b/drivers/gpu/drm/sun4i/sun4i_drv.c
> index 76e922bb60e5..68e9d85085fb 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> @@ -103,7 +103,7 @@ static struct drm_driver sun4i_drv_driver = {
>   .dumb_create= drm_gem_cma_dumb_create,
>   .dumb_destroy   = drm_gem_dumb_destroy,
>   .dumb_map_offset= drm_gem_cma_dumb_map_offset,
> - .gem_free_object= drm_gem_cma_free_object,
> + .gem_free_object_unlocked = drm_gem_cma_free_object,
>   .gem_vm_ops = &drm_gem_cma_vm_ops,

It doesn't compile here, it seems I need some additional patch?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160601/aa4d3560/attachment.sig>


[Bug 88458] The monitor turns off when playing starcraft 2 in wine

2016-06-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=88458

--- Comment #4 from Jaakko Niemi  ---
Created attachment 124241
  --> https://bugs.freedesktop.org/attachment.cgi?id=124241&action=edit
kernel log

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


[PATCH 19/26] drm/sun4i: Implement some semblance of vblank event handling

2016-06-01 Thread Maxime Ripard
Hi Daniel,

On Sun, May 29, 2016 at 08:35:16PM +0200, Daniel Vetter wrote:
> atomic_flush seems to be the right place, right after we commit the
> plane updates. Again use the fullproof version, since the pipe might
> be off.

This looks fine.

How can that be tested? modetest requires async vblank, which is not
there yet, and X doesn't seem to use it at all (since it works fine
without it).

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: 
<https://lists.freedesktop.org/archives/dri-devel/attachments/20160601/51ed5154/attachment-0001.sig>


[PATCH v4 1/2] drm: bridge: Add sii902x driver

2016-06-01 Thread Boris Brezillon
On Tue, 17 May 2016 08:47:11 +0200
Daniel Vetter  wrote:

> > +static struct drm_encoder *sii902x_best_encoder(struct drm_connector 
> > *connector)
> > +{
> > +   struct sii902x *sii902x = connector_to_sii902x(connector);
> > +
> > +   return sii902x->bridge.encoder;
> > +}  
> 
> drm_atomic_helper_best_encoder should do exactly this for you. If you feel
> board pimp the atomic helpers to call that one by default to even remove
> the vfunc assingment line ;-)

Just to be sure, is that what you had in mind?

--->8---


[Bug 117151] amdgpu: Fails to initialize R7 260x (Bonaire)

2016-06-01 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=117151

--- Comment #6 from Parker Reed  ---
Created attachment 218661
  --> https://bugzilla.kernel.org/attachment.cgi?id=218661&action=edit
4.7.0-rc1 log

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 117151] amdgpu: Fails to initialize R7 260x (Bonaire)

2016-06-01 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=117151

--- Comment #5 from Parker Reed  ---
Compiled git today and issue persists. Log attached.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[Bug 117151] amdgpu: Fails to initialize R7 260x (Bonaire)

2016-06-01 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=117151

Parker Reed  changed:

   What|Removed |Added

 Kernel Version|4.6 |4.7

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[PATCH] drm: atomic: Handle funcs->best_encoder == NULL case

2016-06-01 Thread Boris Brezillon
Fallback drm_atomic_helper_best_encoder() is funcs->best_encoder() is NULL
so that DRM drivers can leave this hook unassigned if they know they want
to use drm_atomic_helper_best_encoder().

Signed-off-by: Boris Brezillon 
---
 drivers/gpu/drm/drm_atomic_helper.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index ddfa0d1..f6a3350 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -110,8 +110,10 @@ static int handle_conflicting_encoders(struct 
drm_atomic_state *state,

if (funcs->atomic_best_encoder)
new_encoder = funcs->atomic_best_encoder(connector, 
conn_state);
-   else
+   else if (funcs->best_encoder)
new_encoder = funcs->best_encoder(connector);
+   else
+   new_encoder = drm_atomic_helper_best_encoder(connector);

if (new_encoder) {
if (encoder_mask & (1 << 
drm_encoder_index(new_encoder))) {





[PATCH] drm/rockchip: vop: do axi reset in vop initial time

2016-06-01 Thread Mark yao
On 2016年06月01日 17:19, Yakir Yang wrote:
> There is a bug in RK3399 VOP, when bootloader/kernel only enable
> VOP Big or VOP Little to display, then VOP IOMMU would failed to
> reset at the initial time and VOP register couldn't write rightly.
>
> After do the pure reset of VOP module, then things back to right.
>
> Signed-off-by: Yakir Yang 
Hi Yakir

I think you get vop iommu reset failed should be IOMMU Page fault, the 
vop iommu access a ummap address.

You should ensure all vop windows access right iommu mapping address 
before attach iommu.

Actually, I'm working no flash display from bootloader to kernel, and 
prepare remove all the reset on vop initial, because it would flash the 
display.

Thanks.

> ---
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 ++-
>   1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 1c4d5b5..4150323 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -1292,7 +1292,7 @@ static int vop_initial(struct vop *vop)
>   {
>   const struct vop_data *vop_data = vop->data;
>   const struct vop_reg_data *init_table = vop_data->init_table;
> - struct reset_control *ahb_rst;
> + struct reset_control *ahb_rst, *axi_rst;
>   int i, ret;
>   
>   vop->hclk = devm_clk_get(vop->dev, "hclk_vop");
> @@ -1331,6 +1331,19 @@ static int vop_initial(struct vop *vop)
>   }
>   
>   /*
> +  * do aclk_reset, reset all vop registers.
> +  */
> + axi_rst = devm_reset_control_get(vop->dev, "axi");
> + if (IS_ERR(axi_rst)) {
> + dev_err(vop->dev, "failed to get axi reset\n");
> + ret = PTR_ERR(axi_rst);
> + goto err_disable_aclk;
> + }
> + reset_control_assert(axi_rst);
> + usleep_range(10, 20);
> + reset_control_deassert(axi_rst);
> +
> + /*
>* do hclk_reset, reset all vop registers.
>*/
>   ahb_rst = devm_reset_control_get(vop->dev, "ahb");


-- 
ï¼­ark Yao




[RFC PATCH 2/4] clk: rockchip: rk3399: add ddrc clock support

2016-06-01 Thread Heiko Stübner
Am Mittwoch, 1. Juni 2016, 08:24:48 schrieb Doug Anderson:
> Lin Huang,
> 
> On Wed, Jun 1, 2016 at 2:35 AM, Lin Huang  wrote:
> > add ddrc clock setting, so we can do ddr frequency
> > scaling on rk3399 platform in future.
> > 
> > Signed-off-by: Lin Huang 
> > ---
> > 
> >  drivers/clk/rockchip/clk-rk3399.c  | 16 
> >  include/dt-bindings/clock/rk3399-cru.h |  1 +
> >  2 files changed, 17 insertions(+)
> > 
> > diff --git a/drivers/clk/rockchip/clk-rk3399.c
> > b/drivers/clk/rockchip/clk-rk3399.c index f1d8e44..749ea59 100644
> > --- a/drivers/clk/rockchip/clk-rk3399.c
> > +++ b/drivers/clk/rockchip/clk-rk3399.c
> > @@ -118,6 +118,10 @@ PNAME(mux_armclkb_p)   =
> > { "clk_core_b_lpll_src",> 
> > "clk_core_b_bpll_src",
> > "clk_core_b_dpll_src",
> > "clk_core_b_gpll_src"
> > };
> > 
> > +PNAME(mux_ddrclk_p)= { "clk_ddrc_lpll_src",
> > +   "clk_ddrc_bpll_src",
> > +   "clk_ddrc_dpll_src",
> > +   "clk_ddrc_gpll_src" };
> > 
> >  PNAME(mux_aclk_cci_p)  = { "cpll_aclk_cci_src",
> >  
> > "gpll_aclk_cci_src",
> > "npll_aclk_cci_src",
> > 
> > @@ -1377,6 +1381,18 @@ static struct rockchip_clk_branch
> > rk3399_clk_branches[] __initdata = {> 
> > COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
> > 
> > RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
> > RK3368_CLKGATE_CON(13), 11, GFLAGS),
> > 
> > +
> > +   /* ddrc */
> > +   GATE(0, "clk_ddrc_lpll_src", "lpll", CLK_IGNORE_UNUSED,
> > +RK3399_CLKGATE_CON(3), 0, GFLAGS),
> > +   GATE(0, "clk_ddrc_bpll_src", "bpll", CLK_IGNORE_UNUSED,
> > +RK3399_CLKGATE_CON(3), 1, GFLAGS),
> > +   GATE(0, "clk_ddrc_dpll_src", "dpll", CLK_IGNORE_UNUSED,
> > +RK3399_CLKGATE_CON(3), 2, GFLAGS),
> > +   GATE(0, "clk_ddrc_gpll_src", "gpll", CLK_IGNORE_UNUSED,
> > +RK3399_CLKGATE_CON(3), 3, GFLAGS),
> > +   COMPOSITE_DDRC(SCLK_DDRCLK, "clk_ddrc", mux_ddrclk_p,
> > CLK_IGNORE_UNUSED, +  RK3399_CLKSEL_CON(6), 4, 2,
> > MFLAGS, 0, 3, DFLAGS),
> It seems slightly unfortunate that we need CLK_IGNORE_UNUSED on these.
> Only one of these will ever be used at once and it would be awfully
> nice if the others could get gated, right?
> 
> ...presumably this is needed because we might not have an actual
> driver for DDR Freq and we definitely want to make sure that clk_ddrc
> is enabled in that case.  I guess what we really want is something
> like CLK_ENABLE_HAND_OFF eventually, but until then I think you might
> get slightly better behavior by getting rid of all of these
> CLK_IGNORE_UNUSED and setting "clk_ddrc" as a critical clock, either
> using the table in this file or the new flag.

My current feeling is that staying with the homegrown solution for critical 
clocks might be preferable until the clk-handoff mechanism lands as well, as 
our critical clocks fall into both categories and I'd like to not touch 
everything twice.

The clock above should be controlled by the dcf, so falls into the handoff 
category (critical until a driver picks up the clock).

Also mixing both new and old approach might get confusing.

But I'm definitly open to counter-arguments :-)


> >  };
> >  
> >  static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata =
> >  {
> > 
> > diff --git a/include/dt-bindings/clock/rk3399-cru.h
> > b/include/dt-bindings/clock/rk3399-cru.h index 50a44cf..8a0f0442 100644
> > --- a/include/dt-bindings/clock/rk3399-cru.h
> > +++ b/include/dt-bindings/clock/rk3399-cru.h
> > @@ -131,6 +131,7 @@
> > 
> >  #define SCLK_DPHY_RX0_CFG  165
> >  #define SCLK_RMII_SRC  166
> >  #define SCLK_PCIEPHY_REF100M   167
> > 
> > +#define SCLK_DDRCLK168
> 
> Almost certainly you'll want to create a separate patch for the
> dt-bindings change since it will need to land in a different tree so
> it can be pulled into both Heiko's clock topic branch and dts64 topic
> branch.

correct.


[RFC PATCH 4/4] drm/rockchip: Add dmc notifier in vop driver

2016-06-01 Thread Lin Huang
when in ddr frequency scaling process, vop can not do
enable or disable operate, since dcf will base on vop vblank
time to do frequency scaling and need to get vop irq if there
have vop enabled. So need register to dmc notifier, and we can
get the dmc status.

Signed-off-by: Lin Huang 
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 51 +++--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 1c4d5b5..7ee0cd0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -31,6 +31,8 @@
 #include 
 #include 

+#include 
+
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
 #include "rockchip_drm_fb.h"
@@ -116,6 +118,9 @@ struct vop {

const struct vop_data *data;

+   struct notifier_block dmc_nb;
+   int dmc_in_process;
+
uint32_t *regsbak;
void __iomem *regs;

@@ -426,14 +431,41 @@ static void vop_dsp_hold_valid_irq_disable(struct vop 
*vop)
spin_unlock_irqrestore(&vop->irq_lock, flags);
 }

+static int dmc_notify(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+   struct vop *vop = container_of(nb, struct vop, dmc_nb);
+
+   if (event == DMCFREQ_ADJUST)
+   vop->dmc_in_process = 1;
+   else if (event == DMCFREQ_FINISH)
+   vop->dmc_in_process = 0;
+
+   return NOTIFY_OK;
+}
+
 static void vop_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
int ret;
+   int timeout_count = 500;
+   int timeout_loop = 0;

if (vop->is_enabled)
return;

+   /*
+* if in dmc scaling frequency process, wait until it finish
+* use 100ms as timeout time.
+*/
+   while (timeout_loop < timeout_count) {
+   if (vop->dmc_in_process == 0)
+   break;
+
+   timeout_loop++;
+   usleep_range(150, 200);
+   }
+
ret = pm_runtime_get_sync(vop->dev);
if (ret < 0) {
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
@@ -485,6 +517,7 @@ static void vop_enable(struct drm_crtc *crtc)
enable_irq(vop->irq);

drm_crtc_vblank_on(crtc);
+   rockchip_dmc_get(&vop->dmc_nb);

return;

@@ -500,11 +533,25 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
int i;
+   int timeout_count = 500;
+   int timeout_loop = 0;

if (!vop->is_enabled)
return;

/*
+* if in dmc scaling frequency process, wait until it finish
+* use 100ms as timeout time.
+*/
+   while (timeout_loop < timeout_count) {
+   if (vop->dmc_in_process == 0)
+   break;
+
+   timeout_loop++;
+   usleep_range(150, 200);
+   }
+
+   /*
 * We need to make sure that all windows are disabled before we
 * disable that crtc. Otherwise we might try to scan from a destroyed
 * buffer later.
@@ -517,7 +564,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
VOP_WIN_SET(vop, win, enable, 0);
spin_unlock(&vop->reg_lock);
}
-
+   rockchip_dmc_put(&vop->dmc_nb);
drm_crtc_vblank_off(crtc);

/*
@@ -1243,7 +1290,7 @@ static int vop_create_crtc(struct vop *vop)
ret = -ENOENT;
goto err_cleanup_crtc;
}
-
+   vop->dmc_nb.notifier_call = dmc_notify;
init_completion(&vop->dsp_hold_completion);
init_completion(&vop->wait_update_complete);
crtc->port = port;
-- 
1.9.1



[RFC PATCH 3/4] PM / devfreq: rockchip: add devfreq driver for rk3399 dmc

2016-06-01 Thread Lin Huang
there is dfi controller on rk3399 platform, it can monitor
ddr load, register this controller to devfreq framework, and
default to use simple_ondeamnd policy, and do ddr frequency
scaling base on this result.

Signed-off-by: Lin Huang 
---
 drivers/devfreq/Kconfig |   2 +-
 drivers/devfreq/Makefile|   1 +
 drivers/devfreq/rockchip/Kconfig|  14 +
 drivers/devfreq/rockchip/Makefile   |   2 +
 drivers/devfreq/rockchip/rk3399_dmc.c   | 438 
 drivers/devfreq/rockchip/rockchip_dmc.c | 132 ++
 include/soc/rockchip/rockchip_dmc.h |  44 
 7 files changed, 632 insertions(+), 1 deletion(-)
 create mode 100644 drivers/devfreq/rockchip/Kconfig
 create mode 100644 drivers/devfreq/rockchip/Makefile
 create mode 100644 drivers/devfreq/rockchip/rk3399_dmc.c
 create mode 100644 drivers/devfreq/rockchip/rockchip_dmc.c
 create mode 100644 include/soc/rockchip/rockchip_dmc.h

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 78dac0e..a883744 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -101,5 +101,5 @@ config ARM_TEGRA_DEVFREQ
  operating frequencies and voltages with OPP support.

 source "drivers/devfreq/event/Kconfig"
-
+source "drivers/devfreq/rockchip/Kconfig"
 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9..48e2ae6 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)   += governor_passive.o
 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)   += exynos-bus.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)+= tegra-devfreq.o
+obj-$(CONFIG_ARCH_ROCKCHIP)+= rockchip/

 # DEVFREQ Event Drivers
 obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
diff --git a/drivers/devfreq/rockchip/Kconfig b/drivers/devfreq/rockchip/Kconfig
new file mode 100644
index 000..617b5fe
--- /dev/null
+++ b/drivers/devfreq/rockchip/Kconfig
@@ -0,0 +1,14 @@
+config ARM_ROCKCHIP_DMC_DEVFREQ
+   tristate "ARM ROCKCHIP DMC DEVFREQ Driver"
+   depends on ARCH_ROCKCHIP
+   help
+ This adds the DEVFREQ driver framework for the rockchip dmc.
+
+config ARM_RK3399_DMC_DEVFREQ
+   tristate "ARM RK3399 DMC DEVFREQ Driver"
+   depends on ARM_ROCKCHIP_DMC_DEVFREQ
+   select PM_OPP
+   select DEVFREQ_GOV_SIMPLE_ONDEMAND
+   help
+ This adds the DEVFREQ driver for the RK3399 dmc. It sets the frequency
+ for the memory controller and reads the usage counts from hardware.
diff --git a/drivers/devfreq/rockchip/Makefile 
b/drivers/devfreq/rockchip/Makefile
new file mode 100644
index 000..caca525
--- /dev/null
+++ b/drivers/devfreq/rockchip/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ) += rockchip_dmc.o
+obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ)   += rk3399_dmc.o
diff --git a/drivers/devfreq/rockchip/rk3399_dmc.c 
b/drivers/devfreq/rockchip/rk3399_dmc.c
new file mode 100644
index 000..4907d38
--- /dev/null
+++ b/drivers/devfreq/rockchip/rk3399_dmc.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define RK3399_DMC_NUM_CH  2
+
+/* DDRMON_CTRL */
+#define DDRMON_CTRL0x04
+#define CLR_DDRMON_CTRL(0x1f << 0)
+#define LPDDR4_EN  (0x10001 << 4)
+#define HARDWARE_EN(0x10001 << 3)
+#define LPDDR3_EN  (0x10001 << 2)
+#define SOFTWARE_EN(0x10001 << 1)
+#define TIME_CNT_EN(0x10001 << 0)
+
+#define DDRMON_CH0_COUNT_NUM   0x28
+#define DDRMON_CH0_DFI_ACCESS_NUM  0x2c
+#define DDRMON_CH1_COUNT_NUM   0x3c
+#define DDRMON_CH1_DFI_ACCESS_NUM  0x40
+
+/* pmu grf */
+#define PMUGRF_OS_REG2 0x308
+#define DDRTYPE_SHIFT  13
+#define DDRTYPE_MASK   7
+
+enum {
+   DDR3 = 3,
+   LPDDR3 = 6,
+   LPDDR4 = 7,
+   UNUSED = 0xFF
+};
+
+struct dmc_usage {
+   u32 access;
+   u32 total;
+};
+
+struct rk3399_dmcfreq {
+   struct device *dev;
+   struct devfreq *devfreq;
+   struct devfreq_simple_ondemand_data ondemand_data;
+   struct clk *dmc_clk;
+   struct completion dcf_hold_completion;
+   struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
+   struct mutex lock;
+   struct notifier_block dmc_nb;
+   int irq;

[RFC PATCH 2/4] clk: rockchip: rk3399: add ddrc clock support

2016-06-01 Thread Lin Huang
add ddrc clock setting, so we can do ddr frequency
scaling on rk3399 platform in future.

Signed-off-by: Lin Huang 
---
 drivers/clk/rockchip/clk-rk3399.c  | 16 
 include/dt-bindings/clock/rk3399-cru.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/drivers/clk/rockchip/clk-rk3399.c 
b/drivers/clk/rockchip/clk-rk3399.c
index f1d8e44..749ea59 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -118,6 +118,10 @@ PNAME(mux_armclkb_p)   = { 
"clk_core_b_lpll_src",
"clk_core_b_bpll_src",
"clk_core_b_dpll_src",
"clk_core_b_gpll_src" };
+PNAME(mux_ddrclk_p)= { "clk_ddrc_lpll_src",
+   "clk_ddrc_bpll_src",
+   "clk_ddrc_dpll_src",
+   "clk_ddrc_gpll_src" };
 PNAME(mux_aclk_cci_p)  = { "cpll_aclk_cci_src",
"gpll_aclk_cci_src",
"npll_aclk_cci_src",
@@ -1377,6 +1381,18 @@ static struct rockchip_clk_branch rk3399_clk_branches[] 
__initdata = {
COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+   /* ddrc */
+   GATE(0, "clk_ddrc_lpll_src", "lpll", CLK_IGNORE_UNUSED,
+RK3399_CLKGATE_CON(3), 0, GFLAGS),
+   GATE(0, "clk_ddrc_bpll_src", "bpll", CLK_IGNORE_UNUSED,
+RK3399_CLKGATE_CON(3), 1, GFLAGS),
+   GATE(0, "clk_ddrc_dpll_src", "dpll", CLK_IGNORE_UNUSED,
+RK3399_CLKGATE_CON(3), 2, GFLAGS),
+   GATE(0, "clk_ddrc_gpll_src", "gpll", CLK_IGNORE_UNUSED,
+RK3399_CLKGATE_CON(3), 3, GFLAGS),
+   COMPOSITE_DDRC(SCLK_DDRCLK, "clk_ddrc", mux_ddrclk_p, CLK_IGNORE_UNUSED,
+  RK3399_CLKSEL_CON(6), 4, 2, MFLAGS, 0, 3, DFLAGS),
 };

 static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
diff --git a/include/dt-bindings/clock/rk3399-cru.h 
b/include/dt-bindings/clock/rk3399-cru.h
index 50a44cf..8a0f0442 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -131,6 +131,7 @@
 #define SCLK_DPHY_RX0_CFG  165
 #define SCLK_RMII_SRC  166
 #define SCLK_PCIEPHY_REF100M   167
+#define SCLK_DDRCLK168

 #define DCLK_VOP0  180
 #define DCLK_VOP1  181
-- 
1.9.1



[RFC PATCH 1/4] rockchip: rockchip: add new clock-type for the ddrclk

2016-06-01 Thread Lin Huang
On new rockchip platform(rk3399 etc), there have dcf controller to
do ddr frequency scaling, and this controller will implement in
arm-trust-firmware. We add a special clock-type to handle that.

Signed-off-by: Lin Huang 
---
 drivers/clk/rockchip/Makefile  |   1 +
 drivers/clk/rockchip/clk-ddr.c | 147 +
 drivers/clk/rockchip/clk.c |   9 +++
 drivers/clk/rockchip/clk.h |  27 
 4 files changed, 184 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index f47a2fa..b5f2c8e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -8,6 +8,7 @@ obj-y   += clk-pll.o
 obj-y  += clk-cpu.o
 obj-y  += clk-inverter.o
 obj-y  += clk-mmc-phase.o
+obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o

 obj-y  += clk-rk3036.o
diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c
new file mode 100644
index 000..5b6630d
--- /dev/null
+++ b/drivers/clk/rockchip/clk-ddr.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Lin Huang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "clk.h"
+
+struct rockchip_ddrclk {
+   struct clk_hw   hw;
+   void __iomem*reg_base;
+   int mux_offset;
+   int mux_shift;
+   int mux_width;
+   int mux_flag;
+   int div_shift;
+   int div_width;
+   int div_flag;
+   spinlock_t  *lock;
+};
+
+#define to_rockchip_ddrclk_hw(hw) container_of(hw, struct rockchip_ddrclk, hw)
+#define val_mask(width)((1 << (width)) - 1)
+
+static int rockchip_ddrclk_set_rate(struct clk_hw *hw, unsigned long drate,
+   unsigned long prate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   unsigned long flags;
+
+   spin_lock_irqsave(ddrclk->lock, flags);
+
+   /* TODO: set ddr rate in bl31 */
+
+   spin_unlock_irqrestore(ddrclk->lock, flags);
+
+   return 0;
+}
+
+static unsigned long
+rockchip_ddrclk_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   int val;
+
+   val = clk_readl(ddrclk->reg_base +
+   ddrclk->mux_offset) >> ddrclk->div_shift;
+   val &= val_mask(ddrclk->div_width);
+
+   return DIV_ROUND_UP_ULL((u64)parent_rate, val + 1);
+}
+
+static long clk_ddrclk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+   return rate;
+}
+
+static u8 rockchip_ddrclk_get_parent(struct clk_hw *hw)
+{
+   struct rockchip_ddrclk *ddrclk = to_rockchip_ddrclk_hw(hw);
+   int num_parents = clk_hw_get_num_parents(hw);
+   u32 val;
+
+   val = clk_readl(ddrclk->reg_base +
+   ddrclk->mux_offset) >> ddrclk->mux_shift;
+   val &= val_mask(ddrclk->mux_width);
+
+   if (val >= num_parents)
+   return -EINVAL;
+
+   return val;
+}
+
+static const struct clk_ops rockchip_ddrclk_ops = {
+   .recalc_rate = rockchip_ddrclk_recalc_rate,
+   .set_rate = rockchip_ddrclk_set_rate,
+   .round_rate = clk_ddrclk_round_rate,
+   .get_parent = rockchip_ddrclk_get_parent,
+};
+
+struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
+const char *const *parent_names,
+u8 num_parents, int mux_offset,
+int mux_shift, int mux_width,
+int mux_flag, int div_shift,
+int div_width, int div_flag,
+void __iomem *reg_base,
+spinlock_t *lock)
+{
+   struct rockchip_ddrclk *ddrclk;
+   struct clk_init_data init;
+   struct clk *clk;
+   int ret;
+
+   ddrclk = kzalloc(sizeof(*ddrclk), GFP_KERNEL);
+   if (!ddrclk)
+   return ERR_PTR(-ENOMEM);
+
+   init.name = name;
+   init.parent_names = parent_names;
+   init.num_parents = num_parents;
+   init.ops = &rockchip_ddrclk_ops;
+
+   init.flags = flags;
+   init.flags |= CLK_SET_RATE_NO_REPARENT;
+

[RFC PATCH 0/4] rk3399 support ddr frequency scaling

2016-06-01 Thread Lin Huang
rk3399 platform have dfi controller can monitor ddr load,
and dcf controller to handle ddr register so we can get the
right ddr frequency and make ddr controller happy work(which
will implement in bl31). So we do ddr frequency scaling with
following flow:

 kernelbl31

monitor ddr load
|
|
get_target_rate
|
|   pass rate to bl31
clk_set_rate(ddr) ->run dcf flow
|   |
|   |
wait dcf interrupt<---trigger dcf interrupt  
|
|
  return

Lin Huang (4):
  rockchip: rockchip: add new clock-type for the ddrclk
  clk: rockchip: rk3399: add ddrc clock support
  PM / devfreq: rockchip: add devfreq driver for rk3399 dmc
  drm/rockchip: Add dmc notifier in vop driver

 drivers/clk/rockchip/Makefile   |   1 +
 drivers/clk/rockchip/clk-ddr.c  | 147 ++
 drivers/clk/rockchip/clk-rk3399.c   |  16 +
 drivers/clk/rockchip/clk.c  |   9 +
 drivers/clk/rockchip/clk.h  |  27 ++
 drivers/devfreq/Kconfig |   2 +-
 drivers/devfreq/Makefile|   1 +
 drivers/devfreq/rockchip/Kconfig|  14 +
 drivers/devfreq/rockchip/Makefile   |   2 +
 drivers/devfreq/rockchip/rk3399_dmc.c   | 438 
 drivers/devfreq/rockchip/rockchip_dmc.c | 132 +
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  51 +++-
 include/dt-bindings/clock/rk3399-cru.h  |   1 +
 include/soc/rockchip/rockchip_dmc.h |  44 +++
 14 files changed, 882 insertions(+), 3 deletions(-)
 create mode 100644 drivers/clk/rockchip/clk-ddr.c
 create mode 100644 drivers/devfreq/rockchip/Kconfig
 create mode 100644 drivers/devfreq/rockchip/Makefile
 create mode 100644 drivers/devfreq/rockchip/rk3399_dmc.c
 create mode 100644 drivers/devfreq/rockchip/rockchip_dmc.c
 create mode 100644 include/soc/rockchip/rockchip_dmc.h

-- 
1.9.1



[PATCH 3/3] drm/radeon: load different smc firmware on some CI variants

2016-06-01 Thread Alex Deucher
The power tables on some variants require different firmware.
This may fix stability issues on some newer CI parts.

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=91880

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/cik.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index ba192a3..20a4bd5 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -53,6 +53,7 @@ MODULE_FIRMWARE("radeon/bonaire_mc.bin");
 MODULE_FIRMWARE("radeon/bonaire_rlc.bin");
 MODULE_FIRMWARE("radeon/bonaire_sdma.bin");
 MODULE_FIRMWARE("radeon/bonaire_smc.bin");
+MODULE_FIRMWARE("radeon/bonaire_k_smc.bin");

 MODULE_FIRMWARE("radeon/HAWAII_pfp.bin");
 MODULE_FIRMWARE("radeon/HAWAII_me.bin");
@@ -72,6 +73,7 @@ MODULE_FIRMWARE("radeon/hawaii_mc.bin");
 MODULE_FIRMWARE("radeon/hawaii_rlc.bin");
 MODULE_FIRMWARE("radeon/hawaii_sdma.bin");
 MODULE_FIRMWARE("radeon/hawaii_smc.bin");
+MODULE_FIRMWARE("radeon/hawaii_k_smc.bin");

 MODULE_FIRMWARE("radeon/KAVERI_pfp.bin");
 MODULE_FIRMWARE("radeon/KAVERI_me.bin");
@@ -1990,12 +1992,17 @@ static int cik_init_microcode(struct radeon_device 
*rdev)
int new_fw = 0;
int err;
int num_fw;
+   bool new_smc = false;

DRM_DEBUG("\n");

switch (rdev->family) {
case CHIP_BONAIRE:
chip_name = "BONAIRE";
+   if ((rdev->pdev->revision == 0x80) ||
+   (rdev->pdev->revision == 0x81) ||
+   (rdev->pdev->device == 0x665f))
+   new_smc = true;
new_chip_name = "bonaire";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
@@ -2010,6 +2017,8 @@ static int cik_init_microcode(struct radeon_device *rdev)
break;
case CHIP_HAWAII:
chip_name = "HAWAII";
+   if (rdev->pdev->revision == 0x80)
+   new_smc = true;
new_chip_name = "hawaii";
pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
me_req_size = CIK_ME_UCODE_SIZE * 4;
@@ -2259,7 +2268,10 @@ static int cik_init_microcode(struct radeon_device *rdev)
}
}

-   snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", 
new_chip_name);
+   if (new_smc)
+   snprintf(fw_name, sizeof(fw_name), 
"radeon/%s_k_smc.bin", new_chip_name);
+   else
+   snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", 
new_chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", 
chip_name);
-- 
2.5.5



[PATCH 2/3] drm/radeon: load different smc firmware on some SI variants

2016-06-01 Thread Alex Deucher
The power tables on some variants require different firmware.
This may fix stability issues on some newer SI parts.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/si.c | 45 -
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index b30e719..2523ca9 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -50,6 +50,7 @@ MODULE_FIRMWARE("radeon/tahiti_ce.bin");
 MODULE_FIRMWARE("radeon/tahiti_mc.bin");
 MODULE_FIRMWARE("radeon/tahiti_rlc.bin");
 MODULE_FIRMWARE("radeon/tahiti_smc.bin");
+MODULE_FIRMWARE("radeon/tahiti_k_smc.bin");

 MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
@@ -65,6 +66,7 @@ MODULE_FIRMWARE("radeon/pitcairn_ce.bin");
 MODULE_FIRMWARE("radeon/pitcairn_mc.bin");
 MODULE_FIRMWARE("radeon/pitcairn_rlc.bin");
 MODULE_FIRMWARE("radeon/pitcairn_smc.bin");
+MODULE_FIRMWARE("radeon/pitcairn_k_smc.bin");

 MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
 MODULE_FIRMWARE("radeon/VERDE_me.bin");
@@ -80,6 +82,7 @@ MODULE_FIRMWARE("radeon/verde_ce.bin");
 MODULE_FIRMWARE("radeon/verde_mc.bin");
 MODULE_FIRMWARE("radeon/verde_rlc.bin");
 MODULE_FIRMWARE("radeon/verde_smc.bin");
+MODULE_FIRMWARE("radeon/verde_k_smc.bin");

 MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
 MODULE_FIRMWARE("radeon/OLAND_me.bin");
@@ -95,6 +98,7 @@ MODULE_FIRMWARE("radeon/oland_ce.bin");
 MODULE_FIRMWARE("radeon/oland_mc.bin");
 MODULE_FIRMWARE("radeon/oland_rlc.bin");
 MODULE_FIRMWARE("radeon/oland_smc.bin");
+MODULE_FIRMWARE("radeon/oland_k_smc.bin");

 MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
 MODULE_FIRMWARE("radeon/HAINAN_me.bin");
@@ -110,6 +114,7 @@ MODULE_FIRMWARE("radeon/hainan_ce.bin");
 MODULE_FIRMWARE("radeon/hainan_mc.bin");
 MODULE_FIRMWARE("radeon/hainan_rlc.bin");
 MODULE_FIRMWARE("radeon/hainan_smc.bin");
+MODULE_FIRMWARE("radeon/hainan_k_smc.bin");

 static u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
 static void si_pcie_gen3_enable(struct radeon_device *rdev);
@@ -1653,12 +1658,16 @@ static int si_init_microcode(struct radeon_device *rdev)
char fw_name[30];
int err;
int new_fw = 0;
+   bool new_smc = false;

DRM_DEBUG("\n");

switch (rdev->family) {
case CHIP_TAHITI:
chip_name = "TAHITI";
+   /* XXX: figure out which Tahitis need the new ucode */
+   if (0)
+   new_smc = true;
new_chip_name = "tahiti";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1670,6 +1679,13 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_PITCAIRN:
chip_name = "PITCAIRN";
+   if ((rdev->pdev->revision == 0x81) ||
+   (rdev->pdev->device == 0x6810) ||
+   (rdev->pdev->device == 0x6811) ||
+   (rdev->pdev->device == 0x6816) ||
+   (rdev->pdev->device == 0x6817) ||
+   (rdev->pdev->device == 0x6806))
+   new_smc = true;
new_chip_name = "pitcairn";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1681,6 +1697,16 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_VERDE:
chip_name = "VERDE";
+   if ((rdev->pdev->revision == 0x81) ||
+   (rdev->pdev->revision == 0x83) ||
+   (rdev->pdev->revision == 0x87) ||
+   (rdev->pdev->device == 0x6820) ||
+   (rdev->pdev->device == 0x6821) ||
+   (rdev->pdev->device == 0x6822) ||
+   (rdev->pdev->device == 0x6823) ||
+   (rdev->pdev->device == 0x682A) ||
+   (rdev->pdev->device == 0x682B))
+   new_smc = true;
new_chip_name = "verde";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1692,6 +1718,13 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP_OLAND:
chip_name = "OLAND";
+   if ((rdev->pdev->revision == 0xC7) ||
+   (rdev->pdev->revision == 0x80) ||
+   (rdev->pdev->revision == 0x81) ||
+   (rdev->pdev->revision == 0x83) ||
+   (rdev->pdev->device == 0x6604) ||
+   (rdev->pdev->device == 0x6605))
+   new_smc = true;
new_chip_name = "oland";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1702,6 +1735,13 @@ static int si_init_microcode(struct radeon_device *rdev)
break;
case CHIP

[PATCH 1/3] drm/amdgpu: load different smc firmware on some CI variants

2016-06-01 Thread Alex Deucher
The power tables on some variants require different firmware.
This fixes stability issues on some newer CI parts.

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=91880

Signed-off-by: Alex Deucher 
Signed-off-by: Huang Rui 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c 
b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index 5ec1f1e..102d400 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -50,7 +50,9 @@
 #include "gmc/gmc_7_1_sh_mask.h"

 MODULE_FIRMWARE("radeon/bonaire_smc.bin");
+MODULE_FIRMWARE("radeon/bonaire_k_smc.bin");
 MODULE_FIRMWARE("radeon/hawaii_smc.bin");
+MODULE_FIRMWARE("radeon/hawaii_k_smc.bin");

 #define MC_CG_ARB_FREQ_F0   0x0a
 #define MC_CG_ARB_FREQ_F1   0x0b
@@ -5754,10 +5756,18 @@ static int ci_dpm_init_microcode(struct amdgpu_device 
*adev)

switch (adev->asic_type) {
case CHIP_BONAIRE:
-   chip_name = "bonaire";
+   if ((adev->pdev->revision == 0x80) ||
+   (adev->pdev->revision == 0x81) ||
+   (adev->pdev->device == 0x665f))
+   chip_name = "bonaire_k";
+   else
+   chip_name = "bonaire";
break;
case CHIP_HAWAII:
-   chip_name = "hawaii";
+   if (adev->pdev->revision == 0x80)
+   chip_name = "hawaii_k";
+   else
+   chip_name = "hawaii";
break;
case CHIP_KAVERI:
case CHIP_KABINI:
-- 
2.5.5



[PULL v2] drm: atmel-hlcdc: fixes for 4.7-rc2

2016-06-01 Thread Boris Brezillon
Hi Dave,

Same pull request but after fixing the prototype mismatch in patch 1
(this time I tested it).

This pull request contains 2 trivial fixes for the atmel-hlcdc driver.

The first one is making use of __drm_atomic_helper_crtc_destroy_state()
instead of duplicating its logic in atmel_hlcdc_crtc_reset() and
risking memory leaks if other objects are added to the common CRTC
state.

The second one is fixing a possible NULL pointer dereference.

Regards,

Boris

The following changes since commit 1a695a905c18548062509178b98bc91e67510864:

  Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)

are available in the git repository at:

  git at github.com:bbrezillon/linux-at91.git 
tags/drm-atmel-hlcdc-fixes/for-4.7-rc2

for you to fetch changes up to 58a2ab3af722550b2e4e8155eb08660e16c20ee6:

  drm: atmel-hlcdc: fix a NULL check (2016-06-01 15:59:36 +0200)


Two trivial bugfixes for the atmel-hlcdc driver.

The first one is making use of __drm_atomic_helper_crtc_destroy_state()
instead of duplicating its logic in atmel_hlcdc_crtc_reset() and
risking memory leaks if other objects are added to the common CRTC
state.

The second one is fixing a possible NULL pointer dereference.


Boris Brezillon (1):
  drm: atmel-hlcdc: fix atmel_hlcdc_crtc_reset() implementation

Dan Carpenter (1):
  drm: atmel-hlcdc: fix a NULL check

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)


[PATCH] drm/vc4: Fix ioctl permissions for render nodes.

2016-06-01 Thread Eric Anholt
From: Herve Jourdain 

Contrary to other flags to DRM_IOCTL_DEF_DRV(), which restrict usage,
the flag for render node is an enabler (the IOCTL can't be used from
render node if it's not present).  So DRM_RENDER_ALLOW needs to be
added to all the flags that were previously 0.

Signed-off-by: Herve Jourdain 
Signed-off-by: Eric Anholt 
Fixes: 0cd3e2747662 ("drm/vc4: Add missing render node support")
---
 drivers/gpu/drm/vc4/vc4_drv.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index ef7de8eb2b63..250ed7e3754c 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -66,12 +66,12 @@ static const struct file_operations vc4_drm_fops = {
 };

 static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
-   DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0),
-   DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0),
-   DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0),
-   DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
-   DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
-   DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
+   DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 
DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, DRM_RENDER_ALLOW),
+   DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 
DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
  DRM_ROOT_ONLY),
 };
-- 
2.8.0.rc3



[PATCH 01/27] drm/armada: Use lockless gem BO free callback

2016-06-01 Thread Russell King - ARM Linux
On Mon, May 30, 2016 at 07:52:53PM +0200, Daniel Vetter wrote:
> No dev->struct_mutex anywhere to be seen.
> 
> Cc: Russell King 

Acked-by: Russell King 

(please note the new address.)

Thanks.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.


[PATCH] drm/rockchip: vop: do axi reset in vop initial time

2016-06-01 Thread Thierry Reding
On Wed, Jun 01, 2016 at 05:19:12PM +0800, Yakir Yang wrote:
> There is a bug in RK3399 VOP, when bootloader/kernel only enable
> VOP Big or VOP Little to display, then VOP IOMMU would failed to
> reset at the initial time and VOP register couldn't write rightly.
> 
> After do the pure reset of VOP module, then things back to right.
> 
> Signed-off-by: Yakir Yang 
> ---
>  drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 ++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
> b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 1c4d5b5..4150323 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -1292,7 +1292,7 @@ static int vop_initial(struct vop *vop)
>  {
>   const struct vop_data *vop_data = vop->data;
>   const struct vop_reg_data *init_table = vop_data->init_table;
> - struct reset_control *ahb_rst;
> + struct reset_control *ahb_rst, *axi_rst;
>   int i, ret;
>  
>   vop->hclk = devm_clk_get(vop->dev, "hclk_vop");
> @@ -1331,6 +1331,19 @@ static int vop_initial(struct vop *vop)
>   }
>  
>   /*
> +  * do aclk_reset, reset all vop registers.
> +  */
> + axi_rst = devm_reset_control_get(vop->dev, "axi");

I don't think you want the managed version here since you only store
this in a local variable and hence aren't going to need it afterwards.
Just use reset_control_get() and ...

> + if (IS_ERR(axi_rst)) {
> + dev_err(vop->dev, "failed to get axi reset\n");
> + ret = PTR_ERR(axi_rst);
> + goto err_disable_aclk;
> + }
> + reset_control_assert(axi_rst);
> + usleep_range(10, 20);
> + reset_control_deassert(axi_rst);

call reset_control_put() here.

> +
> + /*
>* do hclk_reset, reset all vop registers.
>*/
>   ahb_rst = devm_reset_control_get(vop->dev, "ahb");

This uses the same pattern, so you might want to consider reworking this
as well, though it should be a separate patch.

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


[PATCH] drm/rockchip: vop: do axi reset in vop initial time

2016-06-01 Thread Yakir Yang
There is a bug in RK3399 VOP, when bootloader/kernel only enable
VOP Big or VOP Little to display, then VOP IOMMU would failed to
reset at the initial time and VOP register couldn't write rightly.

After do the pure reset of VOP module, then things back to right.

Signed-off-by: Yakir Yang 
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 1c4d5b5..4150323 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1292,7 +1292,7 @@ static int vop_initial(struct vop *vop)
 {
const struct vop_data *vop_data = vop->data;
const struct vop_reg_data *init_table = vop_data->init_table;
-   struct reset_control *ahb_rst;
+   struct reset_control *ahb_rst, *axi_rst;
int i, ret;

vop->hclk = devm_clk_get(vop->dev, "hclk_vop");
@@ -1331,6 +1331,19 @@ static int vop_initial(struct vop *vop)
}

/*
+* do aclk_reset, reset all vop registers.
+*/
+   axi_rst = devm_reset_control_get(vop->dev, "axi");
+   if (IS_ERR(axi_rst)) {
+   dev_err(vop->dev, "failed to get axi reset\n");
+   ret = PTR_ERR(axi_rst);
+   goto err_disable_aclk;
+   }
+   reset_control_assert(axi_rst);
+   usleep_range(10, 20);
+   reset_control_deassert(axi_rst);
+
+   /*
 * do hclk_reset, reset all vop registers.
 */
ahb_rst = devm_reset_control_get(vop->dev, "ahb");
-- 
1.9.1




[PATCH 3/3] drm/amdgpu: fix pplib finish bug

2016-06-01 Thread Alex Deucher
From: Monk Liu 

1,should use late_fini to kfree all resource otherwise
the released pointer maybe accessed in IRQ ip fini routine.

2,hwmgr should not be kfree by pem_fini which is invoked
by hw fini path.

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c| 5 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 7 ---
 drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c | 3 ---
 3 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index bb8b149..1996670 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1325,6 +1325,11 @@ static int amdgpu_fini(struct amdgpu_device *adev)
adev->ip_block_status[i].valid = false;
}

+   for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+   if (adev->ip_blocks[i].funcs->late_fini)
+   adev->ip_blocks[i].funcs->late_fini((void *)adev);
+   }
+
return 0;
 }

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
index f2e08b35..078f467 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
@@ -184,13 +184,6 @@ static int amdgpu_pp_sw_fini(void *handle)
if (ret)
return ret;

-#ifdef CONFIG_DRM_AMD_POWERPLAY
-   if (adev->pp_enabled) {
-   amdgpu_pm_sysfs_fini(adev);
-   amd_powerplay_fini(adev->powerplay.pp_handle);
-   }
-#endif
-
return ret;
 }

diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c 
b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
index 46410e3..fb88e4e 100644
--- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
@@ -58,9 +58,6 @@ static void pem_fini(struct pp_eventmgr *eventmgr)
pem_unregister_interrupts(eventmgr);

pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data);
-
-   if (eventmgr != NULL)
-   kfree(eventmgr);
 }

 int eventmgr_init(struct pp_instance *handle)
-- 
2.5.5



[PATCH 2/3] drm/amdgpu: impl late_fini for amdgpu_pp_ip

2016-06-01 Thread Alex Deucher
From: Monk Liu 

This adds a late_fini callback for the powerplay
ip module.

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
index cfbb360..f2e08b35 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
@@ -224,6 +224,22 @@ static int amdgpu_pp_hw_fini(void *handle)
return ret;
 }

+static void amdgpu_pp_late_fini(void *handle)
+{
+   struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+   if (adev->pp_enabled) {
+   amdgpu_pm_sysfs_fini(adev);
+   amd_powerplay_fini(adev->powerplay.pp_handle);
+   }
+
+   if (adev->powerplay.ip_funcs->late_fini)
+   adev->powerplay.ip_funcs->late_fini(
+ adev->powerplay.pp_handle);
+#endif
+}
+
 static int amdgpu_pp_suspend(void *handle)
 {
int ret = 0;
@@ -312,6 +328,7 @@ const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
.sw_fini = amdgpu_pp_sw_fini,
.hw_init = amdgpu_pp_hw_init,
.hw_fini = amdgpu_pp_hw_fini,
+   .late_fini = amdgpu_pp_late_fini,
.suspend = amdgpu_pp_suspend,
.resume = amdgpu_pp_resume,
.is_idle = amdgpu_pp_is_idle,
-- 
2.5.5



[PATCH 1/3] drm/amdgpu: add late_fini for ip_funcs

2016-06-01 Thread Alex Deucher
From: Monk Liu 

This adds a late_fini function for handling special
ordering issues between ip modules at tear down time.

Signed-off-by: Monk Liu 
Reviewed-by: Alex Deucher 
Reviewed-by: Christian König 
Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/include/amd_shared.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/include/amd_shared.h 
b/drivers/gpu/drm/amd/include/amd_shared.h
index 147b2eb..afbd876 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -159,6 +159,7 @@ struct amd_ip_funcs {
int (*hw_init)(void *handle);
/* tears down the hw state */
int (*hw_fini)(void *handle);
+   void (*late_fini)(void *handle);
/* handles IP specific hw/sw changes for suspend */
int (*suspend)(void *handle);
/* handles IP specific hw/sw changes for resume */
-- 
2.5.5



[PATCH 0/3] fix module unloading with powerplay enabled

2016-06-01 Thread Alex Deucher
This fixes a crash in module unloading with powerplay enabled
due to cross IP module dependencies.

Monk Liu (3):
  drm/amdgpu: add late_fini for ip_funcs
  drm/amdgpu: impl late_fini for amdgpu_pp_ip
  drm/amdgpu: fix pplib finish bug

 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c|  5 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | 24 ---
 drivers/gpu/drm/amd/include/amd_shared.h  |  1 +
 drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c |  3 ---
 4 files changed, 23 insertions(+), 10 deletions(-)

-- 
2.5.5



[RFC v2 3/5] drm/mediatek: add *driver_data for different hardware settings

2016-06-01 Thread YT Shen
Hi Thierry,

On Mon, 2016-05-30 at 12:45 +0200, Thierry Reding wrote:
> On Mon, May 23, 2016 at 05:43:02PM +0800, CK Hu wrote:
> > Hi, YT:
> > 
> > One comment below.
> > 
> > On Fri, 2016-05-20 at 23:05 +0800, yt.shen at mediatek.com wrote:
> > > From: YT Shen 
> > > 
> > > There are some hardware settings changed, between MT8173 & MT2701:
> > > DISP_OVL address offset changed, color format definition changed.
> > > DISP_RDMA fifo size changed.
> > > DISP_COLOR offset changed.
> > > 
> > > Signed-off-by: YT Shen 
> > > ---
> > > +
> > > +static inline struct mtk_ddp_comp_driver_data *mtk_ovl_get_driver_data(
> > > + struct platform_device *pdev)
> > > +{
> > > + const struct of_device_id *of_id =
> > > + of_match_device(mtk_disp_ovl_driver_dt_match, &pdev->dev);
> > > +
> > > + return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > > +}
> > > +
> > > +static inline struct mtk_ddp_comp_driver_data *mtk_rdma_get_driver_data(
> > > + struct platform_device *pdev)
> > > +{
> > > + const struct of_device_id *of_id =
> > > + of_match_device(mtk_disp_rdma_driver_dt_match, &pdev->dev);
> > > +
> > > + return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > > +}
> > > +
> > > +static inline struct mtk_ddp_comp_driver_data *mtk_color_get_driver_data(
> > > + struct device_node *node)
> > > +{
> > > + const struct of_device_id *of_id =
> > > + of_match_node(mtk_disp_color_driver_dt_match, node);
> > > +
> > > + return (struct mtk_ddp_comp_driver_data *)of_id->data;
> > > +}
> > > + 
> > 
> > These three functions looks the same with different parameter:
> > mtk_disp_ovl_driver_dt_match, mtk_disp_rdma_driver_dt_match, and
> > mtk_disp_color_driver_dt_match. So merge them to prevent duplicated
> > code.
> 
> I think what you really want is of_device_get_match_data().
> 
> Thierry

Great, that function is really what we need, thanks.

yt.shen




[RFC v2 1/5] drm/mediatek: rename macros, add chip suffix

2016-06-01 Thread YT Shen
Hi Thierry,

On Mon, 2016-05-30 at 12:41 +0200, Thierry Reding wrote:
> On Fri, May 20, 2016 at 11:05:32PM +0800, yt.shen at mediatek.com wrote:
> > From: YT Shen 
> > 
> > Add MT8173 suffix for hardware related macros.
> > 
> > Signed-off-by: YT Shen 
> > ---
> >  drivers/gpu/drm/mediatek/mtk_drm_ddp.c |   62 
> > 
> >  1 file changed, 31 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c 
> > b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> > index 17ba935..d6aafd4 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
> > @@ -36,21 +36,21 @@
> >  #define DISP_REG_MUTEX_MOD(n)  (0x2c + 0x20 * (n))
> >  #define DISP_REG_MUTEX_SOF(n)  (0x30 + 0x20 * (n))
> >  
> > -#define MUTEX_MOD_DISP_OVL0BIT(11)
> > -#define MUTEX_MOD_DISP_OVL1BIT(12)
> > -#define MUTEX_MOD_DISP_RDMA0   BIT(13)
> > -#define MUTEX_MOD_DISP_RDMA1   BIT(14)
> > -#define MUTEX_MOD_DISP_RDMA2   BIT(15)
> > -#define MUTEX_MOD_DISP_WDMA0   BIT(16)
> > -#define MUTEX_MOD_DISP_WDMA1   BIT(17)
> > -#define MUTEX_MOD_DISP_COLOR0  BIT(18)
> > -#define MUTEX_MOD_DISP_COLOR1  BIT(19)
> > -#define MUTEX_MOD_DISP_AAL BIT(20)
> > -#define MUTEX_MOD_DISP_GAMMA   BIT(21)
> > -#define MUTEX_MOD_DISP_UFOEBIT(22)
> > -#define MUTEX_MOD_DISP_PWM0BIT(23)
> > -#define MUTEX_MOD_DISP_PWM1BIT(24)
> > -#define MUTEX_MOD_DISP_OD  BIT(25)
> > +#define MUTEX_MOD_DISP_OVL0_MT8173 BIT(11)
> > +#define MUTEX_MOD_DISP_OVL1_MT8173 BIT(12)
> > +#define MUTEX_MOD_DISP_RDMA0_MT8173BIT(13)
> > +#define MUTEX_MOD_DISP_RDMA1_MT8173BIT(14)
> > +#define MUTEX_MOD_DISP_RDMA2_MT8173BIT(15)
> > +#define MUTEX_MOD_DISP_WDMA0_MT8173BIT(16)
> > +#define MUTEX_MOD_DISP_WDMA1_MT8173BIT(17)
> > +#define MUTEX_MOD_DISP_COLOR0_MT8173   BIT(18)
> > +#define MUTEX_MOD_DISP_COLOR1_MT8173   BIT(19)
> > +#define MUTEX_MOD_DISP_AAL_MT8173  BIT(20)
> > +#define MUTEX_MOD_DISP_GAMMA_MT8173BIT(21)
> > +#define MUTEX_MOD_DISP_UFOE_MT8173 BIT(22)
> > +#define MUTEX_MOD_DISP_PWM0_MT8173 BIT(23)
> > +#define MUTEX_MOD_DISP_PWM1_MT8173 BIT(24)
> > +#define MUTEX_MOD_DISP_OD_MT8173   BIT(25)
> 
> Just a random fly-by comment: this looks like a hardware spinlock, have
> you ever considered implementing this as a hwspinlock driver? See the
> drivers/hwspinlock subdirectory for existing examples.
> 
> Thierry

I see the drivers/hwspinlock and Documentation/hwspinlock.txt
Yes, we can implement this like a hardware spinlock.  But I have some
questions, the document says:

"Hardware spinlock modules provide hardware assistance for
synchronization and mutual exclusion between heterogeneous processors
and those not operating under a single, shared operating system"

The mutex here is a handshake interface between software and hardware.
The hardware is the display controller, the software is the drm display
driver, and no other consumers need to access this mutex.  So I think
that using hwspinlock to implement a bit too complicated, am I right?

I will use iopoll macros to implement this part in the next version.
Thanks.

yt.shen





[PATCH 12/12] drm/radeon/atpx: drop forcing of dGPU power control

2016-06-01 Thread Alex Deucher
Now that we handle this correctly, there is no need to force
it.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon_atpx_handler.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 
b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 51da319..6996b31 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -193,11 +193,6 @@ static int radeon_atpx_validate(struct radeon_atpx *atpx)
if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
printk("Hybrid Graphics, ATPX dGPU power cntl disabled\n");
atpx->functions.power_cntl = false;
-   } else if (atpx->functions.power_cntl == false) {
-   /* make sure required functions are enabled */
-   /* dGPU power control is required */
-   printk("ATPX dGPU power cntl not present, forcing\n");
-   atpx->functions.power_cntl = true;
}

return 0;
-- 
2.5.5



[PATCH 11/12] drm/radeon: use PCI_D3hot for PX systems without dGPU power control

2016-06-01 Thread Alex Deucher
On PX systems without dGPU power control, use PCI_D3hot.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon_drv.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 2dc43f5..ec80050 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -415,7 +415,10 @@ static int radeon_pmops_runtime_suspend(struct device *dev)
pci_save_state(pdev);
pci_disable_device(pdev);
pci_ignore_hotplug(pdev);
-   pci_set_power_state(pdev, PCI_D3cold);
+   if (radeon_has_atpx_dgpu_power_cntl())
+   pci_set_power_state(pdev, PCI_D3cold);
+   else
+   pci_set_power_state(pdev, PCI_D3hot);
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;

return 0;
-- 
2.5.5



[PATCH 10/12] drm/radeon/atpx: add a query for ATPX dGPU power control

2016-06-01 Thread Alex Deucher
The runtime pm sequence is different depending on whether or
not the platform supports ATPX dGPU power control.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon_atpx_handler.c | 4 
 drivers/gpu/drm/radeon/radeon_drv.c  | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 
b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 3d95194..51da319 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -63,6 +63,10 @@ bool radeon_has_atpx(void) {
return radeon_atpx_priv.atpx_detected;
 }

+bool radeon_has_atpx_dgpu_power_cntl(void) {
+   return radeon_atpx_priv.atpx.functions.power_cntl;
+}
+
 /**
  * radeon_atpx_call - call an ATPX method
  *
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c 
b/drivers/gpu/drm/radeon/radeon_drv.c
index 36242a9..2dc43f5 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -165,9 +165,11 @@ void radeon_debugfs_cleanup(struct drm_minor *minor);
 #if defined(CONFIG_VGA_SWITCHEROO)
 void radeon_register_atpx_handler(void);
 void radeon_unregister_atpx_handler(void);
+bool radeon_has_atpx_dgpu_power_cntl(void);
 #else
 static inline void radeon_register_atpx_handler(void) {}
 static inline void radeon_unregister_atpx_handler(void) {}
+static inline bool radeon_has_atpx_dgpu_power_cntl(void) { return false; }
 #endif

 int radeon_no_wb;
-- 
2.5.5



[PATCH 09/12] drm/radeon: add a delay after ATPX dGPU power off

2016-06-01 Thread Alex Deucher
ATPX dGPU power control requires a 200ms delay between
power off and on.  This should fix dGPU failures on
resume from power off.

Signed-off-by: Alex Deucher 
Cc: stable at vger.kernel.org
---
 drivers/gpu/drm/radeon/radeon_atpx_handler.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 
b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 55efbcd..3d95194 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 

 #include "radeon_acpi.h"

@@ -269,6 +270,10 @@ static int radeon_atpx_set_discrete_state(struct 
radeon_atpx *atpx, u8 state)
if (!info)
return -EIO;
kfree(info);
+
+   /* 200ms delay is required after off */
+   if (state == 0)
+   msleep(200);
}
return 0;
 }
-- 
2.5.5



[PATCH 08/12] drm/radeon: clean up atpx power control handling

2016-06-01 Thread Alex Deucher
The presence of the power control method should be determined
via the presence of the method in function 0.  However, some
sbioses only set the appropriate bits in function 1 so use
then to override a missing power control function.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon_atpx_handler.c | 50 
 1 file changed, 28 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 
b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 3e24fe0..55efbcd 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -141,18 +141,12 @@ static void radeon_atpx_parse_functions(struct 
radeon_atpx_functions *f, u32 mas
  */
 static int radeon_atpx_validate(struct radeon_atpx *atpx)
 {
-   /* make sure required functions are enabled */
-   /* dGPU power control is required */
-   if (atpx->functions.power_cntl == false) {
-   printk("ATPX dGPU power cntl not present, forcing\n");
-   atpx->functions.power_cntl = true;
-   }
+   u32 valid_bits = 0;

if (atpx->functions.px_params) {
union acpi_object *info;
struct atpx_px_params output;
size_t size;
-   u32 valid_bits;

info = radeon_atpx_call(atpx->handle, 
ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
if (!info)
@@ -171,24 +165,36 @@ static int radeon_atpx_validate(struct radeon_atpx *atpx)
memcpy(&output, info->buffer.pointer, size);

valid_bits = output.flags & output.valid_flags;
-   /* if separate mux flag is set, mux controls are required */
-   if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
-   atpx->functions.i2c_mux_cntl = true;
-   atpx->functions.disp_mux_cntl = true;
-   }
-   /* if any outputs are muxed, mux controls are required */
-   if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
- ATPX_TV_SIGNAL_MUXED |
- ATPX_DFP_SIGNAL_MUXED))
-   atpx->functions.disp_mux_cntl = true;
-
-   if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
-   printk("Hybrid Graphics, ATPX dGPU power cntl 
disabled\n");
-   atpx->functions.power_cntl = false;
-   }

kfree(info);
}
+
+   /* if separate mux flag is set, mux controls are required */
+   if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
+   atpx->functions.i2c_mux_cntl = true;
+   atpx->functions.disp_mux_cntl = true;
+   }
+   /* if any outputs are muxed, mux controls are required */
+   if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
+ ATPX_TV_SIGNAL_MUXED |
+ ATPX_DFP_SIGNAL_MUXED))
+   atpx->functions.disp_mux_cntl = true;
+
+   /* some bioses set these bits rather than flagging power_cntl as 
supported */
+   if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
+ ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
+   atpx->functions.power_cntl = true;
+
+   if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
+   printk("Hybrid Graphics, ATPX dGPU power cntl disabled\n");
+   atpx->functions.power_cntl = false;
+   } else if (atpx->functions.power_cntl == false) {
+   /* make sure required functions are enabled */
+   /* dGPU power control is required */
+   printk("ATPX dGPU power cntl not present, forcing\n");
+   atpx->functions.power_cntl = true;
+   }
+
return 0;
 }

-- 
2.5.5



[PATCH 07/12] drm/radeon: disable power control on hybrid laptops

2016-06-01 Thread Alex Deucher
Windows 10 (and some 8.1) systems use standardized
ACPI calls for hybrid laptops to control dGPU power.
Detect those cases and disable the AMD specific ATPX
power control.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/radeon/radeon_atpx_handler.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 
b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 95f4fea..3e24fe0 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -182,6 +182,11 @@ static int radeon_atpx_validate(struct radeon_atpx *atpx)
  ATPX_DFP_SIGNAL_MUXED))
atpx->functions.disp_mux_cntl = true;

+   if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
+   printk("Hybrid Graphics, ATPX dGPU power cntl 
disabled\n");
+   atpx->functions.power_cntl = false;
+   }
+
kfree(info);
}
return 0;
-- 
2.5.5



[PATCH 06/12] drm/amdgpu/atpx: drop forcing of dGPU power control

2016-06-01 Thread Alex Deucher
Now that we handle this correctly, there is no need to force
it.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 7b11af1..90dfedc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -195,11 +195,6 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
printk("Hybrid Graphics, ATPX dGPU power cntl disabled\n");
atpx->functions.power_cntl = false;
-   } else if (atpx->functions.power_cntl == false) {
-   /* make sure required functions are enabled */
-   /* dGPU power control is required */
-   printk("ATPX dGPU power cntl not present, forcing\n");
-   atpx->functions.power_cntl = true;
}

return 0;
-- 
2.5.5



[PATCH 05/12] drm/amdgpu: use PCI_D3hot for PX systems without dGPU power control

2016-06-01 Thread Alex Deucher
On PX systems without dGPU power control, use PCI_D3hot.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index f122703..7e49bf4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -417,7 +417,10 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
pci_save_state(pdev);
pci_disable_device(pdev);
pci_ignore_hotplug(pdev);
-   pci_set_power_state(pdev, PCI_D3cold);
+   if (amdgpu_has_atpx_dgpu_power_cntl())
+   pci_set_power_state(pdev, PCI_D3cold);
+   else
+   pci_set_power_state(pdev, PCI_D3hot);
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;

return 0;
-- 
2.5.5



[PATCH 04/12] drm/amdgpu/atpx: add a query for ATPX dGPU power control

2016-06-01 Thread Alex Deucher
The runtime pm sequence is different depending on whether or
not the platform supports ATPX dGPU power control.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h  | 2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 4 
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index ab122cc4..19d15dc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -2393,9 +2393,11 @@ bool amdgpu_device_is_px(struct drm_device *dev);
 #if defined(CONFIG_VGA_SWITCHEROO)
 void amdgpu_register_atpx_handler(void);
 void amdgpu_unregister_atpx_handler(void);
+bool amdgpu_has_atpx_dgpu_power_cntl(void);
 #else
 static inline void amdgpu_register_atpx_handler(void) {}
 static inline void amdgpu_unregister_atpx_handler(void) {}
+static inline bool amdgpu_has_atpx_dgpu_power_cntl(void) { return false; }
 #endif

 /*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index c5d280c..7b11af1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -64,6 +64,10 @@ bool amdgpu_has_atpx(void) {
return amdgpu_atpx_priv.atpx_detected;
 }

+bool amdgpu_has_atpx_dgpu_power_cntl(void) {
+   return amdgpu_atpx_priv.atpx.functions.power_cntl;
+}
+
 /**
  * amdgpu_atpx_call - call an ATPX method
  *
-- 
2.5.5



[PATCH 03/12] drm/amdgpu: add a delay after ATPX dGPU power off

2016-06-01 Thread Alex Deucher
ATPX dGPU power control requires a 200ms delay between
power off and on.  This should fix dGPU failures on
resume from power off.

Signed-off-by: Alex Deucher 
Cc: stable at vger.kernel.org
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 1be2ce4..c5d280c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 

 #include "amd_acpi.h"

@@ -271,6 +272,10 @@ static int amdgpu_atpx_set_discrete_state(struct 
amdgpu_atpx *atpx, u8 state)
if (!info)
return -EIO;
kfree(info);
+
+   /* 200ms delay is required after off */
+   if (state == 0)
+   msleep(200);
}
return 0;
 }
-- 
2.5.5



[PATCH 02/12] drm/amdgpu: clean up atpx power control handling

2016-06-01 Thread Alex Deucher
The presence of the power control method should be determined
via the presence of the method in function 0.  However, some
sbioses only set the appropriate bits in function 1 so use
then to override a missing power control function.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 51 ++--
 1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 3af1c3a..1be2ce4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -142,18 +142,12 @@ static void amdgpu_atpx_parse_functions(struct 
amdgpu_atpx_functions *f, u32 mas
  */
 static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
 {
-   /* make sure required functions are enabled */
-   /* dGPU power control is required */
-   if (atpx->functions.power_cntl == false) {
-   printk("ATPX dGPU power cntl not present, forcing\n");
-   atpx->functions.power_cntl = true;
-   }
+   u32 valid_bits = 0;

if (atpx->functions.px_params) {
union acpi_object *info;
struct atpx_px_params output;
size_t size;
-   u32 valid_bits;

info = amdgpu_atpx_call(atpx->handle, 
ATPX_FUNCTION_GET_PX_PARAMETERS, NULL);
if (!info)
@@ -172,24 +166,37 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
memcpy(&output, info->buffer.pointer, size);

valid_bits = output.flags & output.valid_flags;
-   /* if separate mux flag is set, mux controls are required */
-   if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
-   atpx->functions.i2c_mux_cntl = true;
-   atpx->functions.disp_mux_cntl = true;
-   }
-   /* if any outputs are muxed, mux controls are required */
-   if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
- ATPX_TV_SIGNAL_MUXED |
- ATPX_DFP_SIGNAL_MUXED))
-   atpx->functions.disp_mux_cntl = true;
-
-   if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
-   printk("Hybrid Graphics, ATPX dGPU power cntl 
disabled\n");
-   atpx->functions.power_cntl = false;
-   }

kfree(info);
}
+
+   /* if separate mux flag is set, mux controls are required */
+   if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) {
+   atpx->functions.i2c_mux_cntl = true;
+   atpx->functions.disp_mux_cntl = true;
+   }
+   /* if any outputs are muxed, mux controls are required */
+   if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED |
+ ATPX_TV_SIGNAL_MUXED |
+ ATPX_DFP_SIGNAL_MUXED))
+   atpx->functions.disp_mux_cntl = true;
+
+
+   /* some bioses set these bits rather than flagging power_cntl as 
supported */
+   if (valid_bits & (ATPX_DYNAMIC_PX_SUPPORTED |
+ ATPX_DYNAMIC_DGPU_POWER_OFF_SUPPORTED))
+   atpx->functions.power_cntl = true;
+
+   if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
+   printk("Hybrid Graphics, ATPX dGPU power cntl disabled\n");
+   atpx->functions.power_cntl = false;
+   } else if (atpx->functions.power_cntl == false) {
+   /* make sure required functions are enabled */
+   /* dGPU power control is required */
+   printk("ATPX dGPU power cntl not present, forcing\n");
+   atpx->functions.power_cntl = true;
+   }
+
return 0;
 }

-- 
2.5.5



[PATCH 01/12] drm/amdgpu: disable power control on hybrid laptops

2016-06-01 Thread Alex Deucher
Windows 10 (and some 8.1) systems use standardized
ACPI calls for hybrid laptops to control dGPU power.
Detect those cases and disable the AMD specific ATPX
power control.

Signed-off-by: Alex Deucher 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 35a1248..3af1c3a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -183,6 +183,11 @@ static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
  ATPX_DFP_SIGNAL_MUXED))
atpx->functions.disp_mux_cntl = true;

+   if (valid_bits & ATPX_MS_HYBRID_GFX_SUPPORTED) {
+   printk("Hybrid Graphics, ATPX dGPU power cntl 
disabled\n");
+   atpx->functions.power_cntl = false;
+   }
+
kfree(info);
}
return 0;
-- 
2.5.5



[PATCH 00/12] Improve PX support in radeon and amdgpu

2016-06-01 Thread Alex Deucher
This patch set cleans up and attempts to make runtime pm more
reliable in radeon and amdgpu on PX systems.  If you have a PX
system that requires setting the runpm=0 module parameter for
stability, please try this patch set.

The main fix is that a minimum of 200ms of delay is required between
a dGPU power down and a power up.

This patch also properly handles the detection of the ATPX dGPU
power control method properly and handles dGPU power control for
platforms that do not support the ATPX dGPU power control method.

Alex Deucher (12):
  drm/amdgpu: disable power control on hybrid laptops
  drm/amdgpu: clean up atpx power control handling
  drm/amdgpu: add a delay after ATPX dGPU power off
  drm/amdgpu/atpx: add a query for ATPX dGPU power control
  drm/amdgpu: use PCI_D3hot for PX systems without dGPU power control
  drm/amdgpu/atpx: drop forcing of dGPU power control
  drm/radeon: disable power control on hybrid laptops
  drm/radeon: clean up atpx power control handling
  drm/radeon: add a delay after ATPX dGPU power off
  drm/radeon/atpx: add a query for ATPX dGPU power control
  drm/radeon: use PCI_D3hot for PX systems without dGPU power control
  drm/radeon/atpx: drop forcing of dGPU power control

 drivers/gpu/drm/amd/amdgpu/amdgpu.h  |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 50 
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  |  5 ++-
 drivers/gpu/drm/radeon/radeon_atpx_handler.c | 49 +++
 drivers/gpu/drm/radeon/radeon_drv.c  |  7 +++-
 5 files changed, 77 insertions(+), 36 deletions(-)

-- 
2.5.5



[PATCH v2 4/5] drm: hdlcd: Don't touch vsync interrupts during vblank enable/disable.

2016-06-01 Thread Daniel Vetter
On Wed, Jun 01, 2016 at 03:48:38PM +0100, Liviu Dudau wrote:
> Because the HDLCD lacks a hardware counter for vsync signal, the DRM
> framework expects that the vsync interrupts are left running to feed
> the internal software counter. Currently the HDLCD is masking/unmasking
> the vsync interrupt on vblank enable/disable calls, which break that
> expectation. Fix that.
> 
> Signed-off-by: Liviu Dudau 

As discussed, this is actually not needed. The only thing you need to do
is set max_vblank_count = 0. If vblank enable/disable is causing problems,
then that would indicate an issue in the core drm_irq.c code, and should
be fixed there.

And if the docs are confusion, then please update those insted. This patch
here shouldn't be needed at all.
-Daniel

> ---
>  drivers/gpu/drm/arm/hdlcd_drv.c | 15 +--
>  1 file changed, 5 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
> index fb172d2..3f92dfa 100644
> --- a/drivers/gpu/drm/arm/hdlcd_drv.c
> +++ b/drivers/gpu/drm/arm/hdlcd_drv.c
> @@ -183,9 +183,13 @@ static int hdlcd_irq_postinstall(struct drm_device *drm)
>  
>   /* enable debug interrupts */
>   irq_mask |= HDLCD_DEBUG_INT_MASK;
> +#endif
> +
> + /* enable vsync interrupts */
> + irq_mask |= HDLCD_INTERRUPT_VSYNC;
>  
>   hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
> -#endif
> +
>   return 0;
>  }
>  
> @@ -208,20 +212,11 @@ static void hdlcd_irq_uninstall(struct drm_device *drm)
>  
>  static int hdlcd_enable_vblank(struct drm_device *drm, unsigned int crtc)
>  {
> - struct hdlcd_drm_private *hdlcd = drm->dev_private;
> - unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
> -
> - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask | HDLCD_INTERRUPT_VSYNC);
> -
>   return 0;
>  }
>  
>  static void hdlcd_disable_vblank(struct drm_device *drm, unsigned int crtc)
>  {
> - struct hdlcd_drm_private *hdlcd = drm->dev_private;
> - unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
> -
> - hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask & ~HDLCD_INTERRUPT_VSYNC);
>  }
>  
>  #ifdef CONFIG_DEBUG_FS
> -- 
> 2.8.2
> 
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH] drm/doc: Switch to sphinx/rst fixed-width quoting

2016-06-01 Thread Jani Nikula
On Wed, 01 Jun 2016, Daniel Vetter  wrote:
> On Wed, Jun 1, 2016 at 11:46 AM, Jani Nikula
>  wrote:
>> On Wed, 01 Jun 2016, Daniel Vetter  wrote:
>>> There's still something very fishy going on with some of these, e.g.
>>> the drm_modeset_lock Example: and the "Standard GTF Parameters:" Line
>>> somehow get treated as heading when just appending a :: at the end of
>>> those lines. But it seems to work everywhere else. Maybe the
>>> kernel-doc heading generation logic is still a bit wonky?
>>
>> Try adding a blank line between the line with trailing :: and the actual
>> preformatted text. Seems to do the right thing for me.
>>
>> http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#literal-blocks
>>
>> "Blank lines are required before and after a literal block, but these
>> blank lines are not included as part of the literal block."
>
> That's not what I've meant. The following sometimes (but not always,
> only in the 2 places I've mentioned) becomes a kernel-doc directive

What do you mean by "kernel-doc directive" exactly?

> and not a block quote:
>
>  * Standard GTF Parameters::
>  *
>  * stuff I wanted to have block quoted.
>
> But if I switch the :: to be on a line of it's own (like in the patch)
> it's totally fine.

Odd. It does seem to work for me. What does this print near there?

$ scripts/kernel-doc -rst -function drm_gtf_mode drivers/gpu/drm/drm_modes.c



BR,
Jani.



-- 
Jani Nikula, Intel Open Source Technology Center


[PATCH] drm/doc: Switch to sphinx/rst fixed-width quoting

2016-06-01 Thread Daniel Vetter
Just fallout from switching from asciidoc to sphinx/rst.

v2: Found more. Also s/\//#/ in the vgpu ascii-art - sphinx treats
those as comments and switch to variable-width, which wreaks the
layout.

v3: Undo some of the hacks, rebasing onto latest version of Jani's
series fixed it.

Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_bridge.c|  2 +-
 drivers/gpu/drm/drm_fb_cma_helper.c |  2 +-
 drivers/gpu/drm/drm_fops.c  |  2 +-
 drivers/gpu/drm/drm_modes.c |  3 ++-
 drivers/gpu/drm/drm_modeset_lock.c  |  2 +-
 drivers/gpu/drm/drm_vma_manager.c   |  3 +++
 drivers/gpu/drm/i915/i915_reg.h |  2 +-
 drivers/gpu/drm/i915/i915_vgpu.c| 24 
 include/drm/drm_modes.h |  2 ++
 9 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index b3654404abd0..255543086590 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -36,7 +36,7 @@
  * encoder chain.
  *
  * A bridge is always attached to a single &drm_encoder at a time, but can be
- * either connected to it directly, or through an intermediate bridge:
+ * either connected to it directly, or through an intermediate bridge::
  *
  * encoder ---> bridge B ---> bridge A
  *
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c 
b/drivers/gpu/drm/drm_fb_cma_helper.c
index 2b33b191a172..c50a0ba6fdba 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -52,7 +52,7 @@ struct drm_fbdev_cma {
  * will be set up automatically. dirty() is called by
  * drm_fb_helper_deferred_io() in process context (struct delayed_work).
  *
- * Example fbdev deferred io code:
+ * Example fbdev deferred io code::
  *
  * static int driver_fbdev_fb_dirty(struct drm_framebuffer *fb,
  *  struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 5921b203503a..323c238fcac7 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -68,7 +68,7 @@ DEFINE_MUTEX(drm_global_mutex);
  * specific implementations. For GEM-based drivers this is drm_gem_mmap().
  *
  * No other file operations are supported by the DRM userspace API. Overall the
- * following is an example #file_operations structure:
+ * following is an example #file_operations structure::
  *
  * static const example_drm_fops = {
  * .owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index e5e6f504d8cc..1eb679e5fbb1 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -552,7 +552,8 @@ EXPORT_SYMBOL(drm_gtf_mode_complex);
  * I also refer to the function of fb_get_mode in the file of
  * drivers/video/fbmon.c
  *
- * Standard GTF parameters:
+ * Standard GTF parameters::
+ *
  * M = 600
  * C = 40
  * K = 128
diff --git a/drivers/gpu/drm/drm_modeset_lock.c 
b/drivers/gpu/drm/drm_modeset_lock.c
index f33ebe638a28..61146f5b4f56 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -37,7 +37,7 @@
  *
  * For basic principles of &ww_mutex, see: 
Documentation/locking/ww-mutex-design.txt
  *
- * The basic usage pattern is to:
+ * The basic usage pattern is to::
  *
  * drm_modeset_acquire_init(&ctx)
  * retry:
diff --git a/drivers/gpu/drm/drm_vma_manager.c 
b/drivers/gpu/drm/drm_vma_manager.c
index 2f2ecde8285b..f306c8855978 100644
--- a/drivers/gpu/drm/drm_vma_manager.c
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -127,6 +127,9 @@ EXPORT_SYMBOL(drm_vma_offset_manager_destroy);
  * used to implement weakly referenced lookups using kref_get_unless_zero().
  *
  * Example:
+ *
+ * ::
+ *
  * drm_vma_offset_lock_lookup(mgr);
  * node = drm_vma_offset_lookup_locked(mgr);
  * if (node)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 216cc4ba74ee..d25dd1d694bc 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -886,7 +886,7 @@ enum skl_disp_power_wells {
  * PLLs can be routed to any transcoder A/B/C.
  *
  * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is
- * digital port D (CHV) or port A (BXT).
+ * digital port D (CHV) or port A (BXT). ::
  *
  *
  * Dual channel PHY (VLV/CHV/BXT)
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
index d5a7a5e7ee7e..004326291854 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.c
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
@@ -150,28 +150,28 @@ static int vgt_balloon_space(struct drm_mm *mm,
  * of its graphic space being zero. Yet there are some portions ballooned out(
  * the shadow part, which are marked as reserved by drm allocator). From the
  * host point of view, the graphic address space is partitioned by multiple
- * vGPUs in different VMs.
+ * vGPUs in different VMs. ::
  *
  *vGPU1 view Host view
  *

[PATCH] drm/doc: Switch to sphinx/rst fixed-width quoting

2016-06-01 Thread Daniel Vetter
On Wed, Jun 01, 2016 at 04:46:10PM +0300, Jani Nikula wrote:
> On Wed, 01 Jun 2016, Daniel Vetter  wrote:
> > On Wed, Jun 1, 2016 at 11:46 AM, Jani Nikula
> >  wrote:
> >> On Wed, 01 Jun 2016, Daniel Vetter  wrote:
> >>> There's still something very fishy going on with some of these, e.g.
> >>> the drm_modeset_lock Example: and the "Standard GTF Parameters:" Line
> >>> somehow get treated as heading when just appending a :: at the end of
> >>> those lines. But it seems to work everywhere else. Maybe the
> >>> kernel-doc heading generation logic is still a bit wonky?
> >>
> >> Try adding a blank line between the line with trailing :: and the actual
> >> preformatted text. Seems to do the right thing for me.
> >>
> >> http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#literal-blocks
> >>
> >> "Blank lines are required before and after a literal block, but these
> >> blank lines are not included as part of the literal block."
> >
> > That's not what I've meant. The following sometimes (but not always,
> > only in the 2 places I've mentioned) becomes a kernel-doc directive
> 
> What do you mean by "kernel-doc directive" exactly?
> 
> > and not a block quote:
> >
> >  * Standard GTF Parameters::
> >  *
> >  * stuff I wanted to have block quoted.
> >
> > But if I switch the :: to be on a line of it's own (like in the patch)
> > it's totally fine.
> 
> Odd. It does seem to work for me. What does this print near there?
> 
> $ scripts/kernel-doc -rst -function drm_gtf_mode drivers/gpu/drm/drm_modes.c

Tried again, it works now. Probably fixed through some rebasing and me
being on an older version of your toolchain. I'll send out v3.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH v2 02/21] drm: Add a callback from connector registering

2016-06-01 Thread Daniel Vetter
On Wed, Jun 01, 2016 at 11:38:03AM +0100, Chris Wilson wrote:
> On Wed, Jun 01, 2016 at 11:57:09AM +0200, Daniel Vetter wrote:
> > On Mon, May 30, 2016 at 09:38:20AM +0100, Chris Wilson wrote:
> > > If a driver wants to more precisely control its initialisation and in
> > > particular, defer registering its interfaces with userspace until after
> > > everything is setup, it also needs to defer registering the connectors.
> > > As some devices need more work during registration, add a callback so
> > > that drivers can do additional work if required for a connector.
> > > 
> > > Correspondingly, we also require an unregister callback.
> > > 
> > > Signed-off-by: Chris Wilson 
> > > Cc: Daniel Vetter 
> > > Cc: dri-devel at lists.freedesktop.org
> > 
> > tbh I'd call these hooks simply register/unregister. There shouldn't be
> > any need for ordering every with interface registration/unregistartion,
> > assuming drivers don't fumble things.
> 
> Ah, calling it late_register had the dual purpose of avoiding the
> 'register' keyword. :|
> 
> For consistency with resume's naming scheme, it should be register_late.
> Maybe register_userspace for greater verbage? Though I like the
> shorthand that we have register as meaning expose the internal object to
> third parties, including userspace.

register_aux and unregister_aux, shorthand for auxiliary interfaces?
Slight confusion with dp aux, but hey if that tricks folks into putting
the dp aux register call in here, even better ;-)

Agreed that register_userspace is both doubly the same and not quite the
right thing (since it's also about internal pulication within the kernel).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[Nouveau] [PATCH 9/9] drm: Turn off crtc before tearing down its data structure

2016-06-01 Thread Daniel Vetter
On Wed, Jun 01, 2016 at 02:36:41PM +0200, Lukas Wunner wrote:
> On Wed, May 25, 2016 at 03:43:42PM +0200, Daniel Vetter wrote:
> > On Wed, May 25, 2016 at 12:51 PM, Lukas Wunner  wrote:
> > > On Tue, May 24, 2016 at 11:30:42PM +0200, Daniel Vetter wrote:
> > >> On Tue, May 24, 2016 at 06:03:27PM +0200, Lukas Wunner wrote:
> > >> > When a drm_crtc structure is destroyed with drm_crtc_cleanup(), the DRM
> > >> > core does not turn off the crtc first and neither do the drivers. With
> > >> > nouveau, radeon and amdgpu, this causes a runtime pm ref to be leaked 
> > >> > on
> > >> > driver unload if at least one crtc was enabled.
> > >> >
> > >> > (See usage of have_disp_power_ref in nouveau_crtc_set_config(),
> > >> > radeon_crtc_set_config() and amdgpu_crtc_set_config()).
> > >> >
> > >> > Fixes: 5addcf0a5f0f ("nouveau: add runtime PM support (v0.9)")
> > >> > Cc: Dave Airlie 
> > >> > Tested-by: Karol Herbst 
> > >> > Signed-off-by: Lukas Wunner 
> > >>
> > >> This is a core regression, we fixed it again. Previously when unreference
> > >> drm_planes the core made sure that it's not longer in use, which had the
> > >> side effect of shutting everything off in module unload.
> > >>
> > >> For a bunch of reasons we've stopped doing that, but that turned out to 
> > >> be
> > >> a mistake. It's fixed since
> > >>
> > >> commit f2d580b9a8149735cbc4b59c4a8df60173658140
> > >> Author: Maarten Lankhorst 
> > >> Date:   Wed May 4 14:38:26 2016 +0200
> > >>
> > >> drm/core: Do not preserve framebuffer on rmfb, v4.
> > >>
> > >> Your patch shouldn't be needed with that any more. If it still is it's
> > >> most likely the fbdev cleanup done too late, but you /should/ get a big
> > >> WARNING splat in that case from drm_mode_config_cleanup().
> > >
> > > I tested it and at least with nouveau, the above-mentioned commit does
> > > *not* solve the issue, so patch [9/9] of this series is still needed.
> > > I do not get a WARN splat when unloading nouveau.
> > 
> > With legacy kms the only way to keep a crtc enabled is to display a
> > drm_framebuffer on it. And drm_mode_config_cleanup has a WARN_ON if
> > framebuffers are left behind. There's a bunch of options:
> > - nouveau somehow manages to keep the crtc on without a framebuffer
> > - nouveau somehow leaks a drm_framebuffer, but removes it from the fb_list
> > - something else
> 
> Found it. nouveau_fbcon_destroy() doesn't call drm_framebuffer_remove().
> If I add that, the crtc gets properly disabled on unload.
> 
> It does call drm_framebuffer_cleanup(). That's why there was no WARN,
> drm_mode_config_cleanup() only WARNs if a framebuffer was left on the
> mode_config.fb_list.
> 
> radeon and amdgpu have the same problem. In fact there are very few
> drivers that call drm_framebuffer_remove(): tegra, msm, exynos, omapdrm
> and i915 (since Imre Deak's 9d6612516da0).
> 
> Should we add a WARN to prevent this? How about WARN_ON(crtc->enabled)
> in drm_crtc_cleanup()?
> 
> Also, i915 calls drm_framebuffer_unregister_private() before it calls
> drm_framebuffer_remove(). This ordering has the unfortunate side effect
> that the drm_framebuffer has ID 0 in log messages emitted by
> drm_framebuffer_remove():
> 
> [   39.680874] [drm:drm_mode_object_unreference] OBJ ID: 0 (3)
> [   39.680878] [drm:drm_mode_object_unreference] OBJ ID: 0 (2)
> [   39.680884] [drm:drm_mode_object_unreference] OBJ ID: 0 (1)

Well we must first unregister it before we can remove it, so this is
unavoidable.

Wrt switching from _cleanup to _remove, iirc there was troubles with the
later calling into the fb->funcs->destroy hook. But many drivers have
their fbdev fb embedded into some struct (instead of a pointer like i915),
and then things go sideways badly. That's why you can't just blindly
replace them.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH] drm: Update obsolete information from {enable/disable}_vblank hooks.

2016-06-01 Thread Liviu Dudau
Since commit 4dfd64862ff8 ("drm: Use vblank timestamps to guesstimate
how many vblanks were missed"), the DRM framework can cope with devices
that don't have a hardware counter for vsync events without having
to keep the vsync interrupts enabled all the time. Drivers handling
such hardware should use drm_vblank_no_hw_counter() function for
their ->get_vblank_counter hook.

Cc: Daniel Vetter 
Cc: Ville Syrjälä 
Signed-off-by: Liviu Dudau 
---
 include/drm/drmP.h | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 84f1a8e..d486118 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -434,7 +434,7 @@ struct drm_driver {
 *
 * Driver callback for fetching a raw hardware vblank counter for @crtc.
 * If a device doesn't have a hardware counter, the driver can simply
-* return the value of drm_vblank_count. The DRM core will account for
+* use drm_vblank_no_hw_counter() function. The DRM core will account 
for
 * missed vblank events while interrupts where disabled based on system
 * timestamps.
 *
@@ -452,8 +452,8 @@ struct drm_driver {
 * @pipe: which irq to enable
 *
 * Enable vblank interrupts for @crtc.  If the device doesn't have
-* a hardware vblank counter, this routine should be a no-op, since
-* interrupts will have to stay on to keep the count accurate.
+* a hardware vblank counter, the driver should use the
+* drm_vblank_no_hw_counter() function that keeps a virtual counter.
 *
 * RETURNS
 * Zero on success, appropriate errno if the given @crtc's vblank
@@ -467,8 +467,8 @@ struct drm_driver {
 * @pipe: which irq to enable
 *
 * Disable vblank interrupts for @crtc.  If the device doesn't have
-* a hardware vblank counter, this routine should be a no-op, since
-* interrupts will have to stay on to keep the count accurate.
+* a hardware vblank counter, the driver should use the
+* drm_vblank_no_hw_counter() function that keeps a virtual counter.
 */
void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);

-- 
2.8.2



[PATCH v3 4/4] drm: hdlcd: Add information about the underlying framebuffers in debugfs

2016-06-01 Thread Liviu Dudau
drm_fb_cma code has a nice helper function to display in the debugfs
information about the underlying framebuffers used by HDLCD:

$ cat /sys/kernel/debug/dri/0/fb
fb: 1920x1200 at XR24
   0: offset=0 pitch=7680, obj:  0 ( 2) 001011ba 0xfc30 
ff800a27c000 9338880
fb: 1920x1200 at XR24
   0: offset=0 pitch=7680, obj:  0 ( 2) 001008ca 0xfba0 
ff8009987000 9338880
fb: 1920x1200 at XR24
   0: offset=0 pitch=7680, obj:  0 ( 1) 0010 0xfb10 
ff8008fdc000 9216000

Add the entry in HDLCD's debugfs node.

Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index fb172d2..a6ca36f 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -254,6 +254,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void 
*arg)
 static struct drm_info_list hdlcd_debugfs_list[] = {
{ "interrupt_count", hdlcd_show_underrun_count, 0 },
{ "clocks", hdlcd_show_pxlclock, 0 },
+   { "fb", drm_fb_cma_debugfs_show, 0 },
 };

 static int hdlcd_debugfs_init(struct drm_minor *minor)
-- 
2.8.2



[PATCH v3 3/4] drm: hdlcd: Cleanup the atomic plane operations

2016-06-01 Thread Liviu Dudau
Harden the plane_check() code to drop attempts at scaling because
that is not supported. Make hdlcd_plane_atomic_update() set the pitch
and line length registers that correctly reflect the plane's values.
And make hdlcd_crtc_mode_set_nofb() a helper function for
hdlcd_crtc_enable() rather than an exposed hook.

Cc: Daniel Vetter 
Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 44 ++--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  1 -
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 97326c3..31426ba 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -106,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm;
-   unsigned int polarities, line_length, err;
+   unsigned int polarities, err;

vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -122,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc 
*crtc)
if (m->flags & DRM_MODE_FLAG_PVSYNC)
polarities |= HDLCD_POLARITY_VSYNC;

-   line_length = crtc->primary->state->fb->pitches[0];
-
/* Allow max number of outstanding requests and largest burst size */
hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);

-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
+   hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
-   hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);

err = hdlcd_set_pxl_fmt(crtc);
@@ -153,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

clk_prepare_enable(hdlcd->clk);
+   hdlcd_crtc_mode_set_nofb(crtc);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
-   drm_crtc_vblank_on(crtc);
 }

 static void hdlcd_crtc_disable(struct drm_crtc *crtc)
 {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

-   if (!crtc->primary->fb)
+   if (!crtc->state->active)
return;

hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
clk_disable_unprepare(hdlcd->clk);
-   drm_crtc_vblank_off(crtc);
 }

 static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -232,6 +226,15 @@ static const struct drm_crtc_helper_funcs 
hdlcd_crtc_helper_funcs = {
 static int hdlcd_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
 {
+   u32 src_w, src_h;
+
+   src_w = state->src_w >> 16;
+   src_h = state->src_h >> 16;
+
+   /* we can't do any scaling of the plane source */
+   if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
+   return -EINVAL;
+
return 0;
 }

@@ -240,20 +243,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane 
*plane,
 {
struct hdlcd_drm_private *hdlcd;
struct drm_gem_cma_object *gem;
+   unsigned int depth, bpp;
+   u32 src_w, src_h, dest_w, dest_h;
dma_addr_t scanout_start;

-   if (!plane->state->crtc || !plane->state->fb)
+   if (!plane->state->fb)
return;

-   hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
+   drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
+   src_w = plane->state->src_w >> 16;
+   src_h = plane->state->src_h >> 16;
+   dest_w = plane->state->crtc_w;
+   dest_h = plane->state->crtc_h;
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
-   scanout_start = gem->paddr;
+   scanout_start = gem->paddr + plane->state->fb->offsets[0] +
+   plane->state->crtc_y * plane->state->fb->pitches[0] +
+   plane->state->crtc_x * bpp / 8;
+
+   hdlcd = plane->dev->dev_private;
+   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, 
plane->state->fb->pitches[0]);
+   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, 
plane->state->fb->pitches[0]);
+   hdlcd_write(hdlcd, HDLCD_R

[PATCH v3 2/4] drm/hdlcd: Fix up crtc_state->event handling

2016-06-01 Thread Liviu Dudau
From: Daniel Vetter 

event_list just reimplemented what drm_crtc_arm_vblank_event does. And
we also need to send out drm events when shutting down a pipe.

With this it's possible to use the new nonblocking commit support in
the helpers.

Signed-off-by: Daniel Vetter 
Acked-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 18 --
 drivers/gpu/drm/arm/hdlcd_drv.c  | 19 +--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  1 -
 3 files changed, 9 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index d1e8d31..97326c3 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -189,19 +189,17 @@ static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
-   unsigned long flags;
-
-   if (crtc->state->event) {
-   struct drm_pending_vblank_event *event = crtc->state->event;
+   struct drm_pending_vblank_event *event = crtc->state->event;

+   if (event) {
crtc->state->event = NULL;
-   event->pipe = drm_crtc_index(crtc);
-
-   WARN_ON(drm_crtc_vblank_get(crtc) != 0);

-   spin_lock_irqsave(&crtc->dev->event_lock, flags);
-   list_add_tail(&event->base.link, &hdlcd->event_list);
-   spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+   spin_lock_irq(&crtc->dev->event_lock);
+   if (drm_crtc_vblank_get(crtc) == 0)
+   drm_crtc_arm_vblank_event(crtc, event);
+   else
+   drm_crtc_send_vblank_event(crtc, event);
+   spin_unlock_irq(&crtc->dev->event_lock);
}
 }

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 21b1427..fb172d2 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long 
flags)
atomic_set(&hdlcd->dma_end_count, 0);
 #endif

-   INIT_LIST_HEAD(&hdlcd->event_list);
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
if (IS_ERR(hdlcd->mmio)) {
@@ -160,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
atomic_inc(&hdlcd->vsync_count);

 #endif
-   if (irq_status & HDLCD_INTERRUPT_VSYNC) {
-   bool events_sent = false;
-   unsigned long flags;
-   struct drm_pending_vblank_event *e, *t;
-
+   if (irq_status & HDLCD_INTERRUPT_VSYNC)
drm_crtc_handle_vblank(&hdlcd->crtc);

-   spin_lock_irqsave(&drm->event_lock, flags);
-   list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
-   list_del(&e->base.link);
-   drm_crtc_send_vblank_event(&hdlcd->crtc, e);
-   events_sent = true;
-   }
-   if (events_sent)
-   drm_crtc_vblank_put(&hdlcd->crtc);
-   spin_unlock_irqrestore(&drm->event_lock, flags);
-   }
-
/* acknowledge interrupt(s) */
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index e7cea82..922a1dc 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -10,7 +10,6 @@ struct hdlcd_drm_private {
struct clk  *clk;
struct drm_fbdev_cma*fbdev;
struct drm_framebuffer  *fb;
-   struct list_headevent_list;
struct drm_crtc crtc;
struct drm_plane*plane;
struct drm_atomic_state *state;
-- 
2.8.2



[PATCH v3 1/4] drm: hdlcd: Revamp runtime power management

2016-06-01 Thread Liviu Dudau
Because the HDLCD driver acts as a component master it can end
up enabling the runtime PM functionality before the encoders
are initialised. This can cause crashes if the component slave
never probes (missing module) or if the PM operations kick in
before the probe finishes.

Move the enabling of the runtime PM after the component master
has finished collecting the slave components and use the DRM
atomic helpers to suspend and resume the device.

Tested-by: Robin Murphy 
Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 23 +--
 drivers/gpu/drm/arm/hdlcd_drv.c  | 48 ++--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  3 +--
 3 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index fef1b04..d1e8d31 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -33,8 +33,17 @@
  *
  */

+static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
+{
+   struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
+
+   /* stop the controller on cleanup */
+   hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+   drm_crtc_cleanup(crtc);
+}
+
 static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
-   .destroy = drm_crtc_cleanup,
+   .destroy = hdlcd_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
@@ -155,8 +164,8 @@ static void hdlcd_crtc_disable(struct drm_crtc *crtc)
if (!crtc->primary->fb)
return;

-   clk_disable_unprepare(hdlcd->clk);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+   clk_disable_unprepare(hdlcd->clk);
drm_crtc_vblank_off(crtc);
 }

@@ -294,16 +303,6 @@ static struct drm_plane *hdlcd_plane_init(struct 
drm_device *drm)
return plane;
 }

-void hdlcd_crtc_suspend(struct drm_crtc *crtc)
-{
-   hdlcd_crtc_disable(crtc);
-}
-
-void hdlcd_crtc_resume(struct drm_crtc *crtc)
-{
-   hdlcd_crtc_enable(crtc);
-}
-
 int hdlcd_setup_crtc(struct drm_device *drm)
 {
struct hdlcd_drm_private *hdlcd = drm->dev_private;
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index b987c63..21b1427 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -84,11 +84,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}

-   pm_runtime_enable(drm->dev);
-
-   pm_runtime_get_sync(drm->dev);
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
-   pm_runtime_put_sync(drm->dev);
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
goto irq_fail;
@@ -357,6 +353,8 @@ static int hdlcd_drm_bind(struct device *dev)
return -ENOMEM;

drm->dev_private = hdlcd;
+   dev_set_drvdata(dev, drm);
+
hdlcd_setup_mode_config(drm);
ret = hdlcd_load(drm, 0);
if (ret)
@@ -366,14 +364,18 @@ static int hdlcd_drm_bind(struct device *dev)
if (ret)
goto err_unload;

-   dev_set_drvdata(dev, drm);
-
ret = component_bind_all(dev, drm);
if (ret) {
DRM_ERROR("Failed to bind all components\n");
goto err_unregister;
}

+   ret = pm_runtime_set_active(dev);
+   if (ret)
+   goto err_pm_active;
+
+   pm_runtime_enable(dev);
+
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n");
@@ -399,16 +401,16 @@ err_fbdev:
drm_mode_config_cleanup(drm);
drm_vblank_cleanup(drm);
 err_vblank:
+   pm_runtime_disable(drm->dev);
+err_pm_active:
component_unbind_all(dev, drm);
 err_unregister:
drm_dev_unregister(drm);
 err_unload:
-   pm_runtime_get_sync(drm->dev);
drm_irq_uninstall(drm);
-   pm_runtime_put_sync(drm->dev);
-   pm_runtime_disable(drm->dev);
of_reserved_mem_device_release(drm->dev);
 err_free:
+   dev_set_drvdata(dev, NULL);
drm_dev_unref(drm);

return ret;
@@ -495,30 +497,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
 static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
 {
struct drm_device *drm = dev_get_drvdata(dev);
-   struct drm_crtc *crtc;
+   struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;

-   if (pm_runtime_suspended(dev))
+   if (!hdlcd)
return 0;

-   drm_modeset_lock_all(drm);
-   list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-   hdlcd_crtc_suspend(crtc);
-   drm_modeset_unlock_all(drm);
+   drm_kms_helper_poll_disable(drm);
+
+   hdlcd->state = drm_atomic_helper_suspend(drm);
+   if (IS_ERR(hdlcd->state)) {
+   drm_kms_helper_poll_enable(drm);
+

[PATCH v3 0/4] HDLCD cleanups for v4.7

2016-06-01 Thread Liviu Dudau
Hello,

Here are a series of patches that I would like to add to v4.7. It fixes issues
with suspend/resume on Juno (support for which has been added in v4.7-rc1).
When doing the work I've noticed some breakage on the vsync behaviour so I've
fixed that as well. In order to ease the introduction of Daniel Vetter's series
that adds support for non-blocking atomic operations I also picked up his patch
that cleans up the crtc->state->event handling.

The final patch adds support for dumping information from the CMA allocator on
the underlying framebuffers that I found useful while debugging the non-blocking
atomic operations.

A copy of the series has been pushed to git://linux-arm.org/linux-ld 
for-upstream/hdlcd

v3: drop the vsync disabling patch
v2: collect the individual patches into a series


Best regards,
Liviu


Daniel Vetter (1):
  drm/hdlcd: Fix up crtc_state->event handling

Liviu Dudau (3):
  drm: hdlcd: Revamp runtime power management
  drm: hdlcd: Cleanup the atomic plane operations
  drm: hdlcd: Add information about the underlying framebuffers in debugfs

 drivers/gpu/drm/arm/hdlcd_crtc.c | 85 +++-
 drivers/gpu/drm/arm/hdlcd_drv.c  | 68 ++--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  5 +--
 3 files changed, 78 insertions(+), 80 deletions(-)

-- 
2.8.2



[PULL] drm: atmel-hlcdc: fixes for 4.7-rc2

2016-06-01 Thread Boris Brezillon
Hi Dave,

On Wed, 1 Jun 2016 14:23:27 +0200
Boris Brezillon  wrote:

> Hi Dave,
> 
> This pull request contains 2 trivial fixes for the atmel-hlcdc driver.

Please ignore this PR. The __drm_atomic_helper_crtc_destroy_state()
prototype has changed between my submission and the 4.7-rc1 release and
it no longer compiles.

Sorry for the inconvenience.

Regards,

Boris

> 
> The first one is making use of __drm_atomic_helper_crtc_destroy_state()
> instead of duplicating its logic in atmel_hlcdc_crtc_reset() and
> risking memory leaks if other objects are added to the common CRTC
> state.
> 
> The second one is fixing a possible NULL pointer dereference.
> 
> Regards,
> 
> Boris
> 
> The following changes since commit 1a695a905c18548062509178b98bc91e67510864:
> 
>   Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)
> 
> are available in the git repository at:
> 
>   git at github.com:bbrezillon/linux-at91.git 
> tags/drm-atmel-hlcdc-fixes/for-4.7-rc2
> 
> for you to fetch changes up to dcd64e313ff2d2a15574cd92ec27e73194ba7537:
> 
>   drm: atmel-hlcdc: fix a NULL check (2016-06-01 13:36:26 +0200)
> 
> 
> Two trivial bugfixes on the atmel-hlcdc driver for 4.7-rc2.
> 
> The first one is making use of __drm_atomic_helper_crtc_destroy_state()
> instead of duplicating its logic in atmel_hlcdc_crtc_reset() and
> risking memory leaks if other objects are added to the common CRTC
> state.
> 
> The second one is fixing a possible NULL pointer dereference.
> 
> 
> Boris Brezillon (1):
>   drm: atmel-hlcdc: fix atmel_hlcdc_crtc_reset() implementation
> 
> Dan Carpenter (1):
>   drm: atmel-hlcdc: fix a NULL check
> 
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> 



-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com


[PATCH v2 5/5] drm: hdlcd: Add information about the underlying framebuffers in debugfs

2016-06-01 Thread Liviu Dudau
drm_fb_cma code has a nice helper function to display in the debugfs
information about the underlying framebuffers used by HDLCD:

$ cat /sys/kernel/debug/dri/0/fb
fb: 1920x1200 at XR24
   0: offset=0 pitch=7680, obj:  0 ( 2) 001011ba 0xfc30 
ff800a27c000 9338880
fb: 1920x1200 at XR24
   0: offset=0 pitch=7680, obj:  0 ( 2) 001008ca 0xfba0 
ff8009987000 9338880
fb: 1920x1200 at XR24
   0: offset=0 pitch=7680, obj:  0 ( 1) 0010 0xfb10 
ff8008fdc000 9216000

Add the entry in HDLCD's debugfs node.

Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 3f92dfa..6f389e6 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -249,6 +249,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void 
*arg)
 static struct drm_info_list hdlcd_debugfs_list[] = {
{ "interrupt_count", hdlcd_show_underrun_count, 0 },
{ "clocks", hdlcd_show_pxlclock, 0 },
+   { "fb", drm_fb_cma_debugfs_show, 0 },
 };

 static int hdlcd_debugfs_init(struct drm_minor *minor)
-- 
2.8.2



[PATCH v2 4/5] drm: hdlcd: Don't touch vsync interrupts during vblank enable/disable.

2016-06-01 Thread Liviu Dudau
Because the HDLCD lacks a hardware counter for vsync signal, the DRM
framework expects that the vsync interrupts are left running to feed
the internal software counter. Currently the HDLCD is masking/unmasking
the vsync interrupt on vblank enable/disable calls, which break that
expectation. Fix that.

Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_drv.c | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index fb172d2..3f92dfa 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -183,9 +183,13 @@ static int hdlcd_irq_postinstall(struct drm_device *drm)

/* enable debug interrupts */
irq_mask |= HDLCD_DEBUG_INT_MASK;
+#endif
+
+   /* enable vsync interrupts */
+   irq_mask |= HDLCD_INTERRUPT_VSYNC;

hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
-#endif
+
return 0;
 }

@@ -208,20 +212,11 @@ static void hdlcd_irq_uninstall(struct drm_device *drm)

 static int hdlcd_enable_vblank(struct drm_device *drm, unsigned int crtc)
 {
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
-   unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-   hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask | HDLCD_INTERRUPT_VSYNC);
-
return 0;
 }

 static void hdlcd_disable_vblank(struct drm_device *drm, unsigned int crtc)
 {
-   struct hdlcd_drm_private *hdlcd = drm->dev_private;
-   unsigned int mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-   hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, mask & ~HDLCD_INTERRUPT_VSYNC);
 }

 #ifdef CONFIG_DEBUG_FS
-- 
2.8.2



[PATCH v2 3/5] drm: hdlcd: Cleanup the atomic plane operations

2016-06-01 Thread Liviu Dudau
Harden the plane_check() code to drop attempts at scaling because
that is not supported. Make hdlcd_plane_atomic_update() set the pitch
and line length registers that correctly reflect the plane's values.
And make hdlcd_crtc_mode_set_nofb() a helper function for
hdlcd_crtc_enable() rather than an exposed hook.

Cc: Daniel Vetter 
Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 44 ++--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  1 -
 2 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 97326c3..31426ba 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -106,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm;
-   unsigned int polarities, line_length, err;
+   unsigned int polarities, err;

vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -122,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc 
*crtc)
if (m->flags & DRM_MODE_FLAG_PVSYNC)
polarities |= HDLCD_POLARITY_VSYNC;

-   line_length = crtc->primary->state->fb->pitches[0];
-
/* Allow max number of outstanding requests and largest burst size */
hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);

-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
+   hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
-   hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);

err = hdlcd_set_pxl_fmt(crtc);
@@ -153,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

clk_prepare_enable(hdlcd->clk);
+   hdlcd_crtc_mode_set_nofb(crtc);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
-   drm_crtc_vblank_on(crtc);
 }

 static void hdlcd_crtc_disable(struct drm_crtc *crtc)
 {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

-   if (!crtc->primary->fb)
+   if (!crtc->state->active)
return;

hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
clk_disable_unprepare(hdlcd->clk);
-   drm_crtc_vblank_off(crtc);
 }

 static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -232,6 +226,15 @@ static const struct drm_crtc_helper_funcs 
hdlcd_crtc_helper_funcs = {
 static int hdlcd_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
 {
+   u32 src_w, src_h;
+
+   src_w = state->src_w >> 16;
+   src_h = state->src_h >> 16;
+
+   /* we can't do any scaling of the plane source */
+   if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
+   return -EINVAL;
+
return 0;
 }

@@ -240,20 +243,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane 
*plane,
 {
struct hdlcd_drm_private *hdlcd;
struct drm_gem_cma_object *gem;
+   unsigned int depth, bpp;
+   u32 src_w, src_h, dest_w, dest_h;
dma_addr_t scanout_start;

-   if (!plane->state->crtc || !plane->state->fb)
+   if (!plane->state->fb)
return;

-   hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
+   drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
+   src_w = plane->state->src_w >> 16;
+   src_h = plane->state->src_h >> 16;
+   dest_w = plane->state->crtc_w;
+   dest_h = plane->state->crtc_h;
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
-   scanout_start = gem->paddr;
+   scanout_start = gem->paddr + plane->state->fb->offsets[0] +
+   plane->state->crtc_y * plane->state->fb->pitches[0] +
+   plane->state->crtc_x * bpp / 8;
+
+   hdlcd = plane->dev->dev_private;
+   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, 
plane->state->fb->pitches[0]);
+   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, 
plane->state->fb->pitches[0]);
+   hdlcd_write(hdlcd, HDLCD_R

[PATCH v2 2/5] drm/hdlcd: Fix up crtc_state->event handling

2016-06-01 Thread Liviu Dudau
From: Daniel Vetter 

event_list just reimplemented what drm_crtc_arm_vblank_event does. And
we also need to send out drm events when shutting down a pipe.

With this it's possible to use the new nonblocking commit support in
the helpers.

Signed-off-by: Daniel Vetter 
Acked-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 18 --
 drivers/gpu/drm/arm/hdlcd_drv.c  | 19 +--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  1 -
 3 files changed, 9 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index d1e8d31..97326c3 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -189,19 +189,17 @@ static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
-   unsigned long flags;
-
-   if (crtc->state->event) {
-   struct drm_pending_vblank_event *event = crtc->state->event;
+   struct drm_pending_vblank_event *event = crtc->state->event;

+   if (event) {
crtc->state->event = NULL;
-   event->pipe = drm_crtc_index(crtc);
-
-   WARN_ON(drm_crtc_vblank_get(crtc) != 0);

-   spin_lock_irqsave(&crtc->dev->event_lock, flags);
-   list_add_tail(&event->base.link, &hdlcd->event_list);
-   spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+   spin_lock_irq(&crtc->dev->event_lock);
+   if (drm_crtc_vblank_get(crtc) == 0)
+   drm_crtc_arm_vblank_event(crtc, event);
+   else
+   drm_crtc_send_vblank_event(crtc, event);
+   spin_unlock_irq(&crtc->dev->event_lock);
}
 }

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index 21b1427..fb172d2 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long 
flags)
atomic_set(&hdlcd->dma_end_count, 0);
 #endif

-   INIT_LIST_HEAD(&hdlcd->event_list);
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
if (IS_ERR(hdlcd->mmio)) {
@@ -160,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
atomic_inc(&hdlcd->vsync_count);

 #endif
-   if (irq_status & HDLCD_INTERRUPT_VSYNC) {
-   bool events_sent = false;
-   unsigned long flags;
-   struct drm_pending_vblank_event *e, *t;
-
+   if (irq_status & HDLCD_INTERRUPT_VSYNC)
drm_crtc_handle_vblank(&hdlcd->crtc);

-   spin_lock_irqsave(&drm->event_lock, flags);
-   list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
-   list_del(&e->base.link);
-   drm_crtc_send_vblank_event(&hdlcd->crtc, e);
-   events_sent = true;
-   }
-   if (events_sent)
-   drm_crtc_vblank_put(&hdlcd->crtc);
-   spin_unlock_irqrestore(&drm->event_lock, flags);
-   }
-
/* acknowledge interrupt(s) */
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index e7cea82..922a1dc 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -10,7 +10,6 @@ struct hdlcd_drm_private {
struct clk  *clk;
struct drm_fbdev_cma*fbdev;
struct drm_framebuffer  *fb;
-   struct list_headevent_list;
struct drm_crtc crtc;
struct drm_plane*plane;
struct drm_atomic_state *state;
-- 
2.8.2



[PATCH v2 1/5] drm: hdlcd: Revamp runtime power management

2016-06-01 Thread Liviu Dudau
Because the HDLCD driver acts as a component master it can end
up enabling the runtime PM functionality before the encoders
are initialised. This can cause crashes if the component slave
never probes (missing module) or if the PM operations kick in
before the probe finishes.

Move the enabling of the runtime PM after the component master
has finished collecting the slave components and use the DRM
atomic helpers to suspend and resume the device.

Tested-by: Robin Murphy 
Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 23 +--
 drivers/gpu/drm/arm/hdlcd_drv.c  | 48 ++--
 drivers/gpu/drm/arm/hdlcd_drv.h  |  3 +--
 3 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index fef1b04..d1e8d31 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -33,8 +33,17 @@
  *
  */

+static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
+{
+   struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
+
+   /* stop the controller on cleanup */
+   hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+   drm_crtc_cleanup(crtc);
+}
+
 static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
-   .destroy = drm_crtc_cleanup,
+   .destroy = hdlcd_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
@@ -155,8 +164,8 @@ static void hdlcd_crtc_disable(struct drm_crtc *crtc)
if (!crtc->primary->fb)
return;

-   clk_disable_unprepare(hdlcd->clk);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+   clk_disable_unprepare(hdlcd->clk);
drm_crtc_vblank_off(crtc);
 }

@@ -294,16 +303,6 @@ static struct drm_plane *hdlcd_plane_init(struct 
drm_device *drm)
return plane;
 }

-void hdlcd_crtc_suspend(struct drm_crtc *crtc)
-{
-   hdlcd_crtc_disable(crtc);
-}
-
-void hdlcd_crtc_resume(struct drm_crtc *crtc)
-{
-   hdlcd_crtc_enable(crtc);
-}
-
 int hdlcd_setup_crtc(struct drm_device *drm)
 {
struct hdlcd_drm_private *hdlcd = drm->dev_private;
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index b987c63..21b1427 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -84,11 +84,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long 
flags)
goto setup_fail;
}

-   pm_runtime_enable(drm->dev);
-
-   pm_runtime_get_sync(drm->dev);
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
-   pm_runtime_put_sync(drm->dev);
if (ret < 0) {
DRM_ERROR("failed to install IRQ handler\n");
goto irq_fail;
@@ -357,6 +353,8 @@ static int hdlcd_drm_bind(struct device *dev)
return -ENOMEM;

drm->dev_private = hdlcd;
+   dev_set_drvdata(dev, drm);
+
hdlcd_setup_mode_config(drm);
ret = hdlcd_load(drm, 0);
if (ret)
@@ -366,14 +364,18 @@ static int hdlcd_drm_bind(struct device *dev)
if (ret)
goto err_unload;

-   dev_set_drvdata(dev, drm);
-
ret = component_bind_all(dev, drm);
if (ret) {
DRM_ERROR("Failed to bind all components\n");
goto err_unregister;
}

+   ret = pm_runtime_set_active(dev);
+   if (ret)
+   goto err_pm_active;
+
+   pm_runtime_enable(dev);
+
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n");
@@ -399,16 +401,16 @@ err_fbdev:
drm_mode_config_cleanup(drm);
drm_vblank_cleanup(drm);
 err_vblank:
+   pm_runtime_disable(drm->dev);
+err_pm_active:
component_unbind_all(dev, drm);
 err_unregister:
drm_dev_unregister(drm);
 err_unload:
-   pm_runtime_get_sync(drm->dev);
drm_irq_uninstall(drm);
-   pm_runtime_put_sync(drm->dev);
-   pm_runtime_disable(drm->dev);
of_reserved_mem_device_release(drm->dev);
 err_free:
+   dev_set_drvdata(dev, NULL);
drm_dev_unref(drm);

return ret;
@@ -495,30 +497,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
 static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
 {
struct drm_device *drm = dev_get_drvdata(dev);
-   struct drm_crtc *crtc;
+   struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;

-   if (pm_runtime_suspended(dev))
+   if (!hdlcd)
return 0;

-   drm_modeset_lock_all(drm);
-   list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-   hdlcd_crtc_suspend(crtc);
-   drm_modeset_unlock_all(drm);
+   drm_kms_helper_poll_disable(drm);
+
+   hdlcd->state = drm_atomic_helper_suspend(drm);
+   if (IS_ERR(hdlcd->state)) {
+   drm_kms_helper_poll_enable(drm);
+

[PATCH v2 0/5] HDLCD cleanups for v4.7

2016-06-01 Thread Liviu Dudau
Hello,

Here are a series of patches that I would like to add to v4.7. It fixes issues
with suspend/resume on Juno (support for which has been added in v4.7-rc1).
When doing the work I've noticed some breakage on the vsync behaviour so I've
fixed that as well. In order to ease the introduction of Daniel Vetter's series
that adds support for non-blocking atomic operations I also picked up his patch
that cleans up the crtc->state->event handling.

The final patch adds support for dumping information from the CMA allocator on
the underlying framebuffers that I found useful while debugging the non-blocking
atomic operations.

A copy of the series has been pushed to git://linux-arm.org/linux-ld 
for-upstream/hdlcd

Best regards,
Liviu

Daniel Vetter (1):
  drm/hdlcd: Fix up crtc_state->event handling

Liviu Dudau (4):
  drm: hdlcd: Revamp runtime power management
  drm: hdlcd: Cleanup the atomic plane operations
  drm: hdlcd: Don't touch vsync interrupts during vblank enable/disable.
  drm: hdlcd: Add information about the underlying framebuffers in debugfs

 drivers/gpu/drm/arm/hdlcd_crtc.c | 85 +++-
 drivers/gpu/drm/arm/hdlcd_drv.c  | 83 ---
 drivers/gpu/drm/arm/hdlcd_drv.h  |  5 +--
 3 files changed, 83 insertions(+), 90 deletions(-)

-- 
2.8.2



[PATCH] drm/doc: Switch to sphinx/rst fixed-width quoting

2016-06-01 Thread Daniel Vetter
On Wed, Jun 1, 2016 at 11:46 AM, Jani Nikula
 wrote:
> On Wed, 01 Jun 2016, Daniel Vetter  wrote:
>> There's still something very fishy going on with some of these, e.g.
>> the drm_modeset_lock Example: and the "Standard GTF Parameters:" Line
>> somehow get treated as heading when just appending a :: at the end of
>> those lines. But it seems to work everywhere else. Maybe the
>> kernel-doc heading generation logic is still a bit wonky?
>
> Try adding a blank line between the line with trailing :: and the actual
> preformatted text. Seems to do the right thing for me.
>
> http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#literal-blocks
>
> "Blank lines are required before and after a literal block, but these
> blank lines are not included as part of the literal block."

That's not what I've meant. The following sometimes (but not always,
only in the 2 places I've mentioned) becomes a kernel-doc directive
and not a block quote:

 * Standard GTF Parameters::
 *
 * stuff I wanted to have block quoted.

But if I switch the :: to be on a line of it's own (like in the patch)
it's totally fine.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH 11/11] drm/amdgpu: remove now unnecessary checks

2016-06-01 Thread Christian König
From: Christian König 

vm_flush() now comes directly after vm_grab_id().

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h|  1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 31 +++
 2 files changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 52326d3..e054542 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -886,7 +886,6 @@ struct amdgpu_vm_id {
struct fence*first;
struct amdgpu_sync  active;
struct fence*last_flush;
-   struct amdgpu_ring  *last_user;
atomic64_t  owner;

uint64_tpd_gpu_addr;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 8ea1c73..48d5ad18 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -237,6 +237,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,
i = ring->idx;
do {
struct fence *flushed;
+   bool same_ring = ring->idx == i;

id = vm->ids[i++];
if (i == AMDGPU_MAX_RINGS)
@@ -252,7 +253,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,
if (pd_addr != id->pd_gpu_addr)
continue;

-   if (id->last_user != ring &&
+   if (!same_ring &&
(!id->last_flush || !fence_is_signaled(id->last_flush)))
continue;

@@ -261,15 +262,9 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,
(!flushed || fence_is_later(updates, flushed)))
continue;

-   /* Good we can use this VMID */
-   if (id->last_user == ring) {
-   r = amdgpu_sync_fence(ring->adev, sync,
- id->first);
-   if (r)
-   goto error;
-   }
-
-   /* And remember this submission as user of the VMID */
+   /* Good we can use this VMID. Remember this submission as
+* user of the VMID.
+*/
r = amdgpu_sync_fence(ring->adev, &id->active, fence);
if (r)
goto error;
@@ -306,7 +301,6 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,
id->pd_gpu_addr = pd_addr;

list_move_tail(&id->list, &adev->vm_manager.ids_lru);
-   id->last_user = ring;
atomic64_set(&id->owner, vm->client_id);
vm->ids[ring->idx] = id;

@@ -357,16 +351,13 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,
trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id);
amdgpu_ring_emit_vm_flush(ring, vm_id, pd_addr);

+   r = amdgpu_fence_emit(ring, &fence);
+   if (r)
+   return r;
+
mutex_lock(&adev->vm_manager.lock);
-   if ((id->pd_gpu_addr == pd_addr) && (id->last_user == ring)) {
-   r = amdgpu_fence_emit(ring, &fence);
-   if (r) {
-   mutex_unlock(&adev->vm_manager.lock);
-   return r;
-   }
-   fence_put(id->last_flush);
-   id->last_flush = fence;
-   }
+   fence_put(id->last_flush);
+   id->last_flush = fence;
mutex_unlock(&adev->vm_manager.lock);
}

-- 
2.5.0



[PATCH 10/11] drm/amdgpu: use a fence array for VMID management

2016-06-01 Thread Christian König
From: Christian König 

Just wait for any fence to become available, instead
of waiting for the last entry of the LRU.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h  |  10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c |  69 +++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c   | 155 +++
 4 files changed, 117 insertions(+), 119 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index f154d9f..52326d3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -597,10 +597,8 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
 struct amdgpu_sync *sync,
 struct reservation_object *resv,
 void *owner);
-bool amdgpu_sync_is_idle(struct amdgpu_sync *sync,
-struct amdgpu_ring *ring);
-int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, struct amdgpu_sync *src,
-struct fence *fence);
+struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
+struct amdgpu_ring *ring);
 struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
 void amdgpu_sync_free(struct amdgpu_sync *sync);
 int amdgpu_sync_init(void);
@@ -910,6 +908,10 @@ struct amdgpu_vm_manager {
struct list_headids_lru;
struct amdgpu_vm_id ids[AMDGPU_NUM_VM];

+   /* Handling of VM fences */
+   u64 fence_context;
+   unsignedseqno[AMDGPU_MAX_RINGS];
+
uint32_tmax_pfn;
/* vram base address for page table entry  */
u64 vram_base_offset;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index e395bbe..b50a845 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -166,7 +166,7 @@ static struct fence *amdgpu_job_run(struct amd_sched_job 
*sched_job)
}
job = to_amdgpu_job(sched_job);

-   BUG_ON(!amdgpu_sync_is_idle(&job->sync, NULL));
+   BUG_ON(amdgpu_sync_peek_fence(&job->sync, NULL));

trace_amdgpu_sched_run_job(job);
r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index a2766d7..5c8d302 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -223,16 +223,16 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
 }

 /**
- * amdgpu_sync_is_idle - test if all fences are signaled
+ * amdgpu_sync_peek_fence - get the next fence not signaled yet
  *
  * @sync: the sync object
  * @ring: optional ring to use for test
  *
- * Returns true if all fences in the sync object are signaled or scheduled to
- * the ring (if provided).
+ * Returns the next fence not signaled yet without removing it from the sync
+ * object.
  */
-bool amdgpu_sync_is_idle(struct amdgpu_sync *sync,
-struct amdgpu_ring *ring)
+struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
+struct amdgpu_ring *ring)
 {
struct amdgpu_sync_entry *e;
struct hlist_node *tmp;
@@ -246,68 +246,25 @@ bool amdgpu_sync_is_idle(struct amdgpu_sync *sync,
/* For fences from the same ring it is sufficient
 * when they are scheduled.
 */
-   if (s_fence->sched == &ring->sched &&
-   fence_is_signaled(&s_fence->scheduled))
-   continue;
-   }
+   if (s_fence->sched == &ring->sched) {
+   if (fence_is_signaled(&s_fence->scheduled))
+   continue;

-   if (fence_is_signaled(f)) {
-   hash_del(&e->node);
-   fence_put(f);
-   kmem_cache_free(amdgpu_sync_slab, e);
-   continue;
+   return &s_fence->scheduled;
+   }
}

-   return false;
-   }
-
-   return true;
-}
-
-/**
- * amdgpu_sync_cycle_fences - move fences from one sync object into another
- *
- * @dst: the destination sync object
- * @src: the source sync object
- * @fence: fence to add to source
- *
- * Remove all fences from source and put them into destination and add
- * fence as new one into source.
- */
-int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, struct amdgpu_sync *src,
-struct fence *fence)
-{
-   struct amdgpu_sync_entry *e, *newone;
-   struct hlist_node *tm

[PATCH 09/11] drm/amdgpu: reuse VMIDs assigned to a VM only if there is also a free one

2016-06-01 Thread Christian König
From: Christian König 

This fixes a fairness problem with the GPU scheduler. VM having lot of
jobs could previously starve VM with less jobs.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 113 +
 1 file changed, 59 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index b6484a2..f206820 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -179,75 +179,80 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,
uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
struct amdgpu_device *adev = ring->adev;
struct fence *updates = sync->last_vm_update;
-   struct amdgpu_vm_id *id;
+   struct amdgpu_vm_id *id, *idle;
unsigned i = ring->idx;
int r;

mutex_lock(&adev->vm_manager.lock);

-   /* Check if we can use a VMID already assigned to this VM */
-   do {
-   struct fence *flushed;
-
-   id = vm->ids[i++];
-   if (i == AMDGPU_MAX_RINGS)
-   i = 0;
-
-   /* Check all the prerequisites to using this VMID */
-   if (!id)
-   continue;
-
-   if (atomic64_read(&id->owner) != vm->client_id)
-   continue;
-
-   if (pd_addr != id->pd_gpu_addr)
-   continue;
+   /* Check if we have an idle VMID */
+   list_for_each_entry(idle, &adev->vm_manager.ids_lru, list) {
+   if (amdgpu_sync_is_idle(&idle->active, ring))
+   break;

-   if (id->last_user != ring &&
-   (!id->last_flush || !fence_is_signaled(id->last_flush)))
-   continue;
+   }

-   flushed  = id->flushed_updates;
-   if (updates && (!flushed || fence_is_later(updates, flushed)))
-   continue;
+   /* If we can't find a idle VMID to use, just wait for the oldest */
+   if (&idle->list == &adev->vm_manager.ids_lru) {
+   id = list_first_entry(&adev->vm_manager.ids_lru,
+ struct amdgpu_vm_id,
+ list);
+   } else {
+   /* Check if we can use a VMID already assigned to this VM */
+   do {
+   struct fence *flushed;
+
+   id = vm->ids[i++];
+   if (i == AMDGPU_MAX_RINGS)
+   i = 0;
+
+   /* Check all the prerequisites to using this VMID */
+   if (!id)
+   continue;
+
+   if (atomic64_read(&id->owner) != vm->client_id)
+   continue;
+
+   if (pd_addr != id->pd_gpu_addr)
+   continue;
+
+   if (id->last_user != ring && (!id->last_flush ||
+   !fence_is_signaled(id->last_flush)))
+   continue;
+
+   flushed  = id->flushed_updates;
+   if (updates && (!flushed ||
+   fence_is_later(updates, flushed)))
+   continue;
+
+   /* Good we can use this VMID */
+   if (id->last_user == ring) {
+   r = amdgpu_sync_fence(ring->adev, sync,
+ id->first);
+   if (r)
+   goto error;
+   }

-   /* Good we can use this VMID */
-   if (id->last_user == ring) {
-   r = amdgpu_sync_fence(ring->adev, sync,
- id->first);
+   /* And remember this submission as user of the VMID */
+   r = amdgpu_sync_fence(ring->adev, &id->active, fence);
if (r)
goto error;
-   }
-
-   /* And remember this submission as user of the VMID */
-   r = amdgpu_sync_fence(ring->adev, &id->active, fence);
-   if (r)
-   goto error;

-   list_move_tail(&id->list, &adev->vm_manager.ids_lru);
-   vm->ids[ring->idx] = id;
+   list_move_tail(&id->list, &adev->vm_manager.ids_lru);
+   vm->ids[ring->idx] = id;

-   *vm_id = id - adev->vm_manager.ids;
-   *vm_pd_addr = AMDGPU_VM_NO_FLUSH;
-   trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id, *vm_pd_addr);
+   *vm_id = id - adev->vm_manager.ids;
+   *vm_pd_addr = AMDGPU_VM_NO_FLUSH;
+

[PATCH 08/11] drm/amdgpu: prefer VMIDs idle on the current ring

2016-06-01 Thread Christian König
From: Christian König 

Prefer to use a VMIDs which are idle on the ring we want to submit to. This
also removes bubbling idle VMIDs up on the LRU, which is actually not
beneficial.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 24 +---
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 2bcb623..b6484a2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -236,21 +236,15 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,

} while (i != ring->idx);

-   id = list_first_entry(&adev->vm_manager.ids_lru,
- struct amdgpu_vm_id,
- list);
-
-   if (!amdgpu_sync_is_idle(&id->active, NULL)) {
-   struct list_head *head = &adev->vm_manager.ids_lru;
-   struct amdgpu_vm_id *tmp;
-
-   list_for_each_entry_safe(id, tmp, &adev->vm_manager.ids_lru,
-list) {
-   if (amdgpu_sync_is_idle(&id->active, NULL)) {
-   list_move(&id->list, head);
-   head = &id->list;
-   }
-   }
+   /* Check if we have an idle VMID */
+   list_for_each_entry(id, &adev->vm_manager.ids_lru, list) {
+   if (amdgpu_sync_is_idle(&id->active, ring))
+   break;
+
+   }
+
+   /* If we can't find a idle VMID to use, just wait for the oldest */
+   if (&id->list == &adev->vm_manager.ids_lru) {
id = list_first_entry(&adev->vm_manager.ids_lru,
  struct amdgpu_vm_id,
  list);
-- 
2.5.0



[PATCH 07/11] drm/amdgpu: add optional ring to amdgpu_sync_is_idle

2016-06-01 Thread Christian König
From: Christian König 

Check if the sync object is idle depending on the ring a submission works with.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h  |  3 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c  |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 17 +++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c   |  4 ++--
 4 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 2f4ab1b..f154d9f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -597,7 +597,8 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
 struct amdgpu_sync *sync,
 struct reservation_object *resv,
 void *owner);
-bool amdgpu_sync_is_idle(struct amdgpu_sync *sync);
+bool amdgpu_sync_is_idle(struct amdgpu_sync *sync,
+struct amdgpu_ring *ring);
 int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, struct amdgpu_sync *src,
 struct fence *fence);
 struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 009e905..e395bbe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -166,7 +166,7 @@ static struct fence *amdgpu_job_run(struct amd_sched_job 
*sched_job)
}
job = to_amdgpu_job(sched_job);

-   BUG_ON(!amdgpu_sync_is_idle(&job->sync));
+   BUG_ON(!amdgpu_sync_is_idle(&job->sync, NULL));

trace_amdgpu_sched_run_job(job);
r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index c0ed5b9..a2766d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -226,10 +226,13 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
  * amdgpu_sync_is_idle - test if all fences are signaled
  *
  * @sync: the sync object
+ * @ring: optional ring to use for test
  *
- * Returns true if all fences in the sync object are signaled.
+ * Returns true if all fences in the sync object are signaled or scheduled to
+ * the ring (if provided).
  */
-bool amdgpu_sync_is_idle(struct amdgpu_sync *sync)
+bool amdgpu_sync_is_idle(struct amdgpu_sync *sync,
+struct amdgpu_ring *ring)
 {
struct amdgpu_sync_entry *e;
struct hlist_node *tmp;
@@ -237,6 +240,16 @@ bool amdgpu_sync_is_idle(struct amdgpu_sync *sync)

hash_for_each_safe(sync->fences, i, tmp, e, node) {
struct fence *f = e->fence;
+   struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
+
+   if (ring && s_fence) {
+   /* For fences from the same ring it is sufficient
+* when they are scheduled.
+*/
+   if (s_fence->sched == &ring->sched &&
+   fence_is_signaled(&s_fence->scheduled))
+   continue;
+   }

if (fence_is_signaled(f)) {
hash_del(&e->node);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 62a4c12..2bcb623 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -240,13 +240,13 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct 
amdgpu_ring *ring,
  struct amdgpu_vm_id,
  list);

-   if (!amdgpu_sync_is_idle(&id->active)) {
+   if (!amdgpu_sync_is_idle(&id->active, NULL)) {
struct list_head *head = &adev->vm_manager.ids_lru;
struct amdgpu_vm_id *tmp;

list_for_each_entry_safe(id, tmp, &adev->vm_manager.ids_lru,
 list) {
-   if (amdgpu_sync_is_idle(&id->active)) {
+   if (amdgpu_sync_is_idle(&id->active, NULL)) {
list_move(&id->list, head);
head = &id->list;
}
-- 
2.5.0



[PATCH 06/11] drm/amdgpu: remove amdgpu_sync_wait

2016-06-01 Thread Christian König
From: Christian König 

Stop hiding bugs, instead print a proper error when the scheduler
doesn't handle all dependencies.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h  |  1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c  |  6 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 19 ---
 3 files changed, 1 insertion(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 7d25977..2f4ab1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -601,7 +601,6 @@ bool amdgpu_sync_is_idle(struct amdgpu_sync *sync);
 int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, struct amdgpu_sync *src,
 struct fence *fence);
 struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
-int amdgpu_sync_wait(struct amdgpu_sync *sync);
 void amdgpu_sync_free(struct amdgpu_sync *sync);
 int amdgpu_sync_init(void);
 void amdgpu_sync_fini(void);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index ddfed93..009e905 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -166,11 +166,7 @@ static struct fence *amdgpu_job_run(struct amd_sched_job 
*sched_job)
}
job = to_amdgpu_job(sched_job);

-   r = amdgpu_sync_wait(&job->sync);
-   if (r) {
-   DRM_ERROR("failed to sync wait (%d)\n", r);
-   return NULL;
-   }
+   BUG_ON(!amdgpu_sync_is_idle(&job->sync));

trace_amdgpu_sched_run_job(job);
r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index e0ff1a1..c0ed5b9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -326,25 +326,6 @@ struct fence *amdgpu_sync_get_fence(struct amdgpu_sync 
*sync)
return NULL;
 }

-int amdgpu_sync_wait(struct amdgpu_sync *sync)
-{
-   struct amdgpu_sync_entry *e;
-   struct hlist_node *tmp;
-   int i, r;
-
-   hash_for_each_safe(sync->fences, i, tmp, e, node) {
-   r = fence_wait(e->fence, false);
-   if (r)
-   return r;
-
-   hash_del(&e->node);
-   fence_put(e->fence);
-   kmem_cache_free(amdgpu_sync_slab, e);
-   }
-
-   return 0;
-}
-
 /**
  * amdgpu_sync_free - free the sync object
  *
-- 
2.5.0



[PATCH 05/11] drm/amdgpu: generalize the scheduler fence

2016-06-01 Thread Christian König
From: Christian König 

Make it two events, one for the job being scheduled and one when it is finished.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_job.c |  4 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h   |  4 +-
 drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h |  4 +-
 drivers/gpu/drm/amd/scheduler/gpu_scheduler.c   | 34 +++--
 drivers/gpu/drm/amd/scheduler/gpu_scheduler.h   | 19 
 drivers/gpu/drm/amd/scheduler/sched_fence.c | 63 ++---
 6 files changed, 79 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index d4791a7..ddfed93 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -85,7 +85,7 @@ static void amdgpu_job_free_resources(struct amdgpu_job *job)
unsigned i;

/* use sched fence if available */
-   f = job->base.s_fence ? &job->base.s_fence->base : job->fence;
+   f = job->base.s_fence ? &job->base.s_fence->finished : job->fence;

for (i = 0; i < job->num_ibs; ++i)
amdgpu_ib_free(job->adev, &job->ibs[i], f);
@@ -143,7 +143,7 @@ static struct fence *amdgpu_job_dependency(struct 
amd_sched_job *sched_job)
int r;

r = amdgpu_vm_grab_id(vm, ring, &job->sync,
- &job->base.s_fence->base,
+ &job->base.s_fence->finished,
  &job->vm_id, &job->vm_pd_addr);
if (r)
DRM_ERROR("Error getting VM ID (%d)\n", r);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index 38e5689..ecd08f8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -102,7 +102,7 @@ TRACE_EVENT(amdgpu_cs_ioctl,
   __entry->adev = job->adev;
   __entry->sched_job = &job->base;
   __entry->ib = job->ibs;
-  __entry->fence = &job->base.s_fence->base;
+  __entry->fence = &job->base.s_fence->finished;
   __entry->ring_name = job->ring->name;
   __entry->num_ibs = job->num_ibs;
   ),
@@ -127,7 +127,7 @@ TRACE_EVENT(amdgpu_sched_run_job,
   __entry->adev = job->adev;
   __entry->sched_job = &job->base;
   __entry->ib = job->ibs;
-  __entry->fence = &job->base.s_fence->base;
+  __entry->fence = &job->base.s_fence->finished;
   __entry->ring_name = job->ring->name;
   __entry->num_ibs = job->num_ibs;
   ),
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h 
b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
index c89dc77..b961a1c 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
+++ b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
@@ -26,7 +26,7 @@ TRACE_EVENT(amd_sched_job,
TP_fast_assign(
   __entry->entity = sched_job->s_entity;
   __entry->sched_job = sched_job;
-  __entry->fence = &sched_job->s_fence->base;
+  __entry->fence = &sched_job->s_fence->finished;
   __entry->name = sched_job->sched->name;
   __entry->job_count = kfifo_len(
   &sched_job->s_entity->job_queue) / 
sizeof(sched_job);
@@ -46,7 +46,7 @@ TRACE_EVENT(amd_sched_process_job,
),

TP_fast_assign(
-   __entry->fence = &fence->base;
+   __entry->fence = &fence->finished;
),
TP_printk("fence=%p signaled", __entry->fence)
 );
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c 
b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
index 2425172..74aa0b3 100644
--- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
@@ -140,7 +140,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
return r;

atomic_set(&entity->fence_seq, 0);
-   entity->fence_context = fence_context_alloc(1);
+   entity->fence_context = fence_context_alloc(2);

return 0;
 }
@@ -251,17 +251,21 @@ static bool amd_sched_entity_add_dependency_cb(struct 
amd_sched_entity *entity)

s_fence = to_amd_sched_fence(fence);
if (s_fence && s_fence->sched == sched) {
-   /* Fence is from the same scheduler */
-   if (test_bit(AMD_SCHED_FENCE_SCHEDULED_BIT, &fence->flags)) {
-   /* Ignore it when it is already scheduled */
-   fence_put(entity->de

[PATCH 04/11] drm/amdgpu: document amdgpu_sync_get_fence

2016-06-01 Thread Christian König
From: Christian König 

It's not obvious what it should do.

Signed-off-by: Christian König 
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index 34a9280..e0ff1a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -297,6 +297,13 @@ int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, 
struct amdgpu_sync *src,
return 0;
 }

+/**
+ * amdgpu_sync_get_fence - get the next fence from the sync object
+ *
+ * @sync: sync object to use
+ *
+ * Get and removes the next fence from the sync object not signaled yet.
+ */
 struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
 {
struct amdgpu_sync_entry *e;
-- 
2.5.0



[PATCH 03/11] dma-buf/fence: add signal_on_any to the fence array v2

2016-06-01 Thread Christian König
From: Christian König 

If @signal_on_any is true the fence array signals if any fence in the array
signals, otherwise it signals when all fences in the array signal.

v2: fix signaled test and add comment suggested by Chris Wilson.

Signed-off-by: Christian König 
---
 drivers/dma-buf/fence-array.c | 33 +
 include/linux/fence-array.h   |  3 ++-
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/dma-buf/fence-array.c b/drivers/dma-buf/fence-array.c
index 8141217..a8731c8 100644
--- a/drivers/dma-buf/fence-array.c
+++ b/drivers/dma-buf/fence-array.c
@@ -41,6 +41,7 @@ static void fence_array_cb_func(struct fence *f, struct 
fence_cb *cb)

if (atomic_dec_and_test(&array->num_pending))
fence_signal(&array->base);
+   fence_put(&array->base);
 }

 static bool fence_array_enable_signaling(struct fence *fence)
@@ -51,10 +52,21 @@ static bool fence_array_enable_signaling(struct fence 
*fence)

for (i = 0; i < array->num_fences; ++i) {
cb[i].array = array;
+   /*
+* As we may report that the fence is signaled before all
+* callbacks are complete, we need to take an additional
+* reference count on the array so that we do not free it too
+* early. The core fence handling will only hold the reference
+* until we signal the array as complete (but that is now
+* insufficient).
+*/
+   fence_get(&array->base);
if (fence_add_callback(array->fences[i], &cb[i].cb,
-  fence_array_cb_func))
+  fence_array_cb_func)) {
+   fence_put(&array->base);
if (atomic_dec_and_test(&array->num_pending))
return false;
+   }
}

return true;
@@ -64,7 +76,7 @@ static bool fence_array_signaled(struct fence *fence)
 {
struct fence_array *array = to_fence_array(fence);

-   return atomic_read(&array->num_pending) == 0;
+   return atomic_read(&array->num_pending) <= 0;
 }

 static void fence_array_release(struct fence *fence)
@@ -90,10 +102,11 @@ const struct fence_ops fence_array_ops = {

 /**
  * fence_array_create - Create a custom fence array
- * @num_fences:[in]number of fences to add in the array
- * @fences:[in]array containing the fences
- * @context:   [in]fence context to use
- * @seqno: [in]sequence number to use
+ * @num_fences:[in]number of fences to add in the array
+ * @fences:[in]array containing the fences
+ * @context:   [in]fence context to use
+ * @seqno: [in]sequence number to use
+ * @signal_on_any  [in]signal on any fence in the array
  *
  * Allocate a fence_array object and initialize the base fence with 
fence_init().
  * In case of error it returns NULL.
@@ -101,9 +114,13 @@ const struct fence_ops fence_array_ops = {
  * The caller should allocte the fences array with num_fences size
  * and fill it with the fences it wants to add to the object. Ownership of this
  * array is take and fence_put() is used on each fence on release.
+ *
+ * If @signal_on_any is true the fence array signals if any fence in the array
+ * signals, otherwise it signals when all fences in the array signal.
  */
 struct fence_array *fence_array_create(int num_fences, struct fence **fences,
-  u64 context, unsigned seqno)
+  u64 context, unsigned seqno,
+  bool signal_on_any)
 {
struct fence_array *array;
size_t size = sizeof(*array);
@@ -119,7 +136,7 @@ struct fence_array *fence_array_create(int num_fences, 
struct fence **fences,
   context, seqno);

array->num_fences = num_fences;
-   atomic_set(&array->num_pending, num_fences);
+   atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
array->fences = fences;

return array;
diff --git a/include/linux/fence-array.h b/include/linux/fence-array.h
index 593ab98..86baaa4 100644
--- a/include/linux/fence-array.h
+++ b/include/linux/fence-array.h
@@ -67,6 +67,7 @@ static inline struct fence_array *to_fence_array(struct fence 
*fence)
 }

 struct fence_array *fence_array_create(int num_fences, struct fence **fences,
-  u64 context, unsigned seqno);
+  u64 context, unsigned seqno,
+  bool signal_on_any);

 #endif /* __LINUX_FENCE_ARRAY_H */
-- 
2.5.0



[PATCH 02/11] dma-buf/fence: add fence_array fences v6

2016-06-01 Thread Christian König
From: Gustavo Padovan 

struct fence_collection inherits from struct fence and carries a
collection of fences that needs to be waited together.

It is useful to translate a sync_file to a fence to remove the complexity
of dealing with sync_files on DRM drivers. So even if there are many
fences in the sync_file that needs to waited for a commit to happen,
they all get added to the fence_collection and passed for DRM use as
a standard struct fence.

That means that no changes needed to any driver besides supporting fences.

fence_collection's fence doesn't belong to any timeline context, so
fence_is_later() and fence_later() are not meant to be called with
fence_collections fences.

v2: Comments by Daniel Vetter:
- merge fence_collection_init() and fence_collection_add()
- only add callbacks at ->enable_signalling()
- remove fence_collection_put()
- check for type on to_fence_collection()
- adjust fence_is_later() and fence_later() to WARN_ON() if they
are used with collection fences.

v3: - Initialize fence_cb.node at fence init.

Comments by Chris Wilson:
- return "unbound" on fence_collection_get_timeline_name()
- don't stop adding callbacks if one fails
- remove redundant !! on fence_collection_enable_signaling()
- remove redundant () on fence_collection_signaled
- use fence_default_wait() instead

v4 (chk): Rework, simplification and cleanup:
- Drop FENCE_NO_CONTEXT handling, always allocate a context.
- Rename to fence_array.
- Return fixed driver name.
- Register only one callback at a time.
- Document that create function takes ownership of array.

v5 (chk): More work and fixes:
- Avoid deadlocks by adding all callbacks at once again.
- Stop trying to remove the callbacks.
- Provide context and sequence number for the array fence.

v6 (chk): Fixes found during testing
- Fix stupid typo in _enable_signaling().

Signed-off-by: Gustavo Padovan 
Signed-off-by: Christian König 
---
 drivers/dma-buf/Makefile  |   2 +-
 drivers/dma-buf/fence-array.c | 127 ++
 include/linux/fence-array.h   |  72 
 3 files changed, 200 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/fence-array.c
 create mode 100644 include/linux/fence-array.h

diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 57a675f..85f6928 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1 +1 @@
-obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
+obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o
diff --git a/drivers/dma-buf/fence-array.c b/drivers/dma-buf/fence-array.c
new file mode 100644
index 000..8141217
--- /dev/null
+++ b/drivers/dma-buf/fence-array.c
@@ -0,0 +1,127 @@
+/*
+ * fence-array: aggregate fences to be waited together
+ *
+ * Copyright (C) 2016 Collabora Ltd
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ * Authors:
+ * Gustavo Padovan 
+ * Christian König 
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include 
+#include 
+#include 
+
+static void fence_array_cb_func(struct fence *f, struct fence_cb *cb);
+
+static const char *fence_array_get_driver_name(struct fence *fence)
+{
+   return "fence_array";
+}
+
+static const char *fence_array_get_timeline_name(struct fence *fence)
+{
+   return "unbound";
+}
+
+static void fence_array_cb_func(struct fence *f, struct fence_cb *cb)
+{
+   struct fence_array_cb *array_cb =
+   container_of(cb, struct fence_array_cb, cb);
+   struct fence_array *array = array_cb->array;
+
+   if (atomic_dec_and_test(&array->num_pending))
+   fence_signal(&array->base);
+}
+
+static bool fence_array_enable_signaling(struct fence *fence)
+{
+   struct fence_array *array = to_fence_array(fence);
+   struct fence_array_cb *cb = (void *)(&array[1]);
+   unsigned i;
+
+   for (i = 0; i < array->num_fences; ++i) {
+   cb[i].array = array;
+   if (fence_add_callback(array->fences[i], &cb[i].cb,
+  fence_array_cb_func))
+   if (atomic_dec_and_test(&array->num_pending))
+   return false;
+   }
+
+   return true;
+}
+
+static bool fence_array_signaled(struct fence *fence)
+{
+   struct fence_array *array = to_fence_array(fence);
+
+   return atomic_read(&array->num_pending) == 0;
+}
+
+static void fence_array

[PATCH 01/11] dma-buf/fence: make fence context 64 bit v2

2016-06-01 Thread Christian König
From: Christian König 

Fence contexts are created on the fly (for example) by the GPU scheduler used
in the amdgpu driver as a result of an userspace request. Because of this
userspace could in theory force a wrap around of the 32bit context number
if it doesn't behave well.

Avoid this by increasing the context number to 64bits. This way even when
userspace manages to allocate a billion contexts per second it takes more
than 500 years for the context number to wrap around.

v2: fix printf formats as well.

Signed-off-by: Christian König 
---
 drivers/dma-buf/fence.c |  8 
 drivers/gpu/drm/amd/amdgpu/amdgpu.h |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c  |  2 +-
 drivers/gpu/drm/etnaviv/etnaviv_gpu.h   |  2 +-
 drivers/gpu/drm/nouveau/nouveau_fence.h |  3 ++-
 drivers/gpu/drm/qxl/qxl_release.c   |  2 +-
 drivers/gpu/drm/radeon/radeon.h |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_fence.c   |  2 +-
 drivers/staging/android/sync.h  |  3 ++-
 include/linux/fence.h   | 13 +++--
 10 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/dma-buf/fence.c b/drivers/dma-buf/fence.c
index 7b05dbe..4d51f9e 100644
--- a/drivers/dma-buf/fence.c
+++ b/drivers/dma-buf/fence.c
@@ -35,7 +35,7 @@ EXPORT_TRACEPOINT_SYMBOL(fence_emit);
  * context or not. One device can have multiple separate contexts,
  * and they're used if some engine can run independently of another.
  */
-static atomic_t fence_context_counter = ATOMIC_INIT(0);
+static atomic64_t fence_context_counter = ATOMIC64_INIT(0);

 /**
  * fence_context_alloc - allocate an array of fence contexts
@@ -44,10 +44,10 @@ static atomic_t fence_context_counter = ATOMIC_INIT(0);
  * This function will return the first index of the number of fences allocated.
  * The fence context is used for setting fence->context to a unique number.
  */
-unsigned fence_context_alloc(unsigned num)
+u64 fence_context_alloc(unsigned num)
 {
BUG_ON(!num);
-   return atomic_add_return(num, &fence_context_counter) - num;
+   return atomic64_add_return(num, &fence_context_counter) - num;
 }
 EXPORT_SYMBOL(fence_context_alloc);

@@ -513,7 +513,7 @@ EXPORT_SYMBOL(fence_wait_any_timeout);
  */
 void
 fence_init(struct fence *fence, const struct fence_ops *ops,
-spinlock_t *lock, unsigned context, unsigned seqno)
+spinlock_t *lock, u64 context, unsigned seqno)
 {
BUG_ON(!lock);
BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 3d0cec2..7d25977 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -2045,7 +2045,7 @@ struct amdgpu_device {
struct amdgpu_irq_src   hpd_irq;

/* rings */
-   unsignedfence_context;
+   u64 fence_context;
unsignednum_rings;
struct amdgpu_ring  *rings[AMDGPU_MAX_RINGS];
boolib_pool_ready;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
index 48618ee..d8af37a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
@@ -428,7 +428,7 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager 
*sa_manager,
   soffset, eoffset, eoffset - soffset);

if (i->fence)
-   seq_printf(m, " protected by 0x%08x on context %d",
+   seq_printf(m, " protected by 0x%08x on context %llu",
   i->fence->seqno, i->fence->context);

seq_printf(m, "\n");
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h 
b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index f233ac4..6a69214 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -123,7 +123,7 @@ struct etnaviv_gpu {
u32 completed_fence;
u32 retired_fence;
wait_queue_head_t fence_event;
-   unsigned int fence_context;
+   u64 fence_context;
spinlock_t fence_spinlock;

/* worker for handling active-list retiring: */
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h 
b/drivers/gpu/drm/nouveau/nouveau_fence.h
index 2e3a62d..64c4ce7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -57,7 +57,8 @@ struct nouveau_fence_priv {
int  (*context_new)(struct nouveau_channel *);
void (*context_del)(struct nouveau_channel *);

-   u32 contexts, context_base;
+   u32 contexts;
+   u64 context_base;
bool uevent;
 };

diff --git a/drivers/gpu/drm/qxl/qxl_release.c 
b/drivers/gpu/drm/qxl/qxl_release.c
index 4efa8e2..f599cd0 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -96,7 +96,7 @@ retry:
 

Fence array patchset

2016-06-01 Thread Christian König
Hi guys,

this is the next iteration of the fence array patch set.

Daniel suggested that I provide an example on how this functionality might be
used by a driver. So I added a few additional patches in this series to show
what I want to do with this in the amdgpu driver.

The main idea is that for each VMID we have a set of hardware fences which are
currently using this VMID. Now when a new command submission needs a VMID we
construct a fence array which should signal when any of the VMIDs becomes
available and gives that back to our the scheduler.

This effort and my testing also found a rather stupid typo in the code and I
also tried to incorporate the comments from Chris and Daniel as well.

I think it's ready to land now, but as usual feel free to take it apart.

Cheers,
Christian.



[PATCH 2/3] drm/exynos: fimd: add HW trigger support

2016-06-01 Thread Inki Dae
Hi Javier,

2016년 05월 31일 07:58에 Javier Martinez Canillas 이(가) 쓴 글:
> Hello Inki,
> 
> On 04/05/2016 04:27 AM, Inki Dae wrote:
>> This patch adds HW trigger support on i80 mode.
>>
>> Until now, Exynos DRM only supported SW trigger which was set
>> SWTRGCMD bit of TRIGCON register by CPU to transfer scanout
>> buffer to Display bus device or panel.
>>
>> With this patch, the transmission to Display bus device or
>> panel will be initiated by FIMD controller.
>>
>> Signed-off-by: Inki Dae 
>> ---
> 
> There is a regression for the Exynos5800 Peach Pi Chromebook display due
> this patch. The display is blank and I noticed that it only happens when
> HW start trigger is enabled, but works with SW trigger (as it was before).

Posted below pathch,
[PATCH] drm/exynos: fimd: fix trigger mode change regression

Can you test it again with the patch? I have no HW to test it. :(

Thanks,
Inki Dae

> 
> So for example with the following diff on top of v4.7-rc1, display works
> again. Do you have any hints about what could be the issue?
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
> b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 0444d7fc400d..8c62830e9514 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -171,7 +171,7 @@ static struct fimd_driver_data 
> exynos5420_fimd_driver_data = {
>   .lcdblk_vt_shift = 24,
>   .lcdblk_bypass_shift = 15,
>   .lcdblk_mic_bypass_shift = 11,
> - .trg_type = I80_HW_TRG,
>   .has_shadowcon = 1,
>   .has_vidoutcon = 1,
>   .has_vtsel = 1,
> 
> Best regards,
> 


[PATCH] drm/exynos: fimd: fix trigger mode change regression

2016-06-01 Thread Inki Dae
This patch fixes a regression that Display panel doesn't work
since HW trigger mode was supported.

The trigger mode should be changed on PSR(Panel Self Refresh)
mode of Panel device according to HW guy's saying. However,
with previous HW trigger support, trigger mode could been changed
in normal mode of Panel device.

So this patch makes sure to change the trigger mode after power off
and on again. Later we need to add PSR relevant codes instead.

Signed-off-by: Inki Dae 
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 35 
 1 file changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 3efe1aa..355149f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -203,6 +203,11 @@ struct fimd_context {
atomic_twait_vsync_event;
atomic_twin_updated;
atomic_ttriggering;
+   /*
+* fimd_setup_trigger function will try to change trigger mode
+* only in case that this flag is set.
+*/
+   atomic_tdeferred_tr_mode;

const struct fimd_driver_data *driver_data;
struct drm_encoder *encoder;
@@ -430,11 +435,37 @@ static void fimd_setup_trigger(struct fimd_context *ctx)
val &= ~(TRGMODE_ENABLE);

if (trg_type == I80_HW_TRG) {
+   /*
+* change trigger mode after power off and on again.
+* deferred_tr_mode will be set when fimd_disable is called.
+*
+* TODO. Trigger mode should be changed on PSR mode of Panel
+* device. So we have to add relevant codes to make sure
+* entering into PSR mode later.
+*/
+   if (val & TRGMODE_ENABLE &&
+   !atomic_read(&ctx->deferred_tr_mode))
+   return;
+
if (ctx->driver_data->has_hw_trigger)
val |= HWTRGEN_ENABLE | HWTRGMASK_ENABLE;
if (ctx->driver_data->has_trigger_per_te)
val |= HWTRIGEN_PER_ENABLE;
} else {
+   /*
+* change trigger mode after power off and on again.
+* deferred_tr_mode will be set when fimd_disable is called.
+*
+* TODO. Trigger mode should be changed on PSR mode of Panel
+* device. So we have to add relevant codes to make sure
+* entering into PSR mode later.
+*/
+   if (ctx->driver_data->has_hw_trigger) {
+   if (val & HWTRGEN_ENABLE &&
+   !atomic_read(&ctx->deferred_tr_mode))
+   return;
+   }
+
val |= TRGMODE_ENABLE;
}

@@ -864,6 +895,10 @@ static void fimd_disable(struct exynos_drm_crtc *crtc)
writel(0, ctx->regs + VIDCON0);

pm_runtime_put_sync(ctx->dev);
+
+   if (ctx->i80_if)
+   atomic_set(&ctx->deferred_tr_mode, 1);
+
ctx->suspended = true;
 }

-- 
1.9.1



[PATCH v7 00/12] Support non-lru page migration

2016-06-01 Thread Andrew Morton
On Wed,  1 Jun 2016 08:21:09 +0900 Minchan Kim  wrote:

> Recently, I got many reports about perfermance degradation in embedded
> system(Android mobile phone, webOS TV and so on) and easy fork fail.
> 
> The problem was fragmentation caused by zram and GPU driver mainly.
> With memory pressure, their pages were spread out all of pageblock and
> it cannot be migrated with current compaction algorithm which supports
> only LRU pages. In the end, compaction cannot work well so reclaimer
> shrinks all of working set pages. It made system very slow and even to
> fail to fork easily which requires order-[2 or 3] allocations.
> 
> Other pain point is that they cannot use CMA memory space so when OOM
> kill happens, I can see many free pages in CMA area, which is not
> memory efficient. In our product which has big CMA memory, it reclaims
> zones too exccessively to allocate GPU and zram page although there are
> lots of free space in CMA so system becomes very slow easily.

But this isn't presently implemented for GPU drivers or for CMA, yes?

What's the story there?


[Nouveau] [PATCH 9/9] drm: Turn off crtc before tearing down its data structure

2016-06-01 Thread Lukas Wunner
On Wed, May 25, 2016 at 03:43:42PM +0200, Daniel Vetter wrote:
> On Wed, May 25, 2016 at 12:51 PM, Lukas Wunner  wrote:
> > On Tue, May 24, 2016 at 11:30:42PM +0200, Daniel Vetter wrote:
> >> On Tue, May 24, 2016 at 06:03:27PM +0200, Lukas Wunner wrote:
> >> > When a drm_crtc structure is destroyed with drm_crtc_cleanup(), the DRM
> >> > core does not turn off the crtc first and neither do the drivers. With
> >> > nouveau, radeon and amdgpu, this causes a runtime pm ref to be leaked on
> >> > driver unload if at least one crtc was enabled.
> >> >
> >> > (See usage of have_disp_power_ref in nouveau_crtc_set_config(),
> >> > radeon_crtc_set_config() and amdgpu_crtc_set_config()).
> >> >
> >> > Fixes: 5addcf0a5f0f ("nouveau: add runtime PM support (v0.9)")
> >> > Cc: Dave Airlie 
> >> > Tested-by: Karol Herbst 
> >> > Signed-off-by: Lukas Wunner 
> >>
> >> This is a core regression, we fixed it again. Previously when unreference
> >> drm_planes the core made sure that it's not longer in use, which had the
> >> side effect of shutting everything off in module unload.
> >>
> >> For a bunch of reasons we've stopped doing that, but that turned out to be
> >> a mistake. It's fixed since
> >>
> >> commit f2d580b9a8149735cbc4b59c4a8df60173658140
> >> Author: Maarten Lankhorst 
> >> Date:   Wed May 4 14:38:26 2016 +0200
> >>
> >> drm/core: Do not preserve framebuffer on rmfb, v4.
> >>
> >> Your patch shouldn't be needed with that any more. If it still is it's
> >> most likely the fbdev cleanup done too late, but you /should/ get a big
> >> WARNING splat in that case from drm_mode_config_cleanup().
> >
> > I tested it and at least with nouveau, the above-mentioned commit does
> > *not* solve the issue, so patch [9/9] of this series is still needed.
> > I do not get a WARN splat when unloading nouveau.
> 
> With legacy kms the only way to keep a crtc enabled is to display a
> drm_framebuffer on it. And drm_mode_config_cleanup has a WARN_ON if
> framebuffers are left behind. There's a bunch of options:
> - nouveau somehow manages to keep the crtc on without a framebuffer
> - nouveau somehow leaks a drm_framebuffer, but removes it from the fb_list
> - something else

Found it. nouveau_fbcon_destroy() doesn't call drm_framebuffer_remove().
If I add that, the crtc gets properly disabled on unload.

It does call drm_framebuffer_cleanup(). That's why there was no WARN,
drm_mode_config_cleanup() only WARNs if a framebuffer was left on the
mode_config.fb_list.

radeon and amdgpu have the same problem. In fact there are very few
drivers that call drm_framebuffer_remove(): tegra, msm, exynos, omapdrm
and i915 (since Imre Deak's 9d6612516da0).

Should we add a WARN to prevent this? How about WARN_ON(crtc->enabled)
in drm_crtc_cleanup()?

Also, i915 calls drm_framebuffer_unregister_private() before it calls
drm_framebuffer_remove(). This ordering has the unfortunate side effect
that the drm_framebuffer has ID 0 in log messages emitted by
drm_framebuffer_remove():

[   39.680874] [drm:drm_mode_object_unreference] OBJ ID: 0 (3)
[   39.680878] [drm:drm_mode_object_unreference] OBJ ID: 0 (2)
[   39.680884] [drm:drm_mode_object_unreference] OBJ ID: 0 (1)

Best regards,

Lukas

> 
> There's still no need to forcefully shut down crtc at cleanup time in
> the core, this is still a driver bug. So yes your patch might be
> needed, but it's not the right fix.
> -Daniel
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch


[PATCH] drm: hdlcd: Cleanup the atomic plane operations and vsync handling

2016-06-01 Thread Liviu Dudau
Don't disable the vsync interrupt, as the hardware lacks hardware
counters for vsync time stamping and that breaks the DRM assumptions.

Also harden the plane_check() code to drop attempts at scaling because
that is not supported. Make hdlcd_plane_atomic_update() set the pitch
and line length registers that correctly reflect the plane's values.
And make hdlcd_crtc_mode_set_nofb() a helper function for
hdlcd_crtc_enable() rather than an exposed hook.

Cc: Daniel Vetter 
Signed-off-by: Liviu Dudau 
---
 drivers/gpu/drm/arm/hdlcd_crtc.c | 44 ++--
 drivers/gpu/drm/arm/hdlcd_drv.c  | 17 +++-
 drivers/gpu/drm/arm/hdlcd_drv.h  |  1 -
 3 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index b2e894b..6037076 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -106,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
struct drm_display_mode *m = &crtc->state->adjusted_mode;
struct videomode vm;
-   unsigned int polarities, line_length, err;
+   unsigned int polarities, err;

vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -122,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc 
*crtc)
if (m->flags & DRM_MODE_FLAG_PVSYNC)
polarities |= HDLCD_POLARITY_VSYNC;

-   line_length = crtc->primary->state->fb->pitches[0];
-
/* Allow max number of outstanding requests and largest burst size */
hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);

-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
-   hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
+   hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
-   hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);

err = hdlcd_set_pxl_fmt(crtc);
@@ -153,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

clk_prepare_enable(hdlcd->clk);
+   hdlcd_crtc_mode_set_nofb(crtc);
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
-   drm_crtc_vblank_on(crtc);
 }

 static void hdlcd_crtc_disable(struct drm_crtc *crtc)
 {
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);

-   if (!crtc->primary->fb)
+   if (!crtc->state->active)
return;

hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
clk_disable_unprepare(hdlcd->clk);
-   drm_crtc_vblank_off(crtc);
 }

 static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -213,6 +207,15 @@ static const struct drm_crtc_helper_funcs 
hdlcd_crtc_helper_funcs = {
 static int hdlcd_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
 {
+   u32 src_w, src_h;
+
+   src_w = state->src_w >> 16;
+   src_h = state->src_h >> 16;
+
+   /* we can't do any scaling of the plane source */
+   if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
+   return -EINVAL;
+
return 0;
 }

@@ -221,20 +224,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane 
*plane,
 {
struct hdlcd_drm_private *hdlcd;
struct drm_gem_cma_object *gem;
+   unsigned int depth, bpp;
+   u32 src_w, src_h, dest_w, dest_h;
dma_addr_t scanout_start;

-   if (!plane->state->crtc || !plane->state->fb)
+   if (!plane->state->fb)
return;

-   hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
+   drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
+   src_w = plane->state->src_w >> 16;
+   src_h = plane->state->src_h >> 16;
+   dest_w = plane->state->crtc_w;
+   dest_h = plane->state->crtc_h;
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
-   scanout_start = gem->paddr;
+   scanout_start = gem->paddr + plane->state->fb->offsets[0] +
+   plane->state->crtc_y * plane->state->fb->pitches[0] +
+   plane->state->crtc_x * bpp / 8;
+
+   hdlcd = plane->dev->dev_private;
+

[PULL] drm: atmel-hlcdc: fixes for 4.7-rc2

2016-06-01 Thread Boris Brezillon
Hi Dave,

This pull request contains 2 trivial fixes for the atmel-hlcdc driver.

The first one is making use of __drm_atomic_helper_crtc_destroy_state()
instead of duplicating its logic in atmel_hlcdc_crtc_reset() and
risking memory leaks if other objects are added to the common CRTC
state.

The second one is fixing a possible NULL pointer dereference.

Regards,

Boris

The following changes since commit 1a695a905c18548062509178b98bc91e67510864:

  Linux 4.7-rc1 (2016-05-29 09:29:24 -0700)

are available in the git repository at:

  git at github.com:bbrezillon/linux-at91.git 
tags/drm-atmel-hlcdc-fixes/for-4.7-rc2

for you to fetch changes up to dcd64e313ff2d2a15574cd92ec27e73194ba7537:

  drm: atmel-hlcdc: fix a NULL check (2016-06-01 13:36:26 +0200)


Two trivial bugfixes on the atmel-hlcdc driver for 4.7-rc2.

The first one is making use of __drm_atomic_helper_crtc_destroy_state()
instead of duplicating its logic in atmel_hlcdc_crtc_reset() and
risking memory leaks if other objects are added to the common CRTC
state.

The second one is fixing a possible NULL pointer dereference.


Boris Brezillon (1):
  drm: atmel-hlcdc: fix atmel_hlcdc_crtc_reset() implementation

Dan Carpenter (1):
  drm: atmel-hlcdc: fix a NULL check

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)


-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com


[PATCH v5 1/1] drm: sti: Add ASoC generic hdmi codec support.

2016-06-01 Thread Benjamin Gaignard
Ack-by: Benjamin Gaignard 

2016-05-30 15:31 GMT+02:00 Arnaud Pouliquen :
> Add the interface needed by audio hdmi-codec driver.
>
> Signed-off-by: Arnaud Pouliquen 
> ---
>  drivers/gpu/drm/sti/Kconfig|   1 +
>  drivers/gpu/drm/sti/sti_hdmi.c | 294 
> ++---
>  drivers/gpu/drm/sti/sti_hdmi.h |  13 ++
>  3 files changed, 291 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
> index 5ad43a1..494ab25 100644
> --- a/drivers/gpu/drm/sti/Kconfig
> +++ b/drivers/gpu/drm/sti/Kconfig
> @@ -7,5 +7,6 @@ config DRM_STI
> select DRM_KMS_CMA_HELPER
> select DRM_PANEL
> select FW_LOADER
> +   select SND_SOC_HDMI_CODEC if SND_SOC
> help
>   Choose this option to enable DRM on STM stiH41x chipset
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 6ef0715..f345c2d 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -18,6 +18,8 @@
>  #include 
>  #include 
>
> +#include 
> +
>  #include "sti_hdmi.h"
>  #include "sti_hdmi_tx3g4c28phy.h"
>  #include "sti_hdmi_tx3g0c55phy.h"
> @@ -35,6 +37,8 @@
>  #define HDMI_DFLT_CHL0_DAT  0x0110
>  #define HDMI_DFLT_CHL1_DAT  0x0114
>  #define HDMI_DFLT_CHL2_DAT  0x0118
> +#define HDMI_AUDIO_CFG  0x0200
> +#define HDMI_SPDIF_FIFO_STATUS  0x0204
>  #define HDMI_SW_DI_1_HEAD_WORD  0x0210
>  #define HDMI_SW_DI_1_PKT_WORD0  0x0214
>  #define HDMI_SW_DI_1_PKT_WORD1  0x0218
> @@ -44,6 +48,9 @@
>  #define HDMI_SW_DI_1_PKT_WORD5  0x0228
>  #define HDMI_SW_DI_1_PKT_WORD6  0x022C
>  #define HDMI_SW_DI_CFG  0x0230
> +#define HDMI_SAMPLE_FLAT_MASK   0x0244
> +#define HDMI_AUDN   0x0400
> +#define HDMI_AUD_CTS0x0404
>  #define HDMI_SW_DI_2_HEAD_WORD  0x0600
>  #define HDMI_SW_DI_2_PKT_WORD0  0x0604
>  #define HDMI_SW_DI_2_PKT_WORD1  0x0608
> @@ -103,6 +110,7 @@
>  #define HDMI_INT_DLL_LCKBIT(5)
>  #define HDMI_INT_NEW_FRAME  BIT(6)
>  #define HDMI_INT_GENCTRL_PKTBIT(7)
> +#define HDMI_INT_AUDIO_FIFO_XRUNBIT(8)
>  #define HDMI_INT_SINK_TERM_PRESENT  BIT(11)
>
>  #define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
> @@ -111,6 +119,7 @@
> | HDMI_INT_GLOBAL)
>
>  #define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
> +   | HDMI_INT_AUDIO_FIFO_XRUN \
> | HDMI_INT_GENCTRL_PKT \
> | HDMI_INT_NEW_FRAME \
> | HDMI_INT_DLL_LCK \
> @@ -121,6 +130,27 @@
>
>  #define HDMI_STA_SW_RST BIT(1)
>
> +#define HDMI_AUD_CFG_8CH   BIT(0)
> +#define HDMI_AUD_CFG_SPDIF_DIV_2   BIT(1)
> +#define HDMI_AUD_CFG_SPDIF_DIV_3   BIT(2)
> +#define HDMI_AUD_CFG_SPDIF_CLK_DIV_4   (BIT(1) | BIT(2))
> +#define HDMI_AUD_CFG_CTS_CLK_256FS BIT(12)
> +#define HDMI_AUD_CFG_DTS_INVALID   BIT(16)
> +#define HDMI_AUD_CFG_ONE_BIT_INVALID   (BIT(18) | BIT(19) | BIT(20) |  
> BIT(21))
> +#define HDMI_AUD_CFG_CH12_VALIDBIT(28)
> +#define HDMI_AUD_CFG_CH34_VALIDBIT(29)
> +#define HDMI_AUD_CFG_CH56_VALIDBIT(30)
> +#define HDMI_AUD_CFG_CH78_VALIDBIT(31)
> +
> +/* sample flat mask */
> +#define HDMI_SAMPLE_FLAT_NO 0
> +#define HDMI_SAMPLE_FLAT_SP0 BIT(0)
> +#define HDMI_SAMPLE_FLAT_SP1 BIT(1)
> +#define HDMI_SAMPLE_FLAT_SP2 BIT(2)
> +#define HDMI_SAMPLE_FLAT_SP3 BIT(3)
> +#define HDMI_SAMPLE_FLAT_ALL (HDMI_SAMPLE_FLAT_SP0 | HDMI_SAMPLE_FLAT_SP1 |\
> + HDMI_SAMPLE_FLAT_SP2 | HDMI_SAMPLE_FLAT_SP3)
> +
>  #define HDMI_INFOFRAME_HEADER_TYPE(x)(((x) & 0xff) <<  0)
>  #define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
>  #define HDMI_INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16)
> @@ -171,6 +201,10 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
> wake_up_interruptible(&hdmi->wait_event);
> }
>
> +   /* Audio FIFO underrun IRQ */
> +   if (hdmi->irq_status & HDMI_INT_AUDIO_FIFO_XRUN)
> +   DRM_INFO("Warning: audio FIFO underrun occurs!");
> +
> return IRQ_HANDLED;
>  }
>
> @@ -441,26 +475,29 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi 
> *hdmi)
>   */
>  static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
>  {
> -   struct hdmi_audio_infoframe infofame;
> +   struct hdmi_audio_params *audio = &hdmi->audio;
> u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
> -   int ret;
> -
> -   ret = hdmi_audio_infoframe_init(&infofame);
> -   if (ret < 0) {
> -   DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
> -   return ret;
> -   }
> -
> -   infofame.channels = 2;
> -
> -   ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer));

[PATCH] drm: atmel-hlcdc: actually disable scaling when no scaling is required

2016-06-01 Thread Boris Brezillon
The driver is only enabling scaling, but never disabling it, thus, if you
enable the scaling feature once it stays enabled forever.

Signed-off-by: Boris Brezillon 
Reported-by: Alex Vazquez 
Fixes: 1a396789f65a ("drm: add Atmel HLCDC Display Controller support")
Cc: 
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c 
b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index aef3ca8..016c191 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -339,6 +339,8 @@ atmel_hlcdc_plane_update_pos_and_size(struct 
atmel_hlcdc_plane *plane,

atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0x,
 factor_reg);
+   } else {
+   atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0x, 0);
}
 }

-- 
2.7.4



  1   2   >