ALSA: x86: Cache AUD_CONFIG register value
At enabling the audio, we modify AUD_CONFIG register bit 0. So far, it does read-modify-write procedure with a special hack for the channel bits due to the silicon bug. But we can optimize it by remembering the AUD_CONFIG register value privately. This simplifies the things a lot. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
77531beeb9
commit
40ce4b5d70
|
@ -212,30 +212,13 @@ static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val)
|
||||||
* bad audio. The fix is to always write the AUD_CONFIG[6:4] with
|
* bad audio. The fix is to always write the AUD_CONFIG[6:4] with
|
||||||
* appropriate value when doing read-modify of AUD_CONFIG register.
|
* appropriate value when doing read-modify of AUD_CONFIG register.
|
||||||
*/
|
*/
|
||||||
static void had_enable_audio(struct snd_pcm_substream *substream,
|
static void had_enable_audio(struct snd_intelhad *intelhaddata,
|
||||||
struct snd_intelhad *intelhaddata,
|
|
||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
union aud_cfg cfg_val = {.regval = 0};
|
/* update the cached value */
|
||||||
u8 channels;
|
intelhaddata->aud_config.regx.aud_en = enable;
|
||||||
u32 mask, val;
|
had_write_register(intelhaddata, AUD_CONFIG,
|
||||||
|
intelhaddata->aud_config.regval);
|
||||||
/*
|
|
||||||
* If substream is NULL, there is no active stream.
|
|
||||||
* In this case just set channels to 2
|
|
||||||
*/
|
|
||||||
channels = substream ? substream->runtime->channels : 2;
|
|
||||||
dev_dbg(intelhaddata->dev, "enable %d, ch=%d\n", enable, channels);
|
|
||||||
|
|
||||||
cfg_val.regx.num_ch = channels - 2;
|
|
||||||
if (enable)
|
|
||||||
cfg_val.regx.aud_en = 1;
|
|
||||||
mask = AUD_CONFIG_CH_MASK | 1;
|
|
||||||
|
|
||||||
had_read_register(intelhaddata, AUD_CONFIG, &val);
|
|
||||||
val &= ~mask;
|
|
||||||
val |= cfg_val.regval;
|
|
||||||
had_write_register(intelhaddata, AUD_CONFIG, val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forcibly ACKs to both BUFFER_DONE and BUFFER_UNDERRUN interrupts */
|
/* forcibly ACKs to both BUFFER_DONE and BUFFER_UNDERRUN interrupts */
|
||||||
|
@ -360,6 +343,7 @@ static int had_init_audio_ctrl(struct snd_pcm_substream *substream,
|
||||||
}
|
}
|
||||||
|
|
||||||
had_write_register(intelhaddata, AUD_CONFIG, cfg_val.regval);
|
had_write_register(intelhaddata, AUD_CONFIG, cfg_val.regval);
|
||||||
|
intelhaddata->aud_config = cfg_val;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,6 +988,7 @@ static void had_process_buffer_underrun(struct snd_intelhad *intelhaddata)
|
||||||
|
|
||||||
/* Handle Underrun interrupt within Audio Unit */
|
/* Handle Underrun interrupt within Audio Unit */
|
||||||
had_write_register(intelhaddata, AUD_CONFIG, 0);
|
had_write_register(intelhaddata, AUD_CONFIG, 0);
|
||||||
|
intelhaddata->aud_config.regval = 0;
|
||||||
/* Reset buffer pointers */
|
/* Reset buffer pointers */
|
||||||
had_reset_audio(intelhaddata);
|
had_reset_audio(intelhaddata);
|
||||||
|
|
||||||
|
@ -1169,7 +1154,7 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
|
|
||||||
/* Enable Audio */
|
/* Enable Audio */
|
||||||
had_ack_irqs(intelhaddata); /* FIXME: do we need this? */
|
had_ack_irqs(intelhaddata); /* FIXME: do we need this? */
|
||||||
had_enable_audio(substream, intelhaddata, true);
|
had_enable_audio(intelhaddata, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
|
@ -1182,7 +1167,7 @@ static int had_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
intelhaddata->stream_info.running = false;
|
intelhaddata->stream_info.running = false;
|
||||||
spin_unlock(&intelhaddata->had_spinlock);
|
spin_unlock(&intelhaddata->had_spinlock);
|
||||||
/* Disable Audio */
|
/* Disable Audio */
|
||||||
had_enable_audio(substream, intelhaddata, false);
|
had_enable_audio(intelhaddata, false);
|
||||||
/* Reset buffer pointers */
|
/* Reset buffer pointers */
|
||||||
had_reset_audio(intelhaddata);
|
had_reset_audio(intelhaddata);
|
||||||
break;
|
break;
|
||||||
|
@ -1315,7 +1300,7 @@ static int had_process_mode_change(struct snd_intelhad *intelhaddata)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Disable Audio */
|
/* Disable Audio */
|
||||||
had_enable_audio(substream, intelhaddata, false);
|
had_enable_audio(intelhaddata, false);
|
||||||
|
|
||||||
/* Update CTS value */
|
/* Update CTS value */
|
||||||
disp_samp_freq = intelhaddata->tmds_clock_speed;
|
disp_samp_freq = intelhaddata->tmds_clock_speed;
|
||||||
|
@ -1334,7 +1319,7 @@ static int had_process_mode_change(struct snd_intelhad *intelhaddata)
|
||||||
n_param, intelhaddata);
|
n_param, intelhaddata);
|
||||||
|
|
||||||
/* Enable Audio */
|
/* Enable Audio */
|
||||||
had_enable_audio(substream, intelhaddata, true);
|
had_enable_audio(intelhaddata, true);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
had_substream_put(intelhaddata);
|
had_substream_put(intelhaddata);
|
||||||
|
@ -1389,7 +1374,7 @@ static void had_process_hot_unplug(struct snd_intelhad *intelhaddata)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable Audio */
|
/* Disable Audio */
|
||||||
had_enable_audio(substream, intelhaddata, false);
|
had_enable_audio(intelhaddata, false);
|
||||||
|
|
||||||
intelhaddata->connected = false;
|
intelhaddata->connected = false;
|
||||||
dev_dbg(intelhaddata->dev,
|
dev_dbg(intelhaddata->dev,
|
||||||
|
|
|
@ -127,6 +127,7 @@ struct snd_intelhad {
|
||||||
int irq;
|
int irq;
|
||||||
void __iomem *mmio_start;
|
void __iomem *mmio_start;
|
||||||
unsigned int had_config_offset;
|
unsigned int had_config_offset;
|
||||||
|
union aud_cfg aud_config; /* AUD_CONFIG reg value cache */
|
||||||
struct work_struct hdmi_audio_wq;
|
struct work_struct hdmi_audio_wq;
|
||||||
struct mutex mutex; /* for protecting chmap and eld */
|
struct mutex mutex; /* for protecting chmap and eld */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue