xref: /linux/drivers/gpu/drm/tegra/dsi.c (revision 171e2e6dd912dac625e085919f0822cd94c04ff0)
1dec72739SThierry Reding /*
2dec72739SThierry Reding  * Copyright (C) 2013 NVIDIA Corporation
3dec72739SThierry Reding  *
49a2ac2dcSThierry Reding  * This program is free software; you can redistribute it and/or modify
59a2ac2dcSThierry Reding  * it under the terms of the GNU General Public License version 2 as
69a2ac2dcSThierry Reding  * published by the Free Software Foundation.
7dec72739SThierry Reding  */
8dec72739SThierry Reding 
9dec72739SThierry Reding #include <linux/clk.h>
10dec72739SThierry Reding #include <linux/debugfs.h>
11dec72739SThierry Reding #include <linux/host1x.h>
12dec72739SThierry Reding #include <linux/module.h>
13dec72739SThierry Reding #include <linux/of.h>
14e94236cdSThierry Reding #include <linux/of_platform.h>
15dec72739SThierry Reding #include <linux/platform_device.h>
16dec72739SThierry Reding #include <linux/reset.h>
17dec72739SThierry Reding 
183b077afbSThierry Reding #include <linux/regulator/consumer.h>
193b077afbSThierry Reding 
204aa3df71SThierry Reding #include <drm/drm_atomic_helper.h>
21dec72739SThierry Reding #include <drm/drm_mipi_dsi.h>
22dec72739SThierry Reding #include <drm/drm_panel.h>
23dec72739SThierry Reding 
24dec72739SThierry Reding #include <video/mipi_display.h>
25dec72739SThierry Reding 
26dec72739SThierry Reding #include "dc.h"
27dec72739SThierry Reding #include "drm.h"
28dec72739SThierry Reding #include "dsi.h"
29dec72739SThierry Reding #include "mipi-phy.h"
30dec72739SThierry Reding 
31ebd14afeSThierry Reding struct tegra_dsi_state {
32ebd14afeSThierry Reding 	struct drm_connector_state base;
33ebd14afeSThierry Reding 
34ebd14afeSThierry Reding 	struct mipi_dphy_timing timing;
35ebd14afeSThierry Reding 	unsigned long period;
36ebd14afeSThierry Reding 
37ebd14afeSThierry Reding 	unsigned int vrefresh;
38ebd14afeSThierry Reding 	unsigned int lanes;
39ebd14afeSThierry Reding 	unsigned long pclk;
40ebd14afeSThierry Reding 	unsigned long bclk;
41ebd14afeSThierry Reding 
42ebd14afeSThierry Reding 	enum tegra_dsi_format format;
43ebd14afeSThierry Reding 	unsigned int mul;
44ebd14afeSThierry Reding 	unsigned int div;
45ebd14afeSThierry Reding };
46ebd14afeSThierry Reding 
47ebd14afeSThierry Reding static inline struct tegra_dsi_state *
48ebd14afeSThierry Reding to_dsi_state(struct drm_connector_state *state)
49ebd14afeSThierry Reding {
50ebd14afeSThierry Reding 	return container_of(state, struct tegra_dsi_state, base);
51ebd14afeSThierry Reding }
52ebd14afeSThierry Reding 
53dec72739SThierry Reding struct tegra_dsi {
54dec72739SThierry Reding 	struct host1x_client client;
55dec72739SThierry Reding 	struct tegra_output output;
56dec72739SThierry Reding 	struct device *dev;
57dec72739SThierry Reding 
58dec72739SThierry Reding 	void __iomem *regs;
59dec72739SThierry Reding 
60dec72739SThierry Reding 	struct reset_control *rst;
61dec72739SThierry Reding 	struct clk *clk_parent;
62dec72739SThierry Reding 	struct clk *clk_lp;
63dec72739SThierry Reding 	struct clk *clk;
64dec72739SThierry Reding 
65dec72739SThierry Reding 	struct drm_info_list *debugfs_files;
66dec72739SThierry Reding 	struct drm_minor *minor;
67dec72739SThierry Reding 	struct dentry *debugfs;
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 
1079c0b4ca1SThierry Reding static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned long reg)
108dec72739SThierry Reding {
109dec72739SThierry Reding 	return readl(dsi->regs + (reg << 2));
110dec72739SThierry Reding }
111dec72739SThierry Reding 
1129c0b4ca1SThierry Reding static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
113dec72739SThierry Reding 				    unsigned long reg)
114dec72739SThierry Reding {
115dec72739SThierry Reding 	writel(value, dsi->regs + (reg << 2));
116dec72739SThierry Reding }
117dec72739SThierry Reding 
118dec72739SThierry Reding static int tegra_dsi_show_regs(struct seq_file *s, void *data)
119dec72739SThierry Reding {
120dec72739SThierry Reding 	struct drm_info_node *node = s->private;
121dec72739SThierry Reding 	struct tegra_dsi *dsi = node->info_ent->data;
122*171e2e6dSThierry Reding 	struct drm_crtc *crtc = dsi->output.encoder.crtc;
123*171e2e6dSThierry Reding 	struct drm_device *drm = node->minor->dev;
124*171e2e6dSThierry Reding 	int err = 0;
125*171e2e6dSThierry Reding 
126*171e2e6dSThierry Reding 	drm_modeset_lock_all(drm);
127*171e2e6dSThierry Reding 
128*171e2e6dSThierry Reding 	if (!crtc || !crtc->state->active) {
129*171e2e6dSThierry Reding 		err = -EBUSY;
130*171e2e6dSThierry Reding 		goto unlock;
131*171e2e6dSThierry Reding 	}
132dec72739SThierry Reding 
133dec72739SThierry Reding #define DUMP_REG(name)						\
1349c0b4ca1SThierry Reding 	seq_printf(s, "%-32s %#05x %08x\n", #name, name,	\
135dec72739SThierry Reding 		   tegra_dsi_readl(dsi, name))
136dec72739SThierry Reding 
137dec72739SThierry Reding 	DUMP_REG(DSI_INCR_SYNCPT);
138dec72739SThierry Reding 	DUMP_REG(DSI_INCR_SYNCPT_CONTROL);
139dec72739SThierry Reding 	DUMP_REG(DSI_INCR_SYNCPT_ERROR);
140dec72739SThierry Reding 	DUMP_REG(DSI_CTXSW);
141dec72739SThierry Reding 	DUMP_REG(DSI_RD_DATA);
142dec72739SThierry Reding 	DUMP_REG(DSI_WR_DATA);
143dec72739SThierry Reding 	DUMP_REG(DSI_POWER_CONTROL);
144dec72739SThierry Reding 	DUMP_REG(DSI_INT_ENABLE);
145dec72739SThierry Reding 	DUMP_REG(DSI_INT_STATUS);
146dec72739SThierry Reding 	DUMP_REG(DSI_INT_MASK);
147dec72739SThierry Reding 	DUMP_REG(DSI_HOST_CONTROL);
148dec72739SThierry Reding 	DUMP_REG(DSI_CONTROL);
149dec72739SThierry Reding 	DUMP_REG(DSI_SOL_DELAY);
150dec72739SThierry Reding 	DUMP_REG(DSI_MAX_THRESHOLD);
151dec72739SThierry Reding 	DUMP_REG(DSI_TRIGGER);
152dec72739SThierry Reding 	DUMP_REG(DSI_TX_CRC);
153dec72739SThierry Reding 	DUMP_REG(DSI_STATUS);
154dec72739SThierry Reding 
155dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_CONTROL);
156dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_0);
157dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_1);
158dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_2);
159dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_3);
160dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_4);
161dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_5);
162dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_6);
163dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_7);
164dec72739SThierry Reding 
165dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_0_LO);
166dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_0_HI);
167dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_1_LO);
168dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_1_HI);
169dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_2_LO);
170dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_2_HI);
171dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_3_LO);
172dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_3_HI);
173dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_4_LO);
174dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_4_HI);
175dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_5_LO);
176dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_5_HI);
177dec72739SThierry Reding 
178dec72739SThierry Reding 	DUMP_REG(DSI_DCS_CMDS);
179dec72739SThierry Reding 
180dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_0_1);
181dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_2_3);
182dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_4_5);
183dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_6_7);
184dec72739SThierry Reding 
185dec72739SThierry Reding 	DUMP_REG(DSI_PHY_TIMING_0);
186dec72739SThierry Reding 	DUMP_REG(DSI_PHY_TIMING_1);
187dec72739SThierry Reding 	DUMP_REG(DSI_PHY_TIMING_2);
188dec72739SThierry Reding 	DUMP_REG(DSI_BTA_TIMING);
189dec72739SThierry Reding 
190dec72739SThierry Reding 	DUMP_REG(DSI_TIMEOUT_0);
191dec72739SThierry Reding 	DUMP_REG(DSI_TIMEOUT_1);
192dec72739SThierry Reding 	DUMP_REG(DSI_TO_TALLY);
193dec72739SThierry Reding 
194dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_0);
195dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_CD);
196dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CD_STATUS);
197dec72739SThierry Reding 	DUMP_REG(DSI_VIDEO_MODE_CONTROL);
198dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_1);
199dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_2);
200dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_3);
201dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_4);
202dec72739SThierry Reding 
203dec72739SThierry Reding 	DUMP_REG(DSI_GANGED_MODE_CONTROL);
204dec72739SThierry Reding 	DUMP_REG(DSI_GANGED_MODE_START);
205dec72739SThierry Reding 	DUMP_REG(DSI_GANGED_MODE_SIZE);
206dec72739SThierry Reding 
207dec72739SThierry Reding 	DUMP_REG(DSI_RAW_DATA_BYTE_COUNT);
208dec72739SThierry Reding 	DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL);
209dec72739SThierry Reding 
210dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_8);
211dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_9);
212dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_10);
213dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_11);
214dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_12);
215dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_13);
216dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_14);
217dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_15);
218dec72739SThierry Reding 
219dec72739SThierry Reding #undef DUMP_REG
220dec72739SThierry Reding 
221*171e2e6dSThierry Reding unlock:
222*171e2e6dSThierry Reding 	drm_modeset_unlock_all(drm);
223*171e2e6dSThierry Reding 	return err;
224dec72739SThierry Reding }
225dec72739SThierry Reding 
226dec72739SThierry Reding static struct drm_info_list debugfs_files[] = {
227dec72739SThierry Reding 	{ "regs", tegra_dsi_show_regs, 0, NULL },
228dec72739SThierry Reding };
229dec72739SThierry Reding 
230dec72739SThierry Reding static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi,
231dec72739SThierry Reding 				  struct drm_minor *minor)
232dec72739SThierry Reding {
233dec72739SThierry Reding 	const char *name = dev_name(dsi->dev);
234dec72739SThierry Reding 	unsigned int i;
235dec72739SThierry Reding 	int err;
236dec72739SThierry Reding 
237dec72739SThierry Reding 	dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root);
238dec72739SThierry Reding 	if (!dsi->debugfs)
239dec72739SThierry Reding 		return -ENOMEM;
240dec72739SThierry Reding 
241dec72739SThierry Reding 	dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
242dec72739SThierry Reding 				     GFP_KERNEL);
243dec72739SThierry Reding 	if (!dsi->debugfs_files) {
244dec72739SThierry Reding 		err = -ENOMEM;
245dec72739SThierry Reding 		goto remove;
246dec72739SThierry Reding 	}
247dec72739SThierry Reding 
248dec72739SThierry Reding 	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
249dec72739SThierry Reding 		dsi->debugfs_files[i].data = dsi;
250dec72739SThierry Reding 
251dec72739SThierry Reding 	err = drm_debugfs_create_files(dsi->debugfs_files,
252dec72739SThierry Reding 				       ARRAY_SIZE(debugfs_files),
253dec72739SThierry Reding 				       dsi->debugfs, minor);
254dec72739SThierry Reding 	if (err < 0)
255dec72739SThierry Reding 		goto free;
256dec72739SThierry Reding 
257dec72739SThierry Reding 	dsi->minor = minor;
258dec72739SThierry Reding 
259dec72739SThierry Reding 	return 0;
260dec72739SThierry Reding 
261dec72739SThierry Reding free:
262dec72739SThierry Reding 	kfree(dsi->debugfs_files);
263dec72739SThierry Reding 	dsi->debugfs_files = NULL;
264dec72739SThierry Reding remove:
265dec72739SThierry Reding 	debugfs_remove(dsi->debugfs);
266dec72739SThierry Reding 	dsi->debugfs = NULL;
267dec72739SThierry Reding 
268dec72739SThierry Reding 	return err;
269dec72739SThierry Reding }
270dec72739SThierry Reding 
2714009c224SThierry Reding static void tegra_dsi_debugfs_exit(struct tegra_dsi *dsi)
272dec72739SThierry Reding {
273dec72739SThierry Reding 	drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files),
274dec72739SThierry Reding 				 dsi->minor);
275dec72739SThierry Reding 	dsi->minor = NULL;
276dec72739SThierry Reding 
277dec72739SThierry Reding 	kfree(dsi->debugfs_files);
278dec72739SThierry Reding 	dsi->debugfs_files = NULL;
279dec72739SThierry Reding 
280dec72739SThierry Reding 	debugfs_remove(dsi->debugfs);
281dec72739SThierry Reding 	dsi->debugfs = NULL;
282dec72739SThierry Reding }
283dec72739SThierry Reding 
284dec72739SThierry Reding #define PKT_ID0(id)	((((id) & 0x3f) <<  3) | (1 <<  9))
285dec72739SThierry Reding #define PKT_LEN0(len)	(((len) & 0x07) <<  0)
286dec72739SThierry Reding #define PKT_ID1(id)	((((id) & 0x3f) << 13) | (1 << 19))
287dec72739SThierry Reding #define PKT_LEN1(len)	(((len) & 0x07) << 10)
288dec72739SThierry Reding #define PKT_ID2(id)	((((id) & 0x3f) << 23) | (1 << 29))
289dec72739SThierry Reding #define PKT_LEN2(len)	(((len) & 0x07) << 20)
290dec72739SThierry Reding 
291dec72739SThierry Reding #define PKT_LP		(1 << 30)
292dec72739SThierry Reding #define NUM_PKT_SEQ	12
293dec72739SThierry Reding 
29417297a28SThierry Reding /*
29517297a28SThierry Reding  * non-burst mode with sync pulses
29617297a28SThierry Reding  */
29717297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = {
298dec72739SThierry Reding 	[ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
299dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
300dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
301dec72739SThierry Reding 	       PKT_LP,
302dec72739SThierry Reding 	[ 1] = 0,
303dec72739SThierry Reding 	[ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | PKT_LEN0(0) |
304dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
305dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
306dec72739SThierry Reding 	       PKT_LP,
307dec72739SThierry Reding 	[ 3] = 0,
308dec72739SThierry Reding 	[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
309dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
310dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
311dec72739SThierry Reding 	       PKT_LP,
312dec72739SThierry Reding 	[ 5] = 0,
313dec72739SThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
314dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
315dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
316dec72739SThierry Reding 	[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
317dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
318dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
319dec72739SThierry Reding 	[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
320dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
321dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
322dec72739SThierry Reding 	       PKT_LP,
323dec72739SThierry Reding 	[ 9] = 0,
324dec72739SThierry Reding 	[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
325dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
326dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
327dec72739SThierry Reding 	[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
328dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
329dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
330dec72739SThierry Reding };
331dec72739SThierry Reding 
33217297a28SThierry Reding /*
33317297a28SThierry Reding  * non-burst mode with sync events
33417297a28SThierry Reding  */
33517297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
33617297a28SThierry Reding 	[ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
33717297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
33817297a28SThierry Reding 	       PKT_LP,
33917297a28SThierry Reding 	[ 1] = 0,
34017297a28SThierry Reding 	[ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
34117297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
34217297a28SThierry Reding 	       PKT_LP,
34317297a28SThierry Reding 	[ 3] = 0,
34417297a28SThierry Reding 	[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
34517297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
34617297a28SThierry Reding 	       PKT_LP,
34717297a28SThierry Reding 	[ 5] = 0,
34817297a28SThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
34917297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
35017297a28SThierry Reding 	       PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
35117297a28SThierry Reding 	[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
35217297a28SThierry Reding 	[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
35317297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
35417297a28SThierry Reding 	       PKT_LP,
35517297a28SThierry Reding 	[ 9] = 0,
35617297a28SThierry Reding 	[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
35717297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
35817297a28SThierry Reding 	       PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
35917297a28SThierry Reding 	[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
36017297a28SThierry Reding };
36117297a28SThierry Reding 
362337b443dSThierry Reding static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = {
363337b443dSThierry Reding 	[ 0] = 0,
364337b443dSThierry Reding 	[ 1] = 0,
365337b443dSThierry Reding 	[ 2] = 0,
366337b443dSThierry Reding 	[ 3] = 0,
367337b443dSThierry Reding 	[ 4] = 0,
368337b443dSThierry Reding 	[ 5] = 0,
369337b443dSThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP,
370337b443dSThierry Reding 	[ 7] = 0,
371337b443dSThierry Reding 	[ 8] = 0,
372337b443dSThierry Reding 	[ 9] = 0,
373337b443dSThierry Reding 	[10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP,
374337b443dSThierry Reding 	[11] = 0,
375337b443dSThierry Reding };
376337b443dSThierry Reding 
377ebd14afeSThierry Reding static void tegra_dsi_set_phy_timing(struct tegra_dsi *dsi,
378ebd14afeSThierry Reding 				     unsigned long period,
379ebd14afeSThierry Reding 				     const struct mipi_dphy_timing *timing)
380dec72739SThierry Reding {
3819c0b4ca1SThierry Reding 	u32 value;
382dec72739SThierry Reding 
383ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->hsexit, period, 1) << 24 |
384ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hstrail, period, 0) << 16 |
385ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hszero, period, 3) << 8 |
386ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hsprepare, period, 1);
387dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0);
388dec72739SThierry Reding 
389ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->clktrail, period, 1) << 24 |
390ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkpost, period, 1) << 16 |
391ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkzero, period, 1) << 8 |
392ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->lpx, period, 1);
393dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1);
394dec72739SThierry Reding 
395ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->clkprepare, period, 1) << 16 |
396ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkpre, period, 1) << 8 |
397dec72739SThierry Reding 		DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
398dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2);
399dec72739SThierry Reding 
400ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->taget, period, 1) << 16 |
401ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->tasure, period, 1) << 8 |
402ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->tago, period, 1);
403dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);
404dec72739SThierry Reding 
4057e3bc3a9SSean Paul 	if (dsi->slave)
406ebd14afeSThierry Reding 		tegra_dsi_set_phy_timing(dsi->slave, period, timing);
407dec72739SThierry Reding }
408dec72739SThierry Reding 
409dec72739SThierry Reding static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format,
410dec72739SThierry Reding 				unsigned int *mulp, unsigned int *divp)
411dec72739SThierry Reding {
412dec72739SThierry Reding 	switch (format) {
413dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB666_PACKED:
414dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB888:
415dec72739SThierry Reding 		*mulp = 3;
416dec72739SThierry Reding 		*divp = 1;
417dec72739SThierry Reding 		break;
418dec72739SThierry Reding 
419dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB565:
420dec72739SThierry Reding 		*mulp = 2;
421dec72739SThierry Reding 		*divp = 1;
422dec72739SThierry Reding 		break;
423dec72739SThierry Reding 
424dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB666:
425dec72739SThierry Reding 		*mulp = 9;
426dec72739SThierry Reding 		*divp = 4;
427dec72739SThierry Reding 		break;
428dec72739SThierry Reding 
429dec72739SThierry Reding 	default:
430dec72739SThierry Reding 		return -EINVAL;
431dec72739SThierry Reding 	}
432dec72739SThierry Reding 
433dec72739SThierry Reding 	return 0;
434dec72739SThierry Reding }
435dec72739SThierry Reding 
436f7d6889bSThierry Reding static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format,
437f7d6889bSThierry Reding 				enum tegra_dsi_format *fmt)
438f7d6889bSThierry Reding {
439f7d6889bSThierry Reding 	switch (format) {
440f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB888:
441f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_24P;
442f7d6889bSThierry Reding 		break;
443f7d6889bSThierry Reding 
444f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB666:
445f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_18NP;
446f7d6889bSThierry Reding 		break;
447f7d6889bSThierry Reding 
448f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB666_PACKED:
449f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_18P;
450f7d6889bSThierry Reding 		break;
451f7d6889bSThierry Reding 
452f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB565:
453f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_16P;
454f7d6889bSThierry Reding 		break;
455f7d6889bSThierry Reding 
456f7d6889bSThierry Reding 	default:
457f7d6889bSThierry Reding 		return -EINVAL;
458f7d6889bSThierry Reding 	}
459f7d6889bSThierry Reding 
460f7d6889bSThierry Reding 	return 0;
461f7d6889bSThierry Reding }
462f7d6889bSThierry Reding 
463e94236cdSThierry Reding static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
464e94236cdSThierry Reding 				    unsigned int size)
465e94236cdSThierry Reding {
466e94236cdSThierry Reding 	u32 value;
467e94236cdSThierry Reding 
468e94236cdSThierry Reding 	tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
469e94236cdSThierry Reding 	tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
470e94236cdSThierry Reding 
471e94236cdSThierry Reding 	value = DSI_GANGED_MODE_CONTROL_ENABLE;
472e94236cdSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
473e94236cdSThierry Reding }
474e94236cdSThierry Reding 
475563eff1fSThierry Reding static void tegra_dsi_enable(struct tegra_dsi *dsi)
476dec72739SThierry Reding {
477563eff1fSThierry Reding 	u32 value;
478dec72739SThierry Reding 
479563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
480563eff1fSThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
481563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
482e94236cdSThierry Reding 
483e94236cdSThierry Reding 	if (dsi->slave)
484e94236cdSThierry Reding 		tegra_dsi_enable(dsi->slave);
485e94236cdSThierry Reding }
486e94236cdSThierry Reding 
487e94236cdSThierry Reding static unsigned int tegra_dsi_get_lanes(struct tegra_dsi *dsi)
488e94236cdSThierry Reding {
489e94236cdSThierry Reding 	if (dsi->master)
490e94236cdSThierry Reding 		return dsi->master->lanes + dsi->lanes;
491e94236cdSThierry Reding 
492e94236cdSThierry Reding 	if (dsi->slave)
493e94236cdSThierry Reding 		return dsi->lanes + dsi->slave->lanes;
494e94236cdSThierry Reding 
495e94236cdSThierry Reding 	return dsi->lanes;
496563eff1fSThierry Reding }
497563eff1fSThierry Reding 
498ebd14afeSThierry Reding static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
499563eff1fSThierry Reding 				const struct drm_display_mode *mode)
500563eff1fSThierry Reding {
501563eff1fSThierry Reding 	unsigned int hact, hsw, hbp, hfp, i, mul, div;
502ebd14afeSThierry Reding 	struct tegra_dsi_state *state;
503563eff1fSThierry Reding 	const u32 *pkt_seq;
504563eff1fSThierry Reding 	u32 value;
505ebd14afeSThierry Reding 
506ebd14afeSThierry Reding 	/* XXX: pass in state into this function? */
507ebd14afeSThierry Reding 	if (dsi->master)
508ebd14afeSThierry Reding 		state = tegra_dsi_get_state(dsi->master);
509ebd14afeSThierry Reding 	else
510ebd14afeSThierry Reding 		state = tegra_dsi_get_state(dsi);
511ebd14afeSThierry Reding 
512ebd14afeSThierry Reding 	mul = state->mul;
513ebd14afeSThierry Reding 	div = state->div;
514334ae6b5SThierry Reding 
51517297a28SThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
51617297a28SThierry Reding 		DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n");
51717297a28SThierry Reding 		pkt_seq = pkt_seq_video_non_burst_sync_pulses;
518337b443dSThierry Reding 	} else if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
51917297a28SThierry Reding 		DRM_DEBUG_KMS("Non-burst video mode with sync events\n");
52017297a28SThierry Reding 		pkt_seq = pkt_seq_video_non_burst_sync_events;
521337b443dSThierry Reding 	} else {
522337b443dSThierry Reding 		DRM_DEBUG_KMS("Command mode\n");
523337b443dSThierry Reding 		pkt_seq = pkt_seq_command_mode;
52417297a28SThierry Reding 	}
52517297a28SThierry Reding 
526ebd14afeSThierry Reding 	value = DSI_CONTROL_CHANNEL(0) |
527ebd14afeSThierry Reding 		DSI_CONTROL_FORMAT(state->format) |
528dec72739SThierry Reding 		DSI_CONTROL_LANES(dsi->lanes - 1) |
529563eff1fSThierry Reding 		DSI_CONTROL_SOURCE(pipe);
530dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
531dec72739SThierry Reding 
532976cebc3SThierry Reding 	tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD);
533dec72739SThierry Reding 
534563eff1fSThierry Reding 	value = DSI_HOST_CONTROL_HS;
535dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
536dec72739SThierry Reding 
537dec72739SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
538563eff1fSThierry Reding 
5390c6b1e4bSAlexandre Courbot 	if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
540dec72739SThierry Reding 		value |= DSI_CONTROL_HS_CLK_CTRL;
541563eff1fSThierry Reding 
542dec72739SThierry Reding 	value &= ~DSI_CONTROL_TX_TRIG(3);
543337b443dSThierry Reding 
544337b443dSThierry Reding 	/* enable DCS commands for command mode */
545337b443dSThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO)
546dec72739SThierry Reding 		value &= ~DSI_CONTROL_DCS_ENABLE;
547337b443dSThierry Reding 	else
548337b443dSThierry Reding 		value |= DSI_CONTROL_DCS_ENABLE;
549337b443dSThierry Reding 
550dec72739SThierry Reding 	value |= DSI_CONTROL_VIDEO_ENABLE;
551dec72739SThierry Reding 	value &= ~DSI_CONTROL_HOST_ENABLE;
552dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
553dec72739SThierry Reding 
554dec72739SThierry Reding 	for (i = 0; i < NUM_PKT_SEQ; i++)
555dec72739SThierry Reding 		tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);
556dec72739SThierry Reding 
557337b443dSThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
558dec72739SThierry Reding 		/* horizontal active pixels */
559dec72739SThierry Reding 		hact = mode->hdisplay * mul / div;
560dec72739SThierry Reding 
561dec72739SThierry Reding 		/* horizontal sync width */
562dec72739SThierry Reding 		hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
563dec72739SThierry Reding 
564dec72739SThierry Reding 		/* horizontal back porch */
565dec72739SThierry Reding 		hbp = (mode->htotal - mode->hsync_end) * mul / div;
566b8be0bdbSThierry Reding 
567b8be0bdbSThierry Reding 		if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0)
568b8be0bdbSThierry Reding 			hbp += hsw;
569dec72739SThierry Reding 
570dec72739SThierry Reding 		/* horizontal front porch */
571dec72739SThierry Reding 		hfp = (mode->hsync_start - mode->hdisplay) * mul / div;
572b8be0bdbSThierry Reding 
573b8be0bdbSThierry Reding 		/* subtract packet overhead */
574b8be0bdbSThierry Reding 		hsw -= 10;
575b8be0bdbSThierry Reding 		hbp -= 14;
576dec72739SThierry Reding 		hfp -= 8;
577dec72739SThierry Reding 
578dec72739SThierry Reding 		tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
579dec72739SThierry Reding 		tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3);
580dec72739SThierry Reding 		tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
581dec72739SThierry Reding 		tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
582dec72739SThierry Reding 
583563eff1fSThierry Reding 		/* set SOL delay (for non-burst mode only) */
584dec72739SThierry Reding 		tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
585e94236cdSThierry Reding 
586e94236cdSThierry Reding 		/* TODO: implement ganged mode */
587337b443dSThierry Reding 	} else {
588337b443dSThierry Reding 		u16 bytes;
589337b443dSThierry Reding 
590e94236cdSThierry Reding 		if (dsi->master || dsi->slave) {
591e94236cdSThierry Reding 			/*
592e94236cdSThierry Reding 			 * For ganged mode, assume symmetric left-right mode.
593e94236cdSThierry Reding 			 */
594e94236cdSThierry Reding 			bytes = 1 + (mode->hdisplay / 2) * mul / div;
595e94236cdSThierry Reding 		} else {
596337b443dSThierry Reding 			/* 1 byte (DCS command) + pixel data */
597337b443dSThierry Reding 			bytes = 1 + mode->hdisplay * mul / div;
598e94236cdSThierry Reding 		}
599337b443dSThierry Reding 
600337b443dSThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1);
601337b443dSThierry Reding 		tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_2_3);
602337b443dSThierry Reding 		tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_4_5);
603337b443dSThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_6_7);
604337b443dSThierry Reding 
605337b443dSThierry Reding 		value = MIPI_DCS_WRITE_MEMORY_START << 8 |
606337b443dSThierry Reding 			MIPI_DCS_WRITE_MEMORY_CONTINUE;
607337b443dSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_DCS_CMDS);
608337b443dSThierry Reding 
609e94236cdSThierry Reding 		/* set SOL delay */
610e94236cdSThierry Reding 		if (dsi->master || dsi->slave) {
611e94236cdSThierry Reding 			unsigned long delay, bclk, bclk_ganged;
612ebd14afeSThierry Reding 			unsigned int lanes = state->lanes;
613e94236cdSThierry Reding 
614e94236cdSThierry Reding 			/* SOL to valid, valid to FIFO and FIFO write delay */
615e94236cdSThierry Reding 			delay = 4 + 4 + 2;
616e94236cdSThierry Reding 			delay = DIV_ROUND_UP(delay * mul, div * lanes);
617e94236cdSThierry Reding 			/* FIFO read delay */
618e94236cdSThierry Reding 			delay = delay + 6;
619e94236cdSThierry Reding 
620e94236cdSThierry Reding 			bclk = DIV_ROUND_UP(mode->htotal * mul, div * lanes);
621e94236cdSThierry Reding 			bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes);
622e94236cdSThierry Reding 			value = bclk - bclk_ganged + delay + 20;
623e94236cdSThierry Reding 		} else {
624e94236cdSThierry Reding 			/* TODO: revisit for non-ganged mode */
625337b443dSThierry Reding 			value = 8 * mul / div;
626e94236cdSThierry Reding 		}
627337b443dSThierry Reding 
628337b443dSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_SOL_DELAY);
629337b443dSThierry Reding 	}
630dec72739SThierry Reding 
631e94236cdSThierry Reding 	if (dsi->slave) {
632ebd14afeSThierry Reding 		tegra_dsi_configure(dsi->slave, pipe, mode);
633e94236cdSThierry Reding 
634e94236cdSThierry Reding 		/*
635e94236cdSThierry Reding 		 * TODO: Support modes other than symmetrical left-right
636e94236cdSThierry Reding 		 * split.
637e94236cdSThierry Reding 		 */
638e94236cdSThierry Reding 		tegra_dsi_ganged_enable(dsi, 0, mode->hdisplay / 2);
639e94236cdSThierry Reding 		tegra_dsi_ganged_enable(dsi->slave, mode->hdisplay / 2,
640e94236cdSThierry Reding 					mode->hdisplay / 2);
641e94236cdSThierry Reding 	}
642563eff1fSThierry Reding }
643563eff1fSThierry Reding 
644563eff1fSThierry Reding static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout)
645563eff1fSThierry Reding {
646563eff1fSThierry Reding 	u32 value;
647563eff1fSThierry Reding 
648563eff1fSThierry Reding 	timeout = jiffies + msecs_to_jiffies(timeout);
649563eff1fSThierry Reding 
650563eff1fSThierry Reding 	while (time_before(jiffies, timeout)) {
651563eff1fSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_STATUS);
652563eff1fSThierry Reding 		if (value & DSI_STATUS_IDLE)
653563eff1fSThierry Reding 			return 0;
654563eff1fSThierry Reding 
655563eff1fSThierry Reding 		usleep_range(1000, 2000);
656563eff1fSThierry Reding 	}
657563eff1fSThierry Reding 
658563eff1fSThierry Reding 	return -ETIMEDOUT;
659563eff1fSThierry Reding }
660563eff1fSThierry Reding 
661563eff1fSThierry Reding static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
662563eff1fSThierry Reding {
663563eff1fSThierry Reding 	u32 value;
664563eff1fSThierry Reding 
665563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
666563eff1fSThierry Reding 	value &= ~DSI_CONTROL_VIDEO_ENABLE;
667563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
668e94236cdSThierry Reding 
669e94236cdSThierry Reding 	if (dsi->slave)
670e94236cdSThierry Reding 		tegra_dsi_video_disable(dsi->slave);
671e94236cdSThierry Reding }
672e94236cdSThierry Reding 
673e94236cdSThierry Reding static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
674e94236cdSThierry Reding {
675e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
676e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
677e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
678563eff1fSThierry Reding }
679563eff1fSThierry Reding 
6805b901e78SThierry Reding static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk,
6815b901e78SThierry Reding 				  unsigned int vrefresh)
6825b901e78SThierry Reding {
6835b901e78SThierry Reding 	unsigned int timeout;
6845b901e78SThierry Reding 	u32 value;
6855b901e78SThierry Reding 
6865b901e78SThierry Reding 	/* one frame high-speed transmission timeout */
6875b901e78SThierry Reding 	timeout = (bclk / vrefresh) / 512;
6885b901e78SThierry Reding 	value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
6895b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
6905b901e78SThierry Reding 
6915b901e78SThierry Reding 	/* 2 ms peripheral timeout for panel */
6925b901e78SThierry Reding 	timeout = 2 * bclk / 512 * 1000;
6935b901e78SThierry Reding 	value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
6945b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
6955b901e78SThierry Reding 
6965b901e78SThierry Reding 	value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
6975b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
6985b901e78SThierry Reding 
6995b901e78SThierry Reding 	if (dsi->slave)
7005b901e78SThierry Reding 		tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh);
7015b901e78SThierry Reding }
7025b901e78SThierry Reding 
703563eff1fSThierry Reding static void tegra_dsi_disable(struct tegra_dsi *dsi)
704563eff1fSThierry Reding {
705563eff1fSThierry Reding 	u32 value;
706563eff1fSThierry Reding 
707e94236cdSThierry Reding 	if (dsi->slave) {
708e94236cdSThierry Reding 		tegra_dsi_ganged_disable(dsi->slave);
709e94236cdSThierry Reding 		tegra_dsi_ganged_disable(dsi);
710e94236cdSThierry Reding 	}
711e94236cdSThierry Reding 
712563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
713563eff1fSThierry Reding 	value &= ~DSI_POWER_CONTROL_ENABLE;
714563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
715563eff1fSThierry Reding 
716e94236cdSThierry Reding 	if (dsi->slave)
717e94236cdSThierry Reding 		tegra_dsi_disable(dsi->slave);
718e94236cdSThierry Reding 
719563eff1fSThierry Reding 	usleep_range(5000, 10000);
720563eff1fSThierry Reding }
721563eff1fSThierry Reding 
72292f0e073SThierry Reding static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
72392f0e073SThierry Reding {
72492f0e073SThierry Reding 	u32 value;
72592f0e073SThierry Reding 
72692f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
72792f0e073SThierry Reding 	value &= ~DSI_POWER_CONTROL_ENABLE;
72892f0e073SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
72992f0e073SThierry Reding 
73092f0e073SThierry Reding 	usleep_range(300, 1000);
73192f0e073SThierry Reding 
73292f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
73392f0e073SThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
73492f0e073SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
73592f0e073SThierry Reding 
73692f0e073SThierry Reding 	usleep_range(300, 1000);
73792f0e073SThierry Reding 
73892f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_TRIGGER);
73992f0e073SThierry Reding 	if (value)
74092f0e073SThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_TRIGGER);
74192f0e073SThierry Reding 
74292f0e073SThierry Reding 	if (dsi->slave)
74392f0e073SThierry Reding 		tegra_dsi_soft_reset(dsi->slave);
74492f0e073SThierry Reding }
74592f0e073SThierry Reding 
746ebd14afeSThierry Reding static void tegra_dsi_connector_reset(struct drm_connector *connector)
747ebd14afeSThierry Reding {
748ebd14afeSThierry Reding 	struct tegra_dsi_state *state;
749ebd14afeSThierry Reding 
750ebd14afeSThierry Reding 	kfree(connector->state);
751ebd14afeSThierry Reding 	connector->state = NULL;
752ebd14afeSThierry Reding 
753ebd14afeSThierry Reding 	state = kzalloc(sizeof(*state), GFP_KERNEL);
754ebd14afeSThierry Reding 	if (state)
755ebd14afeSThierry Reding 		connector->state = &state->base;
756ebd14afeSThierry Reding }
757ebd14afeSThierry Reding 
758ebd14afeSThierry Reding static struct drm_connector_state *
759ebd14afeSThierry Reding tegra_dsi_connector_duplicate_state(struct drm_connector *connector)
760ebd14afeSThierry Reding {
761ebd14afeSThierry Reding 	struct tegra_dsi_state *state = to_dsi_state(connector->state);
762ebd14afeSThierry Reding 	struct tegra_dsi_state *copy;
763ebd14afeSThierry Reding 
764ebd14afeSThierry Reding 	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
765ebd14afeSThierry Reding 	if (!copy)
766ebd14afeSThierry Reding 		return NULL;
767ebd14afeSThierry Reding 
768ebd14afeSThierry Reding 	return &copy->base;
769ebd14afeSThierry Reding }
770ebd14afeSThierry Reding 
7715b901e78SThierry Reding static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
772*171e2e6dSThierry Reding 	.dpms = drm_atomic_helper_connector_dpms,
773ebd14afeSThierry Reding 	.reset = tegra_dsi_connector_reset,
7745b901e78SThierry Reding 	.detect = tegra_output_connector_detect,
7755b901e78SThierry Reding 	.fill_modes = drm_helper_probe_single_connector_modes,
7765b901e78SThierry Reding 	.destroy = tegra_output_connector_destroy,
777ebd14afeSThierry Reding 	.atomic_duplicate_state = tegra_dsi_connector_duplicate_state,
7784aa3df71SThierry Reding 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
7795b901e78SThierry Reding };
7805b901e78SThierry Reding 
7815b901e78SThierry Reding static enum drm_mode_status
7825b901e78SThierry Reding tegra_dsi_connector_mode_valid(struct drm_connector *connector,
7835b901e78SThierry Reding 			       struct drm_display_mode *mode)
7845b901e78SThierry Reding {
7855b901e78SThierry Reding 	return MODE_OK;
7865b901e78SThierry Reding }
7875b901e78SThierry Reding 
7885b901e78SThierry Reding static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = {
7895b901e78SThierry Reding 	.get_modes = tegra_output_connector_get_modes,
7905b901e78SThierry Reding 	.mode_valid = tegra_dsi_connector_mode_valid,
7915b901e78SThierry Reding 	.best_encoder = tegra_output_connector_best_encoder,
7925b901e78SThierry Reding };
7935b901e78SThierry Reding 
7945b901e78SThierry Reding static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
7955b901e78SThierry Reding 	.destroy = tegra_output_encoder_destroy,
7965b901e78SThierry Reding };
7975b901e78SThierry Reding 
7985b901e78SThierry Reding static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
7995b901e78SThierry Reding {
8005b901e78SThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
8015b901e78SThierry Reding 	struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
8025b901e78SThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
8035b901e78SThierry Reding 	u32 value;
8045b901e78SThierry Reding 	int err;
8055b901e78SThierry Reding 
8065b901e78SThierry Reding 	if (output->panel)
8075b901e78SThierry Reding 		drm_panel_disable(output->panel);
8085b901e78SThierry Reding 
8095b901e78SThierry Reding 	tegra_dsi_video_disable(dsi);
8105b901e78SThierry Reding 
8115b901e78SThierry Reding 	/*
8125b901e78SThierry Reding 	 * The following accesses registers of the display controller, so make
8135b901e78SThierry Reding 	 * sure it's only executed when the output is attached to one.
8145b901e78SThierry Reding 	 */
8155b901e78SThierry Reding 	if (dc) {
8165b901e78SThierry Reding 		value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
8175b901e78SThierry Reding 		value &= ~DSI_ENABLE;
8185b901e78SThierry Reding 		tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
8195b901e78SThierry Reding 
8205b901e78SThierry Reding 		tegra_dc_commit(dc);
8215b901e78SThierry Reding 	}
8225b901e78SThierry Reding 
8235b901e78SThierry Reding 	err = tegra_dsi_wait_idle(dsi, 100);
8245b901e78SThierry Reding 	if (err < 0)
8255b901e78SThierry Reding 		dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
8265b901e78SThierry Reding 
8275b901e78SThierry Reding 	tegra_dsi_soft_reset(dsi);
8285b901e78SThierry Reding 
8295b901e78SThierry Reding 	if (output->panel)
8305b901e78SThierry Reding 		drm_panel_unprepare(output->panel);
8315b901e78SThierry Reding 
8325b901e78SThierry Reding 	tegra_dsi_disable(dsi);
8335b901e78SThierry Reding 
8345b901e78SThierry Reding 	return;
8355b901e78SThierry Reding }
8365b901e78SThierry Reding 
837*171e2e6dSThierry Reding static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
838*171e2e6dSThierry Reding {
839*171e2e6dSThierry Reding 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
840*171e2e6dSThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
841*171e2e6dSThierry Reding 	struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
842*171e2e6dSThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
843*171e2e6dSThierry Reding 	struct tegra_dsi_state *state;
844*171e2e6dSThierry Reding 	u32 value;
845*171e2e6dSThierry Reding 
846*171e2e6dSThierry Reding 	state = tegra_dsi_get_state(dsi);
847*171e2e6dSThierry Reding 
848*171e2e6dSThierry Reding 	tegra_dsi_set_timeout(dsi, state->bclk, state->vrefresh);
849*171e2e6dSThierry Reding 
850*171e2e6dSThierry Reding 	/*
851*171e2e6dSThierry Reding 	 * The D-PHY timing fields are expressed in byte-clock cycles, so
852*171e2e6dSThierry Reding 	 * multiply the period by 8.
853*171e2e6dSThierry Reding 	 */
854*171e2e6dSThierry Reding 	tegra_dsi_set_phy_timing(dsi, state->period * 8, &state->timing);
855*171e2e6dSThierry Reding 
856*171e2e6dSThierry Reding 	if (output->panel)
857*171e2e6dSThierry Reding 		drm_panel_prepare(output->panel);
858*171e2e6dSThierry Reding 
859*171e2e6dSThierry Reding 	tegra_dsi_configure(dsi, dc->pipe, mode);
860*171e2e6dSThierry Reding 
861*171e2e6dSThierry Reding 	/* enable display controller */
862*171e2e6dSThierry Reding 	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
863*171e2e6dSThierry Reding 	value |= DSI_ENABLE;
864*171e2e6dSThierry Reding 	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
865*171e2e6dSThierry Reding 
866*171e2e6dSThierry Reding 	tegra_dc_commit(dc);
867*171e2e6dSThierry Reding 
868*171e2e6dSThierry Reding 	/* enable DSI controller */
869*171e2e6dSThierry Reding 	tegra_dsi_enable(dsi);
870*171e2e6dSThierry Reding 
871*171e2e6dSThierry Reding 	if (output->panel)
872*171e2e6dSThierry Reding 		drm_panel_enable(output->panel);
873*171e2e6dSThierry Reding 
874*171e2e6dSThierry Reding 	return;
875*171e2e6dSThierry Reding }
876*171e2e6dSThierry Reding 
877ebd14afeSThierry Reding static int
878ebd14afeSThierry Reding tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
879ebd14afeSThierry Reding 			       struct drm_crtc_state *crtc_state,
880ebd14afeSThierry Reding 			       struct drm_connector_state *conn_state)
881ebd14afeSThierry Reding {
882ebd14afeSThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
883ebd14afeSThierry Reding 	struct tegra_dsi_state *state = to_dsi_state(conn_state);
884ebd14afeSThierry Reding 	struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
885ebd14afeSThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
886ebd14afeSThierry Reding 	unsigned int scdiv;
887ebd14afeSThierry Reding 	unsigned long plld;
888ebd14afeSThierry Reding 	int err;
889ebd14afeSThierry Reding 
890ebd14afeSThierry Reding 	state->pclk = crtc_state->mode.clock * 1000;
891ebd14afeSThierry Reding 
892ebd14afeSThierry Reding 	err = tegra_dsi_get_muldiv(dsi->format, &state->mul, &state->div);
893ebd14afeSThierry Reding 	if (err < 0)
894ebd14afeSThierry Reding 		return err;
895ebd14afeSThierry Reding 
896ebd14afeSThierry Reding 	state->lanes = tegra_dsi_get_lanes(dsi);
897ebd14afeSThierry Reding 
898ebd14afeSThierry Reding 	err = tegra_dsi_get_format(dsi->format, &state->format);
899ebd14afeSThierry Reding 	if (err < 0)
900ebd14afeSThierry Reding 		return err;
901ebd14afeSThierry Reding 
902ebd14afeSThierry Reding 	state->vrefresh = drm_mode_vrefresh(&crtc_state->mode);
903ebd14afeSThierry Reding 
904ebd14afeSThierry Reding 	/* compute byte clock */
905ebd14afeSThierry Reding 	state->bclk = (state->pclk * state->mul) / (state->div * state->lanes);
906ebd14afeSThierry Reding 
907ebd14afeSThierry Reding 	DRM_DEBUG_KMS("mul: %u, div: %u, lanes: %u\n", state->mul, state->div,
908ebd14afeSThierry Reding 		      state->lanes);
909ebd14afeSThierry Reding 	DRM_DEBUG_KMS("format: %u, vrefresh: %u\n", state->format,
910ebd14afeSThierry Reding 		      state->vrefresh);
911ebd14afeSThierry Reding 	DRM_DEBUG_KMS("bclk: %lu\n", state->bclk);
912ebd14afeSThierry Reding 
913ebd14afeSThierry Reding 	/*
914ebd14afeSThierry Reding 	 * Compute bit clock and round up to the next MHz.
915ebd14afeSThierry Reding 	 */
916ebd14afeSThierry Reding 	plld = DIV_ROUND_UP(state->bclk * 8, USEC_PER_SEC) * USEC_PER_SEC;
917ebd14afeSThierry Reding 	state->period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, plld);
918ebd14afeSThierry Reding 
919ebd14afeSThierry Reding 	err = mipi_dphy_timing_get_default(&state->timing, state->period);
920ebd14afeSThierry Reding 	if (err < 0)
921ebd14afeSThierry Reding 		return err;
922ebd14afeSThierry Reding 
923ebd14afeSThierry Reding 	err = mipi_dphy_timing_validate(&state->timing, state->period);
924ebd14afeSThierry Reding 	if (err < 0) {
925ebd14afeSThierry Reding 		dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err);
926ebd14afeSThierry Reding 		return err;
927ebd14afeSThierry Reding 	}
928ebd14afeSThierry Reding 
929ebd14afeSThierry Reding 	/*
930ebd14afeSThierry Reding 	 * We divide the frequency by two here, but we make up for that by
931ebd14afeSThierry Reding 	 * setting the shift clock divider (further below) to half of the
932ebd14afeSThierry Reding 	 * correct value.
933ebd14afeSThierry Reding 	 */
934ebd14afeSThierry Reding 	plld /= 2;
935ebd14afeSThierry Reding 
936ebd14afeSThierry Reding 	/*
937ebd14afeSThierry Reding 	 * Derive pixel clock from bit clock using the shift clock divider.
938ebd14afeSThierry Reding 	 * Note that this is only half of what we would expect, but we need
939ebd14afeSThierry Reding 	 * that to make up for the fact that we divided the bit clock by a
940ebd14afeSThierry Reding 	 * factor of two above.
941ebd14afeSThierry Reding 	 *
942ebd14afeSThierry Reding 	 * It's not clear exactly why this is necessary, but the display is
943ebd14afeSThierry Reding 	 * not working properly otherwise. Perhaps the PLLs cannot generate
944ebd14afeSThierry Reding 	 * frequencies sufficiently high.
945ebd14afeSThierry Reding 	 */
946ebd14afeSThierry Reding 	scdiv = ((8 * state->mul) / (state->div * state->lanes)) - 2;
947ebd14afeSThierry Reding 
948ebd14afeSThierry Reding 	err = tegra_dc_state_setup_clock(dc, crtc_state, dsi->clk_parent,
949ebd14afeSThierry Reding 					 plld, scdiv);
950ebd14afeSThierry Reding 	if (err < 0) {
951ebd14afeSThierry Reding 		dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
952ebd14afeSThierry Reding 		return err;
953ebd14afeSThierry Reding 	}
954ebd14afeSThierry Reding 
955ebd14afeSThierry Reding 	return err;
956ebd14afeSThierry Reding }
957ebd14afeSThierry Reding 
9585b901e78SThierry Reding static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
9595b901e78SThierry Reding 	.disable = tegra_dsi_encoder_disable,
960*171e2e6dSThierry Reding 	.enable = tegra_dsi_encoder_enable,
961ebd14afeSThierry Reding 	.atomic_check = tegra_dsi_encoder_atomic_check,
962dec72739SThierry Reding };
963dec72739SThierry Reding 
964dec72739SThierry Reding static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
965dec72739SThierry Reding {
9669c0b4ca1SThierry Reding 	u32 value;
967dec72739SThierry Reding 
968dec72739SThierry Reding 	value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
969dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
970dec72739SThierry Reding 
971dec72739SThierry Reding 	return 0;
972dec72739SThierry Reding }
973dec72739SThierry Reding 
974dec72739SThierry Reding static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
975dec72739SThierry Reding {
976183ef288SThierry Reding 	u32 value;
977dec72739SThierry Reding 
978dec72739SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
979dec72739SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
980dec72739SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
981dec72739SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
982dec72739SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
983dec72739SThierry Reding 
984dec72739SThierry Reding 	/* start calibration */
985dec72739SThierry Reding 	tegra_dsi_pad_enable(dsi);
986dec72739SThierry Reding 
987dec72739SThierry Reding 	value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
988dec72739SThierry Reding 		DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
989dec72739SThierry Reding 		DSI_PAD_OUT_CLK(0x0);
990dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
991dec72739SThierry Reding 
992ddfb406bSThierry Reding 	value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
993ddfb406bSThierry Reding 		DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
994ddfb406bSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
995ddfb406bSThierry Reding 
996dec72739SThierry Reding 	return tegra_mipi_calibrate(dsi->mipi);
997dec72739SThierry Reding }
998dec72739SThierry Reding 
999dec72739SThierry Reding static int tegra_dsi_init(struct host1x_client *client)
1000dec72739SThierry Reding {
10019910f5c4SThierry Reding 	struct drm_device *drm = dev_get_drvdata(client->parent);
1002dec72739SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1003dec72739SThierry Reding 	int err;
1004dec72739SThierry Reding 
1005201106d8SThierry Reding 	reset_control_deassert(dsi->rst);
1006201106d8SThierry Reding 
1007201106d8SThierry Reding 	err = tegra_dsi_pad_calibrate(dsi);
1008201106d8SThierry Reding 	if (err < 0) {
1009201106d8SThierry Reding 		dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
1010201106d8SThierry Reding 		goto reset;
1011201106d8SThierry Reding 	}
1012201106d8SThierry Reding 
1013e94236cdSThierry Reding 	/* Gangsters must not register their own outputs. */
1014e94236cdSThierry Reding 	if (!dsi->master) {
1015dec72739SThierry Reding 		dsi->output.dev = client->dev;
1016dec72739SThierry Reding 
10175b901e78SThierry Reding 		drm_connector_init(drm, &dsi->output.connector,
10185b901e78SThierry Reding 				   &tegra_dsi_connector_funcs,
10195b901e78SThierry Reding 				   DRM_MODE_CONNECTOR_DSI);
10205b901e78SThierry Reding 		drm_connector_helper_add(&dsi->output.connector,
10215b901e78SThierry Reding 					 &tegra_dsi_connector_helper_funcs);
10225b901e78SThierry Reding 		dsi->output.connector.dpms = DRM_MODE_DPMS_OFF;
10235b901e78SThierry Reding 
10245b901e78SThierry Reding 		drm_encoder_init(drm, &dsi->output.encoder,
10255b901e78SThierry Reding 				 &tegra_dsi_encoder_funcs,
10265b901e78SThierry Reding 				 DRM_MODE_ENCODER_DSI);
10275b901e78SThierry Reding 		drm_encoder_helper_add(&dsi->output.encoder,
10285b901e78SThierry Reding 				       &tegra_dsi_encoder_helper_funcs);
10295b901e78SThierry Reding 
10305b901e78SThierry Reding 		drm_mode_connector_attach_encoder(&dsi->output.connector,
10315b901e78SThierry Reding 						  &dsi->output.encoder);
10325b901e78SThierry Reding 		drm_connector_register(&dsi->output.connector);
10335b901e78SThierry Reding 
1034ea130b24SThierry Reding 		err = tegra_output_init(drm, &dsi->output);
1035ea130b24SThierry Reding 		if (err < 0) {
1036ea130b24SThierry Reding 			dev_err(client->dev,
1037ea130b24SThierry Reding 				"failed to initialize output: %d\n",
1038ea130b24SThierry Reding 				err);
1039ea130b24SThierry Reding 			goto reset;
1040ea130b24SThierry Reding 		}
1041ea130b24SThierry Reding 
10425b901e78SThierry Reding 		dsi->output.encoder.possible_crtcs = 0x3;
1043e94236cdSThierry Reding 	}
1044dec72739SThierry Reding 
1045dec72739SThierry Reding 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
10469910f5c4SThierry Reding 		err = tegra_dsi_debugfs_init(dsi, drm->primary);
1047dec72739SThierry Reding 		if (err < 0)
1048dec72739SThierry Reding 			dev_err(dsi->dev, "debugfs setup failed: %d\n", err);
1049dec72739SThierry Reding 	}
1050dec72739SThierry Reding 
1051dec72739SThierry Reding 	return 0;
1052201106d8SThierry Reding 
1053201106d8SThierry Reding reset:
1054201106d8SThierry Reding 	reset_control_assert(dsi->rst);
1055201106d8SThierry Reding 	return err;
1056dec72739SThierry Reding }
1057dec72739SThierry Reding 
1058dec72739SThierry Reding static int tegra_dsi_exit(struct host1x_client *client)
1059dec72739SThierry Reding {
1060dec72739SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1061dec72739SThierry Reding 
10625b901e78SThierry Reding 	tegra_output_exit(&dsi->output);
10635b901e78SThierry Reding 
10644009c224SThierry Reding 	if (IS_ENABLED(CONFIG_DEBUG_FS))
10654009c224SThierry Reding 		tegra_dsi_debugfs_exit(dsi);
1066dec72739SThierry Reding 
1067201106d8SThierry Reding 	reset_control_assert(dsi->rst);
1068201106d8SThierry Reding 
1069dec72739SThierry Reding 	return 0;
1070dec72739SThierry Reding }
1071dec72739SThierry Reding 
1072dec72739SThierry Reding static const struct host1x_client_ops dsi_client_ops = {
1073dec72739SThierry Reding 	.init = tegra_dsi_init,
1074dec72739SThierry Reding 	.exit = tegra_dsi_exit,
1075dec72739SThierry Reding };
1076dec72739SThierry Reding 
1077dec72739SThierry Reding static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
1078dec72739SThierry Reding {
1079dec72739SThierry Reding 	struct clk *parent;
1080dec72739SThierry Reding 	int err;
1081dec72739SThierry Reding 
1082dec72739SThierry Reding 	parent = clk_get_parent(dsi->clk);
1083dec72739SThierry Reding 	if (!parent)
1084dec72739SThierry Reding 		return -EINVAL;
1085dec72739SThierry Reding 
1086dec72739SThierry Reding 	err = clk_set_parent(parent, dsi->clk_parent);
1087dec72739SThierry Reding 	if (err < 0)
1088dec72739SThierry Reding 		return err;
1089dec72739SThierry Reding 
1090dec72739SThierry Reding 	return 0;
1091dec72739SThierry Reding }
1092dec72739SThierry Reding 
10930fffdf6cSThierry Reding static const char * const error_report[16] = {
10940fffdf6cSThierry Reding 	"SoT Error",
10950fffdf6cSThierry Reding 	"SoT Sync Error",
10960fffdf6cSThierry Reding 	"EoT Sync Error",
10970fffdf6cSThierry Reding 	"Escape Mode Entry Command Error",
10980fffdf6cSThierry Reding 	"Low-Power Transmit Sync Error",
10990fffdf6cSThierry Reding 	"Peripheral Timeout Error",
11000fffdf6cSThierry Reding 	"False Control Error",
11010fffdf6cSThierry Reding 	"Contention Detected",
11020fffdf6cSThierry Reding 	"ECC Error, single-bit",
11030fffdf6cSThierry Reding 	"ECC Error, multi-bit",
11040fffdf6cSThierry Reding 	"Checksum Error",
11050fffdf6cSThierry Reding 	"DSI Data Type Not Recognized",
11060fffdf6cSThierry Reding 	"DSI VC ID Invalid",
11070fffdf6cSThierry Reding 	"Invalid Transmission Length",
11080fffdf6cSThierry Reding 	"Reserved",
11090fffdf6cSThierry Reding 	"DSI Protocol Violation",
11100fffdf6cSThierry Reding };
11110fffdf6cSThierry Reding 
11120fffdf6cSThierry Reding static ssize_t tegra_dsi_read_response(struct tegra_dsi *dsi,
11130fffdf6cSThierry Reding 				       const struct mipi_dsi_msg *msg,
11140fffdf6cSThierry Reding 				       size_t count)
11150fffdf6cSThierry Reding {
11160fffdf6cSThierry Reding 	u8 *rx = msg->rx_buf;
11170fffdf6cSThierry Reding 	unsigned int i, j, k;
11180fffdf6cSThierry Reding 	size_t size = 0;
11190fffdf6cSThierry Reding 	u16 errors;
11200fffdf6cSThierry Reding 	u32 value;
11210fffdf6cSThierry Reding 
11220fffdf6cSThierry Reding 	/* read and parse packet header */
11230fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_RD_DATA);
11240fffdf6cSThierry Reding 
11250fffdf6cSThierry Reding 	switch (value & 0x3f) {
11260fffdf6cSThierry Reding 	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
11270fffdf6cSThierry Reding 		errors = (value >> 8) & 0xffff;
11280fffdf6cSThierry Reding 		dev_dbg(dsi->dev, "Acknowledge and error report: %04x\n",
11290fffdf6cSThierry Reding 			errors);
11300fffdf6cSThierry Reding 		for (i = 0; i < ARRAY_SIZE(error_report); i++)
11310fffdf6cSThierry Reding 			if (errors & BIT(i))
11320fffdf6cSThierry Reding 				dev_dbg(dsi->dev, "  %2u: %s\n", i,
11330fffdf6cSThierry Reding 					error_report[i]);
11340fffdf6cSThierry Reding 		break;
11350fffdf6cSThierry Reding 
11360fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
11370fffdf6cSThierry Reding 		rx[0] = (value >> 8) & 0xff;
11380fffdf6cSThierry Reding 		size = 1;
11390fffdf6cSThierry Reding 		break;
11400fffdf6cSThierry Reding 
11410fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
11420fffdf6cSThierry Reding 		rx[0] = (value >>  8) & 0xff;
11430fffdf6cSThierry Reding 		rx[1] = (value >> 16) & 0xff;
11440fffdf6cSThierry Reding 		size = 2;
11450fffdf6cSThierry Reding 		break;
11460fffdf6cSThierry Reding 
11470fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
11480fffdf6cSThierry Reding 		size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
11490fffdf6cSThierry Reding 		break;
11500fffdf6cSThierry Reding 
11510fffdf6cSThierry Reding 	case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
11520fffdf6cSThierry Reding 		size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
11530fffdf6cSThierry Reding 		break;
11540fffdf6cSThierry Reding 
11550fffdf6cSThierry Reding 	default:
11560fffdf6cSThierry Reding 		dev_err(dsi->dev, "unhandled response type: %02x\n",
11570fffdf6cSThierry Reding 			value & 0x3f);
11580fffdf6cSThierry Reding 		return -EPROTO;
11590fffdf6cSThierry Reding 	}
11600fffdf6cSThierry Reding 
11610fffdf6cSThierry Reding 	size = min(size, msg->rx_len);
11620fffdf6cSThierry Reding 
11630fffdf6cSThierry Reding 	if (msg->rx_buf && size > 0) {
11640fffdf6cSThierry Reding 		for (i = 0, j = 0; i < count - 1; i++, j += 4) {
11650fffdf6cSThierry Reding 			u8 *rx = msg->rx_buf + j;
11660fffdf6cSThierry Reding 
11670fffdf6cSThierry Reding 			value = tegra_dsi_readl(dsi, DSI_RD_DATA);
11680fffdf6cSThierry Reding 
11690fffdf6cSThierry Reding 			for (k = 0; k < 4 && (j + k) < msg->rx_len; k++)
11700fffdf6cSThierry Reding 				rx[j + k] = (value >> (k << 3)) & 0xff;
11710fffdf6cSThierry Reding 		}
11720fffdf6cSThierry Reding 	}
11730fffdf6cSThierry Reding 
11740fffdf6cSThierry Reding 	return size;
11750fffdf6cSThierry Reding }
11760fffdf6cSThierry Reding 
11770fffdf6cSThierry Reding static int tegra_dsi_transmit(struct tegra_dsi *dsi, unsigned long timeout)
11780fffdf6cSThierry Reding {
11790fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, DSI_TRIGGER_HOST, DSI_TRIGGER);
11800fffdf6cSThierry Reding 
11810fffdf6cSThierry Reding 	timeout = jiffies + msecs_to_jiffies(timeout);
11820fffdf6cSThierry Reding 
11830fffdf6cSThierry Reding 	while (time_before(jiffies, timeout)) {
11840fffdf6cSThierry Reding 		u32 value = tegra_dsi_readl(dsi, DSI_TRIGGER);
11850fffdf6cSThierry Reding 		if ((value & DSI_TRIGGER_HOST) == 0)
11860fffdf6cSThierry Reding 			return 0;
11870fffdf6cSThierry Reding 
11880fffdf6cSThierry Reding 		usleep_range(1000, 2000);
11890fffdf6cSThierry Reding 	}
11900fffdf6cSThierry Reding 
11910fffdf6cSThierry Reding 	DRM_DEBUG_KMS("timeout waiting for transmission to complete\n");
11920fffdf6cSThierry Reding 	return -ETIMEDOUT;
11930fffdf6cSThierry Reding }
11940fffdf6cSThierry Reding 
11950fffdf6cSThierry Reding static int tegra_dsi_wait_for_response(struct tegra_dsi *dsi,
11960fffdf6cSThierry Reding 				       unsigned long timeout)
11970fffdf6cSThierry Reding {
11980fffdf6cSThierry Reding 	timeout = jiffies + msecs_to_jiffies(250);
11990fffdf6cSThierry Reding 
12000fffdf6cSThierry Reding 	while (time_before(jiffies, timeout)) {
12010fffdf6cSThierry Reding 		u32 value = tegra_dsi_readl(dsi, DSI_STATUS);
12020fffdf6cSThierry Reding 		u8 count = value & 0x1f;
12030fffdf6cSThierry Reding 
12040fffdf6cSThierry Reding 		if (count > 0)
12050fffdf6cSThierry Reding 			return count;
12060fffdf6cSThierry Reding 
12070fffdf6cSThierry Reding 		usleep_range(1000, 2000);
12080fffdf6cSThierry Reding 	}
12090fffdf6cSThierry Reding 
12100fffdf6cSThierry Reding 	DRM_DEBUG_KMS("peripheral returned no data\n");
12110fffdf6cSThierry Reding 	return -ETIMEDOUT;
12120fffdf6cSThierry Reding }
12130fffdf6cSThierry Reding 
12140fffdf6cSThierry Reding static void tegra_dsi_writesl(struct tegra_dsi *dsi, unsigned long offset,
12150fffdf6cSThierry Reding 			      const void *buffer, size_t size)
12160fffdf6cSThierry Reding {
12170fffdf6cSThierry Reding 	const u8 *buf = buffer;
12180fffdf6cSThierry Reding 	size_t i, j;
12190fffdf6cSThierry Reding 	u32 value;
12200fffdf6cSThierry Reding 
12210fffdf6cSThierry Reding 	for (j = 0; j < size; j += 4) {
12220fffdf6cSThierry Reding 		value = 0;
12230fffdf6cSThierry Reding 
12240fffdf6cSThierry Reding 		for (i = 0; i < 4 && j + i < size; i++)
12250fffdf6cSThierry Reding 			value |= buf[j + i] << (i << 3);
12260fffdf6cSThierry Reding 
12270fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_WR_DATA);
12280fffdf6cSThierry Reding 	}
12290fffdf6cSThierry Reding }
12300fffdf6cSThierry Reding 
12310fffdf6cSThierry Reding static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
12320fffdf6cSThierry Reding 				       const struct mipi_dsi_msg *msg)
12330fffdf6cSThierry Reding {
12340fffdf6cSThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
12350fffdf6cSThierry Reding 	struct mipi_dsi_packet packet;
12360fffdf6cSThierry Reding 	const u8 *header;
12370fffdf6cSThierry Reding 	size_t count;
12380fffdf6cSThierry Reding 	ssize_t err;
12390fffdf6cSThierry Reding 	u32 value;
12400fffdf6cSThierry Reding 
12410fffdf6cSThierry Reding 	err = mipi_dsi_create_packet(&packet, msg);
12420fffdf6cSThierry Reding 	if (err < 0)
12430fffdf6cSThierry Reding 		return err;
12440fffdf6cSThierry Reding 
12450fffdf6cSThierry Reding 	header = packet.header;
12460fffdf6cSThierry Reding 
12470fffdf6cSThierry Reding 	/* maximum FIFO depth is 1920 words */
12480fffdf6cSThierry Reding 	if (packet.size > dsi->video_fifo_depth * 4)
12490fffdf6cSThierry Reding 		return -ENOSPC;
12500fffdf6cSThierry Reding 
12510fffdf6cSThierry Reding 	/* reset underflow/overflow flags */
12520fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_STATUS);
12530fffdf6cSThierry Reding 	if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) {
12540fffdf6cSThierry Reding 		value = DSI_HOST_CONTROL_FIFO_RESET;
12550fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
12560fffdf6cSThierry Reding 		usleep_range(10, 20);
12570fffdf6cSThierry Reding 	}
12580fffdf6cSThierry Reding 
12590fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
12600fffdf6cSThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
12610fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
12620fffdf6cSThierry Reding 
12630fffdf6cSThierry Reding 	usleep_range(5000, 10000);
12640fffdf6cSThierry Reding 
12650fffdf6cSThierry Reding 	value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST |
12660fffdf6cSThierry Reding 		DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
12670fffdf6cSThierry Reding 
12680fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0)
12690fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_HS;
12700fffdf6cSThierry Reding 
12710fffdf6cSThierry Reding 	/*
12720fffdf6cSThierry Reding 	 * The host FIFO has a maximum of 64 words, so larger transmissions
12730fffdf6cSThierry Reding 	 * need to use the video FIFO.
12740fffdf6cSThierry Reding 	 */
12750fffdf6cSThierry Reding 	if (packet.size > dsi->host_fifo_depth * 4)
12760fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_FIFO_SEL;
12770fffdf6cSThierry Reding 
12780fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
12790fffdf6cSThierry Reding 
12800fffdf6cSThierry Reding 	/*
12810fffdf6cSThierry Reding 	 * For reads and messages with explicitly requested ACK, generate a
12820fffdf6cSThierry Reding 	 * BTA sequence after the transmission of the packet.
12830fffdf6cSThierry Reding 	 */
12840fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
12850fffdf6cSThierry Reding 	    (msg->rx_buf && msg->rx_len > 0)) {
12860fffdf6cSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
12870fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_PKT_BTA;
12880fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
12890fffdf6cSThierry Reding 	}
12900fffdf6cSThierry Reding 
12910fffdf6cSThierry Reding 	value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE;
12920fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
12930fffdf6cSThierry Reding 
12940fffdf6cSThierry Reding 	/* write packet header, ECC is generated by hardware */
12950fffdf6cSThierry Reding 	value = header[2] << 16 | header[1] << 8 | header[0];
12960fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_WR_DATA);
12970fffdf6cSThierry Reding 
12980fffdf6cSThierry Reding 	/* write payload (if any) */
12990fffdf6cSThierry Reding 	if (packet.payload_length > 0)
13000fffdf6cSThierry Reding 		tegra_dsi_writesl(dsi, DSI_WR_DATA, packet.payload,
13010fffdf6cSThierry Reding 				  packet.payload_length);
13020fffdf6cSThierry Reding 
13030fffdf6cSThierry Reding 	err = tegra_dsi_transmit(dsi, 250);
13040fffdf6cSThierry Reding 	if (err < 0)
13050fffdf6cSThierry Reding 		return err;
13060fffdf6cSThierry Reding 
13070fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
13080fffdf6cSThierry Reding 	    (msg->rx_buf && msg->rx_len > 0)) {
13090fffdf6cSThierry Reding 		err = tegra_dsi_wait_for_response(dsi, 250);
13100fffdf6cSThierry Reding 		if (err < 0)
13110fffdf6cSThierry Reding 			return err;
13120fffdf6cSThierry Reding 
13130fffdf6cSThierry Reding 		count = err;
13140fffdf6cSThierry Reding 
13150fffdf6cSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_RD_DATA);
13160fffdf6cSThierry Reding 		switch (value) {
13170fffdf6cSThierry Reding 		case 0x84:
13180fffdf6cSThierry Reding 			/*
13190fffdf6cSThierry Reding 			dev_dbg(dsi->dev, "ACK\n");
13200fffdf6cSThierry Reding 			*/
13210fffdf6cSThierry Reding 			break;
13220fffdf6cSThierry Reding 
13230fffdf6cSThierry Reding 		case 0x87:
13240fffdf6cSThierry Reding 			/*
13250fffdf6cSThierry Reding 			dev_dbg(dsi->dev, "ESCAPE\n");
13260fffdf6cSThierry Reding 			*/
13270fffdf6cSThierry Reding 			break;
13280fffdf6cSThierry Reding 
13290fffdf6cSThierry Reding 		default:
13300fffdf6cSThierry Reding 			dev_err(dsi->dev, "unknown status: %08x\n", value);
13310fffdf6cSThierry Reding 			break;
13320fffdf6cSThierry Reding 		}
13330fffdf6cSThierry Reding 
13340fffdf6cSThierry Reding 		if (count > 1) {
13350fffdf6cSThierry Reding 			err = tegra_dsi_read_response(dsi, msg, count);
13360fffdf6cSThierry Reding 			if (err < 0)
13370fffdf6cSThierry Reding 				dev_err(dsi->dev,
13380fffdf6cSThierry Reding 					"failed to parse response: %zd\n",
13390fffdf6cSThierry Reding 					err);
13400fffdf6cSThierry Reding 			else {
13410fffdf6cSThierry Reding 				/*
13420fffdf6cSThierry Reding 				 * For read commands, return the number of
13430fffdf6cSThierry Reding 				 * bytes returned by the peripheral.
13440fffdf6cSThierry Reding 				 */
13450fffdf6cSThierry Reding 				count = err;
13460fffdf6cSThierry Reding 			}
13470fffdf6cSThierry Reding 		}
13480fffdf6cSThierry Reding 	} else {
13490fffdf6cSThierry Reding 		/*
13500fffdf6cSThierry Reding 		 * For write commands, we have transmitted the 4-byte header
13510fffdf6cSThierry Reding 		 * plus the variable-length payload.
13520fffdf6cSThierry Reding 		 */
13530fffdf6cSThierry Reding 		count = 4 + packet.payload_length;
13540fffdf6cSThierry Reding 	}
13550fffdf6cSThierry Reding 
13560fffdf6cSThierry Reding 	return count;
13570fffdf6cSThierry Reding }
13580fffdf6cSThierry Reding 
1359e94236cdSThierry Reding static int tegra_dsi_ganged_setup(struct tegra_dsi *dsi)
1360e94236cdSThierry Reding {
1361e94236cdSThierry Reding 	struct clk *parent;
1362e94236cdSThierry Reding 	int err;
1363e94236cdSThierry Reding 
1364e94236cdSThierry Reding 	/* make sure both DSI controllers share the same PLL */
1365e94236cdSThierry Reding 	parent = clk_get_parent(dsi->slave->clk);
1366e94236cdSThierry Reding 	if (!parent)
1367e94236cdSThierry Reding 		return -EINVAL;
1368e94236cdSThierry Reding 
1369e94236cdSThierry Reding 	err = clk_set_parent(parent, dsi->clk_parent);
1370e94236cdSThierry Reding 	if (err < 0)
1371e94236cdSThierry Reding 		return err;
1372e94236cdSThierry Reding 
1373e94236cdSThierry Reding 	return 0;
1374e94236cdSThierry Reding }
1375e94236cdSThierry Reding 
1376dec72739SThierry Reding static int tegra_dsi_host_attach(struct mipi_dsi_host *host,
1377dec72739SThierry Reding 				 struct mipi_dsi_device *device)
1378dec72739SThierry Reding {
1379dec72739SThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
1380dec72739SThierry Reding 
138117297a28SThierry Reding 	dsi->flags = device->mode_flags;
1382dec72739SThierry Reding 	dsi->format = device->format;
1383dec72739SThierry Reding 	dsi->lanes = device->lanes;
1384dec72739SThierry Reding 
1385e94236cdSThierry Reding 	if (dsi->slave) {
1386e94236cdSThierry Reding 		int err;
1387e94236cdSThierry Reding 
1388e94236cdSThierry Reding 		dev_dbg(dsi->dev, "attaching dual-channel device %s\n",
1389e94236cdSThierry Reding 			dev_name(&device->dev));
1390e94236cdSThierry Reding 
1391e94236cdSThierry Reding 		err = tegra_dsi_ganged_setup(dsi);
1392e94236cdSThierry Reding 		if (err < 0) {
1393e94236cdSThierry Reding 			dev_err(dsi->dev, "failed to set up ganged mode: %d\n",
1394e94236cdSThierry Reding 				err);
1395e94236cdSThierry Reding 			return err;
1396e94236cdSThierry Reding 		}
1397e94236cdSThierry Reding 	}
1398e94236cdSThierry Reding 
1399e94236cdSThierry Reding 	/*
1400e94236cdSThierry Reding 	 * Slaves don't have a panel associated with them, so they provide
1401e94236cdSThierry Reding 	 * merely the second channel.
1402e94236cdSThierry Reding 	 */
1403e94236cdSThierry Reding 	if (!dsi->master) {
1404e94236cdSThierry Reding 		struct tegra_output *output = &dsi->output;
1405e94236cdSThierry Reding 
1406dec72739SThierry Reding 		output->panel = of_drm_find_panel(device->dev.of_node);
1407e94236cdSThierry Reding 		if (output->panel && output->connector.dev) {
1408e94236cdSThierry Reding 			drm_panel_attach(output->panel, &output->connector);
1409dec72739SThierry Reding 			drm_helper_hpd_irq_event(output->connector.dev);
1410dec72739SThierry Reding 		}
1411e94236cdSThierry Reding 	}
1412dec72739SThierry Reding 
1413dec72739SThierry Reding 	return 0;
1414dec72739SThierry Reding }
1415dec72739SThierry Reding 
1416dec72739SThierry Reding static int tegra_dsi_host_detach(struct mipi_dsi_host *host,
1417dec72739SThierry Reding 				 struct mipi_dsi_device *device)
1418dec72739SThierry Reding {
1419dec72739SThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
1420dec72739SThierry Reding 	struct tegra_output *output = &dsi->output;
1421dec72739SThierry Reding 
1422dec72739SThierry Reding 	if (output->panel && &device->dev == output->panel->dev) {
1423ba3df979SThierry Reding 		output->panel = NULL;
1424ba3df979SThierry Reding 
1425dec72739SThierry Reding 		if (output->connector.dev)
1426dec72739SThierry Reding 			drm_helper_hpd_irq_event(output->connector.dev);
1427dec72739SThierry Reding 	}
1428dec72739SThierry Reding 
1429dec72739SThierry Reding 	return 0;
1430dec72739SThierry Reding }
1431dec72739SThierry Reding 
1432dec72739SThierry Reding static const struct mipi_dsi_host_ops tegra_dsi_host_ops = {
1433dec72739SThierry Reding 	.attach = tegra_dsi_host_attach,
1434dec72739SThierry Reding 	.detach = tegra_dsi_host_detach,
14350fffdf6cSThierry Reding 	.transfer = tegra_dsi_host_transfer,
1436dec72739SThierry Reding };
1437dec72739SThierry Reding 
1438e94236cdSThierry Reding static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
1439e94236cdSThierry Reding {
1440e94236cdSThierry Reding 	struct device_node *np;
1441e94236cdSThierry Reding 
1442e94236cdSThierry Reding 	np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0);
1443e94236cdSThierry Reding 	if (np) {
1444e94236cdSThierry Reding 		struct platform_device *gangster = of_find_device_by_node(np);
1445e94236cdSThierry Reding 
1446e94236cdSThierry Reding 		dsi->slave = platform_get_drvdata(gangster);
1447e94236cdSThierry Reding 		of_node_put(np);
1448e94236cdSThierry Reding 
1449e94236cdSThierry Reding 		if (!dsi->slave)
1450e94236cdSThierry Reding 			return -EPROBE_DEFER;
1451e94236cdSThierry Reding 
1452e94236cdSThierry Reding 		dsi->slave->master = dsi;
1453e94236cdSThierry Reding 	}
1454e94236cdSThierry Reding 
1455e94236cdSThierry Reding 	return 0;
1456e94236cdSThierry Reding }
1457e94236cdSThierry Reding 
1458dec72739SThierry Reding static int tegra_dsi_probe(struct platform_device *pdev)
1459dec72739SThierry Reding {
1460dec72739SThierry Reding 	struct tegra_dsi *dsi;
1461dec72739SThierry Reding 	struct resource *regs;
1462dec72739SThierry Reding 	int err;
1463dec72739SThierry Reding 
1464dec72739SThierry Reding 	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
1465dec72739SThierry Reding 	if (!dsi)
1466dec72739SThierry Reding 		return -ENOMEM;
1467dec72739SThierry Reding 
1468dec72739SThierry Reding 	dsi->output.dev = dsi->dev = &pdev->dev;
1469976cebc3SThierry Reding 	dsi->video_fifo_depth = 1920;
1470976cebc3SThierry Reding 	dsi->host_fifo_depth = 64;
1471dec72739SThierry Reding 
1472e94236cdSThierry Reding 	err = tegra_dsi_ganged_probe(dsi);
1473e94236cdSThierry Reding 	if (err < 0)
1474e94236cdSThierry Reding 		return err;
1475e94236cdSThierry Reding 
1476dec72739SThierry Reding 	err = tegra_output_probe(&dsi->output);
1477dec72739SThierry Reding 	if (err < 0)
1478dec72739SThierry Reding 		return err;
1479dec72739SThierry Reding 
1480ba3df979SThierry Reding 	dsi->output.connector.polled = DRM_CONNECTOR_POLL_HPD;
1481ba3df979SThierry Reding 
1482dec72739SThierry Reding 	/*
1483dec72739SThierry Reding 	 * Assume these values by default. When a DSI peripheral driver
1484dec72739SThierry Reding 	 * attaches to the DSI host, the parameters will be taken from
1485dec72739SThierry Reding 	 * the attached device.
1486dec72739SThierry Reding 	 */
148717297a28SThierry Reding 	dsi->flags = MIPI_DSI_MODE_VIDEO;
1488dec72739SThierry Reding 	dsi->format = MIPI_DSI_FMT_RGB888;
1489dec72739SThierry Reding 	dsi->lanes = 4;
1490dec72739SThierry Reding 
1491dec72739SThierry Reding 	dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
1492dec72739SThierry Reding 	if (IS_ERR(dsi->rst))
1493dec72739SThierry Reding 		return PTR_ERR(dsi->rst);
1494dec72739SThierry Reding 
1495dec72739SThierry Reding 	dsi->clk = devm_clk_get(&pdev->dev, NULL);
1496dec72739SThierry Reding 	if (IS_ERR(dsi->clk)) {
1497dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get DSI clock\n");
1498d2d0a9d2SThierry Reding 		err = PTR_ERR(dsi->clk);
1499d2d0a9d2SThierry Reding 		goto reset;
1500dec72739SThierry Reding 	}
1501dec72739SThierry Reding 
1502dec72739SThierry Reding 	err = clk_prepare_enable(dsi->clk);
1503dec72739SThierry Reding 	if (err < 0) {
1504dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot enable DSI clock\n");
1505d2d0a9d2SThierry Reding 		goto reset;
1506dec72739SThierry Reding 	}
1507dec72739SThierry Reding 
1508dec72739SThierry Reding 	dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
1509dec72739SThierry Reding 	if (IS_ERR(dsi->clk_lp)) {
1510dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get low-power clock\n");
1511d2d0a9d2SThierry Reding 		err = PTR_ERR(dsi->clk_lp);
1512d2d0a9d2SThierry Reding 		goto disable_clk;
1513dec72739SThierry Reding 	}
1514dec72739SThierry Reding 
1515dec72739SThierry Reding 	err = clk_prepare_enable(dsi->clk_lp);
1516dec72739SThierry Reding 	if (err < 0) {
1517dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot enable low-power clock\n");
1518d2d0a9d2SThierry Reding 		goto disable_clk;
1519dec72739SThierry Reding 	}
1520dec72739SThierry Reding 
1521dec72739SThierry Reding 	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1522dec72739SThierry Reding 	if (IS_ERR(dsi->clk_parent)) {
1523dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get parent clock\n");
1524d2d0a9d2SThierry Reding 		err = PTR_ERR(dsi->clk_parent);
1525d2d0a9d2SThierry Reding 		goto disable_clk_lp;
1526dec72739SThierry Reding 	}
1527dec72739SThierry Reding 
15283b077afbSThierry Reding 	dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
15293b077afbSThierry Reding 	if (IS_ERR(dsi->vdd)) {
15303b077afbSThierry Reding 		dev_err(&pdev->dev, "cannot get VDD supply\n");
1531d2d0a9d2SThierry Reding 		err = PTR_ERR(dsi->vdd);
1532d2d0a9d2SThierry Reding 		goto disable_clk_lp;
15333b077afbSThierry Reding 	}
15343b077afbSThierry Reding 
15353b077afbSThierry Reding 	err = regulator_enable(dsi->vdd);
15363b077afbSThierry Reding 	if (err < 0) {
15373b077afbSThierry Reding 		dev_err(&pdev->dev, "cannot enable VDD supply\n");
1538d2d0a9d2SThierry Reding 		goto disable_clk_lp;
15393b077afbSThierry Reding 	}
15403b077afbSThierry Reding 
1541dec72739SThierry Reding 	err = tegra_dsi_setup_clocks(dsi);
1542dec72739SThierry Reding 	if (err < 0) {
1543dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot setup clocks\n");
1544d2d0a9d2SThierry Reding 		goto disable_vdd;
1545dec72739SThierry Reding 	}
1546dec72739SThierry Reding 
1547dec72739SThierry Reding 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1548dec72739SThierry Reding 	dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
1549d2d0a9d2SThierry Reding 	if (IS_ERR(dsi->regs)) {
1550d2d0a9d2SThierry Reding 		err = PTR_ERR(dsi->regs);
1551d2d0a9d2SThierry Reding 		goto disable_vdd;
1552d2d0a9d2SThierry Reding 	}
1553dec72739SThierry Reding 
1554dec72739SThierry Reding 	dsi->mipi = tegra_mipi_request(&pdev->dev);
1555d2d0a9d2SThierry Reding 	if (IS_ERR(dsi->mipi)) {
1556d2d0a9d2SThierry Reding 		err = PTR_ERR(dsi->mipi);
1557d2d0a9d2SThierry Reding 		goto disable_vdd;
1558d2d0a9d2SThierry Reding 	}
1559dec72739SThierry Reding 
1560dec72739SThierry Reding 	dsi->host.ops = &tegra_dsi_host_ops;
1561dec72739SThierry Reding 	dsi->host.dev = &pdev->dev;
1562dec72739SThierry Reding 
1563dec72739SThierry Reding 	err = mipi_dsi_host_register(&dsi->host);
1564dec72739SThierry Reding 	if (err < 0) {
1565dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to register DSI host: %d\n", err);
1566d2d0a9d2SThierry Reding 		goto mipi_free;
1567dec72739SThierry Reding 	}
1568dec72739SThierry Reding 
1569dec72739SThierry Reding 	INIT_LIST_HEAD(&dsi->client.list);
1570dec72739SThierry Reding 	dsi->client.ops = &dsi_client_ops;
1571dec72739SThierry Reding 	dsi->client.dev = &pdev->dev;
1572dec72739SThierry Reding 
1573dec72739SThierry Reding 	err = host1x_client_register(&dsi->client);
1574dec72739SThierry Reding 	if (err < 0) {
1575dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1576dec72739SThierry Reding 			err);
1577d2d0a9d2SThierry Reding 		goto unregister;
1578dec72739SThierry Reding 	}
1579dec72739SThierry Reding 
1580dec72739SThierry Reding 	platform_set_drvdata(pdev, dsi);
1581dec72739SThierry Reding 
1582dec72739SThierry Reding 	return 0;
1583d2d0a9d2SThierry Reding 
1584d2d0a9d2SThierry Reding unregister:
1585d2d0a9d2SThierry Reding 	mipi_dsi_host_unregister(&dsi->host);
1586d2d0a9d2SThierry Reding mipi_free:
1587d2d0a9d2SThierry Reding 	tegra_mipi_free(dsi->mipi);
1588d2d0a9d2SThierry Reding disable_vdd:
1589d2d0a9d2SThierry Reding 	regulator_disable(dsi->vdd);
1590d2d0a9d2SThierry Reding disable_clk_lp:
1591d2d0a9d2SThierry Reding 	clk_disable_unprepare(dsi->clk_lp);
1592d2d0a9d2SThierry Reding disable_clk:
1593d2d0a9d2SThierry Reding 	clk_disable_unprepare(dsi->clk);
1594d2d0a9d2SThierry Reding reset:
1595d2d0a9d2SThierry Reding 	reset_control_assert(dsi->rst);
1596d2d0a9d2SThierry Reding 	return err;
1597dec72739SThierry Reding }
1598dec72739SThierry Reding 
1599dec72739SThierry Reding static int tegra_dsi_remove(struct platform_device *pdev)
1600dec72739SThierry Reding {
1601dec72739SThierry Reding 	struct tegra_dsi *dsi = platform_get_drvdata(pdev);
1602dec72739SThierry Reding 	int err;
1603dec72739SThierry Reding 
1604dec72739SThierry Reding 	err = host1x_client_unregister(&dsi->client);
1605dec72739SThierry Reding 	if (err < 0) {
1606dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1607dec72739SThierry Reding 			err);
1608dec72739SThierry Reding 		return err;
1609dec72739SThierry Reding 	}
1610dec72739SThierry Reding 
1611328ec69eSThierry Reding 	tegra_output_remove(&dsi->output);
16125b901e78SThierry Reding 
1613dec72739SThierry Reding 	mipi_dsi_host_unregister(&dsi->host);
1614dec72739SThierry Reding 	tegra_mipi_free(dsi->mipi);
1615dec72739SThierry Reding 
16163b077afbSThierry Reding 	regulator_disable(dsi->vdd);
1617dec72739SThierry Reding 	clk_disable_unprepare(dsi->clk_lp);
1618dec72739SThierry Reding 	clk_disable_unprepare(dsi->clk);
1619cb825d89SThierry Reding 	reset_control_assert(dsi->rst);
1620dec72739SThierry Reding 
1621dec72739SThierry Reding 	return 0;
1622dec72739SThierry Reding }
1623dec72739SThierry Reding 
1624dec72739SThierry Reding static const struct of_device_id tegra_dsi_of_match[] = {
1625ddfb406bSThierry Reding 	{ .compatible = "nvidia,tegra210-dsi", },
1626c06c7930SThierry Reding 	{ .compatible = "nvidia,tegra132-dsi", },
16277d338587SThierry Reding 	{ .compatible = "nvidia,tegra124-dsi", },
1628dec72739SThierry Reding 	{ .compatible = "nvidia,tegra114-dsi", },
1629dec72739SThierry Reding 	{ },
1630dec72739SThierry Reding };
1631ef70728cSStephen Warren MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
1632dec72739SThierry Reding 
1633dec72739SThierry Reding struct platform_driver tegra_dsi_driver = {
1634dec72739SThierry Reding 	.driver = {
1635dec72739SThierry Reding 		.name = "tegra-dsi",
1636dec72739SThierry Reding 		.of_match_table = tegra_dsi_of_match,
1637dec72739SThierry Reding 	},
1638dec72739SThierry Reding 	.probe = tegra_dsi_probe,
1639dec72739SThierry Reding 	.remove = tegra_dsi_remove,
1640dec72739SThierry Reding };
1641