oxygen_io.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * C-Media CMI8788 driver - helper functions
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. *
  6. *
  7. * This driver is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License, version 2.
  9. *
  10. * This driver is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this driver; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include <linux/delay.h>
  20. #include <linux/sched.h>
  21. #include <sound/core.h>
  22. #include <asm/io.h>
  23. #include "oxygen.h"
  24. u8 oxygen_read8(struct oxygen *chip, unsigned int reg)
  25. {
  26. return inb(chip->addr + reg);
  27. }
  28. EXPORT_SYMBOL(oxygen_read8);
  29. u16 oxygen_read16(struct oxygen *chip, unsigned int reg)
  30. {
  31. return inw(chip->addr + reg);
  32. }
  33. EXPORT_SYMBOL(oxygen_read16);
  34. u32 oxygen_read32(struct oxygen *chip, unsigned int reg)
  35. {
  36. return inl(chip->addr + reg);
  37. }
  38. EXPORT_SYMBOL(oxygen_read32);
  39. void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value)
  40. {
  41. outb(value, chip->addr + reg);
  42. chip->saved_registers._8[reg] = value;
  43. }
  44. EXPORT_SYMBOL(oxygen_write8);
  45. void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value)
  46. {
  47. outw(value, chip->addr + reg);
  48. chip->saved_registers._16[reg / 2] = cpu_to_le16(value);
  49. }
  50. EXPORT_SYMBOL(oxygen_write16);
  51. void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value)
  52. {
  53. outl(value, chip->addr + reg);
  54. chip->saved_registers._32[reg / 4] = cpu_to_le32(value);
  55. }
  56. EXPORT_SYMBOL(oxygen_write32);
  57. void oxygen_write8_masked(struct oxygen *chip, unsigned int reg,
  58. u8 value, u8 mask)
  59. {
  60. u8 tmp = inb(chip->addr + reg);
  61. tmp &= ~mask;
  62. tmp |= value & mask;
  63. outb(tmp, chip->addr + reg);
  64. chip->saved_registers._8[reg] = tmp;
  65. }
  66. EXPORT_SYMBOL(oxygen_write8_masked);
  67. void oxygen_write16_masked(struct oxygen *chip, unsigned int reg,
  68. u16 value, u16 mask)
  69. {
  70. u16 tmp = inw(chip->addr + reg);
  71. tmp &= ~mask;
  72. tmp |= value & mask;
  73. outw(tmp, chip->addr + reg);
  74. chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp);
  75. }
  76. EXPORT_SYMBOL(oxygen_write16_masked);
  77. void oxygen_write32_masked(struct oxygen *chip, unsigned int reg,
  78. u32 value, u32 mask)
  79. {
  80. u32 tmp = inl(chip->addr + reg);
  81. tmp &= ~mask;
  82. tmp |= value & mask;
  83. outl(tmp, chip->addr + reg);
  84. chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp);
  85. }
  86. EXPORT_SYMBOL(oxygen_write32_masked);
  87. static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask)
  88. {
  89. u8 status = 0;
  90. /*
  91. * Reading the status register also clears the bits, so we have to save
  92. * the read bits in status.
  93. */
  94. wait_event_timeout(chip->ac97_waitqueue,
  95. ({ status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS);
  96. status & mask; }),
  97. msecs_to_jiffies(1) + 1);
  98. /*
  99. * Check even after a timeout because this function should not require
  100. * the AC'97 interrupt to be enabled.
  101. */
  102. status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS);
  103. return status & mask ? 0 : -EIO;
  104. }
  105. /*
  106. * About 10% of AC'97 register reads or writes fail to complete, but even those
  107. * where the controller indicates completion aren't guaranteed to have actually
  108. * happened.
  109. *
  110. * It's hard to assign blame to either the controller or the codec because both
  111. * were made by C-Media ...
  112. */
  113. void oxygen_write_ac97(struct oxygen *chip, unsigned int codec,
  114. unsigned int index, u16 data)
  115. {
  116. unsigned int count, succeeded;
  117. u32 reg;
  118. reg = data;
  119. reg |= index << OXYGEN_AC97_REG_ADDR_SHIFT;
  120. reg |= OXYGEN_AC97_REG_DIR_WRITE;
  121. reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT;
  122. succeeded = 0;
  123. for (count = 5; count > 0; --count) {
  124. udelay(5);
  125. oxygen_write32(chip, OXYGEN_AC97_REGS, reg);
  126. /* require two "completed" writes, just to be sure */
  127. if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 &&
  128. ++succeeded >= 2) {
  129. chip->saved_ac97_registers[codec][index / 2] = data;
  130. return;
  131. }
  132. }
  133. snd_printk(KERN_ERR "AC'97 write timeout\n");
  134. }
  135. EXPORT_SYMBOL(oxygen_write_ac97);
  136. u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec,
  137. unsigned int index)
  138. {
  139. unsigned int count;
  140. unsigned int last_read = UINT_MAX;
  141. u32 reg;
  142. reg = index << OXYGEN_AC97_REG_ADDR_SHIFT;
  143. reg |= OXYGEN_AC97_REG_DIR_READ;
  144. reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT;
  145. for (count = 5; count > 0; --count) {
  146. udelay(5);
  147. oxygen_write32(chip, OXYGEN_AC97_REGS, reg);
  148. udelay(10);
  149. if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_READ_DONE) >= 0) {
  150. u16 value = oxygen_read16(chip, OXYGEN_AC97_REGS);
  151. /* we require two consecutive reads of the same value */
  152. if (value == last_read)
  153. return value;
  154. last_read = value;
  155. /*
  156. * Invert the register value bits to make sure that two
  157. * consecutive unsuccessful reads do not return the same
  158. * value.
  159. */
  160. reg ^= 0xffff;
  161. }
  162. }
  163. snd_printk(KERN_ERR "AC'97 read timeout on codec %u\n", codec);
  164. return 0;
  165. }
  166. EXPORT_SYMBOL(oxygen_read_ac97);
  167. void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
  168. unsigned int index, u16 data, u16 mask)
  169. {
  170. u16 value = oxygen_read_ac97(chip, codec, index);
  171. value &= ~mask;
  172. value |= data & mask;
  173. oxygen_write_ac97(chip, codec, index, value);
  174. }
  175. EXPORT_SYMBOL(oxygen_write_ac97_masked);
  176. void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data)
  177. {
  178. unsigned int count;
  179. /* should not need more than 7.68 us (24 * 320 ns) */
  180. count = 10;
  181. while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY)
  182. && count > 0) {
  183. udelay(1);
  184. --count;
  185. }
  186. oxygen_write8(chip, OXYGEN_SPI_DATA1, data);
  187. oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8);
  188. if (control & OXYGEN_SPI_DATA_LENGTH_3)
  189. oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16);
  190. oxygen_write8(chip, OXYGEN_SPI_CONTROL, control);
  191. }
  192. EXPORT_SYMBOL(oxygen_write_spi);
  193. void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
  194. {
  195. unsigned long timeout;
  196. /* should not need more than about 300 us */
  197. timeout = jiffies + msecs_to_jiffies(1);
  198. do {
  199. if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS)
  200. & OXYGEN_2WIRE_BUSY))
  201. break;
  202. udelay(1);
  203. cond_resched();
  204. } while (time_after_eq(timeout, jiffies));
  205. oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
  206. oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
  207. oxygen_write8(chip, OXYGEN_2WIRE_CONTROL,
  208. device | OXYGEN_2WIRE_DIR_WRITE);
  209. }
  210. EXPORT_SYMBOL(oxygen_write_i2c);