xref: /linux/drivers/gpu/drm/tegra/dsi.c (revision 87154ff86bf69ecf76600e56ecab0b79fc3f71ea)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2dec72739SThierry Reding /*
3dec72739SThierry Reding  * Copyright (C) 2013 NVIDIA Corporation
4dec72739SThierry Reding  */
5dec72739SThierry Reding 
6dec72739SThierry Reding #include <linux/clk.h>
7dec72739SThierry Reding #include <linux/debugfs.h>
8eb1df694SSam Ravnborg #include <linux/delay.h>
9dec72739SThierry Reding #include <linux/host1x.h>
10dec72739SThierry Reding #include <linux/module.h>
11dec72739SThierry Reding #include <linux/of.h>
12e94236cdSThierry Reding #include <linux/of_platform.h>
13dec72739SThierry Reding #include <linux/platform_device.h>
14ef8187d7SThierry Reding #include <linux/pm_runtime.h>
15eb1df694SSam Ravnborg #include <linux/regulator/consumer.h>
16dec72739SThierry Reding #include <linux/reset.h>
17dec72739SThierry Reding 
18eb1df694SSam Ravnborg #include <video/mipi_display.h>
193b077afbSThierry Reding 
204aa3df71SThierry Reding #include <drm/drm_atomic_helper.h>
21eb1df694SSam Ravnborg #include <drm/drm_debugfs.h>
22eb1df694SSam Ravnborg #include <drm/drm_file.h>
23dec72739SThierry Reding #include <drm/drm_mipi_dsi.h>
24dec72739SThierry Reding #include <drm/drm_panel.h>
254d0e95e0SThomas Zimmermann #include <drm/drm_simple_kms_helper.h>
26dec72739SThierry Reding 
27dec72739SThierry Reding #include "dc.h"
28dec72739SThierry Reding #include "drm.h"
29dec72739SThierry Reding #include "dsi.h"
30dec72739SThierry Reding #include "mipi-phy.h"
3175af8fa7SThierry Reding #include "trace.h"
32dec72739SThierry Reding 
33ebd14afeSThierry Reding struct tegra_dsi_state {
34ebd14afeSThierry Reding 	struct drm_connector_state base;
35ebd14afeSThierry Reding 
36ebd14afeSThierry Reding 	struct mipi_dphy_timing timing;
37ebd14afeSThierry Reding 	unsigned long period;
38ebd14afeSThierry Reding 
39ebd14afeSThierry Reding 	unsigned int vrefresh;
40ebd14afeSThierry Reding 	unsigned int lanes;
41ebd14afeSThierry Reding 	unsigned long pclk;
42ebd14afeSThierry Reding 	unsigned long bclk;
43ebd14afeSThierry Reding 
44ebd14afeSThierry Reding 	enum tegra_dsi_format format;
45ebd14afeSThierry Reding 	unsigned int mul;
46ebd14afeSThierry Reding 	unsigned int div;
47ebd14afeSThierry Reding };
48ebd14afeSThierry Reding 
49ebd14afeSThierry Reding static inline struct tegra_dsi_state *
50ebd14afeSThierry Reding to_dsi_state(struct drm_connector_state *state)
51ebd14afeSThierry Reding {
52ebd14afeSThierry Reding 	return container_of(state, struct tegra_dsi_state, base);
53ebd14afeSThierry Reding }
54ebd14afeSThierry Reding 
55dec72739SThierry Reding struct tegra_dsi {
56dec72739SThierry Reding 	struct host1x_client client;
57dec72739SThierry Reding 	struct tegra_output output;
58dec72739SThierry Reding 	struct device *dev;
59dec72739SThierry Reding 
60dec72739SThierry Reding 	void __iomem *regs;
61dec72739SThierry Reding 
62dec72739SThierry Reding 	struct reset_control *rst;
63dec72739SThierry Reding 	struct clk *clk_parent;
64dec72739SThierry Reding 	struct clk *clk_lp;
65dec72739SThierry Reding 	struct clk *clk;
66dec72739SThierry Reding 
67dec72739SThierry Reding 	struct drm_info_list *debugfs_files;
68dec72739SThierry Reding 
6917297a28SThierry Reding 	unsigned long flags;
70dec72739SThierry Reding 	enum mipi_dsi_pixel_format format;
71dec72739SThierry Reding 	unsigned int lanes;
72dec72739SThierry Reding 
73dec72739SThierry Reding 	struct tegra_mipi_device *mipi;
74dec72739SThierry Reding 	struct mipi_dsi_host host;
753b077afbSThierry Reding 
763b077afbSThierry Reding 	struct regulator *vdd;
77976cebc3SThierry Reding 
78976cebc3SThierry Reding 	unsigned int video_fifo_depth;
79976cebc3SThierry Reding 	unsigned int host_fifo_depth;
80e94236cdSThierry Reding 
81e94236cdSThierry Reding 	/* for ganged-mode support */
82e94236cdSThierry Reding 	struct tegra_dsi *master;
83e94236cdSThierry Reding 	struct tegra_dsi *slave;
84dec72739SThierry Reding };
85dec72739SThierry Reding 
86dec72739SThierry Reding static inline struct tegra_dsi *
87dec72739SThierry Reding host1x_client_to_dsi(struct host1x_client *client)
88dec72739SThierry Reding {
89dec72739SThierry Reding 	return container_of(client, struct tegra_dsi, client);
90dec72739SThierry Reding }
91dec72739SThierry Reding 
92dec72739SThierry Reding static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host)
93dec72739SThierry Reding {
94dec72739SThierry Reding 	return container_of(host, struct tegra_dsi, host);
95dec72739SThierry Reding }
96dec72739SThierry Reding 
97dec72739SThierry Reding static inline struct tegra_dsi *to_dsi(struct tegra_output *output)
98dec72739SThierry Reding {
99dec72739SThierry Reding 	return container_of(output, struct tegra_dsi, output);
100dec72739SThierry Reding }
101dec72739SThierry Reding 
102ebd14afeSThierry Reding static struct tegra_dsi_state *tegra_dsi_get_state(struct tegra_dsi *dsi)
103ebd14afeSThierry Reding {
104ebd14afeSThierry Reding 	return to_dsi_state(dsi->output.connector.state);
105ebd14afeSThierry Reding }
106ebd14afeSThierry Reding 
10712831076SThierry Reding static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned int offset)
108dec72739SThierry Reding {
10975af8fa7SThierry Reding 	u32 value = readl(dsi->regs + (offset << 2));
11075af8fa7SThierry Reding 
11175af8fa7SThierry Reding 	trace_dsi_readl(dsi->dev, offset, value);
11275af8fa7SThierry Reding 
11375af8fa7SThierry Reding 	return value;
114dec72739SThierry Reding }
115dec72739SThierry Reding 
1169c0b4ca1SThierry Reding static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
11712831076SThierry Reding 				    unsigned int offset)
118dec72739SThierry Reding {
11975af8fa7SThierry Reding 	trace_dsi_writel(dsi->dev, offset, value);
12012831076SThierry Reding 	writel(value, dsi->regs + (offset << 2));
121dec72739SThierry Reding }
122dec72739SThierry Reding 
123a40051c0SThierry Reding #define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
124a40051c0SThierry Reding 
125a40051c0SThierry Reding static const struct debugfs_reg32 tegra_dsi_regs[] = {
126a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INCR_SYNCPT),
127a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL),
128a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR),
129a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_CTXSW),
130a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_RD_DATA),
131a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_WR_DATA),
132a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_POWER_CONTROL),
133a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INT_ENABLE),
134a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INT_STATUS),
135a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INT_MASK),
136a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_HOST_CONTROL),
137a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_CONTROL),
138a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_SOL_DELAY),
139a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_MAX_THRESHOLD),
140a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_TRIGGER),
141a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_TX_CRC),
142a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_STATUS),
143a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_CONTROL),
144a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_0),
145a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_1),
146a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_2),
147a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_3),
148a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_4),
149a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_5),
150a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_6),
151a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_7),
152a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_0_LO),
153a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_0_HI),
154a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_1_LO),
155a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_1_HI),
156a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_2_LO),
157a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_2_HI),
158a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_3_LO),
159a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_3_HI),
160a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_4_LO),
161a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_4_HI),
162a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_5_LO),
163a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_SEQ_5_HI),
164a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_DCS_CMDS),
165a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_LEN_0_1),
166a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_LEN_2_3),
167a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_LEN_4_5),
168a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PKT_LEN_6_7),
169a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PHY_TIMING_0),
170a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PHY_TIMING_1),
171a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PHY_TIMING_2),
172a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_BTA_TIMING),
173a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_TIMEOUT_0),
174a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_TIMEOUT_1),
175a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_TO_TALLY),
176a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CONTROL_0),
177a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CONTROL_CD),
178a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CD_STATUS),
179a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_VIDEO_MODE_CONTROL),
180a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CONTROL_1),
181a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CONTROL_2),
182a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CONTROL_3),
183a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_PAD_CONTROL_4),
184a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL),
185a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_GANGED_MODE_START),
186a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_GANGED_MODE_SIZE),
187a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT),
188a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL),
189a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8),
190a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9),
191a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10),
192a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11),
193a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12),
194a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13),
195a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14),
196a40051c0SThierry Reding 	DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15),
197a40051c0SThierry Reding };
198a40051c0SThierry Reding 
199dec72739SThierry Reding static int tegra_dsi_show_regs(struct seq_file *s, void *data)
200dec72739SThierry Reding {
201dec72739SThierry Reding 	struct drm_info_node *node = s->private;
202dec72739SThierry Reding 	struct tegra_dsi *dsi = node->info_ent->data;
203171e2e6dSThierry Reding 	struct drm_crtc *crtc = dsi->output.encoder.crtc;
204171e2e6dSThierry Reding 	struct drm_device *drm = node->minor->dev;
205a40051c0SThierry Reding 	unsigned int i;
206171e2e6dSThierry Reding 	int err = 0;
207171e2e6dSThierry Reding 
208171e2e6dSThierry Reding 	drm_modeset_lock_all(drm);
209171e2e6dSThierry Reding 
210171e2e6dSThierry Reding 	if (!crtc || !crtc->state->active) {
211171e2e6dSThierry Reding 		err = -EBUSY;
212171e2e6dSThierry Reding 		goto unlock;
213171e2e6dSThierry Reding 	}
214dec72739SThierry Reding 
215a40051c0SThierry Reding 	for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) {
216a40051c0SThierry Reding 		unsigned int offset = tegra_dsi_regs[i].offset;
217dec72739SThierry Reding 
218a40051c0SThierry Reding 		seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs[i].name,
219a40051c0SThierry Reding 			   offset, tegra_dsi_readl(dsi, offset));
220a40051c0SThierry Reding 	}
221dec72739SThierry Reding 
222171e2e6dSThierry Reding unlock:
223171e2e6dSThierry Reding 	drm_modeset_unlock_all(drm);
224171e2e6dSThierry Reding 	return err;
225dec72739SThierry Reding }
226dec72739SThierry Reding 
227dec72739SThierry Reding static struct drm_info_list debugfs_files[] = {
228dec72739SThierry Reding 	{ "regs", tegra_dsi_show_regs, 0, NULL },
229dec72739SThierry Reding };
230dec72739SThierry Reding 
231a813d704SThierry Reding static int tegra_dsi_late_register(struct drm_connector *connector)
232dec72739SThierry Reding {
233a813d704SThierry Reding 	struct tegra_output *output = connector_to_output(connector);
234a813d704SThierry Reding 	unsigned int i, count = ARRAY_SIZE(debugfs_files);
235a813d704SThierry Reding 	struct drm_minor *minor = connector->dev->primary;
236a813d704SThierry Reding 	struct dentry *root = connector->debugfs_entry;
237a813d704SThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
238dec72739SThierry Reding 
239dec72739SThierry Reding 	dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
240dec72739SThierry Reding 				     GFP_KERNEL);
241a813d704SThierry Reding 	if (!dsi->debugfs_files)
242a813d704SThierry Reding 		return -ENOMEM;
243dec72739SThierry Reding 
244a813d704SThierry Reding 	for (i = 0; i < count; i++)
245dec72739SThierry Reding 		dsi->debugfs_files[i].data = dsi;
246dec72739SThierry Reding 
247ad6d94f2SWambui Karuga 	drm_debugfs_create_files(dsi->debugfs_files, count, root, minor);
248dec72739SThierry Reding 
249dec72739SThierry Reding 	return 0;
250dec72739SThierry Reding }
251dec72739SThierry Reding 
252a813d704SThierry Reding static void tegra_dsi_early_unregister(struct drm_connector *connector)
253dec72739SThierry Reding {
254a813d704SThierry Reding 	struct tegra_output *output = connector_to_output(connector);
255a813d704SThierry Reding 	unsigned int count = ARRAY_SIZE(debugfs_files);
256a813d704SThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
257dec72739SThierry Reding 
258a813d704SThierry Reding 	drm_debugfs_remove_files(dsi->debugfs_files, count,
259a813d704SThierry Reding 				 connector->dev->primary);
260dec72739SThierry Reding 	kfree(dsi->debugfs_files);
261dec72739SThierry Reding 	dsi->debugfs_files = NULL;
262dec72739SThierry Reding }
263dec72739SThierry Reding 
264dec72739SThierry Reding #define PKT_ID0(id)	((((id) & 0x3f) <<  3) | (1 <<  9))
265dec72739SThierry Reding #define PKT_LEN0(len)	(((len) & 0x07) <<  0)
266dec72739SThierry Reding #define PKT_ID1(id)	((((id) & 0x3f) << 13) | (1 << 19))
267dec72739SThierry Reding #define PKT_LEN1(len)	(((len) & 0x07) << 10)
268dec72739SThierry Reding #define PKT_ID2(id)	((((id) & 0x3f) << 23) | (1 << 29))
269dec72739SThierry Reding #define PKT_LEN2(len)	(((len) & 0x07) << 20)
270dec72739SThierry Reding 
271dec72739SThierry Reding #define PKT_LP		(1 << 30)
272dec72739SThierry Reding #define NUM_PKT_SEQ	12
273dec72739SThierry Reding 
27417297a28SThierry Reding /*
27517297a28SThierry Reding  * non-burst mode with sync pulses
27617297a28SThierry Reding  */
27717297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = {
278dec72739SThierry Reding 	[ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
279dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
280dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
281dec72739SThierry Reding 	       PKT_LP,
282dec72739SThierry Reding 	[ 1] = 0,
283dec72739SThierry Reding 	[ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) |
284dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
285dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
286dec72739SThierry Reding 	       PKT_LP,
287dec72739SThierry Reding 	[ 3] = 0,
288dec72739SThierry Reding 	[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
289dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
290dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
291dec72739SThierry Reding 	       PKT_LP,
292dec72739SThierry Reding 	[ 5] = 0,
293dec72739SThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
294dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
295dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
296dec72739SThierry Reding 	[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
297dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
298dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
299dec72739SThierry Reding 	[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
300dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
301dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
302dec72739SThierry Reding 	       PKT_LP,
303dec72739SThierry Reding 	[ 9] = 0,
304dec72739SThierry Reding 	[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
305dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
306dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
307dec72739SThierry Reding 	[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
308dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
309dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
310dec72739SThierry Reding };
311dec72739SThierry Reding 
31217297a28SThierry Reding /*
31317297a28SThierry Reding  * non-burst mode with sync events
31417297a28SThierry Reding  */
31517297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
31617297a28SThierry Reding 	[ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
31717297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
31817297a28SThierry Reding 	       PKT_LP,
31917297a28SThierry Reding 	[ 1] = 0,
32017297a28SThierry Reding 	[ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
32117297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
32217297a28SThierry Reding 	       PKT_LP,
32317297a28SThierry Reding 	[ 3] = 0,
32417297a28SThierry Reding 	[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
32517297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
32617297a28SThierry Reding 	       PKT_LP,
32717297a28SThierry Reding 	[ 5] = 0,
32817297a28SThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
32917297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
33017297a28SThierry Reding 	       PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
33117297a28SThierry Reding 	[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
33217297a28SThierry Reding 	[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
33317297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
33417297a28SThierry Reding 	       PKT_LP,
33517297a28SThierry Reding 	[ 9] = 0,
33617297a28SThierry Reding 	[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
33717297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
33817297a28SThierry Reding 	       PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
33917297a28SThierry Reding 	[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
34017297a28SThierry Reding };
34117297a28SThierry Reding 
342337b443dSThierry Reding static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = {
343337b443dSThierry Reding 	[ 0] = 0,
344337b443dSThierry Reding 	[ 1] = 0,
345337b443dSThierry Reding 	[ 2] = 0,
346337b443dSThierry Reding 	[ 3] = 0,
347337b443dSThierry Reding 	[ 4] = 0,
348337b443dSThierry Reding 	[ 5] = 0,
349337b443dSThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP,
350337b443dSThierry Reding 	[ 7] = 0,
351337b443dSThierry Reding 	[ 8] = 0,
352337b443dSThierry Reding 	[ 9] = 0,
353337b443dSThierry Reding 	[10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP,
354337b443dSThierry Reding 	[11] = 0,
355337b443dSThierry Reding };
356337b443dSThierry Reding 
357ebd14afeSThierry Reding static void tegra_dsi_set_phy_timing(struct tegra_dsi *dsi,
358ebd14afeSThierry Reding 				     unsigned long period,
359ebd14afeSThierry Reding 				     const struct mipi_dphy_timing *timing)
360dec72739SThierry Reding {
3619c0b4ca1SThierry Reding 	u32 value;
362dec72739SThierry Reding 
363ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->hsexit, period, 1) << 24 |
364ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hstrail, period, 0) << 16 |
365ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hszero, period, 3) << 8 |
366ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hsprepare, period, 1);
367dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0);
368dec72739SThierry Reding 
369ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->clktrail, period, 1) << 24 |
370ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkpost, period, 1) << 16 |
371ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkzero, period, 1) << 8 |
372ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->lpx, period, 1);
373dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1);
374dec72739SThierry Reding 
375ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->clkprepare, period, 1) << 16 |
376ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkpre, period, 1) << 8 |
377dec72739SThierry Reding 		DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
378dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2);
379dec72739SThierry Reding 
380ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->taget, period, 1) << 16 |
381ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->tasure, period, 1) << 8 |
382ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->tago, period, 1);
383dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);
384dec72739SThierry Reding 
3857e3bc3a9SSean Paul 	if (dsi->slave)
386ebd14afeSThierry Reding 		tegra_dsi_set_phy_timing(dsi->slave, period, timing);
387dec72739SThierry Reding }
388dec72739SThierry Reding 
389dec72739SThierry Reding static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format,
390dec72739SThierry Reding 				unsigned int *mulp, unsigned int *divp)
391dec72739SThierry Reding {
392dec72739SThierry Reding 	switch (format) {
393dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB666_PACKED:
394dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB888:
395dec72739SThierry Reding 		*mulp = 3;
396dec72739SThierry Reding 		*divp = 1;
397dec72739SThierry Reding 		break;
398dec72739SThierry Reding 
399dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB565:
400dec72739SThierry Reding 		*mulp = 2;
401dec72739SThierry Reding 		*divp = 1;
402dec72739SThierry Reding 		break;
403dec72739SThierry Reding 
404dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB666:
405dec72739SThierry Reding 		*mulp = 9;
406dec72739SThierry Reding 		*divp = 4;
407dec72739SThierry Reding 		break;
408dec72739SThierry Reding 
409dec72739SThierry Reding 	default:
410dec72739SThierry Reding 		return -EINVAL;
411dec72739SThierry Reding 	}
412dec72739SThierry Reding 
413dec72739SThierry Reding 	return 0;
414dec72739SThierry Reding }
415dec72739SThierry Reding 
416f7d6889bSThierry Reding static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format,
417f7d6889bSThierry Reding 				enum tegra_dsi_format *fmt)
418f7d6889bSThierry Reding {
419f7d6889bSThierry Reding 	switch (format) {
420f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB888:
421f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_24P;
422f7d6889bSThierry Reding 		break;
423f7d6889bSThierry Reding 
424f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB666:
425f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_18NP;
426f7d6889bSThierry Reding 		break;
427f7d6889bSThierry Reding 
428f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB666_PACKED:
429f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_18P;
430f7d6889bSThierry Reding 		break;
431f7d6889bSThierry Reding 
432f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB565:
433f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_16P;
434f7d6889bSThierry Reding 		break;
435f7d6889bSThierry Reding 
436f7d6889bSThierry Reding 	default:
437f7d6889bSThierry Reding 		return -EINVAL;
438f7d6889bSThierry Reding 	}
439f7d6889bSThierry Reding 
440f7d6889bSThierry Reding 	return 0;
441f7d6889bSThierry Reding }
442f7d6889bSThierry Reding 
443e94236cdSThierry Reding static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
444e94236cdSThierry Reding 				    unsigned int size)
445e94236cdSThierry Reding {
446e94236cdSThierry Reding 	u32 value;
447e94236cdSThierry Reding 
448e94236cdSThierry Reding 	tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
449e94236cdSThierry Reding 	tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
450e94236cdSThierry Reding 
451e94236cdSThierry Reding 	value = DSI_GANGED_MODE_CONTROL_ENABLE;
452e94236cdSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
453e94236cdSThierry Reding }
454e94236cdSThierry Reding 
455563eff1fSThierry Reding static void tegra_dsi_enable(struct tegra_dsi *dsi)
456dec72739SThierry Reding {
457563eff1fSThierry Reding 	u32 value;
458dec72739SThierry Reding 
459563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
460563eff1fSThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
461563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
462e94236cdSThierry Reding 
463e94236cdSThierry Reding 	if (dsi->slave)
464e94236cdSThierry Reding 		tegra_dsi_enable(dsi->slave);
465e94236cdSThierry Reding }
466e94236cdSThierry Reding 
467e94236cdSThierry Reding static unsigned int tegra_dsi_get_lanes(struct tegra_dsi *dsi)
468e94236cdSThierry Reding {
469e94236cdSThierry Reding 	if (dsi->master)
470e94236cdSThierry Reding 		return dsi->master->lanes + dsi->lanes;
471e94236cdSThierry Reding 
472e94236cdSThierry Reding 	if (dsi->slave)
473e94236cdSThierry Reding 		return dsi->lanes + dsi->slave->lanes;
474e94236cdSThierry Reding 
475e94236cdSThierry Reding 	return dsi->lanes;
476563eff1fSThierry Reding }
477563eff1fSThierry Reding 
478ebd14afeSThierry Reding static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
479563eff1fSThierry Reding 				const struct drm_display_mode *mode)
480563eff1fSThierry Reding {
481563eff1fSThierry Reding 	unsigned int hact, hsw, hbp, hfp, i, mul, div;
482ebd14afeSThierry Reding 	struct tegra_dsi_state *state;
483563eff1fSThierry Reding 	const u32 *pkt_seq;
484563eff1fSThierry Reding 	u32 value;
485ebd14afeSThierry Reding 
486ebd14afeSThierry Reding 	/* XXX: pass in state into this function? */
487ebd14afeSThierry Reding 	if (dsi->master)
488ebd14afeSThierry Reding 		state = tegra_dsi_get_state(dsi->master);
489ebd14afeSThierry Reding 	else
490ebd14afeSThierry Reding 		state = tegra_dsi_get_state(dsi);
491ebd14afeSThierry Reding 
492ebd14afeSThierry Reding 	mul = state->mul;
493ebd14afeSThierry Reding 	div = state->div;
494334ae6b5SThierry Reding 
49517297a28SThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
49617297a28SThierry Reding 		DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n");
49717297a28SThierry Reding 		pkt_seq = pkt_seq_video_non_burst_sync_pulses;
498337b443dSThierry Reding 	} else if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
49917297a28SThierry Reding 		DRM_DEBUG_KMS("Non-burst video mode with sync events\n");
50017297a28SThierry Reding 		pkt_seq = pkt_seq_video_non_burst_sync_events;
501337b443dSThierry Reding 	} else {
502337b443dSThierry Reding 		DRM_DEBUG_KMS("Command mode\n");
503337b443dSThierry Reding 		pkt_seq = pkt_seq_command_mode;
50417297a28SThierry Reding 	}
50517297a28SThierry Reding 
506ebd14afeSThierry Reding 	value = DSI_CONTROL_CHANNEL(0) |
507ebd14afeSThierry Reding 		DSI_CONTROL_FORMAT(state->format) |
508dec72739SThierry Reding 		DSI_CONTROL_LANES(dsi->lanes - 1) |
509563eff1fSThierry Reding 		DSI_CONTROL_SOURCE(pipe);
510dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
511dec72739SThierry Reding 
512976cebc3SThierry Reding 	tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD);
513dec72739SThierry Reding 
514563eff1fSThierry Reding 	value = DSI_HOST_CONTROL_HS;
515dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
516dec72739SThierry Reding 
517dec72739SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
518563eff1fSThierry Reding 
5190c6b1e4bSAlexandre Courbot 	if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
520dec72739SThierry Reding 		value |= DSI_CONTROL_HS_CLK_CTRL;
521563eff1fSThierry Reding 
522dec72739SThierry Reding 	value &= ~DSI_CONTROL_TX_TRIG(3);
523337b443dSThierry Reding 
524337b443dSThierry Reding 	/* enable DCS commands for command mode */
525337b443dSThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO)
526dec72739SThierry Reding 		value &= ~DSI_CONTROL_DCS_ENABLE;
527337b443dSThierry Reding 	else
528337b443dSThierry Reding 		value |= DSI_CONTROL_DCS_ENABLE;
529337b443dSThierry Reding 
530dec72739SThierry Reding 	value |= DSI_CONTROL_VIDEO_ENABLE;
531dec72739SThierry Reding 	value &= ~DSI_CONTROL_HOST_ENABLE;
532dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
533dec72739SThierry Reding 
534dec72739SThierry Reding 	for (i = 0; i < NUM_PKT_SEQ; i++)
535dec72739SThierry Reding 		tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);
536dec72739SThierry Reding 
537337b443dSThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
538dec72739SThierry Reding 		/* horizontal active pixels */
539dec72739SThierry Reding 		hact = mode->hdisplay * mul / div;
540dec72739SThierry Reding 
541dec72739SThierry Reding 		/* horizontal sync width */
542dec72739SThierry Reding 		hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
543dec72739SThierry Reding 
544dec72739SThierry Reding 		/* horizontal back porch */
545dec72739SThierry Reding 		hbp = (mode->htotal - mode->hsync_end) * mul / div;
546b8be0bdbSThierry Reding 
547b8be0bdbSThierry Reding 		if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0)
548b8be0bdbSThierry Reding 			hbp += hsw;
549dec72739SThierry Reding 
550dec72739SThierry Reding 		/* horizontal front porch */
551dec72739SThierry Reding 		hfp = (mode->hsync_start - mode->hdisplay) * mul / div;
552b8be0bdbSThierry Reding 
553b8be0bdbSThierry Reding 		/* subtract packet overhead */
554b8be0bdbSThierry Reding 		hsw -= 10;
555b8be0bdbSThierry Reding 		hbp -= 14;
556dec72739SThierry Reding 		hfp -= 8;
557dec72739SThierry Reding 
558dec72739SThierry Reding 		tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
559dec72739SThierry Reding 		tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3);
560dec72739SThierry Reding 		tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
561dec72739SThierry Reding 		tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
562dec72739SThierry Reding 
563563eff1fSThierry Reding 		/* set SOL delay (for non-burst mode only) */
564dec72739SThierry Reding 		tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
565e94236cdSThierry Reding 
566e94236cdSThierry Reding 		/* TODO: implement ganged mode */
567337b443dSThierry Reding 	} else {
568337b443dSThierry Reding 		u16 bytes;
569337b443dSThierry Reding 
570e94236cdSThierry Reding 		if (dsi->master || dsi->slave) {
571e94236cdSThierry Reding 			/*
572e94236cdSThierry Reding 			 * For ganged mode, assume symmetric left-right mode.
573e94236cdSThierry Reding 			 */
574e94236cdSThierry Reding 			bytes = 1 + (mode->hdisplay / 2) * mul / div;
575e94236cdSThierry Reding 		} else {
576337b443dSThierry Reding 			/* 1 byte (DCS command) + pixel data */
577337b443dSThierry Reding 			bytes = 1 + mode->hdisplay * mul / div;
578e94236cdSThierry Reding 		}
579337b443dSThierry Reding 
580337b443dSThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1);
581337b443dSThierry Reding 		tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_2_3);
582337b443dSThierry Reding 		tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_4_5);
583337b443dSThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_6_7);
584337b443dSThierry Reding 
585337b443dSThierry Reding 		value = MIPI_DCS_WRITE_MEMORY_START << 8 |
586337b443dSThierry Reding 			MIPI_DCS_WRITE_MEMORY_CONTINUE;
587337b443dSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_DCS_CMDS);
588337b443dSThierry Reding 
589e94236cdSThierry Reding 		/* set SOL delay */
590e94236cdSThierry Reding 		if (dsi->master || dsi->slave) {
591e94236cdSThierry Reding 			unsigned long delay, bclk, bclk_ganged;
592ebd14afeSThierry Reding 			unsigned int lanes = state->lanes;
593e94236cdSThierry Reding 
594e94236cdSThierry Reding 			/* SOL to valid, valid to FIFO and FIFO write delay */
595e94236cdSThierry Reding 			delay = 4 + 4 + 2;
596e94236cdSThierry Reding 			delay = DIV_ROUND_UP(delay * mul, div * lanes);
597e94236cdSThierry Reding 			/* FIFO read delay */
598e94236cdSThierry Reding 			delay = delay + 6;
599e94236cdSThierry Reding 
600e94236cdSThierry Reding 			bclk = DIV_ROUND_UP(mode->htotal * mul, div * lanes);
601e94236cdSThierry Reding 			bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes);
602e94236cdSThierry Reding 			value = bclk - bclk_ganged + delay + 20;
603e94236cdSThierry Reding 		} else {
604e94236cdSThierry Reding 			/* TODO: revisit for non-ganged mode */
605337b443dSThierry Reding 			value = 8 * mul / div;
606e94236cdSThierry Reding 		}
607337b443dSThierry Reding 
608337b443dSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_SOL_DELAY);
609337b443dSThierry Reding 	}
610dec72739SThierry Reding 
611e94236cdSThierry Reding 	if (dsi->slave) {
612ebd14afeSThierry Reding 		tegra_dsi_configure(dsi->slave, pipe, mode);
613e94236cdSThierry Reding 
614e94236cdSThierry Reding 		/*
615e94236cdSThierry Reding 		 * TODO: Support modes other than symmetrical left-right
616e94236cdSThierry Reding 		 * split.
617e94236cdSThierry Reding 		 */
618e94236cdSThierry Reding 		tegra_dsi_ganged_enable(dsi, 0, mode->hdisplay / 2);
619e94236cdSThierry Reding 		tegra_dsi_ganged_enable(dsi->slave, mode->hdisplay / 2,
620e94236cdSThierry Reding 					mode->hdisplay / 2);
621e94236cdSThierry Reding 	}
622563eff1fSThierry Reding }
623563eff1fSThierry Reding 
624563eff1fSThierry Reding static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout)
625563eff1fSThierry Reding {
626563eff1fSThierry Reding 	u32 value;
627563eff1fSThierry Reding 
628563eff1fSThierry Reding 	timeout = jiffies + msecs_to_jiffies(timeout);
629563eff1fSThierry Reding 
630563eff1fSThierry Reding 	while (time_before(jiffies, timeout)) {
631563eff1fSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_STATUS);
632563eff1fSThierry Reding 		if (value & DSI_STATUS_IDLE)
633563eff1fSThierry Reding 			return 0;
634563eff1fSThierry Reding 
635563eff1fSThierry Reding 		usleep_range(1000, 2000);
636563eff1fSThierry Reding 	}
637563eff1fSThierry Reding 
638563eff1fSThierry Reding 	return -ETIMEDOUT;
639563eff1fSThierry Reding }
640563eff1fSThierry Reding 
641563eff1fSThierry Reding static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
642563eff1fSThierry Reding {
643563eff1fSThierry Reding 	u32 value;
644563eff1fSThierry Reding 
645563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
646563eff1fSThierry Reding 	value &= ~DSI_CONTROL_VIDEO_ENABLE;
647563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
648e94236cdSThierry Reding 
649e94236cdSThierry Reding 	if (dsi->slave)
650e94236cdSThierry Reding 		tegra_dsi_video_disable(dsi->slave);
651e94236cdSThierry Reding }
652e94236cdSThierry Reding 
653e94236cdSThierry Reding static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
654e94236cdSThierry Reding {
655e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
656e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
657e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
658563eff1fSThierry Reding }
659563eff1fSThierry Reding 
660ef8187d7SThierry Reding static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
661ef8187d7SThierry Reding {
662ef8187d7SThierry Reding 	u32 value;
663ef8187d7SThierry Reding 
664ef8187d7SThierry Reding 	value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
665ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
666ef8187d7SThierry Reding 
667ef8187d7SThierry Reding 	return 0;
668ef8187d7SThierry Reding }
669ef8187d7SThierry Reding 
670ef8187d7SThierry Reding static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
671ef8187d7SThierry Reding {
672ef8187d7SThierry Reding 	u32 value;
673ef8187d7SThierry Reding 
674ef8187d7SThierry Reding 	/*
675ef8187d7SThierry Reding 	 * XXX Is this still needed? The module reset is deasserted right
676ef8187d7SThierry Reding 	 * before this function is called.
677ef8187d7SThierry Reding 	 */
678ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
679ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
680ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
681ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
682ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
683ef8187d7SThierry Reding 
684ef8187d7SThierry Reding 	/* start calibration */
685ef8187d7SThierry Reding 	tegra_dsi_pad_enable(dsi);
686ef8187d7SThierry Reding 
687ef8187d7SThierry Reding 	value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
688ef8187d7SThierry Reding 		DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
689ef8187d7SThierry Reding 		DSI_PAD_OUT_CLK(0x0);
690ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
691ef8187d7SThierry Reding 
692ef8187d7SThierry Reding 	value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
693ef8187d7SThierry Reding 		DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
694ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
695ef8187d7SThierry Reding 
696ef8187d7SThierry Reding 	return tegra_mipi_calibrate(dsi->mipi);
697ef8187d7SThierry Reding }
698ef8187d7SThierry Reding 
6995b901e78SThierry Reding static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk,
7005b901e78SThierry Reding 				  unsigned int vrefresh)
7015b901e78SThierry Reding {
7025b901e78SThierry Reding 	unsigned int timeout;
7035b901e78SThierry Reding 	u32 value;
7045b901e78SThierry Reding 
7055b901e78SThierry Reding 	/* one frame high-speed transmission timeout */
7065b901e78SThierry Reding 	timeout = (bclk / vrefresh) / 512;
7075b901e78SThierry Reding 	value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
7085b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
7095b901e78SThierry Reding 
7105b901e78SThierry Reding 	/* 2 ms peripheral timeout for panel */
7115b901e78SThierry Reding 	timeout = 2 * bclk / 512 * 1000;
7125b901e78SThierry Reding 	value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
7135b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
7145b901e78SThierry Reding 
7155b901e78SThierry Reding 	value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
7165b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
7175b901e78SThierry Reding 
7185b901e78SThierry Reding 	if (dsi->slave)
7195b901e78SThierry Reding 		tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh);
7205b901e78SThierry Reding }
7215b901e78SThierry Reding 
722563eff1fSThierry Reding static void tegra_dsi_disable(struct tegra_dsi *dsi)
723563eff1fSThierry Reding {
724563eff1fSThierry Reding 	u32 value;
725563eff1fSThierry Reding 
726e94236cdSThierry Reding 	if (dsi->slave) {
727e94236cdSThierry Reding 		tegra_dsi_ganged_disable(dsi->slave);
728e94236cdSThierry Reding 		tegra_dsi_ganged_disable(dsi);
729e94236cdSThierry Reding 	}
730e94236cdSThierry Reding 
731563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
732563eff1fSThierry Reding 	value &= ~DSI_POWER_CONTROL_ENABLE;
733563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
734563eff1fSThierry Reding 
735e94236cdSThierry Reding 	if (dsi->slave)
736e94236cdSThierry Reding 		tegra_dsi_disable(dsi->slave);
737e94236cdSThierry Reding 
738563eff1fSThierry Reding 	usleep_range(5000, 10000);
739563eff1fSThierry Reding }
740563eff1fSThierry Reding 
74192f0e073SThierry Reding static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
74292f0e073SThierry Reding {
74392f0e073SThierry Reding 	u32 value;
74492f0e073SThierry Reding 
74592f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
74692f0e073SThierry Reding 	value &= ~DSI_POWER_CONTROL_ENABLE;
74792f0e073SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
74892f0e073SThierry Reding 
74992f0e073SThierry Reding 	usleep_range(300, 1000);
75092f0e073SThierry Reding 
75192f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
75292f0e073SThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
75392f0e073SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
75492f0e073SThierry Reding 
75592f0e073SThierry Reding 	usleep_range(300, 1000);
75692f0e073SThierry Reding 
75792f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_TRIGGER);
75892f0e073SThierry Reding 	if (value)
75992f0e073SThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_TRIGGER);
76092f0e073SThierry Reding 
76192f0e073SThierry Reding 	if (dsi->slave)
76292f0e073SThierry Reding 		tegra_dsi_soft_reset(dsi->slave);
76392f0e073SThierry Reding }
76492f0e073SThierry Reding 
765ebd14afeSThierry Reding static void tegra_dsi_connector_reset(struct drm_connector *connector)
766ebd14afeSThierry Reding {
767280dc0e1SJon Hunter 	struct tegra_dsi_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
768ebd14afeSThierry Reding 
769280dc0e1SJon Hunter 	if (!state)
770280dc0e1SJon Hunter 		return;
771280dc0e1SJon Hunter 
772280dc0e1SJon Hunter 	if (connector->state) {
773280dc0e1SJon Hunter 		__drm_atomic_helper_connector_destroy_state(connector->state);
774ebd14afeSThierry Reding 		kfree(connector->state);
7755459a2adSMaarten Lankhorst 	}
776280dc0e1SJon Hunter 
777280dc0e1SJon Hunter 	__drm_atomic_helper_connector_reset(connector, &state->base);
778ebd14afeSThierry Reding }
779ebd14afeSThierry Reding 
780ebd14afeSThierry Reding static struct drm_connector_state *
781ebd14afeSThierry Reding tegra_dsi_connector_duplicate_state(struct drm_connector *connector)
782ebd14afeSThierry Reding {
783ebd14afeSThierry Reding 	struct tegra_dsi_state *state = to_dsi_state(connector->state);
784ebd14afeSThierry Reding 	struct tegra_dsi_state *copy;
785ebd14afeSThierry Reding 
786ebd14afeSThierry Reding 	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
787ebd14afeSThierry Reding 	if (!copy)
788ebd14afeSThierry Reding 		return NULL;
789ebd14afeSThierry Reding 
790280dc0e1SJon Hunter 	__drm_atomic_helper_connector_duplicate_state(connector,
791280dc0e1SJon Hunter 						      &copy->base);
792280dc0e1SJon Hunter 
793ebd14afeSThierry Reding 	return &copy->base;
794ebd14afeSThierry Reding }
795ebd14afeSThierry Reding 
7965b901e78SThierry Reding static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
797ebd14afeSThierry Reding 	.reset = tegra_dsi_connector_reset,
7985b901e78SThierry Reding 	.detect = tegra_output_connector_detect,
7995b901e78SThierry Reding 	.fill_modes = drm_helper_probe_single_connector_modes,
8005b901e78SThierry Reding 	.destroy = tegra_output_connector_destroy,
801ebd14afeSThierry Reding 	.atomic_duplicate_state = tegra_dsi_connector_duplicate_state,
8024aa3df71SThierry Reding 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
803a813d704SThierry Reding 	.late_register = tegra_dsi_late_register,
804a813d704SThierry Reding 	.early_unregister = tegra_dsi_early_unregister,
8055b901e78SThierry Reding };
8065b901e78SThierry Reding 
8075b901e78SThierry Reding static enum drm_mode_status
8085b901e78SThierry Reding tegra_dsi_connector_mode_valid(struct drm_connector *connector,
8095b901e78SThierry Reding 			       struct drm_display_mode *mode)
8105b901e78SThierry Reding {
8115b901e78SThierry Reding 	return MODE_OK;
8125b901e78SThierry Reding }
8135b901e78SThierry Reding 
8145b901e78SThierry Reding static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = {
8155b901e78SThierry Reding 	.get_modes = tegra_output_connector_get_modes,
8165b901e78SThierry Reding 	.mode_valid = tegra_dsi_connector_mode_valid,
8175b901e78SThierry Reding };
8185b901e78SThierry Reding 
81987904c3eSThierry Reding static void tegra_dsi_unprepare(struct tegra_dsi *dsi)
82087904c3eSThierry Reding {
82187904c3eSThierry Reding 	int err;
82287904c3eSThierry Reding 
82387904c3eSThierry Reding 	if (dsi->slave)
82487904c3eSThierry Reding 		tegra_dsi_unprepare(dsi->slave);
82587904c3eSThierry Reding 
82687904c3eSThierry Reding 	err = tegra_mipi_disable(dsi->mipi);
82787904c3eSThierry Reding 	if (err < 0)
82887904c3eSThierry Reding 		dev_err(dsi->dev, "failed to disable MIPI calibration: %d\n",
82987904c3eSThierry Reding 			err);
83087904c3eSThierry Reding 
831fd67e9c6SThierry Reding 	err = host1x_client_suspend(&dsi->client);
832fd67e9c6SThierry Reding 	if (err < 0)
833fd67e9c6SThierry Reding 		dev_err(dsi->dev, "failed to suspend: %d\n", err);
83487904c3eSThierry Reding }
83587904c3eSThierry Reding 
8365b901e78SThierry Reding static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
8375b901e78SThierry Reding {
8385b901e78SThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
8395b901e78SThierry Reding 	struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
8405b901e78SThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
8415b901e78SThierry Reding 	u32 value;
8425b901e78SThierry Reding 	int err;
8435b901e78SThierry Reding 
8445b901e78SThierry Reding 	if (output->panel)
8455b901e78SThierry Reding 		drm_panel_disable(output->panel);
8465b901e78SThierry Reding 
8475b901e78SThierry Reding 	tegra_dsi_video_disable(dsi);
8485b901e78SThierry Reding 
8495b901e78SThierry Reding 	/*
8505b901e78SThierry Reding 	 * The following accesses registers of the display controller, so make
8515b901e78SThierry Reding 	 * sure it's only executed when the output is attached to one.
8525b901e78SThierry Reding 	 */
8535b901e78SThierry Reding 	if (dc) {
8545b901e78SThierry Reding 		value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
8555b901e78SThierry Reding 		value &= ~DSI_ENABLE;
8565b901e78SThierry Reding 		tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
8575b901e78SThierry Reding 
8585b901e78SThierry Reding 		tegra_dc_commit(dc);
8595b901e78SThierry Reding 	}
8605b901e78SThierry Reding 
8615b901e78SThierry Reding 	err = tegra_dsi_wait_idle(dsi, 100);
8625b901e78SThierry Reding 	if (err < 0)
8635b901e78SThierry Reding 		dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
8645b901e78SThierry Reding 
8655b901e78SThierry Reding 	tegra_dsi_soft_reset(dsi);
8665b901e78SThierry Reding 
8675b901e78SThierry Reding 	if (output->panel)
8685b901e78SThierry Reding 		drm_panel_unprepare(output->panel);
8695b901e78SThierry Reding 
8705b901e78SThierry Reding 	tegra_dsi_disable(dsi);
8715b901e78SThierry Reding 
87287904c3eSThierry Reding 	tegra_dsi_unprepare(dsi);
87387904c3eSThierry Reding }
87487904c3eSThierry Reding 
875fd67e9c6SThierry Reding static int tegra_dsi_prepare(struct tegra_dsi *dsi)
87687904c3eSThierry Reding {
87787904c3eSThierry Reding 	int err;
87887904c3eSThierry Reding 
879fd67e9c6SThierry Reding 	err = host1x_client_resume(&dsi->client);
880fd67e9c6SThierry Reding 	if (err < 0) {
881fd67e9c6SThierry Reding 		dev_err(dsi->dev, "failed to resume: %d\n", err);
882fd67e9c6SThierry Reding 		return err;
883fd67e9c6SThierry Reding 	}
88487904c3eSThierry Reding 
88587904c3eSThierry Reding 	err = tegra_mipi_enable(dsi->mipi);
88687904c3eSThierry Reding 	if (err < 0)
88787904c3eSThierry Reding 		dev_err(dsi->dev, "failed to enable MIPI calibration: %d\n",
88887904c3eSThierry Reding 			err);
88987904c3eSThierry Reding 
89087904c3eSThierry Reding 	err = tegra_dsi_pad_calibrate(dsi);
89187904c3eSThierry Reding 	if (err < 0)
89287904c3eSThierry Reding 		dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
89387904c3eSThierry Reding 
89487904c3eSThierry Reding 	if (dsi->slave)
89587904c3eSThierry Reding 		tegra_dsi_prepare(dsi->slave);
896fd67e9c6SThierry Reding 
897fd67e9c6SThierry Reding 	return 0;
8985b901e78SThierry Reding }
8995b901e78SThierry Reding 
900171e2e6dSThierry Reding static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
901171e2e6dSThierry Reding {
902171e2e6dSThierry Reding 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
903171e2e6dSThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
904171e2e6dSThierry Reding 	struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
905171e2e6dSThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
906171e2e6dSThierry Reding 	struct tegra_dsi_state *state;
907171e2e6dSThierry Reding 	u32 value;
908fd67e9c6SThierry Reding 	int err;
909ef8187d7SThierry Reding 
910fd67e9c6SThierry Reding 	err = tegra_dsi_prepare(dsi);
911fd67e9c6SThierry Reding 	if (err < 0) {
912fd67e9c6SThierry Reding 		dev_err(dsi->dev, "failed to prepare: %d\n", err);
913fd67e9c6SThierry Reding 		return;
914fd67e9c6SThierry Reding 	}
915171e2e6dSThierry Reding 
916171e2e6dSThierry Reding 	state = tegra_dsi_get_state(dsi);
917171e2e6dSThierry Reding 
918171e2e6dSThierry Reding 	tegra_dsi_set_timeout(dsi, state->bclk, state->vrefresh);
919171e2e6dSThierry Reding 
920171e2e6dSThierry Reding 	/*
921171e2e6dSThierry Reding 	 * The D-PHY timing fields are expressed in byte-clock cycles, so
922171e2e6dSThierry Reding 	 * multiply the period by 8.
923171e2e6dSThierry Reding 	 */
924171e2e6dSThierry Reding 	tegra_dsi_set_phy_timing(dsi, state->period * 8, &state->timing);
925171e2e6dSThierry Reding 
926171e2e6dSThierry Reding 	if (output->panel)
927171e2e6dSThierry Reding 		drm_panel_prepare(output->panel);
928171e2e6dSThierry Reding 
929171e2e6dSThierry Reding 	tegra_dsi_configure(dsi, dc->pipe, mode);
930171e2e6dSThierry Reding 
931171e2e6dSThierry Reding 	/* enable display controller */
932171e2e6dSThierry Reding 	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
933171e2e6dSThierry Reding 	value |= DSI_ENABLE;
934171e2e6dSThierry Reding 	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
935171e2e6dSThierry Reding 
936171e2e6dSThierry Reding 	tegra_dc_commit(dc);
937171e2e6dSThierry Reding 
938171e2e6dSThierry Reding 	/* enable DSI controller */
939171e2e6dSThierry Reding 	tegra_dsi_enable(dsi);
940171e2e6dSThierry Reding 
941171e2e6dSThierry Reding 	if (output->panel)
942171e2e6dSThierry Reding 		drm_panel_enable(output->panel);
943171e2e6dSThierry Reding }
944171e2e6dSThierry Reding 
945ebd14afeSThierry Reding static int
946ebd14afeSThierry Reding tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
947ebd14afeSThierry Reding 			       struct drm_crtc_state *crtc_state,
948ebd14afeSThierry Reding 			       struct drm_connector_state *conn_state)
949ebd14afeSThierry Reding {
950ebd14afeSThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
951ebd14afeSThierry Reding 	struct tegra_dsi_state *state = to_dsi_state(conn_state);
952ebd14afeSThierry Reding 	struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
953ebd14afeSThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
954ebd14afeSThierry Reding 	unsigned int scdiv;
955ebd14afeSThierry Reding 	unsigned long plld;
956ebd14afeSThierry Reding 	int err;
957ebd14afeSThierry Reding 
958ebd14afeSThierry Reding 	state->pclk = crtc_state->mode.clock * 1000;
959ebd14afeSThierry Reding 
960ebd14afeSThierry Reding 	err = tegra_dsi_get_muldiv(dsi->format, &state->mul, &state->div);
961ebd14afeSThierry Reding 	if (err < 0)
962ebd14afeSThierry Reding 		return err;
963ebd14afeSThierry Reding 
964ebd14afeSThierry Reding 	state->lanes = tegra_dsi_get_lanes(dsi);
965ebd14afeSThierry Reding 
966ebd14afeSThierry Reding 	err = tegra_dsi_get_format(dsi->format, &state->format);
967ebd14afeSThierry Reding 	if (err < 0)
968ebd14afeSThierry Reding 		return err;
969ebd14afeSThierry Reding 
970ebd14afeSThierry Reding 	state->vrefresh = drm_mode_vrefresh(&crtc_state->mode);
971ebd14afeSThierry Reding 
972ebd14afeSThierry Reding 	/* compute byte clock */
973ebd14afeSThierry Reding 	state->bclk = (state->pclk * state->mul) / (state->div * state->lanes);
974ebd14afeSThierry Reding 
975ebd14afeSThierry Reding 	DRM_DEBUG_KMS("mul: %u, div: %u, lanes: %u\n", state->mul, state->div,
976ebd14afeSThierry Reding 		      state->lanes);
977ebd14afeSThierry Reding 	DRM_DEBUG_KMS("format: %u, vrefresh: %u\n", state->format,
978ebd14afeSThierry Reding 		      state->vrefresh);
979ebd14afeSThierry Reding 	DRM_DEBUG_KMS("bclk: %lu\n", state->bclk);
980ebd14afeSThierry Reding 
981ebd14afeSThierry Reding 	/*
982ebd14afeSThierry Reding 	 * Compute bit clock and round up to the next MHz.
983ebd14afeSThierry Reding 	 */
984ebd14afeSThierry Reding 	plld = DIV_ROUND_UP(state->bclk * 8, USEC_PER_SEC) * USEC_PER_SEC;
985ebd14afeSThierry Reding 	state->period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, plld);
986ebd14afeSThierry Reding 
987ebd14afeSThierry Reding 	err = mipi_dphy_timing_get_default(&state->timing, state->period);
988ebd14afeSThierry Reding 	if (err < 0)
989ebd14afeSThierry Reding 		return err;
990ebd14afeSThierry Reding 
991ebd14afeSThierry Reding 	err = mipi_dphy_timing_validate(&state->timing, state->period);
992ebd14afeSThierry Reding 	if (err < 0) {
993ebd14afeSThierry Reding 		dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err);
994ebd14afeSThierry Reding 		return err;
995ebd14afeSThierry Reding 	}
996ebd14afeSThierry Reding 
997ebd14afeSThierry Reding 	/*
998ebd14afeSThierry Reding 	 * We divide the frequency by two here, but we make up for that by
999ebd14afeSThierry Reding 	 * setting the shift clock divider (further below) to half of the
1000ebd14afeSThierry Reding 	 * correct value.
1001ebd14afeSThierry Reding 	 */
1002ebd14afeSThierry Reding 	plld /= 2;
1003ebd14afeSThierry Reding 
1004ebd14afeSThierry Reding 	/*
1005ebd14afeSThierry Reding 	 * Derive pixel clock from bit clock using the shift clock divider.
1006ebd14afeSThierry Reding 	 * Note that this is only half of what we would expect, but we need
1007ebd14afeSThierry Reding 	 * that to make up for the fact that we divided the bit clock by a
1008ebd14afeSThierry Reding 	 * factor of two above.
1009ebd14afeSThierry Reding 	 *
1010ebd14afeSThierry Reding 	 * It's not clear exactly why this is necessary, but the display is
1011ebd14afeSThierry Reding 	 * not working properly otherwise. Perhaps the PLLs cannot generate
1012ebd14afeSThierry Reding 	 * frequencies sufficiently high.
1013ebd14afeSThierry Reding 	 */
1014ebd14afeSThierry Reding 	scdiv = ((8 * state->mul) / (state->div * state->lanes)) - 2;
1015ebd14afeSThierry Reding 
1016ebd14afeSThierry Reding 	err = tegra_dc_state_setup_clock(dc, crtc_state, dsi->clk_parent,
1017ebd14afeSThierry Reding 					 plld, scdiv);
1018ebd14afeSThierry Reding 	if (err < 0) {
1019ebd14afeSThierry Reding 		dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
1020ebd14afeSThierry Reding 		return err;
1021ebd14afeSThierry Reding 	}
1022ebd14afeSThierry Reding 
1023ebd14afeSThierry Reding 	return err;
1024ebd14afeSThierry Reding }
1025ebd14afeSThierry Reding 
10265b901e78SThierry Reding static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
10275b901e78SThierry Reding 	.disable = tegra_dsi_encoder_disable,
1028171e2e6dSThierry Reding 	.enable = tegra_dsi_encoder_enable,
1029ebd14afeSThierry Reding 	.atomic_check = tegra_dsi_encoder_atomic_check,
1030dec72739SThierry Reding };
1031dec72739SThierry Reding 
1032dec72739SThierry Reding static int tegra_dsi_init(struct host1x_client *client)
1033dec72739SThierry Reding {
1034608f43adSThierry Reding 	struct drm_device *drm = dev_get_drvdata(client->host);
1035dec72739SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1036dec72739SThierry Reding 	int err;
1037dec72739SThierry Reding 
1038e94236cdSThierry Reding 	/* Gangsters must not register their own outputs. */
1039e94236cdSThierry Reding 	if (!dsi->master) {
1040dec72739SThierry Reding 		dsi->output.dev = client->dev;
1041dec72739SThierry Reding 
10425b901e78SThierry Reding 		drm_connector_init(drm, &dsi->output.connector,
10435b901e78SThierry Reding 				   &tegra_dsi_connector_funcs,
10445b901e78SThierry Reding 				   DRM_MODE_CONNECTOR_DSI);
10455b901e78SThierry Reding 		drm_connector_helper_add(&dsi->output.connector,
10465b901e78SThierry Reding 					 &tegra_dsi_connector_helper_funcs);
10475b901e78SThierry Reding 		dsi->output.connector.dpms = DRM_MODE_DPMS_OFF;
10485b901e78SThierry Reding 
10494d0e95e0SThomas Zimmermann 		drm_simple_encoder_init(drm, &dsi->output.encoder,
10504d0e95e0SThomas Zimmermann 					DRM_MODE_ENCODER_DSI);
10515b901e78SThierry Reding 		drm_encoder_helper_add(&dsi->output.encoder,
10525b901e78SThierry Reding 				       &tegra_dsi_encoder_helper_funcs);
10535b901e78SThierry Reding 
1054cde4c44dSDaniel Vetter 		drm_connector_attach_encoder(&dsi->output.connector,
10555b901e78SThierry Reding 						  &dsi->output.encoder);
10565b901e78SThierry Reding 		drm_connector_register(&dsi->output.connector);
10575b901e78SThierry Reding 
1058ea130b24SThierry Reding 		err = tegra_output_init(drm, &dsi->output);
1059ef8187d7SThierry Reding 		if (err < 0)
1060ef8187d7SThierry Reding 			dev_err(dsi->dev, "failed to initialize output: %d\n",
1061ea130b24SThierry Reding 				err);
1062ea130b24SThierry Reding 
10635b901e78SThierry Reding 		dsi->output.encoder.possible_crtcs = 0x3;
1064e94236cdSThierry Reding 	}
1065dec72739SThierry Reding 
1066dec72739SThierry Reding 	return 0;
1067dec72739SThierry Reding }
1068dec72739SThierry Reding 
1069dec72739SThierry Reding static int tegra_dsi_exit(struct host1x_client *client)
1070dec72739SThierry Reding {
1071dec72739SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1072dec72739SThierry Reding 
10735b901e78SThierry Reding 	tegra_output_exit(&dsi->output);
1074201106d8SThierry Reding 
1075dec72739SThierry Reding 	return 0;
1076dec72739SThierry Reding }
1077dec72739SThierry Reding 
1078fd67e9c6SThierry Reding static int tegra_dsi_runtime_suspend(struct host1x_client *client)
1079fd67e9c6SThierry Reding {
1080fd67e9c6SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1081fd67e9c6SThierry Reding 	struct device *dev = client->dev;
1082fd67e9c6SThierry Reding 	int err;
1083fd67e9c6SThierry Reding 
1084fd67e9c6SThierry Reding 	if (dsi->rst) {
1085fd67e9c6SThierry Reding 		err = reset_control_assert(dsi->rst);
1086fd67e9c6SThierry Reding 		if (err < 0) {
1087fd67e9c6SThierry Reding 			dev_err(dev, "failed to assert reset: %d\n", err);
1088fd67e9c6SThierry Reding 			return err;
1089fd67e9c6SThierry Reding 		}
1090fd67e9c6SThierry Reding 	}
1091fd67e9c6SThierry Reding 
1092fd67e9c6SThierry Reding 	usleep_range(1000, 2000);
1093fd67e9c6SThierry Reding 
1094fd67e9c6SThierry Reding 	clk_disable_unprepare(dsi->clk_lp);
1095fd67e9c6SThierry Reding 	clk_disable_unprepare(dsi->clk);
1096fd67e9c6SThierry Reding 
1097fd67e9c6SThierry Reding 	regulator_disable(dsi->vdd);
1098fd67e9c6SThierry Reding 	pm_runtime_put_sync(dev);
1099fd67e9c6SThierry Reding 
1100fd67e9c6SThierry Reding 	return 0;
1101fd67e9c6SThierry Reding }
1102fd67e9c6SThierry Reding 
1103fd67e9c6SThierry Reding static int tegra_dsi_runtime_resume(struct host1x_client *client)
1104fd67e9c6SThierry Reding {
1105fd67e9c6SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1106fd67e9c6SThierry Reding 	struct device *dev = client->dev;
1107fd67e9c6SThierry Reding 	int err;
1108fd67e9c6SThierry Reding 
1109fd67e9c6SThierry Reding 	err = pm_runtime_get_sync(dev);
1110fd67e9c6SThierry Reding 	if (err < 0) {
1111fd67e9c6SThierry Reding 		dev_err(dev, "failed to get runtime PM: %d\n", err);
1112fd67e9c6SThierry Reding 		return err;
1113fd67e9c6SThierry Reding 	}
1114fd67e9c6SThierry Reding 
1115fd67e9c6SThierry Reding 	err = regulator_enable(dsi->vdd);
1116fd67e9c6SThierry Reding 	if (err < 0) {
1117fd67e9c6SThierry Reding 		dev_err(dev, "failed to enable VDD supply: %d\n", err);
1118fd67e9c6SThierry Reding 		goto put_rpm;
1119fd67e9c6SThierry Reding 	}
1120fd67e9c6SThierry Reding 
1121fd67e9c6SThierry Reding 	err = clk_prepare_enable(dsi->clk);
1122fd67e9c6SThierry Reding 	if (err < 0) {
1123fd67e9c6SThierry Reding 		dev_err(dev, "cannot enable DSI clock: %d\n", err);
1124fd67e9c6SThierry Reding 		goto disable_vdd;
1125fd67e9c6SThierry Reding 	}
1126fd67e9c6SThierry Reding 
1127fd67e9c6SThierry Reding 	err = clk_prepare_enable(dsi->clk_lp);
1128fd67e9c6SThierry Reding 	if (err < 0) {
1129fd67e9c6SThierry Reding 		dev_err(dev, "cannot enable low-power clock: %d\n", err);
1130fd67e9c6SThierry Reding 		goto disable_clk;
1131fd67e9c6SThierry Reding 	}
1132fd67e9c6SThierry Reding 
1133fd67e9c6SThierry Reding 	usleep_range(1000, 2000);
1134fd67e9c6SThierry Reding 
1135fd67e9c6SThierry Reding 	if (dsi->rst) {
1136fd67e9c6SThierry Reding 		err = reset_control_deassert(dsi->rst);
1137fd67e9c6SThierry Reding 		if (err < 0) {
1138fd67e9c6SThierry Reding 			dev_err(dev, "cannot assert reset: %d\n", err);
1139fd67e9c6SThierry Reding 			goto disable_clk_lp;
1140fd67e9c6SThierry Reding 		}
1141fd67e9c6SThierry Reding 	}
1142fd67e9c6SThierry Reding 
1143fd67e9c6SThierry Reding 	return 0;
1144fd67e9c6SThierry Reding 
1145fd67e9c6SThierry Reding disable_clk_lp:
1146fd67e9c6SThierry Reding 	clk_disable_unprepare(dsi->clk_lp);
1147fd67e9c6SThierry Reding disable_clk:
1148fd67e9c6SThierry Reding 	clk_disable_unprepare(dsi->clk);
1149fd67e9c6SThierry Reding disable_vdd:
1150fd67e9c6SThierry Reding 	regulator_disable(dsi->vdd);
1151fd67e9c6SThierry Reding put_rpm:
1152fd67e9c6SThierry Reding 	pm_runtime_put_sync(dev);
1153fd67e9c6SThierry Reding 	return err;
1154fd67e9c6SThierry Reding }
1155fd67e9c6SThierry Reding 
1156dec72739SThierry Reding static const struct host1x_client_ops dsi_client_ops = {
1157dec72739SThierry Reding 	.init = tegra_dsi_init,
1158dec72739SThierry Reding 	.exit = tegra_dsi_exit,
1159fd67e9c6SThierry Reding 	.suspend = tegra_dsi_runtime_suspend,
1160fd67e9c6SThierry Reding 	.resume = tegra_dsi_runtime_resume,
1161dec72739SThierry Reding };
1162dec72739SThierry Reding 
1163dec72739SThierry Reding static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
1164dec72739SThierry Reding {
1165dec72739SThierry Reding 	struct clk *parent;
1166dec72739SThierry Reding 	int err;
1167dec72739SThierry Reding 
1168dec72739SThierry Reding 	parent = clk_get_parent(dsi->clk);
1169dec72739SThierry Reding 	if (!parent)
1170dec72739SThierry Reding 		return -EINVAL;
1171dec72739SThierry Reding 
1172dec72739SThierry Reding 	err = clk_set_parent(parent, dsi->clk_parent);
1173dec72739SThierry Reding 	if (err < 0)
1174dec72739SThierry Reding 		return err;
1175dec72739SThierry Reding 
1176dec72739SThierry Reding 	return 0;
1177dec72739SThierry Reding }
1178dec72739SThierry Reding 
11790fffdf6cSThierry Reding static const char * const error_report[16] = {
11800fffdf6cSThierry Reding 	"SoT Error",
11810fffdf6cSThierry Reding 	"SoT Sync Error",
11820fffdf6cSThierry Reding 	"EoT Sync Error",
11830fffdf6cSThierry Reding 	"Escape Mode Entry Command Error",
11840fffdf6cSThierry Reding 	"Low-Power Transmit Sync Error",
11850fffdf6cSThierry Reding 	"Peripheral Timeout Error",
11860fffdf6cSThierry Reding 	"False Control Error",
11870fffdf6cSThierry Reding 	"Contention Detected",
11880fffdf6cSThierry Reding 	"ECC Error, single-bit",
11890fffdf6cSThierry Reding 	"ECC Error, multi-bit",
11900fffdf6cSThierry Reding 	"Checksum Error",
11910fffdf6cSThierry Reding 	"DSI Data Type Not Recognized",
11920fffdf6cSThierry Reding 	"DSI VC ID Invalid",
11930fffdf6cSThierry Reding 	"Invalid Transmission Length",
11940fffdf6cSThierry Reding 	"Reserved",
11950fffdf6cSThierry Reding 	"DSI Protocol Violation",
11960fffdf6cSThierry Reding };
11970fffdf6cSThierry Reding 
11980fffdf6cSThierry Reding static ssize_t tegra_dsi_read_response(struct tegra_dsi *dsi,
11990fffdf6cSThierry Reding 				       const struct mipi_dsi_msg *msg,
12000fffdf6cSThierry Reding 				       size_t count)
12010fffdf6cSThierry Reding {
12020fffdf6cSThierry Reding 	u8 *rx = msg->rx_buf;
12030fffdf6cSThierry Reding 	unsigned int i, j, k;
12040fffdf6cSThierry Reding 	size_t size = 0;
12050fffdf6cSThierry Reding 	u16 errors;
12060fffdf6cSThierry Reding 	u32 value;
12070fffdf6cSThierry Reding 
12080fffdf6cSThierry Reding 	/* read and parse packet header */
12090fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_RD_DATA);
12100fffdf6cSThierry Reding 
12110fffdf6cSThierry Reding 	switch (value & 0x3f) {
12120fffdf6cSThierry Reding 	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
12130fffdf6cSThierry Reding 		errors = (value >> 8) & 0xffff;
12140fffdf6cSThierry Reding 		dev_dbg(dsi->dev, "Acknowledge and error report: %04x\n",
12150fffdf6cSThierry Reding 			errors);
12160fffdf6cSThierry Reding 		for (i = 0; i < ARRAY_SIZE(error_report); i++)
12170fffdf6cSThierry Reding 			if (errors & BIT(i))
12180fffdf6cSThierry Reding 				dev_dbg(dsi->dev, "  %2u: %s\n", i,
12190fffdf6cSThierry Reding 					error_report[i]);
12200fffdf6cSThierry Reding 		break;
12210fffdf6cSThierry Reding 
12220fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
12230fffdf6cSThierry Reding 		rx[0] = (value >> 8) & 0xff;
12240fffdf6cSThierry Reding 		size = 1;
12250fffdf6cSThierry Reding 		break;
12260fffdf6cSThierry Reding 
12270fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
12280fffdf6cSThierry Reding 		rx[0] = (value >>  8) & 0xff;
12290fffdf6cSThierry Reding 		rx[1] = (value >> 16) & 0xff;
12300fffdf6cSThierry Reding 		size = 2;
12310fffdf6cSThierry Reding 		break;
12320fffdf6cSThierry Reding 
12330fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
12340fffdf6cSThierry Reding 		size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
12350fffdf6cSThierry Reding 		break;
12360fffdf6cSThierry Reding 
12370fffdf6cSThierry Reding 	case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
12380fffdf6cSThierry Reding 		size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
12390fffdf6cSThierry Reding 		break;
12400fffdf6cSThierry Reding 
12410fffdf6cSThierry Reding 	default:
12420fffdf6cSThierry Reding 		dev_err(dsi->dev, "unhandled response type: %02x\n",
12430fffdf6cSThierry Reding 			value & 0x3f);
12440fffdf6cSThierry Reding 		return -EPROTO;
12450fffdf6cSThierry Reding 	}
12460fffdf6cSThierry Reding 
12470fffdf6cSThierry Reding 	size = min(size, msg->rx_len);
12480fffdf6cSThierry Reding 
12490fffdf6cSThierry Reding 	if (msg->rx_buf && size > 0) {
12500fffdf6cSThierry Reding 		for (i = 0, j = 0; i < count - 1; i++, j += 4) {
12510fffdf6cSThierry Reding 			u8 *rx = msg->rx_buf + j;
12520fffdf6cSThierry Reding 
12530fffdf6cSThierry Reding 			value = tegra_dsi_readl(dsi, DSI_RD_DATA);
12540fffdf6cSThierry Reding 
12550fffdf6cSThierry Reding 			for (k = 0; k < 4 && (j + k) < msg->rx_len; k++)
12560fffdf6cSThierry Reding 				rx[j + k] = (value >> (k << 3)) & 0xff;
12570fffdf6cSThierry Reding 		}
12580fffdf6cSThierry Reding 	}
12590fffdf6cSThierry Reding 
12600fffdf6cSThierry Reding 	return size;
12610fffdf6cSThierry Reding }
12620fffdf6cSThierry Reding 
12630fffdf6cSThierry Reding static int tegra_dsi_transmit(struct tegra_dsi *dsi, unsigned long timeout)
12640fffdf6cSThierry Reding {
12650fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, DSI_TRIGGER_HOST, DSI_TRIGGER);
12660fffdf6cSThierry Reding 
12670fffdf6cSThierry Reding 	timeout = jiffies + msecs_to_jiffies(timeout);
12680fffdf6cSThierry Reding 
12690fffdf6cSThierry Reding 	while (time_before(jiffies, timeout)) {
12700fffdf6cSThierry Reding 		u32 value = tegra_dsi_readl(dsi, DSI_TRIGGER);
12710fffdf6cSThierry Reding 		if ((value & DSI_TRIGGER_HOST) == 0)
12720fffdf6cSThierry Reding 			return 0;
12730fffdf6cSThierry Reding 
12740fffdf6cSThierry Reding 		usleep_range(1000, 2000);
12750fffdf6cSThierry Reding 	}
12760fffdf6cSThierry Reding 
12770fffdf6cSThierry Reding 	DRM_DEBUG_KMS("timeout waiting for transmission to complete\n");
12780fffdf6cSThierry Reding 	return -ETIMEDOUT;
12790fffdf6cSThierry Reding }
12800fffdf6cSThierry Reding 
12810fffdf6cSThierry Reding static int tegra_dsi_wait_for_response(struct tegra_dsi *dsi,
12820fffdf6cSThierry Reding 				       unsigned long timeout)
12830fffdf6cSThierry Reding {
12840fffdf6cSThierry Reding 	timeout = jiffies + msecs_to_jiffies(250);
12850fffdf6cSThierry Reding 
12860fffdf6cSThierry Reding 	while (time_before(jiffies, timeout)) {
12870fffdf6cSThierry Reding 		u32 value = tegra_dsi_readl(dsi, DSI_STATUS);
12880fffdf6cSThierry Reding 		u8 count = value & 0x1f;
12890fffdf6cSThierry Reding 
12900fffdf6cSThierry Reding 		if (count > 0)
12910fffdf6cSThierry Reding 			return count;
12920fffdf6cSThierry Reding 
12930fffdf6cSThierry Reding 		usleep_range(1000, 2000);
12940fffdf6cSThierry Reding 	}
12950fffdf6cSThierry Reding 
12960fffdf6cSThierry Reding 	DRM_DEBUG_KMS("peripheral returned no data\n");
12970fffdf6cSThierry Reding 	return -ETIMEDOUT;
12980fffdf6cSThierry Reding }
12990fffdf6cSThierry Reding 
13000fffdf6cSThierry Reding static void tegra_dsi_writesl(struct tegra_dsi *dsi, unsigned long offset,
13010fffdf6cSThierry Reding 			      const void *buffer, size_t size)
13020fffdf6cSThierry Reding {
13030fffdf6cSThierry Reding 	const u8 *buf = buffer;
13040fffdf6cSThierry Reding 	size_t i, j;
13050fffdf6cSThierry Reding 	u32 value;
13060fffdf6cSThierry Reding 
13070fffdf6cSThierry Reding 	for (j = 0; j < size; j += 4) {
13080fffdf6cSThierry Reding 		value = 0;
13090fffdf6cSThierry Reding 
13100fffdf6cSThierry Reding 		for (i = 0; i < 4 && j + i < size; i++)
13110fffdf6cSThierry Reding 			value |= buf[j + i] << (i << 3);
13120fffdf6cSThierry Reding 
13130fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_WR_DATA);
13140fffdf6cSThierry Reding 	}
13150fffdf6cSThierry Reding }
13160fffdf6cSThierry Reding 
13170fffdf6cSThierry Reding static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
13180fffdf6cSThierry Reding 				       const struct mipi_dsi_msg *msg)
13190fffdf6cSThierry Reding {
13200fffdf6cSThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
13210fffdf6cSThierry Reding 	struct mipi_dsi_packet packet;
13220fffdf6cSThierry Reding 	const u8 *header;
13230fffdf6cSThierry Reding 	size_t count;
13240fffdf6cSThierry Reding 	ssize_t err;
13250fffdf6cSThierry Reding 	u32 value;
13260fffdf6cSThierry Reding 
13270fffdf6cSThierry Reding 	err = mipi_dsi_create_packet(&packet, msg);
13280fffdf6cSThierry Reding 	if (err < 0)
13290fffdf6cSThierry Reding 		return err;
13300fffdf6cSThierry Reding 
13310fffdf6cSThierry Reding 	header = packet.header;
13320fffdf6cSThierry Reding 
13330fffdf6cSThierry Reding 	/* maximum FIFO depth is 1920 words */
13340fffdf6cSThierry Reding 	if (packet.size > dsi->video_fifo_depth * 4)
13350fffdf6cSThierry Reding 		return -ENOSPC;
13360fffdf6cSThierry Reding 
13370fffdf6cSThierry Reding 	/* reset underflow/overflow flags */
13380fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_STATUS);
13390fffdf6cSThierry Reding 	if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) {
13400fffdf6cSThierry Reding 		value = DSI_HOST_CONTROL_FIFO_RESET;
13410fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
13420fffdf6cSThierry Reding 		usleep_range(10, 20);
13430fffdf6cSThierry Reding 	}
13440fffdf6cSThierry Reding 
13450fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
13460fffdf6cSThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
13470fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
13480fffdf6cSThierry Reding 
13490fffdf6cSThierry Reding 	usleep_range(5000, 10000);
13500fffdf6cSThierry Reding 
13510fffdf6cSThierry Reding 	value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST |
13520fffdf6cSThierry Reding 		DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
13530fffdf6cSThierry Reding 
13540fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0)
13550fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_HS;
13560fffdf6cSThierry Reding 
13570fffdf6cSThierry Reding 	/*
13580fffdf6cSThierry Reding 	 * The host FIFO has a maximum of 64 words, so larger transmissions
13590fffdf6cSThierry Reding 	 * need to use the video FIFO.
13600fffdf6cSThierry Reding 	 */
13610fffdf6cSThierry Reding 	if (packet.size > dsi->host_fifo_depth * 4)
13620fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_FIFO_SEL;
13630fffdf6cSThierry Reding 
13640fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
13650fffdf6cSThierry Reding 
13660fffdf6cSThierry Reding 	/*
13670fffdf6cSThierry Reding 	 * For reads and messages with explicitly requested ACK, generate a
13680fffdf6cSThierry Reding 	 * BTA sequence after the transmission of the packet.
13690fffdf6cSThierry Reding 	 */
13700fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
13710fffdf6cSThierry Reding 	    (msg->rx_buf && msg->rx_len > 0)) {
13720fffdf6cSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
13730fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_PKT_BTA;
13740fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
13750fffdf6cSThierry Reding 	}
13760fffdf6cSThierry Reding 
13770fffdf6cSThierry Reding 	value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE;
13780fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
13790fffdf6cSThierry Reding 
13800fffdf6cSThierry Reding 	/* write packet header, ECC is generated by hardware */
13810fffdf6cSThierry Reding 	value = header[2] << 16 | header[1] << 8 | header[0];
13820fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_WR_DATA);
13830fffdf6cSThierry Reding 
13840fffdf6cSThierry Reding 	/* write payload (if any) */
13850fffdf6cSThierry Reding 	if (packet.payload_length > 0)
13860fffdf6cSThierry Reding 		tegra_dsi_writesl(dsi, DSI_WR_DATA, packet.payload,
13870fffdf6cSThierry Reding 				  packet.payload_length);
13880fffdf6cSThierry Reding 
13890fffdf6cSThierry Reding 	err = tegra_dsi_transmit(dsi, 250);
13900fffdf6cSThierry Reding 	if (err < 0)
13910fffdf6cSThierry Reding 		return err;
13920fffdf6cSThierry Reding 
13930fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
13940fffdf6cSThierry Reding 	    (msg->rx_buf && msg->rx_len > 0)) {
13950fffdf6cSThierry Reding 		err = tegra_dsi_wait_for_response(dsi, 250);
13960fffdf6cSThierry Reding 		if (err < 0)
13970fffdf6cSThierry Reding 			return err;
13980fffdf6cSThierry Reding 
13990fffdf6cSThierry Reding 		count = err;
14000fffdf6cSThierry Reding 
14010fffdf6cSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_RD_DATA);
14020fffdf6cSThierry Reding 		switch (value) {
14030fffdf6cSThierry Reding 		case 0x84:
14040fffdf6cSThierry Reding 			/*
14050fffdf6cSThierry Reding 			dev_dbg(dsi->dev, "ACK\n");
14060fffdf6cSThierry Reding 			*/
14070fffdf6cSThierry Reding 			break;
14080fffdf6cSThierry Reding 
14090fffdf6cSThierry Reding 		case 0x87:
14100fffdf6cSThierry Reding 			/*
14110fffdf6cSThierry Reding 			dev_dbg(dsi->dev, "ESCAPE\n");
14120fffdf6cSThierry Reding 			*/
14130fffdf6cSThierry Reding 			break;
14140fffdf6cSThierry Reding 
14150fffdf6cSThierry Reding 		default:
14160fffdf6cSThierry Reding 			dev_err(dsi->dev, "unknown status: %08x\n", value);
14170fffdf6cSThierry Reding 			break;
14180fffdf6cSThierry Reding 		}
14190fffdf6cSThierry Reding 
14200fffdf6cSThierry Reding 		if (count > 1) {
14210fffdf6cSThierry Reding 			err = tegra_dsi_read_response(dsi, msg, count);
14220fffdf6cSThierry Reding 			if (err < 0)
14230fffdf6cSThierry Reding 				dev_err(dsi->dev,
14240fffdf6cSThierry Reding 					"failed to parse response: %zd\n",
14250fffdf6cSThierry Reding 					err);
14260fffdf6cSThierry Reding 			else {
14270fffdf6cSThierry Reding 				/*
14280fffdf6cSThierry Reding 				 * For read commands, return the number of
14290fffdf6cSThierry Reding 				 * bytes returned by the peripheral.
14300fffdf6cSThierry Reding 				 */
14310fffdf6cSThierry Reding 				count = err;
14320fffdf6cSThierry Reding 			}
14330fffdf6cSThierry Reding 		}
14340fffdf6cSThierry Reding 	} else {
14350fffdf6cSThierry Reding 		/*
14360fffdf6cSThierry Reding 		 * For write commands, we have transmitted the 4-byte header
14370fffdf6cSThierry Reding 		 * plus the variable-length payload.
14380fffdf6cSThierry Reding 		 */
14390fffdf6cSThierry Reding 		count = 4 + packet.payload_length;
14400fffdf6cSThierry Reding 	}
14410fffdf6cSThierry Reding 
14420fffdf6cSThierry Reding 	return count;
14430fffdf6cSThierry Reding }
14440fffdf6cSThierry Reding 
1445e94236cdSThierry Reding static int tegra_dsi_ganged_setup(struct tegra_dsi *dsi)
1446e94236cdSThierry Reding {
1447e94236cdSThierry Reding 	struct clk *parent;
1448e94236cdSThierry Reding 	int err;
1449e94236cdSThierry Reding 
1450e94236cdSThierry Reding 	/* make sure both DSI controllers share the same PLL */
1451e94236cdSThierry Reding 	parent = clk_get_parent(dsi->slave->clk);
1452e94236cdSThierry Reding 	if (!parent)
1453e94236cdSThierry Reding 		return -EINVAL;
1454e94236cdSThierry Reding 
1455e94236cdSThierry Reding 	err = clk_set_parent(parent, dsi->clk_parent);
1456e94236cdSThierry Reding 	if (err < 0)
1457e94236cdSThierry Reding 		return err;
1458e94236cdSThierry Reding 
1459e94236cdSThierry Reding 	return 0;
1460e94236cdSThierry Reding }
1461e94236cdSThierry Reding 
1462dec72739SThierry Reding static int tegra_dsi_host_attach(struct mipi_dsi_host *host,
1463dec72739SThierry Reding 				 struct mipi_dsi_device *device)
1464dec72739SThierry Reding {
1465dec72739SThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
1466dec72739SThierry Reding 
146717297a28SThierry Reding 	dsi->flags = device->mode_flags;
1468dec72739SThierry Reding 	dsi->format = device->format;
1469dec72739SThierry Reding 	dsi->lanes = device->lanes;
1470dec72739SThierry Reding 
1471e94236cdSThierry Reding 	if (dsi->slave) {
1472e94236cdSThierry Reding 		int err;
1473e94236cdSThierry Reding 
1474e94236cdSThierry Reding 		dev_dbg(dsi->dev, "attaching dual-channel device %s\n",
1475e94236cdSThierry Reding 			dev_name(&device->dev));
1476e94236cdSThierry Reding 
1477e94236cdSThierry Reding 		err = tegra_dsi_ganged_setup(dsi);
1478e94236cdSThierry Reding 		if (err < 0) {
1479e94236cdSThierry Reding 			dev_err(dsi->dev, "failed to set up ganged mode: %d\n",
1480e94236cdSThierry Reding 				err);
1481e94236cdSThierry Reding 			return err;
1482e94236cdSThierry Reding 		}
1483e94236cdSThierry Reding 	}
1484e94236cdSThierry Reding 
1485e94236cdSThierry Reding 	/*
1486e94236cdSThierry Reding 	 * Slaves don't have a panel associated with them, so they provide
1487e94236cdSThierry Reding 	 * merely the second channel.
1488e94236cdSThierry Reding 	 */
1489e94236cdSThierry Reding 	if (!dsi->master) {
1490e94236cdSThierry Reding 		struct tegra_output *output = &dsi->output;
1491e94236cdSThierry Reding 
1492dec72739SThierry Reding 		output->panel = of_drm_find_panel(device->dev.of_node);
14935fa8e4a2SBoris Brezillon 		if (IS_ERR(output->panel))
14945fa8e4a2SBoris Brezillon 			output->panel = NULL;
14955fa8e4a2SBoris Brezillon 
1496*87154ff8SJoe Perches 		if (output->panel && output->connector.dev)
1497dec72739SThierry Reding 			drm_helper_hpd_irq_event(output->connector.dev);
1498dec72739SThierry Reding 	}
1499dec72739SThierry Reding 
1500dec72739SThierry Reding 	return 0;
1501dec72739SThierry Reding }
1502dec72739SThierry Reding 
1503dec72739SThierry Reding static int tegra_dsi_host_detach(struct mipi_dsi_host *host,
1504dec72739SThierry Reding 				 struct mipi_dsi_device *device)
1505dec72739SThierry Reding {
1506dec72739SThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
1507dec72739SThierry Reding 	struct tegra_output *output = &dsi->output;
1508dec72739SThierry Reding 
1509dec72739SThierry Reding 	if (output->panel && &device->dev == output->panel->dev) {
1510ba3df979SThierry Reding 		output->panel = NULL;
1511ba3df979SThierry Reding 
1512dec72739SThierry Reding 		if (output->connector.dev)
1513dec72739SThierry Reding 			drm_helper_hpd_irq_event(output->connector.dev);
1514dec72739SThierry Reding 	}
1515dec72739SThierry Reding 
1516dec72739SThierry Reding 	return 0;
1517dec72739SThierry Reding }
1518dec72739SThierry Reding 
1519dec72739SThierry Reding static const struct mipi_dsi_host_ops tegra_dsi_host_ops = {
1520dec72739SThierry Reding 	.attach = tegra_dsi_host_attach,
1521dec72739SThierry Reding 	.detach = tegra_dsi_host_detach,
15220fffdf6cSThierry Reding 	.transfer = tegra_dsi_host_transfer,
1523dec72739SThierry Reding };
1524dec72739SThierry Reding 
1525e94236cdSThierry Reding static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
1526e94236cdSThierry Reding {
1527e94236cdSThierry Reding 	struct device_node *np;
1528e94236cdSThierry Reding 
1529e94236cdSThierry Reding 	np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0);
1530e94236cdSThierry Reding 	if (np) {
1531e94236cdSThierry Reding 		struct platform_device *gangster = of_find_device_by_node(np);
1532e94236cdSThierry Reding 
1533e94236cdSThierry Reding 		dsi->slave = platform_get_drvdata(gangster);
1534e94236cdSThierry Reding 		of_node_put(np);
1535e94236cdSThierry Reding 
1536e94236cdSThierry Reding 		if (!dsi->slave)
1537e94236cdSThierry Reding 			return -EPROBE_DEFER;
1538e94236cdSThierry Reding 
1539e94236cdSThierry Reding 		dsi->slave->master = dsi;
1540e94236cdSThierry Reding 	}
1541e94236cdSThierry Reding 
1542e94236cdSThierry Reding 	return 0;
1543e94236cdSThierry Reding }
1544e94236cdSThierry Reding 
1545dec72739SThierry Reding static int tegra_dsi_probe(struct platform_device *pdev)
1546dec72739SThierry Reding {
1547dec72739SThierry Reding 	struct tegra_dsi *dsi;
1548dec72739SThierry Reding 	struct resource *regs;
1549dec72739SThierry Reding 	int err;
1550dec72739SThierry Reding 
1551dec72739SThierry Reding 	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
1552dec72739SThierry Reding 	if (!dsi)
1553dec72739SThierry Reding 		return -ENOMEM;
1554dec72739SThierry Reding 
1555dec72739SThierry Reding 	dsi->output.dev = dsi->dev = &pdev->dev;
1556976cebc3SThierry Reding 	dsi->video_fifo_depth = 1920;
1557976cebc3SThierry Reding 	dsi->host_fifo_depth = 64;
1558dec72739SThierry Reding 
1559e94236cdSThierry Reding 	err = tegra_dsi_ganged_probe(dsi);
1560e94236cdSThierry Reding 	if (err < 0)
1561e94236cdSThierry Reding 		return err;
1562e94236cdSThierry Reding 
1563dec72739SThierry Reding 	err = tegra_output_probe(&dsi->output);
1564dec72739SThierry Reding 	if (err < 0)
1565dec72739SThierry Reding 		return err;
1566dec72739SThierry Reding 
1567ba3df979SThierry Reding 	dsi->output.connector.polled = DRM_CONNECTOR_POLL_HPD;
1568ba3df979SThierry Reding 
1569dec72739SThierry Reding 	/*
1570dec72739SThierry Reding 	 * Assume these values by default. When a DSI peripheral driver
1571dec72739SThierry Reding 	 * attaches to the DSI host, the parameters will be taken from
1572dec72739SThierry Reding 	 * the attached device.
1573dec72739SThierry Reding 	 */
157417297a28SThierry Reding 	dsi->flags = MIPI_DSI_MODE_VIDEO;
1575dec72739SThierry Reding 	dsi->format = MIPI_DSI_FMT_RGB888;
1576dec72739SThierry Reding 	dsi->lanes = 4;
1577dec72739SThierry Reding 
157864230aa0SJon Hunter 	if (!pdev->dev.pm_domain) {
1579dec72739SThierry Reding 		dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
1580dec72739SThierry Reding 		if (IS_ERR(dsi->rst))
1581dec72739SThierry Reding 			return PTR_ERR(dsi->rst);
158264230aa0SJon Hunter 	}
1583dec72739SThierry Reding 
1584dec72739SThierry Reding 	dsi->clk = devm_clk_get(&pdev->dev, NULL);
1585dec72739SThierry Reding 	if (IS_ERR(dsi->clk)) {
1586dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get DSI clock\n");
1587ef8187d7SThierry Reding 		return PTR_ERR(dsi->clk);
1588dec72739SThierry Reding 	}
1589dec72739SThierry Reding 
1590dec72739SThierry Reding 	dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
1591dec72739SThierry Reding 	if (IS_ERR(dsi->clk_lp)) {
1592dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get low-power clock\n");
1593ef8187d7SThierry Reding 		return PTR_ERR(dsi->clk_lp);
1594dec72739SThierry Reding 	}
1595dec72739SThierry Reding 
1596dec72739SThierry Reding 	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1597dec72739SThierry Reding 	if (IS_ERR(dsi->clk_parent)) {
1598dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get parent clock\n");
1599ef8187d7SThierry Reding 		return PTR_ERR(dsi->clk_parent);
1600dec72739SThierry Reding 	}
1601dec72739SThierry Reding 
16023b077afbSThierry Reding 	dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
16033b077afbSThierry Reding 	if (IS_ERR(dsi->vdd)) {
16043b077afbSThierry Reding 		dev_err(&pdev->dev, "cannot get VDD supply\n");
1605ef8187d7SThierry Reding 		return PTR_ERR(dsi->vdd);
16063b077afbSThierry Reding 	}
16073b077afbSThierry Reding 
1608dec72739SThierry Reding 	err = tegra_dsi_setup_clocks(dsi);
1609dec72739SThierry Reding 	if (err < 0) {
1610dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot setup clocks\n");
1611ef8187d7SThierry Reding 		return err;
1612dec72739SThierry Reding 	}
1613dec72739SThierry Reding 
1614dec72739SThierry Reding 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1615dec72739SThierry Reding 	dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
1616ef8187d7SThierry Reding 	if (IS_ERR(dsi->regs))
1617ef8187d7SThierry Reding 		return PTR_ERR(dsi->regs);
1618dec72739SThierry Reding 
1619dec72739SThierry Reding 	dsi->mipi = tegra_mipi_request(&pdev->dev);
1620ef8187d7SThierry Reding 	if (IS_ERR(dsi->mipi))
1621ef8187d7SThierry Reding 		return PTR_ERR(dsi->mipi);
1622dec72739SThierry Reding 
1623dec72739SThierry Reding 	dsi->host.ops = &tegra_dsi_host_ops;
1624dec72739SThierry Reding 	dsi->host.dev = &pdev->dev;
1625dec72739SThierry Reding 
1626dec72739SThierry Reding 	err = mipi_dsi_host_register(&dsi->host);
1627dec72739SThierry Reding 	if (err < 0) {
1628dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to register DSI host: %d\n", err);
1629d2d0a9d2SThierry Reding 		goto mipi_free;
1630dec72739SThierry Reding 	}
1631dec72739SThierry Reding 
1632ef8187d7SThierry Reding 	platform_set_drvdata(pdev, dsi);
1633ef8187d7SThierry Reding 	pm_runtime_enable(&pdev->dev);
1634ef8187d7SThierry Reding 
1635dec72739SThierry Reding 	INIT_LIST_HEAD(&dsi->client.list);
1636dec72739SThierry Reding 	dsi->client.ops = &dsi_client_ops;
1637dec72739SThierry Reding 	dsi->client.dev = &pdev->dev;
1638dec72739SThierry Reding 
1639dec72739SThierry Reding 	err = host1x_client_register(&dsi->client);
1640dec72739SThierry Reding 	if (err < 0) {
1641dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1642dec72739SThierry Reding 			err);
1643d2d0a9d2SThierry Reding 		goto unregister;
1644dec72739SThierry Reding 	}
1645dec72739SThierry Reding 
1646dec72739SThierry Reding 	return 0;
1647d2d0a9d2SThierry Reding 
1648d2d0a9d2SThierry Reding unregister:
1649d2d0a9d2SThierry Reding 	mipi_dsi_host_unregister(&dsi->host);
1650d2d0a9d2SThierry Reding mipi_free:
1651d2d0a9d2SThierry Reding 	tegra_mipi_free(dsi->mipi);
1652d2d0a9d2SThierry Reding 	return err;
1653dec72739SThierry Reding }
1654dec72739SThierry Reding 
1655dec72739SThierry Reding static int tegra_dsi_remove(struct platform_device *pdev)
1656dec72739SThierry Reding {
1657dec72739SThierry Reding 	struct tegra_dsi *dsi = platform_get_drvdata(pdev);
1658dec72739SThierry Reding 	int err;
1659dec72739SThierry Reding 
1660ef8187d7SThierry Reding 	pm_runtime_disable(&pdev->dev);
1661ef8187d7SThierry Reding 
1662dec72739SThierry Reding 	err = host1x_client_unregister(&dsi->client);
1663dec72739SThierry Reding 	if (err < 0) {
1664dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1665dec72739SThierry Reding 			err);
1666dec72739SThierry Reding 		return err;
1667dec72739SThierry Reding 	}
1668dec72739SThierry Reding 
1669328ec69eSThierry Reding 	tegra_output_remove(&dsi->output);
16705b901e78SThierry Reding 
1671dec72739SThierry Reding 	mipi_dsi_host_unregister(&dsi->host);
1672dec72739SThierry Reding 	tegra_mipi_free(dsi->mipi);
1673dec72739SThierry Reding 
1674ef8187d7SThierry Reding 	return 0;
1675ef8187d7SThierry Reding }
1676ef8187d7SThierry Reding 
1677dec72739SThierry Reding static const struct of_device_id tegra_dsi_of_match[] = {
1678ddfb406bSThierry Reding 	{ .compatible = "nvidia,tegra210-dsi", },
1679c06c7930SThierry Reding 	{ .compatible = "nvidia,tegra132-dsi", },
16807d338587SThierry Reding 	{ .compatible = "nvidia,tegra124-dsi", },
1681dec72739SThierry Reding 	{ .compatible = "nvidia,tegra114-dsi", },
1682dec72739SThierry Reding 	{ },
1683dec72739SThierry Reding };
1684ef70728cSStephen Warren MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
1685dec72739SThierry Reding 
1686dec72739SThierry Reding struct platform_driver tegra_dsi_driver = {
1687dec72739SThierry Reding 	.driver = {
1688dec72739SThierry Reding 		.name = "tegra-dsi",
1689dec72739SThierry Reding 		.of_match_table = tegra_dsi_of_match,
1690dec72739SThierry Reding 	},
1691dec72739SThierry Reding 	.probe = tegra_dsi_probe,
1692dec72739SThierry Reding 	.remove = tegra_dsi_remove,
1693dec72739SThierry Reding };
1694