| .. | .. |
|---|
| 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> |
|---|
| 23 | 25 | #include <soc/rockchip/pm_domains.h> |
|---|
| 24 | 26 | |
|---|
| 25 | 27 | #include "mpp_debug.h" |
|---|
| .. | .. |
|---|
| 57 | 59 | /* NOTE: Don't enable it or decoding AVC would meet problem at rk3288 */ |
|---|
| 58 | 60 | #define VDPU1_REG_DEC_EN 0x008 |
|---|
| 59 | 61 | #define VDPU1_CLOCK_GATE_EN BIT(10) |
|---|
| 62 | + |
|---|
| 63 | +#define VDPU1_REG_SOFT_RESET 0x194 |
|---|
| 64 | +#define VDPU1_REG_SOFT_RESET_INDEX (101) |
|---|
| 60 | 65 | |
|---|
| 61 | 66 | #define VDPU1_REG_SYS_CTRL 0x00c |
|---|
| 62 | 67 | #define VDPU1_REG_SYS_CTRL_INDEX (3) |
|---|
| .. | .. |
|---|
| 387 | 392 | u32 i; |
|---|
| 388 | 393 | u32 reg_en; |
|---|
| 389 | 394 | struct vdpu_task *task = to_vdpu_task(mpp_task); |
|---|
| 395 | + u32 timing_en = mpp->srv->timing_en; |
|---|
| 390 | 396 | |
|---|
| 391 | 397 | mpp_debug_enter(); |
|---|
| 392 | 398 | |
|---|
| .. | .. |
|---|
| 401 | 407 | |
|---|
| 402 | 408 | mpp_write_req(mpp, task->reg, s, e, reg_en); |
|---|
| 403 | 409 | } |
|---|
| 410 | + |
|---|
| 411 | + /* flush tlb before starting hardware */ |
|---|
| 412 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
|---|
| 413 | + |
|---|
| 404 | 414 | /* init current task */ |
|---|
| 405 | 415 | mpp->cur_task = mpp_task; |
|---|
| 416 | + |
|---|
| 417 | + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); |
|---|
| 418 | + |
|---|
| 406 | 419 | /* Flush the register before the start the device */ |
|---|
| 407 | 420 | wmb(); |
|---|
| 408 | 421 | mpp_write(mpp, VDPU1_REG_DEC_INT_EN, |
|---|
| 409 | 422 | task->reg[reg_en] | VDPU1_DEC_START); |
|---|
| 423 | + |
|---|
| 424 | + mpp_task_run_end(mpp_task, timing_en); |
|---|
| 410 | 425 | |
|---|
| 411 | 426 | mpp_debug_leave(); |
|---|
| 412 | 427 | |
|---|
| .. | .. |
|---|
| 503 | 518 | dec->procfs = NULL; |
|---|
| 504 | 519 | return -EIO; |
|---|
| 505 | 520 | } |
|---|
| 521 | + |
|---|
| 522 | + /* for common mpp_dev options */ |
|---|
| 523 | + mpp_procfs_create_common(dec->procfs, mpp); |
|---|
| 524 | + |
|---|
| 506 | 525 | mpp_procfs_create_u32("aclk", 0644, |
|---|
| 507 | 526 | dec->procfs, &dec->aclk_info.debug_rate_hz); |
|---|
| 508 | 527 | mpp_procfs_create_u32("session_buffers", 0644, |
|---|
| .. | .. |
|---|
| 663 | 682 | return IRQ_HANDLED; |
|---|
| 664 | 683 | } |
|---|
| 665 | 684 | |
|---|
| 685 | +static int vdpu_soft_reset(struct mpp_dev *mpp) |
|---|
| 686 | +{ |
|---|
| 687 | + u32 val; |
|---|
| 688 | + |
|---|
| 689 | + mpp_write(mpp, VDPU1_REG_SOFT_RESET, 1); |
|---|
| 690 | + udelay(2); |
|---|
| 691 | + val = mpp_read(mpp, VDPU1_REG_SOFT_RESET); |
|---|
| 692 | + |
|---|
| 693 | + return val; |
|---|
| 694 | +} |
|---|
| 695 | + |
|---|
| 666 | 696 | static int vdpu_reset(struct mpp_dev *mpp) |
|---|
| 667 | 697 | { |
|---|
| 668 | 698 | struct vdpu_dev *dec = to_vdpu_dev(mpp); |
|---|
| 699 | + u32 ret = 0; |
|---|
| 669 | 700 | |
|---|
| 670 | | - if (dec->rst_a && dec->rst_h) { |
|---|
| 701 | + /* soft reset first */ |
|---|
| 702 | + ret = vdpu_soft_reset(mpp); |
|---|
| 703 | + if (ret && dec->rst_a && dec->rst_h) { |
|---|
| 671 | 704 | mpp_debug(DEBUG_RESET, "reset in\n"); |
|---|
| 672 | 705 | |
|---|
| 673 | 706 | /* Don't skip this or iommu won't work after reset */ |
|---|
| 674 | | - rockchip_pmu_idle_request(mpp->dev, true); |
|---|
| 707 | + mpp_pmu_idle_request(mpp, true); |
|---|
| 675 | 708 | mpp_safe_reset(dec->rst_a); |
|---|
| 676 | 709 | mpp_safe_reset(dec->rst_h); |
|---|
| 677 | 710 | udelay(5); |
|---|
| 678 | 711 | mpp_safe_unreset(dec->rst_a); |
|---|
| 679 | 712 | mpp_safe_unreset(dec->rst_h); |
|---|
| 680 | | - rockchip_pmu_idle_request(mpp->dev, false); |
|---|
| 713 | + mpp_pmu_idle_request(mpp, false); |
|---|
| 681 | 714 | |
|---|
| 682 | 715 | mpp_debug(DEBUG_RESET, "reset out\n"); |
|---|
| 683 | 716 | } |
|---|
| .. | .. |
|---|
| 774 | 807 | .data = &vdpu_3368_data, |
|---|
| 775 | 808 | }, |
|---|
| 776 | 809 | #endif |
|---|
| 777 | | -#ifdef CONFIG_CPU_RK3328 |
|---|
| 778 | 810 | { |
|---|
| 779 | 811 | .compatible = "rockchip,avs-plus-decoder", |
|---|
| 780 | 812 | .data = &avsd_plus_data, |
|---|
| 781 | 813 | }, |
|---|
| 782 | | -#endif |
|---|
| 783 | 814 | {}, |
|---|
| 784 | 815 | }; |
|---|
| 785 | 816 | |
|---|
| .. | .. |
|---|
| 864 | 895 | dev_err(dev, "wait total running time out\n"); |
|---|
| 865 | 896 | } |
|---|
| 866 | 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 | + |
|---|
| 867 | 938 | struct platform_driver rockchip_vdpu1_driver = { |
|---|
| 868 | 939 | .probe = vdpu_probe, |
|---|
| 869 | 940 | .remove = vdpu_remove, |
|---|
| 870 | 941 | .shutdown = vdpu_shutdown, |
|---|
| 871 | 942 | .driver = { |
|---|
| 872 | 943 | .name = VDPU1_DRIVER_NAME, |
|---|
| 944 | + .pm = &vdpu_pm_ops, |
|---|
| 873 | 945 | .of_match_table = of_match_ptr(mpp_vdpu1_dt_match), |
|---|
| 874 | 946 | }, |
|---|
| 875 | 947 | }; |
|---|