1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3 * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
4 *
5 * author:
6 * Ding Wei, leo.ding@rock-chips.com
7 * Alpha Lin, alpha.lin@rock-chips.com
8 *
9 */
10 #include <asm/cacheflush.h>
11 #include <linux/delay.h>
12 #include <linux/iopoll.h>
13 #include <linux/interrupt.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/of_platform.h>
17 #include <linux/slab.h>
18 #include <linux/dma-buf.h>
19 #include <linux/uaccess.h>
20 #include <linux/regmap.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/proc_fs.h>
23 #include <soc/rockchip/pm_domains.h>
24
25 #include "rockchip_iep2_regs.h"
26 #include "mpp_debug.h"
27 #include "mpp_common.h"
28 #include "mpp_iommu.h"
29
30 #define IEP2_DRIVER_NAME "mpp-iep2"
31
32 #define IEP2_SESSION_MAX_BUFFERS 20
33
34 #define TILE_WIDTH 16
35 #define TILE_HEIGHT 4
36 #define MVL 28
37 #define MVR 27
38
39 enum rockchip_iep2_fmt {
40 ROCKCHIP_IEP2_FMT_YUV422 = 2,
41 ROCKCHIP_IEP2_FMT_YUV420
42 };
43
44 enum rockchip_iep2_yuv_swap {
45 ROCKCHIP_IEP2_YUV_SWAP_SP_UV,
46 ROCKCHIP_IEP2_YUV_SWAP_SP_VU,
47 ROCKCHIP_IEP2_YUV_SWAP_P0,
48 ROCKCHIP_IEP2_YUV_SWAP_P
49 };
50
51 enum rockchip_iep2_dil_ff_order {
52 ROCKCHIP_IEP2_DIL_FF_ORDER_TB,
53 ROCKCHIP_IEP2_DIL_FF_ORDER_BT
54 };
55
56 enum rockchip_iep2_dil_mode {
57 ROCKCHIP_IEP2_DIL_MODE_DISABLE,
58 ROCKCHIP_IEP2_DIL_MODE_I5O2,
59 ROCKCHIP_IEP2_DIL_MODE_I5O1T,
60 ROCKCHIP_IEP2_DIL_MODE_I5O1B,
61 ROCKCHIP_IEP2_DIL_MODE_I2O2,
62 ROCKCHIP_IEP2_DIL_MODE_I1O1T,
63 ROCKCHIP_IEP2_DIL_MODE_I1O1B,
64 ROCKCHIP_IEP2_DIL_MODE_PD,
65 ROCKCHIP_IEP2_DIL_MODE_BYPASS,
66 ROCKCHIP_IEP2_DIL_MODE_DECT
67 };
68
69 enum ROCKCHIP_IEP2_PD_COMP_FLAG {
70 ROCKCHIP_IEP2_PD_COMP_FLAG_CC,
71 ROCKCHIP_IEP2_PD_COMP_FLAG_CN,
72 ROCKCHIP_IEP2_PD_COMP_FLAG_NC,
73 ROCKCHIP_IEP2_PD_COMP_FLAG_NON
74 };
75
76 /* default iep2 mtn table */
77 static u32 iep2_mtn_tab[] = {
78 0x00000000, 0x00000000, 0x00000000, 0x00000000,
79 0x01010000, 0x06050302, 0x0f0d0a08, 0x1c191512,
80 0x2b282420, 0x3634312e, 0x3d3c3a38, 0x40403f3e,
81 0x40404040, 0x40404040, 0x40404040, 0x40404040
82 };
83
84 #define to_iep_task(task) \
85 container_of(task, struct iep_task, mpp_task)
86 #define to_iep2_dev(dev) \
87 container_of(dev, struct iep2_dev, mpp)
88
89 struct iep2_addr {
90 u32 y;
91 u32 cbcr;
92 u32 cr;
93 };
94
95 struct iep2_params {
96 u32 src_fmt;
97 u32 src_yuv_swap;
98 u32 dst_fmt;
99 u32 dst_yuv_swap;
100 u32 tile_cols;
101 u32 tile_rows;
102 u32 src_y_stride;
103 u32 src_uv_stride;
104 u32 dst_y_stride;
105
106 /* current, previous, next. */
107 struct iep2_addr src[3];
108 struct iep2_addr dst[2];
109 u32 mv_addr;
110 u32 md_addr;
111
112 u32 dil_mode;
113 u32 dil_out_mode;
114 u32 dil_field_order;
115
116 u32 md_theta;
117 u32 md_r;
118 u32 md_lambda;
119
120 u32 dect_resi_thr;
121 u32 osd_area_num;
122 u32 osd_gradh_thr;
123 u32 osd_gradv_thr;
124
125 u32 osd_pos_limit_en;
126 u32 osd_pos_limit_num;
127
128 u32 osd_limit_area[2];
129
130 u32 osd_line_num;
131 u32 osd_pec_thr;
132
133 u32 osd_x_sta[8];
134 u32 osd_x_end[8];
135 u32 osd_y_sta[8];
136 u32 osd_y_end[8];
137
138 u32 me_pena;
139 u32 mv_bonus;
140 u32 mv_similar_thr;
141 u32 mv_similar_num_thr0;
142 s32 me_thr_offset;
143
144 u32 mv_left_limit;
145 u32 mv_right_limit;
146
147 s8 mv_tru_list[8];
148 u32 mv_tru_vld[8];
149
150 u32 eedi_thr0;
151
152 u32 ble_backtoma_num;
153
154 u32 comb_cnt_thr;
155 u32 comb_feature_thr;
156 u32 comb_t_thr;
157 u32 comb_osd_vld[8];
158
159 u32 mtn_en;
160 u32 mtn_tab[16];
161
162 u32 pd_mode;
163
164 u32 roi_en;
165 u32 roi_layer_num;
166 u32 roi_mode[8];
167 u32 xsta[8];
168 u32 xend[8];
169 u32 ysta[8];
170 u32 yend[8];
171 };
172
173 struct iep2_output {
174 u32 mv_hist[MVL + MVR + 1];
175 u32 dect_pd_tcnt;
176 u32 dect_pd_bcnt;
177 u32 dect_ff_cur_tcnt;
178 u32 dect_ff_cur_bcnt;
179 u32 dect_ff_nxt_tcnt;
180 u32 dect_ff_nxt_bcnt;
181 u32 dect_ff_ble_tcnt;
182 u32 dect_ff_ble_bcnt;
183 u32 dect_ff_nz;
184 u32 dect_ff_comb_f;
185 u32 dect_osd_cnt;
186 u32 out_comb_cnt;
187 u32 out_osd_comb_cnt;
188 u32 ff_gradt_tcnt;
189 u32 ff_gradt_bcnt;
190 u32 x_sta[8];
191 u32 x_end[8];
192 u32 y_sta[8];
193 u32 y_end[8];
194 };
195
196 struct iep_task {
197 struct mpp_task mpp_task;
198 struct mpp_hw_info *hw_info;
199
200 enum MPP_CLOCK_MODE clk_mode;
201 struct iep2_params params;
202 struct iep2_output output;
203
204 struct reg_offset_info off_inf;
205 u32 irq_status;
206 /* req for current task */
207 u32 w_req_cnt;
208 struct mpp_request w_reqs[MPP_MAX_MSG_NUM];
209 u32 r_req_cnt;
210 struct mpp_request r_reqs[MPP_MAX_MSG_NUM];
211 };
212
213 struct iep2_dev {
214 struct mpp_dev mpp;
215
216 struct mpp_clk_info aclk_info;
217 struct mpp_clk_info hclk_info;
218 struct mpp_clk_info sclk_info;
219 #ifdef CONFIG_ROCKCHIP_MPP_PROC_FS
220 struct proc_dir_entry *procfs;
221 #endif
222 struct reset_control *rst_a;
223 struct reset_control *rst_h;
224 struct reset_control *rst_s;
225
226 struct mpp_dma_buffer roi;
227 };
228
229 static int iep2_addr_rnum[] = {
230 24, 27, 28, /* src cur */
231 25, 29, 30, /* src nxt */
232 26, 31, 32, /* src prv */
233 44, 46, -1, /* dst top */
234 45, 47, -1, /* dst bot */
235 34, /* mv */
236 33, /* md */
237 };
238
iep2_process_reg_fd(struct mpp_session * session,struct iep_task * task,struct mpp_task_msgs * msgs)239 static int iep2_process_reg_fd(struct mpp_session *session,
240 struct iep_task *task,
241 struct mpp_task_msgs *msgs)
242 {
243 int i;
244 /* see the detail at above table iep2_addr_rnum */
245 int addr_num =
246 ARRAY_SIZE(task->params.src) * 3 +
247 ARRAY_SIZE(task->params.dst) * 3 + 2;
248
249 u32 *paddr = &task->params.src[0].y;
250
251 for (i = 0; i < addr_num; ++i) {
252 int usr_fd;
253 u32 offset;
254 struct mpp_mem_region *mem_region = NULL;
255
256 if (session->msg_flags & MPP_FLAGS_REG_NO_OFFSET) {
257 usr_fd = paddr[i];
258 offset = 0;
259 } else {
260 usr_fd = paddr[i] & 0x3ff;
261 offset = paddr[i] >> 10;
262 }
263
264 if (usr_fd == 0 || iep2_addr_rnum[i] == -1)
265 continue;
266
267 mem_region = mpp_task_attach_fd(&task->mpp_task, usr_fd);
268 if (IS_ERR(mem_region)) {
269 mpp_debug(DEBUG_IOMMU, "reg[%3d]: %08x failed\n",
270 iep2_addr_rnum[i], paddr[i]);
271 return PTR_ERR(mem_region);
272 }
273
274 mem_region->reg_idx = iep2_addr_rnum[i];
275 mpp_debug(DEBUG_IOMMU, "reg[%3d]: %3d => %pad + offset %10d\n",
276 iep2_addr_rnum[i], usr_fd, &mem_region->iova, offset);
277 paddr[i] = mem_region->iova + offset;
278 }
279
280 return 0;
281 }
282
iep2_extract_task_msg(struct iep_task * task,struct mpp_task_msgs * msgs)283 static int iep2_extract_task_msg(struct iep_task *task,
284 struct mpp_task_msgs *msgs)
285 {
286 u32 i;
287 struct mpp_request *req;
288
289 for (i = 0; i < msgs->req_cnt; i++) {
290 req = &msgs->reqs[i];
291 if (!req->size)
292 continue;
293
294 switch (req->cmd) {
295 case MPP_CMD_SET_REG_WRITE: {
296 if (copy_from_user(&task->params,
297 req->data, req->size)) {
298 mpp_err("copy_from_user params failed\n");
299 return -EIO;
300 }
301 } break;
302 case MPP_CMD_SET_REG_READ: {
303 memcpy(&task->r_reqs[task->r_req_cnt++],
304 req, sizeof(*req));
305 } break;
306 case MPP_CMD_SET_REG_ADDR_OFFSET: {
307 mpp_extract_reg_offset_info(&task->off_inf, req);
308 } break;
309 default:
310 break;
311 }
312 }
313 mpp_debug(DEBUG_TASK_INFO, "w_req_cnt %d, r_req_cnt %d\n",
314 task->w_req_cnt, task->r_req_cnt);
315
316 return 0;
317 }
318
iep2_alloc_task(struct mpp_session * session,struct mpp_task_msgs * msgs)319 static void *iep2_alloc_task(struct mpp_session *session,
320 struct mpp_task_msgs *msgs)
321 {
322 int ret;
323 struct iep_task *task = NULL;
324
325 mpp_debug_enter();
326
327 task = kzalloc(sizeof(*task), GFP_KERNEL);
328 if (!task)
329 return NULL;
330
331 mpp_task_init(session, &task->mpp_task);
332 /* extract reqs for current task */
333 ret = iep2_extract_task_msg(task, msgs);
334 if (ret)
335 goto fail;
336 /* process fd in register */
337 if (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) {
338 ret = iep2_process_reg_fd(session, task, msgs);
339 if (ret)
340 goto fail;
341 }
342 task->clk_mode = CLK_MODE_NORMAL;
343
344 mpp_debug_leave();
345
346 return &task->mpp_task;
347
348 fail:
349 mpp_task_finalize(session, &task->mpp_task);
350 kfree(task);
351 return NULL;
352 }
353
iep2_config(struct mpp_dev * mpp,struct iep_task * task)354 static void iep2_config(struct mpp_dev *mpp, struct iep_task *task)
355 {
356 struct iep2_dev *iep = to_iep2_dev(mpp);
357 struct iep2_params *cfg = &task->params;
358 u32 reg;
359 u32 width, height;
360
361 width = cfg->tile_cols * TILE_WIDTH;
362 height = cfg->tile_rows * TILE_HEIGHT;
363
364 reg = IEP2_REG_SRC_FMT(cfg->src_fmt)
365 | IEP2_REG_SRC_YUV_SWAP(cfg->src_yuv_swap)
366 | IEP2_REG_DST_FMT(cfg->dst_fmt)
367 | IEP2_REG_DST_YUV_SWAP(cfg->dst_yuv_swap)
368 | IEP2_REG_DEBUG_DATA_EN;
369 mpp_write_relaxed(mpp, IEP2_REG_IEP_CONFIG0, reg);
370
371 reg = IEP2_REG_SRC_PIC_WIDTH(width - 1)
372 | IEP2_REG_SRC_PIC_HEIGHT(height - 1);
373 mpp_write_relaxed(mpp, IEP2_REG_SRC_IMG_SIZE, reg);
374
375 reg = IEP2_REG_SRC_VIR_Y_STRIDE(cfg->src_y_stride)
376 | IEP2_REG_SRC_VIR_UV_STRIDE(cfg->src_uv_stride);
377 mpp_write_relaxed(mpp, IEP2_REG_VIR_SRC_IMG_WIDTH, reg);
378
379 reg = IEP2_REG_DST_VIR_STRIDE(cfg->dst_y_stride);
380 mpp_write_relaxed(mpp, IEP2_REG_VIR_DST_IMG_WIDTH, reg);
381
382 reg = IEP2_REG_DIL_MV_HIST_EN
383 | IEP2_REG_DIL_COMB_EN
384 | IEP2_REG_DIL_BLE_EN
385 | IEP2_REG_DIL_EEDI_EN
386 | IEP2_REG_DIL_MEMC_EN
387 | IEP2_REG_DIL_OSD_EN
388 | IEP2_REG_DIL_PD_EN
389 | IEP2_REG_DIL_FF_EN
390 | IEP2_REG_DIL_MD_PRE_EN
391 | IEP2_REG_DIL_FIELD_ORDER(cfg->dil_field_order)
392 | IEP2_REG_DIL_OUT_MODE(cfg->dil_out_mode)
393 | IEP2_REG_DIL_MODE(cfg->dil_mode);
394 if (cfg->roi_en)
395 reg |= IEP2_REG_DIL_ROI_EN;
396 mpp_write_relaxed(mpp, IEP2_REG_DIL_CONFIG0, reg);
397
398 if (cfg->dil_mode != ROCKCHIP_IEP2_DIL_MODE_PD) {
399 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_CURY,
400 cfg->src[0].y);
401 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_CURUV,
402 cfg->src[0].cbcr);
403 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_CURV,
404 cfg->src[0].cr);
405
406 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTY,
407 cfg->src[1].y);
408 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTUV,
409 cfg->src[1].cbcr);
410 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTV,
411 cfg->src[1].cr);
412 } else {
413 struct iep2_addr *top, *bot;
414
415 switch (cfg->pd_mode) {
416 default:
417 case ROCKCHIP_IEP2_PD_COMP_FLAG_CC:
418 top = &cfg->src[0];
419 bot = &cfg->src[0];
420 break;
421 case ROCKCHIP_IEP2_PD_COMP_FLAG_CN:
422 top = &cfg->src[0];
423 bot = &cfg->src[1];
424 break;
425 case ROCKCHIP_IEP2_PD_COMP_FLAG_NC:
426 top = &cfg->src[1];
427 bot = &cfg->src[0];
428 break;
429 }
430
431 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_CURY, top->y);
432 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_CURUV, top->cbcr);
433 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_CURV, top->cr);
434 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTY, bot->y);
435 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTUV, bot->cbcr);
436 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_NXTV, bot->cr);
437 }
438
439 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREY, cfg->src[2].y);
440 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREUV, cfg->src[2].cbcr);
441 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_PREV, cfg->src[2].cr);
442
443 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_MD, cfg->md_addr);
444 mpp_write_relaxed(mpp, IEP2_REG_SRC_ADDR_MV, cfg->mv_addr);
445 mpp_write_relaxed(mpp, IEP2_REG_DST_ADDR_MD, cfg->md_addr);
446 mpp_write_relaxed(mpp, IEP2_REG_DST_ADDR_MV, cfg->mv_addr);
447 mpp_write_relaxed(mpp, IEP2_REG_ROI_ADDR, (u32)iep->roi.iova);
448
449 mpp_write_relaxed(mpp, IEP2_REG_DST_ADDR_TOPY, cfg->dst[0].y);
450 mpp_write_relaxed(mpp, IEP2_REG_DST_ADDR_TOPC, cfg->dst[0].cbcr);
451 mpp_write_relaxed(mpp, IEP2_REG_DST_ADDR_BOTY, cfg->dst[1].y);
452 mpp_write_relaxed(mpp, IEP2_REG_DST_ADDR_BOTC, cfg->dst[1].cbcr);
453
454 reg = IEP2_REG_MD_THETA(cfg->md_theta)
455 | IEP2_REG_MD_R(cfg->md_r)
456 | IEP2_REG_MD_LAMBDA(cfg->md_lambda);
457 mpp_write_relaxed(mpp, IEP2_REG_MD_CONFIG0, reg);
458
459 reg = IEP2_REG_DECT_RESI_THR(cfg->dect_resi_thr)
460 | IEP2_REG_OSD_AREA_NUM(cfg->osd_area_num)
461 | IEP2_REG_OSD_GRADH_THR(cfg->osd_gradh_thr)
462 | IEP2_REG_OSD_GRADV_THR(cfg->osd_gradv_thr);
463 mpp_write_relaxed(mpp, IEP2_REG_DECT_CONFIG0, reg);
464
465 reg = IEP2_REG_OSD_POS_LIMIT_NUM(cfg->osd_pos_limit_num);
466 if (cfg->osd_pos_limit_en)
467 reg |= IEP2_REG_OSD_POS_LIMIT_EN;
468 mpp_write_relaxed(mpp, IEP2_REG_OSD_LIMIT_CONFIG, reg);
469
470 mpp_write_relaxed(mpp, IEP2_REG_OSD_LIMIT_AREA(0),
471 cfg->osd_limit_area[0]);
472 mpp_write_relaxed(mpp, IEP2_REG_OSD_LIMIT_AREA(1),
473 cfg->osd_limit_area[1]);
474
475 reg = IEP2_REG_OSD_PEC_THR(cfg->osd_pec_thr)
476 | IEP2_REG_OSD_LINE_NUM(cfg->osd_line_num);
477 mpp_write_relaxed(mpp, IEP2_REG_OSD_CONFIG0, reg);
478
479 reg = IEP2_REG_ME_PENA(cfg->me_pena)
480 | IEP2_REG_MV_BONUS(cfg->mv_bonus)
481 | IEP2_REG_MV_SIMILAR_THR(cfg->mv_similar_thr)
482 | IEP2_REG_MV_SIMILAR_NUM_THR0(cfg->mv_similar_num_thr0)
483 | IEP2_REG_ME_THR_OFFSET(cfg->me_thr_offset);
484 mpp_write_relaxed(mpp, IEP2_REG_ME_CONFIG0, reg);
485
486 reg = IEP2_REG_MV_LEFT_LIMIT((~cfg->mv_left_limit) + 1)
487 | IEP2_REG_MV_RIGHT_LIMIT(cfg->mv_right_limit);
488 mpp_write_relaxed(mpp, IEP2_REG_ME_LIMIT_CONFIG, reg);
489
490 mpp_write_relaxed(mpp, IEP2_REG_EEDI_CONFIG0,
491 IEP2_REG_EEDI_THR0(cfg->eedi_thr0));
492 mpp_write_relaxed(mpp, IEP2_REG_BLE_CONFIG0,
493 IEP2_REG_BLE_BACKTOMA_NUM(cfg->ble_backtoma_num));
494 }
495
iep2_osd_cfg(struct mpp_dev * mpp,struct iep_task * task)496 static void iep2_osd_cfg(struct mpp_dev *mpp, struct iep_task *task)
497 {
498 struct iep2_params *hw_cfg = &task->params;
499 int i;
500 u32 reg;
501
502 for (i = 0; i < hw_cfg->osd_area_num; ++i) {
503 reg = IEP2_REG_OSD_X_STA(hw_cfg->osd_x_sta[i])
504 | IEP2_REG_OSD_X_END(hw_cfg->osd_x_end[i])
505 | IEP2_REG_OSD_Y_STA(hw_cfg->osd_y_sta[i])
506 | IEP2_REG_OSD_Y_END(hw_cfg->osd_y_end[i]);
507 mpp_write_relaxed(mpp, IEP2_REG_OSD_AREA_CONF(i), reg);
508 }
509
510 for (; i < ARRAY_SIZE(hw_cfg->osd_x_sta); ++i)
511 mpp_write_relaxed(mpp, IEP2_REG_OSD_AREA_CONF(i), 0);
512 }
513
iep2_mtn_tab_cfg(struct mpp_dev * mpp,struct iep_task * task)514 static void iep2_mtn_tab_cfg(struct mpp_dev *mpp, struct iep_task *task)
515 {
516 struct iep2_params *hw_cfg = &task->params;
517 int i;
518 u32 *mtn_tab = hw_cfg->mtn_en ? hw_cfg->mtn_tab : iep2_mtn_tab;
519
520 for (i = 0; i < ARRAY_SIZE(hw_cfg->mtn_tab); ++i)
521 mpp_write_relaxed(mpp, IEP2_REG_DIL_MTN_TAB(i), mtn_tab[i]);
522 }
523
524 static u32 iep2_tru_list_vld_tab[] = {
525 IEP2_REG_MV_TRU_LIST0_4_VLD, IEP2_REG_MV_TRU_LIST1_5_VLD,
526 IEP2_REG_MV_TRU_LIST2_6_VLD, IEP2_REG_MV_TRU_LIST3_7_VLD,
527 IEP2_REG_MV_TRU_LIST0_4_VLD, IEP2_REG_MV_TRU_LIST1_5_VLD,
528 IEP2_REG_MV_TRU_LIST2_6_VLD, IEP2_REG_MV_TRU_LIST3_7_VLD
529 };
530
iep2_tru_list_cfg(struct mpp_dev * mpp,struct iep_task * task)531 static void iep2_tru_list_cfg(struct mpp_dev *mpp, struct iep_task *task)
532 {
533 struct iep2_params *cfg = &task->params;
534 int i;
535 u32 reg;
536
537 for (i = 0; i < ARRAY_SIZE(cfg->mv_tru_list); i += 4) {
538 reg = 0;
539
540 if (cfg->mv_tru_vld[i])
541 reg |= IEP2_REG_MV_TRU_LIST0_4(cfg->mv_tru_list[i])
542 | iep2_tru_list_vld_tab[i];
543
544 if (cfg->mv_tru_vld[i + 1])
545 reg |= IEP2_REG_MV_TRU_LIST1_5(cfg->mv_tru_list[i + 1])
546 | iep2_tru_list_vld_tab[i + 1];
547
548 if (cfg->mv_tru_vld[i + 2])
549 reg |= IEP2_REG_MV_TRU_LIST2_6(cfg->mv_tru_list[i + 2])
550 | iep2_tru_list_vld_tab[i + 2];
551
552 if (cfg->mv_tru_vld[i + 3])
553 reg |= IEP2_REG_MV_TRU_LIST3_7(cfg->mv_tru_list[i + 3])
554 | iep2_tru_list_vld_tab[i + 3];
555
556 mpp_write_relaxed(mpp, IEP2_REG_MV_TRU_LIST(i / 4), reg);
557 }
558 }
559
iep2_comb_cfg(struct mpp_dev * mpp,struct iep_task * task)560 static void iep2_comb_cfg(struct mpp_dev *mpp, struct iep_task *task)
561 {
562 struct iep2_params *hw_cfg = &task->params;
563 int i;
564 u32 reg = 0;
565
566 for (i = 0; i < ARRAY_SIZE(hw_cfg->comb_osd_vld); ++i) {
567 if (hw_cfg->comb_osd_vld[i])
568 reg |= IEP2_REG_COMB_OSD_VLD(i);
569 }
570
571 reg |= IEP2_REG_COMB_T_THR(hw_cfg->comb_t_thr)
572 | IEP2_REG_COMB_FEATRUE_THR(hw_cfg->comb_feature_thr)
573 | IEP2_REG_COMB_CNT_THR(hw_cfg->comb_cnt_thr);
574 mpp_write_relaxed(mpp, IEP2_REG_COMB_CONFIG0, reg);
575 }
576
iep2_run(struct mpp_dev * mpp,struct mpp_task * mpp_task)577 static int iep2_run(struct mpp_dev *mpp,
578 struct mpp_task *mpp_task)
579 {
580 struct iep_task *task = NULL;
581
582 mpp_debug_enter();
583
584 task = to_iep_task(mpp_task);
585
586 /* init current task */
587 mpp->cur_task = mpp_task;
588
589 iep2_config(mpp, task);
590 iep2_osd_cfg(mpp, task);
591 iep2_mtn_tab_cfg(mpp, task);
592 iep2_tru_list_cfg(mpp, task);
593 iep2_comb_cfg(mpp, task);
594
595 /* set interrupt enable bits */
596 mpp_write_relaxed(mpp, IEP2_REG_INT_EN,
597 IEP2_REG_FRM_DONE_EN
598 | IEP2_REG_OSD_MAX_EN
599 | IEP2_REG_BUS_ERROR_EN);
600
601 /* Last, flush the registers */
602 wmb();
603 /* start iep2 */
604 mpp_write(mpp, IEP2_REG_FRM_START, 1);
605
606 mpp_debug_leave();
607
608 return 0;
609 }
610
iep2_irq(struct mpp_dev * mpp)611 static int iep2_irq(struct mpp_dev *mpp)
612 {
613 mpp->irq_status = mpp_read(mpp, IEP2_REG_INT_STS);
614 mpp_write(mpp, IEP2_REG_INT_CLR, 0xffffffff);
615
616 if (!IEP2_REG_RO_VALID_INT_STS(mpp->irq_status))
617 return IRQ_NONE;
618
619 return IRQ_WAKE_THREAD;
620 }
621
iep2_isr(struct mpp_dev * mpp)622 static int iep2_isr(struct mpp_dev *mpp)
623 {
624 struct mpp_task *mpp_task = NULL;
625 struct iep_task *task = NULL;
626 struct iep2_dev *iep = to_iep2_dev(mpp);
627
628 mpp_task = mpp->cur_task;
629 task = to_iep_task(mpp_task);
630 if (!task) {
631 dev_err(iep->mpp.dev, "no current task\n");
632 return IRQ_HANDLED;
633 }
634
635 mpp_time_diff(mpp_task);
636 mpp->cur_task = NULL;
637 task->irq_status = mpp->irq_status;
638 mpp_debug(DEBUG_IRQ_STATUS, "irq_status: %08x\n",
639 task->irq_status);
640
641 if (IEP2_REG_RO_BUS_ERROR_STS(task->irq_status))
642 atomic_inc(&mpp->reset_request);
643
644 mpp_task_finish(mpp_task->session, mpp_task);
645
646 mpp_debug_leave();
647
648 return IRQ_HANDLED;
649 }
650
iep2_osd_done(struct mpp_dev * mpp,struct iep_task * task)651 static void iep2_osd_done(struct mpp_dev *mpp, struct iep_task *task)
652 {
653 int i;
654 u32 reg;
655
656 for (i = 0; i < task->output.dect_osd_cnt; ++i) {
657 reg = mpp_read(mpp, IEP2_REG_RO_OSD_AREA_X(i));
658 task->output.x_sta[i] = IEP2_REG_RO_X_STA(reg) / 16;
659 task->output.x_end[i] = IEP2_REG_RO_X_END(reg) / 16;
660
661 reg = mpp_read(mpp, IEP2_REG_RO_OSD_AREA_Y(i));
662 task->output.y_sta[i] = IEP2_REG_RO_Y_STA(reg) / 4;
663 task->output.y_end[i] = IEP2_REG_RO_Y_END(reg) / 4;
664 }
665
666 for (; i < ARRAY_SIZE(task->output.x_sta); ++i) {
667 task->output.x_sta[i] = 0;
668 task->output.x_end[i] = 0;
669 task->output.y_sta[i] = 0;
670 task->output.y_end[i] = 0;
671 }
672 }
673
iep2_finish(struct mpp_dev * mpp,struct mpp_task * mpp_task)674 static int iep2_finish(struct mpp_dev *mpp,
675 struct mpp_task *mpp_task)
676 {
677 struct iep_task *task = to_iep_task(mpp_task);
678 struct iep2_output *output = &task->output;
679 u32 i;
680 u32 reg;
681
682 mpp_debug_enter();
683
684 output->dect_pd_tcnt = mpp_read(mpp, IEP2_REG_RO_PD_TCNT);
685 output->dect_pd_bcnt = mpp_read(mpp, IEP2_REG_RO_PD_BCNT);
686 output->dect_ff_cur_tcnt = mpp_read(mpp, IEP2_REG_RO_FF_CUR_TCNT);
687 output->dect_ff_cur_bcnt = mpp_read(mpp, IEP2_REG_RO_FF_CUR_BCNT);
688 output->dect_ff_nxt_tcnt = mpp_read(mpp, IEP2_REG_RO_FF_NXT_TCNT);
689 output->dect_ff_nxt_bcnt = mpp_read(mpp, IEP2_REG_RO_FF_NXT_BCNT);
690 output->dect_ff_ble_tcnt = mpp_read(mpp, IEP2_REG_RO_FF_BLE_TCNT);
691 output->dect_ff_ble_bcnt = mpp_read(mpp, IEP2_REG_RO_FF_BLE_BCNT);
692 output->dect_ff_nz = mpp_read(mpp, IEP2_REG_RO_FF_COMB_NZ);
693 output->dect_ff_comb_f = mpp_read(mpp, IEP2_REG_RO_FF_COMB_F);
694 output->dect_osd_cnt = mpp_read(mpp, IEP2_REG_RO_OSD_NUM);
695
696 reg = mpp_read(mpp, IEP2_REG_RO_COMB_CNT);
697 output->out_comb_cnt = IEP2_REG_RO_OUT_COMB_CNT(reg);
698 output->out_osd_comb_cnt = IEP2_REG_RO_OUT_OSD_COMB_CNT(reg);
699 output->ff_gradt_tcnt = mpp_read(mpp, IEP2_REG_RO_FF_GRADT_TCNT);
700 output->ff_gradt_bcnt = mpp_read(mpp, IEP2_REG_RO_FF_GRADT_BCNT);
701
702 iep2_osd_done(mpp, task);
703
704 for (i = 0; i < ARRAY_SIZE(output->mv_hist); i += 2) {
705 reg = mpp_read(mpp, IEP2_REG_RO_MV_HIST_BIN(i / 2));
706 output->mv_hist[i] = IEP2_REG_RO_MV_HIST_EVEN(reg);
707 output->mv_hist[i + 1] = IEP2_REG_RO_MV_HIST_ODD(reg);
708 }
709
710 mpp_debug_leave();
711
712 return 0;
713 }
714
iep2_result(struct mpp_dev * mpp,struct mpp_task * mpp_task,struct mpp_task_msgs * msgs)715 static int iep2_result(struct mpp_dev *mpp,
716 struct mpp_task *mpp_task,
717 struct mpp_task_msgs *msgs)
718 {
719 u32 i;
720 struct mpp_request *req;
721 struct iep_task *task = to_iep_task(mpp_task);
722
723 /* FIXME may overflow the kernel */
724 for (i = 0; i < task->r_req_cnt; i++) {
725 req = &task->r_reqs[i];
726
727 if (copy_to_user(req->data, (u8 *)&task->output, req->size)) {
728 mpp_err("copy_to_user reg fail\n");
729 return -EIO;
730 }
731 }
732
733 return 0;
734 }
735
iep2_free_task(struct mpp_session * session,struct mpp_task * mpp_task)736 static int iep2_free_task(struct mpp_session *session,
737 struct mpp_task *mpp_task)
738 {
739 struct iep_task *task = to_iep_task(mpp_task);
740
741 mpp_task_finalize(session, mpp_task);
742 kfree(task);
743
744 return 0;
745 }
746
747 #ifdef CONFIG_ROCKCHIP_MPP_PROC_FS
iep2_procfs_remove(struct mpp_dev * mpp)748 static int iep2_procfs_remove(struct mpp_dev *mpp)
749 {
750 struct iep2_dev *iep = to_iep2_dev(mpp);
751
752 if (iep->procfs) {
753 proc_remove(iep->procfs);
754 iep->procfs = NULL;
755 }
756
757 return 0;
758 }
759
iep2_procfs_init(struct mpp_dev * mpp)760 static int iep2_procfs_init(struct mpp_dev *mpp)
761 {
762 struct iep2_dev *iep = to_iep2_dev(mpp);
763
764 iep->procfs = proc_mkdir(mpp->dev->of_node->name, mpp->srv->procfs);
765 if (IS_ERR_OR_NULL(iep->procfs)) {
766 mpp_err("failed on mkdir\n");
767 iep->procfs = NULL;
768 return -EIO;
769 }
770 mpp_procfs_create_u32("aclk", 0644,
771 iep->procfs, &iep->aclk_info.debug_rate_hz);
772 mpp_procfs_create_u32("session_buffers", 0644,
773 iep->procfs, &mpp->session_max_buffers);
774
775 return 0;
776 }
777 #else
iep2_procfs_remove(struct mpp_dev * mpp)778 static inline int iep2_procfs_remove(struct mpp_dev *mpp)
779 {
780 return 0;
781 }
782
iep2_procfs_init(struct mpp_dev * mpp)783 static inline int iep2_procfs_init(struct mpp_dev *mpp)
784 {
785 return 0;
786 }
787 #endif
788
789 #define IEP2_TILE_W_MAX 120
790 #define IEP2_TILE_H_MAX 272
791
iep2_init(struct mpp_dev * mpp)792 static int iep2_init(struct mpp_dev *mpp)
793 {
794 int ret;
795 struct iep2_dev *iep = to_iep2_dev(mpp);
796
797 mpp->grf_info = &mpp->srv->grf_infos[MPP_DRIVER_IEP2];
798
799 /* Get clock info from dtsi */
800 ret = mpp_get_clk_info(mpp, &iep->aclk_info, "aclk");
801 if (ret)
802 mpp_err("failed on clk_get aclk\n");
803 ret = mpp_get_clk_info(mpp, &iep->hclk_info, "hclk");
804 if (ret)
805 mpp_err("failed on clk_get hclk\n");
806 ret = mpp_get_clk_info(mpp, &iep->sclk_info, "sclk");
807 if (ret)
808 mpp_err("failed on clk_get sclk\n");
809 /* Set default rates */
810 mpp_set_clk_info_rate_hz(&iep->aclk_info, CLK_MODE_DEFAULT, 300 * MHZ);
811
812 iep->rst_a = mpp_reset_control_get(mpp, RST_TYPE_A, "rst_a");
813 if (!iep->rst_a)
814 mpp_err("No aclk reset resource define\n");
815 iep->rst_h = mpp_reset_control_get(mpp, RST_TYPE_H, "rst_h");
816 if (!iep->rst_h)
817 mpp_err("No hclk reset resource define\n");
818 iep->rst_s = mpp_reset_control_get(mpp, RST_TYPE_CORE, "rst_s");
819 if (!iep->rst_s)
820 mpp_err("No sclk reset resource define\n");
821
822 iep->roi.size = IEP2_TILE_W_MAX * IEP2_TILE_H_MAX;
823 iep->roi.vaddr = dma_alloc_coherent(mpp->dev, iep->roi.size,
824 &iep->roi.iova,
825 GFP_KERNEL);
826 if (iep->roi.vaddr) {
827 dev_err(mpp->dev, "allocate roi buffer failed\n");
828 //return -ENOMEM;
829 }
830
831 return 0;
832 }
833
iep2_clk_on(struct mpp_dev * mpp)834 static int iep2_clk_on(struct mpp_dev *mpp)
835 {
836 struct iep2_dev *iep = to_iep2_dev(mpp);
837
838 mpp_clk_safe_enable(iep->aclk_info.clk);
839 mpp_clk_safe_enable(iep->hclk_info.clk);
840 mpp_clk_safe_enable(iep->sclk_info.clk);
841
842 return 0;
843 }
844
iep2_clk_off(struct mpp_dev * mpp)845 static int iep2_clk_off(struct mpp_dev *mpp)
846 {
847 struct iep2_dev *iep = to_iep2_dev(mpp);
848
849 mpp_clk_safe_disable(iep->aclk_info.clk);
850 mpp_clk_safe_disable(iep->hclk_info.clk);
851 mpp_clk_safe_disable(iep->sclk_info.clk);
852
853 return 0;
854 }
855
iep2_set_freq(struct mpp_dev * mpp,struct mpp_task * mpp_task)856 static int iep2_set_freq(struct mpp_dev *mpp,
857 struct mpp_task *mpp_task)
858 {
859 struct iep2_dev *iep = to_iep2_dev(mpp);
860 struct iep_task *task = to_iep_task(mpp_task);
861
862 mpp_clk_set_rate(&iep->aclk_info, task->clk_mode);
863
864 return 0;
865 }
866
iep2_reset(struct mpp_dev * mpp)867 static int iep2_reset(struct mpp_dev *mpp)
868 {
869 struct iep2_dev *iep = to_iep2_dev(mpp);
870
871 if (iep->rst_a && iep->rst_h && iep->rst_s) {
872 /* Don't skip this or iommu won't work after reset */
873 mpp_pmu_idle_request(mpp, true);
874 mpp_safe_reset(iep->rst_a);
875 mpp_safe_reset(iep->rst_h);
876 mpp_safe_reset(iep->rst_s);
877 udelay(5);
878 mpp_safe_unreset(iep->rst_a);
879 mpp_safe_unreset(iep->rst_h);
880 mpp_safe_unreset(iep->rst_s);
881 mpp_pmu_idle_request(mpp, false);
882 }
883
884 return 0;
885 }
886
887 static struct mpp_hw_ops iep_v2_hw_ops = {
888 .init = iep2_init,
889 .clk_on = iep2_clk_on,
890 .clk_off = iep2_clk_off,
891 .set_freq = iep2_set_freq,
892 .reset = iep2_reset,
893 };
894
895 static struct mpp_dev_ops iep_v2_dev_ops = {
896 .alloc_task = iep2_alloc_task,
897 .run = iep2_run,
898 .irq = iep2_irq,
899 .isr = iep2_isr,
900 .finish = iep2_finish,
901 .result = iep2_result,
902 .free_task = iep2_free_task,
903 };
904
905 static struct mpp_hw_info iep2_hw_info = {
906 .reg_id = -1,
907 };
908
909 static const struct mpp_dev_var iep2_v2_data = {
910 .device_type = MPP_DEVICE_IEP2,
911 .hw_ops = &iep_v2_hw_ops,
912 .dev_ops = &iep_v2_dev_ops,
913 .hw_info = &iep2_hw_info,
914 };
915
916 static const struct of_device_id mpp_iep2_match[] = {
917 {
918 .compatible = "rockchip,iep-v2",
919 .data = &iep2_v2_data,
920 },
921 #ifdef CONFIG_CPU_RV1126
922 {
923 .compatible = "rockchip,rv1126-iep",
924 .data = &iep2_v2_data,
925 },
926 #endif
927 {},
928 };
929
iep2_probe(struct platform_device * pdev)930 static int iep2_probe(struct platform_device *pdev)
931 {
932 struct device *dev = &pdev->dev;
933 struct iep2_dev *iep = NULL;
934 struct mpp_dev *mpp = NULL;
935 const struct of_device_id *match = NULL;
936 int ret = 0;
937
938 dev_info(dev, "probe device\n");
939 iep = devm_kzalloc(dev, sizeof(struct iep2_dev), GFP_KERNEL);
940 if (!iep)
941 return -ENOMEM;
942
943 mpp = &iep->mpp;
944 platform_set_drvdata(pdev, mpp);
945
946 if (pdev->dev.of_node) {
947 match = of_match_node(mpp_iep2_match, pdev->dev.of_node);
948 if (match)
949 mpp->var = (struct mpp_dev_var *)match->data;
950 }
951
952 ret = mpp_dev_probe(mpp, pdev);
953 if (ret) {
954 dev_err(dev, "probe sub driver failed\n");
955 return -EINVAL;
956 }
957
958 ret = devm_request_threaded_irq(dev, mpp->irq,
959 mpp_dev_irq,
960 mpp_dev_isr_sched,
961 IRQF_SHARED,
962 dev_name(dev), mpp);
963 if (ret) {
964 dev_err(dev, "register interrupter runtime failed\n");
965 return -EINVAL;
966 }
967
968 mpp->session_max_buffers = IEP2_SESSION_MAX_BUFFERS;
969 iep2_procfs_init(mpp);
970 /* register current device to mpp service */
971 mpp_dev_register_srv(mpp, mpp->srv);
972 dev_info(dev, "probing finish\n");
973
974 return 0;
975 }
976
iep2_remove(struct platform_device * pdev)977 static int iep2_remove(struct platform_device *pdev)
978 {
979 struct device *dev = &pdev->dev;
980 struct mpp_dev *mpp = dev_get_drvdata(dev);
981 struct iep2_dev *iep = to_iep2_dev(mpp);
982
983 dma_free_coherent(dev, iep->roi.size, iep->roi.vaddr, iep->roi.iova);
984
985 dev_info(dev, "remove device\n");
986 mpp_dev_remove(mpp);
987 iep2_procfs_remove(mpp);
988
989 return 0;
990 }
991
992 struct platform_driver rockchip_iep2_driver = {
993 .probe = iep2_probe,
994 .remove = iep2_remove,
995 .shutdown = mpp_dev_shutdown,
996 .driver = {
997 .name = IEP2_DRIVER_NAME,
998 .of_match_table = of_match_ptr(mpp_iep2_match),
999 },
1000 };
1001 EXPORT_SYMBOL(rockchip_iep2_driver);
1002
1003