drm/i915: Get the i2c bus number from the ACPI

Submitted by Deepak M on Feb. 19, 2016, 1:55 p.m.

Details

Message ID 1455890157-23756-1-git-send-email-m.deepak@intel.com
State New
Headers show
Series "drm/i915: Get the i2c bus number from the ACPI" ( rev: 1 ) in Intel GFX

Not browsing as part of any series.

Commit Message

Deepak M Feb. 19, 2016, 1:55 p.m.
Currently for executing the i2c MIPI sequence, we are
relaying on the i2c bus bunmber which is specified in the
VBT.

Signed-off-by: Deepak M <m.deepak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c   |  2 ++
 drivers/gpu/drm/i915/i915_drv.h   |  7 ++++++
 drivers/gpu/drm/i915/intel_acpi.c | 49 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 1c6d227..8cd1d9d 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -387,6 +387,8 @@  static int i915_load_modeset_init(struct drm_device *dev)
 
 	intel_register_dsm_handler();
 
+	intel_acpi_find_i2c(dev_priv);
+
 	ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false);
 	if (ret)
 		goto cleanup_vga_client;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6644c2e..6fe8b64 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -47,6 +47,7 @@ 
 #include <drm/intel-gtt.h>
 #include <drm/drm_legacy.h> /* for struct drm_dma_handle */
 #include <drm/drm_gem.h>
+#include <linux/acpi.h>
 #include <linux/backlight.h>
 #include <linux/hashtable.h>
 #include <linux/intel-iommu.h>
@@ -1880,6 +1881,11 @@  struct drm_i915_private {
 
 	struct i915_workarounds workarounds;
 
+	struct {
+		int i2c_bus_number;
+		int i2c_slave_address;
+	} acpi_data;
+
 	/* Reclocking support */
 	bool render_reclock_avail;
 
@@ -3426,6 +3432,7 @@  intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
 #ifdef CONFIG_ACPI
 extern void intel_register_dsm_handler(void);
 extern void intel_unregister_dsm_handler(void);
+extern acpi_status intel_acpi_find_i2c(struct drm_i915_private *dev_priv);
 #else
 static inline void intel_register_dsm_handler(void) { return; }
 static inline void intel_unregister_dsm_handler(void) { return; }
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index eb638a1..f62be5c 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -110,6 +110,55 @@  static void intel_dsm_platform_mux_info(void)
 	ACPI_FREE(pkg);
 }
 
+static int i2c_acpi_get_name(struct acpi_resource *ares, void *data)
+{
+	struct drm_i915_private *dev_priv = data;
+	struct acpi_resource_i2c_serialbus *sb;
+	unsigned int val;
+	char *resource;
+	int error;
+
+	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+		sb = &ares->data.i2c_serial_bus;
+
+		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+			resource = sb->resource_source.string_ptr;
+			resource = strstr(resource, "I2C");
+			error = kstrtouint(resource+3, 0, &val);
+			if (error)
+				return error;
+			dev_priv->acpi_data.i2c_bus_number = val;
+			dev_priv->acpi_data.i2c_slave_address =
+						sb->slave_address;
+		}
+	}
+	return 1;
+}
+
+acpi_status intel_acpi_find_i2c(struct drm_i915_private *dev_priv)
+{
+	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct list_head resource_list;
+	struct acpi_device *adev;
+	acpi_handle dhandle;
+
+	dhandle = ACPI_HANDLE(&pdev->dev);
+	if (!dhandle)
+		return false;
+
+	if (acpi_bus_get_device(dhandle, &adev))
+		return AE_OK;
+	if (acpi_bus_get_status(adev) || !adev->status.present)
+		return AE_OK;
+
+	INIT_LIST_HEAD(&resource_list);
+	acpi_dev_get_resources(adev, &resource_list,
+			i2c_acpi_get_name, dev_priv);
+	acpi_dev_free_resource_list(&resource_list);
+
+	return AE_OK;
+}
+
 static bool intel_dsm_pci_probe(struct pci_dev *pdev)
 {
 	acpi_handle dhandle;

Comments

This patch reads the i2c bus number from the _CRS table of the display module of the ACPI, which will be updated by the BIOS with the i2c info which is used for this module.

> -----Original Message-----
> From: Deepak, M
> Sent: Friday, February 19, 2016 7:26 PM
> To: intel-gfx@lists.freedesktop.org
> Cc: Deepak, M <m.deepak@intel.com>
> Subject: [PATCH] drm/i915: Get the i2c bus number from the ACPI
> 
> Currently for executing the i2c MIPI sequence, we are relaying on the i2c bus
> bunmber which is specified in the VBT.
> 
> Signed-off-by: Deepak M <m.deepak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c   |  2 ++
>  drivers/gpu/drm/i915/i915_drv.h   |  7 ++++++
>  drivers/gpu/drm/i915/intel_acpi.c | 49
> +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c
> b/drivers/gpu/drm/i915/i915_dma.c index 1c6d227..8cd1d9d 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -387,6 +387,8 @@ static int i915_load_modeset_init(struct drm_device
> *dev)
> 
>  	intel_register_dsm_handler();
> 
> +	intel_acpi_find_i2c(dev_priv);
> +
>  	ret = vga_switcheroo_register_client(dev->pdev,
> &i915_switcheroo_ops, false);
>  	if (ret)
>  		goto cleanup_vga_client;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h index 6644c2e..6fe8b64 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -47,6 +47,7 @@
>  #include <drm/intel-gtt.h>
>  #include <drm/drm_legacy.h> /* for struct drm_dma_handle */  #include
> <drm/drm_gem.h>
> +#include <linux/acpi.h>
>  #include <linux/backlight.h>
>  #include <linux/hashtable.h>
>  #include <linux/intel-iommu.h>
> @@ -1880,6 +1881,11 @@ struct drm_i915_private {
> 
>  	struct i915_workarounds workarounds;
> 
> +	struct {
> +		int i2c_bus_number;
> +		int i2c_slave_address;
> +	} acpi_data;
> +
>  	/* Reclocking support */
>  	bool render_reclock_avail;
> 
> @@ -3426,6 +3432,7 @@ intel_opregion_notify_adapter(struct drm_device
> *dev, pci_power_t state)  #ifdef CONFIG_ACPI  extern void
> intel_register_dsm_handler(void);  extern void
> intel_unregister_dsm_handler(void);
> +extern acpi_status intel_acpi_find_i2c(struct drm_i915_private
> +*dev_priv);
>  #else
>  static inline void intel_register_dsm_handler(void) { return; }  static inline
> void intel_unregister_dsm_handler(void) { return; } diff --git
> a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
> index eb638a1..f62be5c 100644
> --- a/drivers/gpu/drm/i915/intel_acpi.c
> +++ b/drivers/gpu/drm/i915/intel_acpi.c
> @@ -110,6 +110,55 @@ static void intel_dsm_platform_mux_info(void)
>  	ACPI_FREE(pkg);
>  }
> 
> +static int i2c_acpi_get_name(struct acpi_resource *ares, void *data) {
> +	struct drm_i915_private *dev_priv = data;
> +	struct acpi_resource_i2c_serialbus *sb;
> +	unsigned int val;
> +	char *resource;
> +	int error;
> +
> +	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
> +		sb = &ares->data.i2c_serial_bus;
> +
> +		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
> +			resource = sb->resource_source.string_ptr;
> +			resource = strstr(resource, "I2C");
> +			error = kstrtouint(resource+3, 0, &val);
> +			if (error)
> +				return error;
> +			dev_priv->acpi_data.i2c_bus_number = val;
> +			dev_priv->acpi_data.i2c_slave_address =
> +						sb->slave_address;
> +		}
> +	}
> +	return 1;
> +}
> +
> +acpi_status intel_acpi_find_i2c(struct drm_i915_private *dev_priv) {
> +	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct list_head resource_list;
> +	struct acpi_device *adev;
> +	acpi_handle dhandle;
> +
> +	dhandle = ACPI_HANDLE(&pdev->dev);
> +	if (!dhandle)
> +		return false;
> +
> +	if (acpi_bus_get_device(dhandle, &adev))
> +		return AE_OK;
> +	if (acpi_bus_get_status(adev) || !adev->status.present)
> +		return AE_OK;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +	acpi_dev_get_resources(adev, &resource_list,
> +			i2c_acpi_get_name, dev_priv);
> +	acpi_dev_free_resource_list(&resource_list);
> +
> +	return AE_OK;
> +}
> +
>  static bool intel_dsm_pci_probe(struct pci_dev *pdev)  {
>  	acpi_handle dhandle;
> --
> 1.9.1
On Fri, Feb 19, 2016 at 07:25:57PM +0530, Deepak M wrote:
> Currently for executing the i2c MIPI sequence, we are
> relaying on the i2c bus bunmber which is specified in the
> VBT.
> 
> Signed-off-by: Deepak M <m.deepak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c   |  2 ++
>  drivers/gpu/drm/i915/i915_drv.h   |  7 ++++++
>  drivers/gpu/drm/i915/intel_acpi.c | 49 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 1c6d227..8cd1d9d 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -387,6 +387,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  
>  	intel_register_dsm_handler();
>  
> +	intel_acpi_find_i2c(dev_priv);
> +
>  	ret = vga_switcheroo_register_client(dev->pdev, &i915_switcheroo_ops, false);
>  	if (ret)
>  		goto cleanup_vga_client;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 6644c2e..6fe8b64 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -47,6 +47,7 @@
>  #include <drm/intel-gtt.h>
>  #include <drm/drm_legacy.h> /* for struct drm_dma_handle */
>  #include <drm/drm_gem.h>
> +#include <linux/acpi.h>
>  #include <linux/backlight.h>
>  #include <linux/hashtable.h>
>  #include <linux/intel-iommu.h>
> @@ -1880,6 +1881,11 @@ struct drm_i915_private {
>  
>  	struct i915_workarounds workarounds;
>  
> +	struct {
> +		int i2c_bus_number;
> +		int i2c_slave_address;
> +	} acpi_data;

The naming is rather vague. i2c bus for what?

Also is one bus always enough? The VBT i2c stuff could
use multiple i2c busses. Also how do we map this to the bus
number that the VBT has?

> +
>  	/* Reclocking support */
>  	bool render_reclock_avail;
>  
> @@ -3426,6 +3432,7 @@ intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
>  #ifdef CONFIG_ACPI
>  extern void intel_register_dsm_handler(void);
>  extern void intel_unregister_dsm_handler(void);
> +extern acpi_status intel_acpi_find_i2c(struct drm_i915_private *dev_priv);
>  #else
>  static inline void intel_register_dsm_handler(void) { return; }
>  static inline void intel_unregister_dsm_handler(void) { return; }
> diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
> index eb638a1..f62be5c 100644
> --- a/drivers/gpu/drm/i915/intel_acpi.c
> +++ b/drivers/gpu/drm/i915/intel_acpi.c
> @@ -110,6 +110,55 @@ static void intel_dsm_platform_mux_info(void)
>  	ACPI_FREE(pkg);
>  }
>  
> +static int i2c_acpi_get_name(struct acpi_resource *ares, void *data)
> +{
> +	struct drm_i915_private *dev_priv = data;
> +	struct acpi_resource_i2c_serialbus *sb;
> +	unsigned int val;
> +	char *resource;
> +	int error;
> +
> +	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
> +		sb = &ares->data.i2c_serial_bus;
> +
> +		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
> +			resource = sb->resource_source.string_ptr;
> +			resource = strstr(resource, "I2C");
> +			error = kstrtouint(resource+3, 0, &val);
> +			if (error)
> +				return error;
> +			dev_priv->acpi_data.i2c_bus_number = val;
> +			dev_priv->acpi_data.i2c_slave_address =
> +						sb->slave_address;
> +		}
> +	}
> +	return 1;
> +}
> +
> +acpi_status intel_acpi_find_i2c(struct drm_i915_private *dev_priv)
> +{
> +	struct pci_dev *pdev = dev_priv->dev->pdev;
> +	struct list_head resource_list;
> +	struct acpi_device *adev;
> +	acpi_handle dhandle;
> +
> +	dhandle = ACPI_HANDLE(&pdev->dev);
> +	if (!dhandle)
> +		return false;
> +
> +	if (acpi_bus_get_device(dhandle, &adev))
> +		return AE_OK;
> +	if (acpi_bus_get_status(adev) || !adev->status.present)
> +		return AE_OK;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +	acpi_dev_get_resources(adev, &resource_list,
> +			i2c_acpi_get_name, dev_priv);
> +	acpi_dev_free_resource_list(&resource_list);
> +
> +	return AE_OK;
> +}
> +
>  static bool intel_dsm_pci_probe(struct pci_dev *pdev)
>  {
>  	acpi_handle dhandle;
> -- 
> 1.9.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Friday, February 19, 2016 7:38 PM
> To: Deepak, M <m.deepak@intel.com>
> Cc: intel-gfx@lists.freedesktop.org
> Subject: Re: [Intel-gfx] [PATCH] drm/i915: Get the i2c bus number from the
> ACPI
> 
> On Fri, Feb 19, 2016 at 07:25:57PM +0530, Deepak M wrote:
> > Currently for executing the i2c MIPI sequence, we are relaying on the
> > i2c bus bunmber which is specified in the VBT.
> >
> > Signed-off-by: Deepak M <m.deepak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c   |  2 ++
> >  drivers/gpu/drm/i915/i915_drv.h   |  7 ++++++
> >  drivers/gpu/drm/i915/intel_acpi.c | 49
> > +++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 58 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c
> > b/drivers/gpu/drm/i915/i915_dma.c index 1c6d227..8cd1d9d 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -387,6 +387,8 @@ static int i915_load_modeset_init(struct
> > drm_device *dev)
> >
> >  	intel_register_dsm_handler();
> >
> > +	intel_acpi_find_i2c(dev_priv);
> > +
> >  	ret = vga_switcheroo_register_client(dev->pdev,
> &i915_switcheroo_ops, false);
> >  	if (ret)
> >  		goto cleanup_vga_client;
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h
> > b/drivers/gpu/drm/i915/i915_drv.h index 6644c2e..6fe8b64 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -47,6 +47,7 @@
> >  #include <drm/intel-gtt.h>
> >  #include <drm/drm_legacy.h> /* for struct drm_dma_handle */  #include
> > <drm/drm_gem.h>
> > +#include <linux/acpi.h>
> >  #include <linux/backlight.h>
> >  #include <linux/hashtable.h>
> >  #include <linux/intel-iommu.h>
> > @@ -1880,6 +1881,11 @@ struct drm_i915_private {
> >
> >  	struct i915_workarounds workarounds;
> >
> > +	struct {
> > +		int i2c_bus_number;
> > +		int i2c_slave_address;
> > +	} acpi_data;
> 
> The naming is rather vague. i2c bus for what?
> 
> Also is one bus always enough? The VBT i2c stuff could use multiple i2c
> busses. Also how do we map this to the bus number that the VBT has?
> 
[Deepak, M] Most of the cases I have seen only one i2c being used, If there are multiple i2c busses used then need to check which i2c is used for what purpose and is there a protocol which is followed by BIOS team when more than one i2c bus is used.
> > +
> >  	/* Reclocking support */
> >  	bool render_reclock_avail;
> >
> > @@ -3426,6 +3432,7 @@ intel_opregion_notify_adapter(struct
> drm_device
> > *dev, pci_power_t state)  #ifdef CONFIG_ACPI  extern void
> > intel_register_dsm_handler(void);  extern void
> > intel_unregister_dsm_handler(void);
> > +extern acpi_status intel_acpi_find_i2c(struct drm_i915_private
> > +*dev_priv);
> >  #else
> >  static inline void intel_register_dsm_handler(void) { return; }
> > static inline void intel_unregister_dsm_handler(void) { return; } diff
> > --git a/drivers/gpu/drm/i915/intel_acpi.c
> > b/drivers/gpu/drm/i915/intel_acpi.c
> > index eb638a1..f62be5c 100644
> > --- a/drivers/gpu/drm/i915/intel_acpi.c
> > +++ b/drivers/gpu/drm/i915/intel_acpi.c
> > @@ -110,6 +110,55 @@ static void intel_dsm_platform_mux_info(void)
> >  	ACPI_FREE(pkg);
> >  }
> >
> > +static int i2c_acpi_get_name(struct acpi_resource *ares, void *data)
> > +{
> > +	struct drm_i915_private *dev_priv = data;
> > +	struct acpi_resource_i2c_serialbus *sb;
> > +	unsigned int val;
> > +	char *resource;
> > +	int error;
> > +
> > +	if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
> > +		sb = &ares->data.i2c_serial_bus;
> > +
> > +		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
> > +			resource = sb->resource_source.string_ptr;
> > +			resource = strstr(resource, "I2C");
> > +			error = kstrtouint(resource+3, 0, &val);
> > +			if (error)
> > +				return error;
> > +			dev_priv->acpi_data.i2c_bus_number = val;
> > +			dev_priv->acpi_data.i2c_slave_address =
> > +						sb->slave_address;
> > +		}
> > +	}
> > +	return 1;
> > +}
> > +
> > +acpi_status intel_acpi_find_i2c(struct drm_i915_private *dev_priv) {
> > +	struct pci_dev *pdev = dev_priv->dev->pdev;
> > +	struct list_head resource_list;
> > +	struct acpi_device *adev;
> > +	acpi_handle dhandle;
> > +
> > +	dhandle = ACPI_HANDLE(&pdev->dev);
> > +	if (!dhandle)
> > +		return false;
> > +
> > +	if (acpi_bus_get_device(dhandle, &adev))
> > +		return AE_OK;
> > +	if (acpi_bus_get_status(adev) || !adev->status.present)
> > +		return AE_OK;
> > +
> > +	INIT_LIST_HEAD(&resource_list);
> > +	acpi_dev_get_resources(adev, &resource_list,
> > +			i2c_acpi_get_name, dev_priv);
> > +	acpi_dev_free_resource_list(&resource_list);
> > +
> > +	return AE_OK;
> > +}
> > +
> >  static bool intel_dsm_pci_probe(struct pci_dev *pdev)  {
> >  	acpi_handle dhandle;
> > --
> > 1.9.1
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> --
> Ville Syrjälä
> Intel OTC