[Bug 104551] Unable to resume from suspend AMD Radeon HD 6570

2015-09-25 Thread bugzilla-dae...@bugzilla.kernel.org
https://bugzilla.kernel.org/show_bug.cgi?id=104551

--- Comment #6 from Ignacio  ---
Those logs were taken from a Ubuntu 15.04 live USB stick

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


[Bug 91278] Tonga GPU lock/reset fail with Unigine Valley

2015-09-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=91278

--- Comment #10 from Michel Dänzer  ---
Mathias, so you can reliably reproduce the hang by replaying that apitrace?

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


[PATCHv4 3/3] drm: bridge: anx78xx: Add anx78xx driver support by analogix.

2015-09-25 Thread Enric Balletbo i Serra
At the moment it only supports ANX7814.

The ANX7814 is an ultra-low power Full-HD (1080p60) SlimPort transmitter
designed for portable devices.

This driver adds initial support and supports HDMI to DP pass-through mode.

Signed-off-by: Enric Balletbo i Serra 
---
 drivers/gpu/drm/bridge/Kconfig   |2 +
 drivers/gpu/drm/bridge/Makefile  |1 +
 drivers/gpu/drm/bridge/anx78xx/Kconfig   |7 +
 drivers/gpu/drm/bridge/anx78xx/Makefile  |4 +
 drivers/gpu/drm/bridge/anx78xx/anx78xx.h |   41 +
 drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c|  228 ++
 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.c | 3148 ++
 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.h |  214 ++
 drivers/gpu/drm/bridge/anx78xx/slimport_tx_reg.h |  807 ++
 9 files changed, 4452 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/Makefile
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/anx78xx.h
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.c
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.h
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/slimport_tx_reg.h

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 2de52a5..aa6fe12 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -29,4 +29,6 @@ config DRM_PARADE_PS8622
---help---
  Parade eDP-LVDS bridge chip driver.

+source "drivers/gpu/drm/bridge/anx78xx/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index e2eef1c..e5bd38b 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -3,3 +3,4 @@ ccflags-y := -Iinclude/drm
 obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
+obj-$(CONFIG_DRM_ANX78XX) += anx78xx/
diff --git a/drivers/gpu/drm/bridge/anx78xx/Kconfig 
b/drivers/gpu/drm/bridge/anx78xx/Kconfig
new file mode 100644
index 000..08f9c08
--- /dev/null
+++ b/drivers/gpu/drm/bridge/anx78xx/Kconfig
@@ -0,0 +1,7 @@
+config DRM_ANX78XX
+   tristate "Analogix ANX78XX bridge"
+   help
+   ANX78XX is a HD video transmitter chip over micro-USB
+   connector for smartphone device.
+
+
diff --git a/drivers/gpu/drm/bridge/anx78xx/Makefile 
b/drivers/gpu/drm/bridge/anx78xx/Makefile
new file mode 100644
index 000..a843733
--- /dev/null
+++ b/drivers/gpu/drm/bridge/anx78xx/Makefile
@@ -0,0 +1,4 @@
+obj-${CONFIG_DRM_ANX78XX} :=  anx78xx.o
+
+anx78xx-y += anx78xx_main.o
+anx78xx-y += slimport_tx_drv.o
diff --git a/drivers/gpu/drm/bridge/anx78xx/anx78xx.h 
b/drivers/gpu/drm/bridge/anx78xx/anx78xx.h
new file mode 100644
index 000..f62c8e7
--- /dev/null
+++ b/drivers/gpu/drm/bridge/anx78xx/anx78xx.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ *
+ */
+
+#ifndef __ANX78xx_H
+#define __ANX78xx_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct anx78xx_platform_data {
+   struct gpio_desc *gpiod_pd;
+   struct gpio_desc *gpiod_reset;
+   spinlock_t lock;
+};
+
+struct anx78xx {
+   struct i2c_client *client;
+   struct anx78xx_platform_data *pdata;
+   struct delayed_work work;
+   struct workqueue_struct *workqueue;
+   struct mutex lock;
+};
+
+void anx78xx_poweron(struct anx78xx *data);
+void anx78xx_poweroff(struct anx78xx *data);
+
+#endif
diff --git a/drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c 
b/drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c
new file mode 100644
index 000..1e4a87e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright(c) 2015, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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 
+#include 
+#include 
+#include 
+#include 
+#include 

[PATCHv4 2/3] devicetree: Add new ANX7814 SlimPort transmitter binding.

2015-09-25 Thread Enric Balletbo i Serra
The ANX7814 is an ultra-low power Full-HD (1080p60) SlimPort transmitter
designed for portable devices.

You can add support to your board with current binding.

Example:

anx7814: anx7814 at 38 {
compatible = "analogix,anx7814";
reg = <0x38>;
pd-gpios = < 1 GPIO_ACTIVE_HIGH>;
reset-gpios = < 2 GPIO_ACTIVE_HIGH>;
};

Signed-off-by: Enric Balletbo i Serra 
---
 .../devicetree/bindings/video/bridge/anx7814.txt   | 22 ++
 1 file changed, 22 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/bridge/anx7814.txt

diff --git a/Documentation/devicetree/bindings/video/bridge/anx7814.txt 
b/Documentation/devicetree/bindings/video/bridge/anx7814.txt
new file mode 100644
index 000..a8cc746
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/bridge/anx7814.txt
@@ -0,0 +1,22 @@
+Analogix ANX7814 SlimPort (Full-HD Transmitter)
+---
+
+The ANX7814 is an ultra-low power Full-HD (1080p60) SlimPort transmitter
+designed for portable devices.
+
+Required properties:
+
+ - compatible  : "analogix,anx7814"
+ - reg : I2C address of the device
+ - pd-gpios: Which GPIO to use for power down
+ - reset-gpios : Which GPIO to use for reset
+
+Example:
+
+   anx7814: anx7814 at 38 {
+   compatible = "analogix,anx7814";
+   reg = <0x38>;
+   pd-gpios = < 1 GPIO_ACTIVE_HIGH>;
+   reset-gpios = < 2 GPIO_ACTIVE_HIGH>;
+   };
+
-- 
2.1.0



[PATCHv4 1/3] of: Add vendor prefix for Analogix Semiconductor, Inc.

2015-09-25 Thread Enric Balletbo i Serra
Analogix Semiconductor develops analog and mixed-signal devices for digital
media and communications interconnect applications.

Signed-off-by: Enric Balletbo i Serra 
Acked-by: Rob Herring 
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt 
b/Documentation/devicetree/bindings/vendor-prefixes.txt
index ac5f0c3..e914a02 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -22,6 +22,7 @@ ampireAmpire Co., Ltd.
 amsAMS AG
 amstaosAMS-Taos Inc.
 apmApplied Micro Circuits Corporation (APM)
+analogix   Analogix Semiconductor, Inc.
 aptina Aptina Imaging
 arasan Arasan Chip Systems
 armARM Ltd.
-- 
2.1.0



[PATCHv4 0/3] Add initial support for slimport anx78xx

2015-09-25 Thread Enric Balletbo i Serra
Hi all,

This is the fouth version with fixes suggested by Nicolas Boichat and Dan 
Carpenter.

See the changelog below for details.

The following series add initial support for the Slimport ANX7814 transmitter, a
ultra-low power Full-HD (1080p60) transmitter designed for portable device.

The driver was originally created and based from the work of Junhua Xia from
Analogix. This driver is a refactor of the original driver and fixes different
coding style lines, and different errors/warnings reported by checkpatch. Also
there were things that I noticed that we need to change like:

 - Convert the numbered GPIO API to the new descriptor based GPIO API.
 - Review the DT binding
 - Add missing MODULE_DEVICE_TABLE(of, ...);
 - Fix Makefiles and Kconfig to build conditionally.
 - Use SIMPLE_DEV_PM_OPS() instead of the deprecated i2c .suspend and
  .resume callbacks.
 - Move to use managed device resources.
 - Remove dead/unused code.
 - And others ...

Changes since v3:

Nicolas Boichat: 
 - Integrate sp_edid_header_result with sp_check_edid_data
 - Fix loop forever.
 - Use meaningful messages and variable names
 - Replace some 'while' loops and use a for loop.
 - Might be clearer to say >= LINK_6P75G
 - Convert a function to void function because always return 0
 - Remove some magic numbers and refactor sp_tx_pclk_calc
 - Replace sp_read_reg(SP_TX_LINK_BW_SET_REG) for sp_tx_get_link_bw.
 - Mask bits 4:0. Bit 5 has another purpose, and 7:6 are reserved.
 - Use ARRAY_SIZE.
 - Use memset for initialization.
 - Simply condition if (!(c1 & POLLING_EN) || (c & POLLING_ERR))
 - Don not use a temporal variable write the value directly.
 - Fix various typos
 - Return directly PTR_ERR.

Dan Carpenter: 
 - Refactor while loop removing the earlier condition and do while (--c) instead
 - Simplify double negative and fix alignment
 - Remove the superflous casts to u16 and parens
 - Remove debug printks and use ftrace instead.
 - Flip this condition around and pull the code in one indent level.
 - Fix return value 'ret' that should be an int. It causes a signedness bug 
later.
 - Use better style for devm_kzalloc
 - Get rid of AUX_*.  They aren't used much and we could easily use normal 
error codes instead.

Enric Balletbo
 - Fix errors reported by scripts/checkpatch.pl --strict --subjective
 - Remove XTAL_CLK_M10 XTAL_CLK definitions
 - replace ulong for unsigned long
 - remove some magic numbers and refactor sp_tx_enable_audio_output
 - remove some magic numbers and refactor sp_tx_phy_auto_test

Changes since v2 (requested by Daniel Kurtz):
 - clean up the typos, and little nits requested by Dan.
 - move to the drm/bridge directory
 - rename the files, variables, types, etc. to anx78xx
 - plumb through the context struct to all functions that act on the device
 - use proper messaging (dev_ rather than pr_, _dbg/_err rather than _info)

Changes since v1:
 - As requested by Greg, move from staging to a subsystem.

Best regards,

Enric Balletbo i Serra (3):
  of: Add vendor prefix for Analogix Semiconductor, Inc.
  devicetree: Add new ANX7814 SlimPort transmitter binding.
  drm: bridge: anx78xx: Add anx78xx driver support by analogix.

 .../devicetree/bindings/vendor-prefixes.txt|1 +
 .../devicetree/bindings/video/bridge/anx7814.txt   |   22 +
 drivers/gpu/drm/bridge/Kconfig |2 +
 drivers/gpu/drm/bridge/Makefile|1 +
 drivers/gpu/drm/bridge/anx78xx/Kconfig |7 +
 drivers/gpu/drm/bridge/anx78xx/Makefile|4 +
 drivers/gpu/drm/bridge/anx78xx/anx78xx.h   |   41 +
 drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c  |  228 ++
 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.c   | 3148 
 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.h   |  214 ++
 drivers/gpu/drm/bridge/anx78xx/slimport_tx_reg.h   |  807 +
 11 files changed, 4475 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/bridge/anx7814.txt
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/Kconfig
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/Makefile
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/anx78xx.h
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/anx78xx_main.c
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.c
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/slimport_tx_drv.h
 create mode 100644 drivers/gpu/drm/bridge/anx78xx/slimport_tx_reg.h

-- 
2.1.0



No more new fbdev drivers, please

2015-09-25 Thread Daniel Vetter
On Fri, Sep 25, 2015 at 04:09:46PM +0300, Tomi Valkeinen wrote:
> 
> 
> On 25/09/15 13:41, Kamil Lulko wrote:
> > Hi,
> > 
> >> fbdev is (more or less) maintained, but it's a deprecated framework. All
> >> new Linux display drivers should be done on DRM.
> > 
> > What about no-mmu platforms? DRM has a big fat MMU dependency in the
> > kconfig, is there a way to write DRM driver for such devices?
> 
> I guess not.
> 
> Then again, I don't see why DRM would have a hard dependency to MMU, if
> the work is done to make DRM work optionally without MMU. How much work
> that is, I have no idea.

We have plenty drivers in drm without hw mmu, and yeah there's probably no
reason at all why the drm subsystem has a hard depency on cpu MMUs. Might
be some #ifdef fallout that needs to be done, but there shouldn't be
anything fundamental. Maybe the old dri1 days code has something, but
that's all historical cruft anyway.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH] fbdev: put module after running driver callback

2015-09-25 Thread David Herrmann
Hi

On Thu, Sep 24, 2015 at 1:24 PM, Tomi Valkeinen  
wrote:
>
> On 11/09/15 19:10, David Herrmann wrote:
>> Currently, for each open() on an fbdev device, we pin the underlying
>> fbdev device and driver module. On close(), we release both. This
>> guarantees that the fbdev object stays around until the last FD is
>> released (even though it might be unregistered already).
>>
>> However, currently we call module_put() *before* calling put_fb_info().
>> This has the side-effect that the driver module might be unloaded before
>> put_fb_info() calls into fbinfo->fbops->fb_destroy().
>>
>> Fix this by keeping the module pinned until after we release our fbdev
>> reference. Note that register_framebuffer() and unregister_framebuffer()
>> are special as we require the driver to unregister device before
>> unloading. Hence, they don't need to pin the module. However, all open
>> handlers *have to*.
>>
>> Signed-off-by: David Herrmann 
>> ---
>>  drivers/video/fbdev/core/fbmem.c | 5 -
>>  1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/video/fbdev/core/fbmem.c 
>> b/drivers/video/fbdev/core/fbmem.c
>> index 0705d88..4e78731 100644
>> --- a/drivers/video/fbdev/core/fbmem.c
>> +++ b/drivers/video/fbdev/core/fbmem.c
>> @@ -1482,13 +1482,16 @@ __acquires(>lock)
>>  __releases(>lock)
>>  {
>>   struct fb_info * const info = file->private_data;
>> + struct module *owner;
>>
>>   mutex_lock(>lock);
>>   if (info->fbops->fb_release)
>>   info->fbops->fb_release(info,1);
>> - module_put(info->fbops->owner);
>> + owner = info->fbops->owner;
>>   mutex_unlock(>lock);
>> +
>>   put_fb_info(info);
>> + module_put(owner);
>>   return 0;
>>  }
>
> Looking at fb_open(), in error case it calls module_put() followed by
> put_fb_info(). Is that broken also?

Indeed, same issue here. I will send v2 which fixes both.

> Have you hit this bug, or did you just find it by looking at the code?
> In other words, is this for 4.3 fixes, or 4.4. I guess the user needs to
> unload the module just at the right time to trigger this bug.

Theoretical issue. It's almost impossible to trigger, as module
unloading takes ages compared to the time required to release the
fbinfo.

Thanks
David


[PATCH 09/14] drm/exynos: remove call to drm_gem_free_mmap_offset()

2015-09-25 Thread Inki Dae
On 2015년 09월 24일 10:01, Joonyoung Shim wrote:
> Hi Inki,
> 
> On 08/17/2015 06:03 PM, Inki Dae wrote:
>> On 2015년 08월 17일 17:17, Joonyoung Shim wrote:
>>> On 08/17/2015 04:52 PM, Inki Dae wrote:
 On 2015년 08월 17일 14:29, Joonyoung Shim wrote:
> On 08/16/2015 02:07 PM, Inki Dae wrote:
>> On 2015년 07월 28일 17:53, Joonyoung Shim wrote:
>>> The drm_gem_object_release() function already performs this cleanup,
>>> so there is no reason to do it explicitly.
>>>
>>> Signed-off-by: Joonyoung Shim 
>>> ---
>>>  drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 ---
>>>  1 file changed, 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c 
>>> b/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>> index c76aa8a..ab7d029 100644
>>> --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
>>> @@ -100,8 +100,6 @@ out:
>>> exynos_drm_fini_buf(obj->dev, buf);
>>> exynos_gem_obj->buffer = NULL;
>>>  
>>> -   drm_gem_free_mmap_offset(obj);
>>> -
>>> /* release file pointer to gem object. */
>>> drm_gem_object_release(obj);
>>>  
>>> @@ -600,7 +598,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct 
>>> vm_area_struct *vma)
>>>  
>>>  err_close_vm:
>>> drm_gem_vm_close(vma);
>>> -   drm_gem_free_mmap_offset(obj);
>>
>> Without previous patch, drm_gem_free_mmap_offset is required. I guess
>> the reason you removed above line is that you thought
>> drm_gem_object_release function would be called by drm_gem_vm_close
>> function which drops a reference of the gem object.
>>
>> However, drm_gem_vm_close should be a pair with drm_gem_vm_open
>> function. These will be called whenever a process opens or closes the
>> VMA. So the reference count of the gem object had already been taken by
>> open operation when a new reference to the VMA had been created.
>>
>
> This changes is not related with drm_gem_vm_close and prior patch. Why
> should free mmap offset when mmap operation is failed? The mmap offset
> can be used repeatedly.

 Isn't vm space of vm manager still used even if any user-space process
 doesn't use the region? And if mmap is failed, then the user-space
 process will be terminated. Do you think it can be re-tried? However,
 mmap system call never return -EAGAIN. Is it reasonable to you? I cannot
 understand how the mmap offset can be re-used. So can you show me some
 example?

>>>
>>> Currently, mmap offset of exynos-drm gem is made by 
>>> DRM_IOCTL_MODE_MAP_DUMB ioctl and mmap() ioctl just uses the mmap 
>>> offset. User will use same mmap offset about same gem. It's why mmap
>>> offset made by DRM_IOCTL_MODE_MAP_DUMB ioctl is unnecessary, it's just
>>> enough to make mmap offset from when gem is create. You can get a
>>> reference from drm_gem_cma_helper.c file.
>>
>> Hmm... It's not that the mmap offset can be re-used or not. It's that
>> the mmap offset should be released or not when mmap failed. As your
>> original comment, the call of drm_gem_free_mmap_offset() is unnecessary
>> if mmap offset is created when gem creation because the mmap offset is
>> removed by drm_gem_object_release() when gem is destroyed - gem should
>> also be released when mmap failed.
>>
>> Ok, let's create mmap offset at gem creation and remove it gem
>> releasing. Will merge these two patches.
>>
> 
> I can't find them from your git. Could you merge them?

Oops, sorry. Merged.

Thanks,
Inki Dae

> 
> Thanks.
> 



[PATCH 1/6] driver-core: platform: Provide helpers for multi-driver modules

2015-09-25 Thread Greg Kroah-Hartman
On Fri, Sep 25, 2015 at 04:29:44PM +0200, Thierry Reding wrote:
> On Thu, Sep 24, 2015 at 07:02:36PM +0200, Thierry Reding wrote:
> > From: Thierry Reding 
> > 
> > Some modules register several sub-drivers. Provide a helper that makes
> > it easy to register and unregister a list of sub-drivers, as well as
> > unwind properly on error.
> > 
> > Cc: Greg Kroah-Hartman 
> > Signed-off-by: Thierry Reding 
> > ---
> >  Documentation/driver-model/platform.txt | 11 ++
> >  drivers/base/platform.c | 60 
> > +
> >  include/linux/platform_device.h |  5 +++
> >  3 files changed, 76 insertions(+)
> 
> Hi Greg,
> 
> In addition to patches 2-6 I have about two dozen patches across various
> subsystems that make use of this. I didn't want to spam everyone with
> all of them before you've given an indication about what you think about
> this patch.
> 
> The diffstat of the conversions I did is this:
> 
>   drivers/crypto/n2_core.c | 17 +++--
>   drivers/edac/mpc85xx_edac.c  | 16 
>   drivers/edac/mv64x60_edac.c  | 39 
> +++
>   drivers/gpio/gpio-mpc5200.c  | 17 +++--
>   drivers/gpu/drm/armada/armada_drv.c  | 16 +++-
>   drivers/gpu/drm/exynos/exynos_drm_drv.c  | 42 
> --
>   drivers/gpu/drm/omapdrm/omap_drv.c   | 24 
> +++-
>   drivers/gpu/host1x/dev.c | 17 +++--
>   drivers/input/misc/sparcspkr.c   | 18 +++---
>   drivers/iommu/msm_iommu_dev.c| 25 
> +++--
>   drivers/leds/leds-sunfire.c  | 23 
> +++
>   drivers/mfd/sta2x11-mfd.c| 36 
> ++--
>   drivers/net/ethernet/adi/bfin_mac.c  | 14 +++---
>   drivers/net/ethernet/broadcom/bcm63xx_enet.c | 28 
> 
>   drivers/net/ethernet/freescale/fec_mpc52xx.c | 22 +-
>   drivers/net/ethernet/marvell/mv643xx_eth.c   | 19 +++
>   drivers/pinctrl/pinctrl-adi2.c   | 24 
> 
>   drivers/pinctrl/pinctrl-at91.c   | 14 +++---
>   drivers/regulator/lp8788-ldo.c   | 16 +++-
>   drivers/regulator/wm831x-dcdc.c  | 31 
> +--
>   drivers/regulator/wm831x-ldo.c   | 27 
> ---
>   drivers/tty/serial/mpsc.c| 19 ---
>   drivers/usb/gadget/udc/dummy_hcd.c   | 17 -
>   drivers/video/fbdev/s3c2410fb.c  | 15 +++
>   24 files changed, 186 insertions(+), 350 deletions(-)
> 
> That's not too thrilling but in many cases this fixes a potential bug if
> a driver fails to register and the code doesn't properly unregister any
> previously registered drivers.
> 
> Anyway, if you think this is worth merging, how would you like to go
> about it? Do you want Acked-bys on all the patches and merge them
> through your tree? Perhaps the easiest would be to just merge this patch
> and then take the other patches through the maintainer trees after the
> core patch has landed?

The last thing is the easiest, but you have to wait a release cycle for
that.  Or I can take the whole series if you want to, just cc: the
proper subsystem maintainers when you send them.  It's up to you.

thanks,

greg k-h


[RFC 3/5] ASoC: codec: hdmi drm codec driver

2015-09-25 Thread Arnaud Pouliquen
Hello Jyri,

Yes using or not DRM bridge we should be able to have a common 
implementation

Please find,my answer belows

BR,
Arnaud

On 09/25/2015 04:11 PM, Jyri Sarha wrote:
> Despite my earlier comment this implementation and the related HW is
> quite similar in all significant aspects to the patch set posted couple
> of days ago [1] for Beaglebone-Black HDMI audio.
>
> [1] http://permalink.gmane.org/gmane.linux.alsa.devel/144144
yes i trying to align my dev on it. to match with your development.
Aim for me is to reuse it and adapt it using a DRM bridge interface.
i hope to provide a V2 next week.
>
> I have not yet gotten to bottom of drm-side audio bride part, but I am
> working on it. Bellow is couple of early comments to the ASoC part.
>
> Best regards,
> Jyri
>
> On 09/21/15 16:19, Arnaud Pouliquen wrote:
>> +
>> +static int st_hdmi_dai_probe(struct snd_soc_dai *dai)
>> +{
>> +struct hdmi_drm_dai_data *priv;
>> +
>> +dev_err(dai->dev, "%s: enter\n", __func__);
>> +priv = devm_kzalloc(dai->dev, sizeof(*priv), GFP_KERNEL);
>> +
>> +priv->bridge = of_drm_find_bridge(dai->dev->of_node);
>> +
>> +dev_err(dai->dev, "%s: bridge %p\n", __func__, priv->bridge);
>> +
>> +snd_soc_dai_set_drvdata(dai, priv);
>> +
>
> The call above overwrites the private data pointer of the drivers that
> registering the codec. This hardly works in general.
>
> A separate platform driver - with this already merged patch [2] - that I
> use with my patch-set solves this issue quite nicely.
>
> [2] http://lists.freedesktop.org/archives/dri-devel/2015-May/083517.html
Yes same dev,(but no crash...?).i need to define sub node.
>> +return 0;
>> +}here are several important callbacks missing here
>> +
>> +static const struct snd_soc_dai_ops hdmi_drm_codec_ops = {
>> +.prepare =  hdmi_drm_dai_prepare,
>> +.trigger = hdmi_drm_dai_trigger,
>> +};
>
>
> At least set_daifmt() and hw_params() callbacks should be defined before
> this could be generally usable. HDMI encoders do not usually support too
> many daifmts, but the driver should be able the check that the selected
> format is supported. But as you said this not complete code yet.
I'm trying to match codec ops with following DRM audio bridge ops,
that is similar to the existing drm_bridge_funcs structure.
struct drm_audio_bridge_funcs {
void (*disable)(struct drm_bridge *bridge);
void (*post_disable)(struct drm_bridge *bridge);
void (*pre_enable)(struct drm_bridge *bridge);
void (*enable)(struct drm_bridge *bridge);
int  (*mode_set)(struct drm_bridge *bridge,
struct hdmi_audio_mode *mode);
uint8_t *(*mode_get)(struct drm_bridge *bridge); /*return eld*/
};
audio parameters should be part of struct hdmi_audio_mode that contains 
audio configurations ( info frame,iec, format, clk...)




[PATCH 3/5] drm/amd: add ACP driver support

2015-09-25 Thread Alex Deucher
From: Maruthi Bayyavarapu 

This adds the ACP (Audio CoProcessor) IP driver and wires
it up to the amdgpu driver.  The ACP block provides the DMA
engine for i2s based ALSA driver. This is required for audio
on APUs that utilize an i2s codec.

Reviewed-by: Jammy Zhou 
Reviewed-by: Maruthi Bayyavarapu 
Reviewed-by: Alex Deucher 
Reviewed-by: Murali Krishna Vemuri 
Signed-off-by: Maruthi Bayyavarapu 
Signed-off-by: Chunming Zhou 
Signed-off-by: Alex Deucher 
---

v2: integrate i2s/az check patch
v3: s/amd_acp/amdgpu_acp/
v4: update copyright notice
v5: squash multiple patches, convert to mfd
v6: major changes as below :
1. Pass ACP register base to DMA and dw i2s drivers
   as IORESOURCE_MEM resources.
2. add dw i2s as a new mfd cell.
v7: remove dw i2s slave setting from platform data.  this
   is determined in the dw driver directly now.

 drivers/gpu/drm/Kconfig  |   2 +
 drivers/gpu/drm/amd/acp/Kconfig  |  10 +
 drivers/gpu/drm/amd/acp/Makefile |   9 +
 drivers/gpu/drm/amd/acp/acp_hw.c | 127 +
 drivers/gpu/drm/amd/acp/include/acp_gfx_if.h |  49 +
 drivers/gpu/drm/amd/amdgpu/Makefile  |  13 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h  |  12 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c  | 269 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h  |  41 
 drivers/gpu/drm/amd/amdgpu/vi.c  |  12 ++
 drivers/gpu/drm/amd/include/amd_shared.h |   1 +
 include/linux/mfd/amd_acp.h  |  43 +
 12 files changed, 587 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/acp/Kconfig
 create mode 100644 drivers/gpu/drm/amd/acp/Makefile
 create mode 100644 drivers/gpu/drm/amd/acp/acp_hw.c
 create mode 100644 drivers/gpu/drm/amd/acp/include/acp_gfx_if.h
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
 create mode 100644 include/linux/mfd/amd_acp.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1a0a8df..330e9fb 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -161,6 +161,8 @@ config DRM_AMDGPU

 source "drivers/gpu/drm/amd/amdgpu/Kconfig"

+source "drivers/gpu/drm/amd/acp/Kconfig"
+
 source "drivers/gpu/drm/nouveau/Kconfig"

 config DRM_I810
diff --git a/drivers/gpu/drm/amd/acp/Kconfig b/drivers/gpu/drm/amd/acp/Kconfig
new file mode 100644
index 000..1de4fe7
--- /dev/null
+++ b/drivers/gpu/drm/amd/acp/Kconfig
@@ -0,0 +1,10 @@
+menu "ACP Configuration"
+
+config DRM_AMD_ACP
+   bool "Enable ACP IP support"
+   default y
+   depends on MFD_CORE
+   help
+   Choose this option to enable ACP IP support for AMD SOCs.
+
+endmenu
diff --git a/drivers/gpu/drm/amd/acp/Makefile b/drivers/gpu/drm/amd/acp/Makefile
new file mode 100644
index 000..c8c3303
--- /dev/null
+++ b/drivers/gpu/drm/amd/acp/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the ACP, which is a sub-component
+# of AMDSOC/AMDGPU drm driver.
+# It provides the HW control for ACP related functionalities.
+
+ccflags-y += -Idrivers/gpu/drm/amd/include/asic_reg/acp
+subdir-ccflags-y += -I$(AMDACPPATH)/ -I$(AMDACPPATH)/include
+
+AMD_ACP_FILES := $(AMDACPPATH)/acp_hw.o
diff --git a/drivers/gpu/drm/amd/acp/acp_hw.c b/drivers/gpu/drm/amd/acp/acp_hw.c
new file mode 100644
index 000..55220c3
--- /dev/null
+++ b/drivers/gpu/drm/amd/acp/acp_hw.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "acp_gfx_if.h"
+
+#define ACP_MODE_I2S   0
+#define ACP_MODE_AZ1
+
+#define VISLANDS30_IV_SRCID_ACP 0x00a2
+#define mmACP_AZALIA_I2S_SELECT 0x51d4
+
+static int irq_set_source(void *private_data, unsigned src_id, unsigned type,
+   

[PATCH 2/5] ASoC : dwc : support dw i2s in AMD platform

2015-09-25 Thread Alex Deucher
From: Maruthi Srinivas Bayyavarapu 

Vendor specific quirk was added to:
1. Support AMD platform which has two dwc controllers with different
   base address for playback and capture. Also, I2S_COMP_PARAM_*
   registers offsets differed.
2. Resume audio which was active before system suspend.
   After 'resume', dwc need to be reconfigured with params
   configured during 'hw_params' callback. With this, audio usecase
   continues from where it got stopped because of 'suspend'.

Signed-off-by: Maruthi Bayyavarapu 
Signed-off-by: Alex Deucher 
---

v2: Copy quirks from platform data to local struct since platform data
may not be available in some use cases.

 include/sound/designware_i2s.h |   3 +
 sound/soc/dwc/designware_i2s.c | 190 ++---
 2 files changed, 126 insertions(+), 67 deletions(-)

diff --git a/include/sound/designware_i2s.h b/include/sound/designware_i2s.h
index 8966ba7..7e8094a 100644
--- a/include/sound/designware_i2s.h
+++ b/include/sound/designware_i2s.h
@@ -44,6 +44,9 @@ struct i2s_platform_data {
int channel;
u32 snd_fmts;
u32 snd_rates;
+   #define DW_I2S_VENDOR_AMD (1 << 0)
+   unsigned int quirks;
+

void *play_dma_data;
void *capture_dma_data;
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index 3a52f82..dce1e4a 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -89,11 +89,15 @@ union dw_i2s_snd_dma_data {
 };

 struct dw_i2s_dev {
-   void __iomem *i2s_base;
+   void __iomem *i2s_pbase;
+   void __iomem *i2s_cbase;
struct clk *clk;
int active;
unsigned int capability;
+   unsigned int quirks;
struct device *dev;
+   u32 ccr;
+   u32 xfer_resolution;

/* data related to DMA transfers b/w i2s and DMAC */
union dw_i2s_snd_dma_data play_dma_data;
@@ -118,10 +122,10 @@ static inline void i2s_disable_channels(struct dw_i2s_dev 
*dev, u32 stream)

if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
for (i = 0; i < 4; i++)
-   i2s_write_reg(dev->i2s_base, TER(i), 0);
+   i2s_write_reg(dev->i2s_pbase, TER(i), 0);
} else {
for (i = 0; i < 4; i++)
-   i2s_write_reg(dev->i2s_base, RER(i), 0);
+   i2s_write_reg(dev->i2s_cbase, RER(i), 0);
}
 }

@@ -131,25 +135,25 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, 
u32 stream)

if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
for (i = 0; i < 4; i++)
-   i2s_write_reg(dev->i2s_base, TOR(i), 0);
+   i2s_write_reg(dev->i2s_pbase, TOR(i), 0);
} else {
for (i = 0; i < 4; i++)
-   i2s_write_reg(dev->i2s_base, ROR(i), 0);
+   i2s_write_reg(dev->i2s_cbase, ROR(i), 0);
}
 }

 static void i2s_start(struct dw_i2s_dev *dev,
  struct snd_pcm_substream *substream)
 {
-
-   i2s_write_reg(dev->i2s_base, IER, 1);
-
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   i2s_write_reg(dev->i2s_base, ITER, 1);
-   else
-   i2s_write_reg(dev->i2s_base, IRER, 1);
-
-   i2s_write_reg(dev->i2s_base, CER, 1);
+   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+   i2s_write_reg(dev->i2s_pbase, IER, 1);
+   i2s_write_reg(dev->i2s_pbase, ITER, 1);
+   i2s_write_reg(dev->i2s_pbase, CER, 1);
+   } else {
+   i2s_write_reg(dev->i2s_cbase, IER, 1);
+   i2s_write_reg(dev->i2s_cbase, IRER, 1);
+   i2s_write_reg(dev->i2s_cbase, CER, 1);
+   }
 }

 static void i2s_stop(struct dw_i2s_dev *dev,
@@ -159,24 +163,36 @@ static void i2s_stop(struct dw_i2s_dev *dev,

i2s_clear_irqs(dev, substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   i2s_write_reg(dev->i2s_base, ITER, 0);
-
+   i2s_write_reg(dev->i2s_pbase, ITER, 0);
for (i = 0; i < 4; i++) {
-   irq = i2s_read_reg(dev->i2s_base, IMR(i));
-   i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30);
+   irq = i2s_read_reg(dev->i2s_pbase, IMR(i));
+   i2s_write_reg(dev->i2s_pbase, IMR(i),
+   irq | 0x30);
}
} else {
-   i2s_write_reg(dev->i2s_base, IRER, 0);
+   i2s_write_reg(dev->i2s_cbase, IRER, 0);

for (i = 0; i < 4; i++) {
-   irq = i2s_read_reg(dev->i2s_base, IMR(i));
-   i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03);
+   irq = i2s_read_reg(dev->i2s_cbase, IMR(i));
+   i2s_write_reg(dev->i2s_cbase, IMR(i),
+ 

[PATCH 1/5] ASoC : dwc : support dw i2s in slave mode

2015-09-25 Thread Alex Deucher
From: Maruthi Srinivas Bayyavarapu 

dw i2s controller can work in slave mode, codec being master.
dw i2s is made to support master/slave operation, by reading dwc
register.

Signed-off-by: Maruthi Bayyavarapu 
Signed-off-by: Alex Deucher 
---

v2: check register to determine master/slave mode

 include/sound/designware_i2s.h |  2 +
 sound/soc/dwc/designware_i2s.c | 92 +-
 2 files changed, 57 insertions(+), 37 deletions(-)

diff --git a/include/sound/designware_i2s.h b/include/sound/designware_i2s.h
index 3a8fca9..8966ba7 100644
--- a/include/sound/designware_i2s.h
+++ b/include/sound/designware_i2s.h
@@ -38,6 +38,8 @@ struct i2s_clk_config_data {
 struct i2s_platform_data {
#define DWC_I2S_PLAY(1 << 0)
#define DWC_I2S_RECORD  (1 << 1)
+   #define DW_I2S_SLAVE(1 << 2)
+   #define DW_I2S_MASTER   (1 << 3)
unsigned int cap;
int channel;
u32 snd_fmts;
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index a3e97b4..3a52f82 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -273,23 +273,25 @@ static int dw_i2s_hw_params(struct snd_pcm_substream 
*substream,

config->sample_rate = params_rate(params);

-   if (dev->i2s_clk_cfg) {
-   ret = dev->i2s_clk_cfg(config);
-   if (ret < 0) {
-   dev_err(dev->dev, "runtime audio clk config fail\n");
-   return ret;
-   }
-   } else {
-   u32 bitclk = config->sample_rate * config->data_width * 2;
-
-   ret = clk_set_rate(dev->clk, bitclk);
-   if (ret) {
-   dev_err(dev->dev, "Can't set I2S clock rate: %d\n",
-   ret);
-   return ret;
+   if (dev->capability & DW_I2S_MASTER) {
+   if (dev->i2s_clk_cfg) {
+   ret = dev->i2s_clk_cfg(config);
+   if (ret < 0) {
+   dev_err(dev->dev, "runtime audio clk config 
fail\n");
+   return ret;
+   }
+   } else {
+   u32 bitclk = config->sample_rate *
+   config->data_width * 2;
+
+   ret = clk_set_rate(dev->clk, bitclk);
+   if (ret) {
+   dev_err(dev->dev, "Can't set I2S clock rate: 
%d\n",
+   ret);
+   return ret;
+   }
}
}
-
return 0;
 }

@@ -357,7 +359,8 @@ static int dw_i2s_suspend(struct snd_soc_dai *dai)
 {
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);

-   clk_disable(dev->clk);
+   if (dev->capability & DW_I2S_MASTER)
+   clk_disable(dev->clk);
return 0;
 }

@@ -365,7 +368,8 @@ static int dw_i2s_resume(struct snd_soc_dai *dai)
 {
struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);

-   clk_enable(dev->clk);
+   if (dev->capability & DW_I2S_MASTER)
+   clk_enable(dev->clk);
return 0;
 }

@@ -443,6 +447,14 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
dw_i2s_dai->capture.rates = rates;
}

+   if (COMP1_MODE_EN(comp1)) {
+   dev_dbg(dev->dev, "designware: i2s master mode supported\n");
+   dev->capability |= DW_I2S_MASTER;
+   } else {
+   dev_dbg(dev->dev, "designware: i2s slave mode supported\n");
+   dev->capability |= DW_I2S_SLAVE;
+   }
+
return 0;
 }

@@ -529,6 +541,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
struct resource *res;
int ret;
struct snd_soc_dai_driver *dw_i2s_dai;
+   const char *clk_id;

dev = devm_kzalloc(>dev, sizeof(*dev), GFP_KERNEL);
if (!dev) {
@@ -550,32 +563,35 @@ static int dw_i2s_probe(struct platform_device *pdev)
return PTR_ERR(dev->i2s_base);

dev->dev = >dev;
+
if (pdata) {
+   dev->capability = pdata->cap;
+   clk_id = NULL;
ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
-   if (ret < 0)
-   return ret;
+   } else {
+   clk_id = "i2sclk";
+   ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res);
+   }
+   if (ret < 0)
+   return ret;

-   dev->capability = pdata->cap;
-   dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
-   if (!dev->i2s_clk_cfg) {
-   dev_err(>dev, "no clock configure method\n");
-   return -ENODEV;
+   if (dev->capability & DW_I2S_MASTER) {
+   if (pdata) {
+   dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
+   

[PATCH 0/5] Add ASoC support for AMD APUs [v4]

2015-09-25 Thread Alex Deucher
This patch set implements support for i2s audio and new AMD GPUs.
The i2s codec is fed by a DMA engine on the GPU.  To handle this
we create mfd cells which we hang the i2s codec and DMA engine on.
Because of this, this patch set covers two subsystems: drm and alsa.
The drm patches add support for the ACP hw block which provides the
DMA engine for the i2s codec.  The alsa patches add the ASoC driver
for the i2s codec.  Since the alsa changes depend on the drm changes
in this patch set as well as some other drm changes queued for 4.3,
I'd like to take the alsa patches in via the drm tree.

V2 changes:
- Use the MFD subsystem rather than adding our own bus
- Squash all sub-feature patches together
- fix comments mentioned in previous review

V3 changes:
- Update the designware driver to handle slave mode, amd specific
  features
- Use the designware driver directly for i2s
- Move the DMA handling from the GPU driver into the AMD ASoC
  driver
- Change the license on the ASoC driver to GPL

V4 changes:
- get the master vs slave mode for the designware codec from registers
- copy designware quirks from platform data in local struct

Patch 4 adds the register headers for the ACP block which is a
pretty big patch so I've excluded it from email.  The entire patch
set can be viewed here:
http://cgit.freedesktop.org/~agd5f/linux/log/?h=acp-upstream4

Thanks,

Alex

Maruthi Bayyavarapu (1):
  drm/amd: add ACP driver support

Maruthi Srinivas Bayyavarapu (4):
  ASoC : dwc : support dw i2s in slave mode
  ASoC : dwc : support dw i2s in AMD platform
  ASoC : AMD : add ACP 2.2 register headers
  ASoC: AMD: add AMD ASoC ACP-I2S driver

 drivers/gpu/drm/Kconfig  |2 +
 drivers/gpu/drm/amd/acp/Kconfig  |   10 +
 drivers/gpu/drm/amd/acp/Makefile |9 +
 drivers/gpu/drm/amd/acp/acp_hw.c |  127 ++
 drivers/gpu/drm/amd/acp/include/acp_gfx_if.h |   49 +
 drivers/gpu/drm/amd/amdgpu/Makefile  |   13 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h  |   12 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c  |  269 +++
 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h  |   41 +
 drivers/gpu/drm/amd/amdgpu/vi.c  |   12 +
 drivers/gpu/drm/amd/include/amd_shared.h |1 +
 include/linux/mfd/amd_acp.h  |   43 +
 include/sound/designware_i2s.h   |5 +
 sound/soc/Kconfig|1 +
 sound/soc/Makefile   |1 +
 sound/soc/amd/Kconfig|4 +
 sound/soc/amd/Makefile   |3 +
 sound/soc/amd/acp-pcm-dma.c  |  518 ++
 sound/soc/amd/acp.c  |  736 +
 sound/soc/amd/acp.h  |  147 ++
 sound/soc/amd/include/acp_2_2_d.h|  609 +++
 sound/soc/amd/include/acp_2_2_enum.h | 1068 
 sound/soc/amd/include/acp_2_2_sh_mask.h  | 2292 ++
 sound/soc/dwc/designware_i2s.c   |  276 ++--
 24 files changed, 6146 insertions(+), 102 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/acp/Kconfig
 create mode 100644 drivers/gpu/drm/amd/acp/Makefile
 create mode 100644 drivers/gpu/drm/amd/acp/acp_hw.c
 create mode 100644 drivers/gpu/drm/amd/acp/include/acp_gfx_if.h
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
 create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
 create mode 100644 include/linux/mfd/amd_acp.h
 create mode 100644 sound/soc/amd/Kconfig
 create mode 100644 sound/soc/amd/Makefile
 create mode 100644 sound/soc/amd/acp-pcm-dma.c
 create mode 100644 sound/soc/amd/acp.c
 create mode 100644 sound/soc/amd/acp.h
 create mode 100644 sound/soc/amd/include/acp_2_2_d.h
 create mode 100644 sound/soc/amd/include/acp_2_2_enum.h
 create mode 100644 sound/soc/amd/include/acp_2_2_sh_mask.h

-- 
1.8.3.1



[Bug 91278] Tonga GPU lock/reset fail with Unigine Valley

2015-09-25 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=91278

--- Comment #9 from Mathias Tillman  ---
Created attachment 118448
  --> https://bugs.freedesktop.org/attachment.cgi?id=118448=edit
apitrace of hang

Not exactly sure how useful it is, but I have attached an excerpt of an
apitrace of the unigine valley demo. I had to cut out most of it, due to the
size of it - I've run it several times, and the size has always been >500MB.
The last thing in the trace was always glXSwapBuffers, so the excerpt consists
of the contents between the last and the next to last glXSwapBuffers lines.

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


[PATCH v2] driver-core: platform: Provide helpers for multi-driver modules

2015-09-25 Thread Thierry Reding
From: Thierry Reding 

Some modules register several sub-drivers. Provide a helper that makes
it easy to register and unregister a list of sub-drivers, as well as
unwind properly on error.

Cc: Greg Kroah-Hartman 
Signed-off-by: Thierry Reding 
---
Changes in v2:
- properly pass around the owner module

 Documentation/driver-model/platform.txt | 14 
 drivers/base/platform.c | 61 +
 include/linux/platform_device.h |  8 +
 3 files changed, 83 insertions(+)

diff --git a/Documentation/driver-model/platform.txt 
b/Documentation/driver-model/platform.txt
index 07795ec51cde..e456696cfef2 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -63,6 +63,20 @@ runtime memory footprint:
int platform_driver_probe(struct platform_driver *drv,
  int (*probe)(struct platform_device *))

+Kernel modules can be composed of several platform drivers. The platform core
+provides helpers to register and unregister an array of drivers:
+
+   int __platform_register_drivers(struct platform_driver * const *drivers,
+ unsigned int count, struct module *owner);
+   void platform_unregister_drivers(struct platform_driver * const 
*drivers,
+unsigned int count);
+
+If one of the drivers fails to register, all drivers registered up to that
+point will be unregistered in reverse order. Note that there is a convenience
+macro that passes THIS_MODULE as owner parameter:
+
+   #define platform_register_driver(drivers, count)
+

 Device Enumeration
 ~~
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index f80aaaf9f610..68c58c43e45a 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -711,6 +711,67 @@ err_out:
 }
 EXPORT_SYMBOL_GPL(__platform_create_bundle);

+/**
+ * __platform_register_drivers - register an array of platform drivers
+ * @drivers: an array of drivers to register
+ * @count: the number of drivers to register
+ * @owner: module owning the drivers
+ *
+ * Registers platform drivers specified by an array. On failure to register a
+ * driver, all previously registered drivers will be unregistered. Callers of
+ * this API should use platform_unregister_drivers() to unregister drivers in
+ * the reverse order.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int __platform_register_drivers(struct platform_driver * const *drivers,
+   unsigned int count, struct module *owner)
+{
+   unsigned int i;
+   int err;
+
+   for (i = 0; i < count; i++) {
+   pr_debug("registering platform driver %ps\n", drivers[i]);
+
+   err = __platform_driver_register(drivers[i], owner);
+   if (err < 0) {
+   pr_err("failed to register platform driver %ps: %d\n",
+  drivers[i], err);
+   goto error;
+   }
+   }
+
+   return 0;
+
+error:
+   while (i--) {
+   pr_debug("unregistering platform driver %ps\n", drivers[i]);
+   platform_driver_unregister(drivers[i]);
+   }
+
+   return err;
+}
+EXPORT_SYMBOL_GPL(__platform_register_drivers);
+
+/**
+ * platform_unregister_drivers - unregister an array of platform drivers
+ * @drivers: an array of drivers to unregister
+ * @count: the number of drivers to unregister
+ *
+ * Unegisters platform drivers specified by an array. This is typically used
+ * to complement an earlier call to platform_register_drivers(). Drivers are
+ * unregistered in the reverse order in which they were registered.
+ */
+void platform_unregister_drivers(struct platform_driver * const *drivers,
+unsigned int count)
+{
+   while (count--) {
+   pr_debug("unregistering platform driver %ps\n", drivers[count]);
+   platform_driver_unregister(drivers[count]);
+   }
+}
+EXPORT_SYMBOL_GPL(platform_unregister_drivers);
+
 /* modalias support enables more hands-off userspace setup:
  * (a) environment variable lets new-style hotplug events work once system is
  * fully running:  "modprobe $MODALIAS"
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index bba08f44cc97..dc777be5f2e1 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -270,6 +270,14 @@ extern struct platform_device *__platform_create_bundle(
struct resource *res, unsigned int n_res,
const void *data, size_t size, struct module *module);

+int __platform_register_drivers(struct platform_driver * const *drivers,
+   unsigned int count, struct module *owner);
+void platform_unregister_drivers(struct platform_driver * const *drivers,
+unsigned int count);
+

[PATCH 1/6] driver-core: platform: Provide helpers for multi-driver modules

2015-09-25 Thread Thierry Reding
On Thu, Sep 24, 2015 at 07:02:36PM +0200, Thierry Reding wrote:
> From: Thierry Reding 
> 
> Some modules register several sub-drivers. Provide a helper that makes
> it easy to register and unregister a list of sub-drivers, as well as
> unwind properly on error.
> 
> Cc: Greg Kroah-Hartman 
> Signed-off-by: Thierry Reding 
> ---
>  Documentation/driver-model/platform.txt | 11 ++
>  drivers/base/platform.c | 60 
> +
>  include/linux/platform_device.h |  5 +++
>  3 files changed, 76 insertions(+)
> 
> diff --git a/Documentation/driver-model/platform.txt 
> b/Documentation/driver-model/platform.txt
> index 07795ec51cde..e80468738ba9 100644
> --- a/Documentation/driver-model/platform.txt
> +++ b/Documentation/driver-model/platform.txt
> @@ -63,6 +63,17 @@ runtime memory footprint:
>   int platform_driver_probe(struct platform_driver *drv,
> int (*probe)(struct platform_device *))
>  
> +Kernel modules can be composed of several platform drivers. The platform core
> +provides helpers to register and unregister an array of drivers:
> +
> + int platform_register_drivers(struct platform_driver * const *drivers,
> +   unsigned int count);
> + void platform_unregister_drivers(struct platform_driver * const 
> *drivers,
> +  unsigned int count);
> +
> +If one of the drivers fails to register, all drivers registered up to that
> +point will be unregistered in reverse order.
> +
>  
>  Device Enumeration
>  ~~
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index f80aaaf9f610..b7d7987fda97 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -711,6 +711,66 @@ err_out:
>  }
>  EXPORT_SYMBOL_GPL(__platform_create_bundle);
>  
> +/**
> + * platform_register_drivers - register an array of platform drivers
> + * @drivers: an array of drivers to register
> + * @count: the number of drivers to register
> + *
> + * Registers platform drivers specified by an array. On failure to register a
> + * driver, all previously registered drivers will be unregistered. Callers of
> + * this API should use platform_unregister_drivers() to unregister drivers in
> + * the reverse order.
> + *
> + * Returns: 0 on success or a negative error code on failure.
> + */
> +int platform_register_drivers(struct platform_driver * const *drivers,
> +   unsigned int count)
> +{
> + unsigned int i;
> + int err;
> +
> + for (i = 0; i < count; i++) {
> + pr_debug("registering platform driver %ps\n", drivers[i]);
> +
> + err = platform_driver_register(drivers[i]);

I notice that this is actually doing the wrong thing because the
platform drivers will end up with their .owner field set to NULL because
this file is always built-in. I've fixed it up by passing in a struct
module *owner into __platform_register_drivers() and pass it on to the
__platform_driver_register() function instead.

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


[PATCH 1/6] driver-core: platform: Provide helpers for multi-driver modules

2015-09-25 Thread Thierry Reding
On Fri, Sep 25, 2015 at 01:27:28PM +0300, Jani Nikula wrote:
> On Thu, 24 Sep 2015, Thierry Reding  wrote:
[...]
> > diff --git a/drivers/base/platform.c b/drivers/base/platform.c
[...]
> > +/**
> > + * platform_register_drivers - register an array of platform drivers
> > + * @drivers: an array of drivers to register
> > + * @count: the number of drivers to register
> > + *
> > + * Registers platform drivers specified by an array. On failure to 
> > register a
> > + * driver, all previously registered drivers will be unregistered. Callers 
> > of
> > + * this API should use platform_unregister_drivers() to unregister drivers 
> > in
> > + * the reverse order.
> > + *
> > + * Returns: 0 on success or a negative error code on failure.
> > + */
> > +int platform_register_drivers(struct platform_driver * const *drivers,
> > + unsigned int count)
> > +{
> > +   unsigned int i;
> > +   int err;
> > +
> > +   for (i = 0; i < count; i++) {
> > +   pr_debug("registering platform driver %ps\n", drivers[i]);
> > +
> > +   err = platform_driver_register(drivers[i]);
> > +   if (err < 0) {
> > +   pr_err("failed to register platform driver %ps: %d\n",
> > +  drivers[i], err);
> > +   goto error;
> > +   }
> > +   }
> > +
> > +   return 0;
> > +
> > +error:
> > +   while (i--) {
> > +   pr_debug("unregistering platform driver %ps\n", drivers[i]);
> > +   platform_driver_unregister(drivers[i]);
> > +   }
> 
> This will call platform_driver_unregister() on the driver that failed,
> but not the first driver.
> 
> You should probably make i an int, and use while (--i >= 0).

Actually it won't. I was especially careful and even tested this with
one driver by instrumenting platform_driver_register() to return failure
at various points in the sequence.

This works fine.

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


[RFC 3/5] ASoC: codec: hdmi drm codec driver

2015-09-25 Thread Jyri Sarha
Despite my earlier comment this implementation and the related HW is 
quite similar in all significant aspects to the patch set posted couple 
of days ago [1] for Beaglebone-Black HDMI audio.

[1] http://permalink.gmane.org/gmane.linux.alsa.devel/144144

I have not yet gotten to bottom of drm-side audio bride part, but I am 
working on it. Bellow is couple of early comments to the ASoC part.

Best regards,
Jyri

On 09/21/15 16:19, Arnaud Pouliquen wrote:
> Add a generic codec to interface audio with DRM drivers
>
> Signed-off-by: Arnaud Pouliquen 
> ---
>   include/sound/hdmi_drm.h|  16 ++
>   sound/soc/codecs/Kconfig|   4 ++
>   sound/soc/codecs/Makefile   |   2 +
>   sound/soc/codecs/hdmi_drm.c | 125 
> 
>   4 files changed, 147 insertions(+)
>   create mode 100644 include/sound/hdmi_drm.h
>   create mode 100644 sound/soc/codecs/hdmi_drm.c
>
> diff --git a/include/sound/hdmi_drm.h b/include/sound/hdmi_drm.hhere are 
> several important callbacks missing here
> new file mode 100644
> index 000..0146b88
> --- /dev/null
> +++ b/include/sound/hdmi_drm.h
> @@ -0,0 +1,16 @@
> +/*
> + * Interface for HDMI DRM  codec
> + *
> + * Author: Arnaud Pouliquen 
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef __HDMI_DRM__H__
> +#define __HDMI_DRM__H__
> +
> +int hdmi_drm_codec_register(struct device *dev);
> +void hdmi_drm_codec_unregister(struct device *dev);
> +
> +#endif
> diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
> index 0c9733e..922af30 100644
> --- a/sound/soc/codecs/Kconfig
> +++ b/sound/soc/codecs/Kconfig
> @@ -80,6 +80,7 @@ config SND_SOC_ALL_CODECS
>   select SND_SOC_MC13783 if MFD_MC13XXX
>   select SND_SOC_ML26124 if I2C
>   select SND_SOC_HDMI_CODEC
> + select SND_SOC_HDMI_DRM_CODEC
>   select SND_SOC_PCM1681 if I2C
>   select SND_SOC_PCM1792A if SPI_MASTER
>   select SND_SOC_PCM3008
> @@ -445,6 +446,9 @@ config SND_SOC_DMIC
>   config SND_SOC_HDMI_CODEC
>  tristate "HDMI stub CODEC"
>
> +config SND_SOC_HDMI_DRM_CODEC
> +   tristate "HDMI DRM CODEC"
> +
>   config SND_SOC_ES8328
>   tristate "Everest Semi ES8328 CODEC"
>
> diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
> index 4a32077..c92aaf7 100644
> --- a/sound/soc/codecs/Makefile
> +++ b/sound/soc/codecs/Makefile
> @@ -73,6 +73,7 @@ snd-soc-max9850-objs := max9850.o
>   snd-soc-mc13783-objs := mc13783.o
>   snd-soc-ml26124-objs := ml26124.o
>   snd-soc-hdmi-codec-objs := hdmi.o
> +snd-soc-hdmi-drm-codec-objs := hdmi_drm.o
>   snd-soc-pcm1681-objs := pcm1681.o
>   snd-soc-pcm1792a-codec-objs := pcm1792a.o
>   snd-soc-pcm3008-objs := pcm3008.o
> @@ -265,6 +266,7 @@ obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
>   obj-$(CONFIG_SND_SOC_MC13783)   += snd-soc-mc13783.o
>   obj-$(CONFIG_SND_SOC_ML26124)   += snd-soc-ml26124.o
>   obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
> +obj-$(CONFIG_SND_SOC_HDMI_DRM_CODEC) += snd-soc-hdmi-drm-codec.o
>   obj-$(CONFIG_SND_SOC_PCM1681)   += snd-soc-pcm1681.o
>   obj-$(CONFIG_SND_SOC_PCM1792A)  += snd-soc-pcm1792a-codec.o
>   obj-$(CONFIG_SND_SOC_PCM3008)   += snd-soc-pcm3008.o
> diff --git a/sound/soc/codecs/hdmi_drm.c b/sound/soc/codecs/hdmi_drm.c
> new file mode 100644
> index 000..2df9a8f
> --- /dev/null
> +++ b/sound/soc/codecs/hdmi_drm.c
> @@ -0,0 +1,125 @@
> +/*
> + * ALSA SoC codec driver for DRM HDMI device.
> + * Copyright (C) STMicroelectronics SA 2015
> + * Authors: Arnaud Pouliquen 
> + *  for STMicroelectronics.
> + * License terms:  GNU General Public License (GPL), version 2
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +struct hdmi_drm_dai_data {
> + struct drm_bridge *bridge;
> +};here are several important callbacks missing here
> +
> +static const struct snd_soc_dapm_widget hdmi_drm_widgets[] = {
> + SND_SOC_DAPM_OUTPUT("TX"),
> +};
> +
> +static const struct snd_soc_dapm_route hdmi_drm_routes[] = {
> + { "TX", NULL, "Playback" },
> +};
> +
> +int hdmi_drm_dai_prepare(struct snd_pcm_substream *substream,
> +  struct snd_soc_dai *dai)
> +{
> + struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
> +
> + dev_err(dai->dev, "%s: enter for bridge %p\n", __func__, priv->bridge);
> + drm_audio_bridge_pre_enable(priv->bridge);
> + return 0;
> +}
> +
> +int hdmi_drm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
> +  struct snd_soc_dai *dai)
> +{
> + struct hdmi_drm_dai_data *priv = snd_soc_dai_get_drvdata(dai);
> +
> + dev_err(dai->dev, "%s: enter\n", __func__);
> + switch (cmd) {
> + case SNDRV_PCM_TRIGGER_START:
> + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> + case SNDRV_PCM_TRIGGER_RESUME:
> +  

[PATCH RFC v2 0/3] Add a drm_aux-dev module.

2015-09-25 Thread Rafael Antognolli
Oops, sorry, this email shouldn't be in the patch set, please
disconsider it.

--
Rafael

On Fri, Sep 25, 2015 at 04:54:53PM -0700, Rafael Antognolli wrote:
> Second attempt at implementing a module that allows reading/writing arbitrary
> dpcd registers. Changes to this version:
>   - lseek is used to select the register to read/write;
>   - read/write are used instead of ioctl;
>   - no blocking_notifier is used, just a direct callback.
> 
> One thing to notice is that I am not updating the file offset during read or
> write, which is kind of breaking the filesystem abstraction. But i2c-dev
> doesn't do it either, so I assumed it's fine.
> 
> Rafael Antognolli (3):
>   drm/dp: Keep a list of drm_dp_aux helper.
>   drm/dp: Store the drm_connector device pointer on the helper.
>   drm/dp: Add a drm_aux-dev module for reading/writing dpcd registers.
> 
>  drivers/gpu/drm/Kconfig |   4 +
>  drivers/gpu/drm/Makefile|   1 +
>  drivers/gpu/drm/drm_aux-dev.c   | 326 
> 
>  drivers/gpu/drm/drm_dp_helper.c |  73 +
>  drivers/gpu/drm/i915/intel_dp.c |   1 +
>  include/drm/drm_dp_helper.h |   6 +
>  6 files changed, 411 insertions(+)
>  create mode 100644 drivers/gpu/drm/drm_aux-dev.c
> 
> -- 
> 2.4.3
> 


[PATCH v3 2/2] drm/dp: Add a drm_aux-dev module for reading/writing dpcd registers.

2015-09-25 Thread Rafael Antognolli
This module is heavily based on i2c-dev. Once loaded, it provides one
dev node per DP AUX channel, named drm_dp_auxN, where N is an integer.

It's possible to know which connector owns this aux channel by looking
at the respective sysfs /sys/class/drm_aux_dev/drm_dp_auxN/connector, if
the connector device pointer was correctly set in the aux helper struct.

Two main operations are provided on the registers read and write. The
address of the register to be read or written is given using lseek. The
seek position is updated upon read or write.

Signed-off-by: Rafael Antognolli 
---
 drivers/gpu/drm/Kconfig  |   8 +
 drivers/gpu/drm/Makefile |   3 +-
 drivers/gpu/drm/drm_dp_aux_dev.c | 357 +++
 drivers/gpu/drm/drm_dp_helper.c  |   5 +
 include/drm/drm_dp_aux_dev.h |  50 ++
 5 files changed, 422 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_dp_aux_dev.c
 create mode 100644 include/drm/drm_dp_aux_dev.h

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1a0a8df..64fa0f4 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -25,6 +25,14 @@ config DRM_MIPI_DSI
bool
depends on DRM

+config DRM_DP_AUX_CHARDEV
+   bool "DRM DP AUX Interface"
+   depends on DRM
+   help
+ Choose this option to enable a /dev/drm_dp_auxN node that allows to
+ read and write values to arbitrary DPCD registers on the DP aux
+ channel.
+
 config DRM_KMS_HELPER
tristate
depends on DRM
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 45e7719..1afcbed 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -21,7 +21,8 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o
 drm-$(CONFIG_OF) += drm_of.o

 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
-   drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
+   drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
+   drm_dp_aux_dev.o
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
 drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
new file mode 100644
index 000..e337081
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *Rafael Antognolli 
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct drm_dp_aux_dev {
+   struct list_head list;
+   unsigned index;
+   struct drm_dp_aux *aux;
+   struct device *dev;
+};
+
+#define DRM_AUX_MINORS 256
+static int aux_max_offset = 1 << 20;
+static int drm_dp_aux_dev_count = 0;
+static LIST_HEAD(drm_dp_aux_dev_list);
+static DEFINE_SPINLOCK(drm_dp_aux_dev_list_lock);
+
+static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index)
+{
+   struct drm_dp_aux_dev *aux_dev;
+
+   spin_lock(_dp_aux_dev_list_lock);
+   list_for_each_entry(aux_dev, _dp_aux_dev_list, list) {
+   if (aux_dev->index == index)
+   goto found;
+   }
+
+   aux_dev = NULL;
+found:
+   spin_unlock(_dp_aux_dev_list_lock);
+   return aux_dev;
+}
+
+static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_aux(struct drm_dp_aux *aux)
+{
+   struct drm_dp_aux_dev *aux_dev;
+
+   spin_lock(_dp_aux_dev_list_lock);
+   list_for_each_entry(aux_dev, _dp_aux_dev_list, list) {
+   if (aux_dev->aux == aux)
+   goto found;
+   }
+
+   aux_dev = NULL;
+found:
+   spin_unlock(_dp_aux_dev_list_lock);
+   return aux_dev;
+}
+
+static struct 

[PATCH v3 1/2] drm/dp: Store the drm_connector device pointer on the helper.

2015-09-25 Thread Rafael Antognolli
This is useful to determine which connector owns this AUX channel.

Signed-off-by: Rafael Antognolli 
---
 drivers/gpu/drm/i915/intel_dp.c | 1 +
 include/drm/drm_dp_helper.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 06a2b10..1b1df1c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1079,6 +1079,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct 
intel_connector *connector)

intel_dp->aux.name = name;
intel_dp->aux.dev = dev->dev;
+   intel_dp->aux.connector = connector->base.kdev;
intel_dp->aux.transfer = intel_dp_aux_transfer;

DRM_DEBUG_KMS("registering %s bus for %s\n", name,
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 9ec4716..e009b5d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -702,6 +702,7 @@ struct drm_dp_aux {
const char *name;
struct i2c_adapter ddc;
struct device *dev;
+   struct device *connector;
struct mutex hw_mutex;
ssize_t (*transfer)(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg);
-- 
2.4.3



[PATCH v3 0/2] Add drm_dp_aux chardev support.

2015-09-25 Thread Rafael Antognolli
This series implement support to a drm_dp_aux chardev that allows reading and
writing an arbitrary amount of bytes to arbitrary dpcd register addresses using
regular read, write and lseek operations.

v2:
 - lseek is used to select the register to read/write
 - read/write are used instead of ioctl
 - no blocking_notifier is used, just a direct callback

v3:
 - use drm_dp_aux_dev prefix for public functions
 - chardev is named drm_dp_auxN
 - read/write don't allocate a buffer anymore, and transfer up to 16 bytes a
 time
 - remove notifier list from the implementation
 - option on menuconfig is now a boolean
 - add inline stub functions to avoid breakage when this option is disabled

Rafael Antognolli (2):
  drm/dp: Store the drm_connector device pointer on the helper.
  drm/dp: Add a drm_aux-dev module for reading/writing dpcd registers.

 drivers/gpu/drm/Kconfig  |   8 +
 drivers/gpu/drm/Makefile |   3 +-
 drivers/gpu/drm/drm_dp_aux_dev.c | 357 +++
 drivers/gpu/drm/drm_dp_helper.c  |   5 +
 drivers/gpu/drm/i915/intel_dp.c  |   1 +
 include/drm/drm_dp_aux_dev.h |  50 ++
 include/drm/drm_dp_helper.h  |   1 +
 7 files changed, 424 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/drm_dp_aux_dev.c
 create mode 100644 include/drm/drm_dp_aux_dev.h

-- 
2.4.3



[PATCH RFC v2 0/3] Add a drm_aux-dev module.

2015-09-25 Thread Rafael Antognolli
Second attempt at implementing a module that allows reading/writing arbitrary
dpcd registers. Changes to this version:
- lseek is used to select the register to read/write;
- read/write are used instead of ioctl;
- no blocking_notifier is used, just a direct callback.

One thing to notice is that I am not updating the file offset during read or
write, which is kind of breaking the filesystem abstraction. But i2c-dev
doesn't do it either, so I assumed it's fine.

Rafael Antognolli (3):
  drm/dp: Keep a list of drm_dp_aux helper.
  drm/dp: Store the drm_connector device pointer on the helper.
  drm/dp: Add a drm_aux-dev module for reading/writing dpcd registers.

 drivers/gpu/drm/Kconfig |   4 +
 drivers/gpu/drm/Makefile|   1 +
 drivers/gpu/drm/drm_aux-dev.c   | 326 
 drivers/gpu/drm/drm_dp_helper.c |  73 +
 drivers/gpu/drm/i915/intel_dp.c |   1 +
 include/drm/drm_dp_helper.h |   6 +
 6 files changed, 411 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_aux-dev.c

-- 
2.4.3



[PATCH RFC v2 3/3] drm/dp: Add a drm_aux-dev module for reading/writing dpcd registers.

2015-09-25 Thread Rafael Antognolli
On Tue, Sep 22, 2015 at 02:17:51PM +0200, Daniel Vetter wrote:
> On Tue, Sep 22, 2015 at 03:00:54PM +0300, Ville Syrjälä wrote:
> > On Tue, Sep 15, 2015 at 04:55:04PM -0700, Rafael Antognolli wrote:
> > > This module is heavily based on i2c-dev. Once loaded, it provides one
> > > dev node per DP AUX channel, named drm_aux-N.
> > > 
> > > It's possible to know which connector owns this aux channel by looking
> > > at the respective sysfs /sys/class/drm_aux-dev/drm_aux-N/connector, if
> > > the connector device pointer was correctly set in the aux helper struct.
> > > 
> > > Two main operations are provided on the registers: read and write. The
> > > address of the register to be read or written is given using lseek.
> > > Reading or writing does not update the offset of the file.
> > > 
> > > Signed-off-by: Rafael Antognolli 
> > > ---
> > >  drivers/gpu/drm/Kconfig   |   4 +
> > >  drivers/gpu/drm/Makefile  |   1 +
> > >  drivers/gpu/drm/drm_aux-dev.c | 326 
> > > ++
> > >  3 files changed, 331 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/drm_aux-dev.c
> > > 
> > > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> > > index 1a0a8df..eae847c 100644
> > > --- a/drivers/gpu/drm/Kconfig
> > > +++ b/drivers/gpu/drm/Kconfig
> > > @@ -25,6 +25,10 @@ config DRM_MIPI_DSI
> > >   bool
> > >   depends on DRM
> > >  
> > > +config DRM_AUX_CHARDEV
> > > + tristate "DRM DP AUX Interface"
> > > + depends on DRM
> > > +
> > >  config DRM_KMS_HELPER
> > >   tristate
> > >   depends on DRM
> > > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> > > index 45e7719..a1a94306 100644
> > > --- a/drivers/gpu/drm/Makefile
> > > +++ b/drivers/gpu/drm/Makefile
> > > @@ -32,6 +32,7 @@ CFLAGS_drm_trace_points.o := -I$(src)
> > >  
> > >  obj-$(CONFIG_DRM)+= drm.o
> > >  obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
> > > +obj-$(CONFIG_DRM_AUX_CHARDEV) += drm_aux-dev.o
> > >  obj-$(CONFIG_DRM_TTM)+= ttm/
> > >  obj-$(CONFIG_DRM_TDFX)   += tdfx/
> > >  obj-$(CONFIG_DRM_R128)   += r128/
> > > diff --git a/drivers/gpu/drm/drm_aux-dev.c b/drivers/gpu/drm/drm_aux-dev.c
> > > new file mode 100644
> > > index 000..fcc334a
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/drm_aux-dev.c
> > > @@ -0,0 +1,326 @@
> > > +/*
> > > + * Copyright © 2015 Intel Corporation
> > > + *
> > > + * Permission is hereby granted, free of charge, to any person obtaining 
> > > a
> > > + * copy of this software and associated documentation files (the 
> > > "Software"),
> > > + * to deal in the Software without restriction, including without 
> > > limitation
> > > + * the rights to use, copy, modify, merge, publish, distribute, 
> > > sublicense,
> > > + * and/or sell copies of the Software, and to permit persons to whom the
> > > + * Software is furnished to do so, subject to the following conditions:
> > > + *
> > > + * The above copyright notice and this permission notice (including the 
> > > next
> > > + * paragraph) shall be included in all copies or substantial portions of 
> > > the
> > > + * Software.
> > > + *
> > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
> > > EXPRESS OR
> > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
> > > MERCHANTABILITY,
> > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT 
> > > SHALL
> > > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
> > > OTHER
> > > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
> > > ARISING
> > > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
> > > DEALINGS
> > > + * IN THE SOFTWARE.
> > > + *
> > > + * Authors:
> > > + *Rafael Antognolli 
> > > + *
> > > + */
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +struct drm_aux_dev {
> > > + struct list_head list;
> > > + unsigned index;
> > > + struct drm_dp_aux *aux;
> > > + struct device *dev;
> > > +};
> > > +
> > > +#define DRM_AUX_MINORS   256
> > > +static int drm_aux_dev_count = 0;
> > > +static LIST_HEAD(drm_aux_dev_list);
> > > +static DEFINE_SPINLOCK(drm_aux_dev_list_lock);
> > > +
> > > +static struct drm_aux_dev *drm_aux_dev_get_by_minor(unsigned index)
> > > +{
> > > + struct drm_aux_dev *aux_dev;
> > > +
> > > + spin_lock(_aux_dev_list_lock);
> > > + list_for_each_entry(aux_dev, _aux_dev_list, list) {
> > > + if (aux_dev->index == index)
> > > + goto found;
> > > + }
> > > +
> > > + aux_dev = NULL;
> > > +found:
> > > + spin_unlock(_aux_dev_list_lock);
> > > + return aux_dev;
> > > +}
> > > +
> > > +static struct drm_aux_dev *drm_aux_dev_get_by_aux(struct drm_dp_aux *aux)
> > > +{
> > > + struct drm_aux_dev *aux_dev;
> > > +
> > > + spin_lock(_aux_dev_list_lock);
> > > + list_for_each_entry(aux_dev, _aux_dev_list, list) {
> > > + if 

[PATCH 1/6] driver-core: platform: Provide helpers for multi-driver modules

2015-09-25 Thread Thierry Reding
+ *
> + * Registers platform drivers specified by an array. On failure to register a
> + * driver, all previously registered drivers will be unregistered. Callers of
> + * this API should use platform_unregister_drivers() to unregister drivers in
> + * the reverse order.
> + *
> + * Returns: 0 on success or a negative error code on failure.
> + */
> +int platform_register_drivers(struct platform_driver * const *drivers,
> +   unsigned int count)
> +{
> + unsigned int i;
> + int err;
> +
> + for (i = 0; i < count; i++) {
> + pr_debug("registering platform driver %ps\n", drivers[i]);
> +
> + err = platform_driver_register(drivers[i]);
> + if (err < 0) {
> + pr_err("failed to register platform driver %ps: %d\n",
> +drivers[i], err);
> + goto error;
> + }
> + }
> +
> + return 0;
> +
> +error:
> + while (i--) {
> + pr_debug("unregistering platform driver %ps\n", drivers[i]);
> + platform_driver_unregister(drivers[i]);
> + }
> +
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(platform_register_drivers);
> +
> +/**
> + * platform_unregister_drivers - unregister an array of platform drivers
> + * @drivers: an array of drivers to unregister
> + * @count: the number of drivers to unregister
> + *
> + * Unegisters platform drivers specified by an array. This is typically used
> + * to complement an earlier call to platform_register_drivers(). Drivers are
> + * unregistered in the reverse order in which they were registered.
> + */
> +void platform_unregister_drivers(struct platform_driver * const *drivers,
> +  unsigned int count)
> +{
> + while (count--) {
> + pr_debug("unregistering platform driver %ps\n", drivers[count]);
> + platform_driver_unregister(drivers[count]);
> + }
> +}
> +EXPORT_SYMBOL_GPL(platform_unregister_drivers);
> +
>  /* modalias support enables more hands-off userspace setup:
>   * (a) environment variable lets new-style hotplug events work once system is
>   * fully running:  "modprobe $MODALIAS"
> diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
> index bba08f44cc97..0c9f16bfdd99 100644
> --- a/include/linux/platform_device.h
> +++ b/include/linux/platform_device.h
> @@ -270,6 +270,11 @@ extern struct platform_device *__platform_create_bundle(
>   struct resource *res, unsigned int n_res,
>   const void *data, size_t size, struct module *module);
>  
> +int platform_register_drivers(struct platform_driver * const *drivers,
> +   unsigned int count);
> +void platform_unregister_drivers(struct platform_driver * const *drivers,
> +  unsigned int count);
> +
>  /* early platform driver interface */
>  struct early_platform_driver {
>   const char *class_str;
> -- 
> 2.5.0
> 
-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20150925/62893765/attachment.sig>


[PATCH 3/6] drm/imx: Build monolithic driver

2015-09-25 Thread Thierry Reding
On Fri, Sep 25, 2015 at 03:13:54PM +0200, Philipp Zabel wrote:
> Am Freitag, den 25.09.2015, 15:09 +0200 schrieb Philipp Zabel:
> > Am Freitag, den 25.09.2015, 14:17 +0200 schrieb Thierry Reding:
> > > I think you gain much less by splitting up than you realize. Compare
> > > this from before the series:
> > > 
> > >   $ du -ch drivers/gpu/drm/imx/*.ko
> > >   8.0Kdrivers/gpu/drm/imx/dw_hdmi-imx.ko
> > 
> > Oh right, I didn't realize that this is just the shim. The bulk of the
> > HDMI driver is in bridge/dw_hdmi.ko.
> > 
> > >   16K drivers/gpu/drm/imx/imxdrm.ko
> > >   16K drivers/gpu/drm/imx/imx-ipuv3-crtc.ko
> > >   12K drivers/gpu/drm/imx/imx-ldb.ko
> > >   12K drivers/gpu/drm/imx/imx-tve.ko
> > >   8.0Kdrivers/gpu/drm/imx/parallel-display.ko
> > >   72K total
> > [...]
> > > with this after the series:
> > > 
> > >   $ du -ch drivers/gpu/drm/imx/*.ko
> > >   44K drivers/gpu/drm/imx/imx-drm.ko
> > >   44K total
> > [...]
> > > There are other things to consider as well, such as the additional
> > > memory overhead caused by merely having multiple modules, or all of the
> > > exported functions that unnecessarily clutter up the symbol table, and
> > > which end up slowing down every symbol lookup.
> > 
> > Thanks, can't argue with those numbers.
> > I'll queue patches 3 and 4 for imx-drm.
> 
> Wait, I won't because they depend on the helper function in patch 1.
> 
> Acked-by: Philipp Zabel 
> 
> then. Can I get a stable tag so I can solve potential merge conflicts in
> imx-drm-core.c?

Let's see what Greg thinks about patch 1. There are a bunch of other
drivers that can use these helpers, so it might be best to get the
helper merged first and hold off on the depending patches until the
next release.

I'll let you know when we've figured out how to merge this.

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


No more new fbdev drivers, please

2015-09-25 Thread Tomi Valkeinen


On 25/09/15 13:41, Kamil Lulko wrote:
> Hi,
> 
>> fbdev is (more or less) maintained, but it's a deprecated framework. All
>> new Linux display drivers should be done on DRM.
> 
> What about no-mmu platforms? DRM has a big fat MMU dependency in the
> kconfig, is there a way to write DRM driver for such devices?

I guess not.

Then again, I don't see why DRM would have a hard dependency to MMU, if
the work is done to make DRM work optionally without MMU. How much work
that is, I have no idea.

 Tom

-- next part --
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20150925/7b19a948/attachment.sig>


[PATCH 3/6] drm/imx: Build monolithic driver

2015-09-25 Thread Philipp Zabel
Am Freitag, den 25.09.2015, 15:09 +0200 schrieb Philipp Zabel:
> Am Freitag, den 25.09.2015, 14:17 +0200 schrieb Thierry Reding:
> > I think you gain much less by splitting up than you realize. Compare
> > this from before the series:
> > 
> > $ du -ch drivers/gpu/drm/imx/*.ko
> > 8.0Kdrivers/gpu/drm/imx/dw_hdmi-imx.ko
> 
> Oh right, I didn't realize that this is just the shim. The bulk of the
> HDMI driver is in bridge/dw_hdmi.ko.
> 
> > 16K drivers/gpu/drm/imx/imxdrm.ko
> > 16K drivers/gpu/drm/imx/imx-ipuv3-crtc.ko
> > 12K drivers/gpu/drm/imx/imx-ldb.ko
> > 12K drivers/gpu/drm/imx/imx-tve.ko
> > 8.0Kdrivers/gpu/drm/imx/parallel-display.ko
> > 72K total
> [...]
> > with this after the series:
> > 
> > $ du -ch drivers/gpu/drm/imx/*.ko
> > 44K drivers/gpu/drm/imx/imx-drm.ko
> > 44K total
> [...]
> > There are other things to consider as well, such as the additional
> > memory overhead caused by merely having multiple modules, or all of the
> > exported functions that unnecessarily clutter up the symbol table, and
> > which end up slowing down every symbol lookup.
> 
> Thanks, can't argue with those numbers.
> I'll queue patches 3 and 4 for imx-drm.

Wait, I won't because they depend on the helper function in patch 1.

Acked-by: Philipp Zabel 

then. Can I get a stable tag so I can solve potential merge conflicts in
imx-drm-core.c?

regards
Philipp



[PATCH 3/6] drm/imx: Build monolithic driver

2015-09-25 Thread Philipp Zabel
Am Freitag, den 25.09.2015, 14:17 +0200 schrieb Thierry Reding:
> I think you gain much less by splitting up than you realize. Compare
> this from before the series:
> 
>   $ du -ch drivers/gpu/drm/imx/*.ko
>   8.0Kdrivers/gpu/drm/imx/dw_hdmi-imx.ko

Oh right, I didn't realize that this is just the shim. The bulk of the
HDMI driver is in bridge/dw_hdmi.ko.

>   16K drivers/gpu/drm/imx/imxdrm.ko
>   16K drivers/gpu/drm/imx/imx-ipuv3-crtc.ko
>   12K drivers/gpu/drm/imx/imx-ldb.ko
>   12K drivers/gpu/drm/imx/imx-tve.ko
>   8.0Kdrivers/gpu/drm/imx/parallel-display.ko
>   72K total
[...]
> with this after the series:
> 
>   $ du -ch drivers/gpu/drm/imx/*.ko
>   44K drivers/gpu/drm/imx/imx-drm.ko
>   44K total
[...]
> There are other things to consider as well, such as the additional
> memory overhead caused by merely having multiple modules, or all of the
> exported functions that unnecessarily clutter up the symbol table, and
> which end up slowing down every symbol lookup.

Thanks, can't argue with those numbers.
I'll queue patches 3 and 4 for imx-drm.

regards
Philipp



[PATCH 16/16] drm: exynos: mixer: fix using usleep() in atomic context

2015-09-25 Thread Andrzej Hajda
From: Tomasz Stanislawski 

This patch fixes calling usleep_range() after taking reg_slock
using spin_lock_irqsave(). The mdelay() is used instead.
Waiting in atomic context is not the best idea in general.
Hopefully, waiting occurs only when Video Processor fails
to reset correctly.

Signed-off-by: Tomasz Stanislawski 
---
 drivers/gpu/drm/exynos/exynos_mixer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c 
b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7f81cce..ecf956c 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -652,7 +652,7 @@ static void vp_win_reset(struct mixer_context *ctx)
/* waiting until VP_SRESET_PROCESSING is 0 */
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
break;
-   usleep_range(1, 12000);
+   mdelay(10);
}
WARN(tries == 0, "failed to reset Video Processor\n");
 }
-- 
1.9.1



[PATCH 15/16] drm/exynos/hdmi: remove unused field

2015-09-25 Thread Andrzej Hajda
The patch removes unused hdmi_context field.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index a4ec8b9..b0f5ff4 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -103,7 +103,6 @@ struct hdmi_context {
struct device   *dev;
struct drm_device   *drm_dev;
struct drm_connectorconnector;
-   boolhpd;
boolpowered;
booldvi_mode;
struct delayed_work hotplug_work;
-- 
1.9.1



[PATCH 14/16] drm/exynos/hdmi: improve HDMI/ACR related code

2015-09-25 Thread Andrzej Hajda
Simple formula can be used to calculate CTS and N coefficients.
Additionaly ACR registers have different offsets for different versions
of IP.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 71 +++-
 drivers/gpu/drm/exynos/regs-hdmi.h   | 29 ++-
 2 files changed, 32 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index c5a0617..a4ec8b9 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -71,12 +71,18 @@ enum hdmi_mapped_regs {
HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
HDMI_PHY_RSTOUT,
HDMI_ACR_CON,
+   HDMI_ACR_MCTS0,
+   HDMI_ACR_CTS0,
+   HDMI_ACR_N0
 };

 static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
{ HDMI_V13_PHY_STATUS, HDMI_PHY_STATUS_0 },
{ HDMI_V13_PHY_RSTOUT, HDMI_V14_PHY_RSTOUT },
{ HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
+   { HDMI_V13_ACR_MCTS0, HDMI_V14_ACR_MCTS0 },
+   { HDMI_V13_ACR_CTS0, HDMI_V14_ACR_CTS0 },
+   { HDMI_V13_ACR_N0, HDMI_V14_ACR_N0 },
 };

 static const char * const supply[] = {
@@ -1106,65 +1112,16 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
return true;
 }

-static void hdmi_set_acr(u32 freq, u8 *acr)
+static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
 {
u32 n, cts;

-   switch (freq) {
-   case 32000:
-   n = 4096;
-   cts = 27000;
-   break;
-   case 44100:
-   n = 6272;
-   cts = 3;
-   break;
-   case 88200:
-   n = 12544;
-   cts = 3;
-   break;
-   case 176400:
-   n = 25088;
-   cts = 3;
-   break;
-   case 48000:
-   n = 6144;
-   cts = 27000;
-   break;
-   case 96000:
-   n = 12288;
-   cts = 27000;
-   break;
-   case 192000:
-   n = 24576;
-   cts = 27000;
-   break;
-   default:
-   n = 0;
-   cts = 0;
-   break;
-   }
-
-   acr[1] = cts >> 16;
-   acr[2] = cts >> 8 & 0xff;
-   acr[3] = cts & 0xff;
+   cts = (freq % 9) ? 27000 : 3;
+   n = 128 * freq / (2700 / cts);

-   acr[4] = n >> 16;
-   acr[5] = n >> 8 & 0xff;
-   acr[6] = n & 0xff;
-}
-
-static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
-{
-   hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
-   hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
+   hdmi_reg_writev(hdata, HDMI_ACR_N0, 3, n);
+   hdmi_reg_writev(hdata, HDMI_ACR_MCTS0, 3, cts);
+   hdmi_reg_writev(hdata, HDMI_ACR_CTS0, 3, cts);
hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
 }

@@ -1173,7 +1130,6 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
u32 sample_rate, bits_per_sample;
u32 data_num, bit_ch, sample_frq;
u32 val;
-   u8 acr[7];

sample_rate = 44100;
bits_per_sample = 16;
@@ -1193,8 +1149,7 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
break;
}

-   hdmi_set_acr(sample_rate, acr);
-   hdmi_reg_acr(hdata, acr);
+   hdmi_reg_acr(hdata, sample_rate);

hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
| HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h 
b/drivers/gpu/drm/exynos/regs-hdmi.h
index 8b2d337..8c891e5 100644
--- a/drivers/gpu/drm/exynos/regs-hdmi.h
+++ b/drivers/gpu/drm/exynos/regs-hdmi.h
@@ -72,7 +72,6 @@
 #define HDMI_V13_V_SYNC_GEN_3_0HDMI_CORE_BASE(0x0150)
 #define HDMI_V13_V_SYNC_GEN_3_1HDMI_CORE_BASE(0x0154)
 #define HDMI_V13_V_SYNC_GEN_3_2HDMI_CORE_BASE(0x0158)
-#define HDMI_V13_ACR_CON   HDMI_CORE_BASE(0x0180)
 #define HDMI_V13_AVI_CON   HDMI_CORE_BASE(0x0300)
 #define HDMI_V13_AVI_BYTE(n)   HDMI_CORE_BASE(0x0320 + 4 * (n))
 #define HDMI_V13_DC_CONTROLHDMI_CORE_BASE(0x05C0)
@@ -277,16 +276,26 @@
 #define HDMI_ASP_CHCFG2HDMI_CORE_BASE(0x0318)
 #define HDMI_ASP_CHCFG3HDMI_CORE_BASE(0x031C)

+#define HDMI_V13_ACR_CON   HDMI_CORE_BASE(0x0180)
+#define HDMI_V13_ACR_MCTS0 HDMI_CORE_BASE(0x0184)
+#define HDMI_V13_ACR_MCTS1 HDMI_CORE_BASE(0x0188)
+#define HDMI_V13_ACR_MCTS2 

[PATCH 13/16] drm/exynos/hdmi: convert container_of macro to inline function

2015-09-25 Thread Andrzej Hajda
Inline function is safer than macro, also the name has been changed to
be consistent with other inline function encoder_to_hdmi.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 0d538d3..c5a0617 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -46,8 +46,6 @@
 #include "exynos_drm_crtc.h"
 #include "exynos_mixer.h"

-#define ctx_from_connector(c)  container_of(c, struct hdmi_context, connector)
-
 #define HOTPLUG_DEBOUNCE_MS1100

 /* AVI header and aspect ratio */
@@ -128,6 +126,11 @@ static inline struct hdmi_context *encoder_to_hdmi(struct 
drm_encoder *e)
return container_of(e, struct hdmi_context, encoder);
 }

+static inline struct hdmi_context *connector_to_hdmi(struct drm_connector *c)
+{
+   return container_of(c, struct hdmi_context, connector);
+}
+
 struct hdmiphy_config {
int pixel_clock;
u8 conf[32];
@@ -935,7 +938,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
 static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
bool force)
 {
-   struct hdmi_context *hdata = ctx_from_connector(connector);
+   struct hdmi_context *hdata = connector_to_hdmi(connector);

if (gpiod_get_value(hdata->hpd_gpio))
return connector_status_connected;
@@ -961,7 +964,7 @@ static struct drm_connector_funcs hdmi_connector_funcs = {

 static int hdmi_get_modes(struct drm_connector *connector)
 {
-   struct hdmi_context *hdata = ctx_from_connector(connector);
+   struct hdmi_context *hdata = connector_to_hdmi(connector);
struct edid *edid;
int ret;

@@ -1001,7 +1004,7 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, 
u32 pixel_clock)
 static int hdmi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
 {
-   struct hdmi_context *hdata = ctx_from_connector(connector);
+   struct hdmi_context *hdata = connector_to_hdmi(connector);
int ret;

DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
@@ -1022,7 +1025,7 @@ static int hdmi_mode_valid(struct drm_connector 
*connector,

 static struct drm_encoder *hdmi_best_encoder(struct drm_connector *connector)
 {
-   struct hdmi_context *hdata = ctx_from_connector(connector);
+   struct hdmi_context *hdata = connector_to_hdmi(connector);

return >encoder;
 }
-- 
1.9.1



[PATCH 12/16] drm/exynos/hdmi: remove deprecated hdmi_resources structure

2015-09-25 Thread Andrzej Hajda
hdmi_resources structure was filled by old platform data code and is not
necessary anymore. The patch removes it at groups together resource related
fields in hdmi_context.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 105 +++
 1 file changed, 46 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index c0664d53..0d538d3 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -94,16 +94,6 @@ struct hdmi_driver_data {
unsigned int is_apb_phy:1;
 };

-struct hdmi_resources {
-   struct clk  *hdmi;
-   struct clk  *sclk_hdmi;
-   struct clk  *sclk_pixel;
-   struct clk  *sclk_hdmiphy;
-   struct clk  *mout_hdmi;
-   struct regulator_bulk_data  regul_bulk[ARRAY_SIZE(supply)];
-   struct regulator*reg_hdmi_en;
-};
-
 struct hdmi_context {
struct drm_encoder  encoder;
struct device   *dev;
@@ -112,25 +102,25 @@ struct hdmi_context {
boolhpd;
boolpowered;
booldvi_mode;
-
-   void __iomem*regs;
-   int irq;
struct delayed_work hotplug_work;
-
-   struct i2c_adapter  *ddc_adpt;
-   struct i2c_client   *hdmiphy_port;
-
-   /* current hdmiphy conf regs */
struct drm_display_mode current_mode;
u8  cea_video_id;
-
-   struct hdmi_resources   res;
const struct hdmi_driver_data   *drv_data;

-   struct gpio_desc*hpd_gpio;
+   void __iomem*regs;
void __iomem*regs_hdmiphy;
-
+   struct i2c_client   *hdmiphy_port;
+   struct i2c_adapter  *ddc_adpt;
+   struct gpio_desc*hpd_gpio;
+   int irq;
struct regmap   *pmureg;
+   struct clk  *hdmi;
+   struct clk  *sclk_hdmi;
+   struct clk  *sclk_pixel;
+   struct clk  *sclk_hdmiphy;
+   struct clk  *mout_hdmi;
+   struct regulator_bulk_data  regul_bulk[ARRAY_SIZE(supply)];
+   struct regulator*reg_hdmi_en;
 };

 static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
@@ -1567,7 +1557,7 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)

hdmiphy_wait_for_pll(hdata);

-   clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
+   clk_set_parent(hdata->mout_hdmi, hdata->sclk_hdmiphy);

/* enable HDMI and timing generator */
hdmi_start(hdata, true);
@@ -1575,7 +1565,7 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)

 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 {
-   clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
+   clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel);

/* reset hdmiphy */
hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
@@ -1642,7 +1632,6 @@ static void hdmi_mode_set(struct drm_encoder *encoder,
 static void hdmi_enable(struct drm_encoder *encoder)
 {
struct hdmi_context *hdata = encoder_to_hdmi(encoder);
-   struct hdmi_resources *res = >res;

if (hdata->powered)
return;
@@ -1651,15 +1640,15 @@ static void hdmi_enable(struct drm_encoder *encoder)

pm_runtime_get_sync(hdata->dev);

-   if (regulator_bulk_enable(ARRAY_SIZE(supply), res->regul_bulk))
+   if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
DRM_DEBUG_KMS("failed to enable regulator bulk\n");

/* set pmu hdmiphy control bit to enable hdmiphy */
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
PMU_HDMI_PHY_ENABLE_BIT, 1);

-   clk_prepare_enable(res->hdmi);
-   clk_prepare_enable(res->sclk_hdmi);
+   clk_prepare_enable(hdata->hdmi);
+   clk_prepare_enable(hdata->sclk_hdmi);

hdmi_conf_apply(hdata);
 }
@@ -1667,7 +1656,6 @@ static void hdmi_enable(struct drm_encoder *encoder)
 static void hdmi_disable(struct drm_encoder *encoder)
 {
struct hdmi_context *hdata = encoder_to_hdmi(encoder);
-   struct hdmi_resources *res = >res;
struct drm_crtc *crtc = encoder->crtc;
const struct drm_crtc_helper_funcs *funcs = NULL;

@@ -1693,14 +1681,14 @@ static void hdmi_disable(struct drm_encoder *encoder)

cancel_delayed_work(>hotplug_work);

-   clk_disable_unprepare(res->sclk_hdmi);
-   

[PATCH 11/16] drm/exynos/hdmi: convert to gpiod API

2015-09-25 Thread Andrzej Hajda
The patch converts API to gpiod and moves initialization code
to hdmi_resources_init.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 37 ++--
 1 file changed, 14 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 475341f..c0664d53 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -30,11 +30,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -46,8 +46,6 @@
 #include "exynos_drm_crtc.h"
 #include "exynos_mixer.h"

-#include 
-
 #define ctx_from_connector(c)  container_of(c, struct hdmi_context, connector)

 #define HOTPLUG_DEBOUNCE_MS1100
@@ -129,7 +127,7 @@ struct hdmi_context {
struct hdmi_resources   res;
const struct hdmi_driver_data   *drv_data;

-   int hpd_gpio;
+   struct gpio_desc*hpd_gpio;
void __iomem*regs_hdmiphy;

struct regmap   *pmureg;
@@ -949,7 +947,7 @@ static enum drm_connector_status hdmi_detect(struct 
drm_connector *connector,
 {
struct hdmi_context *hdata = ctx_from_connector(connector);

-   if (gpio_get_value(hdata->hpd_gpio))
+   if (gpiod_get_value(hdata->hpd_gpio))
return connector_status_connected;

return connector_status_disconnected;
@@ -1748,6 +1746,17 @@ static int hdmi_resources_init(struct hdmi_context 
*hdata)

DRM_DEBUG_KMS("HDMI resource init\n");

+   hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
+   if (IS_ERR(hdata->hpd_gpio)) {
+   DRM_ERROR("cannot get hpd gpio property\n");
+   return PTR_ERR(hdata->hpd_gpio);
+   }
+
+   hdata->irq = gpiod_to_irq(hdata->hpd_gpio);
+   if (hdata->irq < 0) {
+   DRM_ERROR("failed to get GPIO irq\n");
+   return  hdata->irq;
+   }
/* get clocks, power */
res->hdmi = devm_clk_get(dev, "hdmi");
if (IS_ERR(res->hdmi)) {
@@ -1909,11 +1918,6 @@ static int hdmi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hdata);

hdata->dev = dev;
-   hdata->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpio", 0);
-   if (hdata->hpd_gpio < 0) {
-   DRM_ERROR("cannot get hpd gpio property\n");
-   return hdata->hpd_gpio;
-   }

ret = hdmi_resources_init(hdata);
if (ret) {
@@ -1928,12 +1932,6 @@ static int hdmi_probe(struct platform_device *pdev)
return ret;
}

-   ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
-   if (ret) {
-   DRM_ERROR("failed to request HPD gpio\n");
-   return ret;
-   }
-
ddc_node = hdmi_legacy_ddc_dt_binding(dev);
if (ddc_node)
goto out_get_ddc_adpt;
@@ -1981,13 +1979,6 @@ out_get_phy_port:
}
}

-   hdata->irq = gpio_to_irq(hdata->hpd_gpio);
-   if (hdata->irq < 0) {
-   DRM_ERROR("failed to get GPIO irq\n");
-   ret = hdata->irq;
-   goto err_hdmiphy;
-   }
-
INIT_DELAYED_WORK(>hotplug_work, hdmi_hotplug_work_func);

ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
-- 
1.9.1



[PATCH 10/16] drm/exynos/hdmi: simplify clock re-parenting

2015-09-25 Thread Andrzej Hajda
Driver tries to disable sclk_hdmi during re-parenting, to avoid possible
glitches. It is ineffective as the clock is used also by other devices (mixer).
Anyway driver works without disabling sclk_hdmi.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 583dd5e..475341f 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1569,9 +1569,7 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)

hdmiphy_wait_for_pll(hdata);

-   clk_disable_unprepare(hdata->res.sclk_hdmi);
clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
-   clk_prepare_enable(hdata->res.sclk_hdmi);

/* enable HDMI and timing generator */
hdmi_start(hdata, true);
@@ -1579,9 +1577,7 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)

 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 {
-   clk_disable_unprepare(hdata->res.sclk_hdmi);
clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
-   clk_prepare_enable(hdata->res.sclk_hdmi);

/* reset hdmiphy */
hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
-- 
1.9.1



[PATCH 09/16] drm/exynos/hdmi: use constant size array for regulators

2015-09-25 Thread Andrzej Hajda
Driver always uses the same number of regulators, so there is no point in
dynamic allocation.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 25 +
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 841470c..583dd5e 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -83,6 +83,12 @@ static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
{ HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
 };

+static const char * const supply[] = {
+   "vdd",
+   "vdd_osc",
+   "vdd_pll",
+};
+
 struct hdmi_driver_data {
unsigned int type;
const struct hdmiphy_config *phy_confs;
@@ -96,9 +102,8 @@ struct hdmi_resources {
struct clk  *sclk_pixel;
struct clk  *sclk_hdmiphy;
struct clk  *mout_hdmi;
-   struct regulator_bulk_data  *regul_bulk;
+   struct regulator_bulk_data  regul_bulk[ARRAY_SIZE(supply)];
struct regulator*reg_hdmi_en;
-   int regul_count;
 };

 struct hdmi_context {
@@ -1652,7 +1657,7 @@ static void hdmi_enable(struct drm_encoder *encoder)

pm_runtime_get_sync(hdata->dev);

-   if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
+   if (regulator_bulk_enable(ARRAY_SIZE(supply), res->regul_bulk))
DRM_DEBUG_KMS("failed to enable regulator bulk\n");

/* set pmu hdmiphy control bit to enable hdmiphy */
@@ -1701,7 +1706,7 @@ static void hdmi_disable(struct drm_encoder *encoder)
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
PMU_HDMI_PHY_ENABLE_BIT, 0);

-   regulator_bulk_disable(res->regul_count, res->regul_bulk);
+   regulator_bulk_disable(ARRAY_SIZE(supply), res->regul_bulk);

pm_runtime_put_sync(hdata->dev);

@@ -1743,11 +1748,6 @@ static int hdmi_resources_init(struct hdmi_context 
*hdata)
 {
struct device *dev = hdata->dev;
struct hdmi_resources *res = >res;
-   static char *supply[] = {
-   "vdd",
-   "vdd_osc",
-   "vdd_pll",
-   };
int i, ret;

DRM_DEBUG_KMS("HDMI resource init\n");
@@ -1786,12 +1786,6 @@ static int hdmi_resources_init(struct hdmi_context 
*hdata)

clk_set_parent(res->mout_hdmi, res->sclk_pixel);

-   res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
-   sizeof(res->regul_bulk[0]), GFP_KERNEL);
-   if (!res->regul_bulk) {
-   ret = -ENOMEM;
-   goto fail;
-   }
for (i = 0; i < ARRAY_SIZE(supply); ++i) {
res->regul_bulk[i].supply = supply[i];
res->regul_bulk[i].consumer = NULL;
@@ -1801,7 +1795,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
DRM_ERROR("failed to get regulators\n");
return ret;
}
-   res->regul_count = ARRAY_SIZE(supply);

res->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");

-- 
1.9.1



[PATCH 08/16] drm/exynos/hdmi: use optional regulator_get for hdmi-en

2015-09-25 Thread Andrzej Hajda
hdmi-en is an optional regulator so it should be better handled by
devm_regulator_get_optional call.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 725ddb5..841470c 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1803,19 +1803,17 @@ static int hdmi_resources_init(struct hdmi_context 
*hdata)
}
res->regul_count = ARRAY_SIZE(supply);

-   res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
-   if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
-   DRM_ERROR("failed to get hdmi-en regulator\n");
+   res->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
+
+   if (PTR_ERR(res->reg_hdmi_en) == -ENODEV)
+   return 0;
+
+   if (IS_ERR(res->reg_hdmi_en))
return PTR_ERR(res->reg_hdmi_en);
-   }
-   if (!IS_ERR(res->reg_hdmi_en)) {
-   ret = regulator_enable(res->reg_hdmi_en);
-   if (ret) {
-   DRM_ERROR("failed to enable hdmi-en regulator\n");
-   return ret;
-   }
-   } else
-   res->reg_hdmi_en = NULL;
+
+   ret = regulator_enable(res->reg_hdmi_en);
+   if (ret)
+   DRM_ERROR("failed to enable hdmi-en regulator\n");

return ret;
 fail:
@@ -2050,7 +2048,7 @@ static int hdmi_remove(struct platform_device *pdev)

pm_runtime_disable(>dev);

-   if (hdata->res.reg_hdmi_en)
+   if (!IS_ERR(hdata->res.reg_hdmi_en))
regulator_disable(hdata->res.reg_hdmi_en);

if (hdata->hdmiphy_port)
-- 
1.9.1



[PATCH 07/16] drm/exynos/hdmi: fix removal order

2015-09-25 Thread Andrzej Hajda
DRM device should be destroyed before releasing resources.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 50ced709..725ddb5 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -2046,15 +2046,17 @@ static int hdmi_remove(struct platform_device *pdev)

cancel_delayed_work_sync(>hotplug_work);

+   component_del(>dev, _component_ops);
+
+   pm_runtime_disable(>dev);
+
if (hdata->res.reg_hdmi_en)
regulator_disable(hdata->res.reg_hdmi_en);

if (hdata->hdmiphy_port)
put_device(>hdmiphy_port->dev);
-   put_device(>ddc_adpt->dev);

-   pm_runtime_disable(>dev);
-   component_del(>dev, _component_ops);
+   put_device(>ddc_adpt->dev);

return 0;
 }
-- 
1.9.1



[PATCH 06/16] drm/exynos/hdmi: replace all writeb with writel

2015-09-25 Thread Andrzej Hajda
Registers are 32-bit, even if only lower 8-bits are used.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 814dd8c..50ced709 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -537,7 +537,7 @@ static inline u32 hdmi_reg_read(struct hdmi_context *hdata, 
u32 reg_id)
 static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
 u32 reg_id, u8 value)
 {
-   writeb(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
+   writel(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
 }

 static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
@@ -546,7 +546,7 @@ static inline void hdmi_reg_writev(struct hdmi_context 
*hdata, u32 reg_id,
reg_id = hdmi_map_reg(hdata, reg_id);

while (--bytes >= 0) {
-   writeb(val & 0xff, hdata->regs + reg_id);
+   writel(val & 0xff, hdata->regs + reg_id);
val >>= 8;
reg_id += 4;
}
@@ -579,7 +579,7 @@ static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
} else {
int i;
for (i = 0; i < len; i++)
-   writeb(buf[i], hdata->regs_hdmiphy +
+   writel(buf[i], hdata->regs_hdmiphy +
((reg_offset + i)<<2));
return 0;
}
-- 
1.9.1



[PATCH 05/16] drm/exynos/hdmi: simplify HDMI-PHY power sequence

2015-09-25 Thread Andrzej Hajda
Currently driver tries to set specific HDMI-PHY registers in three situations:
- before reset,
- before power off,
- after applying HDMI-PHY configuration.

First two cases seems to be unnecessary - register contents will be lost
anyway. The third case can be merged with HDMI-PHY configuration by fixing
the last byte of configuration data.

The patch has been tested with following platforms:
- exynos4210-universal_c210,
- exynos4412-odroidu3,
- exynos5422-odroidxu3.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 93 
 1 file changed, 8 insertions(+), 85 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 414ea2d..814dd8c 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -148,7 +148,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
-   0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
+   0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
},
},
{
@@ -157,7 +157,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
-   0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
+   0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x80,
},
},
{
@@ -166,7 +166,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
-   0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
+   0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80,
},
},
{
@@ -175,7 +175,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
-   0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
+   0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80,
},
},
{
@@ -184,7 +184,7 @@ static const struct hdmiphy_config hdmiphy_v13_configs[] = {
0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
-   0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
+   0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80,
},
},
 };
@@ -214,7 +214,7 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-   0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
+   0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80,
},
},
{
@@ -277,7 +277,7 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-   0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
+   0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80,
},
},
{
@@ -340,7 +340,7 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = {
0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
-   0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
+   0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
},
},
 };
@@ -563,26 +563,6 @@ static inline void hdmi_reg_writemask(struct hdmi_context 
*hdata,
writel(value, hdata->regs + reg_id);
 }

-static int hdmiphy_reg_writeb(struct hdmi_context *hdata,
-   u32 reg_offset, u8 value)
-{
-   if (hdata->hdmiphy_port) {
-   u8 buffer[2];
- 

[PATCH 04/16] drm/exynos/hdmi: move PLL stabilization check code to separate function

2015-09-25 Thread Andrzej Hajda
The patch moves PLL stabilization check to separate function, adjust timeout
parameters and de-duplicates code common for both HW variants.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 68 ++--
 1 file changed, 26 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 6221803..414ea2d 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1351,11 +1351,27 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
}
 }

+static void hdmiphy_wait_for_pll(struct hdmi_context *hdata)
+{
+   int tries;
+
+   for (tries = 0; tries < 10; ++tries) {
+   u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
+
+   if (val & HDMI_PHY_STATUS_READY) {
+   DRM_DEBUG_KMS("PLL stabilized after %d tries\n", tries);
+   return;
+   }
+   usleep_range(10, 20);
+   }
+
+   DRM_ERROR("PLL could not reach steady state\n");
+}
+
 static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
 {
struct drm_display_mode *m = >current_mode;
unsigned int val;
-   int tries;

hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
hdmi_reg_writev(hdata, HDMI_V13_H_V_LINE_0, 3,
@@ -1441,32 +1457,11 @@ static void hdmi_v13_mode_apply(struct hdmi_context 
*hdata)
hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
-
-   /* waiting for HDMIPHY's PLL to get to steady state */
-   for (tries = 100; tries; --tries) {
-   u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
-   if (val & HDMI_PHY_STATUS_READY)
-   break;
-   usleep_range(1000, 2000);
-   }
-   /* steady state not achieved */
-   if (tries == 0) {
-   DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
-   hdmi_regs_dump(hdata, "timing apply");
-   }
-
-   clk_disable_unprepare(hdata->res.sclk_hdmi);
-   clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
-   clk_prepare_enable(hdata->res.sclk_hdmi);
-
-   /* enable HDMI and timing generator */
-   hdmi_start(hdata, true);
 }

 static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
 {
struct drm_display_mode *m = >current_mode;
-   int tries;

hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay);
hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
@@ -1578,26 +1573,6 @@ static void hdmi_v14_mode_apply(struct hdmi_context 
*hdata)
hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
hdmi_reg_writev(hdata, HDMI_TG_3D, 1, 0x0);
-
-   /* waiting for HDMIPHY's PLL to get to steady state */
-   for (tries = 100; tries; --tries) {
-   u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
-   if (val & HDMI_PHY_STATUS_READY)
-   break;
-   usleep_range(1000, 2000);
-   }
-   /* steady state not achieved */
-   if (tries == 0) {
-   DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
-   hdmi_regs_dump(hdata, "timing apply");
-   }
-
-   clk_disable_unprepare(hdata->res.sclk_hdmi);
-   clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
-   clk_prepare_enable(hdata->res.sclk_hdmi);
-
-   /* enable HDMI and timing generator */
-   hdmi_start(hdata, true);
 }

 static void hdmi_mode_apply(struct hdmi_context *hdata)
@@ -1606,6 +1581,15 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)
hdmi_v13_mode_apply(hdata);
else
hdmi_v14_mode_apply(hdata);
+
+   hdmiphy_wait_for_pll(hdata);
+
+   clk_disable_unprepare(hdata->res.sclk_hdmi);
+   clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
+   clk_prepare_enable(hdata->res.sclk_hdmi);
+
+   /* enable HDMI and timing generator */
+   hdmi_start(hdata, true);
 }

 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
-- 
1.9.1



[PATCH 03/16] drm/exynos/hdmi: use mappings for registers with IP dependent address

2015-09-25 Thread Andrzej Hajda
Some registers resides at different offsets depending on device version.
This patch adds infrastructure for mapping such registers to proper address
based on hdmi_type. It adds also mappings to some registers.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 56 +++-
 drivers/gpu/drm/exynos/regs-hdmi.h   |  4 +--
 2 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index c25b892..6221803 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -66,6 +66,21 @@
 enum hdmi_type {
HDMI_TYPE13,
HDMI_TYPE14,
+   HDMI_TYPE_COUNT
+};
+
+#define HDMI_MAPPED_BASE 0x
+
+enum hdmi_mapped_regs {
+   HDMI_PHY_STATUS = HDMI_MAPPED_BASE,
+   HDMI_PHY_RSTOUT,
+   HDMI_ACR_CON,
+};
+
+static const u32 hdmi_reg_map[][HDMI_TYPE_COUNT] = {
+   { HDMI_V13_PHY_STATUS, HDMI_PHY_STATUS_0 },
+   { HDMI_V13_PHY_RSTOUT, HDMI_V14_PHY_RSTOUT },
+   { HDMI_V13_ACR_CON, HDMI_V14_ACR_CON },
 };

 struct hdmi_driver_data {
@@ -507,20 +522,29 @@ static struct hdmi_driver_data 
exynos4210_hdmi_driver_data = {
.is_apb_phy = 0,
 };

+static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
+{
+   if ((reg_id & 0x) == HDMI_MAPPED_BASE)
+   return hdmi_reg_map[reg_id & 0x][hdata->drv_data->type];
+   return reg_id;
+}
+
 static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
 {
-   return readl(hdata->regs + reg_id);
+   return readl(hdata->regs + hdmi_map_reg(hdata, reg_id));
 }

 static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
 u32 reg_id, u8 value)
 {
-   writeb(value, hdata->regs + reg_id);
+   writeb(value, hdata->regs + hdmi_map_reg(hdata, reg_id));
 }

 static inline void hdmi_reg_writev(struct hdmi_context *hdata, u32 reg_id,
   int bytes, u32 val)
 {
+   reg_id = hdmi_map_reg(hdata, reg_id);
+
while (--bytes >= 0) {
writeb(val & 0xff, hdata->regs + reg_id);
val >>= 8;
@@ -531,7 +555,10 @@ static inline void hdmi_reg_writev(struct hdmi_context 
*hdata, u32 reg_id,
 static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
 u32 reg_id, u32 value, u32 mask)
 {
-   u32 old = readl(hdata->regs + reg_id);
+   u32 old;
+
+   reg_id = hdmi_map_reg(hdata, reg_id);
+   old = readl(hdata->regs + reg_id);
value = (value & mask) | (old & ~mask);
writel(value, hdata->regs + reg_id);
 }
@@ -682,7 +709,7 @@ static void hdmi_v14_regs_dump(struct hdmi_context *hdata, 
char *prefix)
DUMPREG(HDMI_PHY_STATUS_0);
DUMPREG(HDMI_PHY_STATUS_PLL);
DUMPREG(HDMI_PHY_CON_0);
-   DUMPREG(HDMI_PHY_RSTOUT);
+   DUMPREG(HDMI_V14_PHY_RSTOUT);
DUMPREG(HDMI_PHY_VPLL);
DUMPREG(HDMI_PHY_CMU);
DUMPREG(HDMI_CORE_RSTOUT);
@@ -1162,11 +1189,7 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 
*acr)
hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
-
-   if (hdata->drv_data->type == HDMI_TYPE13)
-   hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
-   else
-   hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
+   hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
 }

 static void hdmi_audio_init(struct hdmi_context *hdata)
@@ -1421,7 +1444,7 @@ static void hdmi_v13_mode_apply(struct hdmi_context 
*hdata)

/* waiting for HDMIPHY's PLL to get to steady state */
for (tries = 100; tries; --tries) {
-   u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
+   u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
if (val & HDMI_PHY_STATUS_READY)
break;
usleep_range(1000, 2000);
@@ -1558,7 +1581,7 @@ static void hdmi_v14_mode_apply(struct hdmi_context 
*hdata)

/* waiting for HDMIPHY's PLL to get to steady state */
for (tries = 100; tries; --tries) {
-   u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
+   u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS);
if (val & HDMI_PHY_STATUS_READY)
break;
usleep_range(1000, 2000);
@@ -1587,8 +1610,6 @@ static void hdmi_mode_apply(struct hdmi_context *hdata)

 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 {
-   u32 reg;
-
clk_disable_unprepare(hdata->res.sclk_hdmi);
clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
clk_prepare_enable(hdata->res.sclk_hdmi);
@@ -1597,15 +1618,10 @@ static void hdmiphy_conf_reset(struct hdmi_context 
*hdata)
hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE,
  

[PATCH 02/16] dt-bindings: remove deprecated compatible string from exynos-hdmi

2015-09-25 Thread Andrzej Hajda
samsung,exynos5-hdmi compatible was marked as deprecated in Jun 2013.
It was never used since then.

Signed-off-by: Andrzej Hajda 
---
 Documentation/devicetree/bindings/video/exynos_hdmi.txt | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_hdmi.txt 
b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
index 1fd8cf9..d474f59 100644
--- a/Documentation/devicetree/bindings/video/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
@@ -2,10 +2,9 @@ Device-Tree bindings for drm hdmi driver

 Required properties:
 - compatible: value should be one among the following:
-   1) "samsung,exynos5-hdmi" 
-   2) "samsung,exynos4210-hdmi"
-   3) "samsung,exynos4212-hdmi"
-   4) "samsung,exynos5420-hdmi"
+   1) "samsung,exynos4210-hdmi"
+   2) "samsung,exynos4212-hdmi"
+   3) "samsung,exynos5420-hdmi"
 - reg: physical base address of the hdmi and length of memory mapped
region.
 - interrupts: interrupt number to the cpu.
-- 
1.9.1



[PATCH 01/16] drm/exynos/hdmi: remove support for deprecated compatible

2015-09-25 Thread Andrzej Hajda
This compatible was marked as deprecated in Jun 2013 and it is not used since
then. Additionally its driver data points to wrong pll settings, so it
cannot work anyway.

Signed-off-by: Andrzej Hajda 
---
 drivers/gpu/drm/exynos/exynos_hdmi.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 932f7fa..c25b892 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -507,13 +507,6 @@ static struct hdmi_driver_data exynos4210_hdmi_driver_data 
= {
.is_apb_phy = 0,
 };

-static struct hdmi_driver_data exynos5_hdmi_driver_data = {
-   .type   = HDMI_TYPE14,
-   .phy_confs  = hdmiphy_v13_configs,
-   .phy_conf_count = ARRAY_SIZE(hdmiphy_v13_configs),
-   .is_apb_phy = 0,
-};
-
 static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
 {
return readl(hdata->regs + reg_id);
@@ -1909,9 +1902,6 @@ fail:

 static struct of_device_id hdmi_match_types[] = {
{
-   .compatible = "samsung,exynos5-hdmi",
-   .data = _hdmi_driver_data,
-   }, {
.compatible = "samsung,exynos4210-hdmi",
.data = _hdmi_driver_data,
}, {
-- 
1.9.1



[PATCH 00/16] drm/exynos/hdmi: refactoring/cleanup patches

2015-09-25 Thread Andrzej Hajda
Hi,

This is another set of cleanup/improvement patches for HDMI.

The patchset is based on exynos-drm-next.
It was tested on Universal and Odroid U3.

Regards
Andrzej


Andrzej Hajda (15):
  drm/exynos/hdmi: remove support for deprecated compatible
  dt-bindings: remove deprecated compatible string from exynos-hdmi
  drm/exynos/hdmi: use mappings for registers with IP dependent address
  drm/exynos/hdmi: move PLL stabilization check code to separate
function
  drm/exynos/hdmi: simplify HDMI-PHY power sequence
  drm/exynos/hdmi: replace all writeb with writel
  drm/exynos/hdmi: fix removal order
  drm/exynos/hdmi: use optional regulator_get for hdmi-en
  drm/exynos/hdmi: use constant size array for regulators
  drm/exynos/hdmi: simplify clock re-parenting
  drm/exynos/hdmi: convert to gpiod API
  drm/exynos/hdmi: remove deprecated hdmi_resources structure
  drm/exynos/hdmi: convert container_of macro to inline function
  drm/exynos/hdmi: improve HDMI/ACR related code
  drm/exynos/hdmi: remove unused field

Tomasz Stanislawski (1):
  drm: exynos: mixer: fix using usleep() in atomic context

 .../devicetree/bindings/video/exynos_hdmi.txt  |   7 +-
 drivers/gpu/drm/exynos/exynos_hdmi.c   | 491 +++--
 drivers/gpu/drm/exynos/exynos_mixer.c  |   2 +-
 drivers/gpu/drm/exynos/regs-hdmi.h |  33 +-
 4 files changed, 189 insertions(+), 344 deletions(-)

-- 
1.9.1



[PATCH 1/2] drm: Add SCDC helpers

2015-09-25 Thread Ville Syrjälä
On Thu, Sep 24, 2015 at 06:51:34PM +0200, Thierry Reding wrote:
> From: Thierry Reding 
> 
> SCDC is a mechanism defined in the HDMI 2.0 specification that allows
> the source and sink devices to communicate.
> 
> This commit introduces helpers to access the SCDC and provides the
> symbolic names for the various registers defined in the specification.
> 
> Signed-off-by: Thierry Reding 
> ---
>  Documentation/DocBook/drm.tmpl|   6 ++
>  drivers/gpu/drm/Kconfig   |   4 ++
>  drivers/gpu/drm/Makefile  |   1 +
>  drivers/gpu/drm/drm_scdc_helper.c | 111 ++
>  include/drm/drm_scdc_helper.h | 124 
> ++
>  5 files changed, 246 insertions(+)
>  create mode 100644 drivers/gpu/drm/drm_scdc_helper.c
>  create mode 100644 include/drm/drm_scdc_helper.h
> 
> diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
> index b4cc6b77d382..3045be492125 100644
> --- a/Documentation/DocBook/drm.tmpl
> +++ b/Documentation/DocBook/drm.tmpl
> @@ -2410,6 +2410,12 @@ void intel_crt_init(struct drm_device *dev)
>  !Edrivers/gpu/drm/drm_hdcp_helper.c
>  
>  
> +  SCDC Helper Functions Reference
> +!Pdrivers/gpu/drm/drm_scdc_helper.c scdc helpers
> +!Iinclude/drm/drm_scdc_helper.h
> +!Edrivers/gpu/drm/drm_scdc_helper.c
> +
> +
>EDID Helper Functions Reference
>  !Edrivers/gpu/drm/drm_edid.c
>  
> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> index fb3a815b53f6..5dc23278be27 100644
> --- a/drivers/gpu/drm/Kconfig
> +++ b/drivers/gpu/drm/Kconfig
> @@ -64,6 +64,10 @@ config DRM_HDCP
>   bool
>   depends on DRM_KMS_HELPER
>  
> +config DRM_SCDC
> + bool
> + depends on DRM_KMS_HELPER
> +
>  config DRM_LOAD_EDID_FIRMWARE
>   bool "Allow to specify an EDID data set instead of probing for it"
>   depends on DRM_KMS_HELPER
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index c4a02a181115..e22c3dff4ae5 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -23,6 +23,7 @@ drm-$(CONFIG_OF) += drm_of.o
>  drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
>   drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
>  drm_kms_helper-$(CONFIG_DRM_HDCP) += drm_hdcp_helper.o
> +drm_kms_helper-$(CONFIG_DRM_SCDC) += drm_scdc_helper.o
>  drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
>  drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
>  drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
> diff --git a/drivers/gpu/drm/drm_scdc_helper.c 
> b/drivers/gpu/drm/drm_scdc_helper.c
> new file mode 100644
> index ..dbc9c770f5b4
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_scdc_helper.c
> @@ -0,0 +1,111 @@
> +/*
> + * Copyright (c) 2015 NVIDIA Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sub license,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial portions
> + * of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include 
> +
> +#include 
> +
> +/**
> + * DOC: scdc helpers
> + *
> + * Status and Control Data Channel (SCDC) is a mechanism introduced by the
> + * HDMI 2.0 specification. It is a point-to-point protocol that allows the
> + * HDMI source and HDMI sink to exchange data. The same I2C interface that
> + * is used to access EDID serves as the transport mechanism for SCDC.
> + */
> +
> +#define SCDC_I2C_SLAVE_ADDRESS 0x54
> +
> +/**
> + * drm_scdc_read - read a block of data from SCDC
> + * @adapter: I2C controller
> + * @offset: start offset of block to read
> + * @buffer: return location for the block to read
> + * @size: size of the block to read
> + *
> + * Reads a block of data from SCDC, starting at a given offset.
> + *
> + * Returns:
> + * The number of bytes read from SCDC or a negative error code on failure.
> + */
> +ssize_t drm_scdc_read(struct i2c_adapter *adapter, u8 offset, void *buffer,

[PATCH 2/2] drm/edid: Implement SCDC support detection

2015-09-25 Thread Ville Syrjälä
On Thu, Sep 24, 2015 at 06:51:35PM +0200, Thierry Reding wrote:
> From: Thierry Reding 
> 
> Sinks compliant with the HDMI 2.0 specification may support SCDC, a
> mechanism for the source and the sink to communicate. Sinks advertise
> support for this feature in the HDMI Forum Vendor Specific Data Block
> as defined in the HDMI 2.0 specification, section 10.4 "Status and
> Control Data Channel". Implement a small helper that find the HF-VSDB
> and parses it to check if the sink supports SCDC.
> 
> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/drm_edid.c | 49 
> ++
>  include/drm/drm_crtc.h |  1 +
>  include/linux/hdmi.h   |  1 +
>  3 files changed, 51 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index d895556be4f0..af4da105d66e 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3059,6 +3059,21 @@ static bool cea_db_is_hdmi_vsdb(const u8 *db)
>   return hdmi_id == HDMI_IEEE_OUI;
>  }
>  
> +static bool cea_db_is_hf_vsdb(const u8 *db)

I would spell out the hdmi_forum here. Otherwise it's starting to look
like random alphabet soup.

> +{
> + unsigned int oui;
> +
> + if (cea_db_tag(db) != VENDOR_BLOCK)
> + return false;
> +
> + if (cea_db_payload_len(db) < 7)
> + return false;
> +
> + oui = db[3] << 16 | db[2] << 8 | db[1];
> +
> + return oui == HDMI_FORUM_IEEE_OUI;
> +}
> +
>  #define for_each_cea_db(cea, i, start, end) \
>   for ((i) = (start); (i) < (end) && (i) + 
> cea_db_payload_len(&(cea)[(i)]) < (end); (i) += 
> cea_db_payload_len(&(cea)[(i)]) + 1)
>  
> @@ -3454,6 +3469,40 @@ bool drm_detect_hdmi_monitor(struct edid *edid)
>  EXPORT_SYMBOL(drm_detect_hdmi_monitor);
>  
>  /**
> + * drm_detect_hdmi_scdc - detect whether an HDMI sink supports SCDC
> + * @edid: sink EDID information
> + *
> + * Parse the CEA extension according to CEA-861-B to find an HF-VSDB as
> + * defined in HDMI 2.0, section 10.3.2 "HDMI Forum Vendor Specific Data
> + * Block" and checks if the SCDC_Present bit (bit 7 of byte 6) is set.
> + *
> + * Returns:
> + * True if the sink supports SCDC, false otherwise.
> + */
> +bool drm_detect_hdmi_scdc(struct edid *edid)
> +{
> + unsigned int start, end, i;
> + const u8 *cea;
> +
> + cea = drm_find_cea_extension(edid);
> + if (!cea)
> + return false;
> +
> + if (cea_db_offsets(cea, , ))
> + return false;
> +
> + for_each_cea_db(cea, i, start, end) {
> + if (cea_db_is_hf_vsdb([i])) {
> + if (cea[i + 6] & 0x80)
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +EXPORT_SYMBOL(drm_detect_hdmi_scdc);
> +
> +/**
>   * drm_detect_monitor_audio - check monitor audio capability
>   * @edid: EDID block to scan
>   *
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 53a6f2455f35..5d0b88e4a80b 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1513,6 +1513,7 @@ extern enum hdmi_picture_aspect 
> drm_get_cea_aspect_ratio(const u8 video_code);
>  extern bool drm_detect_hdmi_monitor(struct edid *edid);
>  extern bool drm_detect_monitor_audio(struct edid *edid);
>  extern bool drm_rgb_quant_range_selectable(struct edid *edid);
> +extern bool drm_detect_hdmi_scdc(struct edid *edid);
>  extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
>   void *data, struct drm_file *file_priv);
>  extern int drm_add_modes_noedid(struct drm_connector *connector,
> diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
> index e9744202fa29..f860071e2d5a 100644
> --- a/include/linux/hdmi.h
> +++ b/include/linux/hdmi.h
> @@ -35,6 +35,7 @@ enum hdmi_infoframe_type {
>  };
>  
>  #define HDMI_IEEE_OUI 0x000c03
> +#define HDMI_FORUM_IEEE_OUI 0xc45dd8
>  #define HDMI_INFOFRAME_HEADER_SIZE  4
>  #define HDMI_AVI_INFOFRAME_SIZE13
>  #define HDMI_SPD_INFOFRAME_SIZE25
> -- 
> 2.5.0
> 
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Ville Syrjälä
Intel OTC


[patch] drm/amdgpu: signedness bug in amdgpu_cs_parser_init()

2015-09-25 Thread Dan Carpenter
The "i" variable should be signed or it leads to a crash in the error
handling code.

Fixes: 1d263474c441 ('drm/amdgpu: unwind properly in amdgpu_cs_parser_init()')
Signed-off-by: Dan Carpenter 

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 749420f..cb3c274 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -156,7 +156,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void 
*data)
uint64_t *chunk_array_user;
uint64_t *chunk_array;
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
-   unsigned size, i;
+   unsigned size;
+   int i;
int ret;

if (cs->in.num_chunks == 0)


[PATCH] drm/i915: fix task reference leak in i915_debugfs.c

2015-09-25 Thread Daniel Vetter
On Fri, Sep 25, 2015 at 02:16:07PM +0300, Jani Nikula wrote:
> On Fri, 25 Sep 2015, Geliang Tang  wrote:
> > Leak a task reference in i915_ppgtt_info(), add put_task_struct()
> > to fix it.
> 
> Introduced by
> 
> commit 1c60fef535d143860d5bf6593e24ab6417f5227c
> Author: Ben Widawsky 
> Date:   Fri Dec 6 14:11:30 2013 -0800
> 
> drm/i915: Dump all ppgtt

Queued for -next, thanks for the patch.
-Daniel

> 
> 
> >
> > Signed-off-by: Geliang Tang 
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c | 8 ++--
> >  1 file changed, 6 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
> > b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 5615d3d..8797717 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -2288,9 +2288,13 @@ static int i915_ppgtt_info(struct seq_file *m, void 
> > *data)
> >  
> > list_for_each_entry_reverse(file, >filelist, lhead) {
> > struct drm_i915_file_private *file_priv = file->driver_priv;
> > +   struct task_struct *task;
> >  
> > -   seq_printf(m, "\nproc: %s\n",
> > -  get_pid_task(file->pid, PIDTYPE_PID)->comm);
> > +   task = get_pid_task(file->pid, PIDTYPE_PID);
> > +   if (!task)
> > +   return -ESRCH;
> > +   seq_printf(m, "\nproc: %s\n", task->comm);
> > +   put_task_struct(task);
> > idr_for_each(_priv->context_idr, per_file_ctx,
> >  (void *)(unsigned long)m);
> > }
> > -- 
> > 1.9.1
> >
> >
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center
> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

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


[PATCH 09/16] drm/irq: Use unsigned int pipe in public API

2015-09-25 Thread Thierry Reding
On Thu, Sep 24, 2015 at 11:20:54PM +0300, Ville Syrjälä wrote:
> On Thu, Sep 24, 2015 at 08:21:53PM +0100, Russell King - ARM Linux wrote:
> > On Thu, Sep 24, 2015 at 06:35:31PM +0200, Thierry Reding wrote:
> > > This continues the pattern started in commit cc1ef118fc09 ("drm/irq:
> > > Make pipe unsigned and name consistent"). This is applied to the public
> > > APIs and driver callbacks, so pretty much all drivers need to be updated
> > > to match the new prototypes.
> > 
> > I don't like being forced to use the "pipe" naming in all drivers; I
> > found that really confusing when I first looked at DRM, and it took
> > a long time to work out that "pipe" basically means "crtc" or "gpu".
> 
> crtc mean "cathode ray tube controller". If you weren't used to it,
> it would be pretty much impossible to guess what piece of modern
> hardware that means. So I think it's more a case of "a lot of this
> junk used to be in what people called the crtc, so we'll call
> this modern thing a crtc too". Although I think most of the
> hardware people moved on from using that name quite a long time ago.
> 
> "gpu" can mean either just the part that does the rendering and 
> whatnot, or it can mean the entire graphics "card". But calling
> a display pipeline a "gpu" is not done. Now _that_ would be
> confusing.
> 
> "pipe" is fairly nice term, meaning "pipeline". That describes the
> thing quite nicely. Stuff comes in from one end, flows through the
> pipe, and goes out the other end.
> 
> At least both Intel and OMAP used the term pipe or pipeline in the
> hardware docs. Can't really say aything about other brands, at least
> if I discount the more ancient junk I'm familiar with.
> 
> > What's wrong with keeping "crtc" as the index terminology for crtc
> > things?  Surely that's more descriptive of what's going on here?
> 
> I can't speak for Thierry, but I assume the real motivation for this
> renaming was to make it clear which is the "index", and which is the
> crtc object. "pipe" for one, "crtc" for the other. Avoids having
> to call the object "dcrtc", "drm_crtc" or something else entirely.
> And since the object is called "crtc" everywhere else, it's nice not
> to have to make an exception in the vblank code.

Exactly this. I find it to be very confusing to read through drivers and
see completely inconsistent naming for what's really the same thing. The
list isn't limited to "pipe", "crtc" or "index". There are others that
use "head" or "crtc_id". The latter in particular is very confusing
because, at least in most of the cases I've seen, it refers to the pipe
rather than the CRTC object ID.

That said this is all only temporary, though it may take us a while to
get rid of it. The ultimate goal is to convert all drivers over to using
struct drm_crtc * everywhere, at which point we don't have to bother
with what to call the CRTC index. As a preliminary step, having drivers
use consistent naming is hopefully going to make it easier to replace.

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


PROBLEM: Intel VGA output busticated on 4.3-rc2 (regression)

2015-09-25 Thread Daniel Vetter
Another regression for Jairo to track.
-Daniel

On Thu, Sep 24, 2015 at 05:22:09PM -0400, Nick Bowler wrote:
> Hi,
> 
> Testing out 4.3-rc2, first thing I notice is that the VGA output is
> not working.  Specifically, the display is continuously powering on
> and off -- at no point is any image visible on the screen (I am expecting
> to see the console output).  The display connected to the HDMI output is
> working fine.
> 
> Linux 4.2 did not suffer from this problem.
> 
> In dmesg I see the following messages, which I do not see on a working
> kernel.  Full dmesg from 4.3-rc2 is attached (gzipped).
> 
>   [0.115339] [drm:drm_calc_timestamping_constants] *ERROR* crtc
> 21: Can't calculate constants, dotclock = 0!
>   [0.117582] [drm:intel_opregion_init] *ERROR* No ACPI video bus found
> 
> This is an older machine with Intel G45 graphics.
> 
> Unfortunately bisection is proving difficult, because the commits it
> wants me to test have a different problem: neither display comes up at
> all (both remain in standby).  Partial results follow.
> 
> Thanks,
>   Nick
> 
>   git bisect start 'drivers/gpu/drm/i915'
>   # bad: [1f93e4a96c9109378204c147b3eec0d0e8100fde] Linux 4.3-rc2
>   git bisect bad 1f93e4a96c9109378204c147b3eec0d0e8100fde
>   # good: [64291f7db5bd8150a74ad2036f1037e6a0428df2] Linux 4.2
>   git bisect good 64291f7db5bd8150a74ad2036f1037e6a0428df2
>   # skip: [a7a6c498927ea42c9a3b26e0caa5c854a980d58c] drm/i915:
> POSTING_READ() in intel_set_memory_cxsr()
>   git bisect skip a7a6c498927ea42c9a3b26e0caa5c854a980d58c
>   # skip: [031b698a77a70a6c394568034437b5486a44e868] drm/i915:
> Unconditionally do fb tracking invalidate in set_domain
>   git bisect skip 031b698a77a70a6c394568034437b5486a44e868
>   # skip: [adeca76d8e2b34b5c739a36f4191aed63080da40] drm/i915:
> Simplify i915_gem_execbuffer_retire_commands() parameters
>   git bisect skip adeca76d8e2b34b5c739a36f4191aed63080da40
>   # good: [369712e89404089fa559235bb1ee8fc40d976e6b] drm/i915: reduce
> duplicate conditions in i9xx_hpd_irq_handler
>   git bisect good 369712e89404089fa559235bb1ee8fc40d976e6b
>   # skip: [6eb1a6817246f1a67de4d6959a84d09efead5329] drm/i915: Read wm
> values from hardware at init on CHV
>   git bisect skip 6eb1a6817246f1a67de4d6959a84d09efead5329
>   # bad: [d14e7b6d1d8747826cb900db852351c550e00fdd] drm/i915: Check DP
> link status on long hpd too
>   git bisect bad d14e7b6d1d8747826cb900db852351c550e00fdd
>   # skip: [fe36f55d4d4447679923fc74564786ae423ca4bd] drm/i915/gtt:
> Cleanup page directory encoding
>   git bisect skip fe36f55d4d4447679923fc74564786ae423ca4bd


> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


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


[PULL] topic/drm-misc

2015-09-25 Thread Daniel Vetter
Hi Dave,

Another attempt at drm-misc for 4.4 ...
- better atomic helpers for runtime pm drivers
- atomic fbdev
- dp aux i2c STATUS_UPDATE handling (for short i2c replies from the sink)
- bunch of constify patches
- inital kerneldoc for vga switcheroo
- some vblank code cleanups from Ville and Thierry
- various polish all over

Cheers, Daniel


The following changes since commit 1f93e4a96c9109378204c147b3eec0d0e8100fde:

  Linux 4.3-rc2 (2015-09-20 14:32:34 -0700)

are available in the git repository at:

  git://anongit.freedesktop.org/drm-intel tags/topic/drm-misc-2015-09-25

for you to fetch changes up to cf6483050e9bf13979415d9fd388554d8c8f3477:

  drm/irq: Add drm_crtc_vblank_count_and_time() (2015-09-24 20:27:17 +0200)


Bob Paauwe (1):
  dtrm/edid: Allow comma separated edid binaries. (v3)

Daniel Vetter (9):
  drm/atomic-helper: properly annotate functions in kerneldoc
  drm/fb-helper: Use -errno return in restore_mode_unlocked
  drm: Make drm_fb_unregister/remove accept NULL fb
  drm/fb-helper: Add module option to disable fbdev emulation
  drm/atomic: refuse changing CRTC for planes directly
  drm/atomic-helper: Add option to update planes only on active crtc
  drm/atomic-helper: Pimp docs with recommendations for rpm drivers
  drm: Nuke drm_framebuffer->helper_private
  Merge tag 'v4.3-rc2' into topic/drm-misc

Danilo Cesar Lemes de Paula (1):
  drm/doc: Fixing xml documentation warning

David Herrmann (2):
  drm: simplify drm_sysfs_destroy() via IS_ERR_OR_NULL()
  drm: move drm_class into drm_sysfs.c

Geliang Tang (2):
  drm: fix kernel-doc warnings in drm_crtc.h
  drm: drm_atomic_crtc_get_property should be static

Gustavo Padovan (1):
  drm: WARN_ON if a modeset driver uses legacy suspend/resume helpers

Laurent Pinchart (1):
  drm/atomic-helper: Don't skip plane disabling on active CRTC

Lukas Wunner (4):
  vga_switcheroo: Document _ALL_ the things!
  drm: Spell vga_switcheroo consistently
  vga_switcheroo: Sort headers alphabetically
  vga_switcheroo: Set active attribute to false for audio clients

Maarten Lankhorst (5):
  drm/atomic: Make sure lock is held in trylock contexts.
  drm/atomic: Make prepare_fb/cleanup_fb only take state, v3.
  drm/core: Do not call drm_framebuffer_remove internally during teardown.
  drm/core: Preserve the framebuffer after removing it.
  drm/core: Preserve the fb id on close.

Matt Roper (1):
  drm/fbdev: Update legacy plane->fb refcounting for atomic restore

Michel Thierry (1):
  drm/mm: Do DRM_MM_CREATE_TOP adj_start calculation after color_adjust

Rob Clark (5):
  drm: cleanup modesetting ioctls, one param per line
  drm/fb-helper: add headerdoc for drm_fb_helper
  drm/fb-helper: atomic restore_fbdev_mode()..
  drm/fb-helper: atomic pan_display()..
  drm/i915: enable atomic fb-helper

Thierry Reding (4):
  drm/atomic-helper: Implement drm_atomic_helper_duplicate_state()
  drm/gma500: Remove DP_LINK_STATUS_SIZE redefinition
  drm/irq: Rename drm_crtc -> crtc
  drm/irq: Add drm_crtc_vblank_count_and_time()

Ville Syrjälä (21):
  drm: Constify generic_edid_names[]
  drm: Constify TV mode names
  drm/i2c/ch7006: Constify ch7006_tv_norms[] and ch7006_modes[]
  drm/dp: s/I2C_STATUS/I2C_WRITE_STATUS_UPDATE/
  drm/i915: Handle DP_AUX_I2C_WRITE_STATUS_UPDATE
  drm/radeon: Handle DP_AUX_I2C_WRITE_STATUS_UPDATE
  drm/tegra: Handle I2C_WRITE_STATUS_UPDATE for address only writes
  drm/dp: Use I2C_WRITE_STATUS_UPDATE to drain partial I2C_WRITE requests
  drm: Make some modes const when iterating through them
  drm: Remove the 'mode' argument from drm_select_eld()
  drm: Make drm_av_sync_delay() 'mode' argument const
  drm: s/int crtc/unsigned int pipe/ straggles
  drm: Move timestamping constants into drm_vblank_crtc
  drm: Stop using linedur_ns and pixeldur_ns for vblank timestamps
  drm: Kill pixeldur_ns
  drm/i915: Fix vblank count variable types
  drm: Pass flags to drm_update_vblank_count()
  drm: Limit the number of .get_vblank_counter() retries
  drm: Clean up drm_calc_vbltimestamp_from_scanoutpos() vbl_status
  drm: store_vblank() is never called with NULL timestamp
  drm: Use vblank timestamps to guesstimate how many vblanks were missed

 Documentation/DocBook/drm.tmpl  |   2 +-
 Documentation/kernel-parameters.txt |  15 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c |  11 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h|   3 +-
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c |   4 +-
 drivers/gpu/drm/drm_atomic.c|  28 +-
 drivers/gpu/drm/drm_atomic_helper.c | 316 --
 drivers/gpu/drm/drm_crtc.c  |  

[PATCH 3/6] drm/imx: Build monolithic driver

2015-09-25 Thread Thierry Reding
On Fri, Sep 25, 2015 at 09:16:06AM +0200, Philipp Zabel wrote:
> Hi Thierry,
> 
> Am Donnerstag, den 24.09.2015, 19:02 +0200 schrieb Thierry Reding:
> > From: Thierry Reding 
> > 
> > There's no use building the individual drivers as separate modules
> > because they are all only useful if combined into a single DRM/KMS
> > device.
> 
> Why not? On an i.MX5 device with VGA(tve) output only, it is nice not to
> have to load the i.MX6 HDMI driver.

I think you gain much less by splitting up than you realize. Compare
this from before the series:

$ du -ch drivers/gpu/drm/imx/*.ko
8.0Kdrivers/gpu/drm/imx/dw_hdmi-imx.ko
16K drivers/gpu/drm/imx/imxdrm.ko
16K drivers/gpu/drm/imx/imx-ipuv3-crtc.ko
12K drivers/gpu/drm/imx/imx-ldb.ko
12K drivers/gpu/drm/imx/imx-tve.ko
8.0Kdrivers/gpu/drm/imx/parallel-display.ko
72K total

$ du -ch drivers/gpu/drm/sti/*.ko
36K drivers/gpu/drm/sti/sticompositor.ko
12K drivers/gpu/drm/sti/sti_drv.ko
16K drivers/gpu/drm/sti/stidvo.ko
16K drivers/gpu/drm/sti/sti_hda.ko
24K drivers/gpu/drm/sti/stihdmi.ko
8.0Kdrivers/gpu/drm/sti/sti_hqvdp.ko
12K drivers/gpu/drm/sti/sti_tvout.ko
8.0Kdrivers/gpu/drm/sti/sti_vtac.ko
8.0Kdrivers/gpu/drm/sti/sti_vtg.ko
140Ktotal

with this after the series:

$ du -ch drivers/gpu/drm/imx/*.ko
44K drivers/gpu/drm/imx/imx-drm.ko
44K total

$ du -ch drivers/gpu/drm/sti/*.ko
92K drivers/gpu/drm/sti/sti-drm.ko
92K total

There are other things to consider as well, such as the additional
memory overhead caused by merely having multiple modules, or all of the
exported functions that unnecessarily clutter up the symbol table, and
which end up slowing down every symbol lookup.

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


[PATCH] drm/i915: fix task reference leak in i915_debugfs.c

2015-09-25 Thread Jani Nikula
On Fri, 25 Sep 2015, Geliang Tang  wrote:
> Leak a task reference in i915_ppgtt_info(), add put_task_struct()
> to fix it.

Introduced by

commit 1c60fef535d143860d5bf6593e24ab6417f5227c
Author: Ben Widawsky 
Date:   Fri Dec 6 14:11:30 2013 -0800

drm/i915: Dump all ppgtt


>
> Signed-off-by: Geliang Tang 
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c | 8 ++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
> b/drivers/gpu/drm/i915/i915_debugfs.c
> index 5615d3d..8797717 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2288,9 +2288,13 @@ static int i915_ppgtt_info(struct seq_file *m, void 
> *data)
>  
>   list_for_each_entry_reverse(file, >filelist, lhead) {
>   struct drm_i915_file_private *file_priv = file->driver_priv;
> + struct task_struct *task;
>  
> - seq_printf(m, "\nproc: %s\n",
> -get_pid_task(file->pid, PIDTYPE_PID)->comm);
> + task = get_pid_task(file->pid, PIDTYPE_PID);
> + if (!task)
> + return -ESRCH;
> + seq_printf(m, "\nproc: %s\n", task->comm);
> + put_task_struct(task);
>   idr_for_each(_priv->context_idr, per_file_ctx,
>(void *)(unsigned long)m);
>   }
> -- 
> 1.9.1
>
>

-- 
Jani Nikula, Intel Open Source Technology Center


[PATCH 48/48] staging: etnaviv: remove CMDSTREAM GEM allocation from UAPI

2015-09-25 Thread Lucas Stach
Neither userspace nor the kernel internal functions use the CMDSTREAM
GEM type anymore. Remove it from the public API and clean up all related
functions.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 127 +++---
 include/uapi/drm/etnaviv_drm.h|   1 -
 2 files changed, 26 insertions(+), 102 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index c9300f1e03d5..1381c952c52f 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -31,19 +31,8 @@ static void etnaviv_gem_scatter_map(struct 
etnaviv_gem_object *etnaviv_obj)
 * For non-cached buffers, ensure the new pages are clean
 * because display controller, GPU, etc. are not coherent.
 */
-   if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK) {
+   if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
-   } else {
-   struct scatterlist *sg;
-   unsigned int i;
-
-   for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-   sg_dma_address(sg) = sg_phys(sg);
-#ifdef CONFIG_NEED_SG_DMA_LENGTH
-   sg_dma_len(sg) = sg->length;
-#endif
-   }
-   }
 }

 static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object 
*etnaviv_obj)
@@ -66,9 +55,8 @@ static void etnaviv_gem_scatterlist_unmap(struct 
etnaviv_gem_object *etnaviv_obj
 * written into the remainder of the region, this can
 * discard those writes.
 */
-   if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK) {
+   if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
-   }
 }

 /* called with dev->struct_mutex held */
@@ -138,27 +126,6 @@ void etnaviv_gem_put_pages(struct etnaviv_gem_object 
*etnaviv_obj)
/* when we start tracking the pin count, then do something here */
 }

-static int etnaviv_gem_mmap_cmd(struct drm_gem_object *obj,
-   struct vm_area_struct *vma)
-{
-   struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
-   int ret;
-
-   /*
-* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
-* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
-* the whole buffer.
-*/
-   vma->vm_flags &= ~VM_PFNMAP;
-   vma->vm_pgoff = 0;
-
-   ret = dma_mmap_coherent(obj->dev->dev, vma,
-   etnaviv_obj->vaddr, etnaviv_obj->paddr,
-   vma->vm_end - vma->vm_start);
-
-   return ret;
-}
-
 static int etnaviv_gem_mmap_obj(struct drm_gem_object *obj,
struct vm_area_struct *vma)
 {
@@ -203,12 +170,7 @@ int etnaviv_gem_mmap(struct file *filp, struct 
vm_area_struct *vma)
}

obj = to_etnaviv_bo(vma->vm_private_data);
-   if (obj->flags & ETNA_BO_CMDSTREAM)
-   ret = etnaviv_gem_mmap_cmd(vma->vm_private_data, vma);
-   else
-   ret = etnaviv_gem_mmap_obj(vma->vm_private_data, vma);
-
-   return ret;
+   return etnaviv_gem_mmap_obj(vma->vm_private_data, vma);
 }

 int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -296,11 +258,6 @@ int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu,
struct etnaviv_vram_mapping *mapping;
int ret = 0;

-   if (etnaviv_obj->flags & ETNA_BO_CMDSTREAM) {
-   *iova = etnaviv_obj->paddr;
-   return 0;
-   }
-
mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, gpu->mmu);
if (!mapping) {
struct page **pages = etnaviv_gem_get_pages(etnaviv_obj);
@@ -535,16 +492,6 @@ void etnaviv_gem_describe_objects(struct list_head *list, 
struct seq_file *m)
 }
 #endif

-static void etnaviv_gem_cmd_release(struct etnaviv_gem_object *etnaviv_obj)
-{
-   dma_free_coherent(etnaviv_obj->base.dev->dev, etnaviv_obj->base.size,
-   etnaviv_obj->vaddr, etnaviv_obj->paddr);
-}
-
-static const struct etnaviv_gem_ops etnaviv_gem_cmd_ops = {
-   .release = etnaviv_gem_cmd_release,
-};
-
 static void etnaviv_gem_shmem_release(struct etnaviv_gem_object *etnaviv_obj)
 {
if (etnaviv_obj->vaddr)
@@ -607,24 +554,18 @@ static int etnaviv_gem_new_impl(struct drm_device *dev,
bool valid = true;

/* validate flags */
-   if (flags & ETNA_BO_CMDSTREAM) {
-   if ((flags & ETNA_BO_CACHE_MASK) != 0)
-   valid = false;
-   } else {
-   switch (flags & ETNA_BO_CACHE_MASK) {
-   case ETNA_BO_UNCACHED:
-   case ETNA_BO_CACHED:
-   case ETNA_BO_WC:
-   break;
-   default:
-   valid = false;
-   }
+   switch (flags & ETNA_BO_CACHE_MASK) {
+   case 

[PATCH 47/48] staging: etnaviv: don't use GEM buffer for internal ring buffer

2015-09-25 Thread Lucas Stach
Instead of using a GEM buffer for the kernel internal ring buffer
use the newly introduced cmdbuf object. This removes the last remaining
user of the CMDSTREAM GEM flag.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_buffer.c | 90 ++--
 drivers/staging/etnaviv/etnaviv_drv.c|  8 +--
 drivers/staging/etnaviv/etnaviv_gpu.c| 13 +++--
 drivers/staging/etnaviv/etnaviv_gpu.h|  4 +-
 4 files changed, 53 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
index 76c646076b05..586f84316f1a 100644
--- a/drivers/staging/etnaviv/etnaviv_buffer.c
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -28,21 +28,22 @@
  */


-static inline void OUT(struct etnaviv_gem_object *buffer, u32 data)
+static inline void OUT(struct etnaviv_cmdbuf *buffer, u32 data)
 {
u32 *vaddr = (u32 *)buffer->vaddr;

-   BUG_ON(buffer->offset >= buffer->base.size / sizeof(*vaddr));
+   BUG_ON(buffer->user_size >= buffer->size);

-   vaddr[buffer->offset++] = data;
+   vaddr[buffer->user_size / 4] = data;
+   buffer->user_size += 4;
 }

-static inline void CMD_LOAD_STATE(struct etnaviv_gem_object *buffer,
+static inline void CMD_LOAD_STATE(struct etnaviv_cmdbuf *buffer,
u32 reg, u32 value)
 {
u32 index = reg >> VIV_FE_LOAD_STATE_HEADER_OFFSET__SHR;

-   buffer->offset = ALIGN(buffer->offset, 2);
+   buffer->user_size = ALIGN(buffer->user_size, 8);

/* write a register via cmd stream */
OUT(buffer, VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
@@ -51,40 +52,40 @@ static inline void CMD_LOAD_STATE(struct etnaviv_gem_object 
*buffer,
OUT(buffer, value);
 }

-static inline void CMD_END(struct etnaviv_gem_object *buffer)
+static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
 {
-   buffer->offset = ALIGN(buffer->offset, 2);
+   buffer->user_size = ALIGN(buffer->user_size, 8);

OUT(buffer, VIV_FE_END_HEADER_OP_END);
 }

-static inline void CMD_WAIT(struct etnaviv_gem_object *buffer)
+static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer)
 {
-   buffer->offset = ALIGN(buffer->offset, 2);
+   buffer->user_size = ALIGN(buffer->user_size, 8);

OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | 200);
 }

-static inline void CMD_LINK(struct etnaviv_gem_object *buffer,
+static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
u16 prefetch, u32 address)
 {
-   buffer->offset = ALIGN(buffer->offset, 2);
+   buffer->user_size = ALIGN(buffer->user_size, 8);

OUT(buffer, VIV_FE_LINK_HEADER_OP_LINK |
VIV_FE_LINK_HEADER_PREFETCH(prefetch));
OUT(buffer, address);
 }

-static inline void CMD_STALL(struct etnaviv_gem_object *buffer,
+static inline void CMD_STALL(struct etnaviv_cmdbuf *buffer,
u32 from, u32 to)
 {
-   buffer->offset = ALIGN(buffer->offset, 2);
+   buffer->user_size = ALIGN(buffer->user_size, 8);

OUT(buffer, VIV_FE_STALL_HEADER_OP_STALL);
OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
 }

-static void etnaviv_cmd_select_pipe(struct etnaviv_gem_object *buffer, u8 pipe)
+static void etnaviv_cmd_select_pipe(struct etnaviv_cmdbuf *buffer, u8 pipe)
 {
u32 flush;
u32 stall;
@@ -106,24 +107,19 @@ static void etnaviv_cmd_select_pipe(struct 
etnaviv_gem_object *buffer, u8 pipe)
   VIVS_GL_PIPE_SELECT_PIPE(pipe));
 }

-static u32 gpu_va(struct etnaviv_gpu *gpu, struct etnaviv_gem_object *obj)
+static u32 gpu_va(struct etnaviv_gpu *gpu, struct etnaviv_cmdbuf *buf)
 {
-   return obj->paddr - gpu->memory_base;
-}
-
-static u32 gpu_va_raw(struct etnaviv_gpu *gpu, u32 paddr)
-{
-   return paddr - gpu->memory_base;
+   return buf->paddr - gpu->memory_base;
 }

 static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
-   struct etnaviv_gem_object *obj, u32 off, u32 len)
+   struct etnaviv_cmdbuf *buf, u32 off, u32 len)
 {
-   u32 size = obj->base.size;
-   u32 *ptr = obj->vaddr + off;
+   u32 size = buf->size;
+   u32 *ptr = buf->vaddr + off;

dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n",
-   ptr, gpu_va(gpu, obj) + off, size - len * 4 - off);
+   ptr, gpu_va(gpu, buf) + off, size - len * 4 - off);

print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
ptr, len * 4, 0);
@@ -131,24 +127,23 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,

 u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
 {
-   struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer);
+   struct etnaviv_cmdbuf *buffer = gpu->buffer;

/* initialize buffer */
-   buffer->offset = 0;
-   buffer->is_ring_buffer = true;
+   buffer->user_size = 0;

CMD_WAIT(buffer);
-   CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + ((buffer->offset - 1) * 4));
+   

[PATCH 46/48] staging: etnaviv: rewrite submit interface to use copy from user

2015-09-25 Thread Lucas Stach
This rewrites the submit interface to copy the command stream from user
memory. This mitigates a potential attack vector of the old interface
where userspace could submit a command buffer that would be validated by
the kernel, but is still mapped into userspace. This could be exploited
by changing the command stream after validation but before the actual
GPU execution.

A nice side effect is that validation and reloc patching can now operate
on cached memory and only the final result is copied to a writecombined
command buffer which should make those operations a bit more efficient.

A simplification to the interface is the removal of the ability to push
multiple command buffers per submit. As we don't use it for context
restore buffers and the fact that userspace doesn't need to work with
a fixed command buffer size anymore, with the potential risk to overflow
its size in the middle of an atomic stream section, there is no need
for this complication anymore.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_buffer.c |  48 +--
 drivers/staging/etnaviv/etnaviv_cmd_parser.c |   6 +-
 drivers/staging/etnaviv/etnaviv_drv.h|   4 +-
 drivers/staging/etnaviv/etnaviv_gem.h|   7 +-
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 122 ++-
 drivers/staging/etnaviv/etnaviv_gpu.c|  38 +
 drivers/staging/etnaviv/etnaviv_gpu.h|  20 +
 include/uapi/drm/etnaviv_drm.h   |  18 ++--
 8 files changed, 136 insertions(+), 127 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
index 1994eceae1ae..76c646076b05 100644
--- a/drivers/staging/etnaviv/etnaviv_buffer.c
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -111,6 +111,11 @@ static u32 gpu_va(struct etnaviv_gpu *gpu, struct 
etnaviv_gem_object *obj)
return obj->paddr - gpu->memory_base;
 }

+static u32 gpu_va_raw(struct etnaviv_gpu *gpu, u32 paddr)
+{
+   return paddr - gpu->memory_base;
+}
+
 static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
struct etnaviv_gem_object *obj, u32 off, u32 len)
 {
@@ -153,10 +158,9 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, 
unsigned int event,
struct etnaviv_gem_submit *submit)
 {
struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer);
-   struct etnaviv_gem_object *cmd;
u32 *lw = buffer->vaddr + ((buffer->offset - 4) * 4);
+   u32 *usercmd = submit->cmdbuf->vaddr;
u32 back, link_target, link_size, reserve_size, extra_size = 0;
-   u32 i;

if (drm_debug & DRM_UT_DRIVER)
etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
@@ -194,35 +198,24 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, 
unsigned int event,
/* Skip over any extra instructions */
link_target += extra_size * sizeof(u32);

-   /* update offset for every cmd stream */
-   for (i = submit->nr_cmds; i--; ) {
-   cmd = submit->cmd[i].obj;
+   if (drm_debug & DRM_UT_DRIVER)
+   pr_info("stream link to 0x%08x @ 0x%08x %p\n",
+   link_target, gpu_va_raw(gpu, submit->cmdbuf->paddr),
+   submit->cmdbuf->vaddr);

-   cmd->offset = submit->cmd[i].offset + submit->cmd[i].size;
+   /* jump back from cmd to main buffer */
+   usercmd[submit->cmdbuf->user_size/4] = VIV_FE_LINK_HEADER_OP_LINK |
+   VIV_FE_LINK_HEADER_PREFETCH(link_size);
+   usercmd[submit->cmdbuf->user_size/4 + 1] = link_target;

-   if (drm_debug & DRM_UT_DRIVER)
-   pr_info("stream link from buffer %u to 0x%08x @ 0x%08x 
%p\n",
-   i, link_target,
-   gpu_va(gpu, cmd) + cmd->offset * 4,
-   cmd->vaddr + cmd->offset * 4);
+   link_target = gpu_va_raw(gpu, submit->cmdbuf->paddr);
+   link_size = submit->cmdbuf->size / 8;

-   /* jump back from last cmd to main buffer */
-   CMD_LINK(cmd, link_size, link_target);

-   /* update the size */
-   submit->cmd[i].size = cmd->offset - submit->cmd[i].offset;
-
-   link_target = gpu_va(gpu, cmd) + submit->cmd[i].offset * 4;
-   link_size = submit->cmd[i].size * 2;
-   }

if (drm_debug & DRM_UT_DRIVER) {
-   for (i = 0; i < submit->nr_cmds; i++) {
-   struct etnaviv_gem_object *obj = submit->cmd[i].obj;
-
-   etnaviv_buffer_dump(gpu, obj, submit->cmd[i].offset,
-   submit->cmd[i].size);
-   }
+   print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
+  submit->cmdbuf->vaddr, submit->cmdbuf->size, 0);

pr_info("link op: %p\n", lw);
pr_info("link addr: %p\n", lw + 1);
@@ -263,6 +256,11 @@ 

[PATCH 45/48] staging: etnaviv: remove submit type

2015-09-25 Thread Lucas Stach
There is no point in having a context restore buffer, as the need for tracking
GPU hardware state in userspace and the fact that we need to submit all states
that reference memory buffers anyway to ensure proper patching of the
relocations, eat away from the potential benefit.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_gem.h| 1 -
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 1 -
 include/uapi/drm/etnaviv_drm.h   | 8 
 3 files changed, 10 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
index 25f7afbc779a..5112c5458306 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.h
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -121,7 +121,6 @@ struct etnaviv_gem_submit {
unsigned int nr_cmds;
unsigned int nr_bos;
struct {
-   u32 type;
u32 offset; /* in dwords */
u32 size;  /* in dwords */
struct etnaviv_gem_object *obj;
diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c 
b/drivers/staging/etnaviv/etnaviv_gem_submit.c
index a0bc61946036..73c1378e96a1 100644
--- a/drivers/staging/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c
@@ -408,7 +408,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void 
*data,
goto out;
}

-   submit->cmd[i].type = submit_cmd->type;
submit->cmd[i].offset = submit_cmd->submit_offset / 4;
submit->cmd[i].size = submit_cmd->size / 4;
submit->cmd[i].obj = etnaviv_obj;
diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h
index 7cc749c30970..1515fa4f6986 100644
--- a/include/uapi/drm/etnaviv_drm.h
+++ b/include/uapi/drm/etnaviv_drm.h
@@ -123,15 +123,7 @@ struct drm_etnaviv_gem_submit_reloc {
__u64 reloc_offset;   /* in, offset from start of reloc_bo */
 };

-/* submit-types:
- *   BUF - this cmd buffer is executed normally.
- *   CTX_RESTORE_BUF - only executed if there has been a GPU context
- *  switch since the last SUBMIT ioctl
- */
-#define ETNA_SUBMIT_CMD_BUF 0x0001
-#define ETNA_SUBMIT_CMD_CTX_RESTORE_BUF 0x0002
 struct drm_etnaviv_gem_submit_cmd {
-   __u32 type;   /* in, one of ETNA_SUBMIT_CMD_x */
__u32 submit_idx; /* in, index of submit_bo cmdstream buffer */
__u32 submit_offset;  /* in, offset into submit_bo */
__u32 size;   /* in, cmdstream size */
-- 
2.5.1



[PATCH 44/48] staging: etnaviv: implement cache maintenance on cpu_(prep|fini)

2015-09-25 Thread Lucas Stach
This makes sure that we are satifying the cache handling rules outlined
in the previous commit. Cached buffers are pulled into the CPU domain
before access and pushed to the GPU again when the CPU is done.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 41 +--
 drivers/staging/etnaviv/etnaviv_gem.h |  3 +++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 5ee43861095d..c9300f1e03d5 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -424,10 +424,21 @@ void etnaviv_gem_move_to_inactive(struct drm_gem_object 
*obj)
list_add_tail(_obj->mm_list, >inactive_list);
 }

+static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
+{
+   if (op & ETNA_PREP_READ)
+   return DMA_FROM_DEVICE;
+   else if (op & ETNA_PREP_WRITE)
+   return DMA_TO_DEVICE;
+   else
+   return DMA_BIDIRECTIONAL;
+}
+
 int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
struct timespec *timeout)
 {
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+   struct drm_device *dev = obj->dev;
int ret = 0;

if (is_active(etnaviv_obj)) {
@@ -444,14 +455,40 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 
op,
ret = etnaviv_gpu_wait_fence_interruptible(gpu, fence, timeout);
}

-   /* TODO cache maintenance */
+   if (etnaviv_obj->flags & ETNA_BO_CACHED) {
+   if (!etnaviv_obj->sgt) {
+   void * ret;
+
+   mutex_lock(>struct_mutex);
+   ret = etnaviv_gem_get_pages(etnaviv_obj);
+   mutex_unlock(>struct_mutex);
+   if (IS_ERR(ret))
+   return PTR_ERR(ret);
+   }
+
+   dma_sync_sg_for_cpu(dev->dev, etnaviv_obj->sgt->sgl,
+   etnaviv_obj->sgt->nents,
+   etnaviv_op_to_dma_dir(op));
+   etnaviv_obj->last_cpu_prep_op = op;
+   }

return ret;
 }

 int etnaviv_gem_cpu_fini(struct drm_gem_object *obj)
 {
-   /* TODO cache maintenance */
+   struct drm_device *dev = obj->dev;
+   struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+   if (etnaviv_obj->flags & ETNA_BO_CACHED) {
+   /* fini without a prep is almost certainly a userspace error */
+   WARN_ON(etnaviv_obj->last_cpu_prep_op == 0);
+   dma_sync_sg_for_device(dev->dev, etnaviv_obj->sgt->sgl,
+   etnaviv_obj->sgt->nents,
+   etnaviv_op_to_dma_dir(etnaviv_obj->last_cpu_prep_op));
+   etnaviv_obj->last_cpu_prep_op = 0;
+   }
+
return 0;
 }

diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
index 4d5455a3fe39..25f7afbc779a 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.h
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -82,6 +82,9 @@ struct etnaviv_gem_object {
bool is_ring_buffer;
u32 offset;

+   /* cache maintenance */
+   uint32_t last_cpu_prep_op;
+
struct etnaviv_gem_userptr userptr;
 };

-- 
2.5.1



[PATCH 43/48] staging: etnaviv: map all buffers to the GPU

2015-09-25 Thread Lucas Stach
This redefines how we do cache handling in the following way:

All buffer are pushed into the GPU domain initially, this will only
be done when populating the buffers backing store, but for simplicity
userspace can assume that the buffer is owned by the GPU as soon as it
constructs a GEM handle. The memory is only implicitly pulled back into
the CPU domain when destroying the handle.

Uncached and writecombined buffers can stay in the GPU domain for their
entire lifetime, as any modification to them will be seen by the GPU
either immediately or latest when the write buffers get flushed when
linking a new submit into the GPUs command stream.

If any modifications needs to be done to a cached buffer they must be
pulled into the CPU domain before and pushed to the GPU afterwards in
an explicit manner.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 3e08f0694021..5ee43861095d 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -31,9 +31,8 @@ static void etnaviv_gem_scatter_map(struct etnaviv_gem_object 
*etnaviv_obj)
 * For non-cached buffers, ensure the new pages are clean
 * because display controller, GPU, etc. are not coherent.
 */
-   if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_CACHED)) {
+   if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK) {
dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
-   dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
} else {
struct scatterlist *sg;
unsigned int i;
@@ -67,8 +66,7 @@ static void etnaviv_gem_scatterlist_unmap(struct 
etnaviv_gem_object *etnaviv_obj
 * written into the remainder of the region, this can
 * discard those writes.
 */
-   if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_CACHED)) {
-   dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+   if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK) {
dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
}
 }
-- 
2.5.1



[PATCH 42/48] staging: etnaviv: implement simple hang recovery

2015-09-25 Thread Lucas Stach
Not bullet proof yet, as this possibly shoots down more submits than
necessary. However it allows for fairly rapid turnarounds during
userspace development.

Signed-off-by: Lucas Stach 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 30 +-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 84dedb77ea76..39ac08d26260 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -719,12 +719,40 @@ static void recover_worker(struct work_struct *work)
struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
   recover_work);
struct drm_device *dev = gpu->drm;
+   unsigned long flags;
+   unsigned int i;

dev_err(gpu->dev, "hangcheck recover!\n");

+   if (pm_runtime_get_sync(gpu->dev) < 0)
+   return;
+
mutex_lock(>struct_mutex);
-   /* TODO gpu->funcs->recover(gpu); */
+
+   etnaviv_hw_reset(gpu);
+
+   /* complete all events, the GPU won't do it after the reset */
+   spin_lock_irqsave(>event_spinlock, flags);
+   for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
+   if (!gpu->event[i].used)
+   continue;
+   gpu->event[i].used = false;
+   complete(>event_free);
+   /*
+* Decrement the PM count for each stuck event. This is safe
+* even in atomic context as we use ASYNC RPM here.
+*/
+   pm_runtime_put_autosuspend(gpu->dev);
+   }
+   spin_unlock_irqrestore(>event_spinlock, flags);
+   gpu->completed_fence = gpu->submitted_fence;
+
+   etnaviv_gpu_hw_init(gpu);
+   gpu->switch_context = true;
+
mutex_unlock(>struct_mutex);
+   pm_runtime_mark_last_busy(gpu->dev);
+   pm_runtime_put_autosuspend(gpu->dev);

/* Retire the buffer objects in a work */
etnaviv_queue_work(gpu->drm, >retire_work);
-- 
2.5.1



[PATCH 41/48] staging: etnaviv: change etnaviv_buffer_init() to return prefetch

2015-09-25 Thread Lucas Stach
From: Christian Gmeiner 

etnaviv_buffer_init() creates a very simple command buffer
to be able to start the FE. FE fetches 'prefetch' number of 64 bit
words via DMA and starts to execute the read buffer.

This is a very simple code cleanup and pushes the whole buffer
logic (alignment, cmd buffer commands, etc.) into etnaviv_buffer.c

Signed-off-by: Christian Gmeiner 
---
 drivers/staging/etnaviv/etnaviv_buffer.c | 4 ++--
 drivers/staging/etnaviv/etnaviv_drv.h| 2 +-
 drivers/staging/etnaviv/etnaviv_gpu.c| 9 +++--
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
index cbeebfde680a..1994eceae1ae 100644
--- a/drivers/staging/etnaviv/etnaviv_buffer.c
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -124,7 +124,7 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
ptr, len * 4, 0);
 }

-u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
+u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
 {
struct etnaviv_gem_object *buffer = to_etnaviv_bo(gpu->buffer);

@@ -135,7 +135,7 @@ u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
CMD_WAIT(buffer);
CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + ((buffer->offset - 1) * 4));

-   return buffer->offset;
+   return buffer->offset / 2;
 }

 void etnaviv_buffer_end(struct etnaviv_gpu *gpu)
diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
index b98db8c11ef3..40629207b04f 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.h
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -103,7 +103,7 @@ struct drm_gem_object *etnaviv_gem_new(struct drm_device 
*dev,
u32 size, u32 flags);
 int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
uintptr_t ptr, u32 size, u32 flags, u32 *handle);
-u32 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
+u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
 void etnaviv_buffer_end(struct etnaviv_gpu *gpu);
 void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
struct etnaviv_gem_submit *submit);
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 948c85a8a591..84dedb77ea76 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -379,7 +379,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)

 static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
 {
-   u32 words; /* 32 bit words */
+   u16 prefetch;

if (gpu->identity.model == chipModel_GC320 &&
gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400 &&
@@ -426,17 +426,14 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
etnaviv_iommu_domain_restore(gpu, gpu->mmu->domain);

/* Start command processor */
-   words = etnaviv_buffer_init(gpu);
-
-   /* convert number of 32 bit words to number of 64 bit words */
-   words = ALIGN(words, 2) / 2;
+   prefetch = etnaviv_buffer_init(gpu);

gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
gpu_write(gpu, VIVS_FE_COMMAND_ADDRESS,
  etnaviv_gem_paddr_locked(gpu->buffer) - gpu->memory_base);
gpu_write(gpu, VIVS_FE_COMMAND_CONTROL,
  VIVS_FE_COMMAND_CONTROL_ENABLE |
- VIVS_FE_COMMAND_CONTROL_PREFETCH(words));
+ VIVS_FE_COMMAND_CONTROL_PREFETCH(prefetch));
 }

 int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
-- 
2.5.1



[PATCH 40/48] staging: etnaviv: debugfs: add possibility to dump kernel buffer

2015-09-25 Thread Lucas Stach
From: Christian Gmeiner 

This is very useful for debugging issues regarding command
buffer processing.

Signed-off-by: Christian Gmeiner 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 85dbe3813859..d55d2c9f4d0f 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -21,6 +21,7 @@
 #include "etnaviv_gpu.h"
 #include "etnaviv_gem.h"
 #include "etnaviv_mmu.h"
+#include "etnaviv_gem.h"

 #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
 static bool reglog;
@@ -234,6 +235,43 @@ static int etnaviv_mmu_show(struct drm_device *dev, struct 
seq_file *m)
return 0;
 }

+static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m)
+{
+   struct etnaviv_gem_object *obj = to_etnaviv_bo(gpu->buffer);
+   u32 size = obj->base.size;
+   u32 *ptr = obj->vaddr;
+   u32 i;
+
+   seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n",
+   obj->vaddr, (u64)obj->paddr, size - (obj->offset * 4));
+
+   for (i = 0; i < size / 4; i++) {
+   if (i && !(i % 4))
+   seq_puts(m, "\n");
+   if (i % 4 == 0)
+   seq_printf(m, "\t0x%p: ", ptr + i);
+   seq_printf(m, "%08x ", *(ptr + i));
+   }
+   seq_puts(m, "\n");
+}
+
+static int etnaviv_ring_show(struct drm_device *dev, struct seq_file *m)
+{
+   struct etnaviv_drm_private *priv = dev->dev_private;
+   struct etnaviv_gpu *gpu;
+   unsigned int i;
+
+   for (i = 0; i < ETNA_MAX_PIPES; i++) {
+   gpu = priv->gpu[i];
+   if (gpu) {
+   seq_printf(m, "Ring Buffer (%s): ",
+  dev_name(gpu->dev));
+   etnaviv_buffer_dump(gpu, m);
+   }
+   }
+   return 0;
+}
+
 static int show_locked(struct seq_file *m, void *arg)
 {
struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -282,6 +320,7 @@ static struct drm_info_list etnaviv_debugfs_list[] = {
{"gem", show_locked, 0, etnaviv_gem_show},
{ "mm", show_locked, 0, etnaviv_mm_show },
{"mmu", show_locked, 0, etnaviv_mmu_show},
+   {"ring", show_locked, 0, etnaviv_ring_show},
 };

 static int etnaviv_debugfs_init(struct drm_minor *minor)
-- 
2.5.1



[PATCH 39/48] staging: etnaviv: fix error: 'etnaviv_gpu_hw_resume' defined but not used

2015-09-25 Thread Lucas Stach
From: Christian Gmeiner 

Signed-off-by: Christian Gmeiner 
Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index f89fa869885e..948c85a8a591 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1154,6 +1154,7 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
return etnaviv_gpu_clk_disable(gpu);
 }

+#ifdef CONFIG_PM
 static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
 {
struct drm_device *drm = gpu->drm;
@@ -1176,6 +1177,7 @@ static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)

return 0;
 }
+#endif

 static int etnaviv_gpu_bind(struct device *dev, struct device *master,
void *data)
-- 
2.5.1



[PATCH 38/48] staging: etnaviv: fix 'ret' may be used uninitialized in this function

2015-09-25 Thread Lucas Stach
From: Christian Gmeiner 

Signed-off-by: Christian Gmeiner 
Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 5c2462d6130d..3e08f0694021 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -752,7 +752,7 @@ struct get_pages_work {
 static struct page **etnaviv_gem_userptr_do_get_pages(
struct etnaviv_gem_object *etnaviv_obj, struct mm_struct *mm, struct 
task_struct *task)
 {
-   int ret, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
+   int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;
struct page **pvec;
uintptr_t ptr;

-- 
2.5.1



[PATCH 37/48] staging: etnaviv: avoid pinning pages in CMA

2015-09-25 Thread Lucas Stach
From: Russell King 

The CMA memory area is shared between CMA and other users.  In order to
allow CMA to work, non-CMA allocations in this area must be for movable
pages, so that a CMA allocation can reclaim its memory from other users
when required.

Page cache backed allocations, such as pages allocated via shmem, are by
default marked as "movable" allocations, which means that they can come
from the CMA region.

However, in etnaviv's case, we allocate shmem pages, and then we pin
these pages for the life of the buffer.  This prevents the pages being
reclaimed, and causes CMA failures.

new_inode() in fs/inode.c even says:

 * Allocates a new inode for given superblock. The default gfp_mask
 * for allocations related to inode->i_mapping is GFP_HIGHUSER_MOVABLE.
 * If HIGHMEM pages are unsuitable or it is known that pages allocated
 * for the page cache are not reclaimable or migratable,
 * mapping_set_gfp_mask() must be called with suitable flags on the
 * newly created inode's mapping

Etnaviv shmem pages are not reclaimable nor migratable once they're
pinned, so etnaviv is not conforming with this requirement.  Change the
gfp_mask to GFP_HIGHUSER, so we can still allocate from highmem, but not
from the CMA area.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 2518f897fdd8..5c2462d6130d 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -640,6 +640,19 @@ static struct drm_gem_object *__etnaviv_gem_new(struct 
drm_device *dev,
} else {
to_etnaviv_bo(obj)->ops = _gem_shmem_ops;
ret = drm_gem_object_init(dev, obj, size);
+   if (ret == 0) {
+   struct address_space *mapping;
+
+   /*
+* Our buffers are kept pinned, so allocating them
+* from the MOVABLE zone is a really bad idea, and
+* conflicts with CMA.  See coments above new_inode()
+* why this is required _and_ expected if you're
+* going to pin these pages.
+*/
+   mapping = file_inode(obj->filp)->i_mapping;
+   mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
+   }
}

if (ret)
-- 
2.5.1



[PATCH 36/48] staging: etnaviv: add support for GEM_WAIT ioctl

2015-09-25 Thread Lucas Stach
From: Russell King 

Add support for the new GEM_WAIT ioctl, which waits for the kernel to
finish with the GEM object (all render complete, and has been retired).
This is different from the WAIT_FENCE ioctl, which just waits for
rendering to complete.

This is an important distinction, as when a gem object is retired and
freed, the kernel will invalidate the cache for this object, which
effectively changes the data userspace sees.  If userspace merely
waits for rendering to complete, there is a race condition where a
userptr BO can be free()d and re-used, and the kernel's invalidation
then corrupts the malloc() free lists.

GEM_WAIT is not fully race free: if the BO is re-submitted via a
different thread, we can't report this (indeed, this could happen
after the call has returned.)  It is up to userspace to ensure that
such behaviour does not occur.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 29 +
 drivers/staging/etnaviv/etnaviv_gem.c |  8 
 drivers/staging/etnaviv/etnaviv_gem.h |  2 +
 drivers/staging/etnaviv/etnaviv_gpu.c | 76 +++
 drivers/staging/etnaviv/etnaviv_gpu.h |  8 
 include/uapi/drm/etnaviv_drm.h| 10 -
 6 files changed, 116 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index d7133e4450c6..85dbe3813859 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -19,6 +19,7 @@

 #include "etnaviv_drv.h"
 #include "etnaviv_gpu.h"
+#include "etnaviv_gem.h"
 #include "etnaviv_mmu.h"

 #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
@@ -451,6 +452,33 @@ static int etnaviv_ioctl_gem_userptr(struct drm_device 
*dev, void *data,
   >handle);
 }

+static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data,
+   struct drm_file *file)
+{
+   struct etnaviv_drm_private *priv = dev->dev_private;
+   struct drm_etnaviv_gem_wait *args = data;
+   struct drm_gem_object *obj;
+   struct etnaviv_gpu *gpu;
+   int ret;
+
+   if (args->pipe >= ETNA_MAX_PIPES)
+   return -EINVAL;
+
+   gpu = priv->gpu[args->pipe];
+   if (!gpu)
+   return -ENXIO;
+
+   obj = drm_gem_object_lookup(dev, file, args->handle);
+   if (!obj)
+   return -ENOENT;
+
+   ret = etnaviv_gem_wait_bo(gpu, obj, (args->timeout));
+
+   drm_gem_object_unreference_unlocked(obj);
+
+   return ret;
+}
+
 static const struct drm_ioctl_desc etnaviv_ioctls[] = {
 #define ETNA_IOCTL(n, func, flags) \
DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags)
@@ -462,6 +490,7 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
ETNA_IOCTL(GEM_SUBMIT,   gem_submit,   
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
ETNA_IOCTL(WAIT_FENCE,   wait_fence,   
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
ETNA_IOCTL(GEM_USERPTR,  gem_userptr,  DRM_UNLOCKED|DRM_RENDER_ALLOW),
+   ETNA_IOCTL(GEM_WAIT, gem_wait, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
 };

 static const struct vm_operations_struct vm_ops = {
diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 1c003afc9ab1..2518f897fdd8 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -457,6 +457,14 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj)
return 0;
 }

+int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
+   struct timespec *timeout)
+{
+   struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+
+   return etnaviv_gpu_wait_obj_inactive(gpu, etnaviv_obj, timeout);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file 
*m)
 {
diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
index f3136d86d73e..4d5455a3fe39 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.h
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -130,6 +130,8 @@ struct etnaviv_gem_submit {
} bos[0];
 };

+int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
+   struct timespec *timeout);
 struct etnaviv_vram_mapping *
 etnaviv_gem_get_vram_mapping(struct etnaviv_gem_object *obj,
 struct etnaviv_iommu *mmu);
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 137c09293375..f89fa869885e 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -743,7 +743,7 @@ static void hangcheck_timer_reset(struct etnaviv_gpu *gpu)
 static void hangcheck_handler(unsigned long data)
 {
struct etnaviv_gpu *gpu = (struct etnaviv_gpu *)data;
-   u32 fence = gpu->retired_fence;
+   u32 fence = gpu->completed_fence;
bool 

[PATCH 35/48] staging: etnaviv: move mapping teardown into etnaviv_gem_free_object()

2015-09-25 Thread Lucas Stach
From: Russell King 

Move the mapping teardown directly into etnaviv_gem_free_object().

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 02c5e46dca75..1c003afc9ab1 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -502,17 +502,6 @@ static const struct etnaviv_gem_ops etnaviv_gem_cmd_ops = {
.release = etnaviv_gem_cmd_release,
 };

-static void etnaviv_free_obj(struct drm_gem_object *obj)
-{
-   struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
-   struct etnaviv_vram_mapping *mapping, *tmp;
-
-   list_for_each_entry_safe(mapping, tmp, _obj->vram_list,
-obj_node) {
-   etnaviv_iommu_unmap_gem(mapping);
-   }
-}
-
 static void etnaviv_gem_shmem_release(struct etnaviv_gem_object *etnaviv_obj)
 {
if (etnaviv_obj->vaddr)
@@ -529,6 +518,7 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
 {
struct drm_device *dev = obj->dev;
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+   struct etnaviv_vram_mapping *mapping, *tmp;

WARN_ON(!mutex_is_locked(>struct_mutex));

@@ -537,8 +527,9 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)

list_del(_obj->mm_list);

-   if (!(etnaviv_obj->flags & ETNA_BO_CMDSTREAM))
-   etnaviv_free_obj(obj);
+   list_for_each_entry_safe(mapping, tmp, _obj->vram_list,
+obj_node)
+   etnaviv_iommu_unmap_gem(mapping);

drm_gem_free_mmap_offset(obj);
etnaviv_obj->ops->release(etnaviv_obj);
-- 
2.5.1



[PATCH 34/48] staging: etnaviv: remove cmd buffer offset validation in submit_reloc()

2015-09-25 Thread Lucas Stach
From: Russell King 

We've already validated the command buffer offset, there's no need to
repeat it elsewhere.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 5 -
 1 file changed, 5 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c 
b/drivers/staging/etnaviv/etnaviv_gem_submit.c
index f94b6e8fb4fb..a0bc61946036 100644
--- a/drivers/staging/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c
@@ -219,11 +219,6 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, 
struct etnaviv_gem_ob
u32 *ptr = obj->vaddr;
int ret;

-   if (offset % 4) {
-   DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
-   return -EINVAL;
-   }
-
for (i = 0; i < nr_relocs; i++) {
struct drm_etnaviv_gem_submit_reloc submit_reloc;
struct etnaviv_gem_object *bobj;
-- 
2.5.1



[PATCH 33/48] staging: etnaviv: copy submit command and bos in one go

2015-09-25 Thread Lucas Stach
From: Russell King 

On GPU submission, copy the submit command and bo structures in one go
and outside of dev->struct_mutex.  There are two reasons:

- This avoids the overhead from calling and checking copy_from_user()
  multiple times.
- Holding dev->struct_mutex over a page fault should be avoided as this
  will block all users of the GPU while page IO is being performed.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 98 
 1 file changed, 57 insertions(+), 41 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c 
b/drivers/staging/etnaviv/etnaviv_gem_submit.c
index e2c94f476810..f94b6e8fb4fb 100644
--- a/drivers/staging/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c
@@ -55,41 +55,34 @@ static struct etnaviv_gem_submit *submit_create(struct 
drm_device *dev,
 }

 static int submit_lookup_objects(struct etnaviv_gem_submit *submit,
-   struct drm_etnaviv_gem_submit *args, struct drm_file *file)
+   struct drm_file *file, struct drm_etnaviv_gem_submit_bo *submit_bos,
+   unsigned nr_bos)
 {
+   struct drm_etnaviv_gem_submit_bo *bo;
unsigned i;
int ret = 0;

spin_lock(>table_lock);

-   for (i = 0; i < args->nr_bos; i++) {
-   struct drm_etnaviv_gem_submit_bo submit_bo;
+   for (i = 0, bo = submit_bos; i < nr_bos; i++, bo++) {
struct drm_gem_object *obj;
struct etnaviv_gem_object *etnaviv_obj;
-   void __user *userptr =
-   to_user_ptr(args->bos + (i * sizeof(submit_bo)));
-
-   ret = copy_from_user(_bo, userptr, sizeof(submit_bo));
-   if (ret) {
-   ret = -EFAULT;
-   goto out_unlock;
-   }

-   if (submit_bo.flags & BO_INVALID_FLAGS) {
-   DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
+   if (bo->flags & BO_INVALID_FLAGS) {
+   DRM_ERROR("invalid flags: %x\n", bo->flags);
ret = -EINVAL;
goto out_unlock;
}

-   submit->bos[i].flags = submit_bo.flags;
+   submit->bos[i].flags = bo->flags;

/* normally use drm_gem_object_lookup(), but for bulk lookup
 * all under single table_lock just hit object_idr directly:
 */
-   obj = idr_find(>object_idr, submit_bo.handle);
+   obj = idr_find(>object_idr, bo->handle);
if (!obj) {
DRM_ERROR("invalid handle %u at index %u\n",
- submit_bo.handle, i);
+ bo->handle, i);
ret = -EINVAL;
goto out_unlock;
}
@@ -98,7 +91,7 @@ static int submit_lookup_objects(struct etnaviv_gem_submit 
*submit,

if (!list_empty(_obj->submit_entry)) {
DRM_ERROR("handle %u at index %u already on submit 
list\n",
- submit_bo.handle, i);
+ bo->handle, i);
ret = -EINVAL;
goto out_unlock;
}
@@ -298,6 +291,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void 
*data,
struct etnaviv_drm_private *priv = dev->dev_private;
struct drm_etnaviv_gem_submit *args = data;
struct etnaviv_file_private *ctx = file->driver_priv;
+   struct drm_etnaviv_gem_submit_cmd *cmds;
+   struct drm_etnaviv_gem_submit_bo *bos;
struct etnaviv_gem_submit *submit;
struct etnaviv_gpu *gpu;
unsigned i;
@@ -314,6 +309,29 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void 
*data,
return -EINVAL;

/*
+* Copy the command submission and bo array to kernel space in
+* one go, and do this outside of the dev->struct_mutex lock.
+*/
+   cmds = drm_malloc_ab(args->nr_cmds, sizeof(*cmds));
+   bos = drm_malloc_ab(args->nr_bos, sizeof(*bos));
+   if (!cmds || !bos)
+   return -ENOMEM;
+
+   ret = copy_from_user(cmds, to_user_ptr(args->cmds),
+args->nr_cmds * sizeof(*cmds));
+   if (ret) {
+   ret = -EFAULT;
+   goto err_submit_cmds;
+   }
+
+   ret = copy_from_user(bos, to_user_ptr(args->bos),
+args->nr_bos * sizeof(*bos));
+   if (ret) {
+   ret = -EFAULT;
+   goto err_submit_cmds;
+   }
+
+   /*
 * Avoid big circular locking dependency loops:
 * - reading debugfs results in mmap_sem depending on i_mutex_key#3
 *   (iterate_dir -> filldir64)
@@ -332,7 +350,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, 

[PATCH 32/48] staging: etnaviv: no point looking up the mapping for cmdstream bos

2015-09-25 Thread Lucas Stach
From: Russell King 

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 3a68295eaee4..02c5e46dca75 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -295,8 +295,7 @@ int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu,
struct drm_gem_object *obj, u32 *iova)
 {
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
-   struct etnaviv_vram_mapping *mapping =
-   etnaviv_gem_get_vram_mapping(etnaviv_obj, gpu->mmu);
+   struct etnaviv_vram_mapping *mapping;
int ret = 0;

if (etnaviv_obj->flags & ETNA_BO_CMDSTREAM) {
@@ -304,6 +303,7 @@ int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu,
return 0;
}

+   mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, gpu->mmu);
if (!mapping) {
struct page **pages = etnaviv_gem_get_pages(etnaviv_obj);
if (IS_ERR(pages))
-- 
2.5.1



[PATCH 31/48] staging: etnaviv: improve efficiency of command parser

2015-09-25 Thread Lucas Stach
From: Russell King 

Performance analysis indicates that the command parser is a hot spot
in the code.  We can improve the efficiency of the command parser by
storing the command length in a table, rather than decoding the
command manually via a switch statement.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_cmd_parser.c | 34 +---
 1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_cmd_parser.c 
b/drivers/staging/etnaviv/etnaviv_cmd_parser.c
index d866b8e2381d..7ae6ddb4306e 100644
--- a/drivers/staging/etnaviv/etnaviv_cmd_parser.c
+++ b/drivers/staging/etnaviv/etnaviv_cmd_parser.c
@@ -54,6 +54,13 @@ static bool etnaviv_validate_load_state(struct etnaviv_gpu 
*gpu, u32 *buf,
return true;
 }

+static uint8_t cmd_length[32] = {
+   [FE_OPCODE_DRAW_PRIMITIVES] = 4,
+   [FE_OPCODE_DRAW_INDEXED_PRIMITIVES] = 6,
+   [FE_OPCODE_NOP] = 2,
+   [FE_OPCODE_STALL] = 2,
+};
+
 bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
struct etnaviv_gem_object *obj, unsigned int offset, unsigned int size)
 {
@@ -69,7 +76,7 @@ bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
switch (op) {
case FE_OPCODE_LOAD_STATE:
n = EXTRACT(cmd, VIV_FE_LOAD_STATE_HEADER_COUNT);
-   len = 1 + n;
+   len = ALIGN(1 + n, 2);
if (buf + len > end)
break;

@@ -89,26 +96,17 @@ bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
len = 2 + n * 2;
break;

-   case FE_OPCODE_DRAW_PRIMITIVES:
-   len = 4;
-   break;
-
-   case FE_OPCODE_DRAW_INDEXED_PRIMITIVES:
-   len = 6;
-   break;
-
-   case FE_OPCODE_NOP:
-   case FE_OPCODE_STALL:
-   len = 2;
-   break;
-
default:
-   dev_err(gpu->dev, "%s: op %u not permitted at offset 
%tu\n",
-   __func__, op, buf - start);
-   return false;
+   len = cmd_length[op];
+   if (len == 0) {
+   dev_err(gpu->dev, "%s: op %u not permitted at 
offset %tu\n",
+   __func__, op, buf - start);
+   return false;
+   }
+   break;
}

-   buf += ALIGN(len, 2);
+   buf += len;
}

if (buf > end) {
-- 
2.5.1



[PATCH 30/48] staging: etnaviv: drop event ring buffer tracking

2015-09-25 Thread Lucas Stach
From: Russell King 

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_buffer.c | 1 -
 drivers/staging/etnaviv/etnaviv_gpu.c| 4 +---
 drivers/staging/etnaviv/etnaviv_gpu.h| 2 --
 3 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
index 01a29793aed3..cbeebfde680a 100644
--- a/drivers/staging/etnaviv/etnaviv_buffer.c
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -262,7 +262,6 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned 
int event,

/* Save the event and buffer position of the new event trigger */
gpu->event[event].fence = submit->fence;
-   gpu->event[event].ring_pos = buffer->offset;

/* trigger event */
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 7b618ed69201..137c09293375 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1021,10 +1021,8 @@ static irqreturn_t irq_handler(int irq, void *data)
 * - event 1 and event 0 complete
 * we can end up processing event 0 first, then 1.
 */
-   if (fence_after(gpu->event[event].fence, 
gpu->retired_fence)) {
+   if (fence_after(gpu->event[event].fence, 
gpu->retired_fence))
gpu->retired_fence = gpu->event[event].fence;
-   gpu->last_ring_pos = gpu->event[event].ring_pos;
-   }
event_free(gpu, event);

/*
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.h 
b/drivers/staging/etnaviv/etnaviv_gpu.h
index 44af5ca3f633..b88340302571 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.h
+++ b/drivers/staging/etnaviv/etnaviv_gpu.h
@@ -80,7 +80,6 @@ struct etnaviv_chip_identity {
 struct etnaviv_event {
bool used;
u32 fence;
-   u32 ring_pos;
 };

 struct etnaviv_gpu {
@@ -105,7 +104,6 @@ struct etnaviv_gpu {
struct list_head active_list;

u32 idle_mask;
-   u32 last_ring_pos;

/* Fencing support */
u32 submitted_fence;
-- 
2.5.1



[PATCH 29/48] staging: etnaviv: fix runtime resume

2015-09-25 Thread Lucas Stach
From: Russell King 

When resuming a core, especially if it has been powered down by a PM
domain, we need to re-initialise the clock control register, and
perform a reload of the context.

This is important where we have a GPU with multiple execution states,
where we must select the appropriate execution state prior to
processing any further GPU operations from userspace.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 38 ++-
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 2a6560be4c51..7b618ed69201 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1078,7 +1078,7 @@ static int etnaviv_gpu_clk_disable(struct etnaviv_gpu 
*gpu)
return 0;
 }

-static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
+static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
 {
if (gpu->buffer) {
unsigned long timeout;
@@ -1112,6 +1112,29 @@ static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
return etnaviv_gpu_clk_disable(gpu);
 }

+static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
+{
+   struct drm_device *drm = gpu->drm;
+   u32 clock;
+   int ret;
+
+   ret = mutex_lock_killable(>struct_mutex);
+   if (ret)
+   return ret;
+
+   clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+   VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);
+
+   etnaviv_gpu_load_clock(gpu, clock);
+   etnaviv_gpu_hw_init(gpu);
+
+   gpu->switch_context = true;
+
+   mutex_unlock(>struct_mutex);
+
+   return 0;
+}
+
 static int etnaviv_gpu_bind(struct device *dev, struct device *master,
void *data)
 {
@@ -1161,7 +1184,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct 
device *master,
pm_runtime_get_sync(gpu->dev);
pm_runtime_put_sync_suspend(gpu->dev);
 #else
-   etnaviv_gpu_suspend(gpu);
+   etnaviv_gpu_hw_suspend(gpu);
 #endif

if (gpu->buffer) {
@@ -1292,17 +1315,16 @@ static int etnaviv_gpu_rpm_suspend(struct device *dev)
if (idle != mask)
return -EBUSY;

-   return etnaviv_gpu_suspend(gpu);
+   return etnaviv_gpu_hw_suspend(gpu);
 }

 static int etnaviv_gpu_rpm_resume(struct device *dev)
 {
struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
-   struct drm_device *drm = gpu->drm;
int ret;

/* We must never runtime-PM resume holding struct_mutex */
-   if (drm && WARN_ON_ONCE(mutex_is_locked(>struct_mutex)))
+   if (gpu->drm && WARN_ON_ONCE(mutex_is_locked(>drm->struct_mutex)))
return -EDEADLK;

ret = etnaviv_gpu_clk_enable(gpu);
@@ -1310,14 +1332,12 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
return ret;

/* Re-initialise the basic hardware state */
-   if (drm && gpu->buffer) {
-   ret = mutex_lock_killable(>struct_mutex);
+   if (gpu->drm && gpu->buffer) {
+   ret = etnaviv_gpu_hw_resume(gpu);
if (ret) {
etnaviv_gpu_clk_disable(gpu);
return ret;
}
-   etnaviv_gpu_hw_init(gpu);
-   mutex_unlock(>struct_mutex);
}

return 0;
-- 
2.5.1



[PATCH 28/48] staging: etnaviv: rename GPU clock functions

2015-09-25 Thread Lucas Stach
From: Russell King 

Rename the GPU clock functions for what they actually are, splitting
the clock disable out from etnaviv_gpu_suspend().  This allows us to
fix etnaviv_gpu_rpm_resume(), which needed only to disable the clocks
on failure, rather than trying to stop an uninitialised GPU.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 33 +++--
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index d274fcf9f5b1..2a6560be4c51 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1046,7 +1046,7 @@ static irqreturn_t irq_handler(int irq, void *data)
return ret;
 }

-static int etnaviv_gpu_resume(struct etnaviv_gpu *gpu)
+static int etnaviv_gpu_clk_enable(struct etnaviv_gpu *gpu)
 {
int ret;

@@ -1063,10 +1063,23 @@ static int etnaviv_gpu_resume(struct etnaviv_gpu *gpu)
return 0;
 }

-static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
+static int etnaviv_gpu_clk_disable(struct etnaviv_gpu *gpu)
 {
int ret;

+   ret = disable_axi(gpu);
+   if (ret)
+   return ret;
+
+   ret = disable_clk(gpu);
+   if (ret)
+   return ret;
+
+   return 0;
+}
+
+static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
+{
if (gpu->buffer) {
unsigned long timeout;

@@ -1096,15 +1109,7 @@ static int etnaviv_gpu_suspend(struct etnaviv_gpu *gpu)
} while (1);
}

-   ret = disable_axi(gpu);
-   if (ret)
-   return ret;
-
-   ret = disable_clk(gpu);
-   if (ret)
-   return ret;
-
-   return 0;
+   return etnaviv_gpu_clk_disable(gpu);
 }

 static int etnaviv_gpu_bind(struct device *dev, struct device *master,
@@ -1118,7 +1123,7 @@ static int etnaviv_gpu_bind(struct device *dev, struct 
device *master,
 #ifdef CONFIG_PM
ret = pm_runtime_get_sync(gpu->dev);
 #else
-   ret = etnaviv_gpu_resume(gpu);
+   ret = etnaviv_gpu_clk_enable(gpu);
 #endif
if (ret < 0)
return ret;
@@ -1300,7 +1305,7 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
if (drm && WARN_ON_ONCE(mutex_is_locked(>struct_mutex)))
return -EDEADLK;

-   ret = etnaviv_gpu_resume(gpu);
+   ret = etnaviv_gpu_clk_enable(gpu);
if (ret)
return ret;

@@ -1308,7 +1313,7 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
if (drm && gpu->buffer) {
ret = mutex_lock_killable(>struct_mutex);
if (ret) {
-   etnaviv_gpu_suspend(gpu);
+   etnaviv_gpu_clk_disable(gpu);
return ret;
}
etnaviv_gpu_hw_init(gpu);
-- 
2.5.1



[PATCH 27/48] staging: etnaviv: provide a helper to load the GPU clock field

2015-09-25 Thread Lucas Stach
From: Russell King 

The GPU requires a double-write to set the clock divisor.  Rather than
open-coding this knowledge in a couple of places, provide a helper to
do this instead.  This avoids spreading this knowledge around the
driver.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index b12d46075732..d274fcf9f5b1 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -280,6 +280,13 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
etnaviv_hw_specs(gpu);
 }

+static void etnaviv_gpu_load_clock(struct etnaviv_gpu *gpu, u32 clock)
+{
+   gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock |
+ VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
+   gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
+}
+
 static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
 {
u32 control, idle;
@@ -301,9 +308,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);

/* enable clock */
-   gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control |
- VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
-   gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+   etnaviv_gpu_load_clock(gpu, control);

/* Wait for stable clock.  Vivante's code waited for 1ms */
usleep_range(1000, 1);
@@ -367,9 +372,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
  VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(0x40);

/* enable clock */
-   gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control |
- VIVS_HI_CLOCK_CONTROL_FSCALE_CMD_LOAD);
-   gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
+   etnaviv_gpu_load_clock(gpu, control);

return 0;
 }
-- 
2.5.1



[PATCH 26/48] staging: etnaviv: fix BUG_ON when removing module

2015-09-25 Thread Lucas Stach
From: Russell King 

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 233b2197eb37..b12d46075732 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1157,7 +1157,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct 
device *master,
 #endif

if (gpu->buffer) {
-   drm_gem_object_unreference(gpu->buffer);
+   drm_gem_object_unreference_unlocked(gpu->buffer);
gpu->buffer = NULL;
}

-- 
2.5.1



[PATCH 25/48] staging: etnaviv: increase page table size to maximum

2015-09-25 Thread Lucas Stach
From: Russell King 

Running the cairo trace "firefox-36-20090609" results in the Xorg server
trying to queue up 319M of buffer objects in a single commit (due to the
number of drawing operations that will fit into a 32K command buffer.)
This causes the commit ioctl to return -ENOSPC as the MMU is unable to
map all these buffer objects simultaneously.

There are three workarounds possible:
- Increase the GPU MMU table size
- Decrease the command buffer size
- Implement reconstruction of the command buffer on -ENOSPC return

All three should be implemented, but the first is only applicable to the
kernel.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_iommu.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_iommu.c 
b/drivers/staging/etnaviv/etnaviv_iommu.c
index 73ba65205705..9efb7d6092b4 100644
--- a/drivers/staging/etnaviv/etnaviv_iommu.c
+++ b/drivers/staging/etnaviv/etnaviv_iommu.c
@@ -25,7 +25,7 @@
 #include "etnaviv_iommu.h"
 #include "state_hi.xml.h"

-#define PT_SIZESZ_512K
+#define PT_SIZESZ_2M
 #define PT_ENTRIES (PT_SIZE / sizeof(u32))

 #define GPU_MEM_START  0x8000
@@ -88,7 +88,7 @@ static void pgtable_write(struct etnaviv_iommu_domain_pgtable 
*pgtable,

 static int __etnaviv_iommu_init(struct etnaviv_iommu_domain *etnaviv_domain)
 {
-   u32 iova, *p;
+   u32 *p;
int ret, i;

etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev,
@@ -110,11 +110,9 @@ static int __etnaviv_iommu_init(struct 
etnaviv_iommu_domain *etnaviv_domain)
return ret;
}

-   for (iova = etnaviv_domain->domain.geometry.aperture_start;
-iova < etnaviv_domain->domain.geometry.aperture_end; iova += 
SZ_4K) {
-   pgtable_write(_domain->pgtable, iova,
- etnaviv_domain->bad_page_dma);
-   }
+   for (i = 0; i < PT_ENTRIES; i++)
+   etnaviv_domain->pgtable.pgtable[i] =
+   etnaviv_domain->bad_page_dma;

spin_lock_init(_domain->map_lock);

-- 
2.5.1



[PATCH 24/48] staging: etnaviv: clean up etnaviv_iommu_unmap_gem() signature

2015-09-25 Thread Lucas Stach
From: Russell King 

The mapping structure contains everything we need; avoid passing extra
data in rather than using the data we have stored in the structure.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c |  2 +-
 drivers/staging/etnaviv/etnaviv_mmu.c | 31 ++-
 drivers/staging/etnaviv/etnaviv_mmu.h |  4 +---
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 256ec0775133..3a68295eaee4 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -509,7 +509,7 @@ static void etnaviv_free_obj(struct drm_gem_object *obj)

list_for_each_entry_safe(mapping, tmp, _obj->vram_list,
 obj_node) {
-   etnaviv_iommu_unmap_gem(mapping->mmu, etnaviv_obj, mapping);
+   etnaviv_iommu_unmap_gem(mapping);
}
 }

diff --git a/drivers/staging/etnaviv/etnaviv_mmu.c 
b/drivers/staging/etnaviv/etnaviv_mmu.c
index b327d37f5111..ca317f633970 100644
--- a/drivers/staging/etnaviv/etnaviv_mmu.c
+++ b/drivers/staging/etnaviv/etnaviv_mmu.c
@@ -196,7 +196,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,

list_for_each_entry_safe(m, n, , scan_node) {
list_del_init(>scan_node);
-   etnaviv_iommu_unmap_gem(mmu, m->object, m);
+   etnaviv_iommu_unmap_gem(m);
}

/*
@@ -230,21 +230,26 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
return ret;
 }

-void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
-struct etnaviv_gem_object *etnaviv_obj,
-struct etnaviv_vram_mapping *mapping)
+void etnaviv_iommu_unmap_gem(struct etnaviv_vram_mapping *mapping)
 {
-   if (mapping) {
-   u32 offset = mapping->vram_node.start;
+   struct etnaviv_iommu *mmu;
+   struct etnaviv_gem_object *etnaviv_obj;

-   if (mapping->iova >= 0x8000) {
-   etnaviv_iommu_unmap(mmu, offset, etnaviv_obj->sgt,
-   etnaviv_obj->base.size);
-   drm_mm_remove_node(>vram_node);
-   }
-   list_del(>obj_node);
-   kfree(mapping);
+   if (!mapping)
+   return;
+
+   mmu = mapping->mmu;
+
+   /* If the vram node is on the mm, unmap and remove the node */
+   if (mapping->vram_node.mm == >mm) {
+   etnaviv_obj = mapping->object;
+   etnaviv_iommu_unmap(mmu, mapping->vram_node.start,
+   etnaviv_obj->sgt, etnaviv_obj->base.size);
+   drm_mm_remove_node(>vram_node);
}
+
+   list_del(>obj_node);
+   kfree(mapping);
 }

 void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu)
diff --git a/drivers/staging/etnaviv/etnaviv_mmu.h 
b/drivers/staging/etnaviv/etnaviv_mmu.h
index 1d619e91f457..444ef296d2b4 100644
--- a/drivers/staging/etnaviv/etnaviv_mmu.h
+++ b/drivers/staging/etnaviv/etnaviv_mmu.h
@@ -49,9 +49,7 @@ int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova,
 int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
struct etnaviv_gem_object *etnaviv_obj, u32 memory_base,
struct etnaviv_vram_mapping **mapping);
-void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
-   struct etnaviv_gem_object *etnaviv_obj,
-   struct etnaviv_vram_mapping *mapping);
+void etnaviv_iommu_unmap_gem(struct etnaviv_vram_mapping *mapping);
 void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);

 struct etnaviv_iommu *etnaviv_iommu_new(struct device *dev,
-- 
2.5.1



[PATCH 23/48] staging: etnaviv: fix oops caused by scanning for free blocks

2015-09-25 Thread Lucas Stach
From: Russell King 

The drm_mm scanning for free MMU blocks walks the list of inactive
objects, looking up their vram node.  Unfortunately, the code assumes
that if it has a vram node, it is registered into drm_mm.

However, there are two cases when a vram node is created - whenever a
MMU entry has to be allocated (when it is registered into the drm_mm)
and when a direct mapping is registered (which isn't.)  The direct
mapping case has vram_node.mm NULL, which causes an oops in
drm_mm_scan_add_block().

The list of objects on the scanning list was also broken - we would end
up calling drm_mm_remove_block() multiple times for the same 'free'
vram node, instead of walking the list of scanned blocks.  Fix this by
having a separate list for scanned blocks.

Fixes: ("staging: etnaviv: allow to map buffer object into multiple address 
spaces")
Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c |  4 ++--
 drivers/staging/etnaviv/etnaviv_gem.h |  5 -
 drivers/staging/etnaviv/etnaviv_mmu.c | 36 +--
 3 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 23e655de7925..256ec0775133 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -508,7 +508,7 @@ static void etnaviv_free_obj(struct drm_gem_object *obj)
struct etnaviv_vram_mapping *mapping, *tmp;

list_for_each_entry_safe(mapping, tmp, _obj->vram_list,
-obj_head) {
+obj_node) {
etnaviv_iommu_unmap_gem(mapping->mmu, etnaviv_obj, mapping);
}
 }
@@ -722,7 +722,7 @@ etnaviv_gem_get_vram_mapping(struct etnaviv_gem_object *obj,
 {
struct etnaviv_vram_mapping *mapping;

-   list_for_each_entry(mapping, >vram_list, obj_head) {
+   list_for_each_entry(mapping, >vram_list, obj_node) {
if (mapping->mmu == mmu)
return mapping;
}
diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
index 08f0e6464cc7..f3136d86d73e 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.h
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -21,6 +21,7 @@
 #include "etnaviv_drv.h"

 struct etnaviv_gem_ops;
+struct etnaviv_gem_object;

 struct etnaviv_gem_userptr {
uintptr_t ptr;
@@ -30,7 +31,9 @@ struct etnaviv_gem_userptr {
 };

 struct etnaviv_vram_mapping {
-   struct list_head obj_head;
+   struct list_head obj_node;
+   struct list_head scan_node;
+   struct etnaviv_gem_object *object;
struct etnaviv_iommu *mmu;
struct drm_mm_node vram_node;
u32 iova;
diff --git a/drivers/staging/etnaviv/etnaviv_mmu.c 
b/drivers/staging/etnaviv/etnaviv_mmu.c
index f40d4ec5ade7..b327d37f5111 100644
--- a/drivers/staging/etnaviv/etnaviv_mmu.c
+++ b/drivers/staging/etnaviv/etnaviv_mmu.c
@@ -104,6 +104,8 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
if (!mapping)
return -ENOMEM;

+   INIT_LIST_HEAD(>scan_node);
+   mapping->object = etnaviv_obj;
mapping->mmu = mmu;

/* v1 MMU can optimize single entry (contiguous) scatterlists */
@@ -113,7 +115,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
iova = sg_dma_address(sgt->sgl) - memory_base;
if (iova < 0x8000 - sg_dma_len(sgt->sgl)) {
mapping->iova = iova;
-   list_add_tail(>obj_head,
+   list_add_tail(>obj_node,
  _obj->vram_list);
if (out_mapping)
*out_mapping = mapping;
@@ -123,7 +125,8 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,

node = >vram_node;
while (1) {
-   struct etnaviv_gem_object *o, *n;
+   struct etnaviv_gem_object *o;
+   struct etnaviv_vram_mapping *m, *n;
struct list_head list;
bool found;

@@ -155,13 +158,19 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
continue;

/*
+* If this vram node has not been used, skip this.
+*/
+   if (!free->vram_node.mm)
+   continue;
+
+   /*
 * If it's on the submit list, then it is part of
 * a submission, and we want to keep its entry.
 */
if (!list_empty(>submit_entry))
continue;

-   list_add(>submit_entry, );
+   list_add(>scan_node, );
if (drm_mm_scan_add_block(>vram_node)) {
 

[PATCH 22/48] staging: etnaviv: no need to initialise a list_head

2015-09-25 Thread Lucas Stach
From: Russell King 

There's no need to initialise a list_head which is only going to be
added with list_add() to an existing list.  Remove this redundant code.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_mmu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_mmu.c 
b/drivers/staging/etnaviv/etnaviv_mmu.c
index 754bcbc0c19a..f40d4ec5ade7 100644
--- a/drivers/staging/etnaviv/etnaviv_mmu.c
+++ b/drivers/staging/etnaviv/etnaviv_mmu.c
@@ -104,7 +104,6 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
if (!mapping)
return -ENOMEM;

-   INIT_LIST_HEAD(>obj_head);
mapping->mmu = mmu;

/* v1 MMU can optimize single entry (contiguous) scatterlists */
-- 
2.5.1



[PATCH 21/48] staging: etnaviv: use standard kernel types rather than stdint.h types

2015-09-25 Thread Lucas Stach
From: Russell King 

The Linux kernel dislikes the use of stdint.h types.  In order to
prepare this code for merging, we need to convert to the preferred
types, which are u8/u16/u32/u64 for unsigned ints of the specified
size, and s8/s16/s32/s64 for signed ints of the same.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_buffer.c | 10 ++--
 drivers/staging/etnaviv/etnaviv_drv.c|  2 +-
 drivers/staging/etnaviv/etnaviv_drv.h| 31 +-
 drivers/staging/etnaviv/etnaviv_gem.c| 28 -
 drivers/staging/etnaviv/etnaviv_gem.h| 24 
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 14 ++---
 drivers/staging/etnaviv/etnaviv_gpu.c| 19 +++
 drivers/staging/etnaviv/etnaviv_gpu.h| 59 ++-
 drivers/staging/etnaviv/etnaviv_iommu.c  | 12 ++--
 drivers/staging/etnaviv/etnaviv_mmu.c| 10 ++--
 drivers/staging/etnaviv/etnaviv_mmu.h|  8 +--
 include/uapi/drm/etnaviv_drm.h   | 85 ++--
 12 files changed, 150 insertions(+), 152 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
index 816dc0c4a287..01a29793aed3 100644
--- a/drivers/staging/etnaviv/etnaviv_buffer.c
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -28,7 +28,7 @@
  */


-static inline void OUT(struct etnaviv_gem_object *buffer, uint32_t data)
+static inline void OUT(struct etnaviv_gem_object *buffer, u32 data)
 {
u32 *vaddr = (u32 *)buffer->vaddr;

@@ -183,7 +183,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned 
int event,
 * if we are going to completely overflow the buffer, we need to wrap.
 */
if (buffer->offset + reserve_size >
-   buffer->base.size / sizeof(uint32_t))
+   buffer->base.size / sizeof(u32))
buffer->offset = 0;

/* save offset back into main buffer */
@@ -192,7 +192,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned 
int event,
link_size = 6;

/* Skip over any extra instructions */
-   link_target += extra_size * sizeof(uint32_t);
+   link_target += extra_size * sizeof(u32);

/* update offset for every cmd stream */
for (i = submit->nr_cmds; i--; ) {
@@ -232,8 +232,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned 
int event,
}

if (gpu->mmu->need_flush || gpu->switch_context) {
-   uint32_t new_target = gpu_va(gpu, buffer) + buffer->offset *
-   sizeof(uint32_t);
+   u32 new_target = gpu_va(gpu, buffer) + buffer->offset *
+   sizeof(u32);

if (gpu->mmu->need_flush) {
/* Add the MMU flush */
diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 4f97bb667278..d7133e4450c6 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -434,7 +434,7 @@ static int etnaviv_ioctl_gem_userptr(struct drm_device 
*dev, void *data,

if (offset_in_page(args->user_ptr | args->user_size) ||
(uintptr_t)args->user_ptr != args->user_ptr ||
-   (uint32_t)args->user_size != args->user_size)
+   (u32)args->user_size != args->user_size)
return -EINVAL;

if (args->flags & ETNA_USERPTR_WRITE)
diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
index 8f9c1f747b4e..b98db8c11ef3 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.h
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -53,7 +53,7 @@ struct etnaviv_drm_private {
int num_gpus;
struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];

-   uint32_t next_fence;
+   u32 next_fence;

/* list of GEM objects: */
struct list_head inactive_list;
@@ -61,9 +61,10 @@ struct etnaviv_drm_private {
struct workqueue_struct *wq;
 };

-static void etnaviv_queue_work(struct drm_device *dev, struct work_struct *w)
+static inline void etnaviv_queue_work(struct drm_device *dev,
+   struct work_struct *w)
 {
-   struct etnaviv_drm_private *priv = drm->dev_private;
+   struct etnaviv_drm_private *priv = dev->dev_private;

queue_work(priv->wq, w);
 }
@@ -73,11 +74,11 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void 
*data,

 int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, uint64_t *offset);
+int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
 int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu,
-   struct drm_gem_object *obj, uint32_t *iova);
+   struct drm_gem_object *obj, u32 *iova);
 int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu, struct 

[PATCH 20/48] staging: etnaviv: provide etnaviv_queue_work()

2015-09-25 Thread Lucas Stach
From: Russell King 

Provide a helper to queue a work_struct onto our private workqueue.
This avoids repetitions of:

struct drm_device *dev = ...
struct etnaviv_private *priv = dev->dev_private;

queue_work(priv->wq, w);

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.h |  7 +++
 drivers/staging/etnaviv/etnaviv_gem.c |  4 +---
 drivers/staging/etnaviv/etnaviv_gpu.c | 18 +-
 3 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
index 98536090e947..8f9c1f747b4e 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.h
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -61,6 +61,13 @@ struct etnaviv_drm_private {
struct workqueue_struct *wq;
 };

+static void etnaviv_queue_work(struct drm_device *dev, struct work_struct *w)
+{
+   struct etnaviv_drm_private *priv = drm->dev_private;
+
+   queue_work(priv->wq, w);
+}
+
 int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct drm_file *file);

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index aaa0f5eaeabd..6e114a390101 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -800,7 +800,6 @@ static void __etnaviv_gem_userptr_get_pages(struct 
work_struct *_work)

 static int etnaviv_gem_userptr_get_pages(struct etnaviv_gem_object 
*etnaviv_obj)
 {
-   struct etnaviv_drm_private *priv;
struct page **pvec = NULL;
struct get_pages_work *work;
struct mm_struct *mm;
@@ -859,8 +858,7 @@ static int etnaviv_gem_userptr_get_pages(struct 
etnaviv_gem_object *etnaviv_obj)
etnaviv_obj->userptr.work = >work;
INIT_WORK(>work, __etnaviv_gem_userptr_get_pages);

-   priv = etnaviv_obj->base.dev->dev_private;
-   queue_work(priv->wq, >work);
+   etnaviv_queue_work(etnaviv_obj->base.dev, >work);

return -EAGAIN;
 }
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 39fe69414679..4f2174431c2b 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -727,7 +727,8 @@ static void recover_worker(struct work_struct *work)
/* TODO gpu->funcs->recover(gpu); */
mutex_unlock(>struct_mutex);

-   etnaviv_gpu_retire(gpu);
+   /* Retire the buffer objects in a work */
+   etnaviv_queue_work(gpu->dev, >retire_work);
 }

 static void hangcheck_timer_reset(struct etnaviv_gpu *gpu)
@@ -740,8 +741,6 @@ static void hangcheck_timer_reset(struct etnaviv_gpu *gpu)
 static void hangcheck_handler(unsigned long data)
 {
struct etnaviv_gpu *gpu = (struct etnaviv_gpu *)data;
-   struct drm_device *dev = gpu->drm;
-   struct etnaviv_drm_private *priv = dev->dev_private;
uint32_t fence = gpu->retired_fence;
bool progress = false;

@@ -765,7 +764,7 @@ static void hangcheck_handler(unsigned long data)
dev_err(gpu->dev, " completed fence: %u\n", fence);
dev_err(gpu->dev, " submitted fence: %u\n",
gpu->submitted_fence);
-   queue_work(priv->wq, >recover_work);
+   etnaviv_queue_work(gpu->dev, >recover_work);
}

/* if still more pending work, reset the hangcheck timer: */
@@ -864,14 +863,6 @@ static void retire_worker(struct work_struct *work)
wake_up_all(>fence_event);
 }

-/* call from irq handler to schedule work to retire bo's */
-void etnaviv_gpu_retire(struct etnaviv_gpu *gpu)
-{
-   struct etnaviv_drm_private *priv = gpu->drm->dev_private;
-
-   queue_work(priv->wq, >retire_work);
-}
-
 int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
uint32_t fence, struct timespec *timeout)
 {
@@ -1044,7 +1035,8 @@ static irqreturn_t irq_handler(int irq, void *data)
pm_runtime_put_autosuspend(gpu->dev);
}

-   etnaviv_gpu_retire(gpu);
+   /* Retire the buffer objects in a work */
+   etnaviv_queue_work(gpu->dev, >retire_work);

ret = IRQ_HANDLED;
}
-- 
2.5.1



[PATCH 19/48] staging: etnaviv: switch to per-GPU fence completion implementation

2015-09-25 Thread Lucas Stach
From: Russell King 

Having a global fence completion implementation in the presence of
mutliple GPU cores which can complete out of order is buggy.  Consider
the case of two processes submitting work for two GPU cores:

GPU A   GPU B
priv->completed_fence = 0
gpu->submitted_fence = 0gpu->submitted_fence = 0
gpu->retired_fence = 0  gpu->retired_fence = 0

process A submits work,
allocated fence 1,
gpu->submitted_fence = 1,
priv->next_fence = 2
process B submits work,
allocated fence 2,
gpu->submitted_fence = 2,
priv->next_fence = 3

GPU B finishes,
gpu->retired_fence = 2
runs work queue,
priv->completed_fence = 2

At this point, GPU A's buffers have fence 1, and when tested by
etnaviv_wait_fence_interruptable(), it compares fence 1 to the global
priv->completed_fence, and decides that GPU A has also finished its
work.

This is plainly incorrect at this point.

Solve this by moving etnaviv_wait_fence_interruptable() into the GPU
code, and arrange for it to decide whether the fence has completed
based upon the GPUs submitted and retired fence markers.

This allows us to get rid of the global priv->completed_fence, and
change the global fence wait queue to a per-GPU fence wait queue, thus
avoiding disturbing sleepers on other (busy) GPUs.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 64 ++-
 drivers/staging/etnaviv/etnaviv_drv.h |  8 +
 drivers/staging/etnaviv/etnaviv_gem.c |  7 ++--
 drivers/staging/etnaviv/etnaviv_gpu.c | 44 ++--
 drivers/staging/etnaviv/etnaviv_gpu.h | 12 ++-
 5 files changed, 58 insertions(+), 77 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 7ec4b224b589..4f97bb667278 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -133,8 +133,6 @@ static int etnaviv_load(struct drm_device *dev, unsigned 
long flags)
goto err_wq;
}

-   init_waitqueue_head(>fence_event);
-
INIT_LIST_HEAD(>inactive_list);
priv->num_gpus = 0;

@@ -310,64 +308,6 @@ static void etnaviv_debugfs_cleanup(struct drm_minor 
*minor)
 #endif

 /*
- * Fences:
- */
-int etnaviv_wait_fence_interruptable(struct drm_device *dev,
-   struct etnaviv_gpu *gpu, uint32_t fence,
-   struct timespec *timeout)
-{
-   struct etnaviv_drm_private *priv = dev->dev_private;
-   int ret;
-
-   if (fence_after(fence, gpu->submitted_fence)) {
-   DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
-   fence, gpu->submitted_fence);
-   return -EINVAL;
-   }
-
-   if (!timeout) {
-   /* no-wait: */
-   ret = fence_completed(dev, fence) ? 0 : -EBUSY;
-   } else {
-   unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
-   unsigned long start_jiffies = jiffies;
-   unsigned long remaining_jiffies;
-
-   if (time_after(start_jiffies, timeout_jiffies))
-   remaining_jiffies = 0;
-   else
-   remaining_jiffies = timeout_jiffies - start_jiffies;
-
-   ret = wait_event_interruptible_timeout(priv->fence_event,
-   fence_completed(dev, fence),
-   remaining_jiffies);
-
-   if (ret == 0) {
-   DBG("timeout waiting for fence: %u (completed: %u)",
-   fence, priv->completed_fence);
-   ret = -ETIMEDOUT;
-   } else if (ret != -ERESTARTSYS) {
-   ret = 0;
-   }
-   }
-
-   return ret;
-}
-
-/* called from workqueue */
-void etnaviv_update_fence(struct drm_device *dev, uint32_t fence)
-{
-   struct etnaviv_drm_private *priv = dev->dev_private;
-
-   mutex_lock(>struct_mutex);
-   if (fence_after(fence, priv->completed_fence))
-   priv->completed_fence = fence;
-   mutex_unlock(>struct_mutex);
-
-   wake_up_all(>fence_event);
-}
-
-/*
  * DRM ioctls:
  */

@@ -478,8 +418,8 @@ static int etnaviv_ioctl_wait_fence(struct drm_device *dev, 
void *data,
if (!gpu)
return -ENXIO;

-   return etnaviv_wait_fence_interruptable(dev, gpu,
-   args->fence, (args->timeout));
+   return etnaviv_gpu_wait_fence_interruptible(gpu, args->fence,
+ 

[PATCH 18/48] staging: etnaviv: make context a per-GPU thing

2015-09-25 Thread Lucas Stach
From: Russell King 

Tracking the current context on a system wide level is incorrect: if the
context for one GPU core changes, the context does not change on other
GPU cores.  Make the context tracking a per-GPU thing.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 9 +++--
 drivers/staging/etnaviv/etnaviv_drv.h | 1 -
 drivers/staging/etnaviv/etnaviv_gpu.c | 5 ++---
 drivers/staging/etnaviv/etnaviv_gpu.h | 1 +
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index a87de2e79fee..7ec4b224b589 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -173,10 +173,15 @@ static void etnaviv_preclose(struct drm_device *dev, 
struct drm_file *file)
 {
struct etnaviv_drm_private *priv = dev->dev_private;
struct etnaviv_file_private *ctx = file->driver_priv;
+   unsigned int i;

mutex_lock(>struct_mutex);
-   if (ctx == priv->lastctx)
-   priv->lastctx = NULL;
+   for (i = 0; i < ETNA_MAX_PIPES; i++) {
+   struct etnaviv_gpu *gpu = priv->gpu[i];
+
+   if (gpu && gpu->lastctx == ctx)
+   gpu->lastctx = NULL;
+   }
mutex_unlock(>struct_mutex);

kfree(ctx);
diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
index 37992342bbf0..f7aff4b2562c 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.h
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -52,7 +52,6 @@ struct etnaviv_file_private {
 struct etnaviv_drm_private {
int num_gpus;
struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
-   struct etnaviv_file_private *lastctx;

uint32_t next_fence, completed_fence;
wait_queue_head_t fence_event;
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 9f4e99855517..2dbf25121a07 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -916,15 +916,14 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,

gpu->submitted_fence = submit->fence;

-   if (priv->lastctx != ctx) {
+   if (gpu->lastctx != ctx) {
gpu->mmu->need_flush = true;
gpu->switch_context = true;
+   gpu->lastctx = ctx;
}

etnaviv_buffer_queue(gpu, event, submit);

-   priv->lastctx = ctx;
-
for (i = 0; i < submit->nr_bos; i++) {
struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.h 
b/drivers/staging/etnaviv/etnaviv_gpu.h
index 6b4f241c0ca6..67f6097ba576 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.h
+++ b/drivers/staging/etnaviv/etnaviv_gpu.h
@@ -87,6 +87,7 @@ struct etnaviv_gpu {
struct drm_device *drm;
struct device *dev;
struct etnaviv_chip_identity identity;
+   struct etnaviv_file_private *lastctx;
bool switch_context;

/* 'ring'-buffer: */
-- 
2.5.1



[PATCH 17/48] staging: etnaviv: allow etnaviv_ioctl_gem_info() locking to be interruptible

2015-09-25 Thread Lucas Stach
From: Russell King 

Move the locking out of etnaviv_gem_mmap_offset() into its solitary
caller, and take the mutex using mutex_lock_interruptible().  This
allows etnaviv_ioctl_gem_info() to handle signals while trying to
obtain this lock.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 7 ++-
 drivers/staging/etnaviv/etnaviv_gem.c | 7 ++-
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 9962318075c5..a87de2e79fee 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -447,7 +447,12 @@ static int etnaviv_ioctl_gem_info(struct drm_device *dev, 
void *data,
if (!obj)
return -ENOENT;

-   ret = etnaviv_gem_mmap_offset(obj, >offset);
+   ret = mutex_lock_interruptible(>struct_mutex);
+   if (ret == 0) {
+   ret = etnaviv_gem_mmap_offset(obj, >offset);
+
+   mutex_unlock(>struct_mutex);
+   }

drm_gem_object_unreference_unlocked(obj);

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 38dee80d996c..b1984a4ac0c5 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -269,20 +269,17 @@ out:
}
 }

-/** get mmap offset */
+/* get mmap offset - must be called under struct_mutex */
 int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, uint64_t *offset)
 {
-   struct drm_device *dev = obj->dev;
int ret;

-   mutex_lock(>struct_mutex);
/* Make it mmapable */
ret = drm_gem_create_mmap_offset(obj);
if (ret)
-   dev_err(dev->dev, "could not allocate mmap offset\n");
+   dev_err(obj->dev->dev, "could not allocate mmap offset\n");
else
*offset = drm_vma_node_offset_addr(>vma_node);
-   mutex_unlock(>struct_mutex);

return ret;
 }
-- 
2.5.1



[PATCH 16/48] staging: etnaviv: give etnaviv_gem_mmap_offset() a sane behaviour

2015-09-25 Thread Lucas Stach
From: Russell King 

etnaviv_gem_mmap_offset() returned zero if drm_gem_create_mmap_offset()
failed.  This is incorrect behaviour as etnaviv_ioctl_gem_info() does
not detect this condition, so it returns success.

Fix this by re-architecting etnaviv_gem_mmap_offset().  Merge
mmap_offset() into this function, and change its prototype to accept a
pointer to the "offset" return value, thereby allowing it to return a
standard negative errno code.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c |  4 ++--
 drivers/staging/etnaviv/etnaviv_drv.h |  2 +-
 drivers/staging/etnaviv/etnaviv_gem.c | 26 +++---
 3 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 1071c449f3d4..9962318075c5 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -438,7 +438,7 @@ static int etnaviv_ioctl_gem_info(struct drm_device *dev, 
void *data,
 {
struct drm_etnaviv_gem_info *args = data;
struct drm_gem_object *obj;
-   int ret = 0;
+   int ret;

if (args->pad)
return -EINVAL;
@@ -447,7 +447,7 @@ static int etnaviv_ioctl_gem_info(struct drm_device *dev, 
void *data,
if (!obj)
return -ENOENT;

-   args->offset = etnaviv_gem_mmap_offset(obj);
+   ret = etnaviv_gem_mmap_offset(obj, >offset);

drm_gem_object_unreference_unlocked(obj);

diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
index 9abb7f8c2dc0..37992342bbf0 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.h
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -73,7 +73,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void 
*data,

 int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-uint64_t etnaviv_gem_mmap_offset(struct drm_gem_object *obj);
+int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, uint64_t *offset);
 int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu,
struct drm_gem_object *obj, uint32_t *iova);
 int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 522e5a6c3612..38dee80d996c 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -270,33 +270,21 @@ out:
 }

 /** get mmap offset */
-static uint64_t mmap_offset(struct drm_gem_object *obj)
+int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, uint64_t *offset)
 {
struct drm_device *dev = obj->dev;
int ret;

-   WARN_ON(!mutex_is_locked(>struct_mutex));
-
+   mutex_lock(>struct_mutex);
/* Make it mmapable */
ret = drm_gem_create_mmap_offset(obj);
-
-   if (ret) {
+   if (ret)
dev_err(dev->dev, "could not allocate mmap offset\n");
-   return 0;
-   }
-
-   return drm_vma_node_offset_addr(>vma_node);
-}
-
-uint64_t etnaviv_gem_mmap_offset(struct drm_gem_object *obj)
-{
-   uint64_t offset;
-
-   mutex_lock(>dev->struct_mutex);
-   offset = mmap_offset(obj);
-   mutex_unlock(>dev->struct_mutex);
+   else
+   *offset = drm_vma_node_offset_addr(>vma_node);
+   mutex_unlock(>struct_mutex);

-   return offset;
+   return ret;
 }

 /* should be called under struct_mutex.. although it can be called
-- 
2.5.1



[PATCH 15/48] staging: etnaviv: etnaviv_gem_fault: reduce struct_mutex exposure

2015-09-25 Thread Lucas Stach
From: Russell King 

Reduce the exposure of struct_mutex to an absolute minimum.  We only
need to take this lock over the call to etnaviv_gem_get_pages() as
vm_insert_page() already does a properly synchronised update of the
PTE (using the pte table lock.)

Reducing the code covered by this lock allows for more parallel
execution in SMP environments.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 69360c899b78..522e5a6c3612 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -221,8 +221,10 @@ int etnaviv_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)
pgoff_t pgoff;
int ret;

-   /* Make sure we don't parallel update on a fault, nor move or remove
-* something from beneath our feet
+   /*
+* Make sure we don't parallel update on a fault, nor move or remove
+* something from beneath our feet.  Note that vm_insert_page() is
+* specifically coded to take care of this, so we don't have to.
 */
ret = mutex_lock_interruptible(>struct_mutex);
if (ret)
@@ -230,9 +232,11 @@ int etnaviv_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)

/* make sure we have pages attached now */
pages = etnaviv_gem_get_pages(to_etnaviv_bo(obj));
+   mutex_unlock(>struct_mutex);
+
if (IS_ERR(pages)) {
ret = PTR_ERR(pages);
-   goto out_unlock;
+   goto out;
}

/* We don't use vmf->pgoff since that has the fake offset: */
@@ -246,8 +250,6 @@ int etnaviv_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)

ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);

-out_unlock:
-   mutex_unlock(>struct_mutex);
 out:
switch (ret) {
case -EAGAIN:
-- 
2.5.1



[PATCH 14/48] staging: etnaviv: use vm_insert_page() rather than vm_insert_mixed()

2015-09-25 Thread Lucas Stach
From: Russell King 

We're only ever going to insert using a pointer to a struct page.  Use
vm_insert_page() rather than converting back and forth between a
struct page and a PFN.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 0b823a9566d3..69360c899b78 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -217,8 +217,7 @@ int etnaviv_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)
 {
struct drm_gem_object *obj = vma->vm_private_data;
struct drm_device *dev = obj->dev;
-   struct page **pages;
-   unsigned long pfn;
+   struct page **pages, *page;
pgoff_t pgoff;
int ret;

@@ -240,12 +239,12 @@ int etnaviv_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)
pgoff = ((unsigned long)vmf->virtual_address -
vma->vm_start) >> PAGE_SHIFT;

-   pfn = page_to_pfn(pages[pgoff]);
+   page = pages[pgoff];

VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
-   pfn, pfn << PAGE_SHIFT);
+page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);

-   ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
+   ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);

 out_unlock:
mutex_unlock(>struct_mutex);
-- 
2.5.1



[PATCH 13/48] staging: etnaviv: fix gpu debugfs show implementation

2015-09-25 Thread Lucas Stach
From: Russell King 

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 43 ---
 drivers/staging/etnaviv/etnaviv_gpu.c | 21 ++---
 drivers/staging/etnaviv/etnaviv_gpu.h |  2 +-
 3 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 8dcd7f19ecff..1071c449f3d4 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -187,23 +187,6 @@ static void etnaviv_preclose(struct drm_device *dev, 
struct drm_file *file)
  */

 #ifdef CONFIG_DEBUG_FS
-static int etnaviv_gpu_show(struct drm_device *dev, struct seq_file *m)
-{
-   struct etnaviv_drm_private *priv = dev->dev_private;
-   struct etnaviv_gpu *gpu;
-   unsigned int i;
-
-   for (i = 0; i < ETNA_MAX_PIPES; i++) {
-   gpu = priv->gpu[i];
-   if (gpu) {
-   seq_printf(m, "%s Status:\n", dev_name(gpu->dev));
-   etnaviv_gpu_debugfs(gpu, m);
-   }
-   }
-
-   return 0;
-}
-
 static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m)
 {
struct etnaviv_drm_private *priv = dev->dev_private;
@@ -266,8 +249,32 @@ static int show_locked(struct seq_file *m, void *arg)
return ret;
 }

+static int show_each_gpu(struct seq_file *m, void *arg)
+{
+   struct drm_info_node *node = (struct drm_info_node *) m->private;
+   struct drm_device *dev = node->minor->dev;
+   struct etnaviv_drm_private *priv = dev->dev_private;
+   struct etnaviv_gpu *gpu;
+   int (*show)(struct etnaviv_gpu *gpu, struct seq_file *m) =
+   node->info_ent->data;
+   unsigned int i;
+   int ret = 0;
+
+   for (i = 0; i < ETNA_MAX_PIPES; i++) {
+   gpu = priv->gpu[i];
+   if (!gpu)
+   continue;
+
+   ret = show(gpu, m);
+   if (ret < 0)
+   break;
+   }
+
+   return ret;
+}
+
 static struct drm_info_list etnaviv_debugfs_list[] = {
-   {"gpu", show_locked, 0, etnaviv_gpu_show},
+   {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs},
{"gem", show_locked, 0, etnaviv_gem_show},
{ "mm", show_locked, 0, etnaviv_mm_show },
{"mmu", show_locked, 0, etnaviv_mmu_show},
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 570bcd60025b..9f4e99855517 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -547,13 +547,21 @@ static void verify_dma(struct etnaviv_gpu *gpu, struct 
dma_debug *debug)
}
 }

-void etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
+int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
 {
struct dma_debug debug;
u32 dma_lo, dma_hi, axi, idle;
+   int ret;
+
+   seq_printf(m, "%s Status:\n", dev_name(gpu->dev));
+
+   ret = pm_runtime_get_sync(gpu->dev);
+   if (ret < 0)
+   return ret;

-   if (pm_runtime_get_sync(gpu->dev) < 0)
-   return;
+   ret = mutex_lock_interruptible(>drm->struct_mutex);
+   if (ret < 0)
+   goto err_rpm;

dma_lo = gpu_read(gpu, VIVS_FE_DMA_LOW);
dma_hi = gpu_read(gpu, VIVS_FE_DMA_HIGH);
@@ -653,8 +661,15 @@ void etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct 
seq_file *m)
seq_printf(m, "\t last fetch 64 bit word: 0x%08x 0x%08x\n",
   dma_lo, dma_hi);

+   ret = 0;
+
+   mutex_unlock(>drm->struct_mutex);
+
+err_rpm:
pm_runtime_mark_last_busy(gpu->dev);
pm_runtime_put_autosuspend(gpu->dev);
+
+   return ret;
 }
 #endif

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.h 
b/drivers/staging/etnaviv/etnaviv_gpu.h
index 21e45e875e73..6b4f241c0ca6 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.h
+++ b/drivers/staging/etnaviv/etnaviv_gpu.h
@@ -146,7 +146,7 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, uint32_t 
param,
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu);

 #ifdef CONFIG_DEBUG_FS
-void etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
+int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
 #endif

 void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
-- 
2.5.1



[PATCH 12/48] staging: etnaviv: avoid lockdep circular dependency warning

2015-09-25 Thread Lucas Stach
From: Russell King 

Avoid the below circular dependency warning by avoiding calling
pm_runtime_get_sync() at a point where struct_mutex is held, and we
may well provoke the power domain to be resumed.

We avoid this simply by referencing the runtime PM in the
etnaviv_gem_submit() function just before we take the lock, and
drop it after we drop the lock.  We leave the rest of the runtime
PM management in place - the runtime PM inside etnaviv_gpu_submit()
won't trigger a resume as the resume will have been done by
etnaviv_gem_submit() outside of the lock.

==
[ INFO: possible circular locking dependency detected ]
4.1.0-rc2+ #1618 Not tainted
---
bash/1261 is trying to acquire lock:
 (>mmap_sem){++}, at: [] might_fault+0x44/0x98

but task is already holding lock:
 (>s_type->i_mutex_key#3){+.+.+.}, at: [] iterate_dir+0x3c/0x108

which lock already depends on the new lock.

the existing dependency chain (in reverse order) is:

-> #6 (>s_type->i_mutex_key#3){+.+.+.}:
   [] mutex_lock_nested+0x5c/0x3dc
   [] start_creating+0x58/0xb4
   [] debugfs_create_dir+0x14/0xcc
   [] create_regulator+0xcc/0x1fc
   [] _regulator_get+0x10c/0x208
   [] regulator_get_optional+0x18/0x1c
   [] _devm_regulator_get+0x84/0xc0
   [] devm_regulator_get_optional+0x14/0x18
   [] imx_gpc_probe+0x20/0x110
   [] platform_drv_probe+0x50/0xac
   [] driver_probe_device+0x1d4/0x278
   [] __driver_attach+0x9c/0xa0
   [] bus_for_each_dev+0x5c/0x90
   [] driver_attach+0x24/0x28
   [] bus_add_driver+0xe0/0x1dc
   [] driver_register+0x80/0xfc
   [] __platform_driver_register+0x50/0x64
   [] imx_pgc_init+0x18/0x20
   [] do_one_initcall+0x88/0x1dc
   [] kernel_init_freeable+0x114/0x1e0
   [] kernel_init+0x10/0xec
   [] ret_from_fork+0x14/0x3c

-> #5 (>mutex){+.+.+.}:
   [] mutex_lock_nested+0x5c/0x3dc
   [] regulator_enable+0x48/0x12c
   [] imx6q_pm_pu_power_on+0x20/0x170
   [] genpd_power_on+0x38/0xf4
   [] __pm_genpd_poweron+0x1a4/0x1b4
   [] pm_genpd_poweron+0x28/0x3c
   [] genpd_dev_pm_attach+0xb4/0x12c
   [] dev_pm_domain_attach+0x10/0x14
   [] platform_drv_probe+0x34/0xac
   [] driver_probe_device+0x1d4/0x278
   [] __driver_attach+0x9c/0xa0
   [] bus_for_each_dev+0x5c/0x90
   [] driver_attach+0x24/0x28
   [] bus_add_driver+0xe0/0x1dc
   [] driver_register+0x80/0xfc
   [] __platform_driver_register+0x50/0x64
   [] etnaviv_init+0x18/0x4c
   [] do_one_initcall+0x88/0x1dc
   [] kernel_init_freeable+0x114/0x1e0
   [] kernel_init+0x10/0xec
   [] ret_from_fork+0x14/0x3c

-> #4 (>lock){+.+...}:
   [] mutex_lock_nested+0x5c/0x3dc
   [] pm_genpd_runtime_resume+0x98/0x230
   [] __rpm_callback+0x3c/0x78
   [] rpm_callback+0x30/0x90
   [] rpm_resume+0x3c4/0x5a4
   [] __pm_runtime_resume+0x70/0x90
   [] etnaviv_gpu_submit+0x30/0x220
   [] etnaviv_ioctl_gem_submit+0x9a4/0xaf0
   [] drm_ioctl+0x2a4/0x4e4
   [] do_vfs_ioctl+0x84/0x66c
   [] SyS_ioctl+0x3c/0x60
   [] ret_fast_syscall+0x0/0x54

-> #3 (reservation_ww_class_mutex){+.+.+.}:
   [] __ww_mutex_lock_interruptible+0x64/0x6f8
   [] etnaviv_ioctl_gem_submit+0x47c/0xaf0
   [] drm_ioctl+0x2a4/0x4e4
   [] do_vfs_ioctl+0x84/0x66c
   [] SyS_ioctl+0x3c/0x60
   [] ret_fast_syscall+0x0/0x54

-> #2 (reservation_ww_class_acquire){+.+.+.}:
   [] etnaviv_ioctl_gem_submit+0x16c/0xaf0
   [] drm_ioctl+0x2a4/0x4e4
   [] do_vfs_ioctl+0x84/0x66c
   [] SyS_ioctl+0x3c/0x60
   [] ret_fast_syscall+0x0/0x54

-> #1 (>struct_mutex){+.+.+.}:
   [] mutex_lock_nested+0x5c/0x3dc
   [] drm_gem_mmap+0x3c/0xe0
   [] drm_gem_cma_mmap+0x14/0x2c
   [] mmap_region+0x3d0/0x6a4
   [] do_mmap_pgoff+0x2e4/0x374
   [] vm_mmap_pgoff+0x6c/0x9c
   [] SyS_mmap_pgoff+0x94/0xb8
   [] ret_fast_syscall+0x0/0x54

-> #0 (>mmap_sem){++}:
   [] lock_acquire+0xa0/0x120
   [] might_fault+0x64/0x98
   [] filldir64+0x74/0x184
   [] dcache_readdir+0x1c8/0x28c
   [] iterate_dir+0x88/0x108
   [] SyS_getdents64+0x7c/0xec
   [] ret_fast_syscall+0x0/0x54

other info that might help us debug this:

Chain exists of:
  >mmap_sem --> >mutex --> >s_type->i_mutex_key#3

 Possible unsafe locking scenario:

   CPU0CPU1
   
  lock(>s_type->i_mutex_key#3);
   lock(>mutex);
   lock(>s_type->i_mutex_key#3);
  lock(>mmap_sem);

 *** DEADLOCK ***

1 lock held by bash/1261:
 #0:  (>s_type->i_mutex_key#3){+.+.+.}, at: [] 
iterate_dir+0x3c/0x108

stack backtrace:
CPU: 0 PID: 1261 Comm: bash Not tainted 4.1.0-rc2+ #1618
Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
Backtrace:
[] (dump_backtrace) from [] 

[PATCH 11/48] staging: etnaviv: fix off-by-one for iommu aperture end

2015-09-25 Thread Lucas Stach
From: Russell King 

The aperture end address is inclusive, not exclusive.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_iommu.c 
b/drivers/staging/etnaviv/etnaviv_iommu.c
index 8f92578ea3ee..8aff23a310fb 100644
--- a/drivers/staging/etnaviv/etnaviv_iommu.c
+++ b/drivers/staging/etnaviv/etnaviv_iommu.c
@@ -209,7 +209,7 @@ struct iommu_domain *etnaviv_iommu_domain_alloc(struct 
etnaviv_gpu *gpu)
etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING;
etnaviv_domain->domain.ops = _iommu_ops;
etnaviv_domain->domain.geometry.aperture_start = GPU_MEM_START;
-   etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + 
PT_ENTRIES * SZ_4K;
+   etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + 
PT_ENTRIES * SZ_4K - 1;

ret = __etnaviv_iommu_init(etnaviv_domain);
if (ret)
-- 
2.5.1



[PATCH 10/48] staging: etnaviv: fix missing error cleanups in etnaviv_load()

2015-09-25 Thread Lucas Stach
From: Russell King 

The only failure which etnaviv_load() implemented was for kzalloc().
Other failures (alloc_ordered_workqueue(), component_bind_all()) were
not implemented.  Add these.

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index b2ce4a6467ed..8dcd7f19ecff 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -128,6 +128,11 @@ static int etnaviv_load(struct drm_device *dev, unsigned 
long flags)
dev->dev_private = priv;

priv->wq = alloc_ordered_workqueue("etnaviv", 0);
+   if (!priv->wq) {
+   err = -ENOMEM;
+   goto err_wq;
+   }
+
init_waitqueue_head(>fence_event);

INIT_LIST_HEAD(>inactive_list);
@@ -137,11 +142,18 @@ static int etnaviv_load(struct drm_device *dev, unsigned 
long flags)

err = component_bind_all(dev->dev, dev);
if (err < 0)
-   return err;
+   goto err_bind;

load_gpu(dev);

return 0;
+
+err_bind:
+   flush_workqueue(priv->wq);
+   destroy_workqueue(priv->wq);
+err_wq:
+   kfree(priv);
+   return err;
 }

 static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
-- 
2.5.1



[PATCH 09/48] staging: etnaviv: add Dove GPU subsystem compatible

2015-09-25 Thread Lucas Stach
From: Russell King 

Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_drv.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index 5a53c6969fcd..b2ce4a6467ed 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -622,6 +622,7 @@ static int etnaviv_pdev_remove(struct platform_device *pdev)

 static const struct of_device_id dt_match[] = {
{ .compatible = "fsl,imx-gpu-subsystem" },
+   { .compatible = "marvell,dove-gpu-subsystem" },
{}
 };
 MODULE_DEVICE_TABLE(of, dt_match);
-- 
2.5.1



[PATCH 08/48] staging: etnaviv: add proper license header to all files

2015-09-25 Thread Lucas Stach
Signed-off-by: Lucas Stach 
Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_buffer.c |  2 +-
 drivers/staging/etnaviv/etnaviv_cmd_parser.c | 16 
 drivers/staging/etnaviv/etnaviv_drv.c|  3 +--
 drivers/staging/etnaviv/etnaviv_drv.h|  3 +--
 drivers/staging/etnaviv/etnaviv_gem.c|  3 +--
 drivers/staging/etnaviv/etnaviv_gem.h|  3 +--
 drivers/staging/etnaviv/etnaviv_gem_submit.c |  3 +--
 drivers/staging/etnaviv/etnaviv_gpu.c|  3 +--
 drivers/staging/etnaviv/etnaviv_gpu.h|  3 +--
 drivers/staging/etnaviv/etnaviv_mmu.c|  3 +--
 drivers/staging/etnaviv/etnaviv_mmu.h|  3 +--
 11 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_buffer.c 
b/drivers/staging/etnaviv/etnaviv_buffer.c
index 85a5a15f0e02..816dc0c4a287 100644
--- a/drivers/staging/etnaviv/etnaviv_buffer.c
+++ b/drivers/staging/etnaviv/etnaviv_buffer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 2014 Etnaviv Project
+ * Copyright (C) 2014 Etnaviv Project
  * Author: Christian Gmeiner 
  *
  * This program is free software; you can redistribute it and/or modify it
diff --git a/drivers/staging/etnaviv/etnaviv_cmd_parser.c 
b/drivers/staging/etnaviv/etnaviv_cmd_parser.c
index b429451baca5..d866b8e2381d 100644
--- a/drivers/staging/etnaviv/etnaviv_cmd_parser.c
+++ b/drivers/staging/etnaviv/etnaviv_cmd_parser.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2015 Etnaviv Project
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
 #include 

 #include "etnaviv_gem.h"
diff --git a/drivers/staging/etnaviv/etnaviv_drv.c 
b/drivers/staging/etnaviv/etnaviv_drv.c
index f7c21b45a991..5a53c6969fcd 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.c
+++ b/drivers/staging/etnaviv/etnaviv_drv.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark 
+ * Copyright (C) 2015 Etnaviv Project
  *
  * 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
diff --git a/drivers/staging/etnaviv/etnaviv_drv.h 
b/drivers/staging/etnaviv/etnaviv_drv.h
index cde898f33c53..9abb7f8c2dc0 100644
--- a/drivers/staging/etnaviv/etnaviv_drv.h
+++ b/drivers/staging/etnaviv/etnaviv_drv.h
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark 
+ * Copyright (C) 2015 Etnaviv Project
  *
  * 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
diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 22407846320b..0b823a9566d3 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark 
+ * Copyright (C) 2015 Etnaviv Project
  *
  * 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
diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
index c801b9a161e6..397b30f39708 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.h
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark 
+ * Copyright (C) 2015 Etnaviv Project
  *
  * 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
diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c 
b/drivers/staging/etnaviv/etnaviv_gem_submit.c
index 2c0eec63e3e1..eb3c5bd68418 100644
--- a/drivers/staging/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark 
+ * Copyright (C) 2015 Etnaviv Project
  *
  * 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
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index c541152a08dc..dd885870cc7c 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2013 Red Hat
- * Author: Rob Clark 
+ * Copyright (C) 2015 Etnaviv Project
  *
  * This 

[PATCH 07/48] staging: etnaviv: quiten down kernel log output

2015-09-25 Thread Lucas Stach
From: Christian Gmeiner 

There is no need to spam the kernel logs with the GPU specs and features
at startup. If someone wants to know about this stuff debugfs should be
the right place to look at.

Also use better format specifiers to make it easier for humans to read.

Signed-off-by: Christian Gmeiner 
Signed-off-by: Lucas Stach 
Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gpu.c | 64 ++-
 1 file changed, 33 insertions(+), 31 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index 0a8c0d3845dd..c541152a08dc 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -187,27 +187,6 @@ static void etnaviv_hw_specs(struct etnaviv_gpu *gpu)
gpu->identity.instruction_count = 256;
break;
}
-
-   dev_info(gpu->dev, "stream_count:  %x\n",
-gpu->identity.stream_count);
-   dev_info(gpu->dev, "register_max: %x\n",
-gpu->identity.register_max);
-   dev_info(gpu->dev, "thread_count: %x\n",
-gpu->identity.thread_count);
-   dev_info(gpu->dev, "vertex_cache_size: %x\n",
-gpu->identity.vertex_cache_size);
-   dev_info(gpu->dev, "shader_core_count: %x\n",
-gpu->identity.shader_core_count);
-   dev_info(gpu->dev, "pixel_pipes: %x\n",
-gpu->identity.pixel_pipes);
-   dev_info(gpu->dev, "vertex_output_buffer_size: %x\n",
-gpu->identity.vertex_output_buffer_size);
-   dev_info(gpu->dev, "buffer_size: %x\n",
-gpu->identity.buffer_size);
-   dev_info(gpu->dev, "instruction_count: %x\n",
-gpu->identity.instruction_count);
-   dev_info(gpu->dev, "num_constants: %x\n",
-gpu->identity.num_constants);
 }

 static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
@@ -252,7 +231,7 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
}
}

-   dev_info(gpu->dev, "model: %x - revision %x\n",
+   dev_info(gpu->dev, "model: GC%x, revision: %x\n",
 gpu->identity.model, gpu->identity.revision);

gpu->identity.features = gpu_read(gpu, VIVS_HI_CHIP_FEATURE);
@@ -286,15 +265,6 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_3);
}

-   dev_info(gpu->dev, "minor_features:  %x\n",
-gpu->identity.minor_features0);
-   dev_info(gpu->dev, "minor_features1: %x\n",
-gpu->identity.minor_features1);
-   dev_info(gpu->dev, "minor_features2: %x\n",
-gpu->identity.minor_features2);
-   dev_info(gpu->dev, "minor_features3: %x\n",
-gpu->identity.minor_features3);
-
/* GC600 idle register reports zero bits where modules aren't present */
if (gpu->identity.model == chipModel_GC600) {
gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
@@ -593,6 +563,38 @@ void etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct 
seq_file *m)

verify_dma(gpu, );

+   seq_puts(m, "\tfeatures\n");
+   seq_printf(m, "\t minor_features0: 0x%08x\n",
+  gpu->identity.minor_features0);
+   seq_printf(m, "\t minor_features1: 0x%08x\n",
+  gpu->identity.minor_features1);
+   seq_printf(m, "\t minor_features2: 0x%08x\n",
+  gpu->identity.minor_features2);
+   seq_printf(m, "\t minor_features3: 0x%08x\n",
+  gpu->identity.minor_features3);
+
+   seq_puts(m, "\tspecs\n");
+   seq_printf(m, "\t stream_count:  %d\n",
+   gpu->identity.stream_count);
+   seq_printf(m, "\t register_max: %d\n",
+   gpu->identity.register_max);
+   seq_printf(m, "\t thread_count: %d\n",
+   gpu->identity.thread_count);
+   seq_printf(m, "\t vertex_cache_size: %d\n",
+   gpu->identity.vertex_cache_size);
+   seq_printf(m, "\t shader_core_count: %d\n",
+   gpu->identity.shader_core_count);
+   seq_printf(m, "\t pixel_pipes: %d\n",
+   gpu->identity.pixel_pipes);
+   seq_printf(m, "\t vertex_output_buffer_size: %d\n",
+   gpu->identity.vertex_output_buffer_size);
+   seq_printf(m, "\t buffer_size: %d\n",
+   gpu->identity.buffer_size);
+   seq_printf(m, "\t instruction_count: %d\n",
+   gpu->identity.instruction_count);
+   seq_printf(m, "\t num_constants: %d\n",
+   gpu->identity.num_constants);
+
seq_printf(m, "\taxi: 0x%08x\n", axi);
seq_printf(m, "\tidle: 0x%08x\n", idle);
idle |= ~gpu->idle_mask & ~VIVS_HI_IDLE_STATE_AXI_LP;
-- 
2.5.1



[PATCH 06/48] staging: etnaviv: rename last remaining bits from msm to etnaviv

2015-09-25 Thread Lucas Stach
Signed-off-by: Lucas Stach 
Signed-off-by: Russell King 
---
 drivers/staging/etnaviv/etnaviv_gem_submit.c | 2 +-
 drivers/staging/etnaviv/etnaviv_gpu.c| 2 +-
 drivers/staging/etnaviv/etnaviv_gpu.h| 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c 
b/drivers/staging/etnaviv/etnaviv_gem_submit.c
index 2de6ee0e75b4..2c0eec63e3e1 100644
--- a/drivers/staging/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c
@@ -24,7 +24,7 @@
  */

 #define BO_INVALID_FLAGS ~(ETNA_SUBMIT_BO_READ | ETNA_SUBMIT_BO_WRITE)
-/* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
+/* make sure these don't conflict w/ ETNAVIV_SUBMIT_BO_x */
 #define BO_LOCKED   0x4000
 #define BO_PINNED   0x2000

diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c 
b/drivers/staging/etnaviv/etnaviv_gpu.c
index c230da7dd526..0a8c0d3845dd 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.c
+++ b/drivers/staging/etnaviv/etnaviv_gpu.c
@@ -718,7 +718,7 @@ static void hangcheck_timer_reset(struct etnaviv_gpu *gpu)
 {
DBG("%s", dev_name(gpu->dev));
mod_timer(>hangcheck_timer,
-   round_jiffies_up(jiffies + DRM_MSM_HANGCHECK_JIFFIES));
+ round_jiffies_up(jiffies + DRM_ETNAVIV_HANGCHECK_JIFFIES));
 }

 static void hangcheck_handler(unsigned long data)
diff --git a/drivers/staging/etnaviv/etnaviv_gpu.h 
b/drivers/staging/etnaviv/etnaviv_gpu.h
index 458e76d71eb9..9af65edd5bdc 100644
--- a/drivers/staging/etnaviv/etnaviv_gpu.h
+++ b/drivers/staging/etnaviv/etnaviv_gpu.h
@@ -123,8 +123,8 @@ struct etnaviv_gpu {
struct clk *clk_shader;

/* Hang Detction: */
-#define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */
-#define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD)
+#define DRM_ETNAVIV_HANGCHECK_PERIOD 500 /* in ms */
+#define DRM_ETNAVIV_HANGCHECK_JIFFIES 
msecs_to_jiffies(DRM_ETNAVIV_HANGCHECK_PERIOD)
struct timer_list hangcheck_timer;
uint32_t hangcheck_fence;
uint32_t hangcheck_dma_addr;
-- 
2.5.1



  1   2   >