aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/drm.c
diff options
context:
space:
mode:
authorThierry Reding <thierry.reding@avionic-design.de>2012-11-28 05:45:47 -0500
committerThierry Reding <thierry.reding@avionic-design.de>2013-02-22 02:21:23 -0500
commit6e5ff998997ba7dc5ca10b6662e95a9d07f764c4 (patch)
treee816da159f67fe32c93e824b2efd6f77c0a0aa47 /drivers/gpu/drm/tegra/drm.c
parent23fb47404e6118eb53fb34c95ed98a3f4f822a76 (diff)
drm/tegra: Implement VBLANK support
Implement support for the VBLANK IOCTL. Note that Tegra is somewhat special in this case because it doesn't use the generic IRQ support provided by the DRM core (DRIVER_HAVE_IRQ) but rather registers one interrupt handler for each display controller. While at it, clean up the way that interrupts are enabled to ensure that the VBLANK interrupt only gets enabled when required. Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Diffstat (limited to 'drivers/gpu/drm/tegra/drm.c')
-rw-r--r--drivers/gpu/drm/tegra/drm.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 3a503c9e4686..4e31dace5275 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -40,6 +40,10 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
40 if (err < 0) 40 if (err < 0)
41 return err; 41 return err;
42 42
43 err = drm_vblank_init(drm, drm->mode_config.num_crtc);
44 if (err < 0)
45 return err;
46
43 err = tegra_drm_fb_init(drm); 47 err = tegra_drm_fb_init(drm);
44 if (err < 0) 48 if (err < 0)
45 return err; 49 return err;
@@ -89,6 +93,48 @@ static const struct file_operations tegra_drm_fops = {
89 .llseek = noop_llseek, 93 .llseek = noop_llseek,
90}; 94};
91 95
96static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe)
97{
98 struct drm_crtc *crtc;
99
100 list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) {
101 struct tegra_dc *dc = to_tegra_dc(crtc);
102
103 if (dc->pipe == pipe)
104 return crtc;
105 }
106
107 return NULL;
108}
109
110static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc)
111{
112 /* TODO: implement real hardware counter using syncpoints */
113 return drm_vblank_count(dev, crtc);
114}
115
116static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
117{
118 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
119 struct tegra_dc *dc = to_tegra_dc(crtc);
120
121 if (!crtc)
122 return -ENODEV;
123
124 tegra_dc_enable_vblank(dc);
125
126 return 0;
127}
128
129static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe)
130{
131 struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
132 struct tegra_dc *dc = to_tegra_dc(crtc);
133
134 if (crtc)
135 tegra_dc_disable_vblank(dc);
136}
137
92struct drm_driver tegra_drm_driver = { 138struct drm_driver tegra_drm_driver = {
93 .driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM, 139 .driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM,
94 .load = tegra_drm_load, 140 .load = tegra_drm_load,
@@ -96,6 +142,10 @@ struct drm_driver tegra_drm_driver = {
96 .open = tegra_drm_open, 142 .open = tegra_drm_open,
97 .lastclose = tegra_drm_lastclose, 143 .lastclose = tegra_drm_lastclose,
98 144
145 .get_vblank_counter = tegra_drm_get_vblank_counter,
146 .enable_vblank = tegra_drm_enable_vblank,
147 .disable_vblank = tegra_drm_disable_vblank,
148
99 .gem_free_object = drm_gem_cma_free_object, 149 .gem_free_object = drm_gem_cma_free_object,
100 .gem_vm_ops = &drm_gem_cma_vm_ops, 150 .gem_vm_ops = &drm_gem_cma_vm_ops,
101 .dumb_create = drm_gem_cma_dumb_create, 151 .dumb_create = drm_gem_cma_dumb_create,