[Intel-gfx] [RFC v4 18/25] drm/client: Make the display modes available to clients

2018-04-14 Thread Noralf Trønnes
Give clients easy access to the display modes.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c | 159 +--
 include/drm/drm_client.h |  25 +++
 2 files changed, 148 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 764c556630b8..bce1630a0db2 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -8,6 +8,7 @@
  * Copyright (c) 2007 Dave Airlie 
  */
 
+#include 
 #include 
 
 #include 
@@ -54,6 +55,7 @@ struct drm_client_display *drm_client_display_create(struct 
drm_device *dev)
}
 
display->dev = dev;
+   INIT_LIST_HEAD(>modes);
display->modeset_count = num_crtc;
 
drm_for_each_crtc(crtc, dev)
@@ -84,12 +86,16 @@ EXPORT_SYMBOL(drm_client_display_create);
  */
 void drm_client_display_free(struct drm_client_display *display)
 {
+   struct drm_display_mode *mode, *tmp;
struct drm_mode_set *modeset;
unsigned int i;
 
if (!display)
return;
 
+   list_for_each_entry_safe(mode, tmp, >modes, head)
+   drm_mode_destroy(display->dev, mode);
+
drm_client_display_for_each_modeset(modeset, display) {
if (modeset->mode)
drm_mode_destroy(display->dev, modeset->mode);
@@ -670,22 +676,70 @@ static int drm_pick_crtcs(struct drm_client_display 
*display,
return best_score;
 }
 
-/**
- * drm_client_find_display() - Find display
- * @dev: DRM device
- * @width: Maximum display mode width (optional)
- * @height: Maximum display mode height (optional)
- *
- * This function returns a display the client can use if available.
- *
- * Free resources by calling drm_client_display_free().
- *
- * Returns:
- * A _client_display on success, NULL if no connectors are found
- * or error pointer on failure.
- */
-struct drm_client_display *
-drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned 
int height)
+/* Give the client a static list of display modes */
+static int drm_client_display_copy_modes(struct drm_client_display *display)
+{
+   int hdisplay = 0, vdisplay = 0, vrefresh;
+   struct drm_device *dev = display->dev;
+   struct drm_display_mode *mode, *copy;
+   struct drm_connector *connector;
+   struct drm_mode_set *modeset;
+   unsigned int count = 0;
+
+   drm_client_display_for_each_modeset(modeset, display) {
+   if (!modeset->num_connectors || !modeset->mode)
+   continue;
+
+   connector = modeset->connectors[0];
+   mode = modeset->mode;
+   count++;
+
+   if (modeset->num_connectors == 2) {
+   /* Cloned output */
+   copy = drm_mode_duplicate(dev, modeset->mode);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   display->mode = copy;
+
+   return 0;
+   }
+
+   if (!modeset->y)
+   hdisplay += modeset->mode->hdisplay;
+   if (!modeset->x)
+   vdisplay += modeset->mode->vdisplay;
+   vrefresh = modeset->mode->vrefresh;
+   }
+
+   if (!count)
+   return 0;
+
+   if (count == 1) {
+   struct drm_display_mode *iter;
+
+   list_for_each_entry(iter, >modes, head) {
+   copy = drm_mode_duplicate(dev, iter);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   if (!display->mode && drm_mode_equal(iter, mode))
+   display->mode = copy;
+   }
+   } else {
+   /* Combined tile mode. Only the default one for now */
+   copy = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, false, 
false, false);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   display->mode = copy;
+   }
+
+   return 0;
+}
+
+static struct drm_client_display *
+drm_client_find_display_default(struct drm_device *dev, unsigned int width, 
unsigned int height)
 {
struct drm_client_display_offset *offsets;
struct drm_client_display *display;
@@ -695,25 +749,6 @@ drm_client_find_display(struct drm_device *dev, unsigned 
int width, unsigned int
int i, connector_count;
bool *enabled;
 
-   DRM_DEBUG_KMS("\n");
-
-   if (!width)
-   width = dev->mode_config.max_width;
-   if (!height)
-   height = dev->mode_config.max_height;
-
-   mutex_lock(>mode_config.mutex);
-   if (!drm_client_probe_connector_modes(dev, width, height))
-   

[Intel-gfx] [RFC v4 18/25] drm/client: Make the display modes available to clients

2018-04-13 Thread Noralf Trønnes
Give clients easy access to the display modes.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c | 159 +--
 include/drm/drm_client.h |  25 +++
 2 files changed, 148 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 764c556630b8..bce1630a0db2 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -8,6 +8,7 @@
  * Copyright (c) 2007 Dave Airlie 
  */
 
+#include 
 #include 
 
 #include 
@@ -54,6 +55,7 @@ struct drm_client_display *drm_client_display_create(struct 
drm_device *dev)
}
 
display->dev = dev;
+   INIT_LIST_HEAD(>modes);
display->modeset_count = num_crtc;
 
drm_for_each_crtc(crtc, dev)
@@ -84,12 +86,16 @@ EXPORT_SYMBOL(drm_client_display_create);
  */
 void drm_client_display_free(struct drm_client_display *display)
 {
+   struct drm_display_mode *mode, *tmp;
struct drm_mode_set *modeset;
unsigned int i;
 
if (!display)
return;
 
+   list_for_each_entry_safe(mode, tmp, >modes, head)
+   drm_mode_destroy(display->dev, mode);
+
drm_client_display_for_each_modeset(modeset, display) {
if (modeset->mode)
drm_mode_destroy(display->dev, modeset->mode);
@@ -670,22 +676,70 @@ static int drm_pick_crtcs(struct drm_client_display 
*display,
return best_score;
 }
 
-/**
- * drm_client_find_display() - Find display
- * @dev: DRM device
- * @width: Maximum display mode width (optional)
- * @height: Maximum display mode height (optional)
- *
- * This function returns a display the client can use if available.
- *
- * Free resources by calling drm_client_display_free().
- *
- * Returns:
- * A _client_display on success, NULL if no connectors are found
- * or error pointer on failure.
- */
-struct drm_client_display *
-drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned 
int height)
+/* Give the client a static list of display modes */
+static int drm_client_display_copy_modes(struct drm_client_display *display)
+{
+   int hdisplay = 0, vdisplay = 0, vrefresh;
+   struct drm_device *dev = display->dev;
+   struct drm_display_mode *mode, *copy;
+   struct drm_connector *connector;
+   struct drm_mode_set *modeset;
+   unsigned int count = 0;
+
+   drm_client_display_for_each_modeset(modeset, display) {
+   if (!modeset->num_connectors || !modeset->mode)
+   continue;
+
+   connector = modeset->connectors[0];
+   mode = modeset->mode;
+   count++;
+
+   if (modeset->num_connectors == 2) {
+   /* Cloned output */
+   copy = drm_mode_duplicate(dev, modeset->mode);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   display->mode = copy;
+
+   return 0;
+   }
+
+   if (!modeset->y)
+   hdisplay += modeset->mode->hdisplay;
+   if (!modeset->x)
+   vdisplay += modeset->mode->vdisplay;
+   vrefresh = modeset->mode->vrefresh;
+   }
+
+   if (!count)
+   return 0;
+
+   if (count == 1) {
+   struct drm_display_mode *iter;
+
+   list_for_each_entry(iter, >modes, head) {
+   copy = drm_mode_duplicate(dev, iter);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   if (!display->mode && drm_mode_equal(iter, mode))
+   display->mode = copy;
+   }
+   } else {
+   /* Combined tile mode. Only the default one for now */
+   copy = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, false, 
false, false);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   display->mode = copy;
+   }
+
+   return 0;
+}
+
+static struct drm_client_display *
+drm_client_find_display_default(struct drm_device *dev, unsigned int width, 
unsigned int height)
 {
struct drm_client_display_offset *offsets;
struct drm_client_display *display;
@@ -695,25 +749,6 @@ drm_client_find_display(struct drm_device *dev, unsigned 
int width, unsigned int
int i, connector_count;
bool *enabled;
 
-   DRM_DEBUG_KMS("\n");
-
-   if (!width)
-   width = dev->mode_config.max_width;
-   if (!height)
-   height = dev->mode_config.max_height;
-
-   mutex_lock(>mode_config.mutex);
-   if (!drm_client_probe_connector_modes(dev, width, height))
-   

[Intel-gfx] [RFC v4 18/25] drm/client: Make the display modes available to clients

2018-04-12 Thread Noralf Trønnes
Give clients easy access to the display modes.

Signed-off-by: Noralf Trønnes 
---
 drivers/gpu/drm/drm_client.c | 159 +--
 include/drm/drm_client.h |  25 +++
 2 files changed, 148 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 764c556630b8..bce1630a0db2 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -8,6 +8,7 @@
  * Copyright (c) 2007 Dave Airlie 
  */
 
+#include 
 #include 
 
 #include 
@@ -54,6 +55,7 @@ struct drm_client_display *drm_client_display_create(struct 
drm_device *dev)
}
 
display->dev = dev;
+   INIT_LIST_HEAD(>modes);
display->modeset_count = num_crtc;
 
drm_for_each_crtc(crtc, dev)
@@ -84,12 +86,16 @@ EXPORT_SYMBOL(drm_client_display_create);
  */
 void drm_client_display_free(struct drm_client_display *display)
 {
+   struct drm_display_mode *mode, *tmp;
struct drm_mode_set *modeset;
unsigned int i;
 
if (!display)
return;
 
+   list_for_each_entry_safe(mode, tmp, >modes, head)
+   drm_mode_destroy(display->dev, mode);
+
drm_client_display_for_each_modeset(modeset, display) {
if (modeset->mode)
drm_mode_destroy(display->dev, modeset->mode);
@@ -670,22 +676,70 @@ static int drm_pick_crtcs(struct drm_client_display 
*display,
return best_score;
 }
 
-/**
- * drm_client_find_display() - Find display
- * @dev: DRM device
- * @width: Maximum display mode width (optional)
- * @height: Maximum display mode height (optional)
- *
- * This function returns a display the client can use if available.
- *
- * Free resources by calling drm_client_display_free().
- *
- * Returns:
- * A _client_display on success, NULL if no connectors are found
- * or error pointer on failure.
- */
-struct drm_client_display *
-drm_client_find_display(struct drm_device *dev, unsigned int width, unsigned 
int height)
+/* Give the client a static list of display modes */
+static int drm_client_display_copy_modes(struct drm_client_display *display)
+{
+   int hdisplay = 0, vdisplay = 0, vrefresh;
+   struct drm_device *dev = display->dev;
+   struct drm_display_mode *mode, *copy;
+   struct drm_connector *connector;
+   struct drm_mode_set *modeset;
+   unsigned int count = 0;
+
+   drm_client_display_for_each_modeset(modeset, display) {
+   if (!modeset->num_connectors || !modeset->mode)
+   continue;
+
+   connector = modeset->connectors[0];
+   mode = modeset->mode;
+   count++;
+
+   if (modeset->num_connectors == 2) {
+   /* Cloned output */
+   copy = drm_mode_duplicate(dev, modeset->mode);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   display->mode = copy;
+
+   return 0;
+   }
+
+   if (!modeset->y)
+   hdisplay += modeset->mode->hdisplay;
+   if (!modeset->x)
+   vdisplay += modeset->mode->vdisplay;
+   vrefresh = modeset->mode->vrefresh;
+   }
+
+   if (!count)
+   return 0;
+
+   if (count == 1) {
+   struct drm_display_mode *iter;
+
+   list_for_each_entry(iter, >modes, head) {
+   copy = drm_mode_duplicate(dev, iter);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   if (!display->mode && drm_mode_equal(iter, mode))
+   display->mode = copy;
+   }
+   } else {
+   /* Combined tile mode. Only the default one for now */
+   copy = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, false, 
false, false);
+   if (!copy)
+   return -ENOMEM;
+   list_add_tail(>head, >modes);
+   display->mode = copy;
+   }
+
+   return 0;
+}
+
+static struct drm_client_display *
+drm_client_find_display_default(struct drm_device *dev, unsigned int width, 
unsigned int height)
 {
struct drm_client_display_offset *offsets;
struct drm_client_display *display;
@@ -695,25 +749,6 @@ drm_client_find_display(struct drm_device *dev, unsigned 
int width, unsigned int
int i, connector_count;
bool *enabled;
 
-   DRM_DEBUG_KMS("\n");
-
-   if (!width)
-   width = dev->mode_config.max_width;
-   if (!height)
-   height = dev->mode_config.max_height;
-
-   mutex_lock(>mode_config.mutex);
-   if (!drm_client_probe_connector_modes(dev, width, height))
-