* [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 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 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
* 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: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 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
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