video: tegra: dc: power optimize DC and host1x clk
[linux-2.6.git] / drivers / video / tegra / dc / dc_priv.h
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  * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
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_PRIV_H
21 #define __DRIVERS_VIDEO_TEGRA_DC_DC_PRIV_H
22
23 #include <linux/io.h>
24 #include <linux/mutex.h>
25 #include <linux/wait.h>
26 #include <linux/fb.h>
27 #include <linux/clk.h>
28 #include <linux/completion.h>
29 #include <linux/switch.h>
30 #include <linux/nvhost.h>
31
32 #include <mach/dc.h>
33
34 #include <mach/tegra_dc_ext.h>
35 #include <mach/clk.h>
36
37 #include "dc_reg.h"
38
39 #define WIN_IS_TILED(win)       ((win)->flags & TEGRA_WIN_FLAG_TILED)
40 #define WIN_IS_ENABLED(win)     ((win)->flags & TEGRA_WIN_FLAG_ENABLED)
41
42 #define NEED_UPDATE_EMC_ON_EVERY_FRAME (windows_idle_detection_time == 0)
43
44 /* DDR: 8 bytes transfer per clock */
45 #define DDR_BW_TO_FREQ(bw) ((bw) / 8)
46
47 #if defined(CONFIG_TEGRA_EMC_TO_DDR_CLOCK)
48 #define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * CONFIG_TEGRA_EMC_TO_DDR_CLOCK)
49 #else
50 #define EMC_BW_TO_FREQ(bw) (DDR_BW_TO_FREQ(bw) * 2)
51 #endif
52
53 #ifndef CONFIG_TEGRA_FPGA_PLATFORM
54 #define ALL_UF_INT (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)
55 #else
56 /* ignore underflows when on simulation and fpga platform */
57 #define ALL_UF_INT (0)
58 #endif
59
60 struct tegra_dc;
61
62 struct tegra_dc_blend {
63         unsigned z[DC_N_WINDOWS];
64         unsigned flags[DC_N_WINDOWS];
65 };
66
67 struct tegra_dc_out_ops {
68         /* initialize output.  dc clocks are not on at this point */
69         int (*init)(struct tegra_dc *dc);
70         /* destroy output.  dc clocks are not on at this point */
71         void (*destroy)(struct tegra_dc *dc);
72         /* detect connected display.  can sleep.*/
73         bool (*detect)(struct tegra_dc *dc);
74         /* enable output.  dc clocks are on at this point */
75         void (*enable)(struct tegra_dc *dc);
76         /* disable output.  dc clocks are on at this point */
77         void (*disable)(struct tegra_dc *dc);
78         /* hold output.  keeps dc clocks on. */
79         void (*hold)(struct tegra_dc *dc);
80         /* release output.  dc clocks may turn off after this. */
81         void (*release)(struct tegra_dc *dc);
82         /* idle routine of output.  dc clocks may turn off after this. */
83         void (*idle)(struct tegra_dc *dc);
84         /* suspend output.  dc clocks are on at this point */
85         void (*suspend)(struct tegra_dc *dc);
86         /* resume output.  dc clocks are on at this point */
87         void (*resume)(struct tegra_dc *dc);
88         /* mode filter. to provide a list of supported modes*/
89         bool (*mode_filter)(const struct tegra_dc *dc,
90                         struct fb_videomode *mode);
91 };
92
93 struct tegra_dc {
94         struct nvhost_device            *ndev;
95         struct tegra_dc_platform_data   *pdata;
96
97         struct resource                 *base_res;
98         void __iomem                    *base;
99         int                             irq;
100
101         struct clk                      *clk;
102         struct clk                      *emc_clk;
103         int                             emc_clk_rate;
104         int                             new_emc_clk_rate;
105         u32                             shift_clk_div;
106
107         bool                            connected;
108         bool                            enabled;
109         bool                            suspended;
110
111         struct tegra_dc_out             *out;
112         struct tegra_dc_out_ops         *out_ops;
113         void                            *out_data;
114
115         struct tegra_dc_mode            mode;
116
117         struct tegra_dc_win             windows[DC_N_WINDOWS];
118         struct tegra_dc_blend           blend;
119         int                             n_windows;
120
121         wait_queue_head_t               wq;
122
123         struct mutex                    lock;
124         struct mutex                    one_shot_lock;
125
126         struct resource                 *fb_mem;
127         struct tegra_fb_info            *fb;
128
129         struct {
130                 u32                     id;
131                 u32                     min;
132                 u32                     max;
133         } syncpt[DC_N_WINDOWS];
134         u32                             vblank_syncpt;
135
136         unsigned long                   underflow_mask;
137         struct work_struct              reset_work;
138
139 #ifdef CONFIG_SWITCH
140         struct switch_dev               modeset_switch;
141 #endif
142
143         struct completion               frame_end_complete;
144
145         struct work_struct              vblank_work;
146         long                            vblank_ref_count;
147
148         struct {
149                 u64                     underflows;
150                 u64                     underflows_a;
151                 u64                     underflows_b;
152                 u64                     underflows_c;
153         } stats;
154
155         struct tegra_dc_ext             *ext;
156
157         struct tegra_dc_feature         *feature;
158
159 #ifdef CONFIG_DEBUG_FS
160         struct dentry                   *debugdir;
161 #endif
162         struct tegra_dc_lut             fb_lut;
163         struct delayed_work             underflow_work;
164         u32                             one_shot_delay_ms;
165         struct delayed_work             one_shot_work;
166 };
167
168 #define print_mode_info(dc, mode) do {                                  \
169         trace_printk("%s:Mode settings: "                               \
170                         "ref_to_sync: H = %d V = %d, "                  \
171                         "sync_width: H = %d V = %d, "                   \
172                         "back_porch: H = %d V = %d, "                   \
173                         "active: H = %d V = %d, "                       \
174                         "front_porch: H = %d V = %d, "                  \
175                         "pclk = %d, stereo mode = %d\n",                \
176                         dc->ndev->name,                                 \
177                         mode.h_ref_to_sync, mode.v_ref_to_sync,         \
178                         mode.h_sync_width, mode.v_sync_width,           \
179                         mode.h_back_porch, mode.v_back_porch,           \
180                         mode.h_active, mode.v_active,                   \
181                         mode.h_front_porch, mode.v_front_porch,         \
182                         mode.pclk, mode.stereo_mode);                   \
183         } while (0)
184
185 static inline void tegra_dc_io_start(struct tegra_dc *dc)
186 {
187         nvhost_module_busy_ext(nvhost_get_parent(dc->ndev));
188 }
189
190 static inline void tegra_dc_io_end(struct tegra_dc *dc)
191 {
192         nvhost_module_idle_ext(nvhost_get_parent(dc->ndev));
193 }
194
195 static inline unsigned long tegra_dc_readl(struct tegra_dc *dc,
196                                            unsigned long reg)
197 {
198         unsigned long ret;
199
200         BUG_ON(!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev)));
201         if (!tegra_is_clk_enabled(dc->clk))
202                 WARN(1, "DC is clock-gated.\n");
203
204         ret = readl(dc->base + reg * 4);
205         trace_printk("readl %p=%#08lx\n", dc->base + reg * 4, ret);
206         return ret;
207 }
208
209 static inline void tegra_dc_writel(struct tegra_dc *dc, unsigned long val,
210                                    unsigned long reg)
211 {
212         BUG_ON(!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev)));
213         if (!tegra_is_clk_enabled(dc->clk))
214                 WARN(1, "DC is clock-gated.\n");
215
216         trace_printk("writel %p=%#08lx\n", dc->base + reg * 4, val);
217         writel(val, dc->base + reg * 4);
218 }
219
220 static inline void _tegra_dc_write_table(struct tegra_dc *dc, const u32 *table,
221                                          unsigned len)
222 {
223         int i;
224
225         for (i = 0; i < len; i++)
226                 tegra_dc_writel(dc, table[i * 2 + 1], table[i * 2]);
227 }
228
229 #define tegra_dc_write_table(dc, table)         \
230         _tegra_dc_write_table(dc, table, ARRAY_SIZE(table) / 2)
231
232 static inline void tegra_dc_set_outdata(struct tegra_dc *dc, void *data)
233 {
234         dc->out_data = data;
235 }
236
237 static inline void *tegra_dc_get_outdata(struct tegra_dc *dc)
238 {
239         return dc->out_data;
240 }
241
242 static inline unsigned long tegra_dc_get_default_emc_clk_rate(
243         struct tegra_dc *dc)
244 {
245         return dc->pdata->emc_clk_rate ? dc->pdata->emc_clk_rate : ULONG_MAX;
246 }
247
248 static inline int tegra_dc_fmt_bpp(int fmt)
249 {
250         switch (fmt) {
251         case TEGRA_WIN_FMT_P1:
252                 return 1;
253
254         case TEGRA_WIN_FMT_P2:
255                 return 2;
256
257         case TEGRA_WIN_FMT_P4:
258                 return 4;
259
260         case TEGRA_WIN_FMT_P8:
261                 return 8;
262
263         case TEGRA_WIN_FMT_B4G4R4A4:
264         case TEGRA_WIN_FMT_B5G5R5A:
265         case TEGRA_WIN_FMT_B5G6R5:
266         case TEGRA_WIN_FMT_AB5G5R5:
267                 return 16;
268
269         case TEGRA_WIN_FMT_B8G8R8A8:
270         case TEGRA_WIN_FMT_R8G8B8A8:
271         case TEGRA_WIN_FMT_B6x2G6x2R6x2A8:
272         case TEGRA_WIN_FMT_R6x2G6x2B6x2A8:
273                 return 32;
274
275         /* for planar formats, size of the Y plane, 8bit */
276         case TEGRA_WIN_FMT_YCbCr420P:
277         case TEGRA_WIN_FMT_YUV420P:
278         case TEGRA_WIN_FMT_YCbCr422P:
279         case TEGRA_WIN_FMT_YUV422P:
280         case TEGRA_WIN_FMT_YCbCr422R:
281         case TEGRA_WIN_FMT_YUV422R:
282         case TEGRA_WIN_FMT_YCbCr422RA:
283         case TEGRA_WIN_FMT_YUV422RA:
284                 return 8;
285
286         /* YUYV packed into 32-bits */
287         case TEGRA_WIN_FMT_YCbCr422:
288         case TEGRA_WIN_FMT_YUV422:
289                 return 16;
290         }
291         return 0;
292 }
293
294 static inline bool tegra_dc_is_yuv(int fmt)
295 {
296         switch (fmt) {
297         case TEGRA_WIN_FMT_YUV420P:
298         case TEGRA_WIN_FMT_YCbCr420P:
299         case TEGRA_WIN_FMT_YCbCr422P:
300         case TEGRA_WIN_FMT_YUV422P:
301         case TEGRA_WIN_FMT_YCbCr422:
302         case TEGRA_WIN_FMT_YUV422:
303         case TEGRA_WIN_FMT_YCbCr422R:
304         case TEGRA_WIN_FMT_YUV422R:
305         case TEGRA_WIN_FMT_YCbCr422RA:
306         case TEGRA_WIN_FMT_YUV422RA:
307                 return true;
308         }
309         return false;
310 }
311
312 static inline bool tegra_dc_is_yuv_planar(int fmt)
313 {
314         switch (fmt) {
315         case TEGRA_WIN_FMT_YUV420P:
316         case TEGRA_WIN_FMT_YCbCr420P:
317         case TEGRA_WIN_FMT_YCbCr422P:
318         case TEGRA_WIN_FMT_YUV422P:
319         case TEGRA_WIN_FMT_YCbCr422R:
320         case TEGRA_WIN_FMT_YUV422R:
321         case TEGRA_WIN_FMT_YCbCr422RA:
322         case TEGRA_WIN_FMT_YUV422RA:
323                 return true;
324         }
325         return false;
326 }
327
328 static inline u32 tegra_dc_unmask_interrupt(struct tegra_dc *dc, u32 int_val)
329 {
330         u32 val;
331
332         val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
333         tegra_dc_writel(dc, val | int_val, DC_CMD_INT_MASK);
334         return val;
335 }
336
337 static inline u32 tegra_dc_mask_interrupt(struct tegra_dc *dc, u32 int_val)
338 {
339         u32 val;
340
341         val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
342         tegra_dc_writel(dc, val & ~int_val, DC_CMD_INT_MASK);
343         return val;
344 }
345
346 static inline void tegra_dc_restore_interrupt(struct tegra_dc *dc, u32 val)
347 {
348         tegra_dc_writel(dc, val, DC_CMD_INT_MASK);
349 }
350
351 static inline unsigned long tegra_dc_clk_get_rate(struct tegra_dc *dc)
352 {
353 #ifdef CONFIG_TEGRA_SILICON_PLATFORM
354         return clk_get_rate(dc->clk);
355 #else
356         return dc->mode.pclk;
357 #endif
358 }
359
360 extern struct tegra_dc_out_ops tegra_dc_rgb_ops;
361 extern struct tegra_dc_out_ops tegra_dc_hdmi_ops;
362 extern struct tegra_dc_out_ops tegra_dc_dsi_ops;
363
364 /* defined in dc_sysfs.c, used by dc.c */
365 void __devexit tegra_dc_remove_sysfs(struct device *dev);
366 void tegra_dc_create_sysfs(struct device *dev);
367
368 /* defined in dc.c, used by dc_sysfs.c */
369 void tegra_dc_stats_enable(struct tegra_dc *dc, bool enable);
370 bool tegra_dc_stats_get(struct tegra_dc *dc);
371
372 /* defined in dc.c, used by dc_sysfs.c */
373 u32 tegra_dc_read_checksum_latched(struct tegra_dc *dc);
374 void tegra_dc_enable_crc(struct tegra_dc *dc);
375 void tegra_dc_disable_crc(struct tegra_dc *dc);
376
377 void tegra_dc_set_out_pin_polars(struct tegra_dc *dc,
378                                 const struct tegra_dc_out_pin *pins,
379                                 const unsigned int n_pins);
380 /* defined in dc.c, used in bandwidth.c and ext/dev.c */
381 unsigned int tegra_dc_has_multiple_dc(void);
382
383 /* defined in dc.c, used in dsi.c */
384 void tegra_dc_clk_enable(struct tegra_dc *dc);
385 void tegra_dc_clk_disable(struct tegra_dc *dc);
386
387 /* defined in dc.c, used in nvsd.c and dsi.c */
388 void tegra_dc_hold_dc_out(struct tegra_dc *dc);
389 void tegra_dc_release_dc_out(struct tegra_dc *dc);
390
391 /* defined in bandwidth.c, used in dc.c */
392 void tegra_dc_clear_bandwidth(struct tegra_dc *dc);
393 void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new);
394 int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n);
395
396 /* defined in mode.c, used in dc.c */
397 int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode);
398 int tegra_dc_calc_refresh(const struct tegra_dc_mode *m);
399
400 /* defined in clock.c, used in dc.c, dsi.c and hdmi.c */
401 void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
402 unsigned long tegra_dc_pclk_round_rate(struct tegra_dc *dc, int pclk);
403
404 /* defined in lut.c, used in dc.c */
405 void tegra_dc_init_lut_defaults(struct tegra_dc_lut *lut);
406 void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win *win);
407
408 /* defined in csc.c, used in dc.c */
409 void tegra_dc_init_csc_defaults(struct tegra_dc_csc *csc);
410 void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc);
411
412 /* defined in window.c, used in dc.c */
413 void tegra_dc_trigger_windows(struct tegra_dc *dc);
414
415 #endif