xref: /openbmc/linux/drivers/gpu/drm/msm/dp/dp_catalog.c (revision 757a2f36)
1c943b494SChandan Uddaraju // SPDX-License-Identifier: GPL-2.0-only
2c943b494SChandan Uddaraju /*
3c943b494SChandan Uddaraju  * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
4c943b494SChandan Uddaraju  */
5c943b494SChandan Uddaraju 
6c943b494SChandan Uddaraju #define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
7c943b494SChandan Uddaraju 
8c943b494SChandan Uddaraju #include <linux/delay.h>
9c943b494SChandan Uddaraju #include <linux/iopoll.h>
10937f941cSStephen Boyd #include <linux/phy/phy.h>
11937f941cSStephen Boyd #include <linux/phy/phy-dp.h>
12c943b494SChandan Uddaraju #include <linux/rational.h>
135b529e8dSThomas Zimmermann #include <drm/dp/drm_dp_helper.h>
14937f941cSStephen Boyd #include <drm/drm_print.h>
15c943b494SChandan Uddaraju 
16c943b494SChandan Uddaraju #include "dp_catalog.h"
17c943b494SChandan Uddaraju #include "dp_reg.h"
18c943b494SChandan Uddaraju 
19c943b494SChandan Uddaraju #define POLLING_SLEEP_US			1000
20c943b494SChandan Uddaraju #define POLLING_TIMEOUT_US			10000
21c943b494SChandan Uddaraju 
22c943b494SChandan Uddaraju #define SCRAMBLER_RESET_COUNT_VALUE		0xFC
23c943b494SChandan Uddaraju 
24c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS_ACK_SHIFT	1
25c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS_MASK_SHIFT	2
26c943b494SChandan Uddaraju 
27*757a2f36SKuogee Hsieh #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
28*757a2f36SKuogee Hsieh 
29c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1 \
30c943b494SChandan Uddaraju 	(DP_INTR_AUX_I2C_DONE| \
31c943b494SChandan Uddaraju 	DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
32c943b494SChandan Uddaraju 	DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \
33c943b494SChandan Uddaraju 	DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \
34c943b494SChandan Uddaraju 	DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR)
35c943b494SChandan Uddaraju 
36c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1_ACK \
37c943b494SChandan Uddaraju 	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT)
38c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS1_MASK \
39c943b494SChandan Uddaraju 	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT)
40c943b494SChandan Uddaraju 
41c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2 \
42c943b494SChandan Uddaraju 	(DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \
43c943b494SChandan Uddaraju 	DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED)
44c943b494SChandan Uddaraju 
45c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2_ACK \
46c943b494SChandan Uddaraju 	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT)
47c943b494SChandan Uddaraju #define DP_INTERRUPT_STATUS2_MASK \
48c943b494SChandan Uddaraju 	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
49c943b494SChandan Uddaraju 
50c943b494SChandan Uddaraju struct dp_catalog_private {
51c943b494SChandan Uddaraju 	struct device *dev;
52c943b494SChandan Uddaraju 	struct dp_io *io;
53d13e36d7SAbhinav Kumar 	u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX];
54c943b494SChandan Uddaraju 	struct dp_catalog dp_catalog;
55c943b494SChandan Uddaraju 	u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX];
56c943b494SChandan Uddaraju };
57c943b494SChandan Uddaraju 
580f6090f3SAbhinav Kumar void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *disp_state)
590f6090f3SAbhinav Kumar {
600f6090f3SAbhinav Kumar 	struct dp_catalog_private *catalog = container_of(dp_catalog,
610f6090f3SAbhinav Kumar 			struct dp_catalog_private, dp_catalog);
62060c160fSBjorn Andersson 	struct dss_io_data *dss = &catalog->io->dp_controller;
630f6090f3SAbhinav Kumar 
64060c160fSBjorn Andersson 	msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb");
65060c160fSBjorn Andersson 	msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux");
66060c160fSBjorn Andersson 	msm_disp_snapshot_add_block(disp_state, dss->link.len, dss->link.base, "dp_link");
67060c160fSBjorn Andersson 	msm_disp_snapshot_add_block(disp_state, dss->p0.len, dss->p0.base, "dp_p0");
680f6090f3SAbhinav Kumar }
690f6090f3SAbhinav Kumar 
70c943b494SChandan Uddaraju static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset)
71c943b494SChandan Uddaraju {
72060c160fSBjorn Andersson 	return readl_relaxed(catalog->io->dp_controller.aux.base + offset);
73c943b494SChandan Uddaraju }
74c943b494SChandan Uddaraju 
75c943b494SChandan Uddaraju static inline void dp_write_aux(struct dp_catalog_private *catalog,
76c943b494SChandan Uddaraju 			       u32 offset, u32 data)
77c943b494SChandan Uddaraju {
78c943b494SChandan Uddaraju 	/*
79c943b494SChandan Uddaraju 	 * To make sure aux reg writes happens before any other operation,
80c943b494SChandan Uddaraju 	 * this function uses writel() instread of writel_relaxed()
81c943b494SChandan Uddaraju 	 */
82060c160fSBjorn Andersson 	writel(data, catalog->io->dp_controller.aux.base + offset);
83c943b494SChandan Uddaraju }
84c943b494SChandan Uddaraju 
85*757a2f36SKuogee Hsieh static inline u32 dp_read_ahb(const struct dp_catalog_private *catalog, u32 offset)
86c943b494SChandan Uddaraju {
87060c160fSBjorn Andersson 	return readl_relaxed(catalog->io->dp_controller.ahb.base + offset);
88c943b494SChandan Uddaraju }
89c943b494SChandan Uddaraju 
90c943b494SChandan Uddaraju static inline void dp_write_ahb(struct dp_catalog_private *catalog,
91c943b494SChandan Uddaraju 			       u32 offset, u32 data)
92c943b494SChandan Uddaraju {
93c943b494SChandan Uddaraju 	/*
94c943b494SChandan Uddaraju 	 * To make sure phy reg writes happens before any other operation,
95c943b494SChandan Uddaraju 	 * this function uses writel() instread of writel_relaxed()
96c943b494SChandan Uddaraju 	 */
97060c160fSBjorn Andersson 	writel(data, catalog->io->dp_controller.ahb.base + offset);
98c943b494SChandan Uddaraju }
99c943b494SChandan Uddaraju 
100c943b494SChandan Uddaraju static inline void dp_write_p0(struct dp_catalog_private *catalog,
101c943b494SChandan Uddaraju 			       u32 offset, u32 data)
102c943b494SChandan Uddaraju {
103c943b494SChandan Uddaraju 	/*
104c943b494SChandan Uddaraju 	 * To make sure interface reg writes happens before any other operation,
105c943b494SChandan Uddaraju 	 * this function uses writel() instread of writel_relaxed()
106c943b494SChandan Uddaraju 	 */
107060c160fSBjorn Andersson 	writel(data, catalog->io->dp_controller.p0.base + offset);
108c943b494SChandan Uddaraju }
109c943b494SChandan Uddaraju 
110c943b494SChandan Uddaraju static inline u32 dp_read_p0(struct dp_catalog_private *catalog,
111c943b494SChandan Uddaraju 			       u32 offset)
112c943b494SChandan Uddaraju {
113c943b494SChandan Uddaraju 	/*
114c943b494SChandan Uddaraju 	 * To make sure interface reg writes happens before any other operation,
115c943b494SChandan Uddaraju 	 * this function uses writel() instread of writel_relaxed()
116c943b494SChandan Uddaraju 	 */
117060c160fSBjorn Andersson 	return readl_relaxed(catalog->io->dp_controller.p0.base + offset);
118c943b494SChandan Uddaraju }
119c943b494SChandan Uddaraju 
120c943b494SChandan Uddaraju static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset)
121c943b494SChandan Uddaraju {
122060c160fSBjorn Andersson 	return readl_relaxed(catalog->io->dp_controller.link.base + offset);
123c943b494SChandan Uddaraju }
124c943b494SChandan Uddaraju 
125c943b494SChandan Uddaraju static inline void dp_write_link(struct dp_catalog_private *catalog,
126c943b494SChandan Uddaraju 			       u32 offset, u32 data)
127c943b494SChandan Uddaraju {
128c943b494SChandan Uddaraju 	/*
129c943b494SChandan Uddaraju 	 * To make sure link reg writes happens before any other operation,
130c943b494SChandan Uddaraju 	 * this function uses writel() instread of writel_relaxed()
131c943b494SChandan Uddaraju 	 */
132060c160fSBjorn Andersson 	writel(data, catalog->io->dp_controller.link.base + offset);
133c943b494SChandan Uddaraju }
134c943b494SChandan Uddaraju 
135c943b494SChandan Uddaraju /* aux related catalog functions */
136c943b494SChandan Uddaraju u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog)
137c943b494SChandan Uddaraju {
138c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
139c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
140c943b494SChandan Uddaraju 
141c943b494SChandan Uddaraju 	return dp_read_aux(catalog, REG_DP_AUX_DATA);
142c943b494SChandan Uddaraju }
143c943b494SChandan Uddaraju 
144c943b494SChandan Uddaraju int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog)
145c943b494SChandan Uddaraju {
146c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
147c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
148c943b494SChandan Uddaraju 
149c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_AUX_DATA, dp_catalog->aux_data);
150c943b494SChandan Uddaraju 	return 0;
151c943b494SChandan Uddaraju }
152c943b494SChandan Uddaraju 
153c943b494SChandan Uddaraju int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog)
154c943b494SChandan Uddaraju {
155c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
156c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
157c943b494SChandan Uddaraju 
158c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, dp_catalog->aux_data);
159c943b494SChandan Uddaraju 	return 0;
160c943b494SChandan Uddaraju }
161c943b494SChandan Uddaraju 
162c943b494SChandan Uddaraju int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read)
163c943b494SChandan Uddaraju {
164c943b494SChandan Uddaraju 	u32 data;
165c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
166c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
167c943b494SChandan Uddaraju 
168c943b494SChandan Uddaraju 	if (read) {
169c943b494SChandan Uddaraju 		data = dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL);
170c943b494SChandan Uddaraju 		data &= ~DP_AUX_TRANS_CTRL_GO;
171c943b494SChandan Uddaraju 		dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data);
172c943b494SChandan Uddaraju 	} else {
173c943b494SChandan Uddaraju 		dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0);
174c943b494SChandan Uddaraju 	}
175c943b494SChandan Uddaraju 	return 0;
176c943b494SChandan Uddaraju }
177c943b494SChandan Uddaraju 
178c943b494SChandan Uddaraju int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog)
179c943b494SChandan Uddaraju {
180c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
181c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
182c943b494SChandan Uddaraju 
183c943b494SChandan Uddaraju 	dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS);
184c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f);
185c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f);
186c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0);
187c943b494SChandan Uddaraju 	return 0;
188c943b494SChandan Uddaraju }
189c943b494SChandan Uddaraju 
1909fc41843SKuogee Hsieh /**
1919fc41843SKuogee Hsieh  * dp_catalog_aux_reset() - reset AUX controller
1929fc41843SKuogee Hsieh  *
1932eb4bfc0SLee Jones  * @dp_catalog: DP catalog structure
1949fc41843SKuogee Hsieh  *
1959fc41843SKuogee Hsieh  * return: void
1969fc41843SKuogee Hsieh  *
1979fc41843SKuogee Hsieh  * This function reset AUX controller
1989fc41843SKuogee Hsieh  *
1999fc41843SKuogee Hsieh  * NOTE: reset AUX controller will also clear any pending HPD related interrupts
2009fc41843SKuogee Hsieh  *
2019fc41843SKuogee Hsieh  */
202c943b494SChandan Uddaraju void dp_catalog_aux_reset(struct dp_catalog *dp_catalog)
203c943b494SChandan Uddaraju {
204c943b494SChandan Uddaraju 	u32 aux_ctrl;
205c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
206c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
207c943b494SChandan Uddaraju 
208c943b494SChandan Uddaraju 	aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL);
209c943b494SChandan Uddaraju 
210c943b494SChandan Uddaraju 	aux_ctrl |= DP_AUX_CTRL_RESET;
211c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
212c943b494SChandan Uddaraju 	usleep_range(1000, 1100); /* h/w recommended delay */
213c943b494SChandan Uddaraju 
214c943b494SChandan Uddaraju 	aux_ctrl &= ~DP_AUX_CTRL_RESET;
215c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
216c943b494SChandan Uddaraju }
217c943b494SChandan Uddaraju 
218c943b494SChandan Uddaraju void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable)
219c943b494SChandan Uddaraju {
220c943b494SChandan Uddaraju 	u32 aux_ctrl;
221c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
222c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
223c943b494SChandan Uddaraju 
224c943b494SChandan Uddaraju 	aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL);
225c943b494SChandan Uddaraju 
226c943b494SChandan Uddaraju 	if (enable) {
227c943b494SChandan Uddaraju 		dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff);
228c943b494SChandan Uddaraju 		dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff);
229c943b494SChandan Uddaraju 		aux_ctrl |= DP_AUX_CTRL_ENABLE;
230c943b494SChandan Uddaraju 	} else {
231c943b494SChandan Uddaraju 		aux_ctrl &= ~DP_AUX_CTRL_ENABLE;
232c943b494SChandan Uddaraju 	}
233c943b494SChandan Uddaraju 
234c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl);
235c943b494SChandan Uddaraju }
236c943b494SChandan Uddaraju 
237937f941cSStephen Boyd void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog)
238c943b494SChandan Uddaraju {
239c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
240c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
241937f941cSStephen Boyd 	struct dp_io *dp_io = catalog->io;
242937f941cSStephen Boyd 	struct phy *phy = dp_io->phy;
243c943b494SChandan Uddaraju 
244937f941cSStephen Boyd 	phy_calibrate(phy);
245c943b494SChandan Uddaraju }
246c943b494SChandan Uddaraju 
247c943b494SChandan Uddaraju static void dump_regs(void __iomem *base, int len)
248c943b494SChandan Uddaraju {
249c943b494SChandan Uddaraju 	int i;
250c943b494SChandan Uddaraju 	u32 x0, x4, x8, xc;
251c943b494SChandan Uddaraju 	u32 addr_off = 0;
252c943b494SChandan Uddaraju 
253c943b494SChandan Uddaraju 	len = DIV_ROUND_UP(len, 16);
254c943b494SChandan Uddaraju 	for (i = 0; i < len; i++) {
255c943b494SChandan Uddaraju 		x0 = readl_relaxed(base + addr_off);
256c943b494SChandan Uddaraju 		x4 = readl_relaxed(base + addr_off + 0x04);
257c943b494SChandan Uddaraju 		x8 = readl_relaxed(base + addr_off + 0x08);
258c943b494SChandan Uddaraju 		xc = readl_relaxed(base + addr_off + 0x0c);
259c943b494SChandan Uddaraju 
260c943b494SChandan Uddaraju 		pr_info("%08x: %08x %08x %08x %08x", addr_off, x0, x4, x8, xc);
261c943b494SChandan Uddaraju 		addr_off += 16;
262c943b494SChandan Uddaraju 	}
263c943b494SChandan Uddaraju }
264c943b494SChandan Uddaraju 
265c943b494SChandan Uddaraju void dp_catalog_dump_regs(struct dp_catalog *dp_catalog)
266c943b494SChandan Uddaraju {
267c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
268c943b494SChandan Uddaraju 		struct dp_catalog_private, dp_catalog);
269060c160fSBjorn Andersson 	struct dss_io_data *io = &catalog->io->dp_controller;
270c943b494SChandan Uddaraju 
271c943b494SChandan Uddaraju 	pr_info("AHB regs\n");
272060c160fSBjorn Andersson 	dump_regs(io->ahb.base, io->ahb.len);
273c943b494SChandan Uddaraju 
274c943b494SChandan Uddaraju 	pr_info("AUXCLK regs\n");
275060c160fSBjorn Andersson 	dump_regs(io->aux.base, io->aux.len);
276c943b494SChandan Uddaraju 
277c943b494SChandan Uddaraju 	pr_info("LCLK regs\n");
278060c160fSBjorn Andersson 	dump_regs(io->link.base, io->link.len);
279c943b494SChandan Uddaraju 
280c943b494SChandan Uddaraju 	pr_info("P0CLK regs\n");
281060c160fSBjorn Andersson 	dump_regs(io->p0.base, io->p0.len);
282c943b494SChandan Uddaraju }
283c943b494SChandan Uddaraju 
28424c7861bSStephen Boyd u32 dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog)
285c943b494SChandan Uddaraju {
286c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
287c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
288c943b494SChandan Uddaraju 	u32 intr, intr_ack;
289c943b494SChandan Uddaraju 
290c943b494SChandan Uddaraju 	intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS);
291c943b494SChandan Uddaraju 	intr &= ~DP_INTERRUPT_STATUS1_MASK;
292c943b494SChandan Uddaraju 	intr_ack = (intr & DP_INTERRUPT_STATUS1)
293c943b494SChandan Uddaraju 			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
294c943b494SChandan Uddaraju 	dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack |
295c943b494SChandan Uddaraju 			DP_INTERRUPT_STATUS1_MASK);
296c943b494SChandan Uddaraju 
297c943b494SChandan Uddaraju 	return intr;
298c943b494SChandan Uddaraju 
299c943b494SChandan Uddaraju }
300c943b494SChandan Uddaraju 
301c943b494SChandan Uddaraju /* controller related catalog functions */
302c943b494SChandan Uddaraju void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog,
303c943b494SChandan Uddaraju 				u32 dp_tu, u32 valid_boundary,
304c943b494SChandan Uddaraju 				u32 valid_boundary2)
305c943b494SChandan Uddaraju {
306c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
307c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
308c943b494SChandan Uddaraju 
309c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_VALID_BOUNDARY, valid_boundary);
310c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_TU, dp_tu);
311c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2);
312c943b494SChandan Uddaraju }
313c943b494SChandan Uddaraju 
314c943b494SChandan Uddaraju void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state)
315c943b494SChandan Uddaraju {
316c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
317c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
318c943b494SChandan Uddaraju 
319c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_STATE_CTRL, state);
320c943b494SChandan Uddaraju }
321c943b494SChandan Uddaraju 
322c943b494SChandan Uddaraju void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 cfg)
323c943b494SChandan Uddaraju {
324c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
325c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
326c943b494SChandan Uddaraju 
327c943b494SChandan Uddaraju 	DRM_DEBUG_DP("DP_CONFIGURATION_CTRL=0x%x\n", cfg);
328c943b494SChandan Uddaraju 
329c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg);
330c943b494SChandan Uddaraju }
331c943b494SChandan Uddaraju 
332c943b494SChandan Uddaraju void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog)
333c943b494SChandan Uddaraju {
334c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
335c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
336c943b494SChandan Uddaraju 	u32 ln_0 = 0, ln_1 = 1, ln_2 = 2, ln_3 = 3; /* One-to-One mapping */
337c943b494SChandan Uddaraju 	u32 ln_mapping;
338c943b494SChandan Uddaraju 
339c943b494SChandan Uddaraju 	ln_mapping = ln_0 << LANE0_MAPPING_SHIFT;
340c943b494SChandan Uddaraju 	ln_mapping |= ln_1 << LANE1_MAPPING_SHIFT;
341c943b494SChandan Uddaraju 	ln_mapping |= ln_2 << LANE2_MAPPING_SHIFT;
342c943b494SChandan Uddaraju 	ln_mapping |= ln_3 << LANE3_MAPPING_SHIFT;
343c943b494SChandan Uddaraju 
344c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING,
345c943b494SChandan Uddaraju 			ln_mapping);
346c943b494SChandan Uddaraju }
347c943b494SChandan Uddaraju 
348c943b494SChandan Uddaraju void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
349c943b494SChandan Uddaraju 						bool enable)
350c943b494SChandan Uddaraju {
351c943b494SChandan Uddaraju 	u32 mainlink_ctrl;
352c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
353c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
354c943b494SChandan Uddaraju 
355601f0479SMaitreyee Rao 	DRM_DEBUG_DP("enable=%d\n", enable);
356c943b494SChandan Uddaraju 	if (enable) {
357c943b494SChandan Uddaraju 		/*
358c943b494SChandan Uddaraju 		 * To make sure link reg writes happens before other operation,
359c943b494SChandan Uddaraju 		 * dp_write_link() function uses writel()
360c943b494SChandan Uddaraju 		 */
3618ede2eccSKuogee Hsieh 		mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
3628ede2eccSKuogee Hsieh 
3638ede2eccSKuogee Hsieh 		mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET |
364c943b494SChandan Uddaraju 						DP_MAINLINK_CTRL_ENABLE);
3658ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
3668ede2eccSKuogee Hsieh 
3678ede2eccSKuogee Hsieh 		mainlink_ctrl |= DP_MAINLINK_CTRL_RESET;
3688ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
3698ede2eccSKuogee Hsieh 
3708ede2eccSKuogee Hsieh 		mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET;
3718ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
3728ede2eccSKuogee Hsieh 
3738ede2eccSKuogee Hsieh 		mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE |
3748ede2eccSKuogee Hsieh 					DP_MAINLINK_FB_BOUNDARY_SEL);
3758ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
376c943b494SChandan Uddaraju 	} else {
377c943b494SChandan Uddaraju 		mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
378c943b494SChandan Uddaraju 		mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE;
379c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
380c943b494SChandan Uddaraju 	}
381c943b494SChandan Uddaraju }
382c943b494SChandan Uddaraju 
383c943b494SChandan Uddaraju void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
384c943b494SChandan Uddaraju 					u32 colorimetry_cfg,
385c943b494SChandan Uddaraju 					u32 test_bits_depth)
386c943b494SChandan Uddaraju {
387c943b494SChandan Uddaraju 	u32 misc_val;
388c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
389c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
390c943b494SChandan Uddaraju 
391c943b494SChandan Uddaraju 	misc_val = dp_read_link(catalog, REG_DP_MISC1_MISC0);
392c943b494SChandan Uddaraju 
393c943b494SChandan Uddaraju 	/* clear bpp bits */
394c943b494SChandan Uddaraju 	misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT);
395c943b494SChandan Uddaraju 	misc_val |= colorimetry_cfg << DP_MISC0_COLORIMETRY_CFG_SHIFT;
396c943b494SChandan Uddaraju 	misc_val |= test_bits_depth << DP_MISC0_TEST_BITS_DEPTH_SHIFT;
397c943b494SChandan Uddaraju 	/* Configure clock to synchronous mode */
398c943b494SChandan Uddaraju 	misc_val |= DP_MISC0_SYNCHRONOUS_CLK;
399c943b494SChandan Uddaraju 
400c943b494SChandan Uddaraju 	DRM_DEBUG_DP("misc settings = 0x%x\n", misc_val);
401c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
402c943b494SChandan Uddaraju }
403c943b494SChandan Uddaraju 
404c943b494SChandan Uddaraju void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
405c943b494SChandan Uddaraju 					u32 rate, u32 stream_rate_khz,
406c943b494SChandan Uddaraju 					bool fixed_nvid)
407c943b494SChandan Uddaraju {
408c943b494SChandan Uddaraju 	u32 pixel_m, pixel_n;
409937f941cSStephen Boyd 	u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
410c943b494SChandan Uddaraju 	u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE;
411c943b494SChandan Uddaraju 	u32 const link_rate_hbr2 = 540000;
412c943b494SChandan Uddaraju 	u32 const link_rate_hbr3 = 810000;
413c943b494SChandan Uddaraju 	unsigned long den, num;
414c943b494SChandan Uddaraju 
415c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
416c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
417c943b494SChandan Uddaraju 
418937f941cSStephen Boyd 	if (rate == link_rate_hbr3)
419c943b494SChandan Uddaraju 		pixel_div = 6;
420937f941cSStephen Boyd 	else if (rate == 1620000 || rate == 270000)
421c943b494SChandan Uddaraju 		pixel_div = 2;
422937f941cSStephen Boyd 	else if (rate == link_rate_hbr2)
423c943b494SChandan Uddaraju 		pixel_div = 4;
424c943b494SChandan Uddaraju 	else
425c943b494SChandan Uddaraju 		DRM_ERROR("Invalid pixel mux divider\n");
426c943b494SChandan Uddaraju 
427c943b494SChandan Uddaraju 	dispcc_input_rate = (rate * 10) / pixel_div;
428c943b494SChandan Uddaraju 
429c943b494SChandan Uddaraju 	rational_best_approximation(dispcc_input_rate, stream_rate_khz,
430c943b494SChandan Uddaraju 			(unsigned long)(1 << 16) - 1,
431c943b494SChandan Uddaraju 			(unsigned long)(1 << 16) - 1, &den, &num);
432c943b494SChandan Uddaraju 
433c943b494SChandan Uddaraju 	den = ~(den - num);
434c943b494SChandan Uddaraju 	den = den & 0xFFFF;
435c943b494SChandan Uddaraju 	pixel_m = num;
436c943b494SChandan Uddaraju 	pixel_n = den;
437c943b494SChandan Uddaraju 
438c943b494SChandan Uddaraju 	mvid = (pixel_m & 0xFFFF) * 5;
439c943b494SChandan Uddaraju 	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
440c943b494SChandan Uddaraju 
441c943b494SChandan Uddaraju 	if (nvid < nvid_fixed) {
442c943b494SChandan Uddaraju 		u32 temp;
443c943b494SChandan Uddaraju 
444c943b494SChandan Uddaraju 		temp = (nvid_fixed / nvid) * nvid;
445c943b494SChandan Uddaraju 		mvid = (nvid_fixed / nvid) * mvid;
446c943b494SChandan Uddaraju 		nvid = temp;
447c943b494SChandan Uddaraju 	}
448c943b494SChandan Uddaraju 
449c943b494SChandan Uddaraju 	if (link_rate_hbr2 == rate)
450c943b494SChandan Uddaraju 		nvid *= 2;
451c943b494SChandan Uddaraju 
452c943b494SChandan Uddaraju 	if (link_rate_hbr3 == rate)
453c943b494SChandan Uddaraju 		nvid *= 3;
454c943b494SChandan Uddaraju 
455c943b494SChandan Uddaraju 	DRM_DEBUG_DP("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
456c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid);
457c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid);
458c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0);
459c943b494SChandan Uddaraju }
460c943b494SChandan Uddaraju 
46195665325SKuogee Hsieh int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
46295665325SKuogee Hsieh 					u32 state_bit)
463c943b494SChandan Uddaraju {
464c943b494SChandan Uddaraju 	int bit, ret;
465c943b494SChandan Uddaraju 	u32 data;
466c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
467c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
468c943b494SChandan Uddaraju 
46995665325SKuogee Hsieh 	bit = BIT(state_bit - 1);
47095665325SKuogee Hsieh 	DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, state_bit);
4718ede2eccSKuogee Hsieh 	dp_catalog_ctrl_state_ctrl(dp_catalog, bit);
472c943b494SChandan Uddaraju 
47395665325SKuogee Hsieh 	bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
474c943b494SChandan Uddaraju 
475c943b494SChandan Uddaraju 	/* Poll for mainlink ready status */
476060c160fSBjorn Andersson 	ret = readx_poll_timeout(readl, catalog->io->dp_controller.link.base +
477c943b494SChandan Uddaraju 					REG_DP_MAINLINK_READY,
478c943b494SChandan Uddaraju 					data, data & bit,
479c943b494SChandan Uddaraju 					POLLING_SLEEP_US, POLLING_TIMEOUT_US);
480c943b494SChandan Uddaraju 	if (ret < 0) {
48195665325SKuogee Hsieh 		DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit);
482c943b494SChandan Uddaraju 		return ret;
483c943b494SChandan Uddaraju 	}
484c943b494SChandan Uddaraju 	return 0;
485c943b494SChandan Uddaraju }
486c943b494SChandan Uddaraju 
4879fc41843SKuogee Hsieh /**
488*757a2f36SKuogee Hsieh  * dp_catalog_hw_revision() - retrieve DP hw revision
489*757a2f36SKuogee Hsieh  *
490*757a2f36SKuogee Hsieh  * @dp_catalog: DP catalog structure
491*757a2f36SKuogee Hsieh  *
492*757a2f36SKuogee Hsieh  * Return: DP controller hw revision
493*757a2f36SKuogee Hsieh  *
494*757a2f36SKuogee Hsieh  */
495*757a2f36SKuogee Hsieh u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
496*757a2f36SKuogee Hsieh {
497*757a2f36SKuogee Hsieh 	const struct dp_catalog_private *catalog = container_of(dp_catalog,
498*757a2f36SKuogee Hsieh 				struct dp_catalog_private, dp_catalog);
499*757a2f36SKuogee Hsieh 
500*757a2f36SKuogee Hsieh 	return dp_read_ahb(catalog, REG_DP_HW_VERSION);
501*757a2f36SKuogee Hsieh }
502*757a2f36SKuogee Hsieh 
503*757a2f36SKuogee Hsieh /**
5049fc41843SKuogee Hsieh  * dp_catalog_ctrl_reset() - reset DP controller
5059fc41843SKuogee Hsieh  *
5069fc41843SKuogee Hsieh  * @dp_catalog: DP catalog structure
5079fc41843SKuogee Hsieh  *
5089fc41843SKuogee Hsieh  * return: void
5099fc41843SKuogee Hsieh  *
5109fc41843SKuogee Hsieh  * This function reset the DP controller
5119fc41843SKuogee Hsieh  *
5129fc41843SKuogee Hsieh  * NOTE: reset DP controller will also clear any pending HPD related interrupts
5139fc41843SKuogee Hsieh  *
5149fc41843SKuogee Hsieh  */
515c943b494SChandan Uddaraju void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog)
516c943b494SChandan Uddaraju {
517c943b494SChandan Uddaraju 	u32 sw_reset;
518c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
519c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
520c943b494SChandan Uddaraju 
521c943b494SChandan Uddaraju 	sw_reset = dp_read_ahb(catalog, REG_DP_SW_RESET);
522c943b494SChandan Uddaraju 
523c943b494SChandan Uddaraju 	sw_reset |= DP_SW_RESET;
524c943b494SChandan Uddaraju 	dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset);
525c943b494SChandan Uddaraju 	usleep_range(1000, 1100); /* h/w recommended delay */
526c943b494SChandan Uddaraju 
527c943b494SChandan Uddaraju 	sw_reset &= ~DP_SW_RESET;
528c943b494SChandan Uddaraju 	dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset);
529c943b494SChandan Uddaraju }
530c943b494SChandan Uddaraju 
531c943b494SChandan Uddaraju bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog)
532c943b494SChandan Uddaraju {
533c943b494SChandan Uddaraju 	u32 data;
534c943b494SChandan Uddaraju 	int ret;
535c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
536c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
537c943b494SChandan Uddaraju 
538c943b494SChandan Uddaraju 	/* Poll for mainlink ready status */
539060c160fSBjorn Andersson 	ret = readl_poll_timeout(catalog->io->dp_controller.link.base +
540c943b494SChandan Uddaraju 				REG_DP_MAINLINK_READY,
541c943b494SChandan Uddaraju 				data, data & DP_MAINLINK_READY_FOR_VIDEO,
542c943b494SChandan Uddaraju 				POLLING_SLEEP_US, POLLING_TIMEOUT_US);
543c943b494SChandan Uddaraju 	if (ret < 0) {
544c943b494SChandan Uddaraju 		DRM_ERROR("mainlink not ready\n");
545c943b494SChandan Uddaraju 		return false;
546c943b494SChandan Uddaraju 	}
547c943b494SChandan Uddaraju 
548c943b494SChandan Uddaraju 	return true;
549c943b494SChandan Uddaraju }
550c943b494SChandan Uddaraju 
551c943b494SChandan Uddaraju void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog,
552c943b494SChandan Uddaraju 						bool enable)
553c943b494SChandan Uddaraju {
554c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
555c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
556c943b494SChandan Uddaraju 
557c943b494SChandan Uddaraju 	if (enable) {
558c943b494SChandan Uddaraju 		dp_write_ahb(catalog, REG_DP_INTR_STATUS,
559c943b494SChandan Uddaraju 				DP_INTERRUPT_STATUS1_MASK);
560c943b494SChandan Uddaraju 		dp_write_ahb(catalog, REG_DP_INTR_STATUS2,
561c943b494SChandan Uddaraju 				DP_INTERRUPT_STATUS2_MASK);
562c943b494SChandan Uddaraju 	} else {
563c943b494SChandan Uddaraju 		dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00);
564c943b494SChandan Uddaraju 		dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00);
565c943b494SChandan Uddaraju 	}
566c943b494SChandan Uddaraju }
567c943b494SChandan Uddaraju 
568220b856aSTanmay Shah void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog,
569220b856aSTanmay Shah 			u32 intr_mask, bool en)
570c943b494SChandan Uddaraju {
571c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
572c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
573c943b494SChandan Uddaraju 
574220b856aSTanmay Shah 	u32 config = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK);
575220b856aSTanmay Shah 
576220b856aSTanmay Shah 	config = (en ? config | intr_mask : config & ~intr_mask);
577220b856aSTanmay Shah 
578601f0479SMaitreyee Rao 	DRM_DEBUG_DP("intr_mask=%#x config=%#x\n", intr_mask, config);
579220b856aSTanmay Shah 	dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK,
580220b856aSTanmay Shah 				config & DP_DP_HPD_INT_MASK);
581220b856aSTanmay Shah }
582220b856aSTanmay Shah 
583220b856aSTanmay Shah void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog)
584220b856aSTanmay Shah {
585220b856aSTanmay Shah 	struct dp_catalog_private *catalog = container_of(dp_catalog,
586220b856aSTanmay Shah 				struct dp_catalog_private, dp_catalog);
587220b856aSTanmay Shah 
588c943b494SChandan Uddaraju 	u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER);
589c943b494SChandan Uddaraju 
590f21c8a27SKuogee Hsieh 	/* enable HPD plug and unplug interrupts */
591220b856aSTanmay Shah 	dp_catalog_hpd_config_intr(dp_catalog,
592f21c8a27SKuogee Hsieh 		DP_DP_HPD_PLUG_INT_MASK | DP_DP_HPD_UNPLUG_INT_MASK, true);
593c943b494SChandan Uddaraju 
594220b856aSTanmay Shah 	/* Configure REFTIMER and enable it */
595220b856aSTanmay Shah 	reftimer |= DP_DP_HPD_REFTIMER_ENABLE;
596c943b494SChandan Uddaraju 	dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer);
597220b856aSTanmay Shah 
598c943b494SChandan Uddaraju 	/* Enable HPD */
599220b856aSTanmay Shah 	dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN);
600c943b494SChandan Uddaraju }
601220b856aSTanmay Shah 
602231a04fcSKuogee Hsieh u32 dp_catalog_link_is_connected(struct dp_catalog *dp_catalog)
60319e52bcbSKuogee Hsieh {
60419e52bcbSKuogee Hsieh 	struct dp_catalog_private *catalog = container_of(dp_catalog,
60519e52bcbSKuogee Hsieh 				struct dp_catalog_private, dp_catalog);
60619e52bcbSKuogee Hsieh 	u32 status;
60719e52bcbSKuogee Hsieh 
60819e52bcbSKuogee Hsieh 	status = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
609601f0479SMaitreyee Rao 	DRM_DEBUG_DP("aux status: %#x\n", status);
61019e52bcbSKuogee Hsieh 	status >>= DP_DP_HPD_STATE_STATUS_BITS_SHIFT;
61119e52bcbSKuogee Hsieh 	status &= DP_DP_HPD_STATE_STATUS_BITS_MASK;
61219e52bcbSKuogee Hsieh 
61319e52bcbSKuogee Hsieh 	return status;
61419e52bcbSKuogee Hsieh }
61519e52bcbSKuogee Hsieh 
616220b856aSTanmay Shah u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog)
617220b856aSTanmay Shah {
618220b856aSTanmay Shah 	struct dp_catalog_private *catalog = container_of(dp_catalog,
619220b856aSTanmay Shah 				struct dp_catalog_private, dp_catalog);
620220b856aSTanmay Shah 	int isr = 0;
621220b856aSTanmay Shah 
622220b856aSTanmay Shah 	isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS);
623220b856aSTanmay Shah 	dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK,
624220b856aSTanmay Shah 				 (isr & DP_DP_HPD_INT_MASK));
625220b856aSTanmay Shah 
626220b856aSTanmay Shah 	return isr;
627c943b494SChandan Uddaraju }
628c943b494SChandan Uddaraju 
629c943b494SChandan Uddaraju int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog)
630c943b494SChandan Uddaraju {
631c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
632c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
633c943b494SChandan Uddaraju 	u32 intr, intr_ack;
634c943b494SChandan Uddaraju 
635c943b494SChandan Uddaraju 	intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS2);
636c943b494SChandan Uddaraju 	intr &= ~DP_INTERRUPT_STATUS2_MASK;
637c943b494SChandan Uddaraju 	intr_ack = (intr & DP_INTERRUPT_STATUS2)
638c943b494SChandan Uddaraju 			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
639c943b494SChandan Uddaraju 	dp_write_ahb(catalog, REG_DP_INTR_STATUS2,
640c943b494SChandan Uddaraju 			intr_ack | DP_INTERRUPT_STATUS2_MASK);
641c943b494SChandan Uddaraju 
642c943b494SChandan Uddaraju 	return intr;
643c943b494SChandan Uddaraju }
644c943b494SChandan Uddaraju 
645c943b494SChandan Uddaraju void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog)
646c943b494SChandan Uddaraju {
647c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
648c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
649c943b494SChandan Uddaraju 
650c943b494SChandan Uddaraju 	dp_write_ahb(catalog, REG_DP_PHY_CTRL,
651937f941cSStephen Boyd 			DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL);
652c943b494SChandan Uddaraju 	usleep_range(1000, 1100); /* h/w recommended delay */
653c943b494SChandan Uddaraju 	dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0);
654c943b494SChandan Uddaraju }
655c943b494SChandan Uddaraju 
656c943b494SChandan Uddaraju int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog,
657c943b494SChandan Uddaraju 		u8 v_level, u8 p_level)
658c943b494SChandan Uddaraju {
659c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
660c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
661937f941cSStephen Boyd 	struct dp_io *dp_io = catalog->io;
662937f941cSStephen Boyd 	struct phy *phy = dp_io->phy;
663937f941cSStephen Boyd 	struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp;
664c943b494SChandan Uddaraju 
665937f941cSStephen Boyd 	/* TODO: Update for all lanes instead of just first one */
666937f941cSStephen Boyd 	opts_dp->voltage[0] = v_level;
667937f941cSStephen Boyd 	opts_dp->pre[0] = p_level;
668937f941cSStephen Boyd 	opts_dp->set_voltages = 1;
669937f941cSStephen Boyd 	phy_configure(phy, &dp_io->phy_opts);
670937f941cSStephen Boyd 	opts_dp->set_voltages = 0;
671c943b494SChandan Uddaraju 
672c943b494SChandan Uddaraju 	return 0;
673c943b494SChandan Uddaraju }
674c943b494SChandan Uddaraju 
675c943b494SChandan Uddaraju void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
676c943b494SChandan Uddaraju 			u32 pattern)
677c943b494SChandan Uddaraju {
678c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
679c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
680c943b494SChandan Uddaraju 	u32 value = 0x0;
681c943b494SChandan Uddaraju 
682c943b494SChandan Uddaraju 	/* Make sure to clear the current pattern before starting a new one */
683c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0);
684c943b494SChandan Uddaraju 
685601f0479SMaitreyee Rao 	DRM_DEBUG_DP("pattern: %#x\n", pattern);
686c943b494SChandan Uddaraju 	switch (pattern) {
6878ede2eccSKuogee Hsieh 	case DP_PHY_TEST_PATTERN_D10_2:
688c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_STATE_CTRL,
689c943b494SChandan Uddaraju 				DP_STATE_CTRL_LINK_TRAINING_PATTERN1);
6908ede2eccSKuogee Hsieh 		break;
6918ede2eccSKuogee Hsieh 	case DP_PHY_TEST_PATTERN_ERROR_COUNT:
6928ede2eccSKuogee Hsieh 		value &= ~(1 << 16);
6938ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
6948ede2eccSKuogee Hsieh 					value);
6958ede2eccSKuogee Hsieh 		value |= SCRAMBLER_RESET_COUNT_VALUE;
6968ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
6978ede2eccSKuogee Hsieh 					value);
6988ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
6998ede2eccSKuogee Hsieh 					DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
7008ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_STATE_CTRL,
7018ede2eccSKuogee Hsieh 					DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
7028ede2eccSKuogee Hsieh 		break;
7038ede2eccSKuogee Hsieh 	case DP_PHY_TEST_PATTERN_PRBS7:
704c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_STATE_CTRL,
705c943b494SChandan Uddaraju 				DP_STATE_CTRL_LINK_PRBS7);
7068ede2eccSKuogee Hsieh 		break;
7078ede2eccSKuogee Hsieh 	case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
708c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_STATE_CTRL,
709c943b494SChandan Uddaraju 				DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN);
710c943b494SChandan Uddaraju 		/* 00111110000011111000001111100000 */
711c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0,
712c943b494SChandan Uddaraju 				0x3E0F83E0);
713c943b494SChandan Uddaraju 		/* 00001111100000111110000011111000 */
714c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1,
715c943b494SChandan Uddaraju 				0x0F83E0F8);
716c943b494SChandan Uddaraju 		/* 1111100000111110 */
717c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2,
718c943b494SChandan Uddaraju 				0x0000F83E);
7198ede2eccSKuogee Hsieh 		break;
7208ede2eccSKuogee Hsieh 	case DP_PHY_TEST_PATTERN_CP2520:
7218ede2eccSKuogee Hsieh 		value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
7228ede2eccSKuogee Hsieh 		value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER;
7238ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
7248ede2eccSKuogee Hsieh 
725c943b494SChandan Uddaraju 		value = DP_HBR2_ERM_PATTERN;
726c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
727c943b494SChandan Uddaraju 				value);
728c943b494SChandan Uddaraju 		value |= SCRAMBLER_RESET_COUNT_VALUE;
729c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
730c943b494SChandan Uddaraju 					value);
731c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
732c943b494SChandan Uddaraju 					DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
733c943b494SChandan Uddaraju 		dp_write_link(catalog, REG_DP_STATE_CTRL,
734c943b494SChandan Uddaraju 					DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
7358ede2eccSKuogee Hsieh 		value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
7368ede2eccSKuogee Hsieh 		value |= DP_MAINLINK_CTRL_ENABLE;
7378ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
7388ede2eccSKuogee Hsieh 		break;
7398ede2eccSKuogee Hsieh 	case DP_PHY_TEST_PATTERN_SEL_MASK:
7408ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
7418ede2eccSKuogee Hsieh 				DP_MAINLINK_CTRL_ENABLE);
7428ede2eccSKuogee Hsieh 		dp_write_link(catalog, REG_DP_STATE_CTRL,
7438ede2eccSKuogee Hsieh 				DP_STATE_CTRL_LINK_TRAINING_PATTERN4);
7448ede2eccSKuogee Hsieh 		break;
745c943b494SChandan Uddaraju 	default:
746601f0479SMaitreyee Rao 		DRM_DEBUG_DP("No valid test pattern requested: %#x\n", pattern);
7478ede2eccSKuogee Hsieh 		break;
748c943b494SChandan Uddaraju 	}
749c943b494SChandan Uddaraju }
750c943b494SChandan Uddaraju 
751c943b494SChandan Uddaraju u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog)
752c943b494SChandan Uddaraju {
753c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
754c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
755c943b494SChandan Uddaraju 
756c943b494SChandan Uddaraju 	return dp_read_link(catalog, REG_DP_MAINLINK_READY);
757c943b494SChandan Uddaraju }
758c943b494SChandan Uddaraju 
759c943b494SChandan Uddaraju /* panel related catalog functions */
760c943b494SChandan Uddaraju int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
761c943b494SChandan Uddaraju {
762c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
763c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
764*757a2f36SKuogee Hsieh 	u32 reg;
765c943b494SChandan Uddaraju 
766c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_TOTAL_HOR_VER,
767c943b494SChandan Uddaraju 				dp_catalog->total);
768c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC,
769c943b494SChandan Uddaraju 				dp_catalog->sync_start);
770c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY,
771c943b494SChandan Uddaraju 				dp_catalog->width_blanking);
772c943b494SChandan Uddaraju 	dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active);
773*757a2f36SKuogee Hsieh 
774*757a2f36SKuogee Hsieh 	reg = dp_read_p0(catalog, MMSS_DP_INTF_CONFIG);
775*757a2f36SKuogee Hsieh 
776*757a2f36SKuogee Hsieh 	if (dp_catalog->wide_bus_en)
777*757a2f36SKuogee Hsieh 		reg |= DP_INTF_CONFIG_DATABUS_WIDEN;
778*757a2f36SKuogee Hsieh 	else
779*757a2f36SKuogee Hsieh 		reg &= ~DP_INTF_CONFIG_DATABUS_WIDEN;
780*757a2f36SKuogee Hsieh 
781*757a2f36SKuogee Hsieh 
782*757a2f36SKuogee Hsieh 	DRM_DEBUG_DP("wide_bus_en=%d reg=%#x\n", dp_catalog->wide_bus_en, reg);
783*757a2f36SKuogee Hsieh 
784*757a2f36SKuogee Hsieh 	dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, reg);
785c943b494SChandan Uddaraju 	return 0;
786c943b494SChandan Uddaraju }
787c943b494SChandan Uddaraju 
788c943b494SChandan Uddaraju void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
789c943b494SChandan Uddaraju 				struct drm_display_mode *drm_mode)
790c943b494SChandan Uddaraju {
791c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
792c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
793c943b494SChandan Uddaraju 	u32 hsync_period, vsync_period;
794c943b494SChandan Uddaraju 	u32 display_v_start, display_v_end;
795c943b494SChandan Uddaraju 	u32 hsync_start_x, hsync_end_x;
796c943b494SChandan Uddaraju 	u32 v_sync_width;
797c943b494SChandan Uddaraju 	u32 hsync_ctl;
798c943b494SChandan Uddaraju 	u32 display_hctl;
799c943b494SChandan Uddaraju 
800c943b494SChandan Uddaraju 	/* TPG config parameters*/
801c943b494SChandan Uddaraju 	hsync_period = drm_mode->htotal;
802c943b494SChandan Uddaraju 	vsync_period = drm_mode->vtotal;
803c943b494SChandan Uddaraju 
804c943b494SChandan Uddaraju 	display_v_start = ((drm_mode->vtotal - drm_mode->vsync_start) *
805c943b494SChandan Uddaraju 					hsync_period);
806c943b494SChandan Uddaraju 	display_v_end = ((vsync_period - (drm_mode->vsync_start -
807c943b494SChandan Uddaraju 					drm_mode->vdisplay))
808c943b494SChandan Uddaraju 					* hsync_period) - 1;
809c943b494SChandan Uddaraju 
810c943b494SChandan Uddaraju 	display_v_start += drm_mode->htotal - drm_mode->hsync_start;
811c943b494SChandan Uddaraju 	display_v_end -= (drm_mode->hsync_start - drm_mode->hdisplay);
812c943b494SChandan Uddaraju 
813c943b494SChandan Uddaraju 	hsync_start_x = drm_mode->htotal - drm_mode->hsync_start;
814c943b494SChandan Uddaraju 	hsync_end_x = hsync_period - (drm_mode->hsync_start -
815c943b494SChandan Uddaraju 					drm_mode->hdisplay) - 1;
816c943b494SChandan Uddaraju 
817c943b494SChandan Uddaraju 	v_sync_width = drm_mode->vsync_end - drm_mode->vsync_start;
818c943b494SChandan Uddaraju 
819c943b494SChandan Uddaraju 	hsync_ctl = (hsync_period << 16) |
820c943b494SChandan Uddaraju 			(drm_mode->hsync_end - drm_mode->hsync_start);
821c943b494SChandan Uddaraju 	display_hctl = (hsync_end_x << 16) | hsync_start_x;
822c943b494SChandan Uddaraju 
823c943b494SChandan Uddaraju 
824c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0);
825c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl);
826c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period *
827c943b494SChandan Uddaraju 			hsync_period);
828c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width *
829c943b494SChandan Uddaraju 			hsync_period);
830c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0);
831c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0);
832c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl);
833c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0);
834c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start);
835c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end);
836c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0);
837c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0);
838c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0);
839c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0);
840c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0);
841c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0);
842c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0);
843c943b494SChandan Uddaraju 
844c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL,
845c943b494SChandan Uddaraju 				DP_TPG_CHECKERED_RECT_PATTERN);
846c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG,
847c943b494SChandan Uddaraju 				DP_TPG_VIDEO_CONFIG_BPP_8BIT |
848c943b494SChandan Uddaraju 				DP_TPG_VIDEO_CONFIG_RGB);
849c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_BIST_ENABLE,
850c943b494SChandan Uddaraju 				DP_BIST_ENABLE_DPBIST_EN);
851c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN,
852c943b494SChandan Uddaraju 				DP_TIMING_ENGINE_EN_EN);
853c943b494SChandan Uddaraju 	DRM_DEBUG_DP("%s: enabled tpg\n", __func__);
854c943b494SChandan Uddaraju }
855c943b494SChandan Uddaraju 
856c943b494SChandan Uddaraju void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog)
857c943b494SChandan Uddaraju {
858c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog = container_of(dp_catalog,
859c943b494SChandan Uddaraju 				struct dp_catalog_private, dp_catalog);
860c943b494SChandan Uddaraju 
861c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0);
862c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0);
863c943b494SChandan Uddaraju 	dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0);
864c943b494SChandan Uddaraju }
865c943b494SChandan Uddaraju 
866c943b494SChandan Uddaraju struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io)
867c943b494SChandan Uddaraju {
868c943b494SChandan Uddaraju 	struct dp_catalog_private *catalog;
869c943b494SChandan Uddaraju 
870c943b494SChandan Uddaraju 	if (!io) {
871c943b494SChandan Uddaraju 		DRM_ERROR("invalid input\n");
872c943b494SChandan Uddaraju 		return ERR_PTR(-EINVAL);
873c943b494SChandan Uddaraju 	}
874c943b494SChandan Uddaraju 
875c943b494SChandan Uddaraju 	catalog  = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL);
876c943b494SChandan Uddaraju 	if (!catalog)
877c943b494SChandan Uddaraju 		return ERR_PTR(-ENOMEM);
878c943b494SChandan Uddaraju 
879c943b494SChandan Uddaraju 	catalog->dev = dev;
880c943b494SChandan Uddaraju 	catalog->io = io;
881c943b494SChandan Uddaraju 
882c943b494SChandan Uddaraju 	return &catalog->dp_catalog;
883c943b494SChandan Uddaraju }
884d13e36d7SAbhinav Kumar 
885d13e36d7SAbhinav Kumar void dp_catalog_audio_get_header(struct dp_catalog *dp_catalog)
886d13e36d7SAbhinav Kumar {
887d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
888d13e36d7SAbhinav Kumar 	u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX];
889d13e36d7SAbhinav Kumar 	enum dp_catalog_audio_sdp_type sdp;
890d13e36d7SAbhinav Kumar 	enum dp_catalog_audio_header_type header;
891d13e36d7SAbhinav Kumar 
892d13e36d7SAbhinav Kumar 	if (!dp_catalog)
893d13e36d7SAbhinav Kumar 		return;
894d13e36d7SAbhinav Kumar 
895d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
896d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
897d13e36d7SAbhinav Kumar 
898d13e36d7SAbhinav Kumar 	sdp_map = catalog->audio_map;
899d13e36d7SAbhinav Kumar 	sdp     = dp_catalog->sdp_type;
900d13e36d7SAbhinav Kumar 	header  = dp_catalog->sdp_header;
901d13e36d7SAbhinav Kumar 
902d13e36d7SAbhinav Kumar 	dp_catalog->audio_data = dp_read_link(catalog,
903d13e36d7SAbhinav Kumar 			sdp_map[sdp][header]);
904d13e36d7SAbhinav Kumar }
905d13e36d7SAbhinav Kumar 
906d13e36d7SAbhinav Kumar void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog)
907d13e36d7SAbhinav Kumar {
908d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
909d13e36d7SAbhinav Kumar 	u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX];
910d13e36d7SAbhinav Kumar 	enum dp_catalog_audio_sdp_type sdp;
911d13e36d7SAbhinav Kumar 	enum dp_catalog_audio_header_type header;
912d13e36d7SAbhinav Kumar 	u32 data;
913d13e36d7SAbhinav Kumar 
914d13e36d7SAbhinav Kumar 	if (!dp_catalog)
915d13e36d7SAbhinav Kumar 		return;
916d13e36d7SAbhinav Kumar 
917d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
918d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
919d13e36d7SAbhinav Kumar 
920d13e36d7SAbhinav Kumar 	sdp_map = catalog->audio_map;
921d13e36d7SAbhinav Kumar 	sdp     = dp_catalog->sdp_type;
922d13e36d7SAbhinav Kumar 	header  = dp_catalog->sdp_header;
923d13e36d7SAbhinav Kumar 	data    = dp_catalog->audio_data;
924d13e36d7SAbhinav Kumar 
925d13e36d7SAbhinav Kumar 	dp_write_link(catalog, sdp_map[sdp][header], data);
926d13e36d7SAbhinav Kumar }
927d13e36d7SAbhinav Kumar 
928d13e36d7SAbhinav Kumar void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog)
929d13e36d7SAbhinav Kumar {
930d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
931d13e36d7SAbhinav Kumar 	u32 acr_ctrl, select;
932d13e36d7SAbhinav Kumar 
933d13e36d7SAbhinav Kumar 	if (!dp_catalog)
934d13e36d7SAbhinav Kumar 		return;
935d13e36d7SAbhinav Kumar 
936d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
937d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
938d13e36d7SAbhinav Kumar 
939d13e36d7SAbhinav Kumar 	select = dp_catalog->audio_data;
940d13e36d7SAbhinav Kumar 	acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14);
941d13e36d7SAbhinav Kumar 
942601f0479SMaitreyee Rao 	DRM_DEBUG_DP("select: %#x, acr_ctrl: %#x\n", select, acr_ctrl);
943d13e36d7SAbhinav Kumar 
944d13e36d7SAbhinav Kumar 	dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl);
945d13e36d7SAbhinav Kumar }
946d13e36d7SAbhinav Kumar 
947d13e36d7SAbhinav Kumar void dp_catalog_audio_enable(struct dp_catalog *dp_catalog)
948d13e36d7SAbhinav Kumar {
949d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
950d13e36d7SAbhinav Kumar 	bool enable;
951d13e36d7SAbhinav Kumar 	u32 audio_ctrl;
952d13e36d7SAbhinav Kumar 
953d13e36d7SAbhinav Kumar 	if (!dp_catalog)
954d13e36d7SAbhinav Kumar 		return;
955d13e36d7SAbhinav Kumar 
956d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
957d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
958d13e36d7SAbhinav Kumar 
959d13e36d7SAbhinav Kumar 	enable = !!dp_catalog->audio_data;
960d13e36d7SAbhinav Kumar 	audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG);
961d13e36d7SAbhinav Kumar 
962d13e36d7SAbhinav Kumar 	if (enable)
963d13e36d7SAbhinav Kumar 		audio_ctrl |= BIT(0);
964d13e36d7SAbhinav Kumar 	else
965d13e36d7SAbhinav Kumar 		audio_ctrl &= ~BIT(0);
966d13e36d7SAbhinav Kumar 
967d13e36d7SAbhinav Kumar 	DRM_DEBUG_DP("dp_audio_cfg = 0x%x\n", audio_ctrl);
968d13e36d7SAbhinav Kumar 
969d13e36d7SAbhinav Kumar 	dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl);
970d13e36d7SAbhinav Kumar 	/* make sure audio engine is disabled */
971d13e36d7SAbhinav Kumar 	wmb();
972d13e36d7SAbhinav Kumar }
973d13e36d7SAbhinav Kumar 
974d13e36d7SAbhinav Kumar void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog)
975d13e36d7SAbhinav Kumar {
976d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
977d13e36d7SAbhinav Kumar 	u32 sdp_cfg = 0;
978d13e36d7SAbhinav Kumar 	u32 sdp_cfg2 = 0;
979d13e36d7SAbhinav Kumar 
980d13e36d7SAbhinav Kumar 	if (!dp_catalog)
981d13e36d7SAbhinav Kumar 		return;
982d13e36d7SAbhinav Kumar 
983d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
984d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
985d13e36d7SAbhinav Kumar 
986d13e36d7SAbhinav Kumar 	sdp_cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
987d13e36d7SAbhinav Kumar 	/* AUDIO_TIMESTAMP_SDP_EN */
988d13e36d7SAbhinav Kumar 	sdp_cfg |= BIT(1);
989d13e36d7SAbhinav Kumar 	/* AUDIO_STREAM_SDP_EN */
990d13e36d7SAbhinav Kumar 	sdp_cfg |= BIT(2);
991d13e36d7SAbhinav Kumar 	/* AUDIO_COPY_MANAGEMENT_SDP_EN */
992d13e36d7SAbhinav Kumar 	sdp_cfg |= BIT(5);
993d13e36d7SAbhinav Kumar 	/* AUDIO_ISRC_SDP_EN  */
994d13e36d7SAbhinav Kumar 	sdp_cfg |= BIT(6);
995d13e36d7SAbhinav Kumar 	/* AUDIO_INFOFRAME_SDP_EN  */
996d13e36d7SAbhinav Kumar 	sdp_cfg |= BIT(20);
997d13e36d7SAbhinav Kumar 
998d13e36d7SAbhinav Kumar 	DRM_DEBUG_DP("sdp_cfg = 0x%x\n", sdp_cfg);
999d13e36d7SAbhinav Kumar 
1000d13e36d7SAbhinav Kumar 	dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg);
1001d13e36d7SAbhinav Kumar 
1002d13e36d7SAbhinav Kumar 	sdp_cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
1003d13e36d7SAbhinav Kumar 	/* IFRM_REGSRC -> Do not use reg values */
1004d13e36d7SAbhinav Kumar 	sdp_cfg2 &= ~BIT(0);
1005d13e36d7SAbhinav Kumar 	/* AUDIO_STREAM_HB3_REGSRC-> Do not use reg values */
1006d13e36d7SAbhinav Kumar 	sdp_cfg2 &= ~BIT(1);
1007d13e36d7SAbhinav Kumar 
1008d13e36d7SAbhinav Kumar 	DRM_DEBUG_DP("sdp_cfg2 = 0x%x\n", sdp_cfg2);
1009d13e36d7SAbhinav Kumar 
1010d13e36d7SAbhinav Kumar 	dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2);
1011d13e36d7SAbhinav Kumar }
1012d13e36d7SAbhinav Kumar 
1013d13e36d7SAbhinav Kumar void dp_catalog_audio_init(struct dp_catalog *dp_catalog)
1014d13e36d7SAbhinav Kumar {
1015d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
1016d13e36d7SAbhinav Kumar 
1017d13e36d7SAbhinav Kumar 	static u32 sdp_map[][DP_AUDIO_SDP_HEADER_MAX] = {
1018d13e36d7SAbhinav Kumar 		{
1019d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_STREAM_0,
1020d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_STREAM_1,
1021d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_STREAM_1,
1022d13e36d7SAbhinav Kumar 		},
1023d13e36d7SAbhinav Kumar 		{
1024d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_TIMESTAMP_0,
1025d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_TIMESTAMP_1,
1026d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_TIMESTAMP_1,
1027d13e36d7SAbhinav Kumar 		},
1028d13e36d7SAbhinav Kumar 		{
1029d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_INFOFRAME_0,
1030d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_INFOFRAME_1,
1031d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_INFOFRAME_1,
1032d13e36d7SAbhinav Kumar 		},
1033d13e36d7SAbhinav Kumar 		{
1034d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_COPYMANAGEMENT_0,
1035d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_COPYMANAGEMENT_1,
1036d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_COPYMANAGEMENT_1,
1037d13e36d7SAbhinav Kumar 		},
1038d13e36d7SAbhinav Kumar 		{
1039d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_ISRC_0,
1040d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_ISRC_1,
1041d13e36d7SAbhinav Kumar 			MMSS_DP_AUDIO_ISRC_1,
1042d13e36d7SAbhinav Kumar 		},
1043d13e36d7SAbhinav Kumar 	};
1044d13e36d7SAbhinav Kumar 
1045d13e36d7SAbhinav Kumar 	if (!dp_catalog)
1046d13e36d7SAbhinav Kumar 		return;
1047d13e36d7SAbhinav Kumar 
1048d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
1049d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
1050d13e36d7SAbhinav Kumar 
1051d13e36d7SAbhinav Kumar 	catalog->audio_map = sdp_map;
1052d13e36d7SAbhinav Kumar }
1053d13e36d7SAbhinav Kumar 
1054d13e36d7SAbhinav Kumar void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog)
1055d13e36d7SAbhinav Kumar {
1056d13e36d7SAbhinav Kumar 	struct dp_catalog_private *catalog;
1057d13e36d7SAbhinav Kumar 	u32 mainlink_levels, safe_to_exit_level;
1058d13e36d7SAbhinav Kumar 
1059d13e36d7SAbhinav Kumar 	if (!dp_catalog)
1060d13e36d7SAbhinav Kumar 		return;
1061d13e36d7SAbhinav Kumar 
1062d13e36d7SAbhinav Kumar 	catalog = container_of(dp_catalog,
1063d13e36d7SAbhinav Kumar 		struct dp_catalog_private, dp_catalog);
1064d13e36d7SAbhinav Kumar 
1065d13e36d7SAbhinav Kumar 	safe_to_exit_level = dp_catalog->audio_data;
1066d13e36d7SAbhinav Kumar 	mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS);
1067d13e36d7SAbhinav Kumar 	mainlink_levels &= 0xFE0;
1068d13e36d7SAbhinav Kumar 	mainlink_levels |= safe_to_exit_level;
1069d13e36d7SAbhinav Kumar 
1070d13e36d7SAbhinav Kumar 	DRM_DEBUG_DP("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n",
1071d13e36d7SAbhinav Kumar 			 mainlink_levels, safe_to_exit_level);
1072d13e36d7SAbhinav Kumar 
1073d13e36d7SAbhinav Kumar 	dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels);
1074d13e36d7SAbhinav Kumar }
1075