public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] gmux: Add generic write32 function
@ 2012-08-13 20:20 Matthew Garrett
  2012-08-13 20:20 ` [PATCH 2/2] apple_gmux: Add support for newer hardware Matthew Garrett
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Matthew Garrett @ 2012-08-13 20:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: platform-driver-x86, Matthew Garrett, Seth Forshee

Move the special-cased backlight update function to a generic gmux_write32
function.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: Seth Forshee <seth.forshee@canonical.com>
---
 drivers/gpu/drm/nouveau/nouveau_bios.c |  3 +++
 drivers/platform/x86/apple-gmux.c      | 23 +++++++++++++----------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index a0a3fe3..818b93c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -6473,6 +6473,9 @@ nouveau_run_vbios_init(struct drm_device *dev)
 		}
 	}
 
+	if (!bios->execute)
+		nouveau_gpio_reset(dev);
+
 	return ret;
 }
 
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 905fa01..43721c1 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -75,6 +75,18 @@ static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port)
 	return inl(gmux_data->iostart + port);
 }
 
+static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port,
+			       u32 val)
+{
+	int i;
+	u8 tmpval;
+
+	for (i = 0; i < 4; i++) {
+		tmpval = (val >> (i * 8)) & 0xff;
+		outb(tmpval, port + i);
+	}
+}
+
 static int gmux_get_brightness(struct backlight_device *bd)
 {
 	struct apple_gmux_data *gmux_data = bl_get_data(bd);
@@ -90,16 +102,7 @@ static int gmux_update_status(struct backlight_device *bd)
 	if (bd->props.state & BL_CORE_SUSPENDED)
 		return 0;
 
-	/*
-	 * Older gmux versions require writing out lower bytes first then
-	 * setting the upper byte to 0 to flush the values. Newer versions
-	 * accept a single u32 write, but the old method also works, so we
-	 * just use the old method for all gmux versions.
-	 */
-	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness);
-	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8);
-	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16);
-	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0);
+	gmux_write32(gmux_data, GMUX_PORT_BRIGHTNES, brightness);
 
 	return 0;
 }
-- 
1.7.11.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] apple_gmux: Add support for newer hardware
  2012-08-13 20:20 [PATCH 1/2] gmux: Add generic write32 function Matthew Garrett
@ 2012-08-13 20:20 ` Matthew Garrett
  2012-08-13 21:04   ` Seth Forshee
  2012-08-13 20:49 ` [PATCH 1/2] gmux: Add generic write32 function Seth Forshee
  2012-08-13 20:55 ` Seth Forshee
  2 siblings, 1 reply; 8+ messages in thread
From: Matthew Garrett @ 2012-08-13 20:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: platform-driver-x86, Matthew Garrett, Bernhard Froemel,
	Seth Forshee

New gmux devices have a different method for accessing the registers.
Update the driver to cope. Incorporates feedback from Bernhard Froemel.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Cc: Bernhard Froemel <froemel@vmars.tuwien.ac.at>
Cc: Seth Forshee <seth.forshee@canonical.com>
---
 drivers/platform/x86/apple-gmux.c | 181 ++++++++++++++++++++++++++++++++++----
 1 file changed, 166 insertions(+), 15 deletions(-)

diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 43721c1..612b6f6 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -18,12 +18,15 @@
 #include <linux/pnp.h>
 #include <linux/apple_bl.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <acpi/video.h>
 #include <asm/io.h>
 
 struct apple_gmux_data {
 	unsigned long iostart;
 	unsigned long iolen;
+	bool indexed;
+	struct mutex index_lock;
 
 	struct backlight_device *bdev;
 };
@@ -45,6 +48,9 @@ struct apple_gmux_data {
 #define GMUX_PORT_DISCRETE_POWER	0x50
 #define GMUX_PORT_MAX_BRIGHTNESS	0x70
 #define GMUX_PORT_BRIGHTNESS		0x74
+#define GMUX_PORT_VALUE			0xc2
+#define GMUX_PORT_READ			0xd0
+#define GMUX_PORT_WRITE			0xd4
 
 #define GMUX_MIN_IO_LEN			(GMUX_PORT_BRIGHTNESS + 4)
 
@@ -59,24 +65,24 @@ struct apple_gmux_data {
 #define GMUX_BRIGHTNESS_MASK		0x00ffffff
 #define GMUX_MAX_BRIGHTNESS		GMUX_BRIGHTNESS_MASK
 
-static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port)
+static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)
 {
 	return inb(gmux_data->iostart + port);
 }
 
-static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port,
+static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port,
 			       u8 val)
 {
 	outb(val, gmux_data->iostart + port);
 }
 
-static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port)
+static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port)
 {
 	return inl(gmux_data->iostart + port);
 }
 
-static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port,
-			       u32 val)
+static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port,
+			     u32 val)
 {
 	int i;
 	u8 tmpval;
@@ -87,6 +93,144 @@ static inline u32 gmux_write32(struct apple_gmux_data *gmux_data, int port,
 	}
 }
 
+static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data)
+{
+	int i = 200;
+	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
+
+	while (i && (gwr & 0x01)) {
+		inb(gmux_data->iostart + GMUX_PORT_READ);
+		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
+		msleep(100);
+		i--;
+	}
+
+	return !!i;
+}
+
+static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data)
+{
+	int i = 200;
+	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
+
+	while (i && (gwr & 0x01)) {
+		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
+		msleep(100);
+		i--;
+	}
+
+	if (gwr & 0x01)
+		inb(gmux_data->iostart + GMUX_PORT_READ);
+
+	return !!i;
+}
+
+static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port)
+{
+	u8 val;
+
+	mutex_lock(&gmux_data->index_lock);
+	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
+	gmux_index_wait_ready(gmux_data);
+	val = inb(gmux_data->iostart + GMUX_PORT_VALUE);
+	mutex_unlock(&gmux_data->index_lock);
+
+	return val;
+}
+
+static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port,
+			      u8 val)
+{
+	mutex_lock(&gmux_data->index_lock);
+	outb(val, gmux_data->iostart + GMUX_PORT_VALUE);
+	gmux_index_wait_ready(gmux_data);
+	outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE);
+	gmux_index_wait_complete(gmux_data);
+	mutex_unlock(&gmux_data->index_lock);
+}
+
+static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port)
+{
+	u32 val;
+
+	mutex_lock(&gmux_data->index_lock);
+	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
+	gmux_index_wait_ready(gmux_data);
+	val = inl(gmux_data->iostart + GMUX_PORT_VALUE);
+	mutex_unlock(&gmux_data->index_lock);
+
+	return val;
+}
+
+static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port,
+			       u32 val)
+{
+	int i;
+	u8 tmpval;
+
+	mutex_lock(&gmux_data->index_lock);
+
+	for (i = 0; i < 4; i++) {
+		tmpval = (val >> (i * 8)) & 0xff;
+		outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i);
+	}
+
+	gmux_index_wait_ready(gmux_data);
+	outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE);
+	gmux_index_wait_complete(gmux_data);
+	mutex_unlock(&gmux_data->index_lock);
+}
+
+static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port)
+{
+	if (gmux_data->indexed)
+		return gmux_index_read8(gmux_data, port);
+	else
+		return gmux_pio_read8(gmux_data, port);
+}
+
+static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val)
+{
+	if (gmux_data->indexed)
+		gmux_index_write8(gmux_data, port, val);
+	else
+		gmux_pio_write8(gmux_data, port, val);
+}
+
+static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port)
+{
+	if (gmux_data->indexed)
+		return gmux_index_read32(gmux_data, port);
+	else
+		return gmux_pio_read32(gmux_data, port);
+}
+
+static void gmux_write32(struct apple_gmux_data *gmux_data, int port,
+			     u32 val)
+{
+	if (gmux_data->indexed)
+		gmux_index_write32(gmux_data, port, val);
+	else
+		gmux_pio_write32(gmux_data, port, val);
+}
+
+static bool gmux_is_indexed(struct apple_gmux_data *gmux_data)
+{
+	u16 val;
+
+	outb(0xaa, gmux_data->iostart + 0xcc);
+	outb(0x55, gmux_data->iostart + 0xcd);
+	outb(0x00, gmux_data->iostart + 0xce);
+
+	val = inb(gmux_data->iostart + 0xcc) |
+		(inb(gmux_data->iostart + 0xcd) << 8);
+
+	if (val == 0x55aa)
+		return true;
+
+	return false;
+}
+
 static int gmux_get_brightness(struct backlight_device *bd)
 {
 	struct apple_gmux_data *gmux_data = bl_get_data(bd);
@@ -102,7 +246,7 @@ static int gmux_update_status(struct backlight_device *bd)
 	if (bd->props.state & BL_CORE_SUSPENDED)
 		return 0;
 
-	gmux_write32(gmux_data, GMUX_PORT_BRIGHTNES, brightness);
+	gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness);
 
 	return 0;
 }
@@ -150,22 +294,29 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,
 	}
 
 	/*
-	 * On some machines the gmux is in ACPI even thought the machine
-	 * doesn't really have a gmux. Check for invalid version information
-	 * to detect this.
+	 * Invalid version information may indicate either that the gmux
+	 * device isn't present or that it's a new one that uses indexed
+	 * io
 	 */
+
 	ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
 	ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
 	ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
 	if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
-		pr_info("gmux device not present\n");
-		ret = -ENODEV;
-		goto err_release;
+		if (gmux_is_indexed(gmux_data)) {
+			mutex_init(&gmux_data->index_lock);
+			gmux_data->indexed = true;
+		} else {
+			pr_info("gmux device not present\n");
+			ret = -ENODEV;
+			goto err_release;
+		}
+		pr_info("Found indexed gmux\n");
+	} else {
+		pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor,
+			ver_release);
 	}
 
-	pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor,
-		ver_release);
-
 	memset(&props, 0, sizeof(props));
 	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
-- 
1.7.11.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] gmux: Add generic write32 function
  2012-08-13 20:20 [PATCH 1/2] gmux: Add generic write32 function Matthew Garrett
  2012-08-13 20:20 ` [PATCH 2/2] apple_gmux: Add support for newer hardware Matthew Garrett
@ 2012-08-13 20:49 ` Seth Forshee
  2012-08-13 21:32   ` Matthew Garrett
  2012-08-13 20:55 ` Seth Forshee
  2 siblings, 1 reply; 8+ messages in thread
From: Seth Forshee @ 2012-08-13 20:49 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-kernel, platform-driver-x86

On Mon, Aug 13, 2012 at 04:20:31PM -0400, Matthew Garrett wrote:
> diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
> index a0a3fe3..818b93c 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_bios.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
> @@ -6473,6 +6473,9 @@ nouveau_run_vbios_init(struct drm_device *dev)
>  		}
>  	}
>  
> +	if (!bios->execute)
> +		nouveau_gpio_reset(dev);
> +
>  	return ret;
>  }

This part doesn't seem to belong.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] gmux: Add generic write32 function
  2012-08-13 20:20 [PATCH 1/2] gmux: Add generic write32 function Matthew Garrett
  2012-08-13 20:20 ` [PATCH 2/2] apple_gmux: Add support for newer hardware Matthew Garrett
  2012-08-13 20:49 ` [PATCH 1/2] gmux: Add generic write32 function Seth Forshee
@ 2012-08-13 20:55 ` Seth Forshee
  2 siblings, 0 replies; 8+ messages in thread
From: Seth Forshee @ 2012-08-13 20:55 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-kernel, platform-driver-x86

On Mon, Aug 13, 2012 at 04:20:31PM -0400, Matthew Garrett wrote:
> +	gmux_write32(gmux_data, GMUX_PORT_BRIGHTNES, brightness);

Also, typo here. Should be GMUX_PORT_BRIGHTNESS.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] apple_gmux: Add support for newer hardware
  2012-08-13 20:20 ` [PATCH 2/2] apple_gmux: Add support for newer hardware Matthew Garrett
@ 2012-08-13 21:04   ` Seth Forshee
  2012-08-13 21:36     ` Matthew Garrett
  0 siblings, 1 reply; 8+ messages in thread
From: Seth Forshee @ 2012-08-13 21:04 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-kernel, platform-driver-x86, Bernhard Froemel

On Mon, Aug 13, 2012 at 04:20:32PM -0400, Matthew Garrett wrote:
> +static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data)
> +{
> +	int i = 200;
> +	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
> +
> +	while (i && (gwr & 0x01)) {
> +		inb(gmux_data->iostart + GMUX_PORT_READ);
> +		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
> +		msleep(100);

Wouldn't it make more sense if the msleep was before reading the port
again? Otherwise there's no substantial dely between the first and
second times we read it.

> +static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data)
> +{
> +	int i = 200;
> +	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
> +
> +	while (i && (gwr & 0x01)) {
> +		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
> +		msleep(100);

Likewise.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] gmux: Add generic write32 function
  2012-08-13 20:49 ` [PATCH 1/2] gmux: Add generic write32 function Seth Forshee
@ 2012-08-13 21:32   ` Matthew Garrett
  0 siblings, 0 replies; 8+ messages in thread
From: Matthew Garrett @ 2012-08-13 21:32 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86

On Mon, Aug 13, 2012 at 03:49:46PM -0500, Seth Forshee wrote:

> This part doesn't seem to belong.

Sigh. Yes, sorry.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] apple_gmux: Add support for newer hardware
  2012-08-13 21:04   ` Seth Forshee
@ 2012-08-13 21:36     ` Matthew Garrett
  2012-08-13 22:03       ` Seth Forshee
  0 siblings, 1 reply; 8+ messages in thread
From: Matthew Garrett @ 2012-08-13 21:36 UTC (permalink / raw)
  To: linux-kernel, platform-driver-x86, Bernhard Froemel

On Mon, Aug 13, 2012 at 04:04:44PM -0500, Seth Forshee wrote:
> > +
> > +	while (i && (gwr & 0x01)) {
> > +		inb(gmux_data->iostart + GMUX_PORT_READ);
> > +		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
> > +		msleep(100);
> 
> Wouldn't it make more sense if the msleep was before reading the port
> again? Otherwise there's no substantial dely between the first and
> second times we read it.

Mm. I'm doing the same as the ACPI implementation - it may be that 
reading GMUX_PORT_READ triggers the update of GMUX_PORT_WRITE? Hard to 
know without the docs.

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] apple_gmux: Add support for newer hardware
  2012-08-13 21:36     ` Matthew Garrett
@ 2012-08-13 22:03       ` Seth Forshee
  0 siblings, 0 replies; 8+ messages in thread
From: Seth Forshee @ 2012-08-13 22:03 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: linux-kernel, platform-driver-x86, Bernhard Froemel

On Mon, Aug 13, 2012 at 10:36:07PM +0100, Matthew Garrett wrote:
> On Mon, Aug 13, 2012 at 04:04:44PM -0500, Seth Forshee wrote:
> > > +
> > > +	while (i && (gwr & 0x01)) {
> > > +		inb(gmux_data->iostart + GMUX_PORT_READ);
> > > +		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE);
> > > +		msleep(100);
> > 
> > Wouldn't it make more sense if the msleep was before reading the port
> > again? Otherwise there's no substantial dely between the first and
> > second times we read it.
> 
> Mm. I'm doing the same as the ACPI implementation - it may be that 
> reading GMUX_PORT_READ triggers the update of GMUX_PORT_WRITE? Hard to 
> know without the docs.

Indeed. I do find the structure of the loop to be odd, but I suppose the
safest approach is to follow the only known working implementation we
have. In that case ...

Acked-by: Seth Forshee <seth.forshee@canonical.com>


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-08-13 22:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-13 20:20 [PATCH 1/2] gmux: Add generic write32 function Matthew Garrett
2012-08-13 20:20 ` [PATCH 2/2] apple_gmux: Add support for newer hardware Matthew Garrett
2012-08-13 21:04   ` Seth Forshee
2012-08-13 21:36     ` Matthew Garrett
2012-08-13 22:03       ` Seth Forshee
2012-08-13 20:49 ` [PATCH 1/2] gmux: Add generic write32 function Seth Forshee
2012-08-13 21:32   ` Matthew Garrett
2012-08-13 20:55 ` Seth Forshee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox