/* * Copyright 2004-2015 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Jérôme Duval, jerome.duval@free.fr * Marcus Overhagen, marcus@overhagen.de * Jérôme Lévêque, leveque.jerome@gmail.com */ #include "io.h" #include "ice1712_reg.h" #include "debug.h" extern pci_module_info *pci; static void ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select, uint8 invert_cs); static void cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select, uint8 invert_cs); static uint8 ak45xx_read_gpio(ice1712 *ice, uint8 reg_addr, uint8 chip_select, uint8 invert_cs) {return 0;} //Unimplemented static uint8 cs84xx_read_gpio(ice1712 *ice, uint8 reg_addr, uint8 chip_select, uint8 invert_cs); static void write_gpio_byte(ice1712 *ice, uint8 data, uint8 gpio_data); static uint8 read_gpio_byte(ice1712 *ice, uint8 gpio_data); //Address are [PCI_10] + xx uint8 read_ccs_uint8(ice1712 *ice, int8 regno) { return pci->read_io_8(ice->Controller + regno); }; uint16 read_ccs_uint16(ice1712 *ice, int8 regno) { return pci->read_io_16(ice->Controller + regno); }; uint32 read_ccs_uint32(ice1712 *ice, int8 regno) { return pci->read_io_32(ice->Controller + regno); }; void write_ccs_uint8(ice1712 *ice, int8 regno, uint8 value) { pci->write_io_8(ice->Controller + regno, value); }; void write_ccs_uint16(ice1712 *ice, int8 regno, uint16 value) { pci->write_io_16(ice->Controller + regno, value); }; void write_ccs_uint32(ice1712 *ice, int8 regno, uint32 value) { pci->write_io_32(ice->Controller + regno, value); }; uint8 read_cci_uint8(ice1712 *ice, int8 index) { write_ccs_uint8(ice, CCS_CCI_INDEX, index); return read_ccs_uint8(ice, CCS_CCI_DATA); }; void write_cci_uint8(ice1712 *ice, int8 index, uint8 value) { write_ccs_uint8(ice, CCS_CCI_INDEX, index); write_ccs_uint8(ice, CCS_CCI_DATA, value); }; //Address are [PCI_14] + xx uint8 read_ddma_uint8(ice1712 *ice, int8 regno) { return pci->read_io_8(ice->DDMA + regno); }; uint16 read_ddma_uint16(ice1712 *ice, int8 regno) { return pci->read_io_16(ice->DDMA + regno); }; uint32 read_ddma_uint32(ice1712 *ice, int8 regno) { return pci->read_io_32(ice->DDMA + regno); }; void write_ddma_uint8(ice1712 *ice, int8 regno, uint8 value) { pci->write_io_8(ice->DDMA + regno, value); }; void write_ddma_uint16(ice1712 *ice, int8 regno, uint16 value) { pci->write_io_16(ice->DDMA + regno, value); }; void write_ddma_uint32(ice1712 *ice, int8 regno, uint32 value) { pci->write_io_32(ice->DDMA + regno, value); }; //Address are [PCI_18] + x uint8 read_ds_uint8(ice1712 *ice, int8 regno) { return pci->read_io_8(ice->DMA_Path + regno); }; uint16 read_ds_uint16(ice1712 *ice, int8 regno) { return pci->read_io_16(ice->DMA_Path + regno); }; uint32 read_ds_uint32(ice1712 *ice, int8 regno) { return pci->read_io_32(ice->DMA_Path + regno); }; void write_ds_uint8(ice1712 *ice, int8 regno, uint8 value) { pci->write_io_8(ice->DMA_Path + regno, value); }; void write_ds_uint16(ice1712 *ice, int8 regno, uint16 value) { pci->write_io_16(ice->DMA_Path + regno, value); }; void write_ds_uint32(ice1712 *ice, int8 regno, uint32 value) { pci->write_io_32(ice->DMA_Path + regno, value); }; uint32 read_ds_channel_data(ice1712 *ice, uint8 channel, ds8_register index) { uint8 ds8_channel_index = channel << 4 | index; write_ds_uint8(ice, DS_CHANNEL_INDEX, ds8_channel_index); return read_ds_uint32(ice, DS_CHANNEL_DATA); } void write_ds_channel_data(ice1712 *ice, uint8 channel, ds8_register index, uint32 data) { uint8 ds8_channel_index = channel << 4 | index; write_ds_uint8(ice, DS_CHANNEL_INDEX, ds8_channel_index); write_ds_uint32(ice, DS_CHANNEL_DATA, data); } //Address are [PCI_1C] + xx uint8 read_mt_uint8(ice1712 *ice, int8 regno) { return pci->read_io_8(ice->Multi_Track + regno); }; uint16 read_mt_uint16(ice1712 *ice, int8 regno) { return pci->read_io_16(ice->Multi_Track + regno); }; uint32 read_mt_uint32(ice1712 *ice, int8 regno) { return pci->read_io_32(ice->Multi_Track + regno); }; void write_mt_uint8(ice1712 *ice, int8 regno, uint8 value) { pci->write_io_8(ice->Multi_Track + regno, value); }; void write_mt_uint16(ice1712 *ice, int8 regno, uint16 value) { pci->write_io_16(ice->Multi_Track + regno, value); }; void write_mt_uint32(ice1712 *ice, int8 regno, uint32 value) { pci->write_io_32(ice->Multi_Track + regno, value); }; /* * return -1 if error else return an uint8 */ int16 read_i2c(ice1712 *ice, uint8 dev_addr, uint8 byte_addr) { if (read_ccs_uint8(ice, CCS_I2C_CONTROL_STATUS) != 0x80) return -1; write_ccs_uint8(ice, CCS_I2C_BYTE_ADDRESS, byte_addr); write_ccs_uint8(ice, CCS_I2C_DEV_ADDRESS, dev_addr); snooze(1000); return read_ccs_uint8(ice, CCS_I2C_DATA); } /* * return -1 if error else return 0 */ int16 write_i2c(ice1712 *ice, uint8 dev_addr, uint8 byte_addr, uint8 value) { if (read_ccs_uint8(ice, CCS_I2C_CONTROL_STATUS) != 0x80) return -1; write_ccs_uint8(ice, CCS_I2C_BYTE_ADDRESS, byte_addr); write_ccs_uint8(ice, CCS_I2C_DEV_ADDRESS, dev_addr); write_ccs_uint8(ice, CCS_I2C_DATA, value); return 0; } int16 read_eeprom(ice1712 *ice, uint8 eeprom[32]) { int i; int16 tmp; for (i = 0; i < 6; i++) { tmp = read_i2c(ice, I2C_EEPROM_ADDRESS_READ, i); if (tmp >= 0) eeprom[i] = (uint8)tmp; else return -1; } if (eeprom[4] > 32) return -1; for (i = 6; i < eeprom[4]; i++) { tmp = read_i2c(ice, I2C_EEPROM_ADDRESS_READ, i); if (tmp >= 0) eeprom[i] = (uint8)tmp; else return -1; } return eeprom[4]; } void codec_write(ice1712 *ice, uint8 reg_addr, uint8 data) { switch (ice->config.product) { case ICE1712_SUBDEVICE_DELTA66: case ICE1712_SUBDEVICE_DELTA44: ak45xx_write_gpio(ice, reg_addr, data, DELTA66_CODEC_CS_0, 0); ak45xx_write_gpio(ice, reg_addr, data, DELTA66_CODEC_CS_1, 0); break; case ICE1712_SUBDEVICE_DELTA410: case ICE1712_SUBDEVICE_AUDIOPHILE_2496: case ICE1712_SUBDEVICE_DELTADIO2496: ak45xx_write_gpio(ice, reg_addr, data, AP2496_CODEC_CS, 0); break; case ICE1712_SUBDEVICE_DELTA1010: case ICE1712_SUBDEVICE_DELTA1010LT: ak45xx_write_gpio(ice, reg_addr, data, DELTA1010LT_CODEC_CS_0, DELTA1010LT_CS_NONE); ak45xx_write_gpio(ice, reg_addr, data, DELTA1010LT_CODEC_CS_1, DELTA1010LT_CS_NONE); ak45xx_write_gpio(ice, reg_addr, data, DELTA1010LT_CODEC_CS_2, DELTA1010LT_CS_NONE); ak45xx_write_gpio(ice, reg_addr, data, DELTA1010LT_CODEC_CS_3, DELTA1010LT_CS_NONE); break; case ICE1712_SUBDEVICE_VX442: ak45xx_write_gpio(ice, reg_addr, data, VX442_CODEC_CS_0, 0); ak45xx_write_gpio(ice, reg_addr, data, VX442_CODEC_CS_1, 0); break; } } void spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data) { switch (ice->config.product) { case ICE1712_SUBDEVICE_DELTA1010: break; case ICE1712_SUBDEVICE_DELTADIO2496: break; case ICE1712_SUBDEVICE_DELTA66: break; case ICE1712_SUBDEVICE_DELTA44: break; case ICE1712_SUBDEVICE_AUDIOPHILE_2496: cs84xx_write_gpio(ice, reg_addr, data, AP2496_SPDIF_CS, 0); break; case ICE1712_SUBDEVICE_DELTA410: break; case ICE1712_SUBDEVICE_DELTA1010LT: cs84xx_write_gpio(ice, reg_addr, data, DELTA1010LT_SPDIF_CS, DELTA1010LT_CS_NONE); break; case ICE1712_SUBDEVICE_VX442: cs84xx_write_gpio(ice, reg_addr, data, VX442_SPDIF_CS, 0); break; } } uint8 codec_read(ice1712 *ice, uint8 reg_addr) { uint8 val = 0xFF; switch (ice->config.product) { case ICE1712_SUBDEVICE_DELTA66: case ICE1712_SUBDEVICE_DELTA44: val = ak45xx_read_gpio(ice, reg_addr, DELTA66_CODEC_CS_0, 0); break; case ICE1712_SUBDEVICE_DELTA410: case ICE1712_SUBDEVICE_AUDIOPHILE_2496: case ICE1712_SUBDEVICE_DELTADIO2496: val = ak45xx_read_gpio(ice, reg_addr, AP2496_CODEC_CS, 0); break; case ICE1712_SUBDEVICE_DELTA1010: case ICE1712_SUBDEVICE_DELTA1010LT: val = ak45xx_read_gpio(ice, reg_addr, DELTA1010LT_CODEC_CS_0, DELTA1010LT_CS_NONE); break; case ICE1712_SUBDEVICE_VX442: val = ak45xx_read_gpio(ice, reg_addr, VX442_CODEC_CS_0, 0); break; } return val; } uint8 spdif_read(ice1712 *ice, uint8 reg_addr) { uint8 val = 0xFF; switch (ice->config.product) { case ICE1712_SUBDEVICE_DELTA1010: break; case ICE1712_SUBDEVICE_DELTADIO2496: break; case ICE1712_SUBDEVICE_DELTA66: break; case ICE1712_SUBDEVICE_DELTA44: break; case ICE1712_SUBDEVICE_AUDIOPHILE_2496: val = cs84xx_read_gpio(ice, reg_addr, AP2496_SPDIF_CS, 0); break; case ICE1712_SUBDEVICE_DELTA410: break; case ICE1712_SUBDEVICE_DELTA1010LT: val = cs84xx_read_gpio(ice, reg_addr, DELTA1010LT_SPDIF_CS, DELTA1010LT_CS_NONE); break; case ICE1712_SUBDEVICE_VX442: val = cs84xx_read_gpio(ice, reg_addr, VX442_SPDIF_CS, 0); break; } return val; } void write_gpio_byte(ice1712 *ice, uint8 data, uint8 gpio_data) { int i; for (i = 7; i >= 0; i--) { // drop clock and data bits gpio_data &= ~(ice->CommLines.clock | ice->CommLines.data_out); // set data bit if needed if (data & (1 << i)) gpio_data |= ice->CommLines.data_out; write_gpio(ice, gpio_data); snooze(GPIO_I2C_DELAY); // raise clock gpio_data |= ice->CommLines.clock; write_gpio(ice, gpio_data); snooze(GPIO_I2C_DELAY); } } uint8 read_gpio_byte(ice1712 *ice, uint8 gpio_data) { int i; uint8 data = 0; for (i = 7; i >= 0; i--) { // drop clock gpio_data &= ~(ice->CommLines.clock); write_gpio(ice, gpio_data); snooze(GPIO_I2C_DELAY); if (read_gpio(ice) &ice->CommLines.data_in) data |= 1 << i; gpio_data |= ice->CommLines.clock; write_gpio(ice, gpio_data); snooze(GPIO_I2C_DELAY); } return data; } void ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select, uint8 invert_cs) { uint8 tmp; tmp = read_gpio(ice); tmp |= ice->CommLines.cs_mask; if (invert_cs != 0) { tmp &= ~invert_cs; tmp |= chip_select; } else { tmp &= ~chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); write_gpio_byte(ice, ((AK45xx_CHIP_ADDRESS & 0x03) << 6) | 0x20 | (reg_addr & 0x1F), tmp); write_gpio_byte(ice, data, tmp); if (invert_cs != 0) { tmp |= invert_cs; } else { tmp |= chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); } void cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select, uint8 invert_cs) { uint8 tmp; tmp = read_gpio(ice); tmp |= ice->CommLines.cs_mask; if (invert_cs != 0) { tmp &= ~invert_cs; tmp |= chip_select; } else { tmp &= ~chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7F) << 1, tmp); write_gpio_byte(ice, reg_addr & 0x7F, tmp); //Do not Increment write_gpio_byte(ice, data, tmp); if (invert_cs != 0) { tmp |= invert_cs; } else { tmp |= chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); } uint8 cs84xx_read_gpio(ice1712 *ice, uint8 reg_addr, uint8 chip_select, uint8 invert_cs) { uint8 tmp, data; tmp = read_gpio(ice); tmp |= ice->CommLines.cs_mask; if (invert_cs != 0) { tmp &= ~invert_cs; tmp |= chip_select; } else { tmp &= ~chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7F) << 1, tmp); //For writing the MAP write_gpio_byte(ice, reg_addr & 0x7F, tmp); //Do not Increment //Deselect the chip if (invert_cs != 0) { tmp |= invert_cs; } else { tmp |= chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); if (invert_cs != 0) { tmp &= ~invert_cs; tmp |= chip_select; } else { tmp &= ~chip_select; } write_gpio(ice, tmp); snooze(GPIO_I2C_DELAY); write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7F) << 1 | 1, tmp); //For writing the MAP data = read_gpio_byte(ice, tmp); //For reading //Deselect the chip if (invert_cs != 0) { tmp |= invert_cs; } else { tmp |= chip_select; } write_gpio(ice, tmp); return data; } /* * return -1 if error else return an uint8 */ uint8 read_gpio(ice1712 *ice) { return read_cci_uint8(ice, CCI_GPIO_DATA); } /* * return -1 if error else return 0 */ void write_gpio(ice1712 *ice, uint8 value) { write_cci_uint8(ice, CCI_GPIO_DATA, value); }