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

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

Merge "drm/msm/sde: add connector property to expose custom mode info"

parents e56b9d8d a9f975ad
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -62,6 +62,11 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
	ctrl->ops.debug_bus = dsi_ctrl_hw_cmn_debug_bus;
	ctrl->ops.get_cmd_read_data = dsi_ctrl_hw_cmn_get_cmd_read_data;
	ctrl->ops.clear_rdbk_register = dsi_ctrl_hw_cmn_clear_rdbk_reg;
	ctrl->ops.ctrl_reset = dsi_ctrl_hw_cmn_ctrl_reset;
	ctrl->ops.mask_error_intr = dsi_ctrl_hw_cmn_mask_error_intr;
	ctrl->ops.error_intr_ctrl = dsi_ctrl_hw_cmn_error_intr_ctrl;
	ctrl->ops.get_error_mask = dsi_ctrl_hw_cmn_get_error_mask;
	ctrl->ops.get_hw_version = dsi_ctrl_hw_cmn_get_hw_version;

	switch (version) {
	case DSI_CTRL_VERSION_1_4:
@@ -203,6 +208,7 @@ static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy)
	phy->ops.ulps_ops.is_lanes_in_ulps =
		dsi_phy_hw_v3_0_is_lanes_in_ulps;
	phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0;
	phy->ops.phy_lane_reset = dsi_phy_hw_v3_0_lane_reset;
}

/**
+8 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy);
bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes);
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
		u32 *timing_val, u32 size);
int dsi_phy_hw_v3_0_lane_reset(struct dsi_phy_hw *phy);

/* DSI controller common ops */
u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl);
@@ -178,6 +179,13 @@ u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
				     u32 pkt_size, u32 *hw_read_cnt);
void dsi_ctrl_hw_cmn_clear_rdbk_reg(struct dsi_ctrl_hw *ctrl);
void dsi_ctrl_hw_22_schedule_dma_cmd(struct dsi_ctrl_hw *ctrl, int line_on);
int dsi_ctrl_hw_cmn_ctrl_reset(struct dsi_ctrl_hw *ctrl,
			int mask);
void dsi_ctrl_hw_cmn_mask_error_intr(struct dsi_ctrl_hw *ctrl, u32 idx,
			bool en);
void dsi_ctrl_hw_cmn_error_intr_ctrl(struct dsi_ctrl_hw *ctrl, bool en);
u32 dsi_ctrl_hw_cmn_get_error_mask(struct dsi_ctrl_hw *ctrl);
u32 dsi_ctrl_hw_cmn_get_hw_version(struct dsi_ctrl_hw *ctrl);

/* Definitions specific to 1.4 DSI controller hardware */
int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
+135 −40
Original line number Diff line number Diff line
@@ -1041,6 +1041,9 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
		dsi_ctrl_wait_for_video_done(dsi_ctrl);
		dsi_ctrl_enable_status_interrupt(dsi_ctrl,
					DSI_SINT_CMD_MODE_DMA_DONE, NULL);
		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), true);
		reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);

		if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
@@ -1081,6 +1084,9 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
			}
		}

		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), false);
		dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw);
	}
error:
@@ -1945,7 +1951,7 @@ int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
	}

	dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
	dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0);
	dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
	dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);

	mutex_unlock(&dsi_ctrl->ctrl_lock);
@@ -1996,33 +2002,77 @@ int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable)
static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
				unsigned long int error)
{
	pr_err("%s: %lu\n", __func__, error);
	struct dsi_event_cb_info cb_info;

	/* DTLN PHY error */
	if (error & 0x3000e00)
	cb_info = dsi_ctrl->irq_info.irq_err_cb;

	/* disable error interrupts */
	if (dsi_ctrl->hw.ops.error_intr_ctrl)
		dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, false);

	/* clear error interrupts first */
	if (dsi_ctrl->hw.ops.clear_error_status)
		dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
					0x3000e00);
					error);

	/* DTLN PHY error */
	if (error & 0x3000E00)
		pr_err("dsi PHY contention error: 0x%lx\n", error);

	/* TX timeout error */
	if (error & 0xE0) {
		if (error & 0xA0) {
			if (cb_info.event_cb) {
				cb_info.event_idx = DSI_LP_Rx_TIMEOUT;
				(void)cb_info.event_cb(cb_info.event_usr_ptr,
							cb_info.event_idx,
							dsi_ctrl->cell_index,
							0, 0, 0, 0);
			}
		}
		pr_err("tx timeout error: 0x%lx\n", error);
	}

	/* DSI FIFO OVERFLOW error */
	if (error & 0xf0000) {
		if (dsi_ctrl->hw.ops.clear_error_status)
			dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
					0xf0000);
	if (error & 0xF0000) {
		u32 mask = 0;

		if (dsi_ctrl->hw.ops.get_error_mask)
			mask = dsi_ctrl->hw.ops.get_error_mask(&dsi_ctrl->hw);
		/* no need to report FIFO overflow if already masked */
		if (cb_info.event_cb && !(mask & 0xf0000)) {
			cb_info.event_idx = DSI_FIFO_OVERFLOW;
			(void)cb_info.event_cb(cb_info.event_usr_ptr,
						cb_info.event_idx,
						dsi_ctrl->cell_index,
						0, 0, 0, 0);
			pr_err("dsi FIFO OVERFLOW error: 0x%lx\n", error);
		}
	}

	/* DSI FIFO UNDERFLOW error */
	if (error & 0xf00000) {
		if (dsi_ctrl->hw.ops.clear_error_status)
			dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
					0xf00000);
	if (error & 0xF00000) {
		if (cb_info.event_cb) {
			cb_info.event_idx = DSI_FIFO_UNDERFLOW;
			(void)cb_info.event_cb(cb_info.event_usr_ptr,
						cb_info.event_idx,
						dsi_ctrl->cell_index,
						0, 0, 0, 0);
		}
		pr_err("dsi FIFO UNDERFLOW error: 0x%lx\n", error);
	}

	/* DSI PLL UNLOCK error */
	if (error & BIT(8))
		if (dsi_ctrl->hw.ops.clear_error_status)
			dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
					BIT(8));
		pr_err("dsi PLL unlock error: 0x%lx\n", error);

	/* ACK error */
	if (error & 0xF)
		pr_err("ack error: 0x%lx\n", error);

	/* enable back DSI interrupts */
	if (dsi_ctrl->hw.ops.error_intr_ctrl)
		dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, true);
}

/**
@@ -2036,39 +2086,28 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
	struct dsi_ctrl *dsi_ctrl;
	struct dsi_event_cb_info cb_info;
	unsigned long flags;
	uint32_t cell_index, status, i;
	uint64_t errors;
	uint32_t status = 0x0, i;
	uint64_t errors = 0x0;

	if (!ptr)
		return IRQ_NONE;
	dsi_ctrl = ptr;

	/* clear status interrupts */
	/* check status interrupts */
	if (dsi_ctrl->hw.ops.get_interrupt_status)
		status = dsi_ctrl->hw.ops.get_interrupt_status(&dsi_ctrl->hw);
	else
		status = 0x0;

	if (dsi_ctrl->hw.ops.clear_interrupt_status)
		dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, status);

	spin_lock_irqsave(&dsi_ctrl->irq_info.irq_lock, flags);
	cell_index = dsi_ctrl->cell_index;
	spin_unlock_irqrestore(&dsi_ctrl->irq_info.irq_lock, flags);

	/* clear error interrupts */
	/* check error interrupts */
	if (dsi_ctrl->hw.ops.get_error_status)
		errors = dsi_ctrl->hw.ops.get_error_status(&dsi_ctrl->hw);
	else
		errors = 0x0;

	if (errors) {
	/* clear interrupts */
	if (dsi_ctrl->hw.ops.clear_interrupt_status)
		dsi_ctrl->hw.ops.clear_interrupt_status(&dsi_ctrl->hw, 0x0);

	/* handle DSI error recovery */
	if (status & DSI_ERROR)
		dsi_ctrl_handle_error_status(dsi_ctrl, errors);
		if (dsi_ctrl->hw.ops.clear_error_status)
			dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
							errors);
	}

	if (status & DSI_CMD_MODE_DMA_DONE) {
		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
@@ -2089,9 +2128,16 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
	}

	if (status & DSI_BTA_DONE) {
		u32 fifo_overflow_mask = (DSI_DLN0_HS_FIFO_OVERFLOW |
					DSI_DLN1_HS_FIFO_OVERFLOW |
					DSI_DLN2_HS_FIFO_OVERFLOW |
					DSI_DLN3_HS_FIFO_OVERFLOW);
		dsi_ctrl_disable_status_interrupt(dsi_ctrl,
					DSI_SINT_BTA_DONE);
		complete_all(&dsi_ctrl->irq_info.bta_done);
		if (dsi_ctrl->hw.ops.clear_error_status)
			dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
					fifo_overflow_mask);
	}

	for (i = 0; status && i < DSI_STATUS_INTERRUPT_COUNT; ++i) {
@@ -2104,7 +2150,8 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
			if (cb_info.event_cb)
				(void)cb_info.event_cb(cb_info.event_usr_ptr,
						cb_info.event_idx,
						cell_index, irq, 0, 0, 0);
						dsi_ctrl->cell_index,
						irq, 0, 0, 0);
		}
		status >>= 1;
	}
@@ -2314,7 +2361,7 @@ int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool is_splash_enabled)
	dsi_ctrl_setup_isr(dsi_ctrl);

	dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
	dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0x0);
	dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);

	pr_debug("[DSI_%d]Host initialization complete, continuous splash status:%d\n",
		dsi_ctrl->cell_index, is_splash_enabled);
@@ -2337,6 +2384,48 @@ int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl)
	return 0;
}

int dsi_ctrl_reset(struct dsi_ctrl *dsi_ctrl, int mask)
{
	int rc = 0;

	if (!dsi_ctrl)
		return -EINVAL;

	mutex_lock(&dsi_ctrl->ctrl_lock);
	rc = dsi_ctrl->hw.ops.ctrl_reset(&dsi_ctrl->hw, mask);
	mutex_unlock(&dsi_ctrl->ctrl_lock);

	return rc;
}

int dsi_ctrl_get_hw_version(struct dsi_ctrl *dsi_ctrl)
{
	int rc = 0;

	if (!dsi_ctrl)
		return -EINVAL;

	mutex_lock(&dsi_ctrl->ctrl_lock);
	rc = dsi_ctrl->hw.ops.get_hw_version(&dsi_ctrl->hw);
	mutex_unlock(&dsi_ctrl->ctrl_lock);

	return rc;
}

int dsi_ctrl_vid_engine_en(struct dsi_ctrl *dsi_ctrl, bool on)
{
	int rc = 0;

	if (!dsi_ctrl)
		return -EINVAL;

	mutex_lock(&dsi_ctrl->ctrl_lock);
	dsi_ctrl->hw.ops.video_engine_en(&dsi_ctrl->hw, on);
	mutex_unlock(&dsi_ctrl->ctrl_lock);

	return rc;
}

/**
 * dsi_ctrl_host_deinit() - De-Initialize DSI host hardware.
 * @dsi_ctrl:        DSI controller handle.
@@ -2538,6 +2627,9 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
		dsi_ctrl_wait_for_video_done(dsi_ctrl);
		dsi_ctrl_enable_status_interrupt(dsi_ctrl,
					DSI_SINT_CMD_MODE_DMA_DONE, NULL);
		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), true);
		reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done);

		/* trigger command */
@@ -2568,6 +2660,9 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
						dsi_ctrl->cell_index);
			}
		}
		if (dsi_ctrl->hw.ops.mask_error_intr)
			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
					BIT(DSI_FIFO_OVERFLOW), false);
	}

	mutex_unlock(&dsi_ctrl->ctrl_lock);
+24 −0
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ struct dsi_ctrl_state_info {
 * @irq_stat_mask:       Hardware mask of currently enabled interrupts.
 * @irq_stat_refcount:   Number of times each interrupt has been requested.
 * @irq_stat_cb:         Status IRQ callback definitions.
 * @irq_err_cb:          IRQ callback definition to handle DSI ERRORs.
 * @cmd_dma_done:          Completion signal for DSI_CMD_MODE_DMA_DONE interrupt
 * @vid_frame_done:        Completion signal for DSI_VIDEO_MODE_FRAME_DONE int.
 * @cmd_frame_done:        Completion signal for DSI_CMD_FRAME_DONE interrupt.
@@ -156,6 +157,7 @@ struct dsi_ctrl_interrupts {
	uint32_t irq_stat_mask;
	int irq_stat_refcount[DSI_STATUS_INTERRUPT_COUNT];
	struct dsi_event_cb_info irq_stat_cb[DSI_STATUS_INTERRUPT_COUNT];
	struct dsi_event_cb_info irq_err_cb;

	struct completion cmd_dma_done;
	struct completion vid_frame_done;
@@ -177,6 +179,7 @@ struct dsi_ctrl_interrupts {
 * @current_state:       Current driver and hardware state.
 * @clk_cb:		 Callback for DSI clock control.
 * @irq_info:            Interrupt information.
 * @recovery_cb:         Recovery call back to SDE.
 * @clk_info:            Clock information.
 * @clk_freq:            DSi Link clock frequency information.
 * @pwr_info:            Power information.
@@ -215,6 +218,7 @@ struct dsi_ctrl {
	struct clk_ctrl_cb clk_cb;

	struct dsi_ctrl_interrupts irq_info;
	struct dsi_event_cb_info recovery_cb;

	/* Clock and power states */
	struct dsi_ctrl_clk_info clk_info;
@@ -651,4 +655,24 @@ void dsi_ctrl_drv_register(void);
 */
void dsi_ctrl_drv_unregister(void);

/**
 * dsi_ctrl_reset() - Reset DSI PHY CLK/DATA lane
 * @dsi_ctrl:        DSI controller handle.
 * @mask:	     Mask to indicate if CLK and/or DATA lane needs reset.
 */
int dsi_ctrl_reset(struct dsi_ctrl *dsi_ctrl, int mask);

/**
 * dsi_ctrl_get_hw_version() - read dsi controller hw revision
 * @dsi_ctrl:        DSI controller handle.
 */
int dsi_ctrl_get_hw_version(struct dsi_ctrl *dsi_ctrl);

/**
 * dsi_ctrl_vid_engine_en() - Control DSI video engine HW state
 * @dsi_ctrl:        DSI controller handle.
 * @on:		variable to control video engine ON/OFF.
 */
int dsi_ctrl_vid_engine_en(struct dsi_ctrl *dsi_ctrl, bool on);

#endif /* _DSI_CTRL_H_ */
+43 −1
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ enum dsi_test_pattern {
 * @DSI_SINT_DESKEW_DONE:              The deskew calibration operation done.
 * @DSI_SINT_DYN_BLANK_DMA_DONE:       The dynamic blankin DMA operation has
 *                                     completed.
 * @DSI_SINT_ERROR:                    DSI error has happened.
 */
enum dsi_status_int_index {
	DSI_SINT_CMD_MODE_DMA_DONE = 0,
@@ -108,6 +109,7 @@ enum dsi_status_int_index {
	DSI_SINT_DYN_REFRESH_DONE = 7,
	DSI_SINT_DESKEW_DONE = 8,
	DSI_SINT_DYN_BLANK_DMA_DONE = 9,
	DSI_SINT_ERROR = 10,

	DSI_STATUS_INTERRUPT_COUNT
};
@@ -126,6 +128,7 @@ enum dsi_status_int_index {
 * @DSI_DESKEW_DONE:              The deskew calibration operation has completed
 * @DSI_DYN_BLANK_DMA_DONE:       The dynamic blankin DMA operation has
 *                                completed.
 * @DSI_ERROR:                    DSI error has happened.
 */
enum dsi_status_int_type {
	DSI_CMD_MODE_DMA_DONE = BIT(DSI_SINT_CMD_MODE_DMA_DONE),
@@ -137,7 +140,8 @@ enum dsi_status_int_type {
	DSI_CMD_FRAME_DONE = BIT(DSI_SINT_CMD_FRAME_DONE),
	DSI_DYN_REFRESH_DONE = BIT(DSI_SINT_DYN_REFRESH_DONE),
	DSI_DESKEW_DONE = BIT(DSI_SINT_DESKEW_DONE),
	DSI_DYN_BLANK_DMA_DONE = BIT(DSI_SINT_DYN_BLANK_DMA_DONE)
	DSI_DYN_BLANK_DMA_DONE = BIT(DSI_SINT_DYN_BLANK_DMA_DONE),
	DSI_ERROR = BIT(DSI_SINT_ERROR)
};

/**
@@ -175,6 +179,7 @@ enum dsi_status_int_type {
 * @DSI_EINT_DLN1_LP1_CONTENTION:        PHY level contention while lane 1 high.
 * @DSI_EINT_DLN2_LP1_CONTENTION:        PHY level contention while lane 2 high.
 * @DSI_EINT_DLN3_LP1_CONTENTION:        PHY level contention while lane 3 high.
 * @DSI_EINT_PANEL_SPECIFIC_ERR:         DSI Protocol violation error.
 */
enum dsi_error_int_index {
	DSI_EINT_RDBK_SINGLE_ECC_ERR = 0,
@@ -209,6 +214,7 @@ enum dsi_error_int_index {
	DSI_EINT_DLN1_LP1_CONTENTION = 29,
	DSI_EINT_DLN2_LP1_CONTENTION = 30,
	DSI_EINT_DLN3_LP1_CONTENTION = 31,
	DSI_EINT_PANEL_SPECIFIC_ERR = 32,

	DSI_ERROR_INTERRUPT_COUNT
};
@@ -248,6 +254,7 @@ enum dsi_error_int_index {
 * @DSI_DLN1_LP1_CONTENTION:        PHY level contention while lane 1 is high.
 * @DSI_DLN2_LP1_CONTENTION:        PHY level contention while lane 2 is high.
 * @DSI_DLN3_LP1_CONTENTION:        PHY level contention while lane 3 is high.
 * @DSI_PANEL_SPECIFIC_ERR:         DSI Protocol violation.
 */
enum dsi_error_int_type {
	DSI_RDBK_SINGLE_ECC_ERR = BIT(DSI_EINT_RDBK_SINGLE_ECC_ERR),
@@ -282,6 +289,7 @@ enum dsi_error_int_type {
	DSI_DLN1_LP1_CONTENTION = BIT(DSI_EINT_DLN1_LP1_CONTENTION),
	DSI_DLN2_LP1_CONTENTION = BIT(DSI_EINT_DLN2_LP1_CONTENTION),
	DSI_DLN3_LP1_CONTENTION = BIT(DSI_EINT_DLN3_LP1_CONTENTION),
	DSI_PANEL_SPECIFIC_ERR = BIT(DSI_EINT_PANEL_SPECIFIC_ERR),
};

/**
@@ -735,6 +743,40 @@ struct dsi_ctrl_hw_ops {
	 *                needs to be sent.
	 */
	void (*schedule_dma_cmd)(struct dsi_ctrl_hw *ctrl, int line_no);

	/**
	 * ctrl_reset() - Reset DSI lanes to recover from DSI errors
	 * @ctrl:         Pointer to the controller host hardware.
	 * @mask:         Indicates the error type.
	 */
	int (*ctrl_reset)(struct dsi_ctrl_hw *ctrl, int mask);

	/**
	 * mask_error_int() - Mask/Unmask particular DSI error interrupts
	 * @ctrl:         Pointer to the controller host hardware.
	 * @idx:	  Indicates the errors to be masked.
	 * @en:		  Bool for mask or unmask of the error
	 */
	void (*mask_error_intr)(struct dsi_ctrl_hw *ctrl, u32 idx, bool en);

	/**
	 * error_intr_ctrl() - Mask/Unmask master DSI error interrupt
	 * @ctrl:         Pointer to the controller host hardware.
	 * @en:		  Bool for mask or unmask of DSI error
	 */
	void (*error_intr_ctrl)(struct dsi_ctrl_hw *ctrl, bool en);

	/**
	 * get_error_mask() - get DSI error interrupt mask status
	 * @ctrl:         Pointer to the controller host hardware.
	 */
	u32 (*get_error_mask)(struct dsi_ctrl_hw *ctrl);

	/**
	 * get_hw_version() - get DSI controller hw version
	 * @ctrl:         Pointer to the controller host hardware.
	 */
	u32 (*get_hw_version)(struct dsi_ctrl_hw *ctrl);
};

/*
Loading