update from Jerome Leveque, with style changes by me (I hope you don't mind).

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35385 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2010-02-01 21:27:42 +00:00
parent c055de4e49
commit 7f2f5e05b0
11 changed files with 953 additions and 540 deletions
@@ -5,7 +5,6 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders media ; UsePrivateHeaders media ;
KernelAddon ice1712 : KernelAddon ice1712 :
debug.c
ice1712.c ice1712.c
io.c io.c
midi.c midi.c
@@ -1,79 +0,0 @@
/*
* ice1712 BeOS/Haiku Driver for VIA - VT1712 Multi Channel Audio Controller
*
* Copyright (c) 2002, Jerome Duval ([email protected])
* Copyright (c) 2003, Marcus Overhagen ([email protected])
* Copyright (c) 2007, Jerome Leveque ([email protected])
*
* All rights reserved
* Distributed under the terms of the MIT license.
*/
#include <KernelExport.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <OS.h>
#include "debug.h"
#include "ice1712.h"
#if DEBUG > 0
static const char * logfile="/boot/home/"DRIVER_NAME".log";
static sem_id loglock;
#endif
void debug_printf(const char *text,...);
void log_printf(const char *text,...);
void log_create(void);
void debug_printf(const char *text,...)
{
char buf[1024];
va_list ap;
va_start(ap,text);
vsprintf(buf,text,ap);
va_end(ap);
dprintf(DRIVER_NAME ": %s",buf);
}
void log_create(void)
{
#if DEBUG > 0
int fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
const char *text = "Driver for " DRIVER_NAME ", Version " VERSION "\n=================\n";
loglock = create_sem(1,"logfile sem");
write(fd,text,strlen(text));
close(fd);
#endif
}
void log_printf(const char *text,...)
{
#if DEBUG > 0
int fd;
char buf[1024];
va_list ap;
va_start(ap,text);
vsprintf(buf,text,ap);
va_end(ap);
dprintf(DRIVER_NAME ": %s",buf);
acquire_sem(loglock);
fd = open(logfile, O_WRONLY | O_APPEND);
if (fd > 0)
{
write(fd, buf, strlen(buf));
close(fd);
}
release_sem(loglock);
#if DEBUG > 1
snooze(150000);
#endif
#endif
}
@@ -8,47 +8,22 @@
* All rights reserved * All rights reserved
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
*/ */
#ifndef _DEBUG_ICE1712_H_
#define _DEBUG_ICE1712_H_
#ifndef _DEBUG_H_ #include <Debug.h>
#define _DEBUG_H_
/* #ifdef TRACE
* PRINT() executes dprintf if DEBUG = 0 (disabled), or expands to LOG() when DEBUG > 0 # undef TRACE
* TRACE() executes dprintf if DEBUG > 0
* LOG() executes dprintf and writes to the logfile if DEBUG > 0
*/
/* DEBUG == 0, no debugging, PRINT writes to syslog
* DEBUG == 1, TRACE & LOG, PRINT
* DEBUG == 2, TRACE & LOG, PRINT with snooze()
*/
#undef DEBUG
#ifndef DEBUG
// #define DEBUG 1
#endif #endif
#undef PRINT_ICE #define TRACE_MULTI_AUDIO
#undef TRACE_ICE #ifdef TRACE_MULTI_AUDIO
#undef ASSERT_ICE # define TRACE(a...) dprintf("\33[34mice1712:\33[0m " a)
#if DEBUG > 0
#define PRINT_ICE(a) log_printf a
// #define TRACE_ICE(a) debug_printf a
#define TRACE_ICE(a) log_printf a
#define LOG_ICE(a) log_printf a
#define LOG_CREATE_ICE() log_create()
#define ASSERT_ICE(a) if (a) {} else LOG_ICE(("ASSERT failed! file = %s, line = %d\n",__FILE__,__LINE__))
void log_create();
void log_printf(const char *text,...);
void debug_printf(const char *text,...);
#else #else
void debug_printf(const char *text,...); # define TRACE(a...) ;
#define PRINT_ICE(a) debug_printf a
#define TRACE_ICE(a) ((void)(0))
#define ASSERT_ICE(a) ((void)(0))
#define LOG_ICE(a) ((void)(0))
#define LOG_CREATE_ICE()
#endif #endif
#endif #define ICE1712_VERY_VERBOSE 0
#endif // _DEBUG_ICE1712_H_
@@ -25,7 +25,6 @@
#include "multi.h" #include "multi.h"
#include "util.h" #include "util.h"
//------------------------------------------------------ //------------------------------------------------------
//------------------------------------------------------ //------------------------------------------------------
@@ -66,6 +65,10 @@ int32 api_version = B_CUR_DRIVER_API_VERSION;
//extern status_t unload_kernel_addon(image_id imid); //extern status_t unload_kernel_addon(image_id imid);
//------------------------------------------------------ //------------------------------------------------------
static status_t load_settings(ice1712 *ice);
static status_t save_settings(ice1712 *ice);
//------------------------------------------------------ //------------------------------------------------------
status_t init_hardware(void) status_t init_hardware(void)
@@ -74,8 +77,7 @@ status_t init_hardware(void)
pci_info info; pci_info info;
memset(cards, 0, sizeof(ice1712) * NUM_CARDS); memset(cards, 0, sizeof(ice1712) * NUM_CARDS);
LOG_CREATE_ICE(); TRACE("===init_hardware()===\n");
TRACE_ICE(("===init_hardware()===\n"));
if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci))
return ENOSYS; return ENOSYS;
@@ -83,7 +85,7 @@ status_t init_hardware(void)
while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) { while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) {
if ((info.vendor_id == ICE1712_VENDOR_ID) && if ((info.vendor_id == ICE1712_VENDOR_ID) &&
(info.device_id == ICE1712_DEVICE_ID)) { (info.device_id == ICE1712_DEVICE_ID)) {
TRACE_ICE(("Found at least 1 card\n")); TRACE("Found at least 1 card\n");
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
return B_OK; return B_OK;
} }
@@ -107,6 +109,7 @@ ice_1712_int(void *arg)
if (reg8 != 0) { if (reg8 != 0) {
ice->buffer++; ice->buffer++;
ice->played_time = system_time(); ice->played_time = system_time();
ice->frames_count += ice->buffer_size;
release_sem_etc(ice->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(ice->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, reg8); write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, reg8);
@@ -153,10 +156,10 @@ ice1712_setup(ice1712 *ice)
result = read_eeprom(ice, ice->eeprom_data); result = read_eeprom(ice, ice->eeprom_data);
/* TRACE_ICE(("EEprom -> ")); /* TRACE("EEprom -> ");
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
TRACE_ICE(("%x, ", eeprom_data[i])); TRACE("%x, ", eeprom_data[i]);
TRACE_ICE(("<- EEprom\n"));*/ TRACE("<- EEprom\n");*/
write_ccs_uint8(ice, CCS_SERR_SHADOW, 0x01); write_ccs_uint8(ice, CCS_SERR_SHADOW, 0x01);
@@ -164,15 +167,15 @@ ice1712_setup(ice1712 *ice)
ice->info.device_id = ice->eeprom_data[E2PROM_MAP_SUBVENDOR_HIGH] << 8 | ice->eeprom_data[E2PROM_MAP_SUBVENDOR_LOW]; ice->info.device_id = ice->eeprom_data[E2PROM_MAP_SUBVENDOR_HIGH] << 8 | ice->eeprom_data[E2PROM_MAP_SUBVENDOR_LOW];
ice->info.vendor_id = ice->eeprom_data[E2PROM_MAP_SUBDEVICE_HIGH] << 8 | ice->eeprom_data[E2PROM_MAP_SUBDEVICE_LOW]; ice->info.vendor_id = ice->eeprom_data[E2PROM_MAP_SUBDEVICE_HIGH] << 8 | ice->eeprom_data[E2PROM_MAP_SUBDEVICE_LOW];
ice->product = ice->info.vendor_id << 16 | ice->info.device_id; ice->product = ice->info.vendor_id << 16 | ice->info.device_id;
TRACE_ICE(("Product ID : 0x%x\n", ice->product)); TRACE("Product ID : 0x%x\n", ice->product);
write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ice->eeprom_data[E2PROM_MAP_GPIOMASK]); write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ice->eeprom_data[E2PROM_MAP_GPIOMASK]);
write_cci_uint8(ice, CCI_GPIO_DATA, ice->eeprom_data[E2PROM_MAP_GPIOSTATE]); write_cci_uint8(ice, CCI_GPIO_DATA, ice->eeprom_data[E2PROM_MAP_GPIOSTATE]);
write_cci_uint8(ice, CCI_GPIO_DIRECTION_CONTROL, ice->eeprom_data[E2PROM_MAP_GPIODIR]); write_cci_uint8(ice, CCI_GPIO_DIRECTION_CONTROL, ice->eeprom_data[E2PROM_MAP_GPIODIR]);
TRACE_ICE(("CCI_GPIO_WRITE_MASK : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIOMASK])); TRACE("CCI_GPIO_WRITE_MASK : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIOMASK]);
TRACE_ICE(("CCI_GPIO_DATA : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIOSTATE])); TRACE("CCI_GPIO_DATA : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIOSTATE]);
TRACE_ICE(("CCI_GPIO_DIRECTION_CONTROL : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIODIR])); TRACE("CCI_GPIO_DIRECTION_CONTROL : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIODIR]);
//Write Configuration in the PCI configuration Register //Write Configuration in the PCI configuration Register
@@ -181,7 +184,7 @@ ice1712_setup(ice1712 *ice)
(pci->write_pci_config)(ice->info.bus, ice->info.device, ice->info.function, 0x62, 1, ice->eeprom_data[E2PROM_MAP_I2S]); (pci->write_pci_config)(ice->info.bus, ice->info.device, ice->info.function, 0x62, 1, ice->eeprom_data[E2PROM_MAP_I2S]);
(pci->write_pci_config)(ice->info.bus, ice->info.device, ice->info.function, 0x63, 1, ice->eeprom_data[E2PROM_MAP_SPDIF]); (pci->write_pci_config)(ice->info.bus, ice->info.device, ice->info.function, 0x63, 1, ice->eeprom_data[E2PROM_MAP_SPDIF]);
TRACE_ICE(("E2PROM_MAP_CONFIG : 0x%x\n", ice->eeprom_data[E2PROM_MAP_CONFIG])); TRACE("E2PROM_MAP_CONFIG : 0x%x\n", ice->eeprom_data[E2PROM_MAP_CONFIG]);
reg8 = ice->eeprom_data[E2PROM_MAP_CONFIG]; reg8 = ice->eeprom_data[E2PROM_MAP_CONFIG];
//Bits signification for E2PROM_MAP_CONFIG Byte //Bits signification for E2PROM_MAP_CONFIG Byte
// //
@@ -199,14 +202,14 @@ ice1712_setup(ice1712 *ice)
reg8 >>= 2; reg8 >>= 2;
if ((reg8 & 0x01) != 0) {//Consumer AC'97 Exist if ((reg8 & 0x01) != 0) {//Consumer AC'97 Exist
TRACE_ICE(("Consumer AC'97 does exist\n")); TRACE("Consumer AC'97 does exist\n");
//For now do nothing //For now do nothing
/* write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x40); /* write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x40);
snooze(10000); snooze(10000);
write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x00); write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x00);
snooze(20000); snooze(20000);
*/ } else { */ } else {
TRACE_ICE(("Consumer AC'97 does NOT exist\n")); TRACE("Consumer AC'97 does NOT exist\n");
} }
reg8 >>= 1; reg8 >>= 1;
ice->nb_MPU401 = (reg8 & 0x1) + 1; ice->nb_MPU401 = (reg8 & 0x1) + 1;
@@ -216,30 +219,37 @@ ice1712_setup(ice1712 *ice)
names[num_names++] = ice->midi_interf[i].name; names[num_names++] = ice->midi_interf[i].name;
} }
TRACE_ICE(("E2PROM_MAP_SPDIF : 0x%x\n", ice->eeprom_data[E2PROM_MAP_SPDIF])); TRACE("E2PROM_MAP_SPDIF : 0x%x\n", ice->eeprom_data[E2PROM_MAP_SPDIF]);
ice->spdif_config = ice->eeprom_data[E2PROM_MAP_SPDIF]; ice->spdif_config = ice->eeprom_data[E2PROM_MAP_SPDIF];
switch (ice->product) switch (ice->product) {
{
case ICE1712_SUBDEVICE_DELTA66 : case ICE1712_SUBDEVICE_DELTA66 :
case ICE1712_SUBDEVICE_DELTA44 : case ICE1712_SUBDEVICE_DELTA44 :
ice->gpio_cs_mask = DELTA66_CLK | DELTA66_DOUT | DELTA66_CODEC_CS_0 | DELTA66_CODEC_CS_1; ice->commlines.clock = DELTA66_CLK;
ice->analog_codec = (codec_info){DELTA66_CLK, 0, DELTA66_DOUT}; ice->commlines.data_in = 0;
ice->commlines.data_out = DELTA66_DOUT;
ice->commlines.cs_mask = DELTA66_CLK | DELTA66_DOUT | DELTA66_CODEC_CS_0 | DELTA66_CODEC_CS_1;
break; break;
case ICE1712_SUBDEVICE_DELTA410 : case ICE1712_SUBDEVICE_DELTA410 :
case ICE1712_SUBDEVICE_AUDIOPHILE_2496 : case ICE1712_SUBDEVICE_AUDIOPHILE_2496 :
case ICE1712_SUBDEVICE_DELTADIO2496 : case ICE1712_SUBDEVICE_DELTADIO2496 :
ice->gpio_cs_mask = AP2496_CLK | AP2496_DIN | AP2496_DOUT | AP2496_SPDIF_CS | AP2496_CODEC_CS; ice->commlines.clock = AP2496_CLK;
ice->analog_codec = (codec_info){AP2496_CLK, AP2496_DIN, AP2496_DOUT}; ice->commlines.data_in = AP2496_DIN;
ice->commlines.data_out = AP2496_DOUT;
ice->commlines.cs_mask = AP2496_CLK | AP2496_DIN | AP2496_DOUT | AP2496_SPDIF_CS | AP2496_CODEC_CS;
break; break;
case ICE1712_SUBDEVICE_DELTA1010 : case ICE1712_SUBDEVICE_DELTA1010 :
case ICE1712_SUBDEVICE_DELTA1010LT : case ICE1712_SUBDEVICE_DELTA1010LT :
ice->gpio_cs_mask = DELTA1010LT_CLK | DELTA1010LT_DIN | DELTA1010LT_DOUT | DELTA1010LT_CS_NONE; ice->commlines.clock = DELTA1010LT_CLK;
ice->analog_codec = (codec_info){DELTA1010LT_CLK, DELTA1010LT_DIN, DELTA1010LT_DOUT}; ice->commlines.data_in = DELTA1010LT_DIN;
ice->commlines.data_out = DELTA1010LT_DOUT;
ice->commlines.cs_mask = DELTA1010LT_CLK | DELTA1010LT_DIN | DELTA1010LT_DOUT | DELTA1010LT_CS_NONE;
break; break;
case ICE1712_SUBDEVICE_VX442 : case ICE1712_SUBDEVICE_VX442 :
ice->gpio_cs_mask = VX442_SPDIF_CS | VX442_CODEC_CS_0 | VX442_CODEC_CS_1; ice->commlines.clock = VX442_CLK;
ice->analog_codec = (codec_info){VX442_CLK, VX442_DIN, VX442_DOUT}; ice->commlines.data_in = VX442_DIN;
ice->commlines.data_out = VX442_DOUT;
ice->commlines.cs_mask = VX442_SPDIF_CS | VX442_CODEC_CS_0 | VX442_CODEC_CS_1;
break; break;
} }
@@ -252,12 +262,12 @@ ice1712_setup(ice1712 *ice)
return ice->buffer_ready_sem; return ice->buffer_ready_sem;
} }
// TRACE_ICE(("installing interrupt : %0x\n", ice->irq)); // TRACE("installing interrupt : %0x\n", ice->irq);
status = install_io_interrupt_handler(ice->irq, ice_1712_int, ice, 0); status = install_io_interrupt_handler(ice->irq, ice_1712_int, ice, 0);
if (status == B_OK) if (status == B_OK)
TRACE_ICE(("Install Interrupt Handler == B_OK\n")); TRACE("Install Interrupt Handler == B_OK\n");
else else
TRACE_ICE(("Install Interrupt Handler != B_OK\n")); TRACE("Install Interrupt Handler != B_OK\n");
ice->mem_id_pb = alloc_mem(&ice->phys_addr_pb, &ice->log_addr_pb, ice->mem_id_pb = alloc_mem(&ice->phys_addr_pb, &ice->log_addr_pb,
PLAYBACK_BUFFER_TOTAL_SIZE, PLAYBACK_BUFFER_TOTAL_SIZE,
@@ -281,10 +291,12 @@ ice1712_setup(ice1712 *ice)
memset(ice->log_addr_pb, 0, PLAYBACK_BUFFER_TOTAL_SIZE); memset(ice->log_addr_pb, 0, PLAYBACK_BUFFER_TOTAL_SIZE);
memset(ice->log_addr_rec, 0, RECORD_BUFFER_TOTAL_SIZE); memset(ice->log_addr_rec, 0, RECORD_BUFFER_TOTAL_SIZE);
load_settings(ice);
ice->sampling_rate = 0x08; ice->sampling_rate = 0x08;
ice->buffer = 0; ice->buffer = 0;
ice->output_buffer_size = MAX_BUFFER_FRAMES; ice->frames_count = 0;
ice->input_buffer_size = MAX_BUFFER_FRAMES; ice->buffer_size = MAX_BUFFER_FRAMES;
ice->total_output_channels = ice->nb_DAC; ice->total_output_channels = ice->nb_DAC;
if (ice->spdif_config & NO_IN_YES_OUT) if (ice->spdif_config & NO_IN_YES_OUT)
@@ -295,9 +307,16 @@ ice1712_setup(ice1712 *ice)
ice->total_input_channels += 2; ice->total_input_channels += 2;
//Write bits in the GPIO //Write bits in the GPIO
write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ~(ice->gpio_cs_mask)); write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ~(ice->commlines.cs_mask));
//Deselect CS //Deselect CS
write_cci_uint8(ice, CCI_GPIO_DATA, ice->gpio_cs_mask); write_cci_uint8(ice, CCI_GPIO_DATA, ice->commlines.cs_mask);
//Set the rampe volume to a faster one
write_mt_uint16(ice, MT_VOLUME_CONTROL_RATE, 0x01);
//Digital Mixer To DAC 0 and SPDIF Out
// write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0x0101);
// write_mt_uint16(ice, MT_ROUTING_CONTROL_SPDOUT, 0x0005);
//Just to route all input to all output //Just to route all input to all output
// write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0xAAAA); // write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0xAAAA);
@@ -318,15 +337,15 @@ ice1712_setup(ice1712 *ice)
write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x41); write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x41);
reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_MASK); reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_MASK);
TRACE_ICE(("-----CCS----- = %x\n", reg8)); TRACE("-----CCS----- = %x\n", reg8);
write_ccs_uint8(ice, CCS_INTERRUPT_MASK, 0x6F); write_ccs_uint8(ice, CCS_INTERRUPT_MASK, 0x6F);
/* reg16 = read_ds_uint16(ice, DS_DMA_INT_MASK); /* reg16 = read_ds_uint16(ice, DS_DMA_INT_MASK);
TRACE_ICE(("-----DS_DMA----- = %x\n", reg16)); TRACE("-----DS_DMA----- = %x\n", reg16);
write_ds_uint16(ice, DS_DMA_INT_MASK, 0x0000); write_ds_uint16(ice, DS_DMA_INT_MASK, 0x0000);
*/ */
reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS); reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS);
TRACE_ICE(("-----MT_DMA----- = %x\n", reg8)); TRACE("-----MT_DMA----- = %x\n", reg8);
write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, 0x00); write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, 0x00);
return B_OK; return B_OK;
@@ -339,7 +358,7 @@ init_driver(void)
int i = 0; int i = 0;
num_cards = 0; num_cards = 0;
TRACE_ICE(("===init_driver()===\n")); TRACE("===init_driver()===\n");
if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci))
return ENOSYS; return ENOSYS;
@@ -354,13 +373,13 @@ init_driver(void)
if ((cards[num_cards].info.vendor_id == ICE1712_VENDOR_ID) if ((cards[num_cards].info.vendor_id == ICE1712_VENDOR_ID)
&& (cards[num_cards].info.device_id == ICE1712_DEVICE_ID)) { && (cards[num_cards].info.device_id == ICE1712_DEVICE_ID)) {
if (num_cards == NUM_CARDS) { if (num_cards == NUM_CARDS) {
TRACE_ICE(("Too many ice1712 cards installed!\n")); TRACE("Too many ice1712 cards installed!\n");
break; break;
} }
if (ice1712_setup(&cards[num_cards]) != B_OK) { if (ice1712_setup(&cards[num_cards]) != B_OK) {
//Vendor_ID and Device_ID has been modified //Vendor_ID and Device_ID has been modified
TRACE_ICE(("Setup of ice1712 %d failed\n", num_cards + 1)); TRACE("Setup of ice1712 %d failed\n", (int)(num_cards + 1));
} else { } else {
num_cards++; num_cards++;
} }
@@ -368,7 +387,7 @@ init_driver(void)
i++; i++;
} }
TRACE_ICE(("Number of succesfully initialised card : %d\n", num_cards)); TRACE("Number of succesfully initialised card : %d\n", (int)num_cards);
if (num_cards == 0) { if (num_cards == 0) {
put_module(B_PCI_MODULE_NAME); put_module(B_PCI_MODULE_NAME);
@@ -388,9 +407,9 @@ ice_1712_shutdown(ice1712 *ice)
result = remove_io_interrupt_handler(ice->irq, ice_1712_int, ice); result = remove_io_interrupt_handler(ice->irq, ice_1712_int, ice);
if (result == B_OK) if (result == B_OK)
TRACE_ICE(("remove Interrupt result == B_OK\n")); TRACE("remove Interrupt result == B_OK\n");
else else
TRACE_ICE(("remove Interrupt result != B_OK\n")); TRACE("remove Interrupt result != B_OK\n");
if (ice->mem_id_pb != B_ERROR) if (ice->mem_id_pb != B_ERROR)
delete_area(ice->mem_id_pb); delete_area(ice->mem_id_pb);
@@ -399,6 +418,8 @@ ice_1712_shutdown(ice1712 *ice)
delete_area(ice->mem_id_rec); delete_area(ice->mem_id_rec);
codec_write(ice, AK45xx_RESET_REGISTER, 0x00); codec_write(ice, AK45xx_RESET_REGISTER, 0x00);
save_settings(ice);
} }
@@ -407,7 +428,7 @@ uninit_driver(void)
{ {
int ix, cnt = num_cards; int ix, cnt = num_cards;
TRACE_ICE(("===uninit_driver()===\n")); TRACE("===uninit_driver()===\n");
num_cards = 0; num_cards = 0;
@@ -425,10 +446,10 @@ const char **
publish_devices(void) publish_devices(void)
{ {
int ix = 0; int ix = 0;
TRACE_ICE(("===publish_devices()===\n")); TRACE("===publish_devices()===\n");
for (ix=0; names[ix]; ix++) { for (ix=0; names[ix]; ix++) {
TRACE_ICE(("publish %s\n", names[ix])); TRACE("publish %s\n", names[ix]);
} }
return (const char **)names; return (const char **)names;
} }
@@ -439,7 +460,7 @@ ice_1712_open(const char *name, uint32 flags, void **cookie)
{ {
int ix; int ix;
ice1712 *card = NULL; ice1712 *card = NULL;
TRACE_ICE(("===open()===\n")); TRACE("===open()===\n");
for (ix=0; ix<num_cards; ix++) { for (ix=0; ix<num_cards; ix++) {
if (!strcmp(cards[ix].name, name)) { if (!strcmp(cards[ix].name, name)) {
@@ -448,9 +469,9 @@ ice_1712_open(const char *name, uint32 flags, void **cookie)
} }
if (card == NULL) { if (card == NULL) {
TRACE_ICE(("open() card not found %s\n", name)); TRACE("open() card not found %s\n", name);
for (ix=0; ix<num_cards; ix++) { for (ix=0; ix<num_cards; ix++) {
TRACE_ICE(("open() card available %s\n", cards[ix].name)); TRACE("open() card available %s\n", cards[ix].name);
} }
return B_ERROR; return B_ERROR;
} }
@@ -462,7 +483,7 @@ ice_1712_open(const char *name, uint32 flags, void **cookie)
static status_t static status_t
ice_1712_close(void *cookie) ice_1712_close(void *cookie)
{ {
TRACE_ICE(("===close()===\n")); TRACE("===close()===\n");
return B_OK; return B_OK;
} }
@@ -470,7 +491,7 @@ ice_1712_close(void *cookie)
static status_t static status_t
ice_1712_free(void *cookie) ice_1712_free(void *cookie)
{ {
TRACE_ICE(("===free()===\n")); TRACE("===free()===\n");
return B_OK; return B_OK;
} }
@@ -478,89 +499,88 @@ ice_1712_free(void *cookie)
static status_t static status_t
ice_1712_control(void *cookie, uint32 op, void *arg, size_t len) ice_1712_control(void *cookie, uint32 op, void *arg, size_t len)
{ {
switch (op) switch (op) {
{
case B_MULTI_GET_DESCRIPTION : case B_MULTI_GET_DESCRIPTION :
TRACE_ICE(("B_MULTI_GET_DESCRIPTION\n")); TRACE("B_MULTI_GET_DESCRIPTION\n");
return ice1712_get_description((ice1712 *)cookie, (multi_description*)arg); return ice1712_get_description((ice1712 *)cookie, (multi_description*)arg);
case B_MULTI_GET_EVENT_INFO : case B_MULTI_GET_EVENT_INFO :
TRACE_ICE(("B_MULTI_GET_EVENT_INFO\n")); TRACE("B_MULTI_GET_EVENT_INFO\n");
return B_ERROR; return B_ERROR;
case B_MULTI_SET_EVENT_INFO : case B_MULTI_SET_EVENT_INFO :
TRACE_ICE(("B_MULTI_SET_EVENT_INFO\n")); TRACE("B_MULTI_SET_EVENT_INFO\n");
return B_ERROR; return B_ERROR;
case B_MULTI_GET_EVENT : case B_MULTI_GET_EVENT :
TRACE_ICE(("B_MULTI_GET_EVENT\n")); TRACE("B_MULTI_GET_EVENT\n");
return B_ERROR; return B_ERROR;
case B_MULTI_GET_ENABLED_CHANNELS : case B_MULTI_GET_ENABLED_CHANNELS :
TRACE_ICE(("B_MULTI_GET_ENABLED_CHANNELS\n")); TRACE("B_MULTI_GET_ENABLED_CHANNELS\n");
return ice1712_get_enabled_channels((ice1712*)cookie, (multi_channel_enable*)arg); return ice1712_get_enabled_channels((ice1712*)cookie, (multi_channel_enable*)arg);
case B_MULTI_SET_ENABLED_CHANNELS : case B_MULTI_SET_ENABLED_CHANNELS :
TRACE_ICE(("B_MULTI_SET_ENABLED_CHANNELS\n")); TRACE("B_MULTI_SET_ENABLED_CHANNELS\n");
return ice1712_set_enabled_channels((ice1712*)cookie, (multi_channel_enable*)arg); return ice1712_set_enabled_channels((ice1712*)cookie, (multi_channel_enable*)arg);
case B_MULTI_GET_GLOBAL_FORMAT : case B_MULTI_GET_GLOBAL_FORMAT :
TRACE_ICE(("B_MULTI_GET_GLOBAL_FORMAT\n")); TRACE("B_MULTI_GET_GLOBAL_FORMAT\n");
return ice1712_get_global_format((ice1712*)cookie, (multi_format_info *)arg); return ice1712_get_global_format((ice1712*)cookie, (multi_format_info *)arg);
case B_MULTI_SET_GLOBAL_FORMAT : case B_MULTI_SET_GLOBAL_FORMAT :
TRACE_ICE(("B_MULTI_SET_GLOBAL_FORMAT\n")); TRACE("B_MULTI_SET_GLOBAL_FORMAT\n");
return ice1712_set_global_format((ice1712*)cookie, (multi_format_info *)arg); return ice1712_set_global_format((ice1712*)cookie, (multi_format_info *)arg);
case B_MULTI_GET_CHANNEL_FORMATS : case B_MULTI_GET_CHANNEL_FORMATS :
TRACE_ICE(("B_MULTI_GET_CHANNEL_FORMATS\n")); TRACE("B_MULTI_GET_CHANNEL_FORMATS\n");
return B_ERROR; return B_ERROR;
case B_MULTI_SET_CHANNEL_FORMATS : case B_MULTI_SET_CHANNEL_FORMATS :
TRACE_ICE(("B_MULTI_SET_CHANNEL_FORMATS\n")); TRACE("B_MULTI_SET_CHANNEL_FORMATS\n");
return B_ERROR; return B_ERROR;
case B_MULTI_GET_MIX : case B_MULTI_GET_MIX :
TRACE_ICE(("B_MULTI_GET_MIX\n")); TRACE("B_MULTI_GET_MIX\n");
return ice1712_get_mix((ice1712*)cookie, (multi_mix_value_info *)arg); return ice1712_get_mix((ice1712*)cookie, (multi_mix_value_info *)arg);
case B_MULTI_SET_MIX : case B_MULTI_SET_MIX :
TRACE_ICE(("B_MULTI_SET_MIX\n")); TRACE("B_MULTI_SET_MIX\n");
return ice1712_set_mix((ice1712*)cookie, (multi_mix_value_info *)arg); return ice1712_set_mix((ice1712*)cookie, (multi_mix_value_info *)arg);
case B_MULTI_LIST_MIX_CHANNELS : case B_MULTI_LIST_MIX_CHANNELS :
TRACE_ICE(("B_MULTI_LIST_MIX_CHANNELS\n")); TRACE("B_MULTI_LIST_MIX_CHANNELS\n");
return ice1712_list_mix_channels((ice1712*)cookie, (multi_mix_channel_info *)arg); return ice1712_list_mix_channels((ice1712*)cookie, (multi_mix_channel_info *)arg);
case B_MULTI_LIST_MIX_CONTROLS : case B_MULTI_LIST_MIX_CONTROLS :
TRACE_ICE(("B_MULTI_LIST_MIX_CONTROLS\n")); TRACE("B_MULTI_LIST_MIX_CONTROLS\n");
return ice1712_list_mix_controls((ice1712*)cookie, (multi_mix_control_info *)arg); return ice1712_list_mix_controls((ice1712*)cookie, (multi_mix_control_info *)arg);
case B_MULTI_LIST_MIX_CONNECTIONS : case B_MULTI_LIST_MIX_CONNECTIONS :
TRACE_ICE(("B_MULTI_LIST_MIX_CONNECTIONS\n")); TRACE("B_MULTI_LIST_MIX_CONNECTIONS\n");
return ice1712_list_mix_connections((ice1712*)cookie, (multi_mix_connection_info *)arg); return ice1712_list_mix_connections((ice1712*)cookie, (multi_mix_connection_info *)arg);
case B_MULTI_GET_BUFFERS : case B_MULTI_GET_BUFFERS :
TRACE_ICE(("B_MULTI_GET_BUFFERS\n")); TRACE("B_MULTI_GET_BUFFERS\n");
return ice1712_get_buffers((ice1712*)cookie, (multi_buffer_list*)arg); return ice1712_get_buffers((ice1712*)cookie, (multi_buffer_list*)arg);
case B_MULTI_SET_BUFFERS : case B_MULTI_SET_BUFFERS :
TRACE_ICE(("B_MULTI_SET_BUFFERS\n")); TRACE("B_MULTI_SET_BUFFERS\n");
return B_ERROR; return B_ERROR;
case B_MULTI_SET_START_TIME : case B_MULTI_SET_START_TIME :
TRACE_ICE(("B_MULTI_SET_START_TIME\n")); TRACE("B_MULTI_SET_START_TIME\n");
return B_ERROR; return B_ERROR;
case B_MULTI_BUFFER_EXCHANGE : case B_MULTI_BUFFER_EXCHANGE :
// TRACE_ICE(("B_MULTI_BUFFER_EXCHANGE\n")); // TRACE("B_MULTI_BUFFER_EXCHANGE\n");
return ice1712_buffer_exchange((ice1712*)cookie, (multi_buffer_info *)arg); return ice1712_buffer_exchange((ice1712*)cookie, (multi_buffer_info *)arg);
case B_MULTI_BUFFER_FORCE_STOP : case B_MULTI_BUFFER_FORCE_STOP :
TRACE_ICE(("B_MULTI_BUFFER_FORCE_STOP\n")); TRACE("B_MULTI_BUFFER_FORCE_STOP\n");
return ice1712_buffer_force_stop((ice1712*)cookie); return ice1712_buffer_force_stop((ice1712*)cookie);
case B_MULTI_LIST_EXTENSIONS : case B_MULTI_LIST_EXTENSIONS :
TRACE_ICE(("B_MULTI_LIST_EXTENSIONS\n")); TRACE("B_MULTI_LIST_EXTENSIONS\n");
return B_ERROR; return B_ERROR;
case B_MULTI_GET_EXTENSION : case B_MULTI_GET_EXTENSION :
TRACE_ICE(("B_MULTI_GET_EXTENSION\n")); TRACE("B_MULTI_GET_EXTENSION\n");
return B_ERROR; return B_ERROR;
case B_MULTI_SET_EXTENSION : case B_MULTI_SET_EXTENSION :
TRACE_ICE(("B_MULTI_SET_EXTENSION\n")); TRACE("B_MULTI_SET_EXTENSION\n");
return B_ERROR; return B_ERROR;
case B_MULTI_LIST_MODES : case B_MULTI_LIST_MODES :
TRACE_ICE(("B_MULTI_LIST_MODES\n")); TRACE("B_MULTI_LIST_MODES\n");
return B_ERROR; return B_ERROR;
case B_MULTI_GET_MODE : case B_MULTI_GET_MODE :
TRACE_ICE(("B_MULTI_GET_MODE\n")); TRACE("B_MULTI_GET_MODE\n");
return B_ERROR; return B_ERROR;
case B_MULTI_SET_MODE : case B_MULTI_SET_MODE :
TRACE_ICE(("B_MULTI_SET_MODE\n")); TRACE("B_MULTI_SET_MODE\n");
return B_ERROR; return B_ERROR;
default : default :
TRACE_ICE(("ERROR: unknown multi_control %#x\n", op)); TRACE("ERROR: unknown multi_control %#x\n", (int)op);
return B_ERROR; return B_ERROR;
} }
} }
@@ -569,7 +589,7 @@ ice_1712_control(void *cookie, uint32 op, void *arg, size_t len)
static status_t static status_t
ice_1712_read(void *cookie, off_t position, void *buf, size_t *num_bytes) ice_1712_read(void *cookie, off_t position, void *buf, size_t *num_bytes)
{ {
TRACE_ICE(("===read()===\n")); TRACE("===read()===\n");
*num_bytes = 0; *num_bytes = 0;
return B_IO_ERROR; return B_IO_ERROR;
} }
@@ -578,13 +598,13 @@ ice_1712_read(void *cookie, off_t position, void *buf, size_t *num_bytes)
static status_t static status_t
ice_1712_write(void *cookie, off_t position, const void *buffer, size_t *num_bytes) ice_1712_write(void *cookie, off_t position, const void *buffer, size_t *num_bytes)
{ {
TRACE_ICE(("===write()===\n")); TRACE("===write()===\n");
*num_bytes = 0; *num_bytes = 0;
return B_IO_ERROR; return B_IO_ERROR;
} }
device_hooks ice_1712_hooks = device_hooks ice1712_hooks =
{ {
ice_1712_open, ice_1712_open,
ice_1712_close, ice_1712_close,
@@ -598,24 +618,131 @@ device_hooks ice_1712_hooks =
NULL NULL
}; };
/*
device_hooks ice1712Midi_hooks =
{
ice1712Midi_open,
ice1712Midi_close,
ice1712Midi_free,
ice1712Midi_control,
ice1712Midi_read,
ice1712Midi_write,
NULL,
NULL,
NULL,
NULL
};
*/
device_hooks * device_hooks *
find_device(const char * name) find_device(const char * name)
{ {
int ix; int ix;
PRINT_ICE(("ice1712: find_device(%s)\n", name)); TRACE("ice1712: find_device(%s)\n", name);
for (ix=0; ix<num_cards; ix++) { for (ix=0; ix<num_cards; ix++) {
/*#if MIDI
if (!strcmp(cards[ix].midi.name, name)) { /* if (!strcmp(cards[ix].midi.name, name)) {
return &midi_hooks; return &midi_hooks;
} }*/
#endif
*/ if (!strcmp(cards[ix].name, name)) { if (!strcmp(cards[ix].name, name)) {
return &ice_1712_hooks; return &ice1712_hooks;
} }
} }
PRINT_ICE(("ice1712: find_device(%s) failed\n", name)); TRACE("ice1712: find_device(%s) failed\n", name);
return NULL; return NULL;
} }
//-----------------------------------------------------------------------------
status_t
load_settings(ice1712 *ice)
{
int i;
for (i = 0; i < 10; i++) {
ice->settings.playback[i].volume = -10.5;
ice->settings.playback[i].mute = false;
}
for (i = 0; i < 10; i++) {
ice->settings.record[i].volume = -10.5;
ice->settings.record[i].mute = false;
}
ice->settings.clock = 0;
ice->settings.sample_rate = 3;
ice->settings.buffer_size = 3;
ice->settings.debug_mode = 0;
//S/PDIF Settings
ice->settings.out_format = 0;
ice->settings.emphasis = 0;
ice->settings.copy_mode = 0;
return apply_settings(ice);
}
status_t
save_settings(ice1712 *ice)
{
return B_OK;
}
#define ICE1712_MUTE_VALUE (0x7F)
status_t
apply_settings(ice1712 *card)
{
int i;
uint16 val;
for (i = 0; i < 10; i++) {
//Select the channel
write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX, i);
if (card->settings.playback[i].mute) {
val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
} else {
unsigned char volume = card->settings.playback[i].volume / -1.5;
if (i & 1) {//a right channel
val = ICE1712_MUTE_VALUE << 0; //Mute left volume
val |= volume << 8;
} else {//a left channel
val = ICE1712_MUTE_VALUE << 8; //Mute right volume
val |= volume << 0;
}
}
write_mt_uint16(card, MT_LR_VOLUME_CONTROL, val);
if (ICE1712_VERY_VERBOSE)
TRACE("Apply Settings %d : 0x%x\n", i, val);
}
for (i = 0; i < 10; i++) {
//Select the channel
write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX, i + 10);
if (card->settings.record[i].mute == true) {
val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8);
} else {
unsigned char volume = card->settings.record[i].volume / -1.5;
if (i & 1) {//a right channel
val = ICE1712_MUTE_VALUE << 0; //Mute left volume
val |= volume << 8;
} else {//a left channel
val = ICE1712_MUTE_VALUE << 8; //Mute right volume
val |= volume << 0;
}
}
write_mt_uint16(card, MT_LR_VOLUME_CONTROL, val);
}
return B_OK;
}
@@ -13,15 +13,13 @@
#define _ICE1712_H_ #define _ICE1712_H_
#include <PCI.h> #include <PCI.h>
#include "hmulti_audio.h"
#define DRIVER_NAME "ice1712" #define DRIVER_NAME "ice1712"
#define VERSION "0.3" #define VERSION "0.4"
#define ICE1712_VENDOR_ID 0x1412 #define ICE1712_VENDOR_ID 0x1412
#define ICE1712_DEVICE_ID 0x1712 #define ICE1712_DEVICE_ID 0x1712
typedef enum product_t { typedef enum product_t {
ICE1712_SUBDEVICE_DELTA1010 = 0x121430d6, ICE1712_SUBDEVICE_DELTA1010 = 0x121430d6,
ICE1712_SUBDEVICE_DELTADIO2496 = 0x121431d6, ICE1712_SUBDEVICE_DELTADIO2496 = 0x121431d6,
@@ -38,7 +36,7 @@ typedef enum product_t {
#define MAX_DAC 10 #define MAX_DAC 10
#define SWAPPING_BUFFERS 2 #define SWAPPING_BUFFERS 2
#define SAMPLE_SIZE 4 #define SAMPLE_SIZE 4
#define MIN_BUFFER_FRAMES 64 #define MIN_BUFFER_FRAMES 256
#define MAX_BUFFER_FRAMES 2048 #define MAX_BUFFER_FRAMES 2048
#define PLAYBACK_BUFFER_SIZE (MAX_BUFFER_FRAMES * MAX_DAC * SAMPLE_SIZE) #define PLAYBACK_BUFFER_SIZE (MAX_BUFFER_FRAMES * MAX_DAC * SAMPLE_SIZE)
@@ -52,6 +50,7 @@ typedef enum product_t {
#define MIXER_OUT_LEFT 10 #define MIXER_OUT_LEFT 10
#define MIXER_OUT_RIGHT 11 #define MIXER_OUT_RIGHT 11
typedef enum { typedef enum {
NO_IN_NO_OUT = 0, NO_IN_NO_OUT = 0,
NO_IN_YES_OUT = 1, NO_IN_YES_OUT = 1,
@@ -59,6 +58,7 @@ typedef enum {
YES_IN_YES_OUT = 3, YES_IN_YES_OUT = 3,
} _spdif_config_ ; } _spdif_config_ ;
typedef struct _midi_dev { typedef struct _midi_dev {
struct _ice1712_ *card; struct _ice1712_ *card;
void *driver; void *driver;
@@ -67,15 +67,45 @@ typedef struct _midi_dev {
char name[64]; char name[64];
} midi_dev; } midi_dev;
typedef struct codec_info
typedef struct _codec_commlines
{ {
uint8 clock; uint8 clock;
uint8 data_in; uint8 data_in;
uint8 data_out; uint8 data_out;
uint8 reserved[5]; uint8 cs_mask; //a Mask for removing all Chip select
} codec_info; uint8 reserved[4];
} codec_comm_lines;
typedef struct _ice1712_
typedef struct channel_volume
{
float volume;
bool mute;
} channel_volume;
typedef struct ice1712_settings
{
channel_volume playback[10]; //Can't change the volume of the digital mixer
channel_volume record[10];
//General Settings
uint8 clock; //an index
uint8 sample_rate; //an index
uint8 buffer_size; //an index
uint8 debug_mode; //an index for debugging
//S/PDif Settings
uint8 out_format; //an index
uint8 emphasis; //an index
uint8 copy_mode; //an index
uint8 reserved[32];
} ice1712_settings;
typedef struct ice1712
{ {
uint32 irq; uint32 irq;
pci_info info; pci_info info;
@@ -96,25 +126,23 @@ typedef struct _ice1712_
int8 nb_MPU401; int8 nb_MPU401;
product_t product; product_t product;
uint8 gpio_cs_mask; //a Mask for removing all Chip select
//We hope all manufacturer will not use different codec on the same card //We hope all manufacturers will use same communication lines for speaking with codec
codec_info analog_codec; codec_comm_lines commlines;
codec_info digital_codec;
uint32 buffer; uint32 buffer;
bigtime_t played_time; bigtime_t played_time;
uint32 buffer_size; //in frames
uint32 frames_count;
//Output //Output
area_id mem_id_pb; area_id mem_id_pb;
void *phys_addr_pb, *log_addr_pb; void *phys_addr_pb, *log_addr_pb;
uint32 output_buffer_size; //in frames
uint8 total_output_channels; uint8 total_output_channels;
//Input //Input
area_id mem_id_rec; area_id mem_id_rec;
void *phys_addr_rec, *log_addr_rec; void *phys_addr_rec, *log_addr_rec;
uint32 input_buffer_size; //in frames
uint8 total_input_channels; uint8 total_input_channels;
sem_id buffer_ready_sem; sem_id buffer_ready_sem;
@@ -122,8 +150,14 @@ typedef struct _ice1712_
uint8 sampling_rate; //in the format of the register uint8 sampling_rate; //in the format of the register
uint32 lock_source; uint32 lock_source;
ice1712_settings settings;
} ice1712; } ice1712;
status_t apply_settings(ice1712 *card);
//For midi.c
extern int32 num_cards; extern int32 num_cards;
extern ice1712 cards[NUM_CARDS]; extern ice1712 cards[NUM_CARDS];
@@ -164,27 +198,15 @@ extern ice1712 cards[NUM_CARDS];
#define VX442_CODEC_CS_0 0x20 // ?? #0 #define VX442_CODEC_CS_0 0x20 // ?? #0
#define VX442_CODEC_CS_1 0x40 // ?? #1 #define VX442_CODEC_CS_1 0x40 // ?? #1
#define AK45xx_BITS_TO_WRITE 16 #define GPIO_I2C_DELAY 5 //Clock Delay for writing I2C data throw GPIO
//2 - Chip Address (10b)
//1 - R/W (Always 1 for Writing)
//5 - Register Address
//8 - Data
//Register definition for the AK45xx codec (xx = 24 or 28) //Register definition for the AK45xx codec (xx = 24 or 28)
#define AK45xx_DELAY 100 //Clock Delay
#define AK45xx_CHIP_ADDRESS 0x02 //Chip address of the codec #define AK45xx_CHIP_ADDRESS 0x02 //Chip address of the codec
#define AK45xx_RESET_REGISTER 0x01 #define AK45xx_RESET_REGISTER 0x01
#define AK45xx_CLOCK_FORMAT_REGISTER 0x02 #define AK45xx_CLOCK_FORMAT_REGISTER 0x02
//Other register are not defined cause they are not used, I'm very lazy... //Other register are not defined cause they are not used, I'm very lazy...
#define CS84xx_BITS_TO_WRITE 24
//7 - Chip Address (0010000b)
//1 - R/W (1 for Reading)
//8 - Register MAP
//8 - Data
//Register definition for the CS84xx codec (xx = 27) //Register definition for the CS84xx codec (xx = 27)
#define CS84xx_DELAY 100 //Clock Delay
#define CS84xx_CHIP_ADDRESS 0x10 //Chip address of the codec #define CS84xx_CHIP_ADDRESS 0x10 //Chip address of the codec
#define CS84xx_CONTROL_1_PORT_REG 0x01 #define CS84xx_CONTROL_1_PORT_REG 0x01
#define CS84xx_CONTROL_2_PORT_REG 0x02 #define CS84xx_CONTROL_2_PORT_REG 0x02
@@ -192,6 +214,8 @@ extern ice1712 cards[NUM_CARDS];
#define CS84xx_CLOCK_SOURCE_REG 0x04 #define CS84xx_CLOCK_SOURCE_REG 0x04
#define CS84xx_SERIAL_INPUT_FORMAT_REG 0x05 #define CS84xx_SERIAL_INPUT_FORMAT_REG 0x05
#define CS84xx_SERIAL_OUTPUT_FORMAT_REG 0x06 #define CS84xx_SERIAL_OUTPUT_FORMAT_REG 0x06
#define CS84xx_VERSION_AND_CHIP_ID 0x7F
//Other register are not defined cause they are not used, I'm very lazy... //Other register are not defined cause they are not used, I'm very lazy...
@@ -217,7 +241,7 @@ extern ice1712 cards[NUM_CARDS];
} }
*/ */
//This map come from ALSA sound drivers //This map comes from ALSA sound drivers
#define E2PROM_MAP_SUBVENDOR_LOW 0x00 #define E2PROM_MAP_SUBVENDOR_LOW 0x00
#define E2PROM_MAP_SUBVENDOR_HIGH 0x01 #define E2PROM_MAP_SUBVENDOR_HIGH 0x01
#define E2PROM_MAP_SUBDEVICE_LOW 0x02 #define E2PROM_MAP_SUBDEVICE_LOW 0x02
+161 -66
View File
@@ -15,13 +15,22 @@
extern pci_module_info *pci; extern pci_module_info *pci;
static void ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr, static void ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr,
uint8 data, uint8 chip_select); uint8 data, uint8 chip_select);
static void cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr, static void cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr,
uint8 data, uint8 chip_select); uint8 data, uint8 chip_select);
static uint8 ak45xx_read_gpio(ice1712 *ice, uint8 reg_addr,
uint8 chip_select) {return 0;} //Unimplemented
static uint8 cs84xx_read_gpio(ice1712 *ice, uint8 reg_addr,
uint8 chip_select);
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 //Address are [PCI_10] + xx
uint8 uint8
@@ -216,6 +225,7 @@ read_mt_uint32(ice1712 *ice, int8 regno)
return pci->read_io_32(ice->Multi_Track + regno); return pci->read_io_32(ice->Multi_Track + regno);
}; };
void void
write_mt_uint8(ice1712 *ice, int8 regno, uint8 value) write_mt_uint8(ice1712 *ice, int8 regno, uint8 value)
{ {
@@ -291,8 +301,7 @@ int16 read_eeprom(ice1712 *ice, uint8 eeprom[32])
void void
codec_write(ice1712 *ice, uint8 reg_addr, uint8 data) codec_write(ice1712 *ice, uint8 reg_addr, uint8 data)
{ {
switch (ice->product) switch (ice->product) {
{
case ICE1712_SUBDEVICE_DELTA66: case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44: case ICE1712_SUBDEVICE_DELTA44:
ak45xx_write_gpio(ice, reg_addr, data, DELTA66_CODEC_CS_0); ak45xx_write_gpio(ice, reg_addr, data, DELTA66_CODEC_CS_0);
@@ -321,8 +330,7 @@ codec_write(ice1712 *ice, uint8 reg_addr, uint8 data)
void void
spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data) spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data)
{ {
switch (ice->product) switch (ice->product) {
{
case ICE1712_SUBDEVICE_DELTA1010: case ICE1712_SUBDEVICE_DELTA1010:
break; break;
case ICE1712_SUBDEVICE_DELTADIO2496: case ICE1712_SUBDEVICE_DELTADIO2496:
@@ -346,98 +354,185 @@ spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data)
} }
uint8
codec_read(ice1712 *ice, uint8 reg_addr)
{
uint8 val = 0xff;
switch (ice->product) {
case ICE1712_SUBDEVICE_DELTA66:
case ICE1712_SUBDEVICE_DELTA44:
val = ak45xx_read_gpio(ice, reg_addr, DELTA66_CODEC_CS_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);
break;
case ICE1712_SUBDEVICE_DELTA1010:
case ICE1712_SUBDEVICE_DELTA1010LT:
val = ak45xx_read_gpio(ice, reg_addr, DELTA1010LT_CODEC_CS_0);
break;
case ICE1712_SUBDEVICE_VX442:
val = ak45xx_read_gpio(ice, reg_addr, VX442_CODEC_CS_0);
break;
}
return val;
}
uint8
spdif_read(ice1712 *ice, uint8 reg_addr)
{
uint8 val = 0xff;
switch (ice->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);
break;
case ICE1712_SUBDEVICE_DELTA410:
break;
case ICE1712_SUBDEVICE_DELTA1010LT:
val = cs84xx_read_gpio(ice, reg_addr, DELTA1010LT_SPDIF_CS);
break;
case ICE1712_SUBDEVICE_VX442:
val = cs84xx_read_gpio(ice, reg_addr, VX442_SPDIF_CS);
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 void
ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select) ak45xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select)
{ {
int i;
uint8 tmp; uint8 tmp;
uint32 serial_data;
tmp = read_gpio(ice); tmp = read_gpio(ice);
tmp |= ice->commlines.cs_mask;
serial_data = ((AK45xx_CHIP_ADDRESS & 0x03) << 6) | 0x20 | (reg_addr & 0x1F);
serial_data = (serial_data << 8) | data;
tmp |= ice->gpio_cs_mask;
tmp &= ~(chip_select); tmp &= ~(chip_select);
write_gpio(ice, tmp); write_gpio(ice, tmp);
snooze(AK45xx_DELAY); snooze(GPIO_I2C_DELAY);
for (i = 0; i < AK45xx_BITS_TO_WRITE; i++) { write_gpio_byte(ice, ((AK45xx_CHIP_ADDRESS & 0x03) << 6) | 0x20 | (reg_addr & 0x1f), tmp);
// drop clock and data bits write_gpio_byte(ice, data, tmp);
tmp &= ~(ice->analog_codec.clock | ice->analog_codec.data_out);
// set data if needed
if (serial_data & (1 << (AK45xx_BITS_TO_WRITE - 1)))
tmp |= ice->analog_codec.data_out;
// shift data for sending next bit
serial_data <<= 1;
tmp |= chip_select;
write_gpio(ice, tmp); write_gpio(ice, tmp);
snooze(AK45xx_DELAY); snooze(GPIO_I2C_DELAY);
// raise clock
tmp |= ice->analog_codec.clock;
write_gpio(ice, tmp);
snooze(AK45xx_DELAY);
}
// drop clock and Data
tmp &= ~(ice->analog_codec.clock | ice->analog_codec.data_out);
tmp |= ice->gpio_cs_mask;
write_gpio(ice, tmp);
snooze(AK45xx_DELAY);
} }
void void
cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select) cs84xx_write_gpio(ice1712 *ice, uint8 reg_addr, uint8 data, uint8 chip_select)
{ {
int i;
uint8 tmp; uint8 tmp;
uint32 serial_data;
tmp = read_gpio(ice); tmp = read_gpio(ice);
tmp |= ice->commlines.cs_mask;
serial_data = (CS84xx_CHIP_ADDRESS & 0x7F) << 1; //Last bit is for writing
serial_data = (serial_data << 8) | (reg_addr & 0x7F); //Do not Increment
serial_data = (serial_data << 8) | data;
tmp |= ice->gpio_cs_mask;
tmp &= ~(chip_select); tmp &= ~(chip_select);
write_gpio(ice, tmp); write_gpio(ice, tmp);
snooze(CS84xx_DELAY); snooze(GPIO_I2C_DELAY);
for (i = 0; i < CS84xx_BITS_TO_WRITE; i++) { write_gpio_byte(ice, (CS84xx_CHIP_ADDRESS & 0x7f) << 1, tmp);
// drop clock and data bits write_gpio_byte(ice, reg_addr & 0x7f, tmp); //Do not Increment
tmp &= ~(ice->digital_codec.clock | ice->digital_codec.data_out); write_gpio_byte(ice, data, tmp);
// set data bit if needed
if (serial_data & (1 << (CS84xx_BITS_TO_WRITE - 1)))
tmp |= ice->digital_codec.data_out;
// shift data for sending next bit
serial_data <<= 1;
tmp |= chip_select;
write_gpio(ice, tmp); write_gpio(ice, tmp);
snooze(CS84xx_DELAY); snooze(GPIO_I2C_DELAY);
// raise clock
tmp |= ice->digital_codec.clock;
write_gpio(ice, tmp);
snooze(CS84xx_DELAY);
} }
// drop clock and Data
tmp &= ~(ice->digital_codec.clock | ice->digital_codec.data_out);
tmp |= ice->gpio_cs_mask; uint8
cs84xx_read_gpio(ice1712 *ice, uint8 reg_addr, uint8 chip_select)
{
uint8 tmp, data;
tmp = read_gpio(ice);
tmp |= ice->commlines.cs_mask;
tmp &= ~(chip_select);
write_gpio(ice, tmp); write_gpio(ice, tmp);
snooze(CS84xx_DELAY); 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
tmp |= chip_select; //Deselect the chip
write_gpio(ice, tmp);
snooze(GPIO_I2C_DELAY);
tmp &= ~(chip_select); //Reselect the chip
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
tmp |= chip_select; //Deselect the chip
write_gpio(ice, tmp);
return data;
} }
@@ -89,8 +89,14 @@ int16 read_eeprom(ice1712 *ice, uint8 eeprom[32]);
//------------------------------------------------------ //------------------------------------------------------
void codec_write(ice1712 *ice, uint8 reg_addr, uint8 data); void codec_write(ice1712 *ice, uint8 reg_addr, uint8 data);
void spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data); void spdif_write(ice1712 *ice, uint8 reg_addr, uint8 data);
void codec_write_mult(ice1712 *ice, uint8 reg_addr, uint8 datas[], uint8 size);
void spdif_write_mult(ice1712 *ice, uint8 reg_addr, uint8 datas[], uint8 size);
uint8 codec_read(ice1712 *ice, uint8 reg_addr);
uint8 spdif_read(ice1712 *ice, uint8 reg_addr);
uint8 codec_read_mult(ice1712 *ice, uint8 reg_addr, uint8 datas[], uint8 size);
uint8 spdif_read_mult(ice1712 *ice, uint8 reg_addr, uint8 datas[], uint8 size);
//------------------------------------------------------ //------------------------------------------------------
+20 -26
View File
@@ -15,10 +15,11 @@
#include "ice1712.h" #include "ice1712.h"
#include "io.h" #include "io.h"
#include "debug.h"
#include "midi_driver.h" #include "midi_driver.h"
#include "util.h" #include "util.h"
#include "debug.h"
extern generic_mpu401_module * mpu401; extern generic_mpu401_module * mpu401;
void midi_interrupt_op(int32 op, void * data) void midi_interrupt_op(int32 op, void * data)
@@ -89,38 +90,35 @@ device_hooks midi_hooks = {
NULL /* writev */ NULL /* writev */
}; };
static status_t midi_open(const char * name, uint32 flags, void ** cookie) static status_t midi_open(const char * name, uint32 flags, void ** cookie)
{ {
int i, ix, used_midi = -1; int i, ix, used_midi = -1;
int ret; int ret;
TRACE_ICE(("midi_open()\n")); TRACE("midi_open()\n");
*cookie = NULL; *cookie = NULL;
for (ix = 0; ix < num_cards; ix++) for (ix = 0; ix < num_cards; ix++) {
{
for (i = 0; i < cards[ix].nb_MPU401; i++) for (i = 0; i < cards[ix].nb_MPU401; i++)
if (!strcmp(name, cards[ix].midi_interf[i].name)) if (!strcmp(name, cards[ix].midi_interf[i].name)) {
{
used_midi = i; used_midi = i;
break; break;
} }
} }
if (ix >= num_cards) if (ix >= num_cards) {
{ TRACE("bad device\n");
TRACE_ICE(("bad device\n"));
return ENODEV; return ENODEV;
} }
TRACE_ICE(("mpu401: %p open(): %p driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi_interf[used_midi].driver)); TRACE("mpu401: %p open(): %p driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi_interf[used_midi].driver);
ret = (*mpu401->open_hook)(cards[ix].midi_interf[used_midi].driver, flags, cookie); ret = (*mpu401->open_hook)(cards[ix].midi_interf[used_midi].driver, flags, cookie);
if (ret >= B_OK) if (ret >= B_OK) {
{
cards[ix].midi_interf[used_midi].cookie = *cookie; cards[ix].midi_interf[used_midi].cookie = *cookie;
atomic_add(&cards[ix].midi_interf[used_midi].count, 1); atomic_add(&cards[ix].midi_interf[used_midi].count, 1);
} }
TRACE_ICE(("mpu401: open returns %x / %p\n", ret, *cookie)); TRACE("mpu401: open returns %x / %p\n", ret, *cookie);
return ret; return ret;
} }
@@ -128,7 +126,7 @@ static status_t midi_open(const char * name, uint32 flags, void ** cookie)
static status_t midi_close(void * cookie) static status_t midi_close(void * cookie)
{ {
TRACE_ICE(("midi_close()\n")); TRACE("midi_close()\n");
return (*mpu401->close_hook)(cookie); return (*mpu401->close_hook)(cookie);
} }
@@ -137,22 +135,19 @@ static status_t midi_free(void * cookie)
{ {
int i, ix; int i, ix;
status_t f; status_t f;
TRACE_ICE(("midi_free()\n")); TRACE("midi_free()\n");
f = (*mpu401->free_hook)(cookie); f = (*mpu401->free_hook)(cookie);
for (ix = 0; ix < num_cards; ix++) for (ix = 0; ix < num_cards; ix++) {
{
for (i = 0; i < cards[ix].nb_MPU401; i++) for (i = 0; i < cards[ix].nb_MPU401; i++)
if (cards[ix].midi_interf[i].cookie == cookie) if (cards[ix].midi_interf[i].cookie == cookie) {
{ if (atomic_add(&cards[ix].midi_interf[i].count, -1) == 1) {
if (atomic_add(&cards[ix].midi_interf[i].count, -1) == 1)
{
cards[ix].midi_interf[i].cookie = NULL; cards[ix].midi_interf[i].cookie = NULL;
TRACE_ICE(("cleared %p card %d\n", cookie, ix)); TRACE("cleared %p card %d\n", cookie, ix);
} }
break; break;
} }
} }
TRACE_ICE(("midi_free() done\n")); TRACE("midi_free() done\n");
return f; return f;
} }
@@ -177,9 +172,8 @@ static status_t midi_write(void * cookie, off_t pos, const void * ptr, size_t *
bool midi_interrupt(ice1712 *card) bool midi_interrupt(ice1712 *card)
{ {
TRACE_ICE(("midi_interrupt\n")); TRACE("midi_interrupt\n");
if (!card->midi_interf[0].driver) if (!card->midi_interf[0].driver) {
{
// kprintf("aiigh\n"); // kprintf("aiigh\n");
return false; return false;
} }
+431 -174
View File
@@ -21,10 +21,11 @@
| B_SR_88200 | B_SR_48000 | B_SR_44100) | B_SR_88200 | B_SR_48000 | B_SR_44100)
#define AUTHORIZED_SAMPLE_SIZE (B_FMT_32BIT) #define AUTHORIZED_SAMPLE_SIZE (B_FMT_32BIT)
static void static void
start_DMA(ice1712 *card) start_DMA(ice1712 *card)
{ {
uint16 size = card->output_buffer_size * MAX_DAC; uint16 size = card->buffer_size * MAX_DAC;
write_mt_uint8(card, MT_PROF_PB_CONTROL, 0); write_mt_uint8(card, MT_PROF_PB_CONTROL, 0);
@@ -32,15 +33,15 @@ start_DMA(ice1712 *card)
write_mt_uint16(card, MT_PROF_PB_DMA_COUNT_ADDRESS, (size * SWAPPING_BUFFERS) - 1); write_mt_uint16(card, MT_PROF_PB_DMA_COUNT_ADDRESS, (size * SWAPPING_BUFFERS) - 1);
//We want interrupt only from playback //We want interrupt only from playback
write_mt_uint16(card, MT_PROF_PB_DMA_TERM_COUNT, size - 1); write_mt_uint16(card, MT_PROF_PB_DMA_TERM_COUNT, size - 1);
TRACE_ICE(("SIZE DMA PLAYBACK %#x\n", size)); TRACE("SIZE DMA PLAYBACK %#x\n", size);
size = card->input_buffer_size * MAX_ADC; size = card->buffer_size * MAX_ADC;
write_mt_uint32(card, MT_PROF_REC_DMA_BASE_ADDRESS, (uint32)card->phys_addr_rec); write_mt_uint32(card, MT_PROF_REC_DMA_BASE_ADDRESS, (uint32)card->phys_addr_rec);
write_mt_uint16(card, MT_PROF_REC_DMA_COUNT_ADDRESS, (size * SWAPPING_BUFFERS) - 1); write_mt_uint16(card, MT_PROF_REC_DMA_COUNT_ADDRESS, (size * SWAPPING_BUFFERS) - 1);
//We do not want any interrupt from the record //We do not want any interrupt from the record
write_mt_uint16(card, MT_PROF_REC_DMA_TERM_COUNT, 0); write_mt_uint16(card, MT_PROF_REC_DMA_TERM_COUNT, 0);
TRACE_ICE(("SIZE DMA RECORD %#x\n", size)); TRACE("SIZE DMA RECORD %#x\n", size);
//Enable output AND Input from Analog CODEC //Enable output AND Input from Analog CODEC
switch (card->product) { switch (card->product) {
@@ -135,78 +136,79 @@ ice1712_get_description(ice1712 *card, multi_description *data)
break; break;
} }
strncpy(data->vendor_info, "J. H Leveque", 32); strncpy(data->vendor_info, "Jerome Leveque", 32);
data->output_channel_count = card->total_output_channels; data->output_channel_count = card->total_output_channels;
data->input_channel_count = card->total_input_channels; data->input_channel_count = card->total_input_channels;
data->output_bus_channel_count = card->total_output_channels; data->output_bus_channel_count = 0;
data->input_bus_channel_count = card->total_input_channels; data->input_bus_channel_count = 0;
data->aux_bus_channel_count = 0; data->aux_bus_channel_count = 0;
if (ICE1712_VERY_VERBOSE)
TRACE("request_channel_count = %ld\n", data->request_channel_count);
TRACE_ICE(("request_channel_count = %d\n", data->request_channel_count));
if (data->request_channel_count >= (card->total_output_channels if (data->request_channel_count >= (card->total_output_channels
+ card->total_input_channels)) { + card->total_input_channels)) {
for (i = 0; i < card->nb_DAC; i++) { for (i = 0; i < card->nb_DAC; i++) {
//Analog STEREO output //Analog STEREO output
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL; data->channels[chan].kind = B_MULTI_OUTPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS data->channels[chan].designations = B_CHANNEL_STEREO_BUS
| ((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT; | ((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_RCA;
} }
if (card->spdif_config & NO_IN_YES_OUT) { if (card->spdif_config & NO_IN_YES_OUT) {
//SPDIF STEREO output //SPDIF STEREO output
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL; data->channels[chan].kind = B_MULTI_OUTPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS data->channels[chan].designations = B_CHANNEL_STEREO_BUS
| B_CHANNEL_LEFT; | B_CHANNEL_LEFT;
data->channels[chan].connectors = 0; data->channels[chan].connectors = B_CHANNEL_COAX_SPDIF;
chan++; chan++;
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL; data->channels[chan].kind = B_MULTI_OUTPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS data->channels[chan].designations = B_CHANNEL_STEREO_BUS
| B_CHANNEL_RIGHT; | B_CHANNEL_RIGHT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_COAX_SPDIF;
} }
for (i = 0; i < card->nb_ADC; i++) { for (i = 0; i < card->nb_ADC; i++) {
//Analog STEREO input //Analog STEREO input
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].kind = B_MULTI_INPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS | data->channels[chan].designations = B_CHANNEL_STEREO_BUS |
((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT; ((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_RCA;
} }
if (card->spdif_config & YES_IN_NO_OUT) { if (card->spdif_config & YES_IN_NO_OUT) {
//SPDIF STEREO input //SPDIF STEREO input
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].kind = B_MULTI_INPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_COAX_SPDIF;
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].kind = B_MULTI_INPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_COAX_SPDIF;
} }
//The digital mixer output //The digital mixer output
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].kind = B_MULTI_INPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_SPDIF_HEADER;
data->channels[chan].channel_id = chan; data->channels[chan].channel_id = chan;
data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].kind = B_MULTI_INPUT_BUS;
data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT;
data->channels[chan++].connectors = 0; data->channels[chan++].connectors = B_CHANNEL_SPDIF_HEADER;
} }
TRACE_ICE(("output_channel_count = %d\n", data->output_channel_count)); TRACE("output_channel_count = %ld\n", data->output_channel_count);
TRACE_ICE(("input_channel_count = %d\n", data->input_channel_count)); TRACE("input_channel_count = %ld\n", data->input_channel_count);
TRACE_ICE(("output_bus_channel_count = %d\n", data->output_bus_channel_count)); TRACE("output_bus_channel_count = %ld\n", data->output_bus_channel_count);
TRACE_ICE(("input_bus_channel_count = %d\n", data->input_bus_channel_count)); TRACE("input_bus_channel_count = %ld\n", data->input_bus_channel_count);
data->output_rates = data->input_rates = AUTHORIZED_RATE; data->output_rates = data->input_rates = AUTHORIZED_RATE;
data->min_cvsr_rate = 44100; data->min_cvsr_rate = 44100;
@@ -248,11 +250,11 @@ ice1712_set_enabled_channels(ice1712 *card, multi_channel_enable *data)
{ {
int i; int i;
for (i = 0; i < (card->total_output_channels + card->total_input_channels); i++) for (i = 0; i < (card->total_output_channels + card->total_input_channels); i++)
TRACE_ICE(("set_enabled_channels %d : %s\n", i, TRACE("set_enabled_channels %d : %s\n", i,
B_TEST_CHANNEL(data->enable_bits, i) ? "enabled": "disabled")); B_TEST_CHANNEL(data->enable_bits, i) ? "enabled": "disabled");
TRACE_ICE(("lock_source %d\n", data->lock_source)); TRACE("lock_source %#08X\n", (int)data->lock_source);
TRACE_ICE(("lock_data %d\n", data->lock_data)); TRACE("lock_data %#08X\n", (int)data->lock_data);
if (data->lock_source == B_MULTI_LOCK_SPDIF) if (data->lock_source == B_MULTI_LOCK_SPDIF)
write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, 0x10); write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, 0x10);
@@ -270,19 +272,22 @@ ice1712_get_global_format(ice1712 *card, multi_format_info *data)
{ {
uint8 sr = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT); uint8 sr = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT);
switch (sr) switch (sr) {
{
case 0x0: case 0x0:
data->input.rate = data->output.rate = B_SR_48000; data->input.rate = data->output.rate = B_SR_48000;
data->input.cvsr = data->output.cvsr = 48000.0f;
break; break;
case 0x7: case 0x7:
data->input.rate = data->output.rate = B_SR_96000; data->input.rate = data->output.rate = B_SR_96000;
data->input.cvsr = data->output.cvsr = 96000.0f;
break; break;
case 0x8: case 0x8:
data->input.rate = data->output.rate = B_SR_44100; data->input.rate = data->output.rate = B_SR_44100;
data->input.cvsr = data->output.cvsr = 44100.0f;
break; break;
case 0xB: case 0xb:
data->input.rate = data->output.rate = B_SR_88200; data->input.rate = data->output.rate = B_SR_88200;
data->input.cvsr = data->output.cvsr = 88200.0f;
break; break;
} }
@@ -290,6 +295,9 @@ ice1712_get_global_format(ice1712 *card, multi_format_info *data)
data->output_latency = data->input_latency = 0; data->output_latency = data->input_latency = 0;
data->output.format = data->input.format = AUTHORIZED_SAMPLE_SIZE; data->output.format = data->input.format = AUTHORIZED_SAMPLE_SIZE;
TRACE("Input Sampling Rate = %d\n", (int)data->input.cvsr);
TRACE("Output Sampling Rate = %d\n", (int)data->output.cvsr);
return B_OK; return B_OK;
} }
@@ -299,8 +307,8 @@ ice1712_set_global_format(ice1712 *card, multi_format_info *data)
{ {
uint8 i; uint8 i;
TRACE_ICE(("Input Sampling Rate = %#x\n", data->input.rate)); TRACE("Input Sampling Rate = %#x\n", (int)data->input.rate);
TRACE_ICE(("Output Sampling Rate = %#x\n", data->output.rate)); TRACE("Output Sampling Rate = %#x\n", (int)data->output.rate);
if ((data->input.rate == data->output.rate) if ((data->input.rate == data->output.rate)
&& (card->lock_source == B_MULTI_LOCK_INTERNAL)) { && (card->lock_source == B_MULTI_LOCK_INTERNAL)) {
@@ -321,98 +329,357 @@ ice1712_set_global_format(ice1712 *card, multi_format_info *data)
write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, card->sampling_rate); write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, card->sampling_rate);
} }
i = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT); i = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT);
TRACE_ICE(("RATE = %#x\n", i)); TRACE("RATE = %#x\n", i);
return B_OK; return B_OK;
} }
status_t status_t
ice1712_get_mix(ice1712 *card, multi_mix_value_info *data) ice1712_get_mix(ice1712 *card, multi_mix_value_info *data)
{//Not Implemented {
return B_ERROR; int i;
TRACE(" Asking to get %ld control(s)\n", data->item_count);
for (i = 0; i < data->item_count; i++) {
multi_mix_value *mmv = &(data->values[i]);
switch (mmv->id & ICE1712_MULTI_CONTROL_MASK) {
case ICE1712_MULTI_CONTROL_VOLUME_PB:
mmv->u.gain = card->settings.playback[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].volume;
break;
case ICE1712_MULTI_CONTROL_VOLUME_REC:
mmv->u.gain = card->settings.record[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].volume;
break;
case ICE1712_MULTI_CONTROL_MUTE | ICE1712_MULTI_CONTROL_VOLUME_PB:
mmv->u.enable = card->settings.playback[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].mute;
break;
case ICE1712_MULTI_CONTROL_MUTE | ICE1712_MULTI_CONTROL_VOLUME_REC:
mmv->u.enable = card->settings.record[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].mute;
break;
case ICE1712_MULTI_CONTROL_MUX:
mmv->u.mux = 0;
break;
}
}
return B_OK;
} }
status_t status_t
ice1712_set_mix(ice1712 *card, multi_mix_value_info *data) ice1712_set_mix(ice1712 *card, multi_mix_value_info *data)
{//Not Implemented {
return B_ERROR; int i;
TRACE(" Asking to set %ld control(s)\n", data->item_count);
for (i = 0; i < data->item_count; i++) {
multi_mix_value *mmv = &(data->values[i]);
switch (mmv->id & ICE1712_MULTI_CONTROL_MASK) {
case ICE1712_MULTI_CONTROL_VOLUME_PB:
card->settings.playback[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].volume = mmv->u.gain;
TRACE(" ICE1712_MULTI_CONTROL_VOLUME_PB 0x%x : %f\n", (unsigned int)mmv->id, mmv->u.gain);
break;
case ICE1712_MULTI_CONTROL_VOLUME_REC:
card->settings.record[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].volume = mmv->u.gain;
TRACE(" ICE1712_MULTI_CONTROL_VOLUME_REC 0x%x : %f\n", (unsigned int)mmv->id, mmv->u.gain);
break;
case ICE1712_MULTI_CONTROL_MUTE | ICE1712_MULTI_CONTROL_VOLUME_PB:
card->settings.playback[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].mute = mmv->u.enable;
card->settings.playback[(mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK) + 1].mute = mmv->u.enable;
TRACE(" ICE1712_MULTI_CONTROL_MUTE_PB 0x%x : %d\n", (unsigned int)mmv->id, mmv->u.enable);
break;
case ICE1712_MULTI_CONTROL_MUTE | ICE1712_MULTI_CONTROL_VOLUME_REC:
card->settings.record[mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK].mute = mmv->u.enable;
card->settings.record[(mmv->id & ICE1712_MULTI_CONTROL_CHANNEL_MASK) + 1].mute = mmv->u.enable;
TRACE(" ICE1712_MULTI_CONTROL_MUTE_REC 0x%x : %d\n", (unsigned int)mmv->id, mmv->u.enable);
break;
case ICE1712_MULTI_CONTROL_MUX:
TRACE(" ICE1712_MULTI_CONTROL_MUX 0x%x : 0x%x\n", (unsigned int)mmv->id, (unsigned int)mmv->u.mux);
break;
default:
TRACE(" default 0x%x\n", (unsigned int)mmv->id);
break;
}
}
return apply_settings(card);
} }
status_t status_t
ice1712_list_mix_channels(ice1712 *card, multi_mix_channel_info *data) ice1712_list_mix_channels(ice1712 *card, multi_mix_channel_info *data)
{//Not Implemented {//Not Implemented
return B_ERROR; return B_OK;
}
static const char *Clock[] = { "Internal", "Digital", NULL };
static const char *SampleRate[] = { "44,1 KHz", "48 KHz", "88,2 KHz",
"96 KHz", NULL };
static const char *BufferSize[] = { "64", "128", "256", "512", "1024",
"2048", NULL };
#if 0
static const char *Debug[] = { "Mode 0", "Mode 1", "Mode 2", "Mode 3",
"Mode 4", "Mode 5", NULL };
#endif
static const char *DigitalFormat[] = { "Consumer", "Professional", NULL };
static const char *DigitalEmphasis[] = { "None", "CCITT", "15/50usec", NULL };
static const char *DigitalCopyMode[] = { "Original", "1st Generation",
"No SCMS", NULL };
static const char **SettingsGeneral[] = { Clock, SampleRate, BufferSize,
#if 0
Debug,
#endif
NULL };
static const char **SettingsDigital[] = { DigitalFormat, DigitalEmphasis,
DigitalCopyMode, NULL };
static const char *string_list[] = { "Setup", "General Not implemented yet",
"Digital Not implemented yet", "Output Selection Not implemented yet",
"Internal Mixer",
//General settings
"Master clock", "Sample rate", "Buffer size", "Debug",
//Digital settings
"Output format", "Emphasis", "Copy mode",
//Output Selection
"Output 1", //12
"Output 2",
"Output 3",
"Output 4",
"Digital Output", //16
"Haiku output", //17
"Input 1", //18
"Input 2",
"Input 3",
"Input 4",
"Digital Input", //22
"Internal mixer", //23
};
static int32 nb_control_created;
//This will create a Tab
static int32
create_group_control(multi_mix_control **p_mmc, int32 offset, int32 parent,
enum strind_id string, const char* name)
{
multi_mix_control *mmc = *p_mmc;
int32 group;
//Increase the index cause we fill it
group = mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + offset;
mmc->parent = parent;
mmc->flags = B_MULTI_MIX_GROUP;
mmc->master = CONTROL_IS_MASTER;
mmc->string = string;
if (name != NULL)
strcpy(mmc->name, name);
nb_control_created++; mmc++;
(*p_mmc) = mmc;
return group;
} }
#define MULTI_AUDIO_BASE_ID 1024 //This will create a Slider with a "Mute" CheckBox
#define MULTI_AUDIO_MASTER_ID 0 static void
create_channel_control(multi_mix_control **p_mmc, int32 offset, int32 parent,
#ifndef B_MULTI_MIX_GROUP const char* name)
#define B_MULTI_MIX_GROUP 10
#endif
#ifndef S_null
#define S_null 10
#endif
#ifndef S_STEREO_MIX
#define S_STEREO_MIX 10
#endif
static int32
create_group_control(multi_mix_control *multi, int32 idx, int32 parent,
int32 string, const char* name)
{ {
multi->id = MULTI_AUDIO_BASE_ID + idx; multi_mix_control *mmc = *p_mmc;
multi->master = parent; multi_mix_control control;
multi->flags = B_MULTI_MIX_GROUP;
multi->master = MULTI_AUDIO_MASTER_ID;
// multi->string = string;
control.master = CONTROL_IS_MASTER;
control.parent = parent;
control.u.gain.max_gain = 0.0;
control.u.gain.min_gain = -144.0;
control.u.gain.granularity = 1.5;
//The Mute Checkbox
control.id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_CONTROL_MUTE + offset;
control.flags = B_MULTI_MIX_ENABLE;
control.string = S_MUTE;
*mmc = control;
mmc++;
//The Left Slider
control.string = S_null;
control.id = ICE1712_MULTI_CONTROL_FIRSTID + offset;
control.flags = B_MULTI_MIX_GAIN;
if (name != NULL) if (name != NULL)
strcpy(multi->name, name); strcpy(control.name, name);
*mmc = control;
mmc++;
return multi->id; //The Right Slider
control.master = control.id; //The Id of the Left Slider
control.id++;
*mmc = control;
mmc++;
nb_control_created += 3;
(*p_mmc) = mmc;
} }
static int32
create_slider_control(multi_mix_control *multi, int32 idx, int32 parent, static void
int32 string, const char* name) create_combo_control(multi_mix_control **p_mmc, const char *values[],
int32 parent, const char *name)
{ {
multi->id = MULTI_AUDIO_BASE_ID + idx; multi_mix_control *mmc = *p_mmc;
multi->master = parent; int32 parentControl, i;
multi->flags = B_MULTI_MIX_GAIN;
multi->master = MULTI_AUDIO_MASTER_ID + 1;
// multi->string = string;
multi->u.gain.min_gain = -144.0; //The label
multi->u.gain.max_gain = 0.0; parentControl = mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_CONTROL_MUX + nb_control_created;
multi->u.gain.granularity = 1.5; mmc->flags = B_MULTI_MIX_MUX;
mmc->parent = parent;
strcpy(mmc->name, name);
nb_control_created++; mmc++;
if (name != NULL) //The values
strcpy(multi->name, name); for (i = 0; values[i] != NULL; i++) {
mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + nb_control_created;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, values[i]);
nb_control_created++; mmc++;
}
return multi->id; (*p_mmc) = mmc;
}
//This will create all possible value for the output
//output 0 -> 3 (physical stereo output) 4 is the Digital
static void
create_output_choice(ice1712 *card, multi_mix_control **p_mmc, int32 output, int32 parent)
{
multi_mix_control *mmc = *p_mmc;
int32 parentControl, i;
//The label
parentControl = mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_CONTROL_MUX + nb_control_created;
mmc->flags = B_MULTI_MIX_MUX;
mmc->parent = parent;
strcpy(mmc->name, string_list[12 + output]);
nb_control_created++; mmc++;
//Haiku output
mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + nb_control_created;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, string_list[17]);
nb_control_created++; mmc++;
//Physical Input
for (i = 0; i < card->nb_DAC; i += 2) {
mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + nb_control_created;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, string_list[18 + (i / 2)]);
nb_control_created++; mmc++;
}
//Physical Digital Input
if (card->spdif_config & YES_IN_NO_OUT) {
mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + nb_control_created;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, string_list[22]);
nb_control_created++; mmc++;
}
//Internal mixer only for Output 1 andd Digital Output
if ((output == 0) || (output == 4)) {
mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + nb_control_created;
mmc->flags = B_MULTI_MIX_MUX_VALUE;
mmc->parent = parentControl;
strcpy(mmc->name, string_list[23]);
nb_control_created++; mmc++;
}
(*p_mmc) = mmc;
} }
status_t status_t
ice1712_list_mix_controls(ice1712 *card, multi_mix_control_info *data) ice1712_list_mix_controls(ice1712 *card, multi_mix_control_info *mmci)
{ {
int32 parent; int32 i, parentTab, parentTabColumn;
multi_mix_control *mmc = mmci->controls;
TRACE_ICE(("count = %d\n", data->control_count)); nb_control_created = 0;
parent = create_group_control(data->controls + 0, 0, 0, S_null, "Playback");
create_slider_control(data->controls + 1, 1, parent, S_STEREO_MIX,
"Master Output");
parent = create_group_control(data->controls + 2, 2, 0, S_null, "Record"); TRACE("count = %ld\n", mmci->control_count);
create_slider_control(data->controls + 3, 3, parent, S_STEREO_MIX,
"Master Input"); //Cleaning
data->control_count = 4; memset(mmc, 0, mmci->control_count * sizeof(multi_mix_control));
//Setup tab
parentTab = create_group_control(&mmc, nb_control_created, CONTROL_IS_MASTER, S_SETUP, NULL);
//General Settings
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[1]);
for (i = 0; SettingsGeneral[i] != NULL; i++)
create_combo_control(&mmc, SettingsGeneral[i], parentTabColumn, string_list[5 + i]);
//Digital Settings
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[2]);
for (i = 0; SettingsDigital[i] != NULL; i++)
create_combo_control(&mmc, SettingsDigital[i], parentTabColumn, string_list[9 + i]);
//Output Selection Settings
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[3]);
for (i = 0; i < card->nb_DAC; i += 2)
create_output_choice(card, &mmc, i / 2, parentTabColumn);
if (card->spdif_config & NO_IN_YES_OUT)
create_output_choice(card, &mmc, 4, parentTabColumn);
//Internal Mixer Tab
parentTab = create_group_control(&mmc, nb_control_created, CONTROL_IS_MASTER, S_null, string_list[4]);
for (i = 0; i < card->nb_DAC; i += 2) {
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[(i / 2) + 18]);
create_channel_control(&mmc, ICE1712_MULTI_CONTROL_VOLUME_PB + i, parentTabColumn, NULL);
}
if (card->spdif_config & YES_IN_NO_OUT) {
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[22]);
create_channel_control(&mmc, ICE1712_MULTI_CONTROL_VOLUME_REC + SPDIF_LEFT, parentTabColumn, NULL);
}
for (i = 0; i < card->nb_ADC; i += 2) {
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[(i / 2) + 12]);
create_channel_control(&mmc, ICE1712_MULTI_CONTROL_VOLUME_REC + i, parentTabColumn, NULL);
}
if (card->spdif_config & NO_IN_YES_OUT) {
parentTabColumn = create_group_control(&mmc, nb_control_created, parentTab, S_null, string_list[16]);
create_channel_control(&mmc, ICE1712_MULTI_CONTROL_VOLUME_PB + SPDIF_LEFT, parentTabColumn, NULL);
}
TRACE("Return %ld control(s)\n", nb_control_created);
mmci->control_count = nb_control_created;
return B_OK; return B_OK;
} }
@@ -421,7 +688,8 @@ ice1712_list_mix_controls(ice1712 *card, multi_mix_control_info *data)
status_t status_t
ice1712_list_mix_connections(ice1712 *card, multi_mix_connection_info *data) ice1712_list_mix_connections(ice1712 *card, multi_mix_connection_info *data)
{//Not Implemented {//Not Implemented
return B_ERROR; data->actual_count = 0;
return B_OK;
} }
@@ -430,38 +698,33 @@ ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
{ {
int buff, chan_i = 0, chan_o = 0; int buff, chan_i = 0, chan_o = 0;
TRACE_ICE(("flags = %#x\n",data->flags)); if (ICE1712_VERY_VERBOSE) {
TRACE_ICE(("request_playback_buffers = %#x\n", TRACE("flags = %#x\n", (int)data->flags);
data->request_playback_buffers)); TRACE("request_playback_buffers = %#x\n", (int)data->request_playback_buffers);
TRACE_ICE(("request_playback_channels = %#x\n", TRACE("request_playback_channels = %#x\n", (int)data->request_playback_channels);
data->request_playback_channels)); TRACE("request_playback_buffer_size = %#x\n", (int)data->request_playback_buffer_size);
TRACE_ICE(("request_playback_buffer_size = %#x\n", TRACE("request_record_buffers = %#x\n", (int)data->request_record_buffers);
data->request_playback_buffer_size)); TRACE("request_record_channels = %#x\n", (int)data->request_record_channels);
TRACE_ICE(("request_record_buffers = %#x\n", TRACE("request_record_buffer_size = %#x\n", (int)data->request_record_buffer_size);
data->request_record_buffers)); } //if (ICE1712_VERY_VERBOSE)
TRACE_ICE(("request_record_channels = %#x\n",
data->request_record_channels));
TRACE_ICE(("request_record_buffer_size = %#x\n",
data->request_record_buffer_size));
// MIN_BUFFER_FRAMES <= requested value <= MAX_BUFFER_FRAMES // MIN_BUFFER_FRAMES <= requested value <= MAX_BUFFER_FRAMES
card->output_buffer_size = data->request_playback_buffer_size; card->buffer_size = data->request_playback_buffer_size <= MAX_BUFFER_FRAMES ? \
if (card->output_buffer_size > MAX_BUFFER_FRAMES) data->request_playback_buffer_size >= MIN_BUFFER_FRAMES ? \
card->output_buffer_size = MAX_BUFFER_FRAMES; data->request_playback_buffer_size : MIN_BUFFER_FRAMES \
if (card->output_buffer_size < MIN_BUFFER_FRAMES) : MAX_BUFFER_FRAMES;
card->output_buffer_size = MIN_BUFFER_FRAMES;
card->input_buffer_size = data->request_record_buffer_size; // MIN_BUFFER_FRAMES <= requested value <= MAX_BUFFER_FRAMES
if (card->input_buffer_size > MAX_BUFFER_FRAMES) card->buffer_size = data->request_record_buffer_size <= MAX_BUFFER_FRAMES ? \
card->input_buffer_size = MAX_BUFFER_FRAMES; data->request_record_buffer_size >= MIN_BUFFER_FRAMES ? \
if (card->input_buffer_size < MIN_BUFFER_FRAMES) data->request_record_buffer_size : MIN_BUFFER_FRAMES \
card->input_buffer_size = MIN_BUFFER_FRAMES; : MAX_BUFFER_FRAMES;
for (buff = 0; buff < SWAPPING_BUFFERS; buff++) { for (buff = 0; buff < SWAPPING_BUFFERS; buff++) {
uint32 stride_o = MAX_DAC * SAMPLE_SIZE; uint32 stride_o = MAX_DAC * SAMPLE_SIZE;
uint32 stride_i = MAX_ADC * SAMPLE_SIZE; uint32 stride_i = MAX_ADC * SAMPLE_SIZE;
uint32 buf_o = stride_o * card->output_buffer_size; uint32 buf_o = stride_o * card->buffer_size;
uint32 buf_i = stride_i * card->input_buffer_size; uint32 buf_i = stride_i * card->buffer_size;
if (data->request_playback_channels == card->total_output_channels) { if (data->request_playback_channels == card->total_output_channels) {
for (chan_o = 0; chan_o < card->nb_DAC; chan_o++) { for (chan_o = 0; chan_o < card->nb_DAC; chan_o++) {
@@ -469,8 +732,8 @@ ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
data->playback_buffers[buff][chan_o].base = card->log_addr_pb data->playback_buffers[buff][chan_o].base = card->log_addr_pb
+ buf_o * buff + SAMPLE_SIZE * chan_o; + buf_o * buff + SAMPLE_SIZE * chan_o;
data->playback_buffers[buff][chan_o].stride = stride_o; data->playback_buffers[buff][chan_o].stride = stride_o;
TRACE_ICE(("pb_buffer[%d][%d] = %#x\n", buff, chan_o, if (ICE1712_VERY_VERBOSE)
data->playback_buffers[buff][chan_o].base)); TRACE("pb_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_o, (int)data->playback_buffers[buff][chan_o].base);
} }
if (card->spdif_config & NO_IN_YES_OUT) { if (card->spdif_config & NO_IN_YES_OUT) {
@@ -478,15 +741,15 @@ ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
data->playback_buffers[buff][chan_o].base = card->log_addr_pb data->playback_buffers[buff][chan_o].base = card->log_addr_pb
+ buf_o * buff + SAMPLE_SIZE * SPDIF_LEFT; + buf_o * buff + SAMPLE_SIZE * SPDIF_LEFT;
data->playback_buffers[buff][chan_o].stride = stride_o; data->playback_buffers[buff][chan_o].stride = stride_o;
TRACE_ICE(("pb_buffer[%d][%d] = %#x\n", buff, chan_o, if (ICE1712_VERY_VERBOSE)
data->playback_buffers[buff][chan_o].base)); TRACE("pb_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_o, (int)data->playback_buffers[buff][chan_o].base);
chan_o++; chan_o++;
data->playback_buffers[buff][chan_o].base = card->log_addr_pb data->playback_buffers[buff][chan_o].base = card->log_addr_pb
+ buf_o * buff + SAMPLE_SIZE * SPDIF_RIGHT; + buf_o * buff + SAMPLE_SIZE * SPDIF_RIGHT;
data->playback_buffers[buff][chan_o].stride = stride_o; data->playback_buffers[buff][chan_o].stride = stride_o;
TRACE_ICE(("pb_buffer[%d][%d] = %#x\n", buff, chan_o, if (ICE1712_VERY_VERBOSE)
data->playback_buffers[buff][chan_o].base)); TRACE("pb_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_o, (int)data->playback_buffers[buff][chan_o].base);
chan_o++; chan_o++;
} }
} }
@@ -497,8 +760,8 @@ ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
data->record_buffers[buff][chan_i].base = card->log_addr_rec data->record_buffers[buff][chan_i].base = card->log_addr_rec
+ buf_i * buff + SAMPLE_SIZE * chan_i; + buf_i * buff + SAMPLE_SIZE * chan_i;
data->record_buffers[buff][chan_i].stride = stride_i; data->record_buffers[buff][chan_i].stride = stride_i;
TRACE_ICE(("rec_buffer[%d][%d] = %#x\n", buff, chan_i, if (ICE1712_VERY_VERBOSE)
data->record_buffers[buff][chan_i].base)); TRACE("rec_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_i, (int)data->record_buffers[buff][chan_i].base);
} }
if (card->spdif_config & YES_IN_NO_OUT) { if (card->spdif_config & YES_IN_NO_OUT) {
@@ -506,15 +769,15 @@ ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
data->record_buffers[buff][chan_i].base = card->log_addr_rec data->record_buffers[buff][chan_i].base = card->log_addr_rec
+ buf_i * buff + SAMPLE_SIZE * SPDIF_LEFT; + buf_i * buff + SAMPLE_SIZE * SPDIF_LEFT;
data->record_buffers[buff][chan_i].stride = stride_i; data->record_buffers[buff][chan_i].stride = stride_i;
TRACE_ICE(("rec_buffer[%d][%d] = %#x\n", buff, chan_i, if (ICE1712_VERY_VERBOSE)
data->record_buffers[buff][chan_i].base)); TRACE("rec_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_i, (int)data->record_buffers[buff][chan_i].base);
chan_i++; chan_i++;
data->record_buffers[buff][chan_i].base = card->log_addr_rec data->record_buffers[buff][chan_i].base = card->log_addr_rec
+ buf_i * buff + SAMPLE_SIZE * SPDIF_RIGHT; + buf_i * buff + SAMPLE_SIZE * SPDIF_RIGHT;
data->record_buffers[buff][chan_i].stride = stride_i; data->record_buffers[buff][chan_i].stride = stride_i;
TRACE_ICE(("rec_buffer[%d][%d] = %#x\n", buff, chan_i, if (ICE1712_VERY_VERBOSE)
data->record_buffers[buff][chan_i].base)); TRACE("rec_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_i, (int)data->record_buffers[buff][chan_i].base);
chan_i++; chan_i++;
} }
@@ -522,41 +785,35 @@ ice1712_get_buffers(ice1712 *card, multi_buffer_list *data)
data->record_buffers[buff][chan_i].base = card->log_addr_rec data->record_buffers[buff][chan_i].base = card->log_addr_rec
+ buf_i * buff + SAMPLE_SIZE * MIXER_OUT_LEFT; + buf_i * buff + SAMPLE_SIZE * MIXER_OUT_LEFT;
data->record_buffers[buff][chan_i].stride = stride_i; data->record_buffers[buff][chan_i].stride = stride_i;
TRACE_ICE(("rec_buffer[%d][%d] = %#x\n", buff, chan_i, if (ICE1712_VERY_VERBOSE)
data->record_buffers[buff][chan_i].base)); TRACE("rec_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_i, (int)data->record_buffers[buff][chan_i].base);
chan_i++; chan_i++;
data->record_buffers[buff][chan_i].base = card->log_addr_rec data->record_buffers[buff][chan_i].base = card->log_addr_rec
+ buf_i * buff + SAMPLE_SIZE * MIXER_OUT_RIGHT; + buf_i * buff + SAMPLE_SIZE * MIXER_OUT_RIGHT;
data->record_buffers[buff][chan_i].stride = stride_i; data->record_buffers[buff][chan_i].stride = stride_i;
TRACE_ICE(("rec_buffer[%d][%d] = %#x\n", buff, chan_i, if (ICE1712_VERY_VERBOSE)
data->record_buffers[buff][chan_i].base)); TRACE("rec_buffer[%d][%d] = %#x\n", (int)buff, (int)chan_i, (int)data->record_buffers[buff][chan_i].base);
chan_i++; chan_i++;
} }
} }
data->return_playback_buffers = SWAPPING_BUFFERS; data->return_playback_buffers = SWAPPING_BUFFERS;
data->return_playback_channels = card->total_output_channels; data->return_playback_channels = card->total_output_channels;
data->return_playback_buffer_size = card->output_buffer_size; data->return_playback_buffer_size = card->buffer_size;
TRACE_ICE(("return_playback_buffers = %#x\n", TRACE("return_playback_buffers = %#x\n", (int)data->return_playback_buffers);
data->return_playback_buffers)); TRACE("return_playback_channels = %#x\n", (int)data->return_playback_channels);
TRACE_ICE(("return_playback_channels = %#x\n", TRACE("return_playback_buffer_size = %#x\n", (int)data->return_playback_buffer_size);
data->return_playback_channels));
TRACE_ICE(("return_playback_buffer_size = %#x\n",
data->return_playback_buffer_size));
data->return_record_buffers = SWAPPING_BUFFERS; data->return_record_buffers = SWAPPING_BUFFERS;
data->return_record_channels = card->total_input_channels; data->return_record_channels = card->total_input_channels;
data->return_record_channels = chan_i; data->return_record_channels = chan_i;
data->return_record_buffer_size = card->input_buffer_size; data->return_record_buffer_size = card->buffer_size;
TRACE_ICE(("return_record_buffers = %#x\n", TRACE("return_record_buffers = %#x\n",(int)data->return_record_buffers);
data->return_record_buffers)); TRACE("return_record_channels = %#x\n", (int)data->return_record_channels);
TRACE_ICE(("return_record_channels = %#x\n", TRACE("return_record_buffer_size = %#x\n", (int)data->return_record_buffer_size);
data->return_record_channels));
TRACE_ICE(("return_record_buffer_size = %#x\n",
data->return_record_buffer_size));
start_DMA(card); start_DMA(card);
@@ -571,78 +828,78 @@ ice1712_buffer_exchange(ice1712 *card, multi_buffer_info *data)
/* unsigned char peak[MAX_ADC]; /* unsigned char peak[MAX_ADC];
int i; int i;
*/ */
// TRACE_ICE(("Avant Exchange p : %d, r : %d\n", data->playback_buffer_cycle, // TRACE("Avant Exchange p : %d, r : %d\n", data->playback_buffer_cycle, data->record_buffer_cycle);
// data->record_buffer_cycle));
status = acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT status = acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000);
| B_CAN_INTERRUPT, 50000);
switch (status) { switch (status) {
case B_OK: case B_NO_ERROR:
// TRACE_ICE(("B_NO_ERROR\n")); // TRACE("B_NO_ERROR\n");
cpu_status = lock(); cpu_status = disable_interrupts();
// do playback // Playback buffers info
data->played_real_time = card->played_time; data->played_real_time = card->played_time;
data->played_frames_count += card->output_buffer_size; data->played_frames_count = card->frames_count;
data->playback_buffer_cycle = (card->buffer/* - 1*/) & 0x1; //Buffer TO fill data->playback_buffer_cycle = (card->buffer - 1) % SWAPPING_BUFFERS; //Buffer played
// do record // Record buffers info
data->recorded_real_time = card->played_time; data->recorded_real_time = card->played_time;
data->recorded_frames_count += card->input_buffer_size; data->recorded_frames_count = card->frames_count;
data->record_buffer_cycle = (card->buffer/* - 1*/) & 0x1; //Buffer filled data->record_buffer_cycle = (card->buffer - 1) % SWAPPING_BUFFERS; //Buffer filled
data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD;
unlock(cpu_status); restore_interrupts(cpu_status);
break; break;
case B_BAD_SEM_ID: case B_BAD_SEM_ID:
TRACE_ICE(("B_BAD_SEM_ID\n")); TRACE("B_BAD_SEM_ID\n");
break; break;
case B_INTERRUPTED: case B_INTERRUPTED:
TRACE_ICE(("B_INTERRUPTED\n")); TRACE("B_INTERRUPTED\n");
break; break;
case B_BAD_VALUE: case B_BAD_VALUE:
TRACE_ICE(("B_BAD_VALUE\n")); TRACE("B_BAD_VALUE\n");
break; break;
case B_WOULD_BLOCK: case B_WOULD_BLOCK:
TRACE_ICE(("B_WOULD_BLOCK\n")); TRACE("B_WOULD_BLOCK\n");
break; break;
case B_TIMED_OUT: case B_TIMED_OUT:
TRACE_ICE(("B_TIMED_OUT\n")); TRACE("B_TIMED_OUT\n");
start_DMA(card); start_DMA(card);
cpu_status = lock(); cpu_status = lock();
data->played_real_time = card->played_time; data->played_real_time = card->played_time;
data->playback_buffer_cycle = 0; data->playback_buffer_cycle = 0;
data->played_frames_count += card->output_buffer_size; data->played_frames_count += card->buffer_size;
data->recorded_real_time = card->played_time; data->recorded_real_time = card->played_time;
data->record_buffer_cycle = 0; data->record_buffer_cycle = 0;
data->recorded_frames_count += card->input_buffer_size; data->recorded_frames_count += card->buffer_size;
data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD;
unlock(cpu_status); unlock(cpu_status);
break; break;
default: default:
TRACE_ICE(("Default\n")); TRACE("Default\n");
break; break;
} }
/* if ((card->buffer % 500) == 0) if ((card->buffer % 1500) == 0) {
{
uint8 reg8, reg8_dir; uint8 reg8, reg8_dir;
reg8 = read_gpio(card); reg8 = read_gpio(card);
reg8_dir = read_cci_uint8(card, CCI_GPIO_DIRECTION_CONTROL); reg8_dir = read_cci_uint8(card, CCI_GPIO_DIRECTION_CONTROL);
TRACE_ICE(("B_NO_ERROR buffer = %d : GPIO = %d (%d)\n", card->buffer, reg8, reg8_dir)); TRACE("DEBUG === GPIO = %d (dir %d)\n", reg8, reg8_dir);
reg8 = spdif_read(card, CS84xx_VERSION_AND_CHIP_ID);
TRACE("DEBUG === S/PDif Version : 0x%x\n", reg8);
} }
*/
return B_OK; return B_OK;
} }
@@ -9,8 +9,23 @@
* Distributed under the terms of the MIT license. * Distributed under the terms of the MIT license.
*/ */
#ifndef _ICE1712_MULTI_H_
#define _ICE1712_MULTI_H_
#include "ice1712.h" #include "ice1712.h"
#include <hmulti_audio.h>
#define ICE1712_MULTI_CONTROL_FIRSTID (0x08000000)
#define ICE1712_MULTI_CONTROL_VOLUME_PB (0x00010000)
#define ICE1712_MULTI_CONTROL_VOLUME_REC (0x00020000)
#define ICE1712_MULTI_CONTROL_MUTE (0x00040000)
#define ICE1712_MULTI_CONTROL_MUX (0x00080000)
#define ICE1712_MULTI_CONTROL_MASK (0x00FF0000)
#define ICE1712_MULTI_CONTROL_CHANNEL_MASK (0x000000FF)
#define CONTROL_IS_MASTER (0)
status_t ice1712_get_description(ice1712 *card, multi_description *data); status_t ice1712_get_description(ice1712 *card, multi_description *data);
status_t ice1712_get_enabled_channels(ice1712 *card, multi_channel_enable *data); status_t ice1712_get_enabled_channels(ice1712 *card, multi_channel_enable *data);
status_t ice1712_set_enabled_channels(ice1712 *card, multi_channel_enable *data); status_t ice1712_set_enabled_channels(ice1712 *card, multi_channel_enable *data);
@@ -24,3 +39,5 @@ status_t ice1712_list_mix_connections(ice1712 *card, multi_mix_connection_info *
status_t ice1712_get_buffers(ice1712 *card, multi_buffer_list *data); status_t ice1712_get_buffers(ice1712 *card, multi_buffer_list *data);
status_t ice1712_buffer_exchange(ice1712 *card, multi_buffer_info *data); status_t ice1712_buffer_exchange(ice1712 *card, multi_buffer_info *data);
status_t ice1712_buffer_force_stop(ice1712 *card); status_t ice1712_buffer_force_stop(ice1712 *card);
#endif //_ICE1712_MULTI_H_
@@ -13,8 +13,6 @@
#include <OS.h> #include <OS.h>
#include <string.h> #include <string.h>
//#define DEBUG 2
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
@@ -55,19 +53,19 @@ alloc_mem(void **phy, void **log, size_t size, const char *name)
area_id areaid; area_id areaid;
status_t rv; status_t rv;
TRACE_ICE(("allocating %#08 bytes for %s\n",size,name)); TRACE("allocating %#08X bytes for %s\n", (int)size, name);
size = round_to_pagesize(size); size = round_to_pagesize(size);
areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size, areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size,
B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA); B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
if (areaid < B_OK) { if (areaid < B_OK) {
TRACE_ICE(("couldn't allocate area %s\n",name)); TRACE("couldn't allocate area %s\n",name);
return B_ERROR; return B_ERROR;
} }
rv = get_memory_map(logadr,size,&pe,1); rv = get_memory_map(logadr,size,&pe,1);
if (rv < B_OK) { if (rv < B_OK) {
delete_area(areaid); delete_area(areaid);
TRACE_ICE(("couldn't map %s\n",name)); TRACE("couldn't map %s\n",name);
return B_ERROR; return B_ERROR;
} }
memset(logadr,0,size); memset(logadr,0,size);
@@ -75,7 +73,7 @@ alloc_mem(void **phy, void **log, size_t size, const char *name)
*log = logadr; *log = logadr;
if (phy) if (phy)
*phy = pe.address; *phy = pe.address;
TRACE_ICE(("area = %d, size = %#08X, log = %#08X, phy = %#08X\n",areaid,size,logadr,pe.address)); TRACE("area = %d, size = %#08X, log = %#08X, phy = %#08X\n", (int)areaid, (int)size, (int)logadr, (int)pe.address);
return areaid; return areaid;
} }