diff options
author | Dave Airlie <airlied@redhat.com> | 2013-04-15 23:20:03 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-04-15 23:20:03 -0400 |
commit | dea14dfab9d1fdf5695ae61dc72c587533706edc (patch) | |
tree | b30f80f3581c706f29911cbe334f6b35569a5847 /drivers/gpu/drm | |
parent | e4fda9f264e154946c678ca7ff07023f573abf6a (diff) | |
parent | 3d62fe5b214fce69ae14abbdb88794a753418614 (diff) |
Merge tag 'omapdss-for-3.10' of git://gitorious.org/linux-omap-dss2/linux into drm-next
Omapdss patches for 3.10 merge window
The biggest changes are:
* DSI video mode: automatic clock and timing calculation
* Lots of platform data related panel driver cleanups, to prepare for DT
* tag 'omapdss-for-3.10' of git://gitorious.org/linux-omap-dss2/linux: (69 commits)
drm/omap: add statics to a few structs
drm/omap: Fix and improve crtc and overlay manager correlation
drm/omap: Take a fb reference in omap_plane_update()
drm/omap: Make fixed resolution panels work
drm/omap: fix modeset_init if a panel doesn't satisfy omapdrm requirements
OMAPDSS: DPI: widen the pck search when using dss fck
OMAPDSS: fix dss_fck clock rate rounding
omapdss: use devm_clk_get()
OMAPDSS: nec-nl8048 panel: Use dev_pm_ops
OMAPDSS: DISPC: Revert to older DISPC Smart Standby mechanism for OMAP5
OMAPDSS: DISPC: Configure doublestride for NV12 when using 2D Tiler buffers
omapdss: Features: Fix some parameter ranges
omapdss: DISPC: add max pixel clock limits for LCD and TV managers
OMAPDSS: DSI: Use devm_clk_get()
drivers: video: omap2: dss: Use PTR_RET function
OMAPDSS: VENC: remove platform_enable/disable calls
OMAPDSS: n8x0 panel: remove use of platform_enable/disable
OMAPDSS: n8x0 panel: handle gpio data in panel driver
OMAPDSS: picodlp panel: remove platform_enable/disable callbacks
OMAPDSS: picodlp panel: handle gpio data in panel driver
...
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_connector.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 165 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_encoder.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_irq.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_plane.c | 6 |
8 files changed, 216 insertions, 84 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index c451c41a7a7d..912759daf562 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c | |||
@@ -110,6 +110,11 @@ static enum drm_connector_status omap_connector_detect( | |||
110 | ret = connector_status_connected; | 110 | ret = connector_status_connected; |
111 | else | 111 | else |
112 | ret = connector_status_disconnected; | 112 | ret = connector_status_disconnected; |
113 | } else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI || | ||
114 | dssdev->type == OMAP_DISPLAY_TYPE_DBI || | ||
115 | dssdev->type == OMAP_DISPLAY_TYPE_SDI || | ||
116 | dssdev->type == OMAP_DISPLAY_TYPE_DSI) { | ||
117 | ret = connector_status_connected; | ||
113 | } else { | 118 | } else { |
114 | ret = connector_status_unknown; | 119 | ret = connector_status_unknown; |
115 | } | 120 | } |
@@ -189,12 +194,30 @@ static int omap_connector_mode_valid(struct drm_connector *connector, | |||
189 | struct omap_video_timings timings = {0}; | 194 | struct omap_video_timings timings = {0}; |
190 | struct drm_device *dev = connector->dev; | 195 | struct drm_device *dev = connector->dev; |
191 | struct drm_display_mode *new_mode; | 196 | struct drm_display_mode *new_mode; |
192 | int ret = MODE_BAD; | 197 | int r, ret = MODE_BAD; |
193 | 198 | ||
194 | copy_timings_drm_to_omap(&timings, mode); | 199 | copy_timings_drm_to_omap(&timings, mode); |
195 | mode->vrefresh = drm_mode_vrefresh(mode); | 200 | mode->vrefresh = drm_mode_vrefresh(mode); |
196 | 201 | ||
197 | if (!dssdrv->check_timings(dssdev, &timings)) { | 202 | /* |
203 | * if the panel driver doesn't have a check_timings, it's most likely | ||
204 | * a fixed resolution panel, check if the timings match with the | ||
205 | * panel's timings | ||
206 | */ | ||
207 | if (dssdrv->check_timings) { | ||
208 | r = dssdrv->check_timings(dssdev, &timings); | ||
209 | } else { | ||
210 | struct omap_video_timings t = {0}; | ||
211 | |||
212 | dssdrv->get_timings(dssdev, &t); | ||
213 | |||
214 | if (memcmp(&timings, &t, sizeof(struct omap_video_timings))) | ||
215 | r = -EINVAL; | ||
216 | else | ||
217 | r = 0; | ||
218 | } | ||
219 | |||
220 | if (!r) { | ||
198 | /* check if vrefresh is still valid */ | 221 | /* check if vrefresh is still valid */ |
199 | new_mode = drm_mode_duplicate(dev, mode); | 222 | new_mode = drm_mode_duplicate(dev, mode); |
200 | new_mode->clock = timings.pixel_clock; | 223 | new_mode->clock = timings.pixel_clock; |
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index bec66a490b8f..79b200aee18a 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
@@ -74,6 +74,13 @@ struct omap_crtc { | |||
74 | struct work_struct page_flip_work; | 74 | struct work_struct page_flip_work; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | uint32_t pipe2vbl(struct drm_crtc *crtc) | ||
78 | { | ||
79 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
80 | |||
81 | return dispc_mgr_get_vsync_irq(omap_crtc->channel); | ||
82 | } | ||
83 | |||
77 | /* | 84 | /* |
78 | * Manager-ops, callbacks from output when they need to configure | 85 | * Manager-ops, callbacks from output when they need to configure |
79 | * the upstream part of the video pipe. | 86 | * the upstream part of the video pipe. |
@@ -613,7 +620,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, | |||
613 | omap_crtc->apply.pre_apply = omap_crtc_pre_apply; | 620 | omap_crtc->apply.pre_apply = omap_crtc_pre_apply; |
614 | omap_crtc->apply.post_apply = omap_crtc_post_apply; | 621 | omap_crtc->apply.post_apply = omap_crtc_post_apply; |
615 | 622 | ||
616 | omap_crtc->apply_irq.irqmask = pipe2vbl(id); | 623 | omap_crtc->channel = channel; |
624 | omap_crtc->plane = plane; | ||
625 | omap_crtc->plane->crtc = crtc; | ||
626 | omap_crtc->name = channel_names[channel]; | ||
627 | omap_crtc->pipe = id; | ||
628 | |||
629 | omap_crtc->apply_irq.irqmask = pipe2vbl(crtc); | ||
617 | omap_crtc->apply_irq.irq = omap_crtc_apply_irq; | 630 | omap_crtc->apply_irq.irq = omap_crtc_apply_irq; |
618 | 631 | ||
619 | omap_crtc->error_irq.irqmask = | 632 | omap_crtc->error_irq.irqmask = |
@@ -621,12 +634,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, | |||
621 | omap_crtc->error_irq.irq = omap_crtc_error_irq; | 634 | omap_crtc->error_irq.irq = omap_crtc_error_irq; |
622 | omap_irq_register(dev, &omap_crtc->error_irq); | 635 | omap_irq_register(dev, &omap_crtc->error_irq); |
623 | 636 | ||
624 | omap_crtc->channel = channel; | ||
625 | omap_crtc->plane = plane; | ||
626 | omap_crtc->plane->crtc = crtc; | ||
627 | omap_crtc->name = channel_names[channel]; | ||
628 | omap_crtc->pipe = id; | ||
629 | |||
630 | /* temporary: */ | 637 | /* temporary: */ |
631 | omap_crtc->mgr.id = channel; | 638 | omap_crtc->mgr.id = channel; |
632 | 639 | ||
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 079c54c6f94c..9c53c25e5201 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
@@ -74,54 +74,53 @@ static int get_connector_type(struct omap_dss_device *dssdev) | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | static bool channel_used(struct drm_device *dev, enum omap_channel channel) | ||
78 | { | ||
79 | struct omap_drm_private *priv = dev->dev_private; | ||
80 | int i; | ||
81 | |||
82 | for (i = 0; i < priv->num_crtcs; i++) { | ||
83 | struct drm_crtc *crtc = priv->crtcs[i]; | ||
84 | |||
85 | if (omap_crtc_channel(crtc) == channel) | ||
86 | return true; | ||
87 | } | ||
88 | |||
89 | return false; | ||
90 | } | ||
91 | |||
77 | static int omap_modeset_init(struct drm_device *dev) | 92 | static int omap_modeset_init(struct drm_device *dev) |
78 | { | 93 | { |
79 | struct omap_drm_private *priv = dev->dev_private; | 94 | struct omap_drm_private *priv = dev->dev_private; |
80 | struct omap_dss_device *dssdev = NULL; | 95 | struct omap_dss_device *dssdev = NULL; |
81 | int num_ovls = dss_feat_get_num_ovls(); | 96 | int num_ovls = dss_feat_get_num_ovls(); |
82 | int id; | 97 | int num_mgrs = dss_feat_get_num_mgrs(); |
98 | int num_crtcs; | ||
99 | int i, id = 0; | ||
83 | 100 | ||
84 | drm_mode_config_init(dev); | 101 | drm_mode_config_init(dev); |
85 | 102 | ||
86 | omap_drm_irq_install(dev); | 103 | omap_drm_irq_install(dev); |
87 | 104 | ||
88 | /* | 105 | /* |
89 | * Create private planes and CRTCs for the last NUM_CRTCs overlay | 106 | * We usually don't want to create a CRTC for each manager, at least |
90 | * plus manager: | 107 | * not until we have a way to expose private planes to userspace. |
108 | * Otherwise there would not be enough video pipes left for drm planes. | ||
109 | * We use the num_crtc argument to limit the number of crtcs we create. | ||
91 | */ | 110 | */ |
92 | for (id = 0; id < min(num_crtc, num_ovls); id++) { | 111 | num_crtcs = min3(num_crtc, num_mgrs, num_ovls); |
93 | struct drm_plane *plane; | ||
94 | struct drm_crtc *crtc; | ||
95 | |||
96 | plane = omap_plane_init(dev, id, true); | ||
97 | crtc = omap_crtc_init(dev, plane, pipe2chan(id), id); | ||
98 | 112 | ||
99 | BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); | 113 | dssdev = NULL; |
100 | priv->crtcs[id] = crtc; | ||
101 | priv->num_crtcs++; | ||
102 | |||
103 | priv->planes[id] = plane; | ||
104 | priv->num_planes++; | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * Create normal planes for the remaining overlays: | ||
109 | */ | ||
110 | for (; id < num_ovls; id++) { | ||
111 | struct drm_plane *plane = omap_plane_init(dev, id, false); | ||
112 | |||
113 | BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); | ||
114 | priv->planes[priv->num_planes++] = plane; | ||
115 | } | ||
116 | 114 | ||
117 | for_each_dss_dev(dssdev) { | 115 | for_each_dss_dev(dssdev) { |
118 | struct drm_connector *connector; | 116 | struct drm_connector *connector; |
119 | struct drm_encoder *encoder; | 117 | struct drm_encoder *encoder; |
118 | enum omap_channel channel; | ||
120 | 119 | ||
121 | if (!dssdev->driver) { | 120 | if (!dssdev->driver) { |
122 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | 121 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", |
123 | dssdev->name); | 122 | dssdev->name); |
124 | return 0; | 123 | continue; |
125 | } | 124 | } |
126 | 125 | ||
127 | if (!(dssdev->driver->get_timings || | 126 | if (!(dssdev->driver->get_timings || |
@@ -129,7 +128,7 @@ static int omap_modeset_init(struct drm_device *dev) | |||
129 | dev_warn(dev->dev, "%s driver does not support " | 128 | dev_warn(dev->dev, "%s driver does not support " |
130 | "get_timings or read_edid.. skipping it!\n", | 129 | "get_timings or read_edid.. skipping it!\n", |
131 | dssdev->name); | 130 | dssdev->name); |
132 | return 0; | 131 | continue; |
133 | } | 132 | } |
134 | 133 | ||
135 | encoder = omap_encoder_init(dev, dssdev); | 134 | encoder = omap_encoder_init(dev, dssdev); |
@@ -157,16 +156,118 @@ static int omap_modeset_init(struct drm_device *dev) | |||
157 | 156 | ||
158 | drm_mode_connector_attach_encoder(connector, encoder); | 157 | drm_mode_connector_attach_encoder(connector, encoder); |
159 | 158 | ||
159 | /* | ||
160 | * if we have reached the limit of the crtcs we are allowed to | ||
161 | * create, let's not try to look for a crtc for this | ||
162 | * panel/encoder and onwards, we will, of course, populate the | ||
163 | * the possible_crtcs field for all the encoders with the final | ||
164 | * set of crtcs we create | ||
165 | */ | ||
166 | if (id == num_crtcs) | ||
167 | continue; | ||
168 | |||
169 | /* | ||
170 | * get the recommended DISPC channel for this encoder. For now, | ||
171 | * we only try to get create a crtc out of the recommended, the | ||
172 | * other possible channels to which the encoder can connect are | ||
173 | * not considered. | ||
174 | */ | ||
175 | channel = dssdev->output->dispc_channel; | ||
176 | |||
177 | /* | ||
178 | * if this channel hasn't already been taken by a previously | ||
179 | * allocated crtc, we create a new crtc for it | ||
180 | */ | ||
181 | if (!channel_used(dev, channel)) { | ||
182 | struct drm_plane *plane; | ||
183 | struct drm_crtc *crtc; | ||
184 | |||
185 | plane = omap_plane_init(dev, id, true); | ||
186 | crtc = omap_crtc_init(dev, plane, channel, id); | ||
187 | |||
188 | BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); | ||
189 | priv->crtcs[id] = crtc; | ||
190 | priv->num_crtcs++; | ||
191 | |||
192 | priv->planes[id] = plane; | ||
193 | priv->num_planes++; | ||
194 | |||
195 | id++; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * we have allocated crtcs according to the need of the panels/encoders, | ||
201 | * adding more crtcs here if needed | ||
202 | */ | ||
203 | for (; id < num_crtcs; id++) { | ||
204 | |||
205 | /* find a free manager for this crtc */ | ||
206 | for (i = 0; i < num_mgrs; i++) { | ||
207 | if (!channel_used(dev, i)) { | ||
208 | struct drm_plane *plane; | ||
209 | struct drm_crtc *crtc; | ||
210 | |||
211 | plane = omap_plane_init(dev, id, true); | ||
212 | crtc = omap_crtc_init(dev, plane, i, id); | ||
213 | |||
214 | BUG_ON(priv->num_crtcs >= | ||
215 | ARRAY_SIZE(priv->crtcs)); | ||
216 | |||
217 | priv->crtcs[id] = crtc; | ||
218 | priv->num_crtcs++; | ||
219 | |||
220 | priv->planes[id] = plane; | ||
221 | priv->num_planes++; | ||
222 | |||
223 | break; | ||
224 | } else { | ||
225 | continue; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | if (i == num_mgrs) { | ||
230 | /* this shouldn't really happen */ | ||
231 | dev_err(dev->dev, "no managers left for crtc\n"); | ||
232 | return -ENOMEM; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * Create normal planes for the remaining overlays: | ||
238 | */ | ||
239 | for (; id < num_ovls; id++) { | ||
240 | struct drm_plane *plane = omap_plane_init(dev, id, false); | ||
241 | |||
242 | BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); | ||
243 | priv->planes[priv->num_planes++] = plane; | ||
244 | } | ||
245 | |||
246 | for (i = 0; i < priv->num_encoders; i++) { | ||
247 | struct drm_encoder *encoder = priv->encoders[i]; | ||
248 | struct omap_dss_device *dssdev = | ||
249 | omap_encoder_get_dssdev(encoder); | ||
250 | |||
160 | /* figure out which crtc's we can connect the encoder to: */ | 251 | /* figure out which crtc's we can connect the encoder to: */ |
161 | encoder->possible_crtcs = 0; | 252 | encoder->possible_crtcs = 0; |
162 | for (id = 0; id < priv->num_crtcs; id++) { | 253 | for (id = 0; id < priv->num_crtcs; id++) { |
163 | enum omap_dss_output_id supported_outputs = | 254 | struct drm_crtc *crtc = priv->crtcs[id]; |
164 | dss_feat_get_supported_outputs(pipe2chan(id)); | 255 | enum omap_channel crtc_channel; |
256 | enum omap_dss_output_id supported_outputs; | ||
257 | |||
258 | crtc_channel = omap_crtc_channel(crtc); | ||
259 | supported_outputs = | ||
260 | dss_feat_get_supported_outputs(crtc_channel); | ||
261 | |||
165 | if (supported_outputs & dssdev->output->id) | 262 | if (supported_outputs & dssdev->output->id) |
166 | encoder->possible_crtcs |= (1 << id); | 263 | encoder->possible_crtcs |= (1 << id); |
167 | } | 264 | } |
168 | } | 265 | } |
169 | 266 | ||
267 | DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", | ||
268 | priv->num_planes, priv->num_crtcs, priv->num_encoders, | ||
269 | priv->num_connectors); | ||
270 | |||
170 | dev->mode_config.min_width = 32; | 271 | dev->mode_config.min_width = 32; |
171 | dev->mode_config.min_height = 32; | 272 | dev->mode_config.min_height = 32; |
172 | 273 | ||
@@ -303,7 +404,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, | |||
303 | return ret; | 404 | return ret; |
304 | } | 405 | } |
305 | 406 | ||
306 | struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = { | 407 | static struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = { |
307 | DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH), | 408 | DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH), |
308 | DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 409 | DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
309 | DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH), | 410 | DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH), |
@@ -567,7 +668,7 @@ static const struct dev_pm_ops omapdrm_pm_ops = { | |||
567 | }; | 668 | }; |
568 | #endif | 669 | #endif |
569 | 670 | ||
570 | struct platform_driver pdev = { | 671 | static struct platform_driver pdev = { |
571 | .driver = { | 672 | .driver = { |
572 | .name = DRIVER_NAME, | 673 | .name = DRIVER_NAME, |
573 | .owner = THIS_MODULE, | 674 | .owner = THIS_MODULE, |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index d4f997bb4ac0..215a20dd340c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
@@ -139,8 +139,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); | |||
139 | int omap_gem_resume(struct device *dev); | 139 | int omap_gem_resume(struct device *dev); |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc); | 142 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id); |
143 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc); | 143 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id); |
144 | irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); | 144 | irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); |
145 | void omap_irq_preinstall(struct drm_device *dev); | 145 | void omap_irq_preinstall(struct drm_device *dev); |
146 | int omap_irq_postinstall(struct drm_device *dev); | 146 | int omap_irq_postinstall(struct drm_device *dev); |
@@ -271,39 +271,9 @@ static inline int align_pitch(int pitch, int width, int bpp) | |||
271 | return ALIGN(pitch, 8 * bytespp); | 271 | return ALIGN(pitch, 8 * bytespp); |
272 | } | 272 | } |
273 | 273 | ||
274 | static inline enum omap_channel pipe2chan(int pipe) | ||
275 | { | ||
276 | int num_mgrs = dss_feat_get_num_mgrs(); | ||
277 | |||
278 | /* | ||
279 | * We usually don't want to create a CRTC for each manager, | ||
280 | * at least not until we have a way to expose private planes | ||
281 | * to userspace. Otherwise there would not be enough video | ||
282 | * pipes left for drm planes. The higher #'d managers tend | ||
283 | * to have more features so start in reverse order. | ||
284 | */ | ||
285 | return num_mgrs - pipe - 1; | ||
286 | } | ||
287 | |||
288 | /* map crtc to vblank mask */ | 274 | /* map crtc to vblank mask */ |
289 | static inline uint32_t pipe2vbl(int crtc) | 275 | uint32_t pipe2vbl(struct drm_crtc *crtc); |
290 | { | 276 | struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder); |
291 | enum omap_channel channel = pipe2chan(crtc); | ||
292 | return dispc_mgr_get_vsync_irq(channel); | ||
293 | } | ||
294 | |||
295 | static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc) | ||
296 | { | ||
297 | struct omap_drm_private *priv = dev->dev_private; | ||
298 | int i; | ||
299 | |||
300 | for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++) | ||
301 | if (priv->crtcs[i] == crtc) | ||
302 | return i; | ||
303 | |||
304 | BUG(); /* bogus CRTC ptr */ | ||
305 | return -1; | ||
306 | } | ||
307 | 277 | ||
308 | /* should these be made into common util helpers? | 278 | /* should these be made into common util helpers? |
309 | */ | 279 | */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 21d126d0317e..c29451ba65da 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c | |||
@@ -41,6 +41,13 @@ struct omap_encoder { | |||
41 | struct omap_dss_device *dssdev; | 41 | struct omap_dss_device *dssdev; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder) | ||
45 | { | ||
46 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
47 | |||
48 | return omap_encoder->dssdev; | ||
49 | } | ||
50 | |||
44 | static void omap_encoder_destroy(struct drm_encoder *encoder) | 51 | static void omap_encoder_destroy(struct drm_encoder *encoder) |
45 | { | 52 | { |
46 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 53 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
@@ -128,13 +135,26 @@ int omap_encoder_update(struct drm_encoder *encoder, | |||
128 | 135 | ||
129 | dssdev->output->manager = mgr; | 136 | dssdev->output->manager = mgr; |
130 | 137 | ||
131 | ret = dssdrv->check_timings(dssdev, timings); | 138 | if (dssdrv->check_timings) { |
139 | ret = dssdrv->check_timings(dssdev, timings); | ||
140 | } else { | ||
141 | struct omap_video_timings t = {0}; | ||
142 | |||
143 | dssdrv->get_timings(dssdev, &t); | ||
144 | |||
145 | if (memcmp(timings, &t, sizeof(struct omap_video_timings))) | ||
146 | ret = -EINVAL; | ||
147 | else | ||
148 | ret = 0; | ||
149 | } | ||
150 | |||
132 | if (ret) { | 151 | if (ret) { |
133 | dev_err(dev->dev, "could not set timings: %d\n", ret); | 152 | dev_err(dev->dev, "could not set timings: %d\n", ret); |
134 | return ret; | 153 | return ret; |
135 | } | 154 | } |
136 | 155 | ||
137 | dssdrv->set_timings(dssdev, timings); | 156 | if (dssdrv->set_timings) |
157 | dssdrv->set_timings(dssdev, timings); | ||
138 | 158 | ||
139 | return 0; | 159 | return 0; |
140 | } | 160 | } |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index ac74d1bc67bf..0682cb5c0150 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | |||
@@ -178,7 +178,7 @@ out_unlock: | |||
178 | return omap_gem_mmap_obj(obj, vma); | 178 | return omap_gem_mmap_obj(obj, vma); |
179 | } | 179 | } |
180 | 180 | ||
181 | struct dma_buf_ops omap_dmabuf_ops = { | 181 | static struct dma_buf_ops omap_dmabuf_ops = { |
182 | .map_dma_buf = omap_gem_map_dma_buf, | 182 | .map_dma_buf = omap_gem_map_dma_buf, |
183 | .unmap_dma_buf = omap_gem_unmap_dma_buf, | 183 | .unmap_dma_buf = omap_gem_unmap_dma_buf, |
184 | .release = omap_gem_dmabuf_release, | 184 | .release = omap_gem_dmabuf_release, |
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index e01303ee00c3..9263db117ff8 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c | |||
@@ -130,12 +130,13 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, | |||
130 | * Zero on success, appropriate errno if the given @crtc's vblank | 130 | * Zero on success, appropriate errno if the given @crtc's vblank |
131 | * interrupt cannot be enabled. | 131 | * interrupt cannot be enabled. |
132 | */ | 132 | */ |
133 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc) | 133 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc_id) |
134 | { | 134 | { |
135 | struct omap_drm_private *priv = dev->dev_private; | 135 | struct omap_drm_private *priv = dev->dev_private; |
136 | struct drm_crtc *crtc = priv->crtcs[crtc_id]; | ||
136 | unsigned long flags; | 137 | unsigned long flags; |
137 | 138 | ||
138 | DBG("dev=%p, crtc=%d", dev, crtc); | 139 | DBG("dev=%p, crtc=%d", dev, crtc_id); |
139 | 140 | ||
140 | dispc_runtime_get(); | 141 | dispc_runtime_get(); |
141 | spin_lock_irqsave(&list_lock, flags); | 142 | spin_lock_irqsave(&list_lock, flags); |
@@ -156,12 +157,13 @@ int omap_irq_enable_vblank(struct drm_device *dev, int crtc) | |||
156 | * a hardware vblank counter, this routine should be a no-op, since | 157 | * a hardware vblank counter, this routine should be a no-op, since |
157 | * interrupts will have to stay on to keep the count accurate. | 158 | * interrupts will have to stay on to keep the count accurate. |
158 | */ | 159 | */ |
159 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc) | 160 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc_id) |
160 | { | 161 | { |
161 | struct omap_drm_private *priv = dev->dev_private; | 162 | struct omap_drm_private *priv = dev->dev_private; |
163 | struct drm_crtc *crtc = priv->crtcs[crtc_id]; | ||
162 | unsigned long flags; | 164 | unsigned long flags; |
163 | 165 | ||
164 | DBG("dev=%p, crtc=%d", dev, crtc); | 166 | DBG("dev=%p, crtc=%d", dev, crtc_id); |
165 | 167 | ||
166 | dispc_runtime_get(); | 168 | dispc_runtime_get(); |
167 | spin_lock_irqsave(&list_lock, flags); | 169 | spin_lock_irqsave(&list_lock, flags); |
@@ -186,9 +188,12 @@ irqreturn_t omap_irq_handler(DRM_IRQ_ARGS) | |||
186 | 188 | ||
187 | VERB("irqs: %08x", irqstatus); | 189 | VERB("irqs: %08x", irqstatus); |
188 | 190 | ||
189 | for (id = 0; id < priv->num_crtcs; id++) | 191 | for (id = 0; id < priv->num_crtcs; id++) { |
190 | if (irqstatus & pipe2vbl(id)) | 192 | struct drm_crtc *crtc = priv->crtcs[id]; |
193 | |||
194 | if (irqstatus & pipe2vbl(crtc)) | ||
191 | drm_handle_vblank(dev, id); | 195 | drm_handle_vblank(dev, id); |
196 | } | ||
192 | 197 | ||
193 | spin_lock_irqsave(&list_lock, flags); | 198 | spin_lock_irqsave(&list_lock, flags); |
194 | list_for_each_entry_safe(handler, n, &priv->irq_list, node) { | 199 | list_for_each_entry_safe(handler, n, &priv->irq_list, node) { |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 2882cda6ea19..8d225d7ff4e3 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
@@ -247,6 +247,12 @@ static int omap_plane_update(struct drm_plane *plane, | |||
247 | { | 247 | { |
248 | struct omap_plane *omap_plane = to_omap_plane(plane); | 248 | struct omap_plane *omap_plane = to_omap_plane(plane); |
249 | omap_plane->enabled = true; | 249 | omap_plane->enabled = true; |
250 | |||
251 | if (plane->fb) | ||
252 | drm_framebuffer_unreference(plane->fb); | ||
253 | |||
254 | drm_framebuffer_reference(fb); | ||
255 | |||
250 | return omap_plane_mode_set(plane, crtc, fb, | 256 | return omap_plane_mode_set(plane, crtc, fb, |
251 | crtc_x, crtc_y, crtc_w, crtc_h, | 257 | crtc_x, crtc_y, crtc_w, crtc_h, |
252 | src_x, src_y, src_w, src_h, | 258 | src_x, src_y, src_w, src_h, |