diff options
| author | Clemens Ladisch <clemens@ladisch.de> | 2008-09-22 03:04:43 -0400 |
|---|---|---|
| committer | Clemens Ladisch <clemens@ladisch.de> | 2008-09-22 03:04:43 -0400 |
| commit | 397b1dcc449082ce3f720c548da9c59db01cb739 (patch) | |
| tree | a5295eabb214f913cd931c50b079c81b8086e577 | |
| parent | dbbbd6744439d95d2b0dc23c5cdca2c477377f76 (diff) | |
ALSA: oxygen: add UART I/O functions
Add functions to allow model drivers to communicate with external chips
by doing I/O with the not-used-for-MIDI UART.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
| -rw-r--r-- | sound/pci/oxygen/oxygen.h | 6 | ||||
| -rw-r--r-- | sound/pci/oxygen/oxygen_io.c | 21 | ||||
| -rw-r--r-- | sound/pci/oxygen/oxygen_lib.c | 32 |
3 files changed, 57 insertions, 2 deletions
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index f82a96290f72..19107c6307e5 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
| @@ -79,6 +79,7 @@ struct oxygen_model { | |||
| 79 | void (*update_dac_volume)(struct oxygen *chip); | 79 | void (*update_dac_volume)(struct oxygen *chip); |
| 80 | void (*update_dac_mute)(struct oxygen *chip); | 80 | void (*update_dac_mute)(struct oxygen *chip); |
| 81 | void (*gpio_changed)(struct oxygen *chip); | 81 | void (*gpio_changed)(struct oxygen *chip); |
| 82 | void (*uart_input)(struct oxygen *chip); | ||
| 82 | void (*ac97_switch)(struct oxygen *chip, | 83 | void (*ac97_switch)(struct oxygen *chip, |
| 83 | unsigned int reg, unsigned int mute); | 84 | unsigned int reg, unsigned int mute); |
| 84 | const unsigned int *dac_tlv; | 85 | const unsigned int *dac_tlv; |
| @@ -125,6 +126,8 @@ struct oxygen { | |||
| 125 | __le32 _32[OXYGEN_IO_SIZE / 4]; | 126 | __le32 _32[OXYGEN_IO_SIZE / 4]; |
| 126 | } saved_registers; | 127 | } saved_registers; |
| 127 | u16 saved_ac97_registers[2][0x40]; | 128 | u16 saved_ac97_registers[2][0x40]; |
| 129 | unsigned int uart_input_count; | ||
| 130 | u8 uart_input[32]; | ||
| 128 | struct oxygen_model model; | 131 | struct oxygen_model model; |
| 129 | }; | 132 | }; |
| 130 | 133 | ||
| @@ -174,6 +177,9 @@ void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, | |||
| 174 | void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data); | 177 | void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data); |
| 175 | void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); | 178 | void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); |
| 176 | 179 | ||
| 180 | void oxygen_reset_uart(struct oxygen *chip); | ||
| 181 | void oxygen_write_uart(struct oxygen *chip, u8 data); | ||
| 182 | |||
| 177 | static inline void oxygen_set_bits8(struct oxygen *chip, | 183 | static inline void oxygen_set_bits8(struct oxygen *chip, |
| 178 | unsigned int reg, u8 value) | 184 | unsigned int reg, u8 value) |
| 179 | { | 185 | { |
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c index 83f135f80df4..deba7389aec3 100644 --- a/sound/pci/oxygen/oxygen_io.c +++ b/sound/pci/oxygen/oxygen_io.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
| 22 | #include <sound/core.h> | 22 | #include <sound/core.h> |
| 23 | #include <sound/mpu401.h> | ||
| 23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 24 | #include "oxygen.h" | 25 | #include "oxygen.h" |
| 25 | 26 | ||
| @@ -232,3 +233,23 @@ void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data) | |||
| 232 | device | OXYGEN_2WIRE_DIR_WRITE); | 233 | device | OXYGEN_2WIRE_DIR_WRITE); |
| 233 | } | 234 | } |
| 234 | EXPORT_SYMBOL(oxygen_write_i2c); | 235 | EXPORT_SYMBOL(oxygen_write_i2c); |
| 236 | |||
| 237 | static void _write_uart(struct oxygen *chip, unsigned int port, u8 data) | ||
| 238 | { | ||
| 239 | if (oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_TX_FULL) | ||
| 240 | msleep(1); | ||
| 241 | oxygen_write8(chip, OXYGEN_MPU401 + port, data); | ||
| 242 | } | ||
| 243 | |||
| 244 | void oxygen_reset_uart(struct oxygen *chip) | ||
| 245 | { | ||
| 246 | _write_uart(chip, 1, MPU401_RESET); | ||
| 247 | _write_uart(chip, 1, MPU401_ENTER_UART); | ||
| 248 | } | ||
| 249 | EXPORT_SYMBOL(oxygen_reset_uart); | ||
| 250 | |||
| 251 | void oxygen_write_uart(struct oxygen *chip, u8 data) | ||
| 252 | { | ||
| 253 | _write_uart(chip, 0, data); | ||
| 254 | } | ||
| 255 | EXPORT_SYMBOL(oxygen_write_uart); | ||
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index b1997216b4af..84f481d41efa 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
| @@ -35,6 +35,30 @@ MODULE_DESCRIPTION("C-Media CMI8788 helper library"); | |||
| 35 | MODULE_LICENSE("GPL v2"); | 35 | MODULE_LICENSE("GPL v2"); |
| 36 | 36 | ||
| 37 | 37 | ||
| 38 | static inline int oxygen_uart_input_ready(struct oxygen *chip) | ||
| 39 | { | ||
| 40 | return !(oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_RX_EMPTY); | ||
| 41 | } | ||
| 42 | |||
| 43 | static void oxygen_read_uart(struct oxygen *chip) | ||
| 44 | { | ||
| 45 | if (unlikely(!oxygen_uart_input_ready(chip))) { | ||
| 46 | /* no data, but read it anyway to clear the interrupt */ | ||
| 47 | oxygen_read8(chip, OXYGEN_MPU401); | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | do { | ||
| 51 | u8 data = oxygen_read8(chip, OXYGEN_MPU401); | ||
| 52 | if (data == MPU401_ACK) | ||
| 53 | continue; | ||
| 54 | if (chip->uart_input_count >= ARRAY_SIZE(chip->uart_input)) | ||
| 55 | chip->uart_input_count = 0; | ||
| 56 | chip->uart_input[chip->uart_input_count++] = data; | ||
| 57 | } while (oxygen_uart_input_ready(chip)); | ||
| 58 | if (chip->model.uart_input) | ||
| 59 | chip->model.uart_input(chip); | ||
| 60 | } | ||
| 61 | |||
| 38 | static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) | 62 | static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) |
| 39 | { | 63 | { |
| 40 | struct oxygen *chip = dev_id; | 64 | struct oxygen *chip = dev_id; |
| @@ -87,8 +111,12 @@ static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) | |||
| 87 | if (status & OXYGEN_INT_GPIO) | 111 | if (status & OXYGEN_INT_GPIO) |
| 88 | schedule_work(&chip->gpio_work); | 112 | schedule_work(&chip->gpio_work); |
| 89 | 113 | ||
| 90 | if ((status & OXYGEN_INT_MIDI) && chip->midi) | 114 | if (status & OXYGEN_INT_MIDI) { |
| 91 | snd_mpu401_uart_interrupt(0, chip->midi->private_data); | 115 | if (chip->midi) |
| 116 | snd_mpu401_uart_interrupt(0, chip->midi->private_data); | ||
| 117 | else | ||
| 118 | oxygen_read_uart(chip); | ||
| 119 | } | ||
| 92 | 120 | ||
| 93 | if (status & OXYGEN_INT_AC97) | 121 | if (status & OXYGEN_INT_AC97) |
| 94 | wake_up(&chip->ac97_waitqueue); | 122 | wake_up(&chip->ac97_waitqueue); |
