aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
diff options
context:
space:
mode:
authorJoonyoung Shim <jy0922.shim@samsung.com>2012-04-23 06:35:50 -0400
committerInki Dae <inki.dae@samsung.com>2012-05-08 05:46:33 -0400
commitcf8fc4f10e2c5c5b6b60d6e79d61cc58afa5967d (patch)
tree74cdc233ce54eb37ef67e7fec7af5ee2bf75911f /drivers/gpu/drm/exynos/exynos_drm_hdmi.c
parent66265a2e8e867a9c5ce63e5f883cf751b35b66d5 (diff)
drm/exynos: add dpms for hdmi
The power and clocks turns on always in exynos hdmi and mixer driver, but we should turn off the power and clocks of exynos hdmi and mixer when the hdmi cable unplugged or when hdmi unused. There are two interrupt to detect hotplug of hdmi cable - internal interrupt and external interrupt. The internal interrupt can use only when hdmi is dpms on so if hdmi is dpms off, we should use external interrupt to detect hotplug of hdmi cable. If hdmi is dpms on, we cannot external interrupt because the gpio pin for external interrupt is used to hdmi HPD pin for internal interrupt. Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_hdmi.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.c77
1 files changed, 43 insertions, 34 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 3424463676e0..5d9d2c2f8f3f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -37,6 +37,8 @@ struct drm_hdmi_context {
37 struct exynos_drm_subdrv subdrv; 37 struct exynos_drm_subdrv subdrv;
38 struct exynos_drm_hdmi_context *hdmi_ctx; 38 struct exynos_drm_hdmi_context *hdmi_ctx;
39 struct exynos_drm_hdmi_context *mixer_ctx; 39 struct exynos_drm_hdmi_context *mixer_ctx;
40
41 bool enabled[MIXER_WIN_NR];
40}; 42};
41 43
42void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) 44void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
@@ -189,23 +191,34 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
189 191
190 DRM_DEBUG_KMS("%s\n", __FILE__); 192 DRM_DEBUG_KMS("%s\n", __FILE__);
191 193
192 switch (mode) { 194 if (mixer_ops && mixer_ops->dpms)
193 case DRM_MODE_DPMS_ON: 195 mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
194 break; 196
195 case DRM_MODE_DPMS_STANDBY: 197 if (hdmi_ops && hdmi_ops->dpms)
196 case DRM_MODE_DPMS_SUSPEND: 198 hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
197 case DRM_MODE_DPMS_OFF: 199}
198 if (hdmi_ops && hdmi_ops->disable) 200
199 hdmi_ops->disable(ctx->hdmi_ctx->ctx); 201static void drm_hdmi_apply(struct device *subdrv_dev)
200 break; 202{
201 default: 203 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
202 DRM_DEBUG_KMS("unkown dps mode: %d\n", mode); 204 int i;
203 break; 205
206 DRM_DEBUG_KMS("%s\n", __FILE__);
207
208 for (i = 0; i < MIXER_WIN_NR; i++) {
209 if (!ctx->enabled[i])
210 continue;
211 if (mixer_ops && mixer_ops->win_commit)
212 mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
204 } 213 }
214
215 if (hdmi_ops && hdmi_ops->commit)
216 hdmi_ops->commit(ctx->hdmi_ctx->ctx);
205} 217}
206 218
207static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { 219static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
208 .dpms = drm_hdmi_dpms, 220 .dpms = drm_hdmi_dpms,
221 .apply = drm_hdmi_apply,
209 .enable_vblank = drm_hdmi_enable_vblank, 222 .enable_vblank = drm_hdmi_enable_vblank,
210 .disable_vblank = drm_hdmi_disable_vblank, 223 .disable_vblank = drm_hdmi_disable_vblank,
211 .mode_fixup = drm_hdmi_mode_fixup, 224 .mode_fixup = drm_hdmi_mode_fixup,
@@ -228,21 +241,37 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
228static void drm_mixer_commit(struct device *subdrv_dev, int zpos) 241static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
229{ 242{
230 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 243 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
244 int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
231 245
232 DRM_DEBUG_KMS("%s\n", __FILE__); 246 DRM_DEBUG_KMS("%s\n", __FILE__);
233 247
248 if (win < 0 || win > MIXER_WIN_NR) {
249 DRM_ERROR("mixer window[%d] is wrong\n", win);
250 return;
251 }
252
234 if (mixer_ops && mixer_ops->win_commit) 253 if (mixer_ops && mixer_ops->win_commit)
235 mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos); 254 mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
255
256 ctx->enabled[win] = true;
236} 257}
237 258
238static void drm_mixer_disable(struct device *subdrv_dev, int zpos) 259static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
239{ 260{
240 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 261 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
262 int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
241 263
242 DRM_DEBUG_KMS("%s\n", __FILE__); 264 DRM_DEBUG_KMS("%s\n", __FILE__);
243 265
266 if (win < 0 || win > MIXER_WIN_NR) {
267 DRM_ERROR("mixer window[%d] is wrong\n", win);
268 return;
269 }
270
244 if (mixer_ops && mixer_ops->win_disable) 271 if (mixer_ops && mixer_ops->win_disable)
245 mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos); 272 mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
273
274 ctx->enabled[win] = false;
246} 275}
247 276
248static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { 277static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
@@ -335,25 +364,6 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
335 return 0; 364 return 0;
336} 365}
337 366
338static int hdmi_runtime_suspend(struct device *dev)
339{
340 DRM_DEBUG_KMS("%s\n", __FILE__);
341
342 return 0;
343}
344
345static int hdmi_runtime_resume(struct device *dev)
346{
347 DRM_DEBUG_KMS("%s\n", __FILE__);
348
349 return 0;
350}
351
352static const struct dev_pm_ops hdmi_pm_ops = {
353 .runtime_suspend = hdmi_runtime_suspend,
354 .runtime_resume = hdmi_runtime_resume,
355};
356
357static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) 367static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
358{ 368{
359 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); 369 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
@@ -372,6 +382,5 @@ struct platform_driver exynos_drm_common_hdmi_driver = {
372 .driver = { 382 .driver = {
373 .name = "exynos-drm-hdmi", 383 .name = "exynos-drm-hdmi",
374 .owner = THIS_MODULE, 384 .owner = THIS_MODULE,
375 .pm = &hdmi_pm_ops,
376 }, 385 },
377}; 386};