xref: /linux/drivers/gpu/drm/tegra/dsi.c (revision 64230aa075864f7c8e270b583bca685304246b57)
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>
16ef8187d7SThierry Reding #include <linux/pm_runtime.h>
17dec72739SThierry Reding #include <linux/reset.h>
18dec72739SThierry Reding 
193b077afbSThierry Reding #include <linux/regulator/consumer.h>
203b077afbSThierry Reding 
214aa3df71SThierry Reding #include <drm/drm_atomic_helper.h>
22dec72739SThierry Reding #include <drm/drm_mipi_dsi.h>
23dec72739SThierry Reding #include <drm/drm_panel.h>
24dec72739SThierry Reding 
25dec72739SThierry Reding #include <video/mipi_display.h>
26dec72739SThierry Reding 
27dec72739SThierry Reding #include "dc.h"
28dec72739SThierry Reding #include "drm.h"
29dec72739SThierry Reding #include "dsi.h"
30dec72739SThierry Reding #include "mipi-phy.h"
31dec72739SThierry Reding 
32ebd14afeSThierry Reding struct tegra_dsi_state {
33ebd14afeSThierry Reding 	struct drm_connector_state base;
34ebd14afeSThierry Reding 
35ebd14afeSThierry Reding 	struct mipi_dphy_timing timing;
36ebd14afeSThierry Reding 	unsigned long period;
37ebd14afeSThierry Reding 
38ebd14afeSThierry Reding 	unsigned int vrefresh;
39ebd14afeSThierry Reding 	unsigned int lanes;
40ebd14afeSThierry Reding 	unsigned long pclk;
41ebd14afeSThierry Reding 	unsigned long bclk;
42ebd14afeSThierry Reding 
43ebd14afeSThierry Reding 	enum tegra_dsi_format format;
44ebd14afeSThierry Reding 	unsigned int mul;
45ebd14afeSThierry Reding 	unsigned int div;
46ebd14afeSThierry Reding };
47ebd14afeSThierry Reding 
48ebd14afeSThierry Reding static inline struct tegra_dsi_state *
49ebd14afeSThierry Reding to_dsi_state(struct drm_connector_state *state)
50ebd14afeSThierry Reding {
51ebd14afeSThierry Reding 	return container_of(state, struct tegra_dsi_state, base);
52ebd14afeSThierry Reding }
53ebd14afeSThierry Reding 
54dec72739SThierry Reding struct tegra_dsi {
55dec72739SThierry Reding 	struct host1x_client client;
56dec72739SThierry Reding 	struct tegra_output output;
57dec72739SThierry Reding 	struct device *dev;
58dec72739SThierry Reding 
59dec72739SThierry Reding 	void __iomem *regs;
60dec72739SThierry Reding 
61dec72739SThierry Reding 	struct reset_control *rst;
62dec72739SThierry Reding 	struct clk *clk_parent;
63dec72739SThierry Reding 	struct clk *clk_lp;
64dec72739SThierry Reding 	struct clk *clk;
65dec72739SThierry Reding 
66dec72739SThierry Reding 	struct drm_info_list *debugfs_files;
67dec72739SThierry Reding 	struct drm_minor *minor;
68dec72739SThierry Reding 	struct dentry *debugfs;
69dec72739SThierry Reding 
7017297a28SThierry Reding 	unsigned long flags;
71dec72739SThierry Reding 	enum mipi_dsi_pixel_format format;
72dec72739SThierry Reding 	unsigned int lanes;
73dec72739SThierry Reding 
74dec72739SThierry Reding 	struct tegra_mipi_device *mipi;
75dec72739SThierry Reding 	struct mipi_dsi_host host;
763b077afbSThierry Reding 
773b077afbSThierry Reding 	struct regulator *vdd;
78976cebc3SThierry Reding 
79976cebc3SThierry Reding 	unsigned int video_fifo_depth;
80976cebc3SThierry Reding 	unsigned int host_fifo_depth;
81e94236cdSThierry Reding 
82e94236cdSThierry Reding 	/* for ganged-mode support */
83e94236cdSThierry Reding 	struct tegra_dsi *master;
84e94236cdSThierry Reding 	struct tegra_dsi *slave;
85dec72739SThierry Reding };
86dec72739SThierry Reding 
87dec72739SThierry Reding static inline struct tegra_dsi *
88dec72739SThierry Reding host1x_client_to_dsi(struct host1x_client *client)
89dec72739SThierry Reding {
90dec72739SThierry Reding 	return container_of(client, struct tegra_dsi, client);
91dec72739SThierry Reding }
92dec72739SThierry Reding 
93dec72739SThierry Reding static inline struct tegra_dsi *host_to_tegra(struct mipi_dsi_host *host)
94dec72739SThierry Reding {
95dec72739SThierry Reding 	return container_of(host, struct tegra_dsi, host);
96dec72739SThierry Reding }
97dec72739SThierry Reding 
98dec72739SThierry Reding static inline struct tegra_dsi *to_dsi(struct tegra_output *output)
99dec72739SThierry Reding {
100dec72739SThierry Reding 	return container_of(output, struct tegra_dsi, output);
101dec72739SThierry Reding }
102dec72739SThierry Reding 
103ebd14afeSThierry Reding static struct tegra_dsi_state *tegra_dsi_get_state(struct tegra_dsi *dsi)
104ebd14afeSThierry Reding {
105ebd14afeSThierry Reding 	return to_dsi_state(dsi->output.connector.state);
106ebd14afeSThierry Reding }
107ebd14afeSThierry Reding 
1089c0b4ca1SThierry Reding static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned long reg)
109dec72739SThierry Reding {
110dec72739SThierry Reding 	return readl(dsi->regs + (reg << 2));
111dec72739SThierry Reding }
112dec72739SThierry Reding 
1139c0b4ca1SThierry Reding static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
114dec72739SThierry Reding 				    unsigned long reg)
115dec72739SThierry Reding {
116dec72739SThierry Reding 	writel(value, dsi->regs + (reg << 2));
117dec72739SThierry Reding }
118dec72739SThierry Reding 
119dec72739SThierry Reding static int tegra_dsi_show_regs(struct seq_file *s, void *data)
120dec72739SThierry Reding {
121dec72739SThierry Reding 	struct drm_info_node *node = s->private;
122dec72739SThierry Reding 	struct tegra_dsi *dsi = node->info_ent->data;
123171e2e6dSThierry Reding 	struct drm_crtc *crtc = dsi->output.encoder.crtc;
124171e2e6dSThierry Reding 	struct drm_device *drm = node->minor->dev;
125171e2e6dSThierry Reding 	int err = 0;
126171e2e6dSThierry Reding 
127171e2e6dSThierry Reding 	drm_modeset_lock_all(drm);
128171e2e6dSThierry Reding 
129171e2e6dSThierry Reding 	if (!crtc || !crtc->state->active) {
130171e2e6dSThierry Reding 		err = -EBUSY;
131171e2e6dSThierry Reding 		goto unlock;
132171e2e6dSThierry Reding 	}
133dec72739SThierry Reding 
134dec72739SThierry Reding #define DUMP_REG(name)						\
1359c0b4ca1SThierry Reding 	seq_printf(s, "%-32s %#05x %08x\n", #name, name,	\
136dec72739SThierry Reding 		   tegra_dsi_readl(dsi, name))
137dec72739SThierry Reding 
138dec72739SThierry Reding 	DUMP_REG(DSI_INCR_SYNCPT);
139dec72739SThierry Reding 	DUMP_REG(DSI_INCR_SYNCPT_CONTROL);
140dec72739SThierry Reding 	DUMP_REG(DSI_INCR_SYNCPT_ERROR);
141dec72739SThierry Reding 	DUMP_REG(DSI_CTXSW);
142dec72739SThierry Reding 	DUMP_REG(DSI_RD_DATA);
143dec72739SThierry Reding 	DUMP_REG(DSI_WR_DATA);
144dec72739SThierry Reding 	DUMP_REG(DSI_POWER_CONTROL);
145dec72739SThierry Reding 	DUMP_REG(DSI_INT_ENABLE);
146dec72739SThierry Reding 	DUMP_REG(DSI_INT_STATUS);
147dec72739SThierry Reding 	DUMP_REG(DSI_INT_MASK);
148dec72739SThierry Reding 	DUMP_REG(DSI_HOST_CONTROL);
149dec72739SThierry Reding 	DUMP_REG(DSI_CONTROL);
150dec72739SThierry Reding 	DUMP_REG(DSI_SOL_DELAY);
151dec72739SThierry Reding 	DUMP_REG(DSI_MAX_THRESHOLD);
152dec72739SThierry Reding 	DUMP_REG(DSI_TRIGGER);
153dec72739SThierry Reding 	DUMP_REG(DSI_TX_CRC);
154dec72739SThierry Reding 	DUMP_REG(DSI_STATUS);
155dec72739SThierry Reding 
156dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_CONTROL);
157dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_0);
158dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_1);
159dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_2);
160dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_3);
161dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_4);
162dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_5);
163dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_6);
164dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_7);
165dec72739SThierry Reding 
166dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_0_LO);
167dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_0_HI);
168dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_1_LO);
169dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_1_HI);
170dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_2_LO);
171dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_2_HI);
172dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_3_LO);
173dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_3_HI);
174dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_4_LO);
175dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_4_HI);
176dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_5_LO);
177dec72739SThierry Reding 	DUMP_REG(DSI_PKT_SEQ_5_HI);
178dec72739SThierry Reding 
179dec72739SThierry Reding 	DUMP_REG(DSI_DCS_CMDS);
180dec72739SThierry Reding 
181dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_0_1);
182dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_2_3);
183dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_4_5);
184dec72739SThierry Reding 	DUMP_REG(DSI_PKT_LEN_6_7);
185dec72739SThierry Reding 
186dec72739SThierry Reding 	DUMP_REG(DSI_PHY_TIMING_0);
187dec72739SThierry Reding 	DUMP_REG(DSI_PHY_TIMING_1);
188dec72739SThierry Reding 	DUMP_REG(DSI_PHY_TIMING_2);
189dec72739SThierry Reding 	DUMP_REG(DSI_BTA_TIMING);
190dec72739SThierry Reding 
191dec72739SThierry Reding 	DUMP_REG(DSI_TIMEOUT_0);
192dec72739SThierry Reding 	DUMP_REG(DSI_TIMEOUT_1);
193dec72739SThierry Reding 	DUMP_REG(DSI_TO_TALLY);
194dec72739SThierry Reding 
195dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_0);
196dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_CD);
197dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CD_STATUS);
198dec72739SThierry Reding 	DUMP_REG(DSI_VIDEO_MODE_CONTROL);
199dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_1);
200dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_2);
201dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_3);
202dec72739SThierry Reding 	DUMP_REG(DSI_PAD_CONTROL_4);
203dec72739SThierry Reding 
204dec72739SThierry Reding 	DUMP_REG(DSI_GANGED_MODE_CONTROL);
205dec72739SThierry Reding 	DUMP_REG(DSI_GANGED_MODE_START);
206dec72739SThierry Reding 	DUMP_REG(DSI_GANGED_MODE_SIZE);
207dec72739SThierry Reding 
208dec72739SThierry Reding 	DUMP_REG(DSI_RAW_DATA_BYTE_COUNT);
209dec72739SThierry Reding 	DUMP_REG(DSI_ULTRA_LOW_POWER_CONTROL);
210dec72739SThierry Reding 
211dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_8);
212dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_9);
213dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_10);
214dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_11);
215dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_12);
216dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_13);
217dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_14);
218dec72739SThierry Reding 	DUMP_REG(DSI_INIT_SEQ_DATA_15);
219dec72739SThierry Reding 
220dec72739SThierry Reding #undef DUMP_REG
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 
231dec72739SThierry Reding static int tegra_dsi_debugfs_init(struct tegra_dsi *dsi,
232dec72739SThierry Reding 				  struct drm_minor *minor)
233dec72739SThierry Reding {
234dec72739SThierry Reding 	const char *name = dev_name(dsi->dev);
235dec72739SThierry Reding 	unsigned int i;
236dec72739SThierry Reding 	int err;
237dec72739SThierry Reding 
238dec72739SThierry Reding 	dsi->debugfs = debugfs_create_dir(name, minor->debugfs_root);
239dec72739SThierry Reding 	if (!dsi->debugfs)
240dec72739SThierry Reding 		return -ENOMEM;
241dec72739SThierry Reding 
242dec72739SThierry Reding 	dsi->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
243dec72739SThierry Reding 				     GFP_KERNEL);
244dec72739SThierry Reding 	if (!dsi->debugfs_files) {
245dec72739SThierry Reding 		err = -ENOMEM;
246dec72739SThierry Reding 		goto remove;
247dec72739SThierry Reding 	}
248dec72739SThierry Reding 
249dec72739SThierry Reding 	for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
250dec72739SThierry Reding 		dsi->debugfs_files[i].data = dsi;
251dec72739SThierry Reding 
252dec72739SThierry Reding 	err = drm_debugfs_create_files(dsi->debugfs_files,
253dec72739SThierry Reding 				       ARRAY_SIZE(debugfs_files),
254dec72739SThierry Reding 				       dsi->debugfs, minor);
255dec72739SThierry Reding 	if (err < 0)
256dec72739SThierry Reding 		goto free;
257dec72739SThierry Reding 
258dec72739SThierry Reding 	dsi->minor = minor;
259dec72739SThierry Reding 
260dec72739SThierry Reding 	return 0;
261dec72739SThierry Reding 
262dec72739SThierry Reding free:
263dec72739SThierry Reding 	kfree(dsi->debugfs_files);
264dec72739SThierry Reding 	dsi->debugfs_files = NULL;
265dec72739SThierry Reding remove:
266dec72739SThierry Reding 	debugfs_remove(dsi->debugfs);
267dec72739SThierry Reding 	dsi->debugfs = NULL;
268dec72739SThierry Reding 
269dec72739SThierry Reding 	return err;
270dec72739SThierry Reding }
271dec72739SThierry Reding 
2724009c224SThierry Reding static void tegra_dsi_debugfs_exit(struct tegra_dsi *dsi)
273dec72739SThierry Reding {
274dec72739SThierry Reding 	drm_debugfs_remove_files(dsi->debugfs_files, ARRAY_SIZE(debugfs_files),
275dec72739SThierry Reding 				 dsi->minor);
276dec72739SThierry Reding 	dsi->minor = NULL;
277dec72739SThierry Reding 
278dec72739SThierry Reding 	kfree(dsi->debugfs_files);
279dec72739SThierry Reding 	dsi->debugfs_files = NULL;
280dec72739SThierry Reding 
281dec72739SThierry Reding 	debugfs_remove(dsi->debugfs);
282dec72739SThierry Reding 	dsi->debugfs = NULL;
283dec72739SThierry Reding }
284dec72739SThierry Reding 
285dec72739SThierry Reding #define PKT_ID0(id)	((((id) & 0x3f) <<  3) | (1 <<  9))
286dec72739SThierry Reding #define PKT_LEN0(len)	(((len) & 0x07) <<  0)
287dec72739SThierry Reding #define PKT_ID1(id)	((((id) & 0x3f) << 13) | (1 << 19))
288dec72739SThierry Reding #define PKT_LEN1(len)	(((len) & 0x07) << 10)
289dec72739SThierry Reding #define PKT_ID2(id)	((((id) & 0x3f) << 23) | (1 << 29))
290dec72739SThierry Reding #define PKT_LEN2(len)	(((len) & 0x07) << 20)
291dec72739SThierry Reding 
292dec72739SThierry Reding #define PKT_LP		(1 << 30)
293dec72739SThierry Reding #define NUM_PKT_SEQ	12
294dec72739SThierry Reding 
29517297a28SThierry Reding /*
29617297a28SThierry Reding  * non-burst mode with sync pulses
29717297a28SThierry Reding  */
29817297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_pulses[NUM_PKT_SEQ] = {
299dec72739SThierry Reding 	[ 0] = PKT_ID0(MIPI_DSI_V_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 	[ 1] = 0,
304dec72739SThierry Reding 	[ 2] = PKT_ID0(MIPI_DSI_V_SYNC_END) | 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 	       PKT_LP,
308dec72739SThierry Reding 	[ 3] = 0,
309dec72739SThierry Reding 	[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
310dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
311dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
312dec72739SThierry Reding 	       PKT_LP,
313dec72739SThierry Reding 	[ 5] = 0,
314dec72739SThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
315dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
316dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
317dec72739SThierry Reding 	[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
318dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
319dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
320dec72739SThierry Reding 	[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
321dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
322dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0) |
323dec72739SThierry Reding 	       PKT_LP,
324dec72739SThierry Reding 	[ 9] = 0,
325dec72739SThierry Reding 	[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
326dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(1) |
327dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_H_SYNC_END) | PKT_LEN2(0),
328dec72739SThierry Reding 	[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(2) |
329dec72739SThierry Reding 	       PKT_ID1(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN1(3) |
330dec72739SThierry Reding 	       PKT_ID2(MIPI_DSI_BLANKING_PACKET) | PKT_LEN2(4),
331dec72739SThierry Reding };
332dec72739SThierry Reding 
33317297a28SThierry Reding /*
33417297a28SThierry Reding  * non-burst mode with sync events
33517297a28SThierry Reding  */
33617297a28SThierry Reding static const u32 pkt_seq_video_non_burst_sync_events[NUM_PKT_SEQ] = {
33717297a28SThierry Reding 	[ 0] = PKT_ID0(MIPI_DSI_V_SYNC_START) | PKT_LEN0(0) |
33817297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
33917297a28SThierry Reding 	       PKT_LP,
34017297a28SThierry Reding 	[ 1] = 0,
34117297a28SThierry Reding 	[ 2] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
34217297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
34317297a28SThierry Reding 	       PKT_LP,
34417297a28SThierry Reding 	[ 3] = 0,
34517297a28SThierry Reding 	[ 4] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
34617297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
34717297a28SThierry Reding 	       PKT_LP,
34817297a28SThierry Reding 	[ 5] = 0,
34917297a28SThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
35017297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
35117297a28SThierry Reding 	       PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
35217297a28SThierry Reding 	[ 7] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
35317297a28SThierry Reding 	[ 8] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
35417297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_END_OF_TRANSMISSION) | PKT_LEN1(7) |
35517297a28SThierry Reding 	       PKT_LP,
35617297a28SThierry Reding 	[ 9] = 0,
35717297a28SThierry Reding 	[10] = PKT_ID0(MIPI_DSI_H_SYNC_START) | PKT_LEN0(0) |
35817297a28SThierry Reding 	       PKT_ID1(MIPI_DSI_BLANKING_PACKET) | PKT_LEN1(2) |
35917297a28SThierry Reding 	       PKT_ID2(MIPI_DSI_PACKED_PIXEL_STREAM_24) | PKT_LEN2(3),
36017297a28SThierry Reding 	[11] = PKT_ID0(MIPI_DSI_BLANKING_PACKET) | PKT_LEN0(4),
36117297a28SThierry Reding };
36217297a28SThierry Reding 
363337b443dSThierry Reding static const u32 pkt_seq_command_mode[NUM_PKT_SEQ] = {
364337b443dSThierry Reding 	[ 0] = 0,
365337b443dSThierry Reding 	[ 1] = 0,
366337b443dSThierry Reding 	[ 2] = 0,
367337b443dSThierry Reding 	[ 3] = 0,
368337b443dSThierry Reding 	[ 4] = 0,
369337b443dSThierry Reding 	[ 5] = 0,
370337b443dSThierry Reding 	[ 6] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(3) | PKT_LP,
371337b443dSThierry Reding 	[ 7] = 0,
372337b443dSThierry Reding 	[ 8] = 0,
373337b443dSThierry Reding 	[ 9] = 0,
374337b443dSThierry Reding 	[10] = PKT_ID0(MIPI_DSI_DCS_LONG_WRITE) | PKT_LEN0(5) | PKT_LP,
375337b443dSThierry Reding 	[11] = 0,
376337b443dSThierry Reding };
377337b443dSThierry Reding 
378ebd14afeSThierry Reding static void tegra_dsi_set_phy_timing(struct tegra_dsi *dsi,
379ebd14afeSThierry Reding 				     unsigned long period,
380ebd14afeSThierry Reding 				     const struct mipi_dphy_timing *timing)
381dec72739SThierry Reding {
3829c0b4ca1SThierry Reding 	u32 value;
383dec72739SThierry Reding 
384ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->hsexit, period, 1) << 24 |
385ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hstrail, period, 0) << 16 |
386ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hszero, period, 3) << 8 |
387ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->hsprepare, period, 1);
388dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_0);
389dec72739SThierry Reding 
390ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->clktrail, period, 1) << 24 |
391ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkpost, period, 1) << 16 |
392ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkzero, period, 1) << 8 |
393ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->lpx, period, 1);
394dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_1);
395dec72739SThierry Reding 
396ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->clkprepare, period, 1) << 16 |
397ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->clkpre, period, 1) << 8 |
398dec72739SThierry Reding 		DSI_TIMING_FIELD(0xff * period, period, 0) << 0;
399dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PHY_TIMING_2);
400dec72739SThierry Reding 
401ebd14afeSThierry Reding 	value = DSI_TIMING_FIELD(timing->taget, period, 1) << 16 |
402ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->tasure, period, 1) << 8 |
403ebd14afeSThierry Reding 		DSI_TIMING_FIELD(timing->tago, period, 1);
404dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_BTA_TIMING);
405dec72739SThierry Reding 
4067e3bc3a9SSean Paul 	if (dsi->slave)
407ebd14afeSThierry Reding 		tegra_dsi_set_phy_timing(dsi->slave, period, timing);
408dec72739SThierry Reding }
409dec72739SThierry Reding 
410dec72739SThierry Reding static int tegra_dsi_get_muldiv(enum mipi_dsi_pixel_format format,
411dec72739SThierry Reding 				unsigned int *mulp, unsigned int *divp)
412dec72739SThierry Reding {
413dec72739SThierry Reding 	switch (format) {
414dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB666_PACKED:
415dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB888:
416dec72739SThierry Reding 		*mulp = 3;
417dec72739SThierry Reding 		*divp = 1;
418dec72739SThierry Reding 		break;
419dec72739SThierry Reding 
420dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB565:
421dec72739SThierry Reding 		*mulp = 2;
422dec72739SThierry Reding 		*divp = 1;
423dec72739SThierry Reding 		break;
424dec72739SThierry Reding 
425dec72739SThierry Reding 	case MIPI_DSI_FMT_RGB666:
426dec72739SThierry Reding 		*mulp = 9;
427dec72739SThierry Reding 		*divp = 4;
428dec72739SThierry Reding 		break;
429dec72739SThierry Reding 
430dec72739SThierry Reding 	default:
431dec72739SThierry Reding 		return -EINVAL;
432dec72739SThierry Reding 	}
433dec72739SThierry Reding 
434dec72739SThierry Reding 	return 0;
435dec72739SThierry Reding }
436dec72739SThierry Reding 
437f7d6889bSThierry Reding static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format,
438f7d6889bSThierry Reding 				enum tegra_dsi_format *fmt)
439f7d6889bSThierry Reding {
440f7d6889bSThierry Reding 	switch (format) {
441f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB888:
442f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_24P;
443f7d6889bSThierry Reding 		break;
444f7d6889bSThierry Reding 
445f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB666:
446f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_18NP;
447f7d6889bSThierry Reding 		break;
448f7d6889bSThierry Reding 
449f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB666_PACKED:
450f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_18P;
451f7d6889bSThierry Reding 		break;
452f7d6889bSThierry Reding 
453f7d6889bSThierry Reding 	case MIPI_DSI_FMT_RGB565:
454f7d6889bSThierry Reding 		*fmt = TEGRA_DSI_FORMAT_16P;
455f7d6889bSThierry Reding 		break;
456f7d6889bSThierry Reding 
457f7d6889bSThierry Reding 	default:
458f7d6889bSThierry Reding 		return -EINVAL;
459f7d6889bSThierry Reding 	}
460f7d6889bSThierry Reding 
461f7d6889bSThierry Reding 	return 0;
462f7d6889bSThierry Reding }
463f7d6889bSThierry Reding 
464e94236cdSThierry Reding static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start,
465e94236cdSThierry Reding 				    unsigned int size)
466e94236cdSThierry Reding {
467e94236cdSThierry Reding 	u32 value;
468e94236cdSThierry Reding 
469e94236cdSThierry Reding 	tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START);
470e94236cdSThierry Reding 	tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE);
471e94236cdSThierry Reding 
472e94236cdSThierry Reding 	value = DSI_GANGED_MODE_CONTROL_ENABLE;
473e94236cdSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL);
474e94236cdSThierry Reding }
475e94236cdSThierry Reding 
476563eff1fSThierry Reding static void tegra_dsi_enable(struct tegra_dsi *dsi)
477dec72739SThierry Reding {
478563eff1fSThierry Reding 	u32 value;
479dec72739SThierry Reding 
480563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
481563eff1fSThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
482563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
483e94236cdSThierry Reding 
484e94236cdSThierry Reding 	if (dsi->slave)
485e94236cdSThierry Reding 		tegra_dsi_enable(dsi->slave);
486e94236cdSThierry Reding }
487e94236cdSThierry Reding 
488e94236cdSThierry Reding static unsigned int tegra_dsi_get_lanes(struct tegra_dsi *dsi)
489e94236cdSThierry Reding {
490e94236cdSThierry Reding 	if (dsi->master)
491e94236cdSThierry Reding 		return dsi->master->lanes + dsi->lanes;
492e94236cdSThierry Reding 
493e94236cdSThierry Reding 	if (dsi->slave)
494e94236cdSThierry Reding 		return dsi->lanes + dsi->slave->lanes;
495e94236cdSThierry Reding 
496e94236cdSThierry Reding 	return dsi->lanes;
497563eff1fSThierry Reding }
498563eff1fSThierry Reding 
499ebd14afeSThierry Reding static void tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
500563eff1fSThierry Reding 				const struct drm_display_mode *mode)
501563eff1fSThierry Reding {
502563eff1fSThierry Reding 	unsigned int hact, hsw, hbp, hfp, i, mul, div;
503ebd14afeSThierry Reding 	struct tegra_dsi_state *state;
504563eff1fSThierry Reding 	const u32 *pkt_seq;
505563eff1fSThierry Reding 	u32 value;
506ebd14afeSThierry Reding 
507ebd14afeSThierry Reding 	/* XXX: pass in state into this function? */
508ebd14afeSThierry Reding 	if (dsi->master)
509ebd14afeSThierry Reding 		state = tegra_dsi_get_state(dsi->master);
510ebd14afeSThierry Reding 	else
511ebd14afeSThierry Reding 		state = tegra_dsi_get_state(dsi);
512ebd14afeSThierry Reding 
513ebd14afeSThierry Reding 	mul = state->mul;
514ebd14afeSThierry Reding 	div = state->div;
515334ae6b5SThierry Reding 
51617297a28SThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
51717297a28SThierry Reding 		DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n");
51817297a28SThierry Reding 		pkt_seq = pkt_seq_video_non_burst_sync_pulses;
519337b443dSThierry Reding 	} else if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
52017297a28SThierry Reding 		DRM_DEBUG_KMS("Non-burst video mode with sync events\n");
52117297a28SThierry Reding 		pkt_seq = pkt_seq_video_non_burst_sync_events;
522337b443dSThierry Reding 	} else {
523337b443dSThierry Reding 		DRM_DEBUG_KMS("Command mode\n");
524337b443dSThierry Reding 		pkt_seq = pkt_seq_command_mode;
52517297a28SThierry Reding 	}
52617297a28SThierry Reding 
527ebd14afeSThierry Reding 	value = DSI_CONTROL_CHANNEL(0) |
528ebd14afeSThierry Reding 		DSI_CONTROL_FORMAT(state->format) |
529dec72739SThierry Reding 		DSI_CONTROL_LANES(dsi->lanes - 1) |
530563eff1fSThierry Reding 		DSI_CONTROL_SOURCE(pipe);
531dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
532dec72739SThierry Reding 
533976cebc3SThierry Reding 	tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD);
534dec72739SThierry Reding 
535563eff1fSThierry Reding 	value = DSI_HOST_CONTROL_HS;
536dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
537dec72739SThierry Reding 
538dec72739SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
539563eff1fSThierry Reding 
5400c6b1e4bSAlexandre Courbot 	if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
541dec72739SThierry Reding 		value |= DSI_CONTROL_HS_CLK_CTRL;
542563eff1fSThierry Reding 
543dec72739SThierry Reding 	value &= ~DSI_CONTROL_TX_TRIG(3);
544337b443dSThierry Reding 
545337b443dSThierry Reding 	/* enable DCS commands for command mode */
546337b443dSThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO)
547dec72739SThierry Reding 		value &= ~DSI_CONTROL_DCS_ENABLE;
548337b443dSThierry Reding 	else
549337b443dSThierry Reding 		value |= DSI_CONTROL_DCS_ENABLE;
550337b443dSThierry Reding 
551dec72739SThierry Reding 	value |= DSI_CONTROL_VIDEO_ENABLE;
552dec72739SThierry Reding 	value &= ~DSI_CONTROL_HOST_ENABLE;
553dec72739SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
554dec72739SThierry Reding 
555dec72739SThierry Reding 	for (i = 0; i < NUM_PKT_SEQ; i++)
556dec72739SThierry Reding 		tegra_dsi_writel(dsi, pkt_seq[i], DSI_PKT_SEQ_0_LO + i);
557dec72739SThierry Reding 
558337b443dSThierry Reding 	if (dsi->flags & MIPI_DSI_MODE_VIDEO) {
559dec72739SThierry Reding 		/* horizontal active pixels */
560dec72739SThierry Reding 		hact = mode->hdisplay * mul / div;
561dec72739SThierry Reding 
562dec72739SThierry Reding 		/* horizontal sync width */
563dec72739SThierry Reding 		hsw = (mode->hsync_end - mode->hsync_start) * mul / div;
564dec72739SThierry Reding 
565dec72739SThierry Reding 		/* horizontal back porch */
566dec72739SThierry Reding 		hbp = (mode->htotal - mode->hsync_end) * mul / div;
567b8be0bdbSThierry Reding 
568b8be0bdbSThierry Reding 		if ((dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0)
569b8be0bdbSThierry Reding 			hbp += hsw;
570dec72739SThierry Reding 
571dec72739SThierry Reding 		/* horizontal front porch */
572dec72739SThierry Reding 		hfp = (mode->hsync_start - mode->hdisplay) * mul / div;
573b8be0bdbSThierry Reding 
574b8be0bdbSThierry Reding 		/* subtract packet overhead */
575b8be0bdbSThierry Reding 		hsw -= 10;
576b8be0bdbSThierry Reding 		hbp -= 14;
577dec72739SThierry Reding 		hfp -= 8;
578dec72739SThierry Reding 
579dec72739SThierry Reding 		tegra_dsi_writel(dsi, hsw << 16 | 0, DSI_PKT_LEN_0_1);
580dec72739SThierry Reding 		tegra_dsi_writel(dsi, hact << 16 | hbp, DSI_PKT_LEN_2_3);
581dec72739SThierry Reding 		tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
582dec72739SThierry Reding 		tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
583dec72739SThierry Reding 
584563eff1fSThierry Reding 		/* set SOL delay (for non-burst mode only) */
585dec72739SThierry Reding 		tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
586e94236cdSThierry Reding 
587e94236cdSThierry Reding 		/* TODO: implement ganged mode */
588337b443dSThierry Reding 	} else {
589337b443dSThierry Reding 		u16 bytes;
590337b443dSThierry Reding 
591e94236cdSThierry Reding 		if (dsi->master || dsi->slave) {
592e94236cdSThierry Reding 			/*
593e94236cdSThierry Reding 			 * For ganged mode, assume symmetric left-right mode.
594e94236cdSThierry Reding 			 */
595e94236cdSThierry Reding 			bytes = 1 + (mode->hdisplay / 2) * mul / div;
596e94236cdSThierry Reding 		} else {
597337b443dSThierry Reding 			/* 1 byte (DCS command) + pixel data */
598337b443dSThierry Reding 			bytes = 1 + mode->hdisplay * mul / div;
599e94236cdSThierry Reding 		}
600337b443dSThierry Reding 
601337b443dSThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_0_1);
602337b443dSThierry Reding 		tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_2_3);
603337b443dSThierry Reding 		tegra_dsi_writel(dsi, bytes << 16, DSI_PKT_LEN_4_5);
604337b443dSThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_PKT_LEN_6_7);
605337b443dSThierry Reding 
606337b443dSThierry Reding 		value = MIPI_DCS_WRITE_MEMORY_START << 8 |
607337b443dSThierry Reding 			MIPI_DCS_WRITE_MEMORY_CONTINUE;
608337b443dSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_DCS_CMDS);
609337b443dSThierry Reding 
610e94236cdSThierry Reding 		/* set SOL delay */
611e94236cdSThierry Reding 		if (dsi->master || dsi->slave) {
612e94236cdSThierry Reding 			unsigned long delay, bclk, bclk_ganged;
613ebd14afeSThierry Reding 			unsigned int lanes = state->lanes;
614e94236cdSThierry Reding 
615e94236cdSThierry Reding 			/* SOL to valid, valid to FIFO and FIFO write delay */
616e94236cdSThierry Reding 			delay = 4 + 4 + 2;
617e94236cdSThierry Reding 			delay = DIV_ROUND_UP(delay * mul, div * lanes);
618e94236cdSThierry Reding 			/* FIFO read delay */
619e94236cdSThierry Reding 			delay = delay + 6;
620e94236cdSThierry Reding 
621e94236cdSThierry Reding 			bclk = DIV_ROUND_UP(mode->htotal * mul, div * lanes);
622e94236cdSThierry Reding 			bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes);
623e94236cdSThierry Reding 			value = bclk - bclk_ganged + delay + 20;
624e94236cdSThierry Reding 		} else {
625e94236cdSThierry Reding 			/* TODO: revisit for non-ganged mode */
626337b443dSThierry Reding 			value = 8 * mul / div;
627e94236cdSThierry Reding 		}
628337b443dSThierry Reding 
629337b443dSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_SOL_DELAY);
630337b443dSThierry Reding 	}
631dec72739SThierry Reding 
632e94236cdSThierry Reding 	if (dsi->slave) {
633ebd14afeSThierry Reding 		tegra_dsi_configure(dsi->slave, pipe, mode);
634e94236cdSThierry Reding 
635e94236cdSThierry Reding 		/*
636e94236cdSThierry Reding 		 * TODO: Support modes other than symmetrical left-right
637e94236cdSThierry Reding 		 * split.
638e94236cdSThierry Reding 		 */
639e94236cdSThierry Reding 		tegra_dsi_ganged_enable(dsi, 0, mode->hdisplay / 2);
640e94236cdSThierry Reding 		tegra_dsi_ganged_enable(dsi->slave, mode->hdisplay / 2,
641e94236cdSThierry Reding 					mode->hdisplay / 2);
642e94236cdSThierry Reding 	}
643563eff1fSThierry Reding }
644563eff1fSThierry Reding 
645563eff1fSThierry Reding static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout)
646563eff1fSThierry Reding {
647563eff1fSThierry Reding 	u32 value;
648563eff1fSThierry Reding 
649563eff1fSThierry Reding 	timeout = jiffies + msecs_to_jiffies(timeout);
650563eff1fSThierry Reding 
651563eff1fSThierry Reding 	while (time_before(jiffies, timeout)) {
652563eff1fSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_STATUS);
653563eff1fSThierry Reding 		if (value & DSI_STATUS_IDLE)
654563eff1fSThierry Reding 			return 0;
655563eff1fSThierry Reding 
656563eff1fSThierry Reding 		usleep_range(1000, 2000);
657563eff1fSThierry Reding 	}
658563eff1fSThierry Reding 
659563eff1fSThierry Reding 	return -ETIMEDOUT;
660563eff1fSThierry Reding }
661563eff1fSThierry Reding 
662563eff1fSThierry Reding static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
663563eff1fSThierry Reding {
664563eff1fSThierry Reding 	u32 value;
665563eff1fSThierry Reding 
666563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_CONTROL);
667563eff1fSThierry Reding 	value &= ~DSI_CONTROL_VIDEO_ENABLE;
668563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
669e94236cdSThierry Reding 
670e94236cdSThierry Reding 	if (dsi->slave)
671e94236cdSThierry Reding 		tegra_dsi_video_disable(dsi->slave);
672e94236cdSThierry Reding }
673e94236cdSThierry Reding 
674e94236cdSThierry Reding static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
675e94236cdSThierry Reding {
676e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START);
677e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE);
678e94236cdSThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
679563eff1fSThierry Reding }
680563eff1fSThierry Reding 
681ef8187d7SThierry Reding static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
682ef8187d7SThierry Reding {
683ef8187d7SThierry Reding 	u32 value;
684ef8187d7SThierry Reding 
685ef8187d7SThierry Reding 	value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
686ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
687ef8187d7SThierry Reding 
688ef8187d7SThierry Reding 	return 0;
689ef8187d7SThierry Reding }
690ef8187d7SThierry Reding 
691ef8187d7SThierry Reding static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
692ef8187d7SThierry Reding {
693ef8187d7SThierry Reding 	u32 value;
694ef8187d7SThierry Reding 
695ef8187d7SThierry Reding 	/*
696ef8187d7SThierry Reding 	 * XXX Is this still needed? The module reset is deasserted right
697ef8187d7SThierry Reding 	 * before this function is called.
698ef8187d7SThierry Reding 	 */
699ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
700ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
701ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
702ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
703ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
704ef8187d7SThierry Reding 
705ef8187d7SThierry Reding 	/* start calibration */
706ef8187d7SThierry Reding 	tegra_dsi_pad_enable(dsi);
707ef8187d7SThierry Reding 
708ef8187d7SThierry Reding 	value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
709ef8187d7SThierry Reding 		DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
710ef8187d7SThierry Reding 		DSI_PAD_OUT_CLK(0x0);
711ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
712ef8187d7SThierry Reding 
713ef8187d7SThierry Reding 	value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
714ef8187d7SThierry Reding 		DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
715ef8187d7SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
716ef8187d7SThierry Reding 
717ef8187d7SThierry Reding 	return tegra_mipi_calibrate(dsi->mipi);
718ef8187d7SThierry Reding }
719ef8187d7SThierry Reding 
7205b901e78SThierry Reding static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk,
7215b901e78SThierry Reding 				  unsigned int vrefresh)
7225b901e78SThierry Reding {
7235b901e78SThierry Reding 	unsigned int timeout;
7245b901e78SThierry Reding 	u32 value;
7255b901e78SThierry Reding 
7265b901e78SThierry Reding 	/* one frame high-speed transmission timeout */
7275b901e78SThierry Reding 	timeout = (bclk / vrefresh) / 512;
7285b901e78SThierry Reding 	value = DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(timeout);
7295b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_0);
7305b901e78SThierry Reding 
7315b901e78SThierry Reding 	/* 2 ms peripheral timeout for panel */
7325b901e78SThierry Reding 	timeout = 2 * bclk / 512 * 1000;
7335b901e78SThierry Reding 	value = DSI_TIMEOUT_PR(timeout) | DSI_TIMEOUT_TA(0x2000);
7345b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TIMEOUT_1);
7355b901e78SThierry Reding 
7365b901e78SThierry Reding 	value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0);
7375b901e78SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_TO_TALLY);
7385b901e78SThierry Reding 
7395b901e78SThierry Reding 	if (dsi->slave)
7405b901e78SThierry Reding 		tegra_dsi_set_timeout(dsi->slave, bclk, vrefresh);
7415b901e78SThierry Reding }
7425b901e78SThierry Reding 
743563eff1fSThierry Reding static void tegra_dsi_disable(struct tegra_dsi *dsi)
744563eff1fSThierry Reding {
745563eff1fSThierry Reding 	u32 value;
746563eff1fSThierry Reding 
747e94236cdSThierry Reding 	if (dsi->slave) {
748e94236cdSThierry Reding 		tegra_dsi_ganged_disable(dsi->slave);
749e94236cdSThierry Reding 		tegra_dsi_ganged_disable(dsi);
750e94236cdSThierry Reding 	}
751e94236cdSThierry Reding 
752563eff1fSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
753563eff1fSThierry Reding 	value &= ~DSI_POWER_CONTROL_ENABLE;
754563eff1fSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
755563eff1fSThierry Reding 
756e94236cdSThierry Reding 	if (dsi->slave)
757e94236cdSThierry Reding 		tegra_dsi_disable(dsi->slave);
758e94236cdSThierry Reding 
759563eff1fSThierry Reding 	usleep_range(5000, 10000);
760563eff1fSThierry Reding }
761563eff1fSThierry Reding 
76292f0e073SThierry Reding static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
76392f0e073SThierry Reding {
76492f0e073SThierry Reding 	u32 value;
76592f0e073SThierry Reding 
76692f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
76792f0e073SThierry Reding 	value &= ~DSI_POWER_CONTROL_ENABLE;
76892f0e073SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
76992f0e073SThierry Reding 
77092f0e073SThierry Reding 	usleep_range(300, 1000);
77192f0e073SThierry Reding 
77292f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
77392f0e073SThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
77492f0e073SThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
77592f0e073SThierry Reding 
77692f0e073SThierry Reding 	usleep_range(300, 1000);
77792f0e073SThierry Reding 
77892f0e073SThierry Reding 	value = tegra_dsi_readl(dsi, DSI_TRIGGER);
77992f0e073SThierry Reding 	if (value)
78092f0e073SThierry Reding 		tegra_dsi_writel(dsi, 0, DSI_TRIGGER);
78192f0e073SThierry Reding 
78292f0e073SThierry Reding 	if (dsi->slave)
78392f0e073SThierry Reding 		tegra_dsi_soft_reset(dsi->slave);
78492f0e073SThierry Reding }
78592f0e073SThierry Reding 
786ebd14afeSThierry Reding static void tegra_dsi_connector_reset(struct drm_connector *connector)
787ebd14afeSThierry Reding {
788280dc0e1SJon Hunter 	struct tegra_dsi_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
789ebd14afeSThierry Reding 
790280dc0e1SJon Hunter 	if (!state)
791280dc0e1SJon Hunter 		return;
792280dc0e1SJon Hunter 
793280dc0e1SJon Hunter 	if (connector->state) {
794280dc0e1SJon Hunter 		__drm_atomic_helper_connector_destroy_state(connector->state);
795ebd14afeSThierry Reding 		kfree(connector->state);
7965459a2adSMaarten Lankhorst 	}
797280dc0e1SJon Hunter 
798280dc0e1SJon Hunter 	__drm_atomic_helper_connector_reset(connector, &state->base);
799ebd14afeSThierry Reding }
800ebd14afeSThierry Reding 
801ebd14afeSThierry Reding static struct drm_connector_state *
802ebd14afeSThierry Reding tegra_dsi_connector_duplicate_state(struct drm_connector *connector)
803ebd14afeSThierry Reding {
804ebd14afeSThierry Reding 	struct tegra_dsi_state *state = to_dsi_state(connector->state);
805ebd14afeSThierry Reding 	struct tegra_dsi_state *copy;
806ebd14afeSThierry Reding 
807ebd14afeSThierry Reding 	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
808ebd14afeSThierry Reding 	if (!copy)
809ebd14afeSThierry Reding 		return NULL;
810ebd14afeSThierry Reding 
811280dc0e1SJon Hunter 	__drm_atomic_helper_connector_duplicate_state(connector,
812280dc0e1SJon Hunter 						      &copy->base);
813280dc0e1SJon Hunter 
814ebd14afeSThierry Reding 	return &copy->base;
815ebd14afeSThierry Reding }
816ebd14afeSThierry Reding 
8175b901e78SThierry Reding static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
818171e2e6dSThierry Reding 	.dpms = drm_atomic_helper_connector_dpms,
819ebd14afeSThierry Reding 	.reset = tegra_dsi_connector_reset,
8205b901e78SThierry Reding 	.detect = tegra_output_connector_detect,
8215b901e78SThierry Reding 	.fill_modes = drm_helper_probe_single_connector_modes,
8225b901e78SThierry Reding 	.destroy = tegra_output_connector_destroy,
823ebd14afeSThierry Reding 	.atomic_duplicate_state = tegra_dsi_connector_duplicate_state,
8244aa3df71SThierry Reding 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
8255b901e78SThierry Reding };
8265b901e78SThierry Reding 
8275b901e78SThierry Reding static enum drm_mode_status
8285b901e78SThierry Reding tegra_dsi_connector_mode_valid(struct drm_connector *connector,
8295b901e78SThierry Reding 			       struct drm_display_mode *mode)
8305b901e78SThierry Reding {
8315b901e78SThierry Reding 	return MODE_OK;
8325b901e78SThierry Reding }
8335b901e78SThierry Reding 
8345b901e78SThierry Reding static const struct drm_connector_helper_funcs tegra_dsi_connector_helper_funcs = {
8355b901e78SThierry Reding 	.get_modes = tegra_output_connector_get_modes,
8365b901e78SThierry Reding 	.mode_valid = tegra_dsi_connector_mode_valid,
8375b901e78SThierry Reding 	.best_encoder = tegra_output_connector_best_encoder,
8385b901e78SThierry Reding };
8395b901e78SThierry Reding 
8405b901e78SThierry Reding static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
8415b901e78SThierry Reding 	.destroy = tegra_output_encoder_destroy,
8425b901e78SThierry Reding };
8435b901e78SThierry Reding 
8445b901e78SThierry Reding static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
8455b901e78SThierry Reding {
8465b901e78SThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
8475b901e78SThierry Reding 	struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
8485b901e78SThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
8495b901e78SThierry Reding 	u32 value;
8505b901e78SThierry Reding 	int err;
8515b901e78SThierry Reding 
8525b901e78SThierry Reding 	if (output->panel)
8535b901e78SThierry Reding 		drm_panel_disable(output->panel);
8545b901e78SThierry Reding 
8555b901e78SThierry Reding 	tegra_dsi_video_disable(dsi);
8565b901e78SThierry Reding 
8575b901e78SThierry Reding 	/*
8585b901e78SThierry Reding 	 * The following accesses registers of the display controller, so make
8595b901e78SThierry Reding 	 * sure it's only executed when the output is attached to one.
8605b901e78SThierry Reding 	 */
8615b901e78SThierry Reding 	if (dc) {
8625b901e78SThierry Reding 		value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
8635b901e78SThierry Reding 		value &= ~DSI_ENABLE;
8645b901e78SThierry Reding 		tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
8655b901e78SThierry Reding 
8665b901e78SThierry Reding 		tegra_dc_commit(dc);
8675b901e78SThierry Reding 	}
8685b901e78SThierry Reding 
8695b901e78SThierry Reding 	err = tegra_dsi_wait_idle(dsi, 100);
8705b901e78SThierry Reding 	if (err < 0)
8715b901e78SThierry Reding 		dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
8725b901e78SThierry Reding 
8735b901e78SThierry Reding 	tegra_dsi_soft_reset(dsi);
8745b901e78SThierry Reding 
8755b901e78SThierry Reding 	if (output->panel)
8765b901e78SThierry Reding 		drm_panel_unprepare(output->panel);
8775b901e78SThierry Reding 
8785b901e78SThierry Reding 	tegra_dsi_disable(dsi);
8795b901e78SThierry Reding 
880ef8187d7SThierry Reding 	pm_runtime_put(dsi->dev);
8815b901e78SThierry Reding }
8825b901e78SThierry Reding 
883171e2e6dSThierry Reding static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
884171e2e6dSThierry Reding {
885171e2e6dSThierry Reding 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
886171e2e6dSThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
887171e2e6dSThierry Reding 	struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
888171e2e6dSThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
889171e2e6dSThierry Reding 	struct tegra_dsi_state *state;
890171e2e6dSThierry Reding 	u32 value;
891ef8187d7SThierry Reding 	int err;
892ef8187d7SThierry Reding 
893ef8187d7SThierry Reding 	pm_runtime_get_sync(dsi->dev);
894ef8187d7SThierry Reding 
895ef8187d7SThierry Reding 	err = tegra_dsi_pad_calibrate(dsi);
896ef8187d7SThierry Reding 	if (err < 0)
897ef8187d7SThierry Reding 		dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
898171e2e6dSThierry Reding 
899171e2e6dSThierry Reding 	state = tegra_dsi_get_state(dsi);
900171e2e6dSThierry Reding 
901171e2e6dSThierry Reding 	tegra_dsi_set_timeout(dsi, state->bclk, state->vrefresh);
902171e2e6dSThierry Reding 
903171e2e6dSThierry Reding 	/*
904171e2e6dSThierry Reding 	 * The D-PHY timing fields are expressed in byte-clock cycles, so
905171e2e6dSThierry Reding 	 * multiply the period by 8.
906171e2e6dSThierry Reding 	 */
907171e2e6dSThierry Reding 	tegra_dsi_set_phy_timing(dsi, state->period * 8, &state->timing);
908171e2e6dSThierry Reding 
909171e2e6dSThierry Reding 	if (output->panel)
910171e2e6dSThierry Reding 		drm_panel_prepare(output->panel);
911171e2e6dSThierry Reding 
912171e2e6dSThierry Reding 	tegra_dsi_configure(dsi, dc->pipe, mode);
913171e2e6dSThierry Reding 
914171e2e6dSThierry Reding 	/* enable display controller */
915171e2e6dSThierry Reding 	value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
916171e2e6dSThierry Reding 	value |= DSI_ENABLE;
917171e2e6dSThierry Reding 	tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
918171e2e6dSThierry Reding 
919171e2e6dSThierry Reding 	tegra_dc_commit(dc);
920171e2e6dSThierry Reding 
921171e2e6dSThierry Reding 	/* enable DSI controller */
922171e2e6dSThierry Reding 	tegra_dsi_enable(dsi);
923171e2e6dSThierry Reding 
924171e2e6dSThierry Reding 	if (output->panel)
925171e2e6dSThierry Reding 		drm_panel_enable(output->panel);
926171e2e6dSThierry Reding }
927171e2e6dSThierry Reding 
928ebd14afeSThierry Reding static int
929ebd14afeSThierry Reding tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
930ebd14afeSThierry Reding 			       struct drm_crtc_state *crtc_state,
931ebd14afeSThierry Reding 			       struct drm_connector_state *conn_state)
932ebd14afeSThierry Reding {
933ebd14afeSThierry Reding 	struct tegra_output *output = encoder_to_output(encoder);
934ebd14afeSThierry Reding 	struct tegra_dsi_state *state = to_dsi_state(conn_state);
935ebd14afeSThierry Reding 	struct tegra_dc *dc = to_tegra_dc(conn_state->crtc);
936ebd14afeSThierry Reding 	struct tegra_dsi *dsi = to_dsi(output);
937ebd14afeSThierry Reding 	unsigned int scdiv;
938ebd14afeSThierry Reding 	unsigned long plld;
939ebd14afeSThierry Reding 	int err;
940ebd14afeSThierry Reding 
941ebd14afeSThierry Reding 	state->pclk = crtc_state->mode.clock * 1000;
942ebd14afeSThierry Reding 
943ebd14afeSThierry Reding 	err = tegra_dsi_get_muldiv(dsi->format, &state->mul, &state->div);
944ebd14afeSThierry Reding 	if (err < 0)
945ebd14afeSThierry Reding 		return err;
946ebd14afeSThierry Reding 
947ebd14afeSThierry Reding 	state->lanes = tegra_dsi_get_lanes(dsi);
948ebd14afeSThierry Reding 
949ebd14afeSThierry Reding 	err = tegra_dsi_get_format(dsi->format, &state->format);
950ebd14afeSThierry Reding 	if (err < 0)
951ebd14afeSThierry Reding 		return err;
952ebd14afeSThierry Reding 
953ebd14afeSThierry Reding 	state->vrefresh = drm_mode_vrefresh(&crtc_state->mode);
954ebd14afeSThierry Reding 
955ebd14afeSThierry Reding 	/* compute byte clock */
956ebd14afeSThierry Reding 	state->bclk = (state->pclk * state->mul) / (state->div * state->lanes);
957ebd14afeSThierry Reding 
958ebd14afeSThierry Reding 	DRM_DEBUG_KMS("mul: %u, div: %u, lanes: %u\n", state->mul, state->div,
959ebd14afeSThierry Reding 		      state->lanes);
960ebd14afeSThierry Reding 	DRM_DEBUG_KMS("format: %u, vrefresh: %u\n", state->format,
961ebd14afeSThierry Reding 		      state->vrefresh);
962ebd14afeSThierry Reding 	DRM_DEBUG_KMS("bclk: %lu\n", state->bclk);
963ebd14afeSThierry Reding 
964ebd14afeSThierry Reding 	/*
965ebd14afeSThierry Reding 	 * Compute bit clock and round up to the next MHz.
966ebd14afeSThierry Reding 	 */
967ebd14afeSThierry Reding 	plld = DIV_ROUND_UP(state->bclk * 8, USEC_PER_SEC) * USEC_PER_SEC;
968ebd14afeSThierry Reding 	state->period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, plld);
969ebd14afeSThierry Reding 
970ebd14afeSThierry Reding 	err = mipi_dphy_timing_get_default(&state->timing, state->period);
971ebd14afeSThierry Reding 	if (err < 0)
972ebd14afeSThierry Reding 		return err;
973ebd14afeSThierry Reding 
974ebd14afeSThierry Reding 	err = mipi_dphy_timing_validate(&state->timing, state->period);
975ebd14afeSThierry Reding 	if (err < 0) {
976ebd14afeSThierry Reding 		dev_err(dsi->dev, "failed to validate D-PHY timing: %d\n", err);
977ebd14afeSThierry Reding 		return err;
978ebd14afeSThierry Reding 	}
979ebd14afeSThierry Reding 
980ebd14afeSThierry Reding 	/*
981ebd14afeSThierry Reding 	 * We divide the frequency by two here, but we make up for that by
982ebd14afeSThierry Reding 	 * setting the shift clock divider (further below) to half of the
983ebd14afeSThierry Reding 	 * correct value.
984ebd14afeSThierry Reding 	 */
985ebd14afeSThierry Reding 	plld /= 2;
986ebd14afeSThierry Reding 
987ebd14afeSThierry Reding 	/*
988ebd14afeSThierry Reding 	 * Derive pixel clock from bit clock using the shift clock divider.
989ebd14afeSThierry Reding 	 * Note that this is only half of what we would expect, but we need
990ebd14afeSThierry Reding 	 * that to make up for the fact that we divided the bit clock by a
991ebd14afeSThierry Reding 	 * factor of two above.
992ebd14afeSThierry Reding 	 *
993ebd14afeSThierry Reding 	 * It's not clear exactly why this is necessary, but the display is
994ebd14afeSThierry Reding 	 * not working properly otherwise. Perhaps the PLLs cannot generate
995ebd14afeSThierry Reding 	 * frequencies sufficiently high.
996ebd14afeSThierry Reding 	 */
997ebd14afeSThierry Reding 	scdiv = ((8 * state->mul) / (state->div * state->lanes)) - 2;
998ebd14afeSThierry Reding 
999ebd14afeSThierry Reding 	err = tegra_dc_state_setup_clock(dc, crtc_state, dsi->clk_parent,
1000ebd14afeSThierry Reding 					 plld, scdiv);
1001ebd14afeSThierry Reding 	if (err < 0) {
1002ebd14afeSThierry Reding 		dev_err(output->dev, "failed to setup CRTC state: %d\n", err);
1003ebd14afeSThierry Reding 		return err;
1004ebd14afeSThierry Reding 	}
1005ebd14afeSThierry Reding 
1006ebd14afeSThierry Reding 	return err;
1007ebd14afeSThierry Reding }
1008ebd14afeSThierry Reding 
10095b901e78SThierry Reding static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
10105b901e78SThierry Reding 	.disable = tegra_dsi_encoder_disable,
1011171e2e6dSThierry Reding 	.enable = tegra_dsi_encoder_enable,
1012ebd14afeSThierry Reding 	.atomic_check = tegra_dsi_encoder_atomic_check,
1013dec72739SThierry Reding };
1014dec72739SThierry Reding 
1015dec72739SThierry Reding static int tegra_dsi_init(struct host1x_client *client)
1016dec72739SThierry Reding {
10179910f5c4SThierry Reding 	struct drm_device *drm = dev_get_drvdata(client->parent);
1018dec72739SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1019dec72739SThierry Reding 	int err;
1020dec72739SThierry Reding 
1021e94236cdSThierry Reding 	/* Gangsters must not register their own outputs. */
1022e94236cdSThierry Reding 	if (!dsi->master) {
1023dec72739SThierry Reding 		dsi->output.dev = client->dev;
1024dec72739SThierry Reding 
10255b901e78SThierry Reding 		drm_connector_init(drm, &dsi->output.connector,
10265b901e78SThierry Reding 				   &tegra_dsi_connector_funcs,
10275b901e78SThierry Reding 				   DRM_MODE_CONNECTOR_DSI);
10285b901e78SThierry Reding 		drm_connector_helper_add(&dsi->output.connector,
10295b901e78SThierry Reding 					 &tegra_dsi_connector_helper_funcs);
10305b901e78SThierry Reding 		dsi->output.connector.dpms = DRM_MODE_DPMS_OFF;
10315b901e78SThierry Reding 
10325b901e78SThierry Reding 		drm_encoder_init(drm, &dsi->output.encoder,
10335b901e78SThierry Reding 				 &tegra_dsi_encoder_funcs,
103413a3d91fSVille Syrjälä 				 DRM_MODE_ENCODER_DSI, NULL);
10355b901e78SThierry Reding 		drm_encoder_helper_add(&dsi->output.encoder,
10365b901e78SThierry Reding 				       &tegra_dsi_encoder_helper_funcs);
10375b901e78SThierry Reding 
10385b901e78SThierry Reding 		drm_mode_connector_attach_encoder(&dsi->output.connector,
10395b901e78SThierry Reding 						  &dsi->output.encoder);
10405b901e78SThierry Reding 		drm_connector_register(&dsi->output.connector);
10415b901e78SThierry Reding 
1042ea130b24SThierry Reding 		err = tegra_output_init(drm, &dsi->output);
1043ef8187d7SThierry Reding 		if (err < 0)
1044ef8187d7SThierry Reding 			dev_err(dsi->dev, "failed to initialize output: %d\n",
1045ea130b24SThierry Reding 				err);
1046ea130b24SThierry Reding 
10475b901e78SThierry Reding 		dsi->output.encoder.possible_crtcs = 0x3;
1048e94236cdSThierry Reding 	}
1049dec72739SThierry Reding 
1050dec72739SThierry Reding 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
10519910f5c4SThierry Reding 		err = tegra_dsi_debugfs_init(dsi, drm->primary);
1052dec72739SThierry Reding 		if (err < 0)
1053dec72739SThierry Reding 			dev_err(dsi->dev, "debugfs setup failed: %d\n", err);
1054dec72739SThierry Reding 	}
1055dec72739SThierry Reding 
1056dec72739SThierry Reding 	return 0;
1057dec72739SThierry Reding }
1058dec72739SThierry Reding 
1059dec72739SThierry Reding static int tegra_dsi_exit(struct host1x_client *client)
1060dec72739SThierry Reding {
1061dec72739SThierry Reding 	struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1062dec72739SThierry Reding 
10635b901e78SThierry Reding 	tegra_output_exit(&dsi->output);
10645b901e78SThierry Reding 
10654009c224SThierry Reding 	if (IS_ENABLED(CONFIG_DEBUG_FS))
10664009c224SThierry Reding 		tegra_dsi_debugfs_exit(dsi);
1067dec72739SThierry Reding 
1068ef8187d7SThierry Reding 	regulator_disable(dsi->vdd);
1069201106d8SThierry Reding 
1070dec72739SThierry Reding 	return 0;
1071dec72739SThierry Reding }
1072dec72739SThierry Reding 
1073dec72739SThierry Reding static const struct host1x_client_ops dsi_client_ops = {
1074dec72739SThierry Reding 	.init = tegra_dsi_init,
1075dec72739SThierry Reding 	.exit = tegra_dsi_exit,
1076dec72739SThierry Reding };
1077dec72739SThierry Reding 
1078dec72739SThierry Reding static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
1079dec72739SThierry Reding {
1080dec72739SThierry Reding 	struct clk *parent;
1081dec72739SThierry Reding 	int err;
1082dec72739SThierry Reding 
1083dec72739SThierry Reding 	parent = clk_get_parent(dsi->clk);
1084dec72739SThierry Reding 	if (!parent)
1085dec72739SThierry Reding 		return -EINVAL;
1086dec72739SThierry Reding 
1087dec72739SThierry Reding 	err = clk_set_parent(parent, dsi->clk_parent);
1088dec72739SThierry Reding 	if (err < 0)
1089dec72739SThierry Reding 		return err;
1090dec72739SThierry Reding 
1091dec72739SThierry Reding 	return 0;
1092dec72739SThierry Reding }
1093dec72739SThierry Reding 
10940fffdf6cSThierry Reding static const char * const error_report[16] = {
10950fffdf6cSThierry Reding 	"SoT Error",
10960fffdf6cSThierry Reding 	"SoT Sync Error",
10970fffdf6cSThierry Reding 	"EoT Sync Error",
10980fffdf6cSThierry Reding 	"Escape Mode Entry Command Error",
10990fffdf6cSThierry Reding 	"Low-Power Transmit Sync Error",
11000fffdf6cSThierry Reding 	"Peripheral Timeout Error",
11010fffdf6cSThierry Reding 	"False Control Error",
11020fffdf6cSThierry Reding 	"Contention Detected",
11030fffdf6cSThierry Reding 	"ECC Error, single-bit",
11040fffdf6cSThierry Reding 	"ECC Error, multi-bit",
11050fffdf6cSThierry Reding 	"Checksum Error",
11060fffdf6cSThierry Reding 	"DSI Data Type Not Recognized",
11070fffdf6cSThierry Reding 	"DSI VC ID Invalid",
11080fffdf6cSThierry Reding 	"Invalid Transmission Length",
11090fffdf6cSThierry Reding 	"Reserved",
11100fffdf6cSThierry Reding 	"DSI Protocol Violation",
11110fffdf6cSThierry Reding };
11120fffdf6cSThierry Reding 
11130fffdf6cSThierry Reding static ssize_t tegra_dsi_read_response(struct tegra_dsi *dsi,
11140fffdf6cSThierry Reding 				       const struct mipi_dsi_msg *msg,
11150fffdf6cSThierry Reding 				       size_t count)
11160fffdf6cSThierry Reding {
11170fffdf6cSThierry Reding 	u8 *rx = msg->rx_buf;
11180fffdf6cSThierry Reding 	unsigned int i, j, k;
11190fffdf6cSThierry Reding 	size_t size = 0;
11200fffdf6cSThierry Reding 	u16 errors;
11210fffdf6cSThierry Reding 	u32 value;
11220fffdf6cSThierry Reding 
11230fffdf6cSThierry Reding 	/* read and parse packet header */
11240fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_RD_DATA);
11250fffdf6cSThierry Reding 
11260fffdf6cSThierry Reding 	switch (value & 0x3f) {
11270fffdf6cSThierry Reding 	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
11280fffdf6cSThierry Reding 		errors = (value >> 8) & 0xffff;
11290fffdf6cSThierry Reding 		dev_dbg(dsi->dev, "Acknowledge and error report: %04x\n",
11300fffdf6cSThierry Reding 			errors);
11310fffdf6cSThierry Reding 		for (i = 0; i < ARRAY_SIZE(error_report); i++)
11320fffdf6cSThierry Reding 			if (errors & BIT(i))
11330fffdf6cSThierry Reding 				dev_dbg(dsi->dev, "  %2u: %s\n", i,
11340fffdf6cSThierry Reding 					error_report[i]);
11350fffdf6cSThierry Reding 		break;
11360fffdf6cSThierry Reding 
11370fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
11380fffdf6cSThierry Reding 		rx[0] = (value >> 8) & 0xff;
11390fffdf6cSThierry Reding 		size = 1;
11400fffdf6cSThierry Reding 		break;
11410fffdf6cSThierry Reding 
11420fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
11430fffdf6cSThierry Reding 		rx[0] = (value >>  8) & 0xff;
11440fffdf6cSThierry Reding 		rx[1] = (value >> 16) & 0xff;
11450fffdf6cSThierry Reding 		size = 2;
11460fffdf6cSThierry Reding 		break;
11470fffdf6cSThierry Reding 
11480fffdf6cSThierry Reding 	case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
11490fffdf6cSThierry Reding 		size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
11500fffdf6cSThierry Reding 		break;
11510fffdf6cSThierry Reding 
11520fffdf6cSThierry Reding 	case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
11530fffdf6cSThierry Reding 		size = ((value >> 8) & 0xff00) | ((value >> 8) & 0xff);
11540fffdf6cSThierry Reding 		break;
11550fffdf6cSThierry Reding 
11560fffdf6cSThierry Reding 	default:
11570fffdf6cSThierry Reding 		dev_err(dsi->dev, "unhandled response type: %02x\n",
11580fffdf6cSThierry Reding 			value & 0x3f);
11590fffdf6cSThierry Reding 		return -EPROTO;
11600fffdf6cSThierry Reding 	}
11610fffdf6cSThierry Reding 
11620fffdf6cSThierry Reding 	size = min(size, msg->rx_len);
11630fffdf6cSThierry Reding 
11640fffdf6cSThierry Reding 	if (msg->rx_buf && size > 0) {
11650fffdf6cSThierry Reding 		for (i = 0, j = 0; i < count - 1; i++, j += 4) {
11660fffdf6cSThierry Reding 			u8 *rx = msg->rx_buf + j;
11670fffdf6cSThierry Reding 
11680fffdf6cSThierry Reding 			value = tegra_dsi_readl(dsi, DSI_RD_DATA);
11690fffdf6cSThierry Reding 
11700fffdf6cSThierry Reding 			for (k = 0; k < 4 && (j + k) < msg->rx_len; k++)
11710fffdf6cSThierry Reding 				rx[j + k] = (value >> (k << 3)) & 0xff;
11720fffdf6cSThierry Reding 		}
11730fffdf6cSThierry Reding 	}
11740fffdf6cSThierry Reding 
11750fffdf6cSThierry Reding 	return size;
11760fffdf6cSThierry Reding }
11770fffdf6cSThierry Reding 
11780fffdf6cSThierry Reding static int tegra_dsi_transmit(struct tegra_dsi *dsi, unsigned long timeout)
11790fffdf6cSThierry Reding {
11800fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, DSI_TRIGGER_HOST, DSI_TRIGGER);
11810fffdf6cSThierry Reding 
11820fffdf6cSThierry Reding 	timeout = jiffies + msecs_to_jiffies(timeout);
11830fffdf6cSThierry Reding 
11840fffdf6cSThierry Reding 	while (time_before(jiffies, timeout)) {
11850fffdf6cSThierry Reding 		u32 value = tegra_dsi_readl(dsi, DSI_TRIGGER);
11860fffdf6cSThierry Reding 		if ((value & DSI_TRIGGER_HOST) == 0)
11870fffdf6cSThierry Reding 			return 0;
11880fffdf6cSThierry Reding 
11890fffdf6cSThierry Reding 		usleep_range(1000, 2000);
11900fffdf6cSThierry Reding 	}
11910fffdf6cSThierry Reding 
11920fffdf6cSThierry Reding 	DRM_DEBUG_KMS("timeout waiting for transmission to complete\n");
11930fffdf6cSThierry Reding 	return -ETIMEDOUT;
11940fffdf6cSThierry Reding }
11950fffdf6cSThierry Reding 
11960fffdf6cSThierry Reding static int tegra_dsi_wait_for_response(struct tegra_dsi *dsi,
11970fffdf6cSThierry Reding 				       unsigned long timeout)
11980fffdf6cSThierry Reding {
11990fffdf6cSThierry Reding 	timeout = jiffies + msecs_to_jiffies(250);
12000fffdf6cSThierry Reding 
12010fffdf6cSThierry Reding 	while (time_before(jiffies, timeout)) {
12020fffdf6cSThierry Reding 		u32 value = tegra_dsi_readl(dsi, DSI_STATUS);
12030fffdf6cSThierry Reding 		u8 count = value & 0x1f;
12040fffdf6cSThierry Reding 
12050fffdf6cSThierry Reding 		if (count > 0)
12060fffdf6cSThierry Reding 			return count;
12070fffdf6cSThierry Reding 
12080fffdf6cSThierry Reding 		usleep_range(1000, 2000);
12090fffdf6cSThierry Reding 	}
12100fffdf6cSThierry Reding 
12110fffdf6cSThierry Reding 	DRM_DEBUG_KMS("peripheral returned no data\n");
12120fffdf6cSThierry Reding 	return -ETIMEDOUT;
12130fffdf6cSThierry Reding }
12140fffdf6cSThierry Reding 
12150fffdf6cSThierry Reding static void tegra_dsi_writesl(struct tegra_dsi *dsi, unsigned long offset,
12160fffdf6cSThierry Reding 			      const void *buffer, size_t size)
12170fffdf6cSThierry Reding {
12180fffdf6cSThierry Reding 	const u8 *buf = buffer;
12190fffdf6cSThierry Reding 	size_t i, j;
12200fffdf6cSThierry Reding 	u32 value;
12210fffdf6cSThierry Reding 
12220fffdf6cSThierry Reding 	for (j = 0; j < size; j += 4) {
12230fffdf6cSThierry Reding 		value = 0;
12240fffdf6cSThierry Reding 
12250fffdf6cSThierry Reding 		for (i = 0; i < 4 && j + i < size; i++)
12260fffdf6cSThierry Reding 			value |= buf[j + i] << (i << 3);
12270fffdf6cSThierry Reding 
12280fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_WR_DATA);
12290fffdf6cSThierry Reding 	}
12300fffdf6cSThierry Reding }
12310fffdf6cSThierry Reding 
12320fffdf6cSThierry Reding static ssize_t tegra_dsi_host_transfer(struct mipi_dsi_host *host,
12330fffdf6cSThierry Reding 				       const struct mipi_dsi_msg *msg)
12340fffdf6cSThierry Reding {
12350fffdf6cSThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
12360fffdf6cSThierry Reding 	struct mipi_dsi_packet packet;
12370fffdf6cSThierry Reding 	const u8 *header;
12380fffdf6cSThierry Reding 	size_t count;
12390fffdf6cSThierry Reding 	ssize_t err;
12400fffdf6cSThierry Reding 	u32 value;
12410fffdf6cSThierry Reding 
12420fffdf6cSThierry Reding 	err = mipi_dsi_create_packet(&packet, msg);
12430fffdf6cSThierry Reding 	if (err < 0)
12440fffdf6cSThierry Reding 		return err;
12450fffdf6cSThierry Reding 
12460fffdf6cSThierry Reding 	header = packet.header;
12470fffdf6cSThierry Reding 
12480fffdf6cSThierry Reding 	/* maximum FIFO depth is 1920 words */
12490fffdf6cSThierry Reding 	if (packet.size > dsi->video_fifo_depth * 4)
12500fffdf6cSThierry Reding 		return -ENOSPC;
12510fffdf6cSThierry Reding 
12520fffdf6cSThierry Reding 	/* reset underflow/overflow flags */
12530fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_STATUS);
12540fffdf6cSThierry Reding 	if (value & (DSI_STATUS_UNDERFLOW | DSI_STATUS_OVERFLOW)) {
12550fffdf6cSThierry Reding 		value = DSI_HOST_CONTROL_FIFO_RESET;
12560fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
12570fffdf6cSThierry Reding 		usleep_range(10, 20);
12580fffdf6cSThierry Reding 	}
12590fffdf6cSThierry Reding 
12600fffdf6cSThierry Reding 	value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
12610fffdf6cSThierry Reding 	value |= DSI_POWER_CONTROL_ENABLE;
12620fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
12630fffdf6cSThierry Reding 
12640fffdf6cSThierry Reding 	usleep_range(5000, 10000);
12650fffdf6cSThierry Reding 
12660fffdf6cSThierry Reding 	value = DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST |
12670fffdf6cSThierry Reding 		DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC;
12680fffdf6cSThierry Reding 
12690fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_USE_LPM) == 0)
12700fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_HS;
12710fffdf6cSThierry Reding 
12720fffdf6cSThierry Reding 	/*
12730fffdf6cSThierry Reding 	 * The host FIFO has a maximum of 64 words, so larger transmissions
12740fffdf6cSThierry Reding 	 * need to use the video FIFO.
12750fffdf6cSThierry Reding 	 */
12760fffdf6cSThierry Reding 	if (packet.size > dsi->host_fifo_depth * 4)
12770fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_FIFO_SEL;
12780fffdf6cSThierry Reding 
12790fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
12800fffdf6cSThierry Reding 
12810fffdf6cSThierry Reding 	/*
12820fffdf6cSThierry Reding 	 * For reads and messages with explicitly requested ACK, generate a
12830fffdf6cSThierry Reding 	 * BTA sequence after the transmission of the packet.
12840fffdf6cSThierry Reding 	 */
12850fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
12860fffdf6cSThierry Reding 	    (msg->rx_buf && msg->rx_len > 0)) {
12870fffdf6cSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_HOST_CONTROL);
12880fffdf6cSThierry Reding 		value |= DSI_HOST_CONTROL_PKT_BTA;
12890fffdf6cSThierry Reding 		tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
12900fffdf6cSThierry Reding 	}
12910fffdf6cSThierry Reding 
12920fffdf6cSThierry Reding 	value = DSI_CONTROL_LANES(0) | DSI_CONTROL_HOST_ENABLE;
12930fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_CONTROL);
12940fffdf6cSThierry Reding 
12950fffdf6cSThierry Reding 	/* write packet header, ECC is generated by hardware */
12960fffdf6cSThierry Reding 	value = header[2] << 16 | header[1] << 8 | header[0];
12970fffdf6cSThierry Reding 	tegra_dsi_writel(dsi, value, DSI_WR_DATA);
12980fffdf6cSThierry Reding 
12990fffdf6cSThierry Reding 	/* write payload (if any) */
13000fffdf6cSThierry Reding 	if (packet.payload_length > 0)
13010fffdf6cSThierry Reding 		tegra_dsi_writesl(dsi, DSI_WR_DATA, packet.payload,
13020fffdf6cSThierry Reding 				  packet.payload_length);
13030fffdf6cSThierry Reding 
13040fffdf6cSThierry Reding 	err = tegra_dsi_transmit(dsi, 250);
13050fffdf6cSThierry Reding 	if (err < 0)
13060fffdf6cSThierry Reding 		return err;
13070fffdf6cSThierry Reding 
13080fffdf6cSThierry Reding 	if ((msg->flags & MIPI_DSI_MSG_REQ_ACK) ||
13090fffdf6cSThierry Reding 	    (msg->rx_buf && msg->rx_len > 0)) {
13100fffdf6cSThierry Reding 		err = tegra_dsi_wait_for_response(dsi, 250);
13110fffdf6cSThierry Reding 		if (err < 0)
13120fffdf6cSThierry Reding 			return err;
13130fffdf6cSThierry Reding 
13140fffdf6cSThierry Reding 		count = err;
13150fffdf6cSThierry Reding 
13160fffdf6cSThierry Reding 		value = tegra_dsi_readl(dsi, DSI_RD_DATA);
13170fffdf6cSThierry Reding 		switch (value) {
13180fffdf6cSThierry Reding 		case 0x84:
13190fffdf6cSThierry Reding 			/*
13200fffdf6cSThierry Reding 			dev_dbg(dsi->dev, "ACK\n");
13210fffdf6cSThierry Reding 			*/
13220fffdf6cSThierry Reding 			break;
13230fffdf6cSThierry Reding 
13240fffdf6cSThierry Reding 		case 0x87:
13250fffdf6cSThierry Reding 			/*
13260fffdf6cSThierry Reding 			dev_dbg(dsi->dev, "ESCAPE\n");
13270fffdf6cSThierry Reding 			*/
13280fffdf6cSThierry Reding 			break;
13290fffdf6cSThierry Reding 
13300fffdf6cSThierry Reding 		default:
13310fffdf6cSThierry Reding 			dev_err(dsi->dev, "unknown status: %08x\n", value);
13320fffdf6cSThierry Reding 			break;
13330fffdf6cSThierry Reding 		}
13340fffdf6cSThierry Reding 
13350fffdf6cSThierry Reding 		if (count > 1) {
13360fffdf6cSThierry Reding 			err = tegra_dsi_read_response(dsi, msg, count);
13370fffdf6cSThierry Reding 			if (err < 0)
13380fffdf6cSThierry Reding 				dev_err(dsi->dev,
13390fffdf6cSThierry Reding 					"failed to parse response: %zd\n",
13400fffdf6cSThierry Reding 					err);
13410fffdf6cSThierry Reding 			else {
13420fffdf6cSThierry Reding 				/*
13430fffdf6cSThierry Reding 				 * For read commands, return the number of
13440fffdf6cSThierry Reding 				 * bytes returned by the peripheral.
13450fffdf6cSThierry Reding 				 */
13460fffdf6cSThierry Reding 				count = err;
13470fffdf6cSThierry Reding 			}
13480fffdf6cSThierry Reding 		}
13490fffdf6cSThierry Reding 	} else {
13500fffdf6cSThierry Reding 		/*
13510fffdf6cSThierry Reding 		 * For write commands, we have transmitted the 4-byte header
13520fffdf6cSThierry Reding 		 * plus the variable-length payload.
13530fffdf6cSThierry Reding 		 */
13540fffdf6cSThierry Reding 		count = 4 + packet.payload_length;
13550fffdf6cSThierry Reding 	}
13560fffdf6cSThierry Reding 
13570fffdf6cSThierry Reding 	return count;
13580fffdf6cSThierry Reding }
13590fffdf6cSThierry Reding 
1360e94236cdSThierry Reding static int tegra_dsi_ganged_setup(struct tegra_dsi *dsi)
1361e94236cdSThierry Reding {
1362e94236cdSThierry Reding 	struct clk *parent;
1363e94236cdSThierry Reding 	int err;
1364e94236cdSThierry Reding 
1365e94236cdSThierry Reding 	/* make sure both DSI controllers share the same PLL */
1366e94236cdSThierry Reding 	parent = clk_get_parent(dsi->slave->clk);
1367e94236cdSThierry Reding 	if (!parent)
1368e94236cdSThierry Reding 		return -EINVAL;
1369e94236cdSThierry Reding 
1370e94236cdSThierry Reding 	err = clk_set_parent(parent, dsi->clk_parent);
1371e94236cdSThierry Reding 	if (err < 0)
1372e94236cdSThierry Reding 		return err;
1373e94236cdSThierry Reding 
1374e94236cdSThierry Reding 	return 0;
1375e94236cdSThierry Reding }
1376e94236cdSThierry Reding 
1377dec72739SThierry Reding static int tegra_dsi_host_attach(struct mipi_dsi_host *host,
1378dec72739SThierry Reding 				 struct mipi_dsi_device *device)
1379dec72739SThierry Reding {
1380dec72739SThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
1381dec72739SThierry Reding 
138217297a28SThierry Reding 	dsi->flags = device->mode_flags;
1383dec72739SThierry Reding 	dsi->format = device->format;
1384dec72739SThierry Reding 	dsi->lanes = device->lanes;
1385dec72739SThierry Reding 
1386e94236cdSThierry Reding 	if (dsi->slave) {
1387e94236cdSThierry Reding 		int err;
1388e94236cdSThierry Reding 
1389e94236cdSThierry Reding 		dev_dbg(dsi->dev, "attaching dual-channel device %s\n",
1390e94236cdSThierry Reding 			dev_name(&device->dev));
1391e94236cdSThierry Reding 
1392e94236cdSThierry Reding 		err = tegra_dsi_ganged_setup(dsi);
1393e94236cdSThierry Reding 		if (err < 0) {
1394e94236cdSThierry Reding 			dev_err(dsi->dev, "failed to set up ganged mode: %d\n",
1395e94236cdSThierry Reding 				err);
1396e94236cdSThierry Reding 			return err;
1397e94236cdSThierry Reding 		}
1398e94236cdSThierry Reding 	}
1399e94236cdSThierry Reding 
1400e94236cdSThierry Reding 	/*
1401e94236cdSThierry Reding 	 * Slaves don't have a panel associated with them, so they provide
1402e94236cdSThierry Reding 	 * merely the second channel.
1403e94236cdSThierry Reding 	 */
1404e94236cdSThierry Reding 	if (!dsi->master) {
1405e94236cdSThierry Reding 		struct tegra_output *output = &dsi->output;
1406e94236cdSThierry Reding 
1407dec72739SThierry Reding 		output->panel = of_drm_find_panel(device->dev.of_node);
1408e94236cdSThierry Reding 		if (output->panel && output->connector.dev) {
1409e94236cdSThierry Reding 			drm_panel_attach(output->panel, &output->connector);
1410dec72739SThierry Reding 			drm_helper_hpd_irq_event(output->connector.dev);
1411dec72739SThierry Reding 		}
1412e94236cdSThierry Reding 	}
1413dec72739SThierry Reding 
1414dec72739SThierry Reding 	return 0;
1415dec72739SThierry Reding }
1416dec72739SThierry Reding 
1417dec72739SThierry Reding static int tegra_dsi_host_detach(struct mipi_dsi_host *host,
1418dec72739SThierry Reding 				 struct mipi_dsi_device *device)
1419dec72739SThierry Reding {
1420dec72739SThierry Reding 	struct tegra_dsi *dsi = host_to_tegra(host);
1421dec72739SThierry Reding 	struct tegra_output *output = &dsi->output;
1422dec72739SThierry Reding 
1423dec72739SThierry Reding 	if (output->panel && &device->dev == output->panel->dev) {
1424ba3df979SThierry Reding 		output->panel = NULL;
1425ba3df979SThierry Reding 
1426dec72739SThierry Reding 		if (output->connector.dev)
1427dec72739SThierry Reding 			drm_helper_hpd_irq_event(output->connector.dev);
1428dec72739SThierry Reding 	}
1429dec72739SThierry Reding 
1430dec72739SThierry Reding 	return 0;
1431dec72739SThierry Reding }
1432dec72739SThierry Reding 
1433dec72739SThierry Reding static const struct mipi_dsi_host_ops tegra_dsi_host_ops = {
1434dec72739SThierry Reding 	.attach = tegra_dsi_host_attach,
1435dec72739SThierry Reding 	.detach = tegra_dsi_host_detach,
14360fffdf6cSThierry Reding 	.transfer = tegra_dsi_host_transfer,
1437dec72739SThierry Reding };
1438dec72739SThierry Reding 
1439e94236cdSThierry Reding static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
1440e94236cdSThierry Reding {
1441e94236cdSThierry Reding 	struct device_node *np;
1442e94236cdSThierry Reding 
1443e94236cdSThierry Reding 	np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0);
1444e94236cdSThierry Reding 	if (np) {
1445e94236cdSThierry Reding 		struct platform_device *gangster = of_find_device_by_node(np);
1446e94236cdSThierry Reding 
1447e94236cdSThierry Reding 		dsi->slave = platform_get_drvdata(gangster);
1448e94236cdSThierry Reding 		of_node_put(np);
1449e94236cdSThierry Reding 
1450e94236cdSThierry Reding 		if (!dsi->slave)
1451e94236cdSThierry Reding 			return -EPROBE_DEFER;
1452e94236cdSThierry Reding 
1453e94236cdSThierry Reding 		dsi->slave->master = dsi;
1454e94236cdSThierry Reding 	}
1455e94236cdSThierry Reding 
1456e94236cdSThierry Reding 	return 0;
1457e94236cdSThierry Reding }
1458e94236cdSThierry Reding 
1459dec72739SThierry Reding static int tegra_dsi_probe(struct platform_device *pdev)
1460dec72739SThierry Reding {
1461dec72739SThierry Reding 	struct tegra_dsi *dsi;
1462dec72739SThierry Reding 	struct resource *regs;
1463dec72739SThierry Reding 	int err;
1464dec72739SThierry Reding 
1465dec72739SThierry Reding 	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
1466dec72739SThierry Reding 	if (!dsi)
1467dec72739SThierry Reding 		return -ENOMEM;
1468dec72739SThierry Reding 
1469dec72739SThierry Reding 	dsi->output.dev = dsi->dev = &pdev->dev;
1470976cebc3SThierry Reding 	dsi->video_fifo_depth = 1920;
1471976cebc3SThierry Reding 	dsi->host_fifo_depth = 64;
1472dec72739SThierry Reding 
1473e94236cdSThierry Reding 	err = tegra_dsi_ganged_probe(dsi);
1474e94236cdSThierry Reding 	if (err < 0)
1475e94236cdSThierry Reding 		return err;
1476e94236cdSThierry Reding 
1477dec72739SThierry Reding 	err = tegra_output_probe(&dsi->output);
1478dec72739SThierry Reding 	if (err < 0)
1479dec72739SThierry Reding 		return err;
1480dec72739SThierry Reding 
1481ba3df979SThierry Reding 	dsi->output.connector.polled = DRM_CONNECTOR_POLL_HPD;
1482ba3df979SThierry Reding 
1483dec72739SThierry Reding 	/*
1484dec72739SThierry Reding 	 * Assume these values by default. When a DSI peripheral driver
1485dec72739SThierry Reding 	 * attaches to the DSI host, the parameters will be taken from
1486dec72739SThierry Reding 	 * the attached device.
1487dec72739SThierry Reding 	 */
148817297a28SThierry Reding 	dsi->flags = MIPI_DSI_MODE_VIDEO;
1489dec72739SThierry Reding 	dsi->format = MIPI_DSI_FMT_RGB888;
1490dec72739SThierry Reding 	dsi->lanes = 4;
1491dec72739SThierry Reding 
1492*64230aa0SJon Hunter 	if (!pdev->dev.pm_domain) {
1493dec72739SThierry Reding 		dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
1494dec72739SThierry Reding 		if (IS_ERR(dsi->rst))
1495dec72739SThierry Reding 			return PTR_ERR(dsi->rst);
1496*64230aa0SJon Hunter 	}
1497dec72739SThierry Reding 
1498dec72739SThierry Reding 	dsi->clk = devm_clk_get(&pdev->dev, NULL);
1499dec72739SThierry Reding 	if (IS_ERR(dsi->clk)) {
1500dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get DSI clock\n");
1501ef8187d7SThierry Reding 		return PTR_ERR(dsi->clk);
1502dec72739SThierry Reding 	}
1503dec72739SThierry Reding 
1504dec72739SThierry Reding 	dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
1505dec72739SThierry Reding 	if (IS_ERR(dsi->clk_lp)) {
1506dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get low-power clock\n");
1507ef8187d7SThierry Reding 		return PTR_ERR(dsi->clk_lp);
1508dec72739SThierry Reding 	}
1509dec72739SThierry Reding 
1510dec72739SThierry Reding 	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1511dec72739SThierry Reding 	if (IS_ERR(dsi->clk_parent)) {
1512dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot get parent clock\n");
1513ef8187d7SThierry Reding 		return PTR_ERR(dsi->clk_parent);
1514dec72739SThierry Reding 	}
1515dec72739SThierry Reding 
15163b077afbSThierry Reding 	dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
15173b077afbSThierry Reding 	if (IS_ERR(dsi->vdd)) {
15183b077afbSThierry Reding 		dev_err(&pdev->dev, "cannot get VDD supply\n");
1519ef8187d7SThierry Reding 		return PTR_ERR(dsi->vdd);
15203b077afbSThierry Reding 	}
15213b077afbSThierry Reding 
1522dec72739SThierry Reding 	err = tegra_dsi_setup_clocks(dsi);
1523dec72739SThierry Reding 	if (err < 0) {
1524dec72739SThierry Reding 		dev_err(&pdev->dev, "cannot setup clocks\n");
1525ef8187d7SThierry Reding 		return err;
1526dec72739SThierry Reding 	}
1527dec72739SThierry Reding 
1528dec72739SThierry Reding 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1529dec72739SThierry Reding 	dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
1530ef8187d7SThierry Reding 	if (IS_ERR(dsi->regs))
1531ef8187d7SThierry Reding 		return PTR_ERR(dsi->regs);
1532dec72739SThierry Reding 
1533dec72739SThierry Reding 	dsi->mipi = tegra_mipi_request(&pdev->dev);
1534ef8187d7SThierry Reding 	if (IS_ERR(dsi->mipi))
1535ef8187d7SThierry Reding 		return PTR_ERR(dsi->mipi);
1536dec72739SThierry Reding 
1537dec72739SThierry Reding 	dsi->host.ops = &tegra_dsi_host_ops;
1538dec72739SThierry Reding 	dsi->host.dev = &pdev->dev;
1539dec72739SThierry Reding 
1540dec72739SThierry Reding 	err = mipi_dsi_host_register(&dsi->host);
1541dec72739SThierry Reding 	if (err < 0) {
1542dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to register DSI host: %d\n", err);
1543d2d0a9d2SThierry Reding 		goto mipi_free;
1544dec72739SThierry Reding 	}
1545dec72739SThierry Reding 
1546ef8187d7SThierry Reding 	platform_set_drvdata(pdev, dsi);
1547ef8187d7SThierry Reding 	pm_runtime_enable(&pdev->dev);
1548ef8187d7SThierry Reding 
1549dec72739SThierry Reding 	INIT_LIST_HEAD(&dsi->client.list);
1550dec72739SThierry Reding 	dsi->client.ops = &dsi_client_ops;
1551dec72739SThierry Reding 	dsi->client.dev = &pdev->dev;
1552dec72739SThierry Reding 
1553dec72739SThierry Reding 	err = host1x_client_register(&dsi->client);
1554dec72739SThierry Reding 	if (err < 0) {
1555dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
1556dec72739SThierry Reding 			err);
1557d2d0a9d2SThierry Reding 		goto unregister;
1558dec72739SThierry Reding 	}
1559dec72739SThierry Reding 
1560dec72739SThierry Reding 	return 0;
1561d2d0a9d2SThierry Reding 
1562d2d0a9d2SThierry Reding unregister:
1563d2d0a9d2SThierry Reding 	mipi_dsi_host_unregister(&dsi->host);
1564d2d0a9d2SThierry Reding mipi_free:
1565d2d0a9d2SThierry Reding 	tegra_mipi_free(dsi->mipi);
1566d2d0a9d2SThierry Reding 	return err;
1567dec72739SThierry Reding }
1568dec72739SThierry Reding 
1569dec72739SThierry Reding static int tegra_dsi_remove(struct platform_device *pdev)
1570dec72739SThierry Reding {
1571dec72739SThierry Reding 	struct tegra_dsi *dsi = platform_get_drvdata(pdev);
1572dec72739SThierry Reding 	int err;
1573dec72739SThierry Reding 
1574ef8187d7SThierry Reding 	pm_runtime_disable(&pdev->dev);
1575ef8187d7SThierry Reding 
1576dec72739SThierry Reding 	err = host1x_client_unregister(&dsi->client);
1577dec72739SThierry Reding 	if (err < 0) {
1578dec72739SThierry Reding 		dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
1579dec72739SThierry Reding 			err);
1580dec72739SThierry Reding 		return err;
1581dec72739SThierry Reding 	}
1582dec72739SThierry Reding 
1583328ec69eSThierry Reding 	tegra_output_remove(&dsi->output);
15845b901e78SThierry Reding 
1585dec72739SThierry Reding 	mipi_dsi_host_unregister(&dsi->host);
1586dec72739SThierry Reding 	tegra_mipi_free(dsi->mipi);
1587dec72739SThierry Reding 
1588ef8187d7SThierry Reding 	return 0;
1589ef8187d7SThierry Reding }
1590ef8187d7SThierry Reding 
1591ef8187d7SThierry Reding #ifdef CONFIG_PM
1592ef8187d7SThierry Reding static int tegra_dsi_suspend(struct device *dev)
1593ef8187d7SThierry Reding {
1594ef8187d7SThierry Reding 	struct tegra_dsi *dsi = dev_get_drvdata(dev);
1595ef8187d7SThierry Reding 	int err;
1596ef8187d7SThierry Reding 
1597*64230aa0SJon Hunter 	if (dsi->rst) {
1598ef8187d7SThierry Reding 		err = reset_control_assert(dsi->rst);
1599ef8187d7SThierry Reding 		if (err < 0) {
1600ef8187d7SThierry Reding 			dev_err(dev, "failed to assert reset: %d\n", err);
1601ef8187d7SThierry Reding 			return err;
1602ef8187d7SThierry Reding 		}
1603*64230aa0SJon Hunter 	}
1604ef8187d7SThierry Reding 
1605ef8187d7SThierry Reding 	usleep_range(1000, 2000);
1606ef8187d7SThierry Reding 
1607dec72739SThierry Reding 	clk_disable_unprepare(dsi->clk_lp);
1608dec72739SThierry Reding 	clk_disable_unprepare(dsi->clk);
1609ef8187d7SThierry Reding 
1610ef8187d7SThierry Reding 	regulator_disable(dsi->vdd);
1611dec72739SThierry Reding 
1612dec72739SThierry Reding 	return 0;
1613dec72739SThierry Reding }
1614dec72739SThierry Reding 
1615ef8187d7SThierry Reding static int tegra_dsi_resume(struct device *dev)
1616ef8187d7SThierry Reding {
1617ef8187d7SThierry Reding 	struct tegra_dsi *dsi = dev_get_drvdata(dev);
1618ef8187d7SThierry Reding 	int err;
1619ef8187d7SThierry Reding 
1620ef8187d7SThierry Reding 	err = regulator_enable(dsi->vdd);
1621ef8187d7SThierry Reding 	if (err < 0) {
1622ef8187d7SThierry Reding 		dev_err(dsi->dev, "failed to enable VDD supply: %d\n", err);
1623ef8187d7SThierry Reding 		return err;
1624ef8187d7SThierry Reding 	}
1625ef8187d7SThierry Reding 
1626ef8187d7SThierry Reding 	err = clk_prepare_enable(dsi->clk);
1627ef8187d7SThierry Reding 	if (err < 0) {
1628ef8187d7SThierry Reding 		dev_err(dev, "cannot enable DSI clock: %d\n", err);
1629ef8187d7SThierry Reding 		goto disable_vdd;
1630ef8187d7SThierry Reding 	}
1631ef8187d7SThierry Reding 
1632ef8187d7SThierry Reding 	err = clk_prepare_enable(dsi->clk_lp);
1633ef8187d7SThierry Reding 	if (err < 0) {
1634ef8187d7SThierry Reding 		dev_err(dev, "cannot enable low-power clock: %d\n", err);
1635ef8187d7SThierry Reding 		goto disable_clk;
1636ef8187d7SThierry Reding 	}
1637ef8187d7SThierry Reding 
1638ef8187d7SThierry Reding 	usleep_range(1000, 2000);
1639ef8187d7SThierry Reding 
1640*64230aa0SJon Hunter 	if (dsi->rst) {
1641ef8187d7SThierry Reding 		err = reset_control_deassert(dsi->rst);
1642ef8187d7SThierry Reding 		if (err < 0) {
1643ef8187d7SThierry Reding 			dev_err(dev, "cannot assert reset: %d\n", err);
1644ef8187d7SThierry Reding 			goto disable_clk_lp;
1645ef8187d7SThierry Reding 		}
1646*64230aa0SJon Hunter 	}
1647ef8187d7SThierry Reding 
1648ef8187d7SThierry Reding 	return 0;
1649ef8187d7SThierry Reding 
1650ef8187d7SThierry Reding disable_clk_lp:
1651ef8187d7SThierry Reding 	clk_disable_unprepare(dsi->clk_lp);
1652ef8187d7SThierry Reding disable_clk:
1653ef8187d7SThierry Reding 	clk_disable_unprepare(dsi->clk);
1654ef8187d7SThierry Reding disable_vdd:
1655ef8187d7SThierry Reding 	regulator_disable(dsi->vdd);
1656ef8187d7SThierry Reding 	return err;
1657ef8187d7SThierry Reding }
1658ef8187d7SThierry Reding #endif
1659ef8187d7SThierry Reding 
1660ef8187d7SThierry Reding static const struct dev_pm_ops tegra_dsi_pm_ops = {
1661ef8187d7SThierry Reding 	SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL)
1662ef8187d7SThierry Reding };
1663ef8187d7SThierry Reding 
1664dec72739SThierry Reding static const struct of_device_id tegra_dsi_of_match[] = {
1665ddfb406bSThierry Reding 	{ .compatible = "nvidia,tegra210-dsi", },
1666c06c7930SThierry Reding 	{ .compatible = "nvidia,tegra132-dsi", },
16677d338587SThierry Reding 	{ .compatible = "nvidia,tegra124-dsi", },
1668dec72739SThierry Reding 	{ .compatible = "nvidia,tegra114-dsi", },
1669dec72739SThierry Reding 	{ },
1670dec72739SThierry Reding };
1671ef70728cSStephen Warren MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
1672dec72739SThierry Reding 
1673dec72739SThierry Reding struct platform_driver tegra_dsi_driver = {
1674dec72739SThierry Reding 	.driver = {
1675dec72739SThierry Reding 		.name = "tegra-dsi",
1676dec72739SThierry Reding 		.of_match_table = tegra_dsi_of_match,
1677ef8187d7SThierry Reding 		.pm = &tegra_dsi_pm_ops,
1678dec72739SThierry Reding 	},
1679dec72739SThierry Reding 	.probe = tegra_dsi_probe,
1680dec72739SThierry Reding 	.remove = tegra_dsi_remove,
1681dec72739SThierry Reding };
1682