Commit 96ec2d98 authored by Orlando Chamberlain's avatar Orlando Chamberlain Committed by Hans de Goede
Browse files

platform/x86: apple-gmux: refactor gmux types



Add apple_gmux_config struct containing operations and data specific to
each mux type.

This is in preparation for adding a third, MMIO based, gmux type.

Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarOrlando Chamberlain <orlandoch.dev@gmail.com>
Link: https://lore.kernel.org/r/20230303112842.3094-3-orlandoch.dev@gmail.com


Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 90caf1df
Loading
Loading
Loading
Loading
+62 −31
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 *  Copyright (C) Canonical Ltd. <seth.forshee@canonical.com>
 *  Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de>
 *  Copyright (C) 2015 Lukas Wunner <lukas@wunner.de>
 *  Copyright (C) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com>
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -43,10 +44,12 @@
 *     http://www.renesas.com/products/mpumcu/h8s/h8s2100/h8s2113/index.jsp
 */

struct apple_gmux_config;

struct apple_gmux_data {
	unsigned long iostart;
	unsigned long iolen;
	bool indexed;
	const struct apple_gmux_config *config;
	struct mutex index_lock;

	struct backlight_device *bdev;
@@ -64,6 +67,18 @@ struct apple_gmux_data {

static struct apple_gmux_data *apple_gmux_data;

struct apple_gmux_config {
	u8 (*read8)(struct apple_gmux_data *gmux_data, int port);
	void (*write8)(struct apple_gmux_data *gmux_data, int port, u8 val);
	u32 (*read32)(struct apple_gmux_data *gmux_data, int port);
	void (*write32)(struct apple_gmux_data *gmux_data, int port, u32 val);
	const struct vga_switcheroo_handler *gmux_handler;
	enum vga_switcheroo_handler_flags_t handler_flags;
	unsigned long resource_type;
	bool read_version_as_u32;
	char *name;
};

#define GMUX_INTERRUPT_ENABLE		0xff
#define GMUX_INTERRUPT_DISABLE		0x00

@@ -195,35 +210,23 @@ static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port,

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);
	return gmux_data->config->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);
	return gmux_data->config->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);
	return gmux_data->config->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);
	return gmux_data->config->write32(gmux_data, port, val);
}

/**
@@ -463,19 +466,43 @@ static enum vga_switcheroo_client_id gmux_get_client_id(struct pci_dev *pdev)
		return VGA_SWITCHEROO_DIS;
}

static const struct vga_switcheroo_handler gmux_handler_indexed = {
static const struct vga_switcheroo_handler gmux_handler_no_ddc = {
	.switchto = gmux_switchto,
	.power_state = gmux_set_power_state,
	.get_client_id = gmux_get_client_id,
};

static const struct vga_switcheroo_handler gmux_handler_classic = {
static const struct vga_switcheroo_handler gmux_handler_ddc = {
	.switchto = gmux_switchto,
	.switch_ddc = gmux_switch_ddc,
	.power_state = gmux_set_power_state,
	.get_client_id = gmux_get_client_id,
};

static const struct apple_gmux_config apple_gmux_pio = {
	.read8 = &gmux_pio_read8,
	.write8 = &gmux_pio_write8,
	.read32 = &gmux_pio_read32,
	.write32 = &gmux_pio_write32,
	.gmux_handler = &gmux_handler_ddc,
	.handler_flags = VGA_SWITCHEROO_CAN_SWITCH_DDC,
	.resource_type = IORESOURCE_IO,
	.read_version_as_u32 = false,
	.name = "classic"
};

static const struct apple_gmux_config apple_gmux_index = {
	.read8 = &gmux_index_read8,
	.write8 = &gmux_index_write8,
	.read32 = &gmux_index_read32,
	.write32 = &gmux_index_write32,
	.gmux_handler = &gmux_handler_no_ddc,
	.handler_flags = VGA_SWITCHEROO_NEEDS_EDP_CONFIG,
	.resource_type = IORESOURCE_IO,
	.read_version_as_u32 = true,
	.name = "indexed"
};

/**
 * DOC: Interrupt
 *
@@ -565,13 +592,13 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
	int ret = -ENXIO;
	acpi_status status;
	unsigned long long gpe;
	bool indexed = false;
	enum apple_gmux_type type;
	u32 version;

	if (apple_gmux_data)
		return -EBUSY;

	if (!apple_gmux_detect(pnp, &indexed)) {
	if (!apple_gmux_detect(pnp, &type)) {
		pr_info("gmux device not present\n");
		return -ENODEV;
	}
@@ -581,6 +608,16 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
		return -ENOMEM;
	pnp_set_drvdata(pnp, gmux_data);

	switch (type) {
	case APPLE_GMUX_TYPE_INDEXED:
		gmux_data->config = &apple_gmux_index;
		mutex_init(&gmux_data->index_lock);
		break;
	case APPLE_GMUX_TYPE_PIO:
		gmux_data->config = &apple_gmux_pio;
		break;
	}

	res = pnp_get_resource(pnp, IORESOURCE_IO, 0);
	gmux_data->iostart = res->start;
	gmux_data->iolen = resource_size(res);
@@ -591,9 +628,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
		goto err_free;
	}

	if (indexed) {
		mutex_init(&gmux_data->index_lock);
		gmux_data->indexed = true;
	if (gmux_data->config->read_version_as_u32) {
		version = gmux_read32(gmux_data, GMUX_PORT_VERSION_MAJOR);
		ver_major = (version >> 24) & 0xff;
		ver_minor = (version >> 16) & 0xff;
@@ -604,7 +639,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
		ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
	}
	pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
		ver_release, (gmux_data->indexed ? "indexed" : "classic"));
		ver_release, gmux_data->config->name);

	memset(&props, 0, sizeof(props));
	props.type = BACKLIGHT_PLATFORM;
@@ -694,12 +729,8 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
	 *
	 * Pre-retina MacBook Pros can switch the panel's DDC separately.
	 */
	if (gmux_data->indexed)
		ret = vga_switcheroo_register_handler(&gmux_handler_indexed,
					      VGA_SWITCHEROO_NEEDS_EDP_CONFIG);
	else
		ret = vga_switcheroo_register_handler(&gmux_handler_classic,
					      VGA_SWITCHEROO_CAN_SWITCH_DDC);
	ret = vga_switcheroo_register_handler(gmux_data->config->gmux_handler,
			gmux_data->config->handler_flags);
	if (ret) {
		pr_err("Failed to register vga_switcheroo handler\n");
		goto err_register_handler;
+12 −6
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@

#define GMUX_MIN_IO_LEN			(GMUX_PORT_BRIGHTNESS + 4)

enum apple_gmux_type {
	APPLE_GMUX_TYPE_PIO,
	APPLE_GMUX_TYPE_INDEXED,
};

#if IS_ENABLED(CONFIG_APPLE_GMUX)
static inline bool apple_gmux_is_indexed(unsigned long iostart)
{
@@ -65,13 +70,13 @@ static inline bool apple_gmux_is_indexed(unsigned long iostart)
 * Return: %true if a supported gmux ACPI device is detected and the kernel
 * was configured with CONFIG_APPLE_GMUX, %false otherwise.
 */
static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, enum apple_gmux_type *type_ret)
{
	u8 ver_major, ver_minor, ver_release;
	struct device *dev = NULL;
	struct acpi_device *adev;
	struct resource *res;
	bool indexed = false;
	enum apple_gmux_type type = APPLE_GMUX_TYPE_PIO;
	bool ret = false;

	if (!pnp_dev) {
@@ -99,13 +104,14 @@ static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
	ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR);
	ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE);
	if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
		indexed = apple_gmux_is_indexed(res->start);
		if (!indexed)
		if (apple_gmux_is_indexed(res->start))
			type = APPLE_GMUX_TYPE_INDEXED;
		else
			goto out;
	}

	if (indexed_ret)
		*indexed_ret = indexed;
	if (type_ret)
		*type_ret = type;

	ret = true;
out: