// SPDX-License-Identifier: GPL-2.0-only /* * Apple Onboard Audio feature call GPIO control * * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> * * This file contains the GPIO control routines for * direct (through feature calls) access to the GPIO * registers.
*/
/* TODO: these are lots of global variables * that aren't used on most machines... * Move them into a dynamically allocated * structure and use that.
*/
/* these are the GPIO numbers (register addresses as offsets into
* the GPIO space) */ staticint headphone_mute_gpio; staticint master_mute_gpio; staticint amp_mute_gpio; staticint lineout_mute_gpio; staticint hw_reset_gpio; staticint lineout_detect_gpio; staticint headphone_detect_gpio; staticint linein_detect_gpio;
/* node pointers that we save when getting the GPIO number
* to get the interrupt later */ staticstruct device_node *lineout_detect_node; staticstruct device_node *linein_detect_node; staticstruct device_node *headphone_detect_node;
staticstruct device_node *get_gpio(char *name, char *altname, int *gpioptr, int *gpioactiveptr)
{ struct device_node *np, *gpio; const u32 *reg; constchar *audio_gpio;
*gpioptr = -1;
/* check if we can get it the easy way ... */
np = of_find_node_by_name(NULL, name); if (!np) { /* some machines have only gpioX/extint-gpioX nodes, * and an audio-gpio property saying what it is ... * So what we have to do is enumerate all children
* of the gpio node and check them all. */
gpio = of_find_node_by_name(NULL, "gpio"); if (!gpio) return NULL; while ((np = of_get_next_child(gpio, np))) {
audio_gpio = of_get_property(np, "audio-gpio", NULL); if (!audio_gpio) continue; if (strcmp(audio_gpio, name) == 0) break; if (altname && (strcmp(audio_gpio, altname) == 0)) break;
}
of_node_put(gpio); /* still not found, assume not there */ if (!np) return NULL;
}
/* this is a hack, usually the GPIOs 'reg' property * should have the offset based from the GPIO space
* which is at 0x50, but apparently not always... */ if (*gpioptr < 0x50)
*gpioptr += 0x50;
reg = of_get_property(np, "audio-gpio-active-state", NULL); if (!reg) /* Apple seems to default to 1, but * that doesn't seem right at least on most * machines. So until proven that the opposite * is necessary, we default to 0
* (which, incidentally, snd-powermac also does...) */
*gpioactiveptr = 0; else
*gpioactiveptr = *reg;
return np;
}
staticvoid get_irq(struct device_node * np, int *irqptr)
{ if (np)
*irqptr = irq_of_parse_and_map(np, 0); else
*irqptr = 0;
}
/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ #define SWITCH_GPIO(name, v, on) \
(((v)&~1) | ((on)? \
(name##_gpio_activestate==0?4:5): \
(name##_gpio_activestate==0?5:4)))
headphone_detect_node = get_gpio("headphone-detect", NULL,
&headphone_detect_gpio,
&headphone_detect_gpio_activestate); /* go Apple, and thanks for giving these different names
* across the board... */
lineout_detect_node = get_gpio("lineout-detect", "line-output-detect",
&lineout_detect_gpio,
&lineout_detect_gpio_activestate);
linein_detect_node = get_gpio("linein-detect", "line-input-detect",
&linein_detect_gpio,
&linein_detect_gpio_activestate);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.