diff options
author | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2018-02-21 11:17:25 +0100 |
---|---|---|
committer | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2018-03-19 16:01:17 +0100 |
commit | 1ac6480cdd0c3d5aa947289c4758b871e91d7953 (patch) | |
tree | 46b83fb7f87b6b5fcec7b91e58620127dafe991b /lib | |
parent | 98f7614bd725afaae48f7b70d18329149075661b (diff) |
lib/igt_kms: Add functions to get only a single output for a pipe, v2.
igt_get_single_output_for_pipe() will give a valid output for a pipe,
for_each_pipe_with_single_output will iterate over all pipes, and
will be called for each pipe with an output once.
Changes since v1:
- pipe = __outputs - __output returned a negative number for pipe,
correctly set it to __output - __outputs.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/igt_kms.c | 93 | ||||
-rw-r--r-- | lib/igt_kms.h | 26 |
2 files changed, 119 insertions, 0 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c index cf6389f2..7222642e 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -2203,6 +2203,99 @@ igt_plane_t *igt_pipe_get_plane_type(igt_pipe_t *pipe, int plane_type) return &pipe->planes[plane_idx]; } +static bool output_is_internal_panel(igt_output_t *output) +{ + switch (output->config.connector->connector_type) { + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + case DRM_MODE_CONNECTOR_DSI: + case DRM_MODE_CONNECTOR_DPI: + return true; + default: + return false; + } +} + +igt_output_t **__igt_pipe_populate_outputs(igt_display_t *display, igt_output_t **chosen_outputs) +{ + unsigned full_pipe_mask = (1 << (display->n_pipes)) - 1, assigned_pipes = 0; + igt_output_t *output; + int i, j; + + memset(chosen_outputs, 0, sizeof(*chosen_outputs) * display->n_pipes); + + /* + * Try to assign all outputs to the first available CRTC for + * it, start with the outputs restricted to 1 pipe, then increase + * number of pipes until we assign connectors to all pipes. + */ + for (i = 0; i <= display->n_pipes; i++) { + for_each_connected_output(display, output) { + uint32_t pipe_mask = output->config.valid_crtc_idx_mask & full_pipe_mask; + bool found = false; + + if (output_is_internal_panel(output)) { + /* + * Internal panel should be assigned to pipe A + * if possible, so make sure they're enumerated + * first. + */ + + if (i) + continue; + } else if (__builtin_popcount(pipe_mask) != i) + continue; + + for (j = 0; j < display->n_pipes; j++) { + bool pipe_assigned = assigned_pipes & (1 << j); + + if (pipe_assigned || !(pipe_mask & (1 << j))) + continue; + + if (!found) { + /* We found an unassigned pipe, use it! */ + found = true; + assigned_pipes |= 1 << j; + chosen_outputs[j] = output; + } else if (!chosen_outputs[j] || + /* + * Overwrite internal panel if not assigned, + * external outputs are faster to do modesets + */ + output_is_internal_panel(chosen_outputs[j])) + chosen_outputs[j] = output; + } + + if (!found) + igt_warn("Output %s could not be assigned to a pipe\n", + igt_output_name(output)); + } + } + + return chosen_outputs; +} + +/** + * igt_get_single_output_for_pipe: + * @display: a pointer to an #igt_display_t structure + * @pipe: The pipe for which an #igt_output_t must be returned. + * + * Get a compatible output for a pipe. + * + * Returns: A compatible output for a given pipe, or NULL. + */ +igt_output_t *igt_get_single_output_for_pipe(igt_display_t *display, enum pipe pipe) +{ + igt_output_t *chosen_outputs[display->n_pipes]; + + igt_assert(pipe != PIPE_NONE); + igt_require(pipe < display->n_pipes); + + __igt_pipe_populate_outputs(display, chosen_outputs); + + return chosen_outputs[pipe]; +} + static igt_output_t *igt_pipe_get_output(igt_pipe_t *pipe) { igt_display_t *display = pipe->display; diff --git a/lib/igt_kms.h b/lib/igt_kms.h index 1ea3be99..3653e4cd 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -389,7 +389,9 @@ igt_plane_t *igt_output_get_plane(igt_output_t *output, int plane_idx); igt_plane_t *igt_output_get_plane_type(igt_output_t *output, int plane_type); igt_output_t *igt_output_from_connector(igt_display_t *display, drmModeConnector *connector); + igt_plane_t *igt_pipe_get_plane_type(igt_pipe_t *pipe, int plane_type); +igt_output_t *igt_get_single_output_for_pipe(igt_display_t *display, enum pipe pipe); void igt_pipe_request_out_fence(igt_pipe_t *pipe); @@ -477,6 +479,10 @@ static inline bool igt_output_is_connected(igt_output_t *output) * * This for loop is called over all connected outputs. This function * will try every combination of @pipe and @output. + * + * If you only need to test a single output for each pipe, use + * for_each_pipe_with_single_output(), if you only need an + * output for a single pipe, use igt_get_single_output_for_pipe(). */ #define for_each_pipe_with_valid_output(display, pipe, output) \ for (int con__ = (pipe) = 0; \ @@ -485,6 +491,26 @@ static inline bool igt_output_is_connected(igt_output_t *output) for_each_if ((((output) = &(display)->outputs[con__]), \ igt_pipe_connector_valid((pipe), (output)))) +igt_output_t **__igt_pipe_populate_outputs(igt_display_t *display, + igt_output_t **chosen_outputs); + +/** + * for_each_pipe_with_single_output: + * @display: a pointer to an #igt_display_t structure + * @pipe: The pipe for which this @pipe / @output combination is valid. + * @output: The output for which this @pipe / @output combination is valid. + * + * This loop is called over all pipes, and will try to find a compatible output + * for each pipe. Unlike for_each_pipe_with_valid_output(), this function will + * be called at most once for each pipe. + */ +#define for_each_pipe_with_single_output(display, pipe, output) \ + for (igt_output_t *__outputs[(display)->n_pipes], \ + **__output = __igt_pipe_populate_outputs((display), __outputs); \ + __output < &__outputs[(display)->n_pipes]; __output++) \ + for_each_if (*__output && \ + ((pipe) = (__output - __outputs), (output) = *__output, 1)) + /** * for_each_valid_output_on_pipe: * @display: a pointer to an #igt_display_t structure |