Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc6 377 lines 8.9 kB view raw
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_ops *hdmi_ops; 34static struct exynos_mixer_ops *mixer_ops; 35 36struct 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; 40}; 41 42void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) 43{ 44 DRM_DEBUG_KMS("%s\n", __FILE__); 45 46 if (ops) 47 hdmi_ops = ops; 48} 49 50void exynos_mixer_ops_register(struct exynos_mixer_ops *ops) 51{ 52 DRM_DEBUG_KMS("%s\n", __FILE__); 53 54 if (ops) 55 mixer_ops = ops; 56} 57 58static bool drm_hdmi_is_connected(struct device *dev) 59{ 60 struct drm_hdmi_context *ctx = to_context(dev); 61 62 DRM_DEBUG_KMS("%s\n", __FILE__); 63 64 if (hdmi_ops && hdmi_ops->is_connected) 65 return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx); 66 67 return false; 68} 69 70static int drm_hdmi_get_edid(struct device *dev, 71 struct drm_connector *connector, u8 *edid, int len) 72{ 73 struct drm_hdmi_context *ctx = to_context(dev); 74 75 DRM_DEBUG_KMS("%s\n", __FILE__); 76 77 if (hdmi_ops && hdmi_ops->get_edid) 78 return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, 79 len); 80 81 return 0; 82} 83 84static int drm_hdmi_check_timing(struct device *dev, void *timing) 85{ 86 struct drm_hdmi_context *ctx = to_context(dev); 87 88 DRM_DEBUG_KMS("%s\n", __FILE__); 89 90 if (hdmi_ops && hdmi_ops->check_timing) 91 return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing); 92 93 return 0; 94} 95 96static int drm_hdmi_power_on(struct device *dev, int mode) 97{ 98 struct drm_hdmi_context *ctx = to_context(dev); 99 100 DRM_DEBUG_KMS("%s\n", __FILE__); 101 102 if (hdmi_ops && hdmi_ops->power_on) 103 return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode); 104 105 return 0; 106} 107 108static struct exynos_drm_display_ops drm_hdmi_display_ops = { 109 .type = EXYNOS_DISPLAY_TYPE_HDMI, 110 .is_connected = drm_hdmi_is_connected, 111 .get_edid = drm_hdmi_get_edid, 112 .check_timing = drm_hdmi_check_timing, 113 .power_on = drm_hdmi_power_on, 114}; 115 116static int drm_hdmi_enable_vblank(struct device *subdrv_dev) 117{ 118 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 119 struct exynos_drm_subdrv *subdrv = &ctx->subdrv; 120 struct exynos_drm_manager *manager = subdrv->manager; 121 122 DRM_DEBUG_KMS("%s\n", __FILE__); 123 124 if (mixer_ops && mixer_ops->enable_vblank) 125 return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, 126 manager->pipe); 127 128 return 0; 129} 130 131static void drm_hdmi_disable_vblank(struct device *subdrv_dev) 132{ 133 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 134 135 DRM_DEBUG_KMS("%s\n", __FILE__); 136 137 if (mixer_ops && mixer_ops->disable_vblank) 138 return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); 139} 140 141static void drm_hdmi_mode_fixup(struct device *subdrv_dev, 142 struct drm_connector *connector, 143 struct drm_display_mode *mode, 144 struct drm_display_mode *adjusted_mode) 145{ 146 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 147 148 DRM_DEBUG_KMS("%s\n", __FILE__); 149 150 if (hdmi_ops && hdmi_ops->mode_fixup) 151 hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode, 152 adjusted_mode); 153} 154 155static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode) 156{ 157 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 158 159 DRM_DEBUG_KMS("%s\n", __FILE__); 160 161 if (hdmi_ops && hdmi_ops->mode_set) 162 hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); 163} 164 165static void drm_hdmi_get_max_resol(struct device *subdrv_dev, 166 unsigned int *width, unsigned int *height) 167{ 168 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 169 170 DRM_DEBUG_KMS("%s\n", __FILE__); 171 172 if (hdmi_ops && hdmi_ops->get_max_resol) 173 hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); 174} 175 176static void drm_hdmi_commit(struct device *subdrv_dev) 177{ 178 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 179 180 DRM_DEBUG_KMS("%s\n", __FILE__); 181 182 if (hdmi_ops && hdmi_ops->commit) 183 hdmi_ops->commit(ctx->hdmi_ctx->ctx); 184} 185 186static void drm_hdmi_dpms(struct device *subdrv_dev, int mode) 187{ 188 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 189 190 DRM_DEBUG_KMS("%s\n", __FILE__); 191 192 switch (mode) { 193 case DRM_MODE_DPMS_ON: 194 break; 195 case DRM_MODE_DPMS_STANDBY: 196 case DRM_MODE_DPMS_SUSPEND: 197 case DRM_MODE_DPMS_OFF: 198 if (hdmi_ops && hdmi_ops->disable) 199 hdmi_ops->disable(ctx->hdmi_ctx->ctx); 200 break; 201 default: 202 DRM_DEBUG_KMS("unkown dps mode: %d\n", mode); 203 break; 204 } 205} 206 207static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { 208 .dpms = drm_hdmi_dpms, 209 .enable_vblank = drm_hdmi_enable_vblank, 210 .disable_vblank = drm_hdmi_disable_vblank, 211 .mode_fixup = drm_hdmi_mode_fixup, 212 .mode_set = drm_hdmi_mode_set, 213 .get_max_resol = drm_hdmi_get_max_resol, 214 .commit = drm_hdmi_commit, 215}; 216 217static void drm_mixer_mode_set(struct device *subdrv_dev, 218 struct exynos_drm_overlay *overlay) 219{ 220 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 221 222 DRM_DEBUG_KMS("%s\n", __FILE__); 223 224 if (mixer_ops && mixer_ops->win_mode_set) 225 mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay); 226} 227 228static void drm_mixer_commit(struct device *subdrv_dev, int zpos) 229{ 230 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 231 232 DRM_DEBUG_KMS("%s\n", __FILE__); 233 234 if (mixer_ops && mixer_ops->win_commit) 235 mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos); 236} 237 238static void drm_mixer_disable(struct device *subdrv_dev, int zpos) 239{ 240 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 241 242 DRM_DEBUG_KMS("%s\n", __FILE__); 243 244 if (mixer_ops && mixer_ops->win_disable) 245 mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos); 246} 247 248static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { 249 .mode_set = drm_mixer_mode_set, 250 .commit = drm_mixer_commit, 251 .disable = drm_mixer_disable, 252}; 253 254static struct exynos_drm_manager hdmi_manager = { 255 .pipe = -1, 256 .ops = &drm_hdmi_manager_ops, 257 .overlay_ops = &drm_hdmi_overlay_ops, 258 .display_ops = &drm_hdmi_display_ops, 259}; 260 261static int hdmi_subdrv_probe(struct drm_device *drm_dev, 262 struct device *dev) 263{ 264 struct exynos_drm_subdrv *subdrv = to_subdrv(dev); 265 struct drm_hdmi_context *ctx; 266 struct platform_device *pdev = to_platform_device(dev); 267 struct exynos_drm_common_hdmi_pd *pd; 268 269 DRM_DEBUG_KMS("%s\n", __FILE__); 270 271 pd = pdev->dev.platform_data; 272 273 if (!pd) { 274 DRM_DEBUG_KMS("platform data is null.\n"); 275 return -EFAULT; 276 } 277 278 if (!pd->hdmi_dev) { 279 DRM_DEBUG_KMS("hdmi device is null.\n"); 280 return -EFAULT; 281 } 282 283 if (!pd->mixer_dev) { 284 DRM_DEBUG_KMS("mixer device is null.\n"); 285 return -EFAULT; 286 } 287 288 ctx = get_ctx_from_subdrv(subdrv); 289 290 ctx->hdmi_ctx = (struct exynos_drm_hdmi_context *) 291 to_context(pd->hdmi_dev); 292 if (!ctx->hdmi_ctx) { 293 DRM_DEBUG_KMS("hdmi context is null.\n"); 294 return -EFAULT; 295 } 296 297 ctx->hdmi_ctx->drm_dev = drm_dev; 298 299 ctx->mixer_ctx = (struct exynos_drm_hdmi_context *) 300 to_context(pd->mixer_dev); 301 if (!ctx->mixer_ctx) { 302 DRM_DEBUG_KMS("mixer context is null.\n"); 303 return -EFAULT; 304 } 305 306 ctx->mixer_ctx->drm_dev = drm_dev; 307 308 return 0; 309} 310 311static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) 312{ 313 struct device *dev = &pdev->dev; 314 struct exynos_drm_subdrv *subdrv; 315 struct drm_hdmi_context *ctx; 316 317 DRM_DEBUG_KMS("%s\n", __FILE__); 318 319 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 320 if (!ctx) { 321 DRM_LOG_KMS("failed to alloc common hdmi context.\n"); 322 return -ENOMEM; 323 } 324 325 subdrv = &ctx->subdrv; 326 327 subdrv->dev = dev; 328 subdrv->manager = &hdmi_manager; 329 subdrv->probe = hdmi_subdrv_probe; 330 331 platform_set_drvdata(pdev, subdrv); 332 333 exynos_drm_subdrv_register(subdrv); 334 335 return 0; 336} 337 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) 358{ 359 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); 360 361 DRM_DEBUG_KMS("%s\n", __FILE__); 362 363 exynos_drm_subdrv_unregister(&ctx->subdrv); 364 kfree(ctx); 365 366 return 0; 367} 368 369struct platform_driver exynos_drm_common_hdmi_driver = { 370 .probe = exynos_drm_hdmi_probe, 371 .remove = __devexit_p(exynos_drm_hdmi_remove), 372 .driver = { 373 .name = "exynos-drm-hdmi", 374 .owner = THIS_MODULE, 375 .pm = &hdmi_pm_ops, 376 }, 377};