[Intel-gfx] [PATCH 1/2] drm/i915: VBT's child_device_config changes over time
Rodrigo Vivi
rodrigo.vivi at gmail.com
Tue Sep 3 16:33:14 CEST 2013
As I told you in irc I'm not sure if the best option is to use common,
raw and old, but since I don't have a better idea and while nobody
else has, just to go ahead ;)
And I liked very much the raw part, although I had to count the bytes
amount on VBT doc when reviewing following patches ;)
For this patch:
Reviewed-by: Rodrigo Vivi <rodrigo.vivi at gmail.com>
Still have to continue reviewing the following ones
On Tue, Aug 27, 2013 at 5:22 PM, Paulo Zanoni <przanoni at gmail.com> wrote:
> From: Paulo Zanoni <paulo.r.zanoni at intel.com>
>
> We currently treat the child_device_config as a simple struct, but
> this is not correct: new BDB versions change the meaning of some
> offsets, so the struct needs to be adjusted for each version.
>
> Since there are too many changes (today we're in version 170!), making
> a big versioned union would be too complicated, so child_device_config
> is now a union of 3 things: (i) a "raw" byte array that's safe to use
> anywhere; (ii) an "old" structure that's the one we've been using and
> should be safe to keep in the SDVO and TV code; and (iii) a "common"
> structure that should contain only fields that are common for all the
> known VBT versions.
>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
> ---
> drivers/gpu/drm/i915/i915_drv.h | 2 +-
> drivers/gpu/drm/i915/intel_bios.c | 36 ++++++++++++++++++------------------
> drivers/gpu/drm/i915/intel_bios.h | 33 +++++++++++++++++++++++++++++++--
> drivers/gpu/drm/i915/intel_dp.c | 6 +++---
> drivers/gpu/drm/i915/intel_lvds.c | 3 ++-
> drivers/gpu/drm/i915/intel_tv.c | 8 ++++----
> 6 files changed, 59 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 84b95b1..08fe1b6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1067,7 +1067,7 @@ struct intel_vbt_data {
> int crt_ddc_pin;
>
> int child_dev_num;
> - struct child_device_config *child_dev;
> + union child_device_config *child_dev;
> };
>
> enum intel_ddb_partitioning {
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 53f2bed..8a27925 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -389,7 +389,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
> {
> struct sdvo_device_mapping *p_mapping;
> struct bdb_general_definitions *p_defs;
> - struct child_device_config *p_child;
> + union child_device_config *p_child;
> int i, child_device_num, count;
> u16 block_size;
>
> @@ -416,36 +416,36 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
> count = 0;
> for (i = 0; i < child_device_num; i++) {
> p_child = &(p_defs->devices[i]);
> - if (!p_child->device_type) {
> + if (!p_child->old.device_type) {
> /* skip the device block if device type is invalid */
> continue;
> }
> - if (p_child->slave_addr != SLAVE_ADDR1 &&
> - p_child->slave_addr != SLAVE_ADDR2) {
> + if (p_child->old.slave_addr != SLAVE_ADDR1 &&
> + p_child->old.slave_addr != SLAVE_ADDR2) {
> /*
> * If the slave address is neither 0x70 nor 0x72,
> * it is not a SDVO device. Skip it.
> */
> continue;
> }
> - if (p_child->dvo_port != DEVICE_PORT_DVOB &&
> - p_child->dvo_port != DEVICE_PORT_DVOC) {
> + if (p_child->old.dvo_port != DEVICE_PORT_DVOB &&
> + p_child->old.dvo_port != DEVICE_PORT_DVOC) {
> /* skip the incorrect SDVO port */
> DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
> continue;
> }
> DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
> " %s port\n",
> - p_child->slave_addr,
> - (p_child->dvo_port == DEVICE_PORT_DVOB) ?
> + p_child->old.slave_addr,
> + (p_child->old.dvo_port == DEVICE_PORT_DVOB) ?
> "SDVOB" : "SDVOC");
> - p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
> + p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]);
> if (!p_mapping->initialized) {
> - p_mapping->dvo_port = p_child->dvo_port;
> - p_mapping->slave_addr = p_child->slave_addr;
> - p_mapping->dvo_wiring = p_child->dvo_wiring;
> - p_mapping->ddc_pin = p_child->ddc_pin;
> - p_mapping->i2c_pin = p_child->i2c_pin;
> + p_mapping->dvo_port = p_child->old.dvo_port;
> + p_mapping->slave_addr = p_child->old.slave_addr;
> + p_mapping->dvo_wiring = p_child->old.dvo_wiring;
> + p_mapping->ddc_pin = p_child->old.ddc_pin;
> + p_mapping->i2c_pin = p_child->old.i2c_pin;
> p_mapping->initialized = 1;
> DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
> p_mapping->dvo_port,
> @@ -457,7 +457,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
> DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
> "two SDVO device.\n");
> }
> - if (p_child->slave2_addr) {
> + if (p_child->old.slave2_addr) {
> /* Maybe this is a SDVO device with multiple inputs */
> /* And the mapping info is not added */
> DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
> @@ -573,7 +573,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
> struct bdb_header *bdb)
> {
> struct bdb_general_definitions *p_defs;
> - struct child_device_config *p_child, *child_dev_ptr;
> + union child_device_config *p_child, *child_dev_ptr;
> int i, child_device_num, count;
> u16 block_size;
>
> @@ -601,7 +601,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
> /* get the number of child device that is present */
> for (i = 0; i < child_device_num; i++) {
> p_child = &(p_defs->devices[i]);
> - if (!p_child->device_type) {
> + if (!p_child->common.device_type) {
> /* skip the device block if device type is invalid */
> continue;
> }
> @@ -621,7 +621,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
> count = 0;
> for (i = 0; i < child_device_num; i++) {
> p_child = &(p_defs->devices[i]);
> - if (!p_child->device_type) {
> + if (!p_child->common.device_type) {
> /* skip the device block if device type is invalid */
> continue;
> }
> diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
> index e088d6f..ae1b423 100644
> --- a/drivers/gpu/drm/i915/intel_bios.h
> +++ b/drivers/gpu/drm/i915/intel_bios.h
> @@ -201,7 +201,10 @@ struct bdb_general_features {
> #define DEVICE_PORT_DVOB 0x01
> #define DEVICE_PORT_DVOC 0x02
>
> -struct child_device_config {
> +/* We used to keep this struct but without any version control. We should avoid
> + * using it in the future, but it should be safe to keep using it in the old
> + * code. */
> +struct old_child_dev_config {
> u16 handle;
> u16 device_type;
> u8 device_id[10]; /* ascii string */
> @@ -223,6 +226,32 @@ struct child_device_config {
> u8 dvo_function;
> } __attribute__((packed));
>
> +/* This one contains field offsets that are known to be common for all BDB
> + * versions. Notice that the meaning of the contents contents may still change,
> + * but at least the offsets are consistent. */
> +struct common_child_dev_config {
> + u16 handle;
> + u16 device_type;
> + u8 not_common1[12];
> + u8 dvo_port;
> + u8 not_common2[2];
> + u8 ddc_pin;
> + u16 edid_ptr;
> +} __attribute__((packed));
> +
> +/* This field changes depending on the BDB version, so the most reliable way to
> + * read it is by checking the BDB version and reading the raw pointer. */
> +union child_device_config {
> + /* This one is safe to be used anywhere, but the code should still check
> + * the BDB version. */
> + u8 raw[33];
> + /* This one should only be kept for legacy code. */
> + struct old_child_dev_config old;
> + /* This one should also be safe to use anywhere, even without version
> + * checks. */
> + struct common_child_dev_config common;
> +};
> +
> struct bdb_general_definitions {
> /* DDC GPIO */
> u8 crt_ddc_gmbus_pin;
> @@ -248,7 +277,7 @@ struct bdb_general_definitions {
> * number = (block_size - sizeof(bdb_general_definitions))/
> * sizeof(child_device_config);
> */
> - struct child_device_config devices[0];
> + union child_device_config devices[0];
> } __attribute__((packed));
>
> struct bdb_lvds_options {
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 2151d13..6224ea2 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3090,7 +3090,7 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
> bool intel_dpd_is_edp(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> - struct child_device_config *p_child;
> + union child_device_config *p_child;
> int i;
>
> if (!dev_priv->vbt.child_dev_num)
> @@ -3099,8 +3099,8 @@ bool intel_dpd_is_edp(struct drm_device *dev)
> for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
> p_child = dev_priv->vbt.child_dev + i;
>
> - if (p_child->dvo_port == PORT_IDPD &&
> - p_child->device_type == DEVICE_TYPE_eDP)
> + if (p_child->common.dvo_port == PORT_IDPD &&
> + p_child->common.device_type == DEVICE_TYPE_eDP)
> return true;
> }
> return false;
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 4d33278..dc99e38 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -786,7 +786,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
> return true;
>
> for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
> - struct child_device_config *child = dev_priv->vbt.child_dev + i;
> + union child_device_config *uchild = dev_priv->vbt.child_dev + i;
> + struct old_child_dev_config *child = &uchild->old;
>
> /* If the device type is not LFP, continue.
> * We have to check both the new identifiers as well as the
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index f2c6d79..78631a2 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -1510,7 +1510,7 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = {
> static int tv_is_present_in_vbt(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> - struct child_device_config *p_child;
> + union child_device_config *p_child;
> int i, ret;
>
> if (!dev_priv->vbt.child_dev_num)
> @@ -1522,13 +1522,13 @@ static int tv_is_present_in_vbt(struct drm_device *dev)
> /*
> * If the device type is not TV, continue.
> */
> - if (p_child->device_type != DEVICE_TYPE_INT_TV &&
> - p_child->device_type != DEVICE_TYPE_TV)
> + if (p_child->old.device_type != DEVICE_TYPE_INT_TV &&
> + p_child->old.device_type != DEVICE_TYPE_TV)
> continue;
> /* Only when the addin_offset is non-zero, it is regarded
> * as present.
> */
> - if (p_child->addin_offset) {
> + if (p_child->old.addin_offset) {
> ret = 1;
> break;
> }
> --
> 1.8.1.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
More information about the Intel-gfx
mailing list