1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3 * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4 *
5 * author:
6 * Alpha Lin, alpha.lin@rock-chips.com
7 * Randy Li, randy.li@rock-chips.com
8 * Ding Wei, leo.ding@rock-chips.com
9 *
10 */
11 #include <asm/cacheflush.h>
12 #include <linux/delay.h>
13 #include <linux/iopoll.h>
14 #include <linux/interrupt.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/of_platform.h>
18 #include <linux/slab.h>
19 #include <linux/seq_file.h>
20 #include <linux/uaccess.h>
21 #include <linux/regmap.h>
22 #include <linux/proc_fs.h>
23 #include <linux/nospec.h>
24 #include <soc/rockchip/pm_domains.h>
25
26 #include "mpp_debug.h"
27 #include "mpp_common.h"
28 #include "mpp_iommu.h"
29
30 #define VEPU1_DRIVER_NAME "mpp_vepu1"
31
32 #define VEPU1_SESSION_MAX_BUFFERS 20
33 /* The maximum registers number of all the version */
34 #define VEPU1_REG_NUM 164
35 #define VEPU1_REG_HW_ID_INDEX 0
36 #define VEPU1_REG_START_INDEX 0
37 #define VEPU1_REG_END_INDEX 163
38
39 #define VEPU1_REG_INT 0x004
40 #define VEPU1_REG_INT_INDEX (1)
41 #define VEPU1_INT_SLICE BIT(8)
42 #define VEPU1_INT_TIMEOUT BIT(6)
43 #define VEPU1_INT_BUF_FULL BIT(5)
44 #define VEPU1_INT_RESET BIT(4)
45 #define VEPU1_INT_BUS_ERROR BIT(3)
46 #define VEPU1_INT_RDY BIT(2)
47 #define VEPU1_IRQ_DIS BIT(1)
48 #define VEPU1_INT_RAW BIT(0)
49
50 #define VEPU1_REG_ENC_EN 0x038
51 #define VEPU1_REG_ENC_EN_INDEX (14)
52 #define VEPU1_INT_TIMEOUT_EN BIT(31)
53 #define VEPU1_INT_SLICE_EN BIT(28)
54 #define VEPU1_ENC_START BIT(0)
55
56 #define VEPU1_GET_FORMAT(x) (((x) >> 1) & 0x3)
57 #define VEPU1_FORMAT_MASK (0x06)
58
59 #define VEPU1_FMT_RESERVED (0)
60 #define VEPU1_FMT_VP8E (1)
61 #define VEPU1_FMT_JPEGE (2)
62 #define VEPU1_FMT_H264E (3)
63
64 #define VEPU1_REG_CLR_CACHE_BASE 0xc10
65
66 #define to_vepu_task(task) \
67 container_of(task, struct vepu_task, mpp_task)
68 #define to_vepu_dev(dev) \
69 container_of(dev, struct vepu_dev, mpp)
70
71 struct vepu_task {
72 struct mpp_task mpp_task;
73
74 enum MPP_CLOCK_MODE clk_mode;
75 u32 reg[VEPU1_REG_NUM];
76
77 struct reg_offset_info off_inf;
78 u32 irq_status;
79 /* req for current task */
80 u32 w_req_cnt;
81 struct mpp_request w_reqs[MPP_MAX_MSG_NUM];
82 u32 r_req_cnt;
83 struct mpp_request r_reqs[MPP_MAX_MSG_NUM];
84 };
85
86 struct vepu_session_priv {
87 struct rw_semaphore rw_sem;
88 /* codec info from user */
89 struct {
90 /* show mode */
91 u32 flag;
92 /* item data */
93 u64 val;
94 } codec_info[ENC_INFO_BUTT];
95 };
96
97 struct vepu_dev {
98 struct mpp_dev mpp;
99
100 struct mpp_clk_info aclk_info;
101 struct mpp_clk_info hclk_info;
102 #ifdef CONFIG_ROCKCHIP_MPP_PROC_FS
103 struct proc_dir_entry *procfs;
104 #endif
105 struct reset_control *rst_a;
106 struct reset_control *rst_h;
107 };
108
109 static struct mpp_hw_info vepu_v1_hw_info = {
110 .reg_num = VEPU1_REG_NUM,
111 .reg_id = VEPU1_REG_HW_ID_INDEX,
112 .reg_start = VEPU1_REG_START_INDEX,
113 .reg_end = VEPU1_REG_END_INDEX,
114 .reg_en = VEPU1_REG_ENC_EN_INDEX,
115 };
116
117 /*
118 * file handle translate information
119 */
120 static const u16 trans_tbl_default[] = {
121 5, 6, 7, 8, 9, 10, 11, 12, 13, 51
122 };
123
124 static const u16 trans_tbl_vp8e[] = {
125 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 26, 51, 52, 58, 59, 71
126 };
127
128 static struct mpp_trans_info trans_rk_vepu1[] = {
129 [VEPU1_FMT_RESERVED] = {
130 .count = 0,
131 .table = NULL,
132 },
133 [VEPU1_FMT_VP8E] = {
134 .count = ARRAY_SIZE(trans_tbl_vp8e),
135 .table = trans_tbl_vp8e,
136 },
137 [VEPU1_FMT_JPEGE] = {
138 .count = ARRAY_SIZE(trans_tbl_default),
139 .table = trans_tbl_default,
140 },
141 [VEPU1_FMT_H264E] = {
142 .count = ARRAY_SIZE(trans_tbl_default),
143 .table = trans_tbl_default,
144 },
145 };
146
vepu_process_reg_fd(struct mpp_session * session,struct vepu_task * task,struct mpp_task_msgs * msgs)147 static int vepu_process_reg_fd(struct mpp_session *session,
148 struct vepu_task *task,
149 struct mpp_task_msgs *msgs)
150 {
151 int ret = 0;
152 int fmt = VEPU1_GET_FORMAT(task->reg[VEPU1_REG_ENC_EN_INDEX]);
153
154 ret = mpp_translate_reg_address(session, &task->mpp_task,
155 fmt, task->reg, &task->off_inf);
156 if (ret)
157 return ret;
158
159 mpp_translate_reg_offset_info(&task->mpp_task,
160 &task->off_inf, task->reg);
161
162 return 0;
163 }
164
vepu_extract_task_msg(struct vepu_task * task,struct mpp_task_msgs * msgs)165 static int vepu_extract_task_msg(struct vepu_task *task,
166 struct mpp_task_msgs *msgs)
167 {
168 u32 i;
169 int ret;
170 struct mpp_request *req;
171 struct mpp_hw_info *hw_info = task->mpp_task.hw_info;
172
173 for (i = 0; i < msgs->req_cnt; i++) {
174 u32 off_s, off_e;
175
176 req = &msgs->reqs[i];
177 if (!req->size)
178 continue;
179
180 switch (req->cmd) {
181 case MPP_CMD_SET_REG_WRITE: {
182 off_s = hw_info->reg_start * sizeof(u32);
183 off_e = hw_info->reg_end * sizeof(u32);
184 ret = mpp_check_req(req, 0, sizeof(task->reg),
185 off_s, off_e);
186 if (ret)
187 continue;
188 if (copy_from_user((u8 *)task->reg + req->offset,
189 req->data, req->size)) {
190 mpp_err("copy_from_user reg failed\n");
191 return -EIO;
192 }
193 memcpy(&task->w_reqs[task->w_req_cnt++],
194 req, sizeof(*req));
195 } break;
196 case MPP_CMD_SET_REG_READ: {
197 off_s = hw_info->reg_start * sizeof(u32);
198 off_e = hw_info->reg_end * sizeof(u32);
199 ret = mpp_check_req(req, 0, sizeof(task->reg),
200 off_s, off_e);
201 if (ret)
202 continue;
203 memcpy(&task->r_reqs[task->r_req_cnt++],
204 req, sizeof(*req));
205 } break;
206 case MPP_CMD_SET_REG_ADDR_OFFSET: {
207 mpp_extract_reg_offset_info(&task->off_inf, req);
208 } break;
209 default:
210 break;
211 }
212 }
213 mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n",
214 task->w_req_cnt, task->r_req_cnt);
215
216 return 0;
217 }
218
vepu_alloc_task(struct mpp_session * session,struct mpp_task_msgs * msgs)219 static void *vepu_alloc_task(struct mpp_session *session,
220 struct mpp_task_msgs *msgs)
221 {
222 int ret;
223 struct mpp_task *mpp_task = NULL;
224 struct vepu_task *task = NULL;
225 struct mpp_dev *mpp = session->mpp;
226
227 mpp_debug_enter();
228
229 task = kzalloc(sizeof(*task), GFP_KERNEL);
230 if (!task)
231 return NULL;
232
233 mpp_task = &task->mpp_task;
234 mpp_task_init(session, mpp_task);
235 mpp_task->hw_info = mpp->var->hw_info;
236 mpp_task->reg = task->reg;
237 /* extract reqs for current task */
238 ret = vepu_extract_task_msg(task, msgs);
239 if (ret)
240 goto fail;
241 /* process fd in register */
242 if (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) {
243 ret = vepu_process_reg_fd(session, task, msgs);
244 if (ret)
245 goto fail;
246 }
247 task->clk_mode = CLK_MODE_NORMAL;
248
249 mpp_debug_leave();
250
251 return mpp_task;
252
253 fail:
254 mpp_task_dump_mem_region(mpp, mpp_task);
255 mpp_task_dump_reg(mpp, mpp_task);
256 mpp_task_finalize(session, mpp_task);
257 kfree(task);
258 return NULL;
259 }
260
vepu_run(struct mpp_dev * mpp,struct mpp_task * mpp_task)261 static int vepu_run(struct mpp_dev *mpp,
262 struct mpp_task *mpp_task)
263 {
264 u32 i;
265 u32 reg_en;
266 struct vepu_task *task = to_vepu_task(mpp_task);
267 u32 timing_en = mpp->srv->timing_en;
268
269 mpp_debug_enter();
270
271 /* clear cache */
272 mpp_write_relaxed(mpp, VEPU1_REG_CLR_CACHE_BASE, 1);
273 /* set registers for hardware */
274 reg_en = mpp_task->hw_info->reg_en;
275 /* First, flush correct encoder format */
276 mpp_write_relaxed(mpp, VEPU1_REG_ENC_EN,
277 task->reg[reg_en] & VEPU1_FORMAT_MASK);
278 /* Second, flush others register */
279 for (i = 0; i < task->w_req_cnt; i++) {
280 struct mpp_request *req = &task->w_reqs[i];
281 int s = req->offset / sizeof(u32);
282 int e = s + req->size / sizeof(u32);
283
284 mpp_write_req(mpp, task->reg, s, e, reg_en);
285 }
286
287 /* flush tlb before starting hardware */
288 mpp_iommu_flush_tlb(mpp->iommu_info);
289
290 /* init current task */
291 mpp->cur_task = mpp_task;
292
293 mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY);
294
295 /* Last, flush start registers */
296 wmb();
297 mpp_write(mpp, VEPU1_REG_ENC_EN,
298 task->reg[reg_en] | VEPU1_ENC_START);
299
300 mpp_task_run_end(mpp_task, timing_en);
301
302 mpp_debug_leave();
303
304 return 0;
305 }
306
vepu_irq(struct mpp_dev * mpp)307 static int vepu_irq(struct mpp_dev *mpp)
308 {
309 mpp->irq_status = mpp_read(mpp, VEPU1_REG_INT);
310 if (!(mpp->irq_status & VEPU1_INT_RAW))
311 return IRQ_NONE;
312
313 mpp_write(mpp, VEPU1_REG_INT, 0);
314
315 return IRQ_WAKE_THREAD;
316 }
317
vepu_isr(struct mpp_dev * mpp)318 static int vepu_isr(struct mpp_dev *mpp)
319 {
320 u32 err_mask;
321 struct vepu_task *task = NULL;
322 struct mpp_task *mpp_task = mpp->cur_task;
323
324 /* FIXME use a spin lock here */
325 if (!mpp_task) {
326 dev_err(mpp->dev, "no current task\n");
327 return IRQ_HANDLED;
328 }
329 mpp_time_diff(mpp_task);
330 mpp->cur_task = NULL;
331 task = to_vepu_task(mpp_task);
332 task->irq_status = mpp->irq_status;
333 mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n",
334 task->irq_status);
335
336 err_mask = VEPU1_INT_TIMEOUT
337 | VEPU1_INT_BUF_FULL
338 | VEPU1_INT_BUS_ERROR;
339
340 if (err_mask & task->irq_status)
341 atomic_inc(&mpp->reset_request);
342
343 mpp_task_finish(mpp_task->session, mpp_task);
344
345 mpp_debug_leave();
346 return IRQ_HANDLED;
347 }
348
vepu_finish(struct mpp_dev * mpp,struct mpp_task * mpp_task)349 static int vepu_finish(struct mpp_dev *mpp,
350 struct mpp_task *mpp_task)
351 {
352 u32 i;
353 u32 s, e;
354 struct mpp_request *req;
355 struct vepu_task *task = to_vepu_task(mpp_task);
356
357 mpp_debug_enter();
358
359 /* read register after running */
360 for (i = 0; i < task->r_req_cnt; i++) {
361 req = &task->r_reqs[i];
362 s = req->offset / sizeof(u32);
363 e = s + req->size / sizeof(u32);
364 mpp_read_req(mpp, task->reg, s, e);
365 }
366 /* revert hack for irq status */
367 task->reg[VEPU1_REG_INT_INDEX] = task->irq_status;
368
369 mpp_debug_leave();
370
371 return 0;
372 }
373
vepu_result(struct mpp_dev * mpp,struct mpp_task * mpp_task,struct mpp_task_msgs * msgs)374 static int vepu_result(struct mpp_dev *mpp,
375 struct mpp_task *mpp_task,
376 struct mpp_task_msgs *msgs)
377 {
378 u32 i;
379 struct mpp_request *req;
380 struct vepu_task *task = to_vepu_task(mpp_task);
381
382 /* FIXME may overflow the kernel */
383 for (i = 0; i < task->r_req_cnt; i++) {
384 req = &task->r_reqs[i];
385
386 if (copy_to_user(req->data,
387 (u8 *)task->reg + req->offset,
388 req->size)) {
389 mpp_err("copy_to_user reg fail\n");
390 return -EIO;
391 }
392 }
393 return 0;
394 }
395
vepu_free_task(struct mpp_session * session,struct mpp_task * mpp_task)396 static int vepu_free_task(struct mpp_session *session,
397 struct mpp_task *mpp_task)
398 {
399 struct vepu_task *task = to_vepu_task(mpp_task);
400
401 mpp_task_finalize(session, mpp_task);
402 kfree(task);
403
404 return 0;
405 }
406
vepu_control(struct mpp_session * session,struct mpp_request * req)407 static int vepu_control(struct mpp_session *session, struct mpp_request *req)
408 {
409 switch (req->cmd) {
410 case MPP_CMD_SEND_CODEC_INFO: {
411 int i;
412 int cnt;
413 struct codec_info_elem elem;
414 struct vepu_session_priv *priv;
415
416 if (!session || !session->priv) {
417 mpp_err("session info null\n");
418 return -EINVAL;
419 }
420 priv = session->priv;
421
422 cnt = req->size / sizeof(elem);
423 cnt = (cnt > ENC_INFO_BUTT) ? ENC_INFO_BUTT : cnt;
424 mpp_debug(DEBUG_IOCTL, "codec info count %d\n", cnt);
425 down_write(&priv->rw_sem);
426 for (i = 0; i < cnt; i++) {
427 if (copy_from_user(&elem, req->data + i * sizeof(elem), sizeof(elem))) {
428 mpp_err("copy_from_user failed\n");
429 continue;
430 }
431 if (elem.type > ENC_INFO_BASE && elem.type < ENC_INFO_BUTT &&
432 elem.flag > CODEC_INFO_FLAG_NULL && elem.flag < CODEC_INFO_FLAG_BUTT) {
433 elem.type = array_index_nospec(elem.type, ENC_INFO_BUTT);
434 priv->codec_info[elem.type].flag = elem.flag;
435 priv->codec_info[elem.type].val = elem.data;
436 } else {
437 mpp_err("codec info invalid, type %d, flag %d\n",
438 elem.type, elem.flag);
439 }
440 }
441 up_write(&priv->rw_sem);
442 } break;
443 default: {
444 mpp_err("unknown mpp ioctl cmd %x\n", req->cmd);
445 } break;
446 }
447
448 return 0;
449 }
450
vepu_free_session(struct mpp_session * session)451 static int vepu_free_session(struct mpp_session *session)
452 {
453 if (session && session->priv) {
454 kfree(session->priv);
455 session->priv = NULL;
456 }
457
458 return 0;
459 }
460
vepu_init_session(struct mpp_session * session)461 static int vepu_init_session(struct mpp_session *session)
462 {
463 struct vepu_session_priv *priv;
464
465 if (!session) {
466 mpp_err("session is null\n");
467 return -EINVAL;
468 }
469
470 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
471 if (!priv)
472 return -ENOMEM;
473
474 init_rwsem(&priv->rw_sem);
475 session->priv = priv;
476
477 return 0;
478 }
479
480 #ifdef CONFIG_ROCKCHIP_MPP_PROC_FS
vepu_procfs_remove(struct mpp_dev * mpp)481 static int vepu_procfs_remove(struct mpp_dev *mpp)
482 {
483 struct vepu_dev *enc = to_vepu_dev(mpp);
484
485 if (enc->procfs) {
486 proc_remove(enc->procfs);
487 enc->procfs = NULL;
488 }
489
490 return 0;
491 }
492
vepu_dump_session(struct mpp_session * session,struct seq_file * seq)493 static int vepu_dump_session(struct mpp_session *session, struct seq_file *seq)
494 {
495 int i;
496 struct vepu_session_priv *priv = session->priv;
497
498 down_read(&priv->rw_sem);
499 /* item name */
500 seq_puts(seq, "------------------------------------------------------");
501 seq_puts(seq, "------------------------------------------------------\n");
502 seq_printf(seq, "|%8s|", (const char *)"session");
503 seq_printf(seq, "%8s|", (const char *)"device");
504 for (i = ENC_INFO_BASE; i < ENC_INFO_BUTT; i++) {
505 bool show = priv->codec_info[i].flag;
506
507 if (show)
508 seq_printf(seq, "%8s|", enc_info_item_name[i]);
509 }
510 seq_puts(seq, "\n");
511 /* item data*/
512 seq_printf(seq, "|%8d|", session->index);
513 seq_printf(seq, "%8s|", mpp_device_name[session->device_type]);
514 for (i = ENC_INFO_BASE; i < ENC_INFO_BUTT; i++) {
515 u32 flag = priv->codec_info[i].flag;
516
517 if (!flag)
518 continue;
519 if (flag == CODEC_INFO_FLAG_NUMBER) {
520 u32 data = priv->codec_info[i].val;
521
522 seq_printf(seq, "%8d|", data);
523 } else if (flag == CODEC_INFO_FLAG_STRING) {
524 const char *name = (const char *)&priv->codec_info[i].val;
525
526 seq_printf(seq, "%8s|", name);
527 } else {
528 seq_printf(seq, "%8s|", (const char *)"null");
529 }
530 }
531 seq_puts(seq, "\n");
532 up_read(&priv->rw_sem);
533
534 return 0;
535 }
536
vepu_show_session_info(struct seq_file * seq,void * offset)537 static int vepu_show_session_info(struct seq_file *seq, void *offset)
538 {
539 struct mpp_session *session = NULL, *n;
540 struct mpp_dev *mpp = seq->private;
541
542 mutex_lock(&mpp->srv->session_lock);
543 list_for_each_entry_safe(session, n,
544 &mpp->srv->session_list,
545 service_link) {
546 if (session->device_type != MPP_DEVICE_VEPU1)
547 continue;
548 if (!session->priv)
549 continue;
550 if (mpp->dev_ops->dump_session)
551 mpp->dev_ops->dump_session(session, seq);
552 }
553 mutex_unlock(&mpp->srv->session_lock);
554
555 return 0;
556 }
557
vepu_procfs_init(struct mpp_dev * mpp)558 static int vepu_procfs_init(struct mpp_dev *mpp)
559 {
560 struct vepu_dev *enc = to_vepu_dev(mpp);
561
562 enc->procfs = proc_mkdir(mpp->dev->of_node->name, mpp->srv->procfs);
563 if (IS_ERR_OR_NULL(enc->procfs)) {
564 mpp_err("failed on open procfs\n");
565 enc->procfs = NULL;
566 return -EIO;
567 }
568
569 /* for common mpp_dev options */
570 mpp_procfs_create_common(enc->procfs, mpp);
571
572 mpp_procfs_create_u32("aclk", 0644,
573 enc->procfs, &enc->aclk_info.debug_rate_hz);
574 mpp_procfs_create_u32("session_buffers", 0644,
575 enc->procfs, &mpp->session_max_buffers);
576 /* for show session info */
577 proc_create_single_data("sessions-info", 0444,
578 enc->procfs, vepu_show_session_info, mpp);
579
580 return 0;
581 }
582 #else
vepu_procfs_remove(struct mpp_dev * mpp)583 static inline int vepu_procfs_remove(struct mpp_dev *mpp)
584 {
585 return 0;
586 }
587
vepu_procfs_init(struct mpp_dev * mpp)588 static inline int vepu_procfs_init(struct mpp_dev *mpp)
589 {
590 return 0;
591 }
592
vepu_dump_session(struct mpp_session * session,struct seq_file * seq)593 static inline int vepu_dump_session(struct mpp_session *session, struct seq_file *seq)
594 {
595 return 0;
596 }
597 #endif
598
vepu_init(struct mpp_dev * mpp)599 static int vepu_init(struct mpp_dev *mpp)
600 {
601 int ret;
602 struct vepu_dev *enc = to_vepu_dev(mpp);
603
604 mpp->grf_info = &mpp->srv->grf_infos[MPP_DRIVER_VEPU1];
605
606 /* Get clock info from dtsi */
607 ret = mpp_get_clk_info(mpp, &enc->aclk_info, "aclk_vcodec");
608 if (ret)
609 mpp_err("failed on clk_get aclk_vcodec\n");
610 ret = mpp_get_clk_info(mpp, &enc->hclk_info, "hclk_vcodec");
611 if (ret)
612 mpp_err("failed on clk_get hclk_vcodec\n");
613 /* Set default rates */
614 mpp_set_clk_info_rate_hz(&enc->aclk_info, CLK_MODE_DEFAULT, 300 * MHZ);
615
616 /* Get reset control from dtsi */
617 enc->rst_a = mpp_reset_control_get(mpp, RST_TYPE_A, "video_a");
618 if (!enc->rst_a)
619 mpp_err("No aclk reset resource define\n");
620 enc->rst_h = mpp_reset_control_get(mpp, RST_TYPE_H, "video_h");
621 if (!enc->rst_h)
622 mpp_err("No hclk reset resource define\n");
623
624 return 0;
625 }
626
vepu_clk_on(struct mpp_dev * mpp)627 static int vepu_clk_on(struct mpp_dev *mpp)
628 {
629 struct vepu_dev *enc = to_vepu_dev(mpp);
630
631 mpp_clk_safe_enable(enc->aclk_info.clk);
632 mpp_clk_safe_enable(enc->hclk_info.clk);
633
634 return 0;
635 }
636
vepu_clk_off(struct mpp_dev * mpp)637 static int vepu_clk_off(struct mpp_dev *mpp)
638 {
639 struct vepu_dev *enc = to_vepu_dev(mpp);
640
641 mpp_clk_safe_disable(enc->aclk_info.clk);
642 mpp_clk_safe_disable(enc->hclk_info.clk);
643
644 return 0;
645 }
646
vepu_set_freq(struct mpp_dev * mpp,struct mpp_task * mpp_task)647 static int vepu_set_freq(struct mpp_dev *mpp,
648 struct mpp_task *mpp_task)
649 {
650 struct vepu_dev *enc = to_vepu_dev(mpp);
651 struct vepu_task *task = to_vepu_task(mpp_task);
652
653 mpp_clk_set_rate(&enc->aclk_info, task->clk_mode);
654
655 return 0;
656 }
657
vepu_reduce_freq(struct mpp_dev * mpp)658 static int vepu_reduce_freq(struct mpp_dev *mpp)
659 {
660 struct vepu_dev *enc = to_vepu_dev(mpp);
661
662 mpp_clk_set_rate(&enc->aclk_info, CLK_MODE_REDUCE);
663
664 return 0;
665 }
666
vepu_reset(struct mpp_dev * mpp)667 static int vepu_reset(struct mpp_dev *mpp)
668 {
669 struct vepu_dev *enc = to_vepu_dev(mpp);
670
671 if (enc->rst_a && enc->rst_h) {
672 /* Don't skip this or iommu won't work after reset */
673 mpp_pmu_idle_request(mpp, true);
674 mpp_safe_reset(enc->rst_a);
675 mpp_safe_reset(enc->rst_h);
676 udelay(5);
677 mpp_safe_unreset(enc->rst_a);
678 mpp_safe_unreset(enc->rst_h);
679 mpp_pmu_idle_request(mpp, false);
680 }
681 mpp_write(mpp, VEPU1_REG_ENC_EN, 0);
682
683 return 0;
684 }
685
686 static struct mpp_hw_ops vepu_v1_hw_ops = {
687 .init = vepu_init,
688 .clk_on = vepu_clk_on,
689 .clk_off = vepu_clk_off,
690 .set_freq = vepu_set_freq,
691 .reduce_freq = vepu_reduce_freq,
692 .reset = vepu_reset,
693 };
694
695 static struct mpp_dev_ops vepu_v1_dev_ops = {
696 .alloc_task = vepu_alloc_task,
697 .run = vepu_run,
698 .irq = vepu_irq,
699 .isr = vepu_isr,
700 .finish = vepu_finish,
701 .result = vepu_result,
702 .free_task = vepu_free_task,
703 .ioctl = vepu_control,
704 .init_session = vepu_init_session,
705 .free_session = vepu_free_session,
706 .dump_session = vepu_dump_session,
707 };
708
709 static const struct mpp_dev_var vepu_v1_data = {
710 .device_type = MPP_DEVICE_VEPU1,
711 .hw_info = &vepu_v1_hw_info,
712 .trans_info = trans_rk_vepu1,
713 .hw_ops = &vepu_v1_hw_ops,
714 .dev_ops = &vepu_v1_dev_ops,
715 };
716
717 static const struct of_device_id mpp_vepu1_dt_match[] = {
718 {
719 .compatible = "rockchip,vpu-encoder-v1",
720 .data = &vepu_v1_data,
721 },
722 {},
723 };
724
vepu_probe(struct platform_device * pdev)725 static int vepu_probe(struct platform_device *pdev)
726 {
727 int ret = 0;
728 struct device *dev = &pdev->dev;
729 struct vepu_dev *enc = NULL;
730 struct mpp_dev *mpp = NULL;
731 const struct of_device_id *match = NULL;
732
733 dev_info(dev, "probe device\n");
734 enc = devm_kzalloc(dev, sizeof(struct vepu_dev), GFP_KERNEL);
735 if (!enc)
736 return -ENOMEM;
737
738 mpp = &enc->mpp;
739 platform_set_drvdata(pdev, mpp);
740
741 if (pdev->dev.of_node) {
742 match = of_match_node(mpp_vepu1_dt_match, pdev->dev.of_node);
743 if (match)
744 mpp->var = (struct mpp_dev_var *)match->data;
745
746 mpp->core_id = of_alias_get_id(pdev->dev.of_node, "vepu");
747 }
748
749 ret = mpp_dev_probe(mpp, pdev);
750 if (ret) {
751 dev_err(dev, "probe sub driver failed\n");
752 return -EINVAL;
753 }
754
755 ret = devm_request_threaded_irq(dev, mpp->irq,
756 mpp_dev_irq,
757 mpp_dev_isr_sched,
758 IRQF_SHARED,
759 dev_name(dev), mpp);
760 if (ret) {
761 dev_err(dev, "register interrupter runtime failed\n");
762 return -EINVAL;
763 }
764
765 mpp->session_max_buffers = VEPU1_SESSION_MAX_BUFFERS;
766 vepu_procfs_init(mpp);
767 /* register current device to mpp service */
768 mpp_dev_register_srv(mpp, mpp->srv);
769 dev_info(dev, "probing finish\n");
770
771 return 0;
772 }
773
vepu_remove(struct platform_device * pdev)774 static int vepu_remove(struct platform_device *pdev)
775 {
776 struct device *dev = &pdev->dev;
777 struct mpp_dev *mpp = dev_get_drvdata(dev);
778
779 dev_info(dev, "remove device\n");
780 mpp_dev_remove(mpp);
781 vepu_procfs_remove(mpp);
782
783 return 0;
784 }
785
786 struct platform_driver rockchip_vepu1_driver = {
787 .probe = vepu_probe,
788 .remove = vepu_remove,
789 .shutdown = mpp_dev_shutdown,
790 .driver = {
791 .name = VEPU1_DRIVER_NAME,
792 .of_match_table = of_match_ptr(mpp_vepu1_dt_match),
793 },
794 };
795 EXPORT_SYMBOL(rockchip_vepu1_driver);
796