| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2012 Samsung Electronics Co.Ltd |
|---|
| 3 | 4 | * Authors: |
|---|
| 4 | 5 | * YoungJun Cho <yj44.cho@samsung.com> |
|---|
| 5 | 6 | * Eunchul Kim <chulspro.kim@samsung.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundationr |
|---|
| 10 | 7 | */ |
|---|
| 11 | 8 | |
|---|
| 12 | | -#include <linux/kernel.h> |
|---|
| 9 | +#include <linux/clk.h> |
|---|
| 13 | 10 | #include <linux/component.h> |
|---|
| 14 | 11 | #include <linux/err.h> |
|---|
| 15 | 12 | #include <linux/interrupt.h> |
|---|
| 16 | 13 | #include <linux/io.h> |
|---|
| 17 | | -#include <linux/platform_device.h> |
|---|
| 18 | | -#include <linux/clk.h> |
|---|
| 14 | +#include <linux/kernel.h> |
|---|
| 19 | 15 | #include <linux/of_device.h> |
|---|
| 16 | +#include <linux/platform_device.h> |
|---|
| 20 | 17 | #include <linux/pm_runtime.h> |
|---|
| 18 | +#include <linux/sizes.h> |
|---|
| 21 | 19 | |
|---|
| 22 | | -#include <drm/drmP.h> |
|---|
| 20 | +#include <drm/drm_fourcc.h> |
|---|
| 23 | 21 | #include <drm/exynos_drm.h> |
|---|
| 24 | | -#include "regs-rotator.h" |
|---|
| 22 | + |
|---|
| 25 | 23 | #include "exynos_drm_drv.h" |
|---|
| 26 | | -#include "exynos_drm_iommu.h" |
|---|
| 27 | 24 | #include "exynos_drm_ipp.h" |
|---|
| 25 | +#include "regs-rotator.h" |
|---|
| 28 | 26 | |
|---|
| 29 | 27 | /* |
|---|
| 30 | 28 | * Rotator supports image crop/rotator and input/output DMA operations. |
|---|
| .. | .. |
|---|
| 58 | 56 | struct rot_context { |
|---|
| 59 | 57 | struct exynos_drm_ipp ipp; |
|---|
| 60 | 58 | struct drm_device *drm_dev; |
|---|
| 59 | + void *dma_priv; |
|---|
| 61 | 60 | struct device *dev; |
|---|
| 62 | 61 | void __iomem *regs; |
|---|
| 63 | 62 | struct clk *clock; |
|---|
| .. | .. |
|---|
| 244 | 243 | struct exynos_drm_ipp *ipp = &rot->ipp; |
|---|
| 245 | 244 | |
|---|
| 246 | 245 | rot->drm_dev = drm_dev; |
|---|
| 247 | | - drm_iommu_attach_device(drm_dev, dev); |
|---|
| 246 | + ipp->drm_dev = drm_dev; |
|---|
| 247 | + exynos_drm_register_dma(drm_dev, dev, &rot->dma_priv); |
|---|
| 248 | 248 | |
|---|
| 249 | | - exynos_drm_ipp_register(drm_dev, ipp, &ipp_funcs, |
|---|
| 249 | + exynos_drm_ipp_register(dev, ipp, &ipp_funcs, |
|---|
| 250 | 250 | DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE, |
|---|
| 251 | 251 | rot->formats, rot->num_formats, "rotator"); |
|---|
| 252 | 252 | |
|---|
| .. | .. |
|---|
| 259 | 259 | void *data) |
|---|
| 260 | 260 | { |
|---|
| 261 | 261 | struct rot_context *rot = dev_get_drvdata(dev); |
|---|
| 262 | | - struct drm_device *drm_dev = data; |
|---|
| 263 | 262 | struct exynos_drm_ipp *ipp = &rot->ipp; |
|---|
| 264 | 263 | |
|---|
| 265 | | - exynos_drm_ipp_unregister(drm_dev, ipp); |
|---|
| 266 | | - drm_iommu_detach_device(rot->drm_dev, rot->dev); |
|---|
| 264 | + exynos_drm_ipp_unregister(dev, ipp); |
|---|
| 265 | + exynos_drm_unregister_dma(rot->drm_dev, rot->dev, &rot->dma_priv); |
|---|
| 267 | 266 | } |
|---|
| 268 | 267 | |
|---|
| 269 | 268 | static const struct component_ops rotator_component_ops = { |
|---|
| .. | .. |
|---|
| 294 | 293 | return PTR_ERR(rot->regs); |
|---|
| 295 | 294 | |
|---|
| 296 | 295 | irq = platform_get_irq(pdev, 0); |
|---|
| 297 | | - if (irq < 0) { |
|---|
| 298 | | - dev_err(dev, "failed to get irq\n"); |
|---|
| 296 | + if (irq < 0) |
|---|
| 299 | 297 | return irq; |
|---|
| 300 | | - } |
|---|
| 301 | 298 | |
|---|
| 302 | 299 | ret = devm_request_irq(dev, irq, rotator_irq_handler, 0, dev_name(dev), |
|---|
| 303 | 300 | rot); |
|---|
| .. | .. |
|---|
| 357 | 354 | } |
|---|
| 358 | 355 | #endif |
|---|
| 359 | 356 | |
|---|
| 357 | +static const struct drm_exynos_ipp_limit rotator_s5pv210_rbg888_limits[] = { |
|---|
| 358 | + { IPP_SIZE_LIMIT(BUFFER, .h = { 8, SZ_16K }, .v = { 8, SZ_16K }) }, |
|---|
| 359 | + { IPP_SIZE_LIMIT(AREA, .h.align = 2, .v.align = 2) }, |
|---|
| 360 | +}; |
|---|
| 361 | + |
|---|
| 360 | 362 | static const struct drm_exynos_ipp_limit rotator_4210_rbg888_limits[] = { |
|---|
| 361 | 363 | { IPP_SIZE_LIMIT(BUFFER, .h = { 8, SZ_16K }, .v = { 8, SZ_16K }) }, |
|---|
| 362 | 364 | { IPP_SIZE_LIMIT(AREA, .h.align = 4, .v.align = 4) }, |
|---|
| .. | .. |
|---|
| 372 | 374 | { IPP_SIZE_LIMIT(AREA, .h.align = 2, .v.align = 2) }, |
|---|
| 373 | 375 | }; |
|---|
| 374 | 376 | |
|---|
| 377 | +static const struct drm_exynos_ipp_limit rotator_s5pv210_yuv_limits[] = { |
|---|
| 378 | + { IPP_SIZE_LIMIT(BUFFER, .h = { 32, SZ_64K }, .v = { 32, SZ_64K }) }, |
|---|
| 379 | + { IPP_SIZE_LIMIT(AREA, .h.align = 8, .v.align = 8) }, |
|---|
| 380 | +}; |
|---|
| 381 | + |
|---|
| 375 | 382 | static const struct drm_exynos_ipp_limit rotator_4210_yuv_limits[] = { |
|---|
| 376 | 383 | { IPP_SIZE_LIMIT(BUFFER, .h = { 32, SZ_64K }, .v = { 32, SZ_64K }) }, |
|---|
| 377 | 384 | { IPP_SIZE_LIMIT(AREA, .h.align = 8, .v.align = 8) }, |
|---|
| .. | .. |
|---|
| 380 | 387 | static const struct drm_exynos_ipp_limit rotator_4412_yuv_limits[] = { |
|---|
| 381 | 388 | { IPP_SIZE_LIMIT(BUFFER, .h = { 32, SZ_32K }, .v = { 32, SZ_32K }) }, |
|---|
| 382 | 389 | { IPP_SIZE_LIMIT(AREA, .h.align = 8, .v.align = 8) }, |
|---|
| 390 | +}; |
|---|
| 391 | + |
|---|
| 392 | +static const struct exynos_drm_ipp_formats rotator_s5pv210_formats[] = { |
|---|
| 393 | + { IPP_SRCDST_FORMAT(XRGB8888, rotator_s5pv210_rbg888_limits) }, |
|---|
| 394 | + { IPP_SRCDST_FORMAT(NV12, rotator_s5pv210_yuv_limits) }, |
|---|
| 383 | 395 | }; |
|---|
| 384 | 396 | |
|---|
| 385 | 397 | static const struct exynos_drm_ipp_formats rotator_4210_formats[] = { |
|---|
| .. | .. |
|---|
| 395 | 407 | static const struct exynos_drm_ipp_formats rotator_5250_formats[] = { |
|---|
| 396 | 408 | { IPP_SRCDST_FORMAT(XRGB8888, rotator_5250_rbg888_limits) }, |
|---|
| 397 | 409 | { IPP_SRCDST_FORMAT(NV12, rotator_4412_yuv_limits) }, |
|---|
| 410 | +}; |
|---|
| 411 | + |
|---|
| 412 | +static const struct rot_variant rotator_s5pv210_data = { |
|---|
| 413 | + .formats = rotator_s5pv210_formats, |
|---|
| 414 | + .num_formats = ARRAY_SIZE(rotator_s5pv210_formats), |
|---|
| 398 | 415 | }; |
|---|
| 399 | 416 | |
|---|
| 400 | 417 | static const struct rot_variant rotator_4210_data = { |
|---|
| .. | .. |
|---|
| 414 | 431 | |
|---|
| 415 | 432 | static const struct of_device_id exynos_rotator_match[] = { |
|---|
| 416 | 433 | { |
|---|
| 434 | + .compatible = "samsung,s5pv210-rotator", |
|---|
| 435 | + .data = &rotator_s5pv210_data, |
|---|
| 436 | + }, { |
|---|
| 417 | 437 | .compatible = "samsung,exynos4210-rotator", |
|---|
| 418 | 438 | .data = &rotator_4210_data, |
|---|
| 419 | 439 | }, { |
|---|