mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	ALSA: x86: intel_hdmi: add definitions and logic for DP audio
Imported from legacy patches Note: the new code doesn't assume a modified ELD but an explicit notification that DP is present. It appears that the i915 code does change the ELD so we could use the ELD-based tests to check for DP audio Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									f95e29b921
								
							
						
					
					
						commit
						964ca8083c
					
				
					 4 changed files with 216 additions and 30 deletions
				
			
		| 
						 | 
					@ -396,6 +396,7 @@ static int snd_intelhad_prog_audio_ctrl_v2(struct snd_pcm_substream *substream,
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		cfg_val.cfg_regx_v2.layout = LAYOUT1;
 | 
							cfg_val.cfg_regx_v2.layout = LAYOUT1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg_val.cfg_regx_v2.val_bit = 1;
 | 
				
			||||||
	had_write_register(AUD_CONFIG, cfg_val.cfg_regval);
 | 
						had_write_register(AUD_CONFIG, cfg_val.cfg_regval);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -447,6 +448,7 @@ static int snd_intelhad_prog_audio_ctrl_v1(struct snd_pcm_substream *substream,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cfg_val.cfg_regx.val_bit = 1;
 | 
				
			||||||
	had_write_register(AUD_CONFIG, cfg_val.cfg_regval);
 | 
						had_write_register(AUD_CONFIG, cfg_val.cfg_regval);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -548,6 +550,7 @@ void had_build_channel_allocation_map(struct snd_intelhad *intelhaddata)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	had_get_caps(HAD_GET_ELD, &intelhaddata->eeld);
 | 
						had_get_caps(HAD_GET_ELD, &intelhaddata->eeld);
 | 
				
			||||||
 | 
						had_get_caps(HAD_GET_DP_OUTPUT, &intelhaddata->dp_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_debug("eeld.speaker_allocation_block = %x\n",
 | 
						pr_debug("eeld.speaker_allocation_block = %x\n",
 | 
				
			||||||
			intelhaddata->eeld.speaker_allocation_block);
 | 
								intelhaddata->eeld.speaker_allocation_block);
 | 
				
			||||||
| 
						 | 
					@ -685,7 +688,7 @@ static void snd_intelhad_prog_dip_v1(struct snd_pcm_substream *substream,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*Calculte the byte wide checksum for all valid DIP words*/
 | 
						/*Calculte the byte wide checksum for all valid DIP words*/
 | 
				
			||||||
	for (i = 0; i < BYTES_PER_WORD; i++)
 | 
						for (i = 0; i < BYTES_PER_WORD; i++)
 | 
				
			||||||
		checksum += (INFO_FRAME_WORD1 >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
							checksum += (HDMI_INFO_FRAME_WORD1 >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
				
			||||||
	for (i = 0; i < BYTES_PER_WORD; i++)
 | 
						for (i = 0; i < BYTES_PER_WORD; i++)
 | 
				
			||||||
		checksum += (frame2.fr2_val >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
							checksum += (frame2.fr2_val >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
				
			||||||
	for (i = 0; i < BYTES_PER_WORD; i++)
 | 
						for (i = 0; i < BYTES_PER_WORD; i++)
 | 
				
			||||||
| 
						 | 
					@ -693,7 +696,7 @@ static void snd_intelhad_prog_dip_v1(struct snd_pcm_substream *substream,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	frame2.fr2_regx.chksum = -(checksum);
 | 
						frame2.fr2_regx.chksum = -(checksum);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	had_write_register(AUD_HDMIW_INFOFR, INFO_FRAME_WORD1);
 | 
						had_write_register(AUD_HDMIW_INFOFR, HDMI_INFO_FRAME_WORD1);
 | 
				
			||||||
	had_write_register(AUD_HDMIW_INFOFR, frame2.fr2_val);
 | 
						had_write_register(AUD_HDMIW_INFOFR, frame2.fr2_val);
 | 
				
			||||||
	had_write_register(AUD_HDMIW_INFOFR, frame3.fr3_val);
 | 
						had_write_register(AUD_HDMIW_INFOFR, frame3.fr3_val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -722,28 +725,35 @@ static void snd_intelhad_prog_dip_v2(struct snd_pcm_substream *substream,
 | 
				
			||||||
	union aud_info_frame2 frame2 = {.fr2_val = 0};
 | 
						union aud_info_frame2 frame2 = {.fr2_val = 0};
 | 
				
			||||||
	union aud_info_frame3 frame3 = {.fr3_val = 0};
 | 
						union aud_info_frame3 frame3 = {.fr3_val = 0};
 | 
				
			||||||
	u8 checksum = 0;
 | 
						u8 checksum = 0;
 | 
				
			||||||
 | 
						u32 info_frame;
 | 
				
			||||||
	int channels;
 | 
						int channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	channels = substream->runtime->channels;
 | 
						channels = substream->runtime->channels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	had_write_register(AUD_CNTL_ST, ctrl_state.ctrl_val);
 | 
						had_write_register(AUD_CNTL_ST, ctrl_state.ctrl_val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	frame2.fr2_regx.chnl_cnt = substream->runtime->channels - 1;
 | 
						if (intelhaddata->dp_output) {
 | 
				
			||||||
 | 
							info_frame = DP_INFO_FRAME_WORD1;
 | 
				
			||||||
 | 
							frame2.fr2_val = 1;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							info_frame = HDMI_INFO_FRAME_WORD1;
 | 
				
			||||||
 | 
							frame2.fr2_regx.chnl_cnt = substream->runtime->channels - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	frame3.fr3_regx.chnl_alloc = snd_intelhad_channel_allocation(
 | 
							frame3.fr3_regx.chnl_alloc = snd_intelhad_channel_allocation(
 | 
				
			||||||
					intelhaddata, channels);
 | 
								intelhaddata, channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*Calculte the byte wide checksum for all valid DIP words*/
 | 
							/*Calculte the byte wide checksum for all valid DIP words*/
 | 
				
			||||||
	for (i = 0; i < BYTES_PER_WORD; i++)
 | 
							for (i = 0; i < BYTES_PER_WORD; i++)
 | 
				
			||||||
		checksum += (INFO_FRAME_WORD1 >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
								checksum += (info_frame >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
				
			||||||
	for (i = 0; i < BYTES_PER_WORD; i++)
 | 
							for (i = 0; i < BYTES_PER_WORD; i++)
 | 
				
			||||||
		checksum += (frame2.fr2_val >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
								checksum += (frame2.fr2_val >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
				
			||||||
	for (i = 0; i < BYTES_PER_WORD; i++)
 | 
							for (i = 0; i < BYTES_PER_WORD; i++)
 | 
				
			||||||
		checksum += (frame3.fr3_val >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
								checksum += (frame3.fr3_val >> i*BITS_PER_BYTE) & MASK_BYTE0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	frame2.fr2_regx.chksum = -(checksum);
 | 
							frame2.fr2_regx.chksum = -(checksum);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	had_write_register(AUD_HDMIW_INFOFR_v2, INFO_FRAME_WORD1);
 | 
						had_write_register(AUD_HDMIW_INFOFR_v2, info_frame);
 | 
				
			||||||
	had_write_register(AUD_HDMIW_INFOFR_v2, frame2.fr2_val);
 | 
						had_write_register(AUD_HDMIW_INFOFR_v2, frame2.fr2_val);
 | 
				
			||||||
	had_write_register(AUD_HDMIW_INFOFR_v2, frame3.fr3_val);
 | 
						had_write_register(AUD_HDMIW_INFOFR_v2, frame3.fr3_val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -839,6 +849,85 @@ int snd_intelhad_read_len(struct snd_intelhad *intelhaddata)
 | 
				
			||||||
	return retval;
 | 
						return retval;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int had_calculate_maud_value(u32 aud_samp_freq, u32 link_rate)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 maud_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Select maud according to DP 1.2 spec*/
 | 
				
			||||||
 | 
						if (link_rate == DP_2_7_GHZ) {
 | 
				
			||||||
 | 
							switch (aud_samp_freq) {
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_32:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_44_1:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_48:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_88_2:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_96:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_176_4:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case HAD_MAX_RATE:
 | 
				
			||||||
 | 
								maud_val = HAD_MAX_RATE_DP_2_7_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								maud_val = -EINVAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (link_rate == DP_1_62_GHZ) {
 | 
				
			||||||
 | 
							switch (aud_samp_freq) {
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_32:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_44_1:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_48:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_88_2:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_96:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case AUD_SAMPLE_RATE_176_4:
 | 
				
			||||||
 | 
								maud_val = AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case HAD_MAX_RATE:
 | 
				
			||||||
 | 
								maud_val = HAD_MAX_RATE_DP_1_62_MAUD_VAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								maud_val = -EINVAL;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							maud_val = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return maud_val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * snd_intelhad_prog_cts_v1 - Program HDMI audio CTS value
 | 
					 * snd_intelhad_prog_cts_v1 - Program HDMI audio CTS value
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -849,8 +938,9 @@ int snd_intelhad_read_len(struct snd_intelhad *intelhaddata)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Program CTS register based on the audio and display sampling frequency
 | 
					 * Program CTS register based on the audio and display sampling frequency
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void snd_intelhad_prog_cts_v1(u32 aud_samp_freq, u32 tmds, u32 n_param,
 | 
					static void snd_intelhad_prog_cts_v1(u32 aud_samp_freq, u32 tmds,
 | 
				
			||||||
				struct snd_intelhad *intelhaddata)
 | 
									     u32 link_rate, u32 n_param,
 | 
				
			||||||
 | 
									     struct snd_intelhad *intelhaddata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 cts_val;
 | 
						u32 cts_val;
 | 
				
			||||||
	u64 dividend, divisor;
 | 
						u64 dividend, divisor;
 | 
				
			||||||
| 
						 | 
					@ -874,18 +964,24 @@ static void snd_intelhad_prog_cts_v1(u32 aud_samp_freq, u32 tmds, u32 n_param,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Program CTS register based on the audio and display sampling frequency
 | 
					 * Program CTS register based on the audio and display sampling frequency
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void snd_intelhad_prog_cts_v2(u32 aud_samp_freq, u32 tmds, u32 n_param,
 | 
					static void snd_intelhad_prog_cts_v2(u32 aud_samp_freq, u32 tmds,
 | 
				
			||||||
				struct snd_intelhad *intelhaddata)
 | 
									     u32 link_rate, u32 n_param,
 | 
				
			||||||
 | 
									     struct snd_intelhad *intelhaddata)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u32 cts_val;
 | 
						u32 cts_val;
 | 
				
			||||||
	u64 dividend, divisor;
 | 
						u64 dividend, divisor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Calculate CTS according to HDMI 1.3a spec*/
 | 
						if (intelhaddata->dp_output) {
 | 
				
			||||||
	dividend = (u64)tmds * n_param*1000;
 | 
							/* Substitute cts_val with Maud according to DP 1.2 spec*/
 | 
				
			||||||
	divisor = 128 * aud_samp_freq;
 | 
							cts_val = had_calculate_maud_value(aud_samp_freq, link_rate);
 | 
				
			||||||
	cts_val = div64_u64(dividend, divisor);
 | 
						} else {
 | 
				
			||||||
 | 
							/* Calculate CTS according to HDMI 1.3a spec*/
 | 
				
			||||||
 | 
							dividend = (u64)tmds * n_param*1000;
 | 
				
			||||||
 | 
							divisor = 128 * aud_samp_freq;
 | 
				
			||||||
 | 
							cts_val = div64_u64(dividend, divisor);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	pr_debug("TMDS value=%d, N value=%d, CTS Value=%d\n",
 | 
						pr_debug("TMDS value=%d, N value=%d, CTS Value=%d\n",
 | 
				
			||||||
			tmds, n_param, cts_val);
 | 
							 tmds, n_param, cts_val);
 | 
				
			||||||
	had_write_register(AUD_HDMI_CTS, (BIT(24) | cts_val));
 | 
						had_write_register(AUD_HDMI_CTS, (BIT(24) | cts_val));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -970,7 +1066,18 @@ static int snd_intelhad_prog_n_v2(u32 aud_samp_freq, u32 *n_param,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	s32 n_val;
 | 
						s32 n_val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	n_val =	had_calculate_n_value(aud_samp_freq);
 | 
						if (intelhaddata->dp_output) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * According to DP specs, Maud and Naud values hold
 | 
				
			||||||
 | 
							 * a relationship, which is stated as:
 | 
				
			||||||
 | 
							 * Maud/Naud = 512 * fs / f_LS_Clk
 | 
				
			||||||
 | 
							 * where, fs is the sampling frequency of the audio stream
 | 
				
			||||||
 | 
							 * and Naud is 32768 for Async clock.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							n_val = DP_NAUD_VAL;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							n_val =	had_calculate_n_value(aud_samp_freq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (n_val < 0)
 | 
						if (n_val < 0)
 | 
				
			||||||
		return n_val;
 | 
							return n_val;
 | 
				
			||||||
| 
						 | 
					@ -1343,6 +1450,7 @@ static int snd_intelhad_pcm_prepare(struct snd_pcm_substream *substream)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int retval;
 | 
						int retval;
 | 
				
			||||||
	u32 disp_samp_freq, n_param;
 | 
						u32 disp_samp_freq, n_param;
 | 
				
			||||||
 | 
						u32 link_rate = 0;
 | 
				
			||||||
	struct snd_intelhad *intelhaddata;
 | 
						struct snd_intelhad *intelhaddata;
 | 
				
			||||||
	struct snd_pcm_runtime *runtime;
 | 
						struct snd_pcm_runtime *runtime;
 | 
				
			||||||
	struct had_pvt_data *had_stream;
 | 
						struct had_pvt_data *had_stream;
 | 
				
			||||||
| 
						 | 
					@ -1387,6 +1495,7 @@ static int snd_intelhad_pcm_prepare(struct snd_pcm_substream *substream)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	had_get_caps(HAD_GET_ELD, &intelhaddata->eeld);
 | 
						had_get_caps(HAD_GET_ELD, &intelhaddata->eeld);
 | 
				
			||||||
 | 
						had_get_caps(HAD_GET_DP_OUTPUT, &intelhaddata->dp_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = intelhaddata->ops->prog_n(substream->runtime->rate, &n_param,
 | 
						retval = intelhaddata->ops->prog_n(substream->runtime->rate, &n_param,
 | 
				
			||||||
								intelhaddata);
 | 
													intelhaddata);
 | 
				
			||||||
| 
						 | 
					@ -1394,8 +1503,14 @@ static int snd_intelhad_pcm_prepare(struct snd_pcm_substream *substream)
 | 
				
			||||||
		pr_err("programming N value failed %#x\n", retval);
 | 
							pr_err("programming N value failed %#x\n", retval);
 | 
				
			||||||
		goto prep_end;
 | 
							goto prep_end;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (intelhaddata->dp_output)
 | 
				
			||||||
 | 
							had_get_caps(HAD_GET_LINK_RATE, &link_rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	intelhaddata->ops->prog_cts(substream->runtime->rate,
 | 
						intelhaddata->ops->prog_cts(substream->runtime->rate,
 | 
				
			||||||
					disp_samp_freq, n_param, intelhaddata);
 | 
									    disp_samp_freq, link_rate,
 | 
				
			||||||
 | 
									    n_param, intelhaddata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	intelhaddata->ops->prog_dip(substream, intelhaddata);
 | 
						intelhaddata->ops->prog_dip(substream, intelhaddata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1503,6 +1618,7 @@ int hdmi_audio_mode_change(struct snd_pcm_substream *substream)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int retval = 0;
 | 
						int retval = 0;
 | 
				
			||||||
	u32 disp_samp_freq, n_param;
 | 
						u32 disp_samp_freq, n_param;
 | 
				
			||||||
 | 
						u32 link_rate = 0;
 | 
				
			||||||
	struct snd_intelhad *intelhaddata;
 | 
						struct snd_intelhad *intelhaddata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	intelhaddata = snd_pcm_substream_chip(substream);
 | 
						intelhaddata = snd_pcm_substream_chip(substream);
 | 
				
			||||||
| 
						 | 
					@ -1523,8 +1639,13 @@ int hdmi_audio_mode_change(struct snd_pcm_substream *substream)
 | 
				
			||||||
		pr_err("programming N value failed %#x\n", retval);
 | 
							pr_err("programming N value failed %#x\n", retval);
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (intelhaddata->dp_output)
 | 
				
			||||||
 | 
							had_get_caps(HAD_GET_LINK_RATE, &link_rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	intelhaddata->ops->prog_cts(substream->runtime->rate,
 | 
						intelhaddata->ops->prog_cts(substream->runtime->rate,
 | 
				
			||||||
					disp_samp_freq, n_param, intelhaddata);
 | 
									    disp_samp_freq, link_rate,
 | 
				
			||||||
 | 
									    n_param, intelhaddata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable Audio */
 | 
						/* Enable Audio */
 | 
				
			||||||
	intelhaddata->ops->enable_audio(substream, 1);
 | 
						intelhaddata->ops->enable_audio(substream, 1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,8 @@
 | 
				
			||||||
#define MAX_CAP_STREAMS		0
 | 
					#define MAX_CAP_STREAMS		0
 | 
				
			||||||
#define HDMI_AUDIO_DRIVER	"hdmi-audio"
 | 
					#define HDMI_AUDIO_DRIVER	"hdmi-audio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define INFO_FRAME_WORD1	0x000a0184
 | 
					#define HDMI_INFO_FRAME_WORD1	0x000a0184
 | 
				
			||||||
 | 
					#define DP_INFO_FRAME_WORD1	0x00441b84
 | 
				
			||||||
#define FIFO_THRESHOLD		0xFE
 | 
					#define FIFO_THRESHOLD		0xFE
 | 
				
			||||||
#define DMA_FIFO_THRESHOLD	0x7
 | 
					#define DMA_FIFO_THRESHOLD	0x7
 | 
				
			||||||
#define BYTES_PER_WORD		0x4
 | 
					#define BYTES_PER_WORD		0x4
 | 
				
			||||||
| 
						 | 
					@ -134,6 +135,7 @@ struct snd_intelhad {
 | 
				
			||||||
	struct		ring_buf_info buf_info[HAD_NUM_OF_RING_BUFS];
 | 
						struct		ring_buf_info buf_info[HAD_NUM_OF_RING_BUFS];
 | 
				
			||||||
	struct		pcm_stream_info stream_info;
 | 
						struct		pcm_stream_info stream_info;
 | 
				
			||||||
	union otm_hdmi_eld_t	eeld;
 | 
						union otm_hdmi_eld_t	eeld;
 | 
				
			||||||
 | 
						bool dp_output;
 | 
				
			||||||
	enum		intel_had_aud_buf_type curr_buf;
 | 
						enum		intel_had_aud_buf_type curr_buf;
 | 
				
			||||||
	int		valid_buf_cnt;
 | 
						int		valid_buf_cnt;
 | 
				
			||||||
	unsigned int	aes_bits;
 | 
						unsigned int	aes_bits;
 | 
				
			||||||
| 
						 | 
					@ -156,8 +158,8 @@ struct had_ops {
 | 
				
			||||||
	void (*reset_audio)(u8 reset);
 | 
						void (*reset_audio)(u8 reset);
 | 
				
			||||||
	int (*prog_n)(u32 aud_samp_freq, u32 *n_param,
 | 
						int (*prog_n)(u32 aud_samp_freq, u32 *n_param,
 | 
				
			||||||
			struct snd_intelhad *intelhaddata);
 | 
								struct snd_intelhad *intelhaddata);
 | 
				
			||||||
	void (*prog_cts)(u32 aud_samp_freq, u32 tmds, u32 n_param,
 | 
						void (*prog_cts)(u32 aud_samp_freq, u32 tmds, u32 link_rate,
 | 
				
			||||||
			struct snd_intelhad *intelhaddata);
 | 
								 u32 n_param, struct snd_intelhad *intelhaddata);
 | 
				
			||||||
	int (*audio_ctrl)(struct snd_pcm_substream *substream,
 | 
						int (*audio_ctrl)(struct snd_pcm_substream *substream,
 | 
				
			||||||
				struct snd_intelhad *intelhaddata);
 | 
									struct snd_intelhad *intelhaddata);
 | 
				
			||||||
	void (*prog_dip)(struct snd_pcm_substream *substream,
 | 
						void (*prog_dip)(struct snd_pcm_substream *substream,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,6 +48,8 @@ struct hdmi_lpe_audio_ctx {
 | 
				
			||||||
	struct snd_intel_had_interface *had_interface;
 | 
						struct snd_intel_had_interface *had_interface;
 | 
				
			||||||
	void *had_pvt_data;
 | 
						void *had_pvt_data;
 | 
				
			||||||
	int tmds_clock_speed;
 | 
						int tmds_clock_speed;
 | 
				
			||||||
 | 
						bool dp_output;
 | 
				
			||||||
 | 
						int link_rate;
 | 
				
			||||||
	unsigned int had_config_offset;
 | 
						unsigned int had_config_offset;
 | 
				
			||||||
	int hdmi_audio_interrupt_mask;
 | 
						int hdmi_audio_interrupt_mask;
 | 
				
			||||||
	struct work_struct hdmi_audio_wq;
 | 
						struct work_struct hdmi_audio_wq;
 | 
				
			||||||
| 
						 | 
					@ -187,6 +189,15 @@ static int hdmi_audio_write(u32 reg, u32 val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_dbg(&hlpe_pdev->dev, "%s: reg[0x%x] = 0x%x\n", __func__, reg, val);
 | 
						dev_dbg(&hlpe_pdev->dev, "%s: reg[0x%x] = 0x%x\n", __func__, reg, val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ctx->dp_output) {
 | 
				
			||||||
 | 
							if ((reg == AUDIO_HDMI_CONFIG_A) ||
 | 
				
			||||||
 | 
							    (reg == AUDIO_HDMI_CONFIG_B) ||
 | 
				
			||||||
 | 
							    (reg == AUDIO_HDMI_CONFIG_C)) {
 | 
				
			||||||
 | 
								if (val & AUD_CONFIG_VALID_BIT)
 | 
				
			||||||
 | 
									val = val | AUD_CONFIG_DP_MODE |
 | 
				
			||||||
 | 
										AUD_CONFIG_BLOCK_BIT;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	iowrite32(val, (ctx->mmio_start+reg));
 | 
						iowrite32(val, (ctx->mmio_start+reg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -220,6 +231,16 @@ static int hdmi_audio_rmw(u32 reg, u32 val, u32 mask)
 | 
				
			||||||
	val_tmp = (val & mask) |
 | 
						val_tmp = (val & mask) |
 | 
				
			||||||
			((ioread32(ctx->mmio_start + reg)) & ~mask);
 | 
								((ioread32(ctx->mmio_start + reg)) & ~mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ctx->dp_output) {
 | 
				
			||||||
 | 
							if ((reg == AUDIO_HDMI_CONFIG_A) ||
 | 
				
			||||||
 | 
							    (reg == AUDIO_HDMI_CONFIG_B) ||
 | 
				
			||||||
 | 
							    (reg == AUDIO_HDMI_CONFIG_C)) {
 | 
				
			||||||
 | 
								if (val_tmp & AUD_CONFIG_VALID_BIT)
 | 
				
			||||||
 | 
									val_tmp = val_tmp | AUD_CONFIG_DP_MODE |
 | 
				
			||||||
 | 
										AUD_CONFIG_BLOCK_BIT;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	iowrite32(val_tmp, (ctx->mmio_start+reg));
 | 
						iowrite32(val_tmp, (ctx->mmio_start+reg));
 | 
				
			||||||
	dev_dbg(&hlpe_pdev->dev, "%s: reg[0x%x] = 0x%x\n", __func__,
 | 
						dev_dbg(&hlpe_pdev->dev, "%s: reg[0x%x] = 0x%x\n", __func__,
 | 
				
			||||||
				reg, val_tmp);
 | 
									reg, val_tmp);
 | 
				
			||||||
| 
						 | 
					@ -249,7 +270,18 @@ static int hdmi_audio_get_caps(enum had_caps_list get_element,
 | 
				
			||||||
		/* ToDo: Verify if sampling freq logic is correct */
 | 
							/* ToDo: Verify if sampling freq logic is correct */
 | 
				
			||||||
		*(u32 *)capabilities = ctx->tmds_clock_speed;
 | 
							*(u32 *)capabilities = ctx->tmds_clock_speed;
 | 
				
			||||||
		dev_dbg(&hlpe_pdev->dev, "%s: tmds_clock_speed = 0x%x\n",
 | 
							dev_dbg(&hlpe_pdev->dev, "%s: tmds_clock_speed = 0x%x\n",
 | 
				
			||||||
				__func__, ctx->tmds_clock_speed);
 | 
								__func__, ctx->tmds_clock_speed);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case HAD_GET_LINK_RATE:
 | 
				
			||||||
 | 
							/* ToDo: Verify if sampling freq logic is correct */
 | 
				
			||||||
 | 
							*(u32 *)capabilities = ctx->link_rate;
 | 
				
			||||||
 | 
							dev_dbg(&hlpe_pdev->dev, "%s: link rate = 0x%x\n",
 | 
				
			||||||
 | 
								__func__, ctx->link_rate);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case HAD_GET_DP_OUTPUT:
 | 
				
			||||||
 | 
							*(u32 *)capabilities = ctx->dp_output;
 | 
				
			||||||
 | 
							dev_dbg(&hlpe_pdev->dev, "%s: dp_output = %d\n",
 | 
				
			||||||
 | 
								__func__, ctx->dp_output);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -442,6 +474,8 @@ static void notify_audio_lpe(void *audio_ptr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pdata->tmds_clock_speed) {
 | 
							if (pdata->tmds_clock_speed) {
 | 
				
			||||||
			ctx->tmds_clock_speed = pdata->tmds_clock_speed;
 | 
								ctx->tmds_clock_speed = pdata->tmds_clock_speed;
 | 
				
			||||||
 | 
								ctx->dp_output = pdata->dp_output;
 | 
				
			||||||
 | 
								ctx->link_rate = pdata->link_rate;
 | 
				
			||||||
			mid_hdmi_audio_signal_event(HAD_EVENT_MODE_CHANGING);
 | 
								mid_hdmi_audio_signal_event(HAD_EVENT_MODE_CHANGING);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,10 @@
 | 
				
			||||||
#include <sound/control.h>
 | 
					#include <sound/control.h>
 | 
				
			||||||
#include <sound/pcm.h>
 | 
					#include <sound/pcm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define AUD_CONFIG_VALID_BIT			(1<<9)
 | 
				
			||||||
 | 
					#define AUD_CONFIG_DP_MODE			(1<<15)
 | 
				
			||||||
 | 
					#define AUD_CONFIG_BLOCK_BIT			(1<<7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HMDI_LPE_AUDIO_DRIVER_NAME		"intel-hdmi-lpe-audio"
 | 
					#define HMDI_LPE_AUDIO_DRIVER_NAME		"intel-hdmi-lpe-audio"
 | 
				
			||||||
#define HAD_MAX_DEVICES		1
 | 
					#define HAD_MAX_DEVICES		1
 | 
				
			||||||
#define HAD_MIN_CHANNEL		2
 | 
					#define HAD_MIN_CHANNEL		2
 | 
				
			||||||
| 
						 | 
					@ -68,6 +72,29 @@
 | 
				
			||||||
#define HAD_MAX_DIP_WORDS		16
 | 
					#define HAD_MAX_DIP_WORDS		16
 | 
				
			||||||
#define INTEL_HAD		"IntelHdmiLpeAudio"
 | 
					#define INTEL_HAD		"IntelHdmiLpeAudio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DP Link Rates */
 | 
				
			||||||
 | 
					#define DP_2_7_GHZ			270000
 | 
				
			||||||
 | 
					#define DP_1_62_GHZ			162000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maud Values */
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_32_DP_2_7_MAUD_VAL		1988
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_44_1_DP_2_7_MAUD_VAL		2740
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_48_DP_2_7_MAUD_VAL		2982
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_88_2_DP_2_7_MAUD_VAL		5480
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_96_DP_2_7_MAUD_VAL		5965
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_176_4_DP_2_7_MAUD_VAL		10961
 | 
				
			||||||
 | 
					#define HAD_MAX_RATE_DP_2_7_MAUD_VAL			11930
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_32_DP_1_62_MAUD_VAL		3314
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_44_1_DP_1_62_MAUD_VAL		4567
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_48_DP_1_62_MAUD_VAL		4971
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_88_2_DP_1_62_MAUD_VAL		9134
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_96_DP_1_62_MAUD_VAL		9942
 | 
				
			||||||
 | 
					#define AUD_SAMPLE_RATE_176_4_DP_1_62_MAUD_VAL		18268
 | 
				
			||||||
 | 
					#define HAD_MAX_RATE_DP_1_62_MAUD_VAL			19884
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Naud Value */
 | 
				
			||||||
 | 
					#define DP_NAUD_VAL					32768
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* _AUD_CONFIG register MASK */
 | 
					/* _AUD_CONFIG register MASK */
 | 
				
			||||||
#define AUD_CONFIG_MASK_UNDERRUN	0xC0000000
 | 
					#define AUD_CONFIG_MASK_UNDERRUN	0xC0000000
 | 
				
			||||||
#define AUD_CONFIG_MASK_SRDBG		0x00000002
 | 
					#define AUD_CONFIG_MASK_SRDBG		0x00000002
 | 
				
			||||||
| 
						 | 
					@ -618,6 +645,8 @@ enum hdmi_connector_status {
 | 
				
			||||||
enum had_caps_list {
 | 
					enum had_caps_list {
 | 
				
			||||||
	HAD_GET_ELD = 1,
 | 
						HAD_GET_ELD = 1,
 | 
				
			||||||
	HAD_GET_DISPLAY_RATE,
 | 
						HAD_GET_DISPLAY_RATE,
 | 
				
			||||||
 | 
						HAD_GET_DP_OUTPUT,
 | 
				
			||||||
 | 
						HAD_GET_LINK_RATE,
 | 
				
			||||||
	HAD_SET_ENABLE_AUDIO,
 | 
						HAD_SET_ENABLE_AUDIO,
 | 
				
			||||||
	HAD_SET_DISABLE_AUDIO,
 | 
						HAD_SET_DISABLE_AUDIO,
 | 
				
			||||||
	HAD_SET_ENABLE_AUDIO_INT,
 | 
						HAD_SET_ENABLE_AUDIO_INT,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue