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

Commit 56689b10 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/dp: Snapshot of DP and supporting files"

parents be7c1ced 10ffbfa2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ msm_drm-$(CONFIG_DRM_MSM_DP) += dp/dp_usbpd.o \
	dp/dp_debug.o \
	dp/dp_hpd.o \
	dp/dp_gpio_hpd.o \
	dp/dp_lphw_hpd.o \
	dp/dp_display.o \
	dp/dp_drm.o \
	dp/dp_hdcp2p2.o \
+6 −35
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
@@ -337,32 +337,6 @@ static void dp_audio_setup_acr(struct dp_audio_private *audio)
	catalog->config_acr(catalog);
}

static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio)
{
	struct dp_catalog_audio *catalog = audio->catalog;
	u32 safe_to_exit_level = 0;

	switch (audio->dp_audio.lane_count) {
	case 1:
		safe_to_exit_level = 14;
		break;
	case 2:
		safe_to_exit_level = 8;
		break;
	case 4:
		safe_to_exit_level = 5;
		break;
	default:
		pr_debug("setting the default safe_to_exit_level = %u\n",
				safe_to_exit_level);
		safe_to_exit_level = 14;
		break;
	}

	catalog->data = safe_to_exit_level;
	catalog->safe_to_exit_level(catalog);
}

static void dp_audio_enable(struct dp_audio_private *audio, bool enable)
{
	struct dp_catalog_audio *catalog = audio->catalog;
@@ -423,7 +397,6 @@ static int dp_audio_info_setup(struct platform_device *pdev,

	dp_audio_setup_sdp(audio);
	dp_audio_setup_acr(audio);
	dp_audio_safe_to_exit_level(audio);
	dp_audio_enable(audio, true);

	mutex_unlock(&audio->ops_lock);
@@ -673,10 +646,8 @@ static int dp_audio_notify(struct dp_audio_private *audio, u32 state)
	reinit_completion(&audio->hpd_comp);
	rc = ext->intf_ops.audio_notify(audio->ext_pdev,
			&ext->codec, state);
	if (rc) {
		pr_err("failed to notify audio. state=%d err=%d\n", state, rc);
	if (rc)
		goto end;
	}

	if (atomic_read(&audio->acked))
		goto end;
@@ -734,6 +705,8 @@ static int dp_audio_on(struct dp_audio *dp_audio)
		return -EINVAL;
	}

	dp_audio_register_ext_disp(audio);

	ext = &audio->ext_audio_data;

	audio->session_on = true;
@@ -781,6 +754,8 @@ static int dp_audio_off(struct dp_audio *dp_audio)
	audio->session_on = false;
	audio->engine_on  = false;

	dp_audio_deregister_ext_disp(audio);

	return rc;
}

@@ -854,8 +829,6 @@ struct dp_audio *dp_audio_get(struct platform_device *pdev,

	catalog->init(catalog);

	dp_audio_register_ext_disp(audio);

	return dp_audio;

error_notify_workqueue:
@@ -873,8 +846,6 @@ void dp_audio_put(struct dp_audio *dp_audio)

	audio = container_of(dp_audio, struct dp_audio_private, dp_audio);

	dp_audio_deregister_ext_disp(audio);

	mutex_destroy(&audio->ops_lock);

	dp_audio_destroy_notify_workqueue(audio);
+53 −25
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
@@ -49,20 +49,26 @@ struct dp_aux_private {
static void dp_aux_hex_dump(struct drm_dp_aux *drm_aux,
		struct drm_dp_aux_msg *msg)
{
	DEFINE_DYNAMIC_DEBUG_METADATA(ddm, "dp aux tracker");

	if (unlikely(ddm.flags & _DPRINTK_FLAGS_PRINT)) {
		u8 buf[SZ_64];
	char prefix[64];
	int i, linelen, remaining = msg->size;
	const int rowsize = 16;
	u8 linebuf[64];
	struct dp_aux_private *aux = container_of(drm_aux,
		struct dp_aux_private, drm_aux);

		snprintf(buf, SZ_64, "[drm-dp] %5s %5s %5xh(%2zu): ",
			aux->native ? "NATIVE" : "I2C",
			aux->read ? "READ" : "WRITE",
	snprintf(prefix, sizeof(prefix), "%s %s %4xh(%2zu): ",
		aux->native ? "NAT" : "I2C",
		aux->read ? "RD" : "WR",
		msg->address, msg->size);

		print_hex_dump(KERN_DEBUG, buf, DUMP_PREFIX_NONE,
			8, 1, msg->buffer, msg->size, false);
	for (i = 0; i < msg->size; i += rowsize) {
		linelen = min(remaining, rowsize);
		remaining -= rowsize;

		hex_dump_to_buffer(msg->buffer + i, linelen, rowsize, 1,
			linebuf, sizeof(linebuf), false);

		pr_debug("%s%s\n", prefix, linebuf);
	}
}
#else
@@ -483,30 +489,44 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
		goto end;
	}

	if ((msg->address + msg->size) > SZ_16K) {
		pr_err("invalid dpcd access: addr=0x%x, size=0x%x\n",
				msg->address + msg->size);
	if ((msg->address + msg->size) > SZ_4K) {
		pr_debug("invalid dpcd access: addr=0x%x, size=0x%lx\n",
				msg->address, msg->size);
		goto address_error;
	}

	if (aux->native) {
		if (aux->read) {
		aux->dp_aux.reg = msg->address;
		aux->dp_aux.read = aux->read;
		aux->dp_aux.size = msg->size;

		reinit_completion(&aux->comp);

		if (aux->read) {
			timeout = wait_for_completion_timeout(&aux->comp, HZ);
			if (!timeout)
			if (!timeout) {
				pr_err("aux timeout for 0x%x\n", msg->address);

			aux->dp_aux.reg = 0xFFFF;
				atomic_set(&aux->aborted, 1);
				ret = -ETIMEDOUT;
				goto end;
			}

			memcpy(msg->buffer, aux->dpcd + msg->address,
				msg->size);
			aux->aux_error_num = DP_AUX_ERR_NONE;
		} else {
			memcpy(aux->dpcd + msg->address, msg->buffer,
				msg->size);

			timeout = wait_for_completion_timeout(&aux->comp, HZ);
			if (!timeout) {
				pr_err("aux timeout for 0x%x\n", msg->address);
				atomic_set(&aux->aborted, 1);
				ret = -ETIMEDOUT;
				goto end;
			}
		}

		aux->aux_error_num = DP_AUX_ERR_NONE;
	} else {
		if (aux->read && msg->address == 0x50) {
			memcpy(msg->buffer,
@@ -536,6 +556,10 @@ static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
	memset(msg->buffer, 0, msg->size);
	ret = msg->size;
end:
	aux->dp_aux.reg = 0xFFFF;
	aux->dp_aux.read = true;
	aux->dp_aux.size = 0;

	mutex_unlock(&aux->mutex);
	return ret;
}
@@ -720,10 +744,12 @@ static void dp_aux_set_sim_mode(struct dp_aux *dp_aux, bool en,
	aux->edid = edid;
	aux->dpcd = dpcd;

	if (en)
	if (en) {
		atomic_set(&aux->aborted, 0);
		aux->drm_aux.transfer = dp_aux_transfer_debug;
	else
	} else {
		aux->drm_aux.transfer = dp_aux_transfer;
	}

	mutex_unlock(&aux->mutex);
}
@@ -782,7 +808,9 @@ struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
	struct dp_aux *dp_aux;

	if (!catalog || !parser ||
			(!parser->no_aux_switch && !aux_switch)) {
			(!parser->no_aux_switch &&
				!aux_switch &&
				!parser->gpio_aux_switch)) {
		pr_err("invalid input\n");
		rc = -ENODEV;
		goto error;
+4 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 */

#ifndef _DP_AUX_H_
@@ -34,8 +34,11 @@ enum dp_aux_error {

struct dp_aux {
	u32 reg;
	u32 size;
	u32 state;

	bool read;

	struct drm_dp_aux *drm_aux;
	int (*drm_aux_register)(struct dp_aux *aux);
	void (*drm_aux_deregister)(struct dp_aux *aux);
+281 −62
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
@@ -695,7 +695,7 @@ static void dp_catalog_ctrl_state_ctrl(struct dp_catalog_ctrl *ctrl, u32 state)
	wmb();
}

static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl)
static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl, u8 ln_cnt)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
@@ -709,13 +709,16 @@ static void dp_catalog_ctrl_config_ctrl(struct dp_catalog_ctrl *ctrl)
	catalog = dp_catalog_get_priv(ctrl);
	io_data = catalog->io.dp_link;

	cfg = dp_read(catalog->exe_mode, io_data, DP_CONFIGURATION_CTRL);
	cfg &= ~(BIT(4) | BIT(5));
	cfg |= (ln_cnt - 1) << 4;
	dp_write(catalog->exe_mode, io_data, DP_CONFIGURATION_CTRL, cfg);

	cfg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL);
	cfg |= 0x02000000;
	dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, cfg);

	pr_debug("DP_MAINLINK_CTRL=0x%x\n", cfg);

	dp_write(catalog->exe_mode, io_data, DP_MAINLINK_LEVELS, 0xa08);
}

static void dp_catalog_panel_config_ctrl(struct dp_catalog_panel *panel,
@@ -766,6 +769,7 @@ static void dp_catalog_panel_config_dto(struct dp_catalog_panel *panel,
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 dsc_dto;

	if (!panel) {
		pr_err("invalid input\n");
@@ -792,7 +796,12 @@ static void dp_catalog_panel_config_dto(struct dp_catalog_panel *panel,
		return;
	}

	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, ack << 1);
	dsc_dto = dp_read(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO);
	if (ack)
		dsc_dto = BIT(1);
	else
		dsc_dto &= ~BIT(1);
	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, dsc_dto);
}

static void dp_catalog_ctrl_lane_mapping(struct dp_catalog_ctrl *ctrl,
@@ -927,6 +936,11 @@ static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,
		 * always be within the range of a 32 bit unsigned int.
		 */
		mvid = (u32) mvid_calc;

		if (panel->widebus_en) {
			mvid <<= 1;
			nvid <<= 1;
		}
	} else {
		io_data = catalog->io.dp_mmss_cc;

@@ -944,6 +958,9 @@ static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,

		pr_debug("rate = %d\n", rate);

		if (panel->widebus_en)
			mvid <<= 1;

		if (link_rate_hbr2 == rate)
			nvid *= 2;

@@ -1105,6 +1122,107 @@ static void dp_catalog_panel_tpg_cfg(struct dp_catalog_panel *panel,
	wmb(); /* ensure Timing generator is turned on */
}

static void dp_catalog_panel_dsc_cfg(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 reg, offset;
	int i;

	if (!panel) {
		pr_err("invalid input\n");
		return;
	}

	if (panel->stream_id >= DP_STREAM_MAX) {
		pr_err("invalid stream_id:%d\n", panel->stream_id);
		return;
	}

	catalog = dp_catalog_get_priv(panel);

	if (panel->stream_id == DP_STREAM_0)
		io_data = catalog->io.dp_p0;
	else
		io_data = catalog->io.dp_p1;

	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO_COUNT,
			panel->dsc.dto_count);

	reg = dp_read(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO);
	if (panel->dsc.dto_en) {
		reg |= BIT(0);
		reg |= (panel->dsc.dto_n << 8);
		reg |= (panel->dsc.dto_d << 16);
	}
	dp_write(catalog->exe_mode, io_data, MMSS_DP_DSC_DTO, reg);

	io_data = catalog->io.dp_link;

	if (panel->stream_id == DP_STREAM_0)
		offset = 0;
	else
		offset = DP1_COMPRESSION_MODE_CTRL - DP_COMPRESSION_MODE_CTRL;

	dp_write(catalog->exe_mode, io_data, DP_PPS_HB_0_3 + offset, 0x7F1000);
	dp_write(catalog->exe_mode, io_data, DP_PPS_PB_0_3 + offset, 0xA22300);

	for (i = 0; i < panel->dsc.parity_word_len; i++)
		dp_write(catalog->exe_mode, io_data,
				DP_PPS_PB_4_7 + (i << 2) + offset,
				panel->dsc.parity_word[i]);

	for (i = 0; i < panel->dsc.pps_word_len; i++)
		dp_write(catalog->exe_mode, io_data,
				DP_PPS_PPS_0_3 + (i << 2) + offset,
				panel->dsc.pps_word[i]);

	reg = 0;
	if (panel->dsc.dsc_en) {
		reg = BIT(0);
		reg |= (panel->dsc.eol_byte_num << 3);
		reg |= (panel->dsc.slice_per_pkt << 5);
		reg |= (panel->dsc.bytes_per_pkt << 16);
		reg |= (panel->dsc.be_in_lane << 10);
	}
	dp_write(catalog->exe_mode, io_data,
			DP_COMPRESSION_MODE_CTRL + offset, reg);

	pr_debug("compression:0x%x for stream:%d\n",
			reg, panel->stream_id);
}

static void dp_catalog_panel_pps_flush(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 dp_flush, offset;

	if (!panel) {
		pr_err("invalid input\n");
		return;
	}

	if (panel->stream_id >= DP_STREAM_MAX) {
		pr_err("invalid stream_id:%d\n", panel->stream_id);
		return;
	}

	catalog = dp_catalog_get_priv(panel);
	io_data = catalog->io.dp_link;

	if (panel->stream_id == DP_STREAM_0)
		offset = 0;
	else
		offset = MMSS_DP1_FLUSH - MMSS_DP_FLUSH;

	dp_flush = dp_read(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset);
	dp_flush |= BIT(0);
	dp_write(catalog->exe_mode, io_data, MMSS_DP_FLUSH + offset, dp_flush);

	pr_debug("pps flush for stream:%d\n", panel->stream_id);
}

static void dp_catalog_ctrl_reset(struct dp_catalog_ctrl *ctrl)
{
	u32 sw_reset;
@@ -1185,37 +1303,6 @@ static void dp_catalog_ctrl_enable_irq(struct dp_catalog_ctrl *ctrl,
	}
}

static void dp_catalog_ctrl_hpd_config(struct dp_catalog_ctrl *ctrl, bool en)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;

	if (!ctrl) {
		pr_err("invalid input\n");
		return;
	}

	catalog = dp_catalog_get_priv(ctrl);
	io_data = catalog->io.dp_aux;

	if (en) {
		u32 reftimer = dp_read(catalog->exe_mode, io_data,
						DP_DP_HPD_REFTIMER);

		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_ACK, 0xF);
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_MASK, 0xF);
		/* Enabling REFTIMER */
		reftimer |= BIT(16);
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_REFTIMER,
				reftimer);
		/* Enable HPD */
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_CTRL, 0x1);
	} else {
		/*Disable HPD */
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_CTRL, 0x0);
	}
}

static void dp_catalog_ctrl_get_interrupt(struct dp_catalog_ctrl *ctrl)
{
	u32 ack = 0;
@@ -1436,6 +1523,39 @@ static u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog_ctrl *ctrl)
	return dp_read(catalog->exe_mode, io_data, DP_MAINLINK_READY);
}

static void dp_catalog_ctrl_fec_config(struct dp_catalog_ctrl *ctrl,
		bool enable)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data = NULL;
	u32 reg;

	if (!ctrl) {
		pr_err("invalid input\n");
		return;
	}

	catalog = dp_catalog_get_priv(ctrl);
	io_data = catalog->io.dp_link;

	reg = dp_read(catalog->exe_mode, io_data, DP_MAINLINK_CTRL);

	/*
	 * fec_en = BIT(12)
	 * fec_seq_mode = BIT(22)
	 * sde_flush = BIT(23) | BIT(24)
	 * fb_boundary_sel = BIT(25)
	 */
	if (enable)
		reg |= BIT(12) | BIT(22) | BIT(23) | BIT(24) | BIT(25);
	else
		reg &= ~BIT(12);

	dp_write(catalog->exe_mode, io_data, DP_MAINLINK_CTRL, reg);
	/* make sure mainlink configuration is updated with fec sequence */
	wmb();
}

static int dp_catalog_reg_dump(struct dp_catalog *dp_catalog,
		char *name, u8 **out_buf, u32 *out_buf_len)
{
@@ -1706,12 +1826,52 @@ static void dp_catalog_ctrl_update_rg(struct dp_catalog_ctrl *ctrl, u32 ch,
	dp_write(catalog->exe_mode, io_data, DP_DP0_RG + reg_off, rg);
}

static void dp_catalog_ctrl_mainlink_levels(struct dp_catalog_ctrl *ctrl,
		u8 lane_cnt)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 mainlink_levels, safe_to_exit_level = 14;

	catalog = dp_catalog_get_priv(ctrl);

	io_data   = catalog->io.dp_link;

	switch (lane_cnt) {
	case 1:
		safe_to_exit_level = 14;
		break;
	case 2:
		safe_to_exit_level = 8;
		break;
	case 4:
		safe_to_exit_level = 5;
		break;
	default:
		pr_debug("setting the default safe_to_exit_level = %u\n",
				safe_to_exit_level);
		break;
	}

	mainlink_levels = dp_read(catalog->exe_mode, io_data,
					DP_MAINLINK_LEVELS);
	mainlink_levels &= 0xFE0;
	mainlink_levels |= safe_to_exit_level;

	pr_debug("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
			mainlink_levels, safe_to_exit_level);

	dp_write(catalog->exe_mode, io_data, DP_MAINLINK_LEVELS,
			mainlink_levels);
}


/* panel related catalog functions */
static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 offset = 0;
	u32 offset = 0, reg;

	if (!panel) {
		pr_err("invalid input\n");
@@ -1737,10 +1897,85 @@ static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel)
		DP_HSYNC_VSYNC_WIDTH_POLARITY + offset, panel->width_blanking);
	dp_write(catalog->exe_mode, io_data, DP_ACTIVE_HOR_VER + offset,
			panel->dp_active);

	if (panel->stream_id == DP_STREAM_0)
		io_data = catalog->io.dp_p0;
	else
		io_data = catalog->io.dp_p1;

	reg = dp_read(catalog->exe_mode, io_data, MMSS_DP_INTF_CONFIG);

	if (panel->widebus_en)
		reg |= BIT(4);
	else
		reg &= ~BIT(4);

	dp_write(catalog->exe_mode, io_data, MMSS_DP_INTF_CONFIG, reg);
end:
	return 0;
}

static void dp_catalog_hpd_config_hpd(struct dp_catalog_hpd *hpd, bool en)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;

	if (!hpd) {
		pr_err("invalid input\n");
		return;
	}

	catalog = dp_catalog_get_priv(hpd);
	io_data = catalog->io.dp_aux;

	if (en) {
		u32 reftimer = dp_read(catalog->exe_mode, io_data,
						DP_DP_HPD_REFTIMER);

		/* Arm only the UNPLUG and HPD_IRQ interrupts */
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_ACK, 0xF);
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_MASK, 0xA);

		/* Enable REFTIMER to count 1ms */
		reftimer |= BIT(16);
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_REFTIMER,
				reftimer);

		 /* Connect_time is 250us & disconnect_time is 2ms */
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_EVENT_TIME_0,
				0x3E800FA);
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_EVENT_TIME_1,
				0x1F407D0);

		/* Enable HPD */
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_CTRL, 0x1);

	} else {
		/* Disable HPD */
		dp_write(catalog->exe_mode, io_data, DP_DP_HPD_CTRL, 0x0);
	}
}

static u32 dp_catalog_hpd_get_interrupt(struct dp_catalog_hpd *hpd)
{
	u32 isr = 0;
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;

	if (!hpd) {
		pr_err("invalid input\n");
		return isr;
	}

	catalog = dp_catalog_get_priv(hpd);

	io_data = catalog->io.dp_aux;
	isr = dp_read(catalog->exe_mode, io_data, DP_DP_HPD_INT_STATUS);
	dp_write(catalog->exe_mode, io_data, DP_DP_HPD_INT_ACK, (isr & 0xf));

	return isr;
}

static void dp_catalog_audio_init(struct dp_catalog_audio *audio)
{
	struct dp_catalog_private *catalog;
@@ -1895,29 +2130,6 @@ static void dp_catalog_audio_config_acr(struct dp_catalog_audio *audio)
	dp_write(catalog->exe_mode, io_data, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
}

static void dp_catalog_audio_safe_to_exit_level(struct dp_catalog_audio *audio)
{
	struct dp_catalog_private *catalog;
	struct dp_io_data *io_data;
	u32 mainlink_levels, safe_to_exit_level;

	catalog = dp_catalog_get_priv(audio);

	io_data   = catalog->io.dp_link;
	safe_to_exit_level = audio->data;

	mainlink_levels = dp_read(catalog->exe_mode, io_data,
					DP_MAINLINK_LEVELS);
	mainlink_levels &= 0xFE0;
	mainlink_levels |= safe_to_exit_level;

	pr_debug("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
			mainlink_levels, safe_to_exit_level);

	dp_write(catalog->exe_mode, io_data, DP_MAINLINK_LEVELS,
			mainlink_levels);
}

static void dp_catalog_audio_enable(struct dp_catalog_audio *audio)
{
	struct dp_catalog_private *catalog;
@@ -2227,7 +2439,6 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.usb_reset      = dp_catalog_ctrl_usb_reset,
		.mainlink_ready = dp_catalog_ctrl_mainlink_ready,
		.enable_irq     = dp_catalog_ctrl_enable_irq,
		.hpd_config     = dp_catalog_ctrl_hpd_config,
		.phy_reset      = dp_catalog_ctrl_phy_reset,
		.phy_lane_cfg   = dp_catalog_ctrl_phy_lane_cfg,
		.update_vx_px   = dp_catalog_ctrl_update_vx_px,
@@ -2241,6 +2452,12 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.channel_alloc = dp_catalog_ctrl_channel_alloc,
		.update_rg = dp_catalog_ctrl_update_rg,
		.channel_dealloc = dp_catalog_ctrl_channel_dealloc,
		.fec_config = dp_catalog_ctrl_fec_config,
		.mainlink_levels = dp_catalog_ctrl_mainlink_levels,
	};
	struct dp_catalog_hpd hpd = {
		.config_hpd	= dp_catalog_hpd_config_hpd,
		.get_interrupt	= dp_catalog_hpd_get_interrupt,
	};
	struct dp_catalog_audio audio = {
		.init       = dp_catalog_audio_init,
@@ -2249,7 +2466,6 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.config_sdp = dp_catalog_audio_config_sdp,
		.set_header = dp_catalog_audio_set_header,
		.get_header = dp_catalog_audio_get_header,
		.safe_to_exit_level = dp_catalog_audio_safe_to_exit_level,
	};
	struct dp_catalog_panel panel = {
		.timing_cfg = dp_catalog_panel_timing_cfg,
@@ -2261,6 +2477,8 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
		.update_transfer_unit = dp_catalog_panel_update_transfer_unit,
		.config_ctrl = dp_catalog_panel_config_ctrl,
		.config_dto = dp_catalog_panel_config_dto,
		.dsc_cfg = dp_catalog_panel_dsc_cfg,
		.pps_flush = dp_catalog_panel_pps_flush,
	};

	if (!dev || !parser) {
@@ -2286,6 +2504,7 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)

	dp_catalog->aux   = aux;
	dp_catalog->ctrl  = ctrl;
	dp_catalog->hpd   = hpd;
	dp_catalog->audio = audio;
	dp_catalog->panel = panel;

Loading