drm/exynos: use define instead of default_win member in struct mixer_context
[linux-2.6-block.git] / drivers / gpu / drm / exynos / exynos_drm_hdmi.c
CommitLineData
d8408326
SWK
1/*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Inki Dae <inki.dae@samsung.com>
5 * Seung-Woo Kim <sw0312.kim@samsung.com>
6 *
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.
11 *
12 */
13
14#include "drmP.h"
15
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>
21
22#include <drm/exynos_drm.h>
23
24#include "exynos_drm_drv.h"
25#include "exynos_drm_hdmi.h"
26
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);
31
32/* these callback points shoud be set by specific drivers. */
33static struct exynos_hdmi_display_ops *hdmi_display_ops;
34static struct exynos_hdmi_manager_ops *hdmi_manager_ops;
35static struct exynos_hdmi_overlay_ops *hdmi_overlay_ops;
36
37struct drm_hdmi_context {
38 struct exynos_drm_subdrv subdrv;
39 struct exynos_drm_hdmi_context *hdmi_ctx;
40 struct exynos_drm_hdmi_context *mixer_ctx;
d8408326
SWK
41};
42
43void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops
44 *display_ops)
45{
46 DRM_DEBUG_KMS("%s\n", __FILE__);
47
48 if (display_ops)
49 hdmi_display_ops = display_ops;
50}
d8408326
SWK
51
52void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops
53 *manager_ops)
54{
55 DRM_DEBUG_KMS("%s\n", __FILE__);
56
57 if (manager_ops)
58 hdmi_manager_ops = manager_ops;
59}
d8408326
SWK
60
61void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops
62 *overlay_ops)
63{
64 DRM_DEBUG_KMS("%s\n", __FILE__);
65
66 if (overlay_ops)
67 hdmi_overlay_ops = overlay_ops;
68}
d8408326
SWK
69
70static bool drm_hdmi_is_connected(struct device *dev)
71{
72 struct drm_hdmi_context *ctx = to_context(dev);
73
74 DRM_DEBUG_KMS("%s\n", __FILE__);
75
76 if (hdmi_display_ops && hdmi_display_ops->is_connected)
77 return hdmi_display_ops->is_connected(ctx->hdmi_ctx->ctx);
78
79 return false;
80}
81
82static int drm_hdmi_get_edid(struct device *dev,
83 struct drm_connector *connector, u8 *edid, int len)
84{
85 struct drm_hdmi_context *ctx = to_context(dev);
86
87 DRM_DEBUG_KMS("%s\n", __FILE__);
88
89 if (hdmi_display_ops && hdmi_display_ops->get_edid)
90 return hdmi_display_ops->get_edid(ctx->hdmi_ctx->ctx,
91 connector, edid, len);
92
93 return 0;
94}
95
96static int drm_hdmi_check_timing(struct device *dev, void *timing)
97{
98 struct drm_hdmi_context *ctx = to_context(dev);
99
100 DRM_DEBUG_KMS("%s\n", __FILE__);
101
102 if (hdmi_display_ops && hdmi_display_ops->check_timing)
103 return hdmi_display_ops->check_timing(ctx->hdmi_ctx->ctx,
104 timing);
105
106 return 0;
107}
108
109static int drm_hdmi_power_on(struct device *dev, int mode)
110{
111 struct drm_hdmi_context *ctx = to_context(dev);
112
113 DRM_DEBUG_KMS("%s\n", __FILE__);
114
115 if (hdmi_display_ops && hdmi_display_ops->power_on)
116 return hdmi_display_ops->power_on(ctx->hdmi_ctx->ctx, mode);
117
118 return 0;
119}
120
121static struct exynos_drm_display_ops drm_hdmi_display_ops = {
122 .type = EXYNOS_DISPLAY_TYPE_HDMI,
123 .is_connected = drm_hdmi_is_connected,
124 .get_edid = drm_hdmi_get_edid,
125 .check_timing = drm_hdmi_check_timing,
126 .power_on = drm_hdmi_power_on,
127};
128
129static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
130{
131 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
132 struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
133 struct exynos_drm_manager *manager = &subdrv->manager;
134
135 DRM_DEBUG_KMS("%s\n", __FILE__);
136
137 if (hdmi_overlay_ops && hdmi_overlay_ops->enable_vblank)
138 return hdmi_overlay_ops->enable_vblank(ctx->mixer_ctx->ctx,
139 manager->pipe);
140
141 return 0;
142}
143
144static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
145{
146 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
147
148 DRM_DEBUG_KMS("%s\n", __FILE__);
149
150 if (hdmi_overlay_ops && hdmi_overlay_ops->disable_vblank)
151 return hdmi_overlay_ops->disable_vblank(ctx->mixer_ctx->ctx);
152}
153
1de425b0
ID
154static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
155 struct drm_connector *connector,
156 struct drm_display_mode *mode,
157 struct drm_display_mode *adjusted_mode)
158{
159 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
160
161 DRM_DEBUG_KMS("%s\n", __FILE__);
162
163 if (hdmi_manager_ops && hdmi_manager_ops->mode_fixup)
164 hdmi_manager_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector,
165 mode, adjusted_mode);
166}
167
d8408326
SWK
168static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
169{
170 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
171
172 DRM_DEBUG_KMS("%s\n", __FILE__);
173
174 if (hdmi_manager_ops && hdmi_manager_ops->mode_set)
175 hdmi_manager_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
176}
177
1de425b0
ID
178static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
179 unsigned int *width, unsigned int *height)
180{
181 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
182
183 DRM_DEBUG_KMS("%s\n", __FILE__);
184
185 if (hdmi_manager_ops && hdmi_manager_ops->get_max_resol)
186 hdmi_manager_ops->get_max_resol(ctx->hdmi_ctx->ctx, width,
187 height);
188}
189
d8408326
SWK
190static void drm_hdmi_commit(struct device *subdrv_dev)
191{
192 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
193
194 DRM_DEBUG_KMS("%s\n", __FILE__);
195
196 if (hdmi_manager_ops && hdmi_manager_ops->commit)
197 hdmi_manager_ops->commit(ctx->hdmi_ctx->ctx);
198}
199
200static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
201{
202 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
203
204 DRM_DEBUG_KMS("%s\n", __FILE__);
205
206 switch (mode) {
207 case DRM_MODE_DPMS_ON:
208 break;
209 case DRM_MODE_DPMS_STANDBY:
210 case DRM_MODE_DPMS_SUSPEND:
211 case DRM_MODE_DPMS_OFF:
212 if (hdmi_manager_ops && hdmi_manager_ops->disable)
213 hdmi_manager_ops->disable(ctx->hdmi_ctx->ctx);
214 break;
215 default:
216 DRM_DEBUG_KMS("unkown dps mode: %d\n", mode);
217 break;
218 }
219}
220
221static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
222 .dpms = drm_hdmi_dpms,
223 .enable_vblank = drm_hdmi_enable_vblank,
224 .disable_vblank = drm_hdmi_disable_vblank,
1de425b0 225 .mode_fixup = drm_hdmi_mode_fixup,
d8408326 226 .mode_set = drm_hdmi_mode_set,
1de425b0 227 .get_max_resol = drm_hdmi_get_max_resol,
d8408326
SWK
228 .commit = drm_hdmi_commit,
229};
230
231static void drm_mixer_mode_set(struct device *subdrv_dev,
232 struct exynos_drm_overlay *overlay)
233{
234 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
235
236 DRM_DEBUG_KMS("%s\n", __FILE__);
237
238 if (hdmi_overlay_ops && hdmi_overlay_ops->win_mode_set)
239 hdmi_overlay_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
240}
241
242static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
243{
244 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
245
246 DRM_DEBUG_KMS("%s\n", __FILE__);
247
248 if (hdmi_overlay_ops && hdmi_overlay_ops->win_commit)
249 hdmi_overlay_ops->win_commit(ctx->mixer_ctx->ctx, zpos);
250}
251
252static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
253{
254 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
255
256 DRM_DEBUG_KMS("%s\n", __FILE__);
257
258 if (hdmi_overlay_ops && hdmi_overlay_ops->win_disable)
259 hdmi_overlay_ops->win_disable(ctx->mixer_ctx->ctx, zpos);
260}
261
262static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
263 .mode_set = drm_mixer_mode_set,
264 .commit = drm_mixer_commit,
265 .disable = drm_mixer_disable,
266};
267
268
269static int hdmi_subdrv_probe(struct drm_device *drm_dev,
270 struct device *dev)
271{
272 struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
273 struct drm_hdmi_context *ctx;
274 struct platform_device *pdev = to_platform_device(dev);
275 struct exynos_drm_common_hdmi_pd *pd;
d8408326
SWK
276
277 DRM_DEBUG_KMS("%s\n", __FILE__);
278
279 pd = pdev->dev.platform_data;
280
281 if (!pd) {
282 DRM_DEBUG_KMS("platform data is null.\n");
283 return -EFAULT;
284 }
285
286 if (!pd->hdmi_dev) {
287 DRM_DEBUG_KMS("hdmi device is null.\n");
288 return -EFAULT;
289 }
290
291 if (!pd->mixer_dev) {
292 DRM_DEBUG_KMS("mixer device is null.\n");
293 return -EFAULT;
294 }
295
d8408326
SWK
296 ctx = get_ctx_from_subdrv(subdrv);
297
298 ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *)
299 to_context(pd->hdmi_dev);
300 if (!ctx->hdmi_ctx) {
301 DRM_DEBUG_KMS("hdmi context is null.\n");
132a5b91 302 return -EFAULT;
d8408326
SWK
303 }
304
305 ctx->hdmi_ctx->drm_dev = drm_dev;
306
307 ctx->mixer_ctx = (struct exynos_drm_hdmi_context *)
308 to_context(pd->mixer_dev);
309 if (!ctx->mixer_ctx) {
310 DRM_DEBUG_KMS("mixer context is null.\n");
132a5b91 311 return -EFAULT;
d8408326
SWK
312 }
313
314 ctx->mixer_ctx->drm_dev = drm_dev;
315
316 return 0;
d8408326
SWK
317}
318
319static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
320{
321 struct device *dev = &pdev->dev;
322 struct exynos_drm_subdrv *subdrv;
323 struct drm_hdmi_context *ctx;
324
325 DRM_DEBUG_KMS("%s\n", __FILE__);
326
327 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
328 if (!ctx) {
329 DRM_LOG_KMS("failed to alloc common hdmi context.\n");
330 return -ENOMEM;
331 }
332
333 subdrv = &ctx->subdrv;
334
335 subdrv->probe = hdmi_subdrv_probe;
d8408326
SWK
336 subdrv->manager.pipe = -1;
337 subdrv->manager.ops = &drm_hdmi_manager_ops;
338 subdrv->manager.overlay_ops = &drm_hdmi_overlay_ops;
339 subdrv->manager.display_ops = &drm_hdmi_display_ops;
340 subdrv->manager.dev = dev;
341
342 platform_set_drvdata(pdev, subdrv);
343
132a5b91 344 exynos_drm_subdrv_register(subdrv);
d8408326
SWK
345
346 return 0;
347}
348
349static int hdmi_runtime_suspend(struct device *dev)
350{
351 DRM_DEBUG_KMS("%s\n", __FILE__);
352
353 return 0;
354}
355
356static int hdmi_runtime_resume(struct device *dev)
357{
358 DRM_DEBUG_KMS("%s\n", __FILE__);
359
360 return 0;
361}
362
363static const struct dev_pm_ops hdmi_pm_ops = {
364 .runtime_suspend = hdmi_runtime_suspend,
365 .runtime_resume = hdmi_runtime_resume,
366};
367
368static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
369{
370 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
371
372 DRM_DEBUG_KMS("%s\n", __FILE__);
373
374 exynos_drm_subdrv_unregister(&ctx->subdrv);
375 kfree(ctx);
376
377 return 0;
378}
379
132a5b91 380struct platform_driver exynos_drm_common_hdmi_driver = {
d8408326
SWK
381 .probe = exynos_drm_hdmi_probe,
382 .remove = __devexit_p(exynos_drm_hdmi_remove),
383 .driver = {
384 .name = "exynos-drm-hdmi",
385 .owner = THIS_MODULE,
386 .pm = &hdmi_pm_ops,
387 },
388};