2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
4 * Inki Dae <inki.dae@samsung.com>
5 * Seung-Woo Kim <sw0312.kim@samsung.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
16 #include <linux/kernel.h>
17 #include <linux/wait.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
22 #include <drm/exynos_drm.h>
24 #include "exynos_drm_drv.h"
25 #include "exynos_drm_hdmi.h"
27 #define to_context(dev) platform_get_drvdata(to_platform_device(dev))
28 #define to_subdrv(dev) to_context(dev)
29 #define get_ctx_from_subdrv(subdrv) container_of(subdrv,\
30 struct drm_hdmi_context, subdrv);
32 /* these callback points shoud be set by specific drivers. */
33 static struct exynos_hdmi_ops
*hdmi_ops
;
34 static struct exynos_mixer_ops
*mixer_ops
;
36 struct drm_hdmi_context
{
37 struct exynos_drm_subdrv subdrv
;
38 struct exynos_drm_hdmi_context
*hdmi_ctx
;
39 struct exynos_drm_hdmi_context
*mixer_ctx
;
41 bool enabled
[MIXER_WIN_NR
];
44 void exynos_hdmi_ops_register(struct exynos_hdmi_ops
*ops
)
46 DRM_DEBUG_KMS("%s\n", __FILE__
);
52 void exynos_mixer_ops_register(struct exynos_mixer_ops
*ops
)
54 DRM_DEBUG_KMS("%s\n", __FILE__
);
60 static bool drm_hdmi_is_connected(struct device
*dev
)
62 struct drm_hdmi_context
*ctx
= to_context(dev
);
64 DRM_DEBUG_KMS("%s\n", __FILE__
);
66 if (hdmi_ops
&& hdmi_ops
->is_connected
)
67 return hdmi_ops
->is_connected(ctx
->hdmi_ctx
->ctx
);
72 static int drm_hdmi_get_edid(struct device
*dev
,
73 struct drm_connector
*connector
, u8
*edid
, int len
)
75 struct drm_hdmi_context
*ctx
= to_context(dev
);
77 DRM_DEBUG_KMS("%s\n", __FILE__
);
79 if (hdmi_ops
&& hdmi_ops
->get_edid
)
80 return hdmi_ops
->get_edid(ctx
->hdmi_ctx
->ctx
, connector
, edid
,
86 static int drm_hdmi_check_timing(struct device
*dev
, void *timing
)
88 struct drm_hdmi_context
*ctx
= to_context(dev
);
90 DRM_DEBUG_KMS("%s\n", __FILE__
);
92 if (hdmi_ops
&& hdmi_ops
->check_timing
)
93 return hdmi_ops
->check_timing(ctx
->hdmi_ctx
->ctx
, timing
);
98 static int drm_hdmi_power_on(struct device
*dev
, int mode
)
100 struct drm_hdmi_context
*ctx
= to_context(dev
);
102 DRM_DEBUG_KMS("%s\n", __FILE__
);
104 if (hdmi_ops
&& hdmi_ops
->power_on
)
105 return hdmi_ops
->power_on(ctx
->hdmi_ctx
->ctx
, mode
);
110 static struct exynos_drm_display_ops drm_hdmi_display_ops
= {
111 .type
= EXYNOS_DISPLAY_TYPE_HDMI
,
112 .is_connected
= drm_hdmi_is_connected
,
113 .get_edid
= drm_hdmi_get_edid
,
114 .check_timing
= drm_hdmi_check_timing
,
115 .power_on
= drm_hdmi_power_on
,
118 static int drm_hdmi_enable_vblank(struct device
*subdrv_dev
)
120 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
121 struct exynos_drm_subdrv
*subdrv
= &ctx
->subdrv
;
122 struct exynos_drm_manager
*manager
= subdrv
->manager
;
124 DRM_DEBUG_KMS("%s\n", __FILE__
);
126 if (mixer_ops
&& mixer_ops
->enable_vblank
)
127 return mixer_ops
->enable_vblank(ctx
->mixer_ctx
->ctx
,
133 static void drm_hdmi_disable_vblank(struct device
*subdrv_dev
)
135 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
137 DRM_DEBUG_KMS("%s\n", __FILE__
);
139 if (mixer_ops
&& mixer_ops
->disable_vblank
)
140 return mixer_ops
->disable_vblank(ctx
->mixer_ctx
->ctx
);
143 static void drm_hdmi_mode_fixup(struct device
*subdrv_dev
,
144 struct drm_connector
*connector
,
145 const struct drm_display_mode
*mode
,
146 struct drm_display_mode
*adjusted_mode
)
148 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
150 DRM_DEBUG_KMS("%s\n", __FILE__
);
152 if (hdmi_ops
&& hdmi_ops
->mode_fixup
)
153 hdmi_ops
->mode_fixup(ctx
->hdmi_ctx
->ctx
, connector
, mode
,
157 static void drm_hdmi_mode_set(struct device
*subdrv_dev
, void *mode
)
159 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
161 DRM_DEBUG_KMS("%s\n", __FILE__
);
163 if (hdmi_ops
&& hdmi_ops
->mode_set
)
164 hdmi_ops
->mode_set(ctx
->hdmi_ctx
->ctx
, mode
);
167 static void drm_hdmi_get_max_resol(struct device
*subdrv_dev
,
168 unsigned int *width
, unsigned int *height
)
170 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
172 DRM_DEBUG_KMS("%s\n", __FILE__
);
174 if (hdmi_ops
&& hdmi_ops
->get_max_resol
)
175 hdmi_ops
->get_max_resol(ctx
->hdmi_ctx
->ctx
, width
, height
);
178 static void drm_hdmi_commit(struct device
*subdrv_dev
)
180 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
182 DRM_DEBUG_KMS("%s\n", __FILE__
);
184 if (hdmi_ops
&& hdmi_ops
->commit
)
185 hdmi_ops
->commit(ctx
->hdmi_ctx
->ctx
);
188 static void drm_hdmi_dpms(struct device
*subdrv_dev
, int mode
)
190 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
192 DRM_DEBUG_KMS("%s\n", __FILE__
);
194 if (mixer_ops
&& mixer_ops
->dpms
)
195 mixer_ops
->dpms(ctx
->mixer_ctx
->ctx
, mode
);
197 if (hdmi_ops
&& hdmi_ops
->dpms
)
198 hdmi_ops
->dpms(ctx
->hdmi_ctx
->ctx
, mode
);
201 static void drm_hdmi_apply(struct device
*subdrv_dev
)
203 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
206 DRM_DEBUG_KMS("%s\n", __FILE__
);
208 for (i
= 0; i
< MIXER_WIN_NR
; i
++) {
209 if (!ctx
->enabled
[i
])
211 if (mixer_ops
&& mixer_ops
->win_commit
)
212 mixer_ops
->win_commit(ctx
->mixer_ctx
->ctx
, i
);
215 if (hdmi_ops
&& hdmi_ops
->commit
)
216 hdmi_ops
->commit(ctx
->hdmi_ctx
->ctx
);
219 static struct exynos_drm_manager_ops drm_hdmi_manager_ops
= {
220 .dpms
= drm_hdmi_dpms
,
221 .apply
= drm_hdmi_apply
,
222 .enable_vblank
= drm_hdmi_enable_vblank
,
223 .disable_vblank
= drm_hdmi_disable_vblank
,
224 .mode_fixup
= drm_hdmi_mode_fixup
,
225 .mode_set
= drm_hdmi_mode_set
,
226 .get_max_resol
= drm_hdmi_get_max_resol
,
227 .commit
= drm_hdmi_commit
,
230 static void drm_mixer_mode_set(struct device
*subdrv_dev
,
231 struct exynos_drm_overlay
*overlay
)
233 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
235 DRM_DEBUG_KMS("%s\n", __FILE__
);
237 if (mixer_ops
&& mixer_ops
->win_mode_set
)
238 mixer_ops
->win_mode_set(ctx
->mixer_ctx
->ctx
, overlay
);
241 static void drm_mixer_commit(struct device
*subdrv_dev
, int zpos
)
243 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
244 int win
= (zpos
== DEFAULT_ZPOS
) ? MIXER_DEFAULT_WIN
: zpos
;
246 DRM_DEBUG_KMS("%s\n", __FILE__
);
248 if (win
< 0 || win
> MIXER_WIN_NR
) {
249 DRM_ERROR("mixer window[%d] is wrong\n", win
);
253 if (mixer_ops
&& mixer_ops
->win_commit
)
254 mixer_ops
->win_commit(ctx
->mixer_ctx
->ctx
, win
);
256 ctx
->enabled
[win
] = true;
259 static void drm_mixer_disable(struct device
*subdrv_dev
, int zpos
)
261 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
262 int win
= (zpos
== DEFAULT_ZPOS
) ? MIXER_DEFAULT_WIN
: zpos
;
264 DRM_DEBUG_KMS("%s\n", __FILE__
);
266 if (win
< 0 || win
> MIXER_WIN_NR
) {
267 DRM_ERROR("mixer window[%d] is wrong\n", win
);
271 if (mixer_ops
&& mixer_ops
->win_disable
)
272 mixer_ops
->win_disable(ctx
->mixer_ctx
->ctx
, win
);
274 ctx
->enabled
[win
] = false;
277 static void drm_mixer_wait_for_vblank(struct device
*subdrv_dev
)
279 struct drm_hdmi_context
*ctx
= to_context(subdrv_dev
);
281 DRM_DEBUG_KMS("%s\n", __FILE__
);
283 if (mixer_ops
&& mixer_ops
->wait_for_vblank
)
284 mixer_ops
->wait_for_vblank(ctx
->mixer_ctx
->ctx
);
287 static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops
= {
288 .mode_set
= drm_mixer_mode_set
,
289 .commit
= drm_mixer_commit
,
290 .disable
= drm_mixer_disable
,
291 .wait_for_vblank
= drm_mixer_wait_for_vblank
,
294 static struct exynos_drm_manager hdmi_manager
= {
296 .ops
= &drm_hdmi_manager_ops
,
297 .overlay_ops
= &drm_hdmi_overlay_ops
,
298 .display_ops
= &drm_hdmi_display_ops
,
301 static int hdmi_subdrv_probe(struct drm_device
*drm_dev
,
304 struct exynos_drm_subdrv
*subdrv
= to_subdrv(dev
);
305 struct drm_hdmi_context
*ctx
;
306 struct platform_device
*pdev
= to_platform_device(dev
);
307 struct exynos_drm_common_hdmi_pd
*pd
;
309 DRM_DEBUG_KMS("%s\n", __FILE__
);
311 pd
= pdev
->dev
.platform_data
;
314 DRM_DEBUG_KMS("platform data is null.\n");
319 DRM_DEBUG_KMS("hdmi device is null.\n");
323 if (!pd
->mixer_dev
) {
324 DRM_DEBUG_KMS("mixer device is null.\n");
328 ctx
= get_ctx_from_subdrv(subdrv
);
330 ctx
->hdmi_ctx
= (struct exynos_drm_hdmi_context
*)
331 to_context(pd
->hdmi_dev
);
332 if (!ctx
->hdmi_ctx
) {
333 DRM_DEBUG_KMS("hdmi context is null.\n");
337 ctx
->hdmi_ctx
->drm_dev
= drm_dev
;
339 ctx
->mixer_ctx
= (struct exynos_drm_hdmi_context
*)
340 to_context(pd
->mixer_dev
);
341 if (!ctx
->mixer_ctx
) {
342 DRM_DEBUG_KMS("mixer context is null.\n");
346 ctx
->mixer_ctx
->drm_dev
= drm_dev
;
351 static int __devinit
exynos_drm_hdmi_probe(struct platform_device
*pdev
)
353 struct device
*dev
= &pdev
->dev
;
354 struct exynos_drm_subdrv
*subdrv
;
355 struct drm_hdmi_context
*ctx
;
357 DRM_DEBUG_KMS("%s\n", __FILE__
);
359 ctx
= devm_kzalloc(&pdev
->dev
, sizeof(*ctx
), GFP_KERNEL
);
361 DRM_LOG_KMS("failed to alloc common hdmi context.\n");
365 subdrv
= &ctx
->subdrv
;
368 subdrv
->manager
= &hdmi_manager
;
369 subdrv
->probe
= hdmi_subdrv_probe
;
371 platform_set_drvdata(pdev
, subdrv
);
373 exynos_drm_subdrv_register(subdrv
);
378 static int __devexit
exynos_drm_hdmi_remove(struct platform_device
*pdev
)
380 struct drm_hdmi_context
*ctx
= platform_get_drvdata(pdev
);
382 DRM_DEBUG_KMS("%s\n", __FILE__
);
384 exynos_drm_subdrv_unregister(&ctx
->subdrv
);
389 struct platform_driver exynos_drm_common_hdmi_driver
= {
390 .probe
= exynos_drm_hdmi_probe
,
391 .remove
= __devexit_p(exynos_drm_hdmi_remove
),
393 .name
= "exynos-drm-hdmi",
394 .owner
= THIS_MODULE
,