support for multiple frame rates
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3186 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -514,6 +514,12 @@ ac97_dump_capabilities(ac97_dev *dev)
|
|||||||
LOG(("CAP_PCM_RATE_96000\n"));
|
LOG(("CAP_PCM_RATE_96000\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ac97_has_capability(ac97_dev *dev, uint64 cap)
|
||||||
|
{
|
||||||
|
return (dev->capabilities & cap);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Codec specific initialization, etc.
|
* Codec specific initialization, etc.
|
||||||
*/
|
*/
|
||||||
@@ -528,7 +534,7 @@ ac97_reg_is_valid(ac97_dev *dev, uint8 reg)
|
|||||||
|
|
||||||
switch (dev->codec_id) {
|
switch (dev->codec_id) {
|
||||||
case CODEC_ID_ALC201A:
|
case CODEC_ID_ALC201A:
|
||||||
if (reg != 0x56)
|
if (reg != 0x54) /* reading register 0x54 causes a semaphore timeout on the next register accessed */
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ enum AC97_REGISTER {
|
|||||||
AC97_PCM_FRONT_DAC_RATE = 0x2C,
|
AC97_PCM_FRONT_DAC_RATE = 0x2C,
|
||||||
AC97_PCM_SURR_DAC_RATE = 0x2E,
|
AC97_PCM_SURR_DAC_RATE = 0x2E,
|
||||||
AC97_PCM_LFE_DAC_RATE = 0x30,
|
AC97_PCM_LFE_DAC_RATE = 0x30,
|
||||||
AC97_PCM_L_R_DAC_RATE = 0x32,
|
AC97_PCM_L_R_ADC_RATE = 0x32,
|
||||||
AC97_MIC_ADC_RATE = 0x34,
|
AC97_MIC_ADC_RATE = 0x34,
|
||||||
AC97_CENTER_LFE_VOLUME = 0x36,
|
AC97_CENTER_LFE_VOLUME = 0x36,
|
||||||
AC97_SURR_VOLUME = 0x38,
|
AC97_SURR_VOLUME = 0x38,
|
||||||
@@ -124,7 +124,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// capabilities
|
// capabilities
|
||||||
enum {
|
enum ac97_capability {
|
||||||
CAP_PCM_MIC = 0x0000000000000001ULL, /* dedicated mic PCM channel */
|
CAP_PCM_MIC = 0x0000000000000001ULL, /* dedicated mic PCM channel */
|
||||||
CAP_BASS_TREBLE_CTRL = 0x0000000000000002ULL,
|
CAP_BASS_TREBLE_CTRL = 0x0000000000000002ULL,
|
||||||
CAP_SIMULATED_STEREO = 0x0000000000000004ULL,
|
CAP_SIMULATED_STEREO = 0x0000000000000004ULL,
|
||||||
@@ -207,6 +207,8 @@ bool ac97_reg_update_bits(ac97_dev *dev, uint8 reg, uint16 mask, uint16 value);
|
|||||||
bool ac97_set_rate(ac97_dev *dev, uint8 reg, uint32 rate);
|
bool ac97_set_rate(ac97_dev *dev, uint8 reg, uint32 rate);
|
||||||
bool ac97_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate);
|
bool ac97_get_rate(ac97_dev *dev, uint8 reg, uint32 *rate);
|
||||||
|
|
||||||
|
bool ac97_has_capability(ac97_dev *dev, uint64 cap);
|
||||||
|
|
||||||
void ac97_set_clock(ac97_dev *dev, uint32 clock);
|
void ac97_set_clock(ac97_dev *dev, uint32 clock);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -106,15 +106,68 @@ static status_t get_description(multi_description *data)
|
|||||||
memcpy(data->channels,&chans,sizeof(chans));
|
memcpy(data->channels,&chans,sizeof(chans));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)) {
|
/* determine output rates */
|
||||||
data->output_rates = B_SR_44100;
|
data->output_rates = 0;
|
||||||
data->input_rates = B_SR_44100;
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 8000))
|
||||||
data->max_cvsr_rate = 44100;
|
data->output_rates |= B_SR_8000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 11025))
|
||||||
|
data->output_rates |= B_SR_11025;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 12000))
|
||||||
|
data->output_rates |= B_SR_12000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 16000))
|
||||||
|
data->output_rates |= B_SR_16000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 22050))
|
||||||
|
data->output_rates |= B_SR_22050;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 24000))
|
||||||
|
data->output_rates |= B_SR_24000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 32000))
|
||||||
|
data->output_rates |= B_SR_32000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100))
|
||||||
|
data->output_rates |= B_SR_44100;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000))
|
||||||
|
data->output_rates |= B_SR_48000;
|
||||||
|
|
||||||
|
/* determine input rates */
|
||||||
|
data->input_rates = 0;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 8000))
|
||||||
|
data->input_rates |= B_SR_8000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 11025))
|
||||||
|
data->input_rates |= B_SR_11025;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 12000))
|
||||||
|
data->input_rates |= B_SR_12000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 16000))
|
||||||
|
data->input_rates |= B_SR_16000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 22050))
|
||||||
|
data->input_rates |= B_SR_22050;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 24000))
|
||||||
|
data->input_rates |= B_SR_24000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 32000))
|
||||||
|
data->input_rates |= B_SR_32000;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 44100))
|
||||||
|
data->input_rates |= B_SR_44100;
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 48000))
|
||||||
|
data->input_rates |= B_SR_48000;
|
||||||
|
|
||||||
|
/* try to set 44100 rate */
|
||||||
|
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)
|
||||||
|
&& ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 44100)) {
|
||||||
|
config->input_rate = B_SR_44100;
|
||||||
|
config->output_rate = B_SR_44100;
|
||||||
} else {
|
} else {
|
||||||
data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
|
/* if that didn't work, continue with 48000 */
|
||||||
data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
|
ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000);
|
||||||
data->max_cvsr_rate = 48000;
|
ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 48000);
|
||||||
|
config->input_rate = B_SR_48000;
|
||||||
|
config->output_rate = B_SR_48000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* force existance of 48kHz if variable rates are not supported */
|
||||||
|
if (data->output_rates == 0)
|
||||||
|
data->output_rates = B_SR_48000;
|
||||||
|
if (data->input_rates == 0)
|
||||||
|
data->input_rates = B_SR_48000;
|
||||||
|
|
||||||
|
data->max_cvsr_rate = 0;
|
||||||
data->min_cvsr_rate = 0;
|
data->min_cvsr_rate = 0;
|
||||||
|
|
||||||
data->output_formats = B_FMT_16BIT;
|
data->output_formats = B_FMT_16BIT;
|
||||||
@@ -122,7 +175,7 @@ static status_t get_description(multi_description *data)
|
|||||||
data->lock_sources = B_MULTI_LOCK_INTERNAL;
|
data->lock_sources = B_MULTI_LOCK_INTERNAL;
|
||||||
data->timecode_sources = 0;
|
data->timecode_sources = 0;
|
||||||
data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD;
|
data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD;
|
||||||
data->start_latency = 3000;
|
data->start_latency = 30000;
|
||||||
|
|
||||||
strcpy(data->control_panel,"");
|
strcpy(data->control_panel,"");
|
||||||
|
|
||||||
@@ -150,22 +203,93 @@ static status_t get_global_format(multi_format_info *data)
|
|||||||
data->output_latency = 0;
|
data->output_latency = 0;
|
||||||
data->input_latency = 0;
|
data->input_latency = 0;
|
||||||
data->timecode_kind = 0;
|
data->timecode_kind = 0;
|
||||||
if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)) {
|
|
||||||
data->input.rate = B_SR_44100;
|
|
||||||
data->input.cvsr = 44100;
|
|
||||||
data->output.rate = B_SR_44100;
|
|
||||||
data->output.cvsr = 44100;
|
|
||||||
} else {
|
|
||||||
data->input.rate = B_SR_48000;
|
|
||||||
data->input.cvsr = 48000;
|
|
||||||
data->output.rate = B_SR_48000;
|
|
||||||
data->output.cvsr = 48000;
|
|
||||||
}
|
|
||||||
data->input.format = B_FMT_16BIT;
|
data->input.format = B_FMT_16BIT;
|
||||||
data->output.format = B_FMT_16BIT;
|
data->output.format = B_FMT_16BIT;
|
||||||
|
data->input.rate = config->input_rate;
|
||||||
|
data->output.rate = config->output_rate;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static status_t set_global_format(multi_format_info *data)
|
||||||
|
{
|
||||||
|
bool in, out;
|
||||||
|
LOG(("set_global_format: input.rate = 0x%x\n", data->input.rate));
|
||||||
|
LOG(("set_global_format: input.cvsr = %d\n", data->input.cvsr));
|
||||||
|
LOG(("set_global_format: output.rate = 0x%x\n", data->output.rate));
|
||||||
|
LOG(("set_global_format: output.cvsr = %d\n", data->output.cvsr));
|
||||||
|
switch (data->input.rate) {
|
||||||
|
case B_SR_8000:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 8000);
|
||||||
|
break;
|
||||||
|
case B_SR_11025:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 11025);
|
||||||
|
break;
|
||||||
|
case B_SR_12000:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 12000);
|
||||||
|
break;
|
||||||
|
case B_SR_16000:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 16000);
|
||||||
|
break;
|
||||||
|
case B_SR_22050:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 22050);
|
||||||
|
break;
|
||||||
|
case B_SR_24000:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 24000);
|
||||||
|
break;
|
||||||
|
case B_SR_32000:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 32000);
|
||||||
|
break;
|
||||||
|
case B_SR_44100:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 44100);
|
||||||
|
break;
|
||||||
|
case B_SR_48000:
|
||||||
|
in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 48000);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
in = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (data->output.rate) {
|
||||||
|
case B_SR_8000:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 8000);
|
||||||
|
break;
|
||||||
|
case B_SR_11025:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 11025);
|
||||||
|
break;
|
||||||
|
case B_SR_12000:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 12000);
|
||||||
|
break;
|
||||||
|
case B_SR_16000:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 16000);
|
||||||
|
break;
|
||||||
|
case B_SR_22050:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 22050);
|
||||||
|
break;
|
||||||
|
case B_SR_24000:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 24000);
|
||||||
|
break;
|
||||||
|
case B_SR_32000:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 32000);
|
||||||
|
break;
|
||||||
|
case B_SR_44100:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
|
||||||
|
break;
|
||||||
|
case B_SR_48000:
|
||||||
|
out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
out = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in || !out)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
config->input_rate = data->input.rate;
|
||||||
|
config->output_rate = data->output.rate;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t get_buffers(multi_buffer_list *data)
|
static status_t get_buffers(multi_buffer_list *data)
|
||||||
{
|
{
|
||||||
LOG(("flags = %#x\n",data->flags));
|
LOG(("flags = %#x\n",data->flags));
|
||||||
@@ -334,6 +458,7 @@ status_t multi_control(void *cookie, uint32 op, void *data, size_t length)
|
|||||||
return get_global_format((multi_format_info *)data);
|
return get_global_format((multi_format_info *)data);
|
||||||
case B_MULTI_SET_GLOBAL_FORMAT:
|
case B_MULTI_SET_GLOBAL_FORMAT:
|
||||||
LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
|
LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
|
||||||
|
set_global_format((multi_format_info *)data);
|
||||||
return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
|
return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
|
||||||
* BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
|
* BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ typedef struct
|
|||||||
area_id area_mbbar; // ich4
|
area_id area_mbbar; // ich4
|
||||||
uint32 codecoffset;
|
uint32 codecoffset;
|
||||||
ac97_dev *ac97;
|
ac97_dev *ac97;
|
||||||
|
|
||||||
|
uint32 input_rate;
|
||||||
|
uint32 output_rate;
|
||||||
} device_config;
|
} device_config;
|
||||||
|
|
||||||
extern device_config *config;
|
extern device_config *config;
|
||||||
|
|||||||
Reference in New Issue
Block a user