2 * drivers/video/tegra/dc/dc.c
4 * Copyright (C) 2010 Google, Inc.
5 * Author: Erik Gilling <konkers@android.com>
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.
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.
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/err.h>
21 #include <linux/errno.h>
22 #include <linux/interrupt.h>
23 #include <linux/slab.h>
25 #include <linux/clk.h>
26 #include <linux/mutex.h>
27 #include <linux/delay.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/workqueue.h>
30 #include <linux/ktime.h>
31 #include <linux/debugfs.h>
32 #include <linux/seq_file.h>
38 #include <mach/nvhost.h>
45 module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
47 struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
49 DEFINE_MUTEX(tegra_dc_lock);
51 static inline int tegra_dc_fmt_bpp(int fmt)
54 case TEGRA_WIN_FMT_P1:
57 case TEGRA_WIN_FMT_P2:
60 case TEGRA_WIN_FMT_P4:
63 case TEGRA_WIN_FMT_P8:
66 case TEGRA_WIN_FMT_B4G4R4A4:
67 case TEGRA_WIN_FMT_B5G5R5A:
68 case TEGRA_WIN_FMT_B5G6R5:
69 case TEGRA_WIN_FMT_AB5G5R5:
72 case TEGRA_WIN_FMT_B8G8R8A8:
73 case TEGRA_WIN_FMT_R8G8B8A8:
74 case TEGRA_WIN_FMT_B6x2G6x2R6x2A8:
75 case TEGRA_WIN_FMT_R6x2G6x2B6x2A8:
78 /* for planar formats, size of the Y plane, 8bit */
79 case TEGRA_WIN_FMT_YCbCr420P:
80 case TEGRA_WIN_FMT_YUV420P:
81 case TEGRA_WIN_FMT_YCbCr422P:
82 case TEGRA_WIN_FMT_YUV422P:
85 case TEGRA_WIN_FMT_YCbCr422:
86 case TEGRA_WIN_FMT_YUV422:
87 case TEGRA_WIN_FMT_YCbCr422R:
88 case TEGRA_WIN_FMT_YUV422R:
89 case TEGRA_WIN_FMT_YCbCr422RA:
90 case TEGRA_WIN_FMT_YUV422RA:
91 /* FIXME: need to know the bpp of these formats */
97 static inline bool tegra_dc_is_yuv_planar(int fmt)
100 case TEGRA_WIN_FMT_YUV420P:
101 case TEGRA_WIN_FMT_YCbCr420P:
102 case TEGRA_WIN_FMT_YCbCr422P:
103 case TEGRA_WIN_FMT_YUV422P:
109 #define DUMP_REG(a) do { \
110 snprintf(buff, sizeof(buff), "%-32s\t%03x\t%08lx\n", \
111 #a, a, tegra_dc_readl(dc, a)); \
115 static void _dump_regs(struct tegra_dc *dc, void *data,
116 void (* print)(void *data, const char *str))
121 tegra_dc_io_start(dc);
124 DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0);
125 DUMP_REG(DC_CMD_DISPLAY_COMMAND);
126 DUMP_REG(DC_CMD_SIGNAL_RAISE);
127 DUMP_REG(DC_CMD_INT_STATUS);
128 DUMP_REG(DC_CMD_INT_MASK);
129 DUMP_REG(DC_CMD_INT_ENABLE);
130 DUMP_REG(DC_CMD_INT_TYPE);
131 DUMP_REG(DC_CMD_INT_POLARITY);
132 DUMP_REG(DC_CMD_SIGNAL_RAISE1);
133 DUMP_REG(DC_CMD_SIGNAL_RAISE2);
134 DUMP_REG(DC_CMD_SIGNAL_RAISE3);
135 DUMP_REG(DC_CMD_STATE_ACCESS);
136 DUMP_REG(DC_CMD_STATE_CONTROL);
137 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
138 DUMP_REG(DC_CMD_REG_ACT_CONTROL);
140 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0);
141 DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1);
142 DUMP_REG(DC_DISP_DISP_WIN_OPTIONS);
143 DUMP_REG(DC_DISP_MEM_HIGH_PRIORITY);
144 DUMP_REG(DC_DISP_MEM_HIGH_PRIORITY_TIMER);
145 DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS);
146 DUMP_REG(DC_DISP_REF_TO_SYNC);
147 DUMP_REG(DC_DISP_SYNC_WIDTH);
148 DUMP_REG(DC_DISP_BACK_PORCH);
149 DUMP_REG(DC_DISP_DISP_ACTIVE);
150 DUMP_REG(DC_DISP_FRONT_PORCH);
151 DUMP_REG(DC_DISP_H_PULSE0_CONTROL);
152 DUMP_REG(DC_DISP_H_PULSE0_POSITION_A);
153 DUMP_REG(DC_DISP_H_PULSE0_POSITION_B);
154 DUMP_REG(DC_DISP_H_PULSE0_POSITION_C);
155 DUMP_REG(DC_DISP_H_PULSE0_POSITION_D);
156 DUMP_REG(DC_DISP_H_PULSE1_CONTROL);
157 DUMP_REG(DC_DISP_H_PULSE1_POSITION_A);
158 DUMP_REG(DC_DISP_H_PULSE1_POSITION_B);
159 DUMP_REG(DC_DISP_H_PULSE1_POSITION_C);
160 DUMP_REG(DC_DISP_H_PULSE1_POSITION_D);
161 DUMP_REG(DC_DISP_H_PULSE2_CONTROL);
162 DUMP_REG(DC_DISP_H_PULSE2_POSITION_A);
163 DUMP_REG(DC_DISP_H_PULSE2_POSITION_B);
164 DUMP_REG(DC_DISP_H_PULSE2_POSITION_C);
165 DUMP_REG(DC_DISP_H_PULSE2_POSITION_D);
166 DUMP_REG(DC_DISP_V_PULSE0_CONTROL);
167 DUMP_REG(DC_DISP_V_PULSE0_POSITION_A);
168 DUMP_REG(DC_DISP_V_PULSE0_POSITION_B);
169 DUMP_REG(DC_DISP_V_PULSE0_POSITION_C);
170 DUMP_REG(DC_DISP_V_PULSE1_CONTROL);
171 DUMP_REG(DC_DISP_V_PULSE1_POSITION_A);
172 DUMP_REG(DC_DISP_V_PULSE1_POSITION_B);
173 DUMP_REG(DC_DISP_V_PULSE1_POSITION_C);
174 DUMP_REG(DC_DISP_V_PULSE2_CONTROL);
175 DUMP_REG(DC_DISP_V_PULSE2_POSITION_A);
176 DUMP_REG(DC_DISP_V_PULSE3_CONTROL);
177 DUMP_REG(DC_DISP_V_PULSE3_POSITION_A);
178 DUMP_REG(DC_DISP_M0_CONTROL);
179 DUMP_REG(DC_DISP_M1_CONTROL);
180 DUMP_REG(DC_DISP_DI_CONTROL);
181 DUMP_REG(DC_DISP_PP_CONTROL);
182 DUMP_REG(DC_DISP_PP_SELECT_A);
183 DUMP_REG(DC_DISP_PP_SELECT_B);
184 DUMP_REG(DC_DISP_PP_SELECT_C);
185 DUMP_REG(DC_DISP_PP_SELECT_D);
186 DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL);
187 DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL);
188 DUMP_REG(DC_DISP_DISP_COLOR_CONTROL);
189 DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS);
190 DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS);
191 DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS);
192 DUMP_REG(DC_DISP_LCD_SPI_OPTIONS);
193 DUMP_REG(DC_DISP_BORDER_COLOR);
194 DUMP_REG(DC_DISP_COLOR_KEY0_LOWER);
195 DUMP_REG(DC_DISP_COLOR_KEY0_UPPER);
196 DUMP_REG(DC_DISP_COLOR_KEY1_LOWER);
197 DUMP_REG(DC_DISP_COLOR_KEY1_UPPER);
198 DUMP_REG(DC_DISP_CURSOR_FOREGROUND);
199 DUMP_REG(DC_DISP_CURSOR_BACKGROUND);
200 DUMP_REG(DC_DISP_CURSOR_START_ADDR);
201 DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS);
202 DUMP_REG(DC_DISP_CURSOR_POSITION);
203 DUMP_REG(DC_DISP_CURSOR_POSITION_NS);
204 DUMP_REG(DC_DISP_INIT_SEQ_CONTROL);
205 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A);
206 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B);
207 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C);
208 DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D);
209 DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL);
210 DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST);
211 DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST);
212 DUMP_REG(DC_DISP_MCCIF_DISPLAY0C_HYST);
213 DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST);
214 DUMP_REG(DC_DISP_DAC_CRT_CTRL);
215 DUMP_REG(DC_DISP_DISP_MISC_CONTROL);
218 for (i = 0; i < 3; i++) {
220 snprintf(buff, sizeof(buff), "WINDOW %c:\n", 'A' + i);
223 tegra_dc_writel(dc, WINDOW_A_SELECT << i,
224 DC_CMD_DISPLAY_WINDOW_HEADER);
225 DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER);
226 DUMP_REG(DC_WIN_WIN_OPTIONS);
227 DUMP_REG(DC_WIN_BYTE_SWAP);
228 DUMP_REG(DC_WIN_BUFFER_CONTROL);
229 DUMP_REG(DC_WIN_COLOR_DEPTH);
230 DUMP_REG(DC_WIN_POSITION);
231 DUMP_REG(DC_WIN_SIZE);
232 DUMP_REG(DC_WIN_PRESCALED_SIZE);
233 DUMP_REG(DC_WIN_H_INITIAL_DDA);
234 DUMP_REG(DC_WIN_V_INITIAL_DDA);
235 DUMP_REG(DC_WIN_DDA_INCREMENT);
236 DUMP_REG(DC_WIN_LINE_STRIDE);
237 DUMP_REG(DC_WIN_BUF_STRIDE);
238 DUMP_REG(DC_WIN_UV_BUF_STRIDE);
239 DUMP_REG(DC_WIN_BLEND_NOKEY);
240 DUMP_REG(DC_WIN_BLEND_1WIN);
241 DUMP_REG(DC_WIN_BLEND_2WIN_X);
242 DUMP_REG(DC_WIN_BLEND_2WIN_Y);
243 DUMP_REG(DC_WIN_BLEND_3WIN_XY);
244 DUMP_REG(DC_WINBUF_START_ADDR);
245 DUMP_REG(DC_WINBUF_START_ADDR_U);
246 DUMP_REG(DC_WINBUF_START_ADDR_V);
247 DUMP_REG(DC_WINBUF_ADDR_H_OFFSET);
248 DUMP_REG(DC_WINBUF_ADDR_V_OFFSET);
249 DUMP_REG(DC_WINBUF_UFLOW_STATUS);
250 DUMP_REG(DC_WIN_CSC_YOF);
251 DUMP_REG(DC_WIN_CSC_KYRGB);
252 DUMP_REG(DC_WIN_CSC_KUR);
253 DUMP_REG(DC_WIN_CSC_KVR);
254 DUMP_REG(DC_WIN_CSC_KUG);
255 DUMP_REG(DC_WIN_CSC_KVG);
256 DUMP_REG(DC_WIN_CSC_KUB);
257 DUMP_REG(DC_WIN_CSC_KVB);
260 clk_disable(dc->clk);
267 static void dump_regs_print(void *data, const char *str)
269 struct tegra_dc *dc = data;
270 dev_dbg(&dc->ndev->dev, "%s", str);
273 static void dump_regs(struct tegra_dc *dc)
275 _dump_regs(dc, dc, dump_regs_print);
279 static void dump_regs(struct tegra_dc *dc) {}
283 #ifdef CONFIG_DEBUG_FS
285 static void dbg_regs_print(void *data, const char *str)
287 struct seq_file *s = data;
289 seq_printf(s, "%s", str);
294 static int dbg_dc_show(struct seq_file *s, void *unused)
296 struct tegra_dc *dc = s->private;
298 _dump_regs(dc, s, dbg_regs_print);
304 static int dbg_dc_open(struct inode *inode, struct file *file)
306 return single_open(file, dbg_dc_show, inode->i_private);
309 static const struct file_operations dbg_fops = {
313 .release = single_release,
316 static void tegra_dc_dbg_add(struct tegra_dc *dc)
320 snprintf(name, sizeof(name), "tegra_dc%d_regs", dc->ndev->id);
321 (void) debugfs_create_file(name, S_IRUGO, NULL, dc, &dbg_fops);
324 static void tegra_dc_dbg_add(struct tegra_dc *dc) {}
329 static int tegra_dc_add(struct tegra_dc *dc, int index)
333 mutex_lock(&tegra_dc_lock);
334 if (index >= TEGRA_MAX_DC) {
339 if (tegra_dcs[index] != NULL) {
344 tegra_dcs[index] = dc;
347 mutex_unlock(&tegra_dc_lock);
352 struct tegra_dc *tegra_dc_get_dc(unsigned idx)
354 if (idx < TEGRA_MAX_DC)
355 return tegra_dcs[idx];
359 EXPORT_SYMBOL(tegra_dc_get_dc);
361 struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
363 if (win >= dc->n_windows)
366 return &dc->windows[win];
368 EXPORT_SYMBOL(tegra_dc_get_window);
370 static int get_topmost_window(u32 *depths, unsigned long *wins)
374 for_each_set_bit(idx, wins, DC_N_WINDOWS) {
375 if (best == -1 || depths[idx] < depths[best])
378 clear_bit(best, wins);
382 static u32 blend_topwin(u32 flags)
384 if (flags & TEGRA_WIN_FLAG_BLEND_COVERAGE)
385 return BLEND(NOKEY, ALPHA, 0xff, 0xff);
386 else if (flags & TEGRA_WIN_FLAG_BLEND_PREMULT)
387 return BLEND(NOKEY, PREMULT, 0xff, 0xff);
389 return BLEND(NOKEY, FIX, 0xff, 0xff);
392 static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
396 for (other = 0; other < DC_N_WINDOWS; other++) {
397 if (other != idx && (xy-- == 0))
400 if (BIT(other) & behind_mask)
401 return blend_topwin(flags[idx]);
402 else if (flags[other])
403 return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
405 return BLEND(NOKEY, FIX, 0x00, 0x00);
408 static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
410 unsigned long infront_mask;
413 infront_mask = ~(behind_mask | BIT(idx));
414 infront_mask &= (BIT(DC_N_WINDOWS) - 1);
415 first = ffs(infront_mask) - 1;
418 return blend_topwin(flags[idx]);
419 else if (behind_mask && first != -1 && flags[first])
420 return BLEND(NOKEY, DEPENDANT, 0x00, 0x00);
422 return BLEND(NOKEY, FIX, 0x0, 0x0);
425 static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *blend)
427 unsigned long mask = BIT(DC_N_WINDOWS) - 1;
430 int idx = get_topmost_window(blend->z, &mask);
432 tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
433 DC_CMD_DISPLAY_WINDOW_HEADER);
434 tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
436 tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
438 tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
439 DC_WIN_BLEND_2WIN_X);
440 tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
441 DC_WIN_BLEND_2WIN_Y);
442 tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
443 DC_WIN_BLEND_3WIN_XY);
447 static void tegra_dc_set_csc(struct tegra_dc *dc)
449 tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF);
450 tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB);
451 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR);
452 tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR);
453 tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG);
454 tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG);
455 tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB);
456 tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB);
459 static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
464 /* linear horizontal and vertical filters */
465 for (i = 0; i < 16; i++) {
466 tegra_dc_writel(dc, (v1 << 16) | (v0 << 8),
467 DC_WIN_H_FILTER_P(i));
469 tegra_dc_writel(dc, v0,
470 DC_WIN_V_FILTER_P(i));
476 /* does not support updating windows on multiple dcs in one call */
477 int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
480 unsigned long update_mask = GENERAL_ACT_REQ;
482 bool update_blend = false;
487 mutex_lock(&dc->lock);
490 mutex_unlock(&dc->lock);
495 tegra_dc_writel(dc, WRITE_MUX_ACTIVE | READ_MUX_ACTIVE, DC_CMD_STATE_ACCESS);
497 tegra_dc_writel(dc, WRITE_MUX_ASSEMBLY | READ_MUX_ASSEMBLY, DC_CMD_STATE_ACCESS);
499 for (i = 0; i < n; i++) {
500 struct tegra_dc_win *win = windows[i];
505 bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
506 bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
507 bool yuvp = tegra_dc_is_yuv_planar(win->fmt);
509 if (win->z != dc->blend.z[win->idx]) {
510 dc->blend.z[win->idx] = win->z;
513 if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
514 dc->blend.flags[win->idx]) {
515 dc->blend.flags[win->idx] =
516 win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
520 tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
521 DC_CMD_DISPLAY_WINDOW_HEADER);
524 update_mask |= WIN_A_ACT_REQ << win->idx;
526 if (!(win->flags & TEGRA_WIN_FLAG_ENABLED)) {
527 tegra_dc_writel(dc, 0, DC_WIN_WIN_OPTIONS);
531 tegra_dc_writel(dc, win->fmt, DC_WIN_COLOR_DEPTH);
532 tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP);
535 V_POSITION(win->out_y) | H_POSITION(win->out_x),
538 V_SIZE(win->out_h) | H_SIZE(win->out_w),
541 V_PRESCALED_SIZE(win->h) |
542 H_PRESCALED_SIZE(win->w * tegra_dc_fmt_bpp(win->fmt) / 8),
543 DC_WIN_PRESCALED_SIZE);
545 h_dda = ((win->w - 1) * 0x1000) / max_t(int, win->out_w - 1, 1);
546 v_dda = ((win->h - 1) * 0x1000) / max_t(int, win->out_h - 1, 1);
547 tegra_dc_writel(dc, V_DDA_INC(v_dda) | H_DDA_INC(h_dda),
548 DC_WIN_DDA_INCREMENT);
549 tegra_dc_writel(dc, 0, DC_WIN_H_INITIAL_DDA);
550 tegra_dc_writel(dc, 0, DC_WIN_V_INITIAL_DDA);
552 tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
553 tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE);
554 tegra_dc_writel(dc, (unsigned long)win->phys_addr,
555 DC_WINBUF_START_ADDR);
558 tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE);
561 (unsigned long)win->phys_addr +
562 (unsigned long)win->offset_u,
563 DC_WINBUF_START_ADDR_U);
565 (unsigned long)win->phys_addr +
566 (unsigned long)win->offset_v,
567 DC_WINBUF_START_ADDR_V);
569 LINE_STRIDE(win->stride) |
570 UV_LINE_STRIDE(win->stride_uv),
576 h_offset += win->w - 1;
578 h_offset *= tegra_dc_fmt_bpp(win->fmt) / 8;
582 v_offset += win->h - 1;
585 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
586 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
588 if (win->flags & TEGRA_WIN_FLAG_TILED)
590 DC_WIN_BUFFER_ADDR_MODE_TILE |
591 DC_WIN_BUFFER_ADDR_MODE_TILE_UV,
592 DC_WIN_BUFFER_ADDR_MODE);
595 DC_WIN_BUFFER_ADDR_MODE_LINEAR |
596 DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
597 DC_WIN_BUFFER_ADDR_MODE);
602 else if (tegra_dc_fmt_bpp(win->fmt) < 24)
605 if (win->w != win->out_w)
606 val |= H_FILTER_ENABLE;
607 if (win->h != win->out_h)
608 val |= V_FILTER_ENABLE;
611 val |= H_DIRECTION_DECREMENT;
613 val |= V_DIRECTION_DECREMENT;
615 tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
617 win->dirty = no_vsync ? 0 : 1;
621 tegra_dc_set_blending(dc, &dc->blend);
622 for (i = 0; i < DC_N_WINDOWS; i++) {
624 dc->windows[i].dirty = 1;
625 update_mask |= WIN_A_ACT_REQ << i;
629 tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
632 val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
633 val |= FRAME_END_INT;
634 tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE);
636 val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
637 val |= FRAME_END_INT;
638 tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
641 tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
642 mutex_unlock(&dc->lock);
646 EXPORT_SYMBOL(tegra_dc_update_windows);
648 u32 tegra_dc_get_syncpt_id(const struct tegra_dc *dc)
650 return dc->syncpt_id;
652 EXPORT_SYMBOL(tegra_dc_get_syncpt_id);
654 u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc)
658 mutex_lock(&dc->lock);
659 max = nvhost_syncpt_incr_max(&dc->ndev->host->syncpt, dc->syncpt_id, 1);
660 dc->syncpt_max = max;
661 mutex_unlock(&dc->lock);
666 void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, u32 val)
668 mutex_lock(&dc->lock);
669 while (dc->syncpt_min < val) {
671 nvhost_syncpt_cpu_incr(&dc->ndev->host->syncpt, dc->syncpt_id);
673 mutex_unlock(&dc->lock);
676 static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
681 for (i = 0; i < n; i++) {
682 if (windows[i]->dirty)
689 /* does not support syncing windows on multiple dcs in one call */
690 int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n)
692 if (n < 1 || n > DC_N_WINDOWS)
695 if (!windows[0]->dc->enabled)
698 return wait_event_interruptible_timeout(windows[0]->dc->wq,
699 tegra_dc_windows_are_clean(windows, n),
702 EXPORT_SYMBOL(tegra_dc_sync_windows);
704 static unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk)
709 rate = clk_get_rate(dc->clk);
711 div = DIV_ROUND_CLOSEST(rate * 2, pclk);
716 return rate * 2 / div;
719 void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
723 if (dc->out->type == TEGRA_DC_OUT_HDMI) {
725 struct clk *pll_d_out0_clk =
726 clk_get_sys(NULL, "pll_d_out0");
727 struct clk *pll_d_clk =
728 clk_get_sys(NULL, "pll_d");
730 if (dc->mode.pclk > 70000000)
735 if (rate != clk_get_rate(pll_d_clk))
736 clk_set_rate(pll_d_clk, rate);
738 if (clk_get_parent(clk) != pll_d_out0_clk)
739 clk_set_parent(clk, pll_d_out0_clk);
742 pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
743 tegra_dvfs_set_rate(clk, pclk);
747 static int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode)
754 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
755 tegra_dc_writel(dc, mode->h_ref_to_sync | (mode->v_ref_to_sync << 16),
756 DC_DISP_REF_TO_SYNC);
757 tegra_dc_writel(dc, mode->h_sync_width | (mode->v_sync_width << 16),
759 tegra_dc_writel(dc, mode->h_back_porch | (mode->v_back_porch << 16),
761 tegra_dc_writel(dc, mode->h_active | (mode->v_active << 16),
762 DC_DISP_DISP_ACTIVE);
763 tegra_dc_writel(dc, mode->h_front_porch | (mode->v_front_porch << 16),
764 DC_DISP_FRONT_PORCH);
766 tegra_dc_writel(dc, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL,
767 DC_DISP_DATA_ENABLE_OPTIONS);
769 val = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_POLARITY1);
770 if (mode->flags & TEGRA_DC_MODE_FLAG_NEG_V_SYNC)
771 val |= PIN1_LVS_OUTPUT;
773 val &= ~PIN1_LVS_OUTPUT;
775 if (mode->flags & TEGRA_DC_MODE_FLAG_NEG_H_SYNC)
776 val |= PIN1_LHS_OUTPUT;
778 val &= ~PIN1_LHS_OUTPUT;
779 tegra_dc_writel(dc, val, DC_COM_PIN_OUTPUT_POLARITY1);
781 /* TODO: MIPI/CRT/HDMI clock cals */
783 val = DISP_DATA_FORMAT_DF1P1C;
785 if (dc->out->align == TEGRA_DC_ALIGN_MSB)
786 val |= DISP_DATA_ALIGNMENT_MSB;
788 val |= DISP_DATA_ALIGNMENT_LSB;
790 if (dc->out->order == TEGRA_DC_ORDER_RED_BLUE)
791 val |= DISP_DATA_ORDER_RED_BLUE;
793 val |= DISP_DATA_ORDER_BLUE_RED;
795 tegra_dc_writel(dc, val, DC_DISP_DISP_INTERFACE_CONTROL);
797 rate = clk_get_rate(dc->clk);
799 pclk = tegra_dc_pclk_round_rate(dc, mode->pclk);
800 if (pclk < (mode->pclk / 100 * 99) ||
801 pclk > (mode->pclk / 100 * 109)) {
802 dev_err(&dc->ndev->dev,
803 "can't divide %ld clock to %d -1/+9%% %ld %d %d\n",
805 pclk, (mode->pclk / 100 * 99),
806 (mode->pclk / 100 * 109));
810 div = (rate * 2 / pclk) - 2;
812 tegra_dc_writel(dc, 0x00010001,
813 DC_DISP_SHIFT_CLOCK_OPTIONS);
814 tegra_dc_writel(dc, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(div),
815 DC_DISP_DISP_CLOCK_CONTROL);
821 int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
823 memcpy(&dc->mode, mode, sizeof(dc->mode));
827 EXPORT_SYMBOL(tegra_dc_set_mode);
829 static void tegra_dc_set_out(struct tegra_dc *dc, struct tegra_dc_out *out)
833 if (out->n_modes > 0)
834 tegra_dc_set_mode(dc, &dc->out->modes[0]);
837 case TEGRA_DC_OUT_RGB:
838 dc->out_ops = &tegra_dc_rgb_ops;
841 case TEGRA_DC_OUT_HDMI:
842 dc->out_ops = &tegra_dc_hdmi_ops;
850 if (dc->out_ops && dc->out_ops->init)
851 dc->out_ops->init(dc);
855 unsigned tegra_dc_get_out_height(struct tegra_dc *dc)
858 return dc->out->height;
862 EXPORT_SYMBOL(tegra_dc_get_out_height);
864 unsigned tegra_dc_get_out_width(struct tegra_dc *dc)
867 return dc->out->width;
871 EXPORT_SYMBOL(tegra_dc_get_out_width);
873 static irqreturn_t tegra_dc_irq(int irq, void *ptr)
875 struct tegra_dc *dc = ptr;
876 unsigned long status;
878 unsigned long underflow_mask;
881 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
882 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
884 if (status & FRAME_END_INT) {
888 val = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
889 for (i = 0; i < DC_N_WINDOWS; i++) {
890 if (!(val & (WIN_A_UPDATE << i))) {
891 dc->windows[i].dirty = 0;
899 val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
900 val &= ~FRAME_END_INT;
901 tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE);
910 * Overlays can get thier internal state corrupted during and underflow
911 * condition. The only way to fix this state is to reset the DC.
912 * if we get 4 consecutive frames with underflows, assume we're
915 underflow_mask = status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT);
916 if (underflow_mask) {
917 val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
919 tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE);
920 dc->underflow_mask |= underflow_mask;
923 if (status & V_BLANK_INT) {
926 for (i = 0; i< DC_N_WINDOWS; i++) {
927 if (dc->underflow_mask & (WIN_A_UF_INT <<i)) {
928 dc->windows[i].underflows++;
930 if (dc->windows[i].underflows > 4)
931 schedule_work(&dc->reset_work);
933 dc->windows[i].underflows = 0;
937 if (!dc->underflow_mask) {
938 val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
940 tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE);
943 dc->underflow_mask = 0;
950 static void tegra_dc_set_color_control(struct tegra_dc *dc)
954 switch (dc->out->depth) {
956 color_control = BASE_COLOR_SIZE111;
960 color_control = BASE_COLOR_SIZE222;
964 color_control = BASE_COLOR_SIZE332;
968 color_control = BASE_COLOR_SIZE333;
972 color_control = BASE_COLOR_SIZE444;
976 color_control = BASE_COLOR_SIZE555;
980 color_control = BASE_COLOR_SIZE565;
984 color_control = BASE_COLOR_SIZE666;
988 color_control = BASE_COLOR_SIZE888;
992 tegra_dc_writel(dc, color_control, DC_DISP_DISP_COLOR_CONTROL);
995 static void tegra_dc_init(struct tegra_dc *dc)
1001 tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1002 if (dc->ndev->id == 0) {
1003 disp_syncpt = NVSYNCPT_DISP0;
1004 vblank_syncpt = NVSYNCPT_VBLANK0;
1006 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0A,
1008 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0B,
1010 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0C,
1012 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY1B,
1014 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAYHC,
1015 TEGRA_MC_PRIO_HIGH);
1016 } else if (dc->ndev->id == 1) {
1017 disp_syncpt = NVSYNCPT_DISP1;
1018 vblank_syncpt = NVSYNCPT_VBLANK1;
1020 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0AB,
1022 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0BB,
1024 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0CB,
1026 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY1BB,
1028 tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAYHCB,
1029 TEGRA_MC_PRIO_HIGH);
1031 tegra_dc_writel(dc, 0x00000100 | vblank_syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
1032 tegra_dc_writel(dc, 0x00004700, DC_CMD_INT_TYPE);
1033 tegra_dc_writel(dc, 0x0001c700, DC_CMD_INT_POLARITY);
1034 tegra_dc_writel(dc, 0x00202020, DC_DISP_MEM_HIGH_PRIORITY);
1035 tegra_dc_writel(dc, 0x00010101, DC_DISP_MEM_HIGH_PRIORITY_TIMER);
1037 tegra_dc_writel(dc, (FRAME_END_INT |
1041 WIN_C_UF_INT), DC_CMD_INT_MASK);
1042 tegra_dc_writel(dc, (WIN_A_UF_INT |
1044 WIN_C_UF_INT), DC_CMD_INT_ENABLE);
1046 tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
1048 tegra_dc_set_color_control(dc);
1049 for (i = 0; i < DC_N_WINDOWS; i++) {
1050 tegra_dc_writel(dc, WINDOW_A_SELECT << i,
1051 DC_CMD_DISPLAY_WINDOW_HEADER);
1052 tegra_dc_set_csc(dc);
1053 tegra_dc_set_scaling_filter(dc);
1057 dc->syncpt_id = disp_syncpt;
1059 dc->syncpt_min = dc->syncpt_max =
1060 nvhost_syncpt_read(&dc->ndev->host->syncpt, disp_syncpt);
1063 tegra_dc_program_mode(dc, &dc->mode);
1066 static bool _tegra_dc_enable(struct tegra_dc *dc)
1068 if (dc->mode.pclk == 0)
1071 tegra_dc_io_start(dc);
1073 if (dc->out && dc->out->enable)
1076 tegra_dc_setup_clk(dc, dc->clk);
1077 clk_enable(dc->clk);
1078 clk_enable(dc->emc_clk);
1079 tegra_periph_reset_deassert(dc->clk);
1082 enable_irq(dc->irq);
1086 if (dc->out_ops && dc->out_ops->enable)
1087 dc->out_ops->enable(dc);
1089 /* force a full blending update */
1090 dc->blend.z[0] = -1;
1095 void tegra_dc_enable(struct tegra_dc *dc)
1097 mutex_lock(&dc->lock);
1100 dc->enabled = _tegra_dc_enable(dc);
1102 mutex_unlock(&dc->lock);
1105 static void _tegra_dc_disable(struct tegra_dc *dc)
1107 disable_irq(dc->irq);
1109 if (dc->out_ops && dc->out_ops->disable)
1110 dc->out_ops->disable(dc);
1112 clk_disable(dc->emc_clk);
1113 clk_disable(dc->clk);
1114 tegra_dvfs_set_rate(dc->clk, 0);
1116 if (dc->out && dc->out->disable)
1119 /* flush any pending syncpt waits */
1120 while (dc->syncpt_min < dc->syncpt_max) {
1122 nvhost_syncpt_cpu_incr(&dc->ndev->host->syncpt, dc->syncpt_id);
1125 tegra_dc_io_end(dc);
1129 void tegra_dc_disable(struct tegra_dc *dc)
1131 mutex_lock(&dc->lock);
1134 dc->enabled = false;
1137 _tegra_dc_disable(dc);
1140 mutex_unlock(&dc->lock);
1143 static void tegra_dc_reset_worker(struct work_struct *work)
1145 struct tegra_dc *dc =
1146 container_of(work, struct tegra_dc, reset_work);
1148 dev_warn(&dc->ndev->dev, "overlay stuck in underflow state. resetting.\n");
1150 mutex_lock(&dc->lock);
1151 if (dc->enabled && !dc->suspended) {
1152 _tegra_dc_disable(dc);
1154 /* A necessary wait. */
1156 tegra_periph_reset_assert(dc->clk);
1158 /* _tegra_dc_enable deasserts reset */
1159 _tegra_dc_enable(dc);
1161 mutex_unlock(&dc->lock);
1165 static int tegra_dc_probe(struct nvhost_device *ndev)
1167 struct tegra_dc *dc;
1169 struct clk *emc_clk;
1170 struct resource *res;
1171 struct resource *base_res;
1172 struct resource *fb_mem = NULL;
1177 unsigned long emc_clk_rate;
1179 if (!ndev->dev.platform_data) {
1180 dev_err(&ndev->dev, "no platform data\n");
1184 dc = kzalloc(sizeof(struct tegra_dc), GFP_KERNEL);
1186 dev_err(&ndev->dev, "can't allocate memory for tegra_dc\n");
1190 irq = nvhost_get_irq_byname(ndev, "irq");
1192 dev_err(&ndev->dev, "no irq\n");
1197 res = nvhost_get_resource_byname(ndev, IORESOURCE_MEM, "regs");
1199 dev_err(&ndev->dev, "no mem resource\n");
1204 base_res = request_mem_region(res->start, resource_size(res), ndev->name);
1206 dev_err(&ndev->dev, "request_mem_region failed\n");
1211 base = ioremap(res->start, resource_size(res));
1213 dev_err(&ndev->dev, "registers can't be mapped\n");
1215 goto err_release_resource_reg;
1218 fb_mem = nvhost_get_resource_byname(ndev, IORESOURCE_MEM, "fbmem");
1220 clk = clk_get(&ndev->dev, NULL);
1221 if (IS_ERR_OR_NULL(clk)) {
1222 dev_err(&ndev->dev, "can't get clock\n");
1224 goto err_iounmap_reg;
1227 emc_clk = clk_get(&ndev->dev, "emc");
1228 if (IS_ERR_OR_NULL(emc_clk)) {
1229 dev_err(&ndev->dev, "can't get emc clock\n");
1235 dc->emc_clk = emc_clk;
1236 dc->base_res = base_res;
1240 dc->pdata = ndev->dev.platform_data;
1243 * The emc is a shared clock, it will be set based on
1244 * the requirements for each user on the bus.
1246 emc_clk_rate = dc->pdata->emc_clk_rate;
1247 clk_set_rate(emc_clk, emc_clk_rate ? emc_clk_rate : ULONG_MAX);
1249 if (dc->pdata->flags & TEGRA_DC_FLAG_ENABLED)
1252 mutex_init(&dc->lock);
1253 init_waitqueue_head(&dc->wq);
1254 INIT_WORK(&dc->reset_work, tegra_dc_reset_worker);
1256 dc->n_windows = DC_N_WINDOWS;
1257 for (i = 0; i < dc->n_windows; i++) {
1258 dc->windows[i].idx = i;
1259 dc->windows[i].dc = dc;
1262 if (request_irq(irq, tegra_dc_irq, IRQF_DISABLED,
1263 dev_name(&ndev->dev), dc)) {
1264 dev_err(&ndev->dev, "request_irq %d failed\n", irq);
1266 goto err_put_emc_clk;
1269 /* hack to ballence enable_irq calls in _tegra_dc_enable() */
1270 disable_irq(dc->irq);
1272 ret = tegra_dc_add(dc, ndev->id);
1274 dev_err(&ndev->dev, "can't add dc\n");
1278 nvhost_set_drvdata(ndev, dc);
1280 if (dc->pdata->default_out)
1281 tegra_dc_set_out(dc, dc->pdata->default_out);
1283 dev_err(&ndev->dev, "No default output specified. Leaving output disabled.\n");
1286 _tegra_dc_enable(dc);
1288 tegra_dc_dbg_add(dc);
1290 dev_info(&ndev->dev, "probed\n");
1292 if (dc->pdata->fb) {
1293 if (dc->pdata->fb->bits_per_pixel == -1) {
1296 WINDOW_A_SELECT << dc->pdata->fb->win,
1297 DC_CMD_DISPLAY_WINDOW_HEADER);
1299 fmt = tegra_dc_readl(dc, DC_WIN_COLOR_DEPTH);
1300 dc->pdata->fb->bits_per_pixel =
1301 tegra_dc_fmt_bpp(fmt);
1304 dc->fb = tegra_fb_register(ndev, dc, dc->pdata->fb, fb_mem);
1305 if (IS_ERR_OR_NULL(dc->fb))
1309 if (dc->out_ops && dc->out_ops->detect)
1310 dc->out_ops->detect(dc);
1323 release_resource(fb_mem);
1324 err_release_resource_reg:
1325 release_resource(base_res);
1332 static int tegra_dc_remove(struct nvhost_device *ndev)
1334 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
1337 tegra_fb_unregister(dc->fb);
1339 release_resource(dc->fb_mem);
1344 _tegra_dc_disable(dc);
1346 free_irq(dc->irq, dc);
1347 clk_put(dc->emc_clk);
1351 release_resource(dc->base_res);
1357 static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state)
1359 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
1361 dev_info(&ndev->dev, "suspend\n");
1363 mutex_lock(&dc->lock);
1365 if (dc->out_ops && dc->out_ops->suspend)
1366 dc->out_ops->suspend(dc);
1369 tegra_fb_suspend(dc->fb);
1370 _tegra_dc_disable(dc);
1372 dc->suspended = true;
1374 mutex_unlock(&dc->lock);
1379 static int tegra_dc_resume(struct nvhost_device *ndev)
1381 struct tegra_dc *dc = nvhost_get_drvdata(ndev);
1383 dev_info(&ndev->dev, "resume\n");
1385 mutex_lock(&dc->lock);
1386 dc->suspended = false;
1389 _tegra_dc_enable(dc);
1391 if (dc->out_ops && dc->out_ops->resume)
1392 dc->out_ops->resume(dc);
1393 mutex_unlock(&dc->lock);
1400 extern int suspend_set(const char *val, struct kernel_param *kp)
1402 if (!strcmp(val, "dump"))
1403 dump_regs(tegra_dcs[0]);
1405 else if (!strcmp(val, "suspend"))
1406 tegra_dc_suspend(tegra_dcs[0]->ndev, PMSG_SUSPEND);
1407 else if (!strcmp(val, "resume"))
1408 tegra_dc_resume(tegra_dcs[0]->ndev);
1414 extern int suspend_get(char *buffer, struct kernel_param *kp)
1421 module_param_call(suspend, suspend_set, suspend_get, &suspend, 0644);
1423 struct nvhost_driver tegra_dc_driver = {
1426 .owner = THIS_MODULE,
1428 .probe = tegra_dc_probe,
1429 .remove = tegra_dc_remove,
1431 .suspend = tegra_dc_suspend,
1432 .resume = tegra_dc_resume,
1436 static int __init tegra_dc_module_init(void)
1438 return nvhost_driver_register(&tegra_dc_driver);
1441 static void __exit tegra_dc_module_exit(void)
1443 nvhost_driver_unregister(&tegra_dc_driver);
1446 module_exit(tegra_dc_module_exit);
1447 module_init(tegra_dc_module_init);