/* set audio latency in in ms/2+1 */ static void set_audio_latency( const struct hw_ctx_audio *hw_ctx, int latency_in_ms) { uint32_t value = 0; if (latency_in_ms < 0) latency_in_ms = 0; if (latency_in_ms > 255) latency_in_ms = 255; value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC); set_reg_field_value(value, latency_in_ms, AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, AUDIO_LIPSYNC); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, value); }
/* set the payload value for the unsolicited response */ static void set_unsolicited_response_payload( const struct hw_ctx_audio *hw_ctx, enum audio_payload payload) { /* set the payload value for the unsolicited response Jack presence is not required to be enabled */ uint32_t value = 0; value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE); set_reg_field_value(value, payload, AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, UNSOLICITED_RESPONSE_PAYLOAD); set_reg_field_value(value, 1, AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, UNSOLICITED_RESPONSE_FORCE); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE, value); }
/* disable Azalia audio */ static void disable_azalia_audio( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id) { uint32_t value; value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL); set_reg_field_value(value, 0, AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, AUDIO_ENABLED); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value); }
/* expose/not expose HBR capability to Audio driver */ static void set_high_bit_rate_capable( const struct hw_ctx_audio *hw_ctx, bool capable) { uint32_t value = 0; /* set high bit rate audio capable*/ value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR); set_reg_field_value(value, capable, AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, HBR_CAPABLE); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, value); }
/* Disable GTC value embedding */ static void disable_gtc_embedding( const struct hw_ctx_audio *hw_ctx) { uint32_t value = 0; value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING); set_reg_field_value(value, 0, AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, PRESENTATION_TIME_EMBEDDING_ENABLE); set_reg_field_value(value, 0, AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, PRESENTATION_TIME_EMBEDDING_GROUP); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, value); }
/* Assign GTC group and enable GTC value embedding */ static void enable_gtc_embedding_with_group( const struct hw_ctx_audio *hw_ctx, uint32_t group_num, uint32_t audio_latency) { /*need to replace the static number with variable */ if (group_num <= 6) { uint32_t value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING); set_reg_field_value( value, group_num, AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, PRESENTATION_TIME_EMBEDDING_GROUP); set_reg_field_value( value, 1, AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, PRESENTATION_TIME_EMBEDDING_ENABLE); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING, value); /*update audio latency to LIPSYNC*/ set_audio_latency(hw_ctx, audio_latency); } else { dal_logger_write( hw_ctx->ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_COMPONENT_AUDIO, "GTC group number %d is too big", group_num); } }
/* enable channel splitting mapping */ static void setup_channel_splitting_mapping( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id, enum signal_type signal, const struct audio_channel_associate_info *audio_mapping, bool enable) { uint32_t value = 0; if ((audio_mapping == NULL || audio_mapping->u32all == 0) && enable) return; value = audio_mapping->u32all; if (enable == false) /*0xFFFFFFFF;*/ value = MULTI_CHANNEL_SPLIT_NO_ASSO_INFO; write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO, value); }
static void configure_azalia( const struct hw_ctx_audio *hw_ctx, enum signal_type signal, const struct audio_crtc_info *crtc_info, const struct audio_info *audio_info) { uint32_t speakers = audio_info->flags.info.ALLSPEAKERS; uint32_t value; uint32_t field = 0; enum audio_format_code audio_format_code; uint32_t format_index; uint32_t index; bool is_ac3_supported = false; bool is_audio_format_supported = false; union audio_sample_rates sample_rate; uint32_t strlen = 0; /* Speaker Allocation */ /* uint32_t value; uint32_t field = 0;*/ value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER); set_reg_field_value(value, speakers, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, SPEAKER_ALLOCATION); /* LFE_PLAYBACK_LEVEL = LFEPBL * LFEPBL = 0 : Unknown or refer to other information * LFEPBL = 1 : 0dB playback * LFEPBL = 2 : +10dB playback * LFE_BL = 3 : Reserved */ set_reg_field_value(value, 0, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, LFE_PLAYBACK_LEVEL); set_reg_field_value(value, 0, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, HDMI_CONNECTION); set_reg_field_value(value, 0, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, DP_CONNECTION); field = get_reg_field_value(value, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, EXTRA_CONNECTION_INFO); field &= ~0x1; set_reg_field_value(value, field, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, EXTRA_CONNECTION_INFO); /* set audio for output signal */ switch (signal) { case SIGNAL_TYPE_HDMI_TYPE_A: set_reg_field_value(value, 1, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, HDMI_CONNECTION); break; case SIGNAL_TYPE_WIRELESS: { /*LSB used for "is wireless" flag */ field = 0; field = get_reg_field_value(value, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, EXTRA_CONNECTION_INFO); field |= 0x1; set_reg_field_value(value, field, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, EXTRA_CONNECTION_INFO); set_reg_field_value(value, 1, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, HDMI_CONNECTION); } break; case SIGNAL_TYPE_EDP: case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT_MST: set_reg_field_value(value, 1, AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, DP_CONNECTION); break; default: break; } write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, value); /* Wireless Display identification */ value = read_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION); set_reg_field_value(value, signal == SIGNAL_TYPE_WIRELESS ? 1 : 0, AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION, WIRELESS_DISPLAY_IDENTIFICATION); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION, value); /* Audio Descriptors */ /* pass through all formats */ for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT; format_index++) { audio_format_code = (AUDIO_FORMAT_CODE_FIRST + format_index); /* those are unsupported, skip programming */ if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO || audio_format_code == AUDIO_FORMAT_CODE_DST) continue; value = 0; /* check if supported */ is_audio_format_supported = dal_audio_hw_ctx_is_audio_format_supported( hw_ctx, audio_info, audio_format_code, &index); if (is_audio_format_supported) { const struct audio_mode *audio_mode = &audio_info->modes[index]; union audio_sample_rates sample_rates = audio_mode->sample_rates; uint8_t byte2 = audio_mode->max_bit_rate; /* adjust specific properties */ switch (audio_format_code) { case AUDIO_FORMAT_CODE_LINEARPCM: { dal_hw_ctx_audio_check_audio_bandwidth( hw_ctx, crtc_info, audio_mode->channel_count, signal, &sample_rates); byte2 = audio_mode->sample_size; set_reg_field_value(value, sample_rates.all, AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, SUPPORTED_FREQUENCIES_STEREO); } break; case AUDIO_FORMAT_CODE_AC3: is_ac3_supported = true; break; case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS: case AUDIO_FORMAT_CODE_DTS_HD: case AUDIO_FORMAT_CODE_MAT_MLP: case AUDIO_FORMAT_CODE_DST: case AUDIO_FORMAT_CODE_WMAPRO: byte2 = audio_mode->vendor_specific; break; default: break; } /* fill audio format data */ set_reg_field_value(value, audio_mode->channel_count - 1, AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, MAX_CHANNELS); set_reg_field_value(value, sample_rates.all, AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, SUPPORTED_FREQUENCIES); set_reg_field_value(value, byte2, AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0, DESCRIPTOR_BYTE_2); } /* if */ write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + format_index, value); } /* for */ if (is_ac3_supported) dal_write_reg(hw_ctx->ctx, mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS, 0x05); /* check for 192khz/8-Ch support for HBR requirements */ sample_rate.all = 0; sample_rate.rate.RATE_192 = 1; dal_hw_ctx_audio_check_audio_bandwidth( hw_ctx, crtc_info, 8, signal, &sample_rate); set_high_bit_rate_capable(hw_ctx, sample_rate.rate.RATE_192); /* Audio and Video Lipsync */ set_video_latency(hw_ctx, audio_info->video_latency); set_audio_latency(hw_ctx, audio_info->audio_latency); value = 0; set_reg_field_value(value, audio_info->manufacture_id, AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, MANUFACTURER_ID); set_reg_field_value(value, audio_info->product_id, AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, PRODUCT_ID); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0, value); value = 0; /*get display name string length */ while (audio_info->display_name[strlen++] != '\0') { if (strlen >= MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS) break; } set_reg_field_value(value, strlen, AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, SINK_DESCRIPTION_LEN); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1, value); /* *write the port ID: *PORT_ID0 = display index *PORT_ID1 = 16bit BDF *(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function) */ value = 0; set_reg_field_value(value, audio_info->port_id[0], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, PORT_ID0); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, value); value = 0; set_reg_field_value(value, audio_info->port_id[1], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, PORT_ID1); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, value); /*write the 18 char monitor string */ value = 0; set_reg_field_value(value, audio_info->display_name[0], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, DESCRIPTION0); set_reg_field_value(value, audio_info->display_name[1], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, DESCRIPTION1); set_reg_field_value(value, audio_info->display_name[2], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, DESCRIPTION2); set_reg_field_value(value, audio_info->display_name[3], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, DESCRIPTION3); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, value); value = 0; set_reg_field_value(value, audio_info->display_name[4], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, DESCRIPTION4); set_reg_field_value(value, audio_info->display_name[5], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, DESCRIPTION5); set_reg_field_value(value, audio_info->display_name[6], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, DESCRIPTION6); set_reg_field_value(value, audio_info->display_name[7], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, DESCRIPTION7); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, value); value = 0; set_reg_field_value(value, audio_info->display_name[8], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, DESCRIPTION8); set_reg_field_value(value, audio_info->display_name[9], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, DESCRIPTION9); set_reg_field_value(value, audio_info->display_name[10], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, DESCRIPTION10); set_reg_field_value(value, audio_info->display_name[11], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, DESCRIPTION11); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, value); value = 0; set_reg_field_value(value, audio_info->display_name[12], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, DESCRIPTION12); set_reg_field_value(value, audio_info->display_name[13], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, DESCRIPTION13); set_reg_field_value(value, audio_info->display_name[14], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, DESCRIPTION14); set_reg_field_value(value, audio_info->display_name[15], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, DESCRIPTION15); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, value); value = 0; set_reg_field_value(value, audio_info->display_name[16], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, DESCRIPTION16); set_reg_field_value(value, audio_info->display_name[17], AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, DESCRIPTION17); write_indirect_azalia_reg( hw_ctx, ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, value); }