.. | .. |
---|
36 | 36 | #define VEPU2_REG_HW_ID_INDEX -1 /* INVALID */ |
---|
37 | 37 | #define VEPU2_REG_START_INDEX 0 |
---|
38 | 38 | #define VEPU2_REG_END_INDEX 183 |
---|
| 39 | +#define VEPU2_REG_OUT_INDEX (77) |
---|
| 40 | +#define VEPU2_REG_STRM_INDEX (53) |
---|
39 | 41 | |
---|
40 | 42 | #define VEPU2_REG_ENC_EN 0x19c |
---|
41 | 43 | #define VEPU2_REG_ENC_EN_INDEX (103) |
---|
.. | .. |
---|
97 | 99 | u32 width; |
---|
98 | 100 | u32 height; |
---|
99 | 101 | u32 pixels; |
---|
| 102 | + struct mpp_dma_buffer *bs_buf; |
---|
| 103 | + u32 offset_bs; |
---|
100 | 104 | }; |
---|
101 | 105 | |
---|
102 | 106 | struct vepu_session_priv { |
---|
.. | .. |
---|
121 | 125 | #endif |
---|
122 | 126 | struct reset_control *rst_a; |
---|
123 | 127 | struct reset_control *rst_h; |
---|
| 128 | + /* for ccu(central control unit) */ |
---|
| 129 | + struct vepu_ccu *ccu; |
---|
| 130 | + bool disable_work; |
---|
| 131 | +}; |
---|
| 132 | + |
---|
| 133 | +struct vepu_ccu { |
---|
| 134 | + u32 core_num; |
---|
| 135 | + /* lock for core attach */ |
---|
| 136 | + spinlock_t lock; |
---|
| 137 | + struct mpp_dev *main_core; |
---|
| 138 | + struct mpp_dev *cores[MPP_MAX_CORE_NUM]; |
---|
| 139 | + unsigned long core_idle; |
---|
124 | 140 | }; |
---|
125 | 141 | |
---|
126 | 142 | static struct mpp_hw_info vepu_v2_hw_info = { |
---|
.. | .. |
---|
167 | 183 | struct mpp_task_msgs *msgs) |
---|
168 | 184 | { |
---|
169 | 185 | int ret; |
---|
| 186 | + int fd_bs; |
---|
170 | 187 | int fmt = VEPU2_GET_FORMAT(task->reg[VEPU2_REG_ENC_EN_INDEX]); |
---|
| 188 | + |
---|
| 189 | + if (session->msg_flags & MPP_FLAGS_REG_NO_OFFSET) |
---|
| 190 | + fd_bs = task->reg[VEPU2_REG_OUT_INDEX]; |
---|
| 191 | + else |
---|
| 192 | + fd_bs = task->reg[VEPU2_REG_OUT_INDEX] & 0x3ff; |
---|
171 | 193 | |
---|
172 | 194 | ret = mpp_translate_reg_address(session, &task->mpp_task, |
---|
173 | 195 | fmt, task->reg, &task->off_inf); |
---|
.. | .. |
---|
176 | 198 | |
---|
177 | 199 | mpp_translate_reg_offset_info(&task->mpp_task, |
---|
178 | 200 | &task->off_inf, task->reg); |
---|
| 201 | + |
---|
| 202 | + if (fmt == VEPU2_FMT_JPEGE) { |
---|
| 203 | + struct mpp_dma_buffer *bs_buf = mpp_dma_find_buffer_fd(session->dma, fd_bs); |
---|
| 204 | + |
---|
| 205 | + task->offset_bs = mpp_query_reg_offset_info(&task->off_inf, VEPU2_REG_OUT_INDEX); |
---|
| 206 | + if (bs_buf && task->offset_bs > 0) |
---|
| 207 | + mpp_dma_buf_sync(bs_buf, 0, task->offset_bs, DMA_TO_DEVICE, false); |
---|
| 208 | + task->bs_buf = bs_buf; |
---|
| 209 | + } |
---|
179 | 210 | |
---|
180 | 211 | return 0; |
---|
181 | 212 | } |
---|
.. | .. |
---|
281 | 312 | return NULL; |
---|
282 | 313 | } |
---|
283 | 314 | |
---|
| 315 | +static void *vepu_prepare(struct mpp_dev *mpp, struct mpp_task *mpp_task) |
---|
| 316 | +{ |
---|
| 317 | + struct mpp_taskqueue *queue = mpp->queue; |
---|
| 318 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 319 | + struct vepu_ccu *ccu = enc->ccu; |
---|
| 320 | + unsigned long core_idle; |
---|
| 321 | + unsigned long flags; |
---|
| 322 | + u32 core_id_max; |
---|
| 323 | + s32 core_id; |
---|
| 324 | + u32 i; |
---|
| 325 | + |
---|
| 326 | + spin_lock_irqsave(&ccu->lock, flags); |
---|
| 327 | + |
---|
| 328 | + core_idle = queue->core_idle; |
---|
| 329 | + core_id_max = queue->core_id_max; |
---|
| 330 | + |
---|
| 331 | + for (i = 0; i <= core_id_max; i++) { |
---|
| 332 | + struct mpp_dev *mpp = queue->cores[i]; |
---|
| 333 | + |
---|
| 334 | + if (mpp && mpp->disable) |
---|
| 335 | + clear_bit(i, &core_idle); |
---|
| 336 | + } |
---|
| 337 | + |
---|
| 338 | + core_id = find_first_bit(&ccu->core_idle, ccu->core_num); |
---|
| 339 | + core_id = array_index_nospec(core_id, MPP_MAX_CORE_NUM); |
---|
| 340 | + if (core_id >= core_id_max + 1 || !queue->cores[core_id]) { |
---|
| 341 | + mpp_task = NULL; |
---|
| 342 | + mpp_dbg_core("core %d all busy %lx\n", core_id, ccu->core_idle); |
---|
| 343 | + } else { |
---|
| 344 | + unsigned long core_idle = ccu->core_idle; |
---|
| 345 | + |
---|
| 346 | + clear_bit(core_id, &ccu->core_idle); |
---|
| 347 | + mpp_task->mpp = ccu->cores[core_id]; |
---|
| 348 | + mpp_task->core_id = core_id; |
---|
| 349 | + |
---|
| 350 | + mpp_dbg_core("core cnt %d core %d set idle %lx -> %lx\n", |
---|
| 351 | + ccu->core_num, core_id, core_idle, ccu->core_idle); |
---|
| 352 | + } |
---|
| 353 | + |
---|
| 354 | + spin_unlock_irqrestore(&ccu->lock, flags); |
---|
| 355 | + |
---|
| 356 | + return mpp_task; |
---|
| 357 | +} |
---|
| 358 | + |
---|
284 | 359 | static int vepu_run(struct mpp_dev *mpp, |
---|
285 | 360 | struct mpp_task *mpp_task) |
---|
286 | 361 | { |
---|
.. | .. |
---|
327 | 402 | return 0; |
---|
328 | 403 | } |
---|
329 | 404 | |
---|
| 405 | +static int vepu_px30_run(struct mpp_dev *mpp, |
---|
| 406 | + struct mpp_task *mpp_task) |
---|
| 407 | +{ |
---|
| 408 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
---|
| 409 | + return vepu_run(mpp, mpp_task); |
---|
| 410 | +} |
---|
| 411 | + |
---|
330 | 412 | static int vepu_irq(struct mpp_dev *mpp) |
---|
331 | 413 | { |
---|
332 | 414 | mpp->irq_status = mpp_read(mpp, VEPU2_REG_INT); |
---|
.. | .. |
---|
343 | 425 | u32 err_mask; |
---|
344 | 426 | struct vepu_task *task = NULL; |
---|
345 | 427 | struct mpp_task *mpp_task = mpp->cur_task; |
---|
| 428 | + unsigned long core_idle; |
---|
| 429 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 430 | + struct vepu_ccu *ccu = enc->ccu; |
---|
346 | 431 | |
---|
347 | 432 | /* FIXME use a spin lock here */ |
---|
348 | 433 | if (!mpp_task) { |
---|
.. | .. |
---|
364 | 449 | atomic_inc(&mpp->reset_request); |
---|
365 | 450 | |
---|
366 | 451 | mpp_task_finish(mpp_task->session, mpp_task); |
---|
| 452 | + /* the whole vepu has no ccu that manage multi core */ |
---|
| 453 | + if (ccu) { |
---|
| 454 | + core_idle = ccu->core_idle; |
---|
| 455 | + set_bit(mpp->core_id, &ccu->core_idle); |
---|
| 456 | + |
---|
| 457 | + mpp_dbg_core("core %d isr idle %lx -> %lx\n", mpp->core_id, core_idle, |
---|
| 458 | + ccu->core_idle); |
---|
| 459 | + } |
---|
367 | 460 | |
---|
368 | 461 | mpp_debug_leave(); |
---|
369 | 462 | |
---|
.. | .. |
---|
390 | 483 | /* revert hack for irq status */ |
---|
391 | 484 | task->reg[VEPU2_REG_INT_INDEX] = task->irq_status; |
---|
392 | 485 | |
---|
| 486 | + if (task->bs_buf) |
---|
| 487 | + mpp_dma_buf_sync(task->bs_buf, 0, |
---|
| 488 | + task->reg[VEPU2_REG_STRM_INDEX] / 8 + |
---|
| 489 | + task->offset_bs, |
---|
| 490 | + DMA_FROM_DEVICE, true); |
---|
393 | 491 | mpp_debug_leave(); |
---|
394 | 492 | |
---|
395 | 493 | return 0; |
---|
.. | .. |
---|
532 | 630 | } |
---|
533 | 631 | seq_puts(seq, "\n"); |
---|
534 | 632 | /* item data*/ |
---|
535 | | - seq_printf(seq, "|%8p|", session); |
---|
| 633 | + seq_printf(seq, "|%8d|", session->index); |
---|
536 | 634 | seq_printf(seq, "%8s|", mpp_device_name[session->device_type]); |
---|
537 | 635 | for (i = ENC_INFO_BASE; i < ENC_INFO_BUTT; i++) { |
---|
538 | 636 | u32 flag = priv->codec_info[i].flag; |
---|
.. | .. |
---|
565 | 663 | mutex_lock(&mpp->srv->session_lock); |
---|
566 | 664 | list_for_each_entry_safe(session, n, |
---|
567 | 665 | &mpp->srv->session_list, |
---|
568 | | - session_link) { |
---|
569 | | - if (session->device_type != MPP_DEVICE_VEPU2) |
---|
| 666 | + service_link) { |
---|
| 667 | + if (session->device_type != MPP_DEVICE_VEPU2 && |
---|
| 668 | + session->device_type != MPP_DEVICE_VEPU2_JPEG) |
---|
570 | 669 | continue; |
---|
571 | 670 | if (!session->priv) |
---|
572 | 671 | continue; |
---|
.. | .. |
---|
581 | 680 | static int vepu_procfs_init(struct mpp_dev *mpp) |
---|
582 | 681 | { |
---|
583 | 682 | struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 683 | + char name[32]; |
---|
584 | 684 | |
---|
585 | | - enc->procfs = proc_mkdir(mpp->dev->of_node->name, mpp->srv->procfs); |
---|
| 685 | + if (!mpp->dev || !mpp->dev->of_node || !mpp->dev->of_node->name || |
---|
| 686 | + !mpp->srv || !mpp->srv->procfs) |
---|
| 687 | + return -EINVAL; |
---|
| 688 | + if (enc->ccu) |
---|
| 689 | + snprintf(name, sizeof(name) - 1, "%s%d", |
---|
| 690 | + mpp->dev->of_node->name, mpp->core_id); |
---|
| 691 | + else |
---|
| 692 | + snprintf(name, sizeof(name) - 1, "%s", |
---|
| 693 | + mpp->dev->of_node->name); |
---|
| 694 | + |
---|
| 695 | + enc->procfs = proc_mkdir(name, mpp->srv->procfs); |
---|
586 | 696 | if (IS_ERR_OR_NULL(enc->procfs)) { |
---|
587 | 697 | mpp_err("failed on open procfs\n"); |
---|
588 | 698 | enc->procfs = NULL; |
---|
.. | .. |
---|
602 | 712 | |
---|
603 | 713 | return 0; |
---|
604 | 714 | } |
---|
| 715 | + |
---|
| 716 | +static int vepu_procfs_ccu_init(struct mpp_dev *mpp) |
---|
| 717 | +{ |
---|
| 718 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 719 | + |
---|
| 720 | + if (!enc->procfs) |
---|
| 721 | + goto done; |
---|
| 722 | + |
---|
| 723 | +done: |
---|
| 724 | + return 0; |
---|
| 725 | +} |
---|
605 | 726 | #else |
---|
606 | 727 | static inline int vepu_procfs_remove(struct mpp_dev *mpp) |
---|
607 | 728 | { |
---|
.. | .. |
---|
609 | 730 | } |
---|
610 | 731 | |
---|
611 | 732 | static inline int vepu_procfs_init(struct mpp_dev *mpp) |
---|
| 733 | +{ |
---|
| 734 | + return 0; |
---|
| 735 | +} |
---|
| 736 | + |
---|
| 737 | +static inline int vepu_procfs_ccu_init(struct mpp_dev *mpp) |
---|
612 | 738 | { |
---|
613 | 739 | return 0; |
---|
614 | 740 | } |
---|
.. | .. |
---|
735 | 861 | static int vepu_reset(struct mpp_dev *mpp) |
---|
736 | 862 | { |
---|
737 | 863 | struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 864 | + struct vepu_ccu *ccu = enc->ccu; |
---|
738 | 865 | |
---|
739 | 866 | mpp_write(mpp, VEPU2_REG_ENC_EN, 0); |
---|
740 | 867 | udelay(5); |
---|
.. | .. |
---|
749 | 876 | mpp_pmu_idle_request(mpp, false); |
---|
750 | 877 | } |
---|
751 | 878 | mpp_write(mpp, VEPU2_REG_INT, VEPU2_INT_CLEAR); |
---|
| 879 | + |
---|
| 880 | + if (ccu) { |
---|
| 881 | + set_bit(mpp->core_id, &ccu->core_idle); |
---|
| 882 | + mpp_dbg_core("core %d reset idle %lx\n", mpp->core_id, ccu->core_idle); |
---|
| 883 | + } |
---|
752 | 884 | |
---|
753 | 885 | return 0; |
---|
754 | 886 | } |
---|
.. | .. |
---|
787 | 919 | .dump_session = vepu_dump_session, |
---|
788 | 920 | }; |
---|
789 | 921 | |
---|
| 922 | +static struct mpp_dev_ops vepu_px30_dev_ops = { |
---|
| 923 | + .alloc_task = vepu_alloc_task, |
---|
| 924 | + .run = vepu_px30_run, |
---|
| 925 | + .irq = vepu_irq, |
---|
| 926 | + .isr = vepu_isr, |
---|
| 927 | + .finish = vepu_finish, |
---|
| 928 | + .result = vepu_result, |
---|
| 929 | + .free_task = vepu_free_task, |
---|
| 930 | + .ioctl = vepu_control, |
---|
| 931 | + .init_session = vepu_init_session, |
---|
| 932 | + .free_session = vepu_free_session, |
---|
| 933 | + .dump_session = vepu_dump_session, |
---|
| 934 | +}; |
---|
| 935 | + |
---|
| 936 | +static struct mpp_dev_ops vepu_ccu_dev_ops = { |
---|
| 937 | + .alloc_task = vepu_alloc_task, |
---|
| 938 | + .prepare = vepu_prepare, |
---|
| 939 | + .run = vepu_run, |
---|
| 940 | + .irq = vepu_irq, |
---|
| 941 | + .isr = vepu_isr, |
---|
| 942 | + .finish = vepu_finish, |
---|
| 943 | + .result = vepu_result, |
---|
| 944 | + .free_task = vepu_free_task, |
---|
| 945 | + .ioctl = vepu_control, |
---|
| 946 | + .init_session = vepu_init_session, |
---|
| 947 | + .free_session = vepu_free_session, |
---|
| 948 | + .dump_session = vepu_dump_session, |
---|
| 949 | +}; |
---|
| 950 | + |
---|
| 951 | + |
---|
790 | 952 | static const struct mpp_dev_var vepu_v2_data = { |
---|
791 | 953 | .device_type = MPP_DEVICE_VEPU2, |
---|
792 | 954 | .hw_info = &vepu_v2_hw_info, |
---|
.. | .. |
---|
800 | 962 | .hw_info = &vepu_v2_hw_info, |
---|
801 | 963 | .trans_info = trans_rk_vepu2, |
---|
802 | 964 | .hw_ops = &vepu_px30_hw_ops, |
---|
803 | | - .dev_ops = &vepu_v2_dev_ops, |
---|
| 965 | + .dev_ops = &vepu_px30_dev_ops, |
---|
| 966 | +}; |
---|
| 967 | + |
---|
| 968 | +static const struct mpp_dev_var vepu_ccu_data = { |
---|
| 969 | + .device_type = MPP_DEVICE_VEPU2_JPEG, |
---|
| 970 | + .hw_info = &vepu_v2_hw_info, |
---|
| 971 | + .trans_info = trans_rk_vepu2, |
---|
| 972 | + .hw_ops = &vepu_v2_hw_ops, |
---|
| 973 | + .dev_ops = &vepu_ccu_dev_ops, |
---|
804 | 974 | }; |
---|
805 | 975 | |
---|
806 | 976 | static const struct of_device_id mpp_vepu2_dt_match[] = { |
---|
.. | .. |
---|
814 | 984 | .data = &vepu_px30_data, |
---|
815 | 985 | }, |
---|
816 | 986 | #endif |
---|
| 987 | +#ifdef CONFIG_CPU_RK3588 |
---|
| 988 | + { |
---|
| 989 | + .compatible = "rockchip,vpu-jpege-core", |
---|
| 990 | + .data = &vepu_ccu_data, |
---|
| 991 | + }, |
---|
| 992 | + { |
---|
| 993 | + .compatible = "rockchip,vpu-jpege-ccu", |
---|
| 994 | + }, |
---|
| 995 | +#endif |
---|
817 | 996 | {}, |
---|
818 | 997 | }; |
---|
819 | 998 | |
---|
820 | | -static int vepu_probe(struct platform_device *pdev) |
---|
| 999 | +static int vepu_ccu_probe(struct platform_device *pdev) |
---|
| 1000 | +{ |
---|
| 1001 | + struct vepu_ccu *ccu; |
---|
| 1002 | + struct device *dev = &pdev->dev; |
---|
| 1003 | + |
---|
| 1004 | + ccu = devm_kzalloc(dev, sizeof(*ccu), GFP_KERNEL); |
---|
| 1005 | + if (!ccu) |
---|
| 1006 | + return -ENOMEM; |
---|
| 1007 | + |
---|
| 1008 | + platform_set_drvdata(pdev, ccu); |
---|
| 1009 | + spin_lock_init(&ccu->lock); |
---|
| 1010 | + return 0; |
---|
| 1011 | +} |
---|
| 1012 | + |
---|
| 1013 | +static int vepu_attach_ccu(struct device *dev, struct vepu_dev *enc) |
---|
| 1014 | +{ |
---|
| 1015 | + struct device_node *np; |
---|
| 1016 | + struct platform_device *pdev; |
---|
| 1017 | + struct vepu_ccu *ccu; |
---|
| 1018 | + unsigned long flags; |
---|
| 1019 | + |
---|
| 1020 | + np = of_parse_phandle(dev->of_node, "rockchip,ccu", 0); |
---|
| 1021 | + if (!np || !of_device_is_available(np)) |
---|
| 1022 | + return -ENODEV; |
---|
| 1023 | + |
---|
| 1024 | + pdev = of_find_device_by_node(np); |
---|
| 1025 | + of_node_put(np); |
---|
| 1026 | + if (!pdev) |
---|
| 1027 | + return -ENODEV; |
---|
| 1028 | + |
---|
| 1029 | + ccu = platform_get_drvdata(pdev); |
---|
| 1030 | + if (!ccu) |
---|
| 1031 | + return -ENOMEM; |
---|
| 1032 | + |
---|
| 1033 | + spin_lock_irqsave(&ccu->lock, flags); |
---|
| 1034 | + ccu->core_num++; |
---|
| 1035 | + ccu->cores[enc->mpp.core_id] = &enc->mpp; |
---|
| 1036 | + set_bit(enc->mpp.core_id, &ccu->core_idle); |
---|
| 1037 | + spin_unlock_irqrestore(&ccu->lock, flags); |
---|
| 1038 | + |
---|
| 1039 | + /* attach the ccu-domain to current core */ |
---|
| 1040 | + if (!ccu->main_core) { |
---|
| 1041 | + /** |
---|
| 1042 | + * set the first device for the main-core, |
---|
| 1043 | + * then the domain of the main-core named ccu-domain |
---|
| 1044 | + */ |
---|
| 1045 | + ccu->main_core = &enc->mpp; |
---|
| 1046 | + } else { |
---|
| 1047 | + struct mpp_iommu_info *ccu_info, *cur_info; |
---|
| 1048 | + |
---|
| 1049 | + /* set the ccu domain for current device */ |
---|
| 1050 | + ccu_info = ccu->main_core->iommu_info; |
---|
| 1051 | + cur_info = enc->mpp.iommu_info; |
---|
| 1052 | + |
---|
| 1053 | + cur_info->domain = ccu_info->domain; |
---|
| 1054 | + mpp_iommu_attach(cur_info); |
---|
| 1055 | + } |
---|
| 1056 | + enc->ccu = ccu; |
---|
| 1057 | + |
---|
| 1058 | + dev_info(dev, "attach ccu success\n"); |
---|
| 1059 | + return 0; |
---|
| 1060 | +} |
---|
| 1061 | + |
---|
| 1062 | +static int vepu_core_probe(struct platform_device *pdev) |
---|
821 | 1063 | { |
---|
822 | 1064 | struct device *dev = &pdev->dev; |
---|
823 | 1065 | struct vepu_dev *enc = NULL; |
---|
.. | .. |
---|
825 | 1067 | const struct of_device_id *match = NULL; |
---|
826 | 1068 | int ret = 0; |
---|
827 | 1069 | |
---|
828 | | - dev_info(dev, "probe device\n"); |
---|
829 | 1070 | enc = devm_kzalloc(dev, sizeof(struct vepu_dev), GFP_KERNEL); |
---|
830 | 1071 | if (!enc) |
---|
831 | 1072 | return -ENOMEM; |
---|
832 | 1073 | |
---|
833 | 1074 | mpp = &enc->mpp; |
---|
834 | | - platform_set_drvdata(pdev, enc); |
---|
| 1075 | + platform_set_drvdata(pdev, mpp); |
---|
835 | 1076 | |
---|
836 | 1077 | if (pdev->dev.of_node) { |
---|
837 | 1078 | match = of_match_node(mpp_vepu2_dt_match, pdev->dev.of_node); |
---|
838 | 1079 | if (match) |
---|
839 | 1080 | mpp->var = (struct mpp_dev_var *)match->data; |
---|
| 1081 | + |
---|
| 1082 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "jpege"); |
---|
| 1083 | + } |
---|
| 1084 | + |
---|
| 1085 | + ret = mpp_dev_probe(mpp, pdev); |
---|
| 1086 | + if (ret) { |
---|
| 1087 | + dev_err(dev, "probe sub driver failed\n"); |
---|
| 1088 | + return -EINVAL; |
---|
| 1089 | + } |
---|
| 1090 | + /* current device attach to ccu */ |
---|
| 1091 | + ret = vepu_attach_ccu(dev, enc); |
---|
| 1092 | + if (ret) |
---|
| 1093 | + return ret; |
---|
| 1094 | + |
---|
| 1095 | + ret = devm_request_threaded_irq(dev, mpp->irq, |
---|
| 1096 | + mpp_dev_irq, |
---|
| 1097 | + mpp_dev_isr_sched, |
---|
| 1098 | + IRQF_SHARED, |
---|
| 1099 | + dev_name(dev), mpp); |
---|
| 1100 | + if (ret) { |
---|
| 1101 | + dev_err(dev, "register interrupter runtime failed\n"); |
---|
| 1102 | + return -EINVAL; |
---|
| 1103 | + } |
---|
| 1104 | + |
---|
| 1105 | + mpp->session_max_buffers = VEPU2_SESSION_MAX_BUFFERS; |
---|
| 1106 | + vepu_procfs_init(mpp); |
---|
| 1107 | + vepu_procfs_ccu_init(mpp); |
---|
| 1108 | + /* if current is main-core, register current device to mpp service */ |
---|
| 1109 | + if (mpp == enc->ccu->main_core) |
---|
| 1110 | + mpp_dev_register_srv(mpp, mpp->srv); |
---|
| 1111 | + |
---|
| 1112 | + return 0; |
---|
| 1113 | +} |
---|
| 1114 | + |
---|
| 1115 | +static int vepu_probe_default(struct platform_device *pdev) |
---|
| 1116 | +{ |
---|
| 1117 | + struct device *dev = &pdev->dev; |
---|
| 1118 | + struct vepu_dev *enc = NULL; |
---|
| 1119 | + struct mpp_dev *mpp = NULL; |
---|
| 1120 | + const struct of_device_id *match = NULL; |
---|
| 1121 | + int ret = 0; |
---|
| 1122 | + |
---|
| 1123 | + enc = devm_kzalloc(dev, sizeof(struct vepu_dev), GFP_KERNEL); |
---|
| 1124 | + if (!enc) |
---|
| 1125 | + return -ENOMEM; |
---|
| 1126 | + |
---|
| 1127 | + mpp = &enc->mpp; |
---|
| 1128 | + platform_set_drvdata(pdev, mpp); |
---|
| 1129 | + |
---|
| 1130 | + if (pdev->dev.of_node) { |
---|
| 1131 | + match = of_match_node(mpp_vepu2_dt_match, pdev->dev.of_node); |
---|
| 1132 | + if (match) |
---|
| 1133 | + mpp->var = (struct mpp_dev_var *)match->data; |
---|
| 1134 | + |
---|
| 1135 | + mpp->core_id = of_alias_get_id(pdev->dev.of_node, "vepu"); |
---|
840 | 1136 | } |
---|
841 | 1137 | |
---|
842 | 1138 | ret = mpp_dev_probe(mpp, pdev); |
---|
.. | .. |
---|
859 | 1155 | vepu_procfs_init(mpp); |
---|
860 | 1156 | /* register current device to mpp service */ |
---|
861 | 1157 | mpp_dev_register_srv(mpp, mpp->srv); |
---|
862 | | - dev_info(dev, "probing finish\n"); |
---|
863 | 1158 | |
---|
864 | 1159 | return 0; |
---|
| 1160 | +} |
---|
| 1161 | + |
---|
| 1162 | +static int vepu_probe(struct platform_device *pdev) |
---|
| 1163 | +{ |
---|
| 1164 | + int ret; |
---|
| 1165 | + struct device *dev = &pdev->dev; |
---|
| 1166 | + struct device_node *np = dev->of_node; |
---|
| 1167 | + |
---|
| 1168 | + dev_info(dev, "probing start\n"); |
---|
| 1169 | + |
---|
| 1170 | + if (strstr(np->name, "ccu")) |
---|
| 1171 | + ret = vepu_ccu_probe(pdev); |
---|
| 1172 | + else if (strstr(np->name, "core")) |
---|
| 1173 | + ret = vepu_core_probe(pdev); |
---|
| 1174 | + else |
---|
| 1175 | + ret = vepu_probe_default(pdev); |
---|
| 1176 | + |
---|
| 1177 | + dev_info(dev, "probing finish\n"); |
---|
| 1178 | + |
---|
| 1179 | + return ret; |
---|
865 | 1180 | } |
---|
866 | 1181 | |
---|
867 | 1182 | static int vepu_remove(struct platform_device *pdev) |
---|
868 | 1183 | { |
---|
869 | 1184 | struct device *dev = &pdev->dev; |
---|
870 | | - struct vepu_dev *enc = platform_get_drvdata(pdev); |
---|
| 1185 | + struct device_node *np = dev->of_node; |
---|
871 | 1186 | |
---|
872 | | - dev_info(dev, "remove device\n"); |
---|
873 | | - mpp_dev_remove(&enc->mpp); |
---|
874 | | - vepu_procfs_remove(&enc->mpp); |
---|
| 1187 | + if (strstr(np->name, "ccu")) { |
---|
| 1188 | + dev_info(dev, "remove ccu device\n"); |
---|
| 1189 | + } else if (strstr(np->name, "core")) { |
---|
| 1190 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1191 | + struct vepu_dev *enc = to_vepu_dev(mpp); |
---|
| 1192 | + |
---|
| 1193 | + dev_info(dev, "remove core\n"); |
---|
| 1194 | + if (enc->ccu) { |
---|
| 1195 | + s32 core_id = mpp->core_id; |
---|
| 1196 | + struct vepu_ccu *ccu = enc->ccu; |
---|
| 1197 | + unsigned long flags; |
---|
| 1198 | + |
---|
| 1199 | + spin_lock_irqsave(&ccu->lock, flags); |
---|
| 1200 | + ccu->core_num--; |
---|
| 1201 | + ccu->cores[core_id] = NULL; |
---|
| 1202 | + clear_bit(core_id, &ccu->core_idle); |
---|
| 1203 | + spin_unlock_irqrestore(&ccu->lock, flags); |
---|
| 1204 | + } |
---|
| 1205 | + mpp_dev_remove(&enc->mpp); |
---|
| 1206 | + vepu_procfs_remove(&enc->mpp); |
---|
| 1207 | + } else { |
---|
| 1208 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1209 | + |
---|
| 1210 | + dev_info(dev, "remove device\n"); |
---|
| 1211 | + mpp_dev_remove(mpp); |
---|
| 1212 | + vepu_procfs_remove(mpp); |
---|
| 1213 | + } |
---|
875 | 1214 | |
---|
876 | 1215 | return 0; |
---|
877 | 1216 | } |
---|
878 | 1217 | |
---|
879 | 1218 | static void vepu_shutdown(struct platform_device *pdev) |
---|
880 | 1219 | { |
---|
881 | | - int ret; |
---|
882 | | - int val; |
---|
883 | 1220 | struct device *dev = &pdev->dev; |
---|
884 | | - struct vepu_dev *enc = platform_get_drvdata(pdev); |
---|
885 | | - struct mpp_dev *mpp = &enc->mpp; |
---|
886 | 1221 | |
---|
887 | | - dev_info(dev, "shutdown device\n"); |
---|
888 | | - |
---|
889 | | - atomic_inc(&mpp->srv->shutdown_request); |
---|
890 | | - ret = readx_poll_timeout(atomic_read, |
---|
891 | | - &mpp->task_count, |
---|
892 | | - val, val == 0, 20000, 200000); |
---|
893 | | - if (ret == -ETIMEDOUT) |
---|
894 | | - dev_err(dev, "wait total running time out\n"); |
---|
| 1222 | + if (!strstr(dev_name(dev), "ccu")) |
---|
| 1223 | + mpp_dev_shutdown(pdev); |
---|
895 | 1224 | } |
---|
896 | 1225 | |
---|
897 | 1226 | struct platform_driver rockchip_vepu2_driver = { |
---|