Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2020 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  *  and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 
0027 #include "dc_bios_types.h"
0028 #include "hw_shared.h"
0029 #include "dcn30_afmt.h"
0030 #include "reg_helper.h"
0031 
0032 #define DC_LOGGER \
0033         afmt3->base.ctx->logger
0034 
0035 #define REG(reg)\
0036     (afmt3->regs->reg)
0037 
0038 #undef FN
0039 #define FN(reg_name, field_name) \
0040     afmt3->afmt_shift->field_name, afmt3->afmt_mask->field_name
0041 
0042 
0043 #define CTX \
0044     afmt3->base.ctx
0045 
0046 
0047 void afmt3_setup_hdmi_audio(
0048     struct afmt *afmt)
0049 {
0050     struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt);
0051 
0052     if (afmt->funcs->afmt_poweron)
0053         afmt->funcs->afmt_poweron(afmt);
0054 
0055     /* AFMT_AUDIO_PACKET_CONTROL */
0056     REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1);
0057 
0058     /* AFMT_AUDIO_PACKET_CONTROL2 */
0059     REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2,
0060             AFMT_AUDIO_LAYOUT_OVRD, 0,
0061             AFMT_60958_OSF_OVRD, 0);
0062 
0063     /* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK &
0064      * AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK
0065      */
0066     REG_UPDATE_2(AFMT_60958_0,
0067             AFMT_60958_CS_CHANNEL_NUMBER_L, 1,
0068             AFMT_60958_CS_CLOCK_ACCURACY, 0);
0069 
0070     /* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */
0071     REG_UPDATE(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, 2);
0072 
0073     /* AFMT_60958_2 now keep this settings until
0074      * Programming guide comes out
0075      */
0076     REG_UPDATE_6(AFMT_60958_2,
0077             AFMT_60958_CS_CHANNEL_NUMBER_2, 3,
0078             AFMT_60958_CS_CHANNEL_NUMBER_3, 4,
0079             AFMT_60958_CS_CHANNEL_NUMBER_4, 5,
0080             AFMT_60958_CS_CHANNEL_NUMBER_5, 6,
0081             AFMT_60958_CS_CHANNEL_NUMBER_6, 7,
0082             AFMT_60958_CS_CHANNEL_NUMBER_7, 8);
0083 }
0084 
0085 static union audio_cea_channels speakers_to_channels(
0086     struct audio_speaker_flags speaker_flags)
0087 {
0088     union audio_cea_channels cea_channels = {0};
0089 
0090     /* these are one to one */
0091     cea_channels.channels.FL = speaker_flags.FL_FR;
0092     cea_channels.channels.FR = speaker_flags.FL_FR;
0093     cea_channels.channels.LFE = speaker_flags.LFE;
0094     cea_channels.channels.FC = speaker_flags.FC;
0095 
0096     /* if Rear Left and Right exist move RC speaker to channel 7
0097      * otherwise to channel 5
0098      */
0099     if (speaker_flags.RL_RR) {
0100         cea_channels.channels.RL_RC = speaker_flags.RL_RR;
0101         cea_channels.channels.RR = speaker_flags.RL_RR;
0102         cea_channels.channels.RC_RLC_FLC = speaker_flags.RC;
0103     } else {
0104         cea_channels.channels.RL_RC = speaker_flags.RC;
0105     }
0106 
0107     /* FRONT Left Right Center and REAR Left Right Center are exclusive */
0108     if (speaker_flags.FLC_FRC) {
0109         cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC;
0110         cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC;
0111     } else {
0112         cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC;
0113         cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC;
0114     }
0115 
0116     return cea_channels;
0117 }
0118 
0119 void afmt3_se_audio_setup(
0120     struct afmt *afmt,
0121     unsigned int az_inst,
0122     struct audio_info *audio_info)
0123 {
0124     struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt);
0125 
0126     uint32_t speakers = 0;
0127     uint32_t channels = 0;
0128 
0129     ASSERT(audio_info);
0130     /* This should not happen.it does so we don't get BSOD*/
0131     if (audio_info == NULL)
0132         return;
0133 
0134     speakers = audio_info->flags.info.ALLSPEAKERS;
0135     channels = speakers_to_channels(audio_info->flags.speaker_flags).all;
0136 
0137     /* setup the audio stream source select (audio -> dig mapping) */
0138     REG_SET(AFMT_AUDIO_SRC_CONTROL, 0, AFMT_AUDIO_SRC_SELECT, az_inst);
0139 
0140     /* Channel allocation */
0141     REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels);
0142 
0143     /* Disable forced mem power off */
0144     if (afmt->funcs->afmt_poweron == NULL)
0145         REG_UPDATE(AFMT_MEM_PWR, AFMT_MEM_PWR_FORCE, 0);
0146 }
0147 
0148 void afmt3_audio_mute_control(
0149     struct afmt *afmt,
0150     bool mute)
0151 {
0152     struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt);
0153     if (mute && afmt->funcs->afmt_powerdown)
0154         afmt->funcs->afmt_powerdown(afmt);
0155     if (!mute && afmt->funcs->afmt_poweron)
0156         afmt->funcs->afmt_poweron(afmt);
0157     /* enable/disable transmission of audio packets */
0158     REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute);
0159 }
0160 
0161 void afmt3_audio_info_immediate_update(
0162     struct afmt *afmt)
0163 {
0164     struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt);
0165 
0166     /* update double-buffered AUDIO_INFO registers immediately */
0167     REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1);
0168 }
0169 
0170 void afmt3_setup_dp_audio(
0171         struct afmt *afmt)
0172 {
0173     struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt);
0174 
0175     if (afmt->funcs->afmt_poweron)
0176         afmt->funcs->afmt_poweron(afmt);
0177 
0178     /* AFMT_AUDIO_PACKET_CONTROL */
0179     REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1);
0180 
0181     /* AFMT_AUDIO_PACKET_CONTROL2 */
0182     /* Program the ATP and AIP next */
0183     REG_UPDATE_2(AFMT_AUDIO_PACKET_CONTROL2,
0184             AFMT_AUDIO_LAYOUT_OVRD, 0,
0185             AFMT_60958_OSF_OVRD, 0);
0186 
0187     /* AFMT_INFOFRAME_CONTROL0 */
0188     REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1);
0189 
0190     /* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
0191     REG_UPDATE(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, 0);
0192 }
0193 
0194 static struct afmt_funcs dcn30_afmt_funcs = {
0195     .setup_hdmi_audio       = afmt3_setup_hdmi_audio,
0196     .se_audio_setup         = afmt3_se_audio_setup,
0197     .audio_mute_control     = afmt3_audio_mute_control,
0198     .audio_info_immediate_update    = afmt3_audio_info_immediate_update,
0199     .setup_dp_audio         = afmt3_setup_dp_audio,
0200 };
0201 
0202 void afmt3_construct(struct dcn30_afmt *afmt3,
0203     struct dc_context *ctx,
0204     uint32_t inst,
0205     const struct dcn30_afmt_registers *afmt_regs,
0206     const struct dcn30_afmt_shift *afmt_shift,
0207     const struct dcn30_afmt_mask *afmt_mask)
0208 {
0209     afmt3->base.ctx = ctx;
0210 
0211     afmt3->base.inst = inst;
0212     afmt3->base.funcs = &dcn30_afmt_funcs;
0213 
0214     afmt3->regs = afmt_regs;
0215     afmt3->afmt_shift = afmt_shift;
0216     afmt3->afmt_mask = afmt_mask;
0217 }