[Intel-gfx] [PATCH] drm/i915/bios: iterate over child devices to initialize ddi_port_info
Jani Nikula
jani.nikula at intel.com
Mon Mar 25 13:30:54 UTC 2019
On Fri, 22 Mar 2019, Jani Nikula <jani.nikula at intel.com> wrote:
> Iterate over child devices instead of ports in parse_ddi_ports() to
> initialize dri_port_info. We'll eventually need to decide some stuff
> based on the child device order, which may be different from the port
> order.
>
> As a bonus, this allows better abstractions for e.g. dvo port mapping.
>
> There's a subtle change in the DDC pin and AUX channel sanitization as
> we change the order. Otherwise, this should not change behaviour.
>
> Reviewed-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Signed-off-by: Jani Nikula <jani.nikula at intel.com>
Pushed to dinq, thanks for the review.
BR,
Jani.
> ---
> drivers/gpu/drm/i915/i915_drv.h | 1 +
> drivers/gpu/drm/i915/intel_bios.c | 104 +++++++++++++++++-------------
> 2 files changed, 59 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index fefcb39aefc4..d82d63dfa5a1 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -954,6 +954,7 @@ struct ddi_vbt_port_info {
> #define HDMI_LEVEL_SHIFT_UNKNOWN 0xff
> u8 hdmi_level_shift;
>
> + u8 present:1;
> u8 supports_dvi:1;
> u8 supports_hdmi:1;
> u8 supports_dp:1;
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 64f20175a6dc..1dc8d03ff127 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -1247,10 +1247,11 @@ static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
> if (!info->alternate_ddc_pin)
> return;
>
> - for_each_port_masked(p, (1 << port) - 1) {
> + for (p = PORT_A; p < I915_MAX_PORTS; p++) {
> struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
>
> - if (info->alternate_ddc_pin != i->alternate_ddc_pin)
> + if (p == port || !i->present ||
> + info->alternate_ddc_pin != i->alternate_ddc_pin)
> continue;
>
> DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, "
> @@ -1264,8 +1265,8 @@ static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
> * port. Otherwise they share the same ddc bin and
> * system couldn't communicate with them separately.
> *
> - * Due to parsing the ports in alphabetical order,
> - * a higher port will always clobber a lower one.
> + * Due to parsing the ports in child device order,
> + * a later device will always clobber an earlier one.
> */
> i->supports_dvi = false;
> i->supports_hdmi = false;
> @@ -1283,10 +1284,11 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
> if (!info->alternate_aux_channel)
> return;
>
> - for_each_port_masked(p, (1 << port) - 1) {
> + for (p = PORT_A; p < I915_MAX_PORTS; p++) {
> struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
>
> - if (info->alternate_aux_channel != i->alternate_aux_channel)
> + if (p == port || !i->present ||
> + info->alternate_aux_channel != i->alternate_aux_channel)
> continue;
>
> DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, "
> @@ -1300,8 +1302,8 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
> * port. Otherwise they share the same aux channel
> * and system couldn't communicate with them separately.
> *
> - * Due to parsing the ports in alphabetical order,
> - * a higher port will always clobber a lower one.
> + * Due to parsing the ports in child device order,
> + * a later device will always clobber an earlier one.
> */
> i->supports_dp = false;
> i->alternate_aux_channel = 0;
> @@ -1349,49 +1351,58 @@ static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin)
> return 0;
> }
>
> -static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
> - u8 bdb_version)
> +static enum port dvo_port_to_port(u8 dvo_port)
> {
> - struct child_device_config *it, *child = NULL;
> - struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
> - int i, j;
> - bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
> - /* Each DDI port can have more than one value on the "DVO Port" field,
> + /*
> + * Each DDI port can have more than one value on the "DVO Port" field,
> * so look for all the possible values for each port.
> */
> - int dvo_ports[][3] = {
> - {DVO_PORT_HDMIA, DVO_PORT_DPA, -1},
> - {DVO_PORT_HDMIB, DVO_PORT_DPB, -1},
> - {DVO_PORT_HDMIC, DVO_PORT_DPC, -1},
> - {DVO_PORT_HDMID, DVO_PORT_DPD, -1},
> - {DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE},
> - {DVO_PORT_HDMIF, DVO_PORT_DPF, -1},
> + static const int dvo_ports[][3] = {
> + [PORT_A] = { DVO_PORT_HDMIA, DVO_PORT_DPA, -1},
> + [PORT_B] = { DVO_PORT_HDMIB, DVO_PORT_DPB, -1},
> + [PORT_C] = { DVO_PORT_HDMIC, DVO_PORT_DPC, -1},
> + [PORT_D] = { DVO_PORT_HDMID, DVO_PORT_DPD, -1},
> + [PORT_E] = { DVO_PORT_CRT, DVO_PORT_HDMIE, DVO_PORT_DPE},
> + [PORT_F] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1},
> };
> + enum port port;
> + int i;
>
> - /*
> - * Find the first child device to reference the port, report if more
> - * than one found.
> - */
> - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
> - it = dev_priv->vbt.child_dev + i;
> -
> - for (j = 0; j < 3; j++) {
> - if (dvo_ports[port][j] == -1)
> + for (port = PORT_A; port < ARRAY_SIZE(dvo_ports); port++) {
> + for (i = 0; i < ARRAY_SIZE(dvo_ports[port]); i++) {
> + if (dvo_ports[port][i] == -1)
> break;
>
> - if (it->dvo_port == dvo_ports[port][j]) {
> - if (child) {
> - DRM_DEBUG_KMS("More than one child device for port %c in VBT, using the first.\n",
> - port_name(port));
> - } else {
> - child = it;
> - }
> - }
> + if (dvo_port == dvo_ports[port][i])
> + return port;
> }
> }
> - if (!child)
> +
> + return PORT_NONE;
> +}
> +
> +static void parse_ddi_port(struct drm_i915_private *dev_priv,
> + const struct child_device_config *child,
> + u8 bdb_version)
> +{
> + struct ddi_vbt_port_info *info;
> + bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
> + enum port port;
> +
> + port = dvo_port_to_port(child->dvo_port);
> + if (port == PORT_NONE)
> return;
>
> + info = &dev_priv->vbt.ddi_port_info[port];
> +
> + if (info->present) {
> + DRM_DEBUG_KMS("More than one child device for port %c in VBT, using the first.\n",
> + port_name(port));
> + return;
> + }
> +
> + info->present = true;
> +
> is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
> is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
> is_crt = child->device_type & DEVICE_TYPE_ANALOG_OUTPUT;
> @@ -1523,19 +1534,20 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
>
> static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version)
> {
> - enum port port;
> + const struct child_device_config *child;
> + int i;
>
> if (!HAS_DDI(dev_priv) && !IS_CHERRYVIEW(dev_priv))
> return;
>
> - if (!dev_priv->vbt.child_dev_num)
> - return;
> -
> if (bdb_version < 155)
> return;
>
> - for (port = PORT_A; port < I915_MAX_PORTS; port++)
> - parse_ddi_port(dev_priv, port, bdb_version);
> + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
> + child = dev_priv->vbt.child_dev + i;
> +
> + parse_ddi_port(dev_priv, child, bdb_version);
> + }
> }
>
> static void
--
Jani Nikula, Intel Open Source Graphics Center
More information about the Intel-gfx
mailing list