| .. | .. |
|---|
| 20 | 20 | #include <linux/uaccess.h> |
|---|
| 21 | 21 | #include <linux/regmap.h> |
|---|
| 22 | 22 | #include <linux/proc_fs.h> |
|---|
| 23 | | -#include <linux/mfd/syscon.h> |
|---|
| 24 | | -#include <linux/rockchip/cpu.h> |
|---|
| 25 | 23 | #include <soc/rockchip/pm_domains.h> |
|---|
| 26 | 24 | |
|---|
| 27 | 25 | #include "mpp_debug.h" |
|---|
| 28 | 26 | #include "mpp_common.h" |
|---|
| 29 | 27 | #include "mpp_iommu.h" |
|---|
| 28 | +#include <soc/rockchip/rockchip_iommu.h> |
|---|
| 30 | 29 | |
|---|
| 31 | 30 | #define VDPU1_DRIVER_NAME "mpp_vdpu1" |
|---|
| 32 | 31 | |
|---|
| .. | .. |
|---|
| 268 | 267 | offset = task->reg[idx] >> 10 << 4; |
|---|
| 269 | 268 | } |
|---|
| 270 | 269 | mem_region = mpp_task_attach_fd(&task->mpp_task, fd); |
|---|
| 271 | | - if (IS_ERR(mem_region)) |
|---|
| 270 | + if (IS_ERR(mem_region)) { |
|---|
| 271 | + mpp_err("reg[%03d]: %08x fd %d attach failed\n", |
|---|
| 272 | + idx, task->reg[idx], fd); |
|---|
| 272 | 273 | goto fail; |
|---|
| 274 | + } |
|---|
| 273 | 275 | |
|---|
| 274 | 276 | iova = mem_region->iova; |
|---|
| 275 | 277 | mpp_debug(DEBUG_IOMMU, "DMV[%3d]: %3d => %pad + offset %10d\n", |
|---|
| .. | .. |
|---|
| 569 | 571 | return 0; |
|---|
| 570 | 572 | } |
|---|
| 571 | 573 | |
|---|
| 574 | +static int vdpu_3036_init(struct mpp_dev *mpp) |
|---|
| 575 | +{ |
|---|
| 576 | + vdpu_init(mpp); |
|---|
| 577 | + set_bit(mpp->var->device_type, &mpp->queue->dev_active_flags); |
|---|
| 578 | + return 0; |
|---|
| 579 | +} |
|---|
| 580 | + |
|---|
| 572 | 581 | static int vdpu_clk_on(struct mpp_dev *mpp) |
|---|
| 573 | 582 | { |
|---|
| 574 | 583 | struct vdpu_dev *dec = to_vdpu_dev(mpp); |
|---|
| .. | .. |
|---|
| 685 | 694 | static int vdpu_soft_reset(struct mpp_dev *mpp) |
|---|
| 686 | 695 | { |
|---|
| 687 | 696 | u32 val; |
|---|
| 697 | + u32 ret; |
|---|
| 688 | 698 | |
|---|
| 689 | 699 | mpp_write(mpp, VDPU1_REG_SOFT_RESET, 1); |
|---|
| 690 | | - udelay(2); |
|---|
| 691 | | - val = mpp_read(mpp, VDPU1_REG_SOFT_RESET); |
|---|
| 700 | + ret = readl_relaxed_poll_timeout(mpp->reg_base + VDPU1_REG_SOFT_RESET, |
|---|
| 701 | + val, !val, 0, 5); |
|---|
| 692 | 702 | |
|---|
| 693 | | - return val; |
|---|
| 703 | + return ret; |
|---|
| 694 | 704 | } |
|---|
| 695 | 705 | |
|---|
| 696 | 706 | static int vdpu_reset(struct mpp_dev *mpp) |
|---|
| .. | .. |
|---|
| 701 | 711 | /* soft reset first */ |
|---|
| 702 | 712 | ret = vdpu_soft_reset(mpp); |
|---|
| 703 | 713 | if (ret && dec->rst_a && dec->rst_h) { |
|---|
| 714 | + mpp_err("soft reset failed, use cru reset!\n"); |
|---|
| 704 | 715 | mpp_debug(DEBUG_RESET, "reset in\n"); |
|---|
| 705 | 716 | |
|---|
| 706 | 717 | /* Don't skip this or iommu won't work after reset */ |
|---|
| .. | .. |
|---|
| 719 | 730 | return 0; |
|---|
| 720 | 731 | } |
|---|
| 721 | 732 | |
|---|
| 733 | +static int vdpu_3036_set_grf(struct mpp_dev *mpp) |
|---|
| 734 | +{ |
|---|
| 735 | + int grf_changed; |
|---|
| 736 | + struct mpp_dev *loop = NULL, *n; |
|---|
| 737 | + struct mpp_taskqueue *queue = mpp->queue; |
|---|
| 738 | + bool pd_is_on; |
|---|
| 739 | + |
|---|
| 740 | + grf_changed = mpp_grf_is_changed(mpp->grf_info); |
|---|
| 741 | + if (grf_changed) { |
|---|
| 742 | + |
|---|
| 743 | + /* |
|---|
| 744 | + * in this case, devices share the queue also share the same pd&clk, |
|---|
| 745 | + * so use mpp->dev's pd to control all the process is okay |
|---|
| 746 | + */ |
|---|
| 747 | + pd_is_on = rockchip_pmu_pd_is_on(mpp->dev); |
|---|
| 748 | + if (!pd_is_on) |
|---|
| 749 | + rockchip_pmu_pd_on(mpp->dev); |
|---|
| 750 | + mpp->hw_ops->clk_on(mpp); |
|---|
| 751 | + |
|---|
| 752 | + list_for_each_entry_safe(loop, n, &queue->dev_list, queue_link) { |
|---|
| 753 | + if (test_bit(loop->var->device_type, &queue->dev_active_flags)) { |
|---|
| 754 | + mpp_set_grf(loop->grf_info); |
|---|
| 755 | + if (loop->hw_ops->clk_on) |
|---|
| 756 | + loop->hw_ops->clk_on(loop); |
|---|
| 757 | + if (loop->hw_ops->reset) |
|---|
| 758 | + loop->hw_ops->reset(loop); |
|---|
| 759 | + rockchip_iommu_disable(loop->dev); |
|---|
| 760 | + if (loop->hw_ops->clk_off) |
|---|
| 761 | + loop->hw_ops->clk_off(loop); |
|---|
| 762 | + clear_bit(loop->var->device_type, &queue->dev_active_flags); |
|---|
| 763 | + } |
|---|
| 764 | + } |
|---|
| 765 | + |
|---|
| 766 | + mpp_set_grf(mpp->grf_info); |
|---|
| 767 | + rockchip_iommu_enable(mpp->dev); |
|---|
| 768 | + set_bit(mpp->var->device_type, &queue->dev_active_flags); |
|---|
| 769 | + |
|---|
| 770 | + mpp->hw_ops->clk_off(mpp); |
|---|
| 771 | + if (!pd_is_on) |
|---|
| 772 | + rockchip_pmu_pd_off(mpp->dev); |
|---|
| 773 | + } |
|---|
| 774 | + |
|---|
| 775 | + return 0; |
|---|
| 776 | +} |
|---|
| 777 | + |
|---|
| 722 | 778 | static struct mpp_hw_ops vdpu_v1_hw_ops = { |
|---|
| 723 | 779 | .init = vdpu_init, |
|---|
| 724 | 780 | .clk_on = vdpu_clk_on, |
|---|
| .. | .. |
|---|
| 726 | 782 | .set_freq = vdpu_set_freq, |
|---|
| 727 | 783 | .reduce_freq = vdpu_reduce_freq, |
|---|
| 728 | 784 | .reset = vdpu_reset, |
|---|
| 785 | + .set_grf = vdpu_3036_set_grf, |
|---|
| 786 | +}; |
|---|
| 787 | + |
|---|
| 788 | +static struct mpp_hw_ops vdpu_3036_hw_ops = { |
|---|
| 789 | + .init = vdpu_3036_init, |
|---|
| 790 | + .clk_on = vdpu_clk_on, |
|---|
| 791 | + .clk_off = vdpu_clk_off, |
|---|
| 792 | + .set_freq = vdpu_set_freq, |
|---|
| 793 | + .reduce_freq = vdpu_reduce_freq, |
|---|
| 794 | + .reset = vdpu_reset, |
|---|
| 795 | + .set_grf = vdpu_3036_set_grf, |
|---|
| 729 | 796 | }; |
|---|
| 730 | 797 | |
|---|
| 731 | 798 | static struct mpp_hw_ops vdpu_3288_hw_ops = { |
|---|
| .. | .. |
|---|
| 766 | 833 | .dev_ops = &vdpu_v1_dev_ops, |
|---|
| 767 | 834 | }; |
|---|
| 768 | 835 | |
|---|
| 836 | +static const struct mpp_dev_var vdpu_3036_data = { |
|---|
| 837 | + .device_type = MPP_DEVICE_VDPU1, |
|---|
| 838 | + .hw_info = &vdpu_v1_hw_info, |
|---|
| 839 | + .trans_info = vdpu_v1_trans, |
|---|
| 840 | + .hw_ops = &vdpu_3036_hw_ops, |
|---|
| 841 | + .dev_ops = &vdpu_v1_dev_ops, |
|---|
| 842 | +}; |
|---|
| 843 | + |
|---|
| 769 | 844 | static const struct mpp_dev_var vdpu_3288_data = { |
|---|
| 770 | 845 | .device_type = MPP_DEVICE_VDPU1, |
|---|
| 771 | 846 | .hw_info = &vdpu_v1_hw_info, |
|---|
| .. | .. |
|---|
| 801 | 876 | .data = &vdpu_3288_data, |
|---|
| 802 | 877 | }, |
|---|
| 803 | 878 | #endif |
|---|
| 879 | +#ifdef CONFIG_CPU_RK3036 |
|---|
| 880 | + { |
|---|
| 881 | + .compatible = "rockchip,vpu-decoder-rk3036", |
|---|
| 882 | + .data = &vdpu_3036_data, |
|---|
| 883 | + }, |
|---|
| 884 | +#endif |
|---|
| 804 | 885 | #ifdef CONFIG_CPU_RK3368 |
|---|
| 805 | 886 | { |
|---|
| 806 | 887 | .compatible = "rockchip,vpu-decoder-rk3368", |
|---|
| .. | .. |
|---|
| 826 | 907 | dec = devm_kzalloc(dev, sizeof(struct vdpu_dev), GFP_KERNEL); |
|---|
| 827 | 908 | if (!dec) |
|---|
| 828 | 909 | return -ENOMEM; |
|---|
| 829 | | - platform_set_drvdata(pdev, dec); |
|---|
| 830 | | - |
|---|
| 831 | 910 | mpp = &dec->mpp; |
|---|
| 911 | + platform_set_drvdata(pdev, mpp); |
|---|
| 912 | + |
|---|
| 832 | 913 | if (pdev->dev.of_node) { |
|---|
| 833 | 914 | match = of_match_node(mpp_vdpu1_dt_match, pdev->dev.of_node); |
|---|
| 834 | 915 | if (match) |
|---|
| 835 | 916 | mpp->var = (struct mpp_dev_var *)match->data; |
|---|
| 917 | + |
|---|
| 918 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "vdpu"); |
|---|
| 836 | 919 | } |
|---|
| 837 | 920 | |
|---|
| 838 | 921 | ret = mpp_dev_probe(mpp, pdev); |
|---|
| .. | .. |
|---|
| 868 | 951 | static int vdpu_remove(struct platform_device *pdev) |
|---|
| 869 | 952 | { |
|---|
| 870 | 953 | struct device *dev = &pdev->dev; |
|---|
| 871 | | - struct vdpu_dev *dec = platform_get_drvdata(pdev); |
|---|
| 954 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
|---|
| 872 | 955 | |
|---|
| 873 | 956 | dev_info(dev, "remove device\n"); |
|---|
| 874 | | - mpp_dev_remove(&dec->mpp); |
|---|
| 875 | | - vdpu_procfs_remove(&dec->mpp); |
|---|
| 957 | + mpp_dev_remove(mpp); |
|---|
| 958 | + vdpu_procfs_remove(mpp); |
|---|
| 876 | 959 | |
|---|
| 877 | 960 | return 0; |
|---|
| 878 | 961 | } |
|---|
| 879 | | - |
|---|
| 880 | | -static void vdpu_shutdown(struct platform_device *pdev) |
|---|
| 881 | | -{ |
|---|
| 882 | | - int ret; |
|---|
| 883 | | - int val; |
|---|
| 884 | | - struct device *dev = &pdev->dev; |
|---|
| 885 | | - struct vdpu_dev *dec = platform_get_drvdata(pdev); |
|---|
| 886 | | - struct mpp_dev *mpp = &dec->mpp; |
|---|
| 887 | | - |
|---|
| 888 | | - dev_info(dev, "shutdown device\n"); |
|---|
| 889 | | - |
|---|
| 890 | | - atomic_inc(&mpp->srv->shutdown_request); |
|---|
| 891 | | - ret = readx_poll_timeout(atomic_read, |
|---|
| 892 | | - &mpp->task_count, |
|---|
| 893 | | - val, val == 0, 20000, 200000); |
|---|
| 894 | | - if (ret == -ETIMEDOUT) |
|---|
| 895 | | - dev_err(dev, "wait total running time out\n"); |
|---|
| 896 | | -} |
|---|
| 897 | | - |
|---|
| 898 | | -static int vdpu_runtime_suspend(struct device *dev) |
|---|
| 899 | | -{ |
|---|
| 900 | | - struct mpp_dev *mpp = dev_get_drvdata(dev); |
|---|
| 901 | | - struct mpp_grf_info *info = mpp->grf_info; |
|---|
| 902 | | - struct mpp_taskqueue *queue = mpp->queue; |
|---|
| 903 | | - |
|---|
| 904 | | - if (cpu_is_rk3528() && info && info->mem_offset) { |
|---|
| 905 | | - mutex_lock(&queue->ref_lock); |
|---|
| 906 | | - if (!atomic_dec_if_positive(&queue->runtime_cnt)) { |
|---|
| 907 | | - regmap_write(info->grf, info->mem_offset, |
|---|
| 908 | | - info->val_mem_off); |
|---|
| 909 | | - } |
|---|
| 910 | | - mutex_unlock(&queue->ref_lock); |
|---|
| 911 | | - } |
|---|
| 912 | | - |
|---|
| 913 | | - return 0; |
|---|
| 914 | | -} |
|---|
| 915 | | - |
|---|
| 916 | | -static int vdpu_runtime_resume(struct device *dev) |
|---|
| 917 | | -{ |
|---|
| 918 | | - struct mpp_dev *mpp = dev_get_drvdata(dev); |
|---|
| 919 | | - struct mpp_grf_info *info = mpp->grf_info; |
|---|
| 920 | | - struct mpp_taskqueue *queue = mpp->queue; |
|---|
| 921 | | - |
|---|
| 922 | | - if (cpu_is_rk3528() && info && info->mem_offset) { |
|---|
| 923 | | - mutex_lock(&queue->ref_lock); |
|---|
| 924 | | - regmap_write(info->grf, info->mem_offset, |
|---|
| 925 | | - info->val_mem_on); |
|---|
| 926 | | - atomic_inc(&queue->runtime_cnt); |
|---|
| 927 | | - mutex_unlock(&queue->ref_lock); |
|---|
| 928 | | - } |
|---|
| 929 | | - |
|---|
| 930 | | - return 0; |
|---|
| 931 | | -} |
|---|
| 932 | | - |
|---|
| 933 | | -static const struct dev_pm_ops vdpu_pm_ops = { |
|---|
| 934 | | - .runtime_suspend = vdpu_runtime_suspend, |
|---|
| 935 | | - .runtime_resume = vdpu_runtime_resume, |
|---|
| 936 | | -}; |
|---|
| 937 | 962 | |
|---|
| 938 | 963 | struct platform_driver rockchip_vdpu1_driver = { |
|---|
| 939 | 964 | .probe = vdpu_probe, |
|---|
| 940 | 965 | .remove = vdpu_remove, |
|---|
| 941 | | - .shutdown = vdpu_shutdown, |
|---|
| 966 | + .shutdown = mpp_dev_shutdown, |
|---|
| 942 | 967 | .driver = { |
|---|
| 943 | 968 | .name = VDPU1_DRIVER_NAME, |
|---|
| 944 | | - .pm = &vdpu_pm_ops, |
|---|
| 945 | 969 | .of_match_table = of_match_ptr(mpp_vdpu1_dt_match), |
|---|
| 946 | 970 | }, |
|---|
| 947 | 971 | }; |
|---|