Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 898a694f authored by Tatenda Chipeperekwa's avatar Tatenda Chipeperekwa
Browse files

msm: mdss: hdmi: add support to program sample present value



The HDMI transmitter core can be used to program the sample
present value of the audio sample packet. The sample present
value is determined in the audio driver and sent as part of
the parameters to the audio setup interface.

Change-Id: I8d580f95467343328ec0d24efc48dabf8a41ad49
Signed-off-by: default avatarTatenda Chipeperekwa <tatendac@codeaurora.org>
parent 551cd06a
Loading
Loading
Loading
Loading
+86 −45
Original line number Diff line number Diff line
@@ -2659,7 +2659,7 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
{
	/* Read first before writing */
	u32 acr_pck_ctrl_reg;
	u32 sample_rate;
	u32 sample_rate_hz;
	u32 pixel_freq;
	struct dss_io_data *io = NULL;

@@ -2668,7 +2668,7 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
		return -EINVAL;
	}

	sample_rate = hdmi_ctrl->audio_data.sample_rate;
	sample_rate_hz = hdmi_ctrl->audio_data.sample_rate_hz;

	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
@@ -2705,19 +2705,19 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
			return -EPERM;
		}

		n = audio_acr->lut[sample_rate].n;
		cts = audio_acr->lut[sample_rate].cts;
		n = audio_acr->lut[sample_rate_hz].n;
		cts = audio_acr->lut[sample_rate_hz].cts;
		layout = (MSM_HDMI_AUDIO_CHANNEL_2 ==
			hdmi_ctrl->audio_data.channel_num) ? 0 : 1;
			hdmi_ctrl->audio_data.num_of_channels) ? 0 : 1;

		if (
		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate_hz)) {
			multiplier = 4;
			n >>= 2; /* divide N by 4 and use multiplier */
		} else if (
		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate_hz)) {
			multiplier = 2;
			n >>= 1; /* divide N by 2 and use multiplier */
		} else {
@@ -2735,9 +2735,9 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
		/* N_MULTIPLE(multiplier) */
		acr_pck_ctrl_reg |= (multiplier & 7) << 16;

		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate_hz)) {
			/* SELECT(3) */
			acr_pck_ctrl_reg |= 3 << 4;
			/* CTS_48 */
@@ -2748,9 +2748,9 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
			/* N */
			DSS_REG_W(io, HDMI_ACR_48_1, n);
		} else if (
		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate_hz)) {
			/* SELECT(2) */
			acr_pck_ctrl_reg |= 2 << 4;
			/* CTS_44 */
@@ -2793,6 +2793,7 @@ static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
{
	struct dss_io_data *io = NULL;

	u32 hdmi_debug_reg = 0;
	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
	u32 num_of_channels;
	u32 channel_allocation;
@@ -2802,16 +2803,18 @@ static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
	u32 audio_info_ctrl_reg;
	u32 aud_pck_ctrl_2_reg;
	u32 layout;
	u32 sample_present;

	if (!hdmi_ctrl) {
		DEV_ERR("%s: invalid input\n", __func__);
		return -EINVAL;
	}

	num_of_channels    = hdmi_ctrl->audio_data.channel_num;
	channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
	num_of_channels    = hdmi_ctrl->audio_data.num_of_channels;
	channel_allocation = hdmi_ctrl->audio_data.channel_allocation;
	level_shift        = hdmi_ctrl->audio_data.level_shift;
	down_mix           = hdmi_ctrl->audio_data.down_mix;
	sample_present     = hdmi_ctrl->audio_data.sample_present;

	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
@@ -2914,6 +2917,19 @@ static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
		 * AUDIO_INFO_SEND
		 */
		audio_info_ctrl_reg |= 0x000000F0;

		/*
		 * Program the Sample Present into the debug register so that
		 * the HDMI transmitter core can add the sample present to
		 * Audio Sample Packet once tranmission starts.
		 */
		if (layout) {
			/* Set the Layout bit */
			hdmi_debug_reg |= BIT(4);
			/* Set the Sample Present bits */
			hdmi_debug_reg |= sample_present & 0xF;
			DSS_REG_W(io, HDMI_DEBUG, hdmi_debug_reg);
		}
	} else {
		/*Clear these flags
		 * ~(AUDIO_INFO_UPDATE |
@@ -2931,15 +2947,50 @@ static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
	return 0;
} /* hdmi_tx_audio_iframe_setup */

static int hdmi_tx_get_audio_sample_rate(u32 *sample_rate_hz)
{
	int ret = 0;
	u32 rate = *sample_rate_hz;

	switch (rate) {
	case 32000:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_32KHZ;
		break;
	case 44100:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_44_1KHZ;
		break;
	case 48000:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_48KHZ;
		break;
	case 88200:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_88_2KHZ;
		break;
	case 96000:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_96KHZ;
		break;
	case 176400:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_176_4KHZ;
		break;
	case 192000:
		*sample_rate_hz = AUDIO_SAMPLE_RATE_192KHZ;
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
} /* hdmi_tx_get_audio_sample_rate */

static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
	u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
	u32 level_shift, bool down_mix)
	struct msm_hdmi_audio_setup_params *params)
{
	int rc = 0;
	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
	u32 is_mode_dvi;
	u32 *sample_rate_hz;

	if (!hdmi_ctrl) {
	if (!hdmi_ctrl || !params) {
		DEV_ERR("%s: invalid input\n", __func__);
		return -ENODEV;
	}
@@ -2949,27 +3000,16 @@ static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
	mutex_lock(&hdmi_ctrl->power_mutex);
	if (!is_mode_dvi && hdmi_tx_is_panel_on(hdmi_ctrl)) {
		mutex_unlock(&hdmi_ctrl->power_mutex);
		/* Map given sample rate to Enum */
		if (sample_rate == 32000)
			sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
		else if (sample_rate == 44100)
			sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
		else if (sample_rate == 48000)
			sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
		else if (sample_rate == 88200)
			sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
		else if (sample_rate == 96000)
			sample_rate = AUDIO_SAMPLE_RATE_96KHZ;
		else if (sample_rate == 176400)
			sample_rate = AUDIO_SAMPLE_RATE_176_4KHZ;
		else if (sample_rate == 192000)
			sample_rate = AUDIO_SAMPLE_RATE_192KHZ;

		hdmi_ctrl->audio_data.sample_rate = sample_rate;
		hdmi_ctrl->audio_data.channel_num = num_of_channels;
		hdmi_ctrl->audio_data.spkr_alloc  = channel_allocation;
		hdmi_ctrl->audio_data.level_shift = level_shift;
		hdmi_ctrl->audio_data.down_mix    = down_mix;
		memcpy(&hdmi_ctrl->audio_data, params,
			sizeof(struct msm_hdmi_audio_setup_params));

		sample_rate_hz = &hdmi_ctrl->audio_data.sample_rate_hz;
		rc = hdmi_tx_get_audio_sample_rate(sample_rate_hz);
		if (rc) {
			DEV_ERR("%s: invalid sample rate = %d\n",
				__func__, hdmi_ctrl->audio_data.sample_rate_hz);
			goto exit;
		}

		rc = hdmi_tx_audio_setup(hdmi_ctrl);
		if (rc)
@@ -2989,6 +3029,7 @@ static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
			is_mode_dvi ? "dvi" : "hdmi",
			hdmi_ctrl->panel_power_on);

exit:
	return rc;
} /* hdmi_tx_audio_info_setup */

@@ -3177,8 +3218,8 @@ static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);

	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
	hdmi_ctrl->audio_data.sample_rate_hz = AUDIO_SAMPLE_RATE_48KHZ;
	hdmi_ctrl->audio_data.num_of_channels = MSM_HDMI_AUDIO_CHANNEL_2;

	DEV_INFO("HDMI Audio: Disabled\n");
} /* hdmi_tx_audio_off */
@@ -3922,8 +3963,8 @@ static int hdmi_tx_dev_init(struct hdmi_tx_ctrl *hdmi_ctrl)

	spin_lock_init(&hdmi_ctrl->hpd_state_lock);

	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
	hdmi_ctrl->audio_data.sample_rate_hz = AUDIO_SAMPLE_RATE_48KHZ;
	hdmi_ctrl->audio_data.num_of_channels = MSM_HDMI_AUDIO_CHANNEL_2;

	hdmi_ctrl->sdev.name = "hdmi";
	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
+1 −9
Original line number Diff line number Diff line
@@ -43,14 +43,6 @@ struct hdmi_tx_platform_data {
	u64 pin_states;
};

struct hdmi_audio {
	int sample_rate;
	int channel_num;
	int spkr_alloc;
	int level_shift;
	int down_mix;
};

struct hdmi_tx_pinctrl {
	struct pinctrl *pinctrl;
	struct pinctrl_state *state_active;
@@ -134,7 +126,7 @@ struct hdmi_tx_ctrl {


	struct hdmi_tx_pinctrl pin_res;
	struct hdmi_audio audio_data;
	struct msm_hdmi_audio_setup_params audio_data;

	struct mutex mutex;
	struct mutex lut_lock;
+11 −4
Original line number Diff line number Diff line
/* include/linux/msm_hdmi.h
 *
 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -36,11 +36,18 @@ struct msm_hdmi_audio_edid_blk {
	unsigned int spk_alloc_data_blk_size; /* in bytes */
};

struct msm_hdmi_audio_setup_params {
	u32 sample_rate_hz;
	u32 num_of_channels;
	u32 channel_allocation;
	u32 level_shift;
	bool down_mix;
	u32 sample_present;
};

struct msm_hdmi_audio_codec_ops {
	int (*audio_info_setup)(struct platform_device *pdev,
		u32 sample_rate, u32 num_of_channels,
		u32 channel_allocation, u32 level_shift,
		bool down_mix);
		struct msm_hdmi_audio_setup_params *params);
	int (*get_audio_edid_blk) (struct platform_device *pdev,
		struct msm_hdmi_audio_edid_blk *blk);
	int (*hdmi_cable_status) (struct platform_device *pdev, u32 vote);
+14 −3
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params(
	bool down_mix = 0;
	u32 num_channels = params_channels(params);
	int rc = 0;
	struct msm_hdmi_audio_setup_params audio_setup_params = {0};

	struct msm_hdmi_audio_codec_rx_data *codec_data =
			dev_get_drvdata(dai->codec->dev);
@@ -141,21 +142,27 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params(
		break;
	case 3:
		channel_allocation  = 0x02;/*default to FL/FR/FC*/
		audio_setup_params.sample_present = 0x3;
		break;
	case 4:
		channel_allocation  = 0x06;/*default to FL/FR/FC/RC*/
		audio_setup_params.sample_present = 0x7;
		break;
	case 5:
		channel_allocation  = 0x0A;/*default to FL/FR/FC/RR/RL*/
		audio_setup_params.sample_present = 0x7;
		break;
	case 6:
		channel_allocation  = 0x0B;
		audio_setup_params.sample_present = 0x7;
		break;
	case 7:
		channel_allocation  = 0x12;/*default to FL/FR/FC/RL/RR/RRC/RLC*/
		audio_setup_params.sample_present = 0xf;
		break;
	case 8:
		channel_allocation  = 0x13;
		audio_setup_params.sample_present = 0xf;
		break;
	default:
		dev_err(dai->dev, "invalid Channels = %u\n", num_channels);
@@ -167,10 +174,14 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params(
		__func__, num_channels, params_rate(params),
		channel_allocation);

	audio_setup_params.sample_rate_hz = params_rate(params);
	audio_setup_params.num_of_channels = num_channels;
	audio_setup_params.channel_allocation = channel_allocation;
	audio_setup_params.level_shift = level_shift;
	audio_setup_params.down_mix = down_mix;

	rc = codec_data->hdmi_ops.audio_info_setup(
			codec_data->hdmi_core_pdev,
			params_rate(params), num_channels,
			channel_allocation, level_shift, down_mix);
			codec_data->hdmi_core_pdev, &audio_setup_params);
	if (IS_ERR_VALUE(rc)) {
		dev_err_ratelimited(dai->dev,
			"%s() HDMI core is not ready, rc: %d\n",