| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2012 Samsung Electronics Co.Ltd |
|---|
| 3 | 4 | * Authors: Joonyoung Shim <jy0922.shim@samsung.com> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundationr |
|---|
| 8 | 5 | */ |
|---|
| 9 | 6 | |
|---|
| 10 | | -#include <linux/kernel.h> |
|---|
| 11 | 7 | #include <linux/clk.h> |
|---|
| 12 | 8 | #include <linux/component.h> |
|---|
| 9 | +#include <linux/delay.h> |
|---|
| 10 | +#include <linux/dma-mapping.h> |
|---|
| 13 | 11 | #include <linux/err.h> |
|---|
| 14 | 12 | #include <linux/interrupt.h> |
|---|
| 15 | 13 | #include <linux/io.h> |
|---|
| 14 | +#include <linux/kernel.h> |
|---|
| 15 | +#include <linux/of.h> |
|---|
| 16 | 16 | #include <linux/platform_device.h> |
|---|
| 17 | 17 | #include <linux/pm_runtime.h> |
|---|
| 18 | 18 | #include <linux/slab.h> |
|---|
| 19 | +#include <linux/uaccess.h> |
|---|
| 19 | 20 | #include <linux/workqueue.h> |
|---|
| 20 | | -#include <linux/dma-mapping.h> |
|---|
| 21 | | -#include <linux/of.h> |
|---|
| 22 | 21 | |
|---|
| 23 | | -#include <drm/drmP.h> |
|---|
| 22 | +#include <drm/drm_file.h> |
|---|
| 24 | 23 | #include <drm/exynos_drm.h> |
|---|
| 24 | + |
|---|
| 25 | 25 | #include "exynos_drm_drv.h" |
|---|
| 26 | 26 | #include "exynos_drm_g2d.h" |
|---|
| 27 | 27 | #include "exynos_drm_gem.h" |
|---|
| 28 | | -#include "exynos_drm_iommu.h" |
|---|
| 29 | 28 | |
|---|
| 30 | 29 | #define G2D_HW_MAJOR_VER 4 |
|---|
| 31 | 30 | #define G2D_HW_MINOR_VER 1 |
|---|
| .. | .. |
|---|
| 233 | 232 | |
|---|
| 234 | 233 | struct g2d_data { |
|---|
| 235 | 234 | struct device *dev; |
|---|
| 235 | + void *dma_priv; |
|---|
| 236 | 236 | struct clk *gate_clk; |
|---|
| 237 | 237 | void __iomem *regs; |
|---|
| 238 | 238 | int irq; |
|---|
| .. | .. |
|---|
| 268 | 268 | static int g2d_init_cmdlist(struct g2d_data *g2d) |
|---|
| 269 | 269 | { |
|---|
| 270 | 270 | struct device *dev = g2d->dev; |
|---|
| 271 | | - struct g2d_cmdlist_node *node = g2d->cmdlist_node; |
|---|
| 271 | + struct g2d_cmdlist_node *node; |
|---|
| 272 | 272 | int nr; |
|---|
| 273 | 273 | int ret; |
|---|
| 274 | 274 | struct g2d_buf_info *buf_info; |
|---|
| .. | .. |
|---|
| 395 | 395 | return; |
|---|
| 396 | 396 | |
|---|
| 397 | 397 | out: |
|---|
| 398 | | - dma_unmap_sg(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt->sgl, |
|---|
| 399 | | - g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL); |
|---|
| 398 | + dma_unmap_sgtable(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt, |
|---|
| 399 | + DMA_BIDIRECTIONAL, 0); |
|---|
| 400 | 400 | |
|---|
| 401 | 401 | pages = frame_vector_pages(g2d_userptr->vec); |
|---|
| 402 | 402 | if (!IS_ERR(pages)) { |
|---|
| .. | .. |
|---|
| 430 | 430 | int ret; |
|---|
| 431 | 431 | |
|---|
| 432 | 432 | if (!size) { |
|---|
| 433 | | - DRM_ERROR("invalid userptr size.\n"); |
|---|
| 433 | + DRM_DEV_ERROR(g2d->dev, "invalid userptr size.\n"); |
|---|
| 434 | 434 | return ERR_PTR(-EINVAL); |
|---|
| 435 | 435 | } |
|---|
| 436 | 436 | |
|---|
| .. | .. |
|---|
| 483 | 483 | ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE, |
|---|
| 484 | 484 | g2d_userptr->vec); |
|---|
| 485 | 485 | if (ret != npages) { |
|---|
| 486 | | - DRM_ERROR("failed to get user pages from userptr.\n"); |
|---|
| 486 | + DRM_DEV_ERROR(g2d->dev, |
|---|
| 487 | + "failed to get user pages from userptr.\n"); |
|---|
| 487 | 488 | if (ret < 0) |
|---|
| 488 | 489 | goto err_destroy_framevec; |
|---|
| 489 | 490 | ret = -EFAULT; |
|---|
| .. | .. |
|---|
| 504 | 505 | frame_vector_pages(g2d_userptr->vec), |
|---|
| 505 | 506 | npages, offset, size, GFP_KERNEL); |
|---|
| 506 | 507 | if (ret < 0) { |
|---|
| 507 | | - DRM_ERROR("failed to get sgt from pages.\n"); |
|---|
| 508 | + DRM_DEV_ERROR(g2d->dev, "failed to get sgt from pages.\n"); |
|---|
| 508 | 509 | goto err_free_sgt; |
|---|
| 509 | 510 | } |
|---|
| 510 | 511 | |
|---|
| 511 | 512 | g2d_userptr->sgt = sgt; |
|---|
| 512 | 513 | |
|---|
| 513 | | - if (!dma_map_sg(to_dma_dev(g2d->drm_dev), sgt->sgl, sgt->nents, |
|---|
| 514 | | - DMA_BIDIRECTIONAL)) { |
|---|
| 515 | | - DRM_ERROR("failed to map sgt with dma region.\n"); |
|---|
| 516 | | - ret = -ENOMEM; |
|---|
| 514 | + ret = dma_map_sgtable(to_dma_dev(g2d->drm_dev), sgt, |
|---|
| 515 | + DMA_BIDIRECTIONAL, 0); |
|---|
| 516 | + if (ret) { |
|---|
| 517 | + DRM_DEV_ERROR(g2d->dev, "failed to map sgt with dma region.\n"); |
|---|
| 517 | 518 | goto err_sg_free_table; |
|---|
| 518 | 519 | } |
|---|
| 519 | 520 | |
|---|
| .. | .. |
|---|
| 561 | 562 | g2d->current_pool = 0; |
|---|
| 562 | 563 | } |
|---|
| 563 | 564 | |
|---|
| 564 | | -static enum g2d_reg_type g2d_get_reg_type(int reg_offset) |
|---|
| 565 | +static enum g2d_reg_type g2d_get_reg_type(struct g2d_data *g2d, int reg_offset) |
|---|
| 565 | 566 | { |
|---|
| 566 | 567 | enum g2d_reg_type reg_type; |
|---|
| 567 | 568 | |
|---|
| .. | .. |
|---|
| 594 | 595 | break; |
|---|
| 595 | 596 | default: |
|---|
| 596 | 597 | reg_type = REG_TYPE_NONE; |
|---|
| 597 | | - DRM_ERROR("Unknown register offset![%d]\n", reg_offset); |
|---|
| 598 | + DRM_DEV_ERROR(g2d->dev, "Unknown register offset![%d]\n", |
|---|
| 599 | + reg_offset); |
|---|
| 598 | 600 | break; |
|---|
| 599 | 601 | } |
|---|
| 600 | 602 | |
|---|
| .. | .. |
|---|
| 628 | 630 | return bpp; |
|---|
| 629 | 631 | } |
|---|
| 630 | 632 | |
|---|
| 631 | | -static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, |
|---|
| 632 | | - enum g2d_reg_type reg_type, |
|---|
| 633 | | - unsigned long size) |
|---|
| 633 | +static bool g2d_check_buf_desc_is_valid(struct g2d_data *g2d, |
|---|
| 634 | + struct g2d_buf_desc *buf_desc, |
|---|
| 635 | + enum g2d_reg_type reg_type, |
|---|
| 636 | + unsigned long size) |
|---|
| 634 | 637 | { |
|---|
| 635 | 638 | int width, height; |
|---|
| 636 | 639 | unsigned long bpp, last_pos; |
|---|
| .. | .. |
|---|
| 645 | 648 | /* This check also makes sure that right_x > left_x. */ |
|---|
| 646 | 649 | width = (int)buf_desc->right_x - (int)buf_desc->left_x; |
|---|
| 647 | 650 | if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { |
|---|
| 648 | | - DRM_ERROR("width[%d] is out of range!\n", width); |
|---|
| 651 | + DRM_DEV_ERROR(g2d->dev, "width[%d] is out of range!\n", width); |
|---|
| 649 | 652 | return false; |
|---|
| 650 | 653 | } |
|---|
| 651 | 654 | |
|---|
| 652 | 655 | /* This check also makes sure that bottom_y > top_y. */ |
|---|
| 653 | 656 | height = (int)buf_desc->bottom_y - (int)buf_desc->top_y; |
|---|
| 654 | 657 | if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { |
|---|
| 655 | | - DRM_ERROR("height[%d] is out of range!\n", height); |
|---|
| 658 | + DRM_DEV_ERROR(g2d->dev, |
|---|
| 659 | + "height[%d] is out of range!\n", height); |
|---|
| 656 | 660 | return false; |
|---|
| 657 | 661 | } |
|---|
| 658 | 662 | |
|---|
| .. | .. |
|---|
| 671 | 675 | */ |
|---|
| 672 | 676 | |
|---|
| 673 | 677 | if (last_pos >= size) { |
|---|
| 674 | | - DRM_ERROR("last engine access position [%lu] " |
|---|
| 675 | | - "is out of range [%lu]!\n", last_pos, size); |
|---|
| 678 | + DRM_DEV_ERROR(g2d->dev, "last engine access position [%lu] " |
|---|
| 679 | + "is out of range [%lu]!\n", last_pos, size); |
|---|
| 676 | 680 | return false; |
|---|
| 677 | 681 | } |
|---|
| 678 | 682 | |
|---|
| .. | .. |
|---|
| 702 | 706 | offset = cmdlist->data[reg_pos]; |
|---|
| 703 | 707 | handle = cmdlist->data[reg_pos + 1]; |
|---|
| 704 | 708 | |
|---|
| 705 | | - reg_type = g2d_get_reg_type(offset); |
|---|
| 709 | + reg_type = g2d_get_reg_type(g2d, offset); |
|---|
| 706 | 710 | if (reg_type == REG_TYPE_NONE) { |
|---|
| 707 | 711 | ret = -EFAULT; |
|---|
| 708 | 712 | goto err; |
|---|
| .. | .. |
|---|
| 719 | 723 | goto err; |
|---|
| 720 | 724 | } |
|---|
| 721 | 725 | |
|---|
| 722 | | - if (!g2d_check_buf_desc_is_valid(buf_desc, |
|---|
| 726 | + if (!g2d_check_buf_desc_is_valid(g2d, buf_desc, |
|---|
| 723 | 727 | reg_type, exynos_gem->size)) { |
|---|
| 724 | 728 | exynos_drm_gem_put(exynos_gem); |
|---|
| 725 | 729 | ret = -EFAULT; |
|---|
| .. | .. |
|---|
| 737 | 741 | goto err; |
|---|
| 738 | 742 | } |
|---|
| 739 | 743 | |
|---|
| 740 | | - if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, |
|---|
| 741 | | - g2d_userptr.size)) { |
|---|
| 744 | + if (!g2d_check_buf_desc_is_valid(g2d, buf_desc, |
|---|
| 745 | + reg_type, |
|---|
| 746 | + g2d_userptr.size)) { |
|---|
| 742 | 747 | ret = -EFAULT; |
|---|
| 743 | 748 | goto err; |
|---|
| 744 | 749 | } |
|---|
| .. | .. |
|---|
| 846 | 851 | * |
|---|
| 847 | 852 | * Has to be called under runqueue lock. |
|---|
| 848 | 853 | */ |
|---|
| 849 | | -static void g2d_remove_runqueue_nodes(struct g2d_data *g2d, struct drm_file* file) |
|---|
| 854 | +static void g2d_remove_runqueue_nodes(struct g2d_data *g2d, struct drm_file *file) |
|---|
| 850 | 855 | { |
|---|
| 851 | 856 | struct g2d_runqueue_node *node, *n; |
|---|
| 852 | 857 | |
|---|
| .. | .. |
|---|
| 1045 | 1050 | if (!for_addr) |
|---|
| 1046 | 1051 | goto err; |
|---|
| 1047 | 1052 | |
|---|
| 1048 | | - reg_type = g2d_get_reg_type(reg_offset); |
|---|
| 1053 | + reg_type = g2d_get_reg_type(g2d, reg_offset); |
|---|
| 1049 | 1054 | |
|---|
| 1050 | 1055 | /* check userptr buffer type. */ |
|---|
| 1051 | 1056 | if ((cmdlist->data[index] & ~0x7fffffff) >> 31) { |
|---|
| .. | .. |
|---|
| 1059 | 1064 | if (for_addr) |
|---|
| 1060 | 1065 | goto err; |
|---|
| 1061 | 1066 | |
|---|
| 1062 | | - reg_type = g2d_get_reg_type(reg_offset); |
|---|
| 1067 | + reg_type = g2d_get_reg_type(g2d, reg_offset); |
|---|
| 1063 | 1068 | |
|---|
| 1064 | 1069 | buf_desc = &buf_info->descs[reg_type]; |
|---|
| 1065 | 1070 | buf_desc->stride = cmdlist->data[index + 1]; |
|---|
| .. | .. |
|---|
| 1069 | 1074 | if (for_addr) |
|---|
| 1070 | 1075 | goto err; |
|---|
| 1071 | 1076 | |
|---|
| 1072 | | - reg_type = g2d_get_reg_type(reg_offset); |
|---|
| 1077 | + reg_type = g2d_get_reg_type(g2d, reg_offset); |
|---|
| 1073 | 1078 | |
|---|
| 1074 | 1079 | buf_desc = &buf_info->descs[reg_type]; |
|---|
| 1075 | 1080 | value = cmdlist->data[index + 1]; |
|---|
| .. | .. |
|---|
| 1081 | 1086 | if (for_addr) |
|---|
| 1082 | 1087 | goto err; |
|---|
| 1083 | 1088 | |
|---|
| 1084 | | - reg_type = g2d_get_reg_type(reg_offset); |
|---|
| 1089 | + reg_type = g2d_get_reg_type(g2d, reg_offset); |
|---|
| 1085 | 1090 | |
|---|
| 1086 | 1091 | buf_desc = &buf_info->descs[reg_type]; |
|---|
| 1087 | 1092 | value = cmdlist->data[index + 1]; |
|---|
| .. | .. |
|---|
| 1094 | 1099 | if (for_addr) |
|---|
| 1095 | 1100 | goto err; |
|---|
| 1096 | 1101 | |
|---|
| 1097 | | - reg_type = g2d_get_reg_type(reg_offset); |
|---|
| 1102 | + reg_type = g2d_get_reg_type(g2d, reg_offset); |
|---|
| 1098 | 1103 | |
|---|
| 1099 | 1104 | buf_desc = &buf_info->descs[reg_type]; |
|---|
| 1100 | 1105 | value = cmdlist->data[index + 1]; |
|---|
| .. | .. |
|---|
| 1405 | 1410 | return ret; |
|---|
| 1406 | 1411 | } |
|---|
| 1407 | 1412 | |
|---|
| 1408 | | - ret = drm_iommu_attach_device(drm_dev, dev); |
|---|
| 1413 | + ret = exynos_drm_register_dma(drm_dev, dev, &g2d->dma_priv); |
|---|
| 1409 | 1414 | if (ret < 0) { |
|---|
| 1410 | 1415 | dev_err(dev, "failed to enable iommu.\n"); |
|---|
| 1411 | 1416 | g2d_fini_cmdlist(g2d); |
|---|
| .. | .. |
|---|
| 1430 | 1435 | priv->g2d_dev = NULL; |
|---|
| 1431 | 1436 | |
|---|
| 1432 | 1437 | cancel_work_sync(&g2d->runqueue_work); |
|---|
| 1433 | | - drm_iommu_detach_device(g2d->drm_dev, dev); |
|---|
| 1438 | + exynos_drm_unregister_dma(g2d->drm_dev, dev, &g2d->dma_priv); |
|---|
| 1434 | 1439 | } |
|---|
| 1435 | 1440 | |
|---|
| 1436 | 1441 | static const struct component_ops g2d_component_ops = { |
|---|
| .. | .. |
|---|
| 1493 | 1498 | |
|---|
| 1494 | 1499 | g2d->irq = platform_get_irq(pdev, 0); |
|---|
| 1495 | 1500 | if (g2d->irq < 0) { |
|---|
| 1496 | | - dev_err(dev, "failed to get irq\n"); |
|---|
| 1497 | 1501 | ret = g2d->irq; |
|---|
| 1498 | 1502 | goto err_put_clk; |
|---|
| 1499 | 1503 | } |
|---|