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