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 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 struct exynos_drm_overlay_ops drm_hdmi_overlay_ops
= {
278 .mode_set
= drm_mixer_mode_set
,
279 .commit
= drm_mixer_commit
,
280 .disable
= drm_mixer_disable
,
283 static struct exynos_drm_manager hdmi_manager
= {
285 .ops
= &drm_hdmi_manager_ops
,
286 .overlay_ops
= &drm_hdmi_overlay_ops
,
287 .display_ops
= &drm_hdmi_display_ops
,
290 static int hdmi_subdrv_probe(struct drm_device
*drm_dev
,
293 struct exynos_drm_subdrv
*subdrv
= to_subdrv(dev
);
294 struct drm_hdmi_context
*ctx
;
295 struct platform_device
*pdev
= to_platform_device(dev
);
296 struct exynos_drm_common_hdmi_pd
*pd
;
298 DRM_DEBUG_KMS("%s\n", __FILE__
);
300 pd
= pdev
->dev
.platform_data
;
303 DRM_DEBUG_KMS("platform data is null.\n");
308 DRM_DEBUG_KMS("hdmi device is null.\n");
312 if (!pd
->mixer_dev
) {
313 DRM_DEBUG_KMS("mixer device is null.\n");
317 ctx
= get_ctx_from_subdrv(subdrv
);
319 ctx
->hdmi_ctx
= (struct exynos_drm_hdmi_context
*)
320 to_context(pd
->hdmi_dev
);
321 if (!ctx
->hdmi_ctx
) {
322 DRM_DEBUG_KMS("hdmi context is null.\n");
326 ctx
->hdmi_ctx
->drm_dev
= drm_dev
;
328 ctx
->mixer_ctx
= (struct exynos_drm_hdmi_context
*)
329 to_context(pd
->mixer_dev
);
330 if (!ctx
->mixer_ctx
) {
331 DRM_DEBUG_KMS("mixer context is null.\n");
335 ctx
->mixer_ctx
->drm_dev
= drm_dev
;
340 static int __devinit
exynos_drm_hdmi_probe(struct platform_device
*pdev
)
342 struct device
*dev
= &pdev
->dev
;
343 struct exynos_drm_subdrv
*subdrv
;
344 struct drm_hdmi_context
*ctx
;
346 DRM_DEBUG_KMS("%s\n", __FILE__
);
348 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
350 DRM_LOG_KMS("failed to alloc common hdmi context.\n");
354 subdrv
= &ctx
->subdrv
;
357 subdrv
->manager
= &hdmi_manager
;
358 subdrv
->probe
= hdmi_subdrv_probe
;
360 platform_set_drvdata(pdev
, subdrv
);
362 exynos_drm_subdrv_register(subdrv
);
367 static int __devexit
exynos_drm_hdmi_remove(struct platform_device
*pdev
)
369 struct drm_hdmi_context
*ctx
= platform_get_drvdata(pdev
);
371 DRM_DEBUG_KMS("%s\n", __FILE__
);
373 exynos_drm_subdrv_unregister(&ctx
->subdrv
);
379 struct platform_driver exynos_drm_common_hdmi_driver
= {
380 .probe
= exynos_drm_hdmi_probe
,
381 .remove
= __devexit_p(exynos_drm_hdmi_remove
),
383 .name
= "exynos-drm-hdmi",
384 .owner
= THIS_MODULE
,