| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* exynos_drm_vidi.c |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2012 Samsung Electronics Co.Ltd |
|---|
| 4 | 5 | * Authors: |
|---|
| 5 | 6 | * Inki Dae <inki.dae@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 | 7 | */ |
|---|
| 13 | | -#include <drm/drmP.h> |
|---|
| 14 | 8 | |
|---|
| 9 | +#include <linux/component.h> |
|---|
| 15 | 10 | #include <linux/kernel.h> |
|---|
| 16 | 11 | #include <linux/platform_device.h> |
|---|
| 17 | | -#include <linux/component.h> |
|---|
| 18 | 12 | #include <linux/timer.h> |
|---|
| 19 | 13 | |
|---|
| 14 | +#include <drm/drm_atomic_helper.h> |
|---|
| 15 | +#include <drm/drm_edid.h> |
|---|
| 16 | +#include <drm/drm_probe_helper.h> |
|---|
| 17 | +#include <drm/drm_simple_kms_helper.h> |
|---|
| 18 | +#include <drm/drm_vblank.h> |
|---|
| 20 | 19 | #include <drm/exynos_drm.h> |
|---|
| 21 | 20 | |
|---|
| 22 | | -#include <drm/drm_edid.h> |
|---|
| 23 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 24 | | -#include <drm/drm_atomic_helper.h> |
|---|
| 25 | | - |
|---|
| 26 | | -#include "exynos_drm_drv.h" |
|---|
| 27 | 21 | #include "exynos_drm_crtc.h" |
|---|
| 22 | +#include "exynos_drm_drv.h" |
|---|
| 28 | 23 | #include "exynos_drm_fb.h" |
|---|
| 29 | 24 | #include "exynos_drm_plane.h" |
|---|
| 30 | 25 | #include "exynos_drm_vidi.h" |
|---|
| .. | .. |
|---|
| 40 | 35 | |
|---|
| 41 | 36 | struct vidi_context { |
|---|
| 42 | 37 | struct drm_encoder encoder; |
|---|
| 43 | | - struct platform_device *pdev; |
|---|
| 44 | 38 | struct drm_device *drm_dev; |
|---|
| 39 | + struct device *dev; |
|---|
| 45 | 40 | struct exynos_drm_crtc *crtc; |
|---|
| 46 | 41 | struct drm_connector connector; |
|---|
| 47 | 42 | struct exynos_drm_plane planes[WINDOWS_NR]; |
|---|
| .. | .. |
|---|
| 123 | 118 | return; |
|---|
| 124 | 119 | |
|---|
| 125 | 120 | addr = exynos_drm_fb_dma_addr(state->fb, 0); |
|---|
| 126 | | - DRM_DEBUG_KMS("dma_addr = %pad\n", &addr); |
|---|
| 121 | + DRM_DEV_DEBUG_KMS(ctx->dev, "dma_addr = %pad\n", &addr); |
|---|
| 127 | 122 | } |
|---|
| 128 | 123 | |
|---|
| 129 | | -static void vidi_enable(struct exynos_drm_crtc *crtc) |
|---|
| 124 | +static void vidi_atomic_enable(struct exynos_drm_crtc *crtc) |
|---|
| 130 | 125 | { |
|---|
| 131 | 126 | struct vidi_context *ctx = crtc->ctx; |
|---|
| 132 | 127 | |
|---|
| .. | .. |
|---|
| 139 | 134 | drm_crtc_vblank_on(&crtc->base); |
|---|
| 140 | 135 | } |
|---|
| 141 | 136 | |
|---|
| 142 | | -static void vidi_disable(struct exynos_drm_crtc *crtc) |
|---|
| 137 | +static void vidi_atomic_disable(struct exynos_drm_crtc *crtc) |
|---|
| 143 | 138 | { |
|---|
| 144 | 139 | struct vidi_context *ctx = crtc->ctx; |
|---|
| 145 | 140 | |
|---|
| .. | .. |
|---|
| 153 | 148 | } |
|---|
| 154 | 149 | |
|---|
| 155 | 150 | static const struct exynos_drm_crtc_ops vidi_crtc_ops = { |
|---|
| 156 | | - .enable = vidi_enable, |
|---|
| 157 | | - .disable = vidi_disable, |
|---|
| 151 | + .atomic_enable = vidi_atomic_enable, |
|---|
| 152 | + .atomic_disable = vidi_atomic_disable, |
|---|
| 158 | 153 | .enable_vblank = vidi_enable_vblank, |
|---|
| 159 | 154 | .disable_vblank = vidi_disable_vblank, |
|---|
| 160 | 155 | .update_plane = vidi_update_plane, |
|---|
| .. | .. |
|---|
| 205 | 200 | |
|---|
| 206 | 201 | /* if raw_edid isn't same as fake data then it can't be tested. */ |
|---|
| 207 | 202 | if (ctx->raw_edid != (struct edid *)fake_edid_info) { |
|---|
| 208 | | - DRM_DEBUG_KMS("edid data is not fake data.\n"); |
|---|
| 203 | + DRM_DEV_DEBUG_KMS(dev, "edid data is not fake data.\n"); |
|---|
| 209 | 204 | return -EINVAL; |
|---|
| 210 | 205 | } |
|---|
| 211 | 206 | |
|---|
| 212 | | - DRM_DEBUG_KMS("requested connection.\n"); |
|---|
| 207 | + DRM_DEV_DEBUG_KMS(dev, "requested connection.\n"); |
|---|
| 213 | 208 | |
|---|
| 214 | 209 | drm_helper_hpd_irq_event(ctx->drm_dev); |
|---|
| 215 | 210 | |
|---|
| .. | .. |
|---|
| 219 | 214 | static DEVICE_ATTR(connection, 0644, vidi_show_connection, |
|---|
| 220 | 215 | vidi_store_connection); |
|---|
| 221 | 216 | |
|---|
| 217 | +static struct attribute *vidi_attrs[] = { |
|---|
| 218 | + &dev_attr_connection.attr, |
|---|
| 219 | + NULL, |
|---|
| 220 | +}; |
|---|
| 221 | +ATTRIBUTE_GROUPS(vidi); |
|---|
| 222 | + |
|---|
| 222 | 223 | int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, |
|---|
| 223 | 224 | struct drm_file *file_priv) |
|---|
| 224 | 225 | { |
|---|
| .. | .. |
|---|
| 226 | 227 | struct drm_exynos_vidi_connection *vidi = data; |
|---|
| 227 | 228 | |
|---|
| 228 | 229 | if (!vidi) { |
|---|
| 229 | | - DRM_DEBUG_KMS("user data for vidi is null.\n"); |
|---|
| 230 | + DRM_DEV_DEBUG_KMS(ctx->dev, |
|---|
| 231 | + "user data for vidi is null.\n"); |
|---|
| 230 | 232 | return -EINVAL; |
|---|
| 231 | 233 | } |
|---|
| 232 | 234 | |
|---|
| 233 | 235 | if (vidi->connection > 1) { |
|---|
| 234 | | - DRM_DEBUG_KMS("connection should be 0 or 1.\n"); |
|---|
| 236 | + DRM_DEV_DEBUG_KMS(ctx->dev, |
|---|
| 237 | + "connection should be 0 or 1.\n"); |
|---|
| 235 | 238 | return -EINVAL; |
|---|
| 236 | 239 | } |
|---|
| 237 | 240 | |
|---|
| 238 | 241 | if (ctx->connected == vidi->connection) { |
|---|
| 239 | | - DRM_DEBUG_KMS("same connection request.\n"); |
|---|
| 242 | + DRM_DEV_DEBUG_KMS(ctx->dev, |
|---|
| 243 | + "same connection request.\n"); |
|---|
| 240 | 244 | return -EINVAL; |
|---|
| 241 | 245 | } |
|---|
| 242 | 246 | |
|---|
| .. | .. |
|---|
| 245 | 249 | |
|---|
| 246 | 250 | raw_edid = (struct edid *)(unsigned long)vidi->edid; |
|---|
| 247 | 251 | if (!drm_edid_is_valid(raw_edid)) { |
|---|
| 248 | | - DRM_DEBUG_KMS("edid data is invalid.\n"); |
|---|
| 252 | + DRM_DEV_DEBUG_KMS(ctx->dev, |
|---|
| 253 | + "edid data is invalid.\n"); |
|---|
| 249 | 254 | return -EINVAL; |
|---|
| 250 | 255 | } |
|---|
| 251 | 256 | ctx->raw_edid = drm_edid_duplicate(raw_edid); |
|---|
| 252 | 257 | if (!ctx->raw_edid) { |
|---|
| 253 | | - DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); |
|---|
| 258 | + DRM_DEV_DEBUG_KMS(ctx->dev, |
|---|
| 259 | + "failed to allocate raw_edid.\n"); |
|---|
| 254 | 260 | return -ENOMEM; |
|---|
| 255 | 261 | } |
|---|
| 256 | 262 | } else { |
|---|
| .. | .. |
|---|
| 308 | 314 | * to ctx->raw_edid through specific ioctl. |
|---|
| 309 | 315 | */ |
|---|
| 310 | 316 | if (!ctx->raw_edid) { |
|---|
| 311 | | - DRM_DEBUG_KMS("raw_edid is null.\n"); |
|---|
| 317 | + DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n"); |
|---|
| 312 | 318 | return -EFAULT; |
|---|
| 313 | 319 | } |
|---|
| 314 | 320 | |
|---|
| 315 | 321 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; |
|---|
| 316 | 322 | edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); |
|---|
| 317 | 323 | if (!edid) { |
|---|
| 318 | | - DRM_DEBUG_KMS("failed to allocate edid\n"); |
|---|
| 324 | + DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n"); |
|---|
| 319 | 325 | return -ENOMEM; |
|---|
| 320 | 326 | } |
|---|
| 321 | 327 | |
|---|
| .. | .. |
|---|
| 339 | 345 | ret = drm_connector_init(ctx->drm_dev, connector, |
|---|
| 340 | 346 | &vidi_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); |
|---|
| 341 | 347 | if (ret) { |
|---|
| 342 | | - DRM_ERROR("Failed to initialize connector with drm\n"); |
|---|
| 348 | + DRM_DEV_ERROR(ctx->dev, |
|---|
| 349 | + "Failed to initialize connector with drm\n"); |
|---|
| 343 | 350 | return ret; |
|---|
| 344 | 351 | } |
|---|
| 345 | 352 | |
|---|
| .. | .. |
|---|
| 367 | 374 | .mode_set = exynos_vidi_mode_set, |
|---|
| 368 | 375 | .enable = exynos_vidi_enable, |
|---|
| 369 | 376 | .disable = exynos_vidi_disable, |
|---|
| 370 | | -}; |
|---|
| 371 | | - |
|---|
| 372 | | -static const struct drm_encoder_funcs exynos_vidi_encoder_funcs = { |
|---|
| 373 | | - .destroy = drm_encoder_cleanup, |
|---|
| 374 | 377 | }; |
|---|
| 375 | 378 | |
|---|
| 376 | 379 | static int vidi_bind(struct device *dev, struct device *master, void *data) |
|---|
| .. | .. |
|---|
| 402 | 405 | ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, |
|---|
| 403 | 406 | EXYNOS_DISPLAY_TYPE_VIDI, &vidi_crtc_ops, ctx); |
|---|
| 404 | 407 | if (IS_ERR(ctx->crtc)) { |
|---|
| 405 | | - DRM_ERROR("failed to create crtc.\n"); |
|---|
| 408 | + DRM_DEV_ERROR(dev, "failed to create crtc.\n"); |
|---|
| 406 | 409 | return PTR_ERR(ctx->crtc); |
|---|
| 407 | 410 | } |
|---|
| 408 | 411 | |
|---|
| 409 | | - drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs, |
|---|
| 410 | | - DRM_MODE_ENCODER_TMDS, NULL); |
|---|
| 412 | + drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS); |
|---|
| 411 | 413 | |
|---|
| 412 | 414 | drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs); |
|---|
| 413 | 415 | |
|---|
| .. | .. |
|---|
| 417 | 419 | |
|---|
| 418 | 420 | ret = vidi_create_connector(encoder); |
|---|
| 419 | 421 | if (ret) { |
|---|
| 420 | | - DRM_ERROR("failed to create connector ret = %d\n", ret); |
|---|
| 422 | + DRM_DEV_ERROR(dev, "failed to create connector ret = %d\n", |
|---|
| 423 | + ret); |
|---|
| 421 | 424 | drm_encoder_cleanup(encoder); |
|---|
| 422 | 425 | return ret; |
|---|
| 423 | 426 | } |
|---|
| .. | .. |
|---|
| 441 | 444 | static int vidi_probe(struct platform_device *pdev) |
|---|
| 442 | 445 | { |
|---|
| 443 | 446 | struct vidi_context *ctx; |
|---|
| 444 | | - int ret; |
|---|
| 447 | + struct device *dev = &pdev->dev; |
|---|
| 445 | 448 | |
|---|
| 446 | | - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); |
|---|
| 449 | + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); |
|---|
| 447 | 450 | if (!ctx) |
|---|
| 448 | 451 | return -ENOMEM; |
|---|
| 449 | 452 | |
|---|
| 450 | | - ctx->pdev = pdev; |
|---|
| 453 | + ctx->dev = dev; |
|---|
| 451 | 454 | |
|---|
| 452 | 455 | timer_setup(&ctx->timer, vidi_fake_vblank_timer, 0); |
|---|
| 453 | 456 | |
|---|
| .. | .. |
|---|
| 455 | 458 | |
|---|
| 456 | 459 | platform_set_drvdata(pdev, ctx); |
|---|
| 457 | 460 | |
|---|
| 458 | | - ret = device_create_file(&pdev->dev, &dev_attr_connection); |
|---|
| 459 | | - if (ret < 0) { |
|---|
| 460 | | - DRM_ERROR("failed to create connection sysfs.\n"); |
|---|
| 461 | | - return ret; |
|---|
| 462 | | - } |
|---|
| 463 | | - |
|---|
| 464 | | - ret = component_add(&pdev->dev, &vidi_component_ops); |
|---|
| 465 | | - if (ret) |
|---|
| 466 | | - goto err_remove_file; |
|---|
| 467 | | - |
|---|
| 468 | | - return ret; |
|---|
| 469 | | - |
|---|
| 470 | | -err_remove_file: |
|---|
| 471 | | - device_remove_file(&pdev->dev, &dev_attr_connection); |
|---|
| 472 | | - |
|---|
| 473 | | - return ret; |
|---|
| 461 | + return component_add(dev, &vidi_component_ops); |
|---|
| 474 | 462 | } |
|---|
| 475 | 463 | |
|---|
| 476 | 464 | static int vidi_remove(struct platform_device *pdev) |
|---|
| .. | .. |
|---|
| 480 | 468 | if (ctx->raw_edid != (struct edid *)fake_edid_info) { |
|---|
| 481 | 469 | kfree(ctx->raw_edid); |
|---|
| 482 | 470 | ctx->raw_edid = NULL; |
|---|
| 483 | | - |
|---|
| 484 | | - return -EINVAL; |
|---|
| 485 | 471 | } |
|---|
| 486 | 472 | |
|---|
| 487 | 473 | component_del(&pdev->dev, &vidi_component_ops); |
|---|
| .. | .. |
|---|
| 495 | 481 | .driver = { |
|---|
| 496 | 482 | .name = "exynos-drm-vidi", |
|---|
| 497 | 483 | .owner = THIS_MODULE, |
|---|
| 484 | + .dev_groups = vidi_groups, |
|---|
| 498 | 485 | }, |
|---|
| 499 | 486 | }; |
|---|