aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/tegra/dc.c55
-rw-r--r--drivers/gpu/drm/tegra/drm.c50
-rw-r--r--drivers/gpu/drm/tegra/drm.h3
3 files changed, 91 insertions, 17 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index ceb2f52c8f7e..5f55a25424a7 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -157,6 +157,32 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
157 return 0; 157 return 0;
158} 158}
159 159
160void tegra_dc_enable_vblank(struct tegra_dc *dc)
161{
162 unsigned long value, flags;
163
164 spin_lock_irqsave(&dc->lock, flags);
165
166 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
167 value |= VBLANK_INT;
168 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
169
170 spin_unlock_irqrestore(&dc->lock, flags);
171}
172
173void tegra_dc_disable_vblank(struct tegra_dc *dc)
174{
175 unsigned long value, flags;
176
177 spin_lock_irqsave(&dc->lock, flags);
178
179 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
180 value &= ~VBLANK_INT;
181 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
182
183 spin_unlock_irqrestore(&dc->lock, flags);
184}
185
160static const struct drm_crtc_funcs tegra_crtc_funcs = { 186static const struct drm_crtc_funcs tegra_crtc_funcs = {
161 .set_config = drm_crtc_helper_set_config, 187 .set_config = drm_crtc_helper_set_config,
162 .destroy = drm_crtc_cleanup, 188 .destroy = drm_crtc_cleanup,
@@ -485,6 +511,8 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
485 unsigned long div, value; 511 unsigned long div, value;
486 int err; 512 int err;
487 513
514 drm_vblank_pre_modeset(crtc->dev, dc->pipe);
515
488 err = tegra_crtc_setup_clk(crtc, mode, &div); 516 err = tegra_crtc_setup_clk(crtc, mode, &div);
489 if (err) { 517 if (err) {
490 dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err); 518 dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
@@ -585,31 +613,23 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
585 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER); 613 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
586 614
587 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; 615 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
588 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
589
590 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
591 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); 616 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
617
618 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
619 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
592} 620}
593 621
594static void tegra_crtc_commit(struct drm_crtc *crtc) 622static void tegra_crtc_commit(struct drm_crtc *crtc)
595{ 623{
596 struct tegra_dc *dc = to_tegra_dc(crtc); 624 struct tegra_dc *dc = to_tegra_dc(crtc);
597 unsigned long update_mask;
598 unsigned long value; 625 unsigned long value;
599 626
600 update_mask = GENERAL_ACT_REQ | WIN_A_ACT_REQ; 627 value = GENERAL_ACT_REQ | WIN_A_ACT_REQ |
601 628 GENERAL_UPDATE | WIN_A_UPDATE;
602 tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL);
603
604 value = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
605 value |= FRAME_END_INT;
606 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
607 629
608 value = tegra_dc_readl(dc, DC_CMD_INT_MASK); 630 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
609 value |= FRAME_END_INT;
610 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
611 631
612 tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); 632 drm_vblank_post_modeset(crtc->dev, dc->pipe);
613} 633}
614 634
615static void tegra_crtc_load_lut(struct drm_crtc *crtc) 635static void tegra_crtc_load_lut(struct drm_crtc *crtc)
@@ -626,7 +646,7 @@ static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
626 .load_lut = tegra_crtc_load_lut, 646 .load_lut = tegra_crtc_load_lut,
627}; 647};
628 648
629static irqreturn_t tegra_drm_irq(int irq, void *data) 649static irqreturn_t tegra_dc_irq(int irq, void *data)
630{ 650{
631 struct tegra_dc *dc = data; 651 struct tegra_dc *dc = data;
632 unsigned long status; 652 unsigned long status;
@@ -971,7 +991,7 @@ static int tegra_dc_drm_init(struct host1x_client *client,
971 dev_err(dc->dev, "debugfs setup failed: %d\n", err); 991 dev_err(dc->dev, "debugfs setup failed: %d\n", err);
972 } 992 }
973 993
974 err = devm_request_irq(dc->dev, dc->irq, tegra_drm_irq, 0, 994 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
975 dev_name(dc->dev), dc); 995 dev_name(dc->dev), dc);
976 if (err < 0) { 996 if (err < 0) {
977 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq, 997 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
@@ -1020,6 +1040,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
1020 if (!dc) 1040 if (!dc)
1021 return -ENOMEM; 1041 return -ENOMEM;
1022 1042
1043 spin_lock_init(&dc->lock);
1023 INIT_LIST_HEAD(&dc->list); 1044 INIT_LIST_HEAD(&dc->list);
1024 dc->dev = &pdev->dev; 1045 dc->dev = &pdev->dev;
1025 1046
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,
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 896ff43d32b1..01f0aee12ad9 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -64,6 +64,7 @@ struct tegra_output;
64 64
65struct tegra_dc { 65struct tegra_dc {
66 struct host1x_client client; 66 struct host1x_client client;
67 spinlock_t lock;
67 68
68 struct host1x *host1x; 69 struct host1x *host1x;
69 struct device *dev; 70 struct device *dev;
@@ -130,6 +131,8 @@ struct tegra_dc_window {
130extern unsigned int tegra_dc_format(uint32_t format); 131extern unsigned int tegra_dc_format(uint32_t format);
131extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, 132extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
132 const struct tegra_dc_window *window); 133 const struct tegra_dc_window *window);
134extern void tegra_dc_enable_vblank(struct tegra_dc *dc);
135extern void tegra_dc_disable_vblank(struct tegra_dc *dc);
133 136
134struct tegra_output_ops { 137struct tegra_output_ops {
135 int (*enable)(struct tegra_output *output); 138 int (*enable)(struct tegra_output *output);