Commit d11f5a7a authored by Dmitry Baryshkov's avatar Dmitry Baryshkov Committed by Dmitry Baryshkov
Browse files

drm/msm/dp: move interrupt handling to dp_ctrl



It makes it easier to keep all interrupts-related code in dp_ctrl
submodule. Move all functions to dp_ctrl.c.

Reviewed-by: default avatarStephen Boyd <swboyd@chromium.org>
Tested-by: Stephen Boyd <swboyd@chromium.org> # sc7180-trogdor
Signed-off-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Patchwork: https://patchwork.freedesktop.org/patch/654330/
Link: https://lore.kernel.org/r/20250518-fd-dp-audio-fixup-v6-10-2f0ec3ec000d@oss.qualcomm.com
parent e30cab9d
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -437,9 +437,8 @@ static ssize_t msm_dp_aux_transfer(struct drm_dp_aux *msm_dp_aux,
	return ret;
}

irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux)
irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux, u32 isr)
{
	u32 isr;
	struct msm_dp_aux_private *aux;

	if (!msm_dp_aux) {
@@ -449,12 +448,6 @@ irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux)

	aux = container_of(msm_dp_aux, struct msm_dp_aux_private, msm_dp_aux);

	isr = msm_dp_catalog_aux_get_irq(aux->catalog);

	/* no interrupts pending, return immediately */
	if (!isr)
		return IRQ_NONE;

	if (!aux->cmd_busy) {
		DRM_ERROR("Unexpected DP AUX IRQ %#010x when not busy\n", isr);
		return IRQ_NONE;
+1 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@

int msm_dp_aux_register(struct drm_dp_aux *msm_dp_aux);
void msm_dp_aux_unregister(struct drm_dp_aux *msm_dp_aux);
irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux);
irqreturn_t msm_dp_aux_isr(struct drm_dp_aux *msm_dp_aux, u32 isr);
void msm_dp_aux_enable_xfers(struct drm_dp_aux *msm_dp_aux, bool enabled);
void msm_dp_aux_init(struct drm_dp_aux *msm_dp_aux);
void msm_dp_aux_deinit(struct drm_dp_aux *msm_dp_aux);
+0 −95
Original line number Diff line number Diff line
@@ -15,41 +15,6 @@
#include "dp_catalog.h"
#include "dp_reg.h"

#define POLLING_SLEEP_US			1000
#define POLLING_TIMEOUT_US			10000

#define DP_INTERRUPT_STATUS_ACK_SHIFT	1
#define DP_INTERRUPT_STATUS_MASK_SHIFT	2

#define DP_INTERRUPT_STATUS1 \
	(DP_INTR_AUX_XFER_DONE| \
	DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
	DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \
	DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \
	DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR)

#define DP_INTERRUPT_STATUS1_ACK \
	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT)
#define DP_INTERRUPT_STATUS1_MASK \
	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT)

#define DP_INTERRUPT_STATUS2 \
	(DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \
	DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED)

#define DP_INTERRUPT_STATUS2_ACK \
	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT)
#define DP_INTERRUPT_STATUS2_MASK \
	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)

#define DP_INTERRUPT_STATUS4 \
	(PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
	PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)

#define DP_INTERRUPT_MASK4 \
	(PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
	PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)

#define DP_DEFAULT_AHB_OFFSET	0x0000
#define DP_DEFAULT_AHB_SIZE	0x0200
#define DP_DEFAULT_AUX_OFFSET	0x0200
@@ -77,66 +42,6 @@ void msm_dp_catalog_snapshot(struct msm_dp_catalog *msm_dp_catalog, struct msm_d
				    msm_dp_catalog->p0_len, msm_dp_catalog->p0_base, "dp_p0");
}

u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog)
{
	u32 intr, intr_ack;

	intr = msm_dp_read_ahb(msm_dp_catalog, REG_DP_INTR_STATUS);
	intr &= ~DP_INTERRUPT_STATUS1_MASK;
	intr_ack = (intr & DP_INTERRUPT_STATUS1)
			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS,
		     intr_ack | DP_INTERRUPT_STATUS1_MASK);

	return intr;

}

void msm_dp_catalog_ctrl_enable_irq(struct msm_dp_catalog *msm_dp_catalog,
						bool enable)
{
	if (enable) {
		msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS,
				DP_INTERRUPT_STATUS1_MASK);
		msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2,
				DP_INTERRUPT_STATUS2_MASK);
	} else {
		msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS, 0x00);
		msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2, 0x00);
	}
}

u32 msm_dp_catalog_ctrl_read_psr_interrupt_status(struct msm_dp_catalog *msm_dp_catalog)
{
	u32 intr, intr_ack;

	intr = msm_dp_read_ahb(msm_dp_catalog, REG_DP_INTR_STATUS4);
	intr_ack = (intr & DP_INTERRUPT_STATUS4)
			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS4, intr_ack);

	return intr;
}

void msm_dp_catalog_ctrl_config_psr_interrupt(struct msm_dp_catalog *msm_dp_catalog)
{
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
}

int msm_dp_catalog_ctrl_get_interrupt(struct msm_dp_catalog *msm_dp_catalog)
{
	u32 intr, intr_ack;

	intr = msm_dp_read_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2);
	intr &= ~DP_INTERRUPT_STATUS2_MASK;
	intr_ack = (intr & DP_INTERRUPT_STATUS2)
			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2,
			intr_ack | DP_INTERRUPT_STATUS2_MASK);

	return intr;
}

static void __iomem *msm_dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
{
	struct resource *res;
+0 −26
Original line number Diff line number Diff line
@@ -11,23 +11,6 @@
#include "dp_utils.h"
#include "disp/msm_disp_snapshot.h"

/* interrupts */
#define DP_INTR_HPD		BIT(0)
#define DP_INTR_AUX_XFER_DONE	BIT(3)
#define DP_INTR_WRONG_ADDR	BIT(6)
#define DP_INTR_TIMEOUT		BIT(9)
#define DP_INTR_NACK_DEFER	BIT(12)
#define DP_INTR_WRONG_DATA_CNT	BIT(15)
#define DP_INTR_I2C_NACK	BIT(18)
#define DP_INTR_I2C_DEFER	BIT(21)
#define DP_INTR_PLL_UNLOCKED	BIT(24)
#define DP_INTR_AUX_ERROR	BIT(27)

#define DP_INTR_READY_FOR_VIDEO		BIT(0)
#define DP_INTR_IDLE_PATTERN_SENT	BIT(3)
#define DP_INTR_FRAME_END		BIT(6)
#define DP_INTR_CRC_UPDATED		BIT(9)

#define DP_HW_VERSION_1_0	0x10000000
#define DP_HW_VERSION_1_2	0x10020000

@@ -112,15 +95,6 @@ static inline void msm_dp_write_link(struct msm_dp_catalog *msm_dp_catalog,
/* Debug module */
void msm_dp_catalog_snapshot(struct msm_dp_catalog *msm_dp_catalog, struct msm_disp_state *disp_state);

/* AUX APIs */
u32 msm_dp_catalog_aux_get_irq(struct msm_dp_catalog *msm_dp_catalog);

/* DP Controller APIs */
void msm_dp_catalog_ctrl_enable_irq(struct msm_dp_catalog *msm_dp_catalog, bool enable);
int msm_dp_catalog_ctrl_get_interrupt(struct msm_dp_catalog *msm_dp_catalog);
void msm_dp_catalog_ctrl_config_psr_interrupt(struct msm_dp_catalog *msm_dp_catalog);
u32 msm_dp_catalog_ctrl_read_psr_interrupt_status(struct msm_dp_catalog *msm_dp_catalog);

struct msm_dp_catalog *msm_dp_catalog_get(struct device *dev);

#endif /* _DP_CATALOG_H_ */
+118 −24
Original line number Diff line number Diff line
@@ -31,6 +31,38 @@
#define PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES       (300 * HZ / 1000) /* 300 ms */
#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2)

#define DP_INTERRUPT_STATUS_ACK_SHIFT	1
#define DP_INTERRUPT_STATUS_MASK_SHIFT	2

#define DP_INTERRUPT_STATUS1 \
	(DP_INTR_AUX_XFER_DONE| \
	DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
	DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \
	DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \
	DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR)

#define DP_INTERRUPT_STATUS1_ACK \
	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT)
#define DP_INTERRUPT_STATUS1_MASK \
	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT)

#define DP_INTERRUPT_STATUS2 \
	(DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \
	DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED)

#define DP_INTERRUPT_STATUS2_ACK \
	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT)
#define DP_INTERRUPT_STATUS2_MASK \
	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)

#define DP_INTERRUPT_STATUS4 \
	(PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
	PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)

#define DP_INTERRUPT_MASK4 \
	(PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
	PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)

#define DP_CTRL_INTR_READY_FOR_VIDEO     BIT(0)
#define DP_CTRL_INTR_IDLE_PATTERN_SENT  BIT(3)

@@ -129,8 +161,10 @@ static int msm_dp_aux_link_configure(struct drm_dp_aux *aux,
/*
 * NOTE: resetting DP controller will also clear any pending HPD related interrupts
 */
static void msm_dp_ctrl_reset(struct msm_dp_ctrl_private *ctrl)
void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl)
{
	struct msm_dp_ctrl_private *ctrl =
		container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;
	u32 sw_reset;

@@ -149,6 +183,79 @@ static void msm_dp_ctrl_reset(struct msm_dp_ctrl_private *ctrl)
	}
}

static u32 msm_dp_ctrl_get_aux_interrupt(struct msm_dp_ctrl_private *ctrl)
{
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;
	u32 intr, intr_ack;

	intr = msm_dp_read_ahb(msm_dp_catalog, REG_DP_INTR_STATUS);
	intr &= ~DP_INTERRUPT_STATUS1_MASK;
	intr_ack = (intr & DP_INTERRUPT_STATUS1)
			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS,
		     intr_ack | DP_INTERRUPT_STATUS1_MASK);

	return intr;

}

static u32 msm_dp_ctrl_get_interrupt(struct msm_dp_ctrl_private *ctrl)
{
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;
	u32 intr, intr_ack;

	intr = msm_dp_read_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2);
	intr &= ~DP_INTERRUPT_STATUS2_MASK;
	intr_ack = (intr & DP_INTERRUPT_STATUS2)
			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2,
		     intr_ack | DP_INTERRUPT_STATUS2_MASK);

	return intr;
}

void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl)
{
	struct msm_dp_ctrl_private *ctrl =
		container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;

	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS,
			DP_INTERRUPT_STATUS1_MASK);
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2,
			DP_INTERRUPT_STATUS2_MASK);
}

void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl)
{
	struct msm_dp_ctrl_private *ctrl =
		container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;

	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS, 0x00);
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS2, 0x00);
}

static u32 msm_dp_ctrl_get_psr_interrupt(struct msm_dp_ctrl_private *ctrl)
{
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;
	u32 intr, intr_ack;

	intr = msm_dp_read_ahb(msm_dp_catalog, REG_DP_INTR_STATUS4);
	intr_ack = (intr & DP_INTERRUPT_STATUS4)
			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_STATUS4, intr_ack);

	return intr;
}

static void msm_dp_ctrl_config_psr_interrupt(struct msm_dp_ctrl_private *ctrl)
{
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;

	msm_dp_write_ahb(msm_dp_catalog, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
}

static void msm_dp_ctrl_psr_mainlink_enable(struct msm_dp_ctrl_private *ctrl)
{
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;
@@ -1674,23 +1781,6 @@ static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl)
	return ret;
}

void msm_dp_ctrl_reset_irq_ctrl(struct msm_dp_ctrl *msm_dp_ctrl, bool enable)
{
	struct msm_dp_ctrl_private *ctrl;

	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);

	msm_dp_ctrl_reset(ctrl);

	/*
	 * all dp controller programmable registers will not
	 * be reset to default value after DP_SW_RESET
	 * therefore interrupt mask bits have to be updated
	 * to enable/disable interrupts
	 */
	msm_dp_catalog_ctrl_enable_irq(ctrl->catalog, enable);
}

static void msm_dp_ctrl_enable_sdp(struct msm_dp_ctrl_private *ctrl)
{
	struct msm_dp_catalog *msm_dp_catalog = ctrl->catalog;
@@ -1743,7 +1833,7 @@ void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl)
	cfg |= PSR1_SUPPORTED;
	msm_dp_write_link(msm_dp_catalog, REG_PSR_CONFIG, cfg);

	msm_dp_catalog_ctrl_config_psr_interrupt(msm_dp_catalog);
	msm_dp_ctrl_config_psr_interrupt(ctrl);
	msm_dp_ctrl_enable_sdp(ctrl);

	cfg = DP_PSR_ENABLE;
@@ -1868,7 +1958,7 @@ static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)

	msm_dp_ctrl_mainlink_disable(ctrl);

	msm_dp_ctrl_reset(ctrl);
	msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl);

	dev_pm_opp_set_rate(ctrl->dev, 0);
	msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
@@ -2499,7 +2589,7 @@ void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl)

	msm_dp_ctrl_mainlink_disable(ctrl);

	msm_dp_ctrl_reset(ctrl);
	msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl);

	if (ctrl->stream_clks_on) {
		clk_disable_unprepare(ctrl->pixel_clk);
@@ -2526,7 +2616,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl)
	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);

	if (ctrl->panel->psr_cap.version) {
		isr = msm_dp_catalog_ctrl_read_psr_interrupt_status(ctrl->catalog);
		isr = msm_dp_ctrl_get_psr_interrupt(ctrl);

		if (isr)
			complete(&ctrl->psr_op_comp);
@@ -2541,8 +2631,7 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl)
			drm_dbg_dp(ctrl->drm_dev, "PSR frame capture done\n");
	}

	isr = msm_dp_catalog_ctrl_get_interrupt(ctrl->catalog);

	isr = msm_dp_ctrl_get_interrupt(ctrl);

	if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) {
		drm_dbg_dp(ctrl->drm_dev, "dp_video_ready\n");
@@ -2556,6 +2645,11 @@ irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl)
		ret = IRQ_HANDLED;
	}

	/* DP aux isr */
	isr = msm_dp_ctrl_get_aux_interrupt(ctrl);
	if (isr)
		ret |= msm_dp_aux_isr(ctrl->aux, isr);

	return ret;
}

Loading