aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tegra/dc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/dc')
-rw-r--r--drivers/video/tegra/dc/Makefile10
-rw-r--r--drivers/video/tegra/dc/dc.c3120
-rw-r--r--drivers/video/tegra/dc/dc_priv.h220
-rw-r--r--drivers/video/tegra/dc/dc_reg.h555
-rw-r--r--drivers/video/tegra/dc/dc_sysfs.c327
-rw-r--r--drivers/video/tegra/dc/dsi.c3042
-rw-r--r--drivers/video/tegra/dc/dsi.h375
-rw-r--r--drivers/video/tegra/dc/dsi_regs.h351
-rw-r--r--drivers/video/tegra/dc/edid.c619
-rw-r--r--drivers/video/tegra/dc/edid.h62
-rw-r--r--drivers/video/tegra/dc/ext/Makefile5
-rw-r--r--drivers/video/tegra/dc/ext/control.c279
-rw-r--r--drivers/video/tegra/dc/ext/cursor.c203
-rw-r--r--drivers/video/tegra/dc/ext/dev.c975
-rw-r--r--drivers/video/tegra/dc/ext/events.c197
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h147
-rw-r--r--drivers/video/tegra/dc/ext/util.c78
-rw-r--r--drivers/video/tegra/dc/hdmi.c2381
-rw-r--r--drivers/video/tegra/dc/hdmi.h222
-rw-r--r--drivers/video/tegra/dc/hdmi_reg.h478
-rw-r--r--drivers/video/tegra/dc/nvhdcp.c1259
-rw-r--r--drivers/video/tegra/dc/nvhdcp.h46
-rw-r--r--drivers/video/tegra/dc/nvsd.c906
-rw-r--r--drivers/video/tegra/dc/nvsd.h25
-rw-r--r--drivers/video/tegra/dc/rgb.c160
25 files changed, 16042 insertions, 0 deletions
diff --git a/drivers/video/tegra/dc/Makefile b/drivers/video/tegra/dc/Makefile
new file mode 100644
index 00000000000..01f13918ca6
--- /dev/null
+++ b/drivers/video/tegra/dc/Makefile
@@ -0,0 +1,10 @@
1GCOV_PROFILE := y
2obj-y += dc.o
3obj-y += rgb.o
4obj-y += hdmi.o
5obj-$(CONFIG_TEGRA_NVHDCP) += nvhdcp.o
6obj-y += edid.o
7obj-y += nvsd.o
8obj-y += dsi.o
9obj-y += dc_sysfs.o
10obj-$(CONFIG_TEGRA_DC_EXTENSIONS) += ext/
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
new file mode 100644
index 00000000000..8b3bf041a7d
--- /dev/null
+++ b/drivers/video/tegra/dc/dc.c
@@ -0,0 +1,3120 @@
1/*
2 * drivers/video/tegra/dc/dc.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * Copyright (C) 2010-2012 NVIDIA Corporation
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/err.h>
23#include <linux/errno.h>
24#include <linux/interrupt.h>
25#include <linux/slab.h>
26#include <linux/io.h>
27#include <linux/clk.h>
28#include <linux/mutex.h>
29#include <linux/delay.h>
30#include <linux/dma-mapping.h>
31#include <linux/workqueue.h>
32#include <linux/ktime.h>
33#include <linux/debugfs.h>
34#include <linux/seq_file.h>
35#include <linux/backlight.h>
36#include <video/tegrafb.h>
37#include <drm/drm_fixed.h>
38#ifdef CONFIG_SWITCH
39#include <linux/switch.h>
40#endif
41
42
43#include <mach/clk.h>
44#include <mach/dc.h>
45#include <mach/fb.h>
46#include <mach/mc.h>
47#include <linux/nvhost.h>
48#include <mach/latency_allowance.h>
49
50#include "dc_reg.h"
51#include "dc_priv.h"
52#include "nvsd.h"
53
54#define TEGRA_CRC_LATCHED_DELAY 34
55
56#define DC_COM_PIN_OUTPUT_POLARITY1_INIT_VAL 0x01000000
57#define DC_COM_PIN_OUTPUT_POLARITY3_INIT_VAL 0x0
58
59#ifndef CONFIG_TEGRA_FPGA_PLATFORM
60#define ALL_UF_INT (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)
61#else
62/* ignore underflows when on simulation and fpga platform */
63#define ALL_UF_INT (0)
64#endif
65
66static int no_vsync;
67
68static void _tegra_dc_controller_disable(struct tegra_dc *dc);
69
70module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
71
72static int use_dynamic_emc = 1;
73
74module_param_named(use_dynamic_emc, use_dynamic_emc, int, S_IRUGO | S_IWUSR);
75
76struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
77
78DEFINE_MUTEX(tegra_dc_lock);
79DEFINE_MUTEX(shared_lock);
80
81static const struct {
82 bool h;
83 bool v;
84} can_filter[] = {
85 /* Window A has no filtering */
86 { false, false },
87 /* Window B has both H and V filtering */
88 { true, true },
89 /* Window C has only H filtering */
90 { false, true },
91};
92static inline bool win_use_v_filter(const struct tegra_dc_win *win)
93{
94 return can_filter[win->idx].v &&
95 win->h.full != dfixed_const(win->out_h);
96}
97static inline bool win_use_h_filter(const struct tegra_dc_win *win)
98{
99 return can_filter[win->idx].h &&
100 win->w.full != dfixed_const(win->out_w);
101}
102
103static inline int tegra_dc_fmt_bpp(int fmt)
104{
105 switch (fmt) {
106 case TEGRA_WIN_FMT_P1:
107 return 1;
108
109 case TEGRA_WIN_FMT_P2:
110 return 2;
111
112 case TEGRA_WIN_FMT_P4:
113 return 4;
114
115 case TEGRA_WIN_FMT_P8:
116 return 8;
117
118 case TEGRA_WIN_FMT_B4G4R4A4:
119 case TEGRA_WIN_FMT_B5G5R5A:
120 case TEGRA_WIN_FMT_B5G6R5:
121 case TEGRA_WIN_FMT_AB5G5R5:
122 return 16;
123
124 case TEGRA_WIN_FMT_B8G8R8A8:
125 case TEGRA_WIN_FMT_R8G8B8A8:
126 case TEGRA_WIN_FMT_B6x2G6x2R6x2A8:
127 case TEGRA_WIN_FMT_R6x2G6x2B6x2A8:
128 return 32;
129
130 /* for planar formats, size of the Y plane, 8bit */
131 case TEGRA_WIN_FMT_YCbCr420P:
132 case TEGRA_WIN_FMT_YUV420P:
133 case TEGRA_WIN_FMT_YCbCr422P:
134 case TEGRA_WIN_FMT_YUV422P:
135 case TEGRA_WIN_FMT_YCbCr422R:
136 case TEGRA_WIN_FMT_YUV422R:
137 case TEGRA_WIN_FMT_YCbCr422RA:
138 case TEGRA_WIN_FMT_YUV422RA:
139 return 8;
140
141 case TEGRA_WIN_FMT_YCbCr422:
142 case TEGRA_WIN_FMT_YUV422:
143 /* FIXME: need to know the bpp of these formats */
144 return 0;
145 }
146 return 0;
147}
148
149static inline bool tegra_dc_is_yuv_planar(int fmt)
150{
151 switch (fmt) {
152 case TEGRA_WIN_FMT_YUV420P:
153 case TEGRA_WIN_FMT_YCbCr420P:
154 case TEGRA_WIN_FMT_YCbCr422P:
155 case TEGRA_WIN_FMT_YUV422P:
156 case TEGRA_WIN_FMT_YCbCr422R:
157 case TEGRA_WIN_FMT_YUV422R:
158 case TEGRA_WIN_FMT_YCbCr422RA:
159 case TEGRA_WIN_FMT_YUV422RA:
160 return true;
161 }
162 return false;
163}
164
165#define DUMP_REG(a) do { \
166 snprintf(buff, sizeof(buff), "%-32s\t%03x\t%08lx\n", \
167 #a, a, tegra_dc_readl(dc, a)); \
168 print(data, buff); \
169 } while (0)
170
171static void _dump_regs(struct tegra_dc *dc, void *data,
172 void (* print)(void *data, const char *str))
173{
174 int i;
175 char buff[256];
176
177 tegra_dc_io_start(dc);
178 clk_enable(dc->clk);
179
180 DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
181 DUMP_REG(DC_CMD_DISPLAY_COMMAND);
182 DUMP_REG(DC_CMD_SIGNAL_RAISE);
183 DUMP_REG(DC_CMD_INT_STATUS);
184 DUMP_REG(DC_CMD_INT_MASK);
185 DUMP_REG(DC_CMD_INT_ENABLE);
186 DUMP_REG(DC_CMD_INT_TYPE);
187 DUMP_REG(DC_CMD_INT_POLARITY);
188 DUMP_REG(DC_CMD_SIGNAL_RAISE1);
189 DUMP_REG(DC_CMD_SIGNAL_RAISE2);
190 DUMP_REG(DC_CMD_SIGNAL_RAISE3);
191 DUMP_REG(DC_CMD_STATE_ACCESS);
192 DUMP_REG(DC_CMD_STATE_CONTROL);
193 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
194 DUMP_REG(DC_CMD_REG_ACT_CONTROL);
195
196 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
197 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
198 DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
199 DUMP_REG(DC_DISP_MEM_HIGH_PRIORITY);
200 DUMP_REG(DC_DISP_MEM_HIGH_PRIORITY_TIMER);
201 DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
202 DUMP_REG(DC_DISP_REF_TO_SYNC);
203 DUMP_REG(DC_DISP_SYNC_WIDTH);
204 DUMP_REG(DC_DISP_BACK_PORCH);
205 DUMP_REG(DC_DISP_DISP_ACTIVE);
206 DUMP_REG(DC_DISP_FRONT_PORCH);
207 DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
208 DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
209 DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
210 DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
211 DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
212 DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
213 DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
214 DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
215 DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
216 DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
217 DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
218 DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
219 DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
220 DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
221 DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
222 DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
223 DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
224 DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
225 DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
226 DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
227 DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
228 DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
229 DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
230 DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
231 DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
232 DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
233 DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
234 DUMP_REG(DC_DISP_M0_CONTROL);
235 DUMP_REG(DC_DISP_M1_CONTROL);
236 DUMP_REG(DC_DISP_DI_CONTROL);
237 DUMP_REG(DC_DISP_PP_CONTROL);
238 DUMP_REG(DC_DISP_PP_SELECT_A);
239 DUMP_REG(DC_DISP_PP_SELECT_B);
240 DUMP_REG(DC_DISP_PP_SELECT_C);
241 DUMP_REG(DC_DISP_PP_SELECT_D);
242 DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
243 DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
244 DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
245 DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
246 DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
247 DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
248 DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
249 DUMP_REG(DC_DISP_BORDER_COLOR);
250 DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
251 DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
252 DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
253 DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
254 DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
255 DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
256 DUMP_REG(DC_DISP_CURSOR_START_ADDR);
257 DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
258 DUMP_REG(DC_DISP_CURSOR_POSITION);
259 DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
260 DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
261 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
262 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
263 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
264 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
265 DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
266 DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
267 DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
268 DUMP_REG(DC_DISP_MCCIF_DISPLAY0C_HYST);
269 DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
270 DUMP_REG(DC_DISP_DAC_CRT_CTRL);
271 DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
272
273
274 for (i = 0; i < 3; i++) {
275 print(data, "\n");
276 snprintf(buff, sizeof(buff), "WINDOW %c:\n", 'A' + i);
277 print(data, buff);
278
279 tegra_dc_writel(dc, WINDOW_A_SELECT << i,
280 DC_CMD_DISPLAY_WINDOW_HEADER);
281 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
282 DUMP_REG(DC_WIN_WIN_OPTIONS);
283 DUMP_REG(DC_WIN_BYTE_SWAP);
284 DUMP_REG(DC_WIN_BUFFER_CONTROL);
285 DUMP_REG(DC_WIN_COLOR_DEPTH);
286 DUMP_REG(DC_WIN_POSITION);
287 DUMP_REG(DC_WIN_SIZE);
288 DUMP_REG(DC_WIN_PRESCALED_SIZE);
289 DUMP_REG(DC_WIN_H_INITIAL_DDA);
290 DUMP_REG(DC_WIN_V_INITIAL_DDA);
291 DUMP_REG(DC_WIN_DDA_INCREMENT);
292 DUMP_REG(DC_WIN_LINE_STRIDE);
293 DUMP_REG(DC_WIN_BUF_STRIDE);
294 DUMP_REG(DC_WIN_UV_BUF_STRIDE);
295 DUMP_REG(DC_WIN_BLEND_NOKEY);
296 DUMP_REG(DC_WIN_BLEND_1WIN);
297 DUMP_REG(DC_WIN_BLEND_2WIN_X);
298 DUMP_REG(DC_WIN_BLEND_2WIN_Y);
299 DUMP_REG(DC_WIN_BLEND_3WIN_XY);
300 DUMP_REG(DC_WINBUF_START_ADDR);
301 DUMP_REG(DC_WINBUF_START_ADDR_U);
302 DUMP_REG(DC_WINBUF_START_ADDR_V);
303 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
304 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
305 DUMP_REG(DC_WINBUF_UFLOW_STATUS);
306 DUMP_REG(DC_WIN_CSC_YOF);
307 DUMP_REG(DC_WIN_CSC_KYRGB);
308 DUMP_REG(DC_WIN_CSC_KUR);
309 DUMP_REG(DC_WIN_CSC_KVR);
310 DUMP_REG(DC_WIN_CSC_KUG);
311 DUMP_REG(DC_WIN_CSC_KVG);
312 DUMP_REG(DC_WIN_CSC_KUB);
313 DUMP_REG(DC_WIN_CSC_KVB);
314 }
315
316 DUMP_REG(DC_CMD_DISPLAY_POWER_CONTROL);
317 DUMP_REG(DC_COM_PIN_OUTPUT_ENABLE2);
318 DUMP_REG(DC_COM_PIN_OUTPUT_POLARITY2);
319 DUMP_REG(DC_COM_PIN_OUTPUT_DATA2);
320 DUMP_REG(DC_COM_PIN_INPUT_ENABLE2);
321 DUMP_REG(DC_COM_PIN_OUTPUT_SELECT5);
322 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
323 DUMP_REG(DC_DISP_M1_CONTROL);
324 DUMP_REG(DC_COM_PM1_CONTROL);
325 DUMP_REG(DC_COM_PM1_DUTY_CYCLE);
326 DUMP_REG(DC_DISP_SD_CONTROL);
327
328 clk_disable(dc->clk);
329 tegra_dc_io_end(dc);
330}
331
332#undef DUMP_REG
333
334#ifdef DEBUG
335static void dump_regs_print(void *data, const char *str)
336{
337 struct tegra_dc *dc = data;
338 dev_dbg(&dc->ndev->dev, "%s", str);
339}
340
341static void dump_regs(struct tegra_dc *dc)
342{
343 _dump_regs(dc, dc, dump_regs_print);
344}
345#else /* !DEBUG */
346
347static void dump_regs(struct tegra_dc *dc) {}
348
349#endif /* DEBUG */
350
351#ifdef CONFIG_DEBUG_FS
352
353static void dbg_regs_print(void *data, const char *str)
354{
355 struct seq_file *s = data;
356
357 seq_printf(s, "%s", str);
358}
359
360#undef DUMP_REG
361
362static int dbg_dc_show(struct seq_file *s, void *unused)
363{
364 struct tegra_dc *dc = s->private;
365
366 _dump_regs(dc, s, dbg_regs_print);
367
368 return 0;
369}
370
371
372static int dbg_dc_open(struct inode *inode, struct file *file)
373{
374 return single_open(file, dbg_dc_show, inode->i_private);
375}
376
377static const struct file_operations regs_fops = {
378 .open = dbg_dc_open,
379 .read = seq_read,
380 .llseek = seq_lseek,
381 .release = single_release,
382};
383
384static int dbg_dc_mode_show(struct seq_file *s, void *unused)
385{
386 struct tegra_dc *dc = s->private;
387 struct tegra_dc_mode *m;
388
389 mutex_lock(&dc->lock);
390 m = &dc->mode;
391 seq_printf(s,
392 "pclk: %d\n"
393 "h_ref_to_sync: %d\n"
394 "v_ref_to_sync: %d\n"
395 "h_sync_width: %d\n"
396 "v_sync_width: %d\n"
397 "h_back_porch: %d\n"
398 "v_back_porch: %d\n"
399 "h_active: %d\n"
400 "v_active: %d\n"
401 "h_front_porch: %d\n"
402 "v_front_porch: %d\n"
403 "stereo_mode: %d\n",
404 m->pclk, m->h_ref_to_sync, m->v_ref_to_sync,
405 m->h_sync_width, m->v_sync_width,
406 m->h_back_porch, m->v_back_porch,
407 m->h_active, m->v_active,
408 m->h_front_porch, m->v_front_porch,
409 m->stereo_mode);
410 mutex_unlock(&dc->lock);
411 return 0;
412}
413
414static int dbg_dc_mode_open(struct inode *inode, struct file *file)
415{
416 return single_open(file, dbg_dc_mode_show, inode->i_private);
417}
418
419static const struct file_operations mode_fops = {
420 .open = dbg_dc_mode_open,
421 .read = seq_read,
422 .llseek = seq_lseek,
423 .release = single_release,
424};
425
426static int dbg_dc_stats_show(struct seq_file *s, void *unused)
427{
428 struct tegra_dc *dc = s->private;
429
430 mutex_lock(&dc->lock);
431 seq_printf(s,
432 "underflows: %llu\n"
433 "underflows_a: %llu\n"
434 "underflows_b: %llu\n"
435 "underflows_c: %llu\n",
436 dc->stats.underflows,
437 dc->stats.underflows_a,
438 dc->stats.underflows_b,
439 dc->stats.underflows_c);
440 mutex_unlock(&dc->lock);
441
442 return 0;
443}
444
445static int dbg_dc_stats_open(struct inode *inode, struct file *file)
446{
447 return single_open(file, dbg_dc_stats_show, inode->i_private);
448}
449
450static const struct file_operations stats_fops = {
451 .open = dbg_dc_stats_open,
452 .read = seq_read,
453 .llseek = seq_lseek,
454 .release = single_release,
455};
456
457static void __devexit tegra_dc_remove_debugfs(struct tegra_dc *dc)
458{
459 if (dc->debugdir)
460 debugfs_remove_recursive(dc->debugdir);
461 dc->debugdir = NULL;
462}
463
464static void tegra_dc_create_debugfs(struct tegra_dc *dc)
465{
466 struct dentry *retval;
467
468 dc->debugdir = debugfs_create_dir(dev_name(&dc->ndev->dev), NULL);
469 if (!dc->debugdir)
470 goto remove_out;
471
472 retval = debugfs_create_file("regs", S_IRUGO, dc->debugdir, dc,
473 &regs_fops);
474 if (!retval)
475 goto remove_out;
476
477 retval = debugfs_create_file("mode", S_IRUGO, dc->debugdir, dc,
478 &mode_fops);
479 if (!retval)
480 goto remove_out;
481
482 retval = debugfs_create_file("stats", S_IRUGO, dc->debugdir, dc,
483 &stats_fops);
484 if (!retval)
485 goto remove_out;
486
487 return;
488remove_out:
489 dev_err(&dc->ndev->dev, "could not create debugfs\n");
490 tegra_dc_remove_debugfs(dc);
491}
492
493#else /* !CONFIG_DEBUGFS */
494static inline void tegra_dc_create_debugfs(struct tegra_dc *dc) { };
495static inline void __devexit tegra_dc_remove_debugfs(struct tegra_dc *dc) { };
496#endif /* CONFIG_DEBUGFS */
497
498static int tegra_dc_set(struct tegra_dc *dc, int index)
499{
500 int ret = 0;
501
502 mutex_lock(&tegra_dc_lock);
503 if (index >= TEGRA_MAX_DC) {
504 ret = -EINVAL;
505 goto out;
506 }
507
508 if (dc != NULL && tegra_dcs[index] != NULL) {
509 ret = -EBUSY;
510 goto out;
511 }
512
513 tegra_dcs[index] = dc;
514
515out:
516 mutex_unlock(&tegra_dc_lock);
517
518 return ret;
519}
520
521static unsigned int tegra_dc_has_multiple_dc(void)
522{
523 unsigned int idx;
524 unsigned int cnt = 0;
525 struct tegra_dc *dc;
526
527 mutex_lock(&tegra_dc_lock);
528 for (idx = 0; idx < TEGRA_MAX_DC; idx++)
529 cnt += ((dc = tegra_dcs[idx]) != NULL && dc->enabled) ? 1 : 0;
530 mutex_unlock(&tegra_dc_lock);
531
532 return (cnt > 1);
533}
534
535struct tegra_dc *tegra_dc_get_dc(unsigned idx)
536{
537 if (idx < TEGRA_MAX_DC)
538 return tegra_dcs[idx];
539 else
540 return NULL;
541}
542EXPORT_SYMBOL(tegra_dc_get_dc);
543
544struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
545{
546 if (win >= dc->n_windows)
547 return NULL;
548
549 return &dc->windows[win];
550}
551EXPORT_SYMBOL(tegra_dc_get_window);
552
553static int get_topmost_window(u32 *depths, unsigned long *wins)
554{
555 int idx, best = -1;
556
557 for_each_set_bit(idx, wins, DC_N_WINDOWS) {
558 if (best == -1 || depths[idx] < depths[best])
559 best = idx;
560 }
561 clear_bit(best, wins);
562 return best;
563}
564
565bool tegra_dc_get_connected(struct tegra_dc *dc)
566{
567 return dc->connected;
568}
569EXPORT_SYMBOL(tegra_dc_get_connected);
570
571static u32 blend_topwin(u32 flags)
572{
573 if (flags & TEGRA_WIN_FLAG_BLEND_COVERAGE)
574 return BLEND(NOKEY, ALPHA, 0xff, 0xff);
575 else if (flags & TEGRA_WIN_FLAG_BLEND_PREMULT)
576 return BLEND(NOKEY, PREMULT, 0xff, 0xff);
577 else
578 return BLEND(NOKEY, FIX, 0xff, 0xff);
579}
580
581static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
582{
583 int other;
584
585 for (other = 0; other < DC_N_WINDOWS; other++) {
586 if (other != idx && (xy-- == 0))
587 break;
588 }
589 if (BIT(other) & behind_mask)
590 return blend_topwin(flags[idx]);
591 else if (flags[other])
592 return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
593 else
594 return BLEND(NOKEY, FIX, 0x00, 0x00);
595}
596
597static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
598{
599 unsigned long infront_mask;
600 int first;
601
602 infront_mask = ~(behind_mask | BIT(idx));
603 infront_mask &= (BIT(DC_N_WINDOWS) - 1);
604 first = ffs(infront_mask) - 1;
605
606 if (!infront_mask)
607 return blend_topwin(flags[idx]);
608 else if (behind_mask && first != -1 && flags[first])
609 return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
610 else
611 return BLEND(NOKEY, FIX, 0x0, 0x0);
612}
613
614static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *blend)
615{
616 unsigned long mask = BIT(DC_N_WINDOWS) - 1;
617
618 while (mask) {
619 int idx = get_topmost_window(blend->z, &mask);
620
621 tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
622 DC_CMD_DISPLAY_WINDOW_HEADER);
623 tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
624 DC_WIN_BLEND_NOKEY);
625 tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
626 DC_WIN_BLEND_1WIN);
627 tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
628 DC_WIN_BLEND_2WIN_X);
629 tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
630 DC_WIN_BLEND_2WIN_Y);
631 tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
632 DC_WIN_BLEND_3WIN_XY);
633 }
634}
635
636static void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc)
637{
638 csc->yof = 0x00f0;
639 csc->kyrgb = 0x012a;
640 csc->kur = 0x0000;
641 csc->kvr = 0x0198;
642 csc->kug = 0x039b;
643 csc->kvg = 0x032f;
644 csc->kub = 0x0204;
645 csc->kvb = 0x0000;
646}
647
648static void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc)
649{
650 tegra_dc_writel(dc, csc->yof, DC_WIN_CSC_YOF);
651 tegra_dc_writel(dc, csc->kyrgb, DC_WIN_CSC_KYRGB);
652 tegra_dc_writel(dc, csc->kur, DC_WIN_CSC_KUR);
653 tegra_dc_writel(dc, csc->kvr, DC_WIN_CSC_KVR);
654 tegra_dc_writel(dc, csc->kug, DC_WIN_CSC_KUG);
655 tegra_dc_writel(dc, csc->kvg, DC_WIN_CSC_KVG);
656 tegra_dc_writel(dc, csc->kub, DC_WIN_CSC_KUB);
657 tegra_dc_writel(dc, csc->kvb, DC_WIN_CSC_KVB);
658}
659
660int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx)
661{
662 mutex_lock(&dc->lock);
663
664 if (!dc->enabled) {
665 mutex_unlock(&dc->lock);
666 return -EFAULT;
667 }
668
669 tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
670 DC_CMD_DISPLAY_WINDOW_HEADER);
671
672 tegra_dc_set_csc(dc, &dc->windows[win_idx].csc);
673
674 mutex_unlock(&dc->lock);
675
676 return 0;
677}
678EXPORT_SYMBOL(tegra_dc_update_csc);
679
680static void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut)
681{
682 int i;
683 for (i = 0; i < 256; i++)
684 lut->r[i] = lut->g[i] = lut->b[i] = (u8)i;
685}
686
687static int tegra_dc_loop_lut(struct tegra_dc *dc,
688 struct tegra_dc_win *win,
689 int(*lambda)(struct tegra_dc *dc, int i, u32 rgb))
690{
691 struct tegra_dc_lut *lut = &win->lut;
692 struct tegra_dc_lut *global_lut = &dc->fb_lut;
693 int i;
694 for (i = 0; i < 256; i++) {
695
696 u32 r = (u32)lut->r[i];
697 u32 g = (u32)lut->g[i];
698 u32 b = (u32)lut->b[i];
699
700 if (!(win->ppflags & TEGRA_WIN_PPFLAG_CP_FBOVERRIDE)) {
701 r = (u32)global_lut->r[r];
702 g = (u32)global_lut->g[g];
703 b = (u32)global_lut->b[b];
704 }
705
706 if (!lambda(dc, i, r | (g<<8) | (b<<16)))
707 return 0;
708 }
709 return 1;
710}
711
712static int tegra_dc_lut_isdefaults_lambda(struct tegra_dc *dc, int i, u32 rgb)
713{
714 if (rgb != (i | (i<<8) | (i<<16)))
715 return 0;
716 return 1;
717}
718
719static int tegra_dc_set_lut_setreg_lambda(struct tegra_dc *dc, int i, u32 rgb)
720{
721 tegra_dc_writel(dc, rgb, DC_WIN_COLOR_PALETTE(i));
722 return 1;
723}
724
725static void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win* win)
726{
727 unsigned long val = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);
728
729 tegra_dc_loop_lut(dc, win, tegra_dc_set_lut_setreg_lambda);
730
731 if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
732 val |= CP_ENABLE;
733 else
734 val &= ~CP_ENABLE;
735
736 tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
737}
738
739static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
740{
741 struct tegra_dc_win *win = &dc->windows[win_idx];
742
743 mutex_lock(&dc->lock);
744
745 if (!dc->enabled) {
746 mutex_unlock(&dc->lock);
747 return -EFAULT;
748 }
749
750 if (fbovr > 0)
751 win->ppflags |= TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
752 else if (fbovr == 0)
753 win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
754
755 if (!tegra_dc_loop_lut(dc, win, tegra_dc_lut_isdefaults_lambda))
756 win->ppflags |= TEGRA_WIN_PPFLAG_CP_ENABLE;
757 else
758 win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_ENABLE;
759
760 tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
761 DC_CMD_DISPLAY_WINDOW_HEADER);
762
763 tegra_dc_set_lut(dc, win);
764
765 mutex_unlock(&dc->lock);
766
767 return 0;
768}
769
770int tegra_dc_update_lut(struct tegra_dc *dc, int win_idx, int fboveride)
771{
772 if (win_idx > -1)
773 return tegra_dc_update_winlut(dc, win_idx, fboveride);
774
775 for (win_idx = 0; win_idx < DC_N_WINDOWS; win_idx++) {
776 int err = tegra_dc_update_winlut(dc, win_idx, fboveride);
777 if (err)
778 return err;
779 }
780
781 return 0;
782}
783EXPORT_SYMBOL(tegra_dc_update_lut);
784
785static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
786{
787 unsigned i;
788 unsigned v0 = 128;
789 unsigned v1 = 0;
790 /* linear horizontal and vertical filters */
791 for (i = 0; i < 16; i++) {
792 tegra_dc_writel(dc, (v1 << 16) | (v0 << 8),
793 DC_WIN_H_FILTER_P(i));
794
795 tegra_dc_writel(dc, v0,
796 DC_WIN_V_FILTER_P(i));
797 v0 -= 8;
798 v1 += 8;
799 }
800}
801
802static void tegra_dc_set_latency_allowance(struct tegra_dc *dc,
803 struct tegra_dc_win *w)
804{
805 /* windows A, B, C for first and second display */
806 static const enum tegra_la_id la_id_tab[2][3] = {
807 /* first display */
808 { TEGRA_LA_DISPLAY_0A, TEGRA_LA_DISPLAY_0B,
809 TEGRA_LA_DISPLAY_0C },
810 /* second display */
811 { TEGRA_LA_DISPLAY_0AB, TEGRA_LA_DISPLAY_0BB,
812 TEGRA_LA_DISPLAY_0CB },
813 };
814 /* window B V-filter tap for first and second display. */
815 static const enum tegra_la_id vfilter_tab[2] = {
816 TEGRA_LA_DISPLAY_1B, TEGRA_LA_DISPLAY_1BB,
817 };
818 unsigned long bw;
819
820 BUG_ON(dc->ndev->id >= ARRAY_SIZE(la_id_tab));
821 BUG_ON(dc->ndev->id >= ARRAY_SIZE(vfilter_tab));
822 BUG_ON(w->idx >= ARRAY_SIZE(*la_id_tab));
823
824 bw = w->new_bandwidth;
825
826 /* tegra_dc_get_bandwidth() treats V filter windows as double
827 * bandwidth, but LA has a seperate client for V filter */
828 if (w->idx == 1 && win_use_v_filter(w))
829 bw /= 2;
830
831 /* our bandwidth is in bytes/sec, but LA takes MBps.
832 * round up bandwidth to 1MBps */
833 bw = bw / 1000000 + 1;
834
835#ifdef CONFIG_TEGRA_SILICON_PLATFORM
836 tegra_set_latency_allowance(la_id_tab[dc->ndev->id][w->idx], bw);
837 /* if window B, also set the 1B client for the 2-tap V filter. */
838 if (w->idx == 1)
839 tegra_set_latency_allowance(vfilter_tab[dc->ndev->id], bw);
840#endif
841
842 w->bandwidth = w->new_bandwidth;
843}
844
845static unsigned int tegra_dc_windows_is_overlapped(struct tegra_dc_win *a,
846 struct tegra_dc_win *b)
847{
848 if (!WIN_IS_ENABLED(a) || !WIN_IS_ENABLED(b))
849 return 0;
850
851 /* because memory access to load the fifo can overlap, only care
852 * if windows overlap vertically */
853 return ((a->out_y + a->out_h > b->out_y) && (a->out_y <= b->out_y)) ||
854 ((b->out_y + b->out_h > a->out_y) && (b->out_y <= a->out_y));
855}
856
857static unsigned long tegra_dc_find_max_bandwidth(struct tegra_dc_win *wins[],
858 int n)
859{
860 unsigned i;
861 unsigned j;
862 unsigned overlap_count;
863 unsigned max_bw = 0;
864
865 WARN_ONCE(n > 3, "Code assumes at most 3 windows, bandwidth is likely"
866 "inaccurate.\n");
867
868 /* If we had a large number of windows, we would compute adjacency
869 * graph representing 2 window overlaps, find all cliques in the graph,
870 * assign bandwidth to each clique, and then select the clique with
871 * maximum bandwidth. But because we have at most 3 windows,
872 * implementing proper Bron-Kerbosh algorithm would be an overkill,
873 * brute force will suffice.
874 *
875 * Thus: find maximum bandwidth for either single or a pair of windows
876 * and count number of window pair overlaps. If there are three
877 * pairs, all 3 window overlap.
878 */
879
880 overlap_count = 0;
881 for (i = 0; i < n; i++) {
882 unsigned int bw1;
883
884 if (wins[i] == NULL)
885 continue;
886 bw1 = wins[i]->new_bandwidth;
887 if (bw1 > max_bw)
888 /* Single window */
889 max_bw = bw1;
890
891 for (j = i + 1; j < n; j++) {
892 if (wins[j] == NULL)
893 continue;
894 if (tegra_dc_windows_is_overlapped(wins[i], wins[j])) {
895 unsigned int bw2 = wins[j]->new_bandwidth;
896 if (bw1 + bw2 > max_bw)
897 /* Window pair overlaps */
898 max_bw = bw1 + bw2;
899 overlap_count++;
900 }
901 }
902 }
903
904 if (overlap_count == 3)
905 /* All three windows overlap */
906 max_bw = wins[0]->new_bandwidth + wins[1]->new_bandwidth +
907 wins[2]->new_bandwidth;
908
909 return max_bw;
910}
911
912/*
913 * Calculate peak EMC bandwidth for each enabled window =
914 * pixel_clock * win_bpp * (use_v_filter ? 2 : 1)) * H_scale_factor *
915 * (windows_tiling ? 2 : 1)
916 *
917 *
918 * note:
919 * (*) We use 2 tap V filter, so need double BW if use V filter
920 * (*) Tiling mode on T30 and DDR3 requires double BW
921 */
922static unsigned long tegra_dc_calc_win_bandwidth(struct tegra_dc *dc,
923 struct tegra_dc_win *w)
924{
925 unsigned long ret;
926 int tiled_windows_bw_multiplier;
927 unsigned long bpp;
928
929 if (!WIN_IS_ENABLED(w))
930 return 0;
931
932 if (dfixed_trunc(w->w) == 0 || dfixed_trunc(w->h) == 0 ||
933 w->out_w == 0 || w->out_h == 0)
934 return 0;
935
936 tiled_windows_bw_multiplier =
937 tegra_mc_get_tiled_memory_bandwidth_multiplier();
938
939 /* all of tegra's YUV formats(420 and 422) fetch 2 bytes per pixel,
940 * but the size reported by tegra_dc_fmt_bpp for the planar version
941 * is of the luma plane's size only. */
942 bpp = tegra_dc_is_yuv_planar(w->fmt) ?
943 2 * tegra_dc_fmt_bpp(w->fmt) : tegra_dc_fmt_bpp(w->fmt);
944 /* perform calculations with most significant bits of pixel clock
945 * to prevent overflow of long. */
946 ret = (unsigned long)(dc->mode.pclk >> 16) *
947 bpp / 8 *
948 (win_use_v_filter(w) ? 2 : 1) * dfixed_trunc(w->w) / w->out_w *
949 (WIN_IS_TILED(w) ? tiled_windows_bw_multiplier : 1);
950
951/*
952 * Assuming 48% efficiency: i.e. if we calculate we need 70MBps, we
953 * will request 147MBps from EMC.
954 */
955 ret = ret * 2 + ret / 10;
956
957 /* if overflowed */
958 if (ret > (1UL << 31))
959 return ULONG_MAX;
960
961 return ret << 16; /* restore the scaling we did above */
962}
963
964static unsigned long tegra_dc_get_bandwidth(
965 struct tegra_dc_win *windows[], int n)
966{
967 int i;
968
969 BUG_ON(n > DC_N_WINDOWS);
970
971 /* emc rate and latency allowance both need to know per window
972 * bandwidths */
973 for (i = 0; i < n; i++) {
974 struct tegra_dc_win *w = windows[i];
975 if (w)
976 w->new_bandwidth = tegra_dc_calc_win_bandwidth(w->dc, w);
977 }
978
979 return tegra_dc_find_max_bandwidth(windows, n);
980}
981
982/* to save power, call when display memory clients would be idle */
983static void tegra_dc_clear_bandwidth(struct tegra_dc *dc)
984{
985 if (tegra_is_clk_enabled(dc->emc_clk))
986 clk_disable(dc->emc_clk);
987 dc->emc_clk_rate = 0;
988}
989
990static void tegra_dc_program_bandwidth(struct tegra_dc *dc)
991{
992 unsigned i;
993
994 if (dc->emc_clk_rate != dc->new_emc_clk_rate) {
995 /* going from 0 to non-zero */
996 if (!dc->emc_clk_rate && !tegra_is_clk_enabled(dc->emc_clk))
997 clk_enable(dc->emc_clk);
998
999 dc->emc_clk_rate = dc->new_emc_clk_rate;
1000 clk_set_rate(dc->emc_clk, dc->emc_clk_rate);
1001
1002 if (!dc->new_emc_clk_rate) /* going from non-zero to 0 */
1003 clk_disable(dc->emc_clk);
1004 }
1005
1006 for (i = 0; i < DC_N_WINDOWS; i++) {
1007 struct tegra_dc_win *w = &dc->windows[i];
1008 if (w->bandwidth != w->new_bandwidth && w->new_bandwidth != 0)
1009 tegra_dc_set_latency_allowance(dc, w);
1010 }
1011}
1012
1013static int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n)
1014{
1015 unsigned long new_rate;
1016 struct tegra_dc *dc;
1017
1018 if (!use_dynamic_emc)
1019 return 0;
1020
1021 dc = windows[0]->dc;
1022
1023 /* calculate the new rate based on this POST */
1024 new_rate = tegra_dc_get_bandwidth(windows, n);
1025 new_rate = EMC_BW_TO_FREQ(new_rate);
1026
1027 if (tegra_dc_has_multiple_dc())
1028 new_rate = ULONG_MAX;
1029
1030 dc->new_emc_clk_rate = new_rate;
1031
1032 return 0;
1033}
1034
1035static inline u32 compute_dda_inc(fixed20_12 in, unsigned out_int,
1036 bool v, unsigned Bpp)
1037{
1038 /*
1039 * min(round((prescaled_size_in_pixels - 1) * 0x1000 /
1040 * (post_scaled_size_in_pixels - 1)), MAX)
1041 * Where the value of MAX is as follows:
1042 * For V_DDA_INCREMENT: 15.0 (0xF000)
1043 * For H_DDA_INCREMENT: 4.0 (0x4000) for 4 Bytes/pix formats.
1044 * 8.0 (0x8000) for 2 Bytes/pix formats.
1045 */
1046
1047 fixed20_12 out = dfixed_init(out_int);
1048 u32 dda_inc;
1049 int max;
1050
1051 if (v) {
1052 max = 15;
1053 } else {
1054 switch (Bpp) {
1055 default:
1056 WARN_ON_ONCE(1);
1057 /* fallthrough */
1058 case 4:
1059 max = 4;
1060 break;
1061 case 2:
1062 max = 8;
1063 break;
1064 }
1065 }
1066
1067 out.full = max_t(u32, out.full - dfixed_const(1), dfixed_const(1));
1068 in.full -= dfixed_const(1);
1069
1070 dda_inc = dfixed_div(in, out);
1071
1072 dda_inc = min_t(u32, dda_inc, dfixed_const(max));
1073
1074 return dda_inc;
1075}
1076
1077static inline u32 compute_initial_dda(fixed20_12 in)
1078{
1079 return dfixed_frac(in);
1080}
1081
1082/* does not support updating windows on multiple dcs in one call */
1083int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
1084{
1085 struct tegra_dc *dc;
1086 unsigned long update_mask = GENERAL_ACT_REQ;
1087 unsigned long val;
1088 bool update_blend = false;
1089 int i;
1090
1091 dc = windows[0]->dc;
1092
1093 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
1094 /* Acquire one_shot_lock to avoid race condition between
1095 * cancellation of old delayed work and schedule of new
1096 * delayed work. */
1097 mutex_lock(&dc->one_shot_lock);
1098 cancel_delayed_work_sync(&dc->one_shot_work);
1099 }
1100 mutex_lock(&dc->lock);
1101
1102 if (!dc->enabled) {
1103 mutex_unlock(&dc->lock);
1104 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
1105 mutex_unlock(&dc->one_shot_lock);
1106 return -EFAULT;
1107 }
1108
1109 if (no_vsync)
1110 tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE, DC_CMD_STATE_ACCESS);
1111 else
1112 tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, DC_CMD_STATE_ACCESS);
1113
1114 for (i = 0; i < DC_N_WINDOWS; i++) {
1115 tegra_dc_writel(dc, WINDOW_A_SELECT << i,
1116 DC_CMD_DISPLAY_WINDOW_HEADER);
1117 tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
1118 if (!no_vsync)
1119 update_mask |= WIN_A_ACT_REQ << i;
1120 }
1121
1122 for (i = 0; i < n; i++) {
1123 struct tegra_dc_win *win = windows[i];
1124 unsigned h_dda;
1125 unsigned v_dda;
1126 fixed20_12 h_offset, v_offset;
1127 bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
1128 bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
1129 bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
1130 unsigned Bpp = tegra_dc_fmt_bpp(win->fmt) / 8;
1131 /* Bytes per pixel of bandwidth, used for dda_inc calculation */
1132 unsigned Bpp_bw = Bpp * (yuvp ? 2 : 1);
1133 const bool filter_h = win_use_h_filter(win);
1134 const bool filter_v = win_use_v_filter(win);
1135
1136 if (win->z != dc->blend.z[win->idx]) {
1137 dc->blend.z[win->idx] = win->z;
1138 update_blend = true;
1139 }
1140 if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
1141 dc->blend.flags[win->idx]) {
1142 dc->blend.flags[win->idx] =
1143 win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
1144 update_blend = true;
1145 }
1146
1147 tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
1148 DC_CMD_DISPLAY_WINDOW_HEADER);
1149
1150 if (!no_vsync)
1151 update_mask |= WIN_A_ACT_REQ << win->idx;
1152
1153 if (!WIN_IS_ENABLED(win)) {
1154 tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
1155 continue;
1156 }
1157
1158 tegra_dc_writel(dc, win->fmt, DC_WIN_COLOR_DEPTH);
1159 tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
1160
1161 tegra_dc_writel(dc,
1162 V_POSITION(win->out_y) | H_POSITION(win->out_x),
1163 DC_WIN_POSITION);
1164 tegra_dc_writel(dc,
1165 V_SIZE(win->out_h) | H_SIZE(win->out_w),
1166 DC_WIN_SIZE);
1167 tegra_dc_writel(dc,
1168 V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
1169 H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
1170 DC_WIN_PRESCALED_SIZE);
1171
1172 h_dda = compute_dda_inc(win->w, win->out_w, false, Bpp_bw);
1173 v_dda = compute_dda_inc(win->h, win->out_h, true, Bpp_bw);
1174 tegra_dc_writel(dc, V_DDA_INC(v_dda) | H_DDA_INC(h_dda),
1175 DC_WIN_DDA_INCREMENT);
1176 h_dda = compute_initial_dda(win->x);
1177 v_dda = compute_initial_dda(win->y);
1178 tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
1179 tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
1180
1181 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
1182 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
1183 tegra_dc_writel(dc,
1184 (unsigned long)win->phys_addr,
1185 DC_WINBUF_START_ADDR);
1186
1187 if (!yuvp) {
1188 tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
1189 } else {
1190 tegra_dc_writel(dc,
1191 (unsigned long)win->phys_addr_u,
1192 DC_WINBUF_START_ADDR_U);
1193 tegra_dc_writel(dc,
1194 (unsigned long)win->phys_addr_v,
1195 DC_WINBUF_START_ADDR_V);
1196 tegra_dc_writel(dc,
1197 LINE_STRIDE(win->stride) |
1198 UV_LINE_STRIDE(win->stride_uv),
1199 DC_WIN_LINE_STRIDE);
1200 }
1201
1202 h_offset = win->x;
1203 if (invert_h) {
1204 h_offset.full += win->w.full - dfixed_const(1);
1205 }
1206
1207 v_offset = win->y;
1208 if (invert_v) {
1209 v_offset.full += win->h.full - dfixed_const(1);
1210 }
1211
1212 tegra_dc_writel(dc, dfixed_trunc(h_offset) * Bpp,
1213 DC_WINBUF_ADDR_H_OFFSET);
1214 tegra_dc_writel(dc, dfixed_trunc(v_offset),
1215 DC_WINBUF_ADDR_V_OFFSET);
1216
1217 if (WIN_IS_TILED(win))
1218 tegra_dc_writel(dc,
1219 DC_WIN_BUFFER_ADDR_MODE_TILE |
1220 DC_WIN_BUFFER_ADDR_MODE_TILE_UV,
1221 DC_WIN_BUFFER_ADDR_MODE);
1222 else
1223 tegra_dc_writel(dc,
1224 DC_WIN_BUFFER_ADDR_MODE_LINEAR |
1225 DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
1226 DC_WIN_BUFFER_ADDR_MODE);
1227
1228 val = WIN_ENABLE;
1229 if (yuvp)
1230 val |= CSC_ENABLE;
1231 else if (tegra_dc_fmt_bpp(win->fmt) < 24)
1232 val |= COLOR_EXPAND;
1233
1234 if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
1235 val |= CP_ENABLE;
1236
1237 if (filter_h)
1238 val |= H_FILTER_ENABLE;
1239 if (filter_v)
1240 val |= V_FILTER_ENABLE;
1241
1242 if (invert_h)
1243 val |= H_DIRECTION_DECREMENT;
1244 if (invert_v)
1245 val |= V_DIRECTION_DECREMENT;
1246
1247 tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
1248
1249 win->dirty = no_vsync ? 0 : 1;
1250
1251 dev_dbg(&dc->ndev->dev, "%s():idx=%d z=%d x=%d y=%d w=%d h=%d "
1252 "out_x=%u out_y=%u out_w=%u out_h=%u "
1253 "fmt=%d yuvp=%d Bpp=%u filter_h=%d filter_v=%d",
1254 __func__, win->idx, win->z,
1255 dfixed_trunc(win->x), dfixed_trunc(win->y),
1256 dfixed_trunc(win->w), dfixed_trunc(win->h),
1257 win->out_x, win->out_y, win->out_w, win->out_h,
1258 win->fmt, yuvp, Bpp, filter_h, filter_v);
1259 }
1260
1261 if (update_blend) {
1262 tegra_dc_set_blending(dc, &dc->blend);
1263 for (i = 0; i < DC_N_WINDOWS; i++) {
1264 if (!no_vsync)
1265 dc->windows[i].dirty = 1;
1266 update_mask |= WIN_A_ACT_REQ << i;
1267 }
1268 }
1269
1270 tegra_dc_set_dynamic_emc(windows, n);
1271
1272 tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
1273
1274 tegra_dc_writel(dc, FRAME_END_INT | V_BLANK_INT, DC_CMD_INT_STATUS);
1275 if (!no_vsync) {
1276 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1277 val |= (FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
1278 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
1279 } else {
1280 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1281 val &= ~(FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
1282 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
1283 }
1284
1285 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
1286 schedule_delayed_work(&dc->one_shot_work,
1287 msecs_to_jiffies(dc->one_shot_delay_ms));
1288
1289 /* update EMC clock if calculated bandwidth has changed */
1290 tegra_dc_program_bandwidth(dc);
1291
1292 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
1293 update_mask |= NC_HOST_TRIG;
1294
1295 tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
1296
1297 mutex_unlock(&dc->lock);
1298 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
1299 mutex_unlock(&dc->one_shot_lock);
1300
1301 return 0;
1302}
1303EXPORT_SYMBOL(tegra_dc_update_windows);
1304
1305u32 tegra_dc_get_syncpt_id(const struct tegra_dc *dc, int i)
1306{
1307 return dc->syncpt[i].id;
1308}
1309EXPORT_SYMBOL(tegra_dc_get_syncpt_id);
1310
1311u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc, int i)
1312{
1313 u32 max;
1314
1315 mutex_lock(&dc->lock);
1316 max = nvhost_syncpt_incr_max(&nvhost_get_host(dc->ndev)->syncpt,
1317 dc->syncpt[i].id, ((dc->enabled) ? 1 : 0));
1318 dc->syncpt[i].max = max;
1319 mutex_unlock(&dc->lock);
1320
1321 return max;
1322}
1323
1324void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val)
1325{
1326 mutex_lock(&dc->lock);
1327 if ( dc->enabled )
1328 while (dc->syncpt[i].min < val) {
1329 dc->syncpt[i].min++;
1330 nvhost_syncpt_cpu_incr(
1331 &nvhost_get_host(dc->ndev)->syncpt,
1332 dc->syncpt[i].id);
1333 }
1334 mutex_unlock(&dc->lock);
1335}
1336
1337static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
1338 int n)
1339{
1340 int i;
1341
1342 for (i = 0; i < n; i++) {
1343 if (windows[i]->dirty)
1344 return false;
1345 }
1346
1347 return true;
1348}
1349
1350/* does not support syncing windows on multiple dcs in one call */
1351int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
1352{
1353 if (n < 1 || n > DC_N_WINDOWS)
1354 return -EINVAL;
1355
1356 if (!windows[0]->dc->enabled)
1357 return -EFAULT;
1358
1359#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
1360 /* Don't want to timeout on simulator */
1361 return wait_event_interruptible(windows[0]->dc->wq,
1362 tegra_dc_windows_are_clean(windows, n));
1363#else
1364 return wait_event_interruptible_timeout(windows[0]->dc->wq,
1365 tegra_dc_windows_are_clean(windows, n),
1366 HZ);
1367#endif
1368}
1369EXPORT_SYMBOL(tegra_dc_sync_windows);
1370
1371static unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
1372{
1373#ifdef CONFIG_TEGRA_SILICON_PLATFORM
1374 return clk_get_rate(dc->clk);
1375#else
1376 return 27000000;
1377#endif
1378}
1379
1380static unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk)
1381{
1382 unsigned long rate;
1383 unsigned long div;
1384
1385 rate = tegra_dc_clk_get_rate(dc);
1386
1387 div = DIV_ROUND_CLOSEST(rate * 2, pclk);
1388
1389 if (div < 2)
1390 return 0;
1391
1392 return rate * 2 / div;
1393}
1394
1395static unsigned long tegra_dc_pclk_predict_rate(struct clk *parent, int pclk)
1396{
1397 unsigned long rate;
1398 unsigned long div;
1399
1400 rate = clk_get_rate(parent);
1401
1402 div = DIV_ROUND_CLOSEST(rate * 2, pclk);
1403
1404 if (div < 2)
1405 return 0;
1406
1407 return rate * 2 / div;
1408}
1409
1410void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
1411{
1412 int pclk;
1413
1414 if (dc->out->type == TEGRA_DC_OUT_RGB) {
1415 unsigned long rate;
1416 struct clk *parent_clk =
1417 clk_get_sys(NULL, dc->out->parent_clk ? : "pll_p");
1418
1419 if (dc->out->parent_clk_backup &&
1420 (parent_clk == clk_get_sys(NULL, "pll_p"))) {
1421 rate = tegra_dc_pclk_predict_rate(
1422 parent_clk, dc->mode.pclk);
1423 /* use pll_d as last resort */
1424 if (rate < (dc->mode.pclk / 100 * 99) ||
1425 rate > (dc->mode.pclk / 100 * 109))
1426 parent_clk = clk_get_sys(
1427 NULL, dc->out->parent_clk_backup);
1428 }
1429
1430 if (clk_get_parent(clk) != parent_clk)
1431 clk_set_parent(clk, parent_clk);
1432
1433 if (parent_clk != clk_get_sys(NULL, "pll_p")) {
1434 struct clk *base_clk = clk_get_parent(parent_clk);
1435
1436 /* Assuming either pll_d or pll_d2 is used */
1437 rate = dc->mode.pclk * 2;
1438
1439 if (rate != clk_get_rate(base_clk))
1440 clk_set_rate(base_clk, rate);
1441 }
1442 }
1443
1444 if (dc->out->type == TEGRA_DC_OUT_HDMI) {
1445 unsigned long rate;
1446 struct clk *parent_clk =
1447 clk_get_sys(NULL, dc->out->parent_clk ? : "pll_d_out0");
1448 struct clk *base_clk = clk_get_parent(parent_clk);
1449
1450 /*
1451 * Providing dynamic frequency rate setting for T20/T30 HDMI.
1452 * The required rate needs to be setup at 4x multiplier,
1453 * as out0 is 1/2 of the actual PLL output.
1454 */
1455
1456 rate = dc->mode.pclk * 4;
1457 if (rate != clk_get_rate(base_clk))
1458 clk_set_rate(base_clk, rate);
1459
1460 if (clk_get_parent(clk) != parent_clk)
1461 clk_set_parent(clk, parent_clk);
1462 }
1463
1464 if (dc->out->type == TEGRA_DC_OUT_DSI) {
1465 unsigned long rate;
1466 struct clk *parent_clk;
1467 struct clk *base_clk;
1468
1469 if (clk == dc->clk) {
1470 parent_clk = clk_get_sys(NULL,
1471 dc->out->parent_clk ? : "pll_d_out0");
1472 base_clk = clk_get_parent(parent_clk);
1473 tegra_clk_cfg_ex(base_clk,
1474 TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
1475 } else {
1476 if (dc->pdata->default_out->dsi->dsi_instance) {
1477 parent_clk = clk_get_sys(NULL,
1478 dc->out->parent_clk ? : "pll_d2_out0");
1479 base_clk = clk_get_parent(parent_clk);
1480 tegra_clk_cfg_ex(base_clk,
1481 TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
1482 } else {
1483 parent_clk = clk_get_sys(NULL,
1484 dc->out->parent_clk ? : "pll_d_out0");
1485 base_clk = clk_get_parent(parent_clk);
1486 tegra_clk_cfg_ex(base_clk,
1487 TEGRA_CLK_PLLD_DSI_OUT_ENB, 1);
1488 }
1489 }
1490
1491 rate = dc->mode.pclk * dc->shift_clk_div * 2;
1492 if (rate != clk_get_rate(base_clk))
1493 clk_set_rate(base_clk, rate);
1494
1495 if (clk_get_parent(clk) != parent_clk)
1496 clk_set_parent(clk, parent_clk);
1497 }
1498
1499 pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
1500 tegra_dvfs_set_rate(clk, pclk);
1501}
1502
1503/* return non-zero if constraint is violated */
1504static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
1505{
1506 long a, b;
1507
1508 /* Constraint 5: H_REF_TO_SYNC >= 0 */
1509 a = 0;
1510
1511 /* Constraint 6: H_FRONT_PORT >= (H_REF_TO_SYNC + 1) */
1512 b = mode->h_front_porch - 1;
1513
1514 /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11 */
1515 if (a + mode->h_sync_width + mode->h_back_porch <= 11)
1516 a = 1 + 11 - mode->h_sync_width - mode->h_back_porch;
1517 /* check Constraint 1 and 6 */
1518 if (a > b)
1519 return 1;
1520
1521 /* Constraint 4: H_SYNC_WIDTH >= 1 */
1522 if (mode->h_sync_width < 1)
1523 return 4;
1524
1525 /* Constraint 7: H_DISP_ACTIVE >= 16 */
1526 if (mode->h_active < 16)
1527 return 7;
1528
1529 if (href) {
1530 if (b > a && a % 2)
1531 *href = a + 1; /* use smallest even value */
1532 else
1533 *href = a; /* even or only possible value */
1534 }
1535
1536 return 0;
1537}
1538
1539static int calc_v_ref_to_sync(const struct tegra_dc_mode *mode, int *vref)
1540{
1541 long a;
1542 a = 1; /* Constraint 5: V_REF_TO_SYNC >= 1 */
1543
1544 /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1 */
1545 if (a + mode->v_sync_width + mode->v_back_porch <= 1)
1546 a = 1 + 1 - mode->v_sync_width - mode->v_back_porch;
1547
1548 /* Constraint 6 */
1549 if (mode->v_front_porch < a + 1)
1550 a = mode->v_front_porch - 1;
1551
1552 /* Constraint 4: V_SYNC_WIDTH >= 1 */
1553 if (mode->v_sync_width < 1)
1554 return 4;
1555
1556 /* Constraint 7: V_DISP_ACTIVE >= 16 */
1557 if (mode->v_active < 16)
1558 return 7;
1559
1560 if (vref)
1561 *vref = a;
1562 return 0;
1563}
1564
1565static int calc_ref_to_sync(struct tegra_dc_mode *mode)
1566{
1567 int ret;
1568 ret = calc_h_ref_to_sync(mode, &mode->h_ref_to_sync);
1569 if (ret)
1570 return ret;
1571 ret = calc_v_ref_to_sync(mode, &mode->v_ref_to_sync);
1572 if (ret)
1573 return ret;
1574
1575 return 0;
1576}
1577
1578static bool check_ref_to_sync(struct tegra_dc_mode *mode)
1579{
1580 /* Constraint 1: H_REF_TO_SYNC + H_SYNC_WIDTH + H_BACK_PORCH > 11. */
1581 if (mode->h_ref_to_sync + mode->h_sync_width + mode->h_back_porch <= 11)
1582 return false;
1583
1584 /* Constraint 2: V_REF_TO_SYNC + V_SYNC_WIDTH + V_BACK_PORCH > 1. */
1585 if (mode->v_ref_to_sync + mode->v_sync_width + mode->v_back_porch <= 1)
1586 return false;
1587
1588 /* Constraint 3: V_FRONT_PORCH + V_SYNC_WIDTH + V_BACK_PORCH > 1
1589 * (vertical blank). */
1590 if (mode->v_front_porch + mode->v_sync_width + mode->v_back_porch <= 1)
1591 return false;
1592
1593 /* Constraint 4: V_SYNC_WIDTH >= 1; H_SYNC_WIDTH >= 1. */
1594 if (mode->v_sync_width < 1 || mode->h_sync_width < 1)
1595 return false;
1596
1597 /* Constraint 5: V_REF_TO_SYNC >= 1; H_REF_TO_SYNC >= 0. */
1598 if (mode->v_ref_to_sync < 1 || mode->h_ref_to_sync < 0)
1599 return false;
1600
1601 /* Constraint 6: V_FRONT_PORT >= (V_REF_TO_SYNC + 1);
1602 * H_FRONT_PORT >= (H_REF_TO_SYNC + 1). */
1603 if (mode->v_front_porch < mode->v_ref_to_sync + 1 ||
1604 mode->h_front_porch < mode->h_ref_to_sync + 1)
1605 return false;
1606
1607 /* Constraint 7: H_DISP_ACTIVE >= 16; V_DISP_ACTIVE >= 16. */
1608 if (mode->h_active < 16 || mode->v_active < 16)
1609 return false;
1610
1611 return true;
1612}
1613
1614#ifdef DEBUG
1615/* return in 1000ths of a Hertz */
1616static int calc_refresh(const struct tegra_dc_mode *m)
1617{
1618 long h_total, v_total, refresh;
1619 h_total = m->h_active + m->h_front_porch + m->h_back_porch +
1620 m->h_sync_width;
1621 v_total = m->v_active + m->v_front_porch + m->v_back_porch +
1622 m->v_sync_width;
1623 refresh = m->pclk / h_total;
1624 refresh *= 1000;
1625 refresh /= v_total;
1626 return refresh;
1627}
1628
1629static void print_mode(struct tegra_dc *dc,
1630 const struct tegra_dc_mode *mode, const char *note)
1631{
1632 if (mode) {
1633 int refresh = calc_refresh(dc, mode);
1634 dev_info(&dc->ndev->dev, "%s():MODE:%dx%d@%d.%03uHz pclk=%d\n",
1635 note ? note : "",
1636 mode->h_active, mode->v_active,
1637 refresh / 1000, refresh % 1000,
1638 mode->pclk);
1639 }
1640}
1641#else /* !DEBUG */
1642static inline void print_mode(struct tegra_dc *dc,
1643 const struct tegra_dc_mode *mode, const char *note) { }
1644#endif /* DEBUG */
1645
1646static inline void enable_dc_irq(unsigned int irq)
1647{
1648#ifndef CONFIG_TEGRA_FPGA_PLATFORM
1649 enable_irq(irq);
1650#else
1651 /* Always disable DC interrupts on FPGA. */
1652 disable_irq(irq);
1653#endif
1654}
1655
1656static inline void disable_dc_irq(unsigned int irq)
1657{
1658 disable_irq(irq);
1659}
1660
1661static int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
1662{
1663 unsigned long val;
1664 unsigned long rate;
1665 unsigned long div;
1666 unsigned long pclk;
1667
1668 print_mode(dc, mode, __func__);
1669
1670 /* use default EMC rate when switching modes */
1671 dc->new_emc_clk_rate = tegra_dc_get_default_emc_clk_rate(dc);
1672 tegra_dc_program_bandwidth(dc);
1673
1674 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
1675 tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
1676 DC_DISP_REF_TO_SYNC);
1677 tegra_dc_writel(dc, mode->h_sync_width | (mode->v_sync_width << 16),
1678 DC_DISP_SYNC_WIDTH);
1679 tegra_dc_writel(dc, mode->h_back_porch | (mode->v_back_porch << 16),
1680 DC_DISP_BACK_PORCH);
1681 tegra_dc_writel(dc, mode->h_active | (mode->v_active << 16),
1682 DC_DISP_DISP_ACTIVE);
1683 tegra_dc_writel(dc, mode->h_front_porch | (mode->v_front_porch << 16),
1684 DC_DISP_FRONT_PORCH);
1685
1686 tegra_dc_writel(dc, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL,
1687 DC_DISP_DATA_ENABLE_OPTIONS);
1688
1689 /* TODO: MIPI/CRT/HDMI clock cals */
1690
1691 val = DISP_DATA_FORMAT_DF1P1C;
1692
1693 if (dc->out->align == TEGRA_DC_ALIGN_MSB)
1694 val |= DISP_DATA_ALIGNMENT_MSB;
1695 else
1696 val |= DISP_DATA_ALIGNMENT_LSB;
1697
1698 if (dc->out->order == TEGRA_DC_ORDER_RED_BLUE)
1699 val |= DISP_DATA_ORDER_RED_BLUE;
1700 else
1701 val |= DISP_DATA_ORDER_BLUE_RED;
1702
1703 tegra_dc_writel(dc, val, DC_DISP_DISP_INTERFACE_CONTROL);
1704
1705 rate = tegra_dc_clk_get_rate(dc);
1706
1707 pclk = tegra_dc_pclk_round_rate(dc, mode->pclk);
1708 if (pclk < (mode->pclk / 100 * 99) ||
1709 pclk > (mode->pclk / 100 * 109)) {
1710 dev_err(&dc->ndev->dev,
1711 "can't divide %ld clock to %d -1/+9%% %ld %d %d\n",
1712 rate, mode->pclk,
1713 pclk, (mode->pclk / 100 * 99),
1714 (mode->pclk / 100 * 109));
1715 return -EINVAL;
1716 }
1717
1718 div = (rate * 2 / pclk) - 2;
1719
1720 tegra_dc_writel(dc, 0x00010001,
1721 DC_DISP_SHIFT_CLOCK_OPTIONS);
1722 tegra_dc_writel(dc, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(div),
1723 DC_DISP_DISP_CLOCK_CONTROL);
1724
1725#ifdef CONFIG_SWITCH
1726 switch_set_state(&dc->modeset_switch,
1727 (mode->h_active << 16) | mode->v_active);
1728#endif
1729
1730 tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
1731 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
1732
1733 return 0;
1734}
1735
1736
1737int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
1738{
1739 memcpy(&dc->mode, mode, sizeof(dc->mode));
1740
1741 print_mode(dc, mode, __func__);
1742
1743 return 0;
1744}
1745EXPORT_SYMBOL(tegra_dc_set_mode);
1746
1747int tegra_dc_set_fb_mode(struct tegra_dc *dc,
1748 const struct fb_videomode *fbmode, bool stereo_mode)
1749{
1750 struct tegra_dc_mode mode;
1751
1752 if (!fbmode->pixclock)
1753 return -EINVAL;
1754
1755 mode.pclk = PICOS2KHZ(fbmode->pixclock) * 1000;
1756 mode.h_sync_width = fbmode->hsync_len;
1757 mode.v_sync_width = fbmode->vsync_len;
1758 mode.h_back_porch = fbmode->left_margin;
1759 mode.v_back_porch = fbmode->upper_margin;
1760 mode.h_active = fbmode->xres;
1761 mode.v_active = fbmode->yres;
1762 mode.h_front_porch = fbmode->right_margin;
1763 mode.v_front_porch = fbmode->lower_margin;
1764 mode.stereo_mode = stereo_mode;
1765 if (dc->out->type == TEGRA_DC_OUT_HDMI) {
1766 /* HDMI controller requires h_ref=1, v_ref=1 */
1767 mode.h_ref_to_sync = 1;
1768 mode.v_ref_to_sync = 1;
1769 } else {
1770 calc_ref_to_sync(&mode);
1771 }
1772 if (!check_ref_to_sync(&mode)) {
1773 dev_err(&dc->ndev->dev,
1774 "Display timing doesn't meet restrictions.\n");
1775 return -EINVAL;
1776 }
1777 dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
1778 mode.h_active, mode.v_active, mode.pclk,
1779 mode.h_ref_to_sync, mode.v_ref_to_sync
1780 );
1781
1782#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
1783 /* Double the pixel clock and update v_active only for frame packed mode */
1784 if (mode.stereo_mode) {
1785 mode.pclk *= 2;
1786 /* total v_active = yres*2 + activespace */
1787 mode.v_active = fbmode->yres*2 +
1788 fbmode->vsync_len +
1789 fbmode->upper_margin +
1790 fbmode->lower_margin;
1791 }
1792#endif
1793
1794 mode.flags = 0;
1795
1796 if (!(fbmode->sync & FB_SYNC_HOR_HIGH_ACT))
1797 mode.flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
1798
1799 if (!(fbmode->sync & FB_SYNC_VERT_HIGH_ACT))
1800 mode.flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
1801
1802 return tegra_dc_set_mode(dc, &mode);
1803}
1804EXPORT_SYMBOL(tegra_dc_set_fb_mode);
1805
1806void
1807tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
1808{
1809 unsigned int ctrl;
1810 unsigned long out_sel;
1811 unsigned long cmd_state;
1812
1813 mutex_lock(&dc->lock);
1814 if (!dc->enabled) {
1815 mutex_unlock(&dc->lock);
1816 return;
1817 }
1818
1819 ctrl = ((cfg->period << PM_PERIOD_SHIFT) |
1820 (cfg->clk_div << PM_CLK_DIVIDER_SHIFT) |
1821 cfg->clk_select);
1822
1823 /* The new value should be effected immediately */
1824 cmd_state = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
1825 tegra_dc_writel(dc, (cmd_state | (1 << 2)), DC_CMD_STATE_ACCESS);
1826
1827 if (cfg->switch_to_sfio && cfg->gpio_conf_to_sfio)
1828 cfg->switch_to_sfio(cfg->gpio_conf_to_sfio);
1829 else
1830 dev_err(&dc->ndev->dev, "Error: Need gpio_conf_to_sfio\n");
1831
1832 switch (cfg->which_pwm) {
1833 case TEGRA_PWM_PM0:
1834 /* Select the LM0 on PM0 */
1835 out_sel = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_SELECT5);
1836 out_sel &= ~(7 << 0);
1837 out_sel |= (3 << 0);
1838 tegra_dc_writel(dc, out_sel, DC_COM_PIN_OUTPUT_SELECT5);
1839 tegra_dc_writel(dc, ctrl, DC_COM_PM0_CONTROL);
1840 tegra_dc_writel(dc, cfg->duty_cycle, DC_COM_PM0_DUTY_CYCLE);
1841 break;
1842 case TEGRA_PWM_PM1:
1843 /* Select the LM1 on PM1 */
1844 out_sel = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_SELECT5);
1845 out_sel &= ~(7 << 4);
1846 out_sel |= (3 << 4);
1847 tegra_dc_writel(dc, out_sel, DC_COM_PIN_OUTPUT_SELECT5);
1848 tegra_dc_writel(dc, ctrl, DC_COM_PM1_CONTROL);
1849 tegra_dc_writel(dc, cfg->duty_cycle, DC_COM_PM1_DUTY_CYCLE);
1850 break;
1851 default:
1852 dev_err(&dc->ndev->dev, "Error: Need which_pwm\n");
1853 break;
1854 }
1855 tegra_dc_writel(dc, cmd_state, DC_CMD_STATE_ACCESS);
1856 mutex_unlock(&dc->lock);
1857}
1858EXPORT_SYMBOL(tegra_dc_config_pwm);
1859
1860void tegra_dc_set_out_pin_polars(struct tegra_dc *dc,
1861 const struct tegra_dc_out_pin *pins,
1862 const unsigned int n_pins)
1863{
1864 unsigned int i;
1865
1866 int name;
1867 int pol;
1868
1869 u32 pol1, pol3;
1870
1871 u32 set1, unset1;
1872 u32 set3, unset3;
1873
1874 set1 = set3 = unset1 = unset3 = 0;
1875
1876 for (i = 0; i < n_pins; i++) {
1877 name = (pins + i)->name;
1878 pol = (pins + i)->pol;
1879
1880 /* set polarity by name */
1881 switch (name) {
1882 case TEGRA_DC_OUT_PIN_DATA_ENABLE:
1883 if (pol == TEGRA_DC_OUT_PIN_POL_LOW)
1884 set3 |= LSPI_OUTPUT_POLARITY_LOW;
1885 else
1886 unset3 |= LSPI_OUTPUT_POLARITY_LOW;
1887 break;
1888 case TEGRA_DC_OUT_PIN_H_SYNC:
1889 if (pol == TEGRA_DC_OUT_PIN_POL_LOW)
1890 set1 |= LHS_OUTPUT_POLARITY_LOW;
1891 else
1892 unset1 |= LHS_OUTPUT_POLARITY_LOW;
1893 break;
1894 case TEGRA_DC_OUT_PIN_V_SYNC:
1895 if (pol == TEGRA_DC_OUT_PIN_POL_LOW)
1896 set1 |= LVS_OUTPUT_POLARITY_LOW;
1897 else
1898 unset1 |= LVS_OUTPUT_POLARITY_LOW;
1899 break;
1900 case TEGRA_DC_OUT_PIN_PIXEL_CLOCK:
1901 if (pol == TEGRA_DC_OUT_PIN_POL_LOW)
1902 set1 |= LSC0_OUTPUT_POLARITY_LOW;
1903 else
1904 unset1 |= LSC0_OUTPUT_POLARITY_LOW;
1905 break;
1906 default:
1907 printk("Invalid argument in function %s\n",
1908 __FUNCTION__);
1909 break;
1910 }
1911 }
1912
1913 pol1 = DC_COM_PIN_OUTPUT_POLARITY1_INIT_VAL;
1914 pol3 = DC_COM_PIN_OUTPUT_POLARITY3_INIT_VAL;
1915
1916 pol1 |= set1;
1917 pol1 &= ~unset1;
1918
1919 pol3 |= set3;
1920 pol3 &= ~unset3;
1921
1922 tegra_dc_writel(dc, pol1, DC_COM_PIN_OUTPUT_POLARITY1);
1923 tegra_dc_writel(dc, pol3, DC_COM_PIN_OUTPUT_POLARITY3);
1924}
1925
1926static void tegra_dc_set_out(struct tegra_dc *dc, struct tegra_dc_out *out)
1927{
1928 dc->out = out;
1929
1930 if (out->n_modes > 0)
1931 tegra_dc_set_mode(dc, &dc->out->modes[0]);
1932
1933 switch (out->type) {
1934 case TEGRA_DC_OUT_RGB:
1935 dc->out_ops = &tegra_dc_rgb_ops;
1936 break;
1937
1938 case TEGRA_DC_OUT_HDMI:
1939 dc->out_ops = &tegra_dc_hdmi_ops;
1940 break;
1941
1942 case TEGRA_DC_OUT_DSI:
1943 dc->out_ops = &tegra_dc_dsi_ops;
1944 break;
1945
1946 default:
1947 dc->out_ops = NULL;
1948 break;
1949 }
1950
1951 if (dc->out_ops && dc->out_ops->init)
1952 dc->out_ops->init(dc);
1953
1954}
1955
1956unsigned tegra_dc_get_out_height(const struct tegra_dc *dc)
1957{
1958 if (dc->out)
1959 return dc->out->height;
1960 else
1961 return 0;
1962}
1963EXPORT_SYMBOL(tegra_dc_get_out_height);
1964
1965unsigned tegra_dc_get_out_width(const struct tegra_dc *dc)
1966{
1967 if (dc->out)
1968 return dc->out->width;
1969 else
1970 return 0;
1971}
1972EXPORT_SYMBOL(tegra_dc_get_out_width);
1973
1974unsigned tegra_dc_get_out_max_pixclock(const struct tegra_dc *dc)
1975{
1976 if (dc->out && dc->out->max_pixclock)
1977 return dc->out->max_pixclock;
1978 else
1979 return 0;
1980}
1981EXPORT_SYMBOL(tegra_dc_get_out_max_pixclock);
1982
1983void tegra_dc_enable_crc(struct tegra_dc *dc)
1984{
1985 u32 val;
1986 tegra_dc_io_start(dc);
1987
1988 val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA |
1989 CRC_ENABLE_ENABLE;
1990 tegra_dc_writel(dc, val, DC_COM_CRC_CONTROL);
1991 tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
1992 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
1993}
1994
1995void tegra_dc_disable_crc(struct tegra_dc *dc)
1996{
1997 tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL);
1998 tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
1999 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
2000
2001 tegra_dc_io_end(dc);
2002}
2003
2004u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc)
2005{
2006 int crc = 0;
2007
2008 if(!dc) {
2009 dev_err(&dc->ndev->dev, "Failed to get dc.\n");
2010 goto crc_error;
2011 }
2012
2013 /* TODO: Replace mdelay with code to sync VBlANK, since
2014 * DC_COM_CRC_CHECKSUM_LATCHED is available after VBLANK */
2015 mdelay(TEGRA_CRC_LATCHED_DELAY);
2016
2017 crc = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM_LATCHED);
2018crc_error:
2019 return crc;
2020}
2021
2022static void tegra_dc_vblank(struct work_struct *work)
2023{
2024 struct tegra_dc *dc = container_of(work, struct tegra_dc, vblank_work);
2025 bool nvsd_updated = false;
2026
2027 mutex_lock(&dc->lock);
2028
2029 /* Update the SD brightness */
2030 if (dc->enabled && dc->out->sd_settings)
2031 nvsd_updated = nvsd_update_brightness(dc);
2032
2033 mutex_unlock(&dc->lock);
2034
2035 /* Do the actual brightness update outside of the mutex */
2036 if (nvsd_updated && dc->out->sd_settings &&
2037 dc->out->sd_settings->bl_device) {
2038
2039 struct platform_device *pdev = dc->out->sd_settings->bl_device;
2040 struct backlight_device *bl = platform_get_drvdata(pdev);
2041 if (bl)
2042 backlight_update_status(bl);
2043 }
2044}
2045
2046/* Must acquire dc lock and dc one-shot lock before invoking this function.
2047 * Acquire dc one-shot lock first and then dc lock. */
2048void tegra_dc_host_trigger(struct tegra_dc *dc)
2049{
2050 /* We release the lock here to prevent deadlock between
2051 * cancel_delayed_work_sync and one-shot work. */
2052 mutex_unlock(&dc->lock);
2053
2054 cancel_delayed_work_sync(&dc->one_shot_work);
2055 mutex_lock(&dc->lock);
2056
2057 schedule_delayed_work(&dc->one_shot_work,
2058 msecs_to_jiffies(dc->one_shot_delay_ms));
2059 tegra_dc_program_bandwidth(dc);
2060 tegra_dc_writel(dc, NC_HOST_TRIG, DC_CMD_STATE_CONTROL);
2061}
2062
2063static void tegra_dc_one_shot_worker(struct work_struct *work)
2064{
2065 struct tegra_dc *dc = container_of(
2066 to_delayed_work(work), struct tegra_dc, one_shot_work);
2067 mutex_lock(&dc->lock);
2068 /* memory client has gone idle */
2069 tegra_dc_clear_bandwidth(dc);
2070 mutex_unlock(&dc->lock);
2071}
2072
2073/* return an arbitrarily large number if count overflow occurs.
2074 * make it a nice base-10 number to show up in stats output */
2075static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg)
2076{
2077 unsigned count = tegra_dc_readl(dc, reg);
2078 tegra_dc_writel(dc, 0, reg);
2079 return ((count & 0x80000000) == 0) ? count : 10000000000ll;
2080}
2081
2082static void tegra_dc_underflow_handler(struct tegra_dc *dc)
2083{
2084 u32 val;
2085 int i;
2086
2087 dc->stats.underflows++;
2088 if (dc->underflow_mask & WIN_A_UF_INT)
2089 dc->stats.underflows_a += tegra_dc_underflow_count(dc,
2090 DC_WINBUF_AD_UFLOW_STATUS);
2091 if (dc->underflow_mask & WIN_B_UF_INT)
2092 dc->stats.underflows_b += tegra_dc_underflow_count(dc,
2093 DC_WINBUF_BD_UFLOW_STATUS);
2094 if (dc->underflow_mask & WIN_C_UF_INT)
2095 dc->stats.underflows_c += tegra_dc_underflow_count(dc,
2096 DC_WINBUF_CD_UFLOW_STATUS);
2097
2098 /* Check for any underflow reset conditions */
2099 for (i = 0; i < DC_N_WINDOWS; i++) {
2100 if (dc->underflow_mask & (WIN_A_UF_INT << i)) {
2101 dc->windows[i].underflows++;
2102
2103#ifdef CONFIG_ARCH_TEGRA_2x_SOC
2104 if (dc->windows[i].underflows > 4)
2105 schedule_work(&dc->reset_work);
2106#endif
2107 } else {
2108 dc->windows[i].underflows = 0;
2109 }
2110 }
2111
2112 /* Clear the underflow mask now that we've checked it. */
2113 tegra_dc_writel(dc, dc->underflow_mask, DC_CMD_INT_STATUS);
2114 dc->underflow_mask = 0;
2115 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
2116 tegra_dc_writel(dc, val | ALL_UF_INT, DC_CMD_INT_MASK);
2117}
2118
2119#ifndef CONFIG_TEGRA_FPGA_PLATFORM
2120static bool tegra_dc_windows_are_dirty(struct tegra_dc *dc)
2121{
2122#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
2123 u32 val;
2124
2125 val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
2126 if (val & (WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE))
2127 return true;
2128#endif
2129 return false;
2130}
2131
2132static void tegra_dc_trigger_windows(struct tegra_dc *dc)
2133{
2134 u32 val, i;
2135 u32 completed = 0;
2136 u32 dirty = 0;
2137
2138 val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
2139 for (i = 0; i < DC_N_WINDOWS; i++) {
2140#ifdef CONFIG_TEGRA_SIMULATION_PLATFORM
2141 /* FIXME: this is not needed when the simulator
2142 clears WIN_x_UPDATE bits as in HW */
2143 dc->windows[i].dirty = 0;
2144 completed = 1;
2145#else
2146 if (!(val & (WIN_A_UPDATE << i))) {
2147 dc->windows[i].dirty = 0;
2148 completed = 1;
2149 } else {
2150 dirty = 1;
2151 }
2152#endif
2153 }
2154
2155 if (!dirty) {
2156 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
2157 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
2158 val &= ~V_BLANK_INT;
2159 else
2160 val &= ~FRAME_END_INT;
2161 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
2162 }
2163
2164 if (completed) {
2165 if (!dirty) {
2166 /* With the last completed window, go ahead
2167 and enable the vblank interrupt for nvsd. */
2168 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
2169 val |= V_BLANK_INT;
2170 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
2171 }
2172
2173 wake_up(&dc->wq);
2174 }
2175}
2176
2177static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status)
2178{
2179 if (status & V_BLANK_INT) {
2180 /* Sync up windows. */
2181 tegra_dc_trigger_windows(dc);
2182
2183 /* Schedule any additional bottom-half vblank actvities. */
2184 schedule_work(&dc->vblank_work);
2185 }
2186
2187 if (status & FRAME_END_INT) {
2188 /* Mark the frame_end as complete. */
2189 if (!completion_done(&dc->frame_end_complete))
2190 complete(&dc->frame_end_complete);
2191 }
2192}
2193
2194static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
2195{
2196 if (status & V_BLANK_INT) {
2197 /* Schedule any additional bottom-half vblank actvities. */
2198 schedule_work(&dc->vblank_work);
2199
2200 /* All windows updated. Mask subsequent V_BLANK interrupts */
2201 if (!tegra_dc_windows_are_dirty(dc)) {
2202 u32 val;
2203
2204 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
2205 val &= ~V_BLANK_INT;
2206 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
2207 }
2208 }
2209
2210 if (status & FRAME_END_INT) {
2211 /* Mark the frame_end as complete. */
2212 if (!completion_done(&dc->frame_end_complete))
2213 complete(&dc->frame_end_complete);
2214
2215 tegra_dc_trigger_windows(dc);
2216 }
2217}
2218#endif
2219
2220static irqreturn_t tegra_dc_irq(int irq, void *ptr)
2221{
2222#ifndef CONFIG_TEGRA_FPGA_PLATFORM
2223 struct tegra_dc *dc = ptr;
2224 unsigned long status;
2225 unsigned long underflow_mask;
2226 u32 val;
2227
2228 if (!nvhost_module_powered(nvhost_get_host(dc->ndev)->dev)) {
2229 WARN(1, "IRQ when DC not powered!\n");
2230 tegra_dc_io_start(dc);
2231 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
2232 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
2233 tegra_dc_io_end(dc);
2234 return IRQ_HANDLED;
2235 }
2236
2237 /* clear all status flags except underflow, save those for the worker */
2238 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
2239 tegra_dc_writel(dc, status & ~ALL_UF_INT, DC_CMD_INT_STATUS);
2240 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
2241 tegra_dc_writel(dc, val & ~ALL_UF_INT, DC_CMD_INT_MASK);
2242
2243 /*
2244 * Overlays can get thier internal state corrupted during and underflow
2245 * condition. The only way to fix this state is to reset the DC.
2246 * if we get 4 consecutive frames with underflows, assume we're
2247 * hosed and reset.
2248 */
2249 underflow_mask = status & ALL_UF_INT;
2250
2251 /* Check underflow */
2252 if (underflow_mask) {
2253 dc->underflow_mask |= underflow_mask;
2254 schedule_delayed_work(&dc->underflow_work,
2255 msecs_to_jiffies(1));
2256 }
2257
2258 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
2259 tegra_dc_one_shot_irq(dc, status);
2260 else
2261 tegra_dc_continuous_irq(dc, status);
2262
2263 return IRQ_HANDLED;
2264#else /* CONFIG_TEGRA_FPGA_PLATFORM */
2265 return IRQ_NONE;
2266#endif /* !CONFIG_TEGRA_FPGA_PLATFORM */
2267}
2268
2269static void tegra_dc_set_color_control(struct tegra_dc *dc)
2270{
2271 u32 color_control;
2272
2273 switch (dc->out->depth) {
2274 case 3:
2275 color_control = BASE_COLOR_SIZE111;
2276 break;
2277
2278 case 6:
2279 color_control = BASE_COLOR_SIZE222;
2280 break;
2281
2282 case 8:
2283 color_control = BASE_COLOR_SIZE332;
2284 break;
2285
2286 case 9:
2287 color_control = BASE_COLOR_SIZE333;
2288 break;
2289
2290 case 12:
2291 color_control = BASE_COLOR_SIZE444;
2292 break;
2293
2294 case 15:
2295 color_control = BASE_COLOR_SIZE555;
2296 break;
2297
2298 case 16:
2299 color_control = BASE_COLOR_SIZE565;
2300 break;
2301
2302 case 18:
2303 color_control = BASE_COLOR_SIZE666;
2304 break;
2305
2306 default:
2307 color_control = BASE_COLOR_SIZE888;
2308 break;
2309 }
2310
2311 switch (dc->out->dither) {
2312 case TEGRA_DC_DISABLE_DITHER:
2313 color_control |= DITHER_CONTROL_DISABLE;
2314 break;
2315 case TEGRA_DC_ORDERED_DITHER:
2316 color_control |= DITHER_CONTROL_ORDERED;
2317 break;
2318 case TEGRA_DC_ERRDIFF_DITHER:
2319 /* The line buffer for error-diffusion dither is limited
2320 * to 1280 pixels per line. This limits the maximum
2321 * horizontal active area size to 1280 pixels when error
2322 * diffusion is enabled.
2323 */
2324 BUG_ON(dc->mode.h_active > 1280);
2325 color_control |= DITHER_CONTROL_ERRDIFF;
2326 break;
2327 }
2328
2329 tegra_dc_writel(dc, color_control, DC_DISP_DISP_COLOR_CONTROL);
2330}
2331
2332static u32 get_syncpt(struct tegra_dc *dc, int idx)
2333{
2334 u32 syncpt_id;
2335
2336 switch (dc->ndev->id) {
2337 case 0:
2338 switch (idx) {
2339 case 0:
2340 syncpt_id = NVSYNCPT_DISP0_A;
2341 break;
2342 case 1:
2343 syncpt_id = NVSYNCPT_DISP0_B;
2344 break;
2345 case 2:
2346 syncpt_id = NVSYNCPT_DISP0_C;
2347 break;
2348 default:
2349 BUG();
2350 break;
2351 }
2352 break;
2353 case 1:
2354 switch (idx) {
2355 case 0:
2356 syncpt_id = NVSYNCPT_DISP1_A;
2357 break;
2358 case 1:
2359 syncpt_id = NVSYNCPT_DISP1_B;
2360 break;
2361 case 2:
2362 syncpt_id = NVSYNCPT_DISP1_C;
2363 break;
2364 default:
2365 BUG();
2366 break;
2367 }
2368 break;
2369 default:
2370 BUG();
2371 break;
2372 }
2373
2374 return syncpt_id;
2375}
2376
2377static int tegra_dc_init(struct tegra_dc *dc)
2378{
2379 int i;
2380
2381 tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
2382 if (dc->ndev->id == 0) {
2383 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0A,
2384 TEGRA_MC_PRIO_MED);
2385 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0B,
2386 TEGRA_MC_PRIO_MED);
2387 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0C,
2388 TEGRA_MC_PRIO_MED);
2389 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY1B,
2390 TEGRA_MC_PRIO_MED);
2391 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAYHC,
2392 TEGRA_MC_PRIO_HIGH);
2393 } else if (dc->ndev->id == 1) {
2394 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0AB,
2395 TEGRA_MC_PRIO_MED);
2396 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0BB,
2397 TEGRA_MC_PRIO_MED);
2398 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0CB,
2399 TEGRA_MC_PRIO_MED);
2400 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY1BB,
2401 TEGRA_MC_PRIO_MED);
2402 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAYHCB,
2403 TEGRA_MC_PRIO_HIGH);
2404 }
2405 tegra_dc_writel(dc, 0x00000100 | dc->vblank_syncpt,
2406 DC_CMD_CONT_SYNCPT_VSYNC);
2407 tegra_dc_writel(dc, 0x00004700, DC_CMD_INT_TYPE);
2408 tegra_dc_writel(dc, 0x0001c700, DC_CMD_INT_POLARITY);
2409 tegra_dc_writel(dc, 0x00202020, DC_DISP_MEM_HIGH_PRIORITY);
2410 tegra_dc_writel(dc, 0x00010101, DC_DISP_MEM_HIGH_PRIORITY_TIMER);
2411
2412 /* enable interrupts for vblank, frame_end and underflows */
2413 tegra_dc_writel(dc, (FRAME_END_INT | V_BLANK_INT | ALL_UF_INT),
2414 DC_CMD_INT_ENABLE);
2415 tegra_dc_writel(dc, ALL_UF_INT, DC_CMD_INT_MASK);
2416
2417 tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
2418
2419 tegra_dc_set_color_control(dc);
2420 for (i = 0; i < DC_N_WINDOWS; i++) {
2421 struct tegra_dc_win *win = &dc->windows[i];
2422 tegra_dc_writel(dc, WINDOW_A_SELECT << i,
2423 DC_CMD_DISPLAY_WINDOW_HEADER);
2424 tegra_dc_set_csc(dc, &win->csc);
2425 tegra_dc_set_lut(dc, win);
2426 tegra_dc_set_scaling_filter(dc);
2427 }
2428
2429
2430 for (i = 0; i < dc->n_windows; i++) {
2431 u32 syncpt = get_syncpt(dc, i);
2432
2433 dc->syncpt[i].id = syncpt;
2434
2435 dc->syncpt[i].min = dc->syncpt[i].max =
2436 nvhost_syncpt_read(&nvhost_get_host(dc->ndev)->syncpt,
2437 syncpt);
2438 }
2439
2440 print_mode(dc, &dc->mode, __func__);
2441
2442 if (dc->mode.pclk)
2443 if (tegra_dc_program_mode(dc, &dc->mode))
2444 return -EINVAL;
2445
2446 /* Initialize SD AFTER the modeset.
2447 nvsd_init handles the sd_settings = NULL case. */
2448 nvsd_init(dc, dc->out->sd_settings);
2449
2450 return 0;
2451}
2452
2453static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
2454{
2455 int failed_init = 0;
2456
2457 if (dc->out->enable)
2458 dc->out->enable();
2459
2460 tegra_dc_setup_clk(dc, dc->clk);
2461 clk_enable(dc->clk);
2462
2463 /* do not accept interrupts during initialization */
2464 tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE);
2465 tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);
2466
2467 enable_dc_irq(dc->irq);
2468
2469 failed_init = tegra_dc_init(dc);
2470 if (failed_init) {
2471 _tegra_dc_controller_disable(dc);
2472 return false;
2473 }
2474
2475 if (dc->out_ops && dc->out_ops->enable)
2476 dc->out_ops->enable(dc);
2477
2478 if (dc->out->postpoweron)
2479 dc->out->postpoweron();
2480
2481 /* force a full blending update */
2482 dc->blend.z[0] = -1;
2483
2484 tegra_dc_ext_enable(dc->ext);
2485
2486 return true;
2487}
2488
2489#ifdef CONFIG_ARCH_TEGRA_2x_SOC
2490static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc)
2491{
2492 bool ret = true;
2493
2494 if (dc->out->enable)
2495 dc->out->enable();
2496
2497 tegra_dc_setup_clk(dc, dc->clk);
2498 clk_enable(dc->clk);
2499
2500 if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) {
2501 mutex_lock(&tegra_dcs[1]->lock);
2502 disable_irq(tegra_dcs[1]->irq);
2503 } else if (dc->ndev->id == 1 && tegra_dcs[0] != NULL) {
2504 mutex_lock(&tegra_dcs[0]->lock);
2505 disable_irq(tegra_dcs[0]->irq);
2506 }
2507
2508 msleep(5);
2509 tegra_periph_reset_assert(dc->clk);
2510 msleep(2);
2511#ifdef CONFIG_TEGRA_SILICON_PLATFORM
2512 tegra_periph_reset_deassert(dc->clk);
2513 msleep(1);
2514#endif
2515
2516 if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) {
2517 enable_dc_irq(tegra_dcs[1]->irq);
2518 mutex_unlock(&tegra_dcs[1]->lock);
2519 } else if (dc->ndev->id == 1 && tegra_dcs[0] != NULL) {
2520 enable_dc_irq(tegra_dcs[0]->irq);
2521 mutex_unlock(&tegra_dcs[0]->lock);
2522 }
2523
2524 enable_dc_irq(dc->irq);
2525
2526 if (tegra_dc_init(dc)) {
2527 dev_err(&dc->ndev->dev, "cannot initialize\n");
2528 ret = false;
2529 }
2530
2531 if (dc->out_ops && dc->out_ops->enable)
2532 dc->out_ops->enable(dc);
2533
2534 if (dc->out->postpoweron)
2535 dc->out->postpoweron();
2536
2537 /* force a full blending update */
2538 dc->blend.z[0] = -1;
2539
2540 tegra_dc_ext_enable(dc->ext);
2541
2542 if (!ret) {
2543 dev_err(&dc->ndev->dev, "initialization failed,disabling");
2544 _tegra_dc_controller_disable(dc);
2545 }
2546
2547 return ret;
2548}
2549#endif
2550
2551static bool _tegra_dc_enable(struct tegra_dc *dc)
2552{
2553 if (dc->mode.pclk == 0)
2554 return false;
2555
2556 if (!dc->out)
2557 return false;
2558
2559 tegra_dc_io_start(dc);
2560
2561 return _tegra_dc_controller_enable(dc);
2562}
2563
2564void tegra_dc_enable(struct tegra_dc *dc)
2565{
2566 mutex_lock(&dc->lock);
2567
2568 if (!dc->enabled)
2569 dc->enabled = _tegra_dc_enable(dc);
2570
2571 mutex_unlock(&dc->lock);
2572}
2573
2574static void _tegra_dc_controller_disable(struct tegra_dc *dc)
2575{
2576 unsigned i;
2577
2578 if (dc->out_ops && dc->out_ops->disable)
2579 dc->out_ops->disable(dc);
2580
2581 tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);
2582 tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE);
2583 disable_irq(dc->irq);
2584
2585 tegra_dc_clear_bandwidth(dc);
2586 clk_disable(dc->clk);
2587 tegra_dvfs_set_rate(dc->clk, 0);
2588
2589 if (dc->out && dc->out->disable)
2590 dc->out->disable();
2591
2592 for (i = 0; i < dc->n_windows; i++) {
2593 struct tegra_dc_win *w = &dc->windows[i];
2594
2595 /* reset window bandwidth */
2596 w->bandwidth = 0;
2597 w->new_bandwidth = 0;
2598
2599 /* disable windows */
2600 w->flags &= ~TEGRA_WIN_FLAG_ENABLED;
2601
2602 /* flush any pending syncpt waits */
2603 while (dc->syncpt[i].min < dc->syncpt[i].max) {
2604 dc->syncpt[i].min++;
2605 nvhost_syncpt_cpu_incr(
2606 &nvhost_get_host(dc->ndev)->syncpt,
2607 dc->syncpt[i].id);
2608 }
2609 }
2610}
2611
2612void tegra_dc_stats_enable(struct tegra_dc *dc, bool enable)
2613{
2614#if 0 /* underflow interrupt is already enabled by dc reset worker */
2615 u32 val;
2616 if (dc->enabled) {
2617 val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
2618 if (enable)
2619 val |= (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT);
2620 else
2621 val &= ~(WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT);
2622 tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE);
2623 }
2624#endif
2625}
2626
2627bool tegra_dc_stats_get(struct tegra_dc *dc)
2628{
2629#if 0 /* right now it is always enabled */
2630 u32 val;
2631 bool res;
2632
2633 if (dc->enabled) {
2634 val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
2635 res = !!(val & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT));
2636 } else {
2637 res = false;
2638 }
2639
2640 return res;
2641#endif
2642 return true;
2643}
2644
2645/* make the screen blank by disabling all windows */
2646void tegra_dc_blank(struct tegra_dc *dc)
2647{
2648 struct tegra_dc_win *dcwins[DC_N_WINDOWS];
2649 unsigned i;
2650
2651 for (i = 0; i < DC_N_WINDOWS; i++) {
2652 dcwins[i] = tegra_dc_get_window(dc, i);
2653 dcwins[i]->flags &= ~TEGRA_WIN_FLAG_ENABLED;
2654 }
2655
2656 tegra_dc_update_windows(dcwins, DC_N_WINDOWS);
2657 tegra_dc_sync_windows(dcwins, DC_N_WINDOWS);
2658}
2659
2660static void _tegra_dc_disable(struct tegra_dc *dc)
2661{
2662 _tegra_dc_controller_disable(dc);
2663 tegra_dc_io_end(dc);
2664}
2665
2666void tegra_dc_disable(struct tegra_dc *dc)
2667{
2668 tegra_dc_ext_disable(dc->ext);
2669
2670 /* it's important that new underflow work isn't scheduled before the
2671 * lock is acquired. */
2672 cancel_delayed_work_sync(&dc->underflow_work);
2673 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
2674 mutex_lock(&dc->one_shot_lock);
2675 cancel_delayed_work_sync(&dc->one_shot_work);
2676 }
2677
2678 mutex_lock(&dc->lock);
2679
2680 if (dc->enabled) {
2681 dc->enabled = false;
2682
2683 if (!dc->suspended)
2684 _tegra_dc_disable(dc);
2685 }
2686
2687#ifdef CONFIG_SWITCH
2688 switch_set_state(&dc->modeset_switch, 0);
2689#endif
2690
2691 mutex_unlock(&dc->lock);
2692 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
2693 mutex_unlock(&dc->one_shot_lock);
2694}
2695
2696#ifdef CONFIG_ARCH_TEGRA_2x_SOC
2697static void tegra_dc_reset_worker(struct work_struct *work)
2698{
2699 struct tegra_dc *dc =
2700 container_of(work, struct tegra_dc, reset_work);
2701
2702 unsigned long val = 0;
2703
2704 mutex_lock(&shared_lock);
2705
2706 dev_warn(&dc->ndev->dev, "overlay stuck in underflow state. resetting.\n");
2707
2708 tegra_dc_ext_disable(dc->ext);
2709
2710 mutex_lock(&dc->lock);
2711
2712 if (dc->enabled == false)
2713 goto unlock;
2714
2715 dc->enabled = false;
2716
2717 /*
2718 * off host read bus
2719 */
2720 val = tegra_dc_readl(dc, DC_CMD_CONT_SYNCPT_VSYNC);
2721 val &= ~(0x00000100);
2722 tegra_dc_writel(dc, val, DC_CMD_CONT_SYNCPT_VSYNC);
2723
2724 /*
2725 * set DC to STOP mode
2726 */
2727 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
2728
2729 msleep(10);
2730
2731 _tegra_dc_controller_disable(dc);
2732
2733 /* _tegra_dc_controller_reset_enable deasserts reset */
2734 _tegra_dc_controller_reset_enable(dc);
2735
2736 dc->enabled = true;
2737unlock:
2738 mutex_unlock(&dc->lock);
2739 mutex_unlock(&shared_lock);
2740}
2741#endif
2742
2743static void tegra_dc_underflow_worker(struct work_struct *work)
2744{
2745 struct tegra_dc *dc = container_of(
2746 to_delayed_work(work), struct tegra_dc, underflow_work);
2747
2748 mutex_lock(&dc->lock);
2749 if (dc->enabled) {
2750 tegra_dc_underflow_handler(dc);
2751 }
2752 mutex_unlock(&dc->lock);
2753}
2754
2755#ifdef CONFIG_SWITCH
2756static ssize_t switch_modeset_print_mode(struct switch_dev *sdev, char *buf)
2757{
2758 struct tegra_dc *dc =
2759 container_of(sdev, struct tegra_dc, modeset_switch);
2760
2761 if (!sdev->state)
2762 return sprintf(buf, "offline\n");
2763
2764 return sprintf(buf, "%dx%d\n", dc->mode.h_active, dc->mode.v_active);
2765}
2766#endif
2767
2768static int tegra_dc_probe(struct nvhost_device *ndev)
2769{
2770 struct tegra_dc *dc;
2771 struct clk *clk;
2772 struct clk *emc_clk;
2773 struct resource *res;
2774 struct resource *base_res;
2775 struct resource *fb_mem = NULL;
2776 int ret = 0;
2777 void __iomem *base;
2778 int irq;
2779 int i;
2780
2781 if (!ndev->dev.platform_data) {
2782 dev_err(&ndev->dev, "no platform data\n");
2783 return -ENOENT;
2784 }
2785
2786 dc = kzalloc(sizeof(struct tegra_dc), GFP_KERNEL);
2787 if (!dc) {
2788 dev_err(&ndev->dev, "can't allocate memory for tegra_dc\n");
2789 return -ENOMEM;
2790 }
2791
2792 irq = nvhost_get_irq_byname(ndev, "irq");
2793 if (irq <= 0) {
2794 dev_err(&ndev->dev, "no irq\n");
2795 ret = -ENOENT;
2796 goto err_free;
2797 }
2798
2799 res = nvhost_get_resource_byname(ndev, IORESOURCE_MEM, "regs");
2800 if (!res) {
2801 dev_err(&ndev->dev, "no mem resource\n");
2802 ret = -ENOENT;
2803 goto err_free;
2804 }
2805
2806 base_res = request_mem_region(res->start, resource_size(res), ndev->name);
2807 if (!base_res) {
2808 dev_err(&ndev->dev, "request_mem_region failed\n");
2809 ret = -EBUSY;
2810 goto err_free;
2811 }
2812
2813 base = ioremap(res->start, resource_size(res));
2814 if (!base) {
2815 dev_err(&ndev->dev, "registers can't be mapped\n");
2816 ret = -EBUSY;
2817 goto err_release_resource_reg;
2818 }
2819
2820 fb_mem = nvhost_get_resource_byname(ndev, IORESOURCE_MEM, "fbmem");
2821
2822 clk = clk_get(&ndev->dev, NULL);
2823 if (IS_ERR_OR_NULL(clk)) {
2824 dev_err(&ndev->dev, "can't get clock\n");
2825 ret = -ENOENT;
2826 goto err_iounmap_reg;
2827 }
2828
2829 emc_clk = clk_get(&ndev->dev, "emc");
2830 if (IS_ERR_OR_NULL(emc_clk)) {
2831 dev_err(&ndev->dev, "can't get emc clock\n");
2832 ret = -ENOENT;
2833 goto err_put_clk;
2834 }
2835
2836 dc->clk = clk;
2837 dc->emc_clk = emc_clk;
2838 dc->shift_clk_div = 1;
2839 /* Initialize one shot work delay, it will be assigned by dsi
2840 * according to refresh rate later. */
2841 dc->one_shot_delay_ms = 40;
2842
2843 dc->base_res = base_res;
2844 dc->base = base;
2845 dc->irq = irq;
2846 dc->ndev = ndev;
2847 dc->pdata = ndev->dev.platform_data;
2848
2849 /*
2850 * The emc is a shared clock, it will be set based on
2851 * the requirements for each user on the bus.
2852 */
2853 dc->emc_clk_rate = 0;
2854
2855 if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED)
2856 dc->enabled = true;
2857
2858 mutex_init(&dc->lock);
2859 mutex_init(&dc->one_shot_lock);
2860 init_completion(&dc->frame_end_complete);
2861 init_waitqueue_head(&dc->wq);
2862#ifdef CONFIG_ARCH_TEGRA_2x_SOC
2863 INIT_WORK(&dc->reset_work, tegra_dc_reset_worker);
2864#endif
2865 INIT_WORK(&dc->vblank_work, tegra_dc_vblank);
2866 INIT_DELAYED_WORK(&dc->underflow_work, tegra_dc_underflow_worker);
2867 INIT_DELAYED_WORK(&dc->one_shot_work, tegra_dc_one_shot_worker);
2868
2869 tegra_dc_init_lut_defaults(&dc->fb_lut);
2870
2871 dc->n_windows = DC_N_WINDOWS;
2872 for (i = 0; i < dc->n_windows; i++) {
2873 struct tegra_dc_win *win = &dc->windows[i];
2874 win->idx = i;
2875 win->dc = dc;
2876 tegra_dc_init_csc_defaults(&win->csc);
2877 tegra_dc_init_lut_defaults(&win->lut);
2878 }
2879
2880 ret = tegra_dc_set(dc, ndev->id);
2881 if (ret < 0) {
2882 dev_err(&ndev->dev, "can't add dc\n");
2883 goto err_free_irq;
2884 }
2885
2886 nvhost_set_drvdata(ndev, dc);
2887
2888#ifdef CONFIG_SWITCH
2889 dc->modeset_switch.name = dev_name(&ndev->dev);
2890 dc->modeset_switch.state = 0;
2891 dc->modeset_switch.print_state = switch_modeset_print_mode;
2892 switch_dev_register(&dc->modeset_switch);
2893#endif
2894
2895 if (dc->pdata->default_out)
2896 tegra_dc_set_out(dc, dc->pdata->default_out);
2897 else
2898 dev_err(&ndev->dev, "No default output specified. Leaving output disabled.\n");
2899
2900 dc->vblank_syncpt = (dc->ndev->id == 0) ?
2901 NVSYNCPT_VBLANK0 : NVSYNCPT_VBLANK1;
2902
2903 dc->ext = tegra_dc_ext_register(ndev, dc);
2904 if (IS_ERR_OR_NULL(dc->ext)) {
2905 dev_warn(&ndev->dev, "Failed to enable Tegra DC extensions.\n");
2906 dc->ext = NULL;
2907 }
2908
2909 /* interrupt handler must be registered before tegra_fb_register() */
2910 if (request_irq(irq, tegra_dc_irq, IRQF_DISABLED,
2911 dev_name(&ndev->dev), dc)) {
2912 dev_err(&ndev->dev, "request_irq %d failed\n", irq);
2913 ret = -EBUSY;
2914 goto err_put_emc_clk;
2915 }
2916
2917 /* hack to balance enable_irq calls in _tegra_dc_enable() */
2918 disable_dc_irq(dc->irq);
2919
2920 mutex_lock(&dc->lock);
2921 if (dc->enabled)
2922 _tegra_dc_enable(dc);
2923 mutex_unlock(&dc->lock);
2924
2925 tegra_dc_create_debugfs(dc);
2926
2927 dev_info(&ndev->dev, "probed\n");
2928
2929 if (dc->pdata->fb) {
2930 if (dc->pdata->fb->bits_per_pixel == -1) {
2931 unsigned long fmt;
2932 tegra_dc_writel(dc,
2933 WINDOW_A_SELECT << dc->pdata->fb->win,
2934 DC_CMD_DISPLAY_WINDOW_HEADER);
2935
2936 fmt = tegra_dc_readl(dc, DC_WIN_COLOR_DEPTH);
2937 dc->pdata->fb->bits_per_pixel =
2938 tegra_dc_fmt_bpp(fmt);
2939 }
2940
2941 dc->fb = tegra_fb_register(ndev, dc, dc->pdata->fb, fb_mem);
2942 if (IS_ERR_OR_NULL(dc->fb))
2943 dc->fb = NULL;
2944 }
2945
2946 if (dc->out && dc->out->hotplug_init)
2947 dc->out->hotplug_init();
2948
2949 if (dc->out_ops && dc->out_ops->detect)
2950 dc->out_ops->detect(dc);
2951 else
2952 dc->connected = true;
2953
2954 tegra_dc_create_sysfs(&dc->ndev->dev);
2955
2956 return 0;
2957
2958err_free_irq:
2959 free_irq(irq, dc);
2960err_put_emc_clk:
2961 clk_put(emc_clk);
2962err_put_clk:
2963 clk_put(clk);
2964err_iounmap_reg:
2965 iounmap(base);
2966 if (fb_mem)
2967 release_resource(fb_mem);
2968err_release_resource_reg:
2969 release_resource(base_res);
2970err_free:
2971 kfree(dc);
2972
2973 return ret;
2974}
2975
2976static int tegra_dc_remove(struct nvhost_device *ndev)
2977{
2978 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
2979
2980 tegra_dc_remove_sysfs(&dc->ndev->dev);
2981 tegra_dc_remove_debugfs(dc);
2982
2983 if (dc->fb) {
2984 tegra_fb_unregister(dc->fb);
2985 if (dc->fb_mem)
2986 release_resource(dc->fb_mem);
2987 }
2988
2989 tegra_dc_ext_disable(dc->ext);
2990
2991 if (dc->ext)
2992 tegra_dc_ext_unregister(dc->ext);
2993
2994 if (dc->enabled)
2995 _tegra_dc_disable(dc);
2996
2997#ifdef CONFIG_SWITCH
2998 switch_dev_unregister(&dc->modeset_switch);
2999#endif
3000 free_irq(dc->irq, dc);
3001 clk_put(dc->emc_clk);
3002 clk_put(dc->clk);
3003 iounmap(dc->base);
3004 if (dc->fb_mem)
3005 release_resource(dc->base_res);
3006 kfree(dc);
3007 tegra_dc_set(NULL, ndev->id);
3008 return 0;
3009}
3010
3011#ifdef CONFIG_PM
3012static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state)
3013{
3014 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
3015
3016 dev_info(&ndev->dev, "suspend\n");
3017
3018 tegra_dc_ext_disable(dc->ext);
3019
3020 mutex_lock(&dc->lock);
3021
3022 if (dc->out_ops && dc->out_ops->suspend)
3023 dc->out_ops->suspend(dc);
3024
3025 if (dc->enabled) {
3026 _tegra_dc_disable(dc);
3027
3028 dc->suspended = true;
3029 }
3030
3031 if (dc->out && dc->out->postsuspend) {
3032 dc->out->postsuspend();
3033 if (dc->out->type && dc->out->type == TEGRA_DC_OUT_HDMI)
3034 /*
3035 * avoid resume event due to voltage falling
3036 */
3037 msleep(100);
3038 }
3039
3040 mutex_unlock(&dc->lock);
3041
3042 return 0;
3043}
3044
3045static int tegra_dc_resume(struct nvhost_device *ndev)
3046{
3047 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
3048
3049 dev_info(&ndev->dev, "resume\n");
3050
3051 mutex_lock(&dc->lock);
3052 dc->suspended = false;
3053
3054 if (dc->enabled)
3055 _tegra_dc_enable(dc);
3056
3057 if (dc->out && dc->out->hotplug_init)
3058 dc->out->hotplug_init();
3059
3060 if (dc->out_ops && dc->out_ops->resume)
3061 dc->out_ops->resume(dc);
3062 mutex_unlock(&dc->lock);
3063
3064 return 0;
3065}
3066
3067#endif /* CONFIG_PM */
3068
3069extern int suspend_set(const char *val, struct kernel_param *kp)
3070{
3071 if (!strcmp(val, "dump"))
3072 dump_regs(tegra_dcs[0]);
3073#ifdef CONFIG_PM
3074 else if (!strcmp(val, "suspend"))
3075 tegra_dc_suspend(tegra_dcs[0]->ndev, PMSG_SUSPEND);
3076 else if (!strcmp(val, "resume"))
3077 tegra_dc_resume(tegra_dcs[0]->ndev);
3078#endif
3079
3080 return 0;
3081}
3082
3083extern int suspend_get(char *buffer, struct kernel_param *kp)
3084{
3085 return 0;
3086}
3087
3088int suspend;
3089
3090module_param_call(suspend, suspend_set, suspend_get, &suspend, 0644);
3091
3092struct nvhost_driver tegra_dc_driver = {
3093 .driver = {
3094 .name = "tegradc",
3095 .owner = THIS_MODULE,
3096 },
3097 .probe = tegra_dc_probe,
3098 .remove = tegra_dc_remove,
3099#ifdef CONFIG_PM
3100 .suspend = tegra_dc_suspend,
3101 .resume = tegra_dc_resume,
3102#endif
3103};
3104
3105static int __init tegra_dc_module_init(void)
3106{
3107 int ret = tegra_dc_ext_module_init();
3108 if (ret)
3109 return ret;
3110 return nvhost_driver_register(&tegra_dc_driver);
3111}
3112
3113static void __exit tegra_dc_module_exit(void)
3114{
3115 nvhost_driver_unregister(&tegra_dc_driver);
3116 tegra_dc_ext_module_exit();
3117}
3118
3119module_exit(tegra_dc_module_exit);
3120module_init(tegra_dc_module_init);
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
new file mode 100644
index 00000000000..a10e648debc
--- /dev/null
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -0,0 +1,220 @@
1/*
2 * drivers/video/tegra/dc/dc_priv.h
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __DRIVERS_VIDEO_TEGRA_DC_DC_PRIV_H
19#define __DRIVERS_VIDEO_TEGRA_DC_DC_PRIV_H
20
21#include <linux/io.h>
22#include <linux/mutex.h>
23#include <linux/wait.h>
24#include <linux/completion.h>
25#include <linux/switch.h>
26
27#include <mach/dc.h>
28
29#include "../host/dev.h"
30#include "../host/host1x/host1x_syncpt.h"
31
32#include <mach/tegra_dc_ext.h>
33
34#define WIN_IS_TILED(win) ((win)->flags & TEGRA_WIN_FLAG_TILED)
35#define WIN_IS_ENABLED(win) ((win)->flags & TEGRA_WIN_FLAG_ENABLED)
36
37#define NEED_UPDATE_EMC_ON_EVERY_FRAME (windows_idle_detection_time == 0)
38
39/* DDR: 8 bytes transfer per clock */
40#define DDR_BW_TO_FREQ(bw) ((bw) / 8)
41
42#if defined(CONFIG_TEGRA_EMC_TO_DDR_CLOCK)
43#define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * CONFIG_TEGRA_EMC_TO_DDR_CLOCK)
44#else
45#define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * 2)
46#endif
47
48struct tegra_dc;
49
50struct tegra_dc_blend {
51 unsigned z[DC_N_WINDOWS];
52 unsigned flags[DC_N_WINDOWS];
53};
54
55struct tegra_dc_out_ops {
56 /* initialize output. dc clocks are not on at this point */
57 int (*init)(struct tegra_dc *dc);
58 /* destroy output. dc clocks are not on at this point */
59 void (*destroy)(struct tegra_dc *dc);
60 /* detect connected display. can sleep.*/
61 bool (*detect)(struct tegra_dc *dc);
62 /* enable output. dc clocks are on at this point */
63 void (*enable)(struct tegra_dc *dc);
64 /* disable output. dc clocks are on at this point */
65 void (*disable)(struct tegra_dc *dc);
66
67 /* suspend output. dc clocks are on at this point */
68 void (*suspend)(struct tegra_dc *dc);
69 /* resume output. dc clocks are on at this point */
70 void (*resume)(struct tegra_dc *dc);
71};
72
73struct tegra_dc {
74 struct nvhost_device *ndev;
75 struct tegra_dc_platform_data *pdata;
76
77 struct resource *base_res;
78 void __iomem *base;
79 int irq;
80
81 struct clk *clk;
82 struct clk *emc_clk;
83 int emc_clk_rate;
84 int new_emc_clk_rate;
85 u32 shift_clk_div;
86
87 bool connected;
88 bool enabled;
89 bool suspended;
90
91 struct tegra_dc_out *out;
92 struct tegra_dc_out_ops *out_ops;
93 void *out_data;
94
95 struct tegra_dc_mode mode;
96
97 struct tegra_dc_win windows[DC_N_WINDOWS];
98 struct tegra_dc_blend blend;
99 int n_windows;
100
101 wait_queue_head_t wq;
102
103 struct mutex lock;
104 struct mutex one_shot_lock;
105
106 struct resource *fb_mem;
107 struct tegra_fb_info *fb;
108
109 struct {
110 u32 id;
111 u32 min;
112 u32 max;
113 } syncpt[DC_N_WINDOWS];
114 u32 vblank_syncpt;
115
116 unsigned long underflow_mask;
117 struct work_struct reset_work;
118
119#ifdef CONFIG_SWITCH
120 struct switch_dev modeset_switch;
121#endif
122
123 struct completion frame_end_complete;
124
125 struct work_struct vblank_work;
126
127 struct {
128 u64 underflows;
129 u64 underflows_a;
130 u64 underflows_b;
131 u64 underflows_c;
132 } stats;
133
134 struct tegra_dc_ext *ext;
135
136#ifdef CONFIG_DEBUG_FS
137 struct dentry *debugdir;
138#endif
139 struct tegra_dc_lut fb_lut;
140 struct delayed_work underflow_work;
141 u32 one_shot_delay_ms;
142 struct delayed_work one_shot_work;
143};
144
145static inline void tegra_dc_io_start(struct tegra_dc *dc)
146{
147 nvhost_module_busy(nvhost_get_host(dc->ndev)->dev);
148}
149
150static inline void tegra_dc_io_end(struct tegra_dc *dc)
151{
152 nvhost_module_idle(nvhost_get_host(dc->ndev)->dev);
153}
154
155static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
156 unsigned long reg)
157{
158 BUG_ON(!nvhost_module_powered(nvhost_get_host(dc->ndev)->dev));
159 return readl(dc->base + reg * 4);
160}
161
162static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long val,
163 unsigned long reg)
164{
165 BUG_ON(!nvhost_module_powered(nvhost_get_host(dc->ndev)->dev));
166 writel(val, dc->base + reg * 4);
167}
168
169static inline void _tegra_dc_write_table(struct tegra_dc *dc, const u32 *table,
170 unsigned len)
171{
172 int i;
173
174 for (i = 0; i < len; i++)
175 tegra_dc_writel(dc, table[i * 2 + 1], table[i * 2]);
176}
177
178#define tegra_dc_write_table(dc, table) \
179 _tegra_dc_write_table(dc, table, ARRAY_SIZE(table) / 2)
180
181static inline void tegra_dc_set_outdata(struct tegra_dc *dc, void *data)
182{
183 dc->out_data = data;
184}
185
186static inline void *tegra_dc_get_outdata(struct tegra_dc *dc)
187{
188 return dc->out_data;
189}
190
191static inline unsigned long tegra_dc_get_default_emc_clk_rate(
192 struct tegra_dc *dc)
193{
194 return dc->pdata->emc_clk_rate ? dc->pdata->emc_clk_rate : ULONG_MAX;
195}
196
197void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
198
199extern struct tegra_dc_out_ops tegra_dc_rgb_ops;
200extern struct tegra_dc_out_ops tegra_dc_hdmi_ops;
201extern struct tegra_dc_out_ops tegra_dc_dsi_ops;
202
203/* defined in dc_sysfs.c, used by dc.c */
204void __devexit tegra_dc_remove_sysfs(struct device *dev);
205void tegra_dc_create_sysfs(struct device *dev);
206
207/* defined in dc.c, used by dc_sysfs.c */
208void tegra_dc_stats_enable(struct tegra_dc *dc, bool enable);
209bool tegra_dc_stats_get(struct tegra_dc *dc);
210
211/* defined in dc.c, used by dc_sysfs.c */
212u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc);
213void tegra_dc_enable_crc(struct tegra_dc *dc);
214void tegra_dc_disable_crc(struct tegra_dc *dc);
215
216void tegra_dc_set_out_pin_polars(struct tegra_dc *dc,
217 const struct tegra_dc_out_pin *pins,
218 const unsigned int n_pins);
219#endif
220
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
new file mode 100644
index 00000000000..22379a19408
--- /dev/null
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -0,0 +1,555 @@
1/*
2 * drivers/video/tegra/dc/dc_reg.h
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * Copyright (C) 2010-2011 NVIDIA Corporation
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#ifndef __DRIVERS_VIDEO_TEGRA_DC_DC_REG_H
21#define __DRIVERS_VIDEO_TEGRA_DC_DC_REG_H
22
23#define DC_CMD_GENERAL_INCR_SYNCPT 0x000
24#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001
25#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002
26#define DC_CMD_WIN_A_INCR_SYNCPT 0x008
27#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009
28#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR 0x00a
29#define DC_CMD_WIN_B_INCR_SYNCPT 0x010
30#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL 0x011
31#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR 0x012
32#define DC_CMD_WIN_C_INCR_SYNCPT 0x018
33#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019
34#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a
35#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
36#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
37#define MSF_POLARITY_HIGH (0 << 0)
38#define MSF_POLARITY_LOW (1 << 0)
39#define MSF_DISABLE (0 << 1)
40#define MSF_ENABLE (1 << 1)
41#define MSF_LSPI (0 << 2)
42#define MSF_LDC (1 << 2)
43#define MSF_LSDI (2 << 2)
44
45#define DC_CMD_DISPLAY_COMMAND 0x032
46#define DISP_COMMAND_RAISE (1 << 0)
47#define DISP_CTRL_MODE_STOP (0 << 5)
48#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
49#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5)
50#define DISP_COMMAND_RAISE_VECTOR(x) (((x) & 0x1f) << 22)
51#define DISP_COMMAND_RAISE_CHANNEL_ID(x) (((x) & 0xf) << 27)
52
53#define DC_CMD_SIGNAL_RAISE 0x033
54#define DC_CMD_DISPLAY_POWER_CONTROL 0x036
55#define PW0_ENABLE (1 << 0)
56#define PW1_ENABLE (1 << 2)
57#define PW2_ENABLE (1 << 4)
58#define PW3_ENABLE (1 << 6)
59#define PW4_ENABLE (1 << 8)
60#define PM0_ENABLE (1 << 16)
61#define PM1_ENABLE (1 << 18)
62#define SPI_ENABLE (1 << 24)
63#define HSPI_ENABLE (1 << 25)
64
65#define DC_CMD_INT_STATUS 0x037
66#define DC_CMD_INT_MASK 0x038
67#define DC_CMD_INT_ENABLE 0x039
68#define DC_CMD_INT_TYPE 0x03a
69#define DC_CMD_INT_POLARITY 0x03b
70#define CTXSW_INT (1 << 0)
71#define FRAME_END_INT (1 << 1)
72#define V_BLANK_INT (1 << 2)
73#define H_BLANK_INT (1 << 3)
74#define V_PULSE3_INT (1 << 4)
75#define SPI_BUSY_INT (1 << 7)
76#define WIN_A_UF_INT (1 << 8)
77#define WIN_B_UF_INT (1 << 9)
78#define WIN_C_UF_INT (1 << 10)
79#define MSF_INT (1 << 12)
80#define SSF_INT (1 << 13)
81#define WIN_A_OF_INT (1 << 14)
82#define WIN_B_OF_INT (1 << 15)
83#define WIN_C_OF_INT (1 << 16)
84#define GPIO_0_INT (1 << 18)
85#define GPIO_1_INT (1 << 19)
86#define GPIO_2_INT (1 << 20)
87
88#define DC_CMD_SIGNAL_RAISE1 0x03c
89#define DC_CMD_SIGNAL_RAISE2 0x03d
90#define DC_CMD_SIGNAL_RAISE3 0x03e
91#define DC_CMD_STATE_ACCESS 0x040
92#define READ_MUX_ASSEMBLY (0 << 0)
93#define READ_MUX_ACTIVE (1 << 0)
94#define WRITE_MUX_ASSEMBLY (0 << 2)
95#define WRITE_MUX_ACTIVE (1 << 2)
96
97#define DC_CMD_STATE_CONTROL 0x041
98#define GENERAL_ACT_REQ (1 << 0)
99#define WIN_A_ACT_REQ (1 << 1)
100#define WIN_B_ACT_REQ (1 << 2)
101#define WIN_C_ACT_REQ (1 << 3)
102#define GENERAL_UPDATE (1 << 8)
103#define WIN_A_UPDATE (1 << 9)
104#define WIN_B_UPDATE (1 << 10)
105#define WIN_C_UPDATE (1 << 11)
106#define NC_HOST_TRIG (1 << 24)
107
108#define DC_CMD_DISPLAY_WINDOW_HEADER 0x042
109#define WINDOW_A_SELECT (1 << 4)
110#define WINDOW_B_SELECT (1 << 5)
111#define WINDOW_C_SELECT (1 << 6)
112
113#define DC_CMD_REG_ACT_CONTROL 0x043
114
115#define DC_COM_CRC_CONTROL 0x300
116#define CRC_ALWAYS_ENABLE (1 << 3)
117#define CRC_ALWAYS_DISABLE (0 << 3)
118#define CRC_INPUT_DATA_ACTIVE_DATA (1 << 2)
119#define CRC_INPUT_DATA_FULL_FRAME (0 << 2)
120#define CRC_WAIT_TWO_VSYNC (1 << 1)
121#define CRC_WAIT_ONE_VSYNC (0 << 1)
122#define CRC_ENABLE_ENABLE (1 << 0)
123#define CRC_ENABLE_DISABLE (0 << 0)
124#define DC_COM_CRC_CHECKSUM 0x301
125#define DC_COM_PIN_OUTPUT_ENABLE0 0x302
126#define DC_COM_PIN_OUTPUT_ENABLE1 0x303
127#define DC_COM_PIN_OUTPUT_ENABLE2 0x304
128#define DC_COM_PIN_OUTPUT_ENABLE3 0x305
129#define PIN_OUTPUT_LSPI_OUTPUT_EN (1 << 8)
130#define PIN_OUTPUT_LSPI_OUTPUT_DIS (1 << 8)
131#define DC_COM_PIN_OUTPUT_POLARITY0 0x306
132
133#define DC_COM_PIN_OUTPUT_POLARITY1 0x307
134#define LHS_OUTPUT_POLARITY_LOW (1 << 30)
135#define LVS_OUTPUT_POLARITY_LOW (1 << 28)
136#define LSC0_OUTPUT_POLARITY_LOW (1 << 24)
137
138#define DC_COM_PIN_OUTPUT_POLARITY2 0x308
139
140#define DC_COM_PIN_OUTPUT_POLARITY3 0x309
141#define LSPI_OUTPUT_POLARITY_LOW (1 << 8)
142
143#define DC_COM_PIN_OUTPUT_DATA0 0x30a
144#define DC_COM_PIN_OUTPUT_DATA1 0x30b
145#define DC_COM_PIN_OUTPUT_DATA2 0x30c
146#define DC_COM_PIN_OUTPUT_DATA3 0x30d
147#define DC_COM_PIN_INPUT_ENABLE0 0x30e
148#define DC_COM_PIN_INPUT_ENABLE1 0x30f
149#define DC_COM_PIN_INPUT_ENABLE2 0x310
150#define DC_COM_PIN_INPUT_ENABLE3 0x311
151#define PIN_INPUT_LSPI_INPUT_EN (1 << 8)
152#define PIN_INPUT_LSPI_INPUT_DIS (1 << 8)
153#define DC_COM_PIN_INPUT_DATA0 0x312
154#define DC_COM_PIN_INPUT_DATA1 0x313
155#define DC_COM_PIN_OUTPUT_SELECT0 0x314
156#define DC_COM_PIN_OUTPUT_SELECT1 0x315
157#define DC_COM_PIN_OUTPUT_SELECT2 0x316
158#define DC_COM_PIN_OUTPUT_SELECT3 0x317
159#define DC_COM_PIN_OUTPUT_SELECT4 0x318
160#define DC_COM_PIN_OUTPUT_SELECT5 0x319
161#define DC_COM_PIN_OUTPUT_SELECT6 0x31a
162
163#define PIN5_LM1_LCD_M1_OUTPUT_MASK (7 << 4)
164#define PIN5_LM1_LCD_M1_OUTPUT_M1 (0 << 4)
165#define PIN5_LM1_LCD_M1_OUTPUT_LD21 (2 << 4)
166#define PIN5_LM1_LCD_M1_OUTPUT_PM1 (3 << 4)
167
168#define PIN1_LHS_OUTPUT (1 << 30)
169#define PIN1_LVS_OUTPUT (1 << 28)
170
171#define DC_COM_PIN_MISC_CONTROL 0x31b
172#define DC_COM_PM0_CONTROL 0x31c
173#define DC_COM_PM0_DUTY_CYCLE 0x31d
174#define DC_COM_PM1_CONTROL 0x31e
175#define DC_COM_PM1_DUTY_CYCLE 0x31f
176
177#define PM_PERIOD_SHIFT 18
178#define PM_CLK_DIVIDER_SHIFT 4
179
180#define DC_COM_SPI_CONTROL 0x320
181#define DC_COM_SPI_START_BYTE 0x321
182#define DC_COM_HSPI_WRITE_DATA_AB 0x322
183#define DC_COM_HSPI_WRITE_DATA_CD 0x323
184#define DC_COM_HSPI_CS_DC 0x324
185#define DC_COM_SCRATCH_REGISTER_A 0x325
186#define DC_COM_SCRATCH_REGISTER_B 0x326
187#define DC_COM_GPIO_CTRL 0x327
188#define DC_COM_GPIO_DEBOUNCE_COUNTER 0x328
189#define DC_COM_CRC_CHECKSUM_LATCHED 0x329
190
191#define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400
192#define H_PULSE_0_ENABLE (1 << 8)
193#define H_PULSE_1_ENABLE (1 << 10)
194#define H_PULSE_2_ENABLE (1 << 12)
195#define V_PULSE_0_ENABLE (1 << 16)
196#define V_PULSE_1_ENABLE (1 << 18)
197#define V_PULSE_2_ENABLE (1 << 19)
198#define V_PULSE_3_ENABLE (1 << 20)
199#define M0_ENABLE (1 << 24)
200#define M1_ENABLE (1 << 26)
201
202#define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401
203#define DI_ENABLE (1 << 16)
204#define PP_ENABLE (1 << 18)
205
206#define DC_DISP_DISP_WIN_OPTIONS 0x402
207#define CURSOR_ENABLE (1 << 16)
208#define TVO_ENABLE (1 << 28)
209#define DSI_ENABLE (1 << 29)
210#define HDMI_ENABLE (1 << 30)
211
212#define DC_DISP_MEM_HIGH_PRIORITY 0x403
213#define DC_DISP_MEM_HIGH_PRIORITY_TIMER 0x404
214#define DC_DISP_DISP_TIMING_OPTIONS 0x405
215#define VSYNC_H_POSITION(x) ((x) & 0xfff)
216
217#define DC_DISP_REF_TO_SYNC 0x406
218#define DC_DISP_SYNC_WIDTH 0x407
219#define DC_DISP_BACK_PORCH 0x408
220#define DC_DISP_DISP_ACTIVE 0x409
221#define DC_DISP_FRONT_PORCH 0x40a
222#define DC_DISP_H_PULSE0_CONTROL 0x40b
223#define DC_DISP_H_PULSE0_POSITION_A 0x40c
224#define DC_DISP_H_PULSE0_POSITION_B 0x40d
225#define DC_DISP_H_PULSE0_POSITION_C 0x40e
226#define DC_DISP_H_PULSE0_POSITION_D 0x40f
227#define DC_DISP_H_PULSE1_CONTROL 0x410
228#define DC_DISP_H_PULSE1_POSITION_A 0x411
229#define DC_DISP_H_PULSE1_POSITION_B 0x412
230#define DC_DISP_H_PULSE1_POSITION_C 0x413
231#define DC_DISP_H_PULSE1_POSITION_D 0x414
232#define DC_DISP_H_PULSE2_CONTROL 0x415
233#define DC_DISP_H_PULSE2_POSITION_A 0x416
234#define DC_DISP_H_PULSE2_POSITION_B 0x417
235#define DC_DISP_H_PULSE2_POSITION_C 0x418
236#define DC_DISP_H_PULSE2_POSITION_D 0x419
237#define DC_DISP_V_PULSE0_CONTROL 0x41a
238#define DC_DISP_V_PULSE0_POSITION_A 0x41b
239#define DC_DISP_V_PULSE0_POSITION_B 0x41c
240#define DC_DISP_V_PULSE0_POSITION_C 0x41d
241#define DC_DISP_V_PULSE1_CONTROL 0x41e
242#define DC_DISP_V_PULSE1_POSITION_A 0x41f
243#define DC_DISP_V_PULSE1_POSITION_B 0x420
244#define DC_DISP_V_PULSE1_POSITION_C 0x421
245#define DC_DISP_V_PULSE2_CONTROL 0x422
246#define DC_DISP_V_PULSE2_POSITION_A 0x423
247#define DC_DISP_V_PULSE3_CONTROL 0x424
248#define DC_DISP_V_PULSE3_POSITION_A 0x425
249#define DC_DISP_M0_CONTROL 0x426
250#define DC_DISP_M1_CONTROL 0x427
251#define DC_DISP_DI_CONTROL 0x428
252#define DC_DISP_PP_CONTROL 0x429
253#define DC_DISP_PP_SELECT_A 0x42a
254#define DC_DISP_PP_SELECT_B 0x42b
255#define DC_DISP_PP_SELECT_C 0x42c
256#define DC_DISP_PP_SELECT_D 0x42d
257
258#define PULSE_MODE_NORMAL (0 << 3)
259#define PULSE_MODE_ONE_CLOCK (1 << 3)
260#define PULSE_POLARITY_HIGH (0 << 4)
261#define PULSE_POLARITY_LOW (1 << 4)
262#define PULSE_QUAL_ALWAYS (0 << 6)
263#define PULSE_QUAL_VACTIVE (2 << 6)
264#define PULSE_QUAL_VACTIVE1 (3 << 6)
265#define PULSE_LAST_START_A (0 << 8)
266#define PULSE_LAST_END_A (1 << 8)
267#define PULSE_LAST_START_B (2 << 8)
268#define PULSE_LAST_END_B (3 << 8)
269#define PULSE_LAST_START_C (4 << 8)
270#define PULSE_LAST_END_C (5 << 8)
271#define PULSE_LAST_START_D (6 << 8)
272#define PULSE_LAST_END_D (7 << 8)
273
274#define PULSE_START(x) ((x) & 0xfff)
275#define PULSE_END(x) (((x) & 0xfff) << 16)
276
277#define DC_DISP_DISP_CLOCK_CONTROL 0x42e
278#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8)
279#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8)
280#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8)
281#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8)
282#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8)
283#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8)
284#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8)
285#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8)
286#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8)
287#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8)
288#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8)
289#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8)
290#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8)
291#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff)
292
293#define DC_DISP_DISP_INTERFACE_CONTROL 0x42f
294#define DISP_DATA_FORMAT_DF1P1C (0 << 0)
295#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0)
296#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0)
297#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0)
298#define DISP_DATA_FORMAT_DF2S (5 << 0)
299#define DISP_DATA_FORMAT_DF3S (6 << 0)
300#define DISP_DATA_FORMAT_DFSPI (7 << 0)
301#define DISP_DATA_FORMAT_DF1P3C24B (8 << 0)
302#define DISP_DATA_FORMAT_DF1P3C18B (9 << 0)
303#define DISP_DATA_ALIGNMENT_MSB (0 << 8)
304#define DISP_DATA_ALIGNMENT_LSB (1 << 8)
305#define DISP_DATA_ORDER_RED_BLUE (0 << 9)
306#define DISP_DATA_ORDER_BLUE_RED (1 << 9)
307
308#define DC_DISP_DISP_COLOR_CONTROL 0x430
309#define BASE_COLOR_SIZE666 (0 << 0)
310#define BASE_COLOR_SIZE111 (1 << 0)
311#define BASE_COLOR_SIZE222 (2 << 0)
312#define BASE_COLOR_SIZE333 (3 << 0)
313#define BASE_COLOR_SIZE444 (4 << 0)
314#define BASE_COLOR_SIZE555 (5 << 0)
315#define BASE_COLOR_SIZE565 (6 << 0)
316#define BASE_COLOR_SIZE332 (7 << 0)
317#define BASE_COLOR_SIZE888 (8 << 0)
318
319#define DITHER_CONTROL_DISABLE (0 << 8)
320#define DITHER_CONTROL_ORDERED (2 << 8)
321#define DITHER_CONTROL_ERRDIFF (3 << 8)
322
323#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
324#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
325#define DE_SELECT_ACTIVE_BLANK 0x0
326#define DE_SELECT_ACTIVE 0x1
327#define DE_SELECT_ACTIVE_IS 0x2
328#define DE_CONTROL_ONECLK (0 << 2)
329#define DE_CONTROL_NORMAL (1 << 2)
330#define DE_CONTROL_EARLY_EXT (2 << 2)
331#define DE_CONTROL_EARLY (3 << 2)
332#define DE_CONTROL_ACTIVE_BLANK (4 << 2)
333
334#define DC_DISP_SERIAL_INTERFACE_OPTIONS 0x433
335#define DC_DISP_LCD_SPI_OPTIONS 0x434
336#define DC_DISP_BORDER_COLOR 0x435
337#define DC_DISP_COLOR_KEY0_LOWER 0x436
338#define DC_DISP_COLOR_KEY0_UPPER 0x437
339#define DC_DISP_COLOR_KEY1_LOWER 0x438
340#define DC_DISP_COLOR_KEY1_UPPER 0x439
341
342#define DC_DISP_CURSOR_FOREGROUND 0x43c
343#define DC_DISP_CURSOR_BACKGROUND 0x43d
344#define CURSOR_COLOR(_r, _g, _b) ((_r) | ((_g) << 8) | ((_b) << 16))
345
346#define DC_DISP_CURSOR_START_ADDR 0x43e
347#define DC_DISP_CURSOR_START_ADDR_NS 0x43f
348#define CURSOR_START_ADDR_MASK (((1 << 22) - 1) << 10)
349#define CURSOR_START_ADDR(_addr) ((_addr) >> 10)
350#define CURSOR_SIZE_64 (1 << 24)
351
352#define DC_DISP_CURSOR_POSITION 0x440
353#define CURSOR_POSITION(_x, _y) \
354 (((_x) & ((1 << 16) - 1)) | \
355 (((_y) & ((1 << 16) - 1)) << 16))
356
357#define DC_DISP_CURSOR_POSITION_NS 0x441
358#define DC_DISP_INIT_SEQ_CONTROL 0x442
359#define DC_DISP_SPI_INIT_SEQ_DATA_A 0x443
360#define DC_DISP_SPI_INIT_SEQ_DATA_B 0x444
361#define DC_DISP_SPI_INIT_SEQ_DATA_C 0x445
362#define DC_DISP_SPI_INIT_SEQ_DATA_D 0x446
363#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480
364#define DC_DISP_MCCIF_DISPLAY0A_HYST 0x481
365#define DC_DISP_MCCIF_DISPLAY0B_HYST 0x482
366#define DC_DISP_MCCIF_DISPLAY0C_HYST 0x483
367#define DC_DISP_MCCIF_DISPLAY1B_HYST 0x484
368#define DC_DISP_DAC_CRT_CTRL 0x4c0
369#define DC_DISP_DISP_MISC_CONTROL 0x4c1
370
371#define DC_WIN_COLOR_PALETTE(x) (0x500 + (x))
372
373#define DC_WIN_PALETTE_COLOR_EXT 0x600
374#define DC_WIN_H_FILTER_P(x) (0x601 + (x))
375#define DC_WIN_CSC_YOF 0x611
376#define DC_WIN_CSC_KYRGB 0x612
377#define DC_WIN_CSC_KUR 0x613
378#define DC_WIN_CSC_KVR 0x614
379#define DC_WIN_CSC_KUG 0x615
380#define DC_WIN_CSC_KVG 0x616
381#define DC_WIN_CSC_KUB 0x617
382#define DC_WIN_CSC_KVB 0x618
383#define DC_WIN_V_FILTER_P(x) (0x619 + (x))
384#define DC_WIN_WIN_OPTIONS 0x700
385#define H_DIRECTION_INCREMENT (0 << 0)
386#define H_DIRECTION_DECREMENT (1 << 0)
387#define V_DIRECTION_INCREMENT (0 << 2)
388#define V_DIRECTION_DECREMENT (1 << 2)
389#define COLOR_EXPAND (1 << 6)
390#define H_FILTER_ENABLE (1 << 8)
391#define V_FILTER_ENABLE (1 << 10)
392#define CP_ENABLE (1 << 16)
393#define CSC_ENABLE (1 << 18)
394#define DV_ENABLE (1 << 20)
395#define WIN_ENABLE (1 << 30)
396
397#define DC_WIN_BYTE_SWAP 0x701
398#define BYTE_SWAP_NOSWAP 0
399#define BYTE_SWAP_SWAP2 1
400#define BYTE_SWAP_SWAP4 2
401#define BYTE_SWAP_SWAP4HW 3
402
403#define DC_WIN_BUFFER_CONTROL 0x702
404#define BUFFER_CONTROL_HOST 0
405#define BUFFER_CONTROL_VI 1
406#define BUFFER_CONTROL_EPP 2
407#define BUFFER_CONTROL_MPEGE 3
408#define BUFFER_CONTROL_SB2D 4
409
410#define DC_WIN_COLOR_DEPTH 0x703
411
412#define DC_WIN_POSITION 0x704
413#define H_POSITION(x) (((x) & 0xfff) << 0)
414#define V_POSITION(x) (((x) & 0xfff) << 16)
415
416#define DC_WIN_SIZE 0x705
417#define H_SIZE(x) (((x) & 0xfff) << 0)
418#define V_SIZE(x) (((x) & 0xfff) << 16)
419
420#define DC_WIN_PRESCALED_SIZE 0x706
421#define H_PRESCALED_SIZE(x) (((x) & 0x3fff) << 0)
422#define V_PRESCALED_SIZE(x) (((x) & 0xfff) << 16)
423
424#define DC_WIN_H_INITIAL_DDA 0x707
425#define DC_WIN_V_INITIAL_DDA 0x708
426#define DC_WIN_DDA_INCREMENT 0x709
427#define H_DDA_INC(x) (((x) & 0xffff) << 0)
428#define V_DDA_INC(x) (((x) & 0xffff) << 16)
429
430#define DC_WIN_LINE_STRIDE 0x70a
431#define LINE_STRIDE(x) (x)
432#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
433#define DC_WIN_BUF_STRIDE 0x70b
434#define DC_WIN_UV_BUF_STRIDE 0x70c
435#define DC_WIN_BUFFER_ADDR_MODE 0x70d
436#define DC_WIN_BUFFER_ADDR_MODE_LINEAR (0 << 0)
437#define DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV (0 << 16)
438#define DC_WIN_BUFFER_ADDR_MODE_TILE (1 << 0)
439#define DC_WIN_BUFFER_ADDR_MODE_TILE_UV (1 << 16)
440#define DC_WIN_DV_CONTROL 0x70e
441#define DC_WIN_BLEND_NOKEY 0x70f
442#define DC_WIN_BLEND_1WIN 0x710
443#define DC_WIN_BLEND_2WIN_X 0x711
444#define DC_WIN_BLEND_2WIN_Y 0x712
445#define DC_WIN_BLEND_3WIN_XY 0x713
446#define CKEY_NOKEY (0 << 0)
447#define CKEY_KEY0 (1 << 0)
448#define CKEY_KEY1 (2 << 0)
449#define CKEY_KEY01 (3 << 0)
450#define BLEND_CONTROL_FIX (0 << 2)
451#define BLEND_CONTROL_ALPHA (1 << 2)
452#define BLEND_CONTROL_DEPENDANT (2 << 2)
453#define BLEND_CONTROL_PREMULT (3 << 2)
454#define BLEND_WEIGHT0(x) (((x) & 0xff) << 8)
455#define BLEND_WEIGHT1(x) (((x) & 0xff) << 16)
456#define BLEND(key, control, weight0, weight1) \
457 (CKEY_ ## key | BLEND_CONTROL_ ## control | \
458 BLEND_WEIGHT0(weight0) | BLEND_WEIGHT1(weight1))
459
460
461#define DC_WIN_HP_FETCH_CONTROL 0x714
462#define DC_WINBUF_START_ADDR 0x800
463#define DC_WINBUF_START_ADDR_NS 0x801
464#define DC_WINBUF_START_ADDR_U 0x802
465#define DC_WINBUF_START_ADDR_U_NS 0x803
466#define DC_WINBUF_START_ADDR_V 0x804
467#define DC_WINBUF_START_ADDR_V_NS 0x805
468#define DC_WINBUF_ADDR_H_OFFSET 0x806
469#define DC_WINBUF_ADDR_H_OFFSET_NS 0x807
470#define DC_WINBUF_ADDR_V_OFFSET 0x808
471#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
472#define DC_WINBUF_UFLOW_STATUS 0x80a
473
474/* direct versions of DC_WINBUF_UFLOW_STATUS */
475#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
476#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
477#define DC_WINBUF_CD_UFLOW_STATUS 0xfca
478
479#define DC_DISP_SD_CONTROL 0x4c2
480#define SD_ENABLE_NORMAL (1 << 0)
481#define SD_ENABLE_ONESHOT (2 << 0)
482#define SD_USE_VID_LUMA (1 << 2)
483#define SD_BIN_WIDTH_ONE (0 << 3)
484#define SD_BIN_WIDTH_TWO (1 << 3)
485#define SD_BIN_WIDTH_FOUR (2 << 3)
486#define SD_BIN_WIDTH_EIGHT (3 << 3)
487#define SD_BIN_WIDTH_MASK (3 << 3)
488#define SD_AGGRESSIVENESS(x) (((x) & 0x7) << 5)
489#define SD_HW_UPDATE_DLY(x) (((x) & 0x3) << 8)
490#define SD_ONESHOT_ENABLE (1 << 10)
491#define SD_CORRECTION_MODE_AUTO (0 << 11)
492#define SD_CORRECTION_MODE_MAN (1 << 11)
493
494#define NUM_BIN_WIDTHS 4
495#define STEPS_PER_AGG_LVL 64
496#define STEPS_PER_AGG_CHG_LOG2 5
497#define STEPS_PER_AGG_CHG (1<<STEPS_PER_AGG_CHG_LOG2)
498#define ADJ_PHASE_STEP 8
499#define K_STEP 4
500
501#define DC_DISP_SD_CSC_COEFF 0x4c3
502#define SD_CSC_COEFF_R(x) (((x) & 0xf) << 4)
503#define SD_CSC_COEFF_G(x) (((x) & 0xf) << 12)
504#define SD_CSC_COEFF_B(x) (((x) & 0xf) << 20)
505
506#define DC_DISP_SD_LUT(i) (0x4c4 + i)
507#define DC_DISP_SD_LUT_NUM 9
508#define SD_LUT_R(x) (((x) & 0xff) << 0)
509#define SD_LUT_G(x) (((x) & 0xff) << 8)
510#define SD_LUT_B(x) (((x) & 0xff) << 16)
511
512#define DC_DISP_SD_FLICKER_CONTROL 0x4cd
513#define SD_FC_TIME_LIMIT(x) (((x) & 0xff) << 0)
514#define SD_FC_THRESHOLD(x) (((x) & 0xff) << 8)
515
516#define DC_DISP_SD_PIXEL_COUNT 0x4ce
517
518#define DC_DISP_SD_HISTOGRAM(i) (0x4cf + i)
519#define DC_DISP_SD_HISTOGRAM_NUM 8
520#define SD_HISTOGRAM_BIN_0(val) (((val) & (0xff << 0)) >> 0)
521#define SD_HISTOGRAM_BIN_1(val) (((val) & (0xff << 8)) >> 8)
522#define SD_HISTOGRAM_BIN_2(val) (((val) & (0xff << 16)) >> 16)
523#define SD_HISTOGRAM_BIN_3(val) (((val) & (0xff << 24)) >> 24)
524
525#define DC_DISP_SD_BL_PARAMETERS 0x4d7
526#define SD_BLP_TIME_CONSTANT(x) (((x) & 0x7ff) << 0)
527#define SD_BLP_STEP(x) (((x) & 0xff) << 16)
528
529#define DC_DISP_SD_BL_TF(i) (0x4d8 + i)
530#define DC_DISP_SD_BL_TF_NUM 4
531#define SD_BL_TF_POINT_0(x) (((x) & 0xff) << 0)
532#define SD_BL_TF_POINT_1(x) (((x) & 0xff) << 8)
533#define SD_BL_TF_POINT_2(x) (((x) & 0xff) << 16)
534#define SD_BL_TF_POINT_3(x) (((x) & 0xff) << 24)
535
536#define DC_DISP_SD_BL_CONTROL 0x4dc
537#define SD_BLC_MODE_MAN (0 << 0)
538#define SD_BLC_MODE_AUTO (1 << 1)
539#define SD_BLC_BRIGHTNESS(val) (((val) & (0xff << 8)) >> 8)
540
541#define DC_DISP_SD_HW_K_VALUES 0x4dd
542#define SD_HW_K_R(val) (((val) & (0x3ff << 0)) >> 0)
543#define SD_HW_K_G(val) (((val) & (0x3ff << 10)) >> 10)
544#define SD_HW_K_B(val) (((val) & (0x3ff << 20)) >> 20)
545
546#define DC_DISP_SD_MAN_K_VALUES 0x4de
547#define SD_MAN_K_R(x) (((x) & 0x3ff) << 0)
548#define SD_MAN_K_G(x) (((x) & 0x3ff) << 10)
549#define SD_MAN_K_B(x) (((x) & 0x3ff) << 20)
550
551#define NUM_AGG_PRI_LVLS 4
552#define SD_AGG_PRI_LVL(x) ((x) >> 3)
553#define SD_GET_AGG(x) ((x) & 0x7)
554
555#endif
diff --git a/drivers/video/tegra/dc/dc_sysfs.c b/drivers/video/tegra/dc/dc_sysfs.c
new file mode 100644
index 00000000000..6bb18382e6e
--- /dev/null
+++ b/drivers/video/tegra/dc/dc_sysfs.c
@@ -0,0 +1,327 @@
1/*
2 * drivers/video/tegra/dc/dc_sysfs.c
3 *
4 * Copyright (c) 2011, NVIDIA Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include <linux/platform_device.h>
22#include <linux/kernel.h>
23
24#include <mach/dc.h>
25#include <mach/fb.h>
26
27#include "dc_reg.h"
28#include "dc_priv.h"
29#include "nvsd.h"
30
31static ssize_t mode_show(struct device *device,
32 struct device_attribute *attr, char *buf)
33{
34 struct nvhost_device *ndev = to_nvhost_device(device);
35 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
36 struct tegra_dc_mode *m;
37 ssize_t res;
38
39 mutex_lock(&dc->lock);
40 m = &dc->mode;
41 res = snprintf(buf, PAGE_SIZE,
42 "pclk: %d\n"
43 "h_ref_to_sync: %d\n"
44 "v_ref_to_sync: %d\n"
45 "h_sync_width: %d\n"
46 "v_sync_width: %d\n"
47 "h_back_porch: %d\n"
48 "v_back_porch: %d\n"
49 "h_active: %d\n"
50 "v_active: %d\n"
51 "h_front_porch: %d\n"
52 "v_front_porch: %d\n"
53 "stereo_mode: %d\n",
54 m->pclk, m->h_ref_to_sync, m->v_ref_to_sync,
55 m->h_sync_width, m->v_sync_width,
56 m->h_back_porch, m->v_back_porch,
57 m->h_active, m->v_active,
58 m->h_front_porch, m->v_front_porch,
59 m->stereo_mode);
60 mutex_unlock(&dc->lock);
61
62 return res;
63}
64
65static DEVICE_ATTR(mode, S_IRUGO, mode_show, NULL);
66
67static ssize_t stats_enable_show(struct device *dev,
68 struct device_attribute *attr, char *buf)
69{
70 struct nvhost_device *ndev = to_nvhost_device(dev);
71 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
72 bool enabled;
73
74 if (mutex_lock_killable(&dc->lock))
75 return -EINTR;
76 enabled = tegra_dc_stats_get(dc);
77 mutex_unlock(&dc->lock);
78
79 return snprintf(buf, PAGE_SIZE, "%d", enabled);
80}
81
82static ssize_t stats_enable_store(struct device *dev,
83 struct device_attribute *attr, const char *buf, size_t count)
84{
85 struct nvhost_device *ndev = to_nvhost_device(dev);
86 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
87 unsigned long val = 0;
88
89 if (strict_strtoul(buf, 10, &val) < 0)
90 return -EINVAL;
91
92 if (mutex_lock_killable(&dc->lock))
93 return -EINTR;
94 tegra_dc_stats_enable(dc, !!val);
95 mutex_unlock(&dc->lock);
96
97 return count;
98}
99
100static DEVICE_ATTR(stats_enable, S_IRUGO|S_IWUSR,
101 stats_enable_show, stats_enable_store);
102
103static ssize_t enable_show(struct device *device,
104 struct device_attribute *attr, char *buf)
105{
106 struct nvhost_device *ndev = to_nvhost_device(device);
107 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
108 ssize_t res;
109
110 mutex_lock(&dc->lock);
111 res = snprintf(buf, PAGE_SIZE, "%d\n", dc->enabled);
112 mutex_unlock(&dc->lock);
113 return res;
114}
115
116static ssize_t enable_store(struct device *dev,
117 struct device_attribute *attr, const char *buf, size_t count)
118{
119 struct nvhost_device *ndev = to_nvhost_device(dev);
120 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
121 unsigned long val = 0;
122
123 if (strict_strtoul(buf, 10, &val) < 0)
124 return -EINVAL;
125
126 if (val) {
127 tegra_dc_enable(dc);
128 } else {
129 tegra_dc_disable(dc);
130 }
131
132 return count;
133}
134
135static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, enable_show, enable_store);
136
137static ssize_t crc_checksum_latched_show(struct device *device,
138 struct device_attribute *attr, char *buf)
139{
140 struct nvhost_device *ndev = to_nvhost_device(device);
141 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
142
143 u32 crc;
144
145 if (!dc->enabled) {
146 dev_err(&dc->ndev->dev, "Failed to get dc.\n");
147 return -EFAULT;
148 }
149
150 crc = tegra_dc_read_checksum_latched(dc);
151
152 return snprintf(buf, PAGE_SIZE, "%u", crc);
153}
154
155static ssize_t crc_checksum_latched_store(struct device *dev,
156 struct device_attribute *attr, const char *buf, size_t count)
157{
158 struct nvhost_device *ndev = to_nvhost_device(dev);
159 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
160 unsigned long val = 0;
161
162 if (!dc->enabled) {
163 dev_err(&dc->ndev->dev, "Failed to get dc.\n");
164 return -EFAULT;
165 }
166
167 if (strict_strtoul(buf, 10, &val) < 0)
168 return -EINVAL;
169
170 if (val == 1) {
171 tegra_dc_enable_crc(dc);
172 dev_err(&dc->ndev->dev, "crc is enabled.\n");
173 } else if (val == 0) {
174 tegra_dc_disable_crc(dc);
175 dev_err(&dc->ndev->dev, "crc is disabled.\n");
176 } else
177 dev_err(&dc->ndev->dev, "Invalid input.\n");
178
179 return count;
180}
181static DEVICE_ATTR(crc_checksum_latched, S_IRUGO|S_IWUSR,
182 crc_checksum_latched_show, crc_checksum_latched_store);
183
184#define ORIENTATION_PORTRAIT "portrait"
185#define ORIENTATION_LANDSCAPE "landscape"
186
187static ssize_t orientation_3d_show(struct device *dev,
188 struct device_attribute *attr, char *buf)
189{
190 struct nvhost_device *ndev = to_nvhost_device(dev);
191 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
192 struct tegra_dc_out *dc_out = dc->out;
193 const char *orientation;
194 switch (dc_out->stereo->orientation) {
195 case TEGRA_DC_STEREO_LANDSCAPE:
196 orientation = ORIENTATION_LANDSCAPE;
197 break;
198 case TEGRA_DC_STEREO_PORTRAIT:
199 orientation = ORIENTATION_PORTRAIT;
200 break;
201 default:
202 pr_err("Invalid value is stored for stereo_orientation.\n");
203 return -EINVAL;
204 }
205 return snprintf(buf, PAGE_SIZE, "%s\n", orientation);
206}
207
208static ssize_t orientation_3d_store(struct device *dev,
209 struct device_attribute *attr, const char *buf, size_t cnt)
210{
211 struct nvhost_device *ndev = to_nvhost_device(dev);
212 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
213 struct tegra_dc_out *dc_out = dc->out;
214 struct tegra_stereo_out *stereo = dc_out->stereo;
215 int orientation;
216
217 if (0 == strncmp(buf, ORIENTATION_PORTRAIT,
218 min(cnt, ARRAY_SIZE(ORIENTATION_PORTRAIT) - 1))) {
219 orientation = TEGRA_DC_STEREO_PORTRAIT;
220 } else if (0 == strncmp(buf, ORIENTATION_LANDSCAPE,
221 min(cnt, ARRAY_SIZE(ORIENTATION_LANDSCAPE) - 1))) {
222 orientation = TEGRA_DC_STEREO_LANDSCAPE;
223 } else {
224 pr_err("Invalid property value for stereo_orientation.\n");
225 return -EINVAL;
226 }
227 stereo->orientation = orientation;
228 stereo->set_orientation(orientation);
229 return cnt;
230}
231
232static DEVICE_ATTR(stereo_orientation,
233 S_IRUGO|S_IWUSR, orientation_3d_show, orientation_3d_store);
234
235#define MODE_2D "2d"
236#define MODE_3D "3d"
237
238static ssize_t mode_3d_show(struct device *dev,
239 struct device_attribute *attr, char *buf)
240{
241 struct nvhost_device *ndev = to_nvhost_device(dev);
242 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
243 struct tegra_dc_out *dc_out = dc->out;
244 const char *mode;
245 switch (dc_out->stereo->mode_2d_3d) {
246 case TEGRA_DC_STEREO_MODE_2D:
247 mode = MODE_2D;
248 break;
249 case TEGRA_DC_STEREO_MODE_3D:
250 mode = MODE_3D;
251 break;
252 default:
253 pr_err("Invalid value is stored for stereo_mode.\n");
254 return -EINVAL;
255 }
256 return snprintf(buf, PAGE_SIZE, "%s\n", mode);
257}
258
259static ssize_t mode_3d_store(struct device *dev,
260 struct device_attribute *attr, const char *buf, size_t cnt)
261{
262 struct nvhost_device *ndev = to_nvhost_device(dev);
263 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
264 struct tegra_dc_out *dc_out = dc->out;
265 struct tegra_stereo_out *stereo = dc_out->stereo;
266 int mode;
267
268 if (0 == strncmp(buf, MODE_2D, min(cnt, ARRAY_SIZE(MODE_2D) - 1))) {
269 mode = TEGRA_DC_STEREO_MODE_2D;
270 } else if (0 == strncmp(buf, MODE_3D,
271 min(cnt, ARRAY_SIZE(MODE_3D) - 1))) {
272 mode = TEGRA_DC_STEREO_MODE_3D;
273 } else {
274 pr_err("Invalid property value for stereo_mode.\n");
275 return -EINVAL;
276 }
277 stereo->mode_2d_3d = mode;
278 stereo->set_mode(mode);
279 return cnt;
280}
281
282static DEVICE_ATTR(stereo_mode,
283 S_IRUGO|S_IWUSR, mode_3d_show, mode_3d_store);
284
285void __devexit tegra_dc_remove_sysfs(struct device *dev)
286{
287 struct nvhost_device *ndev = to_nvhost_device(dev);
288 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
289 struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
290
291 device_remove_file(dev, &dev_attr_mode);
292 device_remove_file(dev, &dev_attr_enable);
293 device_remove_file(dev, &dev_attr_stats_enable);
294 device_remove_file(dev, &dev_attr_crc_checksum_latched);
295
296 if (dc->out->stereo) {
297 device_remove_file(dev, &dev_attr_stereo_orientation);
298 device_remove_file(dev, &dev_attr_stereo_mode);
299 }
300
301 if (sd_settings)
302 nvsd_remove_sysfs(dev);
303}
304
305void tegra_dc_create_sysfs(struct device *dev)
306{
307 struct nvhost_device *ndev = to_nvhost_device(dev);
308 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
309 struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
310 int error = 0;
311
312 error |= device_create_file(dev, &dev_attr_mode);
313 error |= device_create_file(dev, &dev_attr_enable);
314 error |= device_create_file(dev, &dev_attr_stats_enable);
315 error |= device_create_file(dev, &dev_attr_crc_checksum_latched);
316
317 if (dc->out->stereo) {
318 error |= device_create_file(dev, &dev_attr_stereo_orientation);
319 error |= device_create_file(dev, &dev_attr_stereo_mode);
320 }
321
322 if (sd_settings)
323 error |= nvsd_create_sysfs(dev);
324
325 if (error)
326 dev_err(&ndev->dev, "Failed to create sysfs attributes!\n");
327}
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
new file mode 100644
index 00000000000..c33d6e0a58b
--- /dev/null
+++ b/drivers/video/tegra/dc/dsi.c
@@ -0,0 +1,3042 @@
1/*
2 * drivers/video/tegra/dc/dsi.c
3 *
4 * Copyright (c) 2011, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/clk.h>
18#include <linux/delay.h>
19#include <linux/err.h>
20#include <linux/fb.h>
21#include <linux/gpio.h>
22#include <linux/interrupt.h>
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/spinlock.h>
26#include <linux/workqueue.h>
27
28#include <mach/clk.h>
29#include <mach/dc.h>
30#include <mach/fb.h>
31#include <mach/csi.h>
32#include <linux/nvhost.h>
33
34#include "dc_reg.h"
35#include "dc_priv.h"
36#include "dsi_regs.h"
37#include "dsi.h"
38
39#define DSI_USE_SYNC_POINTS 1
40#define S_TO_MS(x) (1000 * (x))
41
42#define DSI_MODULE_NOT_INIT 0x0
43#define DSI_MODULE_INIT 0x1
44
45#define DSI_LPHS_NOT_INIT 0x0
46#define DSI_LPHS_IN_LP_MODE 0x1
47#define DSI_LPHS_IN_HS_MODE 0x2
48
49#define DSI_VIDEO_TYPE_NOT_INIT 0x0
50#define DSI_VIDEO_TYPE_VIDEO_MODE 0x1
51#define DSI_VIDEO_TYPE_CMD_MODE 0x2
52
53#define DSI_DRIVEN_MODE_NOT_INIT 0x0
54#define DSI_DRIVEN_MODE_DC 0x1
55#define DSI_DRIVEN_MODE_HOST 0x2
56
57#define DSI_PHYCLK_OUT_DIS 0x0
58#define DSI_PHYCLK_OUT_EN 0x1
59
60#define DSI_PHYCLK_NOT_INIT 0x0
61#define DSI_PHYCLK_CONTINUOUS 0x1
62#define DSI_PHYCLK_TX_ONLY 0x2
63
64#define DSI_CLK_BURST_NOT_INIT 0x0
65#define DSI_CLK_BURST_NONE_BURST 0x1
66#define DSI_CLK_BURST_BURST_MODE 0x2
67
68#define DSI_DC_STREAM_DISABLE 0x0
69#define DSI_DC_STREAM_ENABLE 0x1
70
71#define DSI_LP_OP_NOT_INIT 0x0
72#define DSI_LP_OP_WRITE 0x1
73#define DSI_LP_OP_READ 0x2
74
75static bool enable_read_debug;
76module_param(enable_read_debug, bool, 0644);
77MODULE_PARM_DESC(enable_read_debug,
78 "Enable to print read fifo and return packet type");
79
80struct dsi_status {
81 unsigned init:2;
82
83 unsigned lphs:2;
84
85 unsigned vtype:2;
86 unsigned driven:2;
87
88 unsigned clk_out:2;
89 unsigned clk_mode:2;
90 unsigned clk_burst:2;
91
92 unsigned lp_op:2;
93
94 unsigned dc_stream:1;
95};
96
97/* source of video data */
98enum {
99 TEGRA_DSI_DRIVEN_BY_DC,
100 TEGRA_DSI_DRIVEN_BY_HOST,
101};
102
103struct tegra_dc_dsi_data {
104 struct tegra_dc *dc;
105 void __iomem *base;
106 struct resource *base_res;
107
108 struct clk *dc_clk;
109 struct clk *dsi_clk;
110 bool clk_ref;
111
112 struct mutex lock;
113
114 /* data from board info */
115 struct tegra_dsi_out info;
116
117 struct dsi_status status;
118
119 struct dsi_phy_timing_inclk phy_timing;
120
121 u8 driven_mode;
122 u8 controller_index;
123
124 u8 pixel_scaler_mul;
125 u8 pixel_scaler_div;
126
127 u32 default_shift_clk_div;
128 u32 default_pixel_clk_khz;
129 u32 default_hs_clk_khz;
130
131 u32 shift_clk_div;
132 u32 target_hs_clk_khz;
133 u32 target_lp_clk_khz;
134
135 u32 syncpt_id;
136 u32 syncpt_val;
137
138 u16 current_bit_clk_ns;
139 u32 current_dsi_clk_khz;
140
141 u32 dsi_control_val;
142
143 bool ulpm;
144 bool enabled;
145};
146
147const u32 dsi_pkt_seq_reg[NUMOF_PKT_SEQ] = {
148 DSI_PKT_SEQ_0_LO,
149 DSI_PKT_SEQ_0_HI,
150 DSI_PKT_SEQ_1_LO,
151 DSI_PKT_SEQ_1_HI,
152 DSI_PKT_SEQ_2_LO,
153 DSI_PKT_SEQ_2_HI,
154 DSI_PKT_SEQ_3_LO,
155 DSI_PKT_SEQ_3_HI,
156 DSI_PKT_SEQ_4_LO,
157 DSI_PKT_SEQ_4_HI,
158 DSI_PKT_SEQ_5_LO,
159 DSI_PKT_SEQ_5_HI,
160};
161
162const u32 dsi_pkt_seq_video_non_burst_syne[NUMOF_PKT_SEQ] = {
163 PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
164 0,
165 PKT_ID0(CMD_VE) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
166 0,
167 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
168 0,
169 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
170 PKT_ID2(CMD_HE) | PKT_LEN2(0),
171 PKT_ID3(CMD_BLNK) | PKT_LEN3(2) | PKT_ID4(CMD_RGB) | PKT_LEN4(3) |
172 PKT_ID5(CMD_BLNK) | PKT_LEN5(4),
173 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
174 0,
175 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
176 PKT_ID2(CMD_HE) | PKT_LEN2(0),
177 PKT_ID3(CMD_BLNK) | PKT_LEN3(2) | PKT_ID4(CMD_RGB) | PKT_LEN4(3) |
178 PKT_ID5(CMD_BLNK) | PKT_LEN5(4),
179};
180
181const u32 dsi_pkt_seq_video_non_burst[NUMOF_PKT_SEQ] = {
182 PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
183 0,
184 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
185 0,
186 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
187 0,
188 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2) |
189 PKT_ID2(CMD_RGB) | PKT_LEN2(3),
190 PKT_ID3(CMD_BLNK) | PKT_LEN3(4),
191 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
192 0,
193 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2) |
194 PKT_ID2(CMD_RGB) | PKT_LEN2(3),
195 PKT_ID3(CMD_BLNK) | PKT_LEN3(4),
196};
197
198static const u32 dsi_pkt_seq_video_burst[NUMOF_PKT_SEQ] = {
199 PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(7) | PKT_LP,
200 0,
201 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(7) | PKT_LP,
202 0,
203 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(7) | PKT_LP,
204 0,
205 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2)|
206 PKT_ID2(CMD_RGB) | PKT_LEN2(3) | PKT_LP,
207 PKT_ID0(CMD_EOT) | PKT_LEN0(7),
208 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(7) | PKT_LP,
209 0,
210 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2)|
211 PKT_ID2(CMD_RGB) | PKT_LEN2(3) | PKT_LP,
212 PKT_ID0(CMD_EOT) | PKT_LEN0(7),
213};
214
215static const u32 dsi_pkt_seq_video_burst_no_eot[NUMOF_PKT_SEQ] = {
216 PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
217 0,
218 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
219 0,
220 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
221 0,
222 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2)|
223 PKT_ID2(CMD_RGB) | PKT_LEN2(3) | PKT_LP,
224 PKT_ID0(CMD_EOT) | PKT_LEN0(0),
225 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
226 0,
227 PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2)|
228 PKT_ID2(CMD_RGB) | PKT_LEN2(3) | PKT_LP,
229 PKT_ID0(CMD_EOT) | PKT_LEN0(0),
230};
231
232/* TODO: verify with hw about this format */
233const u32 dsi_pkt_seq_cmd_mode[NUMOF_PKT_SEQ] = {
234 0,
235 0,
236 0,
237 0,
238 0,
239 0,
240 PKT_ID0(CMD_LONGW) | PKT_LEN0(3) | PKT_ID1(CMD_EOT) | PKT_LEN1(7),
241 0,
242 0,
243 0,
244 PKT_ID0(CMD_LONGW) | PKT_LEN0(3) | PKT_ID1(CMD_EOT) | PKT_LEN1(7),
245 0,
246};
247
248const u32 init_reg[] = {
249 DSI_INT_ENABLE,
250 DSI_INT_STATUS,
251 DSI_INT_MASK,
252 DSI_INIT_SEQ_DATA_0,
253 DSI_INIT_SEQ_DATA_1,
254 DSI_INIT_SEQ_DATA_2,
255 DSI_INIT_SEQ_DATA_3,
256 DSI_INIT_SEQ_DATA_4,
257 DSI_INIT_SEQ_DATA_5,
258 DSI_INIT_SEQ_DATA_6,
259 DSI_INIT_SEQ_DATA_7,
260 DSI_DCS_CMDS,
261 DSI_PKT_SEQ_0_LO,
262 DSI_PKT_SEQ_1_LO,
263 DSI_PKT_SEQ_2_LO,
264 DSI_PKT_SEQ_3_LO,
265 DSI_PKT_SEQ_4_LO,
266 DSI_PKT_SEQ_5_LO,
267 DSI_PKT_SEQ_0_HI,
268 DSI_PKT_SEQ_1_HI,
269 DSI_PKT_SEQ_2_HI,
270 DSI_PKT_SEQ_3_HI,
271 DSI_PKT_SEQ_4_HI,
272 DSI_PKT_SEQ_5_HI,
273 DSI_CONTROL,
274 DSI_HOST_DSI_CONTROL,
275 DSI_PAD_CONTROL,
276 DSI_PAD_CONTROL_CD,
277 DSI_SOL_DELAY,
278 DSI_MAX_THRESHOLD,
279 DSI_TRIGGER,
280 DSI_TX_CRC,
281 DSI_INIT_SEQ_CONTROL,
282 DSI_PKT_LEN_0_1,
283 DSI_PKT_LEN_2_3,
284 DSI_PKT_LEN_4_5,
285 DSI_PKT_LEN_6_7,
286};
287
288inline unsigned long tegra_dsi_readl(struct tegra_dc_dsi_data *dsi, u32 reg)
289{
290 BUG_ON(!nvhost_module_powered(nvhost_get_host(dsi->dc->ndev)->dev));
291 return readl(dsi->base + reg * 4);
292}
293EXPORT_SYMBOL(tegra_dsi_readl);
294
295inline void tegra_dsi_writel(struct tegra_dc_dsi_data *dsi, u32 val, u32 reg)
296{
297 BUG_ON(!nvhost_module_powered(nvhost_get_host(dsi->dc->ndev)->dev));
298 writel(val, dsi->base + reg * 4);
299}
300EXPORT_SYMBOL(tegra_dsi_writel);
301
302static int tegra_dsi_syncpt(struct tegra_dc_dsi_data *dsi)
303{
304 u32 val;
305 int ret;
306
307 ret = 0;
308
309 dsi->syncpt_val = nvhost_syncpt_read(
310 &nvhost_get_host(dsi->dc->ndev)->syncpt,
311 dsi->syncpt_id);
312
313 val = DSI_INCR_SYNCPT_COND(OP_DONE) |
314 DSI_INCR_SYNCPT_INDX(dsi->syncpt_id);
315 tegra_dsi_writel(dsi, val, DSI_INCR_SYNCPT);
316
317 /* TODO: Use interrupt rather than polling */
318 ret = nvhost_syncpt_wait(&nvhost_get_host(dsi->dc->ndev)->syncpt,
319 dsi->syncpt_id, dsi->syncpt_val + 1);
320 if (ret < 0) {
321 dev_err(&dsi->dc->ndev->dev, "DSI sync point failure\n");
322 goto fail;
323 }
324
325 (dsi->syncpt_val)++;
326 return 0;
327fail:
328 return ret;
329}
330
331static u32 tegra_dsi_get_hs_clk_rate(struct tegra_dc_dsi_data *dsi)
332{
333 u32 dsi_clock_rate_khz;
334
335 switch (dsi->info.video_burst_mode) {
336 case TEGRA_DSI_VIDEO_BURST_MODE_LOW_SPEED:
337 case TEGRA_DSI_VIDEO_BURST_MODE_MEDIUM_SPEED:
338 case TEGRA_DSI_VIDEO_BURST_MODE_FAST_SPEED:
339 case TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED:
340 /* Calculate DSI HS clock rate for DSI burst mode */
341 dsi_clock_rate_khz = dsi->default_pixel_clk_khz *
342 dsi->shift_clk_div;
343 break;
344 case TEGRA_DSI_VIDEO_NONE_BURST_MODE:
345 case TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END:
346 case TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED:
347 default:
348 /* Clock rate is default DSI clock rate for non-burst mode */
349 dsi_clock_rate_khz = dsi->default_hs_clk_khz;
350 break;
351 }
352
353 return dsi_clock_rate_khz;
354}
355
356static u32 tegra_dsi_get_lp_clk_rate(struct tegra_dc_dsi_data *dsi, u8 lp_op)
357{
358 u32 dsi_clock_rate_khz;
359
360 if (dsi->info.enable_hs_clock_on_lp_cmd_mode)
361 if (dsi->info.hs_clk_in_lp_cmd_mode_freq_khz)
362 dsi_clock_rate_khz =
363 dsi->info.hs_clk_in_lp_cmd_mode_freq_khz;
364 else
365 dsi_clock_rate_khz = tegra_dsi_get_hs_clk_rate(dsi);
366 else
367 if (lp_op == DSI_LP_OP_READ)
368 dsi_clock_rate_khz =
369 dsi->info.lp_read_cmd_mode_freq_khz;
370 else
371 dsi_clock_rate_khz =
372 dsi->info.lp_cmd_mode_freq_khz;
373
374 return dsi_clock_rate_khz;
375}
376
377static u32 tegra_dsi_get_shift_clk_div(struct tegra_dc_dsi_data *dsi)
378{
379 u32 shift_clk_div;
380 u32 max_shift_clk_div;
381 u32 burst_width;
382 u32 burst_width_max;
383
384 /* Get the real value of default shift_clk_div. default_shift_clk_div
385 * holds the real value of shift_clk_div.
386 */
387 shift_clk_div = dsi->default_shift_clk_div;
388
389 /* Calculate shift_clk_div which can matche the video_burst_mode. */
390 if (dsi->info.video_burst_mode >=
391 TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED) {
392 /* The max_shift_clk_div is multiplied by 10 to save the
393 * fraction
394 */
395 if (dsi->info.max_panel_freq_khz >= dsi->default_hs_clk_khz)
396 max_shift_clk_div = dsi->info.max_panel_freq_khz
397 * shift_clk_div * 10 / dsi->default_hs_clk_khz;
398 else
399 max_shift_clk_div = shift_clk_div * 10;
400
401 burst_width = dsi->info.video_burst_mode
402 - TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED;
403 burst_width_max = TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED
404 - TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED;
405
406 shift_clk_div = (max_shift_clk_div - shift_clk_div * 10) *
407 burst_width / (burst_width_max * 10) + shift_clk_div;
408 }
409
410 return shift_clk_div;
411}
412
413static void tegra_dsi_init_sw(struct tegra_dc *dc,
414 struct tegra_dc_dsi_data *dsi)
415{
416 u32 h_width_pixels;
417 u32 v_width_lines;
418 u32 pixel_clk_hz;
419 u32 byte_clk_hz;
420 u32 plld_clk_mhz;
421
422 switch (dsi->info.pixel_format) {
423 case TEGRA_DSI_PIXEL_FORMAT_16BIT_P:
424 /* 2 bytes per pixel */
425 dsi->pixel_scaler_mul = 2;
426 dsi->pixel_scaler_div = 1;
427 break;
428 case TEGRA_DSI_PIXEL_FORMAT_18BIT_P:
429 /* 2.25 bytes per pixel */
430 dsi->pixel_scaler_mul = 9;
431 dsi->pixel_scaler_div = 4;
432 break;
433 case TEGRA_DSI_PIXEL_FORMAT_18BIT_NP:
434 case TEGRA_DSI_PIXEL_FORMAT_24BIT_P:
435 /* 3 bytes per pixel */
436 dsi->pixel_scaler_mul = 3;
437 dsi->pixel_scaler_div = 1;
438 break;
439 default:
440 break;
441 }
442
443 dsi->controller_index = dc->ndev->id;
444 dsi->ulpm = false;
445 dsi->enabled = false;
446 dsi->clk_ref = false;
447
448 dsi->dsi_control_val =
449 DSI_CONTROL_VIRTUAL_CHANNEL(dsi->info.virtual_channel) |
450 DSI_CONTROL_NUM_DATA_LANES(dsi->info.n_data_lanes - 1) |
451 DSI_CONTROL_VID_SOURCE(dsi->controller_index) |
452 DSI_CONTROL_DATA_FORMAT(dsi->info.pixel_format);
453
454 /* Below we are going to calculate dsi and dc clock rate.
455 * Calcuate the horizontal and vertical width.
456 */
457 h_width_pixels = dc->mode.h_back_porch + dc->mode.h_front_porch +
458 dc->mode.h_sync_width + dc->mode.h_active;
459 v_width_lines = dc->mode.v_back_porch + dc->mode.v_front_porch +
460 dc->mode.v_sync_width + dc->mode.v_active;
461
462 /* Calculate minimum required pixel rate. */
463 pixel_clk_hz = h_width_pixels * v_width_lines * dsi->info.refresh_rate;
464 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
465 if (dsi->info.rated_refresh_rate >= dsi->info.refresh_rate)
466 dev_info(&dc->ndev->dev, "DSI: measured refresh rate "
467 "should be larger than rated refresh rate.\n");
468 dc->mode.rated_pclk = h_width_pixels * v_width_lines *
469 dsi->info.rated_refresh_rate;
470 }
471
472 /* Calculate minimum byte rate on DSI interface. */
473 byte_clk_hz = (pixel_clk_hz * dsi->pixel_scaler_mul) /
474 (dsi->pixel_scaler_div * dsi->info.n_data_lanes);
475
476 /* Round up to multiple of mega hz. */
477 plld_clk_mhz = DIV_ROUND_UP((byte_clk_hz * NUMOF_BIT_PER_BYTE),
478 1000000);
479
480 /* Calculate default real shift_clk_div. */
481 dsi->default_shift_clk_div = (NUMOF_BIT_PER_BYTE / 2) *
482 dsi->pixel_scaler_mul / (dsi->pixel_scaler_div *
483 dsi->info.n_data_lanes);
484 /* Calculate default DSI hs clock. DSI interface is double data rate.
485 * Data is transferred on both rising and falling edge of clk, div by 2
486 * to get the actual clock rate.
487 */
488 dsi->default_hs_clk_khz = plld_clk_mhz * 1000 / 2;
489 dsi->default_pixel_clk_khz = plld_clk_mhz * 1000 / 2
490 / dsi->default_shift_clk_div;
491
492 /* Get the actual shift_clk_div and clock rates. */
493 dsi->shift_clk_div = tegra_dsi_get_shift_clk_div(dsi);
494 dsi->target_lp_clk_khz =
495 tegra_dsi_get_lp_clk_rate(dsi, DSI_LP_OP_WRITE);
496 dsi->target_hs_clk_khz = tegra_dsi_get_hs_clk_rate(dsi);
497
498 dev_info(&dc->ndev->dev, "DSI: HS clock rate is %d\n",
499 dsi->target_hs_clk_khz);
500
501 dsi->controller_index = dc->ndev->id;
502
503#if DSI_USE_SYNC_POINTS
504 dsi->syncpt_id = NVSYNCPT_DSI;
505#endif
506
507 /*
508 * Force video clock to be continuous mode if
509 * enable_hs_clock_on_lp_cmd_mode is set
510 */
511 if (dsi->info.enable_hs_clock_on_lp_cmd_mode) {
512 if (dsi->info.video_clock_mode !=
513 TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS)
514 dev_warn(&dc->ndev->dev,
515 "Force clock continuous mode\n");
516
517 dsi->info.video_clock_mode = TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS;
518 }
519
520}
521
522#define SELECT_T_PHY(platform_t_phy_ns, default_phy, clk_ns, hw_inc) ( \
523(platform_t_phy_ns) ? ( \
524((DSI_CONVERT_T_PHY_NS_TO_T_PHY(platform_t_phy_ns, clk_ns, hw_inc)) < 0 ? 0 : \
525(DSI_CONVERT_T_PHY_NS_TO_T_PHY(platform_t_phy_ns, clk_ns, hw_inc)))) : \
526((default_phy) < 0 ? 0 : (default_phy)))
527
528static void tegra_dsi_get_clk_phy_timing(struct tegra_dc_dsi_data *dsi,
529 struct dsi_phy_timing_inclk *phy_timing_clk, u32 clk_ns)
530{
531 phy_timing_clk->t_tlpx = SELECT_T_PHY(
532 dsi->info.phy_timing.t_tlpx_ns,
533 T_TLPX_DEFAULT(clk_ns), clk_ns, T_TLPX_HW_INC);
534
535 phy_timing_clk->t_clktrail = SELECT_T_PHY(
536 dsi->info.phy_timing.t_clktrail_ns,
537 T_CLKTRAIL_DEFAULT(clk_ns), clk_ns, T_CLKTRAIL_HW_INC);
538
539 phy_timing_clk->t_clkpost = SELECT_T_PHY(
540 dsi->info.phy_timing.t_clkpost_ns,
541 T_CLKPOST_DEFAULT(clk_ns), clk_ns, T_CLKPOST_HW_INC);
542
543 phy_timing_clk->t_clkzero = SELECT_T_PHY(
544 dsi->info.phy_timing.t_clkzero_ns,
545 T_CLKZERO_DEFAULT(clk_ns), clk_ns, T_CLKZERO_HW_INC);
546
547 phy_timing_clk->t_clkprepare = SELECT_T_PHY(
548 dsi->info.phy_timing.t_clkprepare_ns,
549 T_CLKPREPARE_DEFAULT(clk_ns), clk_ns, T_CLKPREPARE_HW_INC);
550
551 phy_timing_clk->t_clkpre = SELECT_T_PHY(
552 dsi->info.phy_timing.t_clkpre_ns,
553 T_CLKPRE_DEFAULT, clk_ns, T_CLKPRE_HW_INC);
554}
555
556static void tegra_dsi_get_hs_phy_timing(struct tegra_dc_dsi_data *dsi,
557 struct dsi_phy_timing_inclk *phy_timing_clk, u32 clk_ns)
558{
559 phy_timing_clk->t_tlpx = SELECT_T_PHY(
560 dsi->info.phy_timing.t_tlpx_ns,
561 T_TLPX_DEFAULT(clk_ns), clk_ns, T_TLPX_HW_INC);
562
563 phy_timing_clk->t_hsdexit = SELECT_T_PHY(
564 dsi->info.phy_timing.t_hsdexit_ns,
565 T_HSEXIT_DEFAULT(clk_ns), clk_ns, T_HSEXIT_HW_INC);
566
567 phy_timing_clk->t_hstrail = SELECT_T_PHY(
568 dsi->info.phy_timing.t_hstrail_ns,
569 T_HSTRAIL_DEFAULT(clk_ns), clk_ns, T_HSTRAIL_HW_INC);
570
571 phy_timing_clk->t_datzero = SELECT_T_PHY(
572 dsi->info.phy_timing.t_datzero_ns,
573 T_DATZERO_DEFAULT(clk_ns), clk_ns, T_DATZERO_HW_INC);
574
575 phy_timing_clk->t_hsprepare = SELECT_T_PHY(
576 dsi->info.phy_timing.t_hsprepare_ns,
577 T_HSPREPARE_DEFAULT(clk_ns), clk_ns, T_HSPREPARE_HW_INC);
578}
579
580static void tegra_dsi_get_escape_phy_timing(struct tegra_dc_dsi_data *dsi,
581 struct dsi_phy_timing_inclk *phy_timing_clk, u32 clk_ns)
582{
583 phy_timing_clk->t_tlpx = SELECT_T_PHY(
584 dsi->info.phy_timing.t_tlpx_ns,
585 T_TLPX_DEFAULT(clk_ns), clk_ns, T_TLPX_HW_INC);
586}
587
588static void tegra_dsi_get_bta_phy_timing(struct tegra_dc_dsi_data *dsi,
589 struct dsi_phy_timing_inclk *phy_timing_clk, u32 clk_ns)
590{
591 phy_timing_clk->t_tlpx = SELECT_T_PHY(
592 dsi->info.phy_timing.t_tlpx_ns,
593 T_TLPX_DEFAULT(clk_ns), clk_ns, T_TLPX_HW_INC);
594
595 phy_timing_clk->t_taget = SELECT_T_PHY(
596 dsi->info.phy_timing.t_taget_ns,
597 T_TAGET_DEFAULT(clk_ns), clk_ns, T_TAGET_HW_INC);
598
599 phy_timing_clk->t_tasure = SELECT_T_PHY(
600 dsi->info.phy_timing.t_tasure_ns,
601 T_TASURE_DEFAULT(clk_ns), clk_ns, T_TASURE_HW_INC);
602
603 phy_timing_clk->t_tago = SELECT_T_PHY(
604 dsi->info.phy_timing.t_tago_ns,
605 T_TAGO_DEFAULT(clk_ns), clk_ns, T_TAGO_HW_INC);
606}
607
608static void tegra_dsi_get_ulps_phy_timing(struct tegra_dc_dsi_data *dsi,
609 struct dsi_phy_timing_inclk *phy_timing_clk, u32 clk_ns)
610{
611 phy_timing_clk->t_tlpx = SELECT_T_PHY(
612 dsi->info.phy_timing.t_tlpx_ns,
613 T_TLPX_DEFAULT(clk_ns), clk_ns, T_TLPX_HW_INC);
614
615 phy_timing_clk->t_wakeup = SELECT_T_PHY(
616 dsi->info.phy_timing.t_wakeup_ns,
617 T_WAKEUP_DEFAULT, clk_ns, T_WAKEUP_HW_INC);
618}
619
620#undef SELECT_T_PHY
621
622static void tegra_dsi_get_phy_timing(struct tegra_dc_dsi_data *dsi,
623 struct dsi_phy_timing_inclk *phy_timing_clk,
624 u32 clk_ns, u8 lphs)
625{
626 if (lphs == DSI_LPHS_IN_HS_MODE) {
627 tegra_dsi_get_clk_phy_timing(dsi, phy_timing_clk, clk_ns);
628 tegra_dsi_get_hs_phy_timing(dsi, phy_timing_clk, clk_ns);
629 } else {
630 /* default is LP mode */
631 tegra_dsi_get_escape_phy_timing(dsi, phy_timing_clk, clk_ns);
632 tegra_dsi_get_bta_phy_timing(dsi, phy_timing_clk, clk_ns);
633 tegra_dsi_get_ulps_phy_timing(dsi, phy_timing_clk, clk_ns);
634 if (dsi->info.enable_hs_clock_on_lp_cmd_mode)
635 tegra_dsi_get_clk_phy_timing
636 (dsi, phy_timing_clk, clk_ns);
637 }
638}
639
640static int tegra_dsi_mipi_phy_timing_range(struct tegra_dc_dsi_data *dsi,
641 struct dsi_phy_timing_inclk *phy_timing,
642 u32 clk_ns, u8 lphs)
643{
644#define CHECK_RANGE(val, min, max) ( \
645 ((min) == NOT_DEFINED ? 0 : (val) < (min)) || \
646 ((max) == NOT_DEFINED ? 0 : (val) > (max)) ? -EINVAL : 0)
647
648 int err = 0;
649
650 err = CHECK_RANGE(
651 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
652 phy_timing->t_tlpx, clk_ns, T_TLPX_HW_INC),
653 MIPI_T_TLPX_NS_MIN, MIPI_T_TLPX_NS_MAX);
654 if (err < 0) {
655 dev_warn(&dsi->dc->ndev->dev,
656 "dsi: Tlpx mipi range violated\n");
657 goto fail;
658 }
659
660 if (lphs == DSI_LPHS_IN_HS_MODE) {
661 err = CHECK_RANGE(
662 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
663 phy_timing->t_hsdexit, clk_ns, T_HSEXIT_HW_INC),
664 MIPI_T_HSEXIT_NS_MIN, MIPI_T_HSEXIT_NS_MAX);
665 if (err < 0) {
666 dev_warn(&dsi->dc->ndev->dev,
667 "dsi: HsExit mipi range violated\n");
668 goto fail;
669 }
670
671 err = CHECK_RANGE(
672 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
673 phy_timing->t_hstrail, clk_ns, T_HSTRAIL_HW_INC),
674 MIPI_T_HSTRAIL_NS_MIN(clk_ns), MIPI_T_HSTRAIL_NS_MAX);
675 if (err < 0) {
676 dev_warn(&dsi->dc->ndev->dev,
677 "dsi: HsTrail mipi range violated\n");
678 goto fail;
679 }
680
681 err = CHECK_RANGE(
682 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
683 phy_timing->t_datzero, clk_ns, T_DATZERO_HW_INC),
684 MIPI_T_HSZERO_NS_MIN, MIPI_T_HSZERO_NS_MAX);
685 if (err < 0) {
686 dev_warn(&dsi->dc->ndev->dev,
687 "dsi: HsZero mipi range violated\n");
688 goto fail;
689 }
690
691 err = CHECK_RANGE(
692 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
693 phy_timing->t_hsprepare, clk_ns, T_HSPREPARE_HW_INC),
694 MIPI_T_HSPREPARE_NS_MIN(clk_ns),
695 MIPI_T_HSPREPARE_NS_MAX(clk_ns));
696 if (err < 0) {
697 dev_warn(&dsi->dc->ndev->dev,
698 "dsi: HsPrepare mipi range violated\n");
699 goto fail;
700 }
701
702 err = CHECK_RANGE(
703 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
704 phy_timing->t_hsprepare, clk_ns, T_HSPREPARE_HW_INC) +
705 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
706 phy_timing->t_datzero, clk_ns, T_DATZERO_HW_INC),
707 MIPI_T_HSPREPARE_ADD_HSZERO_NS_MIN(clk_ns),
708 MIPI_T_HSPREPARE_ADD_HSZERO_NS_MAX);
709 if (err < 0) {
710 dev_warn(&dsi->dc->ndev->dev,
711 "dsi: HsPrepare + HsZero mipi range violated\n");
712 goto fail;
713 }
714 } else {
715 /* default is LP mode */
716 err = CHECK_RANGE(
717 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
718 phy_timing->t_wakeup, clk_ns, T_WAKEUP_HW_INC),
719 MIPI_T_WAKEUP_NS_MIN, MIPI_T_WAKEUP_NS_MAX);
720 if (err < 0) {
721 dev_warn(&dsi->dc->ndev->dev,
722 "dsi: WakeUp mipi range violated\n");
723 goto fail;
724 }
725
726 err = CHECK_RANGE(
727 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
728 phy_timing->t_tasure, clk_ns, T_TASURE_HW_INC),
729 MIPI_T_TASURE_NS_MIN(DSI_CONVERT_T_PHY_TO_T_PHY_NS(
730 phy_timing->t_tlpx, clk_ns, T_TLPX_HW_INC)),
731 MIPI_T_TASURE_NS_MAX(DSI_CONVERT_T_PHY_TO_T_PHY_NS(
732 phy_timing->t_tlpx, clk_ns, T_TLPX_HW_INC)));
733 if (err < 0) {
734 dev_warn(&dsi->dc->ndev->dev,
735 "dsi: TaSure mipi range violated\n");
736 goto fail;
737 }
738 }
739
740 if (lphs == DSI_LPHS_IN_HS_MODE ||
741 dsi->info.enable_hs_clock_on_lp_cmd_mode) {
742 err = CHECK_RANGE(
743 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
744 phy_timing->t_clktrail, clk_ns, T_CLKTRAIL_HW_INC),
745 MIPI_T_CLKTRAIL_NS_MIN, MIPI_T_CLKTRAIL_NS_MAX);
746 if (err < 0) {
747 dev_warn(&dsi->dc->ndev->dev,
748 "dsi: ClkTrail mipi range violated\n");
749 goto fail;
750 }
751
752 err = CHECK_RANGE(
753 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
754 phy_timing->t_clkpost, clk_ns, T_CLKPOST_HW_INC),
755 MIPI_T_CLKPOST_NS_MIN(clk_ns), MIPI_T_CLKPOST_NS_MAX);
756 if (err < 0) {
757 dev_warn(&dsi->dc->ndev->dev,
758 "dsi: ClkPost mipi range violated\n");
759 goto fail;
760 }
761
762 err = CHECK_RANGE(
763 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
764 phy_timing->t_clkzero, clk_ns, T_CLKZERO_HW_INC),
765 MIPI_T_CLKZERO_NS_MIN, MIPI_T_CLKZERO_NS_MAX);
766 if (err < 0) {
767 dev_warn(&dsi->dc->ndev->dev,
768 "dsi: ClkZero mipi range violated\n");
769 goto fail;
770 }
771
772 err = CHECK_RANGE(
773 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
774 phy_timing->t_clkprepare, clk_ns, T_CLKPREPARE_HW_INC),
775 MIPI_T_CLKPREPARE_NS_MIN, MIPI_T_CLKPREPARE_NS_MAX);
776 if (err < 0) {
777 dev_warn(&dsi->dc->ndev->dev,
778 "dsi: ClkPrepare mipi range violated\n");
779 goto fail;
780 }
781
782 err = CHECK_RANGE(
783 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
784 phy_timing->t_clkpre, clk_ns, T_CLKPRE_HW_INC),
785 MIPI_T_CLKPRE_NS_MIN, MIPI_T_CLKPRE_NS_MAX);
786 if (err < 0) {
787 dev_warn(&dsi->dc->ndev->dev,
788 "dsi: ClkPre mipi range violated\n");
789 goto fail;
790 }
791
792 err = CHECK_RANGE(
793 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
794 phy_timing->t_clkprepare, clk_ns, T_CLKPREPARE_HW_INC) +
795 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
796 phy_timing->t_clkzero, clk_ns, T_CLKZERO_HW_INC),
797 MIPI_T_CLKPREPARE_ADD_CLKZERO_NS_MIN,
798 MIPI_T_CLKPREPARE_ADD_CLKZERO_NS_MAX);
799 if (err < 0) {
800 dev_warn(&dsi->dc->ndev->dev,
801 "dsi: ClkPrepare + ClkZero mipi range violated\n");
802 goto fail;
803 }
804 }
805fail:
806#undef CHECK_RANGE
807 return err;
808}
809
810static int tegra_dsi_hs_phy_len(struct tegra_dc_dsi_data *dsi,
811 struct dsi_phy_timing_inclk *phy_timing,
812 u32 clk_ns, u8 lphs)
813{
814 u32 hs_t_phy_ns;
815 u32 clk_t_phy_ns;
816 u32 t_phy_ns;
817 u32 h_blank_ns;
818 struct tegra_dc_mode *modes;
819 u32 t_pix_ns;
820 int err = 0;
821
822 if (!(lphs == DSI_LPHS_IN_HS_MODE))
823 goto fail;
824
825 modes = dsi->dc->out->modes;
826 t_pix_ns = clk_ns * BITS_PER_BYTE *
827 dsi->pixel_scaler_mul / dsi->pixel_scaler_div;
828
829 hs_t_phy_ns =
830 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
831 phy_timing->t_tlpx, clk_ns, T_TLPX_HW_INC) +
832 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
833 phy_timing->t_hsprepare, clk_ns, T_HSPREPARE_HW_INC) +
834 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
835 phy_timing->t_datzero, clk_ns, T_DATZERO_HW_INC) +
836 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
837 phy_timing->t_hstrail, clk_ns, T_HSTRAIL_HW_INC) +
838 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
839 phy_timing->t_hsdexit, clk_ns, T_HSEXIT_HW_INC);
840
841 clk_t_phy_ns =
842 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
843 phy_timing->t_clkpost, clk_ns, T_CLKPOST_HW_INC) +
844 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
845 phy_timing->t_clktrail, clk_ns, T_CLKTRAIL_HW_INC) +
846 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
847 phy_timing->t_hsdexit, clk_ns, T_HSEXIT_HW_INC) +
848 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
849 phy_timing->t_tlpx, clk_ns, T_TLPX_HW_INC) +
850 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
851 phy_timing->t_clkprepare, clk_ns, T_CLKPREPARE_HW_INC) +
852 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
853 phy_timing->t_clkzero, clk_ns, T_CLKZERO_HW_INC) +
854 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
855 phy_timing->t_clkpre, clk_ns, T_CLKPRE_HW_INC);
856
857 h_blank_ns = t_pix_ns * (modes->h_sync_width + modes->h_back_porch +
858 modes->h_front_porch);
859
860 /* Extra tlpx and byte cycle required by dsi HW */
861 t_phy_ns = dsi->info.n_data_lanes * (hs_t_phy_ns + clk_t_phy_ns +
862 DSI_CONVERT_T_PHY_TO_T_PHY_NS(
863 phy_timing->t_tlpx, clk_ns, T_TLPX_HW_INC) +
864 clk_ns * BITS_PER_BYTE);
865
866 if (h_blank_ns < t_phy_ns) {
867 err = -EINVAL;
868 dev_err(&dsi->dc->ndev->dev,
869 "dsi: Hblank is smaller than HS trans phy timing\n");
870 goto fail;
871 }
872
873 return 0;
874fail:
875 return err;
876}
877
878static int tegra_dsi_constraint_phy_timing(struct tegra_dc_dsi_data *dsi,
879 struct dsi_phy_timing_inclk *phy_timing,
880 u32 clk_ns, u8 lphs)
881{
882 int err = 0;
883
884 err = tegra_dsi_mipi_phy_timing_range(dsi, phy_timing, clk_ns, lphs);
885 if (err < 0) {
886 dev_warn(&dsi->dc->ndev->dev, "dsi: mipi range violated\n");
887 goto fail;
888 }
889
890 err = tegra_dsi_hs_phy_len(dsi, phy_timing, clk_ns, lphs);
891 if (err < 0) {
892 dev_err(&dsi->dc->ndev->dev, "dsi: Hblank too short\n");
893 goto fail;
894 }
895
896 /* TODO: add more contraints */
897fail:
898 return err;
899}
900
901static void tegra_dsi_set_phy_timing(struct tegra_dc_dsi_data *dsi, u8 lphs)
902{
903 u32 val;
904 struct dsi_phy_timing_inclk phy_timing = dsi->phy_timing;
905
906 tegra_dsi_get_phy_timing
907 (dsi, &phy_timing, dsi->current_bit_clk_ns, lphs);
908
909 tegra_dsi_constraint_phy_timing(dsi, &phy_timing,
910 dsi->current_bit_clk_ns, lphs);
911
912 val = DSI_PHY_TIMING_0_THSDEXIT(phy_timing.t_hsdexit) |
913 DSI_PHY_TIMING_0_THSTRAIL(phy_timing.t_hstrail) |
914 DSI_PHY_TIMING_0_TDATZERO(phy_timing.t_datzero) |
915 DSI_PHY_TIMING_0_THSPREPR(phy_timing.t_hsprepare);
916 tegra_dsi_writel(dsi, val, DSI_PHY_TIMING_0);
917
918 val = DSI_PHY_TIMING_1_TCLKTRAIL(phy_timing.t_clktrail) |
919 DSI_PHY_TIMING_1_TCLKPOST(phy_timing.t_clkpost) |
920 DSI_PHY_TIMING_1_TCLKZERO(phy_timing.t_clkzero) |
921 DSI_PHY_TIMING_1_TTLPX(phy_timing.t_tlpx);
922 tegra_dsi_writel(dsi, val, DSI_PHY_TIMING_1);
923
924 val = DSI_PHY_TIMING_2_TCLKPREPARE(phy_timing.t_clkprepare) |
925 DSI_PHY_TIMING_2_TCLKPRE(phy_timing.t_clkpre) |
926 DSI_PHY_TIMING_2_TWAKEUP(phy_timing.t_wakeup);
927 tegra_dsi_writel(dsi, val, DSI_PHY_TIMING_2);
928
929 val = DSI_BTA_TIMING_TTAGET(phy_timing.t_taget) |
930 DSI_BTA_TIMING_TTASURE(phy_timing.t_tasure) |
931 DSI_BTA_TIMING_TTAGO(phy_timing.t_tago);
932 tegra_dsi_writel(dsi, val, DSI_BTA_TIMING);
933
934 dsi->phy_timing = phy_timing;
935}
936
937static u32 tegra_dsi_sol_delay_burst(struct tegra_dc *dc,
938 struct tegra_dc_dsi_data *dsi)
939{
940 u32 dsi_to_pixel_clk_ratio;
941 u32 temp;
942 u32 temp1;
943 u32 mipi_clk_adj_kHz;
944 u32 sol_delay;
945 struct tegra_dc_mode *dc_modes = &dc->mode;
946
947 /* Get Fdsi/Fpixel ration (note: Fdsi is in bit format) */
948 dsi_to_pixel_clk_ratio = (dsi->current_dsi_clk_khz * 2 +
949 dsi->default_pixel_clk_khz - 1) / dsi->default_pixel_clk_khz;
950
951 /* Convert Fdsi to byte format */
952 dsi_to_pixel_clk_ratio *= 1000/8;
953
954 /* Multiplying by 1000 so that we don't loose the fraction part */
955 temp = dc_modes->h_active * 1000;
956 temp1 = dc_modes->h_active + dc_modes->h_back_porch +
957 dc_modes->h_sync_width;
958
959 sol_delay = temp1 * dsi_to_pixel_clk_ratio -
960 temp * dsi->pixel_scaler_mul /
961 (dsi->pixel_scaler_div * dsi->info.n_data_lanes);
962
963 /* Do rounding on sol delay */
964 sol_delay = (sol_delay + 1000 - 1)/1000;
965
966 /* TODO:
967 * 1. find out the correct sol fifo depth to use
968 * 2. verify with hw about the clamping function
969 */
970 if (sol_delay > (480 * 4)) {
971 sol_delay = (480 * 4);
972 mipi_clk_adj_kHz = sol_delay +
973 (dc_modes->h_active * dsi->pixel_scaler_mul) /
974 (dsi->info.n_data_lanes * dsi->pixel_scaler_div);
975
976 mipi_clk_adj_kHz *= (dsi->default_pixel_clk_khz / temp1);
977
978 mipi_clk_adj_kHz *= 4;
979 }
980
981 dsi->target_hs_clk_khz = mipi_clk_adj_kHz;
982
983 return sol_delay;
984}
985
986static void tegra_dsi_set_sol_delay(struct tegra_dc *dc,
987 struct tegra_dc_dsi_data *dsi)
988{
989 u32 sol_delay;
990
991 if (dsi->info.video_burst_mode == TEGRA_DSI_VIDEO_NONE_BURST_MODE ||
992 dsi->info.video_burst_mode ==
993 TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END) {
994#define VIDEO_FIFO_LATENCY_PIXEL_CLK 8
995 sol_delay = VIDEO_FIFO_LATENCY_PIXEL_CLK *
996 dsi->pixel_scaler_mul / dsi->pixel_scaler_div;
997#undef VIDEO_FIFO_LATENCY_PIXEL_CLK
998 dsi->status.clk_burst = DSI_CLK_BURST_NONE_BURST;
999 } else {
1000 sol_delay = tegra_dsi_sol_delay_burst(dc, dsi);
1001 dsi->status.clk_burst = DSI_CLK_BURST_BURST_MODE;
1002 }
1003
1004 tegra_dsi_writel(dsi, DSI_SOL_DELAY_SOL_DELAY(sol_delay),
1005 DSI_SOL_DELAY);
1006}
1007
1008static void tegra_dsi_set_timeout(struct tegra_dc_dsi_data *dsi)
1009{
1010 u32 val;
1011 u32 bytes_per_frame;
1012 u32 timeout = 0;
1013
1014 /* TODO: verify the following equation */
1015 bytes_per_frame = dsi->current_dsi_clk_khz * 1000 * 2 /
1016 (dsi->info.refresh_rate * 8);
1017 timeout = bytes_per_frame / DSI_CYCLE_COUNTER_VALUE;
1018 timeout = (timeout + DSI_HTX_TO_MARGIN) & 0xffff;
1019
1020 val = DSI_TIMEOUT_0_LRXH_TO(DSI_LRXH_TO_VALUE) |
1021 DSI_TIMEOUT_0_HTX_TO(timeout);
1022 tegra_dsi_writel(dsi, val, DSI_TIMEOUT_0);
1023
1024 if (dsi->info.panel_reset_timeout_msec)
1025 timeout = (dsi->info.panel_reset_timeout_msec * 1000*1000)
1026 / dsi->current_bit_clk_ns;
1027 else
1028 timeout = DSI_PR_TO_VALUE;
1029
1030 val = DSI_TIMEOUT_1_PR_TO(timeout) |
1031 DSI_TIMEOUT_1_TA_TO(DSI_TA_TO_VALUE);
1032 tegra_dsi_writel(dsi, val, DSI_TIMEOUT_1);
1033
1034 val = DSI_TO_TALLY_P_RESET_STATUS(IN_RESET) |
1035 DSI_TO_TALLY_TA_TALLY(DSI_TA_TALLY_VALUE)|
1036 DSI_TO_TALLY_LRXH_TALLY(DSI_LRXH_TALLY_VALUE)|
1037 DSI_TO_TALLY_HTX_TALLY(DSI_HTX_TALLY_VALUE);
1038 tegra_dsi_writel(dsi, val, DSI_TO_TALLY);
1039}
1040
1041static void tegra_dsi_setup_video_mode_pkt_length(struct tegra_dc *dc,
1042 struct tegra_dc_dsi_data *dsi)
1043{
1044 u32 val;
1045 u32 hact_pkt_len;
1046 u32 hsa_pkt_len;
1047 u32 hbp_pkt_len;
1048 u32 hfp_pkt_len;
1049
1050 hact_pkt_len = dc->mode.h_active * dsi->pixel_scaler_mul /
1051 dsi->pixel_scaler_div;
1052 hsa_pkt_len = dc->mode.h_sync_width * dsi->pixel_scaler_mul /
1053 dsi->pixel_scaler_div;
1054 hbp_pkt_len = dc->mode.h_back_porch * dsi->pixel_scaler_mul /
1055 dsi->pixel_scaler_div;
1056 hfp_pkt_len = dc->mode.h_front_porch * dsi->pixel_scaler_mul /
1057 dsi->pixel_scaler_div;
1058
1059 if (dsi->info.video_burst_mode !=
1060 TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END)
1061 hbp_pkt_len += hsa_pkt_len;
1062
1063 hsa_pkt_len -= DSI_HSYNC_BLNK_PKT_OVERHEAD;
1064 hbp_pkt_len -= DSI_HBACK_PORCH_PKT_OVERHEAD;
1065 hfp_pkt_len -= DSI_HFRONT_PORCH_PKT_OVERHEAD;
1066
1067 val = DSI_PKT_LEN_0_1_LENGTH_0(0) |
1068 DSI_PKT_LEN_0_1_LENGTH_1(hsa_pkt_len);
1069 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_0_1);
1070
1071 val = DSI_PKT_LEN_2_3_LENGTH_2(hbp_pkt_len) |
1072 DSI_PKT_LEN_2_3_LENGTH_3(hact_pkt_len);
1073 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_2_3);
1074
1075 val = DSI_PKT_LEN_4_5_LENGTH_4(hfp_pkt_len) |
1076 DSI_PKT_LEN_4_5_LENGTH_5(0);
1077 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_4_5);
1078
1079 val = DSI_PKT_LEN_6_7_LENGTH_6(0) | DSI_PKT_LEN_6_7_LENGTH_7(0);
1080 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_6_7);
1081}
1082
1083static void tegra_dsi_setup_cmd_mode_pkt_length(struct tegra_dc *dc,
1084 struct tegra_dc_dsi_data *dsi)
1085{
1086 unsigned long val;
1087 unsigned long act_bytes;
1088
1089 act_bytes = dc->mode.h_active * dsi->pixel_scaler_mul /
1090 dsi->pixel_scaler_div + 1;
1091
1092 val = DSI_PKT_LEN_0_1_LENGTH_0(0) | DSI_PKT_LEN_0_1_LENGTH_1(0);
1093 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_0_1);
1094
1095 val = DSI_PKT_LEN_2_3_LENGTH_2(0) | DSI_PKT_LEN_2_3_LENGTH_3(act_bytes);
1096 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_2_3);
1097
1098 val = DSI_PKT_LEN_4_5_LENGTH_4(0) | DSI_PKT_LEN_4_5_LENGTH_5(act_bytes);
1099 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_4_5);
1100
1101 val = DSI_PKT_LEN_6_7_LENGTH_6(0) | DSI_PKT_LEN_6_7_LENGTH_7(0x0f0f);
1102 tegra_dsi_writel(dsi, val, DSI_PKT_LEN_6_7);
1103}
1104
1105static void tegra_dsi_set_pkt_length(struct tegra_dc *dc,
1106 struct tegra_dc_dsi_data *dsi)
1107{
1108 if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST)
1109 return;
1110
1111 if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_VIDEO_MODE)
1112 tegra_dsi_setup_video_mode_pkt_length(dc, dsi);
1113 else
1114 tegra_dsi_setup_cmd_mode_pkt_length(dc, dsi);
1115}
1116
1117static void tegra_dsi_set_pkt_seq(struct tegra_dc *dc,
1118 struct tegra_dc_dsi_data *dsi)
1119{
1120 const u32 *pkt_seq;
1121 u32 rgb_info;
1122 u32 pkt_seq_3_5_rgb_lo;
1123 u32 pkt_seq_3_5_rgb_hi;
1124 u32 val;
1125 u32 reg;
1126 u8 i;
1127
1128 if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST)
1129 return;
1130
1131 switch (dsi->info.pixel_format) {
1132 case TEGRA_DSI_PIXEL_FORMAT_16BIT_P:
1133 rgb_info = CMD_RGB_16BPP;
1134 break;
1135 case TEGRA_DSI_PIXEL_FORMAT_18BIT_P:
1136 rgb_info = CMD_RGB_18BPP;
1137 break;
1138 case TEGRA_DSI_PIXEL_FORMAT_18BIT_NP:
1139 rgb_info = CMD_RGB_18BPPNP;
1140 break;
1141 case TEGRA_DSI_PIXEL_FORMAT_24BIT_P:
1142 default:
1143 rgb_info = CMD_RGB_24BPP;
1144 break;
1145 }
1146
1147 pkt_seq_3_5_rgb_lo = 0;
1148 pkt_seq_3_5_rgb_hi = 0;
1149 if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE)
1150 pkt_seq = dsi_pkt_seq_cmd_mode;
1151 else {
1152 switch (dsi->info.video_burst_mode) {
1153 case TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED:
1154 case TEGRA_DSI_VIDEO_BURST_MODE_LOW_SPEED:
1155 case TEGRA_DSI_VIDEO_BURST_MODE_MEDIUM_SPEED:
1156 case TEGRA_DSI_VIDEO_BURST_MODE_FAST_SPEED:
1157 case TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED:
1158 pkt_seq_3_5_rgb_lo =
1159 DSI_PKT_SEQ_3_LO_PKT_32_ID(rgb_info);
1160 if (!dsi->info.no_pkt_seq_eot)
1161 pkt_seq = dsi_pkt_seq_video_burst;
1162 else
1163 pkt_seq = dsi_pkt_seq_video_burst_no_eot;
1164 break;
1165 case TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END:
1166 pkt_seq_3_5_rgb_hi =
1167 DSI_PKT_SEQ_3_HI_PKT_34_ID(rgb_info);
1168 pkt_seq = dsi_pkt_seq_video_non_burst_syne;
1169 break;
1170 case TEGRA_DSI_VIDEO_NONE_BURST_MODE:
1171 default:
1172 pkt_seq_3_5_rgb_lo =
1173 DSI_PKT_SEQ_3_LO_PKT_32_ID(rgb_info);
1174 pkt_seq = dsi_pkt_seq_video_non_burst;
1175 break;
1176 }
1177 }
1178
1179 for (i = 0; i < NUMOF_PKT_SEQ; i++) {
1180 val = pkt_seq[i];
1181 reg = dsi_pkt_seq_reg[i];
1182 if ((reg == DSI_PKT_SEQ_3_LO) || (reg == DSI_PKT_SEQ_5_LO))
1183 val |= pkt_seq_3_5_rgb_lo;
1184 if ((reg == DSI_PKT_SEQ_3_HI) || (reg == DSI_PKT_SEQ_5_HI))
1185 val |= pkt_seq_3_5_rgb_hi;
1186 tegra_dsi_writel(dsi, val, reg);
1187 }
1188}
1189
1190static void tegra_dsi_reset_underflow_overflow
1191 (struct tegra_dc_dsi_data *dsi)
1192{
1193 u32 val;
1194
1195 val = tegra_dsi_readl(dsi, DSI_STATUS);
1196 val &= (DSI_STATUS_LB_OVERFLOW(0x1) | DSI_STATUS_LB_UNDERFLOW(0x1));
1197 if (val) {
1198 if (val & DSI_STATUS_LB_OVERFLOW(0x1))
1199 dev_warn(&dsi->dc->ndev->dev,
1200 "dsi: video fifo overflow. Resetting flag\n");
1201 if (val & DSI_STATUS_LB_UNDERFLOW(0x1))
1202 dev_warn(&dsi->dc->ndev->dev,
1203 "dsi: video fifo underflow. Resetting flag\n");
1204 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
1205 val |= DSI_HOST_CONTROL_FIFO_STAT_RESET(0x1);
1206 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
1207 udelay(5);
1208 }
1209}
1210
1211static void tegra_dsi_stop_dc_stream(struct tegra_dc *dc,
1212 struct tegra_dc_dsi_data *dsi)
1213{
1214 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
1215 tegra_dc_writel(dc, 0, DC_DISP_DISP_WIN_OPTIONS);
1216 tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
1217 tegra_dc_writel(dc, GENERAL_ACT_REQ , DC_CMD_STATE_CONTROL);
1218
1219 dsi->status.dc_stream = DSI_DC_STREAM_DISABLE;
1220}
1221
1222static void tegra_dsi_stop_dc_stream_at_frame_end(struct tegra_dc *dc,
1223 struct tegra_dc_dsi_data *dsi)
1224{
1225 int val;
1226 long timeout;
1227 u32 frame_period = DIV_ROUND_UP(S_TO_MS(1), dsi->info.refresh_rate);
1228
1229 /* stop dc */
1230 tegra_dsi_stop_dc_stream(dc, dsi);
1231
1232 /* enable frame end interrupt */
1233 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1234 val |= FRAME_END_INT;
1235 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
1236
1237 /* wait for frame_end completion.
1238 * timeout is 2 frame duration to accomodate for
1239 * internal delay.
1240 */
1241 timeout = wait_for_completion_interruptible_timeout(
1242 &dc->frame_end_complete,
1243 msecs_to_jiffies(2 * frame_period));
1244
1245 /* disable frame end interrupt */
1246 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1247 val &= ~FRAME_END_INT;
1248 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
1249
1250 if (timeout == 0)
1251 dev_warn(&dc->ndev->dev,
1252 "DC doesn't stop at end of frame.\n");
1253
1254 tegra_dsi_reset_underflow_overflow(dsi);
1255}
1256
1257static void tegra_dsi_start_dc_stream(struct tegra_dc *dc,
1258 struct tegra_dc_dsi_data *dsi)
1259{
1260 u32 val;
1261
1262 tegra_dc_writel(dc, DSI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
1263
1264 /* TODO: clean up */
1265 tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
1266 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
1267 DC_CMD_DISPLAY_POWER_CONTROL);
1268
1269 /* Configure one-shot mode or continuous mode */
1270 if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) {
1271 /* disable LSPI/LCD_DE output */
1272 val = PIN_OUTPUT_LSPI_OUTPUT_DIS;
1273 tegra_dc_writel(dc, val, DC_COM_PIN_OUTPUT_ENABLE3);
1274
1275 /* enable MSF & set MSF polarity */
1276 val = MSF_ENABLE | MSF_LSPI;
1277 if (!dsi->info.te_polarity_low)
1278 val |= MSF_POLARITY_HIGH;
1279 else
1280 val |= MSF_POLARITY_LOW;
1281 tegra_dc_writel(dc, val, DC_CMD_DISPLAY_COMMAND_OPTION0);
1282
1283 /* set non-continuous mode */
1284 tegra_dc_writel(dc, DISP_CTRL_MODE_NC_DISPLAY,
1285 DC_CMD_DISPLAY_COMMAND);
1286 tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
1287 tegra_dc_writel(dc, GENERAL_ACT_REQ | NC_HOST_TRIG,
1288 DC_CMD_STATE_CONTROL);
1289 } else {
1290 /* set continuous mode */
1291 tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY,
1292 DC_CMD_DISPLAY_COMMAND);
1293 tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
1294 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
1295 }
1296
1297 dsi->status.dc_stream = DSI_DC_STREAM_ENABLE;
1298}
1299
1300static void tegra_dsi_set_dc_clk(struct tegra_dc *dc,
1301 struct tegra_dc_dsi_data *dsi)
1302{
1303 u32 shift_clk_div_register;
1304 u32 val;
1305
1306 /* Get the corresponding register value of shift_clk_div. */
1307 shift_clk_div_register = dsi->shift_clk_div * 2 - 2;
1308
1309#ifndef CONFIG_TEGRA_SILICON_PLATFORM
1310 shift_clk_div_register = 1;
1311#endif
1312
1313 /* TODO: find out if PCD3 option is required */
1314 val = PIXEL_CLK_DIVIDER_PCD1 |
1315 SHIFT_CLK_DIVIDER(shift_clk_div_register);
1316 tegra_dc_writel(dc, val, DC_DISP_DISP_CLOCK_CONTROL);
1317}
1318
1319static void tegra_dsi_set_dsi_clk(struct tegra_dc *dc,
1320 struct tegra_dc_dsi_data *dsi, u32 clk)
1321{
1322 u32 rm;
1323
1324 /* Round up to MHz */
1325 rm = clk % 1000;
1326 if (rm != 0)
1327 clk -= rm;
1328
1329 /* Set up pixel clock */
1330 dc->shift_clk_div = dsi->shift_clk_div;
1331 dc->mode.pclk = (clk * 1000) / dsi->shift_clk_div;
1332 /* TODO: Define one shot work delay in board file. */
1333 /* Since for one-shot mode, refresh rate is usually set larger than
1334 * expected refresh rate, it needs at least 3 frame period. Less
1335 * delay one shot work is, more powering saving we have. */
1336 dc->one_shot_delay_ms = 4 *
1337 DIV_ROUND_UP(S_TO_MS(1), dsi->info.refresh_rate);
1338
1339 /* Enable DSI clock */
1340 tegra_dc_setup_clk(dc, dsi->dsi_clk);
1341 if (!dsi->clk_ref) {
1342 dsi->clk_ref = true;
1343 clk_enable(dsi->dsi_clk);
1344 tegra_periph_reset_deassert(dsi->dsi_clk);
1345 }
1346 dsi->current_dsi_clk_khz = clk_get_rate(dsi->dsi_clk) / 1000;
1347 dsi->current_bit_clk_ns = 1000*1000 / (dsi->current_dsi_clk_khz * 2);
1348}
1349
1350static void tegra_dsi_hs_clk_out_enable(struct tegra_dc_dsi_data *dsi)
1351{
1352 u32 val;
1353
1354 val = tegra_dsi_readl(dsi, DSI_CONTROL);
1355 val &= ~DSI_CONTROL_HS_CLK_CTRL(1);
1356
1357 if (dsi->info.video_clock_mode == TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS) {
1358 val |= DSI_CONTROL_HS_CLK_CTRL(CONTINUOUS);
1359 dsi->status.clk_mode = DSI_PHYCLK_CONTINUOUS;
1360 } else {
1361 val |= DSI_CONTROL_HS_CLK_CTRL(TX_ONLY);
1362 dsi->status.clk_mode = DSI_PHYCLK_TX_ONLY;
1363 }
1364 tegra_dsi_writel(dsi, val, DSI_CONTROL);
1365
1366 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
1367 val &= ~DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(1);
1368 val |= DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_HIGH);
1369 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
1370
1371 dsi->status.clk_out = DSI_PHYCLK_OUT_EN;
1372}
1373
1374static void tegra_dsi_hs_clk_out_enable_in_lp(struct tegra_dc_dsi_data *dsi)
1375{
1376 u32 val;
1377 tegra_dsi_hs_clk_out_enable(dsi);
1378
1379 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
1380 val &= ~DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(1);
1381 val |= DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_LOW);
1382 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
1383}
1384
1385static void tegra_dsi_hs_clk_out_disable(struct tegra_dc *dc,
1386 struct tegra_dc_dsi_data *dsi)
1387{
1388 u32 val;
1389
1390 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
1391 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
1392
1393 tegra_dsi_writel(dsi, TEGRA_DSI_DISABLE, DSI_POWER_CONTROL);
1394 /* stabilization delay */
1395 udelay(300);
1396
1397 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
1398 val &= ~DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(1);
1399 val |= DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_LOW);
1400 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
1401
1402 tegra_dsi_writel(dsi, TEGRA_DSI_ENABLE, DSI_POWER_CONTROL);
1403 /* stabilization delay */
1404 udelay(300);
1405
1406 dsi->status.clk_mode = DSI_PHYCLK_NOT_INIT;
1407 dsi->status.clk_out = DSI_PHYCLK_OUT_DIS;
1408}
1409
1410static void tegra_dsi_set_control_reg_lp(struct tegra_dc_dsi_data *dsi)
1411{
1412 u32 dsi_control;
1413 u32 host_dsi_control;
1414 u32 max_threshold;
1415
1416 dsi_control = dsi->dsi_control_val | DSI_CTRL_HOST_DRIVEN;
1417 host_dsi_control = HOST_DSI_CTRL_COMMON |
1418 HOST_DSI_CTRL_HOST_DRIVEN |
1419 DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_LOW);
1420 max_threshold = DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_HOST_FIFO_DEPTH);
1421
1422 tegra_dsi_writel(dsi, max_threshold, DSI_MAX_THRESHOLD);
1423 tegra_dsi_writel(dsi, dsi_control, DSI_CONTROL);
1424 tegra_dsi_writel(dsi, host_dsi_control, DSI_HOST_DSI_CONTROL);
1425
1426 dsi->status.driven = DSI_DRIVEN_MODE_HOST;
1427 dsi->status.clk_burst = DSI_CLK_BURST_NOT_INIT;
1428 dsi->status.vtype = DSI_VIDEO_TYPE_NOT_INIT;
1429}
1430
1431static void tegra_dsi_set_control_reg_hs(struct tegra_dc_dsi_data *dsi)
1432{
1433 u32 dsi_control;
1434 u32 host_dsi_control;
1435 u32 max_threshold;
1436 u32 dcs_cmd;
1437
1438 dsi_control = dsi->dsi_control_val;
1439 host_dsi_control = HOST_DSI_CTRL_COMMON;
1440 max_threshold = 0;
1441 dcs_cmd = 0;
1442
1443 if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST) {
1444 dsi_control |= DSI_CTRL_HOST_DRIVEN;
1445 host_dsi_control |= HOST_DSI_CTRL_HOST_DRIVEN;
1446 max_threshold =
1447 DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_HOST_FIFO_DEPTH);
1448 dsi->status.driven = DSI_DRIVEN_MODE_HOST;
1449 } else {
1450 dsi_control |= DSI_CTRL_DC_DRIVEN;
1451 host_dsi_control |= HOST_DSI_CTRL_DC_DRIVEN;
1452 max_threshold =
1453 DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_VIDEO_FIFO_DEPTH);
1454 dsi->status.driven = DSI_DRIVEN_MODE_DC;
1455 }
1456
1457 if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE) {
1458 dsi_control |= DSI_CTRL_CMD_MODE;
1459 dcs_cmd = DSI_DCS_CMDS_LT5_DCS_CMD(DSI_WRITE_MEMORY_START)|
1460 DSI_DCS_CMDS_LT3_DCS_CMD(DSI_WRITE_MEMORY_CONTINUE);
1461 dsi->status.vtype = DSI_VIDEO_TYPE_CMD_MODE;
1462
1463 } else {
1464 dsi_control |= DSI_CTRL_VIDEO_MODE;
1465 dsi->status.vtype = DSI_VIDEO_TYPE_VIDEO_MODE;
1466 }
1467
1468 tegra_dsi_writel(dsi, max_threshold, DSI_MAX_THRESHOLD);
1469 tegra_dsi_writel(dsi, dcs_cmd, DSI_DCS_CMDS);
1470 tegra_dsi_writel(dsi, dsi_control, DSI_CONTROL);
1471 tegra_dsi_writel(dsi, host_dsi_control, DSI_HOST_DSI_CONTROL);
1472}
1473
1474static void tegra_dsi_pad_calibration(struct tegra_dc_dsi_data *dsi)
1475{
1476 u32 val;
1477
1478 val = DSI_PAD_CONTROL_PAD_LPUPADJ(0x1) |
1479 DSI_PAD_CONTROL_PAD_LPDNADJ(0x1) |
1480 DSI_PAD_CONTROL_PAD_PREEMP_EN(0x1) |
1481 DSI_PAD_CONTROL_PAD_SLEWDNADJ(0x6) |
1482 DSI_PAD_CONTROL_PAD_SLEWUPADJ(0x6);
1483 if (!dsi->ulpm) {
1484 val |= DSI_PAD_CONTROL_PAD_PDIO(0) |
1485 DSI_PAD_CONTROL_PAD_PDIO_CLK(0) |
1486 DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_DISABLE);
1487 } else {
1488 val |= DSI_PAD_CONTROL_PAD_PDIO(0x3) |
1489 DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) |
1490 DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE);
1491 }
1492 tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL);
1493
1494 val = MIPI_CAL_TERMOSA(0x4);
1495 tegra_vi_csi_writel(val, CSI_CILA_MIPI_CAL_CONFIG_0);
1496
1497 val = MIPI_CAL_TERMOSB(0x4);
1498 tegra_vi_csi_writel(val, CSI_CILB_MIPI_CAL_CONFIG_0);
1499
1500 val = MIPI_CAL_HSPUOSD(0x3) | MIPI_CAL_HSPDOSD(0x4);
1501 tegra_vi_csi_writel(val, CSI_DSI_MIPI_CAL_CONFIG);
1502
1503 val = PAD_DRIV_DN_REF(0x5) | PAD_DRIV_UP_REF(0x7);
1504 tegra_vi_csi_writel(val, CSI_MIPIBIAS_PAD_CONFIG);
1505
1506 val = PAD_CIL_PDVREG(0x0);
1507 tegra_vi_csi_writel(val, CSI_CIL_PAD_CONFIG);
1508}
1509
1510static int tegra_dsi_init_hw(struct tegra_dc *dc,
1511 struct tegra_dc_dsi_data *dsi)
1512{
1513 u32 i;
1514
1515 tegra_dsi_writel(dsi,
1516 DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE),
1517 DSI_POWER_CONTROL);
1518 /* stabilization delay */
1519 udelay(300);
1520
1521 tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_lp_clk_khz);
1522 if (dsi->info.dsi_instance) {
1523 /* TODO:Set the misc register*/
1524 }
1525
1526 /* TODO: only need to change the timing for bta */
1527 tegra_dsi_set_phy_timing(dsi, DSI_LPHS_IN_LP_MODE);
1528
1529 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
1530 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
1531
1532 /* Initializing DSI registers */
1533 for (i = 0; i < ARRAY_SIZE(init_reg); i++)
1534 tegra_dsi_writel(dsi, 0, init_reg[i]);
1535
1536 tegra_dsi_writel(dsi, dsi->dsi_control_val, DSI_CONTROL);
1537
1538 tegra_dsi_pad_calibration(dsi);
1539
1540 tegra_dsi_writel(dsi,
1541 DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_ENABLE),
1542 DSI_POWER_CONTROL);
1543 /* stabilization delay */
1544 udelay(300);
1545
1546 dsi->status.init = DSI_MODULE_INIT;
1547 dsi->status.lphs = DSI_LPHS_NOT_INIT;
1548 dsi->status.vtype = DSI_VIDEO_TYPE_NOT_INIT;
1549 dsi->status.driven = DSI_DRIVEN_MODE_NOT_INIT;
1550 dsi->status.clk_out = DSI_PHYCLK_OUT_DIS;
1551 dsi->status.clk_mode = DSI_PHYCLK_NOT_INIT;
1552 dsi->status.clk_burst = DSI_CLK_BURST_NOT_INIT;
1553 dsi->status.dc_stream = DSI_DC_STREAM_DISABLE;
1554 dsi->status.lp_op = DSI_LP_OP_NOT_INIT;
1555
1556 return 0;
1557}
1558
1559static int tegra_dsi_set_to_lp_mode(struct tegra_dc *dc,
1560 struct tegra_dc_dsi_data *dsi, u8 lp_op)
1561{
1562 int err;
1563
1564 if (dsi->status.init != DSI_MODULE_INIT) {
1565 err = -EPERM;
1566 goto fail;
1567 }
1568
1569 if (dsi->status.lphs == DSI_LPHS_IN_LP_MODE &&
1570 dsi->status.lp_op == lp_op)
1571 goto success;
1572
1573 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
1574 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
1575
1576 /* disable/enable hs clk according to enable_hs_clock_on_lp_cmd_mode */
1577 if ((dsi->status.clk_out == DSI_PHYCLK_OUT_EN) &&
1578 (!dsi->info.enable_hs_clock_on_lp_cmd_mode))
1579 tegra_dsi_hs_clk_out_disable(dc, dsi);
1580
1581 dsi->target_lp_clk_khz = tegra_dsi_get_lp_clk_rate(dsi, lp_op);
1582 if (dsi->current_dsi_clk_khz != dsi->target_lp_clk_khz) {
1583 tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_lp_clk_khz);
1584 tegra_dsi_set_timeout(dsi);
1585 }
1586
1587 tegra_dsi_set_phy_timing(dsi, DSI_LPHS_IN_LP_MODE);
1588
1589 tegra_dsi_set_control_reg_lp(dsi);
1590
1591 if ((dsi->status.clk_out == DSI_PHYCLK_OUT_DIS) &&
1592 (dsi->info.enable_hs_clock_on_lp_cmd_mode))
1593 tegra_dsi_hs_clk_out_enable_in_lp(dsi);
1594
1595 dsi->status.lphs = DSI_LPHS_IN_LP_MODE;
1596 dsi->status.lp_op = lp_op;
1597success:
1598 err = 0;
1599fail:
1600 return err;
1601}
1602
1603static int tegra_dsi_set_to_hs_mode(struct tegra_dc *dc,
1604 struct tegra_dc_dsi_data *dsi)
1605{
1606 int err;
1607
1608 if (dsi->status.init != DSI_MODULE_INIT) {
1609 err = -EPERM;
1610 goto fail;
1611 }
1612
1613 if (dsi->status.lphs == DSI_LPHS_IN_HS_MODE)
1614 goto success;
1615
1616 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
1617 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
1618
1619 if ((dsi->status.clk_out == DSI_PHYCLK_OUT_EN) &&
1620 (!dsi->info.enable_hs_clock_on_lp_cmd_mode))
1621 tegra_dsi_hs_clk_out_disable(dc, dsi);
1622
1623 if (dsi->current_dsi_clk_khz != dsi->target_hs_clk_khz) {
1624 tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_hs_clk_khz);
1625 tegra_dsi_set_timeout(dsi);
1626 }
1627
1628 tegra_dsi_set_phy_timing(dsi, DSI_LPHS_IN_HS_MODE);
1629
1630 if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_DC) {
1631 tegra_dsi_set_pkt_seq(dc, dsi);
1632 tegra_dsi_set_pkt_length(dc, dsi);
1633 tegra_dsi_set_sol_delay(dc, dsi);
1634 tegra_dsi_set_dc_clk(dc, dsi);
1635 }
1636
1637 tegra_dsi_set_control_reg_hs(dsi);
1638
1639 if (dsi->status.clk_out == DSI_PHYCLK_OUT_DIS ||
1640 dsi->info.enable_hs_clock_on_lp_cmd_mode)
1641 tegra_dsi_hs_clk_out_enable(dsi);
1642
1643 dsi->status.lphs = DSI_LPHS_IN_HS_MODE;
1644success:
1645 dsi->status.lp_op = DSI_LP_OP_NOT_INIT;
1646 err = 0;
1647fail:
1648 return err;
1649}
1650
1651static bool tegra_dsi_write_busy(struct tegra_dc_dsi_data *dsi)
1652{
1653 u32 timeout = 0;
1654 bool retVal = true;
1655
1656 while (timeout <= DSI_MAX_COMMAND_DELAY_USEC) {
1657 if (!(DSI_TRIGGER_HOST_TRIGGER(0x1) &
1658 tegra_dsi_readl(dsi, DSI_TRIGGER))) {
1659 retVal = false;
1660 break;
1661 }
1662 udelay(DSI_COMMAND_DELAY_STEPS_USEC);
1663 timeout += DSI_COMMAND_DELAY_STEPS_USEC;
1664 }
1665
1666 return retVal;
1667}
1668
1669static bool tegra_dsi_read_busy(struct tegra_dc_dsi_data *dsi)
1670{
1671 u32 timeout = 0;
1672 bool retVal = true;
1673
1674 while (timeout < DSI_STATUS_POLLING_DURATION_USEC) {
1675 if (!(DSI_HOST_DSI_CONTROL_IMM_BTA(0x1) &
1676 tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL))) {
1677 retVal = false;
1678 break;
1679 }
1680 udelay(DSI_STATUS_POLLING_DELAY_USEC);
1681 timeout += DSI_STATUS_POLLING_DELAY_USEC;
1682 }
1683
1684 return retVal;
1685}
1686
1687static bool tegra_dsi_host_busy(struct tegra_dc_dsi_data *dsi)
1688{
1689 int err = 0;
1690
1691 if (tegra_dsi_write_busy(dsi)) {
1692 err = -EBUSY;
1693 dev_err(&dsi->dc->ndev->dev,
1694 "DSI trigger bit already set\n");
1695 goto fail;
1696 }
1697
1698 if (tegra_dsi_read_busy(dsi)) {
1699 err = -EBUSY;
1700 dev_err(&dsi->dc->ndev->dev,
1701 "DSI immediate bta bit already set\n");
1702 goto fail;
1703 }
1704fail:
1705 return (err < 0 ? true : false);
1706}
1707
1708static void tegra_dsi_soft_reset(struct tegra_dc_dsi_data *dsi)
1709{
1710 u32 trigger;
1711 u32 status;
1712
1713 tegra_dsi_writel(dsi,
1714 DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE),
1715 DSI_POWER_CONTROL);
1716 /* stabilization delay */
1717 udelay(300);
1718
1719 tegra_dsi_writel(dsi,
1720 DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_ENABLE),
1721 DSI_POWER_CONTROL);
1722 /* stabilization delay */
1723 udelay(300);
1724
1725 /* dsi HW does not clear host trigger bit automatically
1726 * on dsi interface disable if host fifo is empty
1727 */
1728 trigger = tegra_dsi_readl(dsi, DSI_TRIGGER);
1729 status = tegra_dsi_readl(dsi, DSI_STATUS);
1730 if (trigger & DSI_TRIGGER_HOST_TRIGGER(0x1) &&
1731 status & DSI_STATUS_IDLE(0x1)) {
1732 trigger &= ~(DSI_TRIGGER_HOST_TRIGGER(0x1));
1733 tegra_dsi_writel(dsi, trigger, DSI_TRIGGER);
1734 }
1735}
1736
1737static void tegra_dsi_reset_read_count(struct tegra_dc_dsi_data *dsi)
1738{
1739 u32 val;
1740
1741 val = tegra_dsi_readl(dsi, DSI_STATUS);
1742 val &= DSI_STATUS_RD_FIFO_COUNT(0x1f);
1743 if (val) {
1744 dev_warn(&dsi->dc->ndev->dev,
1745 "DSI read count not zero, resetting\n");
1746 tegra_dsi_soft_reset(dsi);
1747 }
1748}
1749
1750static struct dsi_status *tegra_dsi_save_state_switch_to_host_cmd_mode(
1751 struct tegra_dc_dsi_data *dsi,
1752 struct tegra_dc *dc,
1753 u8 lp_op)
1754{
1755 struct dsi_status *init_status;
1756 int err;
1757
1758 init_status = kzalloc(sizeof(*init_status), GFP_KERNEL);
1759 if (!init_status)
1760 return ERR_PTR(-ENOMEM);
1761
1762 *init_status = dsi->status;
1763
1764 if (dsi->status.lphs == DSI_LPHS_IN_HS_MODE) {
1765 if (dsi->status.driven == DSI_DRIVEN_MODE_DC) {
1766 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
1767 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
1768 dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_HOST;
1769 if (dsi->info.hs_cmd_mode_supported) {
1770 err = tegra_dsi_set_to_hs_mode(dc, dsi);
1771 if (err < 0) {
1772 dev_err(&dc->ndev->dev,
1773 "Switch to HS host mode failed\n");
1774 goto fail;
1775 }
1776 }
1777 }
1778 if (!dsi->info.hs_cmd_mode_supported) {
1779 err =
1780 tegra_dsi_set_to_lp_mode(dc, dsi, lp_op);
1781 if (err < 0) {
1782 dev_err(&dc->ndev->dev,
1783 "DSI failed to go to LP mode\n");
1784 goto fail;
1785 }
1786 }
1787 } else if (dsi->status.lphs == DSI_LPHS_IN_LP_MODE) {
1788 if (dsi->status.lp_op != lp_op) {
1789 err = tegra_dsi_set_to_lp_mode(dc, dsi, lp_op);
1790 if (err < 0) {
1791 dev_err(&dc->ndev->dev,
1792 "DSI failed to go to LP mode\n");
1793 goto fail;
1794 }
1795 }
1796 }
1797
1798 return init_status;
1799fail:
1800 kfree(init_status);
1801 return ERR_PTR(err);
1802}
1803
1804static struct dsi_status *tegra_dsi_prepare_host_transmission(
1805 struct tegra_dc *dc,
1806 struct tegra_dc_dsi_data *dsi,
1807 u8 lp_op)
1808{
1809 int err = 0;
1810 struct dsi_status *init_status;
1811
1812 if (dsi->status.init != DSI_MODULE_INIT ||
1813 dsi->ulpm) {
1814 err = -EPERM;
1815 goto fail;
1816 }
1817
1818 if (tegra_dsi_host_busy(dsi)) {
1819 tegra_dsi_soft_reset(dsi);
1820 if (tegra_dsi_host_busy(dsi)) {
1821 err = -EBUSY;
1822 dev_err(&dc->ndev->dev, "DSI host busy\n");
1823 goto fail;
1824 }
1825 }
1826
1827 if (lp_op == DSI_LP_OP_READ)
1828 tegra_dsi_reset_read_count(dsi);
1829
1830 if (dsi->status.lphs == DSI_LPHS_NOT_INIT) {
1831 err = tegra_dsi_set_to_lp_mode(dc, dsi, lp_op);
1832 if (err < 0) {
1833 dev_err(&dc->ndev->dev, "Failed to config LP write\n");
1834 goto fail;
1835 }
1836 }
1837
1838 init_status = tegra_dsi_save_state_switch_to_host_cmd_mode
1839 (dsi, dc, lp_op);
1840 if (IS_ERR_OR_NULL(init_status)) {
1841 err = PTR_ERR(init_status);
1842 dev_err(&dc->ndev->dev, "DSI state saving failed\n");
1843 goto fail;
1844 }
1845
1846 return init_status;
1847fail:
1848 return ERR_PTR(err);
1849}
1850
1851static int tegra_dsi_restore_state(struct tegra_dc *dc,
1852 struct tegra_dc_dsi_data *dsi,
1853 struct dsi_status *init_status)
1854{
1855 bool switch_back_to_dc_mode = false;
1856 bool switch_back_to_hs_mode = false;
1857 bool restart_dc_stream;
1858 int err = 0;
1859
1860 switch_back_to_dc_mode = (dsi->status.driven ==
1861 DSI_DRIVEN_MODE_HOST &&
1862 init_status->driven ==
1863 DSI_DRIVEN_MODE_DC);
1864 switch_back_to_hs_mode = (dsi->status.lphs ==
1865 DSI_LPHS_IN_LP_MODE &&
1866 init_status->lphs ==
1867 DSI_LPHS_IN_HS_MODE);
1868 restart_dc_stream = (dsi->status.dc_stream ==
1869 DSI_DC_STREAM_DISABLE &&
1870 init_status->dc_stream ==
1871 DSI_DC_STREAM_ENABLE);
1872
1873 if (dsi->status.lphs == DSI_LPHS_IN_LP_MODE &&
1874 init_status->lphs == DSI_LPHS_IN_LP_MODE) {
1875 if (dsi->status.lp_op != init_status->lp_op) {
1876 err =
1877 tegra_dsi_set_to_lp_mode(dc, dsi, init_status->lp_op);
1878 if (err < 0) {
1879 dev_err(&dc->ndev->dev,
1880 "Failed to config LP mode\n");
1881 goto fail;
1882 }
1883 }
1884 goto success;
1885 }
1886
1887 if (switch_back_to_dc_mode)
1888 dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_DC;
1889 if (switch_back_to_dc_mode || switch_back_to_hs_mode) {
1890 err = tegra_dsi_set_to_hs_mode(dc, dsi);
1891 if (err < 0) {
1892 dev_err(&dc->ndev->dev, "Failed to config HS mode\n");
1893 goto fail;
1894 }
1895 }
1896 if (restart_dc_stream)
1897 tegra_dsi_start_dc_stream(dc, dsi);
1898
1899success:
1900fail:
1901 kfree(init_status);
1902 return err;
1903}
1904
1905static int tegra_dsi_host_trigger(struct tegra_dc_dsi_data *dsi)
1906{
1907 int status = 0;
1908
1909 if (tegra_dsi_readl(dsi, DSI_TRIGGER)) {
1910 status = -EBUSY;
1911 goto fail;
1912 }
1913
1914 tegra_dsi_writel(dsi,
1915 DSI_TRIGGER_HOST_TRIGGER(TEGRA_DSI_ENABLE), DSI_TRIGGER);
1916
1917#if DSI_USE_SYNC_POINTS
1918 status = tegra_dsi_syncpt(dsi);
1919 if (status < 0) {
1920 dev_err(&dsi->dc->ndev->dev,
1921 "DSI syncpt for host trigger failed\n");
1922 goto fail;
1923 }
1924#else
1925 if (tegra_dsi_write_busy(dsi)) {
1926 status = -EBUSY;
1927 dev_err(&dsi->dc->ndev->dev,
1928 "Timeout waiting on write completion\n");
1929 }
1930#endif
1931
1932fail:
1933 return status;
1934}
1935
1936static int _tegra_dsi_write_data(struct tegra_dc_dsi_data *dsi,
1937 u8 *pdata, u8 data_id, u16 data_len)
1938{
1939 u8 virtual_channel;
1940 u8 *pval;
1941 u32 val;
1942 int err;
1943
1944 err = 0;
1945
1946 virtual_channel = dsi->info.virtual_channel <<
1947 DSI_VIR_CHANNEL_BIT_POSITION;
1948
1949 /* always use hw for ecc */
1950 val = (virtual_channel | data_id) << 0 |
1951 data_len << 8;
1952 tegra_dsi_writel(dsi, val, DSI_WR_DATA);
1953
1954 /* if pdata != NULL, pkt type is long pkt */
1955 if (pdata != NULL) {
1956 while (data_len) {
1957 if (data_len >= 4) {
1958 val = ((u32 *) pdata)[0];
1959 data_len -= 4;
1960 pdata += 4;
1961 } else {
1962 val = 0;
1963 pval = (u8 *) &val;
1964 do
1965 *pval++ = *pdata++;
1966 while (--data_len);
1967 }
1968 tegra_dsi_writel(dsi, val, DSI_WR_DATA);
1969 }
1970 }
1971
1972 err = tegra_dsi_host_trigger(dsi);
1973 if (err < 0)
1974 dev_err(&dsi->dc->ndev->dev, "DSI host trigger failed\n");
1975
1976 return err;
1977}
1978
1979int tegra_dsi_write_data(struct tegra_dc *dc,
1980 struct tegra_dc_dsi_data *dsi,
1981 u8 *pdata, u8 data_id, u16 data_len)
1982{
1983 int err = 0;
1984 struct dsi_status *init_status;
1985
1986 tegra_dc_io_start(dc);
1987
1988 init_status = tegra_dsi_prepare_host_transmission(
1989 dc, dsi, DSI_LP_OP_WRITE);
1990 if (IS_ERR_OR_NULL(init_status)) {
1991 err = PTR_ERR(init_status);
1992 dev_err(&dc->ndev->dev, "DSI host config failed\n");
1993 goto fail;
1994 }
1995
1996 err = _tegra_dsi_write_data(dsi, pdata, data_id, data_len);
1997fail:
1998 err = tegra_dsi_restore_state(dc, dsi, init_status);
1999 if (err < 0)
2000 dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
2001 tegra_dc_io_end(dc);
2002 return err;
2003}
2004EXPORT_SYMBOL(tegra_dsi_write_data);
2005
2006static int tegra_dsi_send_panel_cmd(struct tegra_dc *dc,
2007 struct tegra_dc_dsi_data *dsi,
2008 struct tegra_dsi_cmd *cmd,
2009 u32 n_cmd)
2010{
2011 u32 i;
2012 int err;
2013
2014 err = 0;
2015 for (i = 0; i < n_cmd; i++) {
2016 struct tegra_dsi_cmd *cur_cmd;
2017 cur_cmd = &cmd[i];
2018
2019 if (cur_cmd->cmd_type == TEGRA_DSI_DELAY_MS)
2020 mdelay(cur_cmd->sp_len_dly.delay_ms);
2021 else {
2022 err = tegra_dsi_write_data(dc, dsi,
2023 cur_cmd->pdata,
2024 cur_cmd->data_id,
2025 cur_cmd->sp_len_dly.data_len);
2026 if (err < 0)
2027 break;
2028 }
2029 }
2030 return err;
2031}
2032
2033static u8 get_8bit_ecc(u32 header)
2034{
2035 char ecc_parity[24] = {
2036 0x07, 0x0b, 0x0d, 0x0e, 0x13, 0x15, 0x16, 0x19,
2037 0x1a, 0x1c, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c,
2038 0x31, 0x32, 0x34, 0x38, 0x1f, 0x2f, 0x37, 0x3b
2039 };
2040 u8 ecc_byte;
2041 int i;
2042
2043 ecc_byte = 0;
2044 for (i = 0; i < 24; i++)
2045 ecc_byte ^= ((header >> i) & 1) ? ecc_parity[i] : 0x00;
2046
2047 return ecc_byte;
2048}
2049
2050/* This function is written to send DCS short write (1 parameter) only.
2051 * This means the cmd will contain only 1 byte of index and 1 byte of value.
2052 * The data type ID is fixed at 0x15 and the ECC is calculated based on the
2053 * data in pdata.
2054 * The command will be sent by hardware every frame.
2055 * pdata should contain both the index + value for each cmd.
2056 * data_len will be the total number of bytes in pdata.
2057 */
2058int tegra_dsi_send_panel_short_cmd(struct tegra_dc *dc, u8 *pdata, u8 data_len)
2059{
2060 u8 ecc8bits = 0, data_len_orig = 0;
2061 u32 val = 0, pkthdr = 0;
2062 int err = 0, count = 0;
2063 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
2064
2065 data_len_orig = data_len;
2066 if (pdata != NULL) {
2067 while (data_len) {
2068 if (data_len >= 2) {
2069 pkthdr = (CMD_SHORTW |
2070 (((u16 *)pdata)[0]) << 8 | 0x00 << 24);
2071 ecc8bits = get_8bit_ecc(pkthdr);
2072 val = (pkthdr | (ecc8bits << 24));
2073 data_len -= 2;
2074 pdata += 2;
2075 count++;
2076 }
2077 switch (count) {
2078 case 1:
2079 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_0);
2080 break;
2081 case 2:
2082 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_1);
2083 break;
2084 case 3:
2085 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_2);
2086 break;
2087 case 4:
2088 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_3);
2089 break;
2090 case 5:
2091 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_4);
2092 break;
2093 case 6:
2094 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_5);
2095 break;
2096 case 7:
2097 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_6);
2098 break;
2099 case 8:
2100 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_DATA_7);
2101 break;
2102 default:
2103 err = 1;
2104 break;
2105 }
2106 }
2107 }
2108
2109 val = DSI_INIT_SEQ_CONTROL_DSI_FRAME_INIT_BYTE_COUNT(data_len_orig * 2)
2110 | DSI_INIT_SEQ_CONTROL_DSI_SEND_INIT_SEQUENCE(1);
2111 tegra_dsi_writel(dsi, val, DSI_INIT_SEQ_CONTROL);
2112
2113 return err;
2114}
2115EXPORT_SYMBOL(tegra_dsi_send_panel_short_cmd);
2116
2117static int tegra_dsi_bta(struct tegra_dc_dsi_data *dsi)
2118{
2119 u32 val;
2120 u32 poll_time;
2121 int err;
2122
2123 poll_time = 0;
2124 err = 0;
2125
2126 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
2127 val |= DSI_HOST_DSI_CONTROL_IMM_BTA(TEGRA_DSI_ENABLE);
2128 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
2129
2130#if DSI_USE_SYNC_POINTS
2131 /* FIXME: Workaround for nvhost_syncpt_read */
2132 dsi->syncpt_val = nvhost_syncpt_update_min(
2133 &nvhost_get_host(dsi->dc->ndev)->syncpt,
2134 dsi->syncpt_id);
2135
2136 val = DSI_INCR_SYNCPT_COND(OP_DONE) |
2137 DSI_INCR_SYNCPT_INDX(dsi->syncpt_id);
2138 tegra_dsi_writel(dsi, val, DSI_INCR_SYNCPT);
2139
2140 /* TODO: Use interrupt rather than polling */
2141 err = nvhost_syncpt_wait(&nvhost_get_host(dsi->dc->ndev)->syncpt,
2142 dsi->syncpt_id, dsi->syncpt_val + 1);
2143 if (err < 0)
2144 dev_err(&dsi->dc->ndev->dev,
2145 "DSI sync point failure\n");
2146 else
2147 (dsi->syncpt_val)++;
2148#else
2149 if (tegra_dsi_read_busy(dsi)) {
2150 err = -EBUSY;
2151 dev_err(&dsi->dc->ndev->dev,
2152 "Timeout wating on read completion\n");
2153 }
2154#endif
2155
2156 return err;
2157}
2158
2159static int tegra_dsi_parse_read_response(struct tegra_dc *dc,
2160 u32 rd_fifo_cnt, u8 *read_fifo)
2161{
2162 int err;
2163 u32 payload_size;
2164
2165 payload_size = 0;
2166 err = 0;
2167
2168 switch (read_fifo[0]) {
2169 case DSI_ESCAPE_CMD:
2170 dev_info(&dc->ndev->dev, "escape cmd[0x%x]\n", read_fifo[0]);
2171 break;
2172 case DSI_ACK_NO_ERR:
2173 dev_info(&dc->ndev->dev,
2174 "Panel ack, no err[0x%x]\n", read_fifo[0]);
2175 return err;
2176 default:
2177 dev_info(&dc->ndev->dev, "Invalid read response\n");
2178 break;
2179 }
2180
2181 switch (read_fifo[4] & 0xff) {
2182 case GEN_LONG_RD_RES:
2183 /* Fall through */
2184 case DCS_LONG_RD_RES:
2185 payload_size = (read_fifo[5] |
2186 (read_fifo[6] << 8)) & 0xFFFF;
2187 dev_info(&dc->ndev->dev, "Long read response Packet\n"
2188 "payload_size[0x%x]\n", payload_size);
2189 break;
2190 case GEN_1_BYTE_SHORT_RD_RES:
2191 /* Fall through */
2192 case DCS_1_BYTE_SHORT_RD_RES:
2193 payload_size = 1;
2194 dev_info(&dc->ndev->dev, "Short read response Packet\n"
2195 "payload_size[0x%x]\n", payload_size);
2196 break;
2197 case GEN_2_BYTE_SHORT_RD_RES:
2198 /* Fall through */
2199 case DCS_2_BYTE_SHORT_RD_RES:
2200 payload_size = 2;
2201 dev_info(&dc->ndev->dev, "Short read response Packet\n"
2202 "payload_size[0x%x]\n", payload_size);
2203 break;
2204 case ACK_ERR_RES:
2205 payload_size = 2;
2206 dev_info(&dc->ndev->dev, "Acknowledge error report response\n"
2207 "Packet payload_size[0x%x]\n", payload_size);
2208 break;
2209 default:
2210 dev_info(&dc->ndev->dev, "Invalid response packet\n");
2211 err = -EINVAL;
2212 break;
2213 }
2214 return err;
2215}
2216
2217static int tegra_dsi_read_fifo(struct tegra_dc *dc,
2218 struct tegra_dc_dsi_data *dsi,
2219 u8 *read_fifo)
2220{
2221 u32 val;
2222 u32 i;
2223 u32 poll_time = 0;
2224 u32 rd_fifo_cnt;
2225 int err = 0;
2226 u8 *read_fifo_cp = read_fifo;
2227
2228 while (poll_time < DSI_DELAY_FOR_READ_FIFO) {
2229 mdelay(1);
2230 val = tegra_dsi_readl(dsi, DSI_STATUS);
2231 rd_fifo_cnt = val & DSI_STATUS_RD_FIFO_COUNT(0x1f);
2232 if (rd_fifo_cnt << 2 > DSI_READ_FIFO_DEPTH)
2233 dev_err(&dc->ndev->dev,
2234 "DSI RD_FIFO_CNT is greater than RD_FIFO_DEPTH\n");
2235 break;
2236 poll_time++;
2237 }
2238
2239 if (rd_fifo_cnt == 0) {
2240 dev_info(&dc->ndev->dev,
2241 "DSI RD_FIFO_CNT is zero\n");
2242 err = -EINVAL;
2243 goto fail;
2244 }
2245
2246 if (val & (DSI_STATUS_LB_UNDERFLOW(0x1) |
2247 DSI_STATUS_LB_OVERFLOW(0x1))) {
2248 dev_warn(&dc->ndev->dev,
2249 "DSI overflow/underflow error\n");
2250 }
2251
2252 /* Read data from FIFO */
2253 for (i = 0; i < rd_fifo_cnt; i++) {
2254 val = tegra_dsi_readl(dsi, DSI_RD_DATA);
2255 if (enable_read_debug)
2256 dev_info(&dc->ndev->dev,
2257 "Read data[%d]: 0x%x\n", i, val);
2258 memcpy(read_fifo, &val, 4);
2259 read_fifo += 4;
2260 }
2261
2262 /* Make sure all the data is read from the FIFO */
2263 val = tegra_dsi_readl(dsi, DSI_STATUS);
2264 val &= DSI_STATUS_RD_FIFO_COUNT(0x1f);
2265 if (val)
2266 dev_err(&dc->ndev->dev, "DSI FIFO_RD_CNT not zero"
2267 " even after reading FIFO_RD_CNT words from read fifo\n");
2268
2269 if (enable_read_debug) {
2270 err =
2271 tegra_dsi_parse_read_response(dc, rd_fifo_cnt, read_fifo_cp);
2272 if (err < 0)
2273 dev_warn(&dc->ndev->dev, "Unexpected read data\n");
2274 }
2275fail:
2276 return err;
2277}
2278
2279int tegra_dsi_read_data(struct tegra_dc *dc,
2280 struct tegra_dc_dsi_data *dsi,
2281 u32 max_ret_payload_size,
2282 u32 panel_reg_addr, u8 *read_data)
2283{
2284 int err = 0;
2285 struct dsi_status *init_status;
2286
2287 tegra_dc_io_start(dc);
2288
2289 init_status = tegra_dsi_prepare_host_transmission(
2290 dc, dsi, DSI_LP_OP_WRITE);
2291 if (IS_ERR_OR_NULL(init_status)) {
2292 err = PTR_ERR(init_status);
2293 dev_err(&dc->ndev->dev, "DSI host config failed\n");
2294 goto fail;
2295 }
2296
2297 /* Set max return payload size in words */
2298 err = _tegra_dsi_write_data(dsi, NULL,
2299 dsi_command_max_return_pkt_size,
2300 max_ret_payload_size);
2301 if (err < 0) {
2302 dev_err(&dc->ndev->dev,
2303 "DSI write failed\n");
2304 goto fail;
2305 }
2306
2307 /* DCS to read given panel register */
2308 err = _tegra_dsi_write_data(dsi, NULL,
2309 dsi_command_dcs_read_with_no_params,
2310 panel_reg_addr);
2311 if (err < 0) {
2312 dev_err(&dc->ndev->dev,
2313 "DSI write failed\n");
2314 goto fail;
2315 }
2316
2317 tegra_dsi_reset_read_count(dsi);
2318
2319 if (dsi->status.lp_op == DSI_LP_OP_WRITE) {
2320 err = tegra_dsi_set_to_lp_mode(dc, dsi, DSI_LP_OP_READ);
2321 if (err < 0) {
2322 dev_err(&dc->ndev->dev,
2323 "DSI failed to go to LP read mode\n");
2324 goto fail;
2325 }
2326 }
2327
2328 err = tegra_dsi_bta(dsi);
2329 if (err < 0) {
2330 dev_err(&dc->ndev->dev,
2331 "DSI IMM BTA timeout\n");
2332 goto fail;
2333 }
2334
2335 err = tegra_dsi_read_fifo(dc, dsi, read_data);
2336 if (err < 0) {
2337 dev_err(&dc->ndev->dev, "DSI read fifo failure\n");
2338 goto fail;
2339 }
2340fail:
2341 err = tegra_dsi_restore_state(dc, dsi, init_status);
2342 if (err < 0)
2343 dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
2344 tegra_dc_io_end(dc);
2345 return err;
2346}
2347EXPORT_SYMBOL(tegra_dsi_read_data);
2348
2349int tegra_dsi_panel_sanity_check(struct tegra_dc *dc,
2350 struct tegra_dc_dsi_data *dsi)
2351{
2352 int err = 0;
2353 u8 read_fifo[DSI_READ_FIFO_DEPTH];
2354 struct dsi_status *init_status;
2355 static struct tegra_dsi_cmd dsi_nop_cmd =
2356 DSI_CMD_SHORT(0x05, 0x0, 0x0);
2357
2358 tegra_dc_io_start(dc);
2359
2360 init_status = tegra_dsi_prepare_host_transmission(
2361 dc, dsi, DSI_LP_OP_WRITE);
2362 if (IS_ERR_OR_NULL(init_status)) {
2363 err = PTR_ERR(init_status);
2364 dev_err(&dc->ndev->dev, "DSI host config failed\n");
2365 goto fail;
2366 }
2367
2368 err = _tegra_dsi_write_data(dsi, NULL, dsi_nop_cmd.data_id, 0x0);
2369 if (err < 0) {
2370 dev_err(&dc->ndev->dev, "DSI nop write failed\n");
2371 goto fail;
2372 }
2373
2374 tegra_dsi_reset_read_count(dsi);
2375
2376 if (dsi->status.lp_op == DSI_LP_OP_WRITE) {
2377 err = tegra_dsi_set_to_lp_mode(dc, dsi, DSI_LP_OP_READ);
2378 if (err < 0) {
2379 dev_err(&dc->ndev->dev,
2380 "DSI failed to go to LP read mode\n");
2381 goto fail;
2382 }
2383 }
2384
2385 err = tegra_dsi_bta(dsi);
2386 if (err < 0) {
2387 dev_err(&dc->ndev->dev, "DSI BTA failed\n");
2388 goto fail;
2389 }
2390
2391 err = tegra_dsi_read_fifo(dc, dsi, read_fifo);
2392 if (err < 0) {
2393 dev_err(&dc->ndev->dev, "DSI read fifo failure\n");
2394 goto fail;
2395 }
2396
2397 if (read_fifo[0] != DSI_ACK_NO_ERR) {
2398 dev_warn(&dc->ndev->dev,
2399 "Ack no error trigger message not received\n");
2400 err = -EAGAIN;
2401 }
2402fail:
2403 err = tegra_dsi_restore_state(dc, dsi, init_status);
2404 if (err < 0)
2405 dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
2406 tegra_dc_io_end(dc);
2407 return err;
2408}
2409EXPORT_SYMBOL(tegra_dsi_panel_sanity_check);
2410
2411static int tegra_dsi_enter_ulpm(struct tegra_dc_dsi_data *dsi)
2412{
2413 u32 val;
2414 int ret;
2415
2416 ret = 0;
2417
2418 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
2419 val &= ~DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(3);
2420 val |= DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(ENTER_ULPM);
2421 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
2422
2423#if DSI_USE_SYNC_POINTS
2424 ret = tegra_dsi_syncpt(dsi);
2425 if (ret < 0) {
2426 dev_err(&dsi->dc->ndev->dev,
2427 "DSI syncpt for ulpm enter failed\n");
2428 goto fail;
2429 }
2430#else
2431 /* TODO: Find exact delay required */
2432 mdelay(10);
2433#endif
2434 dsi->ulpm = true;
2435fail:
2436 return ret;
2437}
2438
2439static int tegra_dsi_exit_ulpm(struct tegra_dc_dsi_data *dsi)
2440{
2441 u32 val;
2442 int ret;
2443
2444 ret = 0;
2445
2446 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
2447 val &= ~DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(3);
2448 val |= DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(EXIT_ULPM);
2449 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
2450
2451#if DSI_USE_SYNC_POINTS
2452 ret = tegra_dsi_syncpt(dsi);
2453 if (ret < 0) {
2454 dev_err(&dsi->dc->ndev->dev,
2455 "DSI syncpt for ulpm exit failed\n");
2456 goto fail;
2457 }
2458#else
2459 /* TODO: Find exact delay required */
2460 mdelay(10);
2461#endif
2462 dsi->ulpm = false;
2463
2464 val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
2465 val &= ~DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(0x3);
2466 val |= DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(NORMAL);
2467 tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
2468fail:
2469 return ret;
2470
2471}
2472
2473static void tegra_dc_dsi_enable(struct tegra_dc *dc)
2474{
2475 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
2476 int err;
2477 u32 val;
2478
2479 tegra_dc_io_start(dc);
2480 mutex_lock(&dsi->lock);
2481
2482 /* Stop DC stream before configuring DSI registers
2483 * to avoid visible glitches on panel during transition
2484 * from bootloader to kernel driver
2485 */
2486 tegra_dsi_stop_dc_stream(dc, dsi);
2487
2488 if (dsi->enabled) {
2489 if (dsi->ulpm) {
2490 if (tegra_dsi_exit_ulpm(dsi) < 0) {
2491 dev_err(&dc->ndev->dev,
2492 "DSI failed to exit ulpm\n");
2493 goto fail;
2494 }
2495 }
2496
2497 if (dsi->info.panel_reset) {
2498 err = tegra_dsi_send_panel_cmd(dc, dsi,
2499 dsi->info.dsi_init_cmd,
2500 dsi->info.n_init_cmd);
2501 if (err < 0) {
2502 dev_err(&dc->ndev->dev,
2503 "dsi: error sending dsi init cmd\n");
2504 goto fail;
2505 }
2506 } else if (dsi->info.dsi_late_resume_cmd) {
2507 err = tegra_dsi_send_panel_cmd(dc, dsi,
2508 dsi->info.dsi_late_resume_cmd,
2509 dsi->info.n_late_resume_cmd);
2510 if (err < 0) {
2511 dev_err(&dc->ndev->dev,
2512 "dsi: error sending late resume cmd\n");
2513 goto fail;
2514 }
2515 }
2516 } else {
2517 err = tegra_dsi_init_hw(dc, dsi);
2518 if (err < 0) {
2519 dev_err(&dc->ndev->dev,
2520 "dsi: not able to init dsi hardware\n");
2521 goto fail;
2522 }
2523
2524 if (dsi->ulpm) {
2525 if (tegra_dsi_enter_ulpm(dsi) < 0) {
2526 dev_err(&dc->ndev->dev,
2527 "DSI failed to enter ulpm\n");
2528 goto fail;
2529 }
2530
2531 val = tegra_dsi_readl(dsi, DSI_PAD_CONTROL);
2532
2533 /* erase bits we're about to set */
2534 val &= ~(DSI_PAD_CONTROL_PAD_PDIO(0x3) |
2535 DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) |
2536 DSI_PAD_CONTROL_PAD_PULLDN_ENAB(0x1));
2537
2538 val |= (DSI_PAD_CONTROL_PAD_PDIO(0) |
2539 DSI_PAD_CONTROL_PAD_PDIO_CLK(0) |
2540 DSI_PAD_CONTROL_PAD_PULLDN_ENAB
2541 (TEGRA_DSI_DISABLE));
2542
2543 tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL);
2544 if (tegra_dsi_exit_ulpm(dsi) < 0) {
2545 dev_err(&dc->ndev->dev,
2546 "DSI failed to exit ulpm\n");
2547 goto fail;
2548 }
2549 }
2550
2551 err = tegra_dsi_set_to_lp_mode(dc, dsi, DSI_LP_OP_WRITE);
2552 if (err < 0) {
2553 dev_err(&dc->ndev->dev,
2554 "dsi: not able to set to lp mode\n");
2555 goto fail;
2556 }
2557
2558 err = tegra_dsi_send_panel_cmd(dc, dsi, dsi->info.dsi_init_cmd,
2559 dsi->info.n_init_cmd);
2560 if (err < 0) {
2561 dev_err(&dc->ndev->dev,
2562 "dsi: error while sending dsi init cmd\n");
2563 goto fail;
2564 }
2565
2566 err = tegra_dsi_set_to_hs_mode(dc, dsi);
2567 if (err < 0) {
2568 dev_err(&dc->ndev->dev,
2569 "dsi: not able to set to hs mode\n");
2570 goto fail;
2571 }
2572
2573 dsi->enabled = true;
2574 }
2575
2576 if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
2577 tegra_dsi_start_dc_stream(dc, dsi);
2578fail:
2579 mutex_unlock(&dsi->lock);
2580 tegra_dc_io_end(dc);
2581}
2582
2583static void _tegra_dc_dsi_init(struct tegra_dc *dc)
2584{
2585 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
2586
2587 tegra_dsi_init_sw(dc, dsi);
2588 /* TODO: Configure the CSI pad configuration */
2589}
2590
2591static int tegra_dc_dsi_cp_p_cmd(struct tegra_dsi_cmd *src,
2592 struct tegra_dsi_cmd *dst, u16 n_cmd)
2593{
2594 u16 i;
2595 u16 len;
2596
2597 memcpy(dst, src, sizeof(*dst) * n_cmd);
2598
2599 for (i = 0; i < n_cmd; i++)
2600 if (src[i].pdata) {
2601 len = sizeof(*src[i].pdata) *
2602 src[i].sp_len_dly.data_len;
2603 dst[i].pdata = kzalloc(len, GFP_KERNEL);
2604 if (!dst[i].pdata)
2605 goto free_cmd_pdata;
2606 memcpy(dst[i].pdata, src[i].pdata, len);
2607 }
2608
2609 return 0;
2610
2611free_cmd_pdata:
2612 for (--i; i >= 0; i--)
2613 if (dst[i].pdata)
2614 kfree(dst[i].pdata);
2615 return -ENOMEM;
2616}
2617
2618static int tegra_dc_dsi_cp_info(struct tegra_dc_dsi_data *dsi,
2619 struct tegra_dsi_out *p_dsi)
2620{
2621 struct tegra_dsi_cmd *p_init_cmd;
2622 struct tegra_dsi_cmd *p_early_suspend_cmd;
2623 struct tegra_dsi_cmd *p_late_resume_cmd;
2624 struct tegra_dsi_cmd *p_suspend_cmd;
2625 int err;
2626
2627 if (p_dsi->n_data_lanes > MAX_DSI_DATA_LANES)
2628 return -EINVAL;
2629
2630 p_init_cmd = kzalloc(sizeof(*p_init_cmd) *
2631 p_dsi->n_init_cmd, GFP_KERNEL);
2632 if (!p_init_cmd)
2633 return -ENOMEM;
2634
2635 if (p_dsi->dsi_early_suspend_cmd) {
2636 p_early_suspend_cmd = kzalloc(sizeof(*p_early_suspend_cmd) *
2637 p_dsi->n_early_suspend_cmd,
2638 GFP_KERNEL);
2639 if (!p_early_suspend_cmd) {
2640 err = -ENOMEM;
2641 goto err_free_init_cmd;
2642 }
2643 }
2644
2645 if (p_dsi->dsi_late_resume_cmd) {
2646 p_late_resume_cmd = kzalloc(sizeof(*p_late_resume_cmd) *
2647 p_dsi->n_late_resume_cmd,
2648 GFP_KERNEL);
2649 if (!p_late_resume_cmd) {
2650 err = -ENOMEM;
2651 goto err_free_p_early_suspend_cmd;
2652 }
2653 }
2654
2655 p_suspend_cmd = kzalloc(sizeof(*p_suspend_cmd) * p_dsi->n_suspend_cmd,
2656 GFP_KERNEL);
2657 if (!p_suspend_cmd) {
2658 err = -ENOMEM;
2659 goto err_free_p_late_resume_cmd;
2660 }
2661
2662 memcpy(&dsi->info, p_dsi, sizeof(dsi->info));
2663
2664 /* Copy panel init cmd */
2665 err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_init_cmd,
2666 p_init_cmd, p_dsi->n_init_cmd);
2667 if (err < 0)
2668 goto err_free;
2669 dsi->info.dsi_init_cmd = p_init_cmd;
2670
2671 /* Copy panel early suspend cmd */
2672 if (p_dsi->dsi_early_suspend_cmd) {
2673 err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_early_suspend_cmd,
2674 p_early_suspend_cmd,
2675 p_dsi->n_early_suspend_cmd);
2676 if (err < 0)
2677 goto err_free;
2678 dsi->info.dsi_early_suspend_cmd = p_early_suspend_cmd;
2679 }
2680
2681 /* Copy panel late resume cmd */
2682 if (p_dsi->dsi_late_resume_cmd) {
2683 err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_late_resume_cmd,
2684 p_late_resume_cmd,
2685 p_dsi->n_late_resume_cmd);
2686 if (err < 0)
2687 goto err_free;
2688 dsi->info.dsi_late_resume_cmd = p_late_resume_cmd;
2689 }
2690
2691 /* Copy panel suspend cmd */
2692 err = tegra_dc_dsi_cp_p_cmd(p_dsi->dsi_suspend_cmd, p_suspend_cmd,
2693 p_dsi->n_suspend_cmd);
2694 if (err < 0)
2695 goto err_free;
2696 dsi->info.dsi_suspend_cmd = p_suspend_cmd;
2697
2698 if (!dsi->info.panel_reset_timeout_msec)
2699 dsi->info.panel_reset_timeout_msec =
2700 DEFAULT_PANEL_RESET_TIMEOUT;
2701
2702 if (!dsi->info.panel_buffer_size_byte)
2703 dsi->info.panel_buffer_size_byte = DEFAULT_PANEL_BUFFER_BYTE;
2704
2705 if (!dsi->info.max_panel_freq_khz) {
2706 dsi->info.max_panel_freq_khz = DEFAULT_MAX_DSI_PHY_CLK_KHZ;
2707
2708 if (dsi->info.video_burst_mode >
2709 TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END){
2710 dev_err(&dsi->dc->ndev->dev, "DSI: max_panel_freq_khz"
2711 "is not set for DSI burst mode.\n");
2712 dsi->info.video_burst_mode =
2713 TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED;
2714 }
2715 }
2716
2717 if (!dsi->info.lp_cmd_mode_freq_khz)
2718 dsi->info.lp_cmd_mode_freq_khz = DEFAULT_LP_CMD_MODE_CLK_KHZ;
2719
2720 if (!dsi->info.chip_id || !dsi->info.chip_rev)
2721 dev_warn(&dsi->dc->ndev->dev,
2722 "DSI: Failed to get chip info\n");
2723
2724 if (!dsi->info.lp_read_cmd_mode_freq_khz)
2725 dsi->info.lp_read_cmd_mode_freq_khz =
2726 dsi->info.lp_cmd_mode_freq_khz;
2727
2728 /* host mode is for testing only */
2729 dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_DC;
2730 return 0;
2731
2732err_free:
2733 kfree(p_suspend_cmd);
2734err_free_p_late_resume_cmd:
2735 kfree(p_late_resume_cmd);
2736err_free_p_early_suspend_cmd:
2737 kfree(p_early_suspend_cmd);
2738err_free_init_cmd:
2739 kfree(p_init_cmd);
2740 return err;
2741}
2742
2743static int tegra_dc_dsi_init(struct tegra_dc *dc)
2744{
2745 struct tegra_dc_dsi_data *dsi;
2746 struct resource *res;
2747 struct resource *base_res;
2748 void __iomem *base;
2749 struct clk *dc_clk = NULL;
2750 struct clk *dsi_clk = NULL;
2751 struct tegra_dsi_out *dsi_pdata;
2752 int err;
2753
2754 err = 0;
2755
2756 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
2757 if (!dsi)
2758 return -ENOMEM;
2759
2760 res = nvhost_get_resource_byname(dc->ndev, IORESOURCE_MEM,
2761 "dsi_regs");
2762 if (!res) {
2763 dev_err(&dc->ndev->dev, "dsi: no mem resource\n");
2764 err = -ENOENT;
2765 goto err_free_dsi;
2766 }
2767
2768 base_res = request_mem_region(res->start, resource_size(res),
2769 dc->ndev->name);
2770 if (!base_res) {
2771 dev_err(&dc->ndev->dev, "dsi: request_mem_region failed\n");
2772 err = -EBUSY;
2773 goto err_free_dsi;
2774 }
2775
2776 base = ioremap(res->start, resource_size(res));
2777 if (!base) {
2778 dev_err(&dc->ndev->dev, "dsi: registers can't be mapped\n");
2779 err = -EBUSY;
2780 goto err_release_regs;
2781 }
2782
2783 dsi_pdata = dc->pdata->default_out->dsi;
2784 if (!dsi_pdata) {
2785 dev_err(&dc->ndev->dev, "dsi: dsi data not available\n");
2786 goto err_release_regs;
2787 }
2788
2789 if (dsi_pdata->dsi_instance)
2790 dsi_clk = clk_get(&dc->ndev->dev, "dsib");
2791 else
2792 dsi_clk = clk_get(&dc->ndev->dev, "dsia");
2793
2794 if (IS_ERR_OR_NULL(dsi_clk)) {
2795 dev_err(&dc->ndev->dev, "dsi: can't get clock\n");
2796 err = -EBUSY;
2797 goto err_release_regs;
2798 }
2799
2800 dc_clk = clk_get_sys(dev_name(&dc->ndev->dev), NULL);
2801 if (IS_ERR_OR_NULL(dc_clk)) {
2802 dev_err(&dc->ndev->dev, "dsi: dc clock %s unavailable\n",
2803 dev_name(&dc->ndev->dev));
2804 err = -EBUSY;
2805 goto err_clk_put;
2806 }
2807
2808 mutex_init(&dsi->lock);
2809 dsi->dc = dc;
2810 dsi->base = base;
2811 dsi->base_res = base_res;
2812 dsi->dc_clk = dc_clk;
2813 dsi->dsi_clk = dsi_clk;
2814
2815 err = tegra_dc_dsi_cp_info(dsi, dsi_pdata);
2816 if (err < 0)
2817 goto err_dsi_data;
2818
2819 tegra_dc_set_outdata(dc, dsi);
2820 _tegra_dc_dsi_init(dc);
2821
2822 return 0;
2823
2824err_dsi_data:
2825err_clk_put:
2826 clk_put(dsi_clk);
2827err_release_regs:
2828 release_resource(base_res);
2829err_free_dsi:
2830 kfree(dsi);
2831
2832 return err;
2833}
2834
2835static void tegra_dc_dsi_destroy(struct tegra_dc *dc)
2836{
2837 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
2838 u16 i;
2839 u32 val;
2840
2841 mutex_lock(&dsi->lock);
2842
2843 /* free up the pdata */
2844 for (i = 0; i < dsi->info.n_init_cmd; i++) {
2845 if (dsi->info.dsi_init_cmd[i].pdata)
2846 kfree(dsi->info.dsi_init_cmd[i].pdata);
2847 }
2848 kfree(dsi->info.dsi_init_cmd);
2849
2850 /* Disable dc stream */
2851 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
2852 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
2853
2854 /* Disable dsi phy clock */
2855 if (dsi->status.clk_out == DSI_PHYCLK_OUT_EN)
2856 tegra_dsi_hs_clk_out_disable(dc, dsi);
2857
2858 val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE);
2859 tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL);
2860
2861 iounmap(dsi->base);
2862 release_resource(dsi->base_res);
2863
2864 clk_put(dsi->dc_clk);
2865 clk_put(dsi->dsi_clk);
2866
2867 mutex_unlock(&dsi->lock);
2868
2869 mutex_destroy(&dsi->lock);
2870 kfree(dsi);
2871}
2872
2873static int tegra_dsi_deep_sleep(struct tegra_dc *dc,
2874 struct tegra_dc_dsi_data *dsi)
2875{
2876 int err = 0;
2877 int val;
2878 struct clk *parent_clk = NULL;
2879 struct clk *base_clk = NULL;
2880
2881 if (!dsi->enabled) {
2882 err = -EPERM;
2883 goto fail;
2884 }
2885
2886 err = tegra_dsi_set_to_lp_mode(dc, dsi, DSI_LP_OP_WRITE);
2887 if (err < 0) {
2888 dev_err(&dc->ndev->dev,
2889 "DSI failed to go to LP mode\n");
2890 goto fail;
2891 }
2892
2893 /* Suspend panel */
2894 err = tegra_dsi_send_panel_cmd(dc, dsi,
2895 dsi->info.dsi_suspend_cmd,
2896 dsi->info.n_suspend_cmd);
2897 if (err < 0) {
2898 dev_err(&dc->ndev->dev,
2899 "dsi: Error sending suspend cmd\n");
2900 goto fail;
2901 }
2902
2903 if (!dsi->ulpm) {
2904 err = tegra_dsi_enter_ulpm(dsi);
2905 if (err < 0) {
2906 dev_err(&dc->ndev->dev,
2907 "DSI failed to enter ulpm\n");
2908 goto fail;
2909 }
2910 }
2911
2912 /*
2913 * Suspend pad
2914 * It is ok to overwrite previous value of DSI_PAD_CONTROL reg
2915 * because it will be restored properly in resume sequence
2916 */
2917 val = DSI_PAD_CONTROL_PAD_PDIO(0x3) |
2918 DSI_PAD_CONTROL_PAD_PDIO_CLK(0x1) |
2919 DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_ENABLE);
2920 tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL);
2921
2922 /* Suspend core-logic */
2923 val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE);
2924 tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL);
2925
2926 /* Disable dsi fast and slow clock */
2927 parent_clk = clk_get_parent(dsi->dsi_clk);
2928 base_clk = clk_get_parent(parent_clk);
2929 if (dsi->info.dsi_instance)
2930 tegra_clk_cfg_ex(base_clk,
2931 TEGRA_CLK_PLLD_CSI_OUT_ENB,
2932 0);
2933 else
2934 tegra_clk_cfg_ex(base_clk,
2935 TEGRA_CLK_PLLD_DSI_OUT_ENB,
2936 0);
2937
2938 /* Disable dsi source clock */
2939 clk_disable(dsi->dsi_clk);
2940
2941 dsi->clk_ref = false;
2942 dsi->enabled = false;
2943
2944 return 0;
2945fail:
2946 return err;
2947}
2948
2949static void tegra_dc_dsi_disable(struct tegra_dc *dc)
2950{
2951 int err;
2952 struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
2953
2954 tegra_dc_io_start(dc);
2955 mutex_lock(&dsi->lock);
2956
2957 if (dsi->status.dc_stream == DSI_DC_STREAM_ENABLE)
2958 tegra_dsi_stop_dc_stream_at_frame_end(dc, dsi);
2959
2960 if (dsi->info.power_saving_suspend) {
2961 if (tegra_dsi_deep_sleep(dc, dsi) < 0) {
2962 dev_err(&dc->ndev->dev,
2963 "DSI failed to enter deep sleep\n");
2964 goto fail;
2965 }
2966 } else {
2967 if (dsi->info.dsi_early_suspend_cmd) {
2968 err = tegra_dsi_send_panel_cmd(dc, dsi,
2969 dsi->info.dsi_early_suspend_cmd,
2970 dsi->info.n_early_suspend_cmd);
2971 if (err < 0) {
2972 dev_err(&dc->ndev->dev,
2973 "dsi: Error sending early suspend cmd\n");
2974 goto fail;
2975 }
2976 }
2977
2978 if (!dsi->ulpm) {
2979 if (tegra_dsi_enter_ulpm(dsi) < 0) {
2980 dev_err(&dc->ndev->dev,
2981 "DSI failed to enter ulpm\n");
2982 goto fail;
2983 }
2984 }
2985 }
2986
2987fail:
2988 mutex_unlock(&dsi->lock);
2989 tegra_dc_io_end(dc);
2990}
2991
2992#ifdef CONFIG_PM
2993static void tegra_dc_dsi_suspend(struct tegra_dc *dc)
2994{
2995 struct tegra_dc_dsi_data *dsi;
2996
2997 dsi = tegra_dc_get_outdata(dc);
2998
2999 if (!dsi->enabled)
3000 return;
3001
3002 tegra_dc_io_start(dc);
3003 mutex_lock(&dsi->lock);
3004
3005 if (!dsi->info.power_saving_suspend) {
3006 if (dsi->ulpm) {
3007 if (tegra_dsi_exit_ulpm(dsi) < 0) {
3008 dev_err(&dc->ndev->dev,
3009 "DSI failed to exit ulpm");
3010 goto fail;
3011 }
3012 }
3013
3014 if (tegra_dsi_deep_sleep(dc, dsi) < 0) {
3015 dev_err(&dc->ndev->dev,
3016 "DSI failed to enter deep sleep\n");
3017 goto fail;
3018 }
3019 }
3020fail:
3021 mutex_unlock(&dsi->lock);
3022 tegra_dc_io_end(dc);
3023}
3024
3025static void tegra_dc_dsi_resume(struct tegra_dc *dc)
3026{
3027 /* Not required since tegra_dc_dsi_enable
3028 * will reconfigure the controller from scratch
3029 */
3030}
3031#endif
3032
3033struct tegra_dc_out_ops tegra_dc_dsi_ops = {
3034 .init = tegra_dc_dsi_init,
3035 .destroy = tegra_dc_dsi_destroy,
3036 .enable = tegra_dc_dsi_enable,
3037 .disable = tegra_dc_dsi_disable,
3038#ifdef CONFIG_PM
3039 .suspend = tegra_dc_dsi_suspend,
3040 .resume = tegra_dc_dsi_resume,
3041#endif
3042};
diff --git a/drivers/video/tegra/dc/dsi.h b/drivers/video/tegra/dc/dsi.h
new file mode 100644
index 00000000000..18ea9c959e8
--- /dev/null
+++ b/drivers/video/tegra/dc/dsi.h
@@ -0,0 +1,375 @@
1/*
2 * drivers/video/tegra/dc/dsi.h
3 *
4 * Copyright (c) 2011, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
18#define __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
19
20/* source of video data */
21enum {
22 TEGRA_DSI_VIDEO_DRIVEN_BY_DC,
23 TEGRA_DSI_VIDEO_DRIVEN_BY_HOST,
24};
25
26/* Max number of data lanes supported */
27#define MAX_DSI_DATA_LANES 2
28/* Default Peripheral reset timeout */
29#define DSI_PR_TO_VALUE 0x2000
30
31/* DCS commands for command mode */
32#define DSI_ENTER_PARTIAL_MODE 0x12
33#define DSI_SET_PIXEL_FORMAT 0x3A
34#define DSI_AREA_COLOR_MODE 0x4C
35#define DSI_SET_PARTIAL_AREA 0x30
36#define DSI_SET_PAGE_ADDRESS 0x2B
37#define DSI_SET_ADDRESS_MODE 0x36
38#define DSI_SET_COLUMN_ADDRESS 0x2A
39#define DSI_WRITE_MEMORY_START 0x2C
40#define DSI_WRITE_MEMORY_CONTINUE 0x3C
41#define DSI_MAX_COMMAND_DELAY_USEC 250000
42#define DSI_COMMAND_DELAY_STEPS_USEC 10
43
44/* Trigger message */
45#define DSI_ESCAPE_CMD 0x87
46#define DSI_ACK_NO_ERR 0x84
47
48/* DSI return packet types */
49#define GEN_LONG_RD_RES 0x1A
50#define DCS_LONG_RD_RES 0x1C
51#define GEN_1_BYTE_SHORT_RD_RES 0x11
52#define DCS_1_BYTE_SHORT_RD_RES 0x21
53#define GEN_2_BYTE_SHORT_RD_RES 0x12
54#define DCS_2_BYTE_SHORT_RD_RES 0x22
55#define ACK_ERR_RES 0x02
56
57/* End of Transmit command for HS mode */
58#define DSI_CMD_HS_EOT_PACKAGE 0x000F0F08
59
60/* Delay required after issuing the trigger*/
61#define DSI_COMMAND_COMPLETION_DELAY_USEC 5
62
63#define DSI_DELAY_FOR_READ_FIFO 5
64
65/* Dsi virtual channel bit position, refer to the DSI specs */
66#define DSI_VIR_CHANNEL_BIT_POSITION 6
67
68/* DSI packet commands from Host to peripherals */
69enum {
70 dsi_command_v_sync_start = 0x01,
71 dsi_command_v_sync_end = 0x11,
72 dsi_command_h_sync_start = 0x21,
73 dsi_command_h_sync_end = 0x31,
74 dsi_command_end_of_transaction = 0x08,
75 dsi_command_blanking = 0x19,
76 dsi_command_null_packet = 0x09,
77 dsi_command_h_active_length_16bpp = 0x0E,
78 dsi_command_h_active_length_18bpp = 0x1E,
79 dsi_command_h_active_length_18bpp_np = 0x2E,
80 dsi_command_h_active_length_24bpp = 0x3E,
81 dsi_command_h_sync_active = dsi_command_blanking,
82 dsi_command_h_back_porch = dsi_command_blanking,
83 dsi_command_h_front_porch = dsi_command_blanking,
84 dsi_command_writ_no_param = 0x05,
85 dsi_command_long_write = 0x39,
86 dsi_command_max_return_pkt_size = 0x37,
87 dsi_command_generic_read_request_with_2_param = 0x24,
88 dsi_command_dcs_read_with_no_params = 0x06,
89};
90
91/* Maximum polling time for reading the dsi status register */
92#define DSI_STATUS_POLLING_DURATION_USEC 100000
93#define DSI_STATUS_POLLING_DELAY_USEC 100
94
95/*
96 * Horizontal Sync Blank Packet Over head
97 * DSI_overhead = size_of(HS packet header)
98 * + size_of(BLANK packet header) + size_of(checksum)
99 * DSI_overhead = 4 + 4 + 2 = 10
100 */
101#define DSI_HSYNC_BLNK_PKT_OVERHEAD 10
102
103/*
104 * Horizontal Front Porch Packet Overhead
105 * DSI_overhead = size_of(checksum)
106 * + size_of(BLANK packet header) + size_of(checksum)
107 * DSI_overhead = 2 + 4 + 2 = 8
108 */
109#define DSI_HFRONT_PORCH_PKT_OVERHEAD 8
110
111/*
112 * Horizontal Back Porch Packet
113 * DSI_overhead = size_of(HE packet header)
114 * + size_of(BLANK packet header) + size_of(checksum)
115 * + size_of(RGB packet header)
116 * DSI_overhead = 4 + 4 + 2 + 4 = 14
117 */
118#define DSI_HBACK_PORCH_PKT_OVERHEAD 14
119
120/* Additional Hs TX timeout margin */
121#define DSI_HTX_TO_MARGIN 720
122
123#define DSI_CYCLE_COUNTER_VALUE 512
124
125#define DSI_LRXH_TO_VALUE 0x2000
126
127/* Turn around timeout terminal count */
128#define DSI_TA_TO_VALUE 0x2000
129
130/* Turn around timeout tally */
131#define DSI_TA_TALLY_VALUE 0x0
132/* LP Rx timeout tally */
133#define DSI_LRXH_TALLY_VALUE 0x0
134/* HS Tx Timeout tally */
135#define DSI_HTX_TALLY_VALUE 0x0
136
137/* DSI Power control settle time 10 micro seconds */
138#define DSI_POWER_CONTROL_SETTLE_TIME_US 10
139
140#define DSI_HOST_FIFO_DEPTH 64
141#define DSI_VIDEO_FIFO_DEPTH 480
142#define DSI_READ_FIFO_DEPTH (32 << 2)
143
144#define NUMOF_BIT_PER_BYTE 8
145#define DEFAULT_LP_CMD_MODE_CLK_KHZ 10000
146#define DEFAULT_MAX_DSI_PHY_CLK_KHZ (500*1000)
147#define DEFAULT_PANEL_RESET_TIMEOUT 2
148#define DEFAULT_PANEL_BUFFER_BYTE 512
149
150/*
151 * TODO: are DSI_HOST_DSI_CONTROL_CRC_RESET(RESET_CRC) and
152 * DSI_HOST_DSI_CONTROL_HOST_TX_TRIG_SRC(IMMEDIATE) required for everyone?
153 */
154#define HOST_DSI_CTRL_COMMON \
155 (DSI_HOST_DSI_CONTROL_PHY_CLK_DIV(DSI_PHY_CLK_DIV1) | \
156 DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(NORMAL) | \
157 DSI_HOST_DSI_CONTROL_PERIPH_RESET(TEGRA_DSI_DISABLE) | \
158 DSI_HOST_DSI_CONTROL_RAW_DATA(TEGRA_DSI_DISABLE) | \
159 DSI_HOST_DSI_CONTROL_IMM_BTA(TEGRA_DSI_DISABLE) | \
160 DSI_HOST_DSI_CONTROL_PKT_BTA(TEGRA_DSI_DISABLE) | \
161 DSI_HOST_DSI_CONTROL_CS_ENABLE(TEGRA_DSI_ENABLE) | \
162 DSI_HOST_DSI_CONTROL_ECC_ENABLE(TEGRA_DSI_ENABLE) | \
163 DSI_HOST_DSI_CONTROL_PKT_WR_FIFO_SEL(HOST_ONLY))
164
165#define HOST_DSI_CTRL_HOST_DRIVEN \
166 (DSI_HOST_DSI_CONTROL_CRC_RESET(RESET_CRC) | \
167 DSI_HOST_DSI_CONTROL_HOST_TX_TRIG_SRC(IMMEDIATE))
168
169#define HOST_DSI_CTRL_DC_DRIVEN 0
170
171#define DSI_CTRL_HOST_DRIVEN (DSI_CONTROL_VID_ENABLE(TEGRA_DSI_DISABLE) | \
172 DSI_CONTROL_HOST_ENABLE(TEGRA_DSI_ENABLE))
173
174#define DSI_CTRL_DC_DRIVEN (DSI_CONTROL_VID_TX_TRIG_SRC(SOL) | \
175 DSI_CONTROL_VID_ENABLE(TEGRA_DSI_ENABLE) | \
176 DSI_CONTROL_HOST_ENABLE(TEGRA_DSI_DISABLE))
177
178#define DSI_CTRL_CMD_MODE (DSI_CONTROL_VID_DCS_ENABLE(TEGRA_DSI_ENABLE))
179
180#define DSI_CTRL_VIDEO_MODE (DSI_CONTROL_VID_DCS_ENABLE(TEGRA_DSI_DISABLE))
181
182
183enum {
184 CMD_VS = 0x01,
185 CMD_VE = 0x11,
186
187 CMD_HS = 0x21,
188 CMD_HE = 0x31,
189
190 CMD_EOT = 0x08,
191 CMD_NULL = 0x09,
192 CMD_SHORTW = 0x15,
193 CMD_BLNK = 0x19,
194 CMD_LONGW = 0x39,
195
196 CMD_RGB = 0x00,
197 CMD_RGB_16BPP = 0x0E,
198 CMD_RGB_18BPP = 0x1E,
199 CMD_RGB_18BPPNP = 0x2E,
200 CMD_RGB_24BPP = 0x3E,
201};
202
203#define PKT_ID0(id) (DSI_PKT_SEQ_0_LO_PKT_00_ID(id) | \
204 DSI_PKT_SEQ_1_LO_PKT_10_EN(TEGRA_DSI_ENABLE))
205#define PKT_LEN0(len) (DSI_PKT_SEQ_0_LO_PKT_00_SIZE(len))
206
207#define PKT_ID1(id) (DSI_PKT_SEQ_0_LO_PKT_01_ID(id) | \
208 DSI_PKT_SEQ_1_LO_PKT_11_EN(TEGRA_DSI_ENABLE))
209#define PKT_LEN1(len) (DSI_PKT_SEQ_0_LO_PKT_01_SIZE(len))
210
211#define PKT_ID2(id) (DSI_PKT_SEQ_0_LO_PKT_02_ID(id) | \
212 DSI_PKT_SEQ_1_LO_PKT_12_EN(TEGRA_DSI_ENABLE))
213#define PKT_LEN2(len) (DSI_PKT_SEQ_0_LO_PKT_02_SIZE(len))
214
215#define PKT_ID3(id) (DSI_PKT_SEQ_0_HI_PKT_03_ID(id) | \
216 DSI_PKT_SEQ_1_HI_PKT_13_EN(TEGRA_DSI_ENABLE))
217#define PKT_LEN3(len) (DSI_PKT_SEQ_0_HI_PKT_03_SIZE(len))
218
219#define PKT_ID4(id) (DSI_PKT_SEQ_0_HI_PKT_04_ID(id) | \
220 DSI_PKT_SEQ_1_HI_PKT_14_EN(TEGRA_DSI_ENABLE))
221#define PKT_LEN4(len) (DSI_PKT_SEQ_0_HI_PKT_04_SIZE(len))
222
223#define PKT_ID5(id) (DSI_PKT_SEQ_0_HI_PKT_05_ID(id) | \
224 DSI_PKT_SEQ_1_HI_PKT_15_EN(TEGRA_DSI_ENABLE))
225#define PKT_LEN5(len) (DSI_PKT_SEQ_0_HI_PKT_05_SIZE(len))
226
227#define PKT_LP (DSI_PKT_SEQ_0_LO_SEQ_0_FORCE_LP(TEGRA_DSI_ENABLE))
228
229#define NUMOF_PKT_SEQ 12
230
231/* Mipi v1.00.00 phy timing range */
232#define NOT_DEFINED -1
233#define MIPI_T_HSEXIT_NS_MIN 100
234#define MIPI_T_HSEXIT_NS_MAX NOT_DEFINED
235#define MIPI_T_HSTRAIL_NS_MIN(clk_ns) max((8 * (clk_ns)), (60 + 4 * (clk_ns)))
236#define MIPI_T_HSTRAIL_NS_MAX NOT_DEFINED
237#define MIPI_T_HSZERO_NS_MIN NOT_DEFINED
238#define MIPI_T_HSZERO_NS_MAX NOT_DEFINED
239#define MIPI_T_HSPREPARE_NS_MIN(clk_ns) (40 + 4 * (clk_ns))
240#define MIPI_T_HSPREPARE_NS_MAX(clk_ns) (85 + 6 * (clk_ns))
241#define MIPI_T_CLKTRAIL_NS_MIN 60
242#define MIPI_T_CLKTRAIL_NS_MAX NOT_DEFINED
243#define MIPI_T_CLKPOST_NS_MIN(clk_ns) (60 + 52 * (clk_ns))
244#define MIPI_T_CLKPOST_NS_MAX NOT_DEFINED
245#define MIPI_T_CLKZERO_NS_MIN NOT_DEFINED
246#define MIPI_T_CLKZERO_NS_MAX NOT_DEFINED
247#define MIPI_T_TLPX_NS_MIN 50
248#define MIPI_T_TLPX_NS_MAX NOT_DEFINED
249#define MIPI_T_CLKPREPARE_NS_MIN 38
250#define MIPI_T_CLKPREPARE_NS_MAX 95
251#define MIPI_T_CLKPRE_NS_MIN 8
252#define MIPI_T_CLKPRE_NS_MAX NOT_DEFINED
253#define MIPI_T_WAKEUP_NS_MIN 1
254#define MIPI_T_WAKEUP_NS_MAX NOT_DEFINED
255#define MIPI_T_TASURE_NS_MIN(tlpx_ns) (tlpx_ns)
256#define MIPI_T_TASURE_NS_MAX(tlpx_ns) (2 * (tlpx_ns))
257#define MIPI_T_HSPREPARE_ADD_HSZERO_NS_MIN(clk_ns) (145 + 10 * (clk_ns))
258#define MIPI_T_HSPREPARE_ADD_HSZERO_NS_MAX NOT_DEFINED
259#define MIPI_T_CLKPREPARE_ADD_CLKZERO_NS_MIN 300
260#define MIPI_T_CLKPREPARE_ADD_CLKZERO_NS_MAX NOT_DEFINED
261
262#define DSI_TBYTE(clk_ns) ((clk_ns) * (BITS_PER_BYTE))
263#define DSI_CONVERT_T_PHY_NS_TO_T_PHY(t_phy_ns, clk_ns, hw_inc) \
264 ((int)((DIV_ROUND_CLOSEST((t_phy_ns), \
265 (DSI_TBYTE(clk_ns)))) - (hw_inc)))
266
267#define DSI_CONVERT_T_PHY_TO_T_PHY_NS(t_phy, clk_ns, hw_inc) \
268 (((t_phy) + (hw_inc)) * (DSI_TBYTE(clk_ns)))
269
270/* Default phy timing in ns */
271#define T_HSEXIT_NS_DEFAULT 120
272#define T_HSTRAIL_NS_DEFAULT(clk_ns) \
273 max((8 * (clk_ns)), (60 + 4 * (clk_ns)))
274
275#define T_DATZERO_NS_DEFAULT(clk_ns) (145 + 5 * (clk_ns))
276#define T_HSPREPARE_NS_DEFAULT(clk_ns) (65 + 5 * (clk_ns))
277#define T_CLKTRAIL_NS_DEFAULT 80
278#define T_CLKPOST_NS_DEFAULT(clk_ns) (70 + 52 * (clk_ns))
279#define T_CLKZERO_NS_DEFAULT 260
280#define T_TLPX_NS_DEFAULT 60
281#define T_CLKPREPARE_NS_DEFAULT 65
282#define T_TAGO_NS_DEFAULT (4 * (T_TLPX_NS_DEFAULT))
283#define T_TASURE_NS_DEFAULT (2 * (T_TLPX_NS_DEFAULT))
284#define T_TAGET_NS_DEFAULT (5 * (T_TLPX_NS_DEFAULT))
285
286/* HW increment to phy register values */
287#define T_HSEXIT_HW_INC 1
288#define T_HSTRAIL_HW_INC 0
289#define T_DATZERO_HW_INC 3
290#define T_HSPREPARE_HW_INC 1
291#define T_CLKTRAIL_HW_INC 1
292#define T_CLKPOST_HW_INC 1
293#define T_CLKZERO_HW_INC 1
294#define T_TLPX_HW_INC 1
295#define T_CLKPREPARE_HW_INC 1
296#define T_TAGO_HW_INC 1
297#define T_TASURE_HW_INC 1
298#define T_TAGET_HW_INC 1
299#define T_CLKPRE_HW_INC 1
300#define T_WAKEUP_HW_INC 1
301
302/* Default phy timing reg values */
303#define T_HSEXIT_DEFAULT(clk_ns) \
304(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
305T_HSEXIT_NS_DEFAULT, clk_ns, T_HSEXIT_HW_INC))
306
307#define T_HSTRAIL_DEFAULT(clk_ns) \
308(3 + (DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
309T_HSTRAIL_NS_DEFAULT(clk_ns), clk_ns, T_HSTRAIL_HW_INC)))
310
311#define T_DATZERO_DEFAULT(clk_ns) \
312(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
313T_DATZERO_NS_DEFAULT(clk_ns), clk_ns, T_DATZERO_HW_INC))
314
315#define T_HSPREPARE_DEFAULT(clk_ns) \
316(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
317T_HSPREPARE_NS_DEFAULT(clk_ns), clk_ns, T_HSPREPARE_HW_INC))
318
319#define T_CLKTRAIL_DEFAULT(clk_ns) \
320(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
321T_CLKTRAIL_NS_DEFAULT, clk_ns, T_CLKTRAIL_HW_INC))
322
323#define T_CLKPOST_DEFAULT(clk_ns) \
324(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
325T_CLKPOST_NS_DEFAULT(clk_ns), clk_ns, T_CLKPOST_HW_INC))
326
327#define T_CLKZERO_DEFAULT(clk_ns) \
328(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
329T_CLKZERO_NS_DEFAULT, clk_ns, T_CLKZERO_HW_INC))
330
331#define T_TLPX_DEFAULT(clk_ns) \
332(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
333T_TLPX_NS_DEFAULT, clk_ns, T_TLPX_HW_INC))
334
335#define T_CLKPREPARE_DEFAULT(clk_ns) \
336(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
337T_CLKPREPARE_NS_DEFAULT, clk_ns, T_CLKPREPARE_HW_INC))
338
339#define T_CLKPRE_DEFAULT 0x1
340#define T_WAKEUP_DEFAULT 0x7f
341
342#define T_TAGO_DEFAULT(clk_ns) \
343(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
344T_TAGO_NS_DEFAULT, clk_ns, T_TAGO_HW_INC))
345
346#define T_TASURE_DEFAULT(clk_ns) \
347(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
348T_TASURE_NS_DEFAULT, clk_ns, T_TASURE_HW_INC))
349
350#define T_TAGET_DEFAULT(clk_ns) \
351(DSI_CONVERT_T_PHY_NS_TO_T_PHY( \
352T_TAGET_NS_DEFAULT, clk_ns, T_TAGET_HW_INC))
353
354/* Defines the DSI phy timing parameters */
355struct dsi_phy_timing_inclk {
356 unsigned t_hsdexit;
357 unsigned t_hstrail;
358 unsigned t_hsprepare;
359 unsigned t_datzero;
360
361 unsigned t_clktrail;
362 unsigned t_clkpost;
363 unsigned t_clkzero;
364 unsigned t_tlpx;
365
366 unsigned t_clkpre;
367 unsigned t_clkprepare;
368 unsigned t_wakeup;
369
370 unsigned t_taget;
371 unsigned t_tasure;
372 unsigned t_tago;
373};
374
375#endif
diff --git a/drivers/video/tegra/dc/dsi_regs.h b/drivers/video/tegra/dc/dsi_regs.h
new file mode 100644
index 00000000000..203ac32bd92
--- /dev/null
+++ b/drivers/video/tegra/dc/dsi_regs.h
@@ -0,0 +1,351 @@
1/*
2 * drivers/video/tegra/dc/dsi_regs.h
3 *
4 * Copyright (c) 2011, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
18#define __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
19
20enum {
21 TEGRA_DSI_DISABLE,
22 TEGRA_DSI_ENABLE,
23};
24
25/* These are word offsets from base (not byte offsets) */
26enum {
27 OP_DONE = 1,
28};
29#define DSI_INCR_SYNCPT 0x00
30#define DSI_INCR_SYNCPT_COND(x) (((x) & 0xff) << 8)
31#define DSI_INCR_SYNCPT_INDX(x) (((x) & 0xff) << 0)
32
33#define DSI_INCR_SYNCPT_CNTRL 0x01
34#define DSI_INCR_SYNCPT_ERROR 0x02
35#define DSI_CTXSW 0x08
36#define DSI_RD_DATA 0x09
37#define DSI_WR_DATA 0x0a
38
39#define DSI_POWER_CONTROL 0x0b
40#define DSI_POWER_CONTROL_LEG_DSI_ENABLE(x) (((x) & 0x1) << 0)
41
42#define DSI_INT_ENABLE 0x0c
43#define DSI_INT_STATUS 0x0d
44#define DSI_INT_MASK 0x0e
45
46#define DSI_HOST_DSI_CONTROL 0x0f
47enum {
48 RESET_CRC = 1,
49};
50#define DSI_HOST_CONTROL_FIFO_STAT_RESET(x) (((x) & 0x1) << 21)
51#define DSI_HOST_DSI_CONTROL_CRC_RESET(x) (((x) & 0x1) << 20)
52enum {
53 DSI_PHY_CLK_DIV1,
54 DSI_PHY_CLK_DIV2,
55};
56#define DSI_HOST_DSI_CONTROL_PHY_CLK_DIV(x) (((x) & 0x7) << 16)
57enum {
58 SOL,
59 FIFO_LEVEL,
60 IMMEDIATE,
61};
62#define DSI_HOST_DSI_CONTROL_HOST_TX_TRIG_SRC(x) (((x) & 0x3) << 12)
63enum {
64 NORMAL,
65 ENTER_ULPM,
66 EXIT_ULPM,
67};
68#define DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(x) (((x) & 0x3) << 8)
69#define DSI_HOST_DSI_CONTROL_PERIPH_RESET(x) (((x) & 0x1) << 7)
70#define DSI_HOST_DSI_CONTROL_RAW_DATA(x) (((x) & 0x1) << 6)
71enum {
72 TEGRA_DSI_LOW,
73 TEGRA_DSI_HIGH,
74};
75#define DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(x) (((x) & 0x1) << 5)
76enum {
77 HOST_ONLY,
78 VIDEO_HOST,
79};
80#define DSI_HOST_DSI_CONTROL_PKT_WR_FIFO_SEL(x) (((x) & 0x1) << 4)
81#define DSI_HOST_DSI_CONTROL_IMM_BTA(x) (((x) & 0x1) << 3)
82#define DSI_HOST_DSI_CONTROL_PKT_BTA(x) (((x) & 0x1) << 2)
83#define DSI_HOST_DSI_CONTROL_CS_ENABLE(x) (((x) & 0x1) << 1)
84#define DSI_HOST_DSI_CONTROL_ECC_ENABLE(x) (((x) & 0x1) << 0)
85
86#define DSI_CONTROL 0x10
87#define DSI_CONTROL_DBG_ENABLE(x) (((x) & 0x1) << 31)
88enum {
89 CONTINUOUS,
90 TX_ONLY,
91};
92#define DSI_CONTROL_HS_CLK_CTRL(x) (((x) & 0x1) << 20)
93#define DSI_CONTROL_VIRTUAL_CHANNEL(x) (((x) & 0x3) << 16)
94#define DSI_CONTROL_DATA_FORMAT(x) (((x) & 0x3) << 12)
95#define DSI_CONTROL_VID_TX_TRIG_SRC(x) (((x) & 0x3) << 8)
96#define DSI_CONTROL_NUM_DATA_LANES(x) (((x) & 0x3) << 4)
97#define DSI_CONTROL_VID_DCS_ENABLE(x) (((x) & 0x1) << 3)
98#define DSI_CONTROL_VID_SOURCE(x) (((x) & 0x1) << 2)
99#define DSI_CONTROL_VID_ENABLE(x) (((x) & 0x1) << 1)
100#define DSI_CONTROL_HOST_ENABLE(x) (((x) & 0x1) << 0)
101
102#define DSI_SOL_DELAY 0x11
103#define DSI_SOL_DELAY_SOL_DELAY(x) (((x) & 0xffff) << 0)
104
105#define DSI_MAX_THRESHOLD 0x12
106#define DSI_MAX_THRESHOLD_MAX_THRESHOLD(x) (((x) & 0xffff) << 0)
107
108#define DSI_TRIGGER 0x13
109#define DSI_TRIGGER_HOST_TRIGGER(x) (((x) & 0x1) << 1)
110#define DSI_TRIGGER_VID_TRIGGER(x) (((x) & 0x1) << 0)
111
112#define DSI_TX_CRC 0x14
113#define DSI_TX_CRC_TX_CRC(x) (((x) & 0xffffffff) << 0)
114
115#define DSI_STATUS 0x15
116#define DSI_STATUS_IDLE(x) (((x) & 0x1) << 10)
117#define DSI_STATUS_LB_UNDERFLOW(x) (((x) & 0x1) << 9)
118#define DSI_STATUS_LB_OVERFLOW(x) (((x) & 0x1) << 8)
119#define DSI_STATUS_RD_FIFO_COUNT(x) (((x) & 0x1f) << 0)
120
121#define DSI_INIT_SEQ_CONTROL 0x1a
122#define DSI_INIT_SEQ_CONTROL_DSI_FRAME_INIT_BYTE_COUNT(x) \
123 (((x) & 0x3f) << 8)
124#define DSI_INIT_SEQ_CONTROL_DSI_SEND_INIT_SEQUENCE(x) \
125 (((x) & 0xff) << 0)
126
127#define DSI_INIT_SEQ_DATA_0 0x1b
128#define DSI_INIT_SEQ_DATA_1 0x1c
129#define DSI_INIT_SEQ_DATA_2 0x1d
130#define DSI_INIT_SEQ_DATA_3 0x1e
131#define DSI_INIT_SEQ_DATA_4 0x1f
132#define DSI_INIT_SEQ_DATA_5 0x20
133#define DSI_INIT_SEQ_DATA_6 0x21
134#define DSI_INIT_SEQ_DATA_7 0x22
135
136#define DSI_PKT_SEQ_0_LO 0x23
137#define DSI_PKT_SEQ_0_LO_SEQ_0_FORCE_LP(x) (((x) & 0x1) << 30)
138#define DSI_PKT_SEQ_0_LO_PKT_02_EN(x) (((x) & 0x1) << 29)
139#define DSI_PKT_SEQ_0_LO_PKT_02_ID(x) (((x) & 0x3f) << 23)
140#define DSI_PKT_SEQ_0_LO_PKT_02_SIZE(x) (((x) & 0x7) << 20)
141#define DSI_PKT_SEQ_0_LO_PKT_01_EN(x) (((x) & 0x1) << 19)
142#define DSI_PKT_SEQ_0_LO_PKT_01_ID(x) (((x) & 0x3f) << 13)
143#define DSI_PKT_SEQ_0_LO_PKT_01_SIZE(x) (((x) & 0x7) << 10)
144#define DSI_PKT_SEQ_0_LO_PKT_00_EN(x) (((x) & 0x1) << 9)
145#define DSI_PKT_SEQ_0_LO_PKT_00_ID(x) (((x) & 0x3f) << 3)
146#define DSI_PKT_SEQ_0_LO_PKT_00_SIZE(x) (((x) & 0x7) << 0)
147
148#define DSI_PKT_SEQ_0_HI 0x24
149#define DSI_PKT_SEQ_0_HI_PKT_05_EN(x) (((x) & 0x1) << 29)
150#define DSI_PKT_SEQ_0_HI_PKT_05_ID(x) (((x) & 0x3f) << 23)
151#define DSI_PKT_SEQ_0_HI_PKT_05_SIZE(x) (((x) & 0x7) << 20)
152#define DSI_PKT_SEQ_0_HI_PKT_04_EN(x) (((x) & 0x1) << 19)
153#define DSI_PKT_SEQ_0_HI_PKT_04_ID(x) (((x) & 0x3f) << 13)
154#define DSI_PKT_SEQ_0_HI_PKT_04_SIZE(x) (((x) & 0x7) << 10)
155#define DSI_PKT_SEQ_0_HI_PKT_03_EN(x) (((x) & 0x1) << 9)
156#define DSI_PKT_SEQ_0_HI_PKT_03_ID(x) (((x) & 0x3f) << 3)
157#define DSI_PKT_SEQ_0_HI_PKT_03_SIZE(x) (((x) & 0x7) << 0)
158
159#define DSI_PKT_SEQ_1_LO 0x25
160#define DSI_PKT_SEQ_1_LO_SEQ_1_FORCE_LP(x) (((x) & 0x1) << 30)
161#define DSI_PKT_SEQ_1_LO_PKT_12_EN(x) (((x) & 0x1) << 29)
162#define DSI_PKT_SEQ_1_LO_PKT_12_ID(x) (((x) & 0x3f) << 23)
163#define DSI_PKT_SEQ_1_LO_PKT_12_SIZE(x) (((x) & 0x7) << 20)
164#define DSI_PKT_SEQ_1_LO_PKT_11_EN(x) (((x) & 0x1) << 19)
165#define DSI_PKT_SEQ_1_LO_PKT_11_ID(x) (((x) & 0x3f) << 13)
166#define DSI_PKT_SEQ_1_LO_PKT_11_SIZE(x) (((x) & 0x7) << 10)
167#define DSI_PKT_SEQ_1_LO_PKT_10_EN(x) (((x) & 0x1) << 9)
168#define DSI_PKT_SEQ_1_LO_PKT_10_ID(x) (((x) & 0x3f) << 3)
169#define DSI_PKT_SEQ_1_LO_PKT_10_SIZE(x) (((x) & 0x7) << 0)
170
171#define DSI_PKT_SEQ_1_HI 0x26
172#define DSI_PKT_SEQ_1_HI_PKT_15_EN(x) (((x) & 0x1) << 29)
173#define DSI_PKT_SEQ_1_HI_PKT_15_ID(x) (((x) & 0x3f) << 23)
174#define DSI_PKT_SEQ_1_HI_PKT_15_SIZE(x) (((x) & 0x7) << 20)
175#define DSI_PKT_SEQ_1_HI_PKT_14_EN(x) (((x) & 0x1) << 19)
176#define DSI_PKT_SEQ_1_HI_PKT_14_ID(x) (((x) & 0x3f) << 13)
177#define DSI_PKT_SEQ_1_HI_PKT_14_SIZE(x) (((x) & 0x7) << 10)
178#define DSI_PKT_SEQ_1_HI_PKT_13_EN(x) (((x) & 0x1) << 9)
179#define DSI_PKT_SEQ_1_HI_PKT_13_ID(x) (((x) & 0x3f) << 3)
180#define DSI_PKT_SEQ_1_HI_PKT_13_SIZE(x) (((x) & 0x7) << 0)
181
182#define DSI_PKT_SEQ_2_LO 0x27
183#define DSI_PKT_SEQ_2_LO_SEQ_2_FORCE_LP(x) (((x) & 0x1) << 30)
184#define DSI_PKT_SEQ_2_LO_PKT_22_EN(x) (((x) & 0x1) << 29)
185#define DSI_PKT_SEQ_2_LO_PKT_22_ID(x) (((x) & 0x3f) << 23)
186#define DSI_PKT_SEQ_2_LO_PKT_22_SIZE(x) (((x) & 0x7) << 20)
187#define DSI_PKT_SEQ_2_LO_PKT_21_EN(x) (((x) & 0x1) << 19)
188#define DSI_PKT_SEQ_2_LO_PKT_21_ID(x) (((x) & 0x3f) << 13)
189#define DSI_PKT_SEQ_2_LO_PKT_21_SIZE(x) (((x) & 0x7) << 10)
190#define DSI_PKT_SEQ_2_LO_PKT_20_EN(x) (((x) & 0x1) << 9)
191#define DSI_PKT_SEQ_2_LO_PKT_20_ID(x) (((x) & 0x3f) << 3)
192#define DSI_PKT_SEQ_2_LO_PKT_20_SIZE(x) (((x) & 0x7) << 0)
193
194#define DSI_PKT_SEQ_2_HI 0x28
195#define DSI_PKT_SEQ_2_HI_PKT_25_EN(x) (((x) & 0x1) << 29)
196#define DSI_PKT_SEQ_2_HI_PKT_25_ID(x) (((x) & 0x3f) << 23)
197#define DSI_PKT_SEQ_2_HI_PKT_25_SIZE(x) (((x) & 0x7) << 20)
198#define DSI_PKT_SEQ_2_HI_PKT_24_EN(x) (((x) & 0x1) << 19)
199#define DSI_PKT_SEQ_2_HI_PKT_24_ID(x) (((x) & 0x3f) << 13)
200#define DSI_PKT_SEQ_2_HI_PKT_24_SIZE(x) (((x) & 0x7) << 10)
201#define DSI_PKT_SEQ_2_HI_PKT_23_EN(x) (((x) & 0x1) << 9)
202#define DSI_PKT_SEQ_2_HI_PKT_23_ID(x) (((x) & 0x3f) << 3)
203#define DSI_PKT_SEQ_2_HI_PKT_23_SIZE(x) (((x) & 0x7) << 0)
204
205#define DSI_PKT_SEQ_3_LO 0x29
206#define DSI_PKT_SEQ_3_LO_SEQ_3_FORCE_LP(x) (((x) & 0x1) << 30)
207#define DSI_PKT_SEQ_3_LO_PKT_32_EN(x) (((x) & 0x1) << 29)
208#define DSI_PKT_SEQ_3_LO_PKT_32_ID(x) (((x) & 0x3f) << 23)
209#define DSI_PKT_SEQ_3_LO_PKT_32_SIZE(x) (((x) & 0x7) << 20)
210#define DSI_PKT_SEQ_3_LO_PKT_31_EN(x) (((x) & 0x1) << 19)
211#define DSI_PKT_SEQ_3_LO_PKT_31_ID(x) (((x) & 0x3f) << 13)
212#define DSI_PKT_SEQ_3_LO_PKT_31_SIZE(x) (((x) & 0x7) << 10)
213#define DSI_PKT_SEQ_3_LO_PKT_30_EN(x) (((x) & 0x1) << 9)
214#define DSI_PKT_SEQ_3_LO_PKT_30_ID(x) (((x) & 0x3f) << 3)
215#define DSI_PKT_SEQ_3_LO_PKT_30_SIZE(x) (((x) & 0x7) << 0)
216
217#define DSI_PKT_SEQ_3_HI 0x2a
218#define DSI_PKT_SEQ_3_HI_PKT_35_EN(x) (((x) & 0x1) << 29)
219#define DSI_PKT_SEQ_3_HI_PKT_35_ID(x) (((x) & 0x3f) << 23)
220#define DSI_PKT_SEQ_3_HI_PKT_35_SIZE(x) (((x) & 0x7) << 20)
221#define DSI_PKT_SEQ_3_HI_PKT_34_EN(x) (((x) & 0x1) << 19)
222#define DSI_PKT_SEQ_3_HI_PKT_34_ID(x) (((x) & 0x3f) << 13)
223#define DSI_PKT_SEQ_3_HI_PKT_34_SIZE(x) (((x) & 0x7) << 10)
224#define DSI_PKT_SEQ_3_HI_PKT_33_EN(x) (((x) & 0x1) << 9)
225#define DSI_PKT_SEQ_3_HI_PKT_33_ID(x) (((x) & 0x3f) << 3)
226#define DSI_PKT_SEQ_3_HI_PKT_33_SIZE(x) (((x) & 0x7) << 0)
227
228#define DSI_PKT_SEQ_4_LO 0x2b
229#define DSI_PKT_SEQ_4_LO_SEQ_4_FORCE_LP(x) (((x) & 0x1) << 30)
230#define DSI_PKT_SEQ_4_LO_PKT_42_EN(x) (((x) & 0x1) << 29)
231#define DSI_PKT_SEQ_4_LO_PKT_42_ID(x) (((x) & 0x3f) << 23)
232#define DSI_PKT_SEQ_4_LO_PKT_42_SIZE(x) (((x) & 0x7) << 20)
233#define DSI_PKT_SEQ_4_LO_PKT_41_EN(x) (((x) & 0x1) << 19)
234#define DSI_PKT_SEQ_4_LO_PKT_41_ID(x) (((x) & 0x3f) << 13)
235#define DSI_PKT_SEQ_4_LO_PKT_41_SIZE(x) (((x) & 0x7) << 10)
236#define DSI_PKT_SEQ_4_LO_PKT_40_EN(x) (((x) & 0x1) << 9)
237#define DSI_PKT_SEQ_4_LO_PKT_40_ID(x) (((x) & 0x3f) << 3)
238#define DSI_PKT_SEQ_4_LO_PKT_40_SIZE(x) (((x) & 0x7) << 0)
239
240#define DSI_PKT_SEQ_4_HI 0x2c
241#define DSI_PKT_SEQ_4_HI_PKT_45_EN(x) (((x) & 0x1) << 29)
242#define DSI_PKT_SEQ_4_HI_PKT_45_ID(x) (((x) & 0x3f) << 23)
243#define DSI_PKT_SEQ_4_HI_PKT_45_SIZE(x) (((x) & 0x7) << 20)
244#define DSI_PKT_SEQ_4_HI_PKT_44_EN(x) (((x) & 0x1) << 19)
245#define DSI_PKT_SEQ_4_HI_PKT_44_ID(x) (((x) & 0x3f) << 13)
246#define DSI_PKT_SEQ_4_HI_PKT_44_SIZE(x) (((x) & 0x7) << 10)
247#define DSI_PKT_SEQ_4_HI_PKT_43_EN(x) (((x) & 0x1) << 9)
248#define DSI_PKT_SEQ_4_HI_PKT_43_ID(x) (((x) & 0x3f) << 3)
249#define DSI_PKT_SEQ_4_HI_PKT_43_SIZE(x) (((x) & 0x7) << 0)
250
251#define DSI_PKT_SEQ_5_LO 0x2d
252#define DSI_PKT_SEQ_5_LO_SEQ_5_FORCE_LP(x) (((x) & 0x1) << 30)
253#define DSI_PKT_SEQ_5_LO_PKT_52_EN(x) (((x) & 0x1) << 29)
254#define DSI_PKT_SEQ_5_LO_PKT_52_ID(x) (((x) & 0x3f) << 23)
255#define DSI_PKT_SEQ_5_LO_PKT_52_SIZE(x) (((x) & 0x7) << 20)
256#define DSI_PKT_SEQ_5_LO_PKT_51_EN(x) (((x) & 0x1) << 19)
257#define DSI_PKT_SEQ_5_LO_PKT_51_ID(x) (((x) & 0x3f) << 13)
258#define DSI_PKT_SEQ_5_LO_PKT_51_SIZE(x) (((x) & 0x7) << 10)
259#define DSI_PKT_SEQ_5_LO_PKT_50_EN(x) (((x) & 0x1) << 9)
260#define DSI_PKT_SEQ_5_LO_PKT_50_ID(x) (((x) & 0x3f) << 3)
261#define DSI_PKT_SEQ_5_LO_PKT_50_SIZE(x) (((x) & 0x7) << 0)
262
263#define DSI_PKT_SEQ_5_HI 0x2e
264#define DSI_PKT_SEQ_5_HI_PKT_55_EN(x) (((x) & 0x1) << 29)
265#define DSI_PKT_SEQ_5_HI_PKT_55_ID(x) (((x) & 0x3f) << 23)
266#define DSI_PKT_SEQ_5_HI_PKT_55_SIZE(x) (((x) & 0x7) << 20)
267#define DSI_PKT_SEQ_5_HI_PKT_54_EN(x) (((x) & 0x1) << 19)
268#define DSI_PKT_SEQ_5_HI_PKT_54_ID(x) (((x) & 0x3f) << 13)
269#define DSI_PKT_SEQ_5_HI_PKT_54_SIZE(x) (((x) & 0x7) << 10)
270#define DSI_PKT_SEQ_5_HI_PKT_53_EN(x) (((x) & 0x1) << 9)
271#define DSI_PKT_SEQ_5_HI_PKT_53_ID(x) (((x) & 0x3f) << 3)
272#define DSI_PKT_SEQ_5_HI_PKT_53_SIZE(x) (((x) & 0x7) << 0)
273
274#define DSI_DCS_CMDS 0x33
275#define DSI_DCS_CMDS_LT5_DCS_CMD(x) (((x) & 0xff) << 8)
276#define DSI_DCS_CMDS_LT3_DCS_CMD(x) (((x) & 0xff) << 0)
277
278#define DSI_PKT_LEN_0_1 0x34
279#define DSI_PKT_LEN_0_1_LENGTH_1(x) (((x) & 0xffff) << 16)
280#define DSI_PKT_LEN_0_1_LENGTH_0(x) (((x) & 0xffff) << 0)
281
282#define DSI_PKT_LEN_2_3 0x35
283#define DSI_PKT_LEN_2_3_LENGTH_3(x) (((x) & 0xffff) << 16)
284#define DSI_PKT_LEN_2_3_LENGTH_2(x) (((x) & 0xffff) << 0)
285
286
287#define DSI_PKT_LEN_4_5 0x36
288#define DSI_PKT_LEN_4_5_LENGTH_5(x) (((x) & 0xffff) << 16)
289#define DSI_PKT_LEN_4_5_LENGTH_4(x) (((x) & 0xffff) << 0)
290
291#define DSI_PKT_LEN_6_7 0x37
292#define DSI_PKT_LEN_6_7_LENGTH_7(x) (((x) & 0xffff) << 16)
293#define DSI_PKT_LEN_6_7_LENGTH_6(x) (((x) & 0xffff) << 0)
294
295#define DSI_PHY_TIMING_0 0x3c
296#define DSI_PHY_TIMING_0_THSDEXIT(x) (((x) & 0xff) << 24)
297#define DSI_PHY_TIMING_0_THSTRAIL(x) (((x) & 0xff) << 16)
298#define DSI_PHY_TIMING_0_TDATZERO(x) (((x) & 0xff) << 8)
299#define DSI_PHY_TIMING_0_THSPREPR(x) (((x) & 0xff) << 0)
300
301#define DSI_PHY_TIMING_1 0x3d
302#define DSI_PHY_TIMING_1_TCLKTRAIL(x) (((x) & 0xff) << 24)
303#define DSI_PHY_TIMING_1_TCLKPOST(x) (((x) & 0xff) << 16)
304#define DSI_PHY_TIMING_1_TCLKZERO(x) (((x) & 0xff) << 8)
305#define DSI_PHY_TIMING_1_TTLPX(x) (((x) & 0xff) << 0)
306
307#define DSI_PHY_TIMING_2 0x3e
308#define DSI_PHY_TIMING_2_TCLKPREPARE(x) (((x) & 0xff) << 16)
309#define DSI_PHY_TIMING_2_TCLKPRE(x) (((x) & 0xff) << 8)
310#define DSI_PHY_TIMING_2_TWAKEUP(x) (((x) & 0xff) << 0)
311
312#define DSI_BTA_TIMING 0x3f
313#define DSI_BTA_TIMING_TTAGET(x) (((x) & 0xff) << 16)
314#define DSI_BTA_TIMING_TTASURE(x) (((x) & 0xff) << 8)
315#define DSI_BTA_TIMING_TTAGO(x) (((x) & 0xff) << 0)
316
317
318#define DSI_TIMEOUT_0 0x44
319#define DSI_TIMEOUT_0_LRXH_TO(x) (((x) & 0xffff) << 16)
320#define DSI_TIMEOUT_0_HTX_TO(x) (((x) & 0xffff) << 0)
321
322#define DSI_TIMEOUT_1 0x45
323#define DSI_TIMEOUT_1_PR_TO(x) (((x) & 0xffff) << 16)
324#define DSI_TIMEOUT_1_TA_TO(x) (((x) & 0xffff) << 0)
325
326#define DSI_TO_TALLY 0x46
327enum {
328 IN_RESET,
329 READY,
330};
331#define DSI_TO_TALLY_P_RESET_STATUS(x) (((x) & 0x1) << 24)
332#define DSI_TO_TALLY_TA_TALLY(x) (((x) & 0xff) << 16)
333#define DSI_TO_TALLY_LRXH_TALLY(x) (((x) & 0xff) << 8)
334#define DSI_TO_TALLY_HTX_TALLY(x) (((x) & 0xff) << 0)
335
336#define DSI_PAD_CONTROL 0x4b
337#define DSI_PAD_CONTROL_PAD_PULLDN_ENAB(x) (((x) & 0x1) << 28)
338#define DSI_PAD_CONTROL_PAD_SLEWUPADJ(x) (((x) & 0x7) << 24)
339#define DSI_PAD_CONTROL_PAD_SLEWDNADJ(x) (((x) & 0x7) << 20)
340#define DSI_PAD_CONTROL_PAD_PREEMP_EN(x) (((x) & 0x1) << 19)
341#define DSI_PAD_CONTROL_PAD_PDIO_CLK(x) (((x) & 0x1) << 18)
342#define DSI_PAD_CONTROL_PAD_PDIO(x) (((x) & 0x3) << 16)
343#define DSI_PAD_CONTROL_PAD_LPUPADJ(x) (((x) & 0x3) << 14)
344#define DSI_PAD_CONTROL_PAD_LPDNADJ(x) (((x) & 0x3) << 12)
345
346#define DSI_PAD_CONTROL_CD 0x4c
347#define DSI_PAD_CD_STATUS 0x4d
348#define DSI_VID_MODE_CONTROL 0x4e
349
350#endif
351
diff --git a/drivers/video/tegra/dc/edid.c b/drivers/video/tegra/dc/edid.c
new file mode 100644
index 00000000000..fbcf2cc8e37
--- /dev/null
+++ b/drivers/video/tegra/dc/edid.c
@@ -0,0 +1,619 @@
1/*
2 * drivers/video/tegra/dc/edid.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * Copyright (C) 2010-2011 NVIDIA Corporation
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20
21#include <linux/debugfs.h>
22#include <linux/fb.h>
23#include <linux/i2c.h>
24#include <linux/seq_file.h>
25#include <linux/vmalloc.h>
26
27#include "edid.h"
28
29struct tegra_edid_pvt {
30 struct kref refcnt;
31 struct tegra_edid_hdmi_eld eld;
32 bool support_stereo;
33 bool support_underscan;
34 /* Note: dc_edid must remain the last member */
35 struct tegra_dc_edid dc_edid;
36};
37
38struct tegra_edid {
39 struct i2c_client *client;
40 struct i2c_board_info info;
41 int bus;
42
43 struct tegra_edid_pvt *data;
44
45 struct mutex lock;
46};
47
48#if defined(DEBUG) || defined(CONFIG_DEBUG_FS)
49static int tegra_edid_show(struct seq_file *s, void *unused)
50{
51 struct tegra_edid *edid = s->private;
52 struct tegra_dc_edid *data;
53 u8 *buf;
54 int i;
55
56 data = tegra_edid_get_data(edid);
57 if (!data) {
58 seq_printf(s, "No EDID\n");
59 return 0;
60 }
61
62 buf = data->buf;
63
64 for (i = 0; i < data->len; i++) {
65 if (i % 16 == 0)
66 seq_printf(s, "edid[%03x] =", i);
67
68 seq_printf(s, " %02x", buf[i]);
69
70 if (i % 16 == 15)
71 seq_printf(s, "\n");
72 }
73
74 tegra_edid_put_data(data);
75
76 return 0;
77}
78#endif
79
80#ifdef CONFIG_DEBUG_FS
81static int tegra_edid_debug_open(struct inode *inode, struct file *file)
82{
83 return single_open(file, tegra_edid_show, inode->i_private);
84}
85
86static const struct file_operations tegra_edid_debug_fops = {
87 .open = tegra_edid_debug_open,
88 .read = seq_read,
89 .llseek = seq_lseek,
90 .release = single_release,
91};
92
93void tegra_edid_debug_add(struct tegra_edid *edid)
94{
95 char name[] = "edidX";
96
97 snprintf(name, sizeof(name), "edid%1d", edid->bus);
98 debugfs_create_file(name, S_IRUGO, NULL, edid, &tegra_edid_debug_fops);
99}
100#else
101void tegra_edid_debug_add(struct tegra_edid *edid)
102{
103}
104#endif
105
106#ifdef DEBUG
107static char tegra_edid_dump_buff[16 * 1024];
108
109static void tegra_edid_dump(struct tegra_edid *edid)
110{
111 struct seq_file s;
112 int i;
113 char c;
114
115 memset(&s, 0x0, sizeof(s));
116
117 s.buf = tegra_edid_dump_buff;
118 s.size = sizeof(tegra_edid_dump_buff);
119 s.private = edid;
120
121 tegra_edid_show(&s, NULL);
122
123 i = 0;
124 while (i < s.count ) {
125 if ((s.count - i) > 256) {
126 c = s.buf[i + 256];
127 s.buf[i + 256] = 0;
128 printk("%s", s.buf + i);
129 s.buf[i + 256] = c;
130 } else {
131 printk("%s", s.buf + i);
132 }
133 i += 256;
134 }
135}
136#else
137static void tegra_edid_dump(struct tegra_edid *edid)
138{
139}
140#endif
141
142int tegra_edid_read_block(struct tegra_edid *edid, int block, u8 *data)
143{
144 u8 block_buf[] = {block >> 1};
145 u8 cmd_buf[] = {(block & 0x1) * 128};
146 int status;
147 struct i2c_msg msg[] = {
148 {
149 .addr = 0x30,
150 .flags = 0,
151 .len = 1,
152 .buf = block_buf,
153 },
154 {
155 .addr = 0x50,
156 .flags = 0,
157 .len = 1,
158 .buf = cmd_buf,
159 },
160 {
161 .addr = 0x50,
162 .flags = I2C_M_RD,
163 .len = 128,
164 .buf = data,
165 }};
166 struct i2c_msg *m;
167 int msg_len;
168
169 if (block > 1) {
170 msg_len = 3;
171 m = msg;
172 } else {
173 msg_len = 2;
174 m = &msg[1];
175 }
176
177 status = i2c_transfer(edid->client->adapter, m, msg_len);
178
179 if (status < 0)
180 return status;
181
182 if (status != msg_len)
183 return -EIO;
184
185 return 0;
186}
187
188int tegra_edid_parse_ext_block(const u8 *raw, int idx,
189 struct tegra_edid_pvt *edid)
190{
191 const u8 *ptr;
192 u8 tmp;
193 u8 code;
194 int len;
195 int i;
196 bool basic_audio = false;
197
198 ptr = &raw[0];
199
200 /* If CEA 861 block get info for eld struct */
201 if (edid && ptr) {
202 if (*ptr <= 3)
203 edid->eld.eld_ver = 0x02;
204 edid->eld.cea_edid_ver = ptr[1];
205
206 /* check for basic audio support in CEA 861 block */
207 if(raw[3] & (1<<6)) {
208 /* For basic audio, set spk_alloc to Left+Right.
209 * If there is a Speaker Alloc block this will
210 * get over written with that value */
211 basic_audio = true;
212 }
213 }
214
215 if (raw[3] & 0x80)
216 edid->support_underscan = 1;
217 else
218 edid->support_underscan = 0;
219
220 ptr = &raw[4];
221
222 while (ptr < &raw[idx]) {
223 tmp = *ptr;
224 len = tmp & 0x1f;
225
226 /* HDMI Specification v1.4a, section 8.3.2:
227 * see Table 8-16 for HDMI VSDB format.
228 * data blocks have tags in top 3 bits:
229 * tag code 2: video data block
230 * tag code 3: vendor specific data block
231 */
232 code = (tmp >> 5) & 0x7;
233 switch (code) {
234 case 1:
235 {
236 edid->eld.sad_count = len;
237 edid->eld.conn_type = 0x00;
238 edid->eld.support_hdcp = 0x00;
239 for (i = 0; (i < len) && (i < ELD_MAX_SAD); i ++)
240 edid->eld.sad[i] = ptr[i + 1];
241 len++;
242 ptr += len; /* adding the header */
243 /* Got an audio data block so enable audio */
244 if(basic_audio == true)
245 edid->eld.spk_alloc = 1;
246 break;
247 }
248 /* case 2 is commented out for now */
249 case 3:
250 {
251 int j = 0;
252
253 if ((ptr[1] == 0x03) &&
254 (ptr[2] == 0x0c) &&
255 (ptr[3] == 0)) {
256 edid->eld.port_id[0] = ptr[4];
257 edid->eld.port_id[1] = ptr[5];
258 }
259 if ((len >= 8) &&
260 (ptr[1] == 0x03) &&
261 (ptr[2] == 0x0c) &&
262 (ptr[3] == 0)) {
263 j = 8;
264 tmp = ptr[j++];
265 /* HDMI_Video_present? */
266 if (tmp & 0x20) {
267 /* Latency_Fields_present? */
268 if (tmp & 0x80)
269 j += 2;
270 /* I_Latency_Fields_present? */
271 if (tmp & 0x40)
272 j += 2;
273 /* 3D_present? */
274 if (j <= len && (ptr[j] & 0x80))
275 edid->support_stereo = 1;
276 }
277 }
278 if ((len > 5) &&
279 (ptr[1] == 0x03) &&
280 (ptr[2] == 0x0c) &&
281 (ptr[3] == 0)) {
282
283 edid->eld.support_ai = (ptr[6] & 0x80);
284 }
285
286 if ((len > 9) &&
287 (ptr[1] == 0x03) &&
288 (ptr[2] == 0x0c) &&
289 (ptr[3] == 0)) {
290
291 edid->eld.aud_synch_delay = ptr[10];
292 }
293 len++;
294 ptr += len; /* adding the header */
295 break;
296 }
297 case 4:
298 {
299 edid->eld.spk_alloc = ptr[1];
300 len++;
301 ptr += len; /* adding the header */
302 break;
303 }
304 default:
305 len++; /* len does not include header */
306 ptr += len;
307 break;
308 }
309 }
310
311 return 0;
312}
313
314int tegra_edid_mode_support_stereo(struct fb_videomode *mode)
315{
316 if (!mode)
317 return 0;
318
319 if (mode->xres == 1280 &&
320 mode->yres == 720 &&
321 ((mode->refresh == 60) || (mode->refresh == 50)))
322 return 1;
323
324 /* Disabling 1080p stereo mode due to bug 869099. */
325 /* Must re-enable this to 1 once it is fixed. */
326 if (mode->xres == 1920 && mode->yres == 1080 && mode->refresh == 24)
327 return 0;
328
329 return 0;
330}
331
332static void data_release(struct kref *ref)
333{
334 struct tegra_edid_pvt *data =
335 container_of(ref, struct tegra_edid_pvt, refcnt);
336 vfree(data);
337}
338
339int tegra_edid_get_monspecs_test(struct tegra_edid *edid,
340 struct fb_monspecs *specs, unsigned char *edid_ptr)
341{
342 int i, j, ret;
343 int extension_blocks;
344 struct tegra_edid_pvt *new_data, *old_data;
345 u8 *data;
346
347 new_data = vmalloc(SZ_32K + sizeof(struct tegra_edid_pvt));
348 if (!new_data)
349 return -ENOMEM;
350
351 kref_init(&new_data->refcnt);
352
353 new_data->support_stereo = 0;
354 new_data->support_underscan = 0;
355
356 data = new_data->dc_edid.buf;
357 memcpy(data, edid_ptr, 128);
358
359 memset(specs, 0x0, sizeof(struct fb_monspecs));
360 memset(&new_data->eld, 0x0, sizeof(new_data->eld));
361 fb_edid_to_monspecs(data, specs);
362 if (specs->modedb == NULL) {
363 ret = -EINVAL;
364 goto fail;
365 }
366
367 memcpy(new_data->eld.monitor_name, specs->monitor,
368 sizeof(specs->monitor));
369
370 new_data->eld.mnl = strlen(new_data->eld.monitor_name) + 1;
371 new_data->eld.product_id[0] = data[0x8];
372 new_data->eld.product_id[1] = data[0x9];
373 new_data->eld.manufacture_id[0] = data[0xA];
374 new_data->eld.manufacture_id[1] = data[0xB];
375
376 extension_blocks = data[0x7e];
377 for (i = 1; i <= extension_blocks; i++) {
378 memcpy(data+128, edid_ptr+128, 128);
379
380 if (data[i * 128] == 0x2) {
381 fb_edid_add_monspecs(data + i * 128, specs);
382
383 tegra_edid_parse_ext_block(data + i * 128,
384 data[i * 128 + 2], new_data);
385
386 if (new_data->support_stereo) {
387 for (j = 0; j < specs->modedb_len; j++) {
388 if (tegra_edid_mode_support_stereo(
389 &specs->modedb[j]))
390 specs->modedb[j].vmode |=
391#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
392 FB_VMODE_STEREO_FRAME_PACK;
393#else
394 FB_VMODE_STEREO_LEFT_RIGHT;
395#endif
396 }
397 }
398 }
399 }
400
401 new_data->dc_edid.len = i * 128;
402
403 mutex_lock(&edid->lock);
404 old_data = edid->data;
405 edid->data = new_data;
406 mutex_unlock(&edid->lock);
407
408 if (old_data)
409 kref_put(&old_data->refcnt, data_release);
410
411 tegra_edid_dump(edid);
412 return 0;
413fail:
414 vfree(new_data);
415 return ret;
416}
417
418int tegra_edid_get_monspecs(struct tegra_edid *edid, struct fb_monspecs *specs)
419{
420 int i;
421 int j;
422 int ret;
423 int extension_blocks;
424 struct tegra_edid_pvt *new_data, *old_data;
425 u8 *data;
426
427 new_data = vmalloc(SZ_32K + sizeof(struct tegra_edid_pvt));
428 if (!new_data)
429 return -ENOMEM;
430
431 kref_init(&new_data->refcnt);
432
433 new_data->support_stereo = 0;
434
435 data = new_data->dc_edid.buf;
436
437 ret = tegra_edid_read_block(edid, 0, data);
438 if (ret)
439 goto fail;
440
441 memset(specs, 0x0, sizeof(struct fb_monspecs));
442 memset(&new_data->eld, 0x0, sizeof(new_data->eld));
443 fb_edid_to_monspecs(data, specs);
444 if (specs->modedb == NULL) {
445 ret = -EINVAL;
446 goto fail;
447 }
448 memcpy(new_data->eld.monitor_name, specs->monitor, sizeof(specs->monitor));
449 new_data->eld.mnl = strlen(new_data->eld.monitor_name) + 1;
450 new_data->eld.product_id[0] = data[0x8];
451 new_data->eld.product_id[1] = data[0x9];
452 new_data->eld.manufacture_id[0] = data[0xA];
453 new_data->eld.manufacture_id[1] = data[0xB];
454
455 extension_blocks = data[0x7e];
456
457 for (i = 1; i <= extension_blocks; i++) {
458 ret = tegra_edid_read_block(edid, i, data + i * 128);
459 if (ret < 0)
460 break;
461
462 if (data[i * 128] == 0x2) {
463 fb_edid_add_monspecs(data + i * 128, specs);
464
465 tegra_edid_parse_ext_block(data + i * 128,
466 data[i * 128 + 2], new_data);
467
468 if (new_data->support_stereo) {
469 for (j = 0; j < specs->modedb_len; j++) {
470 if (tegra_edid_mode_support_stereo(
471 &specs->modedb[j]))
472 specs->modedb[j].vmode |=
473#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
474 FB_VMODE_STEREO_FRAME_PACK;
475#else
476 FB_VMODE_STEREO_LEFT_RIGHT;
477#endif
478 }
479 }
480 }
481 }
482
483 new_data->dc_edid.len = i * 128;
484
485 mutex_lock(&edid->lock);
486 old_data = edid->data;
487 edid->data = new_data;
488 mutex_unlock(&edid->lock);
489
490 if (old_data)
491 kref_put(&old_data->refcnt, data_release);
492
493 tegra_edid_dump(edid);
494 return 0;
495
496fail:
497 vfree(new_data);
498 return ret;
499}
500
501int tegra_edid_underscan_supported(struct tegra_edid *edid)
502{
503 if ((!edid) || (!edid->data))
504 return 0;
505
506 return edid->data->support_underscan;
507}
508
509int tegra_edid_get_eld(struct tegra_edid *edid, struct tegra_edid_hdmi_eld *elddata)
510{
511 if (!elddata || !edid->data)
512 return -EFAULT;
513
514 memcpy(elddata,&edid->data->eld,sizeof(struct tegra_edid_hdmi_eld));
515
516 return 0;
517}
518
519struct tegra_edid *tegra_edid_create(int bus)
520{
521 struct tegra_edid *edid;
522 struct i2c_adapter *adapter;
523 int err;
524
525 edid = kzalloc(sizeof(struct tegra_edid), GFP_KERNEL);
526 if (!edid)
527 return ERR_PTR(-ENOMEM);
528
529 mutex_init(&edid->lock);
530 strlcpy(edid->info.type, "tegra_edid", sizeof(edid->info.type));
531 edid->bus = bus;
532 edid->info.addr = 0x50;
533 edid->info.platform_data = edid;
534
535 adapter = i2c_get_adapter(bus);
536 if (!adapter) {
537 pr_err("can't get adpater for bus %d\n", bus);
538 err = -EBUSY;
539 goto free_edid;
540 }
541
542 edid->client = i2c_new_device(adapter, &edid->info);
543 i2c_put_adapter(adapter);
544
545 if (!edid->client) {
546 pr_err("can't create new device\n");
547 err = -EBUSY;
548 goto free_edid;
549 }
550
551 tegra_edid_debug_add(edid);
552
553 return edid;
554
555free_edid:
556 kfree(edid);
557
558 return ERR_PTR(err);
559}
560
561void tegra_edid_destroy(struct tegra_edid *edid)
562{
563 i2c_release_client(edid->client);
564 if (edid->data)
565 kref_put(&edid->data->refcnt, data_release);
566 kfree(edid);
567}
568
569struct tegra_dc_edid *tegra_edid_get_data(struct tegra_edid *edid)
570{
571 struct tegra_edid_pvt *data;
572
573 mutex_lock(&edid->lock);
574 data = edid->data;
575 if (data)
576 kref_get(&data->refcnt);
577 mutex_unlock(&edid->lock);
578
579 return data ? &data->dc_edid : NULL;
580}
581
582void tegra_edid_put_data(struct tegra_dc_edid *data)
583{
584 struct tegra_edid_pvt *pvt;
585
586 if (!data)
587 return;
588
589 pvt = container_of(data, struct tegra_edid_pvt, dc_edid);
590
591 kref_put(&pvt->refcnt, data_release);
592}
593
594static const struct i2c_device_id tegra_edid_id[] = {
595 { "tegra_edid", 0 },
596 { }
597};
598
599MODULE_DEVICE_TABLE(i2c, tegra_edid_id);
600
601static struct i2c_driver tegra_edid_driver = {
602 .id_table = tegra_edid_id,
603 .driver = {
604 .name = "tegra_edid",
605 },
606};
607
608static int __init tegra_edid_init(void)
609{
610 return i2c_add_driver(&tegra_edid_driver);
611}
612
613static void __exit tegra_edid_exit(void)
614{
615 i2c_del_driver(&tegra_edid_driver);
616}
617
618module_init(tegra_edid_init);
619module_exit(tegra_edid_exit);
diff --git a/drivers/video/tegra/dc/edid.h b/drivers/video/tegra/dc/edid.h
new file mode 100644
index 00000000000..77db36f4adb
--- /dev/null
+++ b/drivers/video/tegra/dc/edid.h
@@ -0,0 +1,62 @@
1/*
2 * drivers/video/tegra/dc/edid.h
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __DRIVERS_VIDEO_TEGRA_DC_EDID_H
19#define __DRIVERS_VIDEO_TEGRA_DC_EDID_H
20
21#include <linux/i2c.h>
22#include <linux/wait.h>
23#include <mach/dc.h>
24
25#define ELD_MAX_MNL 16
26#define ELD_MAX_SAD 16
27struct tegra_edid;
28
29/*
30 * ELD: EDID Like Data
31 */
32struct tegra_edid_hdmi_eld {
33 u8 baseline_len;
34 u8 eld_ver;
35 u8 cea_edid_ver;
36 char monitor_name[ELD_MAX_MNL + 1];
37 u8 mnl;
38 u8 manufacture_id[2];
39 u8 product_id[2];
40 u8 port_id[8];
41 u8 support_hdcp;
42 u8 support_ai;
43 u8 conn_type;
44 u8 aud_synch_delay;
45 u8 spk_alloc;
46 u8 sad_count;
47 u8 sad[ELD_MAX_SAD];
48};
49
50struct tegra_edid *tegra_edid_create(int bus);
51void tegra_edid_destroy(struct tegra_edid *edid);
52
53int tegra_edid_get_monspecs_test(struct tegra_edid *edid,
54 struct fb_monspecs *specs, u8 *edid_ptr);
55int tegra_edid_get_monspecs(struct tegra_edid *edid, struct fb_monspecs *specs);
56int tegra_edid_get_eld(struct tegra_edid *edid, struct tegra_edid_hdmi_eld *elddata);
57
58struct tegra_dc_edid *tegra_edid_get_data(struct tegra_edid *edid);
59void tegra_edid_put_data(struct tegra_dc_edid *data);
60
61int tegra_edid_underscan_supported(struct tegra_edid *edid);
62#endif
diff --git a/drivers/video/tegra/dc/ext/Makefile b/drivers/video/tegra/dc/ext/Makefile
new file mode 100644
index 00000000000..19860ab5db1
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/Makefile
@@ -0,0 +1,5 @@
1obj-y += dev.o
2obj-y += util.o
3obj-y += cursor.o
4obj-y += events.o
5obj-y += control.o
diff --git a/drivers/video/tegra/dc/ext/control.c b/drivers/video/tegra/dc/ext/control.c
new file mode 100644
index 00000000000..9caf3e11c16
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/control.c
@@ -0,0 +1,279 @@
1/*
2 * drivers/video/tegra/dc/ext/control.c
3 *
4 * Copyright (C) 2011, NVIDIA Corporation
5 *
6 * Author: Robert Morell <rmorell@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 */
18
19#include <linux/device.h>
20#include <linux/err.h>
21#include <linux/file.h>
22#include <linux/fs.h>
23#include <linux/slab.h>
24#include <linux/module.h>
25#include <linux/uaccess.h>
26
27#include "tegra_dc_ext_priv.h"
28
29static struct tegra_dc_ext_control g_control;
30
31int tegra_dc_ext_process_hotplug(int output)
32{
33 return tegra_dc_ext_queue_hotplug(&g_control, output);
34}
35
36static int
37get_output_properties(struct tegra_dc_ext_control_output_properties *properties)
38{
39 struct tegra_dc *dc;
40
41 /* TODO: this should be more dynamic */
42 if (properties->handle > 2)
43 return -EINVAL;
44
45 switch (properties->handle) {
46 case 0:
47 properties->type = TEGRA_DC_EXT_LVDS;
48 break;
49 case 1:
50 properties->type = TEGRA_DC_EXT_HDMI;
51 break;
52 default:
53 return -EINVAL;
54 }
55
56 properties->associated_head = properties->handle;
57 properties->head_mask = (1 << properties->associated_head);
58
59 dc = tegra_dc_get_dc(properties->associated_head);
60 properties->connected = tegra_dc_get_connected(dc);
61
62 return 0;
63}
64
65static int get_output_edid(struct tegra_dc_ext_control_output_edid *edid)
66{
67 struct tegra_dc *dc;
68 size_t user_size = edid->size;
69 struct tegra_dc_edid *dc_edid = NULL;
70 int ret;
71
72 /* TODO: this should be more dynamic */
73 if (edid->handle > 2)
74 return -EINVAL;
75
76 dc = tegra_dc_get_dc(edid->handle);
77
78 dc_edid = tegra_dc_get_edid(dc);
79 if (IS_ERR(dc_edid))
80 return PTR_ERR(dc_edid);
81
82 if (!dc_edid) {
83 edid->size = 0;
84 } else {
85 edid->size = dc_edid->len;
86
87 if (user_size < edid->size) {
88 ret = -EFBIG;
89 goto done;
90 }
91
92 if (copy_to_user(edid->data, dc_edid->buf, edid->size)) {
93 ret = -EFAULT;
94 goto done;
95 }
96
97 }
98
99done:
100 if (dc_edid)
101 tegra_dc_put_edid(dc_edid);
102
103 return ret;
104}
105
106static int set_event_mask(struct tegra_dc_ext_control_user *user, u32 mask)
107{
108 struct list_head *list, *tmp;
109
110 if (mask & ~TEGRA_DC_EXT_EVENT_MASK_ALL)
111 return -EINVAL;
112
113 mutex_lock(&user->lock);
114
115 user->event_mask = mask;
116
117 list_for_each_safe(list, tmp, &user->event_list) {
118 struct tegra_dc_ext_event_list *ev_list;
119 ev_list = list_entry(list, struct tegra_dc_ext_event_list,
120 list);
121 if (!(mask & ev_list->event.type)) {
122 list_del(list);
123 kfree(ev_list);
124 }
125 }
126 mutex_unlock(&user->lock);
127
128 return 0;
129}
130
131static int get_capabilities(struct tegra_dc_ext_control_capabilities *caps)
132{
133 caps->caps = TEGRA_DC_EXT_CAPABILITIES;
134 return 0;
135}
136
137static long tegra_dc_ext_control_ioctl(struct file *filp, unsigned int cmd,
138 unsigned long arg)
139{
140 void __user *user_arg = (void __user *)arg;
141 struct tegra_dc_ext_control_user *user = filp->private_data;
142
143 switch (cmd) {
144 case TEGRA_DC_EXT_CONTROL_GET_NUM_OUTPUTS:
145 {
146 u32 num = tegra_dc_ext_get_num_outputs();
147
148 if (copy_to_user(user_arg, &num, sizeof(num)))
149 return -EFAULT;
150
151 return 0;
152 }
153 case TEGRA_DC_EXT_CONTROL_GET_OUTPUT_PROPERTIES:
154 {
155 struct tegra_dc_ext_control_output_properties args;
156 int ret;
157
158 if (copy_from_user(&args, user_arg, sizeof(args)))
159 return -EFAULT;
160
161 ret = get_output_properties(&args);
162
163 if (copy_to_user(user_arg, &args, sizeof(args)))
164 return -EFAULT;
165
166 return ret;
167 }
168 case TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID:
169 {
170 struct tegra_dc_ext_control_output_edid args;
171 int ret;
172
173 if (copy_from_user(&args, user_arg, sizeof(args)))
174 return -EFAULT;
175
176 ret = get_output_edid(&args);
177
178 if (copy_to_user(user_arg, &args, sizeof(args)))
179 return -EFAULT;
180
181 return ret;
182 }
183 case TEGRA_DC_EXT_CONTROL_SET_EVENT_MASK:
184 return set_event_mask(user, (u32) arg);
185 case TEGRA_DC_EXT_CONTROL_GET_CAPABILITIES:
186 {
187 struct tegra_dc_ext_control_capabilities args;
188 int ret;
189
190 ret = get_capabilities(&args);
191
192 if (copy_to_user(user_arg, &args, sizeof(args)))
193 return -EFAULT;
194
195 return ret;
196 }
197 default:
198 return -EINVAL;
199 }
200}
201
202static int tegra_dc_ext_control_open(struct inode *inode, struct file *filp)
203{
204 struct tegra_dc_ext_control_user *user;
205 struct tegra_dc_ext_control *control;
206
207 user = kzalloc(sizeof(*user), GFP_KERNEL);
208 if (!user)
209 return -ENOMEM;
210
211 control = container_of(inode->i_cdev, struct tegra_dc_ext_control,
212 cdev);
213 user->control = control;;
214
215 INIT_LIST_HEAD(&user->event_list);
216 mutex_init(&user->lock);
217
218 filp->private_data = user;
219
220 mutex_lock(&control->lock);
221 list_add(&user->list, &control->users);
222 mutex_unlock(&control->lock);
223
224 return 0;
225}
226
227static int tegra_dc_ext_control_release(struct inode *inode, struct file *filp)
228{
229 struct tegra_dc_ext_control_user *user = filp->private_data;
230 struct tegra_dc_ext_control *control = user->control;
231
232 /* This will free any pending events for this user */
233 set_event_mask(user, 0);
234
235 mutex_lock(&control->lock);
236 list_del(&user->list);
237 mutex_unlock(&control->lock);
238
239 kfree(user);
240
241 return 0;
242}
243
244static const struct file_operations tegra_dc_ext_event_devops = {
245 .owner = THIS_MODULE,
246 .open = tegra_dc_ext_control_open,
247 .release = tegra_dc_ext_control_release,
248 .read = tegra_dc_ext_event_read,
249 .poll = tegra_dc_ext_event_poll,
250 .unlocked_ioctl = tegra_dc_ext_control_ioctl,
251};
252
253int tegra_dc_ext_control_init(void)
254{
255 struct tegra_dc_ext_control *control = &g_control;
256 int ret;
257
258 cdev_init(&control->cdev, &tegra_dc_ext_event_devops);
259 control->cdev.owner = THIS_MODULE;
260 ret = cdev_add(&control->cdev, tegra_dc_ext_devno, 1);
261 if (ret)
262 return ret;
263
264 control->dev = device_create(tegra_dc_ext_class,
265 NULL,
266 tegra_dc_ext_devno,
267 NULL,
268 "tegra_dc_ctrl");
269 if (IS_ERR(control->dev)) {
270 ret = PTR_ERR(control->dev);
271 cdev_del(&control->cdev);
272 }
273
274 mutex_init(&control->lock);
275
276 INIT_LIST_HEAD(&control->users);
277
278 return ret;
279}
diff --git a/drivers/video/tegra/dc/ext/cursor.c b/drivers/video/tegra/dc/ext/cursor.c
new file mode 100644
index 00000000000..d8fa5fd8e6d
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/cursor.c
@@ -0,0 +1,203 @@
1/*
2 * drivers/video/tegra/dc/ext/cursor.c
3 *
4 * Copyright (C) 2011, NVIDIA Corporation
5 *
6 * Author: Robert Morell <rmorell@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 */
18
19#include <video/tegra_dc_ext.h>
20
21#include "tegra_dc_ext_priv.h"
22
23/* ugh */
24#include "../dc_priv.h"
25#include "../dc_reg.h"
26
27int tegra_dc_ext_get_cursor(struct tegra_dc_ext_user *user)
28{
29 struct tegra_dc_ext *ext = user->ext;
30 int ret = 0;
31
32 mutex_lock(&ext->cursor.lock);
33
34 if (!ext->cursor.user)
35 ext->cursor.user = user;
36 else if (ext->cursor.user != user)
37 ret = -EBUSY;
38
39 mutex_unlock(&ext->cursor.lock);
40
41 return ret;
42}
43
44int tegra_dc_ext_put_cursor(struct tegra_dc_ext_user *user)
45{
46 struct tegra_dc_ext *ext = user->ext;
47 int ret = 0;
48
49 mutex_lock(&ext->cursor.lock);
50
51 if (ext->cursor.user == user)
52 ext->cursor.user = 0;
53 else
54 ret = -EACCES;
55
56 mutex_unlock(&ext->cursor.lock);
57
58 return ret;
59}
60
61static void set_cursor_image_hw(struct tegra_dc *dc,
62 struct tegra_dc_ext_cursor_image *args,
63 dma_addr_t phys_addr)
64{
65 tegra_dc_writel(dc,
66 CURSOR_COLOR(args->foreground.r,
67 args->foreground.g,
68 args->foreground.b),
69 DC_DISP_CURSOR_FOREGROUND);
70 tegra_dc_writel(dc,
71 CURSOR_COLOR(args->background.r,
72 args->background.g,
73 args->background.b),
74 DC_DISP_CURSOR_BACKGROUND);
75
76 BUG_ON(phys_addr & ~CURSOR_START_ADDR_MASK);
77
78 tegra_dc_writel(dc,
79 CURSOR_START_ADDR(((unsigned long) phys_addr)) |
80 ((args->flags & TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64) ?
81 CURSOR_SIZE_64 : 0),
82 DC_DISP_CURSOR_START_ADDR);
83}
84
85int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
86 struct tegra_dc_ext_cursor_image *args)
87{
88 struct tegra_dc_ext *ext = user->ext;
89 struct tegra_dc *dc = ext->dc;
90 struct nvmap_handle_ref *handle, *old_handle;
91 dma_addr_t phys_addr;
92 u32 size;
93 int ret;
94
95 if (!user->nvmap)
96 return -EFAULT;
97
98 size = args->flags & (TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 |
99 TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64);
100
101 if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 &&
102 size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64)
103 return -EINVAL;
104
105 mutex_lock(&ext->cursor.lock);
106
107 if (ext->cursor.user != user) {
108 ret = -EACCES;
109 goto unlock;
110 }
111
112 if (!ext->enabled) {
113 ret = -ENXIO;
114 goto unlock;
115 }
116
117 old_handle = ext->cursor.cur_handle;
118
119 ret = tegra_dc_ext_pin_window(user, args->buff_id, &handle, &phys_addr);
120 if (ret)
121 goto unlock;
122
123 ext->cursor.cur_handle = handle;
124
125 mutex_lock(&dc->lock);
126
127 set_cursor_image_hw(dc, args, phys_addr);
128
129 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
130 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
131
132 /* XXX sync here? */
133
134 mutex_unlock(&dc->lock);
135
136 mutex_unlock(&ext->cursor.lock);
137
138 if (old_handle) {
139 nvmap_unpin(ext->nvmap, old_handle);
140 nvmap_free(ext->nvmap, old_handle);
141 }
142
143 return 0;
144
145unlock:
146 mutex_unlock(&ext->cursor.lock);
147
148 return ret;
149}
150
151int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
152 struct tegra_dc_ext_cursor *args)
153{
154 struct tegra_dc_ext *ext = user->ext;
155 struct tegra_dc *dc = ext->dc;
156 u32 win_options;
157 bool enable;
158 int ret;
159
160 mutex_lock(&ext->cursor.lock);
161
162 if (ext->cursor.user != user) {
163 ret = -EACCES;
164 goto unlock;
165 }
166
167 if (!ext->enabled) {
168 ret = -ENXIO;
169 goto unlock;
170 }
171
172 enable = !!(args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_VISIBLE);
173
174 mutex_lock(&dc->lock);
175
176 win_options = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
177 if (!!(win_options & CURSOR_ENABLE) != enable) {
178 win_options &= ~CURSOR_ENABLE;
179 if (enable)
180 win_options |= CURSOR_ENABLE;
181 tegra_dc_writel(dc, win_options, DC_DISP_DISP_WIN_OPTIONS);
182 }
183
184 tegra_dc_writel(dc, CURSOR_POSITION(args->x, args->y),
185 DC_DISP_CURSOR_POSITION);
186
187 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
188 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
189
190 /* TODO: need to sync here? hopefully can avoid this, but need to
191 * figure out interaction w/ rest of GENERAL_ACT_REQ */
192
193 mutex_unlock(&dc->lock);
194
195 mutex_unlock(&ext->cursor.lock);
196
197 return 0;
198
199unlock:
200 mutex_unlock(&ext->cursor.lock);
201
202 return ret;
203}
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
new file mode 100644
index 00000000000..04553e77839
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -0,0 +1,975 @@
1/*
2 * drivers/video/tegra/dc/dev.c
3 *
4 * Copyright (C) 2011-2012, NVIDIA Corporation
5 *
6 * Author: Robert Morell <rmorell@nvidia.com>
7 * Some code based on fbdev extensions written by:
8 * Erik Gilling <konkers@android.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 */
20
21#include <linux/file.h>
22#include <linux/fs.h>
23#include <linux/uaccess.h>
24#include <linux/slab.h>
25#include <linux/workqueue.h>
26
27#include <video/tegra_dc_ext.h>
28
29#include <mach/dc.h>
30#include <mach/nvmap.h>
31#include <mach/tegra_dc_ext.h>
32
33/* XXX ew */
34#include "../dc_priv.h"
35/* XXX ew 2 */
36#include "../../host/dev.h"
37/* XXX ew 3 */
38#include "../../nvmap/nvmap.h"
39#include "tegra_dc_ext_priv.h"
40
41int tegra_dc_ext_devno;
42struct class *tegra_dc_ext_class;
43static int head_count;
44
45struct tegra_dc_ext_flip_win {
46 struct tegra_dc_ext_flip_windowattr attr;
47 struct nvmap_handle_ref *handle[TEGRA_DC_NUM_PLANES];
48 dma_addr_t phys_addr;
49 dma_addr_t phys_addr_u;
50 dma_addr_t phys_addr_v;
51 u32 syncpt_max;
52};
53
54struct tegra_dc_ext_flip_data {
55 struct tegra_dc_ext *ext;
56 struct work_struct work;
57 struct tegra_dc_ext_flip_win win[DC_N_WINDOWS];
58};
59
60int tegra_dc_ext_get_num_outputs(void)
61{
62 /* TODO: decouple output count from head count */
63 return head_count;
64}
65
66static int tegra_dc_ext_set_nvmap_fd(struct tegra_dc_ext_user *user,
67 int fd)
68{
69 struct nvmap_client *nvmap = NULL;
70
71 if (fd >= 0) {
72 nvmap = nvmap_client_get_file(fd);
73 if (IS_ERR(nvmap))
74 return PTR_ERR(nvmap);
75 }
76
77 if (user->nvmap)
78 nvmap_client_put(user->nvmap);
79
80 user->nvmap = nvmap;
81
82 return 0;
83}
84
85static int tegra_dc_ext_get_window(struct tegra_dc_ext_user *user,
86 unsigned int n)
87{
88 struct tegra_dc_ext *ext = user->ext;
89 struct tegra_dc_ext_win *win;
90 int ret = 0;
91
92 if (n >= DC_N_WINDOWS)
93 return -EINVAL;
94
95 win = &ext->win[n];
96
97 mutex_lock(&win->lock);
98
99 if (!win->user)
100 win->user = user;
101 else if (win->user != user)
102 ret = -EBUSY;
103
104 mutex_unlock(&win->lock);
105
106 return ret;
107}
108
109static int tegra_dc_ext_put_window(struct tegra_dc_ext_user *user,
110 unsigned int n)
111{
112 struct tegra_dc_ext *ext = user->ext;
113 struct tegra_dc_ext_win *win;
114 int ret = 0;
115
116 if (n >= DC_N_WINDOWS)
117 return -EINVAL;
118
119 win = &ext->win[n];
120
121 mutex_lock(&win->lock);
122
123 if (win->user == user) {
124 flush_workqueue(win->flip_wq);
125 win->user = 0;
126 } else {
127 ret = -EACCES;
128 }
129
130 mutex_unlock(&win->lock);
131
132 return ret;
133}
134
135static void set_enable(struct tegra_dc_ext *ext, bool en)
136{
137 int i;
138
139 /*
140 * Take all locks to make sure any flip requests or cursor moves are
141 * out of their critical sections
142 */
143 for (i = 0; i < ext->dc->n_windows; i++)
144 mutex_lock(&ext->win[i].lock);
145 mutex_lock(&ext->cursor.lock);
146
147 ext->enabled = en;
148
149 mutex_unlock(&ext->cursor.lock);
150 for (i = ext->dc->n_windows - 1; i >= 0 ; i--)
151 mutex_unlock(&ext->win[i].lock);
152}
153
154void tegra_dc_ext_enable(struct tegra_dc_ext *ext)
155{
156 set_enable(ext, true);
157}
158
159void tegra_dc_ext_disable(struct tegra_dc_ext *ext)
160{
161 int i;
162 set_enable(ext, false);
163
164 /*
165 * Flush the flip queue -- note that this must be called with dc->lock
166 * unlocked or else it will hang.
167 */
168 for (i = 0; i < ext->dc->n_windows; i++) {
169 struct tegra_dc_ext_win *win = &ext->win[i];
170
171 flush_workqueue(win->flip_wq);
172 }
173}
174
175static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
176 struct tegra_dc_win *win,
177 const struct tegra_dc_ext_flip_win *flip_win)
178{
179 struct tegra_dc_ext_win *ext_win = &ext->win[win->idx];
180
181 if (flip_win->handle[TEGRA_DC_Y] == NULL) {
182 win->flags = 0;
183 memset(ext_win->cur_handle, 0, sizeof(ext_win->cur_handle));
184 return 0;
185 }
186
187 win->flags = TEGRA_WIN_FLAG_ENABLED;
188 if (flip_win->attr.blend == TEGRA_DC_EXT_BLEND_PREMULT)
189 win->flags |= TEGRA_WIN_FLAG_BLEND_PREMULT;
190 else if (flip_win->attr.blend == TEGRA_DC_EXT_BLEND_COVERAGE)
191 win->flags |= TEGRA_WIN_FLAG_BLEND_COVERAGE;
192 if (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_TILED)
193 win->flags |= TEGRA_WIN_FLAG_TILED;
194 if (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_INVERT_H)
195 win->flags |= TEGRA_WIN_FLAG_INVERT_H;
196 if (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_INVERT_V)
197 win->flags |= TEGRA_WIN_FLAG_INVERT_V;
198 win->fmt = flip_win->attr.pixformat;
199 win->x.full = flip_win->attr.x;
200 win->y.full = flip_win->attr.y;
201 win->w.full = flip_win->attr.w;
202 win->h.full = flip_win->attr.h;
203 /* XXX verify that this doesn't go outside display's active region */
204 win->out_x = flip_win->attr.out_x;
205 win->out_y = flip_win->attr.out_y;
206 win->out_w = flip_win->attr.out_w;
207 win->out_h = flip_win->attr.out_h;
208 win->z = flip_win->attr.z;
209 memcpy(ext_win->cur_handle, flip_win->handle,
210 sizeof(ext_win->cur_handle));
211
212 /* XXX verify that this won't read outside of the surface */
213 win->phys_addr = flip_win->phys_addr + flip_win->attr.offset;
214
215 win->phys_addr_u = flip_win->handle[TEGRA_DC_U] ?
216 flip_win->phys_addr_u : flip_win->phys_addr;
217 win->phys_addr_u += flip_win->attr.offset_u;
218
219 win->phys_addr_v = flip_win->handle[TEGRA_DC_V] ?
220 flip_win->phys_addr_v : flip_win->phys_addr;
221 win->phys_addr_v += flip_win->attr.offset_v;
222
223 win->stride = flip_win->attr.stride;
224 win->stride_uv = flip_win->attr.stride_uv;
225
226 if ((s32)flip_win->attr.pre_syncpt_id >= 0) {
227 nvhost_syncpt_wait_timeout(
228 &nvhost_get_host(ext->dc->ndev)->syncpt,
229 flip_win->attr.pre_syncpt_id,
230 flip_win->attr.pre_syncpt_val,
231 msecs_to_jiffies(500), NULL);
232 }
233
234
235 return 0;
236}
237
238static void tegra_dc_ext_flip_worker(struct work_struct *work)
239{
240 struct tegra_dc_ext_flip_data *data =
241 container_of(work, struct tegra_dc_ext_flip_data, work);
242 struct tegra_dc_ext *ext = data->ext;
243 struct tegra_dc_win *wins[DC_N_WINDOWS];
244 struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS *
245 TEGRA_DC_NUM_PLANES];
246 struct nvmap_handle_ref *old_handle;
247 int i, nr_unpin = 0, nr_win = 0;
248 bool skip_flip = false;
249
250 for (i = 0; i < DC_N_WINDOWS; i++) {
251 struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
252 int index = flip_win->attr.index;
253 struct tegra_dc_win *win;
254 struct tegra_dc_ext_win *ext_win;
255
256 if (index < 0)
257 continue;
258
259 win = tegra_dc_get_window(ext->dc, index);
260 ext_win = &ext->win[index];
261
262 if (!(atomic_dec_and_test(&ext_win->nr_pending_flips)) &&
263 (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_CURSOR))
264 skip_flip = true;
265
266 if (win->flags & TEGRA_WIN_FLAG_ENABLED) {
267 int j;
268 for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) {
269 if (skip_flip)
270 old_handle = flip_win->handle[j];
271 else
272 old_handle = ext_win->cur_handle[j];
273
274 if (!old_handle)
275 continue;
276
277 unpin_handles[nr_unpin++] = old_handle;
278 }
279 }
280
281 if (!skip_flip)
282 tegra_dc_ext_set_windowattr(ext, win, &data->win[i]);
283
284 wins[nr_win++] = win;
285 }
286
287 if (!skip_flip) {
288 tegra_dc_update_windows(wins, nr_win);
289 /* TODO: implement swapinterval here */
290 tegra_dc_sync_windows(wins, nr_win);
291 }
292
293 for (i = 0; i < DC_N_WINDOWS; i++) {
294 struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
295 int index = flip_win->attr.index;
296
297 if (index < 0)
298 continue;
299
300 tegra_dc_incr_syncpt_min(ext->dc, index,
301 flip_win->syncpt_max);
302 }
303
304 /* unpin and deref previous front buffers */
305 for (i = 0; i < nr_unpin; i++) {
306 nvmap_unpin(ext->nvmap, unpin_handles[i]);
307 nvmap_free(ext->nvmap, unpin_handles[i]);
308 }
309
310 kfree(data);
311}
312
313static int lock_windows_for_flip(struct tegra_dc_ext_user *user,
314 struct tegra_dc_ext_flip *args)
315{
316 struct tegra_dc_ext *ext = user->ext;
317 u8 idx_mask = 0;
318 int i;
319
320 for (i = 0; i < DC_N_WINDOWS; i++) {
321 int index = args->win[i].index;
322
323 if (index < 0)
324 continue;
325
326 idx_mask |= BIT(index);
327 }
328
329 for (i = 0; i < DC_N_WINDOWS; i++) {
330 struct tegra_dc_ext_win *win;
331
332 if (!(idx_mask & BIT(i)))
333 continue;
334
335 win = &ext->win[i];
336
337 mutex_lock(&win->lock);
338
339 if (win->user != user)
340 goto fail_unlock;
341 }
342
343 return 0;
344
345fail_unlock:
346 do {
347 if (!(idx_mask & BIT(i)))
348 continue;
349
350 mutex_unlock(&ext->win[i].lock);
351 } while (i--);
352
353 return -EACCES;
354}
355
356static void unlock_windows_for_flip(struct tegra_dc_ext_user *user,
357 struct tegra_dc_ext_flip *args)
358{
359 struct tegra_dc_ext *ext = user->ext;
360 u8 idx_mask = 0;
361 int i;
362
363 for (i = 0; i < DC_N_WINDOWS; i++) {
364 int index = args->win[i].index;
365
366 if (index < 0)
367 continue;
368
369 idx_mask |= BIT(index);
370 }
371
372 for (i = DC_N_WINDOWS - 1; i >= 0; i--) {
373 if (!(idx_mask & BIT(i)))
374 continue;
375
376 mutex_unlock(&ext->win[i].lock);
377 }
378}
379
380static int sanitize_flip_args(struct tegra_dc_ext_user *user,
381 struct tegra_dc_ext_flip *args)
382{
383 int i, used_windows = 0;
384
385 for (i = 0; i < DC_N_WINDOWS; i++) {
386 int index = args->win[i].index;
387
388 if (index < 0)
389 continue;
390
391 if (index >= DC_N_WINDOWS)
392 return -EINVAL;
393
394 if (used_windows & BIT(index))
395 return -EINVAL;
396
397 used_windows |= BIT(index);
398 }
399
400 if (!used_windows)
401 return -EINVAL;
402
403 return 0;
404}
405
406static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
407 struct tegra_dc_ext_flip *args)
408{
409 struct tegra_dc_ext *ext = user->ext;
410 struct tegra_dc_ext_flip_data *data;
411 int work_index;
412 int i, ret = 0;
413
414#ifdef CONFIG_ANDROID
415 int index_check[DC_N_WINDOWS] = {0, };
416 int zero_index_id = 0;
417#endif
418
419 if (!user->nvmap)
420 return -EFAULT;
421
422 ret = sanitize_flip_args(user, args);
423 if (ret)
424 return ret;
425
426 data = kzalloc(sizeof(*data), GFP_KERNEL);
427 if (!data)
428 return -ENOMEM;
429
430 INIT_WORK(&data->work, tegra_dc_ext_flip_worker);
431 data->ext = ext;
432
433#ifdef CONFIG_ANDROID
434 for (i = 0; i < DC_N_WINDOWS; i++) {
435 index_check[i] = args->win[i].index;
436 if (index_check[i] == 0)
437 zero_index_id = i;
438 }
439
440 if (index_check[DC_N_WINDOWS - 1] != 0) {
441 struct tegra_dc_ext_flip_windowattr win_temp;
442 win_temp = args->win[DC_N_WINDOWS - 1];
443 args->win[DC_N_WINDOWS - 1] = args->win[zero_index_id];
444 args->win[zero_index_id] = win_temp;
445 }
446#endif
447
448 for (i = 0; i < DC_N_WINDOWS; i++) {
449 struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
450 int index = args->win[i].index;
451
452 memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
453
454 if (index < 0)
455 continue;
456
457 ret = tegra_dc_ext_pin_window(user, flip_win->attr.buff_id,
458 &flip_win->handle[TEGRA_DC_Y],
459 &flip_win->phys_addr);
460 if (ret)
461 goto fail_pin;
462
463 if (flip_win->attr.buff_id_u) {
464 ret = tegra_dc_ext_pin_window(user,
465 flip_win->attr.buff_id_u,
466 &flip_win->handle[TEGRA_DC_U],
467 &flip_win->phys_addr_u);
468 if (ret)
469 goto fail_pin;
470 } else {
471 flip_win->handle[TEGRA_DC_U] = NULL;
472 flip_win->phys_addr_u = 0;
473 }
474
475 if (flip_win->attr.buff_id_v) {
476 ret = tegra_dc_ext_pin_window(user,
477 flip_win->attr.buff_id_v,
478 &flip_win->handle[TEGRA_DC_V],
479 &flip_win->phys_addr_v);
480 if (ret)
481 goto fail_pin;
482 } else {
483 flip_win->handle[TEGRA_DC_V] = NULL;
484 flip_win->phys_addr_v = 0;
485 }
486 }
487
488 ret = lock_windows_for_flip(user, args);
489 if (ret)
490 goto fail_pin;
491
492 if (!ext->enabled) {
493 ret = -ENXIO;
494 goto unlock;
495 }
496
497 for (i = 0; i < DC_N_WINDOWS; i++) {
498 u32 syncpt_max;
499 int index = args->win[i].index;
500 struct tegra_dc_win *win;
501 struct tegra_dc_ext_win *ext_win;
502
503 if (index < 0)
504 continue;
505
506 win = tegra_dc_get_window(ext->dc, index);
507 ext_win = &ext->win[index];
508
509 syncpt_max = tegra_dc_incr_syncpt_max(ext->dc, index);
510
511 data->win[i].syncpt_max = syncpt_max;
512
513 /*
514 * Any of these windows' syncpoints should be equivalent for
515 * the client, so we just send back an arbitrary one of them
516 */
517 args->post_syncpt_val = syncpt_max;
518 args->post_syncpt_id = tegra_dc_get_syncpt_id(ext->dc, index);
519 work_index = index;
520
521 atomic_inc(&ext->win[work_index].nr_pending_flips);
522 }
523 queue_work(ext->win[work_index].flip_wq, &data->work);
524
525 unlock_windows_for_flip(user, args);
526
527 return 0;
528
529unlock:
530 unlock_windows_for_flip(user, args);
531
532fail_pin:
533 for (i = 0; i < DC_N_WINDOWS; i++) {
534 int j;
535 for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) {
536 if (!data->win[i].handle[j])
537 continue;
538
539 nvmap_unpin(ext->nvmap, data->win[i].handle[j]);
540 nvmap_free(ext->nvmap, data->win[i].handle[j]);
541 }
542 }
543 kfree(data);
544
545 return ret;
546}
547
548static int tegra_dc_ext_set_csc(struct tegra_dc_ext_user *user,
549 struct tegra_dc_ext_csc *new_csc)
550{
551 unsigned int index = new_csc->win_index;
552 struct tegra_dc *dc = user->ext->dc;
553 struct tegra_dc_ext_win *ext_win;
554 struct tegra_dc_csc *csc;
555
556 if (index >= DC_N_WINDOWS)
557 return -EINVAL;
558
559 ext_win = &user->ext->win[index];
560 csc = &dc->windows[index].csc;
561
562 mutex_lock(&ext_win->lock);
563
564 if (ext_win->user != user) {
565 mutex_unlock(&ext_win->lock);
566 return -EACCES;
567 }
568
569 csc->yof = new_csc->yof;
570 csc->kyrgb = new_csc->kyrgb;
571 csc->kur = new_csc->kur;
572 csc->kvr = new_csc->kvr;
573 csc->kug = new_csc->kug;
574 csc->kvg = new_csc->kvg;
575 csc->kub = new_csc->kub;
576 csc->kvb = new_csc->kvb;
577
578 tegra_dc_update_csc(dc, index);
579
580 mutex_unlock(&ext_win->lock);
581
582 return 0;
583}
584
585static int set_lut_channel(u16 *channel_from_user,
586 u8 *channel_to,
587 u32 start,
588 u32 len)
589{
590 int i;
591 u16 lut16bpp[256];
592
593 if (channel_from_user) {
594 if (copy_from_user(lut16bpp, channel_from_user, len<<1))
595 return 1;
596
597 for (i = 0; i < len; i++)
598 channel_to[start+i] = lut16bpp[i]>>8;
599 } else {
600 for (i = 0; i < len; i++)
601 channel_to[start+i] = start+i;
602 }
603
604 return 0;
605}
606
607static int tegra_dc_ext_set_lut(struct tegra_dc_ext_user *user,
608 struct tegra_dc_ext_lut *new_lut)
609{
610 int err;
611 unsigned int index = new_lut->win_index;
612 u32 start = new_lut->start;
613 u32 len = new_lut->len;
614
615 struct tegra_dc *dc = user->ext->dc;
616 struct tegra_dc_ext_win *ext_win;
617 struct tegra_dc_lut *lut;
618
619 if (index >= DC_N_WINDOWS)
620 return -EINVAL;
621
622 if ((start >= 256) || (len > 256) || ((start + len) > 256))
623 return -EINVAL;
624
625 ext_win = &user->ext->win[index];
626 lut = &dc->windows[index].lut;
627
628 mutex_lock(&ext_win->lock);
629
630 if (ext_win->user != user) {
631 mutex_unlock(&ext_win->lock);
632 return -EACCES;
633 }
634
635 err = set_lut_channel(new_lut->r, lut->r, start, len) |
636 set_lut_channel(new_lut->g, lut->g, start, len) |
637 set_lut_channel(new_lut->b, lut->b, start, len);
638
639 if (err) {
640 mutex_unlock(&ext_win->lock);
641 return -EFAULT;
642 }
643
644 tegra_dc_update_lut(dc, index,
645 new_lut->flags & TEGRA_DC_EXT_LUT_FLAGS_FBOVERRIDE);
646
647 mutex_unlock(&ext_win->lock);
648
649 return 0;
650}
651
652static u32 tegra_dc_ext_get_vblank_syncpt(struct tegra_dc_ext_user *user)
653{
654 struct tegra_dc *dc = user->ext->dc;
655
656 return dc->vblank_syncpt;
657}
658
659static int tegra_dc_ext_get_status(struct tegra_dc_ext_user *user,
660 struct tegra_dc_ext_status *status)
661{
662 struct tegra_dc *dc = user->ext->dc;
663
664 memset(status, 0, sizeof(*status));
665
666 if (dc->enabled)
667 status->flags |= TEGRA_DC_EXT_FLAGS_ENABLED;
668
669 return 0;
670}
671
672static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
673 unsigned long arg)
674{
675 void __user *user_arg = (void __user *)arg;
676 struct tegra_dc_ext_user *user = filp->private_data;
677
678 switch (cmd) {
679 case TEGRA_DC_EXT_SET_NVMAP_FD:
680 return tegra_dc_ext_set_nvmap_fd(user, arg);
681
682 case TEGRA_DC_EXT_GET_WINDOW:
683 return tegra_dc_ext_get_window(user, arg);
684 case TEGRA_DC_EXT_PUT_WINDOW:
685 return tegra_dc_ext_put_window(user, arg);
686
687 case TEGRA_DC_EXT_FLIP:
688 {
689 struct tegra_dc_ext_flip args;
690 int ret;
691
692 if (copy_from_user(&args, user_arg, sizeof(args)))
693 return -EFAULT;
694
695 ret = tegra_dc_ext_flip(user, &args);
696
697 if (copy_to_user(user_arg, &args, sizeof(args)))
698 return -EFAULT;
699
700 return ret;
701 }
702
703 case TEGRA_DC_EXT_GET_CURSOR:
704 return tegra_dc_ext_get_cursor(user);
705 case TEGRA_DC_EXT_PUT_CURSOR:
706 return tegra_dc_ext_put_cursor(user);
707 case TEGRA_DC_EXT_SET_CURSOR_IMAGE:
708 {
709 struct tegra_dc_ext_cursor_image args;
710
711 if (copy_from_user(&args, user_arg, sizeof(args)))
712 return -EFAULT;
713
714 return tegra_dc_ext_set_cursor_image(user, &args);
715 }
716 case TEGRA_DC_EXT_SET_CURSOR:
717 {
718 struct tegra_dc_ext_cursor args;
719
720 if (copy_from_user(&args, user_arg, sizeof(args)))
721 return -EFAULT;
722
723 return tegra_dc_ext_set_cursor(user, &args);
724 }
725
726 case TEGRA_DC_EXT_SET_CSC:
727 {
728 struct tegra_dc_ext_csc args;
729
730 if (copy_from_user(&args, user_arg, sizeof(args)))
731 return -EFAULT;
732
733 return tegra_dc_ext_set_csc(user, &args);
734 }
735
736 case TEGRA_DC_EXT_GET_VBLANK_SYNCPT:
737 {
738 u32 syncpt = tegra_dc_ext_get_vblank_syncpt(user);
739
740 if (copy_to_user(user_arg, &syncpt, sizeof(syncpt)))
741 return -EFAULT;
742
743 return 0;
744 }
745
746 case TEGRA_DC_EXT_GET_STATUS:
747 {
748 struct tegra_dc_ext_status args;
749 int ret;
750
751 ret = tegra_dc_ext_get_status(user, &args);
752
753 if (copy_to_user(user_arg, &args, sizeof(args)))
754 return -EFAULT;
755
756 return ret;
757 }
758
759 case TEGRA_DC_EXT_SET_LUT:
760 {
761 struct tegra_dc_ext_lut args;
762
763 if (copy_from_user(&args, user_arg, sizeof(args)))
764 return -EFAULT;
765
766 return tegra_dc_ext_set_lut(user, &args);
767 }
768
769 default:
770 return -EINVAL;
771 }
772}
773
774static int tegra_dc_open(struct inode *inode, struct file *filp)
775{
776 struct tegra_dc_ext_user *user;
777 struct tegra_dc_ext *ext;
778
779 user = kzalloc(sizeof(*user), GFP_KERNEL);
780 if (!user)
781 return -ENOMEM;
782
783 ext = container_of(inode->i_cdev, struct tegra_dc_ext, cdev);
784 user->ext = ext;
785
786 filp->private_data = user;
787
788 return 0;
789}
790
791static int tegra_dc_release(struct inode *inode, struct file *filp)
792{
793 struct tegra_dc_ext_user *user = filp->private_data;
794 struct tegra_dc_ext *ext = user->ext;
795 unsigned int i;
796
797 for (i = 0; i < DC_N_WINDOWS; i++) {
798 if (ext->win[i].user == user)
799 tegra_dc_ext_put_window(user, i);
800 }
801 if (ext->cursor.user == user)
802 tegra_dc_ext_put_cursor(user);
803
804 if (user->nvmap)
805 nvmap_client_put(user->nvmap);
806
807 kfree(user);
808
809 return 0;
810}
811
812static int tegra_dc_ext_setup_windows(struct tegra_dc_ext *ext)
813{
814 int i, ret;
815
816 for (i = 0; i < ext->dc->n_windows; i++) {
817 struct tegra_dc_ext_win *win = &ext->win[i];
818 char name[32];
819
820 win->ext = ext;
821 win->idx = i;
822
823 snprintf(name, sizeof(name), "tegradc.%d/%c",
824 ext->dc->ndev->id, 'a' + i);
825 win->flip_wq = create_singlethread_workqueue(name);
826 if (!win->flip_wq) {
827 ret = -ENOMEM;
828 goto cleanup;
829 }
830
831 mutex_init(&win->lock);
832 }
833
834 return 0;
835
836cleanup:
837 while (i--) {
838 struct tegra_dc_ext_win *win = &ext->win[i];
839 destroy_workqueue(win->flip_wq);
840 }
841
842 return ret;
843}
844
845static const struct file_operations tegra_dc_devops = {
846 .owner = THIS_MODULE,
847 .open = tegra_dc_open,
848 .release = tegra_dc_release,
849 .unlocked_ioctl = tegra_dc_ioctl,
850};
851
852struct tegra_dc_ext *tegra_dc_ext_register(struct nvhost_device *ndev,
853 struct tegra_dc *dc)
854{
855 int ret;
856 struct tegra_dc_ext *ext;
857 int devno;
858
859 ext = kzalloc(sizeof(*ext), GFP_KERNEL);
860 if (!ext)
861 return ERR_PTR(-ENOMEM);
862
863 BUG_ON(!tegra_dc_ext_devno);
864 devno = tegra_dc_ext_devno + head_count + 1;
865
866 cdev_init(&ext->cdev, &tegra_dc_devops);
867 ext->cdev.owner = THIS_MODULE;
868 ret = cdev_add(&ext->cdev, devno, 1);
869 if (ret) {
870 dev_err(&ndev->dev, "Failed to create character device\n");
871 goto cleanup_alloc;
872 }
873
874 ext->dev = device_create(tegra_dc_ext_class,
875 &ndev->dev,
876 devno,
877 NULL,
878 "tegra_dc_%d",
879 ndev->id);
880
881 if (IS_ERR(ext->dev)) {
882 ret = PTR_ERR(ext->dev);
883 goto cleanup_cdev;
884 }
885
886 ext->dc = dc;
887
888 ext->nvmap = nvmap_create_client(nvmap_dev, "tegra_dc_ext");
889 if (!ext->nvmap) {
890 ret = -ENOMEM;
891 goto cleanup_device;
892 }
893
894 ret = tegra_dc_ext_setup_windows(ext);
895 if (ret)
896 goto cleanup_nvmap;
897
898 mutex_init(&ext->cursor.lock);
899
900 head_count++;
901
902 return ext;
903
904cleanup_nvmap:
905 nvmap_client_put(ext->nvmap);
906
907cleanup_device:
908 device_del(ext->dev);
909
910cleanup_cdev:
911 cdev_del(&ext->cdev);
912
913cleanup_alloc:
914 kfree(ext);
915
916 return ERR_PTR(ret);
917}
918
919void tegra_dc_ext_unregister(struct tegra_dc_ext *ext)
920{
921 int i;
922
923 for (i = 0; i < ext->dc->n_windows; i++) {
924 struct tegra_dc_ext_win *win = &ext->win[i];
925
926 flush_workqueue(win->flip_wq);
927 destroy_workqueue(win->flip_wq);
928 }
929
930 nvmap_client_put(ext->nvmap);
931 device_del(ext->dev);
932 cdev_del(&ext->cdev);
933
934 kfree(ext);
935
936 head_count--;
937}
938
939int __init tegra_dc_ext_module_init(void)
940{
941 int ret;
942
943 tegra_dc_ext_class = class_create(THIS_MODULE, "tegra_dc_ext");
944 if (!tegra_dc_ext_class) {
945 printk(KERN_ERR "tegra_dc_ext: failed to create class\n");
946 return -ENOMEM;
947 }
948
949 /* Reserve one character device per head, plus the control device */
950 ret = alloc_chrdev_region(&tegra_dc_ext_devno,
951 0, TEGRA_MAX_DC + 1,
952 "tegra_dc_ext");
953 if (ret)
954 goto cleanup_class;
955
956 ret = tegra_dc_ext_control_init();
957 if (ret)
958 goto cleanup_region;
959
960 return 0;
961
962cleanup_region:
963 unregister_chrdev_region(tegra_dc_ext_devno, TEGRA_MAX_DC);
964
965cleanup_class:
966 class_destroy(tegra_dc_ext_class);
967
968 return ret;
969}
970
971void __exit tegra_dc_ext_module_exit(void)
972{
973 unregister_chrdev_region(tegra_dc_ext_devno, TEGRA_MAX_DC);
974 class_destroy(tegra_dc_ext_class);
975}
diff --git a/drivers/video/tegra/dc/ext/events.c b/drivers/video/tegra/dc/ext/events.c
new file mode 100644
index 00000000000..150a1501fce
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/events.c
@@ -0,0 +1,197 @@
1/*
2 * drivers/video/tegra/dc/ext/events.c
3 *
4 * Copyright (C) 2011, NVIDIA Corporation
5 *
6 * Author: Robert Morell <rmorell@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 */
18
19#include <linux/err.h>
20#include <linux/fs.h>
21#include <linux/list.h>
22#include <linux/poll.h>
23#include <linux/sched.h>
24#include <linux/slab.h>
25#include <linux/uaccess.h>
26
27#include "tegra_dc_ext_priv.h"
28
29static DECLARE_WAIT_QUEUE_HEAD(event_wait);
30
31unsigned int tegra_dc_ext_event_poll(struct file *filp, poll_table *wait)
32{
33 struct tegra_dc_ext_control_user *user = filp->private_data;
34 unsigned int mask = 0;
35
36 poll_wait(filp, &event_wait, wait);
37
38 if (atomic_read(&user->num_events))
39 mask |= POLLIN;
40
41 return mask;
42}
43
44static int get_next_event(struct tegra_dc_ext_control_user *user,
45 struct tegra_dc_ext_event_list *event,
46 bool block)
47{
48 struct list_head *list = &user->event_list;
49 struct tegra_dc_ext_event_list *next_event;
50 int ret;
51
52 if (block) {
53 ret = wait_event_interruptible(event_wait,
54 atomic_read(&user->num_events));
55
56 if (unlikely(ret)) {
57 if (ret == -ERESTARTSYS)
58 return -EAGAIN;
59 return ret;
60 }
61 } else {
62 if (!atomic_read(&user->num_events))
63 return 0;
64 }
65
66 mutex_lock(&user->lock);
67
68 BUG_ON(list_empty(list));
69 next_event = list_first_entry(list, struct tegra_dc_ext_event_list,
70 list);
71 *event = *next_event;
72 list_del(&next_event->list);
73 kfree(next_event);
74
75 atomic_dec(&user->num_events);
76
77 mutex_unlock(&user->lock);
78
79 return 1;
80}
81
82ssize_t tegra_dc_ext_event_read(struct file *filp, char __user *buf,
83 size_t size, loff_t *ppos)
84{
85 struct tegra_dc_ext_control_user *user = filp->private_data;
86 struct tegra_dc_ext_event_list event_elem;
87 struct tegra_dc_ext_event *event = &event_elem.event;
88 ssize_t retval = 0, to_copy, event_size, pending;
89 loff_t previously_copied = 0;
90 char *to_copy_ptr;
91
92 if (size == 0)
93 return 0;
94
95 if (user->partial_copy) {
96 /*
97 * We didn't transfer the entire event last time, need to
98 * finish it up
99 */
100 event_elem = user->event_to_copy;
101 previously_copied = user->partial_copy;
102 } else {
103 /* Get the next event, if any */
104 pending = get_next_event(user, &event_elem,
105 !(filp->f_flags & O_NONBLOCK));
106 if (pending <= 0)
107 return pending;
108 }
109
110 /* Write the event to the user */
111 event_size = sizeof(*event) + event->data_size;
112 BUG_ON(event_size <= previously_copied);
113 event_size -= previously_copied;
114
115 to_copy_ptr = (char *)event + previously_copied;
116 to_copy = min_t(ssize_t, size, event_size);
117 if (copy_to_user(buf, to_copy_ptr, to_copy)) {
118 retval = -EFAULT;
119 to_copy = 0;
120 }
121
122 /* Note that we currently only deliver one event at a time */
123
124 if (event_size > to_copy) {
125 /*
126 * We were only able to copy part of this event. Stash it for
127 * next time.
128 */
129 user->event_to_copy = event_elem;
130 user->partial_copy = previously_copied + to_copy;
131 } else {
132 user->partial_copy = 0;
133 }
134
135 return to_copy ? to_copy : retval;
136}
137
138static int tegra_dc_ext_queue_event(struct tegra_dc_ext_control *control,
139 struct tegra_dc_ext_event *event)
140{
141 struct list_head *cur;
142 int retval = 0;
143
144 mutex_lock(&control->lock);
145 list_for_each(cur, &control->users) {
146 struct tegra_dc_ext_control_user *user;
147 struct tegra_dc_ext_event_list *ev_list;
148
149 user = container_of(cur, struct tegra_dc_ext_control_user,
150 list);
151 mutex_lock(&user->lock);
152
153 if (!(user->event_mask & event->type)) {
154 mutex_unlock(&user->lock);
155 continue;
156 }
157
158 ev_list = kmalloc(sizeof(*ev_list), GFP_KERNEL);
159 if (!ev_list) {
160 retval = -ENOMEM;
161 mutex_unlock(&user->lock);
162 continue;
163 }
164
165 memcpy(&ev_list->event, event,
166 sizeof(*event) + event->data_size);
167
168 list_add_tail(&ev_list->list, &user->event_list);
169
170 atomic_inc(&user->num_events);
171
172 mutex_unlock(&user->lock);
173 }
174 mutex_unlock(&control->lock);
175
176 /* Is it worth it to track waiters with more granularity? */
177 wake_up(&event_wait);
178
179 return retval;
180}
181
182int tegra_dc_ext_queue_hotplug(struct tegra_dc_ext_control *control, int output)
183{
184 struct {
185 struct tegra_dc_ext_event event;
186 struct tegra_dc_ext_control_event_hotplug hotplug;
187 } __packed pack;
188
189 pack.event.type = TEGRA_DC_EXT_EVENT_HOTPLUG;
190 pack.event.data_size = sizeof(pack.hotplug);
191
192 pack.hotplug.handle = output;
193
194 tegra_dc_ext_queue_event(control, &pack.event);
195
196 return 0;
197}
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
new file mode 100644
index 00000000000..95a637d5a52
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -0,0 +1,147 @@
1/*
2 * drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
3 *
4 * Copyright (C) 2011, NVIDIA Corporation
5 *
6 * Author: Robert Morell <rmorell@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 */
18
19#ifndef __TEGRA_DC_EXT_PRIV_H
20#define __TEGRA_DC_EXT_PRIV_H
21
22#include <linux/cdev.h>
23#include <linux/list.h>
24#include <linux/mutex.h>
25#include <linux/poll.h>
26
27#include <mach/dc.h>
28#include <mach/nvmap.h>
29
30#include <video/tegra_dc_ext.h>
31
32struct tegra_dc_ext;
33
34struct tegra_dc_ext_user {
35 struct tegra_dc_ext *ext;
36 struct nvmap_client *nvmap;
37};
38
39enum {
40 TEGRA_DC_Y,
41 TEGRA_DC_U,
42 TEGRA_DC_V,
43 TEGRA_DC_NUM_PLANES,
44};
45
46struct tegra_dc_ext_win {
47 struct tegra_dc_ext *ext;
48
49 int idx;
50
51 struct tegra_dc_ext_user *user;
52
53 struct mutex lock;
54
55 /* Current nvmap handle (if any) for Y, U, V planes */
56 struct nvmap_handle_ref *cur_handle[TEGRA_DC_NUM_PLANES];
57
58 struct workqueue_struct *flip_wq;
59
60 atomic_t nr_pending_flips;
61};
62
63struct tegra_dc_ext {
64 struct tegra_dc *dc;
65
66 struct cdev cdev;
67 struct device *dev;
68
69 struct nvmap_client *nvmap;
70
71 struct tegra_dc_ext_win win[DC_N_WINDOWS];
72
73 struct {
74 struct tegra_dc_ext_user *user;
75 struct nvmap_handle_ref *cur_handle;
76 struct mutex lock;
77 } cursor;
78
79 bool enabled;
80};
81
82#define TEGRA_DC_EXT_EVENT_MASK_ALL \
83 TEGRA_DC_EXT_EVENT_HOTPLUG
84
85#define TEGRA_DC_EXT_EVENT_MAX_SZ 8
86
87struct tegra_dc_ext_event_list {
88 struct tegra_dc_ext_event event;
89 /* The data field _must_ follow the event field. */
90 char data[TEGRA_DC_EXT_EVENT_MAX_SZ];
91
92 struct list_head list;
93};
94
95#define TEGRA_DC_EXT_CAPABILITIES \
96 TEGRA_DC_EXT_CAPABILITIES_CURSOR_MODE
97
98struct tegra_dc_ext_control_user {
99 struct tegra_dc_ext_control *control;
100
101 struct list_head event_list;
102 atomic_t num_events;
103
104 u32 event_mask;
105
106 struct tegra_dc_ext_event_list event_to_copy;
107 loff_t partial_copy;
108
109 struct mutex lock;
110
111 struct list_head list;
112};
113
114struct tegra_dc_ext_control {
115 struct cdev cdev;
116 struct device *dev;
117
118 struct list_head users;
119
120 struct mutex lock;
121};
122
123extern int tegra_dc_ext_devno;
124extern struct class *tegra_dc_ext_class;
125
126extern int tegra_dc_ext_pin_window(struct tegra_dc_ext_user *user, u32 id,
127 struct nvmap_handle_ref **handle,
128 dma_addr_t *phys_addr);
129
130extern int tegra_dc_ext_get_cursor(struct tegra_dc_ext_user *user);
131extern int tegra_dc_ext_put_cursor(struct tegra_dc_ext_user *user);
132extern int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
133 struct tegra_dc_ext_cursor_image *);
134extern int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
135 struct tegra_dc_ext_cursor *);
136
137extern int tegra_dc_ext_control_init(void);
138
139extern int tegra_dc_ext_queue_hotplug(struct tegra_dc_ext_control *,
140 int output);
141extern ssize_t tegra_dc_ext_event_read(struct file *filp, char __user *buf,
142 size_t size, loff_t *ppos);
143extern unsigned int tegra_dc_ext_event_poll(struct file *, poll_table *);
144
145extern int tegra_dc_ext_get_num_outputs(void);
146
147#endif /* __TEGRA_DC_EXT_PRIV_H */
diff --git a/drivers/video/tegra/dc/ext/util.c b/drivers/video/tegra/dc/ext/util.c
new file mode 100644
index 00000000000..747085579f1
--- /dev/null
+++ b/drivers/video/tegra/dc/ext/util.c
@@ -0,0 +1,78 @@
1/*
2 * drivers/video/tegra/dc/ext/util.c
3 *
4 * Copyright (C) 2011, NVIDIA Corporation
5 *
6 * Author: Robert Morell <rmorell@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 */
18
19#include <linux/err.h>
20#include <linux/types.h>
21
22#include <mach/dc.h>
23#include <mach/nvmap.h>
24
25/* ugh */
26#include "../../nvmap/nvmap.h"
27
28#include "tegra_dc_ext_priv.h"
29
30int tegra_dc_ext_pin_window(struct tegra_dc_ext_user *user, u32 id,
31 struct nvmap_handle_ref **handle,
32 dma_addr_t *phys_addr)
33{
34 struct tegra_dc_ext *ext = user->ext;
35 struct nvmap_handle_ref *win_dup;
36 struct nvmap_handle *win_handle;
37 dma_addr_t phys;
38
39 if (!id) {
40 *handle = NULL;
41 *phys_addr = -1;
42
43 return 0;
44 }
45
46 /*
47 * Take a reference to the buffer using the user's nvmap context, to
48 * make sure they have permissions to access it.
49 */
50 win_handle = nvmap_get_handle_id(user->nvmap, id);
51 if (!win_handle)
52 return -EACCES;
53
54 /*
55 * Duplicate the buffer's handle into the dc_ext driver's nvmap
56 * context, to ensure that the handle won't be freed as long as it is
57 * in use by display.
58 */
59 win_dup = nvmap_duplicate_handle_id(ext->nvmap, id);
60
61 /* Release the reference we took in the user's context above */
62 nvmap_handle_put(win_handle);
63
64 if (IS_ERR(win_dup))
65 return PTR_ERR(win_dup);
66
67 phys = nvmap_pin(ext->nvmap, win_dup);
68 /* XXX this isn't correct for non-pointers... */
69 if (IS_ERR((void *)phys)) {
70 nvmap_free(ext->nvmap, win_dup);
71 return PTR_ERR((void *)phys);
72 }
73
74 *phys_addr = phys;
75 *handle = win_dup;
76
77 return 0;
78}
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
new file mode 100644
index 00000000000..cb401a167fd
--- /dev/null
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -0,0 +1,2381 @@
1/*
2 * drivers/video/tegra/dc/hdmi.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * Copyright (C) 2010-2011 NVIDIA Corporation
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/clk.h>
21#include <linux/delay.h>
22#include <linux/err.h>
23#include <linux/fb.h>
24#include <linux/gpio.h>
25#include <linux/interrupt.h>
26#include <linux/kernel.h>
27#include <linux/slab.h>
28#include <linux/spinlock.h>
29#ifdef CONFIG_SWITCH
30#include <linux/switch.h>
31#endif
32#include <linux/workqueue.h>
33#include <linux/debugfs.h>
34#include <linux/seq_file.h>
35#include <linux/device.h>
36
37#include <mach/clk.h>
38#include <mach/dc.h>
39#include <mach/fb.h>
40#include <linux/nvhost.h>
41#include <mach/hdmi-audio.h>
42
43#include <video/tegrafb.h>
44
45#include "dc_reg.h"
46#include "dc_priv.h"
47#include "hdmi_reg.h"
48#include "hdmi.h"
49#include "edid.h"
50#include "nvhdcp.h"
51
52/* datasheet claims this will always be 216MHz */
53#define HDMI_AUDIOCLK_FREQ 216000000
54
55#define HDMI_REKEY_DEFAULT 56
56
57#define HDMI_ELD_RESERVED1_INDEX 1
58#define HDMI_ELD_RESERVED2_INDEX 3
59#define HDMI_ELD_VER_INDEX 0
60#define HDMI_ELD_BASELINE_LEN_INDEX 2
61#define HDMI_ELD_CEA_VER_MNL_INDEX 4
62#define HDMI_ELD_SAD_CNT_CON_TYP_SAI_HDCP_INDEX 5
63#define HDMI_ELD_AUD_SYNC_DELAY_INDEX 6
64#define HDMI_ELD_SPK_ALLOC_INDEX 7
65#define HDMI_ELD_PORT_ID_INDEX 8
66#define HDMI_ELD_MANF_NAME_INDEX 16
67#define HDMI_ELD_PRODUCT_CODE_INDEX 18
68#define HDMI_ELD_MONITOR_NAME_INDEX 20
69
70struct tegra_dc_hdmi_data {
71 struct tegra_dc *dc;
72 struct tegra_edid *edid;
73 struct tegra_edid_hdmi_eld eld;
74 struct tegra_nvhdcp *nvhdcp;
75 struct delayed_work work;
76
77 struct resource *base_res;
78 void __iomem *base;
79 struct clk *clk;
80
81 struct clk *disp1_clk;
82 struct clk *disp2_clk;
83 struct clk *hda_clk;
84 struct clk *hda2codec_clk;
85 struct clk *hda2hdmi_clk;
86
87#ifdef CONFIG_SWITCH
88 struct switch_dev hpd_switch;
89#endif
90
91 spinlock_t suspend_lock;
92 bool suspended;
93 bool eld_retrieved;
94 bool clk_enabled;
95 unsigned audio_freq;
96 unsigned audio_source;
97
98 bool dvi;
99};
100
101struct tegra_dc_hdmi_data *dc_hdmi;
102
103const struct fb_videomode tegra_dc_hdmi_supported_modes[] = {
104 /* 1280x720p 60hz: EIA/CEA-861-B Format 4 */
105 {
106 .xres = 1280,
107 .yres = 720,
108 .pixclock = KHZ2PICOS(74250),
109 .hsync_len = 40, /* h_sync_width */
110 .vsync_len = 5, /* v_sync_width */
111 .left_margin = 220, /* h_back_porch */
112 .upper_margin = 20, /* v_back_porch */
113 .right_margin = 110, /* h_front_porch */
114 .lower_margin = 5, /* v_front_porch */
115 .vmode = FB_VMODE_NONINTERLACED,
116 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
117 },
118
119 /* 1280x720p 60hz: EIA/CEA-861-B Format 4 (Stereo)*/
120 {
121 .xres = 1280,
122 .yres = 720,
123 .pixclock = KHZ2PICOS(74250),
124 .hsync_len = 40, /* h_sync_width */
125 .vsync_len = 5, /* v_sync_width */
126 .left_margin = 220, /* h_back_porch */
127 .upper_margin = 20, /* v_back_porch */
128 .right_margin = 110, /* h_front_porch */
129 .lower_margin = 5, /* v_front_porch */
130 .vmode = FB_VMODE_NONINTERLACED |
131#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
132 FB_VMODE_STEREO_FRAME_PACK,
133#else
134 FB_VMODE_STEREO_LEFT_RIGHT,
135#endif
136 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
137 },
138
139 /* 720x480p 59.94hz: EIA/CEA-861-B Formats 2 & 3 */
140 {
141 .xres = 720,
142 .yres = 480,
143 .pixclock = KHZ2PICOS(27000),
144 .hsync_len = 62, /* h_sync_width */
145 .vsync_len = 6, /* v_sync_width */
146 .left_margin = 60, /* h_back_porch */
147 .upper_margin = 30, /* v_back_porch */
148 .right_margin = 16, /* h_front_porch */
149 .lower_margin = 9, /* v_front_porch */
150 .vmode = FB_VMODE_NONINTERLACED,
151 .sync = 0,
152 },
153
154 /* 640x480p 60hz: EIA/CEA-861-B Format 1 */
155 {
156 .xres = 640,
157 .yres = 480,
158 .pixclock = KHZ2PICOS(25200),
159 .hsync_len = 96, /* h_sync_width */
160 .vsync_len = 2, /* v_sync_width */
161 .left_margin = 48, /* h_back_porch */
162 .upper_margin = 33, /* v_back_porch */
163 .right_margin = 16, /* h_front_porch */
164 .lower_margin = 10, /* v_front_porch */
165 .vmode = FB_VMODE_NONINTERLACED,
166 .sync = 0,
167 },
168
169 /* 720x576p 50hz EIA/CEA-861-B Formats 17 & 18 */
170 {
171 .xres = 720,
172 .yres = 576,
173 .pixclock = KHZ2PICOS(27000),
174 .hsync_len = 64, /* h_sync_width */
175 .vsync_len = 5, /* v_sync_width */
176 .left_margin = 68, /* h_back_porch */
177 .upper_margin = 39, /* v_back_porch */
178 .right_margin = 12, /* h_front_porch */
179 .lower_margin = 5, /* v_front_porch */
180 .vmode = FB_VMODE_NONINTERLACED,
181 .sync = 0,
182 },
183
184 /* 1920x1080p 23.98/24hz: EIA/CEA-861-B Format 32 (Stereo)*/
185 {
186 .xres = 1920,
187 .yres = 1080,
188 .pixclock = KHZ2PICOS(74250),
189 .hsync_len = 44, /* h_sync_width */
190 .vsync_len = 5, /* v_sync_width */
191 .left_margin = 148, /* h_back_porch */
192 .upper_margin = 36, /* v_back_porch */
193 .right_margin = 638, /* h_front_porch */
194 .lower_margin = 4, /* v_front_porch */
195 .vmode = FB_VMODE_NONINTERLACED |
196#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
197 FB_VMODE_STEREO_FRAME_PACK,
198#else
199 FB_VMODE_STEREO_LEFT_RIGHT,
200#endif
201 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
202 },
203
204 /* 1920x1080p 30Hz EIA/CEA-861-B Format 34 */
205 {
206 .xres = 1920,
207 .yres = 1080,
208 .pixclock = KHZ2PICOS(74250),
209 .hsync_len = 44, /* h_sync_width */
210 .vsync_len = 5, /* v_sync_width */
211 .left_margin = 148, /* h_back_porch */
212 .upper_margin = 36, /* v_back_porch */
213 .right_margin = 88, /* h_front_porch */
214 .lower_margin = 4, /* v_front_porch */
215 .vmode = FB_VMODE_NONINTERLACED,
216 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
217 },
218 /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */
219 {
220 .xres = 1920,
221 .yres = 1080,
222 .pixclock = KHZ2PICOS(148500),
223 .hsync_len = 44, /* h_sync_width */
224 .vsync_len = 5, /* v_sync_width */
225 .left_margin = 148, /* h_back_porch */
226 .upper_margin = 36, /* v_back_porch */
227 .right_margin = 88, /* h_front_porch */
228 .lower_margin = 4, /* v_front_porch */
229 .vmode = FB_VMODE_NONINTERLACED,
230 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
231 },
232
233 /*
234 * Few VGA/SVGA modes to support monitors with lower
235 * resolutions or to support HDMI<->DVI connection
236 */
237
238 /* 640x480p 75hz */
239 {
240 .xres = 640,
241 .yres = 480,
242 .pixclock = KHZ2PICOS(31500),
243 .hsync_len = 96, /* h_sync_width */
244 .vsync_len = 2, /* v_sync_width */
245 .left_margin = 48, /* h_back_porch */
246 .upper_margin = 32, /* v_back_porch */
247 .right_margin = 16, /* h_front_porch */
248 .lower_margin = 1, /* v_front_porch */
249 .vmode = FB_VMODE_NONINTERLACED,
250 .sync = 0,
251 },
252 /* 720x400p 59hz */
253 {
254 .xres = 720,
255 .yres = 400,
256 .pixclock = KHZ2PICOS(35500),
257 .hsync_len = 72, /* h_sync_width */
258 .vsync_len = 3, /* v_sync_width */
259 .left_margin = 108, /* h_back_porch */
260 .upper_margin = 42, /* v_back_porch */
261 .right_margin = 36, /* h_front_porch */
262 .lower_margin = 1, /* v_front_porch */
263 .vmode = FB_VMODE_NONINTERLACED,
264 .sync = FB_SYNC_VERT_HIGH_ACT,
265 },
266 /* 800x600p 60hz */
267 {
268 .xres = 800,
269 .yres = 600,
270 .pixclock = KHZ2PICOS(40000),
271 .hsync_len = 128, /* h_sync_width */
272 .vsync_len = 4, /* v_sync_width */
273 .left_margin = 88, /* h_back_porch */
274 .upper_margin = 23, /* v_back_porch */
275 .right_margin = 40, /* h_front_porch */
276 .lower_margin = 1, /* v_front_porch */
277 .vmode = FB_VMODE_NONINTERLACED,
278 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
279 },
280 /* 800x600p 75hz */
281 {
282 .xres = 800,
283 .yres = 600,
284 .pixclock = KHZ2PICOS(49500),
285 .hsync_len = 80, /* h_sync_width */
286 .vsync_len = 2, /* v_sync_width */
287 .left_margin = 160, /* h_back_porch */
288 .upper_margin = 21, /* v_back_porch */
289 .right_margin = 16, /* h_front_porch */
290 .lower_margin = 1, /* v_front_porch */
291 .vmode = FB_VMODE_NONINTERLACED,
292 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
293 },
294 /* 1024x768p 60hz */
295 {
296 .xres = 1024,
297 .yres = 768,
298 .pixclock = KHZ2PICOS(65000),
299 .hsync_len = 136, /* h_sync_width */
300 .vsync_len = 6, /* v_sync_width */
301 .left_margin = 160, /* h_back_porch */
302 .upper_margin = 29, /* v_back_porch */
303 .right_margin = 24, /* h_front_porch */
304 .lower_margin = 3, /* v_front_porch */
305 .vmode = FB_VMODE_NONINTERLACED,
306 .sync = 0,
307 },
308 /* 1024x768p 75hz */
309 {
310 .xres = 1024,
311 .yres = 768,
312 .pixclock = KHZ2PICOS(78800),
313 .hsync_len = 96, /* h_sync_width */
314 .vsync_len = 3, /* v_sync_width */
315 .left_margin = 176, /* h_back_porch */
316 .upper_margin = 28, /* v_back_porch */
317 .right_margin = 16, /* h_front_porch */
318 .lower_margin = 1, /* v_front_porch */
319 .vmode = FB_VMODE_NONINTERLACED,
320 .sync = 0,
321 },
322 /* 1152x864p 75hz */
323 {
324 .xres = 1152,
325 .yres = 864,
326 .pixclock = KHZ2PICOS(108000),
327 .hsync_len = 128, /* h_sync_width */
328 .vsync_len = 3, /* v_sync_width */
329 .left_margin = 256, /* h_back_porch */
330 .upper_margin = 32, /* v_back_porch */
331 .right_margin = 64, /* h_front_porch */
332 .lower_margin = 1, /* v_front_porch */
333 .vmode = FB_VMODE_NONINTERLACED,
334 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
335 },
336 /* 1280x800p 60hz */
337 {
338 .xres = 1280,
339 .yres = 800,
340 .pixclock = KHZ2PICOS(83460),
341 .hsync_len = 136, /* h_sync_width */
342 .vsync_len = 3, /* v_sync_width */
343 .left_margin = 200, /* h_back_porch */
344 .upper_margin = 24, /* v_back_porch */
345 .right_margin = 64, /* h_front_porch */
346 .lower_margin = 1, /* v_front_porch */
347 .vmode = FB_VMODE_NONINTERLACED,
348 .sync = FB_SYNC_VERT_HIGH_ACT,
349 },
350 /* 1280x960p 60hz */
351 {
352 .xres = 1280,
353 .yres = 960,
354 .pixclock = KHZ2PICOS(108000),
355 .hsync_len = 136, /* h_sync_width */
356 .vsync_len = 3, /* v_sync_width */
357 .left_margin = 216, /* h_back_porch */
358 .upper_margin = 30, /* v_back_porch */
359 .right_margin = 80, /* h_front_porch */
360 .lower_margin = 1, /* v_front_porch */
361 .vmode = FB_VMODE_NONINTERLACED,
362 .sync = FB_SYNC_VERT_HIGH_ACT,
363 },
364 /* 1280x1024p 60hz */
365 {
366 .xres = 1280,
367 .yres = 1024,
368 .pixclock = KHZ2PICOS(108000),
369 .hsync_len = 112, /* h_sync_width */
370 .vsync_len = 3, /* v_sync_width */
371 .left_margin = 248, /* h_back_porch */
372 .upper_margin = 38, /* v_back_porch */
373 .right_margin = 48, /* h_front_porch */
374 .lower_margin = 1, /* v_front_porch */
375 .vmode = FB_VMODE_NONINTERLACED,
376 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
377 },
378 /* 1280x1024p 75hz */
379 {
380 .xres = 1280,
381 .yres = 1024,
382 .pixclock = KHZ2PICOS(135000),
383 .hsync_len = 144, /* h_sync_width */
384 .vsync_len = 3, /* v_sync_width */
385 .left_margin = 248, /* h_back_porch */
386 .upper_margin = 38, /* v_back_porch */
387 .right_margin = 16, /* h_front_porch */
388 .lower_margin = 1, /* v_front_porch */
389 .vmode = FB_VMODE_NONINTERLACED,
390 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
391 },
392 /* 1368x768p 60hz */
393 {
394 .xres = 1368,
395 .yres = 768,
396 .pixclock = KHZ2PICOS(85860),
397 .hsync_len = 144, /* h_sync_width */
398 .vsync_len = 3, /* v_sync_width */
399 .left_margin = 216, /* h_back_porch */
400 .upper_margin = 23, /* v_back_porch */
401 .right_margin = 72, /* h_front_porch */
402 .lower_margin = 1, /* v_front_porch */
403 .vmode = FB_VMODE_NONINTERLACED,
404 .sync = FB_SYNC_VERT_HIGH_ACT,
405 },
406 /* 1440x900p 60hz */
407 {
408 .xres = 1440,
409 .yres = 900,
410 .pixclock = KHZ2PICOS(106470),
411 .hsync_len = 152, /* h_sync_width */
412 .vsync_len = 3, /* v_sync_width */
413 .left_margin = 232, /* h_back_porch */
414 .upper_margin = 28, /* v_back_porch */
415 .right_margin = 80, /* h_front_porch */
416 .lower_margin = 1, /* v_front_porch */
417 .vmode = FB_VMODE_NONINTERLACED,
418 .sync = FB_SYNC_VERT_HIGH_ACT,
419 },
420 /* 1600x1200p 60hz */
421 {
422 .xres = 1600,
423 .yres = 1200,
424 .pixclock = KHZ2PICOS(162000),
425 .hsync_len = 192, /* h_sync_width */
426 .vsync_len = 3, /* v_sync_width */
427 .left_margin = 304, /* h_back_porch */
428 .upper_margin = 46, /* v_back_porch */
429 .right_margin = 64, /* h_front_porch */
430 .lower_margin = 1, /* v_front_porch */
431 .vmode = FB_VMODE_NONINTERLACED,
432 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
433 },
434 /* 1600x1200p 75hz */
435 {
436 .xres = 1600,
437 .yres = 1200,
438 .pixclock = KHZ2PICOS(202500),
439 .hsync_len = 192, /* h_sync_width */
440 .vsync_len = 3, /* v_sync_width */
441 .left_margin = 304, /* h_back_porch */
442 .upper_margin = 46, /* v_back_porch */
443 .right_margin = 64, /* h_front_porch */
444 .lower_margin = 1, /* v_front_porch */
445 .vmode = FB_VMODE_NONINTERLACED,
446 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
447 },
448 /* 1680x1050p 59.94/60hz */
449 {
450 .xres = 1680,
451 .yres = 1050,
452 .pixclock = KHZ2PICOS(147140),
453 .hsync_len = 184, /* h_sync_width */
454 .vsync_len = 3, /* v_sync_width */
455 .left_margin = 288, /* h_back_porch */
456 .upper_margin = 33, /* v_back_porch */
457 .right_margin = 104, /* h_front_porch */
458 .lower_margin = 1, /* v_front_porch */
459 .vmode = FB_VMODE_NONINTERLACED,
460 .sync = FB_SYNC_VERT_HIGH_ACT,
461 },
462};
463
464/* CVT timing representation of VESA modes*/
465const struct fb_videomode tegra_dc_hdmi_supported_cvt_modes[] = {
466
467 /* 640x480p 60hz */
468 {
469 .refresh = 60,
470 .xres = 640,
471 .yres = 480,
472 .pixclock = KHZ2PICOS(23750),
473 .hsync_len = 64, /* h_sync_width */
474 .vsync_len = 4, /* v_sync_width */
475 .left_margin = 80, /* h_back_porch */
476 .upper_margin = 17, /* v_back_porch */
477 .right_margin = 16, /* h_front_porch */
478 .lower_margin = 3, /* v_front_porch */
479 .vmode = FB_VMODE_NONINTERLACED,
480 .sync = FB_SYNC_VERT_HIGH_ACT,
481 },
482 /* 640x480p 75hz */
483 {
484 .refresh = 75,
485 .xres = 640,
486 .yres = 480,
487 .pixclock = KHZ2PICOS(30750),
488 .hsync_len = 64, /* h_sync_width */
489 .vsync_len = 4, /* v_sync_width */
490 .left_margin = 88, /* h_back_porch */
491 .upper_margin = 21, /* v_back_porch */
492 .right_margin = 24, /* h_front_porch */
493 .lower_margin = 3, /* v_front_porch */
494 .vmode = FB_VMODE_NONINTERLACED,
495 .sync = FB_SYNC_VERT_HIGH_ACT,
496 },
497 /* 720x400p 59hz */
498 {
499 .refresh = 59,
500 .xres = 720,
501 .yres = 400,
502 .pixclock = KHZ2PICOS(22000),
503 .hsync_len = 64, /* h_sync_width */
504 .vsync_len = 10, /* v_sync_width */
505 .left_margin = 88, /* h_back_porch */
506 .upper_margin = 14, /* v_back_porch */
507 .right_margin = 24, /* h_front_porch */
508 .lower_margin = 3, /* v_front_porch */
509 .vmode = FB_VMODE_NONINTERLACED,
510 .sync = FB_SYNC_VERT_HIGH_ACT,
511 },
512 /* 800x600p 60hz */
513 {
514 .refresh = 60,
515 .xres = 800,
516 .yres = 600,
517 .pixclock = KHZ2PICOS(38250),
518 .hsync_len = 80, /* h_sync_width */
519 .vsync_len = 4, /* v_sync_width */
520 .left_margin = 112, /* h_back_porch */
521 .upper_margin = 21, /* v_back_porch */
522 .right_margin = 32, /* h_front_porch */
523 .lower_margin = 3, /* v_front_porch */
524 .vmode = FB_VMODE_NONINTERLACED,
525 .sync = FB_SYNC_VERT_HIGH_ACT,
526 },
527 /* 800x600p 75hz */
528 {
529 .refresh = 75,
530 .xres = 800,
531 .yres = 600,
532 .pixclock = KHZ2PICOS(49000),
533 .hsync_len = 80, /* h_sync_width */
534 .vsync_len = 4, /* v_sync_width */
535 .left_margin = 120, /* h_back_porch */
536 .upper_margin = 26, /* v_back_porch */
537 .right_margin = 40, /* h_front_porch */
538 .lower_margin = 3, /* v_front_porch */
539 .vmode = FB_VMODE_NONINTERLACED,
540 .sync = FB_SYNC_VERT_HIGH_ACT,
541 },
542 /* 1024x768p 60hz */
543 {
544 .refresh = 60,
545 .xres = 1024,
546 .yres = 768,
547 .pixclock = KHZ2PICOS(63500),
548 .hsync_len = 104, /* h_sync_width */
549 .vsync_len = 4, /* v_sync_width */
550 .left_margin = 152, /* h_back_porch */
551 .upper_margin = 27, /* v_back_porch */
552 .right_margin = 48, /* h_front_porch */
553 .lower_margin = 3, /* v_front_porch */
554 .vmode = FB_VMODE_NONINTERLACED,
555 .sync = FB_SYNC_VERT_HIGH_ACT,
556 },
557 /* 1024x768p 75hz */
558 {
559 .refresh = 75,
560 .xres = 1024,
561 .yres = 768,
562 .pixclock = KHZ2PICOS(82000),
563 .hsync_len = 104, /* h_sync_width */
564 .vsync_len = 4, /* v_sync_width */
565 .left_margin = 168, /* h_back_porch */
566 .upper_margin = 34, /* v_back_porch */
567 .right_margin = 64, /* h_front_porch */
568 .lower_margin = 3, /* v_front_porch */
569 .vmode = FB_VMODE_NONINTERLACED,
570 .sync = FB_SYNC_VERT_HIGH_ACT,
571 },
572 /* 1152x864p 75hz */
573 {
574 .refresh = 75,
575 .xres = 1152,
576 .yres = 864,
577 .pixclock = KHZ2PICOS(104500),
578 .hsync_len = 120, /* h_sync_width */
579 .vsync_len = 10, /* v_sync_width */
580 .left_margin = 192, /* h_back_porch */
581 .upper_margin = 38, /* v_back_porch */
582 .right_margin = 72, /* h_front_porch */
583 .lower_margin = 3, /* v_front_porch */
584 .vmode = FB_VMODE_NONINTERLACED,
585 .sync = FB_SYNC_VERT_HIGH_ACT,
586 },
587 /* 1280x800p 60hz */
588 {
589 .refresh = 60,
590 .xres = 1280,
591 .yres = 800,
592 .pixclock = KHZ2PICOS(83500),
593 .hsync_len = 128, /* h_sync_width */
594 .vsync_len = 6, /* v_sync_width */
595 .left_margin = 200, /* h_back_porch */
596 .upper_margin = 28, /* v_back_porch */
597 .right_margin = 72, /* h_front_porch */
598 .lower_margin = 3, /* v_front_porch */
599 .vmode = FB_VMODE_NONINTERLACED,
600 .sync = FB_SYNC_VERT_HIGH_ACT,
601 },
602 /* 1280x960p 60hz */
603 {
604 .refresh = 60,
605 .xres = 1280,
606 .yres = 960,
607 .pixclock = KHZ2PICOS(101250),
608 .hsync_len = 128, /* h_sync_width */
609 .vsync_len = 4, /* v_sync_width */
610 .left_margin = 208, /* h_back_porch */
611 .upper_margin = 33, /* v_back_porch */
612 .right_margin = 80, /* h_front_porch */
613 .lower_margin = 3, /* v_front_porch */
614 .vmode = FB_VMODE_NONINTERLACED,
615 .sync = FB_SYNC_VERT_HIGH_ACT,
616 },
617 /* 1280x1024p 60hz */
618 {
619 .refresh = 60,
620 .xres = 1280,
621 .yres = 1024,
622 .pixclock = KHZ2PICOS(109000),
623 .hsync_len = 136, /* h_sync_width */
624 .vsync_len = 7, /* v_sync_width */
625 .left_margin = 216, /* h_back_porch */
626 .upper_margin = 36, /* v_back_porch */
627 .right_margin = 80, /* h_front_porch */
628 .lower_margin = 3, /* v_front_porch */
629 .vmode = FB_VMODE_NONINTERLACED,
630 .sync = FB_SYNC_VERT_HIGH_ACT,
631 },
632
633 /* 1280x1024p 75hz */
634 {
635 .refresh = 75,
636 .xres = 1280,
637 .yres = 1024,
638 .pixclock = KHZ2PICOS(138750),
639 .hsync_len = 136, /* h_sync_width */
640 .vsync_len = 7, /* v_sync_width */
641 .left_margin = 224, /* h_back_porch */
642 .upper_margin = 45, /* v_back_porch */
643 .right_margin = 88, /* h_front_porch */
644 .lower_margin = 3, /* v_front_porch */
645 .vmode = FB_VMODE_NONINTERLACED,
646 .sync = FB_SYNC_VERT_HIGH_ACT,
647 },
648 /* 1368x768p 60hz */
649 {
650 .refresh = 60,
651 .xres = 1368,
652 .yres = 768,
653 .pixclock = KHZ2PICOS(85250),
654 .hsync_len = 136, /* h_sync_width */
655 .vsync_len = 10, /* v_sync_width */
656 .left_margin = 208, /* h_back_porch */
657 .upper_margin = 27, /* v_back_porch */
658 .right_margin = 72, /* h_front_porch */
659 .lower_margin = 3, /* v_front_porch */
660 .vmode = FB_VMODE_NONINTERLACED,
661 .sync = FB_SYNC_VERT_HIGH_ACT,
662 },
663 /* 1440x900p 60hz */
664 {
665 .refresh = 60,
666 .xres = 1440,
667 .yres = 900,
668 .pixclock = KHZ2PICOS(106500),
669 .hsync_len = 152, /* h_sync_width */
670 .vsync_len = 6, /* v_sync_width */
671 .left_margin = 232, /* h_back_porch */
672 .upper_margin = 31, /* v_back_porch */
673 .right_margin = 80, /* h_front_porch */
674 .lower_margin = 3, /* v_front_porch */
675 .vmode = FB_VMODE_NONINTERLACED,
676 .sync = FB_SYNC_VERT_HIGH_ACT,
677 },
678 /* 1600x1200p 60hz */
679 {
680 .refresh = 60,
681 .xres = 1600,
682 .yres = 1200,
683 .pixclock = KHZ2PICOS(161000),
684 .hsync_len = 168, /* h_sync_width */
685 .vsync_len = 4, /* v_sync_width */
686 .left_margin = 280, /* h_back_porch */
687 .upper_margin = 42, /* v_back_porch */
688 .right_margin = 112, /* h_front_porch */
689 .lower_margin = 3, /* v_front_porch */
690 .vmode = FB_VMODE_NONINTERLACED,
691 .sync = FB_SYNC_VERT_HIGH_ACT,
692 },
693 /* 1600x1200p 75hz */
694 {
695 .refresh = 75,
696 .xres = 1600,
697 .yres = 1200,
698 .pixclock = KHZ2PICOS(204750),
699 .hsync_len = 168, /* h_sync_width */
700 .vsync_len = 4, /* v_sync_width */
701 .left_margin = 288, /* h_back_porch */
702 .upper_margin = 52, /* v_back_porch */
703 .right_margin = 120, /* h_front_porch */
704 .lower_margin = 3, /* v_front_porch */
705 .vmode = FB_VMODE_NONINTERLACED,
706 .sync = FB_SYNC_VERT_HIGH_ACT,
707 },
708 /* 1680x1050p 59.94/60hz */
709 {
710 .refresh = 60,
711 .xres = 1680,
712 .yres = 1050,
713 .pixclock = KHZ2PICOS(140000),
714 .hsync_len = 168, /* h_sync_width */
715 .vsync_len = 10, /* v_sync_width */
716 .left_margin = 272, /* h_back_porch */
717 .upper_margin = 36, /* v_back_porch */
718 .right_margin = 104, /* h_front_porch */
719 .lower_margin = 3, /* v_front_porch */
720 .vmode = FB_VMODE_NONINTERLACED,
721 .sync = FB_SYNC_VERT_HIGH_ACT,
722 },
723};
724
725/* table of electrical settings, must be in acending order. */
726struct tdms_config {
727 int pclk;
728 u32 pll0;
729 u32 pll1;
730 u32 pe_current; /* pre-emphasis */
731 u32 drive_current;
732};
733
734#ifndef CONFIG_ARCH_TEGRA_2x_SOC
735const struct tdms_config tdms_config[] = {
736 { /* 480p modes */
737 .pclk = 27000000,
738 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | SOR_PLL_RESISTORSEL |
739 SOR_PLL_VCOCAP(0) | SOR_PLL_TX_REG_LOAD(0),
740 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
741 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
742 PE_CURRENT1(PE_CURRENT_0_0_mA) |
743 PE_CURRENT2(PE_CURRENT_0_0_mA) |
744 PE_CURRENT3(PE_CURRENT_0_0_mA),
745 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
746 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
747 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
748 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
749 },
750 { /* 720p modes */
751 .pclk = 74250000,
752 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | SOR_PLL_RESISTORSEL |
753 SOR_PLL_VCOCAP(1) | SOR_PLL_TX_REG_LOAD(0),
754 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
755 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
756 PE_CURRENT1(PE_CURRENT_5_0_mA) |
757 PE_CURRENT2(PE_CURRENT_5_0_mA) |
758 PE_CURRENT3(PE_CURRENT_5_0_mA),
759 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
760 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
761 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
762 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
763 },
764 { /* 1080p modes */
765 .pclk = INT_MAX,
766 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | SOR_PLL_RESISTORSEL |
767 SOR_PLL_VCOCAP(3) | SOR_PLL_TX_REG_LOAD(0),
768 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
769 .pe_current = PE_CURRENT0(PE_CURRENT_5_0_mA) |
770 PE_CURRENT1(PE_CURRENT_5_0_mA) |
771 PE_CURRENT2(PE_CURRENT_5_0_mA) |
772 PE_CURRENT3(PE_CURRENT_5_0_mA),
773 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_5_250_mA) |
774 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_5_250_mA) |
775 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_5_250_mA) |
776 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_5_250_mA),
777 },
778};
779#else /* CONFIG_ARCH_TEGRA_2x_SOC */
780const struct tdms_config tdms_config[] = {
781 { /* 480p modes */
782 .pclk = 27000000,
783 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | SOR_PLL_RESISTORSEL |
784 SOR_PLL_VCOCAP(0) | SOR_PLL_TX_REG_LOAD(3),
785 .pll1 = SOR_PLL_TMDS_TERM_ENABLE,
786 .pe_current = PE_CURRENT0(PE_CURRENT_0_0_mA) |
787 PE_CURRENT1(PE_CURRENT_0_0_mA) |
788 PE_CURRENT2(PE_CURRENT_0_0_mA) |
789 PE_CURRENT3(PE_CURRENT_0_0_mA),
790 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
791 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
792 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
793 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
794 },
795 { /* 720p modes */
796 .pclk = 74250000,
797 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | SOR_PLL_RESISTORSEL |
798 SOR_PLL_VCOCAP(1) | SOR_PLL_TX_REG_LOAD(3),
799 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
800 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
801 PE_CURRENT1(PE_CURRENT_6_0_mA) |
802 PE_CURRENT2(PE_CURRENT_6_0_mA) |
803 PE_CURRENT3(PE_CURRENT_6_0_mA),
804 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
805 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
806 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
807 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
808 },
809 { /* 1080p modes */
810 .pclk = INT_MAX,
811 .pll0 = SOR_PLL_BG_V17_S(3) | SOR_PLL_ICHPMP(1) | SOR_PLL_RESISTORSEL |
812 SOR_PLL_VCOCAP(1) | SOR_PLL_TX_REG_LOAD(3),
813 .pll1 = SOR_PLL_TMDS_TERM_ENABLE | SOR_PLL_PE_EN,
814 .pe_current = PE_CURRENT0(PE_CURRENT_6_0_mA) |
815 PE_CURRENT1(PE_CURRENT_6_0_mA) |
816 PE_CURRENT2(PE_CURRENT_6_0_mA) |
817 PE_CURRENT3(PE_CURRENT_6_0_mA),
818 .drive_current = DRIVE_CURRENT_LANE0(DRIVE_CURRENT_7_125_mA) |
819 DRIVE_CURRENT_LANE1(DRIVE_CURRENT_7_125_mA) |
820 DRIVE_CURRENT_LANE2(DRIVE_CURRENT_7_125_mA) |
821 DRIVE_CURRENT_LANE3(DRIVE_CURRENT_7_125_mA),
822 },
823};
824#endif
825
826struct tegra_hdmi_audio_config {
827 unsigned pix_clock;
828 unsigned n;
829 unsigned cts;
830 unsigned aval;
831};
832
833
834const struct tegra_hdmi_audio_config tegra_hdmi_audio_32k[] = {
835 {25200000, 4096, 25200, 24000},
836 {27000000, 4096, 27000, 24000},
837 {74250000, 4096, 74250, 24000},
838 {148500000, 4096, 148500, 24000},
839 {0, 0, 0},
840};
841
842const struct tegra_hdmi_audio_config tegra_hdmi_audio_44_1k[] = {
843 {25200000, 5880, 26250, 25000},
844 {27000000, 5880, 28125, 25000},
845 {74250000, 4704, 61875, 20000},
846 {148500000, 4704, 123750, 20000},
847 {0, 0, 0},
848};
849
850const struct tegra_hdmi_audio_config tegra_hdmi_audio_48k[] = {
851 {25200000, 6144, 25200, 24000},
852 {27000000, 6144, 27000, 24000},
853 {74250000, 6144, 74250, 24000},
854 {148500000, 6144, 148500, 24000},
855 {0, 0, 0},
856};
857
858const struct tegra_hdmi_audio_config tegra_hdmi_audio_88_2k[] = {
859 {25200000, 11760, 26250, 25000},
860 {27000000, 11760, 28125, 25000},
861 {74250000, 9408, 61875, 20000},
862 {148500000, 9408, 123750, 20000},
863 {0, 0, 0},
864};
865
866const struct tegra_hdmi_audio_config tegra_hdmi_audio_96k[] = {
867 {25200000, 12288, 25200, 24000},
868 {27000000, 12288, 27000, 24000},
869 {74250000, 12288, 74250, 24000},
870 {148500000, 12288, 148500, 24000},
871 {0, 0, 0},
872};
873
874const struct tegra_hdmi_audio_config tegra_hdmi_audio_176_4k[] = {
875 {25200000, 23520, 26250, 25000},
876 {27000000, 23520, 28125, 25000},
877 {74250000, 18816, 61875, 20000},
878 {148500000, 18816, 123750, 20000},
879 {0, 0, 0},
880};
881
882const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
883 {25200000, 24576, 25200, 24000},
884 {27000000, 24576, 27000, 24000},
885 {74250000, 24576, 74250, 24000},
886 {148500000, 24576, 148500, 24000},
887 {0, 0, 0},
888};
889
890static const struct tegra_hdmi_audio_config
891*tegra_hdmi_get_audio_config(unsigned audio_freq, unsigned pix_clock)
892{
893 const struct tegra_hdmi_audio_config *table;
894
895 switch (audio_freq) {
896 case AUDIO_FREQ_32K:
897 table = tegra_hdmi_audio_32k;
898 break;
899 case AUDIO_FREQ_44_1K:
900 table = tegra_hdmi_audio_44_1k;
901 break;
902 case AUDIO_FREQ_48K:
903 table = tegra_hdmi_audio_48k;
904 break;
905 case AUDIO_FREQ_88_2K:
906 table = tegra_hdmi_audio_88_2k;
907 break;
908 case AUDIO_FREQ_96K:
909 table = tegra_hdmi_audio_96k;
910 break;
911 case AUDIO_FREQ_176_4K:
912 table = tegra_hdmi_audio_176_4k;
913 break;
914 case AUDIO_FREQ_192K:
915 table = tegra_hdmi_audio_192k;
916 break;
917 default:
918 return NULL;
919 }
920
921 while (table->pix_clock) {
922 if (table->pix_clock == pix_clock)
923 return table;
924 table++;
925 }
926
927 return NULL;
928}
929
930
931unsigned long tegra_hdmi_readl(struct tegra_dc_hdmi_data *hdmi,
932 unsigned long reg)
933{
934 return readl(hdmi->base + reg * 4);
935}
936
937void tegra_hdmi_writel(struct tegra_dc_hdmi_data *hdmi,
938 unsigned long val, unsigned long reg)
939{
940 writel(val, hdmi->base + reg * 4);
941}
942
943static inline void tegra_hdmi_clrsetbits(struct tegra_dc_hdmi_data *hdmi,
944 unsigned long reg, unsigned long clr,
945 unsigned long set)
946{
947 unsigned long val = tegra_hdmi_readl(hdmi, reg);
948 val &= ~clr;
949 val |= set;
950 tegra_hdmi_writel(hdmi, val, reg);
951}
952
953#ifdef CONFIG_DEBUG_FS
954static int dbg_hdmi_show(struct seq_file *s, void *unused)
955{
956 struct tegra_dc_hdmi_data *hdmi = s->private;
957
958#define DUMP_REG(a) do { \
959 seq_printf(s, "%-32s\t%03x\t%08lx\n", \
960 #a, a, tegra_hdmi_readl(hdmi, a)); \
961 } while (0)
962
963 tegra_dc_io_start(hdmi->dc);
964 clk_enable(hdmi->clk);
965
966 DUMP_REG(HDMI_CTXSW);
967 DUMP_REG(HDMI_NV_PDISP_SOR_STATE0);
968 DUMP_REG(HDMI_NV_PDISP_SOR_STATE1);
969 DUMP_REG(HDMI_NV_PDISP_SOR_STATE2);
970 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_MSB);
971 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AN_LSB);
972 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_MSB);
973 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CN_LSB);
974 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_MSB);
975 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
976 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
977 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
978 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
979 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
980 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_MSB);
981 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
982 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CTRL);
983 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CMODE);
984 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB);
985 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
986 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
987 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
988 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
989 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_RI);
990 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_MSB);
991 DUMP_REG(HDMI_NV_PDISP_RG_HDCP_CS_LSB);
992 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU0);
993 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0);
994 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU1);
995 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_EMU2);
996 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
997 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS);
998 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER);
999 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW);
1000 DUMP_REG(HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH);
1001 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
1002 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS);
1003 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER);
1004 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW);
1005 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH);
1006 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW);
1007 DUMP_REG(HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH);
1008 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
1009 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_STATUS);
1010 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_HEADER);
1011 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW);
1012 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH);
1013 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW);
1014 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH);
1015 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW);
1016 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH);
1017 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW);
1018 DUMP_REG(HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH);
1019 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_CTRL);
1020 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW);
1021 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH);
1022 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
1023 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
1024 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW);
1025 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH);
1026 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW);
1027 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH);
1028 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW);
1029 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH);
1030 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW);
1031 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH);
1032 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW);
1033 DUMP_REG(HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH);
1034 DUMP_REG(HDMI_NV_PDISP_HDMI_CTRL);
1035 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT);
1036 DUMP_REG(HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
1037 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_CTRL);
1038 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_STATUS);
1039 DUMP_REG(HDMI_NV_PDISP_HDMI_GCP_SUBPACK);
1040 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1);
1041 DUMP_REG(HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2);
1042 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU0);
1043 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1);
1044 DUMP_REG(HDMI_NV_PDISP_HDMI_EMU1_RDATA);
1045 DUMP_REG(HDMI_NV_PDISP_HDMI_SPARE);
1046 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1);
1047 DUMP_REG(HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2);
1048 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_CTRL);
1049 DUMP_REG(HDMI_NV_PDISP_SOR_CAP);
1050 DUMP_REG(HDMI_NV_PDISP_SOR_PWR);
1051 DUMP_REG(HDMI_NV_PDISP_SOR_TEST);
1052 DUMP_REG(HDMI_NV_PDISP_SOR_PLL0);
1053 DUMP_REG(HDMI_NV_PDISP_SOR_PLL1);
1054 DUMP_REG(HDMI_NV_PDISP_SOR_PLL2);
1055 DUMP_REG(HDMI_NV_PDISP_SOR_CSTM);
1056 DUMP_REG(HDMI_NV_PDISP_SOR_LVDS);
1057 DUMP_REG(HDMI_NV_PDISP_SOR_CRCA);
1058 DUMP_REG(HDMI_NV_PDISP_SOR_CRCB);
1059 DUMP_REG(HDMI_NV_PDISP_SOR_BLANK);
1060 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_CTL);
1061 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST0);
1062 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST1);
1063 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST2);
1064 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST3);
1065 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST4);
1066 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST5);
1067 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST6);
1068 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST7);
1069 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST8);
1070 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INST9);
1071 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INSTA);
1072 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INSTB);
1073 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INSTC);
1074 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INSTD);
1075 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INSTE);
1076 DUMP_REG(HDMI_NV_PDISP_SOR_SEQ_INSTF);
1077 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA0);
1078 DUMP_REG(HDMI_NV_PDISP_SOR_VCRCA1);
1079 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA0);
1080 DUMP_REG(HDMI_NV_PDISP_SOR_CCRCA1);
1081 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA0);
1082 DUMP_REG(HDMI_NV_PDISP_SOR_EDATAA1);
1083 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA0);
1084 DUMP_REG(HDMI_NV_PDISP_SOR_COUNTA1);
1085 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA0);
1086 DUMP_REG(HDMI_NV_PDISP_SOR_DEBUGA1);
1087 DUMP_REG(HDMI_NV_PDISP_SOR_TRIG);
1088 DUMP_REG(HDMI_NV_PDISP_SOR_MSCHECK);
1089 DUMP_REG(HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
1090 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG0);
1091 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG1);
1092 DUMP_REG(HDMI_NV_PDISP_AUDIO_DEBUG2);
1093 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(0));
1094 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(1));
1095 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(2));
1096 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(3));
1097 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(4));
1098 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(5));
1099 DUMP_REG(HDMI_NV_PDISP_AUDIO_FS(6));
1100 DUMP_REG(HDMI_NV_PDISP_AUDIO_PULSE_WIDTH);
1101 DUMP_REG(HDMI_NV_PDISP_AUDIO_THRESHOLD);
1102 DUMP_REG(HDMI_NV_PDISP_AUDIO_CNTRL0);
1103 DUMP_REG(HDMI_NV_PDISP_AUDIO_N);
1104 DUMP_REG(HDMI_NV_PDISP_HDCPRIF_ROM_TIMING);
1105 DUMP_REG(HDMI_NV_PDISP_SOR_REFCLK);
1106 DUMP_REG(HDMI_NV_PDISP_CRC_CONTROL);
1107 DUMP_REG(HDMI_NV_PDISP_INPUT_CONTROL);
1108 DUMP_REG(HDMI_NV_PDISP_SCRATCH);
1109 DUMP_REG(HDMI_NV_PDISP_PE_CURRENT);
1110 DUMP_REG(HDMI_NV_PDISP_KEY_CTRL);
1111 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG0);
1112 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG1);
1113 DUMP_REG(HDMI_NV_PDISP_KEY_DEBUG2);
1114 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_0);
1115 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_1);
1116 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_2);
1117 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_3);
1118 DUMP_REG(HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
1119 DUMP_REG(HDMI_NV_PDISP_KEY_SKEY_INDEX);
1120#undef DUMP_REG
1121
1122 clk_disable(hdmi->clk);
1123 tegra_dc_io_end(hdmi->dc);
1124
1125 return 0;
1126}
1127
1128static int dbg_hdmi_open(struct inode *inode, struct file *file)
1129{
1130 return single_open(file, dbg_hdmi_show, inode->i_private);
1131}
1132
1133static const struct file_operations dbg_fops = {
1134 .open = dbg_hdmi_open,
1135 .read = seq_read,
1136 .llseek = seq_lseek,
1137 .release = single_release,
1138};
1139
1140static struct dentry *hdmidir;
1141
1142static void tegra_dc_hdmi_debug_create(struct tegra_dc_hdmi_data *hdmi)
1143{
1144 struct dentry *retval;
1145
1146 hdmidir = debugfs_create_dir("tegra_hdmi", NULL);
1147 if (!hdmidir)
1148 return;
1149 retval = debugfs_create_file("regs", S_IRUGO, hdmidir, hdmi,
1150 &dbg_fops);
1151 if (!retval)
1152 goto free_out;
1153 return;
1154free_out:
1155 debugfs_remove_recursive(hdmidir);
1156 hdmidir = NULL;
1157 return;
1158}
1159#else
1160static inline void tegra_dc_hdmi_debug_create(struct tegra_dc_hdmi_data *hdmi)
1161{ }
1162#endif
1163
1164#define PIXCLOCK_TOLERANCE 200
1165
1166static int tegra_dc_calc_clock_per_frame(const struct fb_videomode *mode)
1167{
1168 return (mode->left_margin + mode->xres +
1169 mode->right_margin + mode->hsync_len) *
1170 (mode->upper_margin + mode->yres +
1171 mode->lower_margin + mode->vsync_len);
1172}
1173static bool tegra_dc_hdmi_mode_equal(const struct fb_videomode *mode1,
1174 const struct fb_videomode *mode2)
1175{
1176 int clock_per_frame1 = tegra_dc_calc_clock_per_frame(mode1);
1177 int clock_per_frame2 = tegra_dc_calc_clock_per_frame(mode2);
1178
1179 /* allows up to 1Hz of pixclock difference */
1180 return (clock_per_frame1 == clock_per_frame2 &&
1181 mode1->xres == mode2->xres &&
1182 mode1->yres == mode2->yres &&
1183 mode1->vmode == mode2->vmode &&
1184 (mode1->pixclock == mode2->pixclock ||
1185 (abs(PICOS2KHZ(mode1->pixclock) -
1186 PICOS2KHZ(mode2->pixclock)) *
1187 1000 / clock_per_frame1 <= 1)));
1188}
1189
1190static bool tegra_dc_hdmi_valid_pixclock(const struct tegra_dc *dc,
1191 const struct fb_videomode *mode)
1192{
1193 unsigned max_pixclock = tegra_dc_get_out_max_pixclock(dc);
1194 if (max_pixclock) {
1195 /* this might look counter-intuitive,
1196 * but pixclock's unit is picos(not Khz)
1197 */
1198 return mode->pixclock >= max_pixclock;
1199 } else {
1200 return true;
1201 }
1202}
1203
1204static bool tegra_dc_cvt_mode_equal(const struct fb_videomode *mode1,
1205 const struct fb_videomode *mode2)
1206{
1207 return (mode1->xres == mode2->xres &&
1208 mode1->yres == mode2->yres &&
1209 mode1->refresh == mode2->refresh &&
1210 mode1->vmode == mode2->vmode);
1211}
1212
1213static bool tegra_dc_reload_mode(struct fb_videomode *mode)
1214{
1215 int i = 0;
1216 for (i = 0; i < ARRAY_SIZE(tegra_dc_hdmi_supported_cvt_modes); i++) {
1217 const struct fb_videomode *cvt_mode
1218 = &tegra_dc_hdmi_supported_cvt_modes[i];
1219 if (tegra_dc_cvt_mode_equal(cvt_mode, mode)) {
1220 memcpy(mode, cvt_mode, sizeof(*mode));
1221 return true;
1222 }
1223 }
1224 return false;
1225}
1226
1227
1228static bool tegra_dc_hdmi_mode_filter(const struct tegra_dc *dc,
1229 struct fb_videomode *mode)
1230{
1231 int i;
1232 int clock_per_frame;
1233
1234 if (!mode->pixclock)
1235 return false;
1236
1237#ifdef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
1238 if (PICOS2KHZ(mode->pixclock) > 74250)
1239 return false;
1240#endif
1241
1242 for (i = 0; i < ARRAY_SIZE(tegra_dc_hdmi_supported_modes); i++) {
1243 const struct fb_videomode *supported_mode
1244 = &tegra_dc_hdmi_supported_modes[i];
1245 if (tegra_dc_hdmi_mode_equal(supported_mode, mode) &&
1246 tegra_dc_hdmi_valid_pixclock(dc, supported_mode)) {
1247 if (mode->lower_margin == 1) {
1248 /* This might be the case for HDMI<->DVI
1249 * where std VESA representation will not
1250 * pass constraint V_FRONT_PORCH >=
1251 * V_REF_TO_SYNC + 1.So reload mode in
1252 * CVT timing standards.
1253 */
1254 if (!tegra_dc_reload_mode(mode))
1255 return false;
1256 }
1257 else
1258 memcpy(mode, supported_mode, sizeof(*mode));
1259
1260 mode->flag = FB_MODE_IS_DETAILED;
1261 clock_per_frame = tegra_dc_calc_clock_per_frame(mode);
1262 mode->refresh = (PICOS2KHZ(mode->pixclock) * 1000)
1263 / clock_per_frame;
1264 return true;
1265 }
1266 }
1267
1268 return false;
1269}
1270
1271
1272static bool tegra_dc_hdmi_hpd(struct tegra_dc *dc)
1273{
1274 int sense;
1275 int level;
1276
1277 level = gpio_get_value(dc->out->hotplug_gpio);
1278
1279 sense = dc->out->flags & TEGRA_DC_OUT_HOTPLUG_MASK;
1280
1281 return (sense == TEGRA_DC_OUT_HOTPLUG_HIGH && level) ||
1282 (sense == TEGRA_DC_OUT_HOTPLUG_LOW && !level);
1283}
1284
1285
1286void tegra_dc_hdmi_detect_config(struct tegra_dc *dc,
1287 struct fb_monspecs *specs)
1288{
1289 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1290
1291 /* monitors like to lie about these but they are still useful for
1292 * detecting aspect ratios
1293 */
1294 dc->out->h_size = specs->max_x * 1000;
1295 dc->out->v_size = specs->max_y * 1000;
1296
1297 hdmi->dvi = !(specs->misc & FB_MISC_HDMI);
1298
1299 tegra_fb_update_monspecs(dc->fb, specs, tegra_dc_hdmi_mode_filter);
1300#ifdef CONFIG_SWITCH
1301 hdmi->hpd_switch.state = 0;
1302 switch_set_state(&hdmi->hpd_switch, 1);
1303#endif
1304 dev_info(&dc->ndev->dev, "display detected\n");
1305
1306 dc->connected = true;
1307 tegra_dc_ext_process_hotplug(dc->ndev->id);
1308}
1309
1310/* This function is used to enable DC1 and HDMI for the purpose of testing. */
1311bool tegra_dc_hdmi_detect_test(struct tegra_dc *dc, unsigned char *edid_ptr)
1312{
1313 int err;
1314 struct fb_monspecs specs;
1315 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1316
1317 if (!hdmi || !edid_ptr) {
1318 dev_err(&dc->ndev->dev, "HDMI test failed to get arguments.\n");
1319 return false;
1320 }
1321
1322 err = tegra_edid_get_monspecs_test(hdmi->edid, &specs, edid_ptr);
1323 if (err < 0) {
1324 dev_err(&dc->ndev->dev, "error reading edid\n");
1325 goto fail;
1326 }
1327
1328 err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
1329 if (err < 0) {
1330 dev_err(&dc->ndev->dev, "error populating eld\n");
1331 goto fail;
1332 }
1333 hdmi->eld_retrieved = true;
1334
1335 tegra_dc_hdmi_detect_config(dc, &specs);
1336
1337 return true;
1338
1339fail:
1340 hdmi->eld_retrieved = false;
1341#ifdef CONFIG_SWITCH
1342 switch_set_state(&hdmi->hpd_switch, 0);
1343#endif
1344 tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
1345 return false;
1346}
1347EXPORT_SYMBOL(tegra_dc_hdmi_detect_test);
1348
1349static bool tegra_dc_hdmi_detect(struct tegra_dc *dc)
1350{
1351 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1352 struct fb_monspecs specs;
1353 int err;
1354
1355 if (!tegra_dc_hdmi_hpd(dc))
1356 goto fail;
1357
1358 err = tegra_edid_get_monspecs(hdmi->edid, &specs);
1359 if (err < 0) {
1360 dev_err(&dc->ndev->dev, "error reading edid\n");
1361 goto fail;
1362 }
1363
1364 err = tegra_edid_get_eld(hdmi->edid, &hdmi->eld);
1365 if (err < 0) {
1366 dev_err(&dc->ndev->dev, "error populating eld\n");
1367 goto fail;
1368 }
1369 hdmi->eld_retrieved = true;
1370
1371 tegra_dc_hdmi_detect_config(dc, &specs);
1372
1373 return true;
1374
1375fail:
1376 hdmi->eld_retrieved = false;
1377#ifdef CONFIG_SWITCH
1378 switch_set_state(&hdmi->hpd_switch, 0);
1379#endif
1380 tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
1381 return false;
1382}
1383
1384
1385static void tegra_dc_hdmi_detect_worker(struct work_struct *work)
1386{
1387 struct tegra_dc_hdmi_data *hdmi =
1388 container_of(to_delayed_work(work), struct tegra_dc_hdmi_data, work);
1389 struct tegra_dc *dc = hdmi->dc;
1390
1391 tegra_dc_enable(dc);
1392 msleep(5);
1393 if (!tegra_dc_hdmi_detect(dc)) {
1394 tegra_dc_disable(dc);
1395 tegra_fb_update_monspecs(dc->fb, NULL, NULL);
1396
1397 dc->connected = false;
1398 tegra_dc_ext_process_hotplug(dc->ndev->id);
1399 }
1400}
1401
1402static irqreturn_t tegra_dc_hdmi_irq(int irq, void *ptr)
1403{
1404 struct tegra_dc *dc = ptr;
1405 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1406 unsigned long flags;
1407
1408 spin_lock_irqsave(&hdmi->suspend_lock, flags);
1409 if (!hdmi->suspended) {
1410 __cancel_delayed_work(&hdmi->work);
1411 if (tegra_dc_hdmi_hpd(dc))
1412 queue_delayed_work(system_nrt_wq, &hdmi->work,
1413 msecs_to_jiffies(100));
1414 else
1415 queue_delayed_work(system_nrt_wq, &hdmi->work,
1416 msecs_to_jiffies(30));
1417 }
1418 spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
1419
1420 return IRQ_HANDLED;
1421}
1422
1423static void tegra_dc_hdmi_suspend(struct tegra_dc *dc)
1424{
1425 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1426 unsigned long flags;
1427
1428 tegra_nvhdcp_suspend(hdmi->nvhdcp);
1429 spin_lock_irqsave(&hdmi->suspend_lock, flags);
1430 hdmi->suspended = true;
1431 spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
1432}
1433
1434static void tegra_dc_hdmi_resume(struct tegra_dc *dc)
1435{
1436 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1437 unsigned long flags;
1438
1439 spin_lock_irqsave(&hdmi->suspend_lock, flags);
1440 hdmi->suspended = false;
1441
1442 if (tegra_dc_hdmi_hpd(dc))
1443 queue_delayed_work(system_nrt_wq, &hdmi->work,
1444 msecs_to_jiffies(100));
1445 else
1446 queue_delayed_work(system_nrt_wq, &hdmi->work,
1447 msecs_to_jiffies(30));
1448
1449 spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
1450 tegra_nvhdcp_resume(hdmi->nvhdcp);
1451}
1452
1453static ssize_t underscan_show(struct device *dev,
1454 struct device_attribute *attr, char *buf)
1455{
1456#ifdef CONFIG_SWITCH
1457 struct tegra_dc_hdmi_data *hdmi =
1458 container_of(dev_get_drvdata(dev), struct tegra_dc_hdmi_data, hpd_switch);
1459
1460 if (hdmi->edid)
1461 return sprintf(buf, "%d\n", tegra_edid_underscan_supported(hdmi->edid));
1462 else
1463 return 0;
1464#else
1465 return 0;
1466#endif
1467}
1468
1469static DEVICE_ATTR(underscan, S_IRUGO | S_IWUSR, underscan_show, NULL);
1470
1471static int tegra_dc_hdmi_init(struct tegra_dc *dc)
1472{
1473 struct tegra_dc_hdmi_data *hdmi;
1474 struct resource *res;
1475 struct resource *base_res;
1476 int ret;
1477 void __iomem *base;
1478 struct clk *clk = NULL;
1479 struct clk *disp1_clk = NULL;
1480 struct clk *disp2_clk = NULL;
1481 int err;
1482
1483 hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
1484 if (!hdmi)
1485 return -ENOMEM;
1486
1487 res = nvhost_get_resource_byname(dc->ndev, IORESOURCE_MEM, "hdmi_regs");
1488 if (!res) {
1489 dev_err(&dc->ndev->dev, "hdmi: no mem resource\n");
1490 err = -ENOENT;
1491 goto err_free_hdmi;
1492 }
1493
1494 base_res = request_mem_region(res->start, resource_size(res), dc->ndev->name);
1495 if (!base_res) {
1496 dev_err(&dc->ndev->dev, "hdmi: request_mem_region failed\n");
1497 err = -EBUSY;
1498 goto err_free_hdmi;
1499 }
1500
1501 base = ioremap(res->start, resource_size(res));
1502 if (!base) {
1503 dev_err(&dc->ndev->dev, "hdmi: registers can't be mapped\n");
1504 err = -EBUSY;
1505 goto err_release_resource_reg;
1506 }
1507
1508 clk = clk_get(&dc->ndev->dev, "hdmi");
1509 if (IS_ERR_OR_NULL(clk)) {
1510 dev_err(&dc->ndev->dev, "hdmi: can't get clock\n");
1511 err = -ENOENT;
1512 goto err_iounmap_reg;
1513 }
1514
1515 disp1_clk = clk_get_sys("tegradc.0", NULL);
1516 if (IS_ERR_OR_NULL(disp1_clk)) {
1517 dev_err(&dc->ndev->dev, "hdmi: can't disp1 clock\n");
1518 err = -ENOENT;
1519 goto err_put_clock;
1520 }
1521
1522 disp2_clk = clk_get_sys("tegradc.1", NULL);
1523 if (IS_ERR_OR_NULL(disp2_clk)) {
1524 dev_err(&dc->ndev->dev, "hdmi: can't disp2 clock\n");
1525 err = -ENOENT;
1526 goto err_put_clock;
1527 }
1528
1529#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1530 hdmi->hda_clk = clk_get_sys("tegra30-hda", "hda");
1531 if (IS_ERR_OR_NULL(hdmi->hda_clk)) {
1532 dev_err(&dc->ndev->dev, "hdmi: can't get hda clock\n");
1533 err = -ENOENT;
1534 goto err_put_clock;
1535 }
1536
1537 hdmi->hda2codec_clk = clk_get_sys("tegra30-hda", "hda2codec");
1538 if (IS_ERR_OR_NULL(hdmi->hda2codec_clk)) {
1539 dev_err(&dc->ndev->dev, "hdmi: can't get hda2codec clock\n");
1540 err = -ENOENT;
1541 goto err_put_clock;
1542 }
1543
1544 hdmi->hda2hdmi_clk = clk_get_sys("tegra30-hda", "hda2hdmi");
1545 if (IS_ERR_OR_NULL(hdmi->hda2hdmi_clk)) {
1546 dev_err(&dc->ndev->dev, "hdmi: can't get hda2hdmi clock\n");
1547 err = -ENOENT;
1548 goto err_put_clock;
1549 }
1550#endif
1551
1552 /* TODO: support non-hotplug */
1553 if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq,
1554 IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
1555 dev_name(&dc->ndev->dev), dc)) {
1556 dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed\n",
1557 gpio_to_irq(dc->out->hotplug_gpio));
1558 err = -EBUSY;
1559 goto err_put_clock;
1560 }
1561
1562 hdmi->edid = tegra_edid_create(dc->out->dcc_bus);
1563 if (IS_ERR_OR_NULL(hdmi->edid)) {
1564 dev_err(&dc->ndev->dev, "hdmi: can't create edid\n");
1565 err = PTR_ERR(hdmi->edid);
1566 goto err_free_irq;
1567 }
1568
1569#ifdef CONFIG_TEGRA_NVHDCP
1570 hdmi->nvhdcp = tegra_nvhdcp_create(hdmi, dc->ndev->id,
1571 dc->out->dcc_bus);
1572 if (IS_ERR_OR_NULL(hdmi->nvhdcp)) {
1573 dev_err(&dc->ndev->dev, "hdmi: can't create nvhdcp\n");
1574 err = PTR_ERR(hdmi->nvhdcp);
1575 goto err_edid_destroy;
1576 }
1577#else
1578 hdmi->nvhdcp = NULL;
1579#endif
1580
1581 INIT_DELAYED_WORK(&hdmi->work, tegra_dc_hdmi_detect_worker);
1582
1583 hdmi->dc = dc;
1584 hdmi->base = base;
1585 hdmi->base_res = base_res;
1586 hdmi->clk = clk;
1587 hdmi->disp1_clk = disp1_clk;
1588 hdmi->disp2_clk = disp2_clk;
1589 hdmi->suspended = false;
1590 hdmi->eld_retrieved= false;
1591 hdmi->clk_enabled = false;
1592 hdmi->audio_freq = 44100;
1593 hdmi->audio_source = AUTO;
1594 spin_lock_init(&hdmi->suspend_lock);
1595
1596#ifdef CONFIG_SWITCH
1597 hdmi->hpd_switch.name = "hdmi";
1598 ret = switch_dev_register(&hdmi->hpd_switch);
1599
1600 if (!ret)
1601 ret = device_create_file(hdmi->hpd_switch.dev,
1602 &dev_attr_underscan);
1603 BUG_ON(ret != 0);
1604#endif
1605
1606 dc->out->depth = 24;
1607
1608 tegra_dc_set_outdata(dc, hdmi);
1609
1610 dc_hdmi = hdmi;
1611 /* boards can select default content protection policy */
1612 if (dc->out->flags & TEGRA_DC_OUT_NVHDCP_POLICY_ON_DEMAND)
1613 tegra_nvhdcp_set_policy(hdmi->nvhdcp,
1614 TEGRA_NVHDCP_POLICY_ON_DEMAND);
1615 else
1616 tegra_nvhdcp_set_policy(hdmi->nvhdcp,
1617 TEGRA_NVHDCP_POLICY_ALWAYS_ON);
1618
1619 tegra_dc_hdmi_debug_create(hdmi);
1620
1621 return 0;
1622
1623err_edid_destroy:
1624 tegra_edid_destroy(hdmi->edid);
1625err_free_irq:
1626 free_irq(gpio_to_irq(dc->out->hotplug_gpio), dc);
1627err_put_clock:
1628#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1629 if (!IS_ERR_OR_NULL(hdmi->hda2hdmi_clk))
1630 clk_put(hdmi->hda2hdmi_clk);
1631 if (!IS_ERR_OR_NULL(hdmi->hda2codec_clk))
1632 clk_put(hdmi->hda2codec_clk);
1633 if (!IS_ERR_OR_NULL(hdmi->hda_clk))
1634 clk_put(hdmi->hda_clk);
1635#endif
1636 if (!IS_ERR_OR_NULL(disp2_clk))
1637 clk_put(disp2_clk);
1638 if (!IS_ERR_OR_NULL(disp1_clk))
1639 clk_put(disp1_clk);
1640 if (!IS_ERR_OR_NULL(clk))
1641 clk_put(clk);
1642err_iounmap_reg:
1643 iounmap(base);
1644err_release_resource_reg:
1645 release_resource(base_res);
1646err_free_hdmi:
1647 kfree(hdmi);
1648 return err;
1649}
1650
1651static void tegra_dc_hdmi_destroy(struct tegra_dc *dc)
1652{
1653 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1654
1655 free_irq(gpio_to_irq(dc->out->hotplug_gpio), dc);
1656 cancel_delayed_work_sync(&hdmi->work);
1657#ifdef CONFIG_SWITCH
1658 switch_dev_unregister(&hdmi->hpd_switch);
1659#endif
1660 iounmap(hdmi->base);
1661 release_resource(hdmi->base_res);
1662#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1663 clk_put(hdmi->hda2hdmi_clk);
1664 clk_put(hdmi->hda2codec_clk);
1665 clk_put(hdmi->hda_clk);
1666#endif
1667 clk_put(hdmi->clk);
1668 clk_put(hdmi->disp1_clk);
1669 clk_put(hdmi->disp2_clk);
1670 tegra_edid_destroy(hdmi->edid);
1671 tegra_nvhdcp_destroy(hdmi->nvhdcp);
1672
1673 kfree(hdmi);
1674
1675}
1676
1677static void tegra_dc_hdmi_setup_audio_fs_tables(struct tegra_dc *dc)
1678{
1679 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1680 int i;
1681 unsigned freqs[] = {
1682 32000,
1683 44100,
1684 48000,
1685 88200,
1686 96000,
1687 176400,
1688 192000,
1689 };
1690
1691 for (i = 0; i < ARRAY_SIZE(freqs); i++) {
1692 unsigned f = freqs[i];
1693 unsigned eight_half;
1694 unsigned delta;;
1695
1696 if (f > 96000)
1697 delta = 2;
1698 else if (f > 48000)
1699 delta = 6;
1700 else
1701 delta = 9;
1702
1703 eight_half = (8 * HDMI_AUDIOCLK_FREQ) / (f * 128);
1704 tegra_hdmi_writel(hdmi, AUDIO_FS_LOW(eight_half - delta) |
1705 AUDIO_FS_HIGH(eight_half + delta),
1706 HDMI_NV_PDISP_AUDIO_FS(i));
1707 }
1708}
1709
1710#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1711static void tegra_dc_hdmi_setup_eld_buff(struct tegra_dc *dc)
1712{
1713 int i;
1714 int j;
1715 u8 tmp;
1716
1717 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1718
1719 /* program ELD stuff */
1720 for (i = 0; i < HDMI_ELD_MONITOR_NAME_INDEX; i++) {
1721 switch (i) {
1722 case HDMI_ELD_VER_INDEX:
1723 tmp = (hdmi->eld.eld_ver << 3);
1724 tegra_hdmi_writel(hdmi, (i << 8) | tmp,
1725 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1726 break;
1727 case HDMI_ELD_BASELINE_LEN_INDEX:
1728 break;
1729 case HDMI_ELD_CEA_VER_MNL_INDEX:
1730 tmp = (hdmi->eld.cea_edid_ver << 5);
1731 tmp |= (hdmi->eld.mnl & 0x1f);
1732 tegra_hdmi_writel(hdmi, (i << 8) | tmp,
1733 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1734 break;
1735 case HDMI_ELD_SAD_CNT_CON_TYP_SAI_HDCP_INDEX:
1736 tmp = (hdmi->eld.sad_count << 4);
1737 tmp |= (hdmi->eld.conn_type & 0xC);
1738 tmp |= (hdmi->eld.support_ai & 0x2);
1739 tmp |= (hdmi->eld.support_hdcp & 0x1);
1740 tegra_hdmi_writel(hdmi, (i << 8) | tmp,
1741 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1742 break;
1743 case HDMI_ELD_AUD_SYNC_DELAY_INDEX:
1744 tegra_hdmi_writel(hdmi, (i << 8) | (hdmi->eld.aud_synch_delay),
1745 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1746 break;
1747 case HDMI_ELD_SPK_ALLOC_INDEX:
1748 tegra_hdmi_writel(hdmi, (i << 8) | (hdmi->eld.spk_alloc),
1749 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1750 break;
1751 case HDMI_ELD_PORT_ID_INDEX:
1752 for (j = 0; j < 8;j++) {
1753 tegra_hdmi_writel(hdmi, ((i +j) << 8) | (hdmi->eld.port_id[j]),
1754 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1755 }
1756 break;
1757 case HDMI_ELD_MANF_NAME_INDEX:
1758 for (j = 0; j < 2;j++) {
1759 tegra_hdmi_writel(hdmi, ((i +j) << 8) | (hdmi->eld.manufacture_id[j]),
1760 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1761 }
1762 break;
1763 case HDMI_ELD_PRODUCT_CODE_INDEX:
1764 for (j = 0; j < 2;j++) {
1765 tegra_hdmi_writel(hdmi, ((i +j) << 8) | (hdmi->eld.product_id[j]),
1766 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1767 }
1768 break;
1769 }
1770 }
1771 for (j = 0; j < hdmi->eld.mnl;j++) {
1772 tegra_hdmi_writel(hdmi, ((j + HDMI_ELD_MONITOR_NAME_INDEX) << 8) |
1773 (hdmi->eld.monitor_name[j]),
1774 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1775 }
1776 for (j = 0; j < hdmi->eld.sad_count;j++) {
1777 tegra_hdmi_writel(hdmi, ((j + HDMI_ELD_MONITOR_NAME_INDEX + hdmi->eld.mnl) << 8) |
1778 (hdmi->eld.sad[j]),
1779 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0);
1780 }
1781 /* set presence andvalid bit */
1782 tegra_hdmi_writel(hdmi, 3, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_0);
1783}
1784#endif
1785
1786static int tegra_dc_hdmi_setup_audio(struct tegra_dc *dc, unsigned audio_freq,
1787 unsigned audio_source)
1788{
1789 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1790 const struct tegra_hdmi_audio_config *config;
1791 unsigned long audio_n;
1792#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1793 unsigned long reg_addr = 0;
1794#endif
1795 unsigned a_source = AUDIO_CNTRL0_SOURCE_SELECT_AUTO;
1796
1797 if (HDA == audio_source)
1798 a_source = AUDIO_CNTRL0_SOURCE_SELECT_HDAL;
1799 else if (SPDIF == audio_source)
1800 a_source = AUDIO_CNTRL0_SOURCE_SELECT_SPDIF;
1801
1802#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1803 tegra_hdmi_writel(hdmi,a_source | AUDIO_CNTRL0_INJECT_NULLSMPL,
1804 HDMI_NV_PDISP_SOR_AUDIO_CNTRL0_0);
1805 tegra_hdmi_writel(hdmi,
1806 AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
1807 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0),
1808 HDMI_NV_PDISP_AUDIO_CNTRL0);
1809#else
1810 tegra_hdmi_writel(hdmi,
1811 AUDIO_CNTRL0_ERROR_TOLERANCE(6) |
1812 AUDIO_CNTRL0_FRAMES_PER_BLOCK(0xc0) |
1813 a_source,
1814 HDMI_NV_PDISP_AUDIO_CNTRL0);
1815#endif
1816 config = tegra_hdmi_get_audio_config(audio_freq, dc->mode.pclk);
1817 if (!config) {
1818 dev_err(&dc->ndev->dev,
1819 "hdmi: can't set audio to %d at %d pix_clock",
1820 audio_freq, dc->mode.pclk);
1821 return -EINVAL;
1822 }
1823
1824 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_HDMI_ACR_CTRL);
1825
1826 audio_n = AUDIO_N_RESETF | AUDIO_N_GENERATE_ALTERNALTE |
1827 AUDIO_N_VALUE(config->n - 1);
1828 tegra_hdmi_writel(hdmi, audio_n, HDMI_NV_PDISP_AUDIO_N);
1829
1830 tegra_hdmi_writel(hdmi, ACR_SUBPACK_N(config->n) | ACR_ENABLE,
1831 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH);
1832
1833 tegra_hdmi_writel(hdmi, ACR_SUBPACK_CTS(config->cts),
1834 HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW);
1835
1836 tegra_hdmi_writel(hdmi, SPARE_HW_CTS | SPARE_FORCE_SW_CTS |
1837 SPARE_CTS_RESET_VAL(1),
1838 HDMI_NV_PDISP_HDMI_SPARE);
1839
1840 audio_n &= ~AUDIO_N_RESETF;
1841 tegra_hdmi_writel(hdmi, audio_n, HDMI_NV_PDISP_AUDIO_N);
1842
1843#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1844 switch (audio_freq) {
1845 case AUDIO_FREQ_32K:
1846 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320_0;
1847 break;
1848 case AUDIO_FREQ_44_1K:
1849 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441_0;
1850 break;
1851 case AUDIO_FREQ_48K:
1852 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480_0;
1853 break;
1854 case AUDIO_FREQ_88_2K:
1855 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882_0;
1856 break;
1857 case AUDIO_FREQ_96K:
1858 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960_0;
1859 break;
1860 case AUDIO_FREQ_176_4K:
1861 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764_0;
1862 break;
1863 case AUDIO_FREQ_192K:
1864 reg_addr = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920_0;
1865 break;
1866 }
1867
1868 tegra_hdmi_writel(hdmi, config->aval, reg_addr);
1869#endif
1870 tegra_dc_hdmi_setup_audio_fs_tables(dc);
1871
1872 return 0;
1873}
1874
1875int tegra_hdmi_setup_audio_freq_source(unsigned audio_freq, unsigned audio_source)
1876{
1877 struct tegra_dc_hdmi_data *hdmi = dc_hdmi;
1878
1879 if (!hdmi)
1880 return -EAGAIN;
1881
1882 /* check for know freq */
1883 if (AUDIO_FREQ_32K == audio_freq ||
1884 AUDIO_FREQ_44_1K== audio_freq ||
1885 AUDIO_FREQ_48K== audio_freq ||
1886 AUDIO_FREQ_88_2K== audio_freq ||
1887 AUDIO_FREQ_96K== audio_freq ||
1888 AUDIO_FREQ_176_4K== audio_freq ||
1889 AUDIO_FREQ_192K== audio_freq) {
1890 /* If we can program HDMI, then proceed */
1891 if (hdmi->clk_enabled)
1892 tegra_dc_hdmi_setup_audio(hdmi->dc, audio_freq,audio_source);
1893
1894 /* Store it for using it in enable */
1895 hdmi->audio_freq = audio_freq;
1896 hdmi->audio_source = audio_source;
1897 }
1898 else
1899 return -EINVAL;
1900
1901 return 0;
1902}
1903EXPORT_SYMBOL(tegra_hdmi_setup_audio_freq_source);
1904
1905#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
1906int tegra_hdmi_setup_hda_presence()
1907{
1908 struct tegra_dc_hdmi_data *hdmi = dc_hdmi;
1909
1910 if (!hdmi)
1911 return -EAGAIN;
1912
1913 if (hdmi->clk_enabled && hdmi->eld_retrieved) {
1914 /* If HDA_PRESENCE is already set reset it */
1915 if (tegra_hdmi_readl(hdmi,
1916 HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_0))
1917 tegra_hdmi_writel(hdmi, 0,
1918 HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_0);
1919
1920 tegra_dc_hdmi_setup_eld_buff(hdmi->dc);
1921 }
1922 else
1923 return -ENODEV;
1924
1925 return 0;
1926}
1927EXPORT_SYMBOL(tegra_hdmi_setup_hda_presence);
1928#endif
1929
1930static void tegra_dc_hdmi_write_infopack(struct tegra_dc *dc, int header_reg,
1931 u8 type, u8 version, void *data, int len)
1932{
1933 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1934 u32 subpack[2]; /* extra byte for zero padding of subpack */
1935 int i;
1936 u8 csum;
1937
1938 /* first byte of data is the checksum */
1939 csum = type + version + len - 1;
1940 for (i = 1; i < len; i++)
1941 csum +=((u8 *)data)[i];
1942 ((u8 *)data)[0] = 0x100 - csum;
1943
1944 tegra_hdmi_writel(hdmi, INFOFRAME_HEADER_TYPE(type) |
1945 INFOFRAME_HEADER_VERSION(version) |
1946 INFOFRAME_HEADER_LEN(len - 1),
1947 header_reg);
1948
1949 /* The audio inforame only has one set of subpack registers. The hdmi
1950 * block pads the rest of the data as per the spec so we have to fixup
1951 * the length before filling in the subpacks.
1952 */
1953 if (header_reg == HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER)
1954 len = 6;
1955
1956 /* each subpack 7 bytes devided into:
1957 * subpack_low - bytes 0 - 3
1958 * subpack_high - bytes 4 - 6 (with byte 7 padded to 0x00)
1959 */
1960 for (i = 0; i < len; i++) {
1961 int subpack_idx = i % 7;
1962
1963 if (subpack_idx == 0)
1964 memset(subpack, 0x0, sizeof(subpack));
1965
1966 ((u8 *)subpack)[subpack_idx] = ((u8 *)data)[i];
1967
1968 if (subpack_idx == 6 || (i + 1 == len)) {
1969 int reg = header_reg + 1 + (i / 7) * 2;
1970
1971 tegra_hdmi_writel(hdmi, subpack[0], reg);
1972 tegra_hdmi_writel(hdmi, subpack[1], reg + 1);
1973 }
1974 }
1975}
1976
1977static void tegra_dc_hdmi_setup_avi_infoframe(struct tegra_dc *dc, bool dvi)
1978{
1979 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
1980 struct hdmi_avi_infoframe avi;
1981
1982 if (dvi) {
1983 tegra_hdmi_writel(hdmi, 0x0,
1984 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
1985 return;
1986 }
1987
1988 memset(&avi, 0x0, sizeof(avi));
1989
1990 avi.r = HDMI_AVI_R_SAME;
1991
1992 if (dc->mode.v_active == 480) {
1993 if (dc->mode.h_active == 640) {
1994 avi.m = HDMI_AVI_M_4_3;
1995 avi.vic = 1;
1996 } else {
1997 avi.m = HDMI_AVI_M_16_9;
1998 avi.vic = 3;
1999 }
2000 } else if (dc->mode.v_active == 576) {
2001 /* CEC modes 17 and 18 differ only by the pysical size of the
2002 * screen so we have to calculation the physical aspect
2003 * ratio. 4 * 10 / 3 is 13
2004 */
2005 if ((dc->out->h_size * 10) / dc->out->v_size > 14) {
2006 avi.m = HDMI_AVI_M_16_9;
2007 avi.vic = 18;
2008 } else {
2009 avi.m = HDMI_AVI_M_4_3;
2010 avi.vic = 17;
2011 }
2012 } else if (dc->mode.v_active == 720 ||
2013 (dc->mode.v_active == 1470 && dc->mode.stereo_mode)) {
2014 /* VIC for both 720p and 720p 3D mode */
2015 avi.m = HDMI_AVI_M_16_9;
2016 if (dc->mode.h_front_porch == 110)
2017 avi.vic = 4; /* 60 Hz */
2018 else
2019 avi.vic = 19; /* 50 Hz */
2020 } else if (dc->mode.v_active == 1080 ||
2021 (dc->mode.v_active == 2205 && dc->mode.stereo_mode)) {
2022 /* VIC for both 1080p and 1080p 3D mode */
2023 avi.m = HDMI_AVI_M_16_9;
2024 if (dc->mode.h_front_porch == 88)
2025 avi.vic = 16; /* 60 Hz */
2026 else if (dc->mode.h_front_porch == 528)
2027 avi.vic = 31; /* 50 Hz */
2028 else
2029 avi.vic = 32; /* 24 Hz */
2030 } else {
2031 avi.m = HDMI_AVI_M_16_9;
2032 avi.vic = 0;
2033 }
2034
2035
2036 tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
2037 HDMI_INFOFRAME_TYPE_AVI,
2038 HDMI_AVI_VERSION,
2039 &avi, sizeof(avi));
2040
2041 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
2042 HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL);
2043}
2044
2045static void tegra_dc_hdmi_setup_stereo_infoframe(struct tegra_dc *dc)
2046{
2047 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
2048 struct hdmi_stereo_infoframe stereo;
2049 u32 val;
2050
2051 if (!dc->mode.stereo_mode) {
2052 val = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
2053 val &= ~GENERIC_CTRL_ENABLE;
2054 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
2055 return;
2056 }
2057
2058 memset(&stereo, 0x0, sizeof(stereo));
2059
2060 stereo.regid0 = 0x03;
2061 stereo.regid1 = 0x0c;
2062 stereo.regid2 = 0x00;
2063 stereo.hdmi_video_format = 2; /* 3D_Structure present */
2064#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
2065 stereo._3d_structure = 0; /* frame packing */
2066#else
2067 stereo._3d_structure = 8; /* side-by-side (half) */
2068 stereo._3d_ext_data = 0; /* something which fits into 00XX bit req */
2069#endif
2070
2071 tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_GENERIC_HEADER,
2072 HDMI_INFOFRAME_TYPE_VENDOR,
2073 HDMI_VENDOR_VERSION,
2074 &stereo, 6);
2075
2076 val = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
2077 val |= GENERIC_CTRL_ENABLE;
2078
2079 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
2080}
2081
2082static void tegra_dc_hdmi_setup_audio_infoframe(struct tegra_dc *dc, bool dvi)
2083{
2084 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
2085 struct hdmi_audio_infoframe audio;
2086
2087 if (dvi) {
2088 tegra_hdmi_writel(hdmi, 0x0,
2089 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
2090 return;
2091 }
2092
2093 memset(&audio, 0x0, sizeof(audio));
2094
2095 audio.cc = HDMI_AUDIO_CC_2;
2096 tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER,
2097 HDMI_INFOFRAME_TYPE_AUDIO,
2098 HDMI_AUDIO_VERSION,
2099 &audio, sizeof(audio));
2100
2101 tegra_hdmi_writel(hdmi, INFOFRAME_CTRL_ENABLE,
2102 HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL);
2103}
2104
2105static void tegra_dc_hdmi_setup_tdms(struct tegra_dc_hdmi_data *hdmi,
2106 const struct tdms_config *tc)
2107{
2108 tegra_hdmi_writel(hdmi, tc->pll0, HDMI_NV_PDISP_SOR_PLL0);
2109 tegra_hdmi_writel(hdmi, tc->pll1, HDMI_NV_PDISP_SOR_PLL1);
2110
2111 tegra_hdmi_writel(hdmi, tc->pe_current, HDMI_NV_PDISP_PE_CURRENT);
2112
2113 tegra_hdmi_writel(hdmi,
2114 tc->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE,
2115 HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
2116}
2117
2118static void tegra_dc_hdmi_enable(struct tegra_dc *dc)
2119{
2120 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
2121 int pulse_start;
2122 int dispclk_div_8_2;
2123 int retries;
2124 int rekey;
2125 int err;
2126 unsigned long val;
2127 unsigned i;
2128 unsigned long oldrate;
2129
2130 /* enbale power, clocks, resets, etc. */
2131
2132 /* The upstream DC needs to be clocked for accesses to HDMI to not
2133 * hard lock the system. Because we don't know if HDMI is conencted
2134 * to disp1 or disp2 we need to enable both until we set the DC mux.
2135 */
2136 clk_enable(hdmi->disp1_clk);
2137 clk_enable(hdmi->disp2_clk);
2138
2139#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
2140 /* Enabling HDA clocks before asserting HDA PD and ELDV bits */
2141 clk_enable(hdmi->hda_clk);
2142 clk_enable(hdmi->hda2codec_clk);
2143 clk_enable(hdmi->hda2hdmi_clk);
2144#endif
2145
2146 /* back off multiplier before attaching to parent at new rate. */
2147 oldrate = clk_get_rate(hdmi->clk);
2148 clk_set_rate(hdmi->clk, oldrate / 2);
2149
2150 tegra_dc_setup_clk(dc, hdmi->clk);
2151 clk_set_rate(hdmi->clk, dc->mode.pclk);
2152
2153 clk_enable(hdmi->clk);
2154 tegra_periph_reset_assert(hdmi->clk);
2155 mdelay(1);
2156 tegra_periph_reset_deassert(hdmi->clk);
2157
2158 /* TODO: copy HDCP keys from KFUSE to HDMI */
2159
2160 /* Program display timing registers: handled by dc */
2161
2162 /* program HDMI registers and SOR sequencer */
2163
2164 tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS);
2165 tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
2166 DC_DISP_DISP_COLOR_CONTROL);
2167
2168 /* video_preamble uses h_pulse2 */
2169 pulse_start = dc->mode.h_ref_to_sync + dc->mode.h_sync_width +
2170 dc->mode.h_back_porch - 10;
2171 tegra_dc_writel(dc, H_PULSE_2_ENABLE, DC_DISP_DISP_SIGNAL_OPTIONS0);
2172 tegra_dc_writel(dc,
2173 PULSE_MODE_NORMAL |
2174 PULSE_POLARITY_HIGH |
2175 PULSE_QUAL_VACTIVE |
2176 PULSE_LAST_END_A,
2177 DC_DISP_H_PULSE2_CONTROL);
2178 tegra_dc_writel(dc, PULSE_START(pulse_start) | PULSE_END(pulse_start + 8),
2179 DC_DISP_H_PULSE2_POSITION_A);
2180
2181 tegra_hdmi_writel(hdmi,
2182 VSYNC_WINDOW_END(0x210) |
2183 VSYNC_WINDOW_START(0x200) |
2184 VSYNC_WINDOW_ENABLE,
2185 HDMI_NV_PDISP_HDMI_VSYNC_WINDOW);
2186
2187 tegra_hdmi_writel(hdmi,
2188 (dc->ndev->id ? HDMI_SRC_DISPLAYB : HDMI_SRC_DISPLAYA) |
2189 ARM_VIDEO_RANGE_LIMITED,
2190 HDMI_NV_PDISP_INPUT_CONTROL);
2191
2192 clk_disable(hdmi->disp1_clk);
2193 clk_disable(hdmi->disp2_clk);
2194
2195 dispclk_div_8_2 = clk_get_rate(hdmi->clk) / 1000000 * 4;
2196 tegra_hdmi_writel(hdmi,
2197 SOR_REFCLK_DIV_INT(dispclk_div_8_2 >> 2) |
2198 SOR_REFCLK_DIV_FRAC(dispclk_div_8_2),
2199 HDMI_NV_PDISP_SOR_REFCLK);
2200
2201 hdmi->clk_enabled = true;
2202
2203 if (!hdmi->dvi) {
2204 err = tegra_dc_hdmi_setup_audio(dc, hdmi->audio_freq,
2205 hdmi->audio_source);
2206
2207 if (err < 0)
2208 hdmi->dvi = true;
2209 }
2210
2211#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
2212 if (hdmi->eld_retrieved)
2213 tegra_dc_hdmi_setup_eld_buff(dc);
2214#endif
2215
2216 rekey = HDMI_REKEY_DEFAULT;
2217 val = HDMI_CTRL_REKEY(rekey);
2218 val |= HDMI_CTRL_MAX_AC_PACKET((dc->mode.h_sync_width +
2219 dc->mode.h_back_porch +
2220 dc->mode.h_front_porch -
2221 rekey - 18) / 32);
2222 if (!hdmi->dvi)
2223 val |= HDMI_CTRL_ENABLE;
2224 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_HDMI_CTRL);
2225
2226 if (hdmi->dvi)
2227 tegra_hdmi_writel(hdmi, 0x0,
2228 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
2229 else
2230 tegra_hdmi_writel(hdmi, GENERIC_CTRL_AUDIO,
2231 HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
2232
2233 tegra_dc_hdmi_setup_avi_infoframe(dc, hdmi->dvi);
2234 tegra_dc_hdmi_setup_audio_infoframe(dc, hdmi->dvi);
2235 tegra_dc_hdmi_setup_stereo_infoframe(dc);
2236
2237 /* TMDS CONFIG */
2238 for (i = 0; i < ARRAY_SIZE(tdms_config); i++) {
2239 if (dc->mode.pclk <= tdms_config[i].pclk) {
2240 tegra_dc_hdmi_setup_tdms(hdmi, &tdms_config[i]);
2241 break;
2242 }
2243 }
2244
2245 tegra_hdmi_writel(hdmi,
2246 SOR_SEQ_CTL_PU_PC(0) |
2247 SOR_SEQ_PU_PC_ALT(0) |
2248 SOR_SEQ_PD_PC(8) |
2249 SOR_SEQ_PD_PC_ALT(8),
2250 HDMI_NV_PDISP_SOR_SEQ_CTL);
2251
2252 val = SOR_SEQ_INST_WAIT_TIME(1) |
2253 SOR_SEQ_INST_WAIT_UNITS_VSYNC |
2254 SOR_SEQ_INST_HALT |
2255 SOR_SEQ_INST_PIN_A_LOW |
2256 SOR_SEQ_INST_PIN_B_LOW |
2257 SOR_SEQ_INST_DRIVE_PWM_OUT_LO;
2258
2259 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_SOR_SEQ_INST0);
2260 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_SOR_SEQ_INST8);
2261
2262 val = 0x1c800;
2263 val &= ~SOR_CSTM_ROTCLK(~0);
2264 val |= SOR_CSTM_ROTCLK(2);
2265 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_SOR_CSTM);
2266
2267
2268 tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);
2269 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
2270 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
2271
2272
2273 /* start SOR */
2274 tegra_hdmi_writel(hdmi,
2275 SOR_PWR_NORMAL_STATE_PU |
2276 SOR_PWR_NORMAL_START_NORMAL |
2277 SOR_PWR_SAFE_STATE_PD |
2278 SOR_PWR_SETTING_NEW_TRIGGER,
2279 HDMI_NV_PDISP_SOR_PWR);
2280 tegra_hdmi_writel(hdmi,
2281 SOR_PWR_NORMAL_STATE_PU |
2282 SOR_PWR_NORMAL_START_NORMAL |
2283 SOR_PWR_SAFE_STATE_PD |
2284 SOR_PWR_SETTING_NEW_DONE,
2285 HDMI_NV_PDISP_SOR_PWR);
2286
2287 retries = 1000;
2288 do {
2289 BUG_ON(--retries < 0);
2290 val = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_SOR_PWR);
2291 } while (val & SOR_PWR_SETTING_NEW_PENDING);
2292
2293 val = SOR_STATE_ASY_CRCMODE_COMPLETE |
2294 SOR_STATE_ASY_OWNER_HEAD0 |
2295 SOR_STATE_ASY_SUBOWNER_BOTH |
2296 SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A |
2297 SOR_STATE_ASY_DEPOL_POS;
2298
2299 if (dc->mode.flags & TEGRA_DC_MODE_FLAG_NEG_H_SYNC)
2300 val |= SOR_STATE_ASY_HSYNCPOL_NEG;
2301 else
2302 val |= SOR_STATE_ASY_HSYNCPOL_POS;
2303
2304 if (dc->mode.flags & TEGRA_DC_MODE_FLAG_NEG_V_SYNC)
2305 val |= SOR_STATE_ASY_VSYNCPOL_NEG;
2306 else
2307 val |= SOR_STATE_ASY_VSYNCPOL_POS;
2308
2309 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_SOR_STATE2);
2310
2311 val = SOR_STATE_ASY_HEAD_OPMODE_AWAKE | SOR_STATE_ASY_ORMODE_NORMAL;
2312 tegra_hdmi_writel(hdmi, val, HDMI_NV_PDISP_SOR_STATE1);
2313
2314 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
2315 tegra_hdmi_writel(hdmi, SOR_STATE_UPDATE, HDMI_NV_PDISP_SOR_STATE0);
2316 tegra_hdmi_writel(hdmi, val | SOR_STATE_ATTACHED,
2317 HDMI_NV_PDISP_SOR_STATE1);
2318 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_STATE0);
2319
2320 tegra_dc_writel(dc, HDMI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
2321
2322 tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
2323 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
2324 DC_CMD_DISPLAY_POWER_CONTROL);
2325
2326 tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
2327 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
2328 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
2329
2330 tegra_nvhdcp_set_plug(hdmi->nvhdcp, 1);
2331}
2332
2333static void tegra_dc_hdmi_disable(struct tegra_dc *dc)
2334{
2335 struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
2336
2337 tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
2338
2339#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
2340 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_0);
2341 /* sleep 1ms before disabling clocks to ensure HDA gets the interrupt */
2342 msleep(1);
2343 clk_disable(hdmi->hda2hdmi_clk);
2344 clk_disable(hdmi->hda2codec_clk);
2345 clk_disable(hdmi->hda_clk);
2346#endif
2347 tegra_periph_reset_assert(hdmi->clk);
2348 hdmi->clk_enabled = false;
2349 clk_disable(hdmi->clk);
2350 tegra_dvfs_set_rate(hdmi->clk, 0);
2351}
2352
2353struct tegra_dc_out_ops tegra_dc_hdmi_ops = {
2354 .init = tegra_dc_hdmi_init,
2355 .destroy = tegra_dc_hdmi_destroy,
2356 .enable = tegra_dc_hdmi_enable,
2357 .disable = tegra_dc_hdmi_disable,
2358 .detect = tegra_dc_hdmi_detect,
2359 .suspend = tegra_dc_hdmi_suspend,
2360 .resume = tegra_dc_hdmi_resume,
2361};
2362
2363struct tegra_dc_edid *tegra_dc_get_edid(struct tegra_dc *dc)
2364{
2365 struct tegra_dc_hdmi_data *hdmi;
2366
2367 /* TODO: Support EDID on non-HDMI devices */
2368 if (dc->out->type != TEGRA_DC_OUT_HDMI)
2369 return ERR_PTR(-ENODEV);
2370
2371 hdmi = tegra_dc_get_outdata(dc);
2372
2373 return tegra_edid_get_data(hdmi->edid);
2374}
2375EXPORT_SYMBOL(tegra_dc_get_edid);
2376
2377void tegra_dc_put_edid(struct tegra_dc_edid *edid)
2378{
2379 tegra_edid_put_data(edid);
2380}
2381EXPORT_SYMBOL(tegra_dc_put_edid);
diff --git a/drivers/video/tegra/dc/hdmi.h b/drivers/video/tegra/dc/hdmi.h
new file mode 100644
index 00000000000..702ab16e87f
--- /dev/null
+++ b/drivers/video/tegra/dc/hdmi.h
@@ -0,0 +1,222 @@
1/*
2 * drivers/video/tegra/dc/hdmi.h
3 *
4 * non-tegra specific HDMI declarations
5 *
6 * Copyright (C) 2010 Google, Inc.
7 * Author: Erik Gilling <konkers@android.com>
8 *
9 * Copyright (C) 2010-2011 NVIDIA Corporation
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 */
21
22#ifndef __DRIVERS_VIDEO_TEGRA_DC_HDMI_H
23#define __DRIVERS_VIDEO_TEGRA_DC_HDMI_H
24
25#define HDMI_INFOFRAME_TYPE_VENDOR 0x81
26#define HDMI_INFOFRAME_TYPE_AVI 0x82
27#define HDMI_INFOFRAME_TYPE_SPD 0x83
28#define HDMI_INFOFRAME_TYPE_AUDIO 0x84
29#define HDMI_INFOFRAME_TYPE_MPEG_SRC 0x85
30#define HDMI_INFOFRAME_TYPE_NTSC_VBI 0x86
31
32/* all fields little endian */
33struct hdmi_avi_infoframe {
34 /* PB0 */
35 u8 csum;
36
37 /* PB1 */
38 unsigned s:2; /* scan information */
39 unsigned b:2; /* bar info data valid */
40 unsigned a:1; /* active info present */
41 unsigned y:2; /* RGB or YCbCr */
42 unsigned res1:1;
43
44 /* PB2 */
45 unsigned r:4; /* active format aspect ratio */
46 unsigned m:2; /* picture aspect ratio */
47 unsigned c:2; /* colorimetry */
48
49 /* PB3 */
50 unsigned sc:2; /* scan information */
51 unsigned q:2; /* quantization range */
52 unsigned ec:3; /* extended colorimetry */
53 unsigned itc:1; /* it content */
54
55 /* PB4 */
56 unsigned vic:7; /* video format id code */
57 unsigned res4:1;
58
59 /* PB5 */
60 unsigned pr:4; /* pixel repetition factor */
61 unsigned cn:2; /* it content type*/
62 unsigned yq:2; /* ycc quantization range */
63
64 /* PB6-7 */
65 u16 top_bar_end_line;
66
67 /* PB8-9 */
68 u16 bot_bar_start_line;
69
70 /* PB10-11 */
71 u16 left_bar_end_pixel;
72
73 /* PB12-13 */
74 u16 right_bar_start_pixel;
75} __attribute__((packed));
76
77#define HDMI_AVI_VERSION 0x02
78
79#define HDMI_AVI_Y_RGB 0x0
80#define HDMI_AVI_Y_YCBCR_422 0x1
81#define HDMI_AVI_Y_YCBCR_444 0x2
82
83#define HDMI_AVI_B_VERT 0x1
84#define HDMI_AVI_B_HORIZ 0x2
85
86#define HDMI_AVI_S_NONE 0x0
87#define HDMI_AVI_S_OVERSCAN 0x1
88#define HDMI_AVI_S_UNDERSCAN 0x2
89
90#define HDMI_AVI_C_NONE 0x0
91#define HDMI_AVI_C_SMPTE 0x1
92#define HDMI_AVI_C_ITU_R 0x2
93#define HDMI_AVI_C_EXTENDED 0x4
94
95#define HDMI_AVI_M_4_3 0x1
96#define HDMI_AVI_M_16_9 0x2
97
98#define HDMI_AVI_R_SAME 0x8
99#define HDMI_AVI_R_4_3_CENTER 0x9
100#define HDMI_AVI_R_16_9_CENTER 0xa
101#define HDMI_AVI_R_14_9_CENTER 0xb
102
103/* all fields little endian */
104struct hdmi_audio_infoframe {
105 /* PB0 */
106 u8 csum;
107
108 /* PB1 */
109 unsigned cc:3; /* channel count */
110 unsigned res1:1;
111 unsigned ct:4; /* coding type */
112
113 /* PB2 */
114 unsigned ss:2; /* sample size */
115 unsigned sf:3; /* sample frequency */
116 unsigned res2:3;
117
118 /* PB3 */
119 unsigned cxt:5; /* coding extention type */
120 unsigned res3:3;
121
122 /* PB4 */
123 u8 ca; /* channel/speaker allocation */
124
125 /* PB5 */
126 unsigned res5:3;
127 unsigned lsv:4; /* level shift value */
128 unsigned dm_inh:1; /* downmix inhibit */
129
130 /* PB6-10 reserved */
131 u8 res6;
132 u8 res7;
133 u8 res8;
134 u8 res9;
135 u8 res10;
136} __attribute__((packed));
137
138#define HDMI_AUDIO_VERSION 0x01
139
140#define HDMI_AUDIO_CC_STREAM 0x0 /* specified by audio stream */
141#define HDMI_AUDIO_CC_2 0x1
142#define HDMI_AUDIO_CC_3 0x2
143#define HDMI_AUDIO_CC_4 0x3
144#define HDMI_AUDIO_CC_5 0x4
145#define HDMI_AUDIO_CC_6 0x5
146#define HDMI_AUDIO_CC_7 0x6
147#define HDMI_AUDIO_CC_8 0x7
148
149#define HDMI_AUDIO_CT_STREAM 0x0 /* specified by audio stream */
150#define HDMI_AUDIO_CT_PCM 0x1
151#define HDMI_AUDIO_CT_AC3 0x2
152#define HDMI_AUDIO_CT_MPEG1 0x3
153#define HDMI_AUDIO_CT_MP3 0x4
154#define HDMI_AUDIO_CT_MPEG2 0x5
155#define HDMI_AUDIO_CT_AAC_LC 0x6
156#define HDMI_AUDIO_CT_DTS 0x7
157#define HDMI_AUDIO_CT_ATRAC 0x8
158#define HDMI_AUDIO_CT_DSD 0x9
159#define HDMI_AUDIO_CT_E_AC3 0xa
160#define HDMI_AUDIO_CT_DTS_HD 0xb
161#define HDMI_AUDIO_CT_MLP 0xc
162#define HDMI_AUDIO_CT_DST 0xd
163#define HDMI_AUDIO_CT_WMA_PRO 0xe
164#define HDMI_AUDIO_CT_CXT 0xf
165
166#define HDMI_AUDIO_SF_STREAM 0x0 /* specified by audio stream */
167#define HDMI_AUIDO_SF_32K 0x1
168#define HDMI_AUDIO_SF_44_1K 0x2
169#define HDMI_AUDIO_SF_48K 0x3
170#define HDMI_AUDIO_SF_88_2K 0x4
171#define HDMI_AUDIO_SF_96K 0x5
172#define HDMI_AUDIO_SF_176_4K 0x6
173#define HDMI_AUDIO_SF_192K 0x7
174
175#define HDMI_AUDIO_SS_STREAM 0x0 /* specified by audio stream */
176#define HDMI_AUDIO_SS_16BIT 0x1
177#define HDMI_AUDIO_SS_20BIT 0x2
178#define HDMI_AUDIO_SS_24BIT 0x3
179
180#define HDMI_AUDIO_CXT_CT 0x0 /* refer to coding in CT */
181#define HDMI_AUDIO_CXT_HE_AAC 0x1
182#define HDMI_AUDIO_CXT_HE_AAC_V2 0x2
183#define HDMI_AUDIO_CXT_MPEG_SURROUND 0x3
184
185/* all fields little endian */
186struct hdmi_stereo_infoframe {
187 /* PB0 */
188 u8 csum;
189
190 /* PB1 */
191 u8 regid0;
192
193 /* PB2 */
194 u8 regid1;
195
196 /* PB3 */
197 u8 regid2;
198
199 /* PB4 */
200 unsigned res1:5;
201 unsigned hdmi_video_format:3;
202
203 /* PB5 */
204 unsigned res2:4;
205 unsigned _3d_structure:4;
206
207 /* PB6*/
208 unsigned res3:4;
209 unsigned _3d_ext_data:4;
210
211} __attribute__((packed));
212
213#define HDMI_VENDOR_VERSION 0x01
214
215struct tegra_dc_hdmi_data;
216
217unsigned long tegra_hdmi_readl(struct tegra_dc_hdmi_data *hdmi,
218 unsigned long reg);
219void tegra_hdmi_writel(struct tegra_dc_hdmi_data *hdmi,
220 unsigned long val, unsigned long reg);
221
222#endif
diff --git a/drivers/video/tegra/dc/hdmi_reg.h b/drivers/video/tegra/dc/hdmi_reg.h
new file mode 100644
index 00000000000..0bdda43199e
--- /dev/null
+++ b/drivers/video/tegra/dc/hdmi_reg.h
@@ -0,0 +1,478 @@
1/*
2 * drivers/video/tegra/dc/hdmi_reg.h
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#ifndef __DRIVERS_VIDEO_TEGRA_DC_HDMI_REG_H
19#define __DRIVERS_VIDEO_TEGRA_DC_HDMI_REG_H
20
21#define HDMI_CTXSW 0x00
22#define HDMI_NV_PDISP_SOR_STATE0 0x01
23#define SOR_STATE_UPDATE (1 << 0)
24
25#define HDMI_NV_PDISP_SOR_STATE1 0x02
26#define SOR_STATE_ASY_HEAD_OPMODE_SLEEP (0 << 0)
27#define SOR_STATE_ASY_HEAD_OPMODE_SNOOSE (1 << 0)
28#define SOR_STATE_ASY_HEAD_OPMODE_AWAKE (2 << 0)
29#define SOR_STATE_ASY_ORMODE_SAFE (0 << 2)
30#define SOR_STATE_ASY_ORMODE_NORMAL (1 << 2)
31#define SOR_STATE_ATTACHED (1 << 3)
32#define SOR_STATE_ARM_SHOW_VGA (1 << 4)
33
34#define HDMI_NV_PDISP_SOR_STATE2 0x03
35#define SOR_STATE_ASY_OWNER_NONE (0 << 0)
36#define SOR_STATE_ASY_OWNER_HEAD0 (1 << 0)
37#define SOR_STATE_ASY_SUBOWNER_NONE (0 << 4)
38#define SOR_STATE_ASY_SUBOWNER_SUBHEAD0 (1 << 4)
39#define SOR_STATE_ASY_SUBOWNER_SUBHEAD1 (2 << 4)
40#define SOR_STATE_ASY_SUBOWNER_BOTH (3 << 4)
41#define SOR_STATE_ASY_CRCMODE_ACTIVE (0 << 6)
42#define SOR_STATE_ASY_CRCMODE_COMPLETE (1 << 6)
43#define SOR_STATE_ASY_CRCMODE_NON_ACTIVE (2 << 6)
44#define SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A (1 << 8)
45#define SOR_STATE_ASY_PROTOCOL_CUSTOM (15 << 8)
46#define SOR_STATE_ASY_HSYNCPOL_POS (0 << 12)
47#define SOR_STATE_ASY_HSYNCPOL_NEG (1 << 12)
48#define SOR_STATE_ASY_VSYNCPOL_POS (0 << 13)
49#define SOR_STATE_ASY_VSYNCPOL_NEG (1 << 13)
50#define SOR_STATE_ASY_DEPOL_POS (0 << 14)
51#define SOR_STATE_ASY_DEPOL_NEG (1 << 14)
52
53#define HDMI_NV_PDISP_RG_HDCP_AN_MSB 0x04
54#define HDMI_NV_PDISP_RG_HDCP_AN_LSB 0x05
55#define HDMI_NV_PDISP_RG_HDCP_CN_MSB 0x06
56#define HDMI_NV_PDISP_RG_HDCP_CN_LSB 0x07
57#define HDMI_NV_PDISP_RG_HDCP_AKSV_MSB 0x08
58#define HDMI_NV_PDISP_RG_HDCP_AKSV_LSB 0x09
59#define HDMI_NV_PDISP_RG_HDCP_BKSV_MSB 0x0a
60#define REPEATER (1 << 31)
61#define HDMI_NV_PDISP_RG_HDCP_BKSV_LSB 0x0b
62#define HDMI_NV_PDISP_RG_HDCP_CKSV_MSB 0x0c
63#define HDMI_NV_PDISP_RG_HDCP_CKSV_LSB 0x0d
64#define HDMI_NV_PDISP_RG_HDCP_DKSV_MSB 0x0e
65#define HDMI_NV_PDISP_RG_HDCP_DKSV_LSB 0x0f
66#define HDMI_NV_PDISP_RG_HDCP_CTRL 0x10
67#define HDCP_RUN_YES (1 << 0)
68#define CRYPT_ENABLED (1 << 1)
69#define ONEONE_ENABLED (1 << 3)
70#define AN_VALID (1 << 8)
71#define R0_VALID (1 << 9)
72#define SPRIME_VALID (1 << 10)
73#define MPRIME_VALID (1 << 11)
74#define SROM_ERR (1 << 13)
75#define HDMI_NV_PDISP_RG_HDCP_CMODE 0x11
76#define TMDS0_LINK0 (1 << 4)
77#define READ_S (1 << 0)
78#define READ_M (2 << 0)
79#define HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB 0x12
80#define HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB 0x13
81#define HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB 0x14
82#define STATUS_CS (1 << 6)
83#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2 0x15
84#define HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1 0x16
85#define HDMI_NV_PDISP_RG_HDCP_RI 0x17
86#define HDMI_NV_PDISP_RG_HDCP_CS_MSB 0x18
87#define HDMI_NV_PDISP_RG_HDCP_CS_LSB 0x19
88#define HDMI_NV_PDISP_HDMI_AUDIO_EMU0 0x1a
89#define HDMI_NV_PDISP_HDMI_AUDIO_EMU_RDATA0 0x1b
90#define HDMI_NV_PDISP_HDMI_AUDIO_EMU1 0x1c
91#define HDMI_NV_PDISP_HDMI_AUDIO_EMU2 0x1d
92#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL 0x1e
93#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS 0x1f
94#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER 0x20
95#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW 0x21
96#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH 0x22
97#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL 0x23
98#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS 0x24
99#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER 0x25
100#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW 0x26
101#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH 0x27
102#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW 0x28
103#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH 0x29
104#define INFOFRAME_CTRL_ENABLE (1 << 0)
105#define INFOFRAME_CTRL_OTHER (1 << 4)
106#define INFOFRAME_CTRL_SINGLE (1 << 8)
107
108#define INFOFRAME_HEADER_TYPE(x) ((x) & 0xff)
109#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8)
110#define INFOFRAME_HEADER_LEN(x) (((x) & 0xf) << 16)
111
112#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x2a
113#define GENERIC_CTRL_ENABLE (1 << 0)
114#define GENERIC_CTRL_OTHER (1 << 4)
115#define GENERIC_CTRL_SINGLE (1 << 8)
116#define GENERIC_CTRL_HBLANK (1 << 12)
117#define GENERIC_CTRL_AUDIO (1 << 16)
118
119#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS 0x2b
120#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER 0x2c
121#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW 0x2d
122#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH 0x2e
123#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW 0x2f
124#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH 0x30
125#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW 0x31
126#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH 0x32
127#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW 0x33
128#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH 0x34
129#define HDMI_NV_PDISP_HDMI_ACR_CTRL 0x35
130#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW 0x36
131#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH 0x37
132#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW 0x38
133#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH 0x39
134#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW 0x3a
135#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH 0x3b
136#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW 0x3c
137#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH 0x3d
138#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW 0x3e
139#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH 0x3f
140#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW 0x40
141#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH 0x41
142#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW 0x42
143#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH 0x43
144#define ACR_SB3(x) (((x) & 0xff) << 8)
145#define ACR_SB2(x) (((x) & 0xff) << 16)
146#define ACR_SB1(x) (((x) & 0xff) << 24)
147#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8)
148
149#define ACR_SB6(x) (((x) & 0xff) << 0)
150#define ACR_SB5(x) (((x) & 0xff) << 8)
151#define ACR_SB4(x) (((x) & 0xff) << 16)
152#define ACR_ENABLE (1 << 31)
153#define ACR_SUBPACK_N(x) ((x) & 0xffffff)
154
155#define HDMI_NV_PDISP_HDMI_CTRL 0x44
156#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0)
157#define HDMI_CTRL_AUDIO_LAYOUT (1 << 8)
158#define HDMI_CTRL_SAMPLE_FLAT (1 << 12)
159#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16)
160#define HDMI_CTRL_ENABLE (1 << 30)
161
162#define HDMI_NV_PDISP_HDMI_VSYNC_KEEPOUT 0x45
163#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW 0x46
164#define VSYNC_WINDOW_END(x) (((x) & 0x3ff) << 0)
165#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16)
166#define VSYNC_WINDOW_ENABLE (1 << 31)
167
168#define HDMI_NV_PDISP_HDMI_GCP_CTRL 0x47
169#define HDMI_NV_PDISP_HDMI_GCP_STATUS 0x48
170#define HDMI_NV_PDISP_HDMI_GCP_SUBPACK 0x49
171#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS1 0x4a
172#define HDMI_NV_PDISP_HDMI_CHANNEL_STATUS2 0x4b
173#define HDMI_NV_PDISP_HDMI_EMU0 0x4c
174#define HDMI_NV_PDISP_HDMI_EMU1 0x4d
175#define HDMI_NV_PDISP_HDMI_EMU1_RDATA 0x4e
176#define HDMI_NV_PDISP_HDMI_SPARE 0x4f
177#define SPARE_HW_CTS (1 << 0)
178#define SPARE_FORCE_SW_CTS (1 << 1)
179#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16)
180#define SPARE_ACR_PRIORITY_HIGH (0 << 31)
181#define SPARE_ACR_PRIORITY_LOW (1 << 31)
182
183#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS1 0x50
184#define HDMI_NV_PDISP_HDMI_SPDIF_CHN_STATUS2 0x51
185#define HDMI_NV_PDISP_HDCPRIF_ROM_CTRL 0x53
186#define HDMI_NV_PDISP_SOR_CAP 0x54
187#define HDMI_NV_PDISP_SOR_PWR 0x55
188#define SOR_PWR_NORMAL_STATE_PD (0 << 0)
189#define SOR_PWR_NORMAL_STATE_PU (1 << 0)
190#define SOR_PWR_NORMAL_START_NORMAL (0 << 1)
191#define SOR_PWR_NORMAL_START_ALT (1 << 1)
192#define SOR_PWR_SAFE_STATE_PD (0 << 16)
193#define SOR_PWR_SAFE_STATE_PU (1 << 16)
194#define SOR_PWR_SAFE_START_NORMAL (0 << 17)
195#define SOR_PWR_SAFE_START_ALT (1 << 17)
196#define SOR_PWR_HALT_DELAY (1 << 24)
197#define SOR_PWR_MODE (1 << 28)
198#define SOR_PWR_SETTING_NEW_DONE (0 << 31)
199#define SOR_PWR_SETTING_NEW_PENDING (1 << 31)
200#define SOR_PWR_SETTING_NEW_TRIGGER (1 << 31)
201
202#define HDMI_NV_PDISP_SOR_TEST 0x56
203#define HDMI_NV_PDISP_SOR_PLL0 0x57
204#define SOR_PLL_PWR (1 << 0)
205#define SOR_PLL_PDBG (1 << 1)
206#define SOR_PLL_VCOPD (1 << 2)
207#define SOR_PLL_PDPORT (1 << 3)
208#define SOR_PLL_RESISTORSEL (1 << 4)
209#define SOR_PLL_PULLDOWN (1 << 5)
210#define SOR_PLL_VCOCAP(x) (((x) & 0xf) << 8)
211#define SOR_PLL_BG_V17_S(x) (((x) & 0xf) << 12)
212#define SOR_PLL_FILTER(x) (((x) & 0xf) << 16)
213#define SOR_PLL_ICHPMP(x) (((x) & 0xf) << 24)
214#define SOR_PLL_TX_REG_LOAD(x) (((x) & 0x3) << 28)
215
216#define HDMI_NV_PDISP_SOR_PLL1 0x58
217#define SOR_PLL_TMDS_TERM_ENABLE (1 << 8)
218#define SOR_PLL_TMDS_TERMADJ(x) (((x) & 0xf) << 9)
219#define SOR_PLL_LOADADJ(x) (((x) & 0xf) << 20)
220#define SOR_PLL_PE_EN (1 << 28)
221#define SOR_PLL_HALF_FULL_PE (1 << 29)
222#define SOR_PLL_S_D_PIN_PE (1 << 30)
223
224#define HDMI_NV_PDISP_SOR_PLL2 0x59
225#define HDMI_NV_PDISP_SOR_CSTM 0x5a
226#define SOR_CSTM_PD_TXDA_0 (1 << 0)
227#define SOR_CSTM_PD_TXDA_1 (1 << 1)
228#define SOR_CSTM_PD_TXDA_2 (1 << 2)
229#define SOR_CSTM_PD_TXDA_3 (1 << 3)
230#define SOR_CSTM_PD_TXDB_0 (1 << 4)
231#define SOR_CSTM_PD_TXDB_1 (1 << 5)
232#define SOR_CSTM_PD_TXDB_2 (1 << 6)
233#define SOR_CSTM_PD_TXDB_3 (1 << 7)
234#define SOR_CSTM_PD_TXCA (1 << 8)
235#define SOR_CSTM_PD_TXCB (1 << 9)
236#define SOR_CSTM_UPPER (1 << 11)
237#define SOR_CSTM_MODE(x) (((x) & 0x3) << 12)
238#define SOR_CSTM_LINKACTA (1 << 14)
239#define SOR_CSTM_LINKACTB (1 << 15)
240#define SOR_CSTM_LVDS_EN (1 << 16)
241#define SOR_CSTM_DUP_SYNC (1 << 17)
242#define SOR_CSTM_NEW_MODE (1 << 18)
243#define SOR_CSTM_BALANCED (1 << 19)
244#define SOR_CSTM_PLLDIV (1 << 21)
245#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24)
246#define SOR_CSTM_ROTDAT(x) (((x) & 0x7) << 28)
247
248#define HDMI_NV_PDISP_SOR_LVDS 0x5b
249#define HDMI_NV_PDISP_SOR_CRCA 0x5c
250#define HDMI_NV_PDISP_SOR_CRCB 0x5d
251#define HDMI_NV_PDISP_SOR_BLANK 0x5e
252#define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f
253#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) << 0)
254#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4)
255#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8)
256#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
257#define SOR_SEQ_PC(x) (((x) & 0xf) << 16)
258#define SOR_SEQ_STATUS (1 << 28)
259#define SOR_SEQ_SWITCH (1 << 30)
260
261#define HDMI_NV_PDISP_SOR_SEQ_INST0 0x60
262#define HDMI_NV_PDISP_SOR_SEQ_INST1 0x61
263#define HDMI_NV_PDISP_SOR_SEQ_INST2 0x62
264#define HDMI_NV_PDISP_SOR_SEQ_INST3 0x63
265#define HDMI_NV_PDISP_SOR_SEQ_INST4 0x64
266#define HDMI_NV_PDISP_SOR_SEQ_INST5 0x65
267#define HDMI_NV_PDISP_SOR_SEQ_INST6 0x66
268#define HDMI_NV_PDISP_SOR_SEQ_INST7 0x67
269#define HDMI_NV_PDISP_SOR_SEQ_INST8 0x68
270#define HDMI_NV_PDISP_SOR_SEQ_INST9 0x69
271#define HDMI_NV_PDISP_SOR_SEQ_INSTA 0x6a
272#define HDMI_NV_PDISP_SOR_SEQ_INSTB 0x6b
273#define HDMI_NV_PDISP_SOR_SEQ_INSTC 0x6c
274#define HDMI_NV_PDISP_SOR_SEQ_INSTD 0x6d
275#define HDMI_NV_PDISP_SOR_SEQ_INSTE 0x6e
276#define HDMI_NV_PDISP_SOR_SEQ_INSTF 0x6f
277#define SOR_SEQ_INST_WAIT_TIME(x) (((x) & 0x3ff) << 0)
278#define SOR_SEQ_INST_WAIT_UNITS_US (0 << 12)
279#define SOR_SEQ_INST_WAIT_UNITS_MS (1 << 12)
280#define SOR_SEQ_INST_WAIT_UNITS_VSYNC (2 << 12)
281#define SOR_SEQ_INST_HALT (1 << 15)
282#define SOR_SEQ_INST_PIN_A_LOW (0 << 21)
283#define SOR_SEQ_INST_PIN_A_HIGH (1 << 21)
284#define SOR_SEQ_INST_PIN_B_LOW (0 << 22)
285#define SOR_SEQ_INST_PIN_B_HIGH (1 << 22)
286#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23)
287#define SOR_SEQ_INST_TRISTATE_IOS (1 << 24)
288#define SOR_SEQ_INST_SOR_SEQ_INST_BLACK_DATA (1 << 25)
289#define SOR_SEQ_INST_BLANK_DE (1 << 26)
290#define SOR_SEQ_INST_BLANK_H (1 << 27)
291#define SOR_SEQ_INST_BLANK_V (1 << 28)
292#define SOR_SEQ_INST_ASSERT_PLL_RESETV (1 << 29)
293#define SOR_SEQ_INST_POWERDOWN_MACRO (1 << 30)
294#define SOR_SEQ_INST_PLL_PULLDOWN (1 << 31)
295
296#define HDMI_NV_PDISP_SOR_VCRCA0 0x72
297#define HDMI_NV_PDISP_SOR_VCRCA1 0x73
298#define HDMI_NV_PDISP_SOR_CCRCA0 0x74
299#define HDMI_NV_PDISP_SOR_CCRCA1 0x75
300#define HDMI_NV_PDISP_SOR_EDATAA0 0x76
301#define HDMI_NV_PDISP_SOR_EDATAA1 0x77
302#define HDMI_NV_PDISP_SOR_COUNTA0 0x78
303#define HDMI_NV_PDISP_SOR_COUNTA1 0x79
304#define HDMI_NV_PDISP_SOR_DEBUGA0 0x7a
305#define HDMI_NV_PDISP_SOR_DEBUGA1 0x7b
306#define HDMI_NV_PDISP_SOR_TRIG 0x7c
307#define HDMI_NV_PDISP_SOR_MSCHECK 0x7d
308#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT 0x7e
309#define DRIVE_CURRENT_LANE0(x) (((x) & 0x3f) << 0)
310#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8)
311#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16)
312#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24)
313#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
314#define DRIVE_CURRENT_1_500_mA 0x00
315#define DRIVE_CURRENT_1_875_mA 0x01
316#define DRIVE_CURRENT_2_250_mA 0x02
317#define DRIVE_CURRENT_2_625_mA 0x03
318#define DRIVE_CURRENT_3_000_mA 0x04
319#define DRIVE_CURRENT_3_375_mA 0x05
320#define DRIVE_CURRENT_3_750_mA 0x06
321#define DRIVE_CURRENT_4_125_mA 0x07
322#define DRIVE_CURRENT_4_500_mA 0x08
323#define DRIVE_CURRENT_4_875_mA 0x09
324#define DRIVE_CURRENT_5_250_mA 0x0a
325#define DRIVE_CURRENT_5_625_mA 0x0b
326#define DRIVE_CURRENT_6_000_mA 0x0c
327#define DRIVE_CURRENT_6_375_mA 0x0d
328#define DRIVE_CURRENT_6_750_mA 0x0e
329#define DRIVE_CURRENT_7_125_mA 0x0f
330#define DRIVE_CURRENT_7_500_mA 0x10
331#define DRIVE_CURRENT_7_875_mA 0x11
332#define DRIVE_CURRENT_8_250_mA 0x12
333#define DRIVE_CURRENT_8_625_mA 0x13
334#define DRIVE_CURRENT_9_000_mA 0x14
335#define DRIVE_CURRENT_9_375_mA 0x15
336#define DRIVE_CURRENT_9_750_mA 0x16
337#define DRIVE_CURRENT_10_125_mA 0x17
338#define DRIVE_CURRENT_10_500_mA 0x18
339#define DRIVE_CURRENT_10_875_mA 0x19
340#define DRIVE_CURRENT_11_250_mA 0x1a
341#define DRIVE_CURRENT_11_625_mA 0x1b
342#define DRIVE_CURRENT_12_000_mA 0x1c
343#define DRIVE_CURRENT_12_375_mA 0x1d
344#define DRIVE_CURRENT_12_750_mA 0x1e
345#define DRIVE_CURRENT_13_125_mA 0x1f
346#define DRIVE_CURRENT_13_500_mA 0x20
347#define DRIVE_CURRENT_13_875_mA 0x21
348#define DRIVE_CURRENT_14_250_mA 0x22
349#define DRIVE_CURRENT_14_625_mA 0x23
350#define DRIVE_CURRENT_15_000_mA 0x24
351#define DRIVE_CURRENT_15_375_mA 0x25
352#define DRIVE_CURRENT_15_750_mA 0x26
353#define DRIVE_CURRENT_16_125_mA 0x27
354#define DRIVE_CURRENT_16_500_mA 0x28
355#define DRIVE_CURRENT_16_875_mA 0x29
356#define DRIVE_CURRENT_17_250_mA 0x2a
357#define DRIVE_CURRENT_17_625_mA 0x2b
358#define DRIVE_CURRENT_18_000_mA 0x2c
359#define DRIVE_CURRENT_18_375_mA 0x2d
360#define DRIVE_CURRENT_18_750_mA 0x2e
361#define DRIVE_CURRENT_19_125_mA 0x2f
362#define DRIVE_CURRENT_19_500_mA 0x30
363#define DRIVE_CURRENT_19_875_mA 0x31
364#define DRIVE_CURRENT_20_250_mA 0x32
365#define DRIVE_CURRENT_20_625_mA 0x33
366#define DRIVE_CURRENT_21_000_mA 0x34
367#define DRIVE_CURRENT_21_375_mA 0x35
368#define DRIVE_CURRENT_21_750_mA 0x36
369#define DRIVE_CURRENT_22_125_mA 0x37
370#define DRIVE_CURRENT_22_500_mA 0x38
371#define DRIVE_CURRENT_22_875_mA 0x39
372#define DRIVE_CURRENT_23_250_mA 0x3a
373#define DRIVE_CURRENT_23_625_mA 0x3b
374#define DRIVE_CURRENT_24_000_mA 0x3c
375#define DRIVE_CURRENT_24_375_mA 0x3d
376#define DRIVE_CURRENT_24_750_mA 0x3e
377
378#define HDMI_NV_PDISP_AUDIO_DEBUG0 0x7f
379#define HDMI_NV_PDISP_AUDIO_DEBUG1 0x80
380#define HDMI_NV_PDISP_AUDIO_DEBUG2 0x81
381/* note: datasheet defines FS1..FS7. we have FS(0)..FS(6) */
382#define HDMI_NV_PDISP_AUDIO_FS(x) (0x82 + (x))
383#define AUDIO_FS_LOW(x) (((x) & 0xfff) << 0)
384#define AUDIO_FS_HIGH(x) (((x) & 0xfff) << 16)
385
386
387#define HDMI_NV_PDISP_AUDIO_PULSE_WIDTH 0x89
388#define HDMI_NV_PDISP_AUDIO_THRESHOLD 0x8a
389#define HDMI_NV_PDISP_AUDIO_CNTRL0 0x8b
390#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
391#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0_0 0xac
392#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR_0 0xbc
393#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE_0 0xbd
394#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320_0 0xbf
395#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441_0 0xc0
396#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882_0 0xc1
397#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764_0 0xc2
398#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480_0 0xc3
399#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960_0 0xc4
400#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920_0 0xc5
401#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT_0 0xc6
402#endif
403#define AUDIO_CNTRL0_ERROR_TOLERANCE(x) (((x) & 0xff) << 0)
404#define AUDIO_CNTRL0_SOFT_RESET (1 << 8)
405#define AUDIO_CNTRL0_SOFT_RESET_ALL (1 << 12)
406#define AUDIO_CNTRL0_SAMPLING_FREQ_UNKNOWN (1 << 16)
407#define AUDIO_CNTRL0_SAMPLING_FREQ_32K (2 << 16)
408#define AUDIO_CNTRL0_SAMPLING_FREQ_44_1K (0 << 16)
409#define AUDIO_CNTRL0_SAMPLING_FREQ_48K (2 << 16)
410#define AUDIO_CNTRL0_SAMPLING_FREQ_88_2K (8 << 16)
411#define AUDIO_CNTRL0_SAMPLING_FREQ_96K (10 << 16)
412#define AUDIO_CNTRL0_SAMPLING_FREQ_176_4K (12 << 16)
413#define AUDIO_CNTRL0_SAMPLING_FREQ_192K (14 << 16)
414#define AUDIO_CNTRL0_SOURCE_SELECT_AUTO (0 << 20)
415#define AUDIO_CNTRL0_SOURCE_SELECT_SPDIF (1 << 20)
416#define AUDIO_CNTRL0_SOURCE_SELECT_HDAL (2 << 20)
417#define AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29)
418#define AUDIO_CNTRL0_FRAMES_PER_BLOCK(x) (((x) & 0xff) << 24)
419
420#define HDMI_NV_PDISP_AUDIO_N 0x8c
421#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0)
422#define AUDIO_N_RESETF (1 << 20)
423#define AUDIO_N_GENERATE_NORMAL (0 << 24)
424#define AUDIO_N_GENERATE_ALTERNALTE (1 << 24)
425#define AUDIO_N_LOOKUP_ENABLE (1 << 28)
426
427#define HDMI_NV_PDISP_HDCPRIF_ROM_TIMING 0x94
428#define HDMI_NV_PDISP_SOR_REFCLK 0x95
429#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8)
430#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x3) << 6)
431
432#define HDMI_NV_PDISP_CRC_CONTROL 0x96
433#define HDMI_NV_PDISP_INPUT_CONTROL 0x97
434#define HDMI_SRC_DISPLAYA (0 << 0)
435#define HDMI_SRC_DISPLAYB (1 << 0)
436#define ARM_VIDEO_RANGE_FULL (0 << 1)
437#define ARM_VIDEO_RANGE_LIMITED (1 << 1)
438
439#define HDMI_NV_PDISP_SCRATCH 0x98
440#define HDMI_NV_PDISP_PE_CURRENT 0x99
441#define PE_CURRENT0(x) (((x) & 0xf) << 0)
442#define PE_CURRENT1(x) (((x) & 0xf) << 8)
443#define PE_CURRENT2(x) (((x) & 0xf) << 16)
444#define PE_CURRENT3(x) (((x) & 0xf) << 24)
445#define PE_CURRENT_0_0_mA 0x0
446#define PE_CURRENT_0_5_mA 0x1
447#define PE_CURRENT_1_0_mA 0x2
448#define PE_CURRENT_1_5_mA 0x3
449#define PE_CURRENT_2_0_mA 0x4
450#define PE_CURRENT_2_5_mA 0x5
451#define PE_CURRENT_3_0_mA 0x6
452#define PE_CURRENT_3_5_mA 0x7
453#define PE_CURRENT_4_0_mA 0x8
454#define PE_CURRENT_4_5_mA 0x9
455#define PE_CURRENT_5_0_mA 0xa
456#define PE_CURRENT_5_5_mA 0xb
457#define PE_CURRENT_6_0_mA 0xc
458#define PE_CURRENT_6_5_mA 0xd
459#define PE_CURRENT_7_0_mA 0xe
460#define PE_CURRENT_7_5_mA 0xf
461
462#define HDMI_NV_PDISP_KEY_CTRL 0x9a
463#define LOCAL_KEYS (1 << 0)
464#define AUTOINC (1 << 1)
465#define WRITE16 (1 << 4)
466#define PKEY_REQUEST_RELOAD_TRIGGER (1 << 5)
467#define PKEY_LOADED (1 << 6)
468#define HDMI_NV_PDISP_KEY_DEBUG0 0x9b
469#define HDMI_NV_PDISP_KEY_DEBUG1 0x9c
470#define HDMI_NV_PDISP_KEY_DEBUG2 0x9d
471#define HDMI_NV_PDISP_KEY_HDCP_KEY_0 0x9e
472#define HDMI_NV_PDISP_KEY_HDCP_KEY_1 0x9f
473#define HDMI_NV_PDISP_KEY_HDCP_KEY_2 0xa0
474#define HDMI_NV_PDISP_KEY_HDCP_KEY_3 0xa1
475#define HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG 0xa2
476#define HDMI_NV_PDISP_KEY_SKEY_INDEX 0xa3
477
478#endif
diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c
new file mode 100644
index 00000000000..263de07a3da
--- /dev/null
+++ b/drivers/video/tegra/dc/nvhdcp.c
@@ -0,0 +1,1259 @@
1/*
2 * drivers/video/tegra/dc/nvhdcp.c
3 *
4 * Copyright (c) 2010-2011, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/delay.h>
19#include <linux/i2c.h>
20#include <linux/miscdevice.h>
21#include <linux/poll.h>
22#include <linux/sched.h>
23#include <linux/uaccess.h>
24#include <linux/wait.h>
25#include <linux/workqueue.h>
26#include <asm/atomic.h>
27
28#include <mach/dc.h>
29#include <mach/kfuse.h>
30
31#include <video/nvhdcp.h>
32
33#include "dc_reg.h"
34#include "dc_priv.h"
35#include "hdmi_reg.h"
36#include "hdmi.h"
37
38DECLARE_WAIT_QUEUE_HEAD(wq_worker);
39
40/* for 0x40 Bcaps */
41#define BCAPS_REPEATER (1 << 6)
42#define BCAPS_READY (1 << 5)
43#define BCAPS_11 (1 << 1) /* used for both Bcaps and Ainfo */
44
45/* for 0x41 Bstatus */
46#define BSTATUS_MAX_DEVS_EXCEEDED (1 << 7)
47#define BSTATUS_MAX_CASCADE_EXCEEDED (1 << 11)
48
49#ifdef VERBOSE_DEBUG
50#define nvhdcp_vdbg(...) \
51 printk("nvhdcp: " __VA_ARGS__)
52#else
53#define nvhdcp_vdbg(...) \
54({ \
55 if(0) \
56 printk("nvhdcp: " __VA_ARGS__); \
57 0; \
58})
59#endif
60#define nvhdcp_debug(...) \
61 pr_debug("nvhdcp: " __VA_ARGS__)
62#define nvhdcp_err(...) \
63 pr_err("nvhdcp: Error: " __VA_ARGS__)
64#define nvhdcp_info(...) \
65 pr_info("nvhdcp: " __VA_ARGS__)
66
67
68/* for nvhdcp.state */
69enum tegra_nvhdcp_state {
70 STATE_OFF,
71 STATE_UNAUTHENTICATED,
72 STATE_LINK_VERIFY,
73 STATE_RENEGOTIATE,
74};
75
76struct tegra_nvhdcp {
77 struct delayed_work work;
78 struct tegra_dc_hdmi_data *hdmi;
79 struct workqueue_struct *downstream_wq;
80 struct mutex lock;
81 struct miscdevice miscdev;
82 char name[12];
83 unsigned id;
84 bool plugged; /* true if hotplug detected */
85 atomic_t policy; /* set policy */
86 enum tegra_nvhdcp_state state; /* STATE_xxx */
87 struct i2c_client *client;
88 struct i2c_board_info info;
89 int bus;
90 u32 b_status;
91 u64 a_n;
92 u64 c_n;
93 u64 a_ksv;
94 u64 b_ksv;
95 u64 c_ksv;
96 u64 d_ksv;
97 u8 v_prime[20];
98 u64 m_prime;
99 u32 num_bksv_list;
100 u64 bksv_list[TEGRA_NVHDCP_MAX_DEVS];
101 int fail_count;
102};
103
104static inline bool nvhdcp_is_plugged(struct tegra_nvhdcp *nvhdcp)
105{
106 rmb();
107 return nvhdcp->plugged;
108}
109
110static inline bool nvhdcp_set_plugged(struct tegra_nvhdcp *nvhdcp, bool plugged)
111{
112 nvhdcp->plugged = plugged;
113 wmb();
114 return plugged;
115}
116
117static int nvhdcp_i2c_read(struct tegra_nvhdcp *nvhdcp, u8 reg,
118 size_t len, void *data)
119{
120 int status;
121 int retries = 15;
122 struct i2c_msg msg[] = {
123 {
124 .addr = 0x74 >> 1, /* primary link */
125 .flags = 0,
126 .len = 1,
127 .buf = &reg,
128 },
129 {
130 .addr = 0x74 >> 1, /* primary link */
131 .flags = I2C_M_RD,
132 .len = len,
133 .buf = data,
134 },
135 };
136
137 do {
138 if (!nvhdcp_is_plugged(nvhdcp)) {
139 nvhdcp_err("disconnect during i2c xfer\n");
140 return -EIO;
141 }
142 status = i2c_transfer(nvhdcp->client->adapter,
143 msg, ARRAY_SIZE(msg));
144 if ((status < 0) && (retries > 1))
145 msleep(250);
146 } while ((status < 0) && retries--);
147
148 if (status < 0) {
149 nvhdcp_err("i2c xfer error %d\n", status);
150 return status;
151 }
152
153 return 0;
154}
155
156static int nvhdcp_i2c_write(struct tegra_nvhdcp *nvhdcp, u8 reg,
157 size_t len, const void *data)
158{
159 int status;
160 u8 buf[len + 1];
161 struct i2c_msg msg[] = {
162 {
163 .addr = 0x74 >> 1, /* primary link */
164 .flags = 0,
165 .len = len + 1,
166 .buf = buf,
167 },
168 };
169 int retries = 15;
170
171 buf[0] = reg;
172 memcpy(buf + 1, data, len);
173
174 do {
175 if (!nvhdcp_is_plugged(nvhdcp)) {
176 nvhdcp_err("disconnect during i2c xfer\n");
177 return -EIO;
178 }
179 status = i2c_transfer(nvhdcp->client->adapter,
180 msg, ARRAY_SIZE(msg));
181 if ((status < 0) && (retries > 1))
182 msleep(250);
183 } while ((status < 0) && retries--);
184
185 if (status < 0) {
186 nvhdcp_err("i2c xfer error %d\n", status);
187 return status;
188 }
189
190 return 0;
191}
192
193static inline int nvhdcp_i2c_read8(struct tegra_nvhdcp *nvhdcp, u8 reg, u8 *val)
194{
195 return nvhdcp_i2c_read(nvhdcp, reg, 1, val);
196}
197
198static inline int nvhdcp_i2c_write8(struct tegra_nvhdcp *nvhdcp, u8 reg, u8 val)
199{
200 return nvhdcp_i2c_write(nvhdcp, reg, 1, &val);
201}
202
203static inline int nvhdcp_i2c_read16(struct tegra_nvhdcp *nvhdcp,
204 u8 reg, u16 *val)
205{
206 u8 buf[2];
207 int e;
208
209 e = nvhdcp_i2c_read(nvhdcp, reg, sizeof buf, buf);
210 if (e)
211 return e;
212
213 if (val)
214 *val = buf[0] | (u16)buf[1] << 8;
215
216 return 0;
217}
218
219static int nvhdcp_i2c_read40(struct tegra_nvhdcp *nvhdcp, u8 reg, u64 *val)
220{
221 u8 buf[5];
222 int e, i;
223 u64 n;
224
225 e = nvhdcp_i2c_read(nvhdcp, reg, sizeof buf, buf);
226 if (e)
227 return e;
228
229 for(i = 0, n = 0; i < 5; i++ ) {
230 n <<= 8;
231 n |= buf[4 - i];
232 }
233
234 if (val)
235 *val = n;
236
237 return 0;
238}
239
240static int nvhdcp_i2c_write40(struct tegra_nvhdcp *nvhdcp, u8 reg, u64 val)
241{
242 char buf[5];
243 int i;
244 for(i = 0; i < 5; i++ ) {
245 buf[i] = val;
246 val >>= 8;
247 }
248 return nvhdcp_i2c_write(nvhdcp, reg, sizeof buf, buf);
249}
250
251static int nvhdcp_i2c_write64(struct tegra_nvhdcp *nvhdcp, u8 reg, u64 val)
252{
253 char buf[8];
254 int i;
255 for(i = 0; i < 8; i++ ) {
256 buf[i] = val;
257 val >>= 8;
258 }
259 return nvhdcp_i2c_write(nvhdcp, reg, sizeof buf, buf);
260}
261
262
263/* 64-bit link encryption session random number */
264static inline u64 get_an(struct tegra_dc_hdmi_data *hdmi)
265{
266 u64 r;
267 r = (u64)tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_AN_MSB) << 32;
268 r |= tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_AN_LSB);
269 return r;
270}
271
272/* 64-bit upstream exchange random number */
273static inline void set_cn(struct tegra_dc_hdmi_data *hdmi, u64 c_n)
274{
275 tegra_hdmi_writel(hdmi, (u32)c_n, HDMI_NV_PDISP_RG_HDCP_CN_LSB);
276 tegra_hdmi_writel(hdmi, c_n >> 32, HDMI_NV_PDISP_RG_HDCP_CN_MSB);
277}
278
279
280/* 40-bit transmitter's key selection vector */
281static inline u64 get_aksv(struct tegra_dc_hdmi_data *hdmi)
282{
283 u64 r;
284 r = (u64)tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_AKSV_MSB) << 32;
285 r |= tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_AKSV_LSB);
286 return r;
287}
288
289/* 40-bit receiver's key selection vector */
290static inline void set_bksv(struct tegra_dc_hdmi_data *hdmi, u64 b_ksv, bool repeater)
291{
292 if (repeater)
293 b_ksv |= (u64)REPEATER << 32;
294 tegra_hdmi_writel(hdmi, (u32)b_ksv, HDMI_NV_PDISP_RG_HDCP_BKSV_LSB);
295 tegra_hdmi_writel(hdmi, b_ksv >> 32, HDMI_NV_PDISP_RG_HDCP_BKSV_MSB);
296}
297
298
299/* 40-bit software's key selection vector */
300static inline void set_cksv(struct tegra_dc_hdmi_data *hdmi, u64 c_ksv)
301{
302 tegra_hdmi_writel(hdmi, (u32)c_ksv, HDMI_NV_PDISP_RG_HDCP_CKSV_LSB);
303 tegra_hdmi_writel(hdmi, c_ksv >> 32, HDMI_NV_PDISP_RG_HDCP_CKSV_MSB);
304}
305
306/* 40-bit connection state */
307static inline u64 get_cs(struct tegra_dc_hdmi_data *hdmi)
308{
309 u64 r;
310 r = (u64)tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_CS_MSB) << 32;
311 r |= tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_CS_LSB);
312 return r;
313}
314
315/* 40-bit upstream key selection vector */
316static inline u64 get_dksv(struct tegra_dc_hdmi_data *hdmi)
317{
318 u64 r;
319 r = (u64)tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_DKSV_MSB) << 32;
320 r |= tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_DKSV_LSB);
321 return r;
322}
323
324/* 64-bit encrypted M0 value */
325static inline u64 get_mprime(struct tegra_dc_hdmi_data *hdmi)
326{
327 u64 r;
328 r = (u64)tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_MPRIME_MSB) << 32;
329 r |= tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_MPRIME_LSB);
330 return r;
331}
332
333static inline u16 get_transmitter_ri(struct tegra_dc_hdmi_data *hdmi)
334{
335 return tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_RI);
336}
337
338static inline int get_receiver_ri(struct tegra_nvhdcp *nvhdcp, u16 *r)
339{
340 return nvhdcp_i2c_read16(nvhdcp, 0x8, r); /* long read */
341}
342
343static int get_bcaps(struct tegra_nvhdcp *nvhdcp, u8 *b_caps)
344{
345 return nvhdcp_i2c_read8(nvhdcp, 0x40, b_caps);
346}
347
348static int get_ksvfifo(struct tegra_nvhdcp *nvhdcp,
349 unsigned num_bksv_list, u64 *ksv_list)
350{
351 u8 *buf, *p;
352 int e;
353 unsigned i;
354 size_t buf_len = num_bksv_list * 5;
355
356 if (!ksv_list || num_bksv_list > TEGRA_NVHDCP_MAX_DEVS)
357 return -EINVAL;
358
359 if (num_bksv_list == 0)
360 return 0;
361
362 buf = kmalloc(buf_len, GFP_KERNEL);
363 if (IS_ERR_OR_NULL(buf))
364 return -ENOMEM;
365
366 e = nvhdcp_i2c_read(nvhdcp, 0x43, buf_len, buf);
367 if (e) {
368 kfree(buf);
369 return e;
370 }
371
372 /* load 40-bit keys from repeater into array of u64 */
373 p = buf;
374 for (i = 0; i < num_bksv_list; i++) {
375 ksv_list[i] = p[0] | ((u64)p[1] << 8) | ((u64)p[2] << 16)
376 | ((u64)p[3] << 24) | ((u64)p[4] << 32);
377 p += 5;
378 }
379
380 kfree(buf);
381 return 0;
382}
383
384/* get V' 160-bit SHA-1 hash from repeater */
385static int get_vprime(struct tegra_nvhdcp *nvhdcp, u8 *v_prime)
386{
387 int e, i;
388
389 for (i = 0; i < 20; i += 4) {
390 e = nvhdcp_i2c_read(nvhdcp, 0x20 + i, 4, v_prime + i);
391 if (e)
392 return e;
393 }
394 return 0;
395}
396
397
398/* set or clear RUN_YES */
399static void hdcp_ctrl_run(struct tegra_dc_hdmi_data *hdmi, bool v)
400{
401 u32 ctrl;
402
403 if (v) {
404 ctrl = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_CTRL);
405 ctrl |= HDCP_RUN_YES;
406 } else {
407 ctrl = 0;
408 }
409
410 tegra_hdmi_writel(hdmi, ctrl, HDMI_NV_PDISP_RG_HDCP_CTRL);
411}
412
413/* wait for any bits in mask to be set in HDMI_NV_PDISP_RG_HDCP_CTRL
414 * sleeps up to 120mS */
415static int wait_hdcp_ctrl(struct tegra_dc_hdmi_data *hdmi, u32 mask, u32 *v)
416{
417 int retries = 13;
418 u32 ctrl;
419
420 do {
421 ctrl = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_CTRL);
422 if ((ctrl & mask)) {
423 if (v)
424 *v = ctrl;
425 break;
426 }
427 if (retries > 1)
428 msleep(10);
429 } while (--retries);
430 if (!retries) {
431 nvhdcp_err("ctrl read timeout (mask=0x%x)\n", mask);
432 return -EIO;
433 }
434 return 0;
435}
436
437/* wait for bits in mask to be set to value in HDMI_NV_PDISP_KEY_CTRL
438 * waits up to 100mS */
439static int wait_key_ctrl(struct tegra_dc_hdmi_data *hdmi, u32 mask, u32 value)
440{
441 int retries = 101;
442 u32 ctrl;
443
444 do {
445 msleep(1);
446 ctrl = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_KEY_CTRL);
447 if (((ctrl ^ value) & mask) == 0)
448 break;
449 } while (--retries);
450 if (!retries) {
451 nvhdcp_err("key ctrl read timeout (mask=0x%x)\n", mask);
452 return -EIO;
453 }
454 return 0;
455}
456
457/* check that key selection vector is well formed.
458 * NOTE: this function assumes KSV has already been checked against
459 * revocation list.
460 */
461static int verify_ksv(u64 k)
462{
463 unsigned i;
464
465 /* count set bits, must be exactly 20 set to be valid */
466 for(i = 0; k; i++)
467 k ^= k & -k;
468
469 return (i != 20) ? -EINVAL : 0;
470}
471
472/* get Status and Kprime signature - READ_S on TMDS0_LINK0 only */
473static int get_s_prime(struct tegra_nvhdcp *nvhdcp, struct tegra_nvhdcp_packet *pkt)
474{
475 struct tegra_dc_hdmi_data *hdmi = nvhdcp->hdmi;
476 u32 sp_msb, sp_lsb1, sp_lsb2;
477 int e;
478
479 /* if connection isn't authenticated ... */
480 mutex_lock(&nvhdcp->lock);
481 if (nvhdcp->state != STATE_LINK_VERIFY) {
482 memset(pkt, 0, sizeof *pkt);
483 pkt->packet_results = TEGRA_NVHDCP_RESULT_LINK_FAILED;
484 e = 0;
485 goto err;
486 }
487
488 pkt->packet_results = TEGRA_NVHDCP_RESULT_UNSUCCESSFUL;
489
490 /* we will be taking c_n, c_ksv as input */
491 if (!(pkt->value_flags & TEGRA_NVHDCP_FLAG_CN)
492 || !(pkt->value_flags & TEGRA_NVHDCP_FLAG_CKSV)) {
493 nvhdcp_err("missing value_flags (0x%x)\n", pkt->value_flags);
494 e = -EINVAL;
495 goto err;
496 }
497
498 pkt->value_flags = 0;
499
500 pkt->a_ksv = nvhdcp->a_ksv;
501 pkt->a_n = nvhdcp->a_n;
502 pkt->value_flags = TEGRA_NVHDCP_FLAG_AKSV | TEGRA_NVHDCP_FLAG_AN;
503
504 nvhdcp_vdbg("%s():cn %llx cksv %llx\n", __func__, pkt->c_n, pkt->c_ksv);
505
506 set_cn(hdmi, pkt->c_n);
507
508 tegra_hdmi_writel(hdmi, TMDS0_LINK0 | READ_S,
509 HDMI_NV_PDISP_RG_HDCP_CMODE);
510
511 set_cksv(hdmi, pkt->c_ksv);
512
513 e = wait_hdcp_ctrl(hdmi, SPRIME_VALID, NULL);
514 if (e) {
515 nvhdcp_err("Sprime read timeout\n");
516 pkt->packet_results = TEGRA_NVHDCP_RESULT_UNSUCCESSFUL;
517 e = -EIO;
518 goto err;
519 }
520
521 msleep(50);
522
523 /* read 56-bit Sprime plus 16 status bits */
524 sp_msb = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_SPRIME_MSB);
525 sp_lsb1 = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB1);
526 sp_lsb2 = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_SPRIME_LSB2);
527
528 /* top 8 bits of LSB2 and bottom 8 bits of MSB hold status bits. */
529 pkt->hdcp_status = ( sp_msb << 8 ) | ( sp_lsb2 >> 24);
530 pkt->value_flags |= TEGRA_NVHDCP_FLAG_S;
531
532 /* 56-bit Kprime */
533 pkt->k_prime = ((u64)(sp_lsb2 & 0xffffff) << 32) | sp_lsb1;
534 pkt->value_flags |= TEGRA_NVHDCP_FLAG_KP;
535
536 /* is connection state supported? */
537 if (sp_msb & STATUS_CS) {
538 pkt->cs = get_cs(hdmi);
539 pkt->value_flags |= TEGRA_NVHDCP_FLAG_CS;
540 }
541
542 /* load Dksv */
543 pkt->d_ksv = get_dksv(hdmi);
544 if (verify_ksv(pkt->d_ksv)) {
545 nvhdcp_err("Dksv invalid!\n");
546 pkt->packet_results = TEGRA_NVHDCP_RESULT_UNSUCCESSFUL;
547 e = -EIO; /* treat bad Dksv as I/O error */
548 }
549 pkt->value_flags |= TEGRA_NVHDCP_FLAG_DKSV;
550
551 /* copy current Bksv */
552 pkt->b_ksv = nvhdcp->b_ksv;
553 pkt->value_flags |= TEGRA_NVHDCP_FLAG_BKSV;
554
555 pkt->packet_results = TEGRA_NVHDCP_RESULT_SUCCESS;
556 mutex_unlock(&nvhdcp->lock);
557 return 0;
558
559err:
560 mutex_unlock(&nvhdcp->lock);
561 return e;
562}
563
564/* get M prime - READ_M on TMDS0_LINK0 only */
565static inline int get_m_prime(struct tegra_nvhdcp *nvhdcp, struct tegra_nvhdcp_packet *pkt)
566{
567 struct tegra_dc_hdmi_data *hdmi = nvhdcp->hdmi;
568 int e;
569
570 pkt->packet_results = TEGRA_NVHDCP_RESULT_UNSUCCESSFUL;
571
572 /* if connection isn't authenticated ... */
573 mutex_lock(&nvhdcp->lock);
574 if (nvhdcp->state != STATE_LINK_VERIFY) {
575 memset(pkt, 0, sizeof *pkt);
576 pkt->packet_results = TEGRA_NVHDCP_RESULT_LINK_FAILED;
577 e = 0;
578 goto err;
579 }
580
581 pkt->a_ksv = nvhdcp->a_ksv;
582 pkt->a_n = nvhdcp->a_n;
583 pkt->value_flags = TEGRA_NVHDCP_FLAG_AKSV | TEGRA_NVHDCP_FLAG_AN;
584
585 set_cn(hdmi, pkt->c_n);
586
587 tegra_hdmi_writel(hdmi, TMDS0_LINK0 | READ_M,
588 HDMI_NV_PDISP_RG_HDCP_CMODE);
589
590 /* Cksv write triggers Mprime update */
591 set_cksv(hdmi, pkt->c_ksv);
592
593 e = wait_hdcp_ctrl(hdmi, MPRIME_VALID, NULL);
594 if (e) {
595 nvhdcp_err("Mprime read timeout\n");
596 e = -EIO;
597 goto err;
598 }
599 msleep(50);
600
601 /* load Mprime */
602 pkt->m_prime = get_mprime(hdmi);
603 pkt->value_flags |= TEGRA_NVHDCP_FLAG_MP;
604
605 pkt->b_status = nvhdcp->b_status;
606 pkt->value_flags |= TEGRA_NVHDCP_FLAG_BSTATUS;
607
608 /* copy most recent KSVFIFO, if it is non-zero */
609 pkt->num_bksv_list = nvhdcp->num_bksv_list;
610 if( nvhdcp->num_bksv_list ) {
611 BUILD_BUG_ON(sizeof(pkt->bksv_list) != sizeof(nvhdcp->bksv_list));
612 memcpy(pkt->bksv_list, nvhdcp->bksv_list,
613 nvhdcp->num_bksv_list * sizeof(*pkt->bksv_list));
614 pkt->value_flags |= TEGRA_NVHDCP_FLAG_BKSVLIST;
615 }
616
617 /* copy v_prime */
618 BUILD_BUG_ON(sizeof(pkt->v_prime) != sizeof(nvhdcp->v_prime));
619 memcpy(pkt->v_prime, nvhdcp->v_prime, sizeof(nvhdcp->v_prime));
620 pkt->value_flags |= TEGRA_NVHDCP_FLAG_V;
621
622 /* load Dksv */
623 pkt->d_ksv = get_dksv(hdmi);
624 if (verify_ksv(pkt->d_ksv)) {
625 nvhdcp_err("Dksv invalid!\n");
626 e = -EIO;
627 goto err;
628 }
629 pkt->value_flags |= TEGRA_NVHDCP_FLAG_DKSV;
630
631 /* copy current Bksv */
632 pkt->b_ksv = nvhdcp->b_ksv;
633 pkt->value_flags |= TEGRA_NVHDCP_FLAG_BKSV;
634
635 pkt->packet_results = TEGRA_NVHDCP_RESULT_SUCCESS;
636 mutex_unlock(&nvhdcp->lock);
637 return 0;
638
639err:
640 mutex_unlock(&nvhdcp->lock);
641 return e;
642}
643
644static int load_kfuse(struct tegra_dc_hdmi_data *hdmi)
645{
646 unsigned buf[KFUSE_DATA_SZ / 4];
647 int e, i;
648 u32 ctrl;
649 u32 tmp;
650 int retries;
651
652 /* copy load kfuse into buffer - only needed for early Tegra parts */
653 e = tegra_kfuse_read(buf, sizeof buf);
654 if (e) {
655 nvhdcp_err("Kfuse read failure\n");
656 return e;
657 }
658
659 /* write the kfuse to HDMI SRAM */
660
661 tegra_hdmi_writel(hdmi, 1, HDMI_NV_PDISP_KEY_CTRL); /* LOAD_KEYS */
662
663 /* issue a reload */
664 ctrl = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_KEY_CTRL);
665 tegra_hdmi_writel(hdmi, ctrl | PKEY_REQUEST_RELOAD_TRIGGER
666 | LOCAL_KEYS , HDMI_NV_PDISP_KEY_CTRL);
667
668 e = wait_key_ctrl(hdmi, PKEY_LOADED, PKEY_LOADED);
669 if (e) {
670 nvhdcp_err("key reload timeout\n");
671 return -EIO;
672 }
673
674 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_KEY_SKEY_INDEX);
675
676 /* wait for SRAM to be cleared */
677 retries = 6;
678 do {
679 tmp = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_KEY_DEBUG0);
680 if ((tmp & 1) == 0) break;
681 if (retries > 1)
682 mdelay(1);
683 } while (--retries);
684 if (!retries) {
685 nvhdcp_err("key SRAM clear timeout\n");
686 return -EIO;
687 }
688
689 for (i = 0; i < KFUSE_DATA_SZ / 4; i += 4) {
690
691 /* load 128-bits*/
692 tegra_hdmi_writel(hdmi, buf[i], HDMI_NV_PDISP_KEY_HDCP_KEY_0);
693 tegra_hdmi_writel(hdmi, buf[i+1], HDMI_NV_PDISP_KEY_HDCP_KEY_1);
694 tegra_hdmi_writel(hdmi, buf[i+2], HDMI_NV_PDISP_KEY_HDCP_KEY_2);
695 tegra_hdmi_writel(hdmi, buf[i+3], HDMI_NV_PDISP_KEY_HDCP_KEY_3);
696
697 /* trigger LOAD_HDCP_KEY */
698 tegra_hdmi_writel(hdmi, 0x100, HDMI_NV_PDISP_KEY_HDCP_KEY_TRIG);
699
700 tmp = LOCAL_KEYS | WRITE16;
701 if (i)
702 tmp |= AUTOINC;
703 tegra_hdmi_writel(hdmi, tmp, HDMI_NV_PDISP_KEY_CTRL);
704
705 /* wait for WRITE16 to complete */
706 e = wait_key_ctrl(hdmi, 0x10, 0); /* WRITE16 */
707 if (e) {
708 nvhdcp_err("key write timeout\n");
709 return -EIO;
710 }
711 }
712
713 return 0;
714}
715
716static int verify_link(struct tegra_nvhdcp *nvhdcp, bool wait_ri)
717{
718 struct tegra_dc_hdmi_data *hdmi = nvhdcp->hdmi;
719 int retries = 3;
720 u16 old, rx, tx;
721 int e;
722
723 old = 0;
724 rx = 0;
725 tx = 0;
726 /* retry 3 times to deal with I2C link issues */
727 do {
728 if (wait_ri)
729 old = get_transmitter_ri(hdmi);
730
731 e = get_receiver_ri(nvhdcp, &rx);
732 if (!e) {
733 if (!rx) {
734 nvhdcp_err("Ri is 0!\n");
735 return -EINVAL;
736 }
737
738 tx = get_transmitter_ri(hdmi);
739 } else {
740 rx = ~tx;
741 msleep(50);
742 }
743
744 } while (wait_ri && --retries && old != tx);
745
746 nvhdcp_debug("R0 Ri poll:rx=0x%04x tx=0x%04x\n", rx, tx);
747
748 if (!nvhdcp_is_plugged(nvhdcp)) {
749 nvhdcp_err("aborting verify links - lost hdmi connection\n");
750 return -EIO;
751 }
752
753 if (rx != tx)
754 return -EINVAL;
755
756 return 0;
757}
758
759static int get_repeater_info(struct tegra_nvhdcp *nvhdcp)
760{
761 int e, retries;
762 u8 b_caps;
763 u16 b_status;
764
765 nvhdcp_vdbg("repeater found:fetching repeater info\n");
766
767 /* wait up to 5 seconds for READY on repeater */
768 retries = 51;
769 do {
770 if (!nvhdcp_is_plugged(nvhdcp)) {
771 nvhdcp_err("disconnect while waiting for repeater\n");
772 return -EIO;
773 }
774
775 e = get_bcaps(nvhdcp, &b_caps);
776 if (!e && (b_caps & BCAPS_READY)) {
777 nvhdcp_debug("Bcaps READY from repeater\n");
778 break;
779 }
780 if (retries > 1)
781 msleep(100);
782 } while (--retries);
783 if (!retries) {
784 nvhdcp_err("repeater Bcaps read timeout\n");
785 return -ETIMEDOUT;
786 }
787
788 memset(nvhdcp->v_prime, 0, sizeof nvhdcp->v_prime);
789 e = get_vprime(nvhdcp, nvhdcp->v_prime);
790 if (e) {
791 nvhdcp_err("repeater Vprime read failure!\n");
792 return e;
793 }
794
795 e = nvhdcp_i2c_read16(nvhdcp, 0x41, &b_status);
796 if (e) {
797 nvhdcp_err("Bstatus read failure!\n");
798 return e;
799 }
800
801 if (b_status & BSTATUS_MAX_DEVS_EXCEEDED) {
802 nvhdcp_err("repeater:max devices (0x%04x)\n", b_status);
803 return -EINVAL;
804 }
805
806 if (b_status & BSTATUS_MAX_CASCADE_EXCEEDED) {
807 nvhdcp_err("repeater:max cascade (0x%04x)\n", b_status);
808 return -EINVAL;
809 }
810
811 nvhdcp->b_status = b_status;
812 nvhdcp->num_bksv_list = b_status & 0x7f;
813 nvhdcp_vdbg("Bstatus 0x%x (devices: %d)\n",
814 b_status, nvhdcp->num_bksv_list);
815
816 memset(nvhdcp->bksv_list, 0, sizeof nvhdcp->bksv_list);
817 e = get_ksvfifo(nvhdcp, nvhdcp->num_bksv_list, nvhdcp->bksv_list);
818 if (e) {
819 nvhdcp_err("repeater:could not read KSVFIFO (err %d)\n", e);
820 return e;
821 }
822
823 return 0;
824}
825
826static void nvhdcp_downstream_worker(struct work_struct *work)
827{
828 struct tegra_nvhdcp *nvhdcp =
829 container_of(to_delayed_work(work), struct tegra_nvhdcp, work);
830 struct tegra_dc_hdmi_data *hdmi = nvhdcp->hdmi;
831 int e;
832 u8 b_caps;
833 u32 tmp;
834 u32 res;
835
836 nvhdcp_vdbg("%s():started thread %s\n", __func__, nvhdcp->name);
837
838 mutex_lock(&nvhdcp->lock);
839 if (nvhdcp->state == STATE_OFF) {
840 nvhdcp_err("nvhdcp failure - giving up\n");
841 goto err;
842 }
843 nvhdcp->state = STATE_UNAUTHENTICATED;
844
845 /* check plug state to terminate early in case flush_workqueue() */
846 if (!nvhdcp_is_plugged(nvhdcp)) {
847 nvhdcp_err("worker started while unplugged!\n");
848 goto lost_hdmi;
849 }
850 nvhdcp_vdbg("%s():hpd=%d\n", __func__, nvhdcp->plugged);
851
852 nvhdcp->a_ksv = 0;
853 nvhdcp->b_ksv = 0;
854 nvhdcp->a_n = 0;
855
856 e = get_bcaps(nvhdcp, &b_caps);
857 if (e) {
858 nvhdcp_err("Bcaps read failure\n");
859 goto failure;
860 }
861
862 nvhdcp_vdbg("read Bcaps = 0x%02x\n", b_caps);
863
864 nvhdcp_vdbg("kfuse loading ...\n");
865
866 /* repeater flag in Bskv must be configured before loading fuses */
867 set_bksv(hdmi, 0, (b_caps & BCAPS_REPEATER));
868
869 e = load_kfuse(hdmi);
870 if (e) {
871 nvhdcp_err("kfuse could not be loaded\n");
872 goto failure;
873 }
874
875 hdcp_ctrl_run(hdmi, 1);
876
877 nvhdcp_vdbg("wait AN_VALID ...\n");
878
879 /* wait for hardware to generate HDCP values */
880 e = wait_hdcp_ctrl(hdmi, AN_VALID | SROM_ERR, &res);
881 if (e) {
882 nvhdcp_err("An key generation timeout\n");
883 goto failure;
884 }
885 if (res & SROM_ERR) {
886 nvhdcp_err("SROM error\n");
887 goto failure;
888 }
889
890 msleep(25);
891
892 nvhdcp->a_ksv = get_aksv(hdmi);
893 nvhdcp->a_n = get_an(hdmi);
894 nvhdcp_vdbg("Aksv is 0x%016llx\n", nvhdcp->a_ksv);
895 nvhdcp_vdbg("An is 0x%016llx\n", nvhdcp->a_n);
896 if (verify_ksv(nvhdcp->a_ksv)) {
897 nvhdcp_err("Aksv verify failure! (0x%016llx)\n", nvhdcp->a_ksv);
898 goto disable;
899 }
900
901 /* write Ainfo to receiver - set 1.1 only if b_caps supports it */
902 e = nvhdcp_i2c_write8(nvhdcp, 0x15, b_caps & BCAPS_11);
903 if (e) {
904 nvhdcp_err("Ainfo write failure\n");
905 goto failure;
906 }
907
908 /* write An to receiver */
909 e = nvhdcp_i2c_write64(nvhdcp, 0x18, nvhdcp->a_n);
910 if (e) {
911 nvhdcp_err("An write failure\n");
912 goto failure;
913 }
914
915 nvhdcp_vdbg("wrote An = 0x%016llx\n", nvhdcp->a_n);
916
917 /* write Aksv to receiver - triggers auth sequence */
918 e = nvhdcp_i2c_write40(nvhdcp, 0x10, nvhdcp->a_ksv);
919 if (e) {
920 nvhdcp_err("Aksv write failure\n");
921 goto failure;
922 }
923
924 nvhdcp_vdbg("wrote Aksv = 0x%010llx\n", nvhdcp->a_ksv);
925
926 /* bail out if unplugged in the middle of negotiation */
927 if (!nvhdcp_is_plugged(nvhdcp))
928 goto lost_hdmi;
929
930 /* get Bksv from receiver */
931 e = nvhdcp_i2c_read40(nvhdcp, 0x00, &nvhdcp->b_ksv);
932 if (e) {
933 nvhdcp_err("Bksv read failure\n");
934 goto failure;
935 }
936 nvhdcp_vdbg("Bksv is 0x%016llx\n", nvhdcp->b_ksv);
937 if (verify_ksv(nvhdcp->b_ksv)) {
938 nvhdcp_err("Bksv verify failure!\n");
939 goto failure;
940 }
941
942 nvhdcp_vdbg("read Bksv = 0x%010llx from device\n", nvhdcp->b_ksv);
943
944 set_bksv(hdmi, nvhdcp->b_ksv, (b_caps & BCAPS_REPEATER));
945
946 nvhdcp_vdbg("loaded Bksv into controller\n");
947
948 e = wait_hdcp_ctrl(hdmi, R0_VALID, NULL);
949 if (e) {
950 nvhdcp_err("R0 read failure!\n");
951 goto failure;
952 }
953
954 nvhdcp_vdbg("R0 valid\n");
955
956 msleep(100); /* can't read R0' within 100ms of writing Aksv */
957
958 nvhdcp_vdbg("verifying links ...\n");
959
960 e = verify_link(nvhdcp, false);
961 if (e) {
962 nvhdcp_err("link verification failed err %d\n", e);
963 goto failure;
964 }
965
966 /* if repeater then get repeater info */
967 if (b_caps & BCAPS_REPEATER) {
968 e = get_repeater_info(nvhdcp);
969 if (e) {
970 nvhdcp_err("get repeater info failed\n");
971 goto failure;
972 }
973 }
974
975 tmp = tegra_hdmi_readl(hdmi, HDMI_NV_PDISP_RG_HDCP_CTRL);
976 tmp |= CRYPT_ENABLED;
977 if (b_caps & BCAPS_11) /* HDCP 1.1 ? */
978 tmp |= ONEONE_ENABLED;
979 tegra_hdmi_writel(hdmi, tmp, HDMI_NV_PDISP_RG_HDCP_CTRL);
980
981 nvhdcp_vdbg("CRYPT enabled\n");
982
983 nvhdcp->state = STATE_LINK_VERIFY;
984 nvhdcp_info("link verified!\n");
985
986 while (1) {
987 if (!nvhdcp_is_plugged(nvhdcp))
988 goto lost_hdmi;
989
990 if (nvhdcp->state != STATE_LINK_VERIFY)
991 goto failure;
992
993 e = verify_link(nvhdcp, true);
994 if (e) {
995 nvhdcp_err("link verification failed err %d\n", e);
996 goto failure;
997 }
998 mutex_unlock(&nvhdcp->lock);
999 wait_event_interruptible_timeout(wq_worker,
1000 !nvhdcp_is_plugged(nvhdcp), msecs_to_jiffies(1500));
1001 mutex_lock(&nvhdcp->lock);
1002
1003 }
1004
1005failure:
1006 nvhdcp->fail_count++;
1007 if(nvhdcp->fail_count > 5) {
1008 nvhdcp_err("nvhdcp failure - too many failures, giving up!\n");
1009 } else {
1010 nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n");
1011 if (!nvhdcp_is_plugged(nvhdcp))
1012 goto lost_hdmi;
1013 queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work,
1014 msecs_to_jiffies(1000));
1015 }
1016
1017lost_hdmi:
1018 nvhdcp->state = STATE_UNAUTHENTICATED;
1019 hdcp_ctrl_run(hdmi, 0);
1020
1021err:
1022 mutex_unlock(&nvhdcp->lock);
1023 return;
1024disable:
1025 nvhdcp->state = STATE_OFF;
1026 nvhdcp_set_plugged(nvhdcp, false);
1027 mutex_unlock(&nvhdcp->lock);
1028 return;
1029}
1030
1031static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp)
1032{
1033 nvhdcp->state = STATE_UNAUTHENTICATED;
1034 if (nvhdcp_is_plugged(nvhdcp)) {
1035 nvhdcp->fail_count = 0;
1036 queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work,
1037 msecs_to_jiffies(100));
1038 }
1039 return 0;
1040}
1041
1042static int tegra_nvhdcp_off(struct tegra_nvhdcp *nvhdcp)
1043{
1044 mutex_lock(&nvhdcp->lock);
1045 nvhdcp->state = STATE_OFF;
1046 nvhdcp_set_plugged(nvhdcp, false);
1047 mutex_unlock(&nvhdcp->lock);
1048 wake_up_interruptible(&wq_worker);
1049 flush_workqueue(nvhdcp->downstream_wq);
1050 return 0;
1051}
1052
1053void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd)
1054{
1055 nvhdcp_debug("hdmi hotplug detected (hpd = %d)\n", hpd);
1056
1057 if (hpd) {
1058 nvhdcp_set_plugged(nvhdcp, true);
1059 tegra_nvhdcp_on(nvhdcp);
1060 } else {
1061 tegra_nvhdcp_off(nvhdcp);
1062 }
1063}
1064
1065int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol)
1066{
1067 if (pol == TEGRA_NVHDCP_POLICY_ALWAYS_ON) {
1068 nvhdcp_info("using \"always on\" policy.\n");
1069 if (atomic_xchg(&nvhdcp->policy, pol) != pol) {
1070 /* policy changed, start working */
1071 tegra_nvhdcp_on(nvhdcp);
1072 }
1073 } else {
1074 /* unsupported policy */
1075 return -EINVAL;
1076 }
1077
1078 return 0;
1079}
1080
1081static int tegra_nvhdcp_renegotiate(struct tegra_nvhdcp *nvhdcp)
1082{
1083 mutex_lock(&nvhdcp->lock);
1084 nvhdcp->state = STATE_RENEGOTIATE;
1085 mutex_unlock(&nvhdcp->lock);
1086 tegra_nvhdcp_on(nvhdcp);
1087 return 0;
1088}
1089
1090void tegra_nvhdcp_suspend(struct tegra_nvhdcp *nvhdcp)
1091{
1092 if (!nvhdcp) return;
1093 tegra_nvhdcp_off(nvhdcp);
1094}
1095
1096void tegra_nvhdcp_resume(struct tegra_nvhdcp *nvhdcp)
1097{
1098 if (!nvhdcp) return;
1099 tegra_nvhdcp_renegotiate(nvhdcp);
1100}
1101
1102static long nvhdcp_dev_ioctl(struct file *filp,
1103 unsigned int cmd, unsigned long arg)
1104{
1105 struct tegra_nvhdcp *nvhdcp = filp->private_data;
1106 struct tegra_nvhdcp_packet *pkt;
1107 int e = -ENOTTY;
1108
1109 switch (cmd) {
1110 case TEGRAIO_NVHDCP_ON:
1111 return tegra_nvhdcp_on(nvhdcp);
1112
1113 case TEGRAIO_NVHDCP_OFF:
1114 return tegra_nvhdcp_off(nvhdcp);
1115
1116 case TEGRAIO_NVHDCP_SET_POLICY:
1117 return tegra_nvhdcp_set_policy(nvhdcp, arg);
1118
1119 case TEGRAIO_NVHDCP_READ_M:
1120 pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
1121 if (!pkt)
1122 return -ENOMEM;
1123 if (copy_from_user(pkt, (void __user *)arg, sizeof(*pkt))) {
1124 e = -EFAULT;
1125 goto kfree_pkt;
1126 }
1127 e = get_m_prime(nvhdcp, pkt);
1128 if (copy_to_user((void __user *)arg, pkt, sizeof(*pkt))) {
1129 e = -EFAULT;
1130 goto kfree_pkt;
1131 }
1132 kfree(pkt);
1133 return e;
1134
1135 case TEGRAIO_NVHDCP_READ_S:
1136 pkt = kmalloc(sizeof(*pkt), GFP_KERNEL);
1137 if (!pkt)
1138 return -ENOMEM;
1139 if (copy_from_user(pkt, (void __user *)arg, sizeof(*pkt))) {
1140 e = -EFAULT;
1141 goto kfree_pkt;
1142 }
1143 e = get_s_prime(nvhdcp, pkt);
1144 if (copy_to_user((void __user *)arg, pkt, sizeof(*pkt))) {
1145 e = -EFAULT;
1146 goto kfree_pkt;
1147 }
1148 kfree(pkt);
1149 return e;
1150
1151 case TEGRAIO_NVHDCP_RENEGOTIATE:
1152 e = tegra_nvhdcp_renegotiate(nvhdcp);
1153 break;
1154 }
1155
1156 return e;
1157kfree_pkt:
1158 kfree(pkt);
1159 return e;
1160}
1161
1162static int nvhdcp_dev_open(struct inode *inode, struct file *filp)
1163{
1164 struct miscdevice *miscdev = filp->private_data;
1165 struct tegra_nvhdcp *nvhdcp =
1166 container_of(miscdev, struct tegra_nvhdcp, miscdev);
1167 filp->private_data = nvhdcp;
1168 return 0;
1169}
1170
1171static int nvhdcp_dev_release(struct inode *inode, struct file *filp)
1172{
1173 filp->private_data = NULL;
1174 return 0;
1175}
1176
1177static const struct file_operations nvhdcp_fops = {
1178 .owner = THIS_MODULE,
1179 .llseek = no_llseek,
1180 .unlocked_ioctl = nvhdcp_dev_ioctl,
1181 .open = nvhdcp_dev_open,
1182 .release = nvhdcp_dev_release,
1183};
1184
1185/* we only support one AP right now, so should only call this once. */
1186struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi,
1187 int id, int bus)
1188{
1189 static struct tegra_nvhdcp *nvhdcp; /* prevent multiple calls */
1190 struct i2c_adapter *adapter;
1191 int e;
1192
1193 if (nvhdcp)
1194 return ERR_PTR(-EMFILE);
1195
1196 nvhdcp = kzalloc(sizeof(*nvhdcp), GFP_KERNEL);
1197 if (!nvhdcp)
1198 return ERR_PTR(-ENOMEM);
1199
1200 nvhdcp->id = id;
1201 snprintf(nvhdcp->name, sizeof(nvhdcp->name), "nvhdcp%u", id);
1202 nvhdcp->hdmi = hdmi;
1203 mutex_init(&nvhdcp->lock);
1204
1205 strlcpy(nvhdcp->info.type, nvhdcp->name, sizeof(nvhdcp->info.type));
1206 nvhdcp->bus = bus;
1207 nvhdcp->info.addr = 0x74 >> 1;
1208 nvhdcp->info.platform_data = nvhdcp;
1209 nvhdcp->fail_count = 0;
1210
1211 adapter = i2c_get_adapter(bus);
1212 if (!adapter) {
1213 nvhdcp_err("can't get adapter for bus %d\n", bus);
1214 e = -EBUSY;
1215 goto free_nvhdcp;
1216 }
1217
1218 nvhdcp->client = i2c_new_device(adapter, &nvhdcp->info);
1219 i2c_put_adapter(adapter);
1220
1221 if (!nvhdcp->client) {
1222 nvhdcp_err("can't create new device\n");
1223 e = -EBUSY;
1224 goto free_nvhdcp;
1225 }
1226
1227 nvhdcp->state = STATE_UNAUTHENTICATED;
1228
1229 nvhdcp->downstream_wq = create_singlethread_workqueue(nvhdcp->name);
1230 INIT_DELAYED_WORK(&nvhdcp->work, nvhdcp_downstream_worker);
1231
1232 nvhdcp->miscdev.minor = MISC_DYNAMIC_MINOR;
1233 nvhdcp->miscdev.name = nvhdcp->name;
1234 nvhdcp->miscdev.fops = &nvhdcp_fops;
1235
1236 e = misc_register(&nvhdcp->miscdev);
1237 if (e)
1238 goto free_workqueue;
1239
1240 nvhdcp_vdbg("%s(): created misc device %s\n", __func__, nvhdcp->name);
1241
1242 return nvhdcp;
1243free_workqueue:
1244 destroy_workqueue(nvhdcp->downstream_wq);
1245 i2c_release_client(nvhdcp->client);
1246free_nvhdcp:
1247 kfree(nvhdcp);
1248 nvhdcp_err("unable to create device.\n");
1249 return ERR_PTR(e);
1250}
1251
1252void tegra_nvhdcp_destroy(struct tegra_nvhdcp *nvhdcp)
1253{
1254 misc_deregister(&nvhdcp->miscdev);
1255 tegra_nvhdcp_off(nvhdcp);
1256 destroy_workqueue(nvhdcp->downstream_wq);
1257 i2c_release_client(nvhdcp->client);
1258 kfree(nvhdcp);
1259}
diff --git a/drivers/video/tegra/dc/nvhdcp.h b/drivers/video/tegra/dc/nvhdcp.h
new file mode 100644
index 00000000000..90ea0be36d1
--- /dev/null
+++ b/drivers/video/tegra/dc/nvhdcp.h
@@ -0,0 +1,46 @@
1/*
2 * drivers/video/tegra/dc/nvhdcp.h
3 *
4 * Copyright (c) 2010-2011, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __DRIVERS_VIDEO_TEGRA_DC_NVHDCP_H
18#define __DRIVERS_VIDEO_TEGRA_DC_NVHDCP_H
19#include <video/nvhdcp.h>
20
21struct tegra_nvhdcp;
22#ifdef CONFIG_TEGRA_NVHDCP
23void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd);
24int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol);
25void tegra_nvhdcp_suspend(struct tegra_nvhdcp *nvhdcp);
26void tegra_nvhdcp_resume(struct tegra_nvhdcp *nvhdcp);
27struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi,
28 int id, int bus);
29void tegra_nvhdcp_destroy(struct tegra_nvhdcp *nvhdcp);
30#else
31inline void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd) { }
32inline int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol)
33{
34 return 0;
35}
36inline void tegra_nvhdcp_suspend(struct tegra_nvhdcp *nvhdcp) { }
37inline void tegra_nvhdcp_resume(struct tegra_nvhdcp *nvhdcp) { }
38inline struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi,
39 int id, int bus)
40{
41 return NULL;
42}
43inline void tegra_nvhdcp_destroy(struct tegra_nvhdcp *nvhdcp) { }
44#endif
45
46#endif
diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c
new file mode 100644
index 00000000000..a2f3ece6ae7
--- /dev/null
+++ b/drivers/video/tegra/dc/nvsd.c
@@ -0,0 +1,906 @@
1/*
2 * drivers/video/tegra/dc/nvsd.c
3 *
4 * Copyright (c) 2010-2012, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <mach/dc.h>
19#include <linux/types.h>
20#include <linux/string.h>
21#include <linux/slab.h>
22#include <linux/backlight.h>
23#include <linux/platform_device.h>
24
25#include "dc_reg.h"
26#include "dc_priv.h"
27#include "nvsd.h"
28
29/* Elements for sysfs access */
30#define NVSD_ATTR(__name) static struct kobj_attribute nvsd_attr_##__name = \
31 __ATTR(__name, S_IRUGO|S_IWUSR, nvsd_settings_show, nvsd_settings_store)
32#define NVSD_ATTRS_ENTRY(__name) (&nvsd_attr_##__name.attr)
33#define IS_NVSD_ATTR(__name) (attr == &nvsd_attr_##__name)
34
35static ssize_t nvsd_settings_show(struct kobject *kobj,
36 struct kobj_attribute *attr, char *buf);
37
38static ssize_t nvsd_settings_store(struct kobject *kobj,
39 struct kobj_attribute *attr, const char *buf, size_t count);
40
41static ssize_t nvsd_registers_show(struct kobject *kobj,
42 struct kobj_attribute *attr, char *buf);
43
44NVSD_ATTR(enable);
45NVSD_ATTR(aggressiveness);
46NVSD_ATTR(phase_in_settings);
47NVSD_ATTR(phase_in_adjustments);
48NVSD_ATTR(bin_width);
49NVSD_ATTR(hw_update_delay);
50NVSD_ATTR(use_vid_luma);
51NVSD_ATTR(coeff);
52NVSD_ATTR(blp_time_constant);
53NVSD_ATTR(blp_step);
54NVSD_ATTR(fc_time_limit);
55NVSD_ATTR(fc_threshold);
56NVSD_ATTR(lut);
57NVSD_ATTR(bltf);
58static struct kobj_attribute nvsd_attr_registers =
59 __ATTR(registers, S_IRUGO, nvsd_registers_show, NULL);
60
61static struct attribute *nvsd_attrs[] = {
62 NVSD_ATTRS_ENTRY(enable),
63 NVSD_ATTRS_ENTRY(aggressiveness),
64 NVSD_ATTRS_ENTRY(phase_in_settings),
65 NVSD_ATTRS_ENTRY(phase_in_adjustments),
66 NVSD_ATTRS_ENTRY(bin_width),
67 NVSD_ATTRS_ENTRY(hw_update_delay),
68 NVSD_ATTRS_ENTRY(use_vid_luma),
69 NVSD_ATTRS_ENTRY(coeff),
70 NVSD_ATTRS_ENTRY(blp_time_constant),
71 NVSD_ATTRS_ENTRY(blp_step),
72 NVSD_ATTRS_ENTRY(fc_time_limit),
73 NVSD_ATTRS_ENTRY(fc_threshold),
74 NVSD_ATTRS_ENTRY(lut),
75 NVSD_ATTRS_ENTRY(bltf),
76 NVSD_ATTRS_ENTRY(registers),
77 NULL,
78};
79
80static struct attribute_group nvsd_attr_group = {
81 .attrs = nvsd_attrs,
82};
83
84static struct kobject *nvsd_kobj;
85
86/* shared brightness variable */
87static atomic_t *sd_brightness = NULL;
88/* shared boolean for manual K workaround */
89static atomic_t man_k_until_blank = ATOMIC_INIT(0);
90
91static u8 nvsd_get_bw_idx(struct tegra_dc_sd_settings *settings)
92{
93 u8 bw;
94
95 switch (settings->bin_width) {
96 default:
97 case -1:
98 /* A -1 bin-width indicates 'automatic'
99 based upon aggressiveness. */
100 settings->bin_width = -1;
101 switch (settings->aggressiveness) {
102 default:
103 case 0:
104 case 1:
105 bw = SD_BIN_WIDTH_ONE;
106 break;
107 case 2:
108 case 3:
109 case 4:
110 bw = SD_BIN_WIDTH_TWO;
111 break;
112 case 5:
113 bw = SD_BIN_WIDTH_FOUR;
114 break;
115 }
116 break;
117 case 1:
118 bw = SD_BIN_WIDTH_ONE;
119 break;
120 case 2:
121 bw = SD_BIN_WIDTH_TWO;
122 break;
123 case 4:
124 bw = SD_BIN_WIDTH_FOUR;
125 break;
126 case 8:
127 bw = SD_BIN_WIDTH_EIGHT;
128 break;
129 }
130 return bw >> 3;
131
132}
133
134static bool nvsd_phase_in_adjustments(struct tegra_dc *dc,
135 struct tegra_dc_sd_settings *settings)
136{
137 u8 step, cur_sd_brightness;
138 u16 target_k, cur_k;
139 u32 man_k, val;
140
141 cur_sd_brightness = atomic_read(sd_brightness);
142
143 target_k = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES);
144 target_k = SD_HW_K_R(target_k);
145 cur_k = tegra_dc_readl(dc, DC_DISP_SD_MAN_K_VALUES);
146 cur_k = SD_HW_K_R(cur_k);
147
148 /* read brightness value */
149 val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL);
150 val = SD_BLC_BRIGHTNESS(val);
151
152 step = settings->phase_adj_step;
153 if (cur_sd_brightness != val || target_k != cur_k) {
154 if (!step)
155 step = ADJ_PHASE_STEP;
156
157 /* Phase in Backlight and Pixel K
158 every ADJ_PHASE_STEP frames*/
159 if ((step-- & ADJ_PHASE_STEP) == ADJ_PHASE_STEP) {
160
161 if (val != cur_sd_brightness)
162 val > cur_sd_brightness ?
163 (cur_sd_brightness++) :
164 (cur_sd_brightness--);
165
166 if (target_k != cur_k) {
167 if (target_k > cur_k)
168 cur_k += K_STEP;
169 else
170 cur_k -= K_STEP;
171 }
172
173 /* Set manual k value */
174 man_k = SD_MAN_K_R(cur_k) |
175 SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k);
176 tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES);
177 /* Set manual brightness value */
178 atomic_set(sd_brightness, cur_sd_brightness);
179 }
180 settings->phase_adj_step = step;
181 return true;
182 } else
183 return false;
184}
185
186/* phase in the luts based on the current and max step */
187static void nvsd_phase_in_luts(struct tegra_dc_sd_settings *settings,
188 struct tegra_dc *dc)
189{
190 u32 val;
191 u8 bw_idx;
192 int i;
193 u16 phase_settings_step = settings->phase_settings_step;
194 u16 num_phase_in_steps = settings->num_phase_in_steps;
195
196 bw_idx = nvsd_get_bw_idx(settings);
197
198 /* Phase in Final LUT */
199 for (i = 0; i < DC_DISP_SD_LUT_NUM; i++) {
200 val = SD_LUT_R((settings->lut[bw_idx][i].r *
201 phase_settings_step)/num_phase_in_steps) |
202 SD_LUT_G((settings->lut[bw_idx][i].g *
203 phase_settings_step)/num_phase_in_steps) |
204 SD_LUT_B((settings->lut[bw_idx][i].b *
205 phase_settings_step)/num_phase_in_steps);
206
207 tegra_dc_writel(dc, val, DC_DISP_SD_LUT(i));
208 }
209 /* Phase in Final BLTF */
210 for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) {
211 val = SD_BL_TF_POINT_0(255-((255-settings->bltf[bw_idx][i][0])
212 * phase_settings_step)/num_phase_in_steps) |
213 SD_BL_TF_POINT_1(255-((255-settings->bltf[bw_idx][i][1])
214 * phase_settings_step)/num_phase_in_steps) |
215 SD_BL_TF_POINT_2(255-((255-settings->bltf[bw_idx][i][2])
216 * phase_settings_step)/num_phase_in_steps) |
217 SD_BL_TF_POINT_3(255-((255-settings->bltf[bw_idx][i][3])
218 * phase_settings_step)/num_phase_in_steps);
219
220 tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i));
221 }
222}
223
224/* handle the commands that may be invoked for phase_in_settings */
225static void nvsd_cmd_handler(struct tegra_dc_sd_settings *settings,
226 struct tegra_dc *dc)
227{
228 u32 val;
229 u8 bw_idx, bw;
230
231 if (settings->cmd & ENABLE) {
232 settings->phase_settings_step++;
233 if (settings->phase_settings_step >=
234 settings->num_phase_in_steps)
235 settings->cmd &= ~ENABLE;
236
237 nvsd_phase_in_luts(settings, dc);
238 }
239 if (settings->cmd & DISABLE) {
240 settings->phase_settings_step--;
241 nvsd_phase_in_luts(settings, dc);
242 if (settings->phase_settings_step == 0) {
243 /* finish up aggressiveness phase in */
244 if (settings->cmd & AGG_CHG)
245 settings->aggressiveness = settings->final_agg;
246 settings->cmd = NO_CMD;
247 settings->enable = 0;
248 nvsd_init(dc, settings);
249 }
250 }
251 if (settings->cmd & AGG_CHG) {
252 if (settings->aggressiveness == settings->final_agg)
253 settings->cmd &= ~AGG_CHG;
254 if ((settings->cur_agg_step++ & (STEPS_PER_AGG_CHG - 1)) == 0) {
255 settings->final_agg > settings->aggressiveness ?
256 settings->aggressiveness++ :
257 settings->aggressiveness--;
258
259 /* Update aggressiveness value in HW */
260 val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
261 val &= ~SD_AGGRESSIVENESS(0x7);
262 val |= SD_AGGRESSIVENESS(settings->aggressiveness);
263
264 /* Adjust bin_width for automatic setting */
265 if (settings->bin_width == -1) {
266 bw_idx = nvsd_get_bw_idx(settings);
267
268 bw = bw_idx << 3;
269
270 val &= ~SD_BIN_WIDTH_MASK;
271 val |= bw;
272 }
273 tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
274
275 nvsd_phase_in_luts(settings, dc);
276 }
277 }
278}
279
280static bool nvsd_update_enable(struct tegra_dc_sd_settings *settings,
281 int enable_val)
282{
283
284 if (enable_val != 1 && enable_val != 0)
285 return false;
286
287 if (!settings->cmd && settings->enable != enable_val) {
288 settings->num_phase_in_steps =
289 STEPS_PER_AGG_LVL*settings->aggressiveness;
290 settings->phase_settings_step = enable_val ?
291 0 : settings->num_phase_in_steps;
292 }
293
294 if (settings->enable != enable_val || settings->cmd & DISABLE) {
295 settings->cmd &= ~(ENABLE | DISABLE);
296 if (!settings->enable && enable_val)
297 settings->cmd |= PHASE_IN;
298 settings->cmd |= enable_val ? ENABLE : DISABLE;
299 return true;
300 }
301
302 return false;
303}
304
305static bool nvsd_update_agg(struct tegra_dc_sd_settings *settings, int agg_val)
306{
307 int i;
308 int pri_lvl = SD_AGG_PRI_LVL(agg_val);
309 int agg_lvl = SD_GET_AGG(agg_val);
310 struct tegra_dc_sd_agg_priorities *sd_agg_priorities =
311 &settings->agg_priorities;
312
313 if (agg_lvl > 5 || agg_lvl < 0)
314 return false;
315 else if (agg_lvl == 0 && pri_lvl == 0)
316 return false;
317
318 if (pri_lvl >= 0 && pri_lvl < 4)
319 sd_agg_priorities->agg[pri_lvl] = agg_lvl;
320
321 for (i = NUM_AGG_PRI_LVLS - 1; i >= 0; i--) {
322 if (sd_agg_priorities->agg[i])
323 break;
324 }
325
326 sd_agg_priorities->pri_lvl = i;
327 pri_lvl = i;
328 agg_lvl = sd_agg_priorities->agg[i];
329
330 if (settings->phase_in_settings && settings->enable &&
331 settings->aggressiveness != agg_lvl) {
332
333 settings->final_agg = agg_lvl;
334 settings->cmd |= AGG_CHG;
335 settings->cur_agg_step = 0;
336 return true;
337 } else if (settings->aggressiveness != agg_lvl) {
338 settings->aggressiveness = agg_lvl;
339 return true;
340 }
341
342 return false;
343}
344
345/* Functional initialization */
346void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings)
347{
348 u32 i = 0;
349 u32 val = 0;
350 u32 bw_idx = 0;
351 /* TODO: check if HW says SD's available */
352
353 /* If SD's not present or disabled, clear the register and return. */
354 if (!settings || settings->enable == 0) {
355 /* clear the brightness val, too. */
356 if (sd_brightness)
357 atomic_set(sd_brightness, 255);
358
359 sd_brightness = NULL;
360
361 if (settings)
362 settings->phase_settings_step = 0;
363 tegra_dc_writel(dc, 0, DC_DISP_SD_CONTROL);
364 return;
365 }
366
367 dev_dbg(&dc->ndev->dev, "NVSD Init:\n");
368
369 /* init agg_priorities */
370 if (!settings->agg_priorities.agg[0])
371 settings->agg_priorities.agg[0] = settings->aggressiveness;
372
373 /* WAR: Settings will not be valid until the next flip.
374 * Thus, set manual K to either HW's current value (if
375 * we're already enabled) or a non-effective value (if
376 * we're about to enable). */
377 val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
378
379 if (val & SD_ENABLE_NORMAL)
380 i = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES);
381 else
382 i = 0; /* 0 values for RGB = 1.0, i.e. non-affected */
383
384 tegra_dc_writel(dc, i, DC_DISP_SD_MAN_K_VALUES);
385 /* Enable manual correction mode here so that changing the
386 * settings won't immediately impact display dehavior. */
387 val |= SD_CORRECTION_MODE_MAN;
388 tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
389
390 bw_idx = nvsd_get_bw_idx(settings);
391
392 /* Write LUT */
393 if (!settings->cmd) {
394 dev_dbg(&dc->ndev->dev, " LUT:\n");
395
396 for (i = 0; i < DC_DISP_SD_LUT_NUM; i++) {
397 val = SD_LUT_R(settings->lut[bw_idx][i].r) |
398 SD_LUT_G(settings->lut[bw_idx][i].g) |
399 SD_LUT_B(settings->lut[bw_idx][i].b);
400 tegra_dc_writel(dc, val, DC_DISP_SD_LUT(i));
401
402 dev_dbg(&dc->ndev->dev, " %d: 0x%08x\n", i, val);
403 }
404 }
405
406 /* Write BL TF */
407 if (!settings->cmd) {
408 dev_dbg(&dc->ndev->dev, " BL_TF:\n");
409
410 for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) {
411 val = SD_BL_TF_POINT_0(settings->bltf[bw_idx][i][0]) |
412 SD_BL_TF_POINT_1(settings->bltf[bw_idx][i][1]) |
413 SD_BL_TF_POINT_2(settings->bltf[bw_idx][i][2]) |
414 SD_BL_TF_POINT_3(settings->bltf[bw_idx][i][3]);
415
416 tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i));
417
418 dev_dbg(&dc->ndev->dev, " %d: 0x%08x\n", i, val);
419 }
420 } else if ((settings->cmd & PHASE_IN)) {
421 settings->cmd &= ~PHASE_IN;
422 /* Write NO_OP values for BLTF */
423 for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) {
424 val = SD_BL_TF_POINT_0(0xFF) |
425 SD_BL_TF_POINT_1(0xFF) |
426 SD_BL_TF_POINT_2(0xFF) |
427 SD_BL_TF_POINT_3(0xFF);
428
429 tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i));
430
431 dev_dbg(&dc->ndev->dev, " %d: 0x%08x\n", i, val);
432 }
433 }
434
435 /* Set step correctly on init */
436 if (!settings->cmd && settings->phase_in_settings) {
437 settings->num_phase_in_steps = STEPS_PER_AGG_LVL *
438 settings->aggressiveness;
439 settings->phase_settings_step = settings->enable ?
440 settings->num_phase_in_steps : 0;
441 }
442
443 /* Write Coeff */
444 val = SD_CSC_COEFF_R(settings->coeff.r) |
445 SD_CSC_COEFF_G(settings->coeff.g) |
446 SD_CSC_COEFF_B(settings->coeff.b);
447 tegra_dc_writel(dc, val, DC_DISP_SD_CSC_COEFF);
448 dev_dbg(&dc->ndev->dev, " COEFF: 0x%08x\n", val);
449
450 /* Write BL Params */
451 val = SD_BLP_TIME_CONSTANT(settings->blp.time_constant) |
452 SD_BLP_STEP(settings->blp.step);
453 tegra_dc_writel(dc, val, DC_DISP_SD_BL_PARAMETERS);
454 dev_dbg(&dc->ndev->dev, " BLP: 0x%08x\n", val);
455
456 /* Write Auto/Manual PWM */
457 val = (settings->use_auto_pwm) ? SD_BLC_MODE_AUTO : SD_BLC_MODE_MAN;
458 tegra_dc_writel(dc, val, DC_DISP_SD_BL_CONTROL);
459 dev_dbg(&dc->ndev->dev, " BL_CONTROL: 0x%08x\n", val);
460
461 /* Write Flicker Control */
462 val = SD_FC_TIME_LIMIT(settings->fc.time_limit) |
463 SD_FC_THRESHOLD(settings->fc.threshold);
464 tegra_dc_writel(dc, val, DC_DISP_SD_FLICKER_CONTROL);
465 dev_dbg(&dc->ndev->dev, " FLICKER_CONTROL: 0x%08x\n", val);
466
467 /* Manage SD Control */
468 val = 0;
469 /* Stay in manual correction mode until the next flip. */
470 val |= SD_CORRECTION_MODE_MAN;
471 /* Enable / One-Shot */
472 val |= (settings->enable == 2) ?
473 (SD_ENABLE_ONESHOT | SD_ONESHOT_ENABLE) :
474 SD_ENABLE_NORMAL;
475 /* HW Update Delay */
476 val |= SD_HW_UPDATE_DLY(settings->hw_update_delay);
477 /* Video Luma */
478 val |= (settings->use_vid_luma) ? SD_USE_VID_LUMA : 0;
479 /* Aggressiveness */
480 val |= SD_AGGRESSIVENESS(settings->aggressiveness);
481 /* Bin Width (value derived from bw_idx) */
482 val |= bw_idx << 3;
483 /* Finally, Write SD Control */
484 tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
485 dev_dbg(&dc->ndev->dev, " SD_CONTROL: 0x%08x\n", val);
486
487 /* set the brightness pointer */
488 sd_brightness = settings->sd_brightness;
489
490 /* note that we're in manual K until the next flip */
491 atomic_set(&man_k_until_blank, 1);
492}
493
494/* Periodic update */
495bool nvsd_update_brightness(struct tegra_dc *dc)
496{
497 u32 val = 0;
498 int cur_sd_brightness;
499 struct tegra_dc_sd_settings *settings = dc->out->sd_settings;
500
501 if (sd_brightness) {
502 if (atomic_read(&man_k_until_blank) &&
503 !settings->phase_in_adjustments) {
504 val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
505 val &= ~SD_CORRECTION_MODE_MAN;
506 tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
507 atomic_set(&man_k_until_blank, 0);
508 }
509
510 if (settings->cmd)
511 nvsd_cmd_handler(settings, dc);
512
513 /* nvsd_cmd_handler may turn off didim */
514 if (!settings->enable)
515 return true;
516
517 cur_sd_brightness = atomic_read(sd_brightness);
518
519 /* read brightness value */
520 val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL);
521 val = SD_BLC_BRIGHTNESS(val);
522
523 if (settings->phase_in_adjustments) {
524 return nvsd_phase_in_adjustments(dc, settings);
525 } else if (val != (u32)cur_sd_brightness) {
526 /* set brightness value and note the update */
527 atomic_set(sd_brightness, (int)val);
528 return true;
529 }
530 }
531
532 /* No update needed. */
533 return false;
534}
535
536static ssize_t nvsd_lut_show(struct tegra_dc_sd_settings *sd_settings,
537 char *buf, ssize_t res)
538{
539 u32 i;
540 u32 j;
541
542 for (i = 0; i < NUM_BIN_WIDTHS; i++) {
543 res += snprintf(buf + res, PAGE_SIZE - res,
544 "Bin Width: %d\n", 1 << i);
545
546 for (j = 0; j < DC_DISP_SD_LUT_NUM; j++) {
547 res += snprintf(buf + res,
548 PAGE_SIZE - res,
549 "%d: R: %3d / G: %3d / B: %3d\n",
550 j,
551 sd_settings->lut[i][j].r,
552 sd_settings->lut[i][j].g,
553 sd_settings->lut[i][j].b);
554 }
555 }
556 return res;
557}
558
559static ssize_t nvsd_bltf_show(struct tegra_dc_sd_settings *sd_settings,
560 char *buf, ssize_t res)
561{
562 u32 i;
563 u32 j;
564
565 for (i = 0; i < NUM_BIN_WIDTHS; i++) {
566 res += snprintf(buf + res, PAGE_SIZE - res,
567 "Bin Width: %d\n", 1 << i);
568
569 for (j = 0; j < DC_DISP_SD_BL_TF_NUM; j++) {
570 res += snprintf(buf + res,
571 PAGE_SIZE - res,
572 "%d: 0: %3d / 1: %3d / 2: %3d / 3: %3d\n",
573 j,
574 sd_settings->bltf[i][j][0],
575 sd_settings->bltf[i][j][1],
576 sd_settings->bltf[i][j][2],
577 sd_settings->bltf[i][j][3]);
578 }
579 }
580 return res;
581}
582
583/* Sysfs accessors */
584static ssize_t nvsd_settings_show(struct kobject *kobj,
585 struct kobj_attribute *attr, char *buf)
586{
587 struct device *dev = container_of((kobj->parent), struct device, kobj);
588 struct nvhost_device *ndev = to_nvhost_device(dev);
589 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
590 struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
591 ssize_t res = 0;
592
593 if (sd_settings) {
594 if (IS_NVSD_ATTR(enable))
595 res = snprintf(buf, PAGE_SIZE, "%d\n",
596 sd_settings->enable);
597 else if (IS_NVSD_ATTR(aggressiveness))
598 res = snprintf(buf, PAGE_SIZE, "%d\n",
599 sd_settings->aggressiveness);
600 else if (IS_NVSD_ATTR(phase_in_settings))
601 res = snprintf(buf, PAGE_SIZE, "%d\n",
602 sd_settings->phase_in_settings);
603 else if (IS_NVSD_ATTR(phase_in_adjustments))
604 res = snprintf(buf, PAGE_SIZE, "%d\n",
605 sd_settings->phase_in_adjustments);
606 else if (IS_NVSD_ATTR(bin_width))
607 res = snprintf(buf, PAGE_SIZE, "%d\n",
608 sd_settings->bin_width);
609 else if (IS_NVSD_ATTR(hw_update_delay))
610 res = snprintf(buf, PAGE_SIZE, "%d\n",
611 sd_settings->hw_update_delay);
612 else if (IS_NVSD_ATTR(use_vid_luma))
613 res = snprintf(buf, PAGE_SIZE, "%d\n",
614 sd_settings->use_vid_luma);
615 else if (IS_NVSD_ATTR(coeff))
616 res = snprintf(buf, PAGE_SIZE,
617 "R: %d / G: %d / B: %d\n",
618 sd_settings->coeff.r,
619 sd_settings->coeff.g,
620 sd_settings->coeff.b);
621 else if (IS_NVSD_ATTR(blp_time_constant))
622 res = snprintf(buf, PAGE_SIZE, "%d\n",
623 sd_settings->blp.time_constant);
624 else if (IS_NVSD_ATTR(blp_step))
625 res = snprintf(buf, PAGE_SIZE, "%d\n",
626 sd_settings->blp.step);
627 else if (IS_NVSD_ATTR(fc_time_limit))
628 res = snprintf(buf, PAGE_SIZE, "%d\n",
629 sd_settings->fc.time_limit);
630 else if (IS_NVSD_ATTR(fc_threshold))
631 res = snprintf(buf, PAGE_SIZE, "%d\n",
632 sd_settings->fc.threshold);
633 else if (IS_NVSD_ATTR(lut))
634 res = nvsd_lut_show(sd_settings, buf, res);
635 else if (IS_NVSD_ATTR(bltf))
636 res = nvsd_bltf_show(sd_settings, buf, res);
637 else
638 res = -EINVAL;
639 } else {
640 /* This shouldn't be reachable. But just in case... */
641 res = -EINVAL;
642 }
643
644 return res;
645}
646
647#define nvsd_check_and_update(_min, _max, _varname) { \
648 int val = simple_strtol(buf, NULL, 10); \
649 if (val >= _min && val <= _max) { \
650 sd_settings->_varname = val; \
651 settings_updated = true; \
652 } }
653
654#define nvsd_get_multi(_ele, _num, _act, _min, _max) { \
655 char *b, *c, *orig_b; \
656 b = orig_b = kstrdup(buf, GFP_KERNEL); \
657 for (_act = 0; _act < _num; _act++) { \
658 if (!b) \
659 break; \
660 b = strim(b); \
661 c = strsep(&b, " "); \
662 if (!strlen(c)) \
663 break; \
664 _ele[_act] = simple_strtol(c, NULL, 10); \
665 if (_ele[_act] < _min || _ele[_act] > _max) \
666 break; \
667 } \
668 if (orig_b) \
669 kfree(orig_b); \
670}
671
672static int nvsd_lut_store(struct tegra_dc_sd_settings *sd_settings,
673 const char *buf)
674{
675 int ele[3 * DC_DISP_SD_LUT_NUM * NUM_BIN_WIDTHS];
676 int i = 0;
677 int j = 0;
678 int num = 3 * DC_DISP_SD_LUT_NUM * NUM_BIN_WIDTHS;
679
680 nvsd_get_multi(ele, num, i, 0, 255);
681
682 if (i != num)
683 return -EINVAL;
684
685 for (i = 0; i < NUM_BIN_WIDTHS; i++) {
686 for (j = 0; j < DC_DISP_SD_LUT_NUM; j++) {
687 sd_settings->lut[i][j].r =
688 ele[i * NUM_BIN_WIDTHS + j * 3 + 0];
689 sd_settings->lut[i][j].g =
690 ele[i * NUM_BIN_WIDTHS + j * 3 + 1];
691 sd_settings->lut[i][j].b =
692 ele[i * NUM_BIN_WIDTHS + j * 3 + 2];
693 }
694 }
695 return 0;
696}
697
698static int nvsd_bltf_store(struct tegra_dc_sd_settings *sd_settings,
699 const char *buf)
700{
701 int ele[4 * DC_DISP_SD_BL_TF_NUM * NUM_BIN_WIDTHS];
702 int i = 0, j = 0, num = ARRAY_SIZE(ele);
703
704 nvsd_get_multi(ele, num, i, 0, 255);
705
706 if (i != num)
707 return -EINVAL;
708
709 for (i = 0; i < NUM_BIN_WIDTHS; i++) {
710 for (j = 0; j < DC_DISP_SD_BL_TF_NUM; j++) {
711 size_t base = (i * NUM_BIN_WIDTHS *
712 DC_DISP_SD_BL_TF_NUM) + (j * 4);
713 sd_settings->bltf[i][j][0] = ele[base + 0];
714 sd_settings->bltf[i][j][1] = ele[base + 1];
715 sd_settings->bltf[i][j][2] = ele[base + 2];
716 sd_settings->bltf[i][j][3] = ele[base + 3];
717 }
718 }
719
720 return 0;
721}
722
723static ssize_t nvsd_settings_store(struct kobject *kobj,
724 struct kobj_attribute *attr, const char *buf, size_t count)
725{
726 struct device *dev = container_of((kobj->parent), struct device, kobj);
727 struct nvhost_device *ndev = to_nvhost_device(dev);
728 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
729 struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
730 ssize_t res = count;
731 bool settings_updated = false;
732 long int result;
733 int err;
734
735 if (sd_settings) {
736 if (IS_NVSD_ATTR(enable)) {
737 if (sd_settings->phase_in_settings) {
738 err = strict_strtol(buf, 10, &result);
739 if (err)
740 return err;
741
742 if (nvsd_update_enable(sd_settings, result))
743 nvsd_check_and_update(1, 1, enable);
744
745 } else {
746 nvsd_check_and_update(0, 1, enable);
747 }
748 } else if (IS_NVSD_ATTR(aggressiveness)) {
749 err = strict_strtol(buf, 10, &result);
750 if (err)
751 return err;
752
753 if (nvsd_update_agg(sd_settings, result)
754 && !sd_settings->phase_in_settings)
755 settings_updated = true;
756
757 } else if (IS_NVSD_ATTR(phase_in_settings)) {
758 nvsd_check_and_update(0, 1, phase_in_settings);
759 } else if (IS_NVSD_ATTR(phase_in_adjustments)) {
760 nvsd_check_and_update(0, 1, phase_in_adjustments);
761 } else if (IS_NVSD_ATTR(bin_width)) {
762 nvsd_check_and_update(0, 8, bin_width);
763 } else if (IS_NVSD_ATTR(hw_update_delay)) {
764 nvsd_check_and_update(0, 2, hw_update_delay);
765 } else if (IS_NVSD_ATTR(use_vid_luma)) {
766 nvsd_check_and_update(0, 1, use_vid_luma);
767 } else if (IS_NVSD_ATTR(coeff)) {
768 int ele[3], i = 0, num = 3;
769 nvsd_get_multi(ele, num, i, 0, 15);
770
771 if (i == num) {
772 sd_settings->coeff.r = ele[0];
773 sd_settings->coeff.g = ele[1];
774 sd_settings->coeff.b = ele[2];
775 settings_updated = true;
776 } else {
777 res = -EINVAL;
778 }
779 } else if (IS_NVSD_ATTR(blp_time_constant)) {
780 nvsd_check_and_update(0, 1024, blp.time_constant);
781 } else if (IS_NVSD_ATTR(blp_step)) {
782 nvsd_check_and_update(0, 255, blp.step);
783 } else if (IS_NVSD_ATTR(fc_time_limit)) {
784 nvsd_check_and_update(0, 255, fc.time_limit);
785 } else if (IS_NVSD_ATTR(fc_threshold)) {
786 nvsd_check_and_update(0, 255, fc.threshold);
787 } else if (IS_NVSD_ATTR(lut)) {
788 if (nvsd_lut_store(sd_settings, buf))
789 res = -EINVAL;
790 else
791 settings_updated = true;
792 } else if (IS_NVSD_ATTR(bltf)) {
793 if (nvsd_bltf_store(sd_settings, buf))
794 res = -EINVAL;
795 else
796 settings_updated = true;
797 } else {
798 res = -EINVAL;
799 }
800
801 /* Re-init if our settings were updated. */
802 if (settings_updated) {
803 mutex_lock(&dc->lock);
804 if (!dc->enabled) {
805 mutex_unlock(&dc->lock);
806 return -ENODEV;
807 }
808 mutex_unlock(&dc->lock);
809
810 nvsd_init(dc, sd_settings);
811
812 /* Update backlight state IFF we're disabling! */
813 if (!sd_settings->enable && sd_settings->bl_device) {
814 /* Do the actual brightness update outside of
815 * the mutex */
816 struct platform_device *pdev =
817 sd_settings->bl_device;
818 struct backlight_device *bl =
819 platform_get_drvdata(pdev);
820
821 if (bl)
822 backlight_update_status(bl);
823 }
824 }
825 } else {
826 /* This shouldn't be reachable. But just in case... */
827 res = -EINVAL;
828 }
829
830 return res;
831}
832
833#define NVSD_PRINT_REG(__name) { \
834 u32 val = tegra_dc_readl(dc, __name); \
835 res += snprintf(buf + res, PAGE_SIZE - res, #__name ": 0x%08x\n", \
836 val); \
837}
838
839#define NVSD_PRINT_REG_ARRAY(__name) { \
840 u32 val = 0, i = 0; \
841 res += snprintf(buf + res, PAGE_SIZE - res, #__name ":\n"); \
842 for (i = 0; i < __name##_NUM; i++) { \
843 val = tegra_dc_readl(dc, __name(i)); \
844 res += snprintf(buf + res, PAGE_SIZE - res, " %d: 0x%08x\n", \
845 i, val); \
846 } \
847}
848
849static ssize_t nvsd_registers_show(struct kobject *kobj,
850 struct kobj_attribute *attr, char *buf)
851{
852 struct device *dev = container_of((kobj->parent), struct device, kobj);
853 struct nvhost_device *ndev = to_nvhost_device(dev);
854 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
855 ssize_t res = 0;
856
857 mutex_lock(&dc->lock);
858 if (!dc->enabled) {
859 mutex_unlock(&dc->lock);
860 return -ENODEV;
861 }
862
863 mutex_unlock(&dc->lock);
864 NVSD_PRINT_REG(DC_DISP_SD_CONTROL);
865 NVSD_PRINT_REG(DC_DISP_SD_CSC_COEFF);
866 NVSD_PRINT_REG_ARRAY(DC_DISP_SD_LUT);
867 NVSD_PRINT_REG(DC_DISP_SD_FLICKER_CONTROL);
868 NVSD_PRINT_REG(DC_DISP_SD_PIXEL_COUNT);
869 NVSD_PRINT_REG_ARRAY(DC_DISP_SD_HISTOGRAM);
870 NVSD_PRINT_REG(DC_DISP_SD_BL_PARAMETERS);
871 NVSD_PRINT_REG_ARRAY(DC_DISP_SD_BL_TF);
872 NVSD_PRINT_REG(DC_DISP_SD_BL_CONTROL);
873 NVSD_PRINT_REG(DC_DISP_SD_HW_K_VALUES);
874 NVSD_PRINT_REG(DC_DISP_SD_MAN_K_VALUES);
875
876 return res;
877}
878
879/* Sysfs initializer */
880int nvsd_create_sysfs(struct device *dev)
881{
882 int retval = 0;
883
884 nvsd_kobj = kobject_create_and_add("smartdimmer", &dev->kobj);
885
886 if (!nvsd_kobj)
887 return -ENOMEM;
888
889 retval = sysfs_create_group(nvsd_kobj, &nvsd_attr_group);
890
891 if (retval) {
892 kobject_put(nvsd_kobj);
893 dev_err(dev, "%s: failed to create attributes\n", __func__);
894 }
895
896 return retval;
897}
898
899/* Sysfs destructor */
900void __devexit nvsd_remove_sysfs(struct device *dev)
901{
902 if (nvsd_kobj) {
903 sysfs_remove_group(nvsd_kobj, &nvsd_attr_group);
904 kobject_put(nvsd_kobj);
905 }
906}
diff --git a/drivers/video/tegra/dc/nvsd.h b/drivers/video/tegra/dc/nvsd.h
new file mode 100644
index 00000000000..f7fc4a1ead6
--- /dev/null
+++ b/drivers/video/tegra/dc/nvsd.h
@@ -0,0 +1,25 @@
1/*
2 * drivers/video/tegra/dc/nvsd.h
3 *
4 * Copyright (c) 2010-2011, NVIDIA Corporation.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __DRIVERS_VIDEO_TEGRA_DC_NVSD_H
18#define __DRIVERS_VIDEO_TEGRA_DC_NVSD_H
19
20void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings);
21bool nvsd_update_brightness(struct tegra_dc *dc);
22int nvsd_create_sysfs(struct device *dev);
23void __devexit nvsd_remove_sysfs(struct device *dev);
24
25#endif
diff --git a/drivers/video/tegra/dc/rgb.c b/drivers/video/tegra/dc/rgb.c
new file mode 100644
index 00000000000..2112643058f
--- /dev/null
+++ b/drivers/video/tegra/dc/rgb.c
@@ -0,0 +1,160 @@
1/*
2 * drivers/video/tegra/dc/rgb.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/kernel.h>
19
20#include <mach/dc.h>
21
22#include "dc_reg.h"
23#include "dc_priv.h"
24
25
26static const u32 tegra_dc_rgb_enable_partial_pintable[] = {
27 DC_COM_PIN_OUTPUT_ENABLE0, 0x00000000,
28 DC_COM_PIN_OUTPUT_ENABLE1, 0x00000000,
29 DC_COM_PIN_OUTPUT_ENABLE2, 0x00000000,
30 DC_COM_PIN_OUTPUT_ENABLE3, 0x00000000,
31 DC_COM_PIN_OUTPUT_POLARITY0, 0x00000000,
32 DC_COM_PIN_OUTPUT_POLARITY2, 0x00000000,
33 DC_COM_PIN_OUTPUT_DATA0, 0x00000000,
34 DC_COM_PIN_OUTPUT_DATA1, 0x00000000,
35 DC_COM_PIN_OUTPUT_DATA2, 0x00000000,
36 DC_COM_PIN_OUTPUT_DATA3, 0x00000000,
37};
38
39static const u32 tegra_dc_rgb_enable_pintable[] = {
40 DC_COM_PIN_OUTPUT_ENABLE0, 0x00000000,
41 DC_COM_PIN_OUTPUT_ENABLE1, 0x00000000,
42 DC_COM_PIN_OUTPUT_ENABLE2, 0x00000000,
43 DC_COM_PIN_OUTPUT_ENABLE3, 0x00000000,
44 DC_COM_PIN_OUTPUT_POLARITY0, 0x00000000,
45 DC_COM_PIN_OUTPUT_POLARITY1, 0x01000000,
46 DC_COM_PIN_OUTPUT_POLARITY2, 0x00000000,
47 DC_COM_PIN_OUTPUT_POLARITY3, 0x00000000,
48 DC_COM_PIN_OUTPUT_DATA0, 0x00000000,
49 DC_COM_PIN_OUTPUT_DATA1, 0x00000000,
50 DC_COM_PIN_OUTPUT_DATA2, 0x00000000,
51 DC_COM_PIN_OUTPUT_DATA3, 0x00000000,
52};
53
54static const u32 tegra_dc_rgb_enable_out_sel_pintable[] = {
55 DC_COM_PIN_OUTPUT_SELECT0, 0x00000000,
56 DC_COM_PIN_OUTPUT_SELECT1, 0x00000000,
57 DC_COM_PIN_OUTPUT_SELECT2, 0x00000000,
58#ifdef CONFIG_TEGRA_SILICON_PLATFORM
59 DC_COM_PIN_OUTPUT_SELECT3, 0x00000000,
60#else
61 /* The display panel sub-board used on FPGA platforms (panel 86)
62 is non-standard. It expects the Data Enable signal on the WR
63 pin instead of the DE pin. */
64 DC_COM_PIN_OUTPUT_SELECT3, 0x00200000,
65#endif
66 DC_COM_PIN_OUTPUT_SELECT4, 0x00210222,
67 DC_COM_PIN_OUTPUT_SELECT5, 0x00002200,
68 DC_COM_PIN_OUTPUT_SELECT6, 0x00020000,
69};
70
71static const u32 tegra_dc_rgb_disable_pintable[] = {
72 DC_COM_PIN_OUTPUT_ENABLE0, 0x55555555,
73 DC_COM_PIN_OUTPUT_ENABLE1, 0x55150005,
74 DC_COM_PIN_OUTPUT_ENABLE2, 0x55555555,
75 DC_COM_PIN_OUTPUT_ENABLE3, 0x55555555,
76 DC_COM_PIN_OUTPUT_POLARITY0, 0x00000000,
77 DC_COM_PIN_OUTPUT_POLARITY1, 0x00000000,
78 DC_COM_PIN_OUTPUT_POLARITY2, 0x00000000,
79 DC_COM_PIN_OUTPUT_POLARITY3, 0x00000000,
80 DC_COM_PIN_OUTPUT_DATA0, 0xaaaaaaaa,
81 DC_COM_PIN_OUTPUT_DATA1, 0xaaaaaaaa,
82 DC_COM_PIN_OUTPUT_DATA2, 0xaaaaaaaa,
83 DC_COM_PIN_OUTPUT_DATA3, 0xaaaaaaaa,
84 DC_COM_PIN_OUTPUT_SELECT0, 0x00000000,
85 DC_COM_PIN_OUTPUT_SELECT1, 0x00000000,
86 DC_COM_PIN_OUTPUT_SELECT2, 0x00000000,
87 DC_COM_PIN_OUTPUT_SELECT3, 0x00000000,
88 DC_COM_PIN_OUTPUT_SELECT4, 0x00000000,
89 DC_COM_PIN_OUTPUT_SELECT5, 0x00000000,
90 DC_COM_PIN_OUTPUT_SELECT6, 0x00000000,
91};
92
93void tegra_dc_rgb_enable(struct tegra_dc *dc)
94{
95 int i;
96 u32 out_sel_pintable[ARRAY_SIZE(tegra_dc_rgb_enable_out_sel_pintable)];
97
98 tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
99 PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
100 DC_CMD_DISPLAY_POWER_CONTROL);
101
102 tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
103
104 if (dc->out->out_pins) {
105 tegra_dc_set_out_pin_polars(dc, dc->out->out_pins,
106 dc->out->n_out_pins);
107 tegra_dc_write_table(dc, tegra_dc_rgb_enable_partial_pintable);
108 } else {
109 tegra_dc_write_table(dc, tegra_dc_rgb_enable_pintable);
110 }
111
112 memcpy(out_sel_pintable, tegra_dc_rgb_enable_out_sel_pintable,
113 sizeof(tegra_dc_rgb_enable_out_sel_pintable));
114
115 if (dc->out && dc->out->out_sel_configs) {
116 u8 *out_sels = dc->out->out_sel_configs;
117 for (i = 0; i < dc->out->n_out_sel_configs; i++) {
118 switch (out_sels[i]) {
119 case TEGRA_PIN_OUT_CONFIG_SEL_LM1_M1:
120 out_sel_pintable[5*2+1] =
121 (out_sel_pintable[5*2+1] &
122 ~PIN5_LM1_LCD_M1_OUTPUT_MASK) |
123 PIN5_LM1_LCD_M1_OUTPUT_M1;
124 break;
125 case TEGRA_PIN_OUT_CONFIG_SEL_LM1_LD21:
126 out_sel_pintable[5*2+1] =
127 (out_sel_pintable[5*2+1] &
128 ~PIN5_LM1_LCD_M1_OUTPUT_MASK) |
129 PIN5_LM1_LCD_M1_OUTPUT_LD21;
130 break;
131 case TEGRA_PIN_OUT_CONFIG_SEL_LM1_PM1:
132 out_sel_pintable[5*2+1] =
133 (out_sel_pintable[5*2+1] &
134 ~PIN5_LM1_LCD_M1_OUTPUT_MASK) |
135 PIN5_LM1_LCD_M1_OUTPUT_PM1;
136 break;
137 default:
138 dev_err(&dc->ndev->dev,
139 "Invalid pin config[%d]: %d\n",
140 i, out_sels[i]);
141 break;
142 }
143 }
144 }
145
146 tegra_dc_write_table(dc, out_sel_pintable);
147}
148
149void tegra_dc_rgb_disable(struct tegra_dc *dc)
150{
151 tegra_dc_writel(dc, 0x00000000, DC_CMD_DISPLAY_POWER_CONTROL);
152
153 tegra_dc_write_table(dc, tegra_dc_rgb_disable_pintable);
154}
155
156struct tegra_dc_out_ops tegra_dc_rgb_ops = {
157 .enable = tegra_dc_rgb_enable,
158 .disable = tegra_dc_rgb_disable,
159};
160