.. | .. |
---|
7 | 7 | * Ding Wei, leo.ding@rock-chips.com |
---|
8 | 8 | * |
---|
9 | 9 | */ |
---|
| 10 | +#include <linux/pm_runtime.h> |
---|
| 11 | + |
---|
10 | 12 | #include "mpp_debug.h" |
---|
11 | 13 | #include "mpp_common.h" |
---|
12 | 14 | #include "mpp_iommu.h" |
---|
.. | .. |
---|
17 | 19 | |
---|
18 | 20 | #include <linux/devfreq_cooling.h> |
---|
19 | 21 | #include <soc/rockchip/rockchip_ipa.h> |
---|
| 22 | +#include <soc/rockchip/rockchip_dmc.h> |
---|
20 | 23 | #include <soc/rockchip/rockchip_opp_select.h> |
---|
21 | 24 | #include <soc/rockchip/rockchip_system_monitor.h> |
---|
| 25 | +#include <soc/rockchip/rockchip_iommu.h> |
---|
22 | 26 | |
---|
23 | 27 | #ifdef CONFIG_PM_DEVFREQ |
---|
24 | | -#include "../../../devfreq/governor.h" |
---|
| 28 | +#include "../drivers/devfreq/governor.h" |
---|
25 | 29 | #endif |
---|
26 | 30 | |
---|
27 | 31 | /* |
---|
.. | .. |
---|
36 | 40 | .link_info = &rkvdec_link_v2_hw_info, |
---|
37 | 41 | }; |
---|
38 | 42 | |
---|
39 | | -static struct mpp_hw_info rkvdec_rk3568_hw_info = { |
---|
| 43 | +static struct mpp_hw_info rkvdec_rk356x_hw_info = { |
---|
40 | 44 | .reg_num = RKVDEC_REG_NUM, |
---|
41 | 45 | .reg_id = RKVDEC_REG_HW_ID_INDEX, |
---|
42 | 46 | .reg_start = RKVDEC_REG_START_INDEX, |
---|
43 | 47 | .reg_end = RKVDEC_REG_END_INDEX, |
---|
44 | 48 | .reg_en = RKVDEC_REG_START_EN_INDEX, |
---|
45 | | - .link_info = &rkvdec_link_rk3568_hw_info, |
---|
| 49 | + .link_info = &rkvdec_link_rk356x_hw_info, |
---|
| 50 | +}; |
---|
| 51 | + |
---|
| 52 | +static struct mpp_hw_info rkvdec_vdpu382_hw_info = { |
---|
| 53 | + .reg_num = RKVDEC_REG_NUM, |
---|
| 54 | + .reg_id = RKVDEC_REG_HW_ID_INDEX, |
---|
| 55 | + .reg_start = RKVDEC_REG_START_INDEX, |
---|
| 56 | + .reg_end = RKVDEC_REG_END_INDEX, |
---|
| 57 | + .reg_en = RKVDEC_REG_START_EN_INDEX, |
---|
| 58 | + .link_info = &rkvdec_link_vdpu382_hw_info, |
---|
46 | 59 | }; |
---|
47 | 60 | |
---|
48 | 61 | /* |
---|
.. | .. |
---|
180 | 193 | return 0; |
---|
181 | 194 | } |
---|
182 | 195 | |
---|
183 | | -static int mpp_set_rcbbuf(struct mpp_dev *mpp, |
---|
184 | | - struct mpp_session *session, |
---|
185 | | - struct rkvdec2_task *task) |
---|
| 196 | +int mpp_set_rcbbuf(struct mpp_dev *mpp, struct mpp_session *session, |
---|
| 197 | + struct mpp_task *task) |
---|
186 | 198 | { |
---|
187 | 199 | struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
188 | 200 | struct rkvdec2_session_priv *priv = session->priv; |
---|
.. | .. |
---|
202 | 214 | for (i = 0; i < rcb_inf->cnt; i++) { |
---|
203 | 215 | reg_idx = rcb_inf->elem[i].index; |
---|
204 | 216 | rcb_size = rcb_inf->elem[i].size; |
---|
205 | | - if (!rcb_size || |
---|
206 | | - rcb_offset > dec->sram_size || |
---|
207 | | - (rcb_offset + rcb_size) > dec->rcb_size) |
---|
| 217 | + if ((rcb_offset + rcb_size) > dec->rcb_size) { |
---|
| 218 | + mpp_debug(DEBUG_SRAM_INFO, |
---|
| 219 | + "rcb: reg %d use original buffer\n", reg_idx); |
---|
208 | 220 | continue; |
---|
| 221 | + } |
---|
209 | 222 | mpp_debug(DEBUG_SRAM_INFO, "rcb: reg %d offset %d, size %d\n", |
---|
210 | 223 | reg_idx, rcb_offset, rcb_size); |
---|
211 | 224 | task->reg[reg_idx] = dec->rcb_iova + rcb_offset; |
---|
.. | .. |
---|
218 | 231 | return 0; |
---|
219 | 232 | } |
---|
220 | 233 | |
---|
221 | | -void *rkvdec2_alloc_task(struct mpp_session *session, |
---|
222 | | - struct mpp_task_msgs *msgs) |
---|
| 234 | +int rkvdec2_task_init(struct mpp_dev *mpp, struct mpp_session *session, |
---|
| 235 | + struct rkvdec2_task *task, struct mpp_task_msgs *msgs) |
---|
223 | 236 | { |
---|
224 | 237 | int ret; |
---|
225 | | - struct mpp_task *mpp_task = NULL; |
---|
226 | | - struct rkvdec2_task *task = NULL; |
---|
227 | | - struct mpp_dev *mpp = session->mpp; |
---|
| 238 | + struct mpp_task *mpp_task = &task->mpp_task; |
---|
228 | 239 | |
---|
229 | 240 | mpp_debug_enter(); |
---|
230 | 241 | |
---|
231 | | - task = kzalloc(sizeof(*task), GFP_KERNEL); |
---|
232 | | - if (!task) |
---|
233 | | - return NULL; |
---|
234 | | - |
---|
235 | | - mpp_task = &task->mpp_task; |
---|
236 | 242 | mpp_task_init(session, mpp_task); |
---|
237 | 243 | mpp_task->hw_info = mpp->var->hw_info; |
---|
238 | 244 | mpp_task->reg = task->reg; |
---|
239 | 245 | /* extract reqs for current task */ |
---|
240 | 246 | ret = rkvdec2_extract_task_msg(session, task, msgs); |
---|
241 | 247 | if (ret) |
---|
242 | | - goto fail; |
---|
| 248 | + return ret; |
---|
243 | 249 | |
---|
244 | 250 | /* process fd in register */ |
---|
245 | 251 | if (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { |
---|
246 | 252 | u32 fmt = RKVDEC_GET_FORMAT(task->reg[RKVDEC_REG_FORMAT_INDEX]); |
---|
247 | 253 | |
---|
248 | | - ret = mpp_translate_reg_address(session, &task->mpp_task, |
---|
| 254 | + ret = mpp_translate_reg_address(session, mpp_task, |
---|
249 | 255 | fmt, task->reg, &task->off_inf); |
---|
250 | 256 | if (ret) |
---|
251 | 257 | goto fail; |
---|
252 | 258 | |
---|
253 | | - mpp_translate_reg_offset_info(&task->mpp_task, &task->off_inf, task->reg); |
---|
| 259 | + mpp_translate_reg_offset_info(mpp_task, &task->off_inf, task->reg); |
---|
254 | 260 | } |
---|
255 | | - mpp_set_rcbbuf(mpp, session, task); |
---|
| 261 | + |
---|
256 | 262 | task->strm_addr = task->reg[RKVDEC_REG_RLC_BASE_INDEX]; |
---|
257 | 263 | task->clk_mode = CLK_MODE_NORMAL; |
---|
258 | 264 | task->slot_idx = -1; |
---|
259 | | - init_waitqueue_head(&task->wait); |
---|
| 265 | + init_waitqueue_head(&mpp_task->wait); |
---|
260 | 266 | /* get resolution info */ |
---|
261 | 267 | if (session->priv) { |
---|
262 | 268 | struct rkvdec2_session_priv *priv = session->priv; |
---|
.. | .. |
---|
272 | 278 | |
---|
273 | 279 | mpp_debug_leave(); |
---|
274 | 280 | |
---|
275 | | - return mpp_task; |
---|
| 281 | + return 0; |
---|
276 | 282 | |
---|
277 | 283 | fail: |
---|
278 | 284 | mpp_task_dump_mem_region(mpp, mpp_task); |
---|
279 | 285 | mpp_task_dump_reg(mpp, mpp_task); |
---|
280 | 286 | mpp_task_finalize(session, mpp_task); |
---|
281 | | - kfree(task); |
---|
282 | | - return NULL; |
---|
| 287 | + return ret; |
---|
| 288 | +} |
---|
| 289 | + |
---|
| 290 | +void *rkvdec2_alloc_task(struct mpp_session *session, |
---|
| 291 | + struct mpp_task_msgs *msgs) |
---|
| 292 | +{ |
---|
| 293 | + int ret; |
---|
| 294 | + struct rkvdec2_task *task; |
---|
| 295 | + |
---|
| 296 | + task = kzalloc(sizeof(*task), GFP_KERNEL); |
---|
| 297 | + if (!task) |
---|
| 298 | + return NULL; |
---|
| 299 | + |
---|
| 300 | + ret = rkvdec2_task_init(session->mpp, session, task, msgs); |
---|
| 301 | + if (ret) { |
---|
| 302 | + kfree(task); |
---|
| 303 | + return NULL; |
---|
| 304 | + } |
---|
| 305 | + mpp_set_rcbbuf(session->mpp, session, &task->mpp_task); |
---|
| 306 | + |
---|
| 307 | + return &task->mpp_task; |
---|
283 | 308 | } |
---|
284 | 309 | |
---|
285 | 310 | static void *rkvdec2_rk3568_alloc_task(struct mpp_session *session, |
---|
286 | | - struct mpp_task_msgs *msgs) |
---|
| 311 | + struct mpp_task_msgs *msgs) |
---|
287 | 312 | { |
---|
288 | 313 | u32 fmt; |
---|
289 | 314 | struct mpp_task *mpp_task = NULL; |
---|
.. | .. |
---|
304 | 329 | static int rkvdec2_run(struct mpp_dev *mpp, struct mpp_task *mpp_task) |
---|
305 | 330 | { |
---|
306 | 331 | struct rkvdec2_task *task = to_rkvdec2_task(mpp_task); |
---|
| 332 | + u32 timing_en = mpp->srv->timing_en; |
---|
307 | 333 | u32 reg_en = mpp_task->hw_info->reg_en; |
---|
308 | 334 | /* set cache size */ |
---|
309 | 335 | u32 reg = RKVDEC_CACHE_PERMIT_CACHEABLE_ACCESS | |
---|
.. | .. |
---|
332 | 358 | e = s + req->size / sizeof(u32); |
---|
333 | 359 | mpp_write_req(mpp, task->reg, s, e, reg_en); |
---|
334 | 360 | } |
---|
| 361 | + |
---|
| 362 | + /* flush tlb before starting hardware */ |
---|
| 363 | + mpp_iommu_flush_tlb(mpp->iommu_info); |
---|
| 364 | + |
---|
335 | 365 | /* init current task */ |
---|
336 | 366 | mpp->cur_task = mpp_task; |
---|
337 | | - mpp_time_record(mpp_task); |
---|
| 367 | + |
---|
| 368 | + mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); |
---|
| 369 | + |
---|
338 | 370 | /* Flush the register before the start the device */ |
---|
339 | 371 | wmb(); |
---|
340 | 372 | mpp_write(mpp, RKVDEC_REG_START_EN_BASE, task->reg[reg_en] | RKVDEC_START_EN); |
---|
| 373 | + |
---|
| 374 | + mpp_task_run_end(mpp_task, timing_en); |
---|
341 | 375 | |
---|
342 | 376 | mpp_debug_leave(); |
---|
343 | 377 | |
---|
.. | .. |
---|
381 | 415 | u32 err_mask; |
---|
382 | 416 | struct rkvdec2_task *task = NULL; |
---|
383 | 417 | struct mpp_task *mpp_task = mpp->cur_task; |
---|
| 418 | + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
384 | 419 | |
---|
385 | 420 | /* FIXME use a spin lock here */ |
---|
386 | 421 | if (!mpp_task) { |
---|
387 | 422 | dev_err(mpp->dev, "no current task\n"); |
---|
388 | 423 | return IRQ_HANDLED; |
---|
389 | 424 | } |
---|
390 | | - mpp_time_diff(mpp_task); |
---|
| 425 | + mpp_task->hw_cycles = mpp_read(mpp, RKVDEC_PERF_WORKING_CNT); |
---|
| 426 | + mpp_time_diff_with_hw_time(mpp_task, dec->cycle_clk->real_rate_hz); |
---|
391 | 427 | mpp->cur_task = NULL; |
---|
392 | 428 | task = to_rkvdec2_task(mpp_task); |
---|
393 | 429 | task->irq_status = mpp->irq_status; |
---|
.. | .. |
---|
397 | 433 | RKVDEC_TIMEOUT_STA | RKVDEC_ERROR_STA; |
---|
398 | 434 | if (err_mask & task->irq_status) { |
---|
399 | 435 | atomic_inc(&mpp->reset_request); |
---|
400 | | - mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", |
---|
401 | | - task->irq_status); |
---|
402 | | - mpp_task_dump_hw_reg(mpp, mpp_task); |
---|
| 436 | + if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) { |
---|
| 437 | + mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status); |
---|
| 438 | + mpp_task_dump_hw_reg(mpp); |
---|
| 439 | + } |
---|
403 | 440 | } |
---|
404 | 441 | |
---|
405 | 442 | mpp_task_finish(mpp_task->session, mpp_task); |
---|
.. | .. |
---|
470 | 507 | dec_length = dec_get - task->strm_addr; |
---|
471 | 508 | task->reg[RKVDEC_REG_RLC_BASE_INDEX] = dec_length << 10; |
---|
472 | 509 | mpp_debug(DEBUG_REGISTER, "dec_get %08x dec_length %d\n", dec_get, dec_length); |
---|
| 510 | + |
---|
| 511 | + if (mpp->srv->timing_en) { |
---|
| 512 | + s64 time_diff; |
---|
| 513 | + |
---|
| 514 | + mpp_task->on_finish = ktime_get(); |
---|
| 515 | + set_bit(TASK_TIMING_FINISH, &mpp_task->state); |
---|
| 516 | + |
---|
| 517 | + time_diff = ktime_us_delta(mpp_task->on_finish, mpp_task->on_create); |
---|
| 518 | + |
---|
| 519 | + if (mpp->timing_check && time_diff > (s64)mpp->timing_check) |
---|
| 520 | + mpp_task_dump_timing(mpp_task, time_diff); |
---|
| 521 | + } |
---|
473 | 522 | |
---|
474 | 523 | mpp_debug_leave(); |
---|
475 | 524 | |
---|
.. | .. |
---|
610 | 659 | static int rkvdec2_procfs_init(struct mpp_dev *mpp) |
---|
611 | 660 | { |
---|
612 | 661 | struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
| 662 | + char name[32]; |
---|
613 | 663 | |
---|
614 | | - dec->procfs = proc_mkdir(mpp->dev->of_node->name, mpp->srv->procfs); |
---|
| 664 | + if (!mpp->dev || !mpp->dev->of_node || !mpp->dev->of_node->name || |
---|
| 665 | + !mpp->srv || !mpp->srv->procfs) |
---|
| 666 | + return -EINVAL; |
---|
| 667 | + |
---|
| 668 | + snprintf(name, sizeof(name) - 1, "%s%d", |
---|
| 669 | + mpp->dev->of_node->name, mpp->core_id); |
---|
| 670 | + dec->procfs = proc_mkdir(name, mpp->srv->procfs); |
---|
615 | 671 | if (IS_ERR_OR_NULL(dec->procfs)) { |
---|
616 | 672 | mpp_err("failed on open procfs\n"); |
---|
617 | 673 | dec->procfs = NULL; |
---|
618 | 674 | return -EIO; |
---|
619 | 675 | } |
---|
| 676 | + |
---|
| 677 | + /* for common mpp_dev options */ |
---|
| 678 | + mpp_procfs_create_common(dec->procfs, mpp); |
---|
| 679 | + |
---|
620 | 680 | mpp_procfs_create_u32("aclk", 0644, |
---|
621 | 681 | dec->procfs, &dec->aclk_info.debug_rate_hz); |
---|
622 | 682 | mpp_procfs_create_u32("clk_core", 0644, |
---|
.. | .. |
---|
770 | 830 | }; |
---|
771 | 831 | |
---|
772 | 832 | static struct monitor_dev_profile vdec2_mdevp = { |
---|
773 | | - .type = MONITOR_TPYE_DEV, |
---|
| 833 | + .type = MONITOR_TYPE_DEV, |
---|
774 | 834 | .low_temp_adjust = rockchip_monitor_dev_low_temp_adjust, |
---|
775 | 835 | .high_temp_adjust = rockchip_monitor_dev_high_temp_adjust, |
---|
776 | 836 | }; |
---|
.. | .. |
---|
878 | 938 | |
---|
879 | 939 | return 0; |
---|
880 | 940 | } |
---|
| 941 | + |
---|
| 942 | +void mpp_devfreq_set_core_rate(struct mpp_dev *mpp, enum MPP_CLOCK_MODE mode) |
---|
| 943 | +{ |
---|
| 944 | + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
| 945 | + |
---|
| 946 | + if (dec->devfreq) { |
---|
| 947 | + unsigned long core_rate_hz; |
---|
| 948 | + |
---|
| 949 | + mutex_lock(&dec->devfreq->lock); |
---|
| 950 | + core_rate_hz = mpp_get_clk_info_rate_hz(&dec->core_clk_info, mode); |
---|
| 951 | + if (dec->core_rate_hz != core_rate_hz) { |
---|
| 952 | + dec->core_rate_hz = core_rate_hz; |
---|
| 953 | + update_devfreq(dec->devfreq); |
---|
| 954 | + } |
---|
| 955 | + mutex_unlock(&dec->devfreq->lock); |
---|
| 956 | + } |
---|
| 957 | + |
---|
| 958 | + mpp_clk_set_rate(&dec->core_clk_info, mode); |
---|
| 959 | +} |
---|
| 960 | +#else |
---|
| 961 | +static inline int rkvdec2_devfreq_init(struct mpp_dev *mpp) |
---|
| 962 | +{ |
---|
| 963 | + return 0; |
---|
| 964 | +} |
---|
| 965 | + |
---|
| 966 | +static inline int rkvdec2_devfreq_remove(struct mpp_dev *mpp) |
---|
| 967 | +{ |
---|
| 968 | + return 0; |
---|
| 969 | +} |
---|
| 970 | + |
---|
| 971 | +void mpp_devfreq_set_core_rate(struct mpp_dev *mpp, enum MPP_CLOCK_MODE mode) |
---|
| 972 | +{ |
---|
| 973 | + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
| 974 | + |
---|
| 975 | + mpp_clk_set_rate(&dec->core_clk_info, mode); |
---|
| 976 | +} |
---|
881 | 977 | #endif |
---|
882 | 978 | |
---|
883 | 979 | static int rkvdec2_init(struct mpp_dev *mpp) |
---|
.. | .. |
---|
910 | 1006 | mpp_set_clk_info_rate_hz(&dec->cabac_clk_info, CLK_MODE_DEFAULT, 200 * MHZ); |
---|
911 | 1007 | mpp_set_clk_info_rate_hz(&dec->hevc_cabac_clk_info, CLK_MODE_DEFAULT, 300 * MHZ); |
---|
912 | 1008 | |
---|
| 1009 | + dec->cycle_clk = &dec->aclk_info; |
---|
913 | 1010 | /* Get normal max workload from dtsi */ |
---|
914 | 1011 | of_property_read_u32(mpp->dev->of_node, |
---|
915 | 1012 | "rockchip,default-max-load", &dec->default_max_load); |
---|
.. | .. |
---|
936 | 1033 | if (!dec->rst_hevc_cabac) |
---|
937 | 1034 | mpp_err("No hevc cabac reset resource define\n"); |
---|
938 | 1035 | |
---|
939 | | -#ifdef CONFIG_PM_DEVFREQ |
---|
940 | 1036 | ret = rkvdec2_devfreq_init(mpp); |
---|
941 | 1037 | if (ret) |
---|
942 | 1038 | mpp_err("failed to add vdec devfreq\n"); |
---|
943 | | -#endif |
---|
| 1039 | + |
---|
944 | 1040 | return ret; |
---|
945 | 1041 | } |
---|
946 | 1042 | |
---|
.. | .. |
---|
965 | 1061 | { |
---|
966 | 1062 | struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
967 | 1063 | |
---|
968 | | -#ifdef CONFIG_PM_DEVFREQ |
---|
969 | 1064 | rkvdec2_devfreq_remove(mpp); |
---|
970 | | -#endif |
---|
971 | 1065 | |
---|
972 | 1066 | if (dec->fix) |
---|
973 | 1067 | mpp_dma_free(dec->fix); |
---|
.. | .. |
---|
1046 | 1140 | mpp_clk_set_rate(&dec->aclk_info, task->clk_mode); |
---|
1047 | 1141 | mpp_clk_set_rate(&dec->cabac_clk_info, task->clk_mode); |
---|
1048 | 1142 | mpp_clk_set_rate(&dec->hevc_cabac_clk_info, task->clk_mode); |
---|
1049 | | - |
---|
1050 | | -#ifdef CONFIG_PM_DEVFREQ |
---|
1051 | | - if (dec->devfreq) { |
---|
1052 | | - unsigned long core_rate_hz; |
---|
1053 | | - |
---|
1054 | | - mutex_lock(&dec->devfreq->lock); |
---|
1055 | | - core_rate_hz = mpp_get_clk_info_rate_hz(&dec->core_clk_info, task->clk_mode); |
---|
1056 | | - if (dec->core_rate_hz != core_rate_hz) { |
---|
1057 | | - dec->core_rate_hz = core_rate_hz; |
---|
1058 | | - update_devfreq(dec->devfreq); |
---|
1059 | | - } |
---|
1060 | | - mutex_unlock(&dec->devfreq->lock); |
---|
1061 | | - |
---|
1062 | | - return 0; |
---|
1063 | | - } |
---|
1064 | | -#endif |
---|
1065 | | - mpp_clk_set_rate(&dec->core_clk_info, task->clk_mode); |
---|
| 1143 | + mpp_devfreq_set_core_rate(mpp, task->clk_mode); |
---|
1066 | 1144 | |
---|
1067 | 1145 | return 0; |
---|
1068 | 1146 | } |
---|
1069 | 1147 | |
---|
1070 | | -static int rkvdec2_reset(struct mpp_dev *mpp) |
---|
| 1148 | +static int rkvdec2_soft_reset(struct mpp_dev *mpp) |
---|
| 1149 | +{ |
---|
| 1150 | + int ret = 0; |
---|
| 1151 | + |
---|
| 1152 | + /* |
---|
| 1153 | + * for rk3528 and rk3562 |
---|
| 1154 | + * use mmu reset instead of rkvdec soft reset |
---|
| 1155 | + * rkvdec will reset together when rkvdec_mmu force reset |
---|
| 1156 | + */ |
---|
| 1157 | + ret = rockchip_iommu_force_reset(mpp->dev); |
---|
| 1158 | + if (ret) |
---|
| 1159 | + mpp_err("soft mmu reset fail, ret %d\n", ret); |
---|
| 1160 | + mpp_write(mpp, RKVDEC_REG_INT_EN, 0); |
---|
| 1161 | + |
---|
| 1162 | + return ret; |
---|
| 1163 | + |
---|
| 1164 | +} |
---|
| 1165 | + |
---|
| 1166 | +static int rkvdec2_sip_reset(struct mpp_dev *mpp) |
---|
| 1167 | +{ |
---|
| 1168 | + mpp_debug_enter(); |
---|
| 1169 | + |
---|
| 1170 | + if (IS_REACHABLE(CONFIG_ROCKCHIP_SIP)) { |
---|
| 1171 | + /* sip reset */ |
---|
| 1172 | + rockchip_dmcfreq_lock(); |
---|
| 1173 | + sip_smc_vpu_reset(0, 0, 0); |
---|
| 1174 | + rockchip_dmcfreq_unlock(); |
---|
| 1175 | + } else { |
---|
| 1176 | + rkvdec2_reset(mpp); |
---|
| 1177 | + } |
---|
| 1178 | + |
---|
| 1179 | + mpp_debug_leave(); |
---|
| 1180 | + |
---|
| 1181 | + return 0; |
---|
| 1182 | +} |
---|
| 1183 | + |
---|
| 1184 | +int rkvdec2_reset(struct mpp_dev *mpp) |
---|
1071 | 1185 | { |
---|
1072 | 1186 | struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
| 1187 | + int ret = 0; |
---|
1073 | 1188 | |
---|
1074 | 1189 | mpp_debug_enter(); |
---|
1075 | | -#ifdef CONFIG_PM_DEVFREQ |
---|
1076 | | - if (dec->devfreq) |
---|
1077 | | - mutex_lock(&dec->devfreq->lock); |
---|
1078 | | -#endif |
---|
1079 | | - if (dec->rst_a && dec->rst_h) { |
---|
1080 | | - rockchip_pmu_idle_request(mpp->dev, true); |
---|
| 1190 | + |
---|
| 1191 | + /* safe reset first*/ |
---|
| 1192 | + ret = rkvdec2_soft_reset(mpp); |
---|
| 1193 | + |
---|
| 1194 | + /* cru reset */ |
---|
| 1195 | + if (ret && dec->rst_a && dec->rst_h) { |
---|
| 1196 | + mpp_err("soft reset timeout, use cru reset\n"); |
---|
| 1197 | + mpp_pmu_idle_request(mpp, true); |
---|
1081 | 1198 | mpp_safe_reset(dec->rst_niu_a); |
---|
1082 | 1199 | mpp_safe_reset(dec->rst_niu_h); |
---|
1083 | 1200 | mpp_safe_reset(dec->rst_a); |
---|
.. | .. |
---|
1093 | 1210 | mpp_safe_unreset(dec->rst_core); |
---|
1094 | 1211 | mpp_safe_unreset(dec->rst_cabac); |
---|
1095 | 1212 | mpp_safe_unreset(dec->rst_hevc_cabac); |
---|
1096 | | - rockchip_pmu_idle_request(mpp->dev, false); |
---|
| 1213 | + mpp_pmu_idle_request(mpp, false); |
---|
1097 | 1214 | } |
---|
1098 | | -#ifdef CONFIG_PM_DEVFREQ |
---|
1099 | | - if (dec->devfreq) |
---|
1100 | | - mutex_unlock(&dec->devfreq->lock); |
---|
1101 | | -#endif |
---|
1102 | 1215 | mpp_debug_leave(); |
---|
1103 | 1216 | |
---|
1104 | 1217 | return 0; |
---|
.. | .. |
---|
1120 | 1233 | .clk_off = rkvdec2_clk_off, |
---|
1121 | 1234 | .get_freq = rkvdec2_get_freq, |
---|
1122 | 1235 | .set_freq = rkvdec2_set_freq, |
---|
1123 | | - .reset = rkvdec2_reset, |
---|
| 1236 | + .reset = rkvdec2_sip_reset, |
---|
| 1237 | +}; |
---|
| 1238 | + |
---|
| 1239 | +static struct mpp_hw_ops rkvdec_rk3588_hw_ops = { |
---|
| 1240 | + .init = rkvdec2_init, |
---|
| 1241 | + .clk_on = rkvdec2_clk_on, |
---|
| 1242 | + .clk_off = rkvdec2_clk_off, |
---|
| 1243 | + .get_freq = rkvdec2_get_freq, |
---|
| 1244 | + .set_freq = rkvdec2_set_freq, |
---|
| 1245 | + .reset = rkvdec2_sip_reset, |
---|
1124 | 1246 | }; |
---|
1125 | 1247 | |
---|
1126 | 1248 | static struct mpp_dev_ops rkvdec_v2_dev_ops = { |
---|
.. | .. |
---|
1160 | 1282 | |
---|
1161 | 1283 | static const struct mpp_dev_var rkvdec_rk3568_data = { |
---|
1162 | 1284 | .device_type = MPP_DEVICE_RKVDEC, |
---|
1163 | | - .hw_info = &rkvdec_rk3568_hw_info, |
---|
| 1285 | + .hw_info = &rkvdec_rk356x_hw_info, |
---|
1164 | 1286 | .trans_info = rkvdec_v2_trans, |
---|
1165 | 1287 | .hw_ops = &rkvdec_rk3568_hw_ops, |
---|
1166 | 1288 | .dev_ops = &rkvdec_rk3568_dev_ops, |
---|
| 1289 | +}; |
---|
| 1290 | + |
---|
| 1291 | +static const struct mpp_dev_var rkvdec_vdpu382_data = { |
---|
| 1292 | + .device_type = MPP_DEVICE_RKVDEC, |
---|
| 1293 | + .hw_info = &rkvdec_vdpu382_hw_info, |
---|
| 1294 | + .trans_info = rkvdec_v2_trans, |
---|
| 1295 | + .hw_ops = &rkvdec_v2_hw_ops, |
---|
| 1296 | + .dev_ops = &rkvdec_v2_dev_ops, |
---|
| 1297 | +}; |
---|
| 1298 | + |
---|
| 1299 | +static const struct mpp_dev_var rkvdec_rk3588_data = { |
---|
| 1300 | + .device_type = MPP_DEVICE_RKVDEC, |
---|
| 1301 | + .hw_info = &rkvdec_v2_hw_info, |
---|
| 1302 | + .trans_info = rkvdec_v2_trans, |
---|
| 1303 | + .hw_ops = &rkvdec_rk3588_hw_ops, |
---|
| 1304 | + .dev_ops = &rkvdec_v2_dev_ops, |
---|
1167 | 1305 | }; |
---|
1168 | 1306 | |
---|
1169 | 1307 | static const struct of_device_id mpp_rkvdec2_dt_match[] = { |
---|
.. | .. |
---|
1177 | 1315 | .data = &rkvdec_rk3568_data, |
---|
1178 | 1316 | }, |
---|
1179 | 1317 | #endif |
---|
| 1318 | +#ifdef CONFIG_CPU_RK3588 |
---|
| 1319 | + { |
---|
| 1320 | + .compatible = "rockchip,rkv-decoder-v2-ccu", |
---|
| 1321 | + .data = &rkvdec_rk3588_data, |
---|
| 1322 | + }, |
---|
| 1323 | +#endif |
---|
| 1324 | +#ifdef CONFIG_CPU_RK3528 |
---|
| 1325 | + { |
---|
| 1326 | + .compatible = "rockchip,rkv-decoder-rk3528", |
---|
| 1327 | + .data = &rkvdec_vdpu382_data, |
---|
| 1328 | + }, |
---|
| 1329 | +#endif |
---|
| 1330 | +#ifdef CONFIG_CPU_RK3562 |
---|
| 1331 | + { |
---|
| 1332 | + .compatible = "rockchip,rkv-decoder-rk3562", |
---|
| 1333 | + .data = &rkvdec_vdpu382_data, |
---|
| 1334 | + }, |
---|
| 1335 | +#endif |
---|
1180 | 1336 | {}, |
---|
1181 | 1337 | }; |
---|
| 1338 | + |
---|
| 1339 | +static int rkvdec2_ccu_remove(struct device *dev) |
---|
| 1340 | +{ |
---|
| 1341 | + device_init_wakeup(dev, false); |
---|
| 1342 | + pm_runtime_disable(dev); |
---|
| 1343 | + |
---|
| 1344 | + return 0; |
---|
| 1345 | +} |
---|
| 1346 | + |
---|
| 1347 | +static int rkvdec2_ccu_probe(struct platform_device *pdev) |
---|
| 1348 | +{ |
---|
| 1349 | + struct rkvdec2_ccu *ccu; |
---|
| 1350 | + struct resource *res; |
---|
| 1351 | + struct device *dev = &pdev->dev; |
---|
| 1352 | + u32 ccu_mode; |
---|
| 1353 | + |
---|
| 1354 | + ccu = devm_kzalloc(dev, sizeof(*ccu), GFP_KERNEL); |
---|
| 1355 | + if (!ccu) |
---|
| 1356 | + return -ENOMEM; |
---|
| 1357 | + |
---|
| 1358 | + ccu->dev = dev; |
---|
| 1359 | + /* use task-level soft ccu default */ |
---|
| 1360 | + ccu->ccu_mode = RKVDEC2_CCU_TASK_SOFT; |
---|
| 1361 | + atomic_set(&ccu->power_enabled, 0); |
---|
| 1362 | + INIT_LIST_HEAD(&ccu->unused_list); |
---|
| 1363 | + INIT_LIST_HEAD(&ccu->used_list); |
---|
| 1364 | + platform_set_drvdata(pdev, ccu); |
---|
| 1365 | + |
---|
| 1366 | + if (!of_property_read_u32(dev->of_node, "rockchip,ccu-mode", &ccu_mode)) { |
---|
| 1367 | + if (ccu_mode <= RKVDEC2_CCU_MODE_NULL || ccu_mode >= RKVDEC2_CCU_MODE_BUTT) |
---|
| 1368 | + ccu_mode = RKVDEC2_CCU_TASK_SOFT; |
---|
| 1369 | + ccu->ccu_mode = (enum RKVDEC2_CCU_MODE)ccu_mode; |
---|
| 1370 | + } |
---|
| 1371 | + |
---|
| 1372 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ccu"); |
---|
| 1373 | + if (!res) { |
---|
| 1374 | + dev_err(dev, "no memory resource defined\n"); |
---|
| 1375 | + return -ENODEV; |
---|
| 1376 | + } |
---|
| 1377 | + |
---|
| 1378 | + ccu->reg_base = devm_ioremap(dev, res->start, resource_size(res)); |
---|
| 1379 | + if (!ccu->reg_base) { |
---|
| 1380 | + dev_err(dev, "ioremap failed for resource %pR\n", res); |
---|
| 1381 | + return -ENODEV; |
---|
| 1382 | + } |
---|
| 1383 | + |
---|
| 1384 | + ccu->aclk_info.clk = devm_clk_get(dev, "aclk_ccu"); |
---|
| 1385 | + if (!ccu->aclk_info.clk) |
---|
| 1386 | + mpp_err("failed on clk_get ccu aclk\n"); |
---|
| 1387 | + |
---|
| 1388 | + ccu->rst_a = devm_reset_control_get(dev, "video_ccu"); |
---|
| 1389 | + if (ccu->rst_a) |
---|
| 1390 | + mpp_safe_unreset(ccu->rst_a); |
---|
| 1391 | + else |
---|
| 1392 | + mpp_err("failed on clk_get ccu reset\n"); |
---|
| 1393 | + |
---|
| 1394 | + /* power domain autosuspend delay 2s */ |
---|
| 1395 | + pm_runtime_set_autosuspend_delay(dev, 2000); |
---|
| 1396 | + pm_runtime_use_autosuspend(dev); |
---|
| 1397 | + device_init_wakeup(dev, true); |
---|
| 1398 | + pm_runtime_enable(dev); |
---|
| 1399 | + |
---|
| 1400 | + dev_info(dev, "ccu-mode: %d\n", ccu->ccu_mode); |
---|
| 1401 | + return 0; |
---|
| 1402 | +} |
---|
1182 | 1403 | |
---|
1183 | 1404 | static int rkvdec2_alloc_rcbbuf(struct platform_device *pdev, struct rkvdec2_dev *dec) |
---|
1184 | 1405 | { |
---|
.. | .. |
---|
1273 | 1494 | if (!ret && dec->rcb_min_width) |
---|
1274 | 1495 | dev_info(dev, "min_width %u\n", dec->rcb_min_width); |
---|
1275 | 1496 | |
---|
| 1497 | + /* if have, read rcb_info */ |
---|
| 1498 | + dec->rcb_info_count = device_property_count_u32(dev, "rockchip,rcb-info"); |
---|
| 1499 | + if (dec->rcb_info_count > 0 && |
---|
| 1500 | + dec->rcb_info_count <= (sizeof(dec->rcb_infos) / sizeof(u32))) { |
---|
| 1501 | + int i; |
---|
| 1502 | + |
---|
| 1503 | + ret = device_property_read_u32_array(dev, "rockchip,rcb-info", |
---|
| 1504 | + dec->rcb_infos, dec->rcb_info_count); |
---|
| 1505 | + if (!ret) { |
---|
| 1506 | + dev_info(dev, "rcb_info_count %u\n", dec->rcb_info_count); |
---|
| 1507 | + for (i = 0; i < dec->rcb_info_count; i += 2) |
---|
| 1508 | + dev_info(dev, "[%u, %u]\n", |
---|
| 1509 | + dec->rcb_infos[i], dec->rcb_infos[i+1]); |
---|
| 1510 | + } |
---|
| 1511 | + } |
---|
| 1512 | + |
---|
1276 | 1513 | return 0; |
---|
1277 | 1514 | |
---|
1278 | 1515 | err_sram_map: |
---|
.. | .. |
---|
1281 | 1518 | return ret; |
---|
1282 | 1519 | } |
---|
1283 | 1520 | |
---|
1284 | | -static int rkvdec2_probe(struct platform_device *pdev) |
---|
| 1521 | +static int rkvdec2_core_probe(struct platform_device *pdev) |
---|
| 1522 | +{ |
---|
| 1523 | + int ret; |
---|
| 1524 | + struct rkvdec2_dev *dec; |
---|
| 1525 | + struct mpp_dev *mpp; |
---|
| 1526 | + struct device *dev = &pdev->dev; |
---|
| 1527 | + irq_handler_t irq_proc = NULL; |
---|
| 1528 | + |
---|
| 1529 | + dec = devm_kzalloc(dev, sizeof(*dec), GFP_KERNEL); |
---|
| 1530 | + if (!dec) |
---|
| 1531 | + return -ENOMEM; |
---|
| 1532 | + |
---|
| 1533 | + mpp = &dec->mpp; |
---|
| 1534 | + platform_set_drvdata(pdev, mpp); |
---|
| 1535 | + mpp->is_irq_startup = false; |
---|
| 1536 | + if (dev->of_node) { |
---|
| 1537 | + struct device_node *np = pdev->dev.of_node; |
---|
| 1538 | + const struct of_device_id *match; |
---|
| 1539 | + |
---|
| 1540 | + match = of_match_node(mpp_rkvdec2_dt_match, dev->of_node); |
---|
| 1541 | + if (match) |
---|
| 1542 | + mpp->var = (struct mpp_dev_var *)match->data; |
---|
| 1543 | + mpp->core_id = of_alias_get_id(np, "rkvdec"); |
---|
| 1544 | + } |
---|
| 1545 | + |
---|
| 1546 | + ret = mpp_dev_probe(mpp, pdev); |
---|
| 1547 | + if (ret) { |
---|
| 1548 | + dev_err(dev, "probe sub driver failed\n"); |
---|
| 1549 | + return ret; |
---|
| 1550 | + } |
---|
| 1551 | + dec->mmu_base = ioremap(dec->mpp.io_base + 0x600, 0x80); |
---|
| 1552 | + if (!dec->mmu_base) |
---|
| 1553 | + dev_err(dev, "mmu base map failed!\n"); |
---|
| 1554 | + |
---|
| 1555 | + /* attach core to ccu */ |
---|
| 1556 | + ret = rkvdec2_attach_ccu(dev, dec); |
---|
| 1557 | + if (ret) { |
---|
| 1558 | + dev_err(dev, "attach ccu failed\n"); |
---|
| 1559 | + return ret; |
---|
| 1560 | + } |
---|
| 1561 | + |
---|
| 1562 | + /* alloc rcb buffer */ |
---|
| 1563 | + rkvdec2_alloc_rcbbuf(pdev, dec); |
---|
| 1564 | + |
---|
| 1565 | + /* set device for link */ |
---|
| 1566 | + ret = rkvdec2_ccu_link_init(pdev, dec); |
---|
| 1567 | + if (ret) |
---|
| 1568 | + return ret; |
---|
| 1569 | + |
---|
| 1570 | + mpp->dev_ops->alloc_task = rkvdec2_ccu_alloc_task; |
---|
| 1571 | + if (dec->ccu->ccu_mode == RKVDEC2_CCU_TASK_SOFT) { |
---|
| 1572 | + mpp->dev_ops->task_worker = rkvdec2_soft_ccu_worker; |
---|
| 1573 | + irq_proc = rkvdec2_soft_ccu_irq; |
---|
| 1574 | + mpp->fault_handler = rkvdec2_soft_ccu_iommu_fault_handle; |
---|
| 1575 | + } else if (dec->ccu->ccu_mode == RKVDEC2_CCU_TASK_HARD) { |
---|
| 1576 | + if (mpp->core_id == 0 && mpp->task_capacity > 1) { |
---|
| 1577 | + dec->link_dec->task_capacity = mpp->task_capacity; |
---|
| 1578 | + ret = rkvdec2_ccu_alloc_table(dec, dec->link_dec); |
---|
| 1579 | + if (ret) |
---|
| 1580 | + return ret; |
---|
| 1581 | + } |
---|
| 1582 | + mpp->dev_ops->task_worker = rkvdec2_hard_ccu_worker; |
---|
| 1583 | + irq_proc = rkvdec2_hard_ccu_irq; |
---|
| 1584 | + mpp->fault_handler = rkvdec2_hard_ccu_iommu_fault_handle; |
---|
| 1585 | + } |
---|
| 1586 | + kthread_init_work(&mpp->work, mpp->dev_ops->task_worker); |
---|
| 1587 | + |
---|
| 1588 | + /* get irq request */ |
---|
| 1589 | + ret = devm_request_threaded_irq(dev, mpp->irq, irq_proc, NULL, |
---|
| 1590 | + IRQF_SHARED, dev_name(dev), mpp); |
---|
| 1591 | + if (ret) { |
---|
| 1592 | + dev_err(dev, "register interrupter runtime failed\n"); |
---|
| 1593 | + return -EINVAL; |
---|
| 1594 | + } |
---|
| 1595 | + /*make sure mpp->irq is startup then can be en/disable*/ |
---|
| 1596 | + mpp->is_irq_startup = true; |
---|
| 1597 | + |
---|
| 1598 | + mpp->session_max_buffers = RKVDEC_SESSION_MAX_BUFFERS; |
---|
| 1599 | + rkvdec2_procfs_init(mpp); |
---|
| 1600 | + |
---|
| 1601 | + /* if is main-core, register to mpp service */ |
---|
| 1602 | + if (mpp->core_id == 0) |
---|
| 1603 | + mpp_dev_register_srv(mpp, mpp->srv); |
---|
| 1604 | + |
---|
| 1605 | + return ret; |
---|
| 1606 | +} |
---|
| 1607 | + |
---|
| 1608 | +static int rkvdec2_probe_default(struct platform_device *pdev) |
---|
1285 | 1609 | { |
---|
1286 | 1610 | struct device *dev = &pdev->dev; |
---|
1287 | 1611 | struct rkvdec2_dev *dec = NULL; |
---|
.. | .. |
---|
1289 | 1613 | const struct of_device_id *match = NULL; |
---|
1290 | 1614 | int ret = 0; |
---|
1291 | 1615 | |
---|
1292 | | - dev_info(dev, "probing start\n"); |
---|
1293 | 1616 | dec = devm_kzalloc(dev, sizeof(*dec), GFP_KERNEL); |
---|
1294 | 1617 | if (!dec) |
---|
1295 | 1618 | return -ENOMEM; |
---|
1296 | 1619 | |
---|
1297 | 1620 | mpp = &dec->mpp; |
---|
1298 | | - platform_set_drvdata(pdev, dec); |
---|
| 1621 | + platform_set_drvdata(pdev, mpp); |
---|
1299 | 1622 | |
---|
1300 | 1623 | if (pdev->dev.of_node) { |
---|
1301 | 1624 | match = of_match_node(mpp_rkvdec2_dt_match, pdev->dev.of_node); |
---|
.. | .. |
---|
1336 | 1659 | rkvdec2_link_procfs_init(mpp); |
---|
1337 | 1660 | /* register current device to mpp service */ |
---|
1338 | 1661 | mpp_dev_register_srv(mpp, mpp->srv); |
---|
| 1662 | + |
---|
| 1663 | + return ret; |
---|
| 1664 | +} |
---|
| 1665 | + |
---|
| 1666 | +static int rkvdec2_probe(struct platform_device *pdev) |
---|
| 1667 | +{ |
---|
| 1668 | + int ret; |
---|
| 1669 | + struct device *dev = &pdev->dev; |
---|
| 1670 | + struct device_node *np = dev->of_node; |
---|
| 1671 | + |
---|
| 1672 | + dev_info(dev, "%s, probing start\n", np->name); |
---|
| 1673 | + |
---|
| 1674 | + if (strstr(np->name, "ccu")) |
---|
| 1675 | + ret = rkvdec2_ccu_probe(pdev); |
---|
| 1676 | + else if (strstr(np->name, "core")) |
---|
| 1677 | + ret = rkvdec2_core_probe(pdev); |
---|
| 1678 | + else |
---|
| 1679 | + ret = rkvdec2_probe_default(pdev); |
---|
| 1680 | + |
---|
1339 | 1681 | dev_info(dev, "probing finish\n"); |
---|
1340 | 1682 | |
---|
1341 | | - return 0; |
---|
| 1683 | + return ret; |
---|
1342 | 1684 | } |
---|
1343 | 1685 | |
---|
1344 | 1686 | static int rkvdec2_free_rcbbuf(struct platform_device *pdev, struct rkvdec2_dev *dec) |
---|
.. | .. |
---|
1347 | 1689 | |
---|
1348 | 1690 | if (dec->rcb_page) { |
---|
1349 | 1691 | size_t page_size = PAGE_ALIGN(dec->rcb_size - dec->sram_size); |
---|
| 1692 | + int order = min(get_order(page_size), MAX_ORDER); |
---|
1350 | 1693 | |
---|
1351 | | - __free_pages(dec->rcb_page, get_order(page_size)); |
---|
| 1694 | + __free_pages(dec->rcb_page, order); |
---|
1352 | 1695 | } |
---|
1353 | 1696 | if (dec->rcb_iova) { |
---|
1354 | 1697 | domain = dec->mpp.iommu_info->domain; |
---|
.. | .. |
---|
1361 | 1704 | static int rkvdec2_remove(struct platform_device *pdev) |
---|
1362 | 1705 | { |
---|
1363 | 1706 | struct device *dev = &pdev->dev; |
---|
1364 | | - struct rkvdec2_dev *dec = platform_get_drvdata(pdev); |
---|
1365 | 1707 | |
---|
1366 | | - dev_info(dev, "remove device\n"); |
---|
1367 | | - rkvdec2_free_rcbbuf(pdev, dec); |
---|
1368 | | - mpp_dev_remove(&dec->mpp); |
---|
1369 | | - rkvdec2_procfs_remove(&dec->mpp); |
---|
1370 | | - rkvdec2_link_remove(&dec->mpp, dec->link_dec); |
---|
| 1708 | + if (strstr(dev_name(dev), "ccu")) { |
---|
| 1709 | + dev_info(dev, "remove ccu device\n"); |
---|
| 1710 | + rkvdec2_ccu_remove(dev); |
---|
| 1711 | + } else { |
---|
| 1712 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1713 | + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); |
---|
| 1714 | + |
---|
| 1715 | + dev_info(dev, "remove device\n"); |
---|
| 1716 | + if (dec->mmu_base) { |
---|
| 1717 | + iounmap(dec->mmu_base); |
---|
| 1718 | + dec->mmu_base = NULL; |
---|
| 1719 | + } |
---|
| 1720 | + rkvdec2_free_rcbbuf(pdev, dec); |
---|
| 1721 | + mpp_dev_remove(mpp); |
---|
| 1722 | + rkvdec2_procfs_remove(mpp); |
---|
| 1723 | + rkvdec2_link_remove(mpp, dec->link_dec); |
---|
| 1724 | + } |
---|
1371 | 1725 | |
---|
1372 | 1726 | return 0; |
---|
1373 | 1727 | } |
---|
1374 | 1728 | |
---|
1375 | 1729 | static void rkvdec2_shutdown(struct platform_device *pdev) |
---|
1376 | 1730 | { |
---|
1377 | | - int ret; |
---|
1378 | | - int val; |
---|
1379 | 1731 | struct device *dev = &pdev->dev; |
---|
1380 | | - struct rkvdec2_dev *dec = platform_get_drvdata(pdev); |
---|
1381 | | - struct mpp_dev *mpp = &dec->mpp; |
---|
1382 | 1732 | |
---|
1383 | | - dev_info(dev, "shutdown device\n"); |
---|
1384 | | - |
---|
1385 | | - atomic_inc(&mpp->srv->shutdown_request); |
---|
1386 | | - ret = readx_poll_timeout(atomic_read, |
---|
1387 | | - &mpp->task_count, |
---|
1388 | | - val, val == 0, 20000, 200000); |
---|
1389 | | - if (ret == -ETIMEDOUT) |
---|
1390 | | - dev_err(dev, "wait total running time out\n"); |
---|
| 1733 | + if (!strstr(dev_name(dev), "ccu")) |
---|
| 1734 | + mpp_dev_shutdown(pdev); |
---|
1391 | 1735 | } |
---|
| 1736 | + |
---|
| 1737 | +static int __maybe_unused rkvdec2_runtime_suspend(struct device *dev) |
---|
| 1738 | +{ |
---|
| 1739 | + if (strstr(dev_name(dev), "ccu")) { |
---|
| 1740 | + struct rkvdec2_ccu *ccu = dev_get_drvdata(dev); |
---|
| 1741 | + |
---|
| 1742 | + mpp_clk_safe_disable(ccu->aclk_info.clk); |
---|
| 1743 | + } else { |
---|
| 1744 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1745 | + |
---|
| 1746 | + if (mpp->is_irq_startup) { |
---|
| 1747 | + /* disable core irq */ |
---|
| 1748 | + disable_irq(mpp->irq); |
---|
| 1749 | + if (mpp->iommu_info && mpp->iommu_info->got_irq) |
---|
| 1750 | + /* disable mmu irq */ |
---|
| 1751 | + disable_irq(mpp->iommu_info->irq); |
---|
| 1752 | + } |
---|
| 1753 | + |
---|
| 1754 | + if (mpp->hw_ops->clk_off) |
---|
| 1755 | + mpp->hw_ops->clk_off(mpp); |
---|
| 1756 | + } |
---|
| 1757 | + |
---|
| 1758 | + return 0; |
---|
| 1759 | +} |
---|
| 1760 | + |
---|
| 1761 | +static int __maybe_unused rkvdec2_runtime_resume(struct device *dev) |
---|
| 1762 | +{ |
---|
| 1763 | + if (strstr(dev_name(dev), "ccu")) { |
---|
| 1764 | + struct rkvdec2_ccu *ccu = dev_get_drvdata(dev); |
---|
| 1765 | + |
---|
| 1766 | + mpp_clk_safe_enable(ccu->aclk_info.clk); |
---|
| 1767 | + } else { |
---|
| 1768 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 1769 | + |
---|
| 1770 | + if (mpp->hw_ops->clk_on) |
---|
| 1771 | + mpp->hw_ops->clk_on(mpp); |
---|
| 1772 | + if (mpp->is_irq_startup) { |
---|
| 1773 | + /* enable core irq */ |
---|
| 1774 | + enable_irq(mpp->irq); |
---|
| 1775 | + /* enable mmu irq */ |
---|
| 1776 | + if (mpp->iommu_info && mpp->iommu_info->got_irq) |
---|
| 1777 | + enable_irq(mpp->iommu_info->irq); |
---|
| 1778 | + } |
---|
| 1779 | + |
---|
| 1780 | + } |
---|
| 1781 | + |
---|
| 1782 | + return 0; |
---|
| 1783 | +} |
---|
| 1784 | + |
---|
| 1785 | +static const struct dev_pm_ops rkvdec2_pm_ops = { |
---|
| 1786 | + SET_RUNTIME_PM_OPS(rkvdec2_runtime_suspend, rkvdec2_runtime_resume, NULL) |
---|
| 1787 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
---|
| 1788 | +}; |
---|
1392 | 1789 | |
---|
1393 | 1790 | struct platform_driver rockchip_rkvdec2_driver = { |
---|
1394 | 1791 | .probe = rkvdec2_probe, |
---|
.. | .. |
---|
1397 | 1794 | .driver = { |
---|
1398 | 1795 | .name = RKVDEC_DRIVER_NAME, |
---|
1399 | 1796 | .of_match_table = of_match_ptr(mpp_rkvdec2_dt_match), |
---|
| 1797 | + .pm = &rkvdec2_pm_ops, |
---|
1400 | 1798 | }, |
---|
1401 | 1799 | }; |
---|
1402 | 1800 | EXPORT_SYMBOL(rockchip_rkvdec2_driver); |
---|