[PATCH v2 2/2] drm/amd/display: Move PRIMARY plane zpos higher

2024-04-29 Thread sunpeng.li
From: Leo Li 

[Why]

Compositors have different ways of assigning surfaces to DRM planes for
render offloading. It may decide between various strategies: overlay,
underlay, or a mix of both (see here for more info:
https://gitlab.freedesktop.org/emersion/libliftoff/-/issues/76)

One way for compositors to implement the underlay strategy is to assign
a higher zpos to the DRM_PRIMARY plane than the DRM_OVERLAY planes,
effectively turning the DRM_OVERLAY plane into an underlay plane.

Today, amdgpu attaches an immutable zpos of 0 to the DRM_PRIMARY plane.
This however, is an arbitrary restriction. DCN pipes are general
purpose, and can be arranged in any z-order. To support compositors
using this allocation scheme, we can set a non-zero immutable zpos for
the PRIMARY, allowing the placement of OVERLAYS (mutable zpos range
0-254) beneath the PRIMARY.

[How]

Assign a zpos = #no of OVERLAY planes to the PRIMARY plane. Then, clean
up any assumptions in the driver of PRIMARY plane having the lowest
zpos.

Signed-off-by: Leo Li 
Reviewed-by: Harry Wentland 
Acked-by: Pekka Paalanen 

v2: Fix typo s/decending/descending/
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 34 +--
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 18 +++---
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index b4b5b73707c1..6782ca1137d4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -80,6 +80,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -375,6 +376,20 @@ static inline void reverse_planes_order(struct 
dc_surface_update *array_of_surfa
swap(array_of_surface_update[i], array_of_surface_update[j]);
 }
 
+/*
+ * DC will program planes with their z-order determined by their ordering
+ * in the dc_surface_updates array. This comparator is used to sort them
+ * by descending zpos.
+ */
+static int dm_plane_layer_index_cmp(const void *a, const void *b)
+{
+   const struct dc_surface_update *sa = (struct dc_surface_update *)a;
+   const struct dc_surface_update *sb = (struct dc_surface_update *)b;
+
+   /* Sort by descending dc_plane layer_index (i.e. normalized_zpos) */
+   return sb->surface->layer_index - sa->surface->layer_index;
+}
+
 /**
  * update_planes_and_stream_adapter() - Send planes to be updated in DC
  *
@@ -399,7 +414,8 @@ static inline bool update_planes_and_stream_adapter(struct 
dc *dc,
struct dc_stream_update 
*stream_update,
struct dc_surface_update 
*array_of_surface_update)
 {
-   reverse_planes_order(array_of_surface_update, planes_count);
+   sort(array_of_surface_update, planes_count,
+sizeof(*array_of_surface_update), dm_plane_layer_index_cmp, NULL);
 
/*
 * Previous frame finished and HW is ready for optimization.
@@ -9503,6 +9519,8 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
for (j = 0; j < status->plane_count; j++)
dummy_updates[j].surface = status->plane_states[0];
 
+   sort(dummy_updates, status->plane_count,
+sizeof(*dummy_updates), dm_plane_layer_index_cmp, NULL);
 
mutex_lock(&dm->dc_lock);
dc_update_planes_and_stream(dm->dc,
@@ -10237,6 +10255,16 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
if (new_crtc_state->color_mgmt_changed)
return true;
 
+   /*
+* On zpos change, planes need to be reordered by removing and re-adding
+* them one by one to the dc state, in order of descending zpos.
+*
+* TODO: We can likely skip bandwidth validation if the only thing that
+* changed about the plane was it'z z-ordering.
+*/
+   if (new_crtc_state->zpos_changed)
+   return true;
+
if (drm_atomic_crtc_needs_modeset(new_crtc_state))
return true;
 
@@ -11076,7 +11104,7 @@ static int amdgpu_dm_atomic_check(struct drm_device 
*dev,
}
 
/* Remove exiting planes if they are modified */
-   for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, 
new_plane_state, i) {
+   for_each_oldnew_plane_in_descending_zpos(state, plane, old_plane_state, 
new_plane_state) {
if (old_plane_state->fb && new_plane_state->fb &&
get_mem_type(old_plane_state->fb) !=
get_mem_type(new_plane_state->fb))
@@ -11121,7 +11149,7 @@ static int amdgpu_dm_atomic_check(struct drm_device 
*dev,
}
 
/* Add new/modified planes */
-   for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, 
new_plane_state, i) {
+   for_each_oldnew_plane_in_descending_z

[PATCH v2 1/2] drm/amd/display: Introduce overlay cursor mode

2024-04-29 Thread sunpeng.li
From: Leo Li 

[Why]

DCN is the display hardware for amdgpu. DRM planes are backed by DCN
hardware pipes, which carry pixel data from one end (memory), to the
other (output encoder).

Each DCN pipe has the ability to blend in a cursor early on in the
pipeline. In other words, there are no dedicated cursor planes in DCN,
which makes cursor behavior somewhat unintuitive for compositors.

For example, if the cursor is in RGB format, but the top-most DRM plane
is in YUV format, DCN will not be able to blend them. Because of this,
amdgpu_dm rejects all configurations where a cursor needs to be enabled
on top of a YUV formatted plane.

>From a compositor's perspective, when computing an allocation for
hardware plane offloading, this cursor-on-yuv configuration result in an
atomic test failure. Since the failure reason is not obvious at all,
compositors will likely fall back to full rendering, which is not ideal.

Instead, amdgpu_dm can try to accommodate the cursor-on-yuv
configuration by opportunistically reserving a separate DCN pipe just
for the cursor. We can refer to this as "overlay cursor mode". It is
contrasted with "native cursor mode", where the native DCN per-pipe
cursor is used.

[How]

On each crtc, compute whether the cursor plane should be enabled in
overlay mode. If it is, mark the CRTC as requesting overlay cursor mode.

Overlay cursor should be enabled whenever there exists a underlying
plane that has YUV format, or is scaled differently than the cursor. It
should also be enabled if there is no underlying plane, or if underlying
planes do not cover the entire CRTC.

During DC validation, attempt to enable a separate DCN pipe for the
cursor if it's in overlay mode. If that fails, or if no overlay mode is
requested, then fallback to native mode.

v2:
* Update commit message for when overlay cursor should be enabled
* Also consider scale and no-underlying-plane case (cursor on crtc bg)
* Consider all underlying planes when determinig overlay/native, not
  just the plane immediately beneath the cursor, as it may not cover the
  entire CRTC.
* Fix typo s/decending/descending/
* Force native cursor on pre-DCN hardware

Signed-off-by: Leo Li 
Acked-by: Harry Wentland 
Acked-by: Pekka Paalanen 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 490 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   7 +
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c|   1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  13 +-
 4 files changed, 386 insertions(+), 125 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 8245cc63712f..b4b5b73707c1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8490,8 +8490,22 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
 * Disable the cursor first if we're disabling all the planes.
 * It'll remain on the screen after the planes are re-enabled
 * if we don't.
+*
+* If the cursor is transitioning from native to overlay mode, the
+* native cursor needs to be disabled first.
 */
-   if (acrtc_state->active_planes == 0)
+   if (acrtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE &&
+   dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
+   struct dc_cursor_position cursor_position = {0};
+
+   dc_stream_set_cursor_position(acrtc_state->stream,
+ &cursor_position);
+   bundle->stream_update.cursor_position =
+   &acrtc_state->stream->cursor_position;
+   }
+
+   if (acrtc_state->active_planes == 0 &&
+   dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
amdgpu_dm_commit_cursors(state);
 
/* update planes when needed */
@@ -8505,7 +8519,8 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
struct dm_plane_state *dm_new_plane_state = 
to_dm_plane_state(new_plane_state);
 
/* Cursor plane is handled after stream updates */
-   if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+   if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+   acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
if ((fb && crtc == pcrtc) ||
(old_plane_state->fb && old_plane_state->crtc == 
pcrtc)) {
cursor_update = true;
@@ -8863,7 +8878,8 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
 * to be disabling a single plane - those pipes are being disabled.
 */
if (acrtc_state->active_planes &&
-   (!updated_planes_and_streams || amdgpu_ip_version(dm->adev, 
DCE_HWIP, 0) == 0))
+   (!updated_planes_and_streams || amdgpu_ip_version(dm->adev, 
DCE_HWIP, 0) == 0) &&
+ 

[PATCH 2/2] drm/amd/display: Move PRIMARY plane zpos higher

2024-03-15 Thread sunpeng.li
From: Leo Li 

[Why]

Compositors have different ways of assigning surfaces to DRM planes for
render offloading. It may decide between various strategies: overlay,
underlay, or a mix of both

One way for compositors to implement the underlay strategy is to assign
a higher zpos to the DRM_PRIMARY plane than the DRM_OVERLAY planes,
effectively turning the DRM_OVERLAY plane into an underlay plane.

Today, amdgpu attaches an immutable zpos of 0 to the DRM_PRIMARY plane.
This however, is an arbitrary restriction. DCN pipes are general
purpose, and can be arranged in any z-order. To support compositors
using this allocation scheme, we can set a non-zero immutable zpos for
the PRIMARY, allowing the placement of OVERLAYS (mutable zpos range
0-254) beneath the PRIMARY.

[How]

Assign a zpos = #no of OVERLAY planes to the PRIMARY plane. Then, clean
up any assumptions in the driver of PRIMARY plane having the lowest
zpos.

Signed-off-by: Leo Li 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 96 ++-
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 17 +++-
 2 files changed, 104 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 09ab330aed17..01b00f587701 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -80,6 +80,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -369,6 +370,20 @@ static inline void reverse_planes_order(struct 
dc_surface_update *array_of_surfa
swap(array_of_surface_update[i], array_of_surface_update[j]);
 }
 
+/*
+ * DC will program planes with their z-order determined by their ordering
+ * in the dc_surface_updates array. This comparator is used to sort them
+ * by descending zpos.
+ */
+static int dm_plane_layer_index_cmp(const void *a, const void *b)
+{
+   const struct dc_surface_update *sa = (struct dc_surface_update *)a;
+   const struct dc_surface_update *sb = (struct dc_surface_update *)b;
+
+   /* Sort by descending dc_plane layer_index (i.e. normalized_zpos) */
+   return sb->surface->layer_index - sa->surface->layer_index;
+}
+
 /**
  * update_planes_and_stream_adapter() - Send planes to be updated in DC
  *
@@ -393,7 +408,8 @@ static inline bool update_planes_and_stream_adapter(struct 
dc *dc,
struct dc_stream_update 
*stream_update,
struct dc_surface_update 
*array_of_surface_update)
 {
-   reverse_planes_order(array_of_surface_update, planes_count);
+   sort(array_of_surface_update, planes_count,
+sizeof(*array_of_surface_update), dm_plane_layer_index_cmp, NULL);
 
/*
 * Previous frame finished and HW is ready for optimization.
@@ -9363,6 +9379,8 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
for (j = 0; j < status->plane_count; j++)
dummy_updates[j].surface = status->plane_states[0];
 
+   sort(dummy_updates, status->plane_count,
+sizeof(*dummy_updates), dm_plane_layer_index_cmp, NULL);
 
mutex_lock(&dm->dc_lock);
dc_update_planes_and_stream(dm->dc,
@@ -10097,6 +10115,17 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
if (new_crtc_state->color_mgmt_changed)
return true;
 
+   /*
+* On zpos change, planes need to be reordered by removing and re-adding
+* them one by one to the dc state, in order of descending zpos.
+*
+* TODO: We can likely skip bandwidth validation if the only thing that
+* changed about the plane was it'z z-ordering.
+*/
+   if (new_crtc_state->zpos_changed) {
+   return true;
+   }
+
if (drm_atomic_crtc_needs_modeset(new_crtc_state))
return true;
 
@@ -10509,6 +10538,65 @@ dm_get_plane_scale(struct drm_plane_state *plane_state,
*out_plane_scale_h = plane_state->crtc_h * 1000 / plane_src_h;
 }
 
+/*
+ * The normalized_zpos value cannot be used by this iterator directly. It's 
only
+ * calculated for enabled planes, potentially causing normalized_zpos 
collisions
+ * between enabled/disabled planes in the atomic state. We need a unique value
+ * so that the iterator will not generate the same object twice, or loop
+ * indefinitely.
+ */
+static inline struct __drm_planes_state *__get_next_zpos(
+   struct drm_atomic_state *state,
+   struct __drm_planes_state *prev)
+{
+   unsigned int highest_zpos = 0, prev_zpos = 256;
+   uint32_t highest_id = 0, prev_id = UINT_MAX;
+   struct drm_plane_state *new_plane_state;
+   struct drm_plane *plane;
+   int i, highest_i = -1;
+
+   if (prev != NULL) {
+   prev_zpos = prev->new_state->zpos;
+   prev_id = prev->ptr

[PATCH 1/2] drm/amd/display: Introduce overlay cursor mode

2024-03-15 Thread sunpeng.li
From: Leo Li 

[Why]

DCN is the display hardware for amdgpu. DRM planes are backed by DCN
hardware pipes, which carry pixel data from one end (memory), to the
other (output encoder).

Each DCN pipe has the ability to blend in a cursor early on in the
pipeline. In other words, there are no dedicated cursor planes in DCN,
which makes cursor behavior somewhat unintuitive for compositors.

For example, if the cursor is in RGB format, but the top-most DRM plane
is in YUV format, DCN will not be able to blend them. Because of this,
amdgpu_dm rejects all configurations where a cursor needs to be enabled
on top of a YUV formatted plane.

>From a compositor's perspective, when computing an allocation for
hardware plane offloading, this cursor-on-yuv configuration result in an
atomic test failure. Since the failure reason is not obvious at all,
compositors will likely fall back to full rendering, which is not ideal.

Instead, amdgpu_dm can try to accommodate the cursor-on-yuv
configuration by opportunistically reserving a separate DCN pipe just
for the cursor. We can refer to this as "overlay cursor mode". It is
contrasted with "native cursor mode", where the native DCN per-pipe
cursor is used.

[How]

On each crtc, compute whether the cursor plane should be enabled in
overlay mode (which currently, is iff the immediate plane below has a
YUV format). If it is, mark the CRTC as requesting overlay cursor mode.

During DC validation, attempt to enable a separate DCN pipe for the
cursor if it's in overlay mode. If that fails, or if no overlay mode is
requested, then fallback to native mode.

Signed-off-by: Leo Li 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 309 +++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   7 +
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c|   1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  13 +-
 4 files changed, 288 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 21a61454c878..09ab330aed17 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8359,8 +8359,19 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
 * Disable the cursor first if we're disabling all the planes.
 * It'll remain on the screen after the planes are re-enabled
 * if we don't.
+*
+* If the cursor is transitioning from native to overlay mode, the
+* native cursor needs to be disabled first.
 */
-   if (acrtc_state->active_planes == 0)
+   if (acrtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE &&
+   dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
+   struct dc_cursor_position cursor_position = {0};
+   dc_stream_set_cursor_position(acrtc_state->stream,
+ &cursor_position);
+   }
+
+   if (acrtc_state->active_planes == 0 &&
+   dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
amdgpu_dm_commit_cursors(state);
 
/* update planes when needed */
@@ -8374,7 +8385,8 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
struct dm_plane_state *dm_new_plane_state = 
to_dm_plane_state(new_plane_state);
 
/* Cursor plane is handled after stream updates */
-   if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+   if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+   acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
if ((fb && crtc == pcrtc) ||
(old_plane_state->fb && old_plane_state->crtc == 
pcrtc))
cursor_update = true;
@@ -8727,7 +8739,8 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
 * This avoids redundant programming in the case where we're going
 * to be disabling a single plane - those pipes are being disabled.
 */
-   if (acrtc_state->active_planes)
+   if (acrtc_state->active_planes &&
+   acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
amdgpu_dm_commit_cursors(state);
 
 cleanup:
@@ -10039,7 +10052,8 @@ static bool should_reset_plane(struct drm_atomic_state 
*state,
 {
struct drm_plane *other;
struct drm_plane_state *old_other_state, *new_other_state;
-   struct drm_crtc_state *new_crtc_state;
+   struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+   struct dm_crtc_state *old_dm_crtc_state, *new_dm_crtc_state;
struct amdgpu_device *adev = drm_to_adev(plane->dev);
int i;
 
@@ -10061,10 +10075,24 @@ static bool should_reset_plane(struct 
drm_atomic_state *state,
 
new_crtc_state =
drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
+   old_crtc_state =
+   drm_atomic_g

[PATCH 0/2] drm/amdgpu/display: Make multi-plane configurations more flexible

2024-03-15 Thread sunpeng.li
From: Leo Li 

These patches aim to make the amdgpgu KMS driver play nicer with compositors
when building multi-plane scanout configurations. They do so by:

1. Making cursor behavior more sensible.
2. Allowing placement of DRM OVERLAY planes underneath the PRIMARY plane for
   'underlay' configurations (perhaps more of a RFC, see below).

Please see the commit messages for details.


For #2, the simplest way to accomplish this was to increase the value of the
immutable zpos property for the PRIMARY plane. This allowed OVERLAY planes with
a mutable zpos range of (0-254) to be positioned underneath the PRIMARY for an
underlay scanout configuration.

Technically speaking, DCN hardware does not have a concept of primary or overlay
planes - there are simply 4 general purpose hardware pipes that can be maped in
any configuration. So the immutable zpos restriction on the PRIMARY plane is
kind of arbitrary; it can have a mutable range of (0-254) just like the
OVERLAYs. The distinction between PRIMARY and OVERLAY planes is also somewhat
arbitrary. We can interpret PRIMARY as the first plane that should be enabled on
a CRTC, but beyond that, it doesn't mean much for amdgpu.

Therefore, I'm curious about how compositors devs understand KMS planes and
their zpos properties, and how we would like to use them. It isn't clear to me
how compositors wish to interpret and use the DRM zpos property, or
differentiate between OVERLAY and PRIMARY planes, when it comes to setting up
multi-plane scanout.

Ultimately, what I'd like to answer is "What can we do on the KMS driver and DRM
plane API side, that can make building multi-plane scanout configurations easier
for compositors?" I'm hoping we can converge on something, whether that be
updating the existing documentation to better define the usage, or update the
API to provide support for something that is lacking.

Thanks,
Leo


Some links to provide context and details:
* What is underlay?: 
https://gitlab.freedesktop.org/emersion/libliftoff/-/issues/76
* Discussion on how to implement underlay on Weston: 
https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1258#note_2325164

Cc: Joshua Ashton 
Cc: Michel Dänzer 
Cc: Chao Guo 
Cc: Xaver Hugl 
Cc: Vikas Korjani 
Cc: Robert Mader 
Cc: Pekka Paalanen 
Cc: Sean Paul 
Cc: Simon Ser 
Cc: Shashank Sharma 
Cc: Harry Wentland 
Cc: Sebastian Wick 

Leo Li (2):
  drm/amd/display: Introduce overlay cursor mode
  drm/amd/display: Move PRIMARY plane zpos higher

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 405 --
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   7 +
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c|   1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  28 +-
 4 files changed, 391 insertions(+), 50 deletions(-)

-- 
2.44.0



[PATCH] drm: Add PSR version 4 macro

2022-01-17 Thread sunpeng.li
From: Leo Li 

eDP 1.5 specification defines PSR version 4.

It defines PSR1 and PSR2 support with selective-update (SU)
capabilities, with additional support for Y-coordinate and Early
Transport of the selective-update region.

This differs from PSR version 3 in that early transport is supported
for version 4, but not for version 3.

Signed-off-by: Leo Li 
---
 include/drm/drm_dp_helper.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 3f2715eb965f..05268c51acaa 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -360,6 +360,7 @@ struct drm_dp_aux;
 # define DP_PSR_IS_SUPPORTED1
 # define DP_PSR2_IS_SUPPORTED  2   /* eDP 1.4 */
 # define DP_PSR2_WITH_Y_COORD_IS_SUPPORTED  3  /* eDP 1.4a */
+# define DP_PSR2_WITH_ET_IS_SUPPORTED   4  /* eDP 1.5 (eDP 1.4b SCR) */
 
 #define DP_PSR_CAPS 0x071   /* XXX 1.2? */
 # define DP_PSR_NO_TRAIN_ON_EXIT1
-- 
2.34.1



[PATCH v2] drm/amdgpu: Add DC feature mask to disable fractional pwm

2019-10-21 Thread sunpeng.li
From: Leo Li 

[Why]

Some LED panel drivers might not like fractional PWM. In such cases,
backlight flickering may be observed.

[How]

Add a DC feature mask to disable fractional PWM, and associate it with
the preexisting dc_config flag.

The flag is only plumbed through the dmcu firmware, so plumb it through
the driver path as well.

To disable, add the following to the linux cmdline:
amdgpu.dcfeaturemask=0x4

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=204957
Signed-off-by: Leo Li 
---

v2: Add bugzilla link

 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++
 drivers/gpu/drm/amd/display/dc/dce/dce_abm.c  | 4 
 drivers/gpu/drm/amd/include/amd_shared.h  | 1 +
 3 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 1cf4beb76835..73f917d4d1e1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -728,6 +728,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_dc_feature_mask & DC_MULTI_MON_PP_MCLK_SWITCH_MASK)
init_data.flags.multi_mon_pp_mclk_switch = true;
 
+   if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK)
+   init_data.flags.disable_fractional_pwm = true;
+
init_data.flags.power_down_display_on_boot = true;
 
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
index d759fdca7fdb..b8a3fc505c9b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -404,6 +404,10 @@ static bool dce_abm_init_backlight(struct abm *abm)
/* Enable the backlight output */
REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
 
+   /* Disable fractional pwm if configured */
+   REG_UPDATE(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN,
+  abm->ctx->dc->config.disable_fractional_pwm ? 0 : 1);
+
/* Unlock group 2 backlight registers */
REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
BL_PWM_GRP1_REG_LOCK, 0);
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h 
b/drivers/gpu/drm/amd/include/amd_shared.h
index 8889aaceec60..5450ed762b7a 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -143,6 +143,7 @@ enum PP_FEATURE_MASK {
 enum DC_FEATURE_MASK {
DC_FBC_MASK = 0x1,
DC_MULTI_MON_PP_MCLK_SWITCH_MASK = 0x2,
+   DC_DISABLE_FRACTIONAL_PWM_MASK = 0x4,
 };
 
 enum amd_dpm_forced_level;
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] drm/amdgpu: Add DC feature mask to disable fractional pwm

2019-10-21 Thread sunpeng.li
From: Leo Li 

[Why]

Some LED panel drivers might not like fractional PWM. In such cases,
backlight flickering may be observed.

[How]

Add a DC feature mask to disable fractional PWM, and associate it with
the preexisting dc_config flag.

The flag is only plumbed through the dmcu firmware, so plumb it through
the driver path as well.

To disable, add the following to the linux cmdline:
amdgpu.dcfeaturemask=0x4

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++
 drivers/gpu/drm/amd/display/dc/dce/dce_abm.c  | 4 
 drivers/gpu/drm/amd/include/amd_shared.h  | 1 +
 3 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 1cf4beb76835..73f917d4d1e1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -728,6 +728,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_dc_feature_mask & DC_MULTI_MON_PP_MCLK_SWITCH_MASK)
init_data.flags.multi_mon_pp_mclk_switch = true;
 
+   if (amdgpu_dc_feature_mask & DC_DISABLE_FRACTIONAL_PWM_MASK)
+   init_data.flags.disable_fractional_pwm = true;
+
init_data.flags.power_down_display_on_boot = true;
 
 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
index d759fdca7fdb..b8a3fc505c9b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -404,6 +404,10 @@ static bool dce_abm_init_backlight(struct abm *abm)
/* Enable the backlight output */
REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
 
+   /* Disable fractional pwm if configured */
+   REG_UPDATE(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN,
+  abm->ctx->dc->config.disable_fractional_pwm ? 0 : 1);
+
/* Unlock group 2 backlight registers */
REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
BL_PWM_GRP1_REG_LOCK, 0);
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h 
b/drivers/gpu/drm/amd/include/amd_shared.h
index 8889aaceec60..5450ed762b7a 100644
--- a/drivers/gpu/drm/amd/include/amd_shared.h
+++ b/drivers/gpu/drm/amd/include/amd_shared.h
@@ -143,6 +143,7 @@ enum PP_FEATURE_MASK {
 enum DC_FEATURE_MASK {
DC_FBC_MASK = 0x1,
DC_MULTI_MON_PP_MCLK_SWITCH_MASK = 0x2,
+   DC_DISABLE_FRACTIONAL_PWM_MASK = 0x4,
 };
 
 enum amd_dpm_forced_level;
-- 
2.23.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 6/9 v2] drm/i915: Implement MST Aux device registration

2019-07-23 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Signed-off-by: Leo Li 

v2 changes:
Unwind intel_connector_register on mst late register failure.
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 33 +++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 60652ebbdf61..0633ebf3f1bf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -400,13 +400,42 @@ intel_dp_mst_detect(struct drm_connector *connector, bool 
force)
  intel_connector->port);
 }
 
+static int
+intel_dp_mst_connector_late_register(struct drm_connector *connector)
+{
+   struct intel_connector *intel_connector = to_intel_connector(connector);
+   struct drm_dp_mst_port *port = intel_connector->port;
+
+   int ret;
+
+   ret = intel_connector_register(connector);
+   if (ret)
+   return ret;
+
+   ret = drm_dp_mst_connector_late_register(connector, port);
+   if (ret)
+   intel_connector_unregister(connector);
+
+   return ret;
+}
+
+static void
+intel_dp_mst_connector_early_unregister(struct drm_connector *connector)
+{
+   struct intel_connector *intel_connector = to_intel_connector(connector);
+   struct drm_dp_mst_port *port = intel_connector->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+   intel_connector_unregister(connector);
+}
+
 static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
.detect = intel_dp_mst_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property,
-   .late_register = intel_connector_register,
-   .early_unregister = intel_connector_unregister,
+   .late_register = intel_dp_mst_connector_late_register,
+   .early_unregister = intel_dp_mst_connector_early_unregister,
.destroy = intel_connector_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 8/9] drm/radeon: Implement MST Aux device registration

2019-07-23 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Cc: Alex Deucher 
Cc: Harry Wentland 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/radeon/radeon_dp_mst.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c 
b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 2994f07fbad9..2d53699734fb 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -260,11 +260,33 @@ radeon_dp_mst_connector_destroy(struct drm_connector 
*connector)
kfree(radeon_connector);
 }
 
+static int
+radeon_dp_mst_connector_late_register(struct drm_connector *connector)
+{
+   struct radeon_connector *radeon_connector =
+   to_radeon_connector(connector);
+   struct drm_dp_mst_port *port = radeon_connector->port;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+radeon_dp_mst_connector_early_unregister(struct drm_connector *connector)
+{
+   struct radeon_connector *radeon_connector =
+   to_radeon_connector(connector);
+   struct drm_dp_mst_port *port = radeon_connector->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = radeon_dp_mst_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_dp_mst_connector_destroy,
+   .late_register = radeon_dp_mst_connector_late_register,
+   .early_unregister = radeon_dp_mst_connector_early_unregister,
 };
 
 static struct drm_connector *radeon_dp_add_mst_connector(struct 
drm_dp_mst_topology_mgr *mgr,
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 4/9] drm/bridge/analogix-anx78xx: Use connector kdev as aux device parent

2019-07-23 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

To do so, the connector needs to be registered beforehand. Therefore,
shift aux registration to be after connector registration.

Cc: Enric Balletbo i Serra 
Cc: Nicolas Boichat 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/bridge/analogix-anx78xx.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c 
b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index 3c7cc5af735c..c2800cd3e2ee 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1008,17 +1008,6 @@ static int anx78xx_bridge_attach(struct drm_bridge 
*bridge)
return -ENODEV;
}
 
-   /* Register aux channel */
-   anx78xx->aux.name = "DP-AUX";
-   anx78xx->aux.dev = &anx78xx->client->dev;
-   anx78xx->aux.transfer = anx78xx_aux_transfer;
-
-   err = drm_dp_aux_register(&anx78xx->aux);
-   if (err < 0) {
-   DRM_ERROR("Failed to register aux channel: %d\n", err);
-   return err;
-   }
-
err = drm_connector_init(bridge->dev, &anx78xx->connector,
 &anx78xx_connector_funcs,
 DRM_MODE_CONNECTOR_DisplayPort);
@@ -1038,6 +1027,17 @@ static int anx78xx_bridge_attach(struct drm_bridge 
*bridge)
 
anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
+   /* Register aux channel */
+   anx78xx->aux.name = "DP-AUX";
+   anx78xx->aux.dev = anx78xx->connector.kdev;
+   anx78xx->aux.transfer = anx78xx_aux_transfer;
+
+   err = drm_dp_aux_register(&anx78xx->aux);
+   if (err < 0) {
+   DRM_ERROR("Failed to register aux channel: %d\n", err);
+   return err;
+   }
+
err = drm_connector_attach_encoder(&anx78xx->connector,
   bridge->encoder);
if (err) {
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 9/9] drm/amd/display: Implement MST Aux device registration

2019-07-23 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Cc: Jerry Zuo 
Cc: Nicholas Kazlauskas 
Cc: Harry Wentland 
Signed-off-by: Leo Li 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 24 ++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 53d2cfe62e13..16218a202b59 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -156,6 +156,26 @@ dm_dp_mst_connector_destroy(struct drm_connector 
*connector)
kfree(amdgpu_dm_connector);
 }
 
+static int
+amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
+{
+   struct amdgpu_dm_connector *amdgpu_dm_connector =
+   to_amdgpu_dm_connector(connector);
+   struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
+{
+   struct amdgpu_dm_connector *amdgpu_dm_connector =
+   to_amdgpu_dm_connector(connector);
+   struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
.detect = dm_dp_mst_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -164,7 +184,9 @@ static const struct drm_connector_funcs 
dm_dp_mst_connector_funcs = {
.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_set_property = amdgpu_dm_connector_atomic_set_property,
-   .atomic_get_property = amdgpu_dm_connector_atomic_get_property
+   .atomic_get_property = amdgpu_dm_connector_atomic_get_property,
+   .late_register = amdgpu_dm_mst_connector_late_register,
+   .early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 5/9] drm/amd/display: Use connector kdev as aux device parent

2019-07-23 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

For example, the following udev rule:

SUBSYSTEM=="drm_dp_aux_dev", SUBSYSTEMS=="drm", ATTRS{edid}=="*",
SYMLINK+="drm_dp_aux/by-name/$id"

Will create the following symlinks using the connector's name:

$ ls /dev/drm_dp_aux/by-name/
card0-DP-1  card0-DP-2  card0-DP-3

Cc: Nicholas Kazlauskas 
Cc: Jerry (Fangzhi) Zuo 
Cc: Harry Wentland 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6e205ee36ac3..53d2cfe62e13 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -388,7 +388,7 @@ void amdgpu_dm_initialize_dp_connector(struct 
amdgpu_display_manager *dm,
   struct amdgpu_dm_connector *aconnector)
 {
aconnector->dm_dp_aux.aux.name = "dmdc";
-   aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+   aconnector->dm_dp_aux.aux.dev = aconnector->base.kdev;
aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc;
 
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 2/9 v3] drm/dp_mst: Enable registration of AUX devices for MST ports

2019-07-23 Thread sunpeng.li
From: Ville Syrjälä 

All available downstream ports - physical and logical - are exposed for
each MST device. They are listed in /dev/, following the same naming
scheme as SST devices by appending an incremental ID.

Although all downstream ports are exposed, only some will work as
expected. Consider the following topology:

   +-+
   |  ASIC   |
   +-+
  Conn-0|
|
   +v+
  +| MST HUB |+
  |+-+|
  |   |
  |Port-1   Port-2|
+-v-+   +-v-+
|  MST  |   |  SST  |
|  Display  |   |  Display  |
+---+   +---+
  |Port-1
  x

 MST Path  | MST Device
 --+--
 sst:0 | MST Hub
 mst:0-1   | MST Display
 mst:0-1-1 | MST Display's disconnected DP out
 mst:0-1-8 | MST Display's internal sink
 mst:0-2   | SST Display

On certain MST displays, the upstream physical port will ACK DPCD reads.
However, reads on the local logical port to the internal sink will
*NAK*. i.e. reading mst:0-1 ACKs, but mst:0-1-8 NAKs.

There may also be duplicates. Some displays will return the same GUID
when reading DPCD from both mst:0-1 and mst:0-1-8.

There are some device-dependent behavior as well. The MST hub used
during testing will actually *ACK* read requests on a disconnected
physical port, whereas the MST displays will NAK.

In light of these discrepancies, it's simpler to expose all downstream
ports - both physical and logical - and let the user decide what to use.

v3 changes:
* Change WARN_ON_ONCE -> DRM_ERROR on dpcd read errors
* Docstring and cosmetic fixes

v2 changes:

Moved remote aux device (un)registration to new mst connector late
register and early unregister helpers. Drivers should call these from
their own mst connector function hooks.

This is to solve an issue during driver unload, where mst connector
devices are unregistered before the remote aux devices are. In a setup
where aux devices are created as children of connector devices, the aux
device would be removed too early, and uncleanly. Doing so in
early_unregister solves this issue, as that is called before connector
unregistration.

Signed-off-by: Ville Syrjälä 
Signed-off-by: Leo Li 
Reviewed-by: Lyude Paul 
---
 drivers/gpu/drm/drm_dp_aux_dev.c  |  15 ++-
 drivers/gpu/drm/drm_dp_mst_topology.c | 144 --
 include/drm/drm_dp_helper.h   |   4 +
 include/drm/drm_dp_mst_helper.h   |  11 ++
 4 files changed, 162 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 26e38dacf654..0cfb386754c3 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -37,6 +37,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "drm_crtc_helper_internal.h"
@@ -162,7 +163,12 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf,
+  todo);
+   else
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
@@ -209,7 +215,12 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
break;
}
 
-   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf,
+   todo);
+   else
+   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 0984b9a34d55..4733d3350ede 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -36,6 +36,8 @@
 #include 
 #include 
 
+#include "drm_crtc_helper_internal.h"
+
 /**
  * DOC: dp mst helper
  *
@@ -53,6 +55,9 @@ static int drm_dp_dpcd_write_payload(struct 
drm_dp_mst_topology_mgr *mgr,
 int id,
 struct drm_dp_payload *payload);
 
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+struct drm_dp_mst_port *port,
+int offset, int size, u8 *bytes);
 static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
  struct drm_dp_mst_port *port,
  

[PATCH 3/9] drm/nouveau: Use connector kdev as aux device parent

2019-07-23 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

Cc: Ben Skeggs 
Signed-off-by: Leo Li 
Reviewed-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 8f15281faa79..330d7d29a6e3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1349,7 +1349,7 @@ nouveau_connector_create(struct drm_device *dev,
break;
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_eDP:
-   nv_connector->aux.dev = dev->dev;
+   nv_connector->aux.dev = connector->kdev;
nv_connector->aux.transfer = nouveau_connector_aux_xfer;
snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
 dcbe->hasht, dcbe->hashm);
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 7/9] drm/nouveau/kms/nv50: Implement MST Aux device registration

2019-07-23 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Cc: Ben Skeggs 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 8497768f1b41..0d6e9350ba44 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1024,6 +1024,24 @@ nv50_mstc_destroy(struct drm_connector *connector)
kfree(mstc);
 }
 
+static int
+nv50_mstc_late_register(struct drm_connector *connector)
+{
+   struct nv50_mstc *mstc = nv50_mstc(connector);
+   struct drm_dp_mst_port *port = mstc->port;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+nv50_mstc_early_unregister(struct drm_connector *connector)
+{
+   struct nv50_mstc *mstc = nv50_mstc(connector);
+   struct drm_dp_mst_port *port = mstc->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs
 nv50_mstc = {
.reset = nouveau_conn_reset,
@@ -1034,6 +1052,8 @@ nv50_mstc = {
.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
.atomic_set_property = nouveau_conn_atomic_set_property,
.atomic_get_property = nouveau_conn_atomic_get_property,
+   .late_register = nv50_mstc_late_register,
+   .early_unregister = nv50_mstc_early_unregister,
 };
 
 static int
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 0/9] MST AUX Devices (v3)

2019-07-23 Thread sunpeng.li
From: Leo Li 

Here's what changed in v3:

* Dropped patch to expose the mst-path device attribute, in lieu of
  ongoing discussion for defining a better connector path property
* Change WARN_ON_ONCE -> DRM_ERROR on MST dpcd read errors to avoid
  tainting the kernel
* Unwind intel_connector_register() on
  drm_dp_mst_connector_late_register() failure.
* Docstring and cosmetic fixes

Leo Li (8):
  drm/dp: Use non-cyclic idr
  drm/nouveau: Use connector kdev as aux device parent
  drm/bridge/analogix-anx78xx: Use connector kdev as aux device parent
  drm/amd/display: Use connector kdev as aux device parent
  drm/i915: Implement MST Aux device registration (v2)
  drm/nouveau/kms/nv50: Implement MST Aux device registration
  drm/radeon: Implement MST Aux device registration
  drm/amd/display: Implement MST Aux device registration

Ville Syrjälä (1):
  drm/dp_mst: Enable registration of AUX devices for MST ports

 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  26 +++-
 drivers/gpu/drm/bridge/analogix-anx78xx.c |  22 +--
 drivers/gpu/drm/drm_dp_aux_dev.c  |  18 ++-
 drivers/gpu/drm/drm_dp_mst_topology.c | 144 --
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  33 +++-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  20 +++
 drivers/gpu/drm/nouveau/nouveau_connector.c   |   2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c|  22 +++
 include/drm/drm_dp_helper.h   |   4 +
 include/drm/drm_dp_mst_helper.h   |  11 ++
 10 files changed, 272 insertions(+), 30 deletions(-)

-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 1/9] drm/dp: Use non-cyclic idr

2019-07-23 Thread sunpeng.li
From: Leo Li 

In preparation for adding aux devices for DP MST, make the IDR
non-cyclic. That way, hotplug cycling MST devices won't needlessly
increment the minor version index.

Signed-off-by: Leo Li 
Reviewed-by: Lyude Paul 
Reviewed-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_dp_aux_dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 5be28e3295f3..26e38dacf654 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -82,8 +82,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct 
drm_dp_aux *aux)
kref_init(&aux_dev->refcount);
 
mutex_lock(&aux_idr_mutex);
-   index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-GFP_KERNEL);
+   index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
mutex_unlock(&aux_idr_mutex);
if (index < 0) {
kfree(aux_dev);
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2] drm/sysfs: Add mstpath attribute to connector devices

2019-07-05 Thread sunpeng.li
From: Leo Li 

This can be used to create more descriptive symlinks for MST aux
devices. Consider the following udev rule:

SUBSYSTEM=="drm_dp_aux_dev", SUBSYSTEMS=="drm", ATTRS{mstpath}=="?*",
SYMLINK+="drm_dp_aux/by-path/$attr{mstpath}"

The following symlinks will be created (depending on your MST topology):

$ ls /dev/drm_dp_aux/by-path/
card0-mst:0-1  card0-mst:0-1-1  card0-mst:0-1-8  card0-mst:0-8

v2: remove unnecessary locking of mode_config.mutex

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_sysfs.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index ad10810bc972..7d483ab684a0 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -236,16 +236,36 @@ static ssize_t modes_show(struct device *device,
return written;
 }
 
+static ssize_t mstpath_show(struct device *device,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct drm_connector *connector = to_drm_connector(device);
+   ssize_t ret = 0;
+   char *path;
+
+   if (!connector->path_blob_ptr)
+   return ret;
+
+   path = connector->path_blob_ptr->data;
+   ret = snprintf(buf, PAGE_SIZE, "card%d-%s\n",
+  connector->dev->primary->index, path);
+
+   return ret;
+}
+
 static DEVICE_ATTR_RW(status);
 static DEVICE_ATTR_RO(enabled);
 static DEVICE_ATTR_RO(dpms);
 static DEVICE_ATTR_RO(modes);
+static DEVICE_ATTR_RO(mstpath);
 
 static struct attribute *connector_dev_attrs[] = {
&dev_attr_status.attr,
&dev_attr_enabled.attr,
&dev_attr_dpms.attr,
&dev_attr_modes.attr,
+   &dev_attr_mstpath.attr,
NULL
 };
 
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 08/10] drm/nouveau/kms/nv50: Implement MST Aux device registration

2019-07-04 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Cc: Ben Skeggs 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/nouveau/dispnv50/disp.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c 
b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 7ba373f493b2..6d0fbb6036cf 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -1019,6 +1019,24 @@ nv50_mstc_destroy(struct drm_connector *connector)
kfree(mstc);
 }
 
+static int
+nv50_mstc_late_register(struct drm_connector *connector)
+{
+   struct nv50_mstc *mstc = nv50_mstc(connector);
+   struct drm_dp_mst_port *port = mstc->port;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+nv50_mstc_early_unregister(struct drm_connector *connector)
+{
+   struct nv50_mstc *mstc = nv50_mstc(connector);
+   struct drm_dp_mst_port *port = mstc->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs
 nv50_mstc = {
.reset = nouveau_conn_reset,
@@ -1029,6 +1047,8 @@ nv50_mstc = {
.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
.atomic_set_property = nouveau_conn_atomic_set_property,
.atomic_get_property = nouveau_conn_atomic_get_property,
+   .late_register = nv50_mstc_late_register,
+   .early_unregister = nv50_mstc_early_unregister,
 };
 
 static int
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 03/10] drm/sysfs: Add mstpath attribute to connector devices

2019-07-04 Thread sunpeng.li
From: Leo Li 

This can be used to create more descriptive symlinks for MST aux
devices. Consider the following udev rule:

SUBSYSTEM=="drm_dp_aux_dev", SUBSYSTEMS=="drm", ATTRS{mstpath}=="?*",
SYMLINK+="drm_dp_aux/by-path/$attr{mstpath}"

The following symlinks will be created (depending on your MST topology):

$ ls /dev/drm_dp_aux/by-path/
card0-mst:0-1  card0-mst:0-1-1  card0-mst:0-1-8  card0-mst:0-8

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_sysfs.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index ad10810bc972..53fd1f71e900 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -236,16 +236,39 @@ static ssize_t modes_show(struct device *device,
return written;
 }
 
+static ssize_t mstpath_show(struct device *device,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct drm_connector *connector = to_drm_connector(device);
+   ssize_t ret = 0;
+   char *path;
+
+   mutex_lock(&connector->dev->mode_config.mutex);
+   if (!connector->path_blob_ptr)
+   goto unlock;
+
+   path = connector->path_blob_ptr->data;
+   ret = snprintf(buf, PAGE_SIZE, "card%d-%s\n",
+  connector->dev->primary->index, path);
+
+unlock:
+   mutex_unlock(&connector->dev->mode_config.mutex);
+   return ret;
+}
+
 static DEVICE_ATTR_RW(status);
 static DEVICE_ATTR_RO(enabled);
 static DEVICE_ATTR_RO(dpms);
 static DEVICE_ATTR_RO(modes);
+static DEVICE_ATTR_RO(mstpath);
 
 static struct attribute *connector_dev_attrs[] = {
&dev_attr_status.attr,
&dev_attr_enabled.attr,
&dev_attr_dpms.attr,
&dev_attr_modes.attr,
+   &dev_attr_mstpath.attr,
NULL
 };
 
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 04/10] drm/nouveau: Use connector kdev as aux device parent

2019-07-04 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

Cc: Ben Skeggs 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 4116ee62adaf..e32def09ef89 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1346,7 +1346,7 @@ nouveau_connector_create(struct drm_device *dev,
break;
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_eDP:
-   nv_connector->aux.dev = dev->dev;
+   nv_connector->aux.dev = connector->kdev;
nv_connector->aux.transfer = nouveau_connector_aux_xfer;
snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
 dcbe->hasht, dcbe->hashm);
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 06/10] drm/amd/display: Use connector kdev as aux device parent

2019-07-04 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

For example, the following udev rule:

SUBSYSTEM=="drm_dp_aux_dev", SUBSYSTEMS=="drm", ATTRS{edid}=="*",
SYMLINK+="drm_dp_aux/by-name/$id"

Will create the following symlinks using the connector's name:

$ ls /dev/drm_dp_aux/by-name/
card0-DP-1  card0-DP-2  card0-DP-3

Cc: Nicholas Kazlauskas 
Cc: Jerry (Fangzhi) Zuo 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 6e205ee36ac3..53d2cfe62e13 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -388,7 +388,7 @@ void amdgpu_dm_initialize_dp_connector(struct 
amdgpu_display_manager *dm,
   struct amdgpu_dm_connector *aconnector)
 {
aconnector->dm_dp_aux.aux.name = "dmdc";
-   aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+   aconnector->dm_dp_aux.aux.dev = aconnector->base.kdev;
aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc;
 
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 01/10] drm/dp: Use non-cyclic idr

2019-07-04 Thread sunpeng.li
From: Leo Li 

In preparation for adding aux devices for DP MST, make the IDR
non-cyclic. That way, hotplug cycling MST devices won't needlessly
increment the minor version index.

Signed-off-by: Leo Li 
Reviewed-by: Lyude Paul 
Reviewed-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_dp_aux_dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 5be28e3295f3..26e38dacf654 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -82,8 +82,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct 
drm_dp_aux *aux)
kref_init(&aux_dev->refcount);
 
mutex_lock(&aux_idr_mutex);
-   index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-GFP_KERNEL);
+   index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
mutex_unlock(&aux_idr_mutex);
if (index < 0) {
kfree(aux_dev);
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 05/10] drm/bridge/analogix-anx78xx: Use connector kdev as aux device parent

2019-07-04 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

To do so, the connector needs to be registered beforehand. Therefore,
shift aux registration to be after connector registration.

Cc: Enric Balletbo i Serra 
Cc: Nicolas Boichat 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/bridge/analogix-anx78xx.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c 
b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index 3c7cc5af735c..c2800cd3e2ee 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1008,17 +1008,6 @@ static int anx78xx_bridge_attach(struct drm_bridge 
*bridge)
return -ENODEV;
}
 
-   /* Register aux channel */
-   anx78xx->aux.name = "DP-AUX";
-   anx78xx->aux.dev = &anx78xx->client->dev;
-   anx78xx->aux.transfer = anx78xx_aux_transfer;
-
-   err = drm_dp_aux_register(&anx78xx->aux);
-   if (err < 0) {
-   DRM_ERROR("Failed to register aux channel: %d\n", err);
-   return err;
-   }
-
err = drm_connector_init(bridge->dev, &anx78xx->connector,
 &anx78xx_connector_funcs,
 DRM_MODE_CONNECTOR_DisplayPort);
@@ -1038,6 +1027,17 @@ static int anx78xx_bridge_attach(struct drm_bridge 
*bridge)
 
anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
+   /* Register aux channel */
+   anx78xx->aux.name = "DP-AUX";
+   anx78xx->aux.dev = anx78xx->connector.kdev;
+   anx78xx->aux.transfer = anx78xx_aux_transfer;
+
+   err = drm_dp_aux_register(&anx78xx->aux);
+   if (err < 0) {
+   DRM_ERROR("Failed to register aux channel: %d\n", err);
+   return err;
+   }
+
err = drm_connector_attach_encoder(&anx78xx->connector,
   bridge->encoder);
if (err) {
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 00/10] Enable MST Aux devices (v2)

2019-07-04 Thread sunpeng.li
From: Leo Li 

Hi all,

Here's the second revision of patches to enable mst aux devices.

v2 fixes an aux device unregistration issue during driver unload. See
patch 2/10 for details. Consequently, drivers supporting mst are
modified to use the new mst connector late register and early unregister
helpers.

Thanks,
Leo

Leo Li (9):
  drm/dp: Use non-cyclic idr
  drm/sysfs: Add mstpath attribute to connector devices
  drm/nouveau: Use connector kdev as aux device parent
  drm/bridge/analogix-anx78xx: Use connector kdev as aux device parent
  drm/amd/display: Use connector kdev as aux device parent
  drm/i915: Implement MST Aux device registration
  drm/nouveau/kms/nv50: Implement MST Aux device registration
  drm/radeon: Implement MST Aux device registration
  drm/amd/display: Implement MST Aux device registration

Ville Syrjälä (1):
  drm/dp_mst: Enable registration of AUX devices for MST ports

 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  26 +++-
 drivers/gpu/drm/bridge/analogix-anx78xx.c |  22 +--
 drivers/gpu/drm/drm_dp_aux_dev.c  |  19 ++-
 drivers/gpu/drm/drm_dp_mst_topology.c | 137 --
 drivers/gpu/drm/drm_sysfs.c   |  23 +++
 drivers/gpu/drm/i915/display/intel_dp_mst.c   |  29 +++-
 drivers/gpu/drm/nouveau/dispnv50/disp.c   |  20 +++
 drivers/gpu/drm/nouveau/nouveau_connector.c   |   2 +-
 drivers/gpu/drm/radeon/radeon_dp_mst.c|  22 +++
 include/drm/drm_dp_helper.h   |   4 +
 include/drm/drm_dp_mst_helper.h   |  11 ++
 11 files changed, 285 insertions(+), 30 deletions(-)

-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 02/10] drm/dp_mst: Enable registration of AUX devices for MST ports (v2)

2019-07-04 Thread sunpeng.li
From: Ville Syrjälä 

All available downstream ports - physical and logical - are exposed for
each MST device. They are listed in /dev/, following the same naming
scheme as SST devices by appending an incremental ID.

Although all downstream ports are exposed, only some will work as
expected. Consider the following topology:

   +-+
   |  ASIC   |
   +-+
  Conn-0|
|
   +v+
  +| MST HUB |+
  |+-+|
  |   |
  |Port-1   Port-2|
+-v-+   +-v-+
|  MST  |   |  SST  |
|  Display  |   |  Display  |
+---+   +---+
  |Port-1
  x

 MST Path  | MST Device
 --+--
 sst:0 | MST Hub
 mst:0-1   | MST Display
 mst:0-1-1 | MST Display's disconnected DP out
 mst:0-1-8 | MST Display's internal sink
 mst:0-2   | SST Display

On certain MST displays, the upstream physical port will ACK DPCD reads.
However, reads on the local logical port to the internal sink will
*NAK*. i.e. reading mst:0-1 ACKs, but mst:0-1-8 NAKs.

There may also be duplicates. Some displays will return the same GUID
when reading DPCD from both mst:0-1 and mst:0-1-8.

There are some device-dependent behavior as well. The MST hub used
during testing will actually *ACK* read requests on a disconnected
physical port, whereas the MST displays will NAK.

In light of these discrepancies, it's simpler to expose all downstream
ports - both physical and logical - and let the user decide what to use.

(v2) changes:

Moved remote aux device (un)registration to new mst connector late
register and early unregister helpers. Drivers should call these from
their own mst connector function hooks.

This is to solve an issue during driver unload, where mst connector
devices are unregistered before the remote aux devices are. In a setup
where aux devices are created as children of connector devices, the aux
device would be removed too early, and uncleanly. Doing so in
early_unregister solves this issue, as that is called before connector
unregistration.

Signed-off-by: Ville Syrjälä 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c  |  16 ++-
 drivers/gpu/drm/drm_dp_mst_topology.c | 137 --
 include/drm/drm_dp_helper.h   |   4 +
 include/drm/drm_dp_mst_helper.h   |  11 +++
 4 files changed, 156 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 26e38dacf654..4aa5e455e894 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -37,6 +37,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "drm_crtc_helper_internal.h"
@@ -116,6 +117,7 @@ static ssize_t name_show(struct device *dev,
 
return res;
 }
+
 static DEVICE_ATTR_RO(name);
 
 static struct attribute *drm_dp_aux_attrs[] = {
@@ -162,7 +164,12 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf,
+  todo);
+   else
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
@@ -209,7 +216,12 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
break;
}
 
-   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf,
+   todo);
+   else
+   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 0984b9a34d55..dde79c44b625 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -36,6 +36,8 @@
 #include 
 #include 
 
+#include "drm_crtc_helper_internal.h"
+
 /**
  * DOC: dp mst helper
  *
@@ -53,6 +55,9 @@ static int drm_dp_dpcd_write_payload(struct 
drm_dp_mst_topology_mgr *mgr,
 int id,
 struct drm_dp_payload *payload);
 
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+struct drm_dp_mst_port *port,
+int offset, int size, u8 *bytes);
 static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
  

[PATCH 10/10] drm/amd/display: Implement MST Aux device registration

2019-07-04 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Cc: Jerry Zuo 
Cc: Nicholas Kazlauskas 
Signed-off-by: Leo Li 
---
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 24 ++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 53d2cfe62e13..16218a202b59 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -156,6 +156,26 @@ dm_dp_mst_connector_destroy(struct drm_connector 
*connector)
kfree(amdgpu_dm_connector);
 }
 
+static int
+amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
+{
+   struct amdgpu_dm_connector *amdgpu_dm_connector =
+   to_amdgpu_dm_connector(connector);
+   struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
+{
+   struct amdgpu_dm_connector *amdgpu_dm_connector =
+   to_amdgpu_dm_connector(connector);
+   struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
.detect = dm_dp_mst_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -164,7 +184,9 @@ static const struct drm_connector_funcs 
dm_dp_mst_connector_funcs = {
.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_set_property = amdgpu_dm_connector_atomic_set_property,
-   .atomic_get_property = amdgpu_dm_connector_atomic_get_property
+   .atomic_get_property = amdgpu_dm_connector_atomic_get_property,
+   .late_register = amdgpu_dm_mst_connector_late_register,
+   .early_unregister = amdgpu_dm_mst_connector_early_unregister,
 };
 
 static int dm_dp_mst_get_modes(struct drm_connector *connector)
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 09/10] drm/radeon: Implement MST Aux device registration

2019-07-04 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Cc: Alex Deucher 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/radeon/radeon_dp_mst.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c 
b/drivers/gpu/drm/radeon/radeon_dp_mst.c
index 2994f07fbad9..2d53699734fb 100644
--- a/drivers/gpu/drm/radeon/radeon_dp_mst.c
+++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c
@@ -260,11 +260,33 @@ radeon_dp_mst_connector_destroy(struct drm_connector 
*connector)
kfree(radeon_connector);
 }
 
+static int
+radeon_dp_mst_connector_late_register(struct drm_connector *connector)
+{
+   struct radeon_connector *radeon_connector =
+   to_radeon_connector(connector);
+   struct drm_dp_mst_port *port = radeon_connector->port;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+radeon_dp_mst_connector_early_unregister(struct drm_connector *connector)
+{
+   struct radeon_connector *radeon_connector =
+   to_radeon_connector(connector);
+   struct drm_dp_mst_port *port = radeon_connector->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+}
+
 static const struct drm_connector_funcs radeon_dp_mst_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = radeon_dp_mst_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_dp_mst_connector_destroy,
+   .late_register = radeon_dp_mst_connector_late_register,
+   .early_unregister = radeon_dp_mst_connector_early_unregister,
 };
 
 static struct drm_connector *radeon_dp_add_mst_connector(struct 
drm_dp_mst_topology_mgr *mgr,
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 07/10] drm/i915: Implement MST Aux device registration

2019-07-04 Thread sunpeng.li
From: Leo Li 

Implement late_register and early_unregister hooks for MST connectors.
Call drm helpers for MST connector registration, which registers the
AUX devices.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/i915/display/intel_dp_mst.c | 29 +++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 60652ebbdf61..be309016f746 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -400,13 +400,38 @@ intel_dp_mst_detect(struct drm_connector *connector, bool 
force)
  intel_connector->port);
 }
 
+static int
+intel_dp_mst_connector_late_register(struct drm_connector *connector)
+{
+   struct intel_connector *intel_connector = to_intel_connector(connector);
+   struct drm_dp_mst_port *port = intel_connector->port;
+
+   int ret;
+
+   ret = intel_connector_register(connector);
+   if (ret)
+   return ret;
+
+   return drm_dp_mst_connector_late_register(connector, port);
+}
+
+static void
+intel_dp_mst_connector_early_unregister(struct drm_connector *connector)
+{
+   struct intel_connector *intel_connector = to_intel_connector(connector);
+   struct drm_dp_mst_port *port = intel_connector->port;
+
+   drm_dp_mst_connector_early_unregister(connector, port);
+   intel_connector_unregister(connector);
+}
+
 static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
.detect = intel_dp_mst_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.atomic_get_property = intel_digital_connector_atomic_get_property,
.atomic_set_property = intel_digital_connector_atomic_set_property,
-   .late_register = intel_connector_register,
-   .early_unregister = intel_connector_unregister,
+   .late_register = intel_dp_mst_connector_late_register,
+   .early_unregister = intel_dp_mst_connector_early_unregister,
.destroy = intel_connector_destroy,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
-- 
2.22.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 2/7] drm/dp_mst: Register AUX devices for MST ports

2019-05-16 Thread sunpeng.li
From: Ville Syrjälä 

All available downstream ports - physical and logical - are exposed for
each MST device. They are listed in /dev/, following the same naming
scheme as SST devices by appending an incremental ID.

Although all downstream ports are exposed, only some will work as
expected. Consider the following topology:

   +-+
   |  ASIC   |
   +-+
  Conn-0|
|
   +v+
  +| MST HUB |+
  |+-+|
  |   |
  |Port-1   Port-2|
+-v-+   +-v-+
|  MST  |   |  SST  |
|  Display  |   |  Display  |
+---+   +---+
  |Port-1
  x

 MST Path  | MST Device
 --+--
 sst:0 | MST Hub
 mst:0-1   | MST Display
 mst:0-1-1 | MST Display's disconnected DP out
 mst:0-1-8 | MST Display's internal sink
 mst:0-2   | SST Display

On certain MST displays, the upstream physical port will ACK DPCD reads.
However, reads on the local logical port to the internal sink will
*NAK*. i.e. reading mst:0-1 ACKs, but mst:0-1-8 NAKs.

There may also be duplicates. Some displays will return the same GUID
when reading DPCD from both mst:0-1 and mst:0-1-8.

There are some device-dependent behavior as well. The MST hub used
during testing will actually *ACK* read requests on a disconnected
physical port, whereas the MST displays will NAK.

In light of these discrepancies, it's simpler to expose all downstream
ports - both physical and logical - and let the user decide what to use.

Cc: Lyude Paul 
Signed-off-by: Ville Syrjälä 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c  |  14 -
 drivers/gpu/drm/drm_dp_mst_topology.c | 103 +-
 include/drm/drm_dp_helper.h   |   4 ++
 include/drm/drm_dp_mst_helper.h   |   6 ++
 4 files changed, 112 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 6d84611..01c02b9 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -114,6 +115,7 @@ static ssize_t name_show(struct device *dev,
 
return res;
 }
+
 static DEVICE_ATTR_RO(name);
 
 static struct attribute *drm_dp_aux_attrs[] = {
@@ -160,7 +162,11 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, 
todo);
+   else
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
@@ -207,7 +213,11 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
break;
}
 
-   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf, 
todo);
+   else
+   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 2ab16c9..54da68e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -35,6 +35,8 @@
 #include 
 #include 
 
+#include "drm_crtc_helper_internal.h"
+
 /**
  * DOC: dp mst helper
  *
@@ -52,6 +54,9 @@ static int drm_dp_dpcd_write_payload(struct 
drm_dp_mst_topology_mgr *mgr,
 int id,
 struct drm_dp_payload *payload);
 
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+struct drm_dp_mst_port *port,
+int offset, int size, u8 *bytes);
 static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
  struct drm_dp_mst_port *port,
  int offset, int size, u8 *bytes);
@@ -941,6 +946,8 @@ static void drm_dp_destroy_port(struct kref *kref)
struct drm_dp_mst_topology_mgr *mgr = port->mgr;
 
if (!port->input) {
+   drm_dp_aux_unregister_devnode(&port->aux);
+
port->vcpi.num_slots = 0;
 
kfree(port->cached_edid);
@@ -1095,6 +1102,46 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port 
*port)
return send_link;
 }
 
+/**
+ * drm_dp_mst_dpcd_read() - read a series of bytes from the DPCD via sideband
+ * @aux: Fake sideband AUX CH
+ * @offset: address of the

[PATCH 1/7] drm/dp: Use non-cyclic idr

2019-05-16 Thread sunpeng.li
From: Leo Li 

In preparation for adding aux devices for DP MST, make the IDR
non-cyclic. That way, hotplug cycling MST devices won't needlessly
increment the minor version index.

Signed-off-by: Leo Li 
Reviewed-by: Lyude Paul 
Reviewed-by: Ville Syrjälä 
---
 drivers/gpu/drm/drm_dp_aux_dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 0e4f25d..6d84611 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -80,8 +80,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct 
drm_dp_aux *aux)
kref_init(&aux_dev->refcount);
 
mutex_lock(&aux_idr_mutex);
-   index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-GFP_KERNEL);
+   index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
mutex_unlock(&aux_idr_mutex);
if (index < 0) {
kfree(aux_dev);
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 6/7] drm/bridge/analogix-anx78xx: Use connector kdev as aux device parent

2019-05-16 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

To do so, the connector needs to be registered beforehand. Therefore,
shift aux registration to be after connector registration.

Cc: Enric Balletbo i Serra 
Cc: Nicolas Boichat 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/bridge/analogix-anx78xx.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c 
b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index f8433c9..9fc8b4c 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1018,17 +1018,6 @@ static int anx78xx_bridge_attach(struct drm_bridge 
*bridge)
return -ENODEV;
}
 
-   /* Register aux channel */
-   anx78xx->aux.name = "DP-AUX";
-   anx78xx->aux.dev = &anx78xx->client->dev;
-   anx78xx->aux.transfer = anx78xx_aux_transfer;
-
-   err = drm_dp_aux_register(&anx78xx->aux);
-   if (err < 0) {
-   DRM_ERROR("Failed to register aux channel: %d\n", err);
-   return err;
-   }
-
err = drm_connector_init(bridge->dev, &anx78xx->connector,
 &anx78xx_connector_funcs,
 DRM_MODE_CONNECTOR_DisplayPort);
@@ -1048,6 +1037,17 @@ static int anx78xx_bridge_attach(struct drm_bridge 
*bridge)
 
anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
+   /* Register aux channel */
+   anx78xx->aux.name = "DP-AUX";
+   anx78xx->aux.dev = &anx78xx->connector.kdev;
+   anx78xx->aux.transfer = anx78xx_aux_transfer;
+
+   err = drm_dp_aux_register(&anx78xx->aux);
+   if (err < 0) {
+   DRM_ERROR("Failed to register aux channel: %d\n", err);
+   return err;
+   }
+
err = drm_connector_attach_encoder(&anx78xx->connector,
   bridge->encoder);
if (err) {
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 3/7] drm/dp-mst: Use connector kdev as aux device parent

2019-05-16 Thread sunpeng.li
From: Leo Li 

Placing the MST aux device as a child of the connector gives udev the
ability to access the connector device's attributes. This will come in
handy when writing udev rules to create more descriptive symlinks to the
MST aux devices.

Cc: Ville Syrjälä 
Cc: Lyude Paul 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 54da68e..cd2f3c4 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1269,6 +1269,9 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
}
(*mstb->mgr->cbs->register_connector)(port->connector);
 
+   if (port->connector->registration_state == 
DRM_CONNECTOR_REGISTERED)
+   port->aux.dev = port->connector->kdev;
+
drm_dp_aux_register_devnode(&port->aux);
}
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 4/7] drm/sysfs: Add mstpath attribute to connector devices

2019-05-16 Thread sunpeng.li
From: Leo Li 

This can be used to create more descriptive symlinks for MST aux
devices. Consider the following udev rule:

SUBSYSTEM=="drm_dp_aux_dev", SUBSYSTEMS=="drm", ATTRS{mstpath}=="?*",
SYMLINK+="drm_dp_aux/by-path/$attr{mstpath}"

The following symlinks will be created (depending on your MST topology):

$ ls /dev/drm_dp_aux/by-path/
card0-mst:0-1  card0-mst:0-1-1  card0-mst:0-1-8  card0-mst:0-8

Cc: Ville Syrjälä 
Cc: Lyude Paul 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_sysfs.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index ecb7b33..e000e0c 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -229,16 +229,39 @@ static ssize_t modes_show(struct device *device,
return written;
 }
 
+static ssize_t mstpath_show(struct device *device,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct drm_connector *connector = to_drm_connector(device);
+   ssize_t ret = 0;
+   char *path;
+
+   mutex_lock(&connector->dev->mode_config.mutex);
+   if (!connector->path_blob_ptr)
+   goto unlock;
+
+   path = connector->path_blob_ptr->data;
+   ret = snprintf(buf, PAGE_SIZE, "card%d-%s\n",
+  connector->dev->primary->index, path);
+
+unlock:
+   mutex_unlock(&connector->dev->mode_config.mutex);
+   return ret;
+}
+
 static DEVICE_ATTR_RW(status);
 static DEVICE_ATTR_RO(enabled);
 static DEVICE_ATTR_RO(dpms);
 static DEVICE_ATTR_RO(modes);
+static DEVICE_ATTR_RO(mstpath);
 
 static struct attribute *connector_dev_attrs[] = {
&dev_attr_status.attr,
&dev_attr_enabled.attr,
&dev_attr_dpms.attr,
&dev_attr_modes.attr,
+   &dev_attr_mstpath.attr,
NULL
 };
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 5/7] drm/amd/display: Use connector kdev as aux device parent

2019-05-16 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

For example, the following udev rule:

SUBSYSTEM=="drm_dp_aux_dev", SUBSYSTEMS=="drm", ATTRS{edid}=="*",
SYMLINK+="drm_dp_aux/by-name/$id"

Will create the following symlinks using the connector's name:

$ ls /dev/drm_dp_aux/by-name/
card0-DP-1  card0-DP-2  card0-DP-3

Cc: Ville Syrjälä 
Cc: Lyude Paul 
Cc: Nicholas Kazlauskas 
Cc: Harry Wentland 
Cc: Jerry (Fangzhi) Zuo 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index a6f44a4..083fb97 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -385,7 +385,7 @@ void amdgpu_dm_initialize_dp_connector(struct 
amdgpu_display_manager *dm,
   struct amdgpu_dm_connector *aconnector)
 {
aconnector->dm_dp_aux.aux.name = "dmdc";
-   aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+   aconnector->dm_dp_aux.aux.dev = aconnector->base.kdev;
aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc;
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 7/7] drm/nouveau: Use connector kdev as aux device parent

2019-05-16 Thread sunpeng.li
From: Leo Li 

Set the connector's kernel device as the parent for the aux kernel
device. This allows udev rules to access connector attributes when
creating symlinks to aux devices.

Cc: Ben Skeggs 
Cc: Lyude Paul 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c 
b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 3f463c9..738782a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -1345,7 +1345,7 @@ nouveau_connector_create(struct drm_device *dev,
break;
case DRM_MODE_CONNECTOR_DisplayPort:
case DRM_MODE_CONNECTOR_eDP:
-   nv_connector->aux.dev = dev->dev;
+   nv_connector->aux.dev = connector->kdev;
nv_connector->aux.transfer = nouveau_connector_aux_xfer;
snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x",
 dcbe->hasht, dcbe->hashm);
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 0/7] Add DP MST AUX devices

2019-05-16 Thread sunpeng.li
From: Leo Li 

This series adds support for MST AUX devices. 

A more descriptive 'mstpath' attribute is also added to MST connector
devices. In addition, the DP aux device is made to be a child of the
corresponding connector's device where possible (*). This allows udev
rules to provide descriptive symlinks to the AUX devices.

(*) This can only be done on drivers that register their connector and
aux devices via drm_connector_register() and drm_dp_aux_register()
respectively. The connector also needs to be registered before the aux
device.

Leo Li (6):
  drm/dp: Use non-cyclic idr
  drm/dp-mst: Use connector kdev as aux device parent
  drm/sysfs: Add mstpath attribute to connector devices
  drm/amd/display: Use connector kdev as aux device parent
  drm/bridge/analogix-anx78xx: Use connector kdev as aux device parent
  drm/nouveau: Use connector kdev as aux device parent

Ville Syrjälä (1):
  drm/dp_mst: Register AUX devices for MST ports

 .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c|   2 +-
 drivers/gpu/drm/bridge/analogix-anx78xx.c  |  22 ++---
 drivers/gpu/drm/drm_dp_aux_dev.c   |  17 +++-
 drivers/gpu/drm/drm_dp_mst_topology.c  | 106 ++---
 drivers/gpu/drm/drm_sysfs.c|  23 +
 drivers/gpu/drm/nouveau/nouveau_connector.c|   2 +-
 include/drm/drm_dp_helper.h|   4 +
 include/drm/drm_dp_mst_helper.h|   6 ++
 8 files changed, 152 insertions(+), 30 deletions(-)

-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 3/3] drm/dp_mst: Register AUX devices for MST ports

2019-04-22 Thread sunpeng.li
From: Ville Syrjälä 

All available downstream ports - physical and logical - are exposed for
each MST device. They are listed in /dev/, following the same naming
scheme as SST devices by appending an incremental ID.

Additionally, a 'path' attribute is attached to the device. This is to
allow udev to provide more identifiable symlinks to these devices,
similar to /dev/disks. For example, adding the following udev rule:

SUBSYSTEMS=="drm_dp_aux_dev", ATTR{path}=="?*", 
SYMLINK+="drm_dp_aux/by-path/$attr{path}"

With a MST topology like so:

   +-+
   |  ASIC   |
   +-+
  Conn-0|
|
   +v+
  +| MST HUB |+
  |+-+|
  |   |
  |Port-1   Port-2|
+-v-+   +-v-+
|  MST  |   |  SST  |
|  Display  |   |  Display  |
+---+   +---+
  |Port-1
  x

Will create the following symlinks in 'drm_dp_aux/by-path/':

AUX Device Name   | MST Device
--+--
card0_sst:0 (*)   | MST Hub
card0_mst:0-1 | MST Display
card0_mst:0-1-1   | MST Display's disconnected DP out
card0_mst:0-1-8   | MST Display's internal sink
card0_mst:0-2 | SST Display

(*) Note that the first digit is suppose to mean 'Connector ID'.
However, that's only true for 'mst:' paths. A TODO item has been left to
address this.

Although all downstream ports are exposed, only some will work. On
certain MST displays, the upstream physical port will ACK DPCD reads.
However, reads on the local logical port to the internal sink will
*NAK*. i.e. reading mst:0-1 ACKs, but mst:0-1-8 NAKs.

There may also be duplicates. Some displays will return the same GUID
when reading DPCD from both mst:0-1 and mst:0-1-8.

There are some device-dependent behavior as well. The MST hub used
during testing will actually *ACK* read requests on a disconnected
physical port, whereas the MST displays will NAK.

In light of these discrepancies, it's simpler to expose all downstream
ports - both physical and logical - and let the user decide what to use.

Signed-off-by: Ville Syrjälä 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c  |  53 -
 drivers/gpu/drm/drm_dp_mst_topology.c | 103 +-
 include/drm/drm_dp_helper.h   |   4 ++
 include/drm/drm_dp_mst_helper.h   |   6 ++
 4 files changed, 151 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 6d84611..4218bbf 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -114,10 +115,50 @@ static ssize_t name_show(struct device *dev,
 
return res;
 }
+
+static int is_drm_primary_device(struct device *dev, void *data)
+{
+   return strstr(dev_name(dev), "card") != NULL;
+}
+
+static ssize_t path_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+   struct drm_dp_aux_dev *aux_dev =
+   drm_dp_aux_dev_get_by_minor(MINOR(dev->devt));
+   struct drm_dp_aux *aux = aux_dev->aux;
+   struct drm_dp_mst_port *port;
+   struct device *card;
+   char temp[64];
+   ssize_t res;
+
+   card = device_find_child(dev->parent, NULL,
+is_drm_primary_device);
+
+   if (!aux->is_remote) {
+   /*
+* TODO: AUX index does not correlate with connector ID. See if
+* connector ID can be used instead.
+*/
+   res = sprintf(buf, "%s_%s:%d\n",
+ dev_name(card), "sst", aux_dev->index);
+   return res;
+   }
+
+   port = container_of(aux, struct drm_dp_mst_port, aux);
+   drm_dp_build_mst_prop_path(port->parent, port->port_num,
+  temp, sizeof(temp));
+   res = sprintf(buf, "%s_%s\n", dev_name(card), temp);
+
+   return res;
+}
+
 static DEVICE_ATTR_RO(name);
+static DEVICE_ATTR_RO(path);
 
 static struct attribute *drm_dp_aux_attrs[] = {
&dev_attr_name.attr,
+   &dev_attr_path.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(drm_dp_aux);
@@ -160,7 +201,11 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, 
todo);
+   else
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
@@ -207,7 +252,11 @@ static ssize_t auxdev_write_iter(str

[PATCH 1/3] drm/dp: Use non-cyclic idr

2019-04-22 Thread sunpeng.li
From: Leo Li 

In preparation for adding aux devices for DP MST, make the IDR
non-cyclic. That way, hotplug cycling MST devices won't needlessly
increment the minor version index.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 0e4f25d..6d84611 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -80,8 +80,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct 
drm_dp_aux *aux)
kref_init(&aux_dev->refcount);
 
mutex_lock(&aux_idr_mutex);
-   index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-GFP_KERNEL);
+   index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
mutex_unlock(&aux_idr_mutex);
if (index < 0) {
kfree(aux_dev);
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 2/3] drm/dp_mst: Expose build_mst_prop_path()

2019-04-22 Thread sunpeng.li
From: Leo Li 

To give identifiable attributes to MST DP aux devices, we can use the
MST relative address. Expose this function for later use.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 4 ++--
 include/drm/drm_dp_mst_helper.h   | 4 
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 2ab16c9..86ff8e2 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1120,7 +1120,7 @@ static void drm_dp_check_mstb_guid(struct 
drm_dp_mst_branch *mstb, u8 *guid)
}
 }
 
-static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
+void drm_dp_build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
int pnum,
char *proppath,
size_t proppath_size)
@@ -1202,7 +1202,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch 
*mstb,
if (created && !port->input) {
char proppath[255];
 
-   build_mst_prop_path(mstb, port->port_num, proppath, 
sizeof(proppath));
+   drm_dp_build_mst_prop_path(mstb, port->port_num, proppath, 
sizeof(proppath));
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, 
port, proppath);
if (!port->connector) {
/* remove it from the port list */
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 371cc28..81c8d79 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -602,6 +602,10 @@ void drm_dp_mst_deallocate_vcpi(struct 
drm_dp_mst_topology_mgr *mgr,
 int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
   int pbn);
 
+void drm_dp_build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
+  int pnum,
+  char *proppath,
+  size_t proppath_size);
 
 int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr);
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 1/2] drm/dp_aux: Use non-cyclic idr, add suffix option for aux device

2019-04-12 Thread sunpeng.li
From: Leo Li 

In preparation for adding aux devices for DP MST:

1. A non-cyclic idr is used for the device minor version. That way,
   hotplug cycling MST devices won't needlessly increment the minor
   version index.
2. A suffix option is added to the aux device file name. It can be used
   to identify the corresponding MST device.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_crtc_helper_internal.h | 5 +++--
 drivers/gpu/drm/drm_dp_aux_dev.c   | 8 
 drivers/gpu/drm/drm_dp_helper.c| 2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h 
b/drivers/gpu/drm/drm_crtc_helper_internal.h
index b5ac158..9f0907b 100644
--- a/drivers/gpu/drm/drm_crtc_helper_internal.h
+++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
@@ -46,7 +46,7 @@ static inline int drm_fb_helper_modinit(void)
 #ifdef CONFIG_DRM_DP_AUX_CHARDEV
 int drm_dp_aux_dev_init(void);
 void drm_dp_aux_dev_exit(void);
-int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
+int drm_dp_aux_register_devnode(struct drm_dp_aux *aux, const char *suffix);
 void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
 #else
 static inline int drm_dp_aux_dev_init(void)
@@ -58,7 +58,8 @@ static inline void drm_dp_aux_dev_exit(void)
 {
 }
 
-static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
+static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux,
+ const char *suffix)
 {
return 0;
 }
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 0e4f25d..2310a67 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -80,8 +80,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct 
drm_dp_aux *aux)
kref_init(&aux_dev->refcount);
 
mutex_lock(&aux_idr_mutex);
-   index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS,
-GFP_KERNEL);
+   index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL);
mutex_unlock(&aux_idr_mutex);
if (index < 0) {
kfree(aux_dev);
@@ -290,7 +289,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
 }
 
-int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
+int drm_dp_aux_register_devnode(struct drm_dp_aux *aux, const char *suffix)
 {
struct drm_dp_aux_dev *aux_dev;
int res;
@@ -301,7 +300,8 @@ int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
 
aux_dev->dev = device_create(drm_dp_aux_dev_class, aux->dev,
 MKDEV(drm_dev_major, aux_dev->index), NULL,
-"drm_dp_aux%d", aux_dev->index);
+"drm_dp_aux%d%s", aux_dev->index,
+suffix ? suffix : "");
if (IS_ERR(aux_dev->dev)) {
res = PTR_ERR(aux_dev->dev);
aux_dev->dev = NULL;
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index e2266ac..13f1005 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -1143,7 +1143,7 @@ int drm_dp_aux_register(struct drm_dp_aux *aux)
strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
sizeof(aux->ddc.name));
 
-   ret = drm_dp_aux_register_devnode(aux);
+   ret = drm_dp_aux_register_devnode(aux, NULL);
if (ret)
return ret;
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 2/2] drm/dp_mst: Register aux-dev nodes for MST ports

2019-04-12 Thread sunpeng.li
From: Ville Syrjälä 

Expose AUX devices for MST ports, similar to how they are exposed for
SST.

The registered device will have it's MST port path appended in order to
identify it. i.e. /dev/drm_dp_aux4_mst:0-2-1

So for a MST topology like so:

   +-+
   |  ASIC   |
   +-+
  Conn-0|
|
   +v+
  +| MST HUB |+
  |+-+|
  |   |
  |Port-1   Port-2|
+-v-+   +-v-+
|  MST  |   |  SST  |
|  Display  |   |  Display  |
+---+   +---+
  |Port-1
  x

The list of AUX device names will look like:

AUX Device Name   | MST Device
--+--
drm_dp_aux0   | MST Hub
drm_dp_aux1_mst:0-1-1 | MST Display's disconnected DP out
drm_dp_aux2_mst:0-1   | MST Display
drm_dp_aux3_mst:0-2   | SST Display

Note that aux devices are only created for Physical Ports. Logical Ports
are left out, since they are internally connected within the MST device
(not connected to a DP RX or TX).

Leo Li:
* Add missing drm_crtc_helper_internal.h include
* Fix hard-coded offset and size in drm_dp_send_dpcd_read()
* Only create aux devices for physical ports.

Signed-off-by: Ville Syrjälä 
Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_dp_aux_dev.c  |  13 +++-
 drivers/gpu/drm/drm_dp_mst_topology.c | 109 ++
 include/drm/drm_dp_helper.h   |   4 ++
 include/drm/drm_dp_mst_helper.h   |   6 ++
 4 files changed, 117 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 2310a67..f1241d1 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -160,7 +161,11 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct 
iov_iter *to)
break;
}
 
-   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, 
todo);
+   else
+   res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
@@ -207,7 +212,11 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
break;
}
 
-   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+   if (aux_dev->aux->is_remote)
+   res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf, 
todo);
+   else
+   res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo);
+
if (res <= 0)
break;
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 2ab16c9..d5282db 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -35,6 +35,8 @@
 #include 
 #include 
 
+#include "drm_crtc_helper_internal.h"
+
 /**
  * DOC: dp mst helper
  *
@@ -52,6 +54,9 @@ static int drm_dp_dpcd_write_payload(struct 
drm_dp_mst_topology_mgr *mgr,
 int id,
 struct drm_dp_payload *payload);
 
+static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr,
+struct drm_dp_mst_port *port,
+int offset, int size, u8 *bytes);
 static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
  struct drm_dp_mst_port *port,
  int offset, int size, u8 *bytes);
@@ -941,6 +946,8 @@ static void drm_dp_destroy_port(struct kref *kref)
struct drm_dp_mst_topology_mgr *mgr = port->mgr;
 
if (!port->input) {
+   drm_dp_aux_unregister_devnode(&port->aux);
+
port->vcpi.num_slots = 0;
 
kfree(port->cached_edid);
@@ -1095,6 +1102,46 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port 
*port)
return send_link;
 }
 
+/**
+ * drm_dp_mst_dpcd_read() - read a series of bytes from the DPCD via sideband
+ * @aux: Fake sideband AUX CH
+ * @offset: address of the (first) register to read
+ * @buffer: buffer to store the register values
+ * @size: number of bytes in @buffer
+ *
+ * Performs the same functionality for remote devices via
+ * sideband messaging as drm_dp_dpcd_read() does for local
+ * devices via actual AUX CH.
+ */
+ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux,
+unsigned int offset, void *buffer, size_t size)
+{
+   struct drm_dp_mst_port *port = container_of(aux, struct 
drm_dp_mst_port, aux);
+
+ 

[RFC 0/2] Add AUX device entries for DP MST devices

2019-04-12 Thread sunpeng.li
From: Leo Li 

Hi all,

This is a follup to this change made by Ville to add MST aux nodes:
https://github.com/vsyrjala/linux/commit/cac63f799ee2f5fbbe4f0a375383f13e03d640a5
Patch 2/2 describes what I added on top.

Sending as an RFC since there are some items I'm not certain on:

1) Only expose aux devices for physical ports. FWICT, only DPTX and DPRX
   can handle AUX transactions, leaving logical ports out.
2) Naming of exposed AUX devices. I'm not sure if the scheme implemented
   here is the best approach.

Let me know your thoughts,
Leo

Leo Li (1):
  drm/dp_mst: Use non-cyclic idr, add suffix option for aux device

Ville Syrjälä (1):
  drm/dp_mst: Register aux-dev nodes for MST ports

 drivers/gpu/drm/drm_crtc_helper_internal.h |   5 +-
 drivers/gpu/drm/drm_dp_aux_dev.c   |  21 --
 drivers/gpu/drm/drm_dp_helper.c|   2 +-
 drivers/gpu/drm/drm_dp_mst_topology.c  | 109 +
 include/drm/drm_dp_helper.h|   4 ++
 include/drm/drm_dp_mst_helper.h|   6 ++
 6 files changed, 125 insertions(+), 22 deletions(-)

-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] drm/amd/display: Fix 64-bit division for 32-bit builds

2018-12-19 Thread sunpeng.li
From: Ken Chalmers 

[Why]
32-bit builds break when doing 64-bit division directly.

[How]
Use the div_u64() function instead to perform the division.

Fixes: 
https://lists.freedesktop.org/archives/dri-devel/2018-December/201008.html
Signed-off-by: Ken Chalmers 
Reviewed-by: Leo Li 
---
 drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c 
b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
index 5c629ae..8b5ce55 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
@@ -94,7 +94,7 @@ static void program_pix_dur(struct timing_generator *tg, 
uint32_t pix_clk_100hz)
if (pix_clk_100hz == 0)
return;
 
-   pix_dur = 100ull / pix_clk_100hz;
+   pix_dur = div_u64(100ull, pix_clk_100hz);
 
set_reg_field_value(
value,
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2] drm: Get ref on CRTC commit object when waiting for flip_done

2018-10-15 Thread sunpeng.li
From: Leo Li 

This fixes a general protection fault, caused by accessing the contents
of a flip_done completion object that has already been freed. It occurs
due to the preemption of a non-blocking commit worker thread W by
another commit thread X. X continues to clear its atomic state at the
end, destroying the CRTC commit object that W still needs. Switching
back to W and accessing the commit objects then leads to bad results.

Worker W becomes preemptable when waiting for flip_done to complete. At
this point, a frequently occurring commit thread X can take over. Here's
an example where W is a worker thread that flips on both CRTCs, and X
does a legacy cursor update on both CRTCs:

...
 1. W does flip work
 2. W runs commit_hw_done()
 3. W waits for flip_done on CRTC 1
 4. > flip_done for CRTC 1 completes
 5. W finishes waiting for CRTC 1
 6. W waits for flip_done on CRTC 2

 7. > Preempted by X
 8. > flip_done for CRTC 2 completes
 9. X atomic_check: hw_done and flip_done are complete on all CRTCs
10. X updates cursor on both CRTCs
11. X destroys atomic state
12. X done

13. > Switch back to W
14. W waits for flip_done on CRTC 2
15. W raises general protection fault

The error looks like so:

general protection fault:  [#1] PREEMPT SMP PTI
**snip**
Call Trace:
 lock_acquire+0xa2/0x1b0
 _raw_spin_lock_irq+0x39/0x70
 wait_for_completion_timeout+0x31/0x130
 drm_atomic_helper_wait_for_flip_done+0x64/0x90 [drm_kms_helper]
 amdgpu_dm_atomic_commit_tail+0xcae/0xdd0 [amdgpu]
 commit_tail+0x3d/0x70 [drm_kms_helper]
 process_one_work+0x212/0x650
 worker_thread+0x49/0x420
 kthread+0xfb/0x130
 ret_from_fork+0x3a/0x50
Modules linked in: x86_pkg_temp_thermal amdgpu(O) chash(O)
gpu_sched(O) drm_kms_helper(O) syscopyarea sysfillrect sysimgblt
fb_sys_fops ttm(O) drm(O)

Note that i915 has this issue masked, since hw_done is signaled after
waiting for flip_done. Doing so will block the cursor update from
happening until hw_done is signaled, preventing the cursor commit from
destroying the state.

v2: The reference on the commit object needs to be obtained before
hw_done() is signaled, since that's the point where another commit
is allowed to modify the state. Assuming that the
new_crtc_state->commit object still exists within flip_done() is
incorrect.

Fix by getting a reference in setup_commit(), and releasing it
during default_clear().

Signed-off-by: Leo Li 
---

Sending again, this time to the correct mailing list :)

Leo

 drivers/gpu/drm/drm_atomic.c|  5 +
 drivers/gpu/drm/drm_atomic_helper.c | 12 
 include/drm/drm_atomic.h| 11 +++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 3eb061e..12ae917 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -174,6 +174,11 @@ void drm_atomic_state_default_clear(struct 
drm_atomic_state *state)
state->crtcs[i].state = NULL;
state->crtcs[i].old_state = NULL;
state->crtcs[i].new_state = NULL;
+
+   if (state->crtcs[i].commit) {
+   drm_crtc_commit_put(state->crtcs[i].commit);
+   state->crtcs[i].commit = NULL;
+   }
}
 
for (i = 0; i < config->num_total_plane; i++) {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 80be74d..1bb4c31 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1408,15 +1408,16 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
 void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
  struct drm_atomic_state *old_state)
 {
-   struct drm_crtc_state *new_crtc_state;
struct drm_crtc *crtc;
int i;
 
-   for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
-   struct drm_crtc_commit *commit = new_crtc_state->commit;
+   for (i = 0; i < dev->mode_config.num_crtc; i++) {
+   struct drm_crtc_commit *commit = old_state->crtcs[i].commit;
int ret;
 
-   if (!commit)
+   crtc = old_state->crtcs[i].ptr;
+
+   if (!crtc || !commit)
continue;
 
ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ);
@@ -1934,6 +1935,9 @@ int drm_atomic_helper_setup_commit(struct 
drm_atomic_state *state,
drm_crtc_commit_get(commit);
 
commit->abort_completion = true;
+
+   state->crtcs[i].commit = commit;
+   drm_crtc_commit_get(commit);
}
 
for_each_oldnew_connector_in_state(state, conn, old_conn_state, 
new_conn_state, i) {
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_a

[PATCH] drm: Get ref on CRTC commit object when waiting for flip_done

2018-10-11 Thread sunpeng.li
From: Leo Li 

This fixes a general protection fault, caused by accessing the contents
of a flip_done completion object that has already been freed. It occurs
due to the preemption of a non-blocking commit worker thread W by
another commit thread X. X continues to clear its atomic state at the
end, destroying the CRTC commit object that W still needs. Switching
back to W and accessing the commit objects then leads to bad results.

Worker W becomes preemptable when waiting for flip_done to complete. At
this point, a frequently occurring commit thread X can take over. Here's
an example where W is a worker thread that flips on both CRTCs, and X
does a legacy cursor update on both CRTCs:

...
 1. W does flip work
 2. W runs commit_hw_done()
 3. W waits for flip_done on CRTC 1
 4. > flip_done for CRTC 1 completes
 5. W finishes waiting for CRTC 1
 6. W waits for flip_done on CRTC 2

 7. > Preempted by X
 8. > flip_done for CRTC 2 completes
 9. X atomic_check: hw_done and flip_done are complete on all CRTCs
10. X updates cursor on both CRTCs
11. X destroys atomic state
12. X done

13. > Switch back to W
14. W waits for flip_done on CRTC 2
15. W raises general protection fault

The error looks like so:

general protection fault:  [#1] PREEMPT SMP PTI
**snip**
Call Trace:
 lock_acquire+0xa2/0x1b0
 _raw_spin_lock_irq+0x39/0x70
 wait_for_completion_timeout+0x31/0x130
 drm_atomic_helper_wait_for_flip_done+0x64/0x90 [drm_kms_helper]
 amdgpu_dm_atomic_commit_tail+0xcae/0xdd0 [amdgpu]
 commit_tail+0x3d/0x70 [drm_kms_helper]
 process_one_work+0x212/0x650
 worker_thread+0x49/0x420
 kthread+0xfb/0x130
 ret_from_fork+0x3a/0x50
Modules linked in: x86_pkg_temp_thermal amdgpu(O) chash(O)
gpu_sched(O) drm_kms_helper(O) syscopyarea sysfillrect sysimgblt
fb_sys_fops ttm(O) drm(O)

Note that i915 has this issue masked, since hw_done is signaled after
waiting for flip_done. Doing so will block the cursor update from
happening until hw_done is signaled, preventing the cursor commit from
destroying the state.

Signed-off-by: Leo Li 
---
 drivers/gpu/drm/drm_atomic_helper.c | 30 ++
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 80be74d..efdf043 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1410,20 +1410,42 @@ void drm_atomic_helper_wait_for_flip_done(struct 
drm_device *dev,
 {
struct drm_crtc_state *new_crtc_state;
struct drm_crtc *crtc;
+   struct drm_crtc_commit **commits;
int i;
+   int num_crtc = dev->mode_config.num_crtc;
 
+   commits = kcalloc(num_crtc, sizeof(*commits), GFP_KERNEL);
+
+   /*
+* Because we open ourselves to preemption by calling
+* wait_for_completion_timeout(), we need to get our own references to
+* the commit objects. This is so that a preempting commit won't free
+* them.
+*/
for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
-   struct drm_crtc_commit *commit = new_crtc_state->commit;
+   commits[i] = new_crtc_state->commit;
+   if (commits[i])
+   drm_crtc_commit_get(commits[i]);
+   }
+
+   for (i = 0; i < num_crtc; i++) {
int ret;
 
-   if (!commit)
+   if (!commits[i])
continue;
 
-   ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ);
+   ret = wait_for_completion_timeout(&commits[i]->flip_done,
+ 10 * HZ);
if (ret == 0)
DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n",
- crtc->base.id, crtc->name);
+ commits[i]->crtc->base.id,
+ commits[i]->crtc->name);
}
+
+   for (i = 0; i < num_crtc; i++)
+   if (commits[i])
+   drm_crtc_commit_put(commits[i]);
+   kfree(commits);
 }
 EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done);
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/amd/display: Remove erroneous if statement in gamma set

2018-04-26 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

The lines were removed as part of the original change. They may have
been missed during merge.

This is a fixup to:

committ 265083076187e619aa9176aeb05ad630013429b4
Author: Leo (Sunpeng) Li 
Date:   Fri Feb 2 10:18:56 2018 -0500

drm/amd/display: Hookup color management functions
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index b7265f6..0d4a133 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -2206,11 +2206,9 @@ static int fill_plane_attributes(struct amdgpu_device 
*adev,
 
dc_plane_state->in_transfer_func = input_tf;
 
-   /* In case of gamma set, update gamma value */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) || \
defined(OS_NAME_RHEL_7_3) || \
defined(OS_NAME_RHEL_7_4_5)
-   if (crtc_state->gamma_lut)
/*
 * Always set input transfer function, since plane state is refreshed
 * every time.
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH] drm/atomic: Fix memleak on ERESTARTSYS during non-blocking commits

2018-01-04 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

During a non-blocking commit, it is possible to return before the
commit_tail work is queued (-ERESTARTSYS, for example).

Since a reference on the crtc commit object is obtained for the pending
vblank event when preparing the commit, the above situation will leave
us with an extra reference.

Therefore, if the commit_tail worker has not consumed the event at the
end of a commit, release it's reference.

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/drm_atomic_helper.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index ab40321..4253f57 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3421,6 +3421,15 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
 void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
 {
if (state->commit) {
+   /*
+* In the event that a non-blocking commit returns
+* -ERESTARTSYS before the commit_tail work is queued, we will
+* have an extra reference to the commit object. Release it, if
+* the event has not been consumed by the worker.
+*/
+   if (state->event)
+   drm_crtc_commit_put(state->commit);
+
kfree(state->commit->event);
state->commit->event = NULL;
drm_crtc_commit_put(state->commit);
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 1/6] drm/amd/display: Use DRM new-style object iterators.

2017-10-13 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

Use the correct for_each_new/old_* iterators instead of for_each_*

The following functions were considered:

amdgpu_dm_find_first_crtc_matching_connector: use for_each_new
- Old from_state_var flag was always choosing the new state

amdgpu_dm_display_resume: use for_each_new
- drm_atomic_helper_duplicate_state is called during suspend to
  cache the state
- It sets 'state' within the state triplet to 'new_state'

amdgpu_dm_commit_planes: use for_each_old
- Called after the state was swapped (via atomic commit tail)

amdgpu_dm_atomic_commit: use for_each_new
- Called before the state is swapped

amdgpu_dm_atomic_commit_tail: use for_each_old
- Called after the state was swapped

dm_update_crtcs_state: use for_each_new
- Called before the state is swapped (via atomic check)

amdgpu_dm_atomic_check: use for_each_new
- Called before the state is swapped

v2: Split out typo fixes to a new patch.

v3: Say "functions considered" instead of "affected functions". The
latter implies that changes are made to each.

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  3 +--
 2 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 9bfe1f9..cc024ab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -570,23 +570,15 @@ static int dm_suspend(void *handle)
 
 struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector(
struct drm_atomic_state *state,
-   struct drm_crtc *crtc,
-   bool from_state_var)
+   struct drm_crtc *crtc)
 {
uint32_t i;
struct drm_connector_state *conn_state;
struct drm_connector *connector;
struct drm_crtc *crtc_from_state;
 
-   for_each_new_connector_in_state(
-   state,
-   connector,
-   conn_state,
-   i) {
-   crtc_from_state =
-   from_state_var ?
-   conn_state->crtc :
-   connector->state->crtc;
+   for_each_new_connector_in_state(state, connector, conn_state, i) {
+   crtc_from_state = conn_state->crtc;
 
if (crtc_from_state == crtc)
return to_amdgpu_dm_connector(connector);
@@ -3890,7 +3882,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
unsigned long flags;
 
/* update planes when needed */
-   for_each_new_plane_in_state(state, plane, old_plane_state, i) {
+   for_each_old_plane_in_state(state, plane, old_plane_state, i) {
struct drm_plane_state *plane_state = plane->state;
struct drm_crtc *crtc = plane_state->crtc;
struct drm_framebuffer *fb = plane_state->fb;
@@ -4024,7 +4016,7 @@ void amdgpu_dm_atomic_commit_tail(
dm_state = to_dm_atomic_state(state);
 
/* update changed items */
-   for_each_new_crtc_in_state(state, crtc, old_crtc_state, i) {
+   for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
struct drm_crtc_state *new_state = crtc->state;
 
@@ -4113,11 +4105,9 @@ void amdgpu_dm_atomic_commit_tail(
new_acrtc_state = 
to_dm_crtc_state(new_crtcs[i]->base.state);
 
new_stream = new_acrtc_state->stream;
-   aconnector =
-   amdgpu_dm_find_first_crct_matching_connector(
+   aconnector = 
amdgpu_dm_find_first_crct_matching_connector(
state,
-   &new_crtcs[i]->base,
-   false);
+   &new_crtcs[i]->base);
if (!aconnector) {
DRM_DEBUG_DRIVER("Atomic commit: Failed to find 
connector for acrtc id:%d "
 "skipping freesync init\n",
@@ -4151,7 +4141,7 @@ void amdgpu_dm_atomic_commit_tail(
}
 
/* Handle scaling and undersacn changes*/
-   for_each_new_connector_in_state(state, connector, old_conn_state, i) {
+   for_each_old_connector_in_state(state, connector, old_conn_state, i) {
struct amdgpu_dm_connector *aconnector = 
to_amdgpu_dm_connector(connector);
struct dm_connector_state *con_new_state =
to_dm_connector_state(aconnector->base.state);
@@ -4205,7 +4195,7 @@ void amdgpu_dm_atomic_commit_tail(
}
 
/* update planes when needed per crtc*/
-   for_each_new_crtc_in_state(state, pcrtc, old_crtc_stat

[PATCH 3/6] drm/amd/display: Unify DRM state variable namings.

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

Use new_*_state and old_*_state for their respective new/old DRM object
states.

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 80 +++
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index d4426b3..fe0b658 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -573,12 +573,12 @@ struct amdgpu_dm_connector 
*amdgpu_dm_find_first_crct_matching_connector(
struct drm_crtc *crtc)
 {
uint32_t i;
-   struct drm_connector_state *conn_state;
+   struct drm_connector_state *new_con_state;
struct drm_connector *connector;
struct drm_crtc *crtc_from_state;
 
-   for_each_new_connector_in_state(state, connector, conn_state, i) {
-   crtc_from_state = conn_state->crtc;
+   for_each_new_connector_in_state(state, connector, new_con_state, i) {
+   crtc_from_state = new_con_state->crtc;
 
if (crtc_from_state == crtc)
return to_amdgpu_dm_connector(connector);
@@ -608,7 +608,7 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector;
struct drm_crtc *crtc;
-   struct drm_crtc_state *crtc_state;
+   struct drm_crtc_state *new_crtc_state;
int ret = 0;
int i;
 
@@ -644,8 +644,8 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
}
 
/* Force mode set in atomic comit */
-   for_each_new_crtc_in_state(adev->dm.cached_state, crtc, crtc_state, i)
-   crtc_state->active_changed = true;
+   for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, 
i)
+   new_crtc_state->active_changed = true;
 
ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state);
 
@@ -3971,7 +3971,7 @@ int amdgpu_dm_atomic_commit(
bool nonblock)
 {
struct drm_crtc *crtc;
-   struct drm_crtc_state *old_crtc_state, *new_state;
+   struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct amdgpu_device *adev = dev->dev_private;
int i;
 
@@ -3982,11 +3982,11 @@ int amdgpu_dm_atomic_commit(
 * it will update crtc->dm_crtc_state->stream pointer which is used in
 * the ISRs.
 */
-   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_state, 
i) {
+   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
struct dm_crtc_state *old_acrtc_state = 
to_dm_crtc_state(old_crtc_state);
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
-   if (drm_atomic_crtc_needs_modeset(new_state) && 
old_acrtc_state->stream)
+   if (drm_atomic_crtc_needs_modeset(new_crtc_state) && 
old_acrtc_state->stream)
manage_dm_interrupts(adev, acrtc, false);
}
 
@@ -4011,7 +4011,7 @@ void amdgpu_dm_atomic_commit_tail(
unsigned long flags;
bool wait_for_vblank = true;
struct drm_connector *connector;
-   struct drm_connector_state *old_conn_state, *new_con_state;
+   struct drm_connector_state *old_con_state, *new_con_state;
struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
 
drm_atomic_helper_update_legacy_modeset_state(dev, state);
@@ -4145,9 +4145,9 @@ void amdgpu_dm_atomic_commit_tail(
}
 
/* Handle scaling and undersacn changes*/
-   for_each_oldnew_connector_in_state(state, connector, old_conn_state, 
new_con_state, i) {
+   for_each_oldnew_connector_in_state(state, connector, old_con_state, 
new_con_state, i) {
struct dm_connector_state *con_new_state = 
to_dm_connector_state(new_con_state);
-   struct dm_connector_state *con_old_state = 
to_dm_connector_state(old_conn_state);
+   struct dm_connector_state *con_old_state = 
to_dm_connector_state(old_con_state);
struct amdgpu_crtc *acrtc = 
to_amdgpu_crtc(con_new_state->base.crtc);
struct dc_stream_status *status = NULL;
 
@@ -4375,7 +4375,7 @@ static int dm_update_crtcs_state(
bool *lock_and_validation_needed)
 {
struct drm_crtc *crtc;
-   struct drm_crtc_state *old_crtc_state, *crtc_state;
+   struct drm_crtc_state *old_crtc_state, *new_crtc_state;
int i;
struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
@@ -4384,34 +4384,34 @@ static int dm_update_crtcs_state(
 
/*TODO Move this code into dm_crtc_atomic_check once we get rid of 
dc_validation_set */
/* update changed items */
-   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, 
i) 

[PATCH 6/6] drm/amd/display: Remove useless pcrtc pointer

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

in amdgpu_dm_atomic_commit_tail. Just use crtc instead.

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 67222ff..f9b5769 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4004,7 +4004,7 @@ void amdgpu_dm_atomic_commit_tail(
struct dm_atomic_state *dm_state;
uint32_t i, j;
uint32_t new_crtcs_count = 0;
-   struct drm_crtc *crtc, *pcrtc;
+   struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
struct amdgpu_crtc *new_crtcs[MAX_STREAMS];
struct dc_stream_state *new_stream = NULL;
@@ -4200,11 +4200,11 @@ void amdgpu_dm_atomic_commit_tail(
}
 
/* update planes when needed per crtc*/
-   for_each_new_crtc_in_state(state, pcrtc, new_crtc_state, j) {
+   for_each_new_crtc_in_state(state, crtc, new_crtc_state, j) {
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
 
if (dm_new_crtc_state->stream)
-   amdgpu_dm_commit_planes(state, dev, dm, pcrtc, 
&wait_for_vblank);
+   amdgpu_dm_commit_planes(state, dev, dm, crtc, 
&wait_for_vblank);
}
 
 
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 0/6] Use new DRM API where possible, and cleanups.

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

Hi Dave,

This series reworks the previous patch. Patch 1 is a v2 of the previous,
and additional patches are from the feedback received. They apply on top
of your drm-next-amd-dc-staging branch.

Thanks,
Leo

Leo (Sunpeng) Li (6):
  drm/amd/display: Use DRM new-style object iterators.
  drm/amd/display: Use new DRM API where possible
  drm/amd/display: Unify DRM state variable namings.
  drm/amd/display: Unify amdgpu_dm state variable namings.
  drm/amd/display: Fix typo
  drm/amd/display: Remove useless pcrtc pointer

 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 320 +++---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   3 +-
 2 files changed, 156 insertions(+), 167 deletions(-)

-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 4/6] drm/amd/display: Unify amdgpu_dm state variable namings.

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

Use dm_new_*_state and dm_old_*_state for their respective amdgpu_dm new
and old object states. Helps with readability, and enforces use of new
DRM api (choose either new, or old).

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 137 +++---
 1 file changed, 68 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index fe0b658..de88ee1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3890,7 +3890,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
drm_atomic_get_new_crtc_state(state, crtc);
struct drm_framebuffer *fb = new_plane_state->fb;
bool pflip_needed;
-   struct dm_plane_state *dm_plane_state = 
to_dm_plane_state(new_plane_state);
+   struct dm_plane_state *dm_new_plane_state = 
to_dm_plane_state(new_plane_state);
 
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
handle_cursor_update(plane, old_plane_state);
@@ -3914,9 +3914,9 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 
if (!pflip_needed) {
-   WARN_ON(!dm_plane_state->dc_state);
+   WARN_ON(!dm_new_plane_state->dc_state);
 
-   plane_states_constructed[planes_count] = 
dm_plane_state->dc_state;
+   plane_states_constructed[planes_count] = 
dm_new_plane_state->dc_state;
 
dc_stream_attach = acrtc_state->stream;
planes_count++;
@@ -3983,10 +3983,10 @@ int amdgpu_dm_atomic_commit(
 * the ISRs.
 */
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
-   struct dm_crtc_state *old_acrtc_state = 
to_dm_crtc_state(old_crtc_state);
+   struct dm_crtc_state *dm_old_crtc_state = 
to_dm_crtc_state(old_crtc_state);
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
-   if (drm_atomic_crtc_needs_modeset(new_crtc_state) && 
old_acrtc_state->stream)
+   if (drm_atomic_crtc_needs_modeset(new_crtc_state) && 
dm_old_crtc_state->stream)
manage_dm_interrupts(adev, acrtc, false);
}
 
@@ -4012,7 +4012,7 @@ void amdgpu_dm_atomic_commit_tail(
bool wait_for_vblank = true;
struct drm_connector *connector;
struct drm_connector_state *old_con_state, *new_con_state;
-   struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
+   struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
 
drm_atomic_helper_update_legacy_modeset_state(dev, state);
 
@@ -4022,8 +4022,8 @@ void amdgpu_dm_atomic_commit_tail(
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
-   new_acrtc_state = to_dm_crtc_state(new_crtc_state);
-   old_acrtc_state = to_dm_crtc_state(old_crtc_state);
+   dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
+   dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
DRM_DEBUG_DRIVER(
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, 
active:%d, "
@@ -4041,11 +4041,11 @@ void amdgpu_dm_atomic_commit_tail(
 * aconnector as needed
 */
 
-   if (modeset_required(new_crtc_state, new_acrtc_state->stream, 
old_acrtc_state->stream)) {
+   if (modeset_required(new_crtc_state, dm_new_crtc_state->stream, 
dm_old_crtc_state->stream)) {
 
DRM_DEBUG_DRIVER("Atomic commit: SET crtc id %d: 
[%p]\n", acrtc->crtc_id, acrtc);
 
-   if (!new_acrtc_state->stream) {
+   if (!dm_new_crtc_state->stream) {
/*
 * this could happen because of issues with
 * userspace notifications delivery.
@@ -4067,8 +4067,8 @@ void amdgpu_dm_atomic_commit_tail(
}
 
 
-   if (old_acrtc_state->stream)
-   remove_stream(adev, acrtc, 
old_acrtc_state->stream);
+   if (dm_old_crtc_state->stream)
+   remove_stream(adev, acrtc, 
dm_old_crtc_state->stream);
 
 
/*
@@ -4092,8 +4092,8 @@ void amdgpu_dm_atomic_commit_tail(
DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id 
%d:[%p]\n", acrtc->crtc_id, acrtc);
 
/* i.e. reset mode */
-   if (old_acrtc_state->stream)
-

[PATCH 5/6] drm/amd/display: Fix typo

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

undersacn -> underscan

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index de88ee1..67222ff 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4144,7 +4144,7 @@ void amdgpu_dm_atomic_commit_tail(
}
}
 
-   /* Handle scaling and undersacn changes*/
+   /* Handle scaling and underscan changes*/
for_each_oldnew_connector_in_state(state, connector, old_con_state, 
new_con_state, i) {
struct dm_connector_state *dm_new_con_state = 
to_dm_connector_state(new_con_state);
struct dm_connector_state *dm_old_con_state = 
to_dm_connector_state(old_con_state);
@@ -4707,7 +4707,7 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
 if (ret)
 goto fail;
 
-   /* Check scaling and undersacn changes*/
+   /* Check scaling and underscan changes*/
/*TODO Removed scaling changes validation due to inability to commit
 * new stream into context w\o causing full reset. Need to
 * decide how to handle.
-- 
2.7.4

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH 2/6] drm/amd/display: Use new DRM API where possible

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

To conform to DRM's new API, we should not be accessing a DRM object's
internal state directly. Rather, the DRM for_each_old/new_* iterators,
and drm_atomic_get_old/new_* interface should be used.

This is an ongoing process. For now, update the DRM-facing atomic
functions, where the atomic state object is given.

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 131 +++---
 1 file changed, 66 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cc024ab..d4426b3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3873,28 +3873,31 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
 {
uint32_t i;
struct drm_plane *plane;
-   struct drm_plane_state *old_plane_state;
+   struct drm_plane_state *old_plane_state, *new_plane_state;
struct dc_stream_state *dc_stream_attach;
struct dc_plane_state *plane_states_constructed[MAX_SURFACES];
struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
-   struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state);
+   struct drm_crtc_state *new_pcrtc_state =
+   drm_atomic_get_new_crtc_state(state, pcrtc);
+   struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
int planes_count = 0;
unsigned long flags;
 
/* update planes when needed */
-   for_each_old_plane_in_state(state, plane, old_plane_state, i) {
-   struct drm_plane_state *plane_state = plane->state;
-   struct drm_crtc *crtc = plane_state->crtc;
-   struct drm_framebuffer *fb = plane_state->fb;
+   for_each_oldnew_plane_in_state(state, plane, old_plane_state, 
new_plane_state, i) {
+   struct drm_crtc *crtc = new_plane_state->crtc;
+   struct drm_crtc_state *new_crtc_state =
+   drm_atomic_get_new_crtc_state(state, crtc);
+   struct drm_framebuffer *fb = new_plane_state->fb;
bool pflip_needed;
-   struct dm_plane_state *dm_plane_state = 
to_dm_plane_state(plane_state);
+   struct dm_plane_state *dm_plane_state = 
to_dm_plane_state(new_plane_state);
 
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
handle_cursor_update(plane, old_plane_state);
continue;
}
 
-   if (!fb || !crtc || pcrtc != crtc || !crtc->state->active)
+   if (!fb || !crtc || pcrtc != crtc || !new_crtc_state->active)
continue;
 
pflip_needed = !state->allow_modeset;
@@ -3918,13 +3921,13 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
dc_stream_attach = acrtc_state->stream;
planes_count++;
 
-   } else if (crtc->state->planes_changed) {
+   } else if (new_crtc_state->planes_changed) {
/* Assume even ONE crtc with immediate flip means
 * entire can't wait for VBLANK
 * TODO Check if it's correct
 */
*wait_for_vblank =
-   pcrtc->state->pageflip_flags & 
DRM_MODE_PAGE_FLIP_ASYNC ?
+   new_pcrtc_state->pageflip_flags & 
DRM_MODE_PAGE_FLIP_ASYNC ?
false : true;
 
/* TODO: Needs rework for multiplane flip */
@@ -3942,7 +3945,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
if (planes_count) {
unsigned long flags;
 
-   if (pcrtc->state->event) {
+   if (new_pcrtc_state->event) {
 
drm_crtc_vblank_get(pcrtc);
 
@@ -3968,7 +3971,7 @@ int amdgpu_dm_atomic_commit(
bool nonblock)
 {
struct drm_crtc *crtc;
-   struct drm_crtc_state *new_state;
+   struct drm_crtc_state *old_crtc_state, *new_state;
struct amdgpu_device *adev = dev->dev_private;
int i;
 
@@ -3979,8 +3982,8 @@ int amdgpu_dm_atomic_commit(
 * it will update crtc->dm_crtc_state->stream pointer which is used in
 * the ISRs.
 */
-   for_each_new_crtc_in_state(state, crtc, new_state, i) {
-   struct dm_crtc_state *old_acrtc_state = 
to_dm_crtc_state(crtc->state);
+   for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_state, 
i) {
+   struct dm_crtc_state *old_acrtc_state = 
to_dm_crtc_state(old_crtc_state);
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
if (drm_atomic_crtc_needs_modeset(new_state) && 
old_acrtc_state->stream)
@@ -4002,13

[PATCH v2 1/6] drm/amd/display: Use DRM new-style object iterators.

2017-10-12 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

Use the correct for_each_new/old_* iterators instead of for_each_*

List of affected functions:

amdgpu_dm_find_first_crtc_matching_connector: use for_each_new
- Old from_state_var flag was always choosing the new state

amdgpu_dm_display_resume: use for_each_new
- drm_atomic_helper_duplicate_state is called during suspend to
  cache the state
- It sets 'state' within the state triplet to 'new_state'

amdgpu_dm_commit_planes: use for_each_old
- Called after the state was swapped (via atomic commit tail)

amdgpu_dm_atomic_commit: use for_each_new
- Called before the state is swapped

amdgpu_dm_atomic_commit_tail: use for_each_old
- Called after the state was swapped

dm_update_crtcs_state: use for_each_new
- Called before the state is swapped (via atomic check)

amdgpu_dm_atomic_check: use for_each_new
- Called before the state is swapped

v2: Split out typo fixes to a new patch.

Signed-off-by: Leo (Sunpeng) Li 
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  3 +--
 2 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 9bfe1f9..cc024ab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -570,23 +570,15 @@ static int dm_suspend(void *handle)
 
 struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector(
struct drm_atomic_state *state,
-   struct drm_crtc *crtc,
-   bool from_state_var)
+   struct drm_crtc *crtc)
 {
uint32_t i;
struct drm_connector_state *conn_state;
struct drm_connector *connector;
struct drm_crtc *crtc_from_state;
 
-   for_each_new_connector_in_state(
-   state,
-   connector,
-   conn_state,
-   i) {
-   crtc_from_state =
-   from_state_var ?
-   conn_state->crtc :
-   connector->state->crtc;
+   for_each_new_connector_in_state(state, connector, conn_state, i) {
+   crtc_from_state = conn_state->crtc;
 
if (crtc_from_state == crtc)
return to_amdgpu_dm_connector(connector);
@@ -3890,7 +3882,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
unsigned long flags;
 
/* update planes when needed */
-   for_each_new_plane_in_state(state, plane, old_plane_state, i) {
+   for_each_old_plane_in_state(state, plane, old_plane_state, i) {
struct drm_plane_state *plane_state = plane->state;
struct drm_crtc *crtc = plane_state->crtc;
struct drm_framebuffer *fb = plane_state->fb;
@@ -4024,7 +4016,7 @@ void amdgpu_dm_atomic_commit_tail(
dm_state = to_dm_atomic_state(state);
 
/* update changed items */
-   for_each_new_crtc_in_state(state, crtc, old_crtc_state, i) {
+   for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
struct drm_crtc_state *new_state = crtc->state;
 
@@ -4113,11 +4105,9 @@ void amdgpu_dm_atomic_commit_tail(
new_acrtc_state = 
to_dm_crtc_state(new_crtcs[i]->base.state);
 
new_stream = new_acrtc_state->stream;
-   aconnector =
-   amdgpu_dm_find_first_crct_matching_connector(
+   aconnector = 
amdgpu_dm_find_first_crct_matching_connector(
state,
-   &new_crtcs[i]->base,
-   false);
+   &new_crtcs[i]->base);
if (!aconnector) {
DRM_DEBUG_DRIVER("Atomic commit: Failed to find 
connector for acrtc id:%d "
 "skipping freesync init\n",
@@ -4151,7 +4141,7 @@ void amdgpu_dm_atomic_commit_tail(
}
 
/* Handle scaling and undersacn changes*/
-   for_each_new_connector_in_state(state, connector, old_conn_state, i) {
+   for_each_old_connector_in_state(state, connector, old_conn_state, i) {
struct amdgpu_dm_connector *aconnector = 
to_amdgpu_dm_connector(connector);
struct dm_connector_state *con_new_state =
to_dm_connector_state(aconnector->base.state);
@@ -4205,7 +4195,7 @@ void amdgpu_dm_atomic_commit_tail(
}
 
/* update planes when needed per crtc*/
-   for_each_new_crtc_in_state(state, pcrtc, old_crtc_state, j) {
+   for_each_old_crtc_in_state(state, pcrtc, old_crtc_state, j) {
new_acrtc_state = to_dm_crtc_state(pcr

[PATCH] amdgpu/dc: Use DRM new-style object iterators.

2017-10-11 Thread sunpeng.li
From: "Leo (Sunpeng) Li" 

Use the correct for_each_new/old_* iterators instead of for_each_*

List of affected functions:

amdgpu_dm_find_first_crtc_matching_connector: use for_each_new
- Old from_state_var flag was always choosing the new state

amdgpu_dm_display_resume: use for_each_new
- drm_atomic_helper_duplicate_state is called during suspend to
  cache the state
- It sets 'state' within the state triplet to 'new_state'

amdgpu_dm_commit_planes: use for_each_old
- Called after the state was swapped (via atomic commit tail)

amdgpu_dm_atomic_commit: use for_each_new
- Called before the state is swapped

amdgpu_dm_atomic_commit_tail: use for_each_old
- Called after the state was swapped

dm_update_crtcs_state: use for_each_new
- Called before the state is swapped (via atomic check)

amdgpu_dm_atomic_check: use for_each_new
- Called before the state is swapped

Also fix some typos.

crct -> crtc
undersacn -> underscan

Signed-off-by: Leo (Sunpeng) Li 
---

Hi Dave,

This patch goes on top of your fixup for new api's patch. Please feel
free to squash them.

Thanks,
Leo

 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 38 +--
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  5 ++-
 2 files changed, 16 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 9bfe1f9..9394558 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -568,25 +568,17 @@ static int dm_suspend(void *handle)
return ret;
 }
 
-struct amdgpu_dm_connector *amdgpu_dm_find_first_crct_matching_connector(
+struct amdgpu_dm_connector *amdgpu_dm_find_first_crtc_matching_connector(
struct drm_atomic_state *state,
-   struct drm_crtc *crtc,
-   bool from_state_var)
+   struct drm_crtc *crtc)
 {
uint32_t i;
struct drm_connector_state *conn_state;
struct drm_connector *connector;
struct drm_crtc *crtc_from_state;
 
-   for_each_new_connector_in_state(
-   state,
-   connector,
-   conn_state,
-   i) {
-   crtc_from_state =
-   from_state_var ?
-   conn_state->crtc :
-   connector->state->crtc;
+   for_each_new_connector_in_state(state, connector, conn_state, i) {
+   crtc_from_state = conn_state->crtc;
 
if (crtc_from_state == crtc)
return to_amdgpu_dm_connector(connector);
@@ -3890,7 +3882,7 @@ static void amdgpu_dm_commit_planes(struct 
drm_atomic_state *state,
unsigned long flags;
 
/* update planes when needed */
-   for_each_new_plane_in_state(state, plane, old_plane_state, i) {
+   for_each_old_plane_in_state(state, plane, old_plane_state, i) {
struct drm_plane_state *plane_state = plane->state;
struct drm_crtc *crtc = plane_state->crtc;
struct drm_framebuffer *fb = plane_state->fb;
@@ -4024,7 +4016,7 @@ void amdgpu_dm_atomic_commit_tail(
dm_state = to_dm_atomic_state(state);
 
/* update changed items */
-   for_each_new_crtc_in_state(state, crtc, old_crtc_state, i) {
+   for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
struct drm_crtc_state *new_state = crtc->state;
 
@@ -4113,11 +4105,9 @@ void amdgpu_dm_atomic_commit_tail(
new_acrtc_state = 
to_dm_crtc_state(new_crtcs[i]->base.state);
 
new_stream = new_acrtc_state->stream;
-   aconnector =
-   amdgpu_dm_find_first_crct_matching_connector(
+   aconnector = 
amdgpu_dm_find_first_crtc_matching_connector(
state,
-   &new_crtcs[i]->base,
-   false);
+   &new_crtcs[i]->base);
if (!aconnector) {
DRM_DEBUG_DRIVER("Atomic commit: Failed to find 
connector for acrtc id:%d "
 "skipping freesync init\n",
@@ -4150,8 +4140,8 @@ void amdgpu_dm_atomic_commit_tail(
}
}
 
-   /* Handle scaling and undersacn changes*/
-   for_each_new_connector_in_state(state, connector, old_conn_state, i) {
+   /* Handle scaling and underscan changes*/
+   for_each_old_connector_in_state(state, connector, old_conn_state, i) {
struct amdgpu_dm_connector *aconnector = 
to_amdgpu_dm_connector(connector);
struct dm_connector_state *con_new_state =
to_dm_connector_state(aconnector->base.state);
@@ -4205,7 +