1
0
Fork 0

MLK-24916-3: drm: bridge: synopsys: Add HBR support for gp audio

Only non_pcm, 32bit, 192kHz, 8channel streams be recognized as
HBR streams.

In order to support this feature, need to enhance the API in
dw-hdmi driver.

The test command is:
$iecset -c 4 audio off
$aplay -Dhw:4 -r 192000 -c 8 -f S32_LE out_put.spd.iec958
$iecset -c 4 audio on

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
zero-colors
Shengjiu Wang 2020-10-23 17:25:45 +08:00
parent 538b19ad6f
commit bb41b563b3
6 changed files with 51 additions and 7 deletions

View File

@ -89,6 +89,10 @@ static int audio_hw_params(struct device *dev, void *data,
dw_hdmi_set_channel_count(dw->data.hdmi, params->channels);
dw_hdmi_set_channel_allocation(dw->data.hdmi, ca);
dw_hdmi_set_sample_non_pcm(dw->data.hdmi,
params->iec.status[0] & IEC958_AES0_NONAUDIO);
dw_hdmi_set_sample_width(dw->data.hdmi, params->sample_width);
return ret;
}

View File

@ -180,6 +180,8 @@ struct dw_hdmi {
spinlock_t audio_lock;
struct mutex audio_mutex;
unsigned int sample_non_pcm;
unsigned int sample_width;
unsigned int sample_rate;
unsigned int channels;
unsigned int audio_cts;
@ -678,6 +680,22 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
mutex_unlock(&hdmi->audio_mutex);
}
void dw_hdmi_set_sample_width(struct dw_hdmi *hdmi, unsigned int width)
{
mutex_lock(&hdmi->audio_mutex);
hdmi->sample_width = width;
mutex_unlock(&hdmi->audio_mutex);
}
EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_width);
void dw_hdmi_set_sample_non_pcm(struct dw_hdmi *hdmi, unsigned int non_pcm)
{
mutex_lock(&hdmi->audio_mutex);
hdmi->sample_non_pcm = non_pcm;
mutex_unlock(&hdmi->audio_mutex);
}
EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_non_pcm);
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
{
mutex_lock(&hdmi->audio_mutex);
@ -797,8 +815,18 @@ static void dw_hdmi_gp_audio_enable(struct dw_hdmi *hdmi)
hdmi_modb(hdmi, 0x3, 0x3, HDMI_FC_DATAUTO3);
/* hbr */
if (hdmi->sample_rate == 192000 && hdmi->channels == 8 &&
hdmi->sample_width == 32 && hdmi->sample_non_pcm) {
hdmi_modb(hdmi, 0x01, 0x01, HDMI_GP_CONF2);
}
if (hdmi->phy.ops->enable_audio)
hdmi->phy.ops->enable_audio(hdmi, hdmi->phy.data, hdmi->channels);
hdmi->phy.ops->enable_audio(hdmi, hdmi->phy.data,
hdmi->channels,
hdmi->sample_width,
hdmi->sample_rate,
hdmi->sample_non_pcm);
}
static void dw_hdmi_gp_audio_disable(struct dw_hdmi *hdmi)

View File

@ -335,9 +335,10 @@ static int imx8mp_hdmimix_setup(struct imx_hdmi *hdmi)
return clk_bulk_prepare_enable(ARRAY_SIZE(imx8mp_clocks), imx8mp_clocks);
}
void imx8mp_hdmi_enable_audio(struct dw_hdmi *dw_hdmi, void *data, int channel)
void imx8mp_hdmi_enable_audio(struct dw_hdmi *dw_hdmi, void *data, int channel,
int width, int rate, int non_pcm)
{
imx8mp_hdmi_pai_enable(channel);
imx8mp_hdmi_pai_enable(channel, width, rate, non_pcm);
}
void imx8mp_hdmi_disable_audio(struct dw_hdmi *dw_hdmi, void *data)

View File

@ -42,12 +42,20 @@
static struct imx8mp_hdmi_pavi *gpavi;
/* PAI APIs */
void imx8mp_hdmi_pai_enable(int channel)
void imx8mp_hdmi_pai_enable(int channel, int width, int rate, int non_pcm)
{
/* PAI set */
writel((0x3030000 | ((channel-1) << 8)),
gpavi->base + HTX_PAI_CTRL_EXT);
writel(0x1c0c675b, gpavi->base + HTX_PAI_FIELD_CTRL);
/* hbr */
if (non_pcm && width == 32 && channel == 8 && rate == 192000)
writel(0x004e77df, gpavi->base + HTX_PAI_FIELD_CTRL);
else if (width == 32)
writel(0x1c8c675b, gpavi->base + HTX_PAI_FIELD_CTRL);
else
writel(0x1c0c675b, gpavi->base + HTX_PAI_FIELD_CTRL);
/* PAI start running */
writel(HTX_PAI_CTRL_ENABLE, gpavi->base + HTX_PAI_CTRL);
}

View File

@ -24,7 +24,7 @@ struct imx8mp_hdmi_pavi {
struct reset_control *reset_pvi;
};
void imx8mp_hdmi_pai_enable(int channel);
void imx8mp_hdmi_pai_enable(int channel, int width, int rate, int non_pcm);
void imx8mp_hdmi_pai_disable(void);
void imx8mp_hdmi_pvi_enable(struct drm_display_mode *mode);

View File

@ -120,7 +120,8 @@ struct dw_hdmi_phy_ops {
void (*update_hpd)(struct dw_hdmi *hdmi, void *data,
bool force, bool disabled, bool rxsense);
void (*setup_hpd)(struct dw_hdmi *hdmi, void *data);
void (*enable_audio)(struct dw_hdmi *hdmi, void *data, int channel);
void (*enable_audio)(struct dw_hdmi *hdmi, void *data, int channel,
int width, int rate, int non_pcm);
void (*disable_audio)(struct dw_hdmi *hdmi, void *data);
};
@ -160,6 +161,8 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense);
int dw_hdmi_set_plugged_cb(struct dw_hdmi *hdmi, hdmi_codec_plugged_cb fn,
struct device *codec_dev);
void dw_hdmi_set_sample_non_pcm(struct dw_hdmi *hdmi, unsigned int non_pcm);
void dw_hdmi_set_sample_width(struct dw_hdmi *hdmi, unsigned int width);
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt);
void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca);