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

Commit 031e28bb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

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

parents efa3d35b 898a694f
Loading
Loading
Loading
Loading
+86 −45
Original line number Original line 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 */
	/* Read first before writing */
	u32 acr_pck_ctrl_reg;
	u32 acr_pck_ctrl_reg;
	u32 sample_rate;
	u32 sample_rate_hz;
	u32 pixel_freq;
	u32 pixel_freq;
	struct dss_io_data *io = NULL;
	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;
		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];
	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
	if (!io->base) {
@@ -2705,19 +2705,19 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
			return -EPERM;
			return -EPERM;
		}
		}


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


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


		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate_hz)) {
			/* SELECT(3) */
			/* SELECT(3) */
			acr_pck_ctrl_reg |= 3 << 4;
			acr_pck_ctrl_reg |= 3 << 4;
			/* CTS_48 */
			/* CTS_48 */
@@ -2748,9 +2748,9 @@ static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
			/* N */
			/* N */
			DSS_REG_W(io, HDMI_ACR_48_1, n);
			DSS_REG_W(io, HDMI_ACR_48_1, n);
		} else if (
		} else if (
		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate_hz) ||
		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate_hz)) {
			/* SELECT(2) */
			/* SELECT(2) */
			acr_pck_ctrl_reg |= 2 << 4;
			acr_pck_ctrl_reg |= 2 << 4;
			/* CTS_44 */
			/* 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;
	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 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
	u32 num_of_channels;
	u32 num_of_channels;
	u32 channel_allocation;
	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 audio_info_ctrl_reg;
	u32 aud_pck_ctrl_2_reg;
	u32 aud_pck_ctrl_2_reg;
	u32 layout;
	u32 layout;
	u32 sample_present;


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


	num_of_channels    = hdmi_ctrl->audio_data.channel_num;
	num_of_channels    = hdmi_ctrl->audio_data.num_of_channels;
	channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
	channel_allocation = hdmi_ctrl->audio_data.channel_allocation;
	level_shift        = hdmi_ctrl->audio_data.level_shift;
	level_shift        = hdmi_ctrl->audio_data.level_shift;
	down_mix           = hdmi_ctrl->audio_data.down_mix;
	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];
	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
	if (!io->base) {
	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_SEND
		 */
		 */
		audio_info_ctrl_reg |= 0x000000F0;
		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 {
	} else {
		/*Clear these flags
		/*Clear these flags
		 * ~(AUDIO_INFO_UPDATE |
		 * ~(AUDIO_INFO_UPDATE |
@@ -2931,15 +2947,50 @@ static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
	return 0;
	return 0;
} /* hdmi_tx_audio_iframe_setup */
} /* 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,
static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
	u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
	struct msm_hdmi_audio_setup_params *params)
	u32 level_shift, bool down_mix)
{
{
	int rc = 0;
	int rc = 0;
	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
	u32 is_mode_dvi;
	u32 is_mode_dvi;
	u32 *sample_rate_hz;


	if (!hdmi_ctrl) {
	if (!hdmi_ctrl || !params) {
		DEV_ERR("%s: invalid input\n", __func__);
		DEV_ERR("%s: invalid input\n", __func__);
		return -ENODEV;
		return -ENODEV;
	}
	}
@@ -2949,27 +3000,16 @@ static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
	mutex_lock(&hdmi_ctrl->power_mutex);
	mutex_lock(&hdmi_ctrl->power_mutex);
	if (!is_mode_dvi && hdmi_tx_is_panel_on(hdmi_ctrl)) {
	if (!is_mode_dvi && hdmi_tx_is_panel_on(hdmi_ctrl)) {
		mutex_unlock(&hdmi_ctrl->power_mutex);
		mutex_unlock(&hdmi_ctrl->power_mutex);
		/* Map given sample rate to Enum */
		memcpy(&hdmi_ctrl->audio_data, params,
		if (sample_rate == 32000)
			sizeof(struct msm_hdmi_audio_setup_params));
			sample_rate = AUDIO_SAMPLE_RATE_32KHZ;

		else if (sample_rate == 44100)
		sample_rate_hz = &hdmi_ctrl->audio_data.sample_rate_hz;
			sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
		rc = hdmi_tx_get_audio_sample_rate(sample_rate_hz);
		else if (sample_rate == 48000)
		if (rc) {
			sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
			DEV_ERR("%s: invalid sample rate = %d\n",
		else if (sample_rate == 88200)
				__func__, hdmi_ctrl->audio_data.sample_rate_hz);
			sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
			goto exit;
		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;


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


exit:
	return rc;
	return rc;
} /* hdmi_tx_audio_info_setup */
} /* 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))
	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
		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.sample_rate_hz = AUDIO_SAMPLE_RATE_48KHZ;
	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
	hdmi_ctrl->audio_data.num_of_channels = MSM_HDMI_AUDIO_CHANNEL_2;


	DEV_INFO("HDMI Audio: Disabled\n");
	DEV_INFO("HDMI Audio: Disabled\n");
} /* hdmi_tx_audio_off */
} /* 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);
	spin_lock_init(&hdmi_ctrl->hpd_state_lock);


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


	hdmi_ctrl->sdev.name = "hdmi";
	hdmi_ctrl->sdev.name = "hdmi";
	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
+1 −9
Original line number Original line Diff line number Diff line
@@ -43,14 +43,6 @@ struct hdmi_tx_platform_data {
	u64 pin_states;
	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 hdmi_tx_pinctrl {
	struct pinctrl *pinctrl;
	struct pinctrl *pinctrl;
	struct pinctrl_state *state_active;
	struct pinctrl_state *state_active;
@@ -134,7 +126,7 @@ struct hdmi_tx_ctrl {




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


	struct mutex mutex;
	struct mutex mutex;
	struct mutex lut_lock;
	struct mutex lut_lock;
+11 −4
Original line number Original line Diff line number Diff line
/* include/linux/msm_hdmi.h
/* 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
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * 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 */
	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 {
struct msm_hdmi_audio_codec_ops {
	int (*audio_info_setup)(struct platform_device *pdev,
	int (*audio_info_setup)(struct platform_device *pdev,
		u32 sample_rate, u32 num_of_channels,
		struct msm_hdmi_audio_setup_params *params);
		u32 channel_allocation, u32 level_shift,
		bool down_mix);
	int (*get_audio_edid_blk) (struct platform_device *pdev,
	int (*get_audio_edid_blk) (struct platform_device *pdev,
		struct msm_hdmi_audio_edid_blk *blk);
		struct msm_hdmi_audio_edid_blk *blk);
	int (*hdmi_cable_status) (struct platform_device *pdev, u32 vote);
	int (*hdmi_cable_status) (struct platform_device *pdev, u32 vote);
+14 −3
Original line number Original line Diff line number Diff line
@@ -118,6 +118,7 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params(
	bool down_mix = 0;
	bool down_mix = 0;
	u32 num_channels = params_channels(params);
	u32 num_channels = params_channels(params);
	int rc = 0;
	int rc = 0;
	struct msm_hdmi_audio_setup_params audio_setup_params = {0};


	struct msm_hdmi_audio_codec_rx_data *codec_data =
	struct msm_hdmi_audio_codec_rx_data *codec_data =
			dev_get_drvdata(dai->codec->dev);
			dev_get_drvdata(dai->codec->dev);
@@ -141,21 +142,27 @@ static int msm_hdmi_audio_codec_rx_dai_hw_params(
		break;
		break;
	case 3:
	case 3:
		channel_allocation  = 0x02;/*default to FL/FR/FC*/
		channel_allocation  = 0x02;/*default to FL/FR/FC*/
		audio_setup_params.sample_present = 0x3;
		break;
		break;
	case 4:
	case 4:
		channel_allocation  = 0x06;/*default to FL/FR/FC/RC*/
		channel_allocation  = 0x06;/*default to FL/FR/FC/RC*/
		audio_setup_params.sample_present = 0x7;
		break;
		break;
	case 5:
	case 5:
		channel_allocation  = 0x0A;/*default to FL/FR/FC/RR/RL*/
		channel_allocation  = 0x0A;/*default to FL/FR/FC/RR/RL*/
		audio_setup_params.sample_present = 0x7;
		break;
		break;
	case 6:
	case 6:
		channel_allocation  = 0x0B;
		channel_allocation  = 0x0B;
		audio_setup_params.sample_present = 0x7;
		break;
		break;
	case 7:
	case 7:
		channel_allocation  = 0x12;/*default to FL/FR/FC/RL/RR/RRC/RLC*/
		channel_allocation  = 0x12;/*default to FL/FR/FC/RL/RR/RRC/RLC*/
		audio_setup_params.sample_present = 0xf;
		break;
		break;
	case 8:
	case 8:
		channel_allocation  = 0x13;
		channel_allocation  = 0x13;
		audio_setup_params.sample_present = 0xf;
		break;
		break;
	default:
	default:
		dev_err(dai->dev, "invalid Channels = %u\n", num_channels);
		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),
		__func__, num_channels, params_rate(params),
		channel_allocation);
		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(
	rc = codec_data->hdmi_ops.audio_info_setup(
			codec_data->hdmi_core_pdev,
			codec_data->hdmi_core_pdev, &audio_setup_params);
			params_rate(params), num_channels,
			channel_allocation, level_shift, down_mix);
	if (IS_ERR_VALUE(rc)) {
	if (IS_ERR_VALUE(rc)) {
		dev_err_ratelimited(dai->dev,
		dev_err_ratelimited(dai->dev,
			"%s() HDMI core is not ready, rc: %d\n",
			"%s() HDMI core is not ready, rc: %d\n",