[PATCH 12/15] drm/edid: Add API to help find connection type

2015-12-01 Thread Subhransu S. Prusty
To fill the audio infoframe it is required to identify the connection type
as DP or HDMI. So parse the required bits in ELD to find the connection
type.

Signed-off-by: Subhransu S. Prusty 
Signed-off-by: Vinod Koul 
Cc: David Airlie 
Cc: dri-devel at lists.freedesktop.org
Cc: Daniel Vetter 
---
 include/drm/drm_edid.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 2af9769..c7595a5 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -403,6 +403,16 @@ static inline int drm_eld_size(const uint8_t *eld)
return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4;
 }

+/**
+ * drm_eld_get_conn_type - Get device type hdmi/dp connected
+ * @eld: pointer to an eld memory structure
+ */
+static inline int drm_eld_get_conn_type(const uint8_t *eld)
+{
+   return (eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK) >>
+   DRM_ELD_CONN_TYPE_SHIFT;
+}
+
 struct edid *drm_do_get_edid(struct drm_connector *connector,
int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
  size_t len),
-- 
1.9.1



[PATCH 00/15] ASoC: hdac_hdmi: Add DP & notification support

2015-12-01 Thread Subhransu S. Prusty
This patch series adds DP audio and hotplug notification
support.

On Skylake two DP ports are available and to enable DP on both
ports all pins need to be enabled.

There is a special vendor widget which need to be programmed to
enable all pins and converters. This series adds hotplug
notification, read/set constraint based on ELD, enable all
pin/cvts, DP1.2, programs the audio infoframe for DP. There is
a one to one mapping between converter and stream, so the dais
are created based on the no of streams supported on hdmi codec.
Even though cvts can be mapped dynamically to the streams,
currently it is statically mapped as simultaneous playback on
both DP and HDMI is not supported as of now.

Pin muxes and controls are created dynamically to map converter
to pin widget. So at run time specific pin is mapped to the dai
based on the control selected (based on the display type DP/HDMI
connected).

Finally the DP audio infoframe programming is added to support
the DP feature. 

Also with hotplug notification support, ELD is read and
capabilities are set for rate, formats and channels. drm_eld
sound/core framework is updated to limit the formats based on
ELD.

There are few fixes one fixing the static checker warning and
other one not to fail if no connection list is found for a pin
widget.


Pls note, the 12th patch is adding a small macro for getting
connection type in drm header, we have CCed drm folks on that and
this one. Pls ack so that we can have this series merged thru
sound trees

Jeeja KP (1):
  ASoC: hdac_hdmi: Add codec suspend/resume handler

Ramesh Babu (1):
  ASoC: hdac_hdmi: Keep display active while enumerating codec

Subhransu S. Prusty (13):
  ASoC: hdac_hdmi: Fix to check num nodes correctly
  ASoC: hdac_hdmi: Fix to warn instead of err for no connected nids
  ASoC: hdac_hdmi - Use list to add pins and converters
  ALSA: hda - Add helper to read eld data
  ASoC: hdac_hdmi: Add hotplug notification and read eld
  ALSA: pcm: Add DRM helper to set constraint for format
  ASoC: hdac_hdmi: Apply constraints based on ELD
  ASoC: hdac_hdmi: Enable DP1.2 and all converters/pins
  ASoC: hdac_hdmi - create dais based on number of streams
  ASoC: hdac_hdmi: Create widget/route based on nodes enumerated
  ASoC: hdac_hdmi: Assign pin for stream based on dapm connection
  drm/edid: Add API to help find connection type
  ASoC: hdac_hdmi: Add infoframe support for dp audio

 include/drm/drm_edid.h   |  10 +
 include/sound/hdaudio.h  |   3 +
 sound/core/pcm_drm_eld.c |  42 +-
 sound/hda/Makefile   |   2 +-
 sound/hda/hdac_eld.c |  95 +
 sound/soc/codecs/Kconfig |   1 +
 sound/soc/codecs/hdac_hdmi.c | 908 ---
 7 files changed, 908 insertions(+), 153 deletions(-)
 create mode 100644 sound/hda/hdac_eld.c

-- 
1.9.1



[PATCH v2 10/10] drm/hisilicon: Add support for external bridge

2015-12-01 Thread Xinliang Liu
On 1 December 2015 at 17:04, Archit Taneja  wrote:
>
>
> On 11/28/2015 04:09 PM, Xinliang Liu wrote:
>>
>> Add support for external HDMI bridge.
>>
>> Signed-off-by: Xinliang Liu 
>> Signed-off-by: Xinwei Kong 
>> Signed-off-by: Andy Green 
>> ---
>>   drivers/gpu/drm/hisilicon/hisi_drm_dsi.c | 51
>> 
>>   1 file changed, 51 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> index 066e08d..9e056db 100644
>> --- a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> @@ -78,6 +78,7 @@ struct dsi_hw_ctx {
>>
>>   struct hisi_dsi {
>> struct drm_encoder encoder;
>> +   struct drm_bridge *bridge;
>> struct mipi_dsi_host host;
>> struct drm_display_mode cur_mode;
>> struct dsi_hw_ctx *ctx;
>> @@ -671,6 +672,25 @@ static int dsi_host_init(struct device *dev, struct
>> hisi_dsi *dsi)
>> return 0;
>>   }
>>
>> +static int dsi_bridge_init(struct drm_device *dev, struct hisi_dsi *dsi)
>> +{
>> +   struct drm_encoder *encoder = >encoder;
>> +   struct drm_bridge *bridge = dsi->bridge;
>> +   int ret;
>> +
>> +   /* associate the bridge to dsi encoder */
>> +   encoder->bridge = bridge;
>> +   bridge->encoder = encoder;
>> +
>> +   ret = drm_bridge_attach(dev, bridge);
>> +   if (ret) {
>> +   DRM_ERROR("failed to attach exteranl bridge\n");
>
>
> s/exteranl/external
>

will be fixed in v3.

>
>> +   return ret;
>> +   }
>> +
>> +   return 0;
>> +}
>> +
>>   static int dsi_bind(struct device *dev, struct device *master, void
>> *data)
>>   {
>> struct dsi_data *ddata = dev_get_drvdata(dev);
>> @@ -686,6 +706,10 @@ static int dsi_bind(struct device *dev, struct device
>> *master, void *data)
>> if (ret)
>> return ret;
>>
>> +   ret = dsi_bridge_init(drm_dev, dsi);
>> +   if (ret)
>> +   return ret;
>> +
>> return 0;
>>   }
>>
>> @@ -702,8 +726,35 @@ static const struct component_ops dsi_ops = {
>>   static int dsi_parse_dt(struct platform_device *pdev, struct hisi_dsi
>> *dsi)
>>   {
>> struct dsi_hw_ctx *ctx = dsi->ctx;
>> +   struct device_node *np = pdev->dev.of_node;
>> +   struct device_node *endpoint, *bridge_node;
>> +   struct drm_bridge *bridge;
>> struct resource *res;
>>
>> +   /*
>> +* Get the endpoint node. In our case, dsi has one output port
>> +* to which the external HDMI bridge is connected.
>> +*/
>> +   endpoint = of_graph_get_next_endpoint(np, NULL);
>> +   if (!endpoint) {
>> +   DRM_ERROR("no valid endpoint node\n");
>> +   return -ENODEV;
>> +   }
>> +   of_node_put(endpoint);
>> +
>> +   bridge_node = of_graph_get_remote_port_parent(endpoint);
>> +   if (!bridge_node) {
>> +   DRM_ERROR("no valid bridge node\n");
>> +   return -ENODEV;
>> +   }
>> +   of_node_put(bridge_node);
>> +
>> +   bridge = of_drm_find_bridge(bridge_node);
>> +   if (!bridge) {
>> +   DRM_INFO("wait for external HDMI bridge driver.\n");
>> +   return -EPROBE_DEFER;
>> +   }
>> +   dsi->bridge = bridge;
>
>
> This could be left for later, but it would be better if the dsi driver
> registers even if the bridge driver module isn't inserted yet, or
> happens much later in boot.
>
> We could achieve this by trying to attach the bridge (done in
> dsi_bridge_init) in the dsi_host_attach callback instead of having it
> in dsi_bind.

Do you mean that it is the right time or place to attach the bridge in
dsi_host_attach callback.
Why? Because at this time bridge driver must be register?

Thanks,
-xinliang

>
> Thanks,
> Archit
>
>>
>> ctx->dsi_cfg_clk = devm_clk_get(>dev, "pclk_dsi");
>> if (IS_ERR(ctx->dsi_cfg_clk)) {
>>
>
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation


[Bug 92996] [Fiji/amdgpu/Powerplay] Problems with vsync, interactivity, performance, EQ overflow with Powerplay

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=92996

--- Comment #7 from Alex Deucher  ---
The vsync/pageflip issue is probably bug 93147.

-- 
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/20151201/e70a762d/attachment-0001.html>


[Bug 92996] [Fiji/amdgpu/Powerplay] Problems with vsync, interactivity, performance, EQ overflow with Powerplay

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=92996

--- Comment #6 from Ernst Sjöstrand  ---
I don't even get 60 fps in glxgears with a tiny window:
292 frames in 5.0 seconds = 58.264 FPS
286 frames in 5.0 seconds = 57.198 FPS
291 frames in 5.0 seconds = 58.198 FPS
(amdgpu ddx+dri2)

-- 
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/20151201/33c9f8ff/attachment.html>


[PATCH v2 08/10] drm/hisilicon: Add dsi encoder driver

2015-12-01 Thread Xinliang Liu
On 1 December 2015 at 16:58, Archit Taneja  wrote:

Hi Archit , thank you for review.

>
>
> On 11/28/2015 04:09 PM, Xinliang Liu wrote:
>>
>> Add dsi encoder driver for hi6220 SoC.
>>
>> Signed-off-by: Xinliang Liu 
>> Signed-off-by: Xinwei Kong 
>> Signed-off-by: Andy Green 
>> ---
>>   drivers/gpu/drm/hisilicon/Kconfig|   1 +
>>   drivers/gpu/drm/hisilicon/Makefile   |   3 +-
>>   drivers/gpu/drm/hisilicon/hisi_drm_dsi.c | 728
>> +++
>>   drivers/gpu/drm/hisilicon/hisi_dsi_reg.h |  89 
>>   4 files changed, 820 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hisi_dsi_reg.h
>>
>> diff --git a/drivers/gpu/drm/hisilicon/Kconfig
>> b/drivers/gpu/drm/hisilicon/Kconfig
>> index 70aa8d1..f1c33c2 100644
>> --- a/drivers/gpu/drm/hisilicon/Kconfig
>> +++ b/drivers/gpu/drm/hisilicon/Kconfig
>> @@ -4,6 +4,7 @@ config DRM_HISI
>> select DRM_KMS_HELPER
>> select DRM_GEM_CMA_HELPER
>> select DRM_KMS_CMA_HELPER
>> +   select DRM_MIPI_DSI
>> help
>>   Choose this option if you have a hisilicon chipsets(hi6220).
>>   If M is selected the module will be called hisi-drm.
>> diff --git a/drivers/gpu/drm/hisilicon/Makefile
>> b/drivers/gpu/drm/hisilicon/Makefile
>> index 3433c8b..5083c1f 100644
>> --- a/drivers/gpu/drm/hisilicon/Makefile
>> +++ b/drivers/gpu/drm/hisilicon/Makefile
>> @@ -1,4 +1,5 @@
>>   hisi-drm-y := hisi_drm_drv.o \
>> - hisi_drm_ade.o
>> + hisi_drm_ade.o \
>> + hisi_drm_dsi.o
>>
>>   obj-$(CONFIG_DRM_HISI)+= hisi-drm.o
>> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> new file mode 100644
>> index 000..7a6cf66
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>> @@ -0,0 +1,728 @@
>> +/*
>> + * Hisilicon hi6220 SoC dsi driver
>> + *
>> + * Copyright (c) 2014-2015 Hisilicon Limited.
>> + * Author:
>> + * Xinliang Liu 
>> + * Xinliang Liu 
>> + * Xinwei Kong 
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include "hisi_dsi_reg.h"
>> +
>> +#define MAX_TX_ESC_CLK(10)
>> +#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
>> +#define DEFAULT_MIPI_CLK_RATE   1920
>> +#define DEFAULT_MIPI_CLK_PERIOD_PS (10 / (DEFAULT_MIPI_CLK_RATE /
>> 1000))
>> +#define R(x) ((u32)u64)(x) * (u64)1000 * (u64)mode->clock) / \
>> + phy->lane_byte_clk_kHz)))
>> +
>> +#define encoder_to_dsi(encoder) \
>> +   container_of(encoder, struct hisi_dsi, encoder)
>> +#define host_to_dsi(host) \
>> +   container_of(host, struct hisi_dsi, host)
>> +
>> +struct mipi_phy_register {
>> +   u32 clk_t_lpx;
>> +   u32 clk_t_hs_prepare;
>> +   u32 clk_t_hs_zero;
>> +   u32 clk_t_hs_trial;
>> +   u32 clk_t_wakeup;
>> +   u32 data_t_lpx;
>> +   u32 data_t_hs_prepare;
>> +   u32 data_t_hs_zero;
>> +   u32 data_t_hs_trial;
>> +   u32 data_t_ta_go;
>> +   u32 data_t_ta_get;
>> +   u32 data_t_wakeup;
>> +   u32 hstx_ckg_sel;
>> +   u32 pll_fbd_div5f;
>> +   u32 pll_fbd_div1f;
>> +   u32 pll_fbd_2p;
>> +   u32 pll_enbwt;
>> +   u32 pll_fbd_p;
>> +   u32 pll_fbd_s;
>> +   u32 pll_pre_div1p;
>> +   u32 pll_pre_p;
>> +   u32 pll_vco_750M;
>> +   u32 pll_lpf_rs;
>> +   u32 pll_lpf_cs;
>> +   u32 clklp2hs_time;
>> +   u32 clkhs2lp_time;
>> +   u32 lp2hs_time;
>> +   u32 hs2lp_time;
>> +   u32 clk_to_data_delay;
>> +   u32 data_to_clk_delay;
>> +   u32 lane_byte_clk_kHz;
>> +   u32 clk_division;
>> +};
>> +
>> +struct dsi_hw_ctx {
>> +   void __iomem *base;
>> +   struct clk *dsi_cfg_clk;
>> +};
>> +
>> +struct hisi_dsi {
>> +   struct drm_encoder encoder;
>> +   struct drm_display_mode cur_mode;
>> +   struct dsi_hw_ctx *ctx;
>> +   struct mipi_phy_register phy;
>> +
>> +   u32 lanes;
>> +   enum mipi_dsi_pixel_format format;
>> +   unsigned long mode_flags;
>> +   bool enable;
>> +};
>> +
>> +struct dsi_data {
>> +   struct hisi_dsi dsi;
>> +   struct dsi_hw_ctx ctx;
>> +};
>> +
>> +struct dsi_phy_seq_info {
>> +   u32 min_range_kHz;
>> +   u32 max_range_kHz;
>> +   u32 pll_vco_750M;
>> +   u32 hstx_ckg_sel;
>> +};
>> +
>> +static const struct dsi_phy_seq_info dphy_seq_info[] = {
>> +   {   46000,62000,   1,7 },
>> +   {   62000,93000,   0,7 },
>> +   {   93000,   125000,   1,6 },
>> +   {  125000,   187000,   0,6 },
>> +   {  187000,   25,   1,5 },

[Bug 91880] Radeonsi on Grenada cards (r9 390) exceptionally unstable and poorly performing

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=91880

--- Comment #22 from Jonas  ---
Created attachment 120237
  --> https://bugs.freedesktop.org/attachment.cgi?id=120237=edit
Xorg log

This is Xorg log.

-- 
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/20151201/49539705/attachment-0001.html>


[Bug 91880] Radeonsi on Grenada cards (r9 390) exceptionally unstable and poorly performing

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=91880

--- Comment #21 from Jonas  ---
Created attachment 120236
  --> https://bugs.freedesktop.org/attachment.cgi?id=120236=edit
dmesg output

This is my "dmesg" after successful reboot, after crash.

-- 
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/20151201/ae595082/attachment.html>


[PATCH v2 03/10] drm/hisilicon: Add hisilicon DRM master driver

2015-12-01 Thread Xinliang Liu
On 30 November 2015 at 15:46, Daniel Vetter  wrote:
> On Sat, Nov 28, 2015 at 03:25:35PM +, Emil Velikov wrote:
>> Hi Xinliang,
>>
>> On 28 November 2015 at 10:38, Xinliang Liu  
>> wrote:
>> > Add DRM master driver for hi6220 SoC which used in HiKey board.
>> > Add dumb buffer feature.
>> > Add prime dmabuf feature.
>> >
>> > Signed-off-by: Xinliang Liu 
>> > Signed-off-by: Xinwei Kong 
>> > Signed-off-by: Andy Green 
>> Your s-o-b should be the bottom of the list. There was a presentation
>> (ages ago) from Greg KH, who nicely described the order as a "chain of
>> command" or "guilt path". Looks like the rest of the series could use
>> this tweak.
>>
>> > ---
>> >  drivers/gpu/drm/Kconfig  |   2 +
>> >  drivers/gpu/drm/Makefile |   1 +
>> >  drivers/gpu/drm/hisilicon/Kconfig|   9 ++
>> >  drivers/gpu/drm/hisilicon/Makefile   |   3 +
>> >  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 214 
>> > +++
>> >  5 files changed, 229 insertions(+)
>> >  create mode 100644 drivers/gpu/drm/hisilicon/Kconfig
>> >  create mode 100644 drivers/gpu/drm/hisilicon/Makefile
>> >  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_drv.c
>> >
>> > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> > index 8773fad..038aae8 100644
>> > --- a/drivers/gpu/drm/Kconfig
>> > +++ b/drivers/gpu/drm/Kconfig
>> > @@ -274,3 +274,5 @@ source "drivers/gpu/drm/amd/amdkfd/Kconfig"
>> >  source "drivers/gpu/drm/imx/Kconfig"
>> >
>> >  source "drivers/gpu/drm/vc4/Kconfig"
>> > +
>> > +source "drivers/gpu/drm/hisilicon/Kconfig"
>> I could swear that we can a patch that sorts these alphabetically,
>> although it doesn't seem to have made it upstream yet :-(
>>
>> > --- /dev/null
>> > +++ b/drivers/gpu/drm/hisilicon/hisi_drm_drv.c
>>
>> > +static int hisi_drm_load(struct drm_device *dev, unsigned long flags)
>> > +{
>> The use of .load (and .unload?) callbacks is not recommended. Take a
>> look at Laurent Pinchart's patch [1] about the whys and hows on the
>> topic
>>
>> > +static struct dma_buf *hisi_gem_prime_export(struct drm_device *dev,
>> > +struct drm_gem_object *obj,
>> > +int flags)
>> > +{
>> > +   /* we want to be able to write in mmapped buffer */
>> > +   flags |= O_RDWR;
>> Erm... something feels fishy here. Out of the existing 15 drivers
>> setting up the prime callbacks only one (sti) does a similar thing. So
>> either everyone else is missing something obvious or hisilicon and sti
>> can rework their inner working to remove this (dare I say it) hack.
>
> Mmap on drm dma-bufs doesn't work, and fairly intentionally. There's been
> some rfc patch series to address this:
>
> http://lists.freedesktop.org/archives/dri-devel/2015-August/089263.html
>
> Unfortunately it seems stuck with getting the userspace piece in shape.
> Might be best to ping Tiago for an update.
>
> Meanwhile please don't do this in drivers ;-)

It seems Tiago's patch is the best way to fix mmap issue.
I'll ping him, hope he will repsonse.

>
>> > +static int hisi_gem_cma_dumb_create(struct drm_file *file,
>> > +   struct drm_device *dev,
>> > +   struct drm_mode_create_dumb *args)
>> > +{
>> > +   int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
>> > +
>> > +   /* mali gpu need pitch 8 bytes alignment for 32bpp */
>> > +   args->pitch = roundup(min_pitch, 8);
>> > +
>> I'm not sure you want this kind of dependency of an out of tree driver
>> upstream. If this is some limitation on the display engine so be it,
>> but tailoring things for an external module seems like a very bad
>> idea.
>
> Yup, nacked. dumb_create is for dumb buffers, not rendering. Mali needs to
> go upstream to fix this ...

Oh! I have use dumb buffers for rendering now. What does dumb buffer
mean and what's dumb buffers  for?
For rendering buffer requirements how should I do then?

Thanks,
-xinliang

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


[PATCH v2 06/10] drm/hisilicon: Add vblank feature

2015-12-01 Thread Xinliang Liu
On 1 December 2015 at 15:13, Daniel Vetter  wrote:
> On Tue, Dec 01, 2015 at 11:16:19AM +0800, Xinliang Liu wrote:
>> On 30 November 2015 at 15:54, Daniel Vetter  wrote:
>> > On Sat, Nov 28, 2015 at 06:39:01PM +0800, Xinliang Liu wrote:
>> >> Add vblank handle for ADE.
>> >>
>> >> Signed-off-by: Xinliang Liu 
>> >> Signed-off-by: Xinwei Kong 
>> >> Signed-off-by: Andy Green 
>> >> ---
>> >>  drivers/gpu/drm/hisilicon/hisi_drm_ade.c | 78 
>> >> 
>> >>  drivers/gpu/drm/hisilicon/hisi_drm_ade.h | 16 +++
>> >>  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 19 +++-
>> >>  3 files changed, 112 insertions(+), 1 deletion(-)
>> >>  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_ade.h
>> >>
>> >> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c 
>> >> b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
>> >> index b0976c3..acb11e7 100644
>> >> --- a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
>> >> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
>> >> @@ -267,7 +267,79 @@ static void ade_power_down(struct ade_hw_ctx *ctx)
>> >>   ctx->power_on = false;
>> >>  }
>> >>
>> >> +static struct drm_crtc *hisi_get_crtc_from_index(struct drm_device *dev,
>> >> +  unsigned int index)
>> >
>> > Ugly that you had to add this, but unfortunately necessary :( Fixing up
>> > the drm vblank hooks so that they deal with struct drm_crtc directly is
>> > somewhere on my todo. But drm_irq.c is still a bit a mess, so this is some
>> > ways off still.
>> >
>> > What might be possible as a follow-up cleanup though is to add
>> > vblank_enable and vblank_disable functions to struct
>> > drm_crtc_helper_funcs. And then provide this code here to map from int
>> > index to struct drm_crtc * as helpers in a new drm_vblank_helper.c file.
>> > That might be a good intermediate step.
>>
>> I would like to have a try to make this intermediate step patch and
>> send out for review soon.
>
> Awesome, looking forward to reviewing it. If you have questions about
> details fastest to ping me on irc (nick: danvet, #dri-devel on
> freenode.net).

Great!  What't your time zone. So that I can ping you in right time.

Thanks,
-xinliang

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


[PATCH] drm/nouveau: Fix pre-nv50 pageflip events

2015-12-01 Thread Mario Kleiner
When we are at it, the one with the title "[PATCH] drm/nouveau: Use 
drm_vblank_on/off consistently" from Daniel, which has a reviewed and 
tested by me also never made it into nouveau.

Maybe pick that up as well?

-mario

On 12/01/2015 04:55 PM, Daniel Vetter wrote:
> On Tue, Dec 01, 2015 at 04:08:16PM +0100, poma wrote:
>> On Mon, Nov 16, 2015 at 4:11 PM, Daniel Vetter  wrote:
>>> On Mon, Nov 02, 2015 at 04:45:00PM +0900, Michel Dänzer wrote:
 On 31.10.2015 06:55, Daniel Vetter wrote:
> Apparently pre-nv50 pageflip events happen before the actual vblank
> period. Therefore that functionality got semi-disabled in
>
> commit af4870e406126b7ac0ae7c7ce5751f25ebe60f28
> Author: Mario Kleiner 
> Date:   Tue May 13 00:42:08 2014 +0200
>
>  drm/nouveau/kms/nv04-nv40: fix pageflip events via special case.
>
> Unfortunately that hack got uprooted in
>
> commit cc1ef118fc099295ae6aabbacc8af94d8d8885eb
> Author: Thierry Reding 
> Date:   Wed Aug 12 17:00:31 2015 +0200
>
>  drm/irq: Make pipe unsigned and name consistent
>
> Trigering a warning when trying to sample the vblank timestamp for a
> non-existing pipe. There's a few ways to fix this:
>
> - Open-code the old behaviour, which just enshrines this slight
>breakage of the userspace ABI.
>
> - Revert Mario's commit and again inflict broken timestamps, again not
>pretty.
>
> - Fix this for real by delaying the pageflip TS until the next vblank
>interrupt, thereby making it accurate.
>
> This patch implements the third option. Since having a page flip
> interrupt that happens when the pageflip gets armed and not when it
> completes in the next vblank seems to be fairly common (older i915 hw
> works very similarly) create a new helper to arm vblank events for
> such drivers.

 What happens when the page flip interrupt arrives during a vertical
 blank period?  Presumably the userspace event will be deferred until the
 next vertical blank period, but the flip might already take effect in
 the current one.
>>>
>>> Hm yeah there's a tiny race if your update handler for the pageflip can
>>> race with your vblank handler. That's impossible here since it's all done
>>> from the same hw irq hanlder, and since that is single-threaded there
>>> shouldn't be a problem, as long as vblank handling are pageflip are
>>> ordered correctly.
>>>
>>> Might be worth a note in the kerneldoc though that this function isn't
>>> perfectly foolproof.
>>> -Daniel
>>
>>
>> Is there any updates in this respect?
>>
>> drm-nouveau-Fix-pre-nv50-pageflip-events-v4.patch
>> https://patchwork.kernel.org/patch/7591531
>>
>> https://bugzilla.kernel.org/show_bug.cgi?id=106431
>> Reported: 2015-10-21
>
> Ben Skeggs asleep probably. Dave, can you pls pick this up?
> -Daniel
>


[PATCH v2 03/10] drm/hisilicon: Add hisilicon DRM master driver

2015-12-01 Thread Xinliang Liu
On 28 November 2015 at 23:25, Emil Velikov  wrote:

Hi Emil, thanks again for review.

> Hi Xinliang,
>
> On 28 November 2015 at 10:38, Xinliang Liu  wrote:
>> Add DRM master driver for hi6220 SoC which used in HiKey board.
>> Add dumb buffer feature.
>> Add prime dmabuf feature.
>>
>> Signed-off-by: Xinliang Liu 
>> Signed-off-by: Xinwei Kong 
>> Signed-off-by: Andy Green 
> Your s-o-b should be the bottom of the list. There was a presentation
> (ages ago) from Greg KH, who nicely described the order as a "chain of
> command" or "guilt path". Looks like the rest of the series could use
> this tweak.

will fixed in v3.

>
>> ---
>>  drivers/gpu/drm/Kconfig  |   2 +
>>  drivers/gpu/drm/Makefile |   1 +
>>  drivers/gpu/drm/hisilicon/Kconfig|   9 ++
>>  drivers/gpu/drm/hisilicon/Makefile   |   3 +
>>  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 214 
>> +++
>>  5 files changed, 229 insertions(+)
>>  create mode 100644 drivers/gpu/drm/hisilicon/Kconfig
>>  create mode 100644 drivers/gpu/drm/hisilicon/Makefile
>>  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_drv.c
>>
>> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
>> index 8773fad..038aae8 100644
>> --- a/drivers/gpu/drm/Kconfig
>> +++ b/drivers/gpu/drm/Kconfig
>> @@ -274,3 +274,5 @@ source "drivers/gpu/drm/amd/amdkfd/Kconfig"
>>  source "drivers/gpu/drm/imx/Kconfig"
>>
>>  source "drivers/gpu/drm/vc4/Kconfig"
>> +
>> +source "drivers/gpu/drm/hisilicon/Kconfig"
> I could swear that we can a patch that sorts these alphabetically,
> although it doesn't seem to have made it upstream yet :-(

Yes, as there are so many drm drivers now, it's time to do this work I think.
I'll try to send a separate patch for this soon.

>
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_drv.c
>
>> +static int hisi_drm_load(struct drm_device *dev, unsigned long flags)
>> +{
> The use of .load (and .unload?) callbacks is not recommended. Take a
> look at Laurent Pinchart's patch [1] about the whys and hows on the
> topic

will removed .load/unload in v3.

>
>> +static struct dma_buf *hisi_gem_prime_export(struct drm_device *dev,
>> +struct drm_gem_object *obj,
>> +int flags)
>> +{
>> +   /* we want to be able to write in mmapped buffer */
>> +   flags |= O_RDWR;
> Erm... something feels fishy here. Out of the existing 15 drivers
> setting up the prime callbacks only one (sti) does a similar thing. So
> either everyone else is missing something obvious or hisilicon and sti
> can rework their inner working to remove this (dare I say it) hack.

I would talk to sti guys about this. Not sure how to handle this now.

>
>> +static int hisi_gem_cma_dumb_create(struct drm_file *file,
>> +   struct drm_device *dev,
>> +   struct drm_mode_create_dumb *args)
>> +{
>> +   int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
>> +
>> +   /* mali gpu need pitch 8 bytes alignment for 32bpp */
>> +   args->pitch = roundup(min_pitch, 8);
>> +
> I'm not sure you want this kind of dependency of an out of tree driver
> upstream. If this is some limitation on the display engine so be it,
> but tailoring things for an external module seems like a very bad
> idea.

I can move this mali dependency to user drivers (such as gralloc and
xf86-video-armsoc).
Do you think it is reasonable?

>
>> +   return drm_gem_cma_dumb_create_internal(file, dev, args);
>> +}
>
>> +static int hisi_drm_bind(struct device *dev)
>> +{
>> +   dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
>> +   return drm_platform_init(_drm_driver, to_platform_device(dev));
> As pointed out by the the kernel doc - drm_platform_init is deprecated.
>

will remove drm_platform_init in v3.

Thanks,
-xinliang

>
> Regards,
> Emil
>
> [1] http://lists.freedesktop.org/archives/dri-devel/2015-November/095466.html


[RFC PATCH 2/9] drm/rockchip: Use new vblank api drm_crtc_vblank_*

2015-12-01 Thread Mark yao
On 2015年12月01日 17:01, Daniel Vetter wrote:
> On Tue, Dec 01, 2015 at 04:33:27PM +0800, Mark yao wrote:
>> On 2015年12月01日 15:56, Daniel Stone wrote:
>>> Hi,
>>>
>>> On 1 December 2015 at 03:26, Mark Yao  wrote:
 No functional update, drm_vblank_* is the legacy version of
 drm_crtc_vblank_*. and use new api make driver more clean.

 Signed-off-by: Mark Yao 
>>> Heh, I had the same patch in my series to fix pageflip events.
>>>
>>> Reviewed-by: Daniel Stone 
>>>
>>> Cheers,
>>> Daniel
>>>
>>>
>>>
>> Hi Daniel
>> I had picked your patch "[PATCH 1/2] drm/rockchip: Use CRTC vblank event
>> interface" into my drm-next, this patch is base on it.
> That really should be mentioned in the commit message, and you must keep
> the signed-off-by chain intact when adapting or reusing other peoples
> work.
> -Daniel

Oh, Sorry for that, this patch is another patch rebase on Daniel Stone's 
one, I use "base on it" may be ambiguity.
like that:
0e6919f drm/rockchip: Use new vblank api drm_crtc_vblank_*
4f0cb7c drm/rockchip: Use CRTC vblank event interface

Thanks for pointing that, I will be carefully next time.

>> Thanks for your review.
>>
>> -- 
>> ï¼­ark Yao
>>
>>
>> ___
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel



[Bug 92850] Segfault loading War Thunder

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=92850

haro41 at gmx.de changed:

   What|Removed |Added

 CC||haro41 at gmx.de

--- Comment #23 from haro41 at gmx.de ---
I have a similiar segmentation fault error in game 'war thunder' (mesa
11.2-devel radeonsi). Unlike the original reporter, i dont use/need any GL
version override.

If i configure latest git mesa with '--enable-debug', i get this additional
output at console, before the crash:

'context mis-match in pipe_sampler_view_release()'

glxinfo |grep OpenGL:

OpenGL vendor string: X.Org
OpenGL renderer string: Gallium 0.4 on AMD PITCAIRN (DRM 2.43.0, LLVM 3.7.0)
OpenGL core profile version string: 4.1 (Core Profile) Mesa 11.2.0-devel
(git-241f15a)
OpenGL core profile shading language version string: 4.10
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 11.2.0-devel (git-241f15a)
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.0 Mesa 11.2.0-devel (git-241f15a)
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.00
OpenGL ES profile extensions:

If additinal infos are needed please let me know.

-- 
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/20151201/8ac87e2b/attachment.html>


[RFC PATCH 3/9] drm/rockchip: Convert to support atomic API

2015-12-01 Thread Mark yao
On 2015年12月01日 16:18, Daniel Stone wrote:
> Hi Mark,
>
> On 1 December 2015 at 03:26, Mark Yao  wrote:
>> >+static void rockchip_atomic_wait_for_complete(struct drm_atomic_state 
>> >*state)
>> >+{
>> >+   struct drm_crtc_state *crtc_state;
>> >+   struct drm_crtc *crtc;
>> >+   int i;
>> >+
>> >+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> >+   if (!crtc->state->active)
>> >+   continue;
>> >+
>> >+   WARN_ON(drm_crtc_vblank_get(crtc));
>> >+   }
>> >+
>> >+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> >+   if (!crtc->state->active)
>> >+   continue;
>> >+
>> >+   rockchip_crtc_wait_for_update(crtc);
>> >+   }
> I'd be much more comfortable if this passed in an explicit pointer to
> state, or an address to wait for, rather than have wait_for_complete
> dig out state with no locking. The latter is potentially racy for
> async operations.
>
Hi Daniel
"if this passed in an explicit pointer to state, or an address to 
wait for", I don't understand, can you point how it work?

-- 
ï¼­ark Yao




[RFC PATCH] drm/edid: index CEA/HDMI mode tables using the VIC

2015-12-01 Thread Ville Syrjälä
On Tue, Dec 01, 2015 at 05:16:54PM +0200, Jani Nikula wrote:
> Add a dummy entry to CEA/HDMI mode tables so they can be indexed
> directly using the VIC, avoiding a +1/-1 dance here and there. This adds
> clarity to the error checking for various functions that return the VIC
> on success and zero on failure; we now explicitly check for 0 instead of
> just subtracting one from an unsigned type.
> 
> Cc: Ville Syrjälä 
> Signed-off-by: Jani Nikula 
> 
> ---
> 
> This is on top of
> 
> commit 4c6bcf44549907cb50b67f98eb13717a4adc6b33
> Author: Ville Syrjälä 
> Date:   Mon Nov 16 21:05:12 2015 +0200
> 
> drm/edid: Make the detailed timing CEA/HDMI mode fixup accept up to 5kHz 
> clock difference
> 
> in drm-intel/topic/drm-misc
> ---
>  drivers/gpu/drm/drm_edid.c | 84 
> --
>  1 file changed, 43 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index c214f1246cb4..aea09eae407e 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c

> @@ -2713,16 +2716,16 @@ add_alternate_cea_modes(struct drm_connector 
> *connector, struct edid *edid)
>   list_for_each_entry(mode, >probed_modes, head) {
>   const struct drm_display_mode *cea_mode = NULL;
>   struct drm_display_mode *newmode;
> - u8 mode_idx = drm_match_cea_mode(mode) - 1;
> + u8 vic = drm_match_cea_mode(mode);
>   unsigned int clock1, clock2;
>  
> - if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
> - cea_mode = _cea_modes[mode_idx];
> + if (vic > 0 && vic < ARRAY_SIZE(edid_cea_modes)) {

Maybe add some sort of vic_is_valid() helpers to avoid duplicating
these in so many places?

Otherwise I like it.

> + cea_mode = _cea_modes[vic];
>   clock2 = cea_mode_alternate_clock(cea_mode);
>   } else {
> - mode_idx = drm_match_hdmi_mode(mode) - 1;
> - if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
> - cea_mode = _4k_modes[mode_idx];
> + vic = drm_match_hdmi_mode(mode);
> + if (vic > 0 && vic < ARRAY_SIZE(edid_4k_modes)) {
> + cea_mode = _4k_modes[vic];
>   clock2 = hdmi_mode_alternate_clock(cea_mode);
>   }
>   }
> @@ -2773,17 +2776,17 @@ drm_display_mode_from_vic_index(struct drm_connector 
> *connector,
>  {
>   struct drm_device *dev = connector->dev;
>   struct drm_display_mode *newmode;
> - u8 cea_mode;
> + u8 vic;
>  
>   if (video_db == NULL || video_index >= video_len)
>   return NULL;
>  
>   /* CEA modes are numbered 1..127 */
> - cea_mode = (video_db[video_index] & 127) - 1;
> - if (cea_mode >= ARRAY_SIZE(edid_cea_modes))
> + vic = (video_db[video_index] & 127);
> + if (vic == 0 || vic >= ARRAY_SIZE(edid_cea_modes))
>   return NULL;
>  
> - newmode = drm_mode_duplicate(dev, _cea_modes[cea_mode]);
> + newmode = drm_mode_duplicate(dev, _cea_modes[vic]);
>   if (!newmode)
>   return NULL;
>  
> @@ -2878,8 +2881,7 @@ static int add_hdmi_mode(struct drm_connector 
> *connector, u8 vic)
>   struct drm_device *dev = connector->dev;
>   struct drm_display_mode *newmode;
>  
> - vic--; /* VICs start at 1 */
> - if (vic >= ARRAY_SIZE(edid_4k_modes)) {
> + if (vic == 0 || vic >= ARRAY_SIZE(edid_4k_modes)) {
>   DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
>   return 0;
>   }
> @@ -3170,24 +3172,24 @@ static void fixup_detailed_cea_mode_clock(struct 
> drm_display_mode *mode)
>  {
>   const struct drm_display_mode *cea_mode;
>   int clock1, clock2, clock;
> - u8 mode_idx;
> + u8 vic;
>   const char *type;
>  
>   /*
>* allow 5kHz clock difference either way to account for
>* the 10kHz clock resolution limit of detailed timings.
>*/
> - mode_idx = drm_match_cea_mode_clock_tolerance(mode, 5) - 1;
> - if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
> + vic = drm_match_cea_mode_clock_tolerance(mode, 5);
> + if (vic > 0 && vic < ARRAY_SIZE(edid_cea_modes)) {
>   type = "CEA";
> - cea_mode = _cea_modes[mode_idx];
> + cea_mode = _cea_modes[vic];
>   clock1 = cea_mode->clock;
>   clock2 = cea_mode_alternate_clock(cea_mode);
>   } else {
> - mode_idx = drm_match_hdmi_mode_clock_tolerance(mode, 5) - 1;
> - if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
> + vic = drm_match_hdmi_mode_clock_tolerance(mode, 5);
> + if (vic > 0 && vic < ARRAY_SIZE(edid_4k_modes)) {
>   type = "HDMI";
> - cea_mode = _4k_modes[mode_idx];
> + cea_mode = _4k_modes[vic];
>  

[RFC PATCH 3/9] drm/rockchip: Convert to support atomic API

2015-12-01 Thread Mark yao
On 2015年12月01日 16:18, Daniel Stone wrote:
> Hi Mark,
>
> On 1 December 2015 at 03:26, Mark Yao  wrote:
>> +static void rockchip_atomic_wait_for_complete(struct drm_atomic_state 
>> *state)
>> +{
>> +   struct drm_crtc_state *crtc_state;
>> +   struct drm_crtc *crtc;
>> +   int i;
>> +
>> +   for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> +   if (!crtc->state->active)
>> +   continue;
>> +
>> +   WARN_ON(drm_crtc_vblank_get(crtc));
>> +   }
>> +
>> +   for_each_crtc_in_state(state, crtc, crtc_state, i) {
>> +   if (!crtc->state->active)
>> +   continue;
>> +
>> +   rockchip_crtc_wait_for_update(crtc);
>> +   }
> I'd be much more comfortable if this passed in an explicit pointer to
> state, or an address to wait for, rather than have wait_for_complete
> dig out state with no locking. The latter is potentially racy for
> async operations.
>
>> +struct vop_plane_state {
>> +   struct drm_plane_state base;
>> +   dma_addr_t dma_addr[ROCKCHIP_MAX_FB_BUFFER];
> Can you get rid of this by just using the pointer to a
> rockchip_gem_object already provided?

Good idea, I will do that.

>> -static int vop_update_plane_event(struct drm_plane *plane,
>> - struct drm_crtc *crtc,
>> - struct drm_framebuffer *fb, int crtc_x,
>> - int crtc_y, unsigned int crtc_w,
>> - unsigned int crtc_h, uint32_t src_x,
>> - uint32_t src_y, uint32_t src_w,
>> - uint32_t src_h,
>> - struct drm_pending_vblank_event *event)
>> +static int vop_plane_atomic_check(struct drm_plane *plane,
>> +  struct drm_plane_state *state)
>>   {
>> +   struct drm_crtc *crtc = state->crtc;
>> +   struct drm_framebuffer *fb = state->fb;
>>  struct vop_win *vop_win = to_vop_win(plane);
>> +   struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
>>  const struct vop_win_data *win = vop_win->data;
>> -   struct vop *vop = to_vop(crtc);
>>  struct drm_gem_object *obj;
>>  struct rockchip_gem_object *rk_obj;
>> -   struct drm_gem_object *uv_obj;
>> -   struct rockchip_gem_object *rk_uv_obj;
>>  unsigned long offset;
>> -   unsigned int actual_w;
>> -   unsigned int actual_h;
>> -   unsigned int dsp_stx;
>> -   unsigned int dsp_sty;
>> -   unsigned int y_vir_stride;
>> -   unsigned int uv_vir_stride = 0;
>> -   dma_addr_t yrgb_mst;
>> -   dma_addr_t uv_mst = 0;
>> -   enum vop_data_format format;
>> -   uint32_t val;
>> -   bool is_alpha;
>> -   bool rb_swap;
>>  bool is_yuv;
>>  bool visible;
>>  int ret;
>> -   struct drm_rect dest = {
>> -   .x1 = crtc_x,
>> -   .y1 = crtc_y,
>> -   .x2 = crtc_x + crtc_w,
>> -   .y2 = crtc_y + crtc_h,
>> -   };
>> -   struct drm_rect src = {
>> -   /* 16.16 fixed point */
>> -   .x1 = src_x,
>> -   .y1 = src_y,
>> -   .x2 = src_x + src_w,
>> -   .y2 = src_y + src_h,
>> -   };
>> -   const struct drm_rect clip = {
>> -   .x2 = crtc->mode.hdisplay,
>> -   .y2 = crtc->mode.vdisplay,
>> -   };
>> -   bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
>> +   struct drm_rect *dest = _plane_state->dest;
>> +   struct drm_rect *src = _plane_state->src;
>> +   struct drm_rect clip;
>>  int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
>>  DRM_PLANE_HELPER_NO_SCALING;
>>  int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
>>  DRM_PLANE_HELPER_NO_SCALING;
>>
>> -   ret = drm_plane_helper_check_update(plane, crtc, fb,
>> -   , , ,
>> +   crtc = crtc ? crtc : plane->state->crtc;
>> +   /*
>> +* Both crtc or plane->state->crtc can be null.
>> +*/
>> +   if (!crtc || !fb)
>> +   goto out_disable;
>> +   src->x1 = state->src_x;
>> +   src->y1 = state->src_y;
>> +   src->x2 = state->src_x + state->src_w;
>> +   src->y2 = state->src_y + state->src_h;
>> +   dest->x1 = state->crtc_x;
>> +   dest->y1 = state->crtc_y;
>> +   dest->x2 = state->crtc_x + state->crtc_w;
>> +   dest->y2 = state->crtc_y + state->crtc_h;
>> +
>> +   clip.x1 = 0;
>> +   clip.y1 = 0;
>> +   clip.x2 = crtc->mode.hdisplay;
>> +   clip.y2 = crtc->mode.vdisplay;
>> +
>> +   ret = drm_plane_helper_check_update(plane, crtc, state->fb,
>> +   src, dest, ,
>>  

[RFC PATCH] drm/edid: index CEA/HDMI mode tables using the VIC

2015-12-01 Thread Jani Nikula
Add a dummy entry to CEA/HDMI mode tables so they can be indexed
directly using the VIC, avoiding a +1/-1 dance here and there. This adds
clarity to the error checking for various functions that return the VIC
on success and zero on failure; we now explicitly check for 0 instead of
just subtracting one from an unsigned type.

Cc: Ville Syrjälä 
Signed-off-by: Jani Nikula 

---

This is on top of

commit 4c6bcf44549907cb50b67f98eb13717a4adc6b33
Author: Ville Syrjälä 
Date:   Mon Nov 16 21:05:12 2015 +0200

drm/edid: Make the detailed timing CEA/HDMI mode fixup accept up to 5kHz 
clock difference

in drm-intel/topic/drm-misc
---
 drivers/gpu/drm/drm_edid.c | 84 --
 1 file changed, 43 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index c214f1246cb4..aea09eae407e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -637,8 +637,12 @@ static const struct minimode extra_modes[] = {
 /*
  * Probably taken from CEA-861 spec.
  * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
+ *
+ * Index using the VIC.
  */
 static const struct drm_display_mode edid_cea_modes[] = {
+   /* 0 - dummy, VICs start at 1 */
+   { 0 },
/* 1 - 640x480 at 60Hz */
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
   752, 800, 0, 480, 490, 492, 525, 0,
@@ -987,9 +991,11 @@ static const struct drm_display_mode edid_cea_modes[] = {
 };

 /*
- * HDMI 1.4 4k modes.
+ * HDMI 1.4 4k modes. Index using the VIC.
  */
 static const struct drm_display_mode edid_4k_modes[] = {
+   /* 0 - dummy, VICs start at 1 */
+   { 0 },
/* 1 - 3840x2160 at 30Hz */
{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
   3840, 4016, 4104, 4400, 0,
@@ -2548,13 +2554,13 @@ cea_mode_alternate_clock(const struct drm_display_mode 
*cea_mode)
 static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode 
*to_match,
 unsigned int clock_tolerance)
 {
-   u8 mode;
+   u8 vic;

if (!to_match->clock)
return 0;

-   for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
-   const struct drm_display_mode *cea_mode = _cea_modes[mode];
+   for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
+   const struct drm_display_mode *cea_mode = _cea_modes[vic];
unsigned int clock1, clock2;

/* Check both 60Hz and 59.94Hz */
@@ -2566,7 +2572,7 @@ static u8 drm_match_cea_mode_clock_tolerance(const struct 
drm_display_mode *to_m
continue;

if (drm_mode_equal_no_clocks(to_match, cea_mode))
-   return mode + 1;
+   return vic;
}

return 0;
@@ -2581,13 +2587,13 @@ static u8 drm_match_cea_mode_clock_tolerance(const 
struct drm_display_mode *to_m
  */
 u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
 {
-   u8 mode;
+   u8 vic;

if (!to_match->clock)
return 0;

-   for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
-   const struct drm_display_mode *cea_mode = _cea_modes[mode];
+   for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
+   const struct drm_display_mode *cea_mode = _cea_modes[vic];
unsigned int clock1, clock2;

/* Check both 60Hz and 59.94Hz */
@@ -2597,7 +2603,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode 
*to_match)
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
-   return mode + 1;
+   return vic;
}
return 0;
 }
@@ -2612,10 +2618,7 @@ EXPORT_SYMBOL(drm_match_cea_mode);
  */
 enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
 {
-   /* return picture aspect ratio for video_code - 1 to access the
-* right array element
-   */
-   return edid_cea_modes[video_code-1].picture_aspect_ratio;
+   return edid_cea_modes[video_code].picture_aspect_ratio;
 }
 EXPORT_SYMBOL(drm_get_cea_aspect_ratio);

@@ -2639,13 +2642,13 @@ hdmi_mode_alternate_clock(const struct drm_display_mode 
*hdmi_mode)
 static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode 
*to_match,
  unsigned int clock_tolerance)
 {
-   u8 mode;
+   u8 vic;

if (!to_match->clock)
return 0;

-   for (mode = 0; mode < ARRAY_SIZE(edid_4k_modes); mode++) {
-   const struct drm_display_mode *hdmi_mode = _4k_modes[mode];
+   for (vic = 1; vic < ARRAY_SIZE(edid_4k_modes); vic++) {
+   const struct drm_display_mode 

[PATCH] drm/nouveau: Fix pre-nv50 pageflip events

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 04:08:16PM +0100, poma wrote:
> On Mon, Nov 16, 2015 at 4:11 PM, Daniel Vetter  wrote:
> > On Mon, Nov 02, 2015 at 04:45:00PM +0900, Michel Dänzer wrote:
> >> On 31.10.2015 06:55, Daniel Vetter wrote:
> >> > Apparently pre-nv50 pageflip events happen before the actual vblank
> >> > period. Therefore that functionality got semi-disabled in
> >> >
> >> > commit af4870e406126b7ac0ae7c7ce5751f25ebe60f28
> >> > Author: Mario Kleiner 
> >> > Date:   Tue May 13 00:42:08 2014 +0200
> >> >
> >> > drm/nouveau/kms/nv04-nv40: fix pageflip events via special case.
> >> >
> >> > Unfortunately that hack got uprooted in
> >> >
> >> > commit cc1ef118fc099295ae6aabbacc8af94d8d8885eb
> >> > Author: Thierry Reding 
> >> > Date:   Wed Aug 12 17:00:31 2015 +0200
> >> >
> >> > drm/irq: Make pipe unsigned and name consistent
> >> >
> >> > Trigering a warning when trying to sample the vblank timestamp for a
> >> > non-existing pipe. There's a few ways to fix this:
> >> >
> >> > - Open-code the old behaviour, which just enshrines this slight
> >> >   breakage of the userspace ABI.
> >> >
> >> > - Revert Mario's commit and again inflict broken timestamps, again not
> >> >   pretty.
> >> >
> >> > - Fix this for real by delaying the pageflip TS until the next vblank
> >> >   interrupt, thereby making it accurate.
> >> >
> >> > This patch implements the third option. Since having a page flip
> >> > interrupt that happens when the pageflip gets armed and not when it
> >> > completes in the next vblank seems to be fairly common (older i915 hw
> >> > works very similarly) create a new helper to arm vblank events for
> >> > such drivers.
> >>
> >> What happens when the page flip interrupt arrives during a vertical
> >> blank period?  Presumably the userspace event will be deferred until the
> >> next vertical blank period, but the flip might already take effect in
> >> the current one.
> >
> > Hm yeah there's a tiny race if your update handler for the pageflip can
> > race with your vblank handler. That's impossible here since it's all done
> > from the same hw irq hanlder, and since that is single-threaded there
> > shouldn't be a problem, as long as vblank handling are pageflip are
> > ordered correctly.
> >
> > Might be worth a note in the kerneldoc though that this function isn't
> > perfectly foolproof.
> > -Daniel
> 
> 
> Is there any updates in this respect?
> 
> drm-nouveau-Fix-pre-nv50-pageflip-events-v4.patch
> https://patchwork.kernel.org/patch/7591531
> 
> https://bugzilla.kernel.org/show_bug.cgi?id=106431
> Reported: 2015-10-21

Ben Skeggs asleep probably. Dave, can you pls pick this up?
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[PATCH] kernel/latencytop: Add non-scheduler interface for latency reporting

2015-12-01 Thread Daniel Vetter
Some sources of significant amounts of latency aren't simple sleeps
but instead busy-loops or a series of hundreds of small sleeps simply
because the hardware can't do better. Unfortunately latencytop doesn't
register these and so they slip under the radar. Hence expose a
simplified interface to report additional latencies and export the
underlying function so that modules can use this.

The example I have in mind are edid reads. The drm subsystem exposes
both interfaces to do full probes and to just get at the cached state
from the last probe and often userspace developers don't know about
the difference and incur unecessary big latencies. And usually the i2c
transfer is done with busy-looping or if there is a hw engine it might
only be able to transfer a few bytes per sleep/irq cycle. And edid
reads take at least 12ms and with crappy hw can easily be a few
hundred ms.

v2: Simplify #ifdefs a bit (Chris).

Cc: Chris Wilson 
Cc: Thomas Gleixner 
Cc: Arjan van de Ven 
Cc: Andrew Morton 
Signed-off-by: Daniel Vetter 
---
 include/linux/latencytop.h | 9 +
 kernel/latencytop.c| 2 ++
 2 files changed, 11 insertions(+)

diff --git a/include/linux/latencytop.h b/include/linux/latencytop.h
index e23121f9d82a..6f7c35a0bbfe 100644
--- a/include/linux/latencytop.h
+++ b/include/linux/latencytop.h
@@ -10,6 +10,9 @@
 #define _INCLUDE_GUARD_LATENCYTOP_H_

 #include 
+
+#include 
+
 struct task_struct;

 #ifdef CONFIG_LATENCYTOP
@@ -50,4 +53,10 @@ static inline void clear_all_latency_tracing(struct 
task_struct *p)

 #endif

+static inline void
+account_latency(int usecs)
+{
+   account_scheduler_latency(current, usecs, 0);
+}
+
 #endif
diff --git a/kernel/latencytop.c b/kernel/latencytop.c
index a02812743a7e..b066a19fc52a 100644
--- a/kernel/latencytop.c
+++ b/kernel/latencytop.c
@@ -64,6 +64,7 @@ static DEFINE_RAW_SPINLOCK(latency_lock);
 static struct latency_record latency_record[MAXLR];

 int latencytop_enabled;
+EXPORT_SYMBOL_GPL(latencytop_enabled);

 void clear_all_latency_tracing(struct task_struct *p)
 {
@@ -234,6 +235,7 @@ __account_scheduler_latency(struct task_struct *tsk, int 
usecs, int inter)
 out_unlock:
raw_spin_unlock_irqrestore(_lock, flags);
 }
+EXPORT_SYMBOL_GPL(__account_scheduler_latency);

 static int lstats_show(struct seq_file *m, void *v)
 {
-- 
2.5.1



[PATCH libdrm] intel: add the missing header

2015-12-01 Thread Emil Velikov
On 1 December 2015 at 07:40, Chih-Wei Huang  wrote:
> Any concern to merge such a simple fix??
>
Absolutely none - it just fell through the cracks. Just pushed it to
master, feel free to CC me on future patches.

Thanks
Emil


[Intel-gfx] [PATCH v8 2/2] drm/dp: Set aux.dev to the drm_connector device, instead of drm_device.

2015-12-01 Thread Rafael Antognolli
On Tue, Nov 24, 2015 at 10:31:41PM +0200, Ville Syrjälä wrote:
> On Mon, Nov 02, 2015 at 12:33:48PM -0800, Rafael Antognolli wrote:
> > So far, the i915 driver and some other drivers set it to the drm_device,
> > which doesn't allow one to know which DP a given aux channel is related
> > to. Changing this to be the drm_connector provides proper nesting, still
> > allowing one to get the drm_device from it. Some drivers already set it
> > to the drm_connector.
> > 
> > This also removes the need to add a sysfs link for the i2c device under
> > the connector, as it will already be there.
> > 
> > Signed-off-by: Rafael Antognolli 
> 
> I gave aux_dev a bit of a testing here, and it appaers to work quite
> splendidly.
> 
> This patch however causes lots of WARN spew if I unload the driver
> while in middle of dumping the DPCD via the aux_dev. It appears we
> we clean up things the wrong order now.

It looks like device_destroy is being called twice on the drm_aux_dev
and i2c adapter devices.

If I understood correctly, this is happening because I changed the
parent device, from the drm_device to the drm_connector, but the
drm_connector is being destroyed before the drm_aux_dev and i2c adapter
devices, which already causes them to be destroyed too.

Changing the drm_dp_aux_unregister() from inside intel_dp_aux_fini() to
intel_dp_connector_unregister(), right before
intel_connector_unregister(), seems to fix everything, and it still
makes sense in my opinion, since the auxdev is going to be unregistered
before we destroy the drm_connector. Do you think that would be ok?

> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 19 ++-
> >  1 file changed, 2 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c 
> > b/drivers/gpu/drm/i915/intel_dp.c
> > index 8287df4..7aacc08 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1078,36 +1078,21 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct 
> > intel_connector *connector)
> > intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
> >  
> > intel_dp->aux.name = name;
> > -   intel_dp->aux.dev = dev->dev;
> > +   intel_dp->aux.dev = connector->base.kdev;
> > intel_dp->aux.transfer = intel_dp_aux_transfer;
> >  
> > DRM_DEBUG_KMS("registering %s bus for %s\n", name,
> >   connector->base.kdev->kobj.name);
> >  
> > ret = drm_dp_aux_register(_dp->aux);
> > -   if (ret < 0) {
> > +   if (ret < 0)
> > DRM_ERROR("drm_dp_aux_register() for %s failed (%d)\n",
> >   name, ret);
> > -   return;
> > -   }
> > -
> > -   ret = sysfs_create_link(>base.kdev->kobj,
> > -   _dp->aux.ddc.dev.kobj,
> > -   intel_dp->aux.ddc.dev.kobj.name);
> > -   if (ret < 0) {
> > -   DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", name, 
> > ret);
> > -   drm_dp_aux_unregister(_dp->aux);
> > -   }
> >  }
> >  
> >  static void
> >  intel_dp_connector_unregister(struct intel_connector *intel_connector)
> >  {
> > -   struct intel_dp *intel_dp = intel_attached_dp(_connector->base);
> > -
> > -   if (!intel_connector->mst_port)
> > -   sysfs_remove_link(_connector->base.kdev->kobj,
> > - intel_dp->aux.ddc.dev.kobj.name);
> > intel_connector_unregister(intel_connector);
> >  }
> >  
> > -- 
> > 2.4.3
> > 
> > ___
> > Intel-gfx mailing list
> > Intel-gfx at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Ville Syrjälä
> Intel OTC


[RFC PATCH 2/9] drm/rockchip: Use new vblank api drm_crtc_vblank_*

2015-12-01 Thread Mark yao
On 2015年12月01日 15:56, Daniel Stone wrote:
> Hi,
>
> On 1 December 2015 at 03:26, Mark Yao  wrote:
>> No functional update, drm_vblank_* is the legacy version of
>> drm_crtc_vblank_*. and use new api make driver more clean.
>>
>> Signed-off-by: Mark Yao 
> Heh, I had the same patch in my series to fix pageflip events.
>
> Reviewed-by: Daniel Stone 
>
> Cheers,
> Daniel
>
>
>

Hi Daniel
I had picked your patch "[PATCH 1/2] drm/rockchip: Use CRTC vblank 
event interface" into my drm-next, this patch is base on it.

Thanks for your review.

-- 
ï¼­ark Yao




[PATCH 2/2] drm/edid: report latency due to reading edids

2015-12-01 Thread Daniel Vetter
A forced EDID read takes 22.5ms best-case, and that's per 128byte
block. HDMI screens tend to have 2-3 of those. Mutliply that by a few
outputs and then it's clear that userspace really never ever should
re-probe connector state on its own and trust the kernel to tell it
when anything changed. The only exception is a manual reprobe button that
the user must press itself (for extremely shitty KVM switches that
don't wire up hotplug handling properly).

There have been bugs in the past, but we're slowly fixing them up. To
the point even that some of the most abused interfaces (e.g. in sysfs)
have been changed to only return the cached state ever due to too much
polling by userspace.

But there's other places where we can't pull these tricks, so give
userspace the tools to notice their abuse and expose delays due to
EDID reads in latencytop.

Cc: Thomas Gleixner 
Cc: Arjan van de Ven 
Cc: Andrew Morton 
Signed-off-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_edid.c | 27 +++
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index c214f1246cb4..370003e0cc69 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1272,14 +1273,17 @@ struct edid *drm_do_get_edid(struct drm_connector 
*connector,
int i, j = 0, valid_extensions = 0;
u8 *block, *new;
bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & 
DRM_UT_KMS);
+   u64 before, after;

if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
return NULL;

+   before = ktime_get_raw_ns();
+
/* base block fetch */
for (i = 0; i < 4; i++) {
if (get_edid_block(data, block, 0, EDID_LENGTH))
-   goto out;
+   goto none;
if (drm_edid_block_valid(block, 0, print_bad_edid,
 >edid_corrupt))
break;
@@ -1293,11 +1297,11 @@ struct edid *drm_do_get_edid(struct drm_connector 
*connector,

/* if there's no extensions, we're done */
if (block[0x7e] == 0)
-   return (struct edid *)block;
+   goto out;

new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
if (!new)
-   goto out;
+   goto none;
block = new;

for (j = 1; j <= block[0x7e]; j++) {
@@ -1305,7 +1309,7 @@ struct edid *drm_do_get_edid(struct drm_connector 
*connector,
if (get_edid_block(data,
  block + (valid_extensions + 1) * EDID_LENGTH,
  j, EDID_LENGTH))
-   goto out;
+   goto none;
if (drm_edid_block_valid(block + (valid_extensions + 1)
 * EDID_LENGTH, j,
 print_bad_edid,
@@ -1329,11 +1333,11 @@ struct edid *drm_do_get_edid(struct drm_connector 
*connector,
block[0x7e] = valid_extensions;
new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, 
GFP_KERNEL);
if (!new)
-   goto out;
+   goto none;
block = new;
}

-   return (struct edid *)block;
+   goto out;

 carp:
if (print_bad_edid) {
@@ -1342,9 +1346,16 @@ carp:
}
connector->bad_edid_counter++;

-out:
+none:
kfree(block);
-   return NULL;
+   block = NULL;
+
+out:
+   after = ktime_get_raw_ns();
+
+   account_latency(DIV_ROUND_UP_ULL(after - before, 1000));
+
+   return (struct edid *)block;
 }
 EXPORT_SYMBOL_GPL(drm_do_get_edid);

-- 
2.5.1



[PATCH 1/2] kernel/latencytop: Add non-scheduler interface for latency reporting

2015-12-01 Thread Daniel Vetter
Some sources of significant amounts of latency aren't simple sleeps
but instead busy-loops or a series of hundreds of small sleeps simply
because the hardware can't do better. Unfortunately latencytop doesn't
register these and so they slip under the radar. Hence expose a
simplified interface to report additional latencies and export the
underlying function so that modules can use this.

The example I have in mind are edid reads. The drm subsystem exposes
both interfaces to do full probes and to just get at the cached state
from the last probe and often userspace developers don't know about
the difference and incur unecessary big latencies. And usually the i2c
transfer is done with busy-looping or if there is a hw engine it might
only be able to transfer a few bytes per sleep/irq cycle. And edid
reads take at least 12ms and with crappy hw can easily be a few
hundred ms.

Cc: Thomas Gleixner 
Cc: Arjan van de Ven 
Cc: Andrew Morton 
Signed-off-by: Daniel Vetter 
---
 include/linux/latencytop.h | 15 +++
 kernel/latencytop.c|  2 ++
 2 files changed, 17 insertions(+)

diff --git a/include/linux/latencytop.h b/include/linux/latencytop.h
index e23121f9d82a..46b69bc35f02 100644
--- a/include/linux/latencytop.h
+++ b/include/linux/latencytop.h
@@ -10,6 +10,9 @@
 #define _INCLUDE_GUARD_LATENCYTOP_H_

 #include 
+
+#include 
+
 struct task_struct;

 #ifdef CONFIG_LATENCYTOP
@@ -35,6 +38,13 @@ account_scheduler_latency(struct task_struct *task, int 
usecs, int inter)
__account_scheduler_latency(task, usecs, inter);
 }

+static inline void
+account_latency(int usecs)
+{
+   if (unlikely(latencytop_enabled))
+   __account_scheduler_latency(current, usecs, 0);
+}
+
 void clear_all_latency_tracing(struct task_struct *p);

 #else
@@ -44,6 +54,11 @@ account_scheduler_latency(struct task_struct *task, int 
usecs, int inter)
 {
 }

+static inline void
+account_latency(int usecs)
+{
+}
+
 static inline void clear_all_latency_tracing(struct task_struct *p)
 {
 }
diff --git a/kernel/latencytop.c b/kernel/latencytop.c
index a02812743a7e..b066a19fc52a 100644
--- a/kernel/latencytop.c
+++ b/kernel/latencytop.c
@@ -64,6 +64,7 @@ static DEFINE_RAW_SPINLOCK(latency_lock);
 static struct latency_record latency_record[MAXLR];

 int latencytop_enabled;
+EXPORT_SYMBOL_GPL(latencytop_enabled);

 void clear_all_latency_tracing(struct task_struct *p)
 {
@@ -234,6 +235,7 @@ __account_scheduler_latency(struct task_struct *tsk, int 
usecs, int inter)
 out_unlock:
raw_spin_unlock_irqrestore(_lock, flags);
 }
+EXPORT_SYMBOL_GPL(__account_scheduler_latency);

 static int lstats_show(struct seq_file *m, void *v)
 {
-- 
2.5.1



[PATCH] drm: bridge/dw_hdmi: add atomic API support

2015-12-01 Thread Mark Yao
Fill atomic needed funcs with default atomic helper library.

Rockchip use dw_hdmi, and drm/rockchip will covert to atomic api,
we need dw_hdmi support atomic funcs.

Now another drm driver use dw_hdmi is imx, not yet atomic, so
check DRIVER_ATOMIC at runtime to spilt atomic and not atomic.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/bridge/dw_hdmi.c |   23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 56de9f1..dc0bdd4 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -22,6 +22,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1522,6 +1523,17 @@ static struct drm_connector_funcs 
dw_hdmi_connector_funcs = {
.force = dw_hdmi_connector_force,
 };

+static struct drm_connector_funcs dw_hdmi_atomic_connector_funcs = {
+   .dpms = drm_atomic_helper_connector_dpms,
+   .fill_modes = drm_helper_probe_single_connector_modes,
+   .detect = dw_hdmi_connector_detect,
+   .destroy = dw_hdmi_connector_destroy,
+   .force = dw_hdmi_connector_force,
+   .reset = drm_atomic_helper_connector_reset,
+   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
 static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
.get_modes = dw_hdmi_connector_get_modes,
.mode_valid = dw_hdmi_connector_mode_valid,
@@ -1645,8 +1657,15 @@ static int dw_hdmi_register(struct drm_device *drm, 
struct dw_hdmi *hdmi)

drm_connector_helper_add(>connector,
 _hdmi_connector_helper_funcs);
-   drm_connector_init(drm, >connector, _hdmi_connector_funcs,
-  DRM_MODE_CONNECTOR_HDMIA);
+
+   if (drm_core_check_feature(drm, DRIVER_ATOMIC))
+   drm_connector_init(drm, >connector,
+  _hdmi_atomic_connector_funcs,
+  DRM_MODE_CONNECTOR_HDMIA);
+   else
+   drm_connector_init(drm, >connector,
+  _hdmi_connector_funcs,
+  DRM_MODE_CONNECTOR_HDMIA);

hdmi->connector.encoder = encoder;

-- 
1.7.9.5




[RESEND 3/3] drm :fsl-dcu: Add multi layers support

2015-12-01 Thread Dongsheng Wang
From: Jianwei Wang 

For DCU support atmost 16 layers(on ls1021a) or 64 layers(on vf610),
add (total_layer - 1) overlay planes.

Signed-off-by: Jianwei Wang 
Signed-off-by: Yi Meng 
Signed-off-by: Wang Dongsheng 

diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c 
b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index a8932a8..7ed1a7e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -235,7 +235,10 @@ static const u32 fsl_dcu_drm_plane_formats[] = {

 struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
 {
+   struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
struct drm_plane *primary;
+   struct drm_plane *overlay;
+   unsigned int total_layer, formats_size, i;
int ret;

primary = kzalloc(sizeof(*primary), GFP_KERNEL);
@@ -244,11 +247,12 @@ struct drm_plane *fsl_dcu_drm_primary_create_plane(struct 
drm_device *dev)
return NULL;
}

+   formats_size = ARRAY_SIZE(fsl_dcu_drm_plane_formats);
/* possible_crtc's will be filled in later by crtc_init */
ret = drm_universal_plane_init(dev, primary, 0,
   _dcu_drm_plane_funcs,
   fsl_dcu_drm_plane_formats,
-  ARRAY_SIZE(fsl_dcu_drm_plane_formats),
+  formats_size,
   DRM_PLANE_TYPE_PRIMARY);
if (ret) {
kfree(primary);
@@ -256,5 +260,26 @@ struct drm_plane *fsl_dcu_drm_primary_create_plane(struct 
drm_device *dev)
}
drm_plane_helper_add(primary, _dcu_drm_plane_helper_funcs);

+   total_layer = fsl_dev->soc->total_layer;
+   for (i = 0; i < total_layer - 1; i++) {
+   overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
+   if (!overlay) {
+   DRM_DEBUG_KMS("Failed to allocate overlay plane\n");
+   goto out;
+   }
+
+   ret = drm_universal_plane_init(dev, overlay, 1,
+  _dcu_drm_plane_funcs,
+  fsl_dcu_drm_plane_formats,
+  formats_size,
+  DRM_PLANE_TYPE_OVERLAY);
+   if (ret) {
+   kfree(overlay);
+   goto out;
+   }
+   drm_plane_helper_add(overlay, _dcu_drm_plane_helper_funcs);
+   }
+
+out:
return primary;
 }
-- 
2.1.0.27.g96db324



[RESEND 2/3] drm :fsl-dcu: Cleanup vblank interrupt mask and status setting code

2015-12-01 Thread Dongsheng Wang
From: Jianwei Wang 

Switch update interrupt mask bit with regmap_update_bits, and clear
interrupt status by writing 1 to relevant bit before setting mask in
fsl_dcu_drm_irq_init function.

Signed-off-by: Jianwei Wang 
Signed-off-by: Yi Meng 
Signed-off-by: Wang Dongsheng 

diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c 
b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index 1930234..5c29ff7 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -38,21 +38,17 @@ static const struct regmap_config fsl_dcu_regmap_config = {
 static int fsl_dcu_drm_irq_init(struct drm_device *dev)
 {
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-   unsigned int value;
int ret;

ret = drm_irq_install(dev, fsl_dev->irq);
if (ret < 0)
dev_err(dev->dev, "failed to install IRQ handler\n");

-   ret = regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0);
+   ret = regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0x);
if (ret)
dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
-   ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, );
-   if (ret)
-   dev_err(dev->dev, "read DCU_INT_MASK failed\n");
-   value &= DCU_INT_MASK_VBLANK;
-   ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
+   ret = regmap_update_bits(fsl_dev->regmap, DCU_INT_MASK,
+DCU_INT_MASK_VBLANK, ~DCU_INT_MASK_VBLANK);
if (ret)
dev_err(dev->dev, "set DCU_INT_MASK failed\n");
ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
@@ -143,14 +139,10 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
 static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-   unsigned int value;
int ret;

-   ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, );
-   if (ret)
-   dev_err(dev->dev, "read DCU_INT_MASK failed\n");
-   value &= ~DCU_INT_MASK_VBLANK;
-   ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
+   ret = regmap_update_bits(fsl_dev->regmap, DCU_INT_MASK,
+DCU_INT_MASK_VBLANK, ~DCU_INT_MASK_VBLANK);
if (ret)
dev_err(dev->dev, "set DCU_INT_MASK failed\n");
return 0;
@@ -160,14 +152,10 @@ static void fsl_dcu_drm_disable_vblank(struct drm_device 
*dev,
   unsigned int pipe)
 {
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
-   unsigned int value;
int ret;

-   ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, );
-   if (ret)
-   dev_err(dev->dev, "read DCU_INT_MASK failed\n");
-   value |= DCU_INT_MASK_VBLANK;
-   ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
+   ret = regmap_update_bits(fsl_dev->regmap, DCU_INT_MASK,
+DCU_INT_MASK_VBLANK, DCU_INT_MASK_VBLANK);
if (ret)
dev_err(dev->dev, "set DCU_INT_MASK failed\n");
 }
-- 
2.1.0.27.g96db324



[RESEND 1/3] drm: fsl-dcu: Fix no fb check bug

2015-12-01 Thread Dongsheng Wang
From: Jianwei Wang 

For state->fb may be NULL in fsl_dcu_drm_plane_atomic_check function,
if so, return -EINVAL. No need check in fsl_dcu_drm_plane_atomic_update
anymore.

Signed-off-by: Jianwei Wang 
Signed-off-by: Yi Meng 
Signed-off-by: Wang Dongsheng 
Tested-by: Stefan Agner 

diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c 
b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
index 51daaea..a8932a8 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -41,6 +41,9 @@ static int fsl_dcu_drm_plane_atomic_check(struct drm_plane 
*plane,
 {
struct drm_framebuffer *fb = state->fb;

+   if (!fb)
+   return -EINVAL;
+
switch (fb->pixel_format) {
case DRM_FORMAT_RGB565:
case DRM_FORMAT_RGB888:
@@ -85,9 +88,6 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane 
*plane,
unsigned int alpha, bpp;
int index, ret;

-   if (!fb)
-   return;
-
index = fsl_dcu_drm_plane_index(plane);
if (index < 0)
return;
-- 
2.1.0.27.g96db324



[PATCH] drm/nouveau: Fix pre-nv50 pageflip events

2015-12-01 Thread poma
On Mon, Nov 16, 2015 at 4:11 PM, Daniel Vetter  wrote:
> On Mon, Nov 02, 2015 at 04:45:00PM +0900, Michel Dänzer wrote:
>> On 31.10.2015 06:55, Daniel Vetter wrote:
>> > Apparently pre-nv50 pageflip events happen before the actual vblank
>> > period. Therefore that functionality got semi-disabled in
>> >
>> > commit af4870e406126b7ac0ae7c7ce5751f25ebe60f28
>> > Author: Mario Kleiner 
>> > Date:   Tue May 13 00:42:08 2014 +0200
>> >
>> > drm/nouveau/kms/nv04-nv40: fix pageflip events via special case.
>> >
>> > Unfortunately that hack got uprooted in
>> >
>> > commit cc1ef118fc099295ae6aabbacc8af94d8d8885eb
>> > Author: Thierry Reding 
>> > Date:   Wed Aug 12 17:00:31 2015 +0200
>> >
>> > drm/irq: Make pipe unsigned and name consistent
>> >
>> > Trigering a warning when trying to sample the vblank timestamp for a
>> > non-existing pipe. There's a few ways to fix this:
>> >
>> > - Open-code the old behaviour, which just enshrines this slight
>> >   breakage of the userspace ABI.
>> >
>> > - Revert Mario's commit and again inflict broken timestamps, again not
>> >   pretty.
>> >
>> > - Fix this for real by delaying the pageflip TS until the next vblank
>> >   interrupt, thereby making it accurate.
>> >
>> > This patch implements the third option. Since having a page flip
>> > interrupt that happens when the pageflip gets armed and not when it
>> > completes in the next vblank seems to be fairly common (older i915 hw
>> > works very similarly) create a new helper to arm vblank events for
>> > such drivers.
>>
>> What happens when the page flip interrupt arrives during a vertical
>> blank period?  Presumably the userspace event will be deferred until the
>> next vertical blank period, but the flip might already take effect in
>> the current one.
>
> Hm yeah there's a tiny race if your update handler for the pageflip can
> race with your vblank handler. That's impossible here since it's all done
> from the same hw irq hanlder, and since that is single-threaded there
> shouldn't be a problem, as long as vblank handling are pageflip are
> ordered correctly.
>
> Might be worth a note in the kerneldoc though that this function isn't
> perfectly foolproof.
> -Daniel


Is there any updates in this respect?

drm-nouveau-Fix-pre-nv50-pageflip-events-v4.patch
https://patchwork.kernel.org/patch/7591531

https://bugzilla.kernel.org/show_bug.cgi?id=106431
Reported: 2015-10-21


[RFC PATCH 8/9] drm: bridge/dw_hdmi: Covert to support atomic API

2015-12-01 Thread Mark yao
On 2015年12月01日 15:21, Daniel Vetter wrote:
> On Tue, Dec 01, 2015 at 11:35:53AM +0800, Mark Yao wrote:
>> Fill atomic needed funcs with default atomic helper library.
>>
>> Rockchip use dw_hdmi, and drm/rockchip will covert to atomic api,
>> we need dw_hdmi support atomic funcs.
>>
>> Signed-off-by: Mark Yao 
> Aren't there drivers around which use dw_hdmi and which are still not yet
> atomic? This would break them. I think we neeed two connector_func tables
> and dw_hdmi needs to check for DRIVER_ATOMIC at runtime and pick the right
> version.

Right, another drm driver use dw_hdmi is imx, not yet atomic, this would 
break it.
as you said, I would resend a patch to check DRIVER_ATOMIC at runtime.

Thanks
-Mark

>
> The larger problem here is that "who should register the drm_connector" is
> a bit an unsolved problem, since both the bridge and the driver should be
> able to customize/adjust the drm_connector at the end of a bridge chain.
> This here is just another example of this problem.
> -Daniel
>
>> ---
>>   drivers/gpu/drm/bridge/dw_hdmi.c |6 +-
>>   1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c 
>> b/drivers/gpu/drm/bridge/dw_hdmi.c
>> index 56de9f1..587065a 100644
>> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
>> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
>> @@ -22,6 +22,7 @@
>>   
>>   #include 
>>   #include 
>> +#include 
>>   #include 
>>   #include 
>>   #include 
>> @@ -1515,11 +1516,14 @@ static void dw_hdmi_connector_force(struct 
>> drm_connector *connector)
>>   }
>>   
>>   static struct drm_connector_funcs dw_hdmi_connector_funcs = {
>> -.dpms = drm_helper_connector_dpms,
>> +.dpms = drm_atomic_helper_connector_dpms,
>>  .fill_modes = drm_helper_probe_single_connector_modes,
>>  .detect = dw_hdmi_connector_detect,
>>  .destroy = dw_hdmi_connector_destroy,
>>  .force = dw_hdmi_connector_force,
>> +.reset = drm_atomic_helper_connector_reset,
>> +.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
>> +.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>>   };
>>   
>>   static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
>> -- 
>> 1.7.9.5
>>
>>
>> ___
>> dri-devel mailing list
>> dri-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel



[PATCH 1/2] kernel/latencytop: Add non-scheduler interface for latency reporting

2015-12-01 Thread Chris Wilson
On Tue, Dec 01, 2015 at 04:29:27PM +0100, Daniel Vetter wrote:
> Some sources of significant amounts of latency aren't simple sleeps
> but instead busy-loops or a series of hundreds of small sleeps simply
> because the hardware can't do better. Unfortunately latencytop doesn't
> register these and so they slip under the radar. Hence expose a
> simplified interface to report additional latencies and export the
> underlying function so that modules can use this.
> 
> The example I have in mind are edid reads. The drm subsystem exposes
> both interfaces to do full probes and to just get at the cached state
> from the last probe and often userspace developers don't know about
> the difference and incur unecessary big latencies. And usually the i2c
> transfer is done with busy-looping or if there is a hw engine it might
> only be able to transfer a few bytes per sleep/irq cycle. And edid
> reads take at least 12ms and with crappy hw can easily be a few
> hundred ms.
> 
> Cc: Thomas Gleixner 
> Cc: Arjan van de Ven 
> Cc: Andrew Morton 
> Signed-off-by: Daniel Vetter 
> ---
>  include/linux/latencytop.h | 15 +++
>  kernel/latencytop.c|  2 ++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/include/linux/latencytop.h b/include/linux/latencytop.h
> index e23121f9d82a..46b69bc35f02 100644
> --- a/include/linux/latencytop.h
> +++ b/include/linux/latencytop.h
> @@ -10,6 +10,9 @@
>  #define _INCLUDE_GUARD_LATENCYTOP_H_
>  
>  #include 
> +
> +#include 
> +
>  struct task_struct;
>  
>  #ifdef CONFIG_LATENCYTOP
> @@ -35,6 +38,13 @@ account_scheduler_latency(struct task_struct *task, int 
> usecs, int inter)
>   __account_scheduler_latency(task, usecs, inter);
>  }
>  
> +static inline void
> +account_latency(int usecs)
> +{
> + if (unlikely(latencytop_enabled))
> + __account_scheduler_latency(current, usecs, 0);

Just

account_scheduler_latency(current, usecs, 0);
> +}

And then that can be used for both ifdef paths, i.e. move account_latency() to 
after the #endif.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre


[PATCH libdrm] intel: add the missing header

2015-12-01 Thread Chih-Wei Huang
Any concern to merge such a simple fix??

2015-10-30 11:49 GMT+08:00 Chih-Wei Huang :
> It defines the prototype of ffs that fixes the building error
> on Android 6.0 64-bit image.
>
> Signed-off-by: Chih-Wei Huang 
> ---
>  intel/intel_bufmgr_fake.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/intel/intel_bufmgr_fake.c b/intel/intel_bufmgr_fake.c
> index 551e05d..7f4c7b9 100644
> --- a/intel/intel_bufmgr_fake.c
> +++ b/intel/intel_bufmgr_fake.c
> @@ -42,6 +42,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include "intel_bufmgr.h"
> --
> 1.9.1
>



-- 
Chih-Wei
Android-x86 project
http://www.android-x86.org


[Bug 92309] Box drawn around cursor in multiple 3D games

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=92309

--- Comment #13 from Kamil Páral  ---
acutiator, thanks in advanced for the effort. I have zero knowledge about all
of this, but this wikipedia article seems to be comprehensible:
https://en.wikipedia.org/wiki/Alpha_compositing

The important part:
~~~
If an alpha channel is used in an image, it is common to also multiply the
color by the alpha value, to save on additional multiplications during
compositing. This is usually referred to as premultiplied alpha.

Assuming that the pixel color is expressed using straight (non-premultiplied)
RGBA tuples, a pixel value of (0.0, 0.5, 0.0, 0.5) implies a pixel that has 50%
of the maximum green intensity and 50% opacity. If the color were fully green,
its RGBA would be (0, 1, 0, 0.5).

However, if this pixel uses premultiplied alpha, all of the RGB values (0, 1,
0) are multiplied by 0.5 and then the alpha is appended to the end to yield (0,
0.5, 0, 0.5). In this case, the 0.5 value for the G channel actually indicates
100% green intensity (with 50% opacity). For this reason, knowing whether a
file uses premultiplied or straight alpha is essential to correctly process or
composite it.
~~~

I've also found the following howtos when searching for this:
http://www.gamedev.net/topic/623481-how-to-create-pre-multiplied-alpha-for-use-with-opengl/
http://blog.qythyx.com/2014/01/premultiplied-alpha.html

Hope that helps a bit. You might wait a while whether someone more
knowledgeable gives you a better advice.

-- 
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/20151201/9b7313ab/attachment.html>


[PATCH v3 12/12] dt-bindings: msm/dsi: Add DSIv2 documentation

2015-12-01 Thread Archit Taneja
Add additional property info needed for DSIv2 DT.

Cc: devicetree at vger.kernel.org
Cc: Rob Herring 

Signed-off-by: Archit Taneja 
---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt 
b/Documentation/devicetree/bindings/display/msm/dsi.txt
index e097955..e7423be 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
@@ -21,10 +21,13 @@ Required properties:
   * "byte_clk"
   * "pixel_clk"
   * "core_clk"
+  For DSIv2, we need an additional clock:
+   * "src_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
 - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)

 Optional properties:
 - panel at 0: Node of panel connected to this DSI controller.
@@ -51,6 +54,7 @@ Required properties:
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
   * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 11/12] dt-bindings: msm/dsi: Fix the order in which clocks are listed

2015-12-01 Thread Archit Taneja
List the clocks in the order that's used in DT. We don't have mdp/dsi
DT nodes for any SoC in upstream yet, but we align with the order
we intend to use.

Cc: devicetree at vger.kernel.org
Cc: Rob Herring 

Signed-off-by: Archit Taneja 
---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt 
b/Documentation/devicetree/bindings/display/msm/dsi.txt
index f344b9e..e097955 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
@@ -14,13 +14,13 @@ Required properties:
 - clocks: device clocks
   See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
 - clock-names: the following clocks are required:
+  * "mdp_core_clk"
+  * "iface_clk"
   * "bus_clk"
-  * "byte_clk"
-  * "core_clk"
   * "core_mmss_clk"
-  * "iface_clk"
-  * "mdp_core_clk"
+  * "byte_clk"
   * "pixel_clk"
+  * "core_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 10/12] drm/msm/dsi: Enable MMSS SPFB port via syscon

2015-12-01 Thread Archit Taneja
For DSIv2 to work, we need to enable MMSS_AHB_ARB_MASTER_PORT in
MMSS_SFPB. We enable the required bitfield by retrieving MMSS_SFPB
regmap pointer via syscon.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index bbf7f72..f61b88e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -24,10 +24,13 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 

 #include "dsi.h"
 #include "dsi.xml.h"
+#include "sfpb.xml.h"
 #include "dsi_cfg.h"

 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
@@ -149,6 +152,8 @@ struct msm_dsi_host {

u8 *rx_buf;

+   struct regmap *sfpb;
+
struct drm_display_mode *mode;

/* connected device info */
@@ -1568,6 +1573,16 @@ static int dsi_host_parse_dt(struct msm_dsi_host 
*msm_host)

msm_host->device_node = device_node;

+   if (of_property_read_bool(np, "syscon-sfpb")) {
+   msm_host->sfpb = syscon_regmap_lookup_by_phandle(np,
+   "syscon-sfpb");
+   if (IS_ERR(msm_host->sfpb)) {
+   dev_err(dev, "%s: failed to get sfpb regmap\n",
+   __func__);
+   return PTR_ERR(msm_host->sfpb);
+   }
+   }
+
return 0;
 }

@@ -2031,6 +2046,20 @@ int msm_dsi_host_disable(struct mipi_dsi_host *host)
return 0;
 }

+static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
+{
+   enum sfpb_ahb_arb_master_port_en en;
+
+   if (!msm_host->sfpb)
+   return;
+
+   en = enable ? SFPB_MASTER_PORT_ENABLE : SFPB_MASTER_PORT_DISABLE;
+
+   regmap_update_bits(msm_host->sfpb, REG_SFPB_GPREG,
+   SFPB_GPREG_MASTER_PORT_EN__MASK,
+   SFPB_GPREG_MASTER_PORT_EN(en));
+}
+
 int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 {
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2043,6 +2072,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
goto unlock_ret;
}

+   msm_dsi_sfpb_config(msm_host, true);
+
ret = dsi_calc_clk_rate(msm_host);
if (ret) {
pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
@@ -2130,6 +2161,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)

dsi_host_regulator_disable(msm_host);

+   msm_dsi_sfpb_config(msm_host, false);
+
DBG("-");

msm_host->power_on = false;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 09/12] drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2

2015-12-01 Thread Archit Taneja
We currently use iommu allocated DMA buffers for sending DSI commands.
DSIv2 doesn't have a port connected to the MDP iommu. Therefore, it
can't use iommu allocated buffers to fetch DSI commands.

Use a regular contiguous DMA buffer if we are DSIv2.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi.h |   4 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c| 110 +++---
 drivers/gpu/drm/msm/dsi/dsi_manager.c |   6 +-
 3 files changed, 79 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 7336b55..749fbb2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -91,7 +91,7 @@ int msm_dsi_manager_phy_enable(int id,
u32 *clk_pre, u32 *clk_post);
 void msm_dsi_manager_phy_disable(int id);
 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len);
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
 int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);

@@ -145,7 +145,7 @@ int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host,
 int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg);
 void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host,
-   u32 iova, u32 len);
+   u32 dma_base, u32 len);
 int msm_dsi_host_enable(struct mipi_dsi_host *host);
 int msm_dsi_host_disable(struct mipi_dsi_host *host);
 int msm_dsi_host_power_on(struct mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 6ec2178..bbf7f72 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -138,7 +138,15 @@ struct msm_dsi_host {
struct work_struct err_work;
struct workqueue_struct *workqueue;

+   /* DSI 6G TX buffer*/
struct drm_gem_object *tx_gem_obj;
+
+   /* DSI v2 TX buffer */
+   void *tx_buf;
+   dma_addr_t tx_buf_paddr;
+
+   int tx_size;
+
u8 *rx_buf;

struct drm_display_mode *mode;
@@ -983,29 +991,46 @@ static void dsi_wait4video_eng_busy(struct msm_dsi_host 
*msm_host)
 static int dsi_tx_buf_alloc(struct msm_dsi_host *msm_host, int size)
 {
struct drm_device *dev = msm_host->dev;
+   const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
int ret;
u32 iova;

-   mutex_lock(>struct_mutex);
-   msm_host->tx_gem_obj = msm_gem_new(dev, size, MSM_BO_UNCACHED);
-   if (IS_ERR(msm_host->tx_gem_obj)) {
-   ret = PTR_ERR(msm_host->tx_gem_obj);
-   pr_err("%s: failed to allocate gem, %d\n", __func__, ret);
-   msm_host->tx_gem_obj = NULL;
+   if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
+   mutex_lock(>struct_mutex);
+   msm_host->tx_gem_obj = msm_gem_new(dev, size, MSM_BO_UNCACHED);
+   if (IS_ERR(msm_host->tx_gem_obj)) {
+   ret = PTR_ERR(msm_host->tx_gem_obj);
+   pr_err("%s: failed to allocate gem, %d\n",
+   __func__, ret);
+   msm_host->tx_gem_obj = NULL;
+   mutex_unlock(>struct_mutex);
+   return ret;
+   }
+
+   ret = msm_gem_get_iova_locked(msm_host->tx_gem_obj, 0, );
+   if (ret) {
+   pr_err("%s: failed to get iova, %d\n", __func__, ret);
+   return ret;
+   }
mutex_unlock(>struct_mutex);
-   return ret;
-   }

-   ret = msm_gem_get_iova_locked(msm_host->tx_gem_obj, 0, );
-   if (ret) {
-   pr_err("%s: failed to get iova, %d\n", __func__, ret);
-   return ret;
-   }
-   mutex_unlock(>struct_mutex);
+   if (iova & 0x07) {
+   pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+   return -EINVAL;
+   }

-   if (iova & 0x07) {
-   pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
-   return -EINVAL;
+   msm_host->tx_size = msm_host->tx_gem_obj->size;
+   } else {
+   msm_host->tx_buf = dma_alloc_coherent(dev->dev, size,
+   _host->tx_buf_paddr, GFP_KERNEL);
+   if (!msm_host->tx_buf) {
+   ret = -ENOMEM;
+   pr_err("%s: failed to allocate tx buf, %d\n",
+   __func__, ret);
+   return ret;
+   }
+
+   msm_host->tx_size = size;
}

return 0;
@@ -1022,14 +1047,19 @@ static void dsi_tx_buf_free(struct msm_dsi_host 
*msm_host)

[PATCH v3 08/12] drm/msm/dsi: Add dsi_cfg for APQ8064

2015-12-01 Thread Archit Taneja
Add a dsi_cfg entry for APQ8064. Since this is the first DSIv2 chip to
be supported, add a list of bus clocks that are required by the DSIv2
block.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi_cfg.c | 19 ---
 drivers/gpu/drm/msm/dsi/dsi_cfg.h |  2 ++
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index c40044f..2a827d8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -13,9 +13,22 @@

 #include "dsi_cfg.h"

-/* DSI v2 has not been supported by now */
-static const struct msm_dsi_config dsi_v2_cfg = {
+static const char * const dsi_v2_bus_clk_names[] = {
+   "core_mmss_clk", "iface_clk", "bus_clk",
+};
+
+static const struct msm_dsi_config apq8064_dsi_cfg = {
.io_offset = 0,
+   .reg_cfg = {
+   .num = 3,
+   .regs = {
+   {"vdda", 120, 120, 10, 100},
+   {"avdd", 300, 300, 11, 100},
+   {"vddio", 180, 180, 10, 100},
+   },
+   },
+   .bus_clk_names = dsi_v2_bus_clk_names,
+   .num_bus_clks = ARRAY_SIZE(dsi_v2_bus_clk_names),
 };

 static const char * const dsi_6g_bus_clk_names[] = {
@@ -75,7 +88,7 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 };

 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
-   {MSM_DSI_VER_MAJOR_V2, U32_MAX, _v2_cfg},
+   {MSM_DSI_VER_MAJOR_V2, MSM_DSI_V2_VER_MINOR_8064, _dsi_cfg},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
_apq8084_dsi_cfg},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 5a36836..a68c836 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -25,6 +25,8 @@
 #define MSM_DSI_6G_VER_MINOR_V1_3  0x1003
 #define MSM_DSI_6G_VER_MINOR_V1_3_10x10030001

+#define MSM_DSI_V2_VER_MINOR_8064  0x0
+
 #define DSI_6G_REG_SHIFT   4

 struct msm_dsi_config {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 07/12] drm/msm/dsi: Set up link clocks for DSIv2

2015-12-01 Thread Archit Taneja
DSIv2 (DSI on older A family chips) has slightly different link clock
requirements.

First, we have an extra clock called src_clk (with a dedicated RCG).
This is required by the DSI controller to process the pixel data
coming from MDP. It needs to be set at the rate "pclk * bytes_per_pixel".

We also need to explicitly configure esc_clk. On DSI6G chips, we don't
need to set a rate to esc_clk because its RCG is always sourced from
crystal clock (19.2 Mhz in all cases), which is within the escape clock
frequency range in the mipi DSI spec. For chips with DSIv2, the crystal
clock rate may not be within the required range (27Mhz on APQ8064).
Therefore, we derive it from the DSI byte clock. We calculate an esc_clck
rate that is within the mipi spec and also divisible by the byte clock
rate.

When setting rate and enabling the link clocks, we make sure that byte_clk
is configured before esc_clk, and src_clk before pixel_clk. We create two
different link_enable funcs for DSI6G and DSIv2 since the sequences are
different.

We also obtain two extra source clocks (dsi_src_clk and esc_src_clk) and
set their parent to the clocks provided by DSI PLL.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 191 -
 1 file changed, 186 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 56c7535..6ec2178 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -113,6 +113,14 @@ struct msm_dsi_host {
struct clk *pixel_clk_src;

u32 byte_clk_rate;
+   u32 esc_clk_rate;
+
+   /* DSI v2 specific clocks */
+   struct clk *src_clk;
+   struct clk *esc_clk_src;
+   struct clk *dsi_clk_src;
+
+   u32 src_clk_rate;

struct gpio_desc *disp_en_gpio;
struct gpio_desc *te_gpio;
@@ -318,7 +326,8 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
 static int dsi_clk_init(struct msm_dsi_host *msm_host)
 {
struct device *dev = _host->pdev->dev;
-   const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg;
+   const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+   const struct msm_dsi_config *cfg = cfg_hnd->cfg;
int i, ret = 0;

/* get bus clocks */
@@ -372,8 +381,34 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
if (!msm_host->pixel_clk_src) {
ret = -ENODEV;
pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret);
+   goto exit;
}

+   if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+   msm_host->src_clk = devm_clk_get(dev, "src_clk");
+   if (IS_ERR(msm_host->src_clk)) {
+   ret = PTR_ERR(msm_host->src_clk);
+   pr_err("%s: can't find dsi_src_clk. ret=%d\n",
+   __func__, ret);
+   msm_host->src_clk = NULL;
+   goto exit;
+   }
+
+   msm_host->esc_clk_src = clk_get_parent(msm_host->esc_clk);
+   if (!msm_host->esc_clk_src) {
+   ret = -ENODEV;
+   pr_err("%s: can't get esc_clk_src. ret=%d\n",
+   __func__, ret);
+   goto exit;
+   }
+
+   msm_host->dsi_clk_src = clk_get_parent(msm_host->src_clk);
+   if (!msm_host->dsi_clk_src) {
+   ret = -ENODEV;
+   pr_err("%s: can't get dsi_clk_src. ret=%d\n",
+   __func__, ret);
+   }
+   }
 exit:
return ret;
 }
@@ -413,7 +448,7 @@ static void dsi_bus_clk_disable(struct msm_dsi_host 
*msm_host)
clk_disable_unprepare(msm_host->bus_clks[i]);
 }

-static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host)
 {
int ret;

@@ -460,11 +495,98 @@ error:
return ret;
 }

-static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host)
 {
+   int ret;
+
+   DBG("Set clk rates: pclk=%d, byteclk=%d, esc_clk=%d, dsi_src_clk=%d",
+   msm_host->mode->clock, msm_host->byte_clk_rate,
+   msm_host->esc_clk_rate, msm_host->src_clk_rate);
+
+   ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate);
+   if (ret) {
+   pr_err("%s: Failed to set rate byte clk, %d\n", __func__, ret);
+   goto error;
+   }
+
+   ret = clk_set_rate(msm_host->esc_clk, msm_host->esc_clk_rate);
+   if (ret) {
+   pr_err("%s: Failed to set rate esc clk, %d\n", __func__, ret);
+   goto error;
+   }
+
+   ret = clk_set_rate(msm_host->src_clk, msm_host->src_clk_rate);
+   if (ret) {
+   pr_err("%s: Failed to set rate src clk, 

[PATCH v3 06/12] drm/msm/dsi: Parse bus clocks from a list

2015-12-01 Thread Archit Taneja
DSI bus clocks seem to vary between different DSI host versions, and the
SOC to which they belong. Even the enable/disable sequence varies.

Provide a list of bus clock names in dsi_cfg. The driver will use this to
retrieve the clocks, and enable/disable them.

Add bus clock lists for DSI6G, and DSI for MSM8916(this is DSI6G too, but
there is no MMSS_CC specific clock since there is no MMSS clock controller
on 8916).

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi.h  |   1 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  16 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |   2 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 107 -
 4 files changed, 53 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 8140e8b..7336b55 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -36,6 +36,7 @@ enum msm_dsi_phy_type {
 };

 #define DSI_DEV_REGULATOR_MAX  8
+#define DSI_BUS_CLK_MAX4

 /* Regulators for DSI devices */
 struct dsi_reg_entry {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 5872d5e..c40044f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -18,6 +18,10 @@ static const struct msm_dsi_config dsi_v2_cfg = {
.io_offset = 0,
 };

+static const char * const dsi_6g_bus_clk_names[] = {
+   "mdp_core_clk", "iface_clk", "bus_clk", "core_mmss_clk",
+};
+
 static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
.io_offset = DSI_6G_REG_SHIFT,
.reg_cfg = {
@@ -29,6 +33,12 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = 
{
{"vddio", 180, 180, 10, 100},
},
},
+   .bus_clk_names = dsi_6g_bus_clk_names,
+   .num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
+};
+
+static const char * const dsi_8916_bus_clk_names[] = {
+   "mdp_core_clk", "iface_clk", "bus_clk",
 };

 static const struct msm_dsi_config msm8916_dsi_cfg = {
@@ -42,6 +52,8 @@ static const struct msm_dsi_config msm8916_dsi_cfg = {
{"vddio", 180, 180, 10, 100},
},
},
+   .bus_clk_names = dsi_8916_bus_clk_names,
+   .num_bus_clks = ARRAY_SIZE(dsi_8916_bus_clk_names),
 };

 static const struct msm_dsi_config msm8994_dsi_cfg = {
@@ -57,7 +69,9 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
{"lab_reg", -1, -1, -1, -1},
{"ibb_reg", -1, -1, -1, -1},
},
-   }
+   },
+   .bus_clk_names = dsi_6g_bus_clk_names,
+   .num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
 };

 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 4cf8872..5a36836 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -30,6 +30,8 @@
 struct msm_dsi_config {
u32 io_offset;
struct dsi_reg_config reg_cfg;
+   const char * const *bus_clk_names;
+   const int num_bus_clks;
 };

 struct msm_dsi_cfg_handler {
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index f787024..56c7535 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -103,10 +103,9 @@ struct msm_dsi_host {

void __iomem *ctrl_base;
struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
-   struct clk *mdp_core_clk;
-   struct clk *ahb_clk;
-   struct clk *axi_clk;
-   struct clk *mmss_misc_ahb_clk;
+
+   struct clk *bus_clks[DSI_BUS_CLK_MAX];
+
struct clk *byte_clk;
struct clk *esc_clk;
struct clk *pixel_clk;
@@ -319,40 +318,22 @@ static int dsi_regulator_init(struct msm_dsi_host 
*msm_host)
 static int dsi_clk_init(struct msm_dsi_host *msm_host)
 {
struct device *dev = _host->pdev->dev;
-   int ret = 0;
-
-   msm_host->mdp_core_clk = devm_clk_get(dev, "mdp_core_clk");
-   if (IS_ERR(msm_host->mdp_core_clk)) {
-   ret = PTR_ERR(msm_host->mdp_core_clk);
-   pr_err("%s: Unable to get mdp core clk. ret=%d\n",
-   __func__, ret);
-   goto exit;
-   }
-
-   msm_host->ahb_clk = devm_clk_get(dev, "iface_clk");
-   if (IS_ERR(msm_host->ahb_clk)) {
-   ret = PTR_ERR(msm_host->ahb_clk);
-   pr_err("%s: Unable to get mdss ahb clk. ret=%d\n",
-   __func__, ret);
-   goto exit;
-   }
-
-   msm_host->axi_clk = devm_clk_get(dev, "bus_clk");
-   if (IS_ERR(msm_host->axi_clk)) {
-   ret = PTR_ERR(msm_host->axi_clk);
-   pr_err("%s: Unable to get axi bus clk. ret=%d\n",
-   __func__, ret);
-   goto exit;
-   }
-
-   msm_host->mmss_misc_ahb_clk = 

[PATCH v3 05/12] drm/msm/dsi: Delay dsi_clk_init

2015-12-01 Thread Archit Taneja
Initialize clocks only after we get the DSI host version. This will allow
us to get clocks using a pre-defined list based on the DSI major/minor
version of the host. This is required since clock requirements of
different major DSI revisions(v2 vs 6g) aren't the same.

Modify dsi_get_version to get the interface clock, and then put it after
it is used.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 32 ++--
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 7a365df..f787024 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -177,21 +177,31 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
struct msm_dsi_host *msm_host)
 {
const struct msm_dsi_cfg_handler *cfg_hnd = NULL;
+   struct device *dev = _host->pdev->dev;
struct regulator *gdsc_reg;
+   struct clk *ahb_clk;
int ret;
u32 major = 0, minor = 0;

-   gdsc_reg = regulator_get(_host->pdev->dev, "gdsc");
+   gdsc_reg = regulator_get(dev, "gdsc");
if (IS_ERR(gdsc_reg)) {
pr_err("%s: cannot get gdsc\n", __func__);
goto exit;
}
+
+   ahb_clk = clk_get(dev, "iface_clk");
+   if (IS_ERR(ahb_clk)) {
+   pr_err("%s: cannot get interface clock\n", __func__);
+   goto put_gdsc;
+   }
+
ret = regulator_enable(gdsc_reg);
if (ret) {
pr_err("%s: unable to enable gdsc\n", __func__);
-   goto put_gdsc;
+   goto put_clk;
}
-   ret = clk_prepare_enable(msm_host->ahb_clk);
+
+   ret = clk_prepare_enable(ahb_clk);
if (ret) {
pr_err("%s: unable to enable ahb_clk\n", __func__);
goto disable_gdsc;
@@ -208,9 +218,11 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
DBG("%s: Version %x:%x\n", __func__, major, minor);

 disable_clks:
-   clk_disable_unprepare(msm_host->ahb_clk);
+   clk_disable_unprepare(ahb_clk);
 disable_gdsc:
regulator_disable(gdsc_reg);
+put_clk:
+   clk_put(ahb_clk);
 put_gdsc:
regulator_put(gdsc_reg);
 exit:
@@ -1417,12 +1429,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
goto fail;
}

-   ret = dsi_clk_init(msm_host);
-   if (ret) {
-   pr_err("%s: unable to initialize dsi clks\n", __func__);
-   goto fail;
-   }
-
msm_host->ctrl_base = msm_ioremap(pdev, "dsi_ctrl", "DSI CTRL");
if (IS_ERR(msm_host->ctrl_base)) {
pr_err("%s: unable to map Dsi ctrl base\n", __func__);
@@ -1446,6 +1452,12 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
goto fail;
}

+   ret = dsi_clk_init(msm_host);
+   if (ret) {
+   pr_err("%s: unable to initialize dsi clks\n", __func__);
+   goto fail;
+   }
+
msm_host->rx_buf = devm_kzalloc(>dev, SZ_4K, GFP_KERNEL);
if (!msm_host->rx_buf) {
pr_err("%s: alloc rx temp buf failed\n", __func__);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 04/12] drm/msm/dsi: Use a better way to figure out DSI version

2015-12-01 Thread Archit Taneja
The current version checking mechanism works fine for DSI6G blocks. It
doesn't work so well for older generation DSIv2 blocks.

The initial read of REG_DSI_6G_HW_VERSION(offset 0x0) would result in a
read of REG_DSI_CTRL for DSIv2. This register won't necessarily be 0 on
DSIv2. It can be non zero if DSI was previously initialized by the
bootloader.

Instead of reading offset 0x0, we now read offset 0x1f0. For DSIv2, this
register is DSI_VERSION, and is bound to be non-zero. On DSI6G, this
register(offset 0x1f0) is SCRATCH_REGISTER_0, which no one ever seems to
touch, and from all register dumps I'vc seen, holds 0 all the time.

Modify dsi_get_version to read REG_DSI_VERSION to determine whether we
are DSI6G or DSIv2.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index aec97c8..7a365df 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -33,17 +33,24 @@
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
u32 ver;
-   u32 ver_6g;

if (!major || !minor)
return -EINVAL;

-   /* From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
+   /*
+* From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
 * makes all other registers 4-byte shifted down.
+*
+* In order to identify between DSI6G(v3) and beyond, and DSIv2 and
+* older, we read the DSI_VERSION register without any shift(offset
+* 0x1f0). In the case of DSIv2, this hast to be a non-zero value. In
+* the case of DSI6G, this has to be zero (the offset points to a
+* scratch register which we never touch)
 */
-   ver_6g = msm_readl(base + REG_DSI_6G_HW_VERSION);
-   if (ver_6g == 0) {
-   ver = msm_readl(base + REG_DSI_VERSION);
+
+   ver = msm_readl(base + REG_DSI_VERSION);
+   if (ver) {
+   /* older dsi host, there is no register shift */
ver = FIELD(ver, DSI_VERSION_MAJOR);
if (ver <= MSM_DSI_VER_MAJOR_V2) {
/* old versions */
@@ -54,12 +61,17 @@ static int dsi_get_version(const void __iomem *base, u32 
*major, u32 *minor)
return -EINVAL;
}
} else {
+   /*
+* newer host, offset 0 has 6G_HW_VERSION, the rest of the
+* registers are shifted down, read DSI_VERSION again with
+* the shifted offset
+*/
ver = msm_readl(base + DSI_6G_REG_SHIFT + REG_DSI_VERSION);
ver = FIELD(ver, DSI_VERSION_MAJOR);
if (ver == MSM_DSI_VER_MAJOR_6G) {
/* 6G version */
*major = ver;
-   *minor = ver_6g;
+   *minor = msm_readl(base + REG_DSI_6G_HW_VERSION);
return 0;
} else {
return -EINVAL;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 03/12] drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

2015-12-01 Thread Archit Taneja
Add DSI PLL common clock framework clocks for 8960 PHY.

The PLL here is different from the ones found in B family msm chips. As
before, the DSI provides two clocks to the outside world. dsixpll and
dsixpllbyte (x = 1, 2). dsixpll is a regular clock divider, but
dsixpllbyte is modelled as a custom clock divider.

dsixpllbyte is the starting point of the PLL configuration. It is the
one that sets up the VCO clock rate. We need the VCO clock rate in the
form: F * byteclk, where F is a multiplication factor that varies on
the byte clock the DSI driver is trying to set. We use the custom
clk_ops for dsixpllbyte to ensure that the parent (VCO) is set at this
rate.

An additional divider (POSTDIV1) generates the bitclk. Since bit clock
can be derived from byteclock, we calculate it internally, and don't
expose it as a clock.

Cc: Stephen Boyd 
Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/Makefile|   1 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c   |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h   |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c | 533 
 4 files changed, 547 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 1888fd3..065ad41 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -68,6 +68,7 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += 
dsi/phy/dsi_phy_28nm_8960.o
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o
 endif

 obj-$(CONFIG_DRM_MSM)  += msm.o
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c 
b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
index 5104fc9..5cd438f 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
@@ -151,6 +151,9 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device 
*pdev,
case MSM_DSI_PHY_28NM_LP:
pll = msm_dsi_pll_28nm_init(pdev, type, id);
break;
+   case MSM_DSI_PHY_28NM_8960:
+   pll = msm_dsi_pll_28nm_8960_init(pdev, id);
+   break;
default:
pll = ERR_PTR(-ENXIO);
break;
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h 
b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
index 063caa2..80b6038 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
@@ -93,6 +93,16 @@ static inline struct msm_dsi_pll *msm_dsi_pll_28nm_init(
return ERR_PTR(-ENODEV);
 }
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+  int id);
+#else
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+  int id)
+{
+   return ERR_PTR(-ENODEV);
+}
+#endif

 #endif /* __DSI_PLL_H__ */

diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c 
b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
new file mode 100644
index 000..38c90e1
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. 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 "dsi_pll.h"
+#include "dsi.xml.h"
+
+/*
+ * DSI PLL 28nm (8960/A family) - clock diagram (eg: DSI1):
+ *
+ *
+ *+--+
+ *  dsi1vco_clk o-| DIV1 |---dsi1pllbit (not exposed as clock)
+ *  F * byte_clk| +--+
+ *  | bit clock divider (F / 8)
+ *  |
+ *  | +--+
+ *  o-| DIV2 |---dsi0pllbyte---o---> To byte RCG
+ *  | +--+ | (sets parent rate)
+ *  | byte clock divider (F)   |
+ *  |  |
+ *  |  o---> To esc RCG
+ *  |(doesn't set parent rate)
+ *  |
+ *  | +--+
+ *  o-| DIV3 |dsi0pll--o---> To dsi RCG
+ *+--+ | (sets parent rate)
+ *  dsi clock divider (F * magic)  |
+ * |
+ * 

[PATCH v3 02/12] drm/msm/dsi: Add support for 28nm PHY on 8960

2015-12-01 Thread Archit Taneja
DSI PHY on MSM8960 and APQ8064 is a 28nm PHY that's different from the
supported 28nm LP PHY found in newer chips.

Add support for the new PHY.

Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/Kconfig |   8 +
 drivers/gpu/drm/msm/Makefile|   1 +
 drivers/gpu/drm/msm/dsi/dsi.h   |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c   |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h   |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 195 
 6 files changed, 210 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c

diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 84d3ec9..215495c 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -54,3 +54,11 @@ config DRM_MSM_DSI_20NM_PHY
default y
help
  Choose this option if the 20nm DSI PHY is used on the platform.
+
+config DRM_MSM_DSI_28NM_8960_PHY
+   bool "Enable DSI 28nm 8960 PHY driver in MSM DRM"
+   depends on DRM_MSM_DSI
+   default y
+   help
+ Choose this option if the 28nm DSI PHY 8960 variant is used on the
+ platform.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 2224fdd..1888fd3 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \

 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o
 msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o

 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 5f5a373..8140e8b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -31,6 +31,7 @@ enum msm_dsi_phy_type {
MSM_DSI_PHY_28NM_HPM,
MSM_DSI_PHY_28NM_LP,
MSM_DSI_PHY_20NM,
+   MSM_DSI_PHY_28NM_8960,
MSM_DSI_PHY_MAX
 };

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index f1f955f..91a95fb 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -277,6 +277,10 @@ static const struct of_device_id dsi_phy_dt_match[] = {
{ .compatible = "qcom,dsi-phy-20nm",
  .data = _phy_20nm_cfgs },
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+   { .compatible = "qcom,dsi-phy-28nm-8960",
+ .data = _phy_28nm_8960_cfgs },
+#endif
{}
 };

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 0456b25..0d54ed0 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -43,6 +43,7 @@ struct msm_dsi_phy_cfg {
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;

 struct msm_dsi_dphy_timing {
u32 clk_pre;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
new file mode 100644
index 000..197b039
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. 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 "dsi_phy.h"
+#include "dsi.xml.h"
+
+static void dsi_28nm_dphy_set_timing(struct msm_dsi_phy *phy,
+   struct msm_dsi_dphy_timing *timing)
+{
+   void __iomem *base = phy->base;
+
+   dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_0,
+   DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(timing->clk_zero));
+   dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_1,
+   DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(timing->clk_trail));
+   dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_2,
+   
DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(timing->clk_prepare));
+   dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_3, 0x0);
+   dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_4,
+   DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(timing->hs_exit));
+   dsi_phy_write(base + REG_DSI_28nm_8960_PHY_TIMING_CTRL_5,
+   DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(timing->hs_zero));
+   dsi_phy_write(base + 

[PATCH v3 01/12] drm/msm/dsi: Don't get byte/pixel source clocks from DT

2015-12-01 Thread Archit Taneja
We retrieve the byte and pixel source clocks (RCG clocks) in the dsi
driver via DT. These are needed so that we can re-parent these source
clocks if we want to drive it using a different DSI PLL.

We shouldn't get these via DT because they aren't clocks that directly
serve as inputs to the dsi host.

Fortunately, there is a static parent-child link between the
byte_clk_src/pixel_clk_src and byte_clk/pixel_clk clocks. So, we can
retrieve the source clocks via clk_get_parent.

Do this instead of retrieving via DT.

Cc: Rob Herring 
Cc: Stephen Boyd 
Signed-off-by: Archit Taneja 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 4c49868..aec97c8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -356,20 +356,17 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
goto exit;
}

-   msm_host->byte_clk_src = devm_clk_get(dev, "byte_clk_src");
-   if (IS_ERR(msm_host->byte_clk_src)) {
-   ret = PTR_ERR(msm_host->byte_clk_src);
+   msm_host->byte_clk_src = clk_get_parent(msm_host->byte_clk);
+   if (!msm_host->byte_clk_src) {
+   ret = -ENODEV;
pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret);
-   msm_host->byte_clk_src = NULL;
goto exit;
}

-   msm_host->pixel_clk_src = devm_clk_get(dev, "pixel_clk_src");
-   if (IS_ERR(msm_host->pixel_clk_src)) {
-   ret = PTR_ERR(msm_host->pixel_clk_src);
+   msm_host->pixel_clk_src = clk_get_parent(msm_host->pixel_clk);
+   if (!msm_host->pixel_clk_src) {
+   ret = -ENODEV;
pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret);
-   msm_host->pixel_clk_src = NULL;
-   goto exit;
}

 exit:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v3 00/12] drm/msm/dsi: Add support for DSI on MSM8960/APQ8064

2015-12-01 Thread Archit Taneja
Add support for DSI on 8960/8064. The DSI IP used in these chips is an
older version(DSIv2) of what we have right now(DSI6G).

The bulk of the additions come thanks to a different PHY/PLL. The DSI
host in itself doesn't have too many changes.

Changes in v3:
- Add a patch that removes the need to provide source clocks (RCG clocks)
  via DT, as suggested by Rob Herring.
- Make cleaner dt-binding doc patches.

Changes in v2:
- Incorporated Stephen's comments for the DSI PLL patch.
- The dsi.xml.h and sfpb.xml.h changes were already picked up by Rob.
  Removed those patches.


Archit Taneja (12):
  drm/msm/dsi: Don't get byte/pixel source clocks from DT
  drm/msm/dsi: Add support for 28nm PHY on 8960
  drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY
  drm/msm/dsi: Use a better way to figure out DSI version
  drm/msm/dsi: Delay dsi_clk_init
  drm/msm/dsi: Parse bus clocks from a list
  drm/msm/dsi: Set up link clocks for DSIv2
  drm/msm/dsi: Add dsi_cfg for APQ8064
  drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2
  drm/msm/dsi: Enable MMSS SPFB port via syscon
  dt-bindings: msm/dsi: Fix the order in which clocks are listed
  dt-bindings: msm/dsi: Add DSIv2 documentation

 .../devicetree/bindings/display/msm/dsi.txt|  12 +-
 drivers/gpu/drm/msm/Kconfig|   8 +
 drivers/gpu/drm/msm/Makefile   |   2 +
 drivers/gpu/drm/msm/dsi/dsi.h  |   6 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  35 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |   4 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 508 ++--
 drivers/gpu/drm/msm/dsi/dsi_manager.c  |   6 +-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c  |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h  |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c| 195 
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c  |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h  |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c| 533 +
 14 files changed, 1178 insertions(+), 149 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation



[PATCH v2 02/10] drm/hisilicon: Add DT binding docs for hi6220 display subsystem

2015-12-01 Thread Xinliang Liu
On 1 December 2015 at 03:31, Rob Herring  wrote:

Hi Rob, thank you for review.

> On Sat, Nov 28, 2015 at 06:38:57PM +0800, Xinliang Liu wrote:
>> Add the device tree binding documentation for hi6220 SoC display subsystem.
>> drm master device binding doc.
>> ADE display controller binding doc.
>> DSI controller binding doc.
>>
>> Signed-off-by: Xinliang Liu 
>> Signed-off-by: Xinwei Kong 
>> Signed-off-by: Andy Green 
>> ---
>>  .../bindings/display/hisilicon/hisi-ade.txt| 42 ++
>>  .../bindings/display/hisilicon/hisi-drm.txt| 66 
>> ++
>>  .../bindings/display/hisilicon/hisi-dsi.txt| 53 +
>>  3 files changed, 161 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
>>  create mode 100644 
>> Documentation/devicetree/bindings/display/hisilicon/hisi-drm.txt
>>  create mode 100644 
>> Documentation/devicetree/bindings/display/hisilicon/hisi-dsi.txt
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt 
>> b/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
>> new file mode 100644
>> index 000..2777a2c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
>> @@ -0,0 +1,42 @@
>> +Device-Tree bindings for hisilicon ADE display controller driver
>> +
>> +ADE (Advanced Display Engine) is the display controller which grab image
>> +data from memory, do composition, do post image processing, generate RGB
>> +timing stream and transfer to DSI.
>> +
>> +Required properties:
>> +- compatible: value should be one of the following
>> + "hisilicon,hi6220-ade".
>> +- reg: physical base address and length of the controller's registers.
>> +- reg-names: name of physical base.
>> +- interrupt: the interrupt number.
>> +- clocks: the clocks needed.
>> +- clock-names: the name of the clocks.
>> +- ade_core_clk_rate: ADE core clock rate.
>> +- media_noc_clk_rate: media noc module clock rate.
>
> I think you can use assigned clock properties instead:
>
> assigned-clocks = <_ctrl HI6220_ADE_CORE>;
> assigned-clock-rates = <36000>;
>
> I'm not sure about what media_noc corresponds to in clocks list though.
>

will use assigned-clocks in v3.

>> +
>> +
>> +A example of HiKey board hi6220 SoC specific DT entry:
>> +Example:
>> +
>> + ade: ade at f410 {
>> + compatible = "hisilicon,hi6220-ade";
>> + reg = <0x0 0xf410 0x0 0x7800>,
>> +   <0x0 0xf441 0x0 0x1000>;
>> + reg-names = "ade_base",
>> + "media_base";
>> + interrupts = <0 115 4>;
>> +
>> + clocks = <_ctrl HI6220_ADE_CORE>,
>> +  <_ctrl HI6220_CODEC_JPEG>,
>> +  <_ctrl HI6220_ADE_PIX_SRC>,
>> +  <_ctrl HI6220_PLL_SYS>,
>> +  <_ctrl HI6220_PLL_SYS_MEDIA>;
>> + clock-names  = "clk_ade_core",
>> +"aclk_codec_jpeg_src",
>> +"clk_ade_pix",
>> +"clk_syspll_src",
>> +"clk_medpll_src";
>> + ade_core_clk_rate = <36000>;
>> + media_noc_clk_rate = <28800>;
>> + };
>> diff --git 
>> a/Documentation/devicetree/bindings/display/hisilicon/hisi-drm.txt 
>> b/Documentation/devicetree/bindings/display/hisilicon/hisi-drm.txt
>> new file mode 100644
>> index 000..fd93026
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/display/hisilicon/hisi-drm.txt
>> @@ -0,0 +1,66 @@
>> +Hisilicon DRM master device
>> +
>> +The Hisilicon DRM master device is a virtual device needed to list all
>> +the other display relevant nodes that comprise the display subsystem.
>
> There is no need for this in DT. The ADE can be the master device and
> of-graph can link to the DSI node. I have a similar example here[1]
> with a LCD controller block, DSI block and adv7533.

This sounds good, then I can remove the virtual master device.
I will refer to this example and make ADE as the master device in v3.

>
>> +Required properties:
>> +- compatible: Should be "hisilicon,-dss"
>> +- #address-cells: should be set to 2.
>> +- #size-cells: should be set to 2.
>> +- range: to allow probing of subdevices.
>> +
>> +Optional properties:
>> +- dma-coherent: Present if dma operations are coherent.
>
> Put this on the actually DMA master.

The DMA modules reside in the begining of each channel(or plane) of ADE.
So I need to put this dma-coherent property to ADE device node, right?

Thanks,
-xinliang

>
> Rob
>
> [1] https://git.linaro.org/people/rob.herring/linux.git pxa1928-drm-v2


[Bug 92309] Box drawn around cursor in multiple 3D games

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=92309

--- Comment #12 from acutiator at outlook.com ---
I'd like to start contacting these game developers to tell them about the
issue, but I'd like to be quite specific about what they need to do to fix it.
Can anyone provide some more insight on this so I know what to tell them?

-- 
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/20151201/6271d61c/attachment-0001.html>


[PATCH v2 10/10] drm/hisilicon: Add support for external bridge

2015-12-01 Thread Archit Taneja


On 11/28/2015 04:09 PM, Xinliang Liu wrote:
> Add support for external HDMI bridge.
>
> Signed-off-by: Xinliang Liu 
> Signed-off-by: Xinwei Kong 
> Signed-off-by: Andy Green 
> ---
>   drivers/gpu/drm/hisilicon/hisi_drm_dsi.c | 51 
> 
>   1 file changed, 51 insertions(+)
>
> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c 
> b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
> index 066e08d..9e056db 100644
> --- a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
> @@ -78,6 +78,7 @@ struct dsi_hw_ctx {
>
>   struct hisi_dsi {
>   struct drm_encoder encoder;
> + struct drm_bridge *bridge;
>   struct mipi_dsi_host host;
>   struct drm_display_mode cur_mode;
>   struct dsi_hw_ctx *ctx;
> @@ -671,6 +672,25 @@ static int dsi_host_init(struct device *dev, struct 
> hisi_dsi *dsi)
>   return 0;
>   }
>
> +static int dsi_bridge_init(struct drm_device *dev, struct hisi_dsi *dsi)
> +{
> + struct drm_encoder *encoder = >encoder;
> + struct drm_bridge *bridge = dsi->bridge;
> + int ret;
> +
> + /* associate the bridge to dsi encoder */
> + encoder->bridge = bridge;
> + bridge->encoder = encoder;
> +
> + ret = drm_bridge_attach(dev, bridge);
> + if (ret) {
> + DRM_ERROR("failed to attach exteranl bridge\n");

s/exteranl/external

> + return ret;
> + }
> +
> + return 0;
> +}
> +
>   static int dsi_bind(struct device *dev, struct device *master, void *data)
>   {
>   struct dsi_data *ddata = dev_get_drvdata(dev);
> @@ -686,6 +706,10 @@ static int dsi_bind(struct device *dev, struct device 
> *master, void *data)
>   if (ret)
>   return ret;
>
> + ret = dsi_bridge_init(drm_dev, dsi);
> + if (ret)
> + return ret;
> +
>   return 0;
>   }
>
> @@ -702,8 +726,35 @@ static const struct component_ops dsi_ops = {
>   static int dsi_parse_dt(struct platform_device *pdev, struct hisi_dsi *dsi)
>   {
>   struct dsi_hw_ctx *ctx = dsi->ctx;
> + struct device_node *np = pdev->dev.of_node;
> + struct device_node *endpoint, *bridge_node;
> + struct drm_bridge *bridge;
>   struct resource *res;
>
> + /*
> +  * Get the endpoint node. In our case, dsi has one output port
> +  * to which the external HDMI bridge is connected.
> +  */
> + endpoint = of_graph_get_next_endpoint(np, NULL);
> + if (!endpoint) {
> + DRM_ERROR("no valid endpoint node\n");
> + return -ENODEV;
> + }
> + of_node_put(endpoint);
> +
> + bridge_node = of_graph_get_remote_port_parent(endpoint);
> + if (!bridge_node) {
> + DRM_ERROR("no valid bridge node\n");
> + return -ENODEV;
> + }
> + of_node_put(bridge_node);
> +
> + bridge = of_drm_find_bridge(bridge_node);
> + if (!bridge) {
> + DRM_INFO("wait for external HDMI bridge driver.\n");
> + return -EPROBE_DEFER;
> + }
> + dsi->bridge = bridge;

This could be left for later, but it would be better if the dsi driver
registers even if the bridge driver module isn't inserted yet, or
happens much later in boot.

We could achieve this by trying to attach the bridge (done in 
dsi_bridge_init) in the dsi_host_attach callback instead of having it
in dsi_bind.

Thanks,
Archit

>
>   ctx->dsi_cfg_clk = devm_clk_get(>dev, "pclk_dsi");
>   if (IS_ERR(ctx->dsi_cfg_clk)) {
>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum, hosted by The Linux Foundation


[PATCH v2 08/10] drm/hisilicon: Add dsi encoder driver

2015-12-01 Thread Archit Taneja


On 11/28/2015 04:09 PM, Xinliang Liu wrote:
> Add dsi encoder driver for hi6220 SoC.
>
> Signed-off-by: Xinliang Liu 
> Signed-off-by: Xinwei Kong 
> Signed-off-by: Andy Green 
> ---
>   drivers/gpu/drm/hisilicon/Kconfig|   1 +
>   drivers/gpu/drm/hisilicon/Makefile   |   3 +-
>   drivers/gpu/drm/hisilicon/hisi_drm_dsi.c | 728 
> +++
>   drivers/gpu/drm/hisilicon/hisi_dsi_reg.h |  89 
>   4 files changed, 820 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
>   create mode 100644 drivers/gpu/drm/hisilicon/hisi_dsi_reg.h
>
> diff --git a/drivers/gpu/drm/hisilicon/Kconfig 
> b/drivers/gpu/drm/hisilicon/Kconfig
> index 70aa8d1..f1c33c2 100644
> --- a/drivers/gpu/drm/hisilicon/Kconfig
> +++ b/drivers/gpu/drm/hisilicon/Kconfig
> @@ -4,6 +4,7 @@ config DRM_HISI
>   select DRM_KMS_HELPER
>   select DRM_GEM_CMA_HELPER
>   select DRM_KMS_CMA_HELPER
> + select DRM_MIPI_DSI
>   help
> Choose this option if you have a hisilicon chipsets(hi6220).
> If M is selected the module will be called hisi-drm.
> diff --git a/drivers/gpu/drm/hisilicon/Makefile 
> b/drivers/gpu/drm/hisilicon/Makefile
> index 3433c8b..5083c1f 100644
> --- a/drivers/gpu/drm/hisilicon/Makefile
> +++ b/drivers/gpu/drm/hisilicon/Makefile
> @@ -1,4 +1,5 @@
>   hisi-drm-y := hisi_drm_drv.o \
> -   hisi_drm_ade.o
> +   hisi_drm_ade.o \
> +   hisi_drm_dsi.o
>
>   obj-$(CONFIG_DRM_HISI)  += hisi-drm.o
> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c 
> b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
> new file mode 100644
> index 000..7a6cf66
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_dsi.c
> @@ -0,0 +1,728 @@
> +/*
> + * Hisilicon hi6220 SoC dsi driver
> + *
> + * Copyright (c) 2014-2015 Hisilicon Limited.
> + * Author:
> + *   Xinliang Liu 
> + *   Xinliang Liu 
> + *   Xinwei Kong 
> + *
> + * 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.
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "hisi_dsi_reg.h"
> +
> +#define MAX_TX_ESC_CLK  (10)
> +#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
> +#define DEFAULT_MIPI_CLK_RATE   1920
> +#define DEFAULT_MIPI_CLK_PERIOD_PS (10 / (DEFAULT_MIPI_CLK_RATE / 
> 1000))
> +#define R(x) ((u32)u64)(x) * (u64)1000 * (u64)mode->clock) / \
> +   phy->lane_byte_clk_kHz)))
> +
> +#define encoder_to_dsi(encoder) \
> + container_of(encoder, struct hisi_dsi, encoder)
> +#define host_to_dsi(host) \
> + container_of(host, struct hisi_dsi, host)
> +
> +struct mipi_phy_register {
> + u32 clk_t_lpx;
> + u32 clk_t_hs_prepare;
> + u32 clk_t_hs_zero;
> + u32 clk_t_hs_trial;
> + u32 clk_t_wakeup;
> + u32 data_t_lpx;
> + u32 data_t_hs_prepare;
> + u32 data_t_hs_zero;
> + u32 data_t_hs_trial;
> + u32 data_t_ta_go;
> + u32 data_t_ta_get;
> + u32 data_t_wakeup;
> + u32 hstx_ckg_sel;
> + u32 pll_fbd_div5f;
> + u32 pll_fbd_div1f;
> + u32 pll_fbd_2p;
> + u32 pll_enbwt;
> + u32 pll_fbd_p;
> + u32 pll_fbd_s;
> + u32 pll_pre_div1p;
> + u32 pll_pre_p;
> + u32 pll_vco_750M;
> + u32 pll_lpf_rs;
> + u32 pll_lpf_cs;
> + u32 clklp2hs_time;
> + u32 clkhs2lp_time;
> + u32 lp2hs_time;
> + u32 hs2lp_time;
> + u32 clk_to_data_delay;
> + u32 data_to_clk_delay;
> + u32 lane_byte_clk_kHz;
> + u32 clk_division;
> +};
> +
> +struct dsi_hw_ctx {
> + void __iomem *base;
> + struct clk *dsi_cfg_clk;
> +};
> +
> +struct hisi_dsi {
> + struct drm_encoder encoder;
> + struct drm_display_mode cur_mode;
> + struct dsi_hw_ctx *ctx;
> + struct mipi_phy_register phy;
> +
> + u32 lanes;
> + enum mipi_dsi_pixel_format format;
> + unsigned long mode_flags;
> + bool enable;
> +};
> +
> +struct dsi_data {
> + struct hisi_dsi dsi;
> + struct dsi_hw_ctx ctx;
> +};
> +
> +struct dsi_phy_seq_info {
> + u32 min_range_kHz;
> + u32 max_range_kHz;
> + u32 pll_vco_750M;
> + u32 hstx_ckg_sel;
> +};
> +
> +static const struct dsi_phy_seq_info dphy_seq_info[] = {
> + {   46000,62000,   1,7 },
> + {   62000,93000,   0,7 },
> + {   93000,   125000,   1,6 },
> + {  125000,   187000,   0,6 },
> + {  187000,   25,   1,5 },
> + {  25,   375000,   0,5 },
> + {  375000,   50,   1,4 },
> + {  50,   75,   0,4 },
> + {  75,  100,   1,0 },
> + { 100,  150,   0,0 }
> +};
> +
> +static void set_dsi_phy_rate_equal_or_faster(u32 phy_freq_kHz,
> +  struct mipi_phy_register *phy)
> +{
> + u32 

[PATCH v2 06/10] drm/hisilicon: Add vblank feature

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 06:34:43PM +0800, Xinliang Liu wrote:
> On 1 December 2015 at 15:13, Daniel Vetter  wrote:
> > On Tue, Dec 01, 2015 at 11:16:19AM +0800, Xinliang Liu wrote:
> >> On 30 November 2015 at 15:54, Daniel Vetter  wrote:
> >> > On Sat, Nov 28, 2015 at 06:39:01PM +0800, Xinliang Liu wrote:
> >> >> Add vblank handle for ADE.
> >> >>
> >> >> Signed-off-by: Xinliang Liu 
> >> >> Signed-off-by: Xinwei Kong 
> >> >> Signed-off-by: Andy Green 
> >> >> ---
> >> >>  drivers/gpu/drm/hisilicon/hisi_drm_ade.c | 78 
> >> >> 
> >> >>  drivers/gpu/drm/hisilicon/hisi_drm_ade.h | 16 +++
> >> >>  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 19 +++-
> >> >>  3 files changed, 112 insertions(+), 1 deletion(-)
> >> >>  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_ade.h
> >> >>
> >> >> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c 
> >> >> b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
> >> >> index b0976c3..acb11e7 100644
> >> >> --- a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
> >> >> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
> >> >> @@ -267,7 +267,79 @@ static void ade_power_down(struct ade_hw_ctx *ctx)
> >> >>   ctx->power_on = false;
> >> >>  }
> >> >>
> >> >> +static struct drm_crtc *hisi_get_crtc_from_index(struct drm_device 
> >> >> *dev,
> >> >> +  unsigned int index)
> >> >
> >> > Ugly that you had to add this, but unfortunately necessary :( Fixing up
> >> > the drm vblank hooks so that they deal with struct drm_crtc directly is
> >> > somewhere on my todo. But drm_irq.c is still a bit a mess, so this is 
> >> > some
> >> > ways off still.
> >> >
> >> > What might be possible as a follow-up cleanup though is to add
> >> > vblank_enable and vblank_disable functions to struct
> >> > drm_crtc_helper_funcs. And then provide this code here to map from int
> >> > index to struct drm_crtc * as helpers in a new drm_vblank_helper.c file.
> >> > That might be a good intermediate step.
> >>
> >> I would like to have a try to make this intermediate step patch and
> >> send out for review soon.
> >
> > Awesome, looking forward to reviewing it. If you have questions about
> > details fastest to ping me on irc (nick: danvet, #dri-devel on
> > freenode.net).
> 
> Great!  What't your time zone. So that I can ping you in right time.

Europe, GMT+1.

Cheers, Daniel

> 
> Thanks,
> -xinliang
> 
> >
> > Cheers, Daniel
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > http://blog.ffwll.ch

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


[PATCH v2 03/10] drm/hisilicon: Add hisilicon DRM master driver

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 06:52:20PM +0800, Xinliang Liu wrote:
> On 30 November 2015 at 15:46, Daniel Vetter  wrote:
> > On Sat, Nov 28, 2015 at 03:25:35PM +, Emil Velikov wrote:
> >> Hi Xinliang,
> >>
> >> On 28 November 2015 at 10:38, Xinliang Liu  
> >> wrote:
> >> > Add DRM master driver for hi6220 SoC which used in HiKey board.
> >> > Add dumb buffer feature.
> >> > Add prime dmabuf feature.
> >> >
> >> > Signed-off-by: Xinliang Liu 
> >> > Signed-off-by: Xinwei Kong 
> >> > Signed-off-by: Andy Green 
> >> Your s-o-b should be the bottom of the list. There was a presentation
> >> (ages ago) from Greg KH, who nicely described the order as a "chain of
> >> command" or "guilt path". Looks like the rest of the series could use
> >> this tweak.
> >>
> >> > ---
> >> >  drivers/gpu/drm/Kconfig  |   2 +
> >> >  drivers/gpu/drm/Makefile |   1 +
> >> >  drivers/gpu/drm/hisilicon/Kconfig|   9 ++
> >> >  drivers/gpu/drm/hisilicon/Makefile   |   3 +
> >> >  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 214 
> >> > +++
> >> >  5 files changed, 229 insertions(+)
> >> >  create mode 100644 drivers/gpu/drm/hisilicon/Kconfig
> >> >  create mode 100644 drivers/gpu/drm/hisilicon/Makefile
> >> >  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_drv.c
> >> >
> >> > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
> >> > index 8773fad..038aae8 100644
> >> > --- a/drivers/gpu/drm/Kconfig
> >> > +++ b/drivers/gpu/drm/Kconfig
> >> > @@ -274,3 +274,5 @@ source "drivers/gpu/drm/amd/amdkfd/Kconfig"
> >> >  source "drivers/gpu/drm/imx/Kconfig"
> >> >
> >> >  source "drivers/gpu/drm/vc4/Kconfig"
> >> > +
> >> > +source "drivers/gpu/drm/hisilicon/Kconfig"
> >> I could swear that we can a patch that sorts these alphabetically,
> >> although it doesn't seem to have made it upstream yet :-(
> >>
> >> > --- /dev/null
> >> > +++ b/drivers/gpu/drm/hisilicon/hisi_drm_drv.c
> >>
> >> > +static int hisi_drm_load(struct drm_device *dev, unsigned long flags)
> >> > +{
> >> The use of .load (and .unload?) callbacks is not recommended. Take a
> >> look at Laurent Pinchart's patch [1] about the whys and hows on the
> >> topic
> >>
> >> > +static struct dma_buf *hisi_gem_prime_export(struct drm_device *dev,
> >> > +struct drm_gem_object *obj,
> >> > +int flags)
> >> > +{
> >> > +   /* we want to be able to write in mmapped buffer */
> >> > +   flags |= O_RDWR;
> >> Erm... something feels fishy here. Out of the existing 15 drivers
> >> setting up the prime callbacks only one (sti) does a similar thing. So
> >> either everyone else is missing something obvious or hisilicon and sti
> >> can rework their inner working to remove this (dare I say it) hack.
> >
> > Mmap on drm dma-bufs doesn't work, and fairly intentionally. There's been
> > some rfc patch series to address this:
> >
> > http://lists.freedesktop.org/archives/dri-devel/2015-August/089263.html
> >
> > Unfortunately it seems stuck with getting the userspace piece in shape.
> > Might be best to ping Tiago for an update.
> >
> > Meanwhile please don't do this in drivers ;-)
> 
> It seems Tiago's patch is the best way to fix mmap issue.
> I'll ping him, hope he will repsonse.
> 
> >
> >> > +static int hisi_gem_cma_dumb_create(struct drm_file *file,
> >> > +   struct drm_device *dev,
> >> > +   struct drm_mode_create_dumb *args)
> >> > +{
> >> > +   int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
> >> > +
> >> > +   /* mali gpu need pitch 8 bytes alignment for 32bpp */
> >> > +   args->pitch = roundup(min_pitch, 8);
> >> > +
> >> I'm not sure you want this kind of dependency of an out of tree driver
> >> upstream. If this is some limitation on the display engine so be it,
> >> but tailoring things for an external module seems like a very bad
> >> idea.
> >
> > Yup, nacked. dumb_create is for dumb buffers, not rendering. Mali needs to
> > go upstream to fix this ...
> 
> Oh! I have use dumb buffers for rendering now. What does dumb buffer
> mean and what's dumb buffers  for?
> For rendering buffer requirements how should I do then?

Dumb buffers are really just a very thin in-kernel abstraction for boot
splash screens. As soon as you have real userspace (surfaceflinger, gl es,
whatever) the idea is that an allocator in userspace (like gralloc, gbm or
similar) figures out the allocation constraints and where to allocate
things exactly. Maybe that includes allocating from dumb buffers with
special knowledge (by increasing x/y perhaps), but most likely that means
you either allocate from your proprietary/out-of-tree gpu render driver or
some other central allocator like ion.

Anyway, adding hacks to the dumb buffer which are meant to facilite
sharing with other devices, or using it for anything else than a boot
splash is a no-go. 

[Bug 93147] [regression bisected] Stuttering in games caused by commit 4dfd6486 "drm: Use vblank timestamps to guesstimate how many vblanks were missed"

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=93147

--- Comment #9 from Mario Kleiner  ---
(In reply to Michel Dänzer from comment #7)
> Mario, can you submit your fix(es) for inclusion?

Still on it. The proper patch for radeon-kms will hopefully be finished and
tested within a day or so. But ideally i'd need some feedback on the line
buffer sizes/partitions/watermarks - see my last e-mail on that. Otherwise i'll
have to use very conservative guesstimates for the fudge constant in the
current patch to be on the safe side.

amdgpu-kms will have the same problem and solution, but i haven't looked into
how to hook that up, with the difference in how the display engine code is
hooked up.

thanks,
-mario

-- 
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/20151201/ded70c29/attachment.html>


[Bug 76490] Hang during boot when DPM is on (R9 270X)

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=76490

--- Comment #75 from Maxim Sheviakov  ---
(In reply to Maxim Sheviakov from comment #74)
> (In reply to Maxim Sheviakov from comment #73)
> > (In reply to Alex Deucher from comment #72)
> > > (In reply to Maxim Sheviakov from comment #71)
> > > > Hmm, nice point. By the way, is the MCLK kinda divided by four? So, if
> > > > Memory Clock is 5600MHz, I'll have to do 5600/4*1 to get the correct
> > > > value? It's like, 12 value = 1.2GHz*4 = Original frequency = 
> > > > 4800MHz,
> > > > right? If that's it, I'll fix my quirk (AGAIN, LOL) and try using 
> > > > 970MHz and
> > > > 5600MHz written as needed, 'cause my GPU is MSI R7 370 Armor 2X, and 
> > > > looks
> > > > like values in quirk are *kinda* low for it.
> > > 
> > > The mclk values are the actual mclk values.  GDDR5 is quad pumped so you 
> > > get
> > > 4x effective data rate per clock.  That might be what you are thinking of.
> > 
> > Looks like I get it now. Today I'll try to play with those values and
> > experiment with MCLK values, maybe with GPU clock too; if it's good, I will
> > let everyone know.
> 
> So right now I'm building a test kernel based on Linux Zen 4.3. Changed
> values in my line: from "{... 0, 12}," to "{... 97000, 14}", so that
> GPU clock is 970MHz and Memory clock is 1.4GHz aka 5.6GHz. Will let you all
> know if I succeed in that.

Nope, the system is unusable after Plymouth tries to start. Even with 1.3GHz.
Looks like it's a dpm error, as on Windows the card is really stable. with
those values, even if it's a bit overclocked.

-- 
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/20151201/69cc881c/attachment.html>


[PATCH] drm: Fix an unwanted master inheritance

2015-12-01 Thread Thomas Hellstrom
On 12/01/2015 11:57 AM, Emil Velikov wrote:
> Hi Thomas,
>
> Something doesn't feel quite right, please read on.
>
> On 30 November 2015 at 12:44, Thomas Hellstrom  
> wrote:
>> A client calling drmSetMaster() using a file descriptor that was opened
>> when another client was master would inherit the latter client's master
>> object and all it's authenticated clients.
>>
>> This is unwanted behaviour, and when this happens, instead allocate a
>> brand new master object for the client calling drmSetMaster().
>>
>> Signed-off-by: Thomas Hellstrom 
>> ---
>>  drivers/gpu/drm/drm_drv.c  | 12 +++
>>  drivers/gpu/drm/drm_fops.c | 80 
>> ++
>>  include/drm/drmP.h |  6 
>>  3 files changed, 70 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
>> index 9362609..1f072ba 100644
>> --- a/drivers/gpu/drm/drm_drv.c
>> +++ b/drivers/gpu/drm/drm_drv.c
>> @@ -160,6 +160,18 @@ int drm_setmaster_ioctl(struct drm_device *dev, void 
>> *data,
>> goto out_unlock;
>> }
>>
>> +   if (!file_priv->allowed_master) {
>> +   struct drm_master *saved_master = file_priv->master;
>> +
>> +   ret = drm_new_set_master(dev, file_priv);
>> +   if (ret)
>> +   file_priv->master = saved_master;
> Imho this shouldn'e belong here but in drm_new_set_master() - i.e. it
> should unwind things on error. Similarly, although we restore the old
> drm_master (below), we still have is_master, allowed_master and
> authenticated set. Thus one can reuse the elevated credentials (is
> this the right terminology?) despite that the ioctl has failed.
>
>> +   else
>> +   drm_master_put(_master);
>> +
>> +   goto out_unlock;
>> +   }
>> +
>> file_priv->minor->master = drm_master_get(file_priv->master);
>> file_priv->is_master = 1;
>> if (dev->driver->master_set) {
>> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
>> index c59ce4d..4b5c11c 100644
>> --- a/drivers/gpu/drm/drm_fops.c
>> +++ b/drivers/gpu/drm/drm_fops.c
>> @@ -126,6 +126,56 @@ static int drm_cpu_valid(void)
>>  }
>>
>>  /**
>> + * drm_new_set_master - Allocate a new master object and become master for 
>> the
>> + * associated master realm.
>> + *
>> + * @dev: The associated device.
>> + * @fpriv: File private identifying the client.
>> + *
>> + * This function must be called with dev::struct_mutex held. Returns 
>> negative
>> + * error code on failure, zero on success.
>> + */
>> +int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
>> +{
>> +   int ret;
>> +
>> +   lockdep_assert_held_once(>master_mutex);
>> +   /* create a new master */
>> +   fpriv->minor->master = drm_master_create(fpriv->minor);
>> +   if (!fpriv->minor->master)
>> +   return -ENOMEM;
>> +
>> +   fpriv->is_master = 1;
>> +   fpriv->allowed_master = 1;
>> +
>> +   /* take another reference for the copy in the local file priv */
>> +   fpriv->master = drm_master_get(fpriv->minor->master);
>> +
>> +   fpriv->authenticated = 1;
>> +
>> +   if (dev->driver->master_create) {
>> +   ret = dev->driver->master_create(dev, fpriv->master);
>> +   if (ret) {
>> +   /* drop both references if this fails */
>> +   drm_master_put(>minor->master);
>> +   drm_master_put(>master);
>> +   return ret;
>> +   }
>> +   }
>> +   if (dev->driver->master_set) {
>> +   ret = dev->driver->master_set(dev, fpriv, true);
>> +   if (ret) {
> Afaics both of these callbacks are available from legacy(UMS) drivers
> aren't they ? With the radeon UMS removal patches in the works, this
> leaves vmwgfx.
>
> Either way, perhaps we should set is_master, allowed_master and
> authenticated after these two ? Or alternatively restore the original
> values on error.
>
> Did I miss something or the above sounds about right ?
It does. I'll address this and resend.

Thanks for reviewing!

/Thomas



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



[Bug 93147] [regression bisected] Stuttering in games caused by commit 4dfd6486 "drm: Use vblank timestamps to guesstimate how many vblanks were missed"

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=93147

--- Comment #8 from Dave Witbrodt  ---
(In reply to Michel Dänzer from comment #6)
> (In reply to Ville Syrjala from comment #5)
> > I'm guessing this is the stuff Mario was trying to fix.
> 
> You're right, the patch from
> http://lists.freedesktop.org/archives/dri-devel/2015-November/095679.html
> fixes it for me.

Applying the patch in question to my local 4.3 + DRM 4.4 kernel (with no
reverts) makes the symptoms go away for me also.

-- 
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/20151201/e35f6c40/attachment-0001.html>


[Bug 76490] Hang during boot when DPM is on (R9 270X)

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=76490

--- Comment #74 from Maxim Sheviakov  ---
(In reply to Maxim Sheviakov from comment #73)
> (In reply to Alex Deucher from comment #72)
> > (In reply to Maxim Sheviakov from comment #71)
> > > Hmm, nice point. By the way, is the MCLK kinda divided by four? So, if
> > > Memory Clock is 5600MHz, I'll have to do 5600/4*1 to get the correct
> > > value? It's like, 12 value = 1.2GHz*4 = Original frequency = 4800MHz,
> > > right? If that's it, I'll fix my quirk (AGAIN, LOL) and try using 970MHz 
> > > and
> > > 5600MHz written as needed, 'cause my GPU is MSI R7 370 Armor 2X, and looks
> > > like values in quirk are *kinda* low for it.
> > 
> > The mclk values are the actual mclk values.  GDDR5 is quad pumped so you get
> > 4x effective data rate per clock.  That might be what you are thinking of.
> 
> Looks like I get it now. Today I'll try to play with those values and
> experiment with MCLK values, maybe with GPU clock too; if it's good, I will
> let everyone know.

So right now I'm building a test kernel based on Linux Zen 4.3. Changed values
in my line: from "{... 0, 12}," to "{... 97000, 14}", so that GPU clock
is 970MHz and Memory clock is 1.4GHz aka 5.6GHz. Will let you all know if I
succeed in that.

-- 
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/20151201/76731cb1/attachment.html>


[PATCH 9/9] drm/vc4: Add an interface for capturing the GPU state after a hang.

2015-12-01 Thread Eric Anholt
This can be parsed with vc4-gpu-tools tools for trying to figure out
what was going on.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/vc4_drv.c |   2 +
 drivers/gpu/drm/vc4/vc4_drv.h |   4 +
 drivers/gpu/drm/vc4/vc4_gem.c | 185 ++
 include/uapi/drm/vc4_drm.h|  45 ++
 4 files changed, 236 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 2cfee59..97226b6 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -80,6 +80,8 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
+   DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
+ DRM_ROOT_ONLY),
 };

 static struct drm_driver vc4_drm_driver = {
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 9a8ee23..cd3e243 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -19,6 +19,8 @@ struct vc4_dev {

struct drm_fbdev_cma *fbdev;

+   struct vc4_hang_state *hang_state;
+
/* The kernel-space BO cache.  Tracks buffers that have been
 * unreferenced by all other users (refcounts of 0!) but not
 * yet freed, so we can do cheap allocations.
@@ -369,6 +371,8 @@ int vc4_create_shader_bo_ioctl(struct drm_device *dev, void 
*data,
   struct drm_file *file_priv);
 int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
  struct drm_file *file_priv);
+int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
+struct drm_file *file_priv);
 int vc4_mmap(struct file *filp, struct vm_area_struct *vma);
 int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
 void *vc4_prime_vmap(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index a62ca68..fb0b92d 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -40,6 +40,186 @@ vc4_queue_hangcheck(struct drm_device *dev)
  round_jiffies_up(jiffies + msecs_to_jiffies(100)));
 }

+struct vc4_hang_state {
+   struct drm_vc4_get_hang_state user_state;
+
+   u32 bo_count;
+   struct drm_gem_object **bo;
+};
+
+static void
+vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state)
+{
+   unsigned int i;
+
+   mutex_lock(>struct_mutex);
+   for (i = 0; i < state->user_state.bo_count; i++)
+   drm_gem_object_unreference(state->bo[i]);
+   mutex_unlock(>struct_mutex);
+
+   kfree(state);
+}
+
+int
+vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
+struct drm_file *file_priv)
+{
+   struct drm_vc4_get_hang_state *get_state = data;
+   struct drm_vc4_get_hang_state_bo *bo_state;
+   struct vc4_hang_state *kernel_state;
+   struct drm_vc4_get_hang_state *state;
+   struct vc4_dev *vc4 = to_vc4_dev(dev);
+   unsigned long irqflags;
+   u32 i;
+   int ret;
+
+   spin_lock_irqsave(>job_lock, irqflags);
+   kernel_state = vc4->hang_state;
+   if (!kernel_state) {
+   spin_unlock_irqrestore(>job_lock, irqflags);
+   return -ENOENT;
+   }
+   state = _state->user_state;
+
+   /* If the user's array isn't big enough, just return the
+* required array size.
+*/
+   if (get_state->bo_count < state->bo_count) {
+   get_state->bo_count = state->bo_count;
+   spin_unlock_irqrestore(>job_lock, irqflags);
+   return 0;
+   }
+
+   vc4->hang_state = NULL;
+   spin_unlock_irqrestore(>job_lock, irqflags);
+
+   /* Save the user's BO pointer, so we don't stomp it with the memcpy. */
+   state->bo = get_state->bo;
+   memcpy(get_state, state, sizeof(*state));
+
+   bo_state = kcalloc(state->bo_count, sizeof(*bo_state), GFP_KERNEL);
+   if (!bo_state) {
+   ret = -ENOMEM;
+   goto err_free;
+   }
+
+   for (i = 0; i < state->bo_count; i++) {
+   struct vc4_bo *vc4_bo = to_vc4_bo(kernel_state->bo[i]);
+   u32 handle;
+
+   ret = drm_gem_handle_create(file_priv, kernel_state->bo[i],
+   );
+
+   if (ret) {
+   state->bo_count = i - 1;
+   goto err;
+   }
+   bo_state[i].handle = handle;
+   bo_state[i].paddr = vc4_bo->base.paddr;
+   bo_state[i].size = vc4_bo->base.base.size;
+   }
+
+   ret = copy_to_user((void __user *)(uintptr_t)get_state->bo,
+  bo_state,
+  state->bo_count 

[PATCH 8/9] drm/vc4: Add support for async pageflips.

2015-12-01 Thread Eric Anholt
An async pageflip stores the modeset to be done and executes it once
the BOs are ready to be displayed.  This gets us about 3x performance
in full screen rendering with pageflipping.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/vc4_crtc.c  |  99 +-
 drivers/gpu/drm/vc4/vc4_drv.h   |  16 +
 drivers/gpu/drm/vc4/vc4_gem.c   |  40 +++
 drivers/gpu/drm/vc4/vc4_kms.c   | 149 +++-
 drivers/gpu/drm/vc4/vc4_plane.c |  40 +++
 5 files changed, 342 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7a9f476..a319332 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -35,6 +35,7 @@
 #include "drm_atomic_helper.h"
 #include "drm_crtc_helper.h"
 #include "linux/clk.h"
+#include "drm_fb_cma_helper.h"
 #include "linux/component.h"
 #include "linux/of_device.h"
 #include "vc4_drv.h"
@@ -475,10 +476,106 @@ static irqreturn_t vc4_crtc_irq_handler(int irq, void 
*data)
return ret;
 }

+struct vc4_async_flip_state {
+   struct drm_crtc *crtc;
+   struct drm_framebuffer *fb;
+   struct drm_pending_vblank_event *event;
+
+   struct vc4_seqno_cb cb;
+};
+
+/* Called when the V3D execution for the BO being flipped to is done, so that
+ * we can actually update the plane's address to point to it.
+ */
+static void
+vc4_async_page_flip_complete(struct vc4_seqno_cb *cb)
+{
+   struct vc4_async_flip_state *flip_state =
+   container_of(cb, struct vc4_async_flip_state, cb);
+   struct drm_crtc *crtc = flip_state->crtc;
+   struct drm_device *dev = crtc->dev;
+   struct vc4_dev *vc4 = to_vc4_dev(dev);
+   struct drm_plane *plane = crtc->primary;
+
+   vc4_plane_async_set_fb(plane, flip_state->fb);
+   if (flip_state->event) {
+   unsigned long flags;
+
+   spin_lock_irqsave(>event_lock, flags);
+   drm_crtc_send_vblank_event(crtc, flip_state->event);
+   spin_unlock_irqrestore(>event_lock, flags);
+   }
+
+   drm_framebuffer_unreference(flip_state->fb);
+   kfree(flip_state);
+
+   up(>async_modeset);
+}
+
+/* Implements async (non-vblank-synced) page flips.
+ *
+ * The page flip ioctl needs to return immediately, so we grab the
+ * modeset semaphore on the pipe, and queue the address update for
+ * when V3D is done with the BO being flipped to.
+ */
+static int vc4_async_page_flip(struct drm_crtc *crtc,
+  struct drm_framebuffer *fb,
+  struct drm_pending_vblank_event *event,
+  uint32_t flags)
+{
+   struct drm_device *dev = crtc->dev;
+   struct vc4_dev *vc4 = to_vc4_dev(dev);
+   struct drm_plane *plane = crtc->primary;
+   int ret = 0;
+   struct vc4_async_flip_state *flip_state;
+   struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0);
+   struct vc4_bo *bo = to_vc4_bo(_bo->base);
+
+   flip_state = kzalloc(sizeof(*flip_state), GFP_KERNEL);
+   if (!flip_state)
+   return -ENOMEM;
+
+   drm_framebuffer_reference(fb);
+   flip_state->fb = fb;
+   flip_state->crtc = crtc;
+   flip_state->event = event;
+
+   /* Make sure all other async modesetes have landed. */
+   ret = down_interruptible(>async_modeset);
+   if (ret) {
+   kfree(flip_state);
+   return ret;
+   }
+
+   /* Immediately update the plane's legacy fb pointer, so that later
+* modeset prep sees the state that will be present when the semaphore
+* is released.
+*/
+   drm_atomic_set_fb_for_plane(plane->state, fb);
+   plane->fb = fb;
+
+   vc4_queue_seqno_cb(dev, _state->cb, bo->seqno,
+  vc4_async_page_flip_complete);
+
+   /* Driver takes ownership of state on successful async commit. */
+   return 0;
+}
+
+static int vc4_page_flip(struct drm_crtc *crtc,
+struct drm_framebuffer *fb,
+struct drm_pending_vblank_event *event,
+uint32_t flags)
+{
+   if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
+   return vc4_async_page_flip(crtc, fb, event, flags);
+   else
+   return drm_atomic_helper_page_flip(crtc, fb, event, flags);
+}
+
 static const struct drm_crtc_funcs vc4_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = vc4_crtc_destroy,
-   .page_flip = drm_atomic_helper_page_flip,
+   .page_flip = vc4_page_flip,
.set_property = NULL,
.cursor_set = NULL, /* handled by drm_mode_cursor_universal */
.cursor_move = NULL, /* handled by drm_mode_cursor_universal */
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index a3dbfee..9a8ee23 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ 

[PATCH 7/9] drm/vc4: Add support for drawing 3D frames.

2015-12-01 Thread Eric Anholt
The user submission is basically a pointer to a command list and a
pointer to uniforms.  We copy those in to the kernel, validate and
relocate them, and store the result in a GPU BO which we queue for
execution.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/Makefile   |   7 +
 drivers/gpu/drm/vc4/vc4_drv.c  |  15 +-
 drivers/gpu/drm/vc4/vc4_drv.h  | 192 +++
 drivers/gpu/drm/vc4/vc4_gem.c  | 640 ++
 drivers/gpu/drm/vc4/vc4_irq.c  | 210 
 drivers/gpu/drm/vc4/vc4_packet.h   | 399 ++
 drivers/gpu/drm/vc4/vc4_render_cl.c| 631 ++
 drivers/gpu/drm/vc4/vc4_trace.h|  63 +++
 drivers/gpu/drm/vc4/vc4_trace_points.c |  14 +
 drivers/gpu/drm/vc4/vc4_v3d.c  |  37 ++
 drivers/gpu/drm/vc4/vc4_validate.c | 955 +
 include/uapi/drm/vc4_drm.h | 141 +
 12 files changed, 3303 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_gem.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_irq.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_packet.h
 create mode 100644 drivers/gpu/drm/vc4/vc4_render_cl.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_trace.h
 create mode 100644 drivers/gpu/drm/vc4/vc4_trace_points.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_validate.c

diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index e87a6f2..4c6a99f 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -8,12 +8,19 @@ vc4-y := \
vc4_crtc.o \
vc4_drv.o \
vc4_kms.o \
+   vc4_gem.o \
vc4_hdmi.o \
vc4_hvs.o \
+   vc4_irq.o \
vc4_plane.o \
+   vc4_render_cl.o \
+   vc4_trace_points.o \
vc4_v3d.o \
+   vc4_validate.o \
vc4_validate_shaders.o

 vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o

 obj-$(CONFIG_DRM_VC4)  += vc4.o
+
+CFLAGS_vc4_trace_points.o := -I$(src)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index db58d74..2cfee59 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -74,6 +74,9 @@ static const struct file_operations vc4_drm_fops = {
 };

 static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
+   DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0),
+   DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0),
+   DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
@@ -83,10 +86,16 @@ static struct drm_driver vc4_drm_driver = {
.driver_features = (DRIVER_MODESET |
DRIVER_ATOMIC |
DRIVER_GEM |
+   DRIVER_HAVE_IRQ |
DRIVER_PRIME),
.lastclose = vc4_lastclose,
.preclose = vc4_drm_preclose,

+   .irq_handler = vc4_irq,
+   .irq_preinstall = vc4_irq_preinstall,
+   .irq_postinstall = vc4_irq_postinstall,
+   .irq_uninstall = vc4_irq_uninstall,
+
.enable_vblank = vc4_enable_vblank,
.disable_vblank = vc4_disable_vblank,
.get_vblank_counter = drm_vblank_count,
@@ -181,9 +190,11 @@ static int vc4_drm_bind(struct device *dev)
if (ret)
goto unref;

+   vc4_gem_init(drm);
+
ret = component_bind_all(dev, drm);
if (ret)
-   goto unref;
+   goto gem_destroy;

ret = drm_dev_register(drm, 0);
if (ret < 0)
@@ -207,6 +218,8 @@ unregister:
drm_dev_unregister(drm);
 unbind_all:
component_unbind_all(dev, drm);
+gem_destroy:
+   vc4_gem_destroy(drm);
 unref:
drm_dev_unref(drm);
vc4_bo_cache_destroy(drm);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 8945463..a3dbfee 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -49,6 +49,48 @@ struct vc4_dev {

/* Protects bo_cache and the BO stats. */
struct mutex bo_lock;
+
+   /* Sequence number for the last job queued in job_list.
+* Starts at 0 (no jobs emitted).
+*/
+   uint64_t emit_seqno;
+
+   /* Sequence number for the last completed job on the GPU.
+* Starts at 0 (no jobs completed).
+*/
+   uint64_t finished_seqno;
+
+   /* List of all struct vc4_exec_info for jobs to be executed.
+* The first job in the list is the one currently programmed
+* into ct0ca/ct1ca for execution.
+*/
+   struct list_head job_list;
+   /* List of the finished vc4_exec_infos waiting to be freed by
+* job_done_work.
+*/
+   struct list_head job_done_list;
+   /* Spinlock used to synchronize the job_list and seqno
+* accesses between the IRQ handler 

[PATCH 6/9] drm/vc4: Bind and initialize the V3D engine.

2015-12-01 Thread Eric Anholt
This is the component of the GPU that does 3D rendering.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/Makefile  |   1 +
 drivers/gpu/drm/vc4/vc4_debugfs.c |   2 +
 drivers/gpu/drm/vc4/vc4_drv.c |   1 +
 drivers/gpu/drm/vc4/vc4_drv.h |  13 +++
 drivers/gpu/drm/vc4/vc4_v3d.c | 225 ++
 5 files changed, 242 insertions(+)
 create mode 100644 drivers/gpu/drm/vc4/vc4_v3d.c

diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index eb776a6..e87a6f2 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -11,6 +11,7 @@ vc4-y := \
vc4_hdmi.o \
vc4_hvs.o \
vc4_plane.o \
+   vc4_v3d.o \
vc4_validate_shaders.o

 vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c 
b/drivers/gpu/drm/vc4/vc4_debugfs.c
index 6bcf96e..d76ad10 100644
--- a/drivers/gpu/drm/vc4/vc4_debugfs.c
+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c
@@ -22,6 +22,8 @@ static const struct drm_info_list vc4_debugfs_list[] = {
{"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
{"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1},
{"crtc2_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)2},
+   {"v3d_ident", vc4_v3d_debugfs_ident, 0},
+   {"v3d_regs", vc4_v3d_debugfs_regs, 0},
 };

 #define VC4_DEBUGFS_ENTRIES ARRAY_SIZE(vc4_debugfs_list)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index da4be9c..db58d74 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -236,6 +236,7 @@ static struct platform_driver *const component_drivers[] = {
_hdmi_driver,
_crtc_driver,
_hvs_driver,
+   _v3d_driver,
 };

 static int vc4_platform_drm_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index bd77d55..8945463 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -15,6 +15,7 @@ struct vc4_dev {
struct vc4_hdmi *hdmi;
struct vc4_hvs *hvs;
struct vc4_crtc *crtc[3];
+   struct vc4_v3d *v3d;

struct drm_fbdev_cma *fbdev;

@@ -82,6 +83,11 @@ to_vc4_bo(struct drm_gem_object *bo)
return (struct vc4_bo *)bo;
 }

+struct vc4_v3d {
+   struct platform_device *pdev;
+   void __iomem *regs;
+};
+
 struct vc4_hvs {
struct platform_device *pdev;
void __iomem *regs;
@@ -119,6 +125,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
return container_of(encoder, struct vc4_encoder, base);
 }

+#define V3D_READ(offset) readl(vc4->v3d->regs + offset)
+#define V3D_WRITE(offset, val) writel(val, vc4->v3d->regs + offset)
 #define HVS_READ(offset) readl(vc4->hvs->regs + offset)
 #define HVS_WRITE(offset, val) writel(val, vc4->hvs->regs + offset)

@@ -241,6 +249,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
 u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
 u32 vc4_plane_dlist_size(struct drm_plane_state *state);

+/* vc4_v3d.c */
+extern struct platform_driver vc4_v3d_driver;
+int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
+int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
+
 /* vc4_validate_shader.c */
 struct vc4_validated_shader_info *
 vc4_validate_shader(struct drm_gem_cma_object *shader_obj);
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
new file mode 100644
index 000..040ad0d
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark 
+ *
+ * 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 "linux/component.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+#ifdef CONFIG_DEBUG_FS
+#define REGDEF(reg) { reg, #reg }
+static const struct {
+   uint32_t reg;
+   const char *name;
+} vc4_reg_defs[] = {
+   REGDEF(V3D_IDENT0),
+   REGDEF(V3D_IDENT1),
+   REGDEF(V3D_IDENT2),
+   REGDEF(V3D_SCRATCH),
+   REGDEF(V3D_L2CACTL),
+   REGDEF(V3D_SLCACTL),
+   REGDEF(V3D_INTCTL),
+   REGDEF(V3D_INTENA),
+   REGDEF(V3D_INTDIS),
+   REGDEF(V3D_CT0CS),
+   REGDEF(V3D_CT1CS),
+   REGDEF(V3D_CT0EA),
+   REGDEF(V3D_CT1EA),
+   REGDEF(V3D_CT0CA),
+   REGDEF(V3D_CT1CA),
+   REGDEF(V3D_CT00RA0),
+   

[PATCH 5/9] drm/vc4: Fix a typo in a V3D debug register.

2015-12-01 Thread Eric Anholt
Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/vc4_regs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 9e4e904..4e52a0a 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -154,7 +154,7 @@
 #define V3D_PCTRS14  0x006f4
 #define V3D_PCTR15   0x006f8
 #define V3D_PCTRS15  0x006fc
-#define V3D_BGE  0x00f00
+#define V3D_DBGE 0x00f00
 #define V3D_FDBGO0x00f04
 #define V3D_FDBGB0x00f08
 #define V3D_FDBGR0x00f0c
-- 
2.6.2



[PATCH 4/9] drm/vc4: Add an API for creating GPU shaders in GEM BOs.

2015-12-01 Thread Eric Anholt
Since we have no MMU, the kernel needs to validate that the submitted
shader code won't make any accesses to memory that the user doesn't
control, which involves banning some operations (general purpose DMA
writes), and tracking where we need to write out pointers for other
operations (texture sampling).  Once it's validated, we return a GEM
BO containing the shader, which doesn't allow mapping for write or
exporting to other subsystems.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/Makefile   |   3 +-
 drivers/gpu/drm/vc4/vc4_bo.c   | 140 
 drivers/gpu/drm/vc4/vc4_drv.c  |   9 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |  50 +++
 drivers/gpu/drm/vc4/vc4_qpu_defines.h  | 264 +++
 drivers/gpu/drm/vc4/vc4_validate_shaders.c | 513 +
 include/uapi/drm/vc4_drm.h |  25 ++
 7 files changed, 999 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_qpu_defines.h
 create mode 100644 drivers/gpu/drm/vc4/vc4_validate_shaders.c

diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index 32b4f9c..eb776a6 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -10,7 +10,8 @@ vc4-y := \
vc4_kms.o \
vc4_hdmi.o \
vc4_hvs.o \
-   vc4_plane.o
+   vc4_plane.o \
+   vc4_validate_shaders.o

 vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o

diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index 06cba26..18dfe3e 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -79,6 +79,12 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
struct drm_gem_object *obj = >base.base;
struct vc4_dev *vc4 = to_vc4_dev(obj->dev);

+   if (bo->validated_shader) {
+   kfree(bo->validated_shader->texture_samples);
+   kfree(bo->validated_shader);
+   bo->validated_shader = NULL;
+   }
+
vc4->bo_stats.num_allocated--;
vc4->bo_stats.size_allocated -= obj->size;
drm_gem_cma_free_object(obj);
@@ -315,6 +321,12 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
goto out;
}

+   if (bo->validated_shader) {
+   kfree(bo->validated_shader->texture_samples);
+   kfree(bo->validated_shader);
+   bo->validated_shader = NULL;
+   }
+
bo->free_time = jiffies;
list_add(>size_head, cache_list);
list_add(>unref_head, >bo_cache.time_list);
@@ -347,6 +359,78 @@ static void vc4_bo_cache_time_timer(unsigned long data)
schedule_work(>bo_cache.time_work);
 }

+struct dma_buf *
+vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags)
+{
+   struct vc4_bo *bo = to_vc4_bo(obj);
+
+   if (bo->validated_shader) {
+   DRM_ERROR("Attempting to export shader BO\n");
+   return ERR_PTR(-EINVAL);
+   }
+
+   return drm_gem_prime_export(dev, obj, flags);
+}
+
+int vc4_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+   struct drm_gem_object *gem_obj;
+   struct vc4_bo *bo;
+   int ret;
+
+   ret = drm_gem_mmap(filp, vma);
+   if (ret)
+   return ret;
+
+   gem_obj = vma->vm_private_data;
+   bo = to_vc4_bo(gem_obj);
+
+   if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
+   DRM_ERROR("mmaping of shader BOs for writing not allowed.\n");
+   return -EINVAL;
+   }
+
+   /*
+* 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_writecombine(bo->base.base.dev->dev, vma,
+   bo->base.vaddr, bo->base.paddr,
+   vma->vm_end - vma->vm_start);
+   if (ret)
+   drm_gem_vm_close(vma);
+
+   return ret;
+}
+
+int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+   struct vc4_bo *bo = to_vc4_bo(obj);
+
+   if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
+   DRM_ERROR("mmaping of shader BOs for writing not allowed.\n");
+   return -EINVAL;
+   }
+
+   return drm_gem_cma_prime_mmap(obj, vma);
+}
+
+void *vc4_prime_vmap(struct drm_gem_object *obj)
+{
+   struct vc4_bo *bo = to_vc4_bo(obj);
+
+   if (bo->validated_shader) {
+   DRM_ERROR("mmaping of shader BOs not allowed.\n");
+   return ERR_PTR(-EINVAL);
+   }
+
+   return drm_gem_cma_prime_vmap(obj);
+}
+
 int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
 {
@@ -387,6 +471,62 @@ int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
return 0;
 }

+int

[PATCH 3/9] drm/vc4: Add create and map BO ioctls.

2015-12-01 Thread Eric Anholt
While there exist dumb APIs for creating and mapping BOs, one of the
rules is that drivers doing 3D acceleration have to provide their own
APIs for buffer allocation (besides, the pitch/height parameters of
the dumb alloc don't really make sense for a lot of 3D allocations).

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/vc4_bo.c  | 41 ++
 drivers/gpu/drm/vc4/vc4_drv.c |  3 ++
 drivers/gpu/drm/vc4/vc4_drv.h |  4 +++
 include/uapi/drm/Kbuild   |  1 +
 include/uapi/drm/vc4_drm.h| 68 +++
 5 files changed, 117 insertions(+)
 create mode 100644 include/uapi/drm/vc4_drm.h

diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index 18faa5b..06cba26 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -19,6 +19,7 @@
  */

 #include "vc4_drv.h"
+#include "uapi/drm/vc4_drm.h"

 static void vc4_bo_stats_dump(struct vc4_dev *vc4)
 {
@@ -346,6 +347,46 @@ static void vc4_bo_cache_time_timer(unsigned long data)
schedule_work(>bo_cache.time_work);
 }

+int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
+   struct drm_file *file_priv)
+{
+   struct drm_vc4_create_bo *args = data;
+   struct vc4_bo *bo = NULL;
+   int ret;
+
+   /*
+* We can't allocate from the BO cache, because the BOs don't
+* get zeroed, and that might leak data between users.
+*/
+   bo = vc4_bo_create(dev, args->size, false);
+   if (!bo)
+   return -ENOMEM;
+
+   ret = drm_gem_handle_create(file_priv, >base.base, >handle);
+   drm_gem_object_unreference_unlocked(>base.base);
+
+   return ret;
+}
+
+int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+   struct drm_vc4_mmap_bo *args = data;
+   struct drm_gem_object *gem_obj;
+
+   gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+   if (!gem_obj) {
+   DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+   return -EINVAL;
+   }
+
+   /* The mmap offset was set up at BO allocation time. */
+   args->offset = drm_vma_node_offset_addr(_obj->vma_node);
+
+   drm_gem_object_unreference_unlocked(gem_obj);
+   return 0;
+}
+
 void vc4_bo_cache_init(struct drm_device *dev)
 {
struct vc4_dev *vc4 = to_vc4_dev(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index da041fa..5fa4688 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -16,6 +16,7 @@
 #include 
 #include "drm_fb_cma_helper.h"

+#include "uapi/drm/vc4_drm.h"
 #include "vc4_drv.h"
 #include "vc4_regs.h"

@@ -73,6 +74,8 @@ static const struct file_operations vc4_drm_fops = {
 };

 static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
+   DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
+   DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
 };

 static struct drm_driver vc4_drm_driver = {
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 39a1ff5..fddb0a0 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -155,6 +155,10 @@ int vc4_dumb_create(struct drm_file *file_priv,
struct drm_mode_create_dumb *args);
 struct dma_buf *vc4_prime_export(struct drm_device *dev,
 struct drm_gem_object *obj, int flags);
+int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
+   struct drm_file *file_priv);
+int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
 void vc4_bo_cache_init(struct drm_device *dev);
 void vc4_bo_cache_destroy(struct drm_device *dev);
 int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild
index 38d4370..974fcd5 100644
--- a/include/uapi/drm/Kbuild
+++ b/include/uapi/drm/Kbuild
@@ -17,4 +17,5 @@ header-y += tegra_drm.h
 header-y += via_drm.h
 header-y += vmwgfx_drm.h
 header-y += msm_drm.h
+header-y += vc4_drm.h
 header-y += virtgpu_drm.h
diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h
new file mode 100644
index 000..068aab9
--- /dev/null
+++ b/include/uapi/drm/vc4_drm.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2014-2015 Broadcom
+ *
+ * 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 

[PATCH 2/9] drm/vc4: Add a BO cache.

2015-12-01 Thread Eric Anholt
We need to allocate new BOs in the kernel as part of each frame, but
the CMA allocator is way too slow for that.  As an optimization, keep
track of recently-freed BOs and reuse them, with a 1 second timeout to
fully free them back to the system.

This improves 3D performance by about 15%.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/vc4/vc4_bo.c  | 336 +-
 drivers/gpu/drm/vc4/vc4_debugfs.c |   1 +
 drivers/gpu/drm/vc4/vc4_drv.c |   6 +-
 drivers/gpu/drm/vc4/vc4_drv.h |  49 +-
 4 files changed, 384 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index ab9f510..18faa5b 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -12,19 +12,229 @@
  * access to system memory with no MMU in between.  To support it, we
  * use the GEM CMA helper functions to allocate contiguous ranges of
  * physical memory for our BOs.
+ *
+ * Since the CMA allocator is very slow, we keep a cache of recently
+ * freed BOs around so that the kernel's allocation of objects for 3D
+ * rendering can return quickly.
  */

 #include "vc4_drv.h"

-struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size)
+static void vc4_bo_stats_dump(struct vc4_dev *vc4)
+{
+   DRM_INFO("num bos allocated: %d\n",
+vc4->bo_stats.num_allocated);
+   DRM_INFO("size bos allocated: %dkb\n",
+vc4->bo_stats.size_allocated / 1024);
+   DRM_INFO("num bos used: %d\n",
+vc4->bo_stats.num_allocated - vc4->bo_stats.num_cached);
+   DRM_INFO("size bos used: %dkb\n",
+(vc4->bo_stats.size_allocated -
+ vc4->bo_stats.size_cached) / 1024);
+   DRM_INFO("num bos cached: %d\n",
+vc4->bo_stats.num_cached);
+   DRM_INFO("size bos cached: %dkb\n",
+vc4->bo_stats.size_cached / 1024);
+}
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_bo_stats_debugfs(struct seq_file *m, void *unused)
+{
+   struct drm_info_node *node = (struct drm_info_node *)m->private;
+   struct drm_device *dev = node->minor->dev;
+   struct vc4_dev *vc4 = to_vc4_dev(dev);
+   struct vc4_bo_stats stats;
+
+   /* Take a snapshot of the current stats with the lock held. */
+   mutex_lock(>bo_lock);
+   stats = vc4->bo_stats;
+   mutex_unlock(>bo_lock);
+
+   seq_printf(m, "num bos allocated: %d\n",
+  stats.num_allocated);
+   seq_printf(m, "size bos allocated: %dkb\n",
+  stats.size_allocated / 1024);
+   seq_printf(m, "num bos used: %d\n",
+  stats.num_allocated - stats.num_cached);
+   seq_printf(m, "size bos used: %dkb\n",
+  (stats.size_allocated - stats.size_cached) / 1024);
+   seq_printf(m, "num bos cached: %d\n",
+  stats.num_cached);
+   seq_printf(m, "size bos cached: %dkb\n",
+  stats.size_cached / 1024);
+
+   return 0;
+}
+#endif
+
+static uint32_t bo_page_index(size_t size)
+{
+   return (size / PAGE_SIZE) - 1;
+}
+
+/* Must be called with bo_lock held. */
+static void vc4_bo_destroy(struct vc4_bo *bo)
 {
+   struct drm_gem_object *obj = >base.base;
+   struct vc4_dev *vc4 = to_vc4_dev(obj->dev);
+
+   vc4->bo_stats.num_allocated--;
+   vc4->bo_stats.size_allocated -= obj->size;
+   drm_gem_cma_free_object(obj);
+}
+
+/* Must be called with bo_lock held. */
+static void vc4_bo_remove_from_cache(struct vc4_bo *bo)
+{
+   struct drm_gem_object *obj = >base.base;
+   struct vc4_dev *vc4 = to_vc4_dev(obj->dev);
+
+   vc4->bo_stats.num_cached--;
+   vc4->bo_stats.size_cached -= obj->size;
+
+   list_del(>unref_head);
+   list_del(>size_head);
+}
+
+static struct list_head *vc4_get_cache_list_for_size(struct drm_device *dev,
+size_t size)
+{
+   struct vc4_dev *vc4 = to_vc4_dev(dev);
+   uint32_t page_index = bo_page_index(size);
+
+   if (vc4->bo_cache.size_list_size <= page_index) {
+   uint32_t new_size = max(vc4->bo_cache.size_list_size * 2,
+   page_index + 1);
+   struct list_head *new_list;
+   uint32_t i;
+
+   new_list = kmalloc_array(new_size, sizeof(struct list_head),
+GFP_KERNEL);
+   if (!new_list)
+   return NULL;
+
+   /* Rebase the old cached BO lists to their new list
+* head locations.
+*/
+   for (i = 0; i < vc4->bo_cache.size_list_size; i++) {
+   struct list_head *old_list =
+   >bo_cache.size_list[i];
+
+   if (list_empty(old_list))
+   INIT_LIST_HEAD(_list[i]);
+   else
+   list_replace(old_list, 

[PATCH 1/9] drm: Create a driver hook for allocating GEM object structs.

2015-12-01 Thread Eric Anholt
The CMA helpers had no way for a driver to extend the struct with its
own fields.  Since the CMA helpers are mostly "Allocate a
drm_gem_cma_object, then fill in a few fields", it's hard to write as
pure helpers without passing in a driver callback for the allocate
step.

Signed-off-by: Eric Anholt 
---
 drivers/gpu/drm/drm_gem_cma_helper.c | 10 ++
 include/drm/drmP.h   |  7 +++
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index e109b49..0f7b00ba 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -59,11 +59,13 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size)
struct drm_gem_object *gem_obj;
int ret;

-   cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
-   if (!cma_obj)
+   if (drm->driver->gem_create_object)
+   gem_obj = drm->driver->gem_create_object(drm, size);
+   else
+   gem_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
+   if (!gem_obj)
return ERR_PTR(-ENOMEM);
-
-   gem_obj = _obj->base;
+   cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base);

ret = drm_gem_object_init(drm, gem_obj, size);
if (ret)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 0b921ae..22ff162 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -580,6 +580,13 @@ struct drm_driver {
int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);

+   /**
+* Hook for allocating the GEM object struct, for use by core
+* helpers.
+*/
+   struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
+   size_t size);
+
/* prime: */
/* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file 
*file_priv,
-- 
2.6.2



[RFC PATCH 9/9] drm/rockchip: dw_hdmi: use encoder enable function

2015-12-01 Thread Mark Yao
encoder.enable is more compatible to atomic api than encoder.prepare/commit

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c |   14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c 
b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 80d6fc8..cfe052c 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -195,12 +195,15 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct 
drm_encoder *encoder,
 {
 }

-static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
+static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
 {
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
u32 val;
int mux;

+   rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
+ ROCKCHIP_OUT_MODE_);
+
mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
if (mux)
val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
@@ -212,17 +215,10 @@ static void dw_hdmi_rockchip_encoder_commit(struct 
drm_encoder *encoder)
(mux) ? "LIT" : "BIG");
 }

-static void dw_hdmi_rockchip_encoder_prepare(struct drm_encoder *encoder)
-{
-   rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
- ROCKCHIP_OUT_MODE_);
-}
-
 static struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = 
{
.mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
.mode_set   = dw_hdmi_rockchip_encoder_mode_set,
-   .prepare= dw_hdmi_rockchip_encoder_prepare,
-   .commit = dw_hdmi_rockchip_encoder_commit,
+   .enable = dw_hdmi_rockchip_encoder_enable,
.disable= dw_hdmi_rockchip_encoder_disable,
 };

-- 
1.7.9.5




[RFC PATCH 8/9] drm: bridge/dw_hdmi: Covert to support atomic API

2015-12-01 Thread Mark Yao
Fill atomic needed funcs with default atomic helper library.

Rockchip use dw_hdmi, and drm/rockchip will covert to atomic api,
we need dw_hdmi support atomic funcs.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/bridge/dw_hdmi.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 56de9f1..587065a 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -22,6 +22,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1515,11 +1516,14 @@ static void dw_hdmi_connector_force(struct 
drm_connector *connector)
 }

 static struct drm_connector_funcs dw_hdmi_connector_funcs = {
-   .dpms = drm_helper_connector_dpms,
+   .dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = dw_hdmi_connector_detect,
.destroy = dw_hdmi_connector_destroy,
.force = dw_hdmi_connector_force,
+   .reset = drm_atomic_helper_connector_reset,
+   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };

 static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
-- 
1.7.9.5




[RFC PATCH 7/9] drm/rockchip: force enable vop when do mode setting

2015-12-01 Thread Mark Yao
When do mode setting, mean that we want to enable display output,
but sometimes, vop_crtc_enable is after mode_set, we can't allow
that, so force enable vop in mode setting.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index c65b454..7c07537 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1110,6 +1110,7 @@ static void vop_crtc_mode_set_nofb(struct drm_crtc *crtc)
u16 vact_end = vact_st + vdisplay;
uint32_t val;

+   vop_crtc_enable(crtc);
/*
 * If dclk rate is zero, mean that scanout is stop,
 * we don't need wait any more.
-- 
1.7.9.5




[RFC PATCH 6/9] drm/rockchip: direct config connecter gate and out_mode

2015-12-01 Thread Mark Yao
Both connecter gate and out_mode are not conflict with mode set
configure. Direct setting connecter gate and out_mode, that allow
connector do rockchip_drm_crtc_mode_config after mode set.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   41 ---
 1 file changed, 18 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 6317dea..c65b454 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -90,9 +90,6 @@ struct vop {
struct drm_device *drm_dev;
bool is_enabled;

-   int connector_type;
-   int connector_out_mode;
-
/* mutex vsync_ work */
struct mutex vsync_mutex;
bool vsync_work_pending;
@@ -1029,8 +1026,24 @@ int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
 {
struct vop *vop = to_vop(crtc);

-   vop->connector_type = connector_type;
-   vop->connector_out_mode = out_mode;
+   if (WARN_ON(!vop->is_enabled))
+   return -EINVAL;
+
+   switch (connector_type) {
+   case DRM_MODE_CONNECTOR_LVDS:
+   VOP_CTRL_SET(vop, rgb_en, 1);
+   break;
+   case DRM_MODE_CONNECTOR_eDP:
+   VOP_CTRL_SET(vop, edp_en, 1);
+   break;
+   case DRM_MODE_CONNECTOR_HDMIA:
+   VOP_CTRL_SET(vop, hdmi_en, 1);
+   break;
+   default:
+   DRM_ERROR("unsupport connector_type[%d]\n", connector_type);
+   return -EINVAL;
+   };
+   VOP_CTRL_SET(vop, out_mode, out_mode);

return 0;
 }
@@ -1132,24 +1145,6 @@ static void vop_crtc_mode_set_nofb(struct drm_crtc *crtc)

vop_dsp_hold_valid_irq_disable(vop);
}
-
-   switch (vop->connector_type) {
-   case DRM_MODE_CONNECTOR_LVDS:
-   VOP_CTRL_SET(vop, rgb_en, 1);
-   break;
-   case DRM_MODE_CONNECTOR_eDP:
-   VOP_CTRL_SET(vop, edp_en, 1);
-   break;
-   case DRM_MODE_CONNECTOR_HDMIA:
-   VOP_CTRL_SET(vop, hdmi_en, 1);
-   break;
-   default:
-   DRM_ERROR("unsupport connector_type[%d]\n",
- vop->connector_type);
-   goto out;
-   };
-   VOP_CTRL_SET(vop, out_mode, vop->connector_out_mode);
-
val = 0x8;
val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
-- 
1.7.9.5




[RFC PATCH 5/9] drm/rockchip: Optimization vop mode set

2015-12-01 Thread Mark Yao
Rk3288 vop timing registers is immediately register, when configure
timing on display active time, will cause tearing. use dclk reset is
not a good idea to avoid this tearing. we can avoid tearing by using
standby register.

Vop standby register will take effect at end of current frame, and
go back to work immediately when exit standby.

So we can use standby register to protect this context.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   49 +++
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index a28e255..6317dea 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -1098,10 +1098,40 @@ static void vop_crtc_mode_set_nofb(struct drm_crtc 
*crtc)
uint32_t val;

/*
-* disable dclk to stop frame scan, so that we can safe config mode and
-* enable iommu.
+* If dclk rate is zero, mean that scanout is stop,
+* we don't need wait any more.
 */
-   clk_disable(vop->dclk);
+   if (clk_get_rate(vop->dclk)) {
+   /*
+* Rk3288 vop timing register is immediately, when configure
+* display timing on display time, may cause tearing.
+*
+* Vop standby will take effect at end of current frame,
+* if dsp hold valid irq happen, it means standby complete.
+*
+* mode set:
+*standby and wait complete --> |
+*  | display time
+*  |
+*  |---> dsp hold irq
+* configure display timing --> |
+* standby exit |
+*  | new frame start.
+*/
+
+   reinit_completion(>dsp_hold_completion);
+   vop_dsp_hold_valid_irq_enable(vop);
+
+   spin_lock(>reg_lock);
+
+   VOP_CTRL_SET(vop, standby, 1);
+
+   spin_unlock(>reg_lock);
+
+   wait_for_completion(>dsp_hold_completion);
+
+   vop_dsp_hold_valid_irq_disable(vop);
+   }

switch (vop->connector_type) {
case DRM_MODE_CONNECTOR_LVDS:
@@ -1137,20 +1167,9 @@ static void vop_crtc_mode_set_nofb(struct drm_crtc *crtc)
VOP_CTRL_SET(vop, vact_st_end, val);
VOP_CTRL_SET(vop, vpost_st_end, val);

-
-   /*
-* reset dclk, take all mode config affect, so the clk would run in
-* correct frame.
-*/
-   reset_control_assert(vop->dclk_rst);
-   usleep_range(10, 20);
-   reset_control_deassert(vop->dclk_rst);
-
clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
-out:
-   if (clk_enable(vop->dclk) < 0)
-   dev_err(vop->dev, "failed to enable dclk - %d\n", ret_clk);

+   VOP_CTRL_SET(vop, standby, 0);
 }

 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
-- 
1.7.9.5




[RFC PATCH 4/9] drm/rockchip: support atomic asynchronous commit

2015-12-01 Thread Mark Yao
If drm core requests a async commit, rockchip_drm_atomic_commit
will schedule a work task to update later.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c |   60 ++--
 1 file changed, 47 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index c86d93a..30ddf4a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -29,6 +29,12 @@ struct rockchip_drm_fb {
struct drm_gem_object *obj[ROCKCHIP_MAX_FB_BUFFER];
 };

+struct rockchip_atomic_commit {
+   struct work_struct  work;
+   struct drm_device   *dev;
+   struct drm_atomic_state *state;
+};
+
 struct drm_gem_object *rockchip_fb_get_gem_obj(struct drm_framebuffer *fb,
   unsigned int plane)
 {
@@ -195,20 +201,11 @@ static void rockchip_atomic_wait_for_complete(struct 
drm_atomic_state *state)
}
 }

-int rockchip_drm_atomic_commit(struct drm_device *dev,
-  struct drm_atomic_state *state,
-  bool async)
+static void
+rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
 {
-   int ret;
-
-   if (async)
-   return -EBUSY;
-
-   ret = drm_atomic_helper_prepare_planes(dev, state);
-   if (ret)
-   return ret;
-
-   drm_atomic_helper_swap_state(dev, state);
+   struct drm_device *dev = commit->dev;
+   struct drm_atomic_state *state = commit->state;

/*
 * TODO: do fence wait here.
@@ -226,6 +223,43 @@ int rockchip_drm_atomic_commit(struct drm_device *dev,

drm_atomic_state_free(state);

+   kfree(commit);
+}
+
+static void rockchip_drm_atomic_work(struct work_struct *work)
+{
+   struct rockchip_atomic_commit *commit = container_of(work,
+   struct rockchip_atomic_commit, work);
+
+   rockchip_atomic_commit_complete(commit);
+}
+
+int rockchip_drm_atomic_commit(struct drm_device *dev,
+  struct drm_atomic_state *state,
+  bool async)
+{
+   int ret;
+   struct rockchip_atomic_commit *commit;
+
+   ret = drm_atomic_helper_prepare_planes(dev, state);
+   if (ret)
+   return ret;
+
+   drm_atomic_helper_swap_state(dev, state);
+
+   commit = kzalloc(sizeof(*commit), GFP_KERNEL);
+   if (!commit)
+   return -ENOMEM;
+
+   INIT_WORK(>work, rockchip_drm_atomic_work);
+   commit->dev = dev;
+   commit->state = state;
+
+   if (async)
+   schedule_work(>work);
+   else
+   rockchip_atomic_commit_complete(commit);
+
return 0;
 }

-- 
1.7.9.5




[RFC PATCH 3/9] drm/rockchip: Convert to support atomic API

2015-12-01 Thread Mark Yao
Rockchip vop not support hw vblank counter, needed check the committed
register if it's really take effect.

Signed-off-by: Mark Yao 
Signed-off-by: Tomasz Figa 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |2 +
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |   65 +++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  603 ++-
 4 files changed, 301 insertions(+), 374 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index ccd46f2..5de51fd 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -214,6 +214,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 */
drm_dev->vblank_disable_allowed = true;

+   drm_mode_config_reset(drm_dev);
+
ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
goto err_vblank_cleanup;
@@ -277,7 +279,8 @@ const struct vm_operations_struct rockchip_drm_vm_ops = {
 };

 static struct drm_driver rockchip_drm_driver = {
-   .driver_features= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+   .driver_features= DRIVER_MODESET | DRIVER_GEM |
+ DRIVER_PRIME | DRIVER_ATOMIC,
.load   = rockchip_drm_load,
.unload = rockchip_drm_unload,
.lastclose  = rockchip_drm_lastclose,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 069d6d4..513ff98 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,6 +18,7 @@
 #define _ROCKCHIP_DRM_DRV_H

 #include 
+#include 
 #include 

 #include 
@@ -63,5 +64,6 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
+void rockchip_crtc_wait_for_update(struct drm_crtc *crtc);

 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 002645b..c86d93a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 

@@ -166,9 +167,73 @@ static void rockchip_drm_output_poll_changed(struct 
drm_device *dev)
drm_fb_helper_hotplug_event(fb_helper);
 }

+static void rockchip_atomic_wait_for_complete(struct drm_atomic_state *state)
+{
+   struct drm_crtc_state *crtc_state;
+   struct drm_crtc *crtc;
+   int i;
+
+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
+   if (!crtc->state->active)
+   continue;
+
+   WARN_ON(drm_crtc_vblank_get(crtc));
+   }
+
+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
+   if (!crtc->state->active)
+   continue;
+
+   rockchip_crtc_wait_for_update(crtc);
+   }
+
+   for_each_crtc_in_state(state, crtc, crtc_state, i) {
+   if (!crtc->state->active)
+   continue;
+
+   drm_crtc_vblank_put(crtc);
+   }
+}
+
+int rockchip_drm_atomic_commit(struct drm_device *dev,
+  struct drm_atomic_state *state,
+  bool async)
+{
+   int ret;
+
+   if (async)
+   return -EBUSY;
+
+   ret = drm_atomic_helper_prepare_planes(dev, state);
+   if (ret)
+   return ret;
+
+   drm_atomic_helper_swap_state(dev, state);
+
+   /*
+* TODO: do fence wait here.
+*/
+
+   drm_atomic_helper_commit_modeset_disables(dev, state);
+
+   drm_atomic_helper_commit_planes(dev, state, false);
+
+   drm_atomic_helper_commit_modeset_enables(dev, state);
+
+   rockchip_atomic_wait_for_complete(state);
+
+   drm_atomic_helper_cleanup_planes(dev, state);
+
+   drm_atomic_state_free(state);
+
+   return 0;
+}
+
 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
.fb_create = rockchip_user_fb_create,
.output_poll_changed = rockchip_drm_output_poll_changed,
+   .atomic_check = drm_atomic_helper_check,
+   .atomic_commit = rockchip_drm_atomic_commit,
 };

 struct drm_framebuffer *
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3d16e70..a28e255 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -14,6 +14,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -63,12 +64,16 @@

 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) 

[RFC PATCH 2/9] drm/rockchip: Use new vblank api drm_crtc_vblank_*

2015-12-01 Thread Mark Yao
No functional update, drm_vblank_* is the legacy version of
drm_crtc_vblank_*. and use new api make driver more clean.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   13 +++--
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |7 +++
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   24 +++-
 3 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 574324e..ccd46f2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -65,11 +65,11 @@ void rockchip_drm_dma_detach_device(struct drm_device 
*drm_dev,
 }
 EXPORT_SYMBOL_GPL(rockchip_drm_dma_detach_device);

-int rockchip_register_crtc_funcs(struct drm_device *dev,
-const struct rockchip_crtc_funcs *crtc_funcs,
-int pipe)
+int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
+const struct rockchip_crtc_funcs *crtc_funcs)
 {
-   struct rockchip_drm_private *priv = dev->dev_private;
+   int pipe = drm_crtc_index(crtc);
+   struct rockchip_drm_private *priv = crtc->dev->dev_private;

if (pipe > ROCKCHIP_MAX_CRTC)
return -EINVAL;
@@ -80,9 +80,10 @@ int rockchip_register_crtc_funcs(struct drm_device *dev,
 }
 EXPORT_SYMBOL_GPL(rockchip_register_crtc_funcs);

-void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe)
+void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc)
 {
-   struct rockchip_drm_private *priv = dev->dev_private;
+   int pipe = drm_crtc_index(crtc);
+   struct rockchip_drm_private *priv = crtc->dev->dev_private;

if (pipe > ROCKCHIP_MAX_CRTC)
return;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index dc4e5f0..069d6d4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -52,10 +52,9 @@ struct rockchip_drm_private {
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
 };

-int rockchip_register_crtc_funcs(struct drm_device *dev,
-const struct rockchip_crtc_funcs *crtc_funcs,
-int pipe);
-void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe);
+int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
+const struct rockchip_crtc_funcs *crtc_funcs);
+void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
 int rockchip_drm_encoder_get_mux_id(struct device_node *node,
struct drm_encoder *encoder);
 int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 41905e2..3d16e70 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -119,8 +119,6 @@ struct vop {
/* vop dclk reset */
struct reset_control *dclk_rst;

-   int pipe;
-
struct vop_win win[];
 };

@@ -691,7 +689,7 @@ static void vop_crtc_enable(struct drm_crtc *crtc)

enable_irq(vop->irq);

-   drm_vblank_on(vop->drm_dev, vop->pipe);
+   drm_crtc_vblank_on(crtc);

return;

@@ -710,7 +708,7 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
if (!vop->is_enabled)
return;

-   drm_vblank_off(crtc->dev, vop->pipe);
+   drm_crtc_vblank_off(crtc);

/*
 * Vop standby will take effect at end of current frame,
@@ -917,7 +915,7 @@ static int vop_update_plane_event(struct drm_plane *plane,
 */
mutex_lock(>vsync_mutex);
if (fb != vop_win_last_pending_fb(vop_win)) {
-   ret = drm_vblank_get(plane->dev, vop->pipe);
+   ret = drm_crtc_vblank_get(crtc);
if (ret) {
DRM_ERROR("failed to get vblank, %d\n", ret);
mutex_unlock(>vsync_mutex);
@@ -928,7 +926,7 @@ static int vop_update_plane_event(struct drm_plane *plane,

ret = vop_win_queue_fb(vop_win, fb, yrgb_mst, event);
if (ret) {
-   drm_vblank_put(plane->dev, vop->pipe);
+   drm_crtc_vblank_put(crtc);
mutex_unlock(>vsync_mutex);
return ret;
}
@@ -1022,7 +1020,7 @@ static int vop_disable_plane(struct drm_plane *plane)

vop = to_vop(plane->crtc);

-   ret = drm_vblank_get(plane->dev, vop->pipe);
+   ret = drm_crtc_vblank_get(plane->crtc);
if (ret) {
DRM_ERROR("failed to get vblank, %d\n", ret);
return ret;
@@ -1032,7 +1030,7 @@ static int vop_disable_plane(struct drm_plane *plane)

ret = 

[RFC PATCH 1/9] drm/rockchip: vop: replace dpms with enable/disable

2015-12-01 Thread Mark Yao
For vop, power by enable/disable is more suitable then legacy dpms
function, and enable/disable more closely to the new atomic API.

Signed-off-by: Mark Yao 
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   37 +++
 1 file changed, 4 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 5f79d06..41905e2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -633,7 +633,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
spin_unlock_irqrestore(>irq_lock, flags);
 }

-static void vop_enable(struct drm_crtc *crtc)
+static void vop_crtc_enable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);
int ret;
@@ -703,7 +703,7 @@ err_disable_hclk:
clk_disable(vop->hclk);
 }

-static void vop_disable(struct drm_crtc *crtc)
+static void vop_crtc_disable(struct drm_crtc *crtc)
 {
struct vop *vop = to_vop(crtc);

@@ -1108,30 +1108,6 @@ static const struct rockchip_crtc_funcs 
private_crtc_funcs = {
.disable_vblank = vop_crtc_disable_vblank,
 };

-static void vop_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-   DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
-
-   switch (mode) {
-   case DRM_MODE_DPMS_ON:
-   vop_enable(crtc);
-   break;
-   case DRM_MODE_DPMS_STANDBY:
-   case DRM_MODE_DPMS_SUSPEND:
-   case DRM_MODE_DPMS_OFF:
-   vop_disable(crtc);
-   break;
-   default:
-   DRM_DEBUG_KMS("unspecified mode %d\n", mode);
-   break;
-   }
-}
-
-static void vop_crtc_prepare(struct drm_crtc *crtc)
-{
-   vop_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
 static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -1242,17 +1218,12 @@ out:
return ret;
 }

-static void vop_crtc_commit(struct drm_crtc *crtc)
-{
-}
-
 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
-   .dpms = vop_crtc_dpms,
-   .prepare = vop_crtc_prepare,
+   .enable = vop_crtc_enable,
+   .disable = vop_crtc_disable,
.mode_fixup = vop_crtc_mode_fixup,
.mode_set = vop_crtc_mode_set,
.mode_set_base = vop_crtc_mode_set_base,
-   .commit = vop_crtc_commit,
 };

 static int vop_crtc_page_flip(struct drm_crtc *crtc,
-- 
1.7.9.5




[RFC PATCH 0/9] drm/rockchip: covert to support atomic API

2015-12-01 Thread Mark Yao
The series of patches coverting drm rockchip to atomic API, do some
cleanup and some fixes on atomic side.

TODO: fence is not support on current version.

Tested on rk3288 popmetal board.

All guys can test it with following url:
 test case: https://github.com/markyzq/libdrm.git atomictest
 kernel: https://github.com/markyzq/kernel-drm-rockchip.git 
drm-rockchip-2015-11-31

Mark Yao (9):
  drm/rockchip: vop: replace dpms with enable/disable
  drm/rockchip: Use new vblank api drm_crtc_vblank_*
  drm/rockchip: Convert to support atomic API
  drm/rockchip: support atomic asynchronous commit
  drm/rockchip: Optimization vop mode set
  drm/rockchip: direct config connecter gate and out_mode
  drm/rockchip: force enable vop when do mode setting
  drm: bridge/dw_hdmi: Covert to support atomic API
  drm/rockchip: dw_hdmi: use encoder enable function

 drivers/gpu/drm/bridge/dw_hdmi.c|6 +-
 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c |   14 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |   18 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |9 +-
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |   99 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  735 +++
 6 files changed, 413 insertions(+), 468 deletions(-)

-- 
1.7.9.5




[PATCH v2 06/10] drm/hisilicon: Add vblank feature

2015-12-01 Thread Xinliang Liu
On 30 November 2015 at 15:54, Daniel Vetter  wrote:
> On Sat, Nov 28, 2015 at 06:39:01PM +0800, Xinliang Liu wrote:
>> Add vblank handle for ADE.
>>
>> Signed-off-by: Xinliang Liu 
>> Signed-off-by: Xinwei Kong 
>> Signed-off-by: Andy Green 
>> ---
>>  drivers/gpu/drm/hisilicon/hisi_drm_ade.c | 78 
>> 
>>  drivers/gpu/drm/hisilicon/hisi_drm_ade.h | 16 +++
>>  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 19 +++-
>>  3 files changed, 112 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_ade.h
>>
>> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c 
>> b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
>> index b0976c3..acb11e7 100644
>> --- a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
>> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
>> @@ -267,7 +267,79 @@ static void ade_power_down(struct ade_hw_ctx *ctx)
>>   ctx->power_on = false;
>>  }
>>
>> +static struct drm_crtc *hisi_get_crtc_from_index(struct drm_device *dev,
>> +  unsigned int index)
>
> Ugly that you had to add this, but unfortunately necessary :( Fixing up
> the drm vblank hooks so that they deal with struct drm_crtc directly is
> somewhere on my todo. But drm_irq.c is still a bit a mess, so this is some
> ways off still.
>
> What might be possible as a follow-up cleanup though is to add
> vblank_enable and vblank_disable functions to struct
> drm_crtc_helper_funcs. And then provide this code here to map from int
> index to struct drm_crtc * as helpers in a new drm_vblank_helper.c file.
> That might be a good intermediate step.

I would like to have a try to make this intermediate step patch and
send out for review soon.

> But nothing that needs to be done before merging hisilicon, that's for
> sure.
>
> One more comment below.
>
>> +{
>> + unsigned int index_tmp = 0;
>> + struct drm_crtc *crtc;
>> +
>> + list_for_each_entry(crtc, >mode_config.crtc_list, head) {
>> + if (index_tmp == index)
>> + return crtc;
>> +
>> + index_tmp++;
>> + }
>> +
>> + WARN_ON(true);
>> +}
>> +
>> +int ade_enable_vblank(struct drm_device *dev, int crtc_index)
>> +{
>> + struct drm_crtc *crtc = hisi_get_crtc_from_index(dev, crtc_index);
>> + struct ade_crtc *acrtc = to_ade_crtc(crtc);
>> + struct ade_hw_ctx *ctx = acrtc->ctx;
>> + void __iomem *base = ctx->base;
>> + u32 intr_en;
>> +
>> + DRM_INFO("enable_vblank enter.\n");
>> + if (!ctx->power_on)
>> + (void)ade_power_up(ctx);
>> +
>> + intr_en = readl(base + LDI_INT_EN);
>> + intr_en |= LDI_ISR_FRAME_END_INT;
>> + writel(intr_en, base + LDI_INT_EN);
>>
>> + return 0;
>> +}
>> +
>> +void ade_disable_vblank(struct drm_device *dev, int crtc_index)
>> +{
>> + struct drm_crtc *crtc = hisi_get_crtc_from_index(dev, crtc_index);
>> + struct ade_crtc *acrtc = to_ade_crtc(crtc);
>> + struct ade_hw_ctx *ctx = acrtc->ctx;
>> + void __iomem *base = ctx->base;
>> + u32 intr_en;
>> +
>> + DRM_INFO("disable_vblank enter.\n");
>> + if (!ctx->power_on) {
>> + DRM_ERROR("power is down! vblank disable fail\n");
>> + return;
>> + }
>> + intr_en = readl(base + LDI_INT_EN);
>> + intr_en &= ~LDI_ISR_FRAME_END_INT;
>> + writel(intr_en, base + LDI_INT_EN);
>> +}
>> +
>> +static irqreturn_t ade_irq_handler(int irq, void *data)
>> +{
>> + struct ade_crtc *acrtc = data;
>> + struct ade_hw_ctx *ctx = acrtc->ctx;
>> + struct drm_crtc *crtc = >base;
>> + struct drm_device *dev = crtc->dev;
>> + void __iomem *base = ctx->base;
>> + u32 status;
>> +
>> + status = readl(base + LDI_MSK_INT);
>> + /* DRM_INFO("LDI IRQ: status=0x%X\n",status); */
>> +
>> + /* vblank irq */
>> + if (status & LDI_ISR_FRAME_END_INT) {
>> + writel(LDI_ISR_FRAME_END_INT, base + LDI_INT_CLR);
>> + drm_handle_vblank(dev, drm_crtc_index(crtc));
>
> drm_crtc_handle_vblank please. At least when calling into the vblank code
> drivers don't have to do the struct drm_crtc -> int index conversion any
> more. Please make sure you do that everywhere, in case I've missed one.

will use drm_crtc_handle_vblank in v3.

Thanks,
-xinliang

>
> Cheers, Daniel
>
>> + }
>> +
>> + return IRQ_HANDLED;
>> +}
>>
>>  /*
>>   * set modules' reset mode: by software or hardware
>> @@ -858,6 +930,12 @@ static int ade_bind(struct device *dev, struct device 
>> *master, void *data)
>>   if (ret)
>>   return ret;
>>
>> + /* vblank irq init */
>> + ret = request_irq(ctx->irq, ade_irq_handler, DRIVER_IRQ_SHARED,
>> +   drm_dev->driver->name, acrtc);
>> + if (ret)
>> + return ret;
>> +
>>   return 0;
>>  }
>>
>> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_ade.h 
>> b/drivers/gpu/drm/hisilicon/hisi_drm_ade.h
>> new file mode 100644
>> index 000..d1d7b5d
>> --- 

[PATCH 2/2] virtio-gpu: update cursor after scanout

2015-12-01 Thread Dave Airlie
On 13 November 2015 at 23:00, Marc-André Lureau
 wrote:
> It seems appropriate for paravirtual hardware to reset cursor when the
> resolution changes, that way the cursor is removed if the machine is
> forcefully rebooted for ex. That's what the QXL/Spice server does. In
> order for virtio-gpu to work will with the Spice server, set the cursor
> again after changing the scanout.

I'm really not sure about this, I think we should probably have qemu
do this if necessary.

Normal GPU hw the cursor is independant from the modesetting, and we
turn it on/off.

I don't think the virt GPU should operate differently here.

Dave.


[PATCH v4 2/3] drm/atomic-helper: Implement subsystem-level suspend/resume

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 10:57:00AM +0100, Thierry Reding wrote:
> From: Thierry Reding 
> 
> Provide subsystem-level suspend and resume helpers that can be used to
> implement suspend/resume on atomic mode-setting enabled drivers.
> 
> v2: simplify locking, enhance kerneldoc comments
> v3: pass lock acquisition context by parameter, improve kerneldoc
> v4: - remove redundant code (already provided by atomic helpers)
>   (Maarten Lankhorst)
> - move backoff dance from drm_modeset_lock_all_ctx() into suspend
>   helper (Daniel Vetter)
> 
> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 163 
> +++-
>  drivers/gpu/drm/drm_crtc_helper.c   |   6 ++
>  include/drm/drm_atomic_helper.h |   6 ++
>  3 files changed, 174 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index 3731a26979bc..1b51722b2a00 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1818,6 +1818,162 @@ commit:
>  }
>  
>  /**
> + * drm_atomic_helper_disable_all - disable all currently active outputs
> + * @dev: DRM device
> + * @ctx: lock acquisition context
> + *
> + * Loops through all connectors, finding those that aren't turned off and 
> then
> + * turns them off by setting their DPMS mode to OFF and deactivating the CRTC
> + * that they are connected to.
> + *
> + * This is used for example in suspend/resume to disable all currently active
> + * functions when suspending.
> + *
> + * Note that if callers haven't already acquired all modeset locks this might
> + * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
> + *
> + * Returns:
> + * 0 on success or a negative error code on failure.
> + *
> + * See also:
> + * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
> + */
> +int drm_atomic_helper_disable_all(struct drm_device *dev,
> +   struct drm_modeset_acquire_ctx *ctx)
> +{
> + struct drm_atomic_state *state;
> + struct drm_connector *conn;
> + int err;
> +
> + state = drm_atomic_state_alloc(dev);
> + if (!state)
> + return -ENOMEM;
> +
> + state->acquire_ctx = ctx;
> +
> + drm_for_each_connector(conn, dev) {
> + struct drm_crtc *crtc = conn->state->crtc;
> + struct drm_crtc_state *crtc_state;
> +
> + if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
> + continue;
> +
> + crtc_state = drm_atomic_get_crtc_state(state, crtc);
> + if (IS_ERR(crtc_state)) {
> + err = PTR_ERR(crtc_state);
> + goto free;
> + }
> +
> + crtc_state->active = false;
> + }
> +
> + err = drm_atomic_commit(state);
> +
> +free:
> + if (err < 0)
> + drm_atomic_state_free(state);
> +
> + return err;
> +}
> +EXPORT_SYMBOL(drm_atomic_helper_disable_all);
> +
> +/**
> + * drm_atomic_helper_suspend - subsystem-level suspend helper
> + * @dev: DRM device
> + *
> + * Duplicates the current atomic state, disables all active outputs and then
> + * returns a pointer to the original atomic state to the caller. Drivers can
> + * pass this pointer to the drm_atomic_helper_resume() helper upon resume to
> + * restore the output configuration that was active at the time the system
> + * entered suspend.
> + *
> + * Note that it is potentially unsafe to use this. The atomic state object
> + * returned by this function is assumed to be persistent. Drivers must ensure
> + * that this holds true. Before calling this function, drivers must make sure
> + * to suspend fbdev emulation so that nothing can be using the device.
> + *
> + * Returns:
> + * A pointer to a copy of the state before suspend on success or an 
> ERR_PTR()-
> + * encoded error code on failure. Drivers should store the returned atomic
> + * state object and pass it to the drm_atomic_helper_resume() helper upon
> + * resume.
> + *
> + * See also:
> + * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
> + * drm_atomic_helper_resume()
> + */
> +struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
> +{
> + struct drm_modeset_acquire_ctx ctx;
> + struct drm_atomic_state *state;
> + int err;
> +
> + drm_modeset_acquire_init(, 0);
> +
> +retry:
> + err = drm_modeset_lock_all_ctx(dev, );
> + if (err < 0) {
> + if (err == -EDEADLK) {
> + drm_modeset_backoff();
> + goto retry;
> + }
> +
> + state = ERR_PTR(err);
> + goto fini;
> + }
> +
> + state = drm_atomic_helper_duplicate_state(dev, );
> + if (IS_ERR(state))
> + goto unlock;
> +
> + err = drm_atomic_helper_disable_all(dev, );

If the driver has some internal state protected with it's own locking the
above two function might return 

[PATCH v4 1/3] drm: Implement drm_modeset_lock_all_ctx()

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 10:56:59AM +0100, Thierry Reding wrote:
> From: Thierry Reding 
> 
> This function is like drm_modeset_lock_all(), but it takes the lock
> acquisition context as a parameter rather than storing it in the DRM
> device's mode_config structure.
> 
> Implement drm_modeset_{,un}lock_all() in terms of the new function for
> better code reuse, and add a note to the kerneldoc that new code should
> use the new functions.
> 
> v2: improve kerneldoc
> v4: rename drm_modeset_lock_all_crtcs() to drm_modeset_lock_all_ctx()
> and take mode_config's .connection_mutex instead of .mutex lock to
> avoid lock inversion (Daniel Vetter), use drm_modeset_drop_locks()
> which is now the equivalent of drm_modeset_unlock_all_ctx()
> 
> Signed-off-by: Thierry Reding 
> ---
>  drivers/gpu/drm/drm_atomic.c   |  3 +-
>  drivers/gpu/drm/drm_modeset_lock.c | 82 
> --
>  include/drm/drm_modeset_lock.h |  4 +-
>  3 files changed, 56 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 55b4debad79b..4cbe7c07231c 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,8 +1192,7 @@ retry:
>  state->acquire_ctx);

You forgot to remove the connection_mutex right above here
>   if (ret)
>   goto retry;
> - ret = drm_modeset_lock_all_crtcs(state->dev,
> -  state->acquire_ctx);
> + ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
>   if (ret)
>   goto retry;
>  }
> diff --git a/drivers/gpu/drm/drm_modeset_lock.c 
> b/drivers/gpu/drm/drm_modeset_lock.c
> index 6675b1428410..341158c92027 100644
> --- a/drivers/gpu/drm/drm_modeset_lock.c
> +++ b/drivers/gpu/drm/drm_modeset_lock.c
> @@ -57,11 +57,18 @@
>  
>  /**
>   * drm_modeset_lock_all - take all modeset locks
> - * @dev: drm device
> + * @dev: DRM device
>   *
>   * This function takes all modeset locks, suitable where a more fine-grained
> - * scheme isn't (yet) implemented. Locks must be dropped with
> - * drm_modeset_unlock_all.
> + * scheme isn't (yet) implemented. Locks must be dropped by calling the
> + * drm_modeset_unlock_all() function.
> + *
> + * This function is deprecated. It allocates a lock acquisition context and
> + * stores it in the DRM device's ->mode_config. This facilitate conversion of
> + * existing code because it removes the need to manually deal with the
> + * acquisition context, but it is also brittle because the context is global
> + * and care must be taken not to nest calls. New code should use the
> + * drm_modeset_lock_all_ctx() function and pass in the context explicitly.
>   */
>  void drm_modeset_lock_all(struct drm_device *dev)
>  {
> @@ -78,39 +85,43 @@ void drm_modeset_lock_all(struct drm_device *dev)
>   drm_modeset_acquire_init(ctx, 0);
>  
>  retry:
> - ret = drm_modeset_lock(>connection_mutex, ctx);
> - if (ret)
> - goto fail;
> - ret = drm_modeset_lock_all_crtcs(dev, ctx);
> - if (ret)
> - goto fail;
> + ret = drm_modeset_lock_all_ctx(dev, ctx);
> + if (ret < 0) {
> + if (ret == -EDEADLK) {
> + drm_modeset_backoff(ctx);
> + goto retry;
> + }
> +
> + drm_modeset_acquire_fini(ctx);
> + kfree(ctx);
> + return;
> + }
>  
>   WARN_ON(config->acquire_ctx);
>  
> - /* now we hold the locks, so now that it is safe, stash the
> -  * ctx for drm_modeset_unlock_all():
> + /*
> +  * We hold the locks now, so it is safe to stash the acquisition
> +  * context for drm_modeset_unlock_all().
>*/
>   config->acquire_ctx = ctx;
>  
>   drm_warn_on_modeset_not_all_locked(dev);
> -
> - return;
> -
> -fail:
> - if (ret == -EDEADLK) {
> - drm_modeset_backoff(ctx);
> - goto retry;
> - }
> -
> - kfree(ctx);
>  }
>  EXPORT_SYMBOL(drm_modeset_lock_all);
>  
>  /**
>   * drm_modeset_unlock_all - drop all modeset locks
> - * @dev: device
> + * @dev: DRM device
> + *
> + * This function drops all modeset locks taken by a previous call to the
> + * drm_modeset_lock_all() function.
>   *
> - * This function drop all modeset locks taken by drm_modeset_lock_all.
> + * This function is deprecated. It uses the lock acquisition context stored
> + * in the DRM device's ->mode_config. This facilitates conversion of existing
> + * code because it removes the need to manually deal with the acquisition
> + * context, but it is also brittle because the context is global and care 
> must
> + * be taken not to nest calls. New code should pass the acquisition context
> + * directly to the drm_modeset_drop_locks() function.
>   */
>  void drm_modeset_unlock_all(struct drm_device *dev)
>  {
> @@ -431,14 +442,27 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
>  

[radeon r100] when ring test fails, provide users with option to test

2015-12-01 Thread Pavel Machek
On Mon 2015-11-30 09:39:54, Christian König wrote:
> On 29.11.2015 23:22, Pavel Machek wrote:
> >On Sun 2015-11-29 20:48:53, Christian König wrote:
> >>On 28.11.2015 21:58, Pavel Machek wrote:
> >>>Ring test failure is often caused by too high agpmode. Tell the user
> >>>what to try.
> >>>
> >>>Signed-off-by: Pavel Machek 
> >>NAK, the ring test can fail for any number of reasons and the agpmode is
> >>actually rather unlikely to be the cause.
> >Well, when I asked on the list "why this is happened" I got "umm,
> >noone knows" response that was not exactly helpful. And then someone
> >told me about agpmode.
> >
> >If you know about the reasons it can fail, could you list them near
> >the DRM_ERROR, at least as a comment?
> 
> Well as I said, that could be any number of reasons. Some of them even
> completely unrelated to the driver itself.
> 
> E.g. BIOS setting, faulty hardware, problems with the writeback etc... There
> is really not a list you could give here.
> 
> Lowering the agpmode usually helps more to prevent random corruptions and
> problems under load.

Take a look at

http://www.gossamer-threads.com/lists/linux/kernel/2197183

. I had a problem, you did not know how to debug it, but it already
happened to pebolle at tiscali ... and yes, it was agpmode. That
problem is clearly more common then you realize... So this should go
in.

Pavel

> >>>--- a/drivers/gpu/drm/radeon/r100.c
> >>>+++ b/drivers/gpu/drm/radeon/r100.c
> >>>@@ -3665,7 +3665,7 @@ int r100_ring_test(struct radeon_device *rdev, 
> >>>struct radeon_ring *ring)
> >>>   if (i < rdev->usec_timeout) {
> >>>   DRM_INFO("ring test succeeded in %d usecs\n", i);
> >>>   } else {
> >>>-  DRM_ERROR("radeon: ring test failed (scratch(0x%04X)=0x%08X)\n",
> >>>+  DRM_ERROR("radeon: ring test failed (scratch(0x%04X)=0x%08X), 
> >>>try radeon.agpmode=1?\n",
> >>> scratch, tmp);
> >>>   r = -EINVAL;
> >>>   }
> >>>

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


[PATCH] drm: Fix an unwanted master inheritance

2015-12-01 Thread Emil Velikov
Hi Thomas,

Something doesn't feel quite right, please read on.

On 30 November 2015 at 12:44, Thomas Hellstrom  wrote:
> A client calling drmSetMaster() using a file descriptor that was opened
> when another client was master would inherit the latter client's master
> object and all it's authenticated clients.
>
> This is unwanted behaviour, and when this happens, instead allocate a
> brand new master object for the client calling drmSetMaster().
>
> Signed-off-by: Thomas Hellstrom 
> ---
>  drivers/gpu/drm/drm_drv.c  | 12 +++
>  drivers/gpu/drm/drm_fops.c | 80 
> ++
>  include/drm/drmP.h |  6 
>  3 files changed, 70 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 9362609..1f072ba 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -160,6 +160,18 @@ int drm_setmaster_ioctl(struct drm_device *dev, void 
> *data,
> goto out_unlock;
> }
>
> +   if (!file_priv->allowed_master) {
> +   struct drm_master *saved_master = file_priv->master;
> +
> +   ret = drm_new_set_master(dev, file_priv);
> +   if (ret)
> +   file_priv->master = saved_master;
Imho this shouldn'e belong here but in drm_new_set_master() - i.e. it
should unwind things on error. Similarly, although we restore the old
drm_master (below), we still have is_master, allowed_master and
authenticated set. Thus one can reuse the elevated credentials (is
this the right terminology?) despite that the ioctl has failed.

> +   else
> +   drm_master_put(_master);
> +
> +   goto out_unlock;
> +   }
> +
> file_priv->minor->master = drm_master_get(file_priv->master);
> file_priv->is_master = 1;
> if (dev->driver->master_set) {
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index c59ce4d..4b5c11c 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -126,6 +126,56 @@ static int drm_cpu_valid(void)
>  }
>
>  /**
> + * drm_new_set_master - Allocate a new master object and become master for 
> the
> + * associated master realm.
> + *
> + * @dev: The associated device.
> + * @fpriv: File private identifying the client.
> + *
> + * This function must be called with dev::struct_mutex held. Returns negative
> + * error code on failure, zero on success.
> + */
> +int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
> +{
> +   int ret;
> +
> +   lockdep_assert_held_once(>master_mutex);
> +   /* create a new master */
> +   fpriv->minor->master = drm_master_create(fpriv->minor);
> +   if (!fpriv->minor->master)
> +   return -ENOMEM;
> +
> +   fpriv->is_master = 1;
> +   fpriv->allowed_master = 1;
> +
> +   /* take another reference for the copy in the local file priv */
> +   fpriv->master = drm_master_get(fpriv->minor->master);
> +
> +   fpriv->authenticated = 1;
> +
> +   if (dev->driver->master_create) {
> +   ret = dev->driver->master_create(dev, fpriv->master);
> +   if (ret) {
> +   /* drop both references if this fails */
> +   drm_master_put(>minor->master);
> +   drm_master_put(>master);
> +   return ret;
> +   }
> +   }
> +   if (dev->driver->master_set) {
> +   ret = dev->driver->master_set(dev, fpriv, true);
> +   if (ret) {
Afaics both of these callbacks are available from legacy(UMS) drivers
aren't they ? With the radeon UMS removal patches in the works, this
leaves vmwgfx.

Either way, perhaps we should set is_master, allowed_master and
authenticated after these two ? Or alternatively restore the original
values on error.

Did I miss something or the above sounds about right ?

Regards,
Emil


[PATCH v4 3/3] drm/tegra: Implement subsystem-level suspend/resume

2015-12-01 Thread Thierry Reding
From: Thierry Reding 

Use the drm_atomic_helper_suspend() and drm_atomic_helper_resume()
helpers to implement subsystem-level suspend/resume.

v2: suspend framebuffer device to avoid concurrency issues
v3: resume fbdev on failure to suspend (Emil Velikov)

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/tegra/drm.c | 12 
 drivers/gpu/drm/tegra/drm.h |  4 
 drivers/gpu/drm/tegra/fb.c  | 24 
 3 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index c8a5dce4e46e..639a1041e178 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1021,8 +1021,17 @@ static int host1x_drm_remove(struct host1x_device *dev)
 static int host1x_drm_suspend(struct device *dev)
 {
struct drm_device *drm = dev_get_drvdata(dev);
+   struct tegra_drm *tegra = drm->dev_private;

drm_kms_helper_poll_disable(drm);
+   tegra_drm_fb_suspend(drm);
+
+   tegra->state = drm_atomic_helper_suspend(drm);
+   if (IS_ERR(tegra->state)) {
+   tegra_drm_fb_resume(drm);
+   drm_kms_helper_poll_enable(drm);
+   return PTR_ERR(tegra->state);
+   }

return 0;
 }
@@ -1030,7 +1039,10 @@ static int host1x_drm_suspend(struct device *dev)
 static int host1x_drm_resume(struct device *dev)
 {
struct drm_device *drm = dev_get_drvdata(dev);
+   struct tegra_drm *tegra = drm->dev_private;

+   drm_atomic_helper_resume(drm, tegra->state);
+   tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);

return 0;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 69566b616f88..dd9bb4816d0b 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -57,6 +57,8 @@ struct tegra_drm {
struct work_struct work;
struct mutex lock;
} commit;
+
+   struct drm_atomic_state *state;
 };

 struct tegra_drm_client;
@@ -265,6 +267,8 @@ int tegra_drm_fb_prepare(struct drm_device *drm);
 void tegra_drm_fb_free(struct drm_device *drm);
 int tegra_drm_fb_init(struct drm_device *drm);
 void tegra_drm_fb_exit(struct drm_device *drm);
+void tegra_drm_fb_suspend(struct drm_device *drm);
+void tegra_drm_fb_resume(struct drm_device *drm);
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
 void tegra_fb_output_poll_changed(struct drm_device *drm);
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index ede9e94f3312..a7213f30fb20 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */

+#include 
+
 #include "drm.h"
 #include "gem.h"

@@ -413,3 +415,25 @@ void tegra_drm_fb_exit(struct drm_device *drm)
tegra_fbdev_exit(tegra->fbdev);
 #endif
 }
+
+void tegra_drm_fb_suspend(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+   struct tegra_drm *tegra = drm->dev_private;
+
+   console_lock();
+   drm_fb_helper_set_suspend(>fbdev->base, 1);
+   console_unlock();
+#endif
+}
+
+void tegra_drm_fb_resume(struct drm_device *drm)
+{
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+   struct tegra_drm *tegra = drm->dev_private;
+
+   console_lock();
+   drm_fb_helper_set_suspend(>fbdev->base, 0);
+   console_unlock();
+#endif
+}
-- 
2.5.0



[PATCH v4 2/3] drm/atomic-helper: Implement subsystem-level suspend/resume

2015-12-01 Thread Thierry Reding
From: Thierry Reding 

Provide subsystem-level suspend and resume helpers that can be used to
implement suspend/resume on atomic mode-setting enabled drivers.

v2: simplify locking, enhance kerneldoc comments
v3: pass lock acquisition context by parameter, improve kerneldoc
v4: - remove redundant code (already provided by atomic helpers)
  (Maarten Lankhorst)
- move backoff dance from drm_modeset_lock_all_ctx() into suspend
  helper (Daniel Vetter)

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_atomic_helper.c | 163 +++-
 drivers/gpu/drm/drm_crtc_helper.c   |   6 ++
 include/drm/drm_atomic_helper.h |   6 ++
 3 files changed, 174 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 3731a26979bc..1b51722b2a00 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1818,6 +1818,162 @@ commit:
 }

 /**
+ * drm_atomic_helper_disable_all - disable all currently active outputs
+ * @dev: DRM device
+ * @ctx: lock acquisition context
+ *
+ * Loops through all connectors, finding those that aren't turned off and then
+ * turns them off by setting their DPMS mode to OFF and deactivating the CRTC
+ * that they are connected to.
+ *
+ * This is used for example in suspend/resume to disable all currently active
+ * functions when suspending.
+ *
+ * Note that if callers haven't already acquired all modeset locks this might
+ * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ *
+ * See also:
+ * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
+ */
+int drm_atomic_helper_disable_all(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+   struct drm_atomic_state *state;
+   struct drm_connector *conn;
+   int err;
+
+   state = drm_atomic_state_alloc(dev);
+   if (!state)
+   return -ENOMEM;
+
+   state->acquire_ctx = ctx;
+
+   drm_for_each_connector(conn, dev) {
+   struct drm_crtc *crtc = conn->state->crtc;
+   struct drm_crtc_state *crtc_state;
+
+   if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
+   continue;
+
+   crtc_state = drm_atomic_get_crtc_state(state, crtc);
+   if (IS_ERR(crtc_state)) {
+   err = PTR_ERR(crtc_state);
+   goto free;
+   }
+
+   crtc_state->active = false;
+   }
+
+   err = drm_atomic_commit(state);
+
+free:
+   if (err < 0)
+   drm_atomic_state_free(state);
+
+   return err;
+}
+EXPORT_SYMBOL(drm_atomic_helper_disable_all);
+
+/**
+ * drm_atomic_helper_suspend - subsystem-level suspend helper
+ * @dev: DRM device
+ *
+ * Duplicates the current atomic state, disables all active outputs and then
+ * returns a pointer to the original atomic state to the caller. Drivers can
+ * pass this pointer to the drm_atomic_helper_resume() helper upon resume to
+ * restore the output configuration that was active at the time the system
+ * entered suspend.
+ *
+ * Note that it is potentially unsafe to use this. The atomic state object
+ * returned by this function is assumed to be persistent. Drivers must ensure
+ * that this holds true. Before calling this function, drivers must make sure
+ * to suspend fbdev emulation so that nothing can be using the device.
+ *
+ * Returns:
+ * A pointer to a copy of the state before suspend on success or an ERR_PTR()-
+ * encoded error code on failure. Drivers should store the returned atomic
+ * state object and pass it to the drm_atomic_helper_resume() helper upon
+ * resume.
+ *
+ * See also:
+ * drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
+ * drm_atomic_helper_resume()
+ */
+struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
+{
+   struct drm_modeset_acquire_ctx ctx;
+   struct drm_atomic_state *state;
+   int err;
+
+   drm_modeset_acquire_init(, 0);
+
+retry:
+   err = drm_modeset_lock_all_ctx(dev, );
+   if (err < 0) {
+   if (err == -EDEADLK) {
+   drm_modeset_backoff();
+   goto retry;
+   }
+
+   state = ERR_PTR(err);
+   goto fini;
+   }
+
+   state = drm_atomic_helper_duplicate_state(dev, );
+   if (IS_ERR(state))
+   goto unlock;
+
+   err = drm_atomic_helper_disable_all(dev, );
+   if (err < 0) {
+   drm_atomic_state_free(state);
+   state = ERR_PTR(err);
+   goto unlock;
+   }
+
+unlock:
+   drm_modeset_drop_locks();
+fini:
+   drm_modeset_acquire_fini();
+   return state;
+}
+EXPORT_SYMBOL(drm_atomic_helper_suspend);
+
+/**
+ * drm_atomic_helper_resume - subsystem-level 

[PATCH v4 1/3] drm: Implement drm_modeset_lock_all_ctx()

2015-12-01 Thread Thierry Reding
From: Thierry Reding 

This function is like drm_modeset_lock_all(), but it takes the lock
acquisition context as a parameter rather than storing it in the DRM
device's mode_config structure.

Implement drm_modeset_{,un}lock_all() in terms of the new function for
better code reuse, and add a note to the kerneldoc that new code should
use the new functions.

v2: improve kerneldoc
v4: rename drm_modeset_lock_all_crtcs() to drm_modeset_lock_all_ctx()
and take mode_config's .connection_mutex instead of .mutex lock to
avoid lock inversion (Daniel Vetter), use drm_modeset_drop_locks()
which is now the equivalent of drm_modeset_unlock_all_ctx()

Signed-off-by: Thierry Reding 
---
 drivers/gpu/drm/drm_atomic.c   |  3 +-
 drivers/gpu/drm/drm_modeset_lock.c | 82 --
 include/drm/drm_modeset_lock.h |  4 +-
 3 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 55b4debad79b..4cbe7c07231c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1192,8 +1192,7 @@ retry:
   state->acquire_ctx);
if (ret)
goto retry;
-   ret = drm_modeset_lock_all_crtcs(state->dev,
-state->acquire_ctx);
+   ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
if (ret)
goto retry;
 }
diff --git a/drivers/gpu/drm/drm_modeset_lock.c 
b/drivers/gpu/drm/drm_modeset_lock.c
index 6675b1428410..341158c92027 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -57,11 +57,18 @@

 /**
  * drm_modeset_lock_all - take all modeset locks
- * @dev: drm device
+ * @dev: DRM device
  *
  * This function takes all modeset locks, suitable where a more fine-grained
- * scheme isn't (yet) implemented. Locks must be dropped with
- * drm_modeset_unlock_all.
+ * scheme isn't (yet) implemented. Locks must be dropped by calling the
+ * drm_modeset_unlock_all() function.
+ *
+ * This function is deprecated. It allocates a lock acquisition context and
+ * stores it in the DRM device's ->mode_config. This facilitate conversion of
+ * existing code because it removes the need to manually deal with the
+ * acquisition context, but it is also brittle because the context is global
+ * and care must be taken not to nest calls. New code should use the
+ * drm_modeset_lock_all_ctx() function and pass in the context explicitly.
  */
 void drm_modeset_lock_all(struct drm_device *dev)
 {
@@ -78,39 +85,43 @@ void drm_modeset_lock_all(struct drm_device *dev)
drm_modeset_acquire_init(ctx, 0);

 retry:
-   ret = drm_modeset_lock(>connection_mutex, ctx);
-   if (ret)
-   goto fail;
-   ret = drm_modeset_lock_all_crtcs(dev, ctx);
-   if (ret)
-   goto fail;
+   ret = drm_modeset_lock_all_ctx(dev, ctx);
+   if (ret < 0) {
+   if (ret == -EDEADLK) {
+   drm_modeset_backoff(ctx);
+   goto retry;
+   }
+
+   drm_modeset_acquire_fini(ctx);
+   kfree(ctx);
+   return;
+   }

WARN_ON(config->acquire_ctx);

-   /* now we hold the locks, so now that it is safe, stash the
-* ctx for drm_modeset_unlock_all():
+   /*
+* We hold the locks now, so it is safe to stash the acquisition
+* context for drm_modeset_unlock_all().
 */
config->acquire_ctx = ctx;

drm_warn_on_modeset_not_all_locked(dev);
-
-   return;
-
-fail:
-   if (ret == -EDEADLK) {
-   drm_modeset_backoff(ctx);
-   goto retry;
-   }
-
-   kfree(ctx);
 }
 EXPORT_SYMBOL(drm_modeset_lock_all);

 /**
  * drm_modeset_unlock_all - drop all modeset locks
- * @dev: device
+ * @dev: DRM device
+ *
+ * This function drops all modeset locks taken by a previous call to the
+ * drm_modeset_lock_all() function.
  *
- * This function drop all modeset locks taken by drm_modeset_lock_all.
+ * This function is deprecated. It uses the lock acquisition context stored
+ * in the DRM device's ->mode_config. This facilitates conversion of existing
+ * code because it removes the need to manually deal with the acquisition
+ * context, but it is also brittle because the context is global and care must
+ * be taken not to nest calls. New code should pass the acquisition context
+ * directly to the drm_modeset_drop_locks() function.
  */
 void drm_modeset_unlock_all(struct drm_device *dev)
 {
@@ -431,14 +442,27 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
 }
 EXPORT_SYMBOL(drm_modeset_unlock);

-/* In some legacy codepaths it's convenient to just grab all the crtc and plane
- * related locks. */
-int drm_modeset_lock_all_crtcs(struct drm_device *dev,
-   struct drm_modeset_acquire_ctx *ctx)
+/**
+ * drm_modeset_lock_all_ctx - take all 

[PATCH v2 04/10] drm/hisilicon: Add crtc funcs for ADE

2015-12-01 Thread Xinliang Liu
le if vsw exceed 15.
You are right maybe ​
​
DRM_DEBUG_DRIVER is better.
​

>
> > +   vsw = 15;
> > +   }
> > +
> > +   writel((hbp << 20) | (hfp << 0), base + LDI_HRZ_CTRL0);
> > +   /* p3-73 6220V100 pdf:
> > +*  "The configured value is the actual width - 1"
> > +*/
> > +   writel(hsw - 1, base + LDI_HRZ_CTRL1);
> > +   writel((vbp << 20) | (vfp << 0), base + LDI_VRT_CTRL0);
> > +   /* p3-74 6220V100 pdf:
> > +*  "The configured value is the actual width - 1"
> > +*/
> > +   writel(vsw - 1, base + LDI_VRT_CTRL1);
> > +
> > +   /* p3-75 6220V100 pdf:
> > +*  "The configured value is the actual width - 1"
> > +*/
> > +   writel(((out_h - 1) << 20) | ((out_w - 1) << 0),
> > +  base + LDI_DSP_SIZE);
> > +   writel(plr_flags, base + LDI_PLR_CTRL);
> > +
> > +   ret = clk_set_rate(ctx->ade_pix_clk, mode->clock * 1000);
> > +   /* Success should be guaranteed in aotomic_check
> > +* failer shouldn't happen here
> > +*/
> > +   if (ret)
> > +   DRM_ERROR("set ade_pixel_clk_rate fail\n");
> DItto
>
​will use
​
DRM_DEBUG_DRIVER
​ in v3.​
​


>
> > +   adj_mode->clock = clk_get_rate(ctx->ade_pix_clk) / 1000;
> > +
> > +   /* ctran6 setting */
> > +   writel(1, base + ADE_CTRAN_DIS(ADE_CTRAN6));
> > +   writel(out_w * out_h - 1, base +
> ADE_CTRAN_IMAGE_SIZE(ADE_CTRAN6));
> > +   acrtc->use_mask |= BIT(ADE_CTRAN_BIT_OFST + ADE_CTRAN6);
> > +   DRM_INFO("set mode: %dx%d\n", out_w, out_h);
> > +
> ​​
> ​​
> DRM_DEBUG_DRIVER ?
>
​
will use
​
DRM_DEBUG_DRIVER
​ in v3.
​


>
> > +   /*
> > +* other parameters setting
> > +*/
> > +   writel(BIT(0), base + LDI_WORK_MODE);
> > +   writel((0x3c << 6) | (ADE_OUT_RGB_888 << 3) | BIT(2) | BIT(0),
> > +  base + LDI_CTRL);
> > +   set_reg(base + LDI_DE_SPACE_LOW, 0x1, 1, 1);
> > +}
> > +
> > +static int ade_power_up(struct ade_hw_ctx *ctx)
> > +{
> > +   void __iomem *media_base = ctx->media_base;
> > +   int ret;
> > +
> > +   ret = clk_set_rate(ctx->ade_core_clk, ctx->ade_core_rate);
> > +   if (ret) {
> > +   DRM_ERROR("clk_set_rate ade_core_rate error\n");
> How about the following (or alike) less cryptic and more informative
> message. Other places could use a similar treatment.
>
> "Failed to set rate X clk (%d)\n", ret ?
>
​yes, good advice. will be fixed in v3.
​


>
>
> > +static void ade_crtc_enable(struct drm_crtc *crtc)
> > +{
> > +   struct ade_crtc *acrtc = to_ade_crtc(crtc);
> > +   struct ade_hw_ctx *ctx = acrtc->ctx;
> > +   int ret;
> > +
> > +   DRM_DEBUG_DRIVER("enter.\n");
> Does this and the remaining
> ​​
> DEBUG_DRIVER(enter|exit) messages provide
> any meaningful input, past the driver
> ​​
> development stage ?
>
> > +   if (acrtc->enable)
> > +   return;
> Esp. since we have cases like this where no message is available.
>
yeap, these
​
 DEBUG_DRIVER(enter|exit) messages​ are for
​
development stage.
Which forgot to be removed. will be removed in v3.

Thanks,
-xinliang


>
> Regards,
> Emil
>
-- next part --
An HTML attachment was scrubbed...
URL: 
<http://lists.freedesktop.org/archives/dri-devel/attachments/20151201/6a8126e9/attachment-0001.html>


[RFC PATCH] drm/edid: index CEA/HDMI mode tables using the VIC

2015-12-01 Thread Alex Deucher
On Tue, Dec 1, 2015 at 10:16 AM, Jani Nikula  wrote:
> Add a dummy entry to CEA/HDMI mode tables so they can be indexed
> directly using the VIC, avoiding a +1/-1 dance here and there. This adds
> clarity to the error checking for various functions that return the VIC
> on success and zero on failure; we now explicitly check for 0 instead of
> just subtracting one from an unsigned type.
>
> Cc: Ville Syrjälä 
> Signed-off-by: Jani Nikula 

Reviewed-by: Alex Deucher 

>
> ---
>
> This is on top of
>
> commit 4c6bcf44549907cb50b67f98eb13717a4adc6b33
> Author: Ville Syrjälä 
> Date:   Mon Nov 16 21:05:12 2015 +0200
>
> drm/edid: Make the detailed timing CEA/HDMI mode fixup accept up to 5kHz 
> clock difference
>
> in drm-intel/topic/drm-misc
> ---
>  drivers/gpu/drm/drm_edid.c | 84 
> --
>  1 file changed, 43 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index c214f1246cb4..aea09eae407e 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -637,8 +637,12 @@ static const struct minimode extra_modes[] = {
>  /*
>   * Probably taken from CEA-861 spec.
>   * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
> + *
> + * Index using the VIC.
>   */
>  static const struct drm_display_mode edid_cea_modes[] = {
> +   /* 0 - dummy, VICs start at 1 */
> +   { 0 },
> /* 1 - 640x480 at 60Hz */
> { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
>752, 800, 0, 480, 490, 492, 525, 0,
> @@ -987,9 +991,11 @@ static const struct drm_display_mode edid_cea_modes[] = {
>  };
>
>  /*
> - * HDMI 1.4 4k modes.
> + * HDMI 1.4 4k modes. Index using the VIC.
>   */
>  static const struct drm_display_mode edid_4k_modes[] = {
> +   /* 0 - dummy, VICs start at 1 */
> +   { 0 },
> /* 1 - 3840x2160 at 30Hz */
> { DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000,
>3840, 4016, 4104, 4400, 0,
> @@ -2548,13 +2554,13 @@ cea_mode_alternate_clock(const struct 
> drm_display_mode *cea_mode)
>  static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode 
> *to_match,
>  unsigned int clock_tolerance)
>  {
> -   u8 mode;
> +   u8 vic;
>
> if (!to_match->clock)
> return 0;
>
> -   for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
> -   const struct drm_display_mode *cea_mode = 
> _cea_modes[mode];
> +   for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
> +   const struct drm_display_mode *cea_mode = 
> _cea_modes[vic];
> unsigned int clock1, clock2;
>
> /* Check both 60Hz and 59.94Hz */
> @@ -2566,7 +2572,7 @@ static u8 drm_match_cea_mode_clock_tolerance(const 
> struct drm_display_mode *to_m
> continue;
>
> if (drm_mode_equal_no_clocks(to_match, cea_mode))
> -   return mode + 1;
> +   return vic;
> }
>
> return 0;
> @@ -2581,13 +2587,13 @@ static u8 drm_match_cea_mode_clock_tolerance(const 
> struct drm_display_mode *to_m
>   */
>  u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
>  {
> -   u8 mode;
> +   u8 vic;
>
> if (!to_match->clock)
> return 0;
>
> -   for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
> -   const struct drm_display_mode *cea_mode = 
> _cea_modes[mode];
> +   for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
> +   const struct drm_display_mode *cea_mode = 
> _cea_modes[vic];
> unsigned int clock1, clock2;
>
> /* Check both 60Hz and 59.94Hz */
> @@ -2597,7 +2603,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode 
> *to_match)
> if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
>  KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
> drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
> -   return mode + 1;
> +   return vic;
> }
> return 0;
>  }
> @@ -2612,10 +2618,7 @@ EXPORT_SYMBOL(drm_match_cea_mode);
>   */
>  enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code)
>  {
> -   /* return picture aspect ratio for video_code - 1 to access the
> -* right array element
> -   */
> -   return edid_cea_modes[video_code-1].picture_aspect_ratio;
> +   return edid_cea_modes[video_code].picture_aspect_ratio;
>  }
>  EXPORT_SYMBOL(drm_get_cea_aspect_ratio);
>
> @@ -2639,13 +2642,13 @@ hdmi_mode_alternate_clock(const struct 
> drm_display_mode *hdmi_mode)
>  static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode 
> *to_match,
>   unsigned int clock_tolerance)
>  {
> - 

[RFC PATCH 2/9] drm/rockchip: Use new vblank api drm_crtc_vblank_*

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 04:33:27PM +0800, Mark yao wrote:
> On 2015年12月01日 15:56, Daniel Stone wrote:
> >Hi,
> >
> >On 1 December 2015 at 03:26, Mark Yao  wrote:
> >>No functional update, drm_vblank_* is the legacy version of
> >>drm_crtc_vblank_*. and use new api make driver more clean.
> >>
> >>Signed-off-by: Mark Yao 
> >Heh, I had the same patch in my series to fix pageflip events.
> >
> >Reviewed-by: Daniel Stone 
> >
> >Cheers,
> >Daniel
> >
> >
> >
> 
> Hi Daniel
>I had picked your patch "[PATCH 1/2] drm/rockchip: Use CRTC vblank event
> interface" into my drm-next, this patch is base on it.

That really should be mentioned in the commit message, and you must keep
the signed-off-by chain intact when adapting or reusing other peoples
work.
-Daniel

> 
> Thanks for your review.
> 
> -- 
> ï¼­ark Yao
> 
> 
> ___
> 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] drm/atomic-helper: Grab connection_mutex while duplicating state

2015-12-01 Thread Maarten Lankhorst
Op 01-12-15 om 00:22 schreef Matt Roper:
> Callers of drm_atomic_helper_duplicate_state() may not have grabbed
> locks before calling this function.  We're not supposed to iterate over
> connectors without holding connection_mutex (since MST allows new
> connectors to be spawned at hotplug), so make sure we grab that
> ourselves before invoking drm_for_each_connector().  Failure to grab
> this lock would cause us to stumble over the assertion added in commit:
>
> commit 7a3f3d6667f5f9ffd1517f6b21d64bbf5312042c
> Author: Daniel Vetter 
> Date:   Thu Jul 9 23:44:28 2015 +0200
>
> drm: Check locking in drm_for_each_connector
>
> Cc: Daniel Vetter 
> Cc: Maarten Lankhorst 
> Signed-off-by: Matt Roper 
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 4 
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index 3731a26..e5d0b21 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -2478,6 +2478,10 @@ drm_atomic_helper_duplicate_state(struct drm_device 
> *dev,
>   }
>   }
>  
> + err = drm_modeset_lock(>mode_config.connection_mutex, ctx);
> + if (err)
> + goto free;
> +
>   drm_for_each_connector(conn, dev) {
>   struct drm_connector_state *conn_state;
>  
Thanks, that's a lot better than just a random hunk without explanation.

Signed-off-by: Maarten Lankhorst 


[Intel-gfx] [PATCH] drm/atomic-helper: Grab connection_mutex while duplicating state

2015-12-01 Thread Daniel Vetter
On Mon, Nov 30, 2015 at 03:22:49PM -0800, Matt Roper wrote:
> Callers of drm_atomic_helper_duplicate_state() may not have grabbed
> locks before calling this function.  We're not supposed to iterate over
> connectors without holding connection_mutex (since MST allows new
> connectors to be spawned at hotplug), so make sure we grab that
> ourselves before invoking drm_for_each_connector().  Failure to grab
> this lock would cause us to stumble over the assertion added in commit:
> 
> commit 7a3f3d6667f5f9ffd1517f6b21d64bbf5312042c
> Author: Daniel Vetter 
> Date:   Thu Jul 9 23:44:28 2015 +0200
> 
> drm: Check locking in drm_for_each_connector
> 
> Cc: Daniel Vetter 
> Cc: Maarten Lankhorst 
> Signed-off-by: Matt Roper 

These helpers are wip and Thierry is working on some additional
higher-level wrappers for bullet proof save/restore for atomic drivers.
It's very much intentinoal that this function here does _not_ grab any
locks - if it does the higher-level magic would be impossible.
-Daniel

> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
> b/drivers/gpu/drm/drm_atomic_helper.c
> index 3731a26..e5d0b21 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -2478,6 +2478,10 @@ drm_atomic_helper_duplicate_state(struct drm_device 
> *dev,
>   }
>   }
>  
> + err = drm_modeset_lock(>mode_config.connection_mutex, ctx);
> + if (err)
> + goto free;
> +
>   drm_for_each_connector(conn, dev) {
>   struct drm_connector_state *conn_state;
>  
> -- 
> 2.1.4
> 
> ___
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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


[RFC PATCH 8/9] drm: bridge/dw_hdmi: Covert to support atomic API

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 11:35:53AM +0800, Mark Yao wrote:
> Fill atomic needed funcs with default atomic helper library.
> 
> Rockchip use dw_hdmi, and drm/rockchip will covert to atomic api,
> we need dw_hdmi support atomic funcs.
> 
> Signed-off-by: Mark Yao 

Aren't there drivers around which use dw_hdmi and which are still not yet
atomic? This would break them. I think we neeed two connector_func tables
and dw_hdmi needs to check for DRIVER_ATOMIC at runtime and pick the right
version.

The larger problem here is that "who should register the drm_connector" is
a bit an unsolved problem, since both the bridge and the driver should be
able to customize/adjust the drm_connector at the end of a bridge chain.
This here is just another example of this problem.
-Daniel

> ---
>  drivers/gpu/drm/bridge/dw_hdmi.c |6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c 
> b/drivers/gpu/drm/bridge/dw_hdmi.c
> index 56de9f1..587065a 100644
> --- a/drivers/gpu/drm/bridge/dw_hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw_hdmi.c
> @@ -22,6 +22,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -1515,11 +1516,14 @@ static void dw_hdmi_connector_force(struct 
> drm_connector *connector)
>  }
>  
>  static struct drm_connector_funcs dw_hdmi_connector_funcs = {
> - .dpms = drm_helper_connector_dpms,
> + .dpms = drm_atomic_helper_connector_dpms,
>   .fill_modes = drm_helper_probe_single_connector_modes,
>   .detect = dw_hdmi_connector_detect,
>   .destroy = dw_hdmi_connector_destroy,
>   .force = dw_hdmi_connector_force,
> + .reset = drm_atomic_helper_connector_reset,
> + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
>  };
>  
>  static struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
> -- 
> 1.7.9.5
> 
> 
> ___
> 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


[RFC PATCH 3/9] drm/rockchip: Convert to support atomic API

2015-12-01 Thread Daniel Stone
Hi Mark,

On 1 December 2015 at 03:26, Mark Yao  wrote:
> +static void rockchip_atomic_wait_for_complete(struct drm_atomic_state *state)
> +{
> +   struct drm_crtc_state *crtc_state;
> +   struct drm_crtc *crtc;
> +   int i;
> +
> +   for_each_crtc_in_state(state, crtc, crtc_state, i) {
> +   if (!crtc->state->active)
> +   continue;
> +
> +   WARN_ON(drm_crtc_vblank_get(crtc));
> +   }
> +
> +   for_each_crtc_in_state(state, crtc, crtc_state, i) {
> +   if (!crtc->state->active)
> +   continue;
> +
> +   rockchip_crtc_wait_for_update(crtc);
> +   }

I'd be much more comfortable if this passed in an explicit pointer to
state, or an address to wait for, rather than have wait_for_complete
dig out state with no locking. The latter is potentially racy for
async operations.

> +struct vop_plane_state {
> +   struct drm_plane_state base;
> +   dma_addr_t dma_addr[ROCKCHIP_MAX_FB_BUFFER];

Can you get rid of this by just using the pointer to a
rockchip_gem_object already provided?

> -static int vop_update_plane_event(struct drm_plane *plane,
> - struct drm_crtc *crtc,
> - struct drm_framebuffer *fb, int crtc_x,
> - int crtc_y, unsigned int crtc_w,
> - unsigned int crtc_h, uint32_t src_x,
> - uint32_t src_y, uint32_t src_w,
> - uint32_t src_h,
> - struct drm_pending_vblank_event *event)
> +static int vop_plane_atomic_check(struct drm_plane *plane,
> +  struct drm_plane_state *state)
>  {
> +   struct drm_crtc *crtc = state->crtc;
> +   struct drm_framebuffer *fb = state->fb;
> struct vop_win *vop_win = to_vop_win(plane);
> +   struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
> const struct vop_win_data *win = vop_win->data;
> -   struct vop *vop = to_vop(crtc);
> struct drm_gem_object *obj;
> struct rockchip_gem_object *rk_obj;
> -   struct drm_gem_object *uv_obj;
> -   struct rockchip_gem_object *rk_uv_obj;
> unsigned long offset;
> -   unsigned int actual_w;
> -   unsigned int actual_h;
> -   unsigned int dsp_stx;
> -   unsigned int dsp_sty;
> -   unsigned int y_vir_stride;
> -   unsigned int uv_vir_stride = 0;
> -   dma_addr_t yrgb_mst;
> -   dma_addr_t uv_mst = 0;
> -   enum vop_data_format format;
> -   uint32_t val;
> -   bool is_alpha;
> -   bool rb_swap;
> bool is_yuv;
> bool visible;
> int ret;
> -   struct drm_rect dest = {
> -   .x1 = crtc_x,
> -   .y1 = crtc_y,
> -   .x2 = crtc_x + crtc_w,
> -   .y2 = crtc_y + crtc_h,
> -   };
> -   struct drm_rect src = {
> -   /* 16.16 fixed point */
> -   .x1 = src_x,
> -   .y1 = src_y,
> -   .x2 = src_x + src_w,
> -   .y2 = src_y + src_h,
> -   };
> -   const struct drm_rect clip = {
> -   .x2 = crtc->mode.hdisplay,
> -   .y2 = crtc->mode.vdisplay,
> -   };
> -   bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
> +   struct drm_rect *dest = _plane_state->dest;
> +   struct drm_rect *src = _plane_state->src;
> +   struct drm_rect clip;
> int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
> DRM_PLANE_HELPER_NO_SCALING;
> int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
> DRM_PLANE_HELPER_NO_SCALING;
>
> -   ret = drm_plane_helper_check_update(plane, crtc, fb,
> -   , , ,
> +   crtc = crtc ? crtc : plane->state->crtc;
> +   /*
> +* Both crtc or plane->state->crtc can be null.
> +*/
> +   if (!crtc || !fb)
> +   goto out_disable;
> +   src->x1 = state->src_x;
> +   src->y1 = state->src_y;
> +   src->x2 = state->src_x + state->src_w;
> +   src->y2 = state->src_y + state->src_h;
> +   dest->x1 = state->crtc_x;
> +   dest->y1 = state->crtc_y;
> +   dest->x2 = state->crtc_x + state->crtc_w;
> +   dest->y2 = state->crtc_y + state->crtc_h;
> +
> +   clip.x1 = 0;
> +   clip.y1 = 0;
> +   clip.x2 = crtc->mode.hdisplay;
> +   clip.y2 = crtc->mode.vdisplay;
> +
> +   ret = drm_plane_helper_check_update(plane, crtc, state->fb,
> +   src, dest, ,
> min_scale,
> max_scale,
> -   can_position, false, );
> +   true, true, );
> if (ret)
>

[PATCH v2 06/10] drm/hisilicon: Add vblank feature

2015-12-01 Thread Daniel Vetter
On Tue, Dec 01, 2015 at 11:16:19AM +0800, Xinliang Liu wrote:
> On 30 November 2015 at 15:54, Daniel Vetter  wrote:
> > On Sat, Nov 28, 2015 at 06:39:01PM +0800, Xinliang Liu wrote:
> >> Add vblank handle for ADE.
> >>
> >> Signed-off-by: Xinliang Liu 
> >> Signed-off-by: Xinwei Kong 
> >> Signed-off-by: Andy Green 
> >> ---
> >>  drivers/gpu/drm/hisilicon/hisi_drm_ade.c | 78 
> >> 
> >>  drivers/gpu/drm/hisilicon/hisi_drm_ade.h | 16 +++
> >>  drivers/gpu/drm/hisilicon/hisi_drm_drv.c | 19 +++-
> >>  3 files changed, 112 insertions(+), 1 deletion(-)
> >>  create mode 100644 drivers/gpu/drm/hisilicon/hisi_drm_ade.h
> >>
> >> diff --git a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c 
> >> b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
> >> index b0976c3..acb11e7 100644
> >> --- a/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
> >> +++ b/drivers/gpu/drm/hisilicon/hisi_drm_ade.c
> >> @@ -267,7 +267,79 @@ static void ade_power_down(struct ade_hw_ctx *ctx)
> >>   ctx->power_on = false;
> >>  }
> >>
> >> +static struct drm_crtc *hisi_get_crtc_from_index(struct drm_device *dev,
> >> +  unsigned int index)
> >
> > Ugly that you had to add this, but unfortunately necessary :( Fixing up
> > the drm vblank hooks so that they deal with struct drm_crtc directly is
> > somewhere on my todo. But drm_irq.c is still a bit a mess, so this is some
> > ways off still.
> >
> > What might be possible as a follow-up cleanup though is to add
> > vblank_enable and vblank_disable functions to struct
> > drm_crtc_helper_funcs. And then provide this code here to map from int
> > index to struct drm_crtc * as helpers in a new drm_vblank_helper.c file.
> > That might be a good intermediate step.
> 
> I would like to have a try to make this intermediate step patch and
> send out for review soon.

Awesome, looking forward to reviewing it. If you have questions about
details fastest to ping me on irc (nick: danvet, #dri-devel on
freenode.net).

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


[PATCH v2 03/10] drm/hisilicon: Add hisilicon DRM master driver

2015-12-01 Thread Daniel Vetter
On Mon, Nov 30, 2015 at 11:25:28AM -0600, Rob Herring wrote:
> On Mon, Nov 30, 2015 at 08:46:03AM +0100, Daniel Vetter wrote:
> > On Sat, Nov 28, 2015 at 03:25:35PM +, Emil Velikov wrote:
> > > Hi Xinliang,
> > > 
> > > On 28 November 2015 at 10:38, Xinliang Liu  
> > > wrote:
> > > > Add DRM master driver for hi6220 SoC which used in HiKey board.
> > > > Add dumb buffer feature.
> > > > Add prime dmabuf feature.
> > > >
> 
> > > > +static int hisi_gem_cma_dumb_create(struct drm_file *file,
> > > > +   struct drm_device *dev,
> > > > +   struct drm_mode_create_dumb *args)
> > > > +{
> > > > +   int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
> > > > +
> > > > +   /* mali gpu need pitch 8 bytes alignment for 32bpp */
> > > > +   args->pitch = roundup(min_pitch, 8);
> > > > +
> > > I'm not sure you want this kind of dependency of an out of tree driver
> > > upstream. If this is some limitation on the display engine so be it,
> > > but tailoring things for an external module seems like a very bad
> > > idea.
> > 
> > Yup, nacked. dumb_create is for dumb buffers, not rendering. Mali needs to
> > go upstream to fix this ...
> 
> I believe this is copy-n-paste from Rockchip driver.
> 
> I'm curious why there is not a common interface for rendering buffers at 
> least for systems without graphics memory like most ARM systems. Are the 
> requirements of GPU so diverse that things like pitch alignment can't be 
> parameterized?

pitch requirements is generally the least worry. The real fun starts with
tiling modes and how all that stuff interacts. Atm the only solution we
have is "userspace needs to know" in form of either gralloc (android) or
gbm (cros, desktop linux). There have been ideas to for describing buffer
limits, but nothing concrete yet.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[Bug 93178] Textures are filled with garbage

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=93178

--- Comment #4 from Józef Kucia  ---
https://drive.google.com/file/d/0Bz0HXJUyjAh3ZkFEOHdNVnAyWWM/view

This apitrace was captured with radeonsi. It is not trimmed. The problem
appears at 935th frame. The previous frames are rendered correctly.

-- 
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/20151201/8f3c5205/attachment-0001.html>


[PATCH v2 02/10] drm/hisilicon: Add DT binding docs for hi6220 display subsystem

2015-12-01 Thread Rob Herring
On Tue, Dec 1, 2015 at 1:17 AM, Xinliang Liu  wrote:
> On 1 December 2015 at 03:31, Rob Herring  wrote:
>
> Hi Rob, thank you for review.
>
>> On Sat, Nov 28, 2015 at 06:38:57PM +0800, Xinliang Liu wrote:
>>> Add the device tree binding documentation for hi6220 SoC display subsystem.
>>> drm master device binding doc.
>>> ADE display controller binding doc.
>>> DSI controller binding doc.

>>> +Required properties:
>>> +- compatible: Should be "hisilicon,-dss"
>>> +- #address-cells: should be set to 2.
>>> +- #size-cells: should be set to 2.
>>> +- range: to allow probing of subdevices.
>>> +
>>> +Optional properties:
>>> +- dma-coherent: Present if dma operations are coherent.
>>
>> Put this on the actually DMA master.
>
> The DMA modules reside in the begining of each channel(or plane) of ADE.
> So I need to put this dma-coherent property to ADE device node, right?

Right.

Rob


[PATCH] drm/edid: Make the detailed timing CEA/HDMI mode fixup accept up to 5kHz clock difference

2015-12-01 Thread Daniel Vetter
On Mon, Nov 30, 2015 at 01:02:59PM -0500, Adam Jackson wrote:
> On Thu, 2015-11-26 at 19:01 +0200, Ville Syrjälä wrote:
> > On Mon, Nov 16, 2015 at 09:05:12PM +0200, ville.syrjala at linux.intel.com 
> > wrote:
> > > From: Ville Syrjälä 
> > > 
> > > Rather than using drm_match_cea_mode() to see if the EDID detailed
> > > timings are supposed to represent one of the CEA/HDMI modes, add a
> > > special version of that function that takes in an explicit clock
> > > tolerance value (in kHz). When looking at the detailed timings specify
> > > the tolerance as 5kHz due to the 10kHz clock resolution limit inherent
> > > in detailed timings.
> > > 
> > > drm_match_cea_mode() uses the normal KHZ2PICOS() matching of clocks,
> > > which only allows smaller errors for lower clocks (eg. for 25200 it
> > > won't allow any error) and a bigger error for higher clocks (eg. for
> > > 297000 it actually matches 296913-297000). So it doesn't really match
> > > what we want for the fixup. Using the explicit +-5kHz is much better
> > > for this use case.
> > > 
> > > Not sure if we should change the normal mode matching to also use
> > > something else besides KHZ2PICOS() since it allows a different
> > > proportion of error depending on the clock. I believe VESA CVT
> > > allows a maximum deviation of .5%, so using that for normal mode
> > > matching might be a good idea?
> > 
> > Ping. Any thoughts from anyone?
> 
> Reviewed-by: Adam Jackson 

Applied to drm-misc, thanks for patch
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


[RFC PATCH 2/9] drm/rockchip: Use new vblank api drm_crtc_vblank_*

2015-12-01 Thread Daniel Stone
Hi,

On 1 December 2015 at 03:26, Mark Yao  wrote:
> No functional update, drm_vblank_* is the legacy version of
> drm_crtc_vblank_*. and use new api make driver more clean.
>
> Signed-off-by: Mark Yao 

Heh, I had the same patch in my series to fix pageflip events.

Reviewed-by: Daniel Stone 

Cheers,
Daniel


[Bug 93178] Textures are filled with garbage

2015-12-01 Thread bugzilla-dae...@freedesktop.org
https://bugs.freedesktop.org/show_bug.cgi?id=93178

--- Comment #3 from Józef Kucia  ---
(In reply to Michel Dänzer from comment #2)
> Replaying the trace on radeonsi generates lots of GL API errors:
>
> I think those errors could explain the incorrect rendering. Which driver was
> the apitrace captured with? Does the same problem occur when running the
> application with radeonsi directly?

The GL errors should not be related. Those are generated by format support
detection code.

This particular apitrace was captured with nouveau. The application generates
different GL errors in this part of code when run with radeonsi. However, it
exhibits exactly the same problem when run directly. I'll upload another
apitrace later.

-- 
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/20151201/44d9112f/attachment.html>


  1   2   >