1 /*
2 * Rockchip isp1 driver
3 *
4 * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 */
34
35 #include <media/v4l2-common.h>
36 #include <linux/rk-camera-module.h>
37 #include "regs.h"
38
rkisp_disable_dcrop(struct rkisp_stream * stream,bool async)39 void rkisp_disable_dcrop(struct rkisp_stream *stream, bool async)
40 {
41 struct rkisp_device *dev = stream->ispdev;
42 u32 mask = stream->config->dual_crop.yuvmode_mask |
43 stream->config->dual_crop.rawmode_mask;
44 u32 val = CIF_DUAL_CROP_CFG_UPD;
45
46 if (async && dev->hw_dev->is_single)
47 val = CIF_DUAL_CROP_GEN_CFG_UPD;
48 rkisp_unite_set_bits(dev, stream->config->dual_crop.ctrl,
49 mask, val, false, dev->hw_dev->is_unite);
50 }
51
rkisp_config_dcrop(struct rkisp_stream * stream,struct v4l2_rect * rect,bool async)52 void rkisp_config_dcrop(struct rkisp_stream *stream,
53 struct v4l2_rect *rect, bool async)
54 {
55 struct rkisp_device *dev = stream->ispdev;
56 u32 val = stream->config->dual_crop.yuvmode_mask;
57 bool is_unite = dev->hw_dev->is_unite;
58 struct v4l2_rect tmp = *rect;
59 u32 reg;
60
61 if (is_unite) {
62 tmp.width /= 2;
63 if (stream->id == RKISP_STREAM_FBC)
64 tmp.width &= ~0xf;
65 }
66 reg = stream->config->dual_crop.h_offset;
67 rkisp_write(dev, reg, tmp.left, false);
68 reg = stream->config->dual_crop.h_size;
69 rkisp_write(dev, reg, tmp.width, false);
70
71 reg = stream->config->dual_crop.v_offset;
72 rkisp_unite_write(dev, reg, tmp.top, false, is_unite);
73 reg = stream->config->dual_crop.v_size;
74 rkisp_unite_write(dev, reg, tmp.height, false, is_unite);
75
76 if (async && dev->hw_dev->is_single)
77 val |= CIF_DUAL_CROP_GEN_CFG_UPD;
78 else
79 val |= CIF_DUAL_CROP_CFG_UPD;
80 if (is_unite) {
81 u32 right_w, left_w = tmp.width;
82
83 reg = stream->config->dual_crop.h_offset;
84 rkisp_next_write(dev, reg, RKMOUDLE_UNITE_EXTEND_PIXEL, false);
85 reg = stream->config->dual_crop.h_size;
86 right_w = rect->width - left_w;
87 rkisp_next_write(dev, reg, right_w, false);
88 reg = stream->config->dual_crop.ctrl;
89 rkisp_next_set_bits(dev, reg, 0, val, false);
90 /* output with scale */
91 if (stream->out_fmt.width < rect->width) {
92 left_w += RKMOUDLE_UNITE_EXTEND_PIXEL;
93 reg = stream->config->dual_crop.h_size;
94 rkisp_write(dev, reg, left_w, false);
95 }
96 v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
97 "left dcrop (%d, %d) %dx%d\n",
98 tmp.left, tmp.top, left_w, tmp.height);
99 v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
100 "right dcrop (%d, %d) %dx%d\n",
101 RKMOUDLE_UNITE_EXTEND_PIXEL, tmp.top, right_w, tmp.height);
102 }
103 if (val) {
104 reg = stream->config->dual_crop.ctrl;
105 rkisp_set_bits(dev, reg, 0, val, false);
106 }
107 }
108
rkisp_dump_rsz_regs(struct rkisp_stream * stream)109 void rkisp_dump_rsz_regs(struct rkisp_stream *stream)
110 {
111 struct rkisp_device *dev = stream->ispdev;
112
113 pr_info("RSZ_CTRL 0x%08x/0x%08x\n"
114 "RSZ_SCALE_HY %d/%d\n"
115 "RSZ_SCALE_HCB %d/%d\n"
116 "RSZ_SCALE_HCR %d/%d\n"
117 "RSZ_SCALE_VY %d/%d\n"
118 "RSZ_SCALE_VC %d/%d\n"
119 "RSZ_PHASE_HY %d/%d\n"
120 "RSZ_PHASE_HC %d/%d\n"
121 "RSZ_PHASE_VY %d/%d\n"
122 "RSZ_PHASE_VC %d/%d\n",
123 rkisp_read(dev, stream->config->rsz.ctrl, false),
124 rkisp_read(dev, stream->config->rsz.ctrl_shd, true),
125 rkisp_read(dev, stream->config->rsz.scale_hy, false),
126 rkisp_read(dev, stream->config->rsz.scale_hy_shd, true),
127 rkisp_read(dev, stream->config->rsz.scale_hcb, false),
128 rkisp_read(dev, stream->config->rsz.scale_hcb_shd, true),
129 rkisp_read(dev, stream->config->rsz.scale_hcr, false),
130 rkisp_read(dev, stream->config->rsz.scale_hcr_shd, true),
131 rkisp_read(dev, stream->config->rsz.scale_vy, false),
132 rkisp_read(dev, stream->config->rsz.scale_vy_shd, true),
133 rkisp_read(dev, stream->config->rsz.scale_vc, false),
134 rkisp_read(dev, stream->config->rsz.scale_vc_shd, true),
135 rkisp_read(dev, stream->config->rsz.phase_hy, false),
136 rkisp_read(dev, stream->config->rsz.phase_hy_shd, true),
137 rkisp_read(dev, stream->config->rsz.phase_hc, false),
138 rkisp_read(dev, stream->config->rsz.phase_hc_shd, true),
139 rkisp_read(dev, stream->config->rsz.phase_vy, false),
140 rkisp_read(dev, stream->config->rsz.phase_vy_shd, true),
141 rkisp_read(dev, stream->config->rsz.phase_vc, false),
142 rkisp_read(dev, stream->config->rsz.phase_vc_shd, true));
143 }
144
update_rsz_shadow(struct rkisp_stream * stream,bool async)145 static void update_rsz_shadow(struct rkisp_stream *stream, bool async)
146 {
147 struct rkisp_device *dev = stream->ispdev;
148 u32 val = CIF_RSZ_CTRL_CFG_UPD;
149
150 if (async && dev->hw_dev->is_single)
151 val = CIF_RSZ_CTRL_CFG_UPD_AUTO;
152 rkisp_unite_set_bits(dev, stream->config->rsz.ctrl, 0,
153 val, false, dev->hw_dev->is_unite);
154 }
155
set_scale(struct rkisp_stream * stream,struct v4l2_rect * in_y,struct v4l2_rect * in_c,struct v4l2_rect * out_y,struct v4l2_rect * out_c)156 static void set_scale(struct rkisp_stream *stream, struct v4l2_rect *in_y,
157 struct v4l2_rect *in_c, struct v4l2_rect *out_y,
158 struct v4l2_rect *out_c)
159 {
160 struct rkisp_device *dev = stream->ispdev;
161 u32 scale_hy_addr = stream->config->rsz.scale_hy;
162 u32 scale_hcr_addr = stream->config->rsz.scale_hcr;
163 u32 scale_hcb_addr = stream->config->rsz.scale_hcb;
164 u32 scale_vy_addr = stream->config->rsz.scale_vy;
165 u32 scale_vc_addr = stream->config->rsz.scale_vc;
166 u32 rsz_ctrl_addr = stream->config->rsz.ctrl;
167 u32 scale_hy = 1, scale_hc = 1, scale_vy = 1, scale_vc = 1;
168 u32 rsz_ctrl = 0;
169
170 if (in_y->width < out_y->width) {
171 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
172 CIF_RSZ_CTRL_SCALE_HY_UP;
173 scale_hy = ((in_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
174 (out_y->width - 1);
175 rkisp_write(dev, scale_hy_addr, scale_hy, false);
176 } else if (in_y->width > out_y->width) {
177 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
178 scale_hy = ((out_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
179 (in_y->width - 1) + 1;
180 rkisp_write(dev, scale_hy_addr, scale_hy, false);
181 }
182 if (in_c->width < out_c->width) {
183 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
184 CIF_RSZ_CTRL_SCALE_HC_UP;
185 scale_hc = ((in_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
186 (out_c->width - 1);
187 rkisp_write(dev, scale_hcb_addr, scale_hc, false);
188 rkisp_write(dev, scale_hcr_addr, scale_hc, false);
189 } else if (in_c->width > out_c->width) {
190 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
191 scale_hc = ((out_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
192 (in_c->width - 1) + 1;
193 rkisp_write(dev, scale_hcb_addr, scale_hc, false);
194 rkisp_write(dev, scale_hcr_addr, scale_hc, false);
195 }
196
197 if (in_y->height < out_y->height) {
198 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
199 CIF_RSZ_CTRL_SCALE_VY_UP;
200 scale_vy = ((in_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
201 (out_y->height - 1);
202 rkisp_write(dev, scale_vy_addr, scale_vy, false);
203 } else if (in_y->height > out_y->height) {
204 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
205 scale_vy = ((out_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
206 (in_y->height - 1) + 1;
207 rkisp_write(dev, scale_vy_addr, scale_vy, false);
208 }
209
210 if (in_c->height < out_c->height) {
211 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
212 CIF_RSZ_CTRL_SCALE_VC_UP;
213 scale_vc = ((in_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
214 (out_c->height - 1);
215 rkisp_write(dev, scale_vc_addr, scale_vc, false);
216 } else if (in_c->height > out_c->height) {
217 rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
218 scale_vc = ((out_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
219 (in_c->height - 1) + 1;
220 rkisp_write(dev, scale_vc_addr, scale_vc, false);
221 }
222
223 if (dev->hw_dev->is_unite) {
224 u32 hy_size_reg = stream->id == RKISP_STREAM_MP ?
225 ISP3X_MAIN_RESIZE_HY_SIZE : ISP3X_SELF_RESIZE_HY_SIZE;
226 u32 hc_size_reg = stream->id == RKISP_STREAM_MP ?
227 ISP3X_MAIN_RESIZE_HC_SIZE : ISP3X_SELF_RESIZE_HC_SIZE;
228 u32 hy_offs_mi_reg = stream->id == RKISP_STREAM_MP ?
229 ISP3X_MAIN_RESIZE_HY_OFFS_MI : ISP3X_SELF_RESIZE_HY_OFFS_MI;
230 u32 hc_offs_mi_reg = stream->id == RKISP_STREAM_MP ?
231 ISP3X_MAIN_RESIZE_HC_OFFS_MI : ISP3X_SELF_RESIZE_HC_OFFS_MI;
232 u32 in_crop_offs_reg = stream->id == RKISP_STREAM_MP ?
233 ISP3X_MAIN_RESIZE_IN_CROP_OFFSET : ISP3X_SELF_RESIZE_IN_CROP_OFFSET;
234 u32 isp_in_w = in_y->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
235 u32 scl_w = out_y->width / 2;
236 u32 left_y = DIV_ROUND_UP(scl_w * 65536, scale_hy);
237 u32 left_c = DIV_ROUND_UP(scl_w * 65536 / 2, scale_hc);
238 u32 phase_src_y = left_y * scale_hy;
239 u32 phase_dst_y = scl_w * 65536;
240 u32 phase_left_y = scale_hy - (phase_src_y - phase_dst_y);
241 u32 phase_src_c = left_c * scale_hc;
242 u32 phase_dst_c = scl_w * 65536 / 2;
243 u32 phase_left_c = scale_hc - (phase_src_c - phase_dst_c);
244 u32 right_y = phase_left_y ?
245 in_y->width - (left_y - 1) :
246 in_y->width - left_y;
247 u32 right_c = phase_left_c ?
248 in_y->width - (left_c - 1) * 2 :
249 in_y->width - left_c * 2;
250 u32 right_crop_y = isp_in_w - right_y;
251 u32 right_crop_c = isp_in_w - right_c;
252 u32 right_scl_in_y = right_crop_y - RKMOUDLE_UNITE_EXTEND_PIXEL;
253 u32 right_scl_in_c = right_crop_c - RKMOUDLE_UNITE_EXTEND_PIXEL;
254
255 /* left isp */
256 rkisp_write(dev, hy_size_reg, scl_w, false);
257 rkisp_write(dev, hc_size_reg, scl_w, false);
258 rkisp_write(dev, hy_offs_mi_reg, 0, false);
259 rkisp_write(dev, hc_offs_mi_reg, 0, false);
260 rkisp_write(dev, in_crop_offs_reg, 0, false);
261
262 /* right isp */
263 rkisp_next_write(dev, hy_size_reg, scl_w, false);
264 rkisp_next_write(dev, hc_size_reg, scl_w, false);
265 rkisp_next_write(dev, scale_hy_addr, scale_hy, false);
266 rkisp_next_write(dev, scale_hcb_addr, scale_hc, false);
267 rkisp_next_write(dev, scale_hcr_addr, scale_hc, false);
268 rkisp_next_write(dev, scale_vy_addr, scale_vy, false);
269 rkisp_next_write(dev, scale_vc_addr, scale_vc, false);
270 rkisp_next_write(dev, stream->config->rsz.phase_hy, phase_left_y, false);
271 rkisp_next_write(dev, stream->config->rsz.phase_hc, phase_left_c, false);
272 rkisp_next_write(dev, stream->config->rsz.phase_vy, 0, false);
273 rkisp_next_write(dev, stream->config->rsz.phase_vc, 0, false);
274 rkisp_next_write(dev, hy_offs_mi_reg, scl_w & 15, false);
275 rkisp_next_write(dev, hc_offs_mi_reg, scl_w & 15, false);
276 rkisp_next_write(dev, in_crop_offs_reg,
277 right_scl_in_c << 4 | right_scl_in_y, false);
278
279 rsz_ctrl |= ISP3X_SCL_CLIP_EN;
280 rkisp_next_write(dev, rsz_ctrl_addr,
281 rsz_ctrl | ISP3X_SCL_HPHASE_EN | ISP3X_SCL_IN_CLIP_EN, false);
282 v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
283 "scl:%dx%d, scl factor[hy:%d hc:%d vy:%d vc:%d]\n",
284 scl_w, out_y->height, scale_hy, scale_hc, scale_vy, scale_vc);
285 v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
286 "scl_left size[y:%d c:%d] phase[y:%d c:%d]\n",
287 left_y, left_c, phase_left_y, phase_left_c);
288 v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
289 "scl_right size[y:%d c:%d] offs_mi[y:%d c:%d] in_crop[y:%d c:%d]\n",
290 right_y, right_c, scl_w & 15, scl_w & 15, right_scl_in_y, right_scl_in_c);
291 }
292 rkisp_write(dev, rsz_ctrl_addr, rsz_ctrl, false);
293 }
294
rkisp_config_rsz(struct rkisp_stream * stream,struct v4l2_rect * in_y,struct v4l2_rect * in_c,struct v4l2_rect * out_y,struct v4l2_rect * out_c,bool async)295 void rkisp_config_rsz(struct rkisp_stream *stream, struct v4l2_rect *in_y,
296 struct v4l2_rect *in_c, struct v4l2_rect *out_y,
297 struct v4l2_rect *out_c, bool async)
298 {
299 struct rkisp_device *dev = stream->ispdev;
300 int i = 0;
301 bool is_unite = dev->hw_dev->is_unite;
302
303 /* No phase offset */
304 rkisp_write(dev, stream->config->rsz.phase_hy, 0, true);
305 rkisp_write(dev, stream->config->rsz.phase_hc, 0, true);
306 rkisp_write(dev, stream->config->rsz.phase_vy, 0, true);
307 rkisp_write(dev, stream->config->rsz.phase_vc, 0, true);
308
309 /* Linear interpolation */
310 for (i = 0; i < 64; i++) {
311 rkisp_unite_write(dev, stream->config->rsz.scale_lut_addr, i, true, is_unite);
312 rkisp_unite_write(dev, stream->config->rsz.scale_lut, i, true, is_unite);
313 }
314
315 set_scale(stream, in_y, in_c, out_y, out_c);
316
317 update_rsz_shadow(stream, async);
318 }
319
rkisp_disable_rsz(struct rkisp_stream * stream,bool async)320 void rkisp_disable_rsz(struct rkisp_stream *stream, bool async)
321 {
322 bool is_unite = stream->ispdev->hw_dev->is_unite;
323
324 rkisp_unite_write(stream->ispdev, stream->config->rsz.ctrl, 0, false, is_unite);
325
326 if (!async)
327 update_rsz_shadow(stream, async);
328 }
329