* 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;}
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);
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);
};
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);
};
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);
}
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--) {
gpio_data &= ~(ice->CommLines.clock | ice->CommLines.data_out);
if (data & (1 << i))
gpio_data |= ice->CommLines.data_out;
write_gpio(ice, gpio_data);
snooze(GPIO_I2C_DELAY);
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--) {
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);
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);
write_gpio_byte(ice, reg_addr & 0x7F, tmp);
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);
data = read_gpio_byte(ice, tmp);
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);
}