status_t ice1712_set_global_format(ice1712 *card, multi_format_info *data) { uint8 i; TRACE("Input Sampling Rate = %#x\n", (int)data->input.rate); TRACE("Output Sampling Rate = %#x\n", (int)data->output.rate); if ((data->input.rate == data->output.rate) && (card->lock_source == B_MULTI_LOCK_INTERNAL)) { switch (data->input.rate) { case B_SR_96000: card->sampling_rate = 0x07; break; case B_SR_88200: card->sampling_rate = 0x0B; break; case B_SR_48000: card->sampling_rate = 0x00; break; case B_SR_44100: card->sampling_rate = 0x08; break; } write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, card->sampling_rate); } i = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT); TRACE("RATE = %#x\n", i); return B_OK; }
status_t ice1712_get_global_format(ice1712 *card, multi_format_info *data) { uint8 sr = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT); switch (sr) { case 0x0: data->input.rate = data->output.rate = B_SR_48000; data->input.cvsr = data->output.cvsr = 48000.0f; break; case 0x7: data->input.rate = data->output.rate = B_SR_96000; data->input.cvsr = data->output.cvsr = 96000.0f; break; case 0x8: data->input.rate = data->output.rate = B_SR_44100; data->input.cvsr = data->output.cvsr = 44100.0f; break; case 0xb: data->input.rate = data->output.rate = B_SR_88200; data->input.cvsr = data->output.cvsr = 88200.0f; break; } data->timecode_kind = 0; data->output_latency = data->input_latency = 0; 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; }
status_t ice1712_set_global_format(ice1712 *card, multi_format_info *data) { TRACE("Input Sampling Rate = %d\n", data->input.rate); TRACE("Output Sampling Rate = %d\n", data->output.rate); //We can't have a different rate for input and output //so just wait to change our sample rate when //media server will do what we need //Lie to it and say we are living in wonderland if (data->input.rate != data->output.rate) return B_OK; if (card->lock_source == B_MULTI_LOCK_INTERNAL) { switch (data->output.rate) { case B_SR_96000: card->sampling_rate = 0x07; break; case B_SR_88200: card->sampling_rate = 0x0B; break; case B_SR_48000: card->sampling_rate = 0x00; break; case B_SR_44100: card->sampling_rate = 0x08; break; } write_mt_uint8(card, MT_SAMPLING_RATE_SELECT, card->sampling_rate); } TRACE("New rate = %#x\n", read_mt_uint8(card, MT_SAMPLING_RATE_SELECT)); return B_OK; }
int32 ice_1712_int(void *arg) { ice1712 *ice = arg; uint8 reg8 = 0; uint16 reg16 = 0; uint32 status = B_UNHANDLED_INTERRUPT; // interrupt from DMA PATH reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS); if (reg8 != 0) { ice->buffer++; ice->played_time = system_time(); ice->frames_count += ice->buffer_size; release_sem_etc(ice->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE); write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, reg8); status = B_HANDLED_INTERRUPT; } // interrupt from Controller Registers reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_STATUS); if (reg8 != 0) { bool ret; if (reg8 & CCS_INTERRUPT_MIDI_1) { ret = (*mpu401->interrupt_hook)(ice->midi_interf[0].mpu401device); if (ret) { //Do not ack, cause more datas are available reg8 &= ~CCS_INTERRUPT_MIDI_1; } } if (reg8 & CCS_INTERRUPT_MIDI_2) { ret = (*mpu401->interrupt_hook)(ice->midi_interf[1].mpu401device); if (ret) { //Do not ack, cause more datas are available reg8 &= ~CCS_INTERRUPT_MIDI_2; } } if (reg8 != 0) { write_ccs_uint8(ice, CCS_INTERRUPT_STATUS, reg8); status = B_HANDLED_INTERRUPT; } } // interrupt from DS PATH reg16 = read_ds_uint16(ice, DS_DMA_INT_STATUS); if (reg16 != 0) { //Ack interrupt write_ds_uint16(ice, DS_DMA_INT_STATUS, reg16); status = B_HANDLED_INTERRUPT; } return status; }
status_t ice1712_get_enabled_channels(ice1712 *card, multi_channel_enable *data) { int i; uint8 reg; for (i = 0; i < (card->total_output_channels + card->total_input_channels); i++) B_SET_CHANNEL(data->enable_bits, i, true); reg = read_mt_uint8(card, MT_SAMPLING_RATE_SELECT); if (reg == 0x10) data->lock_source = B_MULTI_LOCK_SPDIF; else data->lock_source = B_MULTI_LOCK_INTERNAL; return B_OK; }
static status_t ice1712_setup(ice1712 *ice) { int result, i; uint8 reg8 = 0; uint16 mute; ice->irq = ice->info.u.h0.interrupt_line; ice->Controller = ice->info.u.h0.base_registers[0]; ice->DDMA = ice->info.u.h0.base_registers[1]; ice->DMA_Path = ice->info.u.h0.base_registers[2]; ice->Multi_Track = ice->info.u.h0.base_registers[3]; // Soft Reset write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x81); snooze(200000); write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x01); snooze(200000); result = read_eeprom(ice, ice->eeprom_data); /* TRACE("EEprom -> "); for (i = 0; i < 32; i++) TRACE("%x, ", eeprom_data[i]); TRACE("<- EEprom\n");*/ write_ccs_uint8(ice, CCS_SERR_SHADOW, 0x01); //Write all configurations register from EEProm 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->product = ice->info.vendor_id << 16 | ice->info.device_id; 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_DATA, ice->eeprom_data[E2PROM_MAP_GPIOSTATE]); write_cci_uint8(ice, CCI_GPIO_DIRECTION_CONTROL, ice->eeprom_data[E2PROM_MAP_GPIODIR]); TRACE("CCI_GPIO_WRITE_MASK : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIOMASK]); TRACE("CCI_GPIO_DATA : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIOSTATE]); TRACE("CCI_GPIO_DIRECTION_CONTROL : 0x%x\n", ice->eeprom_data[E2PROM_MAP_GPIODIR]); //Write Configuration in the PCI configuration Register (pci->write_pci_config)(ice->info.bus, ice->info.device, ice->info.function, 0x60, 1, ice->eeprom_data[E2PROM_MAP_CONFIG]); (pci->write_pci_config)(ice->info.bus, ice->info.device, ice->info.function, 0x61, 1, ice->eeprom_data[E2PROM_MAP_ACL]); (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]); TRACE("E2PROM_MAP_CONFIG : 0x%x\n", ice->eeprom_data[E2PROM_MAP_CONFIG]); reg8 = ice->eeprom_data[E2PROM_MAP_CONFIG]; //Bits signification for E2PROM_MAP_CONFIG Byte // // 8 7 6 5 4 3 2 1 0 // |-D-|-C-|---B---|---A--- // // D : MPU401 number minus 1 // C : AC'97 // B : Stereo ADC number minus 1 (=> 1 to 4) // A : Stereo DAC number minus 1 (=> 1 to 4) ice->config.nb_DAC = ((reg8 & 0x03) + 1) * 2; reg8 >>= 2; ice->config.nb_ADC = ((reg8 & 0x03) + 1) * 2; reg8 >>= 2; if ((reg8 & 0x01) != 0) {//Consumer AC'97 Exist TRACE("Consumer AC'97 does exist\n"); //For now do nothing /* write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x40); snooze(10000); write_ccs_uint8(ice, CCS_CONS_AC97_COMMAND_STATUS, 0x00); snooze(20000); */ } else { TRACE("Consumer AC'97 does NOT exist\n"); } reg8 >>= 1; ice->config.nb_MPU401 = (reg8 & 0x1) + 1; if (ice->config.nb_MPU401 > 0) { sprintf(ice->midi_interf[0].name, "midi/ice1712/%ld/1", ice - cards + 1); (*mpu401->create_device)(ice->Controller + CCS_MIDI_1_DATA, &ice->midi_interf[0].mpu401device, 0x14121712, ice_1712_midi_interrupt_op, &ice->midi_interf[0]); names[num_names++] = ice->midi_interf[0].name; ice->midi_interf[0].card = ice; ice->midi_interf[0].int_mask = CCS_INTERRUPT_MIDI_1; } if (ice->config.nb_MPU401 > 1) { sprintf(ice->midi_interf[1].name, "midi/ice1712/%ld/2", ice - cards + 1); (*mpu401->create_device)(ice->Controller + CCS_MIDI_2_DATA, &ice->midi_interf[1].mpu401device, 0x14121712, ice_1712_midi_interrupt_op, &ice->midi_interf[1]); names[num_names++] = ice->midi_interf[1].name; ice->midi_interf[1].card = ice; ice->midi_interf[1].int_mask = CCS_INTERRUPT_MIDI_2; } TRACE("E2PROM_MAP_SPDIF : 0x%x\n", ice->eeprom_data[E2PROM_MAP_SPDIF]); ice->config.spdif = ice->eeprom_data[E2PROM_MAP_SPDIF]; switch (ice->product) { case ICE1712_SUBDEVICE_DELTA66 : case ICE1712_SUBDEVICE_DELTA44 : ice->CommLines.clock = DELTA66_CLK; 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; case ICE1712_SUBDEVICE_DELTA410 : case ICE1712_SUBDEVICE_AUDIOPHILE_2496 : case ICE1712_SUBDEVICE_DELTADIO2496 : ice->CommLines.clock = AP2496_CLK; 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; case ICE1712_SUBDEVICE_DELTA1010 : case ICE1712_SUBDEVICE_DELTA1010LT : ice->CommLines.clock = DELTA1010LT_CLK; 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; case ICE1712_SUBDEVICE_VX442 : ice->CommLines.clock = VX442_CLK; 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; } sprintf(ice->name, "%s/%ld", HMULTI_AUDIO_DEV_PATH, ice - cards + 1); names[num_names++] = ice->name; names[num_names] = NULL; ice->buffer_ready_sem = create_sem(0, "Buffer Exchange"); if (ice->buffer_ready_sem < B_OK) { return ice->buffer_ready_sem; } // TRACE("installing interrupt : %0x\n", ice->irq); install_io_interrupt_handler(ice->irq, ice_1712_int, ice, 0); ice->mem_id_pb = alloc_mem(&ice->phys_addr_pb, &ice->log_addr_pb, PLAYBACK_BUFFER_TOTAL_SIZE, "playback buffer"); if (ice->mem_id_pb < B_OK) { remove_io_interrupt_handler(ice->irq, ice_1712_int, ice); delete_sem(ice->buffer_ready_sem); return ice->mem_id_pb; } ice->mem_id_rec = alloc_mem(&ice->phys_addr_rec, &ice->log_addr_rec, RECORD_BUFFER_TOTAL_SIZE, "record buffer"); if (ice->mem_id_rec < B_OK) { remove_io_interrupt_handler(ice->irq, ice_1712_int, ice); delete_sem(ice->buffer_ready_sem); delete_area(ice->mem_id_pb); return(ice->mem_id_rec); } memset(ice->log_addr_pb, 0, PLAYBACK_BUFFER_TOTAL_SIZE); memset(ice->log_addr_rec, 0, RECORD_BUFFER_TOTAL_SIZE); ice->sampling_rate = 0x08; ice->buffer = 0; ice->frames_count = 0; ice->buffer_size = MAX_BUFFER_FRAMES; ice->total_output_channels = ice->config.nb_DAC; if (ice->config.spdif & SPDIF_OUT_PRESENT) ice->total_output_channels += 2; ice->total_input_channels = ice->config.nb_ADC + 2; if (ice->config.spdif & SPDIF_IN_PRESENT) ice->total_input_channels += 2; //Write bits in the GPIO write_cci_uint8(ice, CCI_GPIO_WRITE_MASK, ~(ice->CommLines.cs_mask)); //Deselect CS 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); //All Analog outputs from DMA write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0x0000); //All Digital output from DMA write_mt_uint16(ice, MT_ROUTING_CONTROL_SPDOUT, 0x0000); //Just to route all input to all output // write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0xAAAA); // write_mt_uint32(ice, MT_CAPTURED_DATA, 0x76543210); //Just to route SPDIF Input to DAC 0 // write_mt_uint16(ice, MT_ROUTING_CONTROL_PSDOUT, 0xAAAF); // write_mt_uint32(ice, MT_CAPTURED_DATA, 0x76543280); //Mute all input mute = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8); for (i = 0; i < 2 * ICE1712_HARDWARE_VOLUME; i++) { write_mt_uint8(ice, MT_VOLUME_CONTROL_CHANNEL_INDEX, i); write_mt_uint16(ice, MT_VOLUME_CONTROL_CHANNEL_INDEX, mute); } //Unmask Interrupt write_ccs_uint8(ice, CCS_CONTROL_STATUS, 0x41); reg8 = read_ccs_uint8(ice, CCS_INTERRUPT_MASK); TRACE("-----CCS----- = %x\n", reg8); write_ccs_uint8(ice, CCS_INTERRUPT_MASK, 0xEF); /* reg16 = read_ds_uint16(ice, DS_DMA_INT_MASK); TRACE("-----DS_DMA----- = %x\n", reg16); write_ds_uint16(ice, DS_DMA_INT_MASK, 0x0000); */ reg8 = read_mt_uint8(ice, MT_DMA_INT_MASK_STATUS); TRACE("-----MT_DMA----- = %x\n", reg8); write_mt_uint8(ice, MT_DMA_INT_MASK_STATUS, 0x00); return B_OK; };