xref: /OK3568_Linux_fs/kernel/drivers/media/platform/rockchip/isp1/regs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 "regs.h"
37 
disable_dcrop(struct rkisp1_stream * stream,bool async)38 void disable_dcrop(struct rkisp1_stream *stream, bool async)
39 {
40 	void __iomem *base = stream->ispdev->base_addr;
41 	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
42 	u32 dc_ctrl = readl(dc_ctrl_addr);
43 	u32 mask = ~(stream->config->dual_crop.yuvmode_mask |
44 			stream->config->dual_crop.rawmode_mask);
45 	u32 val = dc_ctrl & mask;
46 
47 	if (async)
48 		val |= CIF_DUAL_CROP_GEN_CFG_UPD;
49 	else
50 		val |= CIF_DUAL_CROP_CFG_UPD;
51 	writel(val, dc_ctrl_addr);
52 }
53 
config_dcrop(struct rkisp1_stream * stream,struct v4l2_rect * rect,bool async)54 void config_dcrop(struct rkisp1_stream *stream, struct v4l2_rect *rect, bool async)
55 {
56 	void __iomem *base = stream->ispdev->base_addr;
57 	void __iomem *dc_ctrl_addr = base + stream->config->dual_crop.ctrl;
58 	u32 dc_ctrl = readl(dc_ctrl_addr);
59 
60 	writel(rect->left, base + stream->config->dual_crop.h_offset);
61 	writel(rect->top, base + stream->config->dual_crop.v_offset);
62 	writel(rect->width, base + stream->config->dual_crop.h_size);
63 	writel(rect->height, base + stream->config->dual_crop.v_size);
64 	dc_ctrl |= stream->config->dual_crop.yuvmode_mask;
65 	if (async)
66 		dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
67 	else
68 		dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
69 	writel(dc_ctrl, dc_ctrl_addr);
70 }
71 
dump_rsz_regs(struct rkisp1_stream * stream)72 void dump_rsz_regs(struct rkisp1_stream *stream)
73 {
74 	void __iomem *base = stream->ispdev->base_addr;
75 
76 	pr_info("RSZ_CTRL 0x%08x/0x%08x\n"
77 			"RSZ_SCALE_HY %d/%d\n"
78 			"RSZ_SCALE_HCB %d/%d\n"
79 			"RSZ_SCALE_HCR %d/%d\n"
80 			"RSZ_SCALE_VY %d/%d\n"
81 			"RSZ_SCALE_VC %d/%d\n"
82 			"RSZ_PHASE_HY %d/%d\n"
83 			"RSZ_PHASE_HC %d/%d\n"
84 			"RSZ_PHASE_VY %d/%d\n"
85 			"RSZ_PHASE_VC %d/%d\n",
86 			readl(base + stream->config->rsz.ctrl),
87 			readl(base + stream->config->rsz.ctrl_shd),
88 			readl(base + stream->config->rsz.scale_hy),
89 			readl(base + stream->config->rsz.scale_hy_shd),
90 			readl(base + stream->config->rsz.scale_hcb),
91 			readl(base + stream->config->rsz.scale_hcb_shd),
92 			readl(base + stream->config->rsz.scale_hcr),
93 			readl(base + stream->config->rsz.scale_hcr_shd),
94 			readl(base + stream->config->rsz.scale_vy),
95 			readl(base + stream->config->rsz.scale_vy_shd),
96 			readl(base + stream->config->rsz.scale_vc),
97 			readl(base + stream->config->rsz.scale_vc_shd),
98 			readl(base + stream->config->rsz.phase_hy),
99 			readl(base + stream->config->rsz.phase_hy_shd),
100 			readl(base + stream->config->rsz.phase_hc),
101 			readl(base + stream->config->rsz.phase_hc_shd),
102 			readl(base + stream->config->rsz.phase_vy),
103 			readl(base + stream->config->rsz.phase_vy_shd),
104 			readl(base + stream->config->rsz.phase_vc),
105 			readl(base + stream->config->rsz.phase_vc_shd));
106 }
107 
update_rsz_shadow(struct rkisp1_stream * stream,bool async)108 static void update_rsz_shadow(struct rkisp1_stream *stream, bool async)
109 {
110 	void *addr = stream->ispdev->base_addr + stream->config->rsz.ctrl;
111 	u32 ctrl_cfg = readl(addr);
112 
113 	if (async)
114 		writel(CIF_RSZ_CTRL_CFG_UPD_AUTO | ctrl_cfg, addr);
115 	else
116 		writel(CIF_RSZ_CTRL_CFG_UPD | ctrl_cfg, addr);
117 }
118 
set_scale(struct rkisp1_stream * stream,struct v4l2_rect * in_y,struct v4l2_rect * in_c,struct v4l2_rect * out_y,struct v4l2_rect * out_c)119 static void set_scale(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
120 		struct v4l2_rect *in_c, struct v4l2_rect *out_y,
121 		struct v4l2_rect *out_c)
122 {
123 	void __iomem *base = stream->ispdev->base_addr;
124 	void __iomem *scale_hy_addr = base + stream->config->rsz.scale_hy;
125 	void __iomem *scale_hcr_addr = base + stream->config->rsz.scale_hcr;
126 	void __iomem *scale_hcb_addr = base + stream->config->rsz.scale_hcb;
127 	void __iomem *scale_vy_addr = base + stream->config->rsz.scale_vy;
128 	void __iomem *scale_vc_addr = base + stream->config->rsz.scale_vc;
129 	void __iomem *rsz_ctrl_addr = base + stream->config->rsz.ctrl;
130 	u32 scale_hy, scale_hc, scale_vy, scale_vc, rsz_ctrl = 0;
131 
132 	if (in_y->width < out_y->width) {
133 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
134 				CIF_RSZ_CTRL_SCALE_HY_UP;
135 		scale_hy = ((in_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
136 				(out_y->width - 1);
137 		writel(scale_hy, scale_hy_addr);
138 	} else if (in_y->width > out_y->width) {
139 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
140 		scale_hy = ((out_y->width - 1) * CIF_RSZ_SCALER_FACTOR) /
141 				(in_y->width - 1) + 1;
142 		writel(scale_hy, scale_hy_addr);
143 	}
144 	if (in_c->width < out_c->width) {
145 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
146 				CIF_RSZ_CTRL_SCALE_HC_UP;
147 		scale_hc = ((in_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
148 				(out_c->width - 1);
149 		writel(scale_hc, scale_hcb_addr);
150 		writel(scale_hc, scale_hcr_addr);
151 	} else if (in_c->width > out_c->width) {
152 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
153 		scale_hc = ((out_c->width - 1) * CIF_RSZ_SCALER_FACTOR) /
154 				(in_c->width - 1) + 1;
155 		writel(scale_hc, scale_hcb_addr);
156 		writel(scale_hc, scale_hcr_addr);
157 	}
158 
159 	if (in_y->height < out_y->height) {
160 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
161 				CIF_RSZ_CTRL_SCALE_VY_UP;
162 		scale_vy = ((in_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
163 				(out_y->height - 1);
164 		writel(scale_vy, scale_vy_addr);
165 	} else if (in_y->height > out_y->height) {
166 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
167 		scale_vy = ((out_y->height - 1) * CIF_RSZ_SCALER_FACTOR) /
168 				(in_y->height - 1) + 1;
169 		writel(scale_vy, scale_vy_addr);
170 	}
171 
172 	if (in_c->height < out_c->height) {
173 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
174 				CIF_RSZ_CTRL_SCALE_VC_UP;
175 		scale_vc = ((in_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
176 				(out_c->height - 1);
177 		writel(scale_vc, scale_vc_addr);
178 	} else if (in_c->height > out_c->height) {
179 		rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
180 		scale_vc = ((out_c->height - 1) * CIF_RSZ_SCALER_FACTOR) /
181 				(in_c->height - 1) + 1;
182 		writel(scale_vc, scale_vc_addr);
183 	}
184 
185 	writel(rsz_ctrl, rsz_ctrl_addr);
186 }
187 
config_rsz(struct rkisp1_stream * stream,struct v4l2_rect * in_y,struct v4l2_rect * in_c,struct v4l2_rect * out_y,struct v4l2_rect * out_c,bool async)188 void config_rsz(struct rkisp1_stream *stream, struct v4l2_rect *in_y,
189 	struct v4l2_rect *in_c, struct v4l2_rect *out_y,
190 	struct v4l2_rect *out_c, bool async)
191 {
192 	int i = 0;
193 
194 	/* No phase offset */
195 	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hy);
196 	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_hc);
197 	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vy);
198 	writel(0, stream->ispdev->base_addr + stream->config->rsz.phase_vc);
199 
200 	/* Linear interpolation */
201 	for (i = 0; i < 64; i++) {
202 		writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut_addr);
203 		writel(i, stream->ispdev->base_addr + stream->config->rsz.scale_lut);
204 	}
205 
206 	set_scale(stream, in_y, in_c, out_y, out_c);
207 
208 	update_rsz_shadow(stream, async);
209 }
210 
disable_rsz(struct rkisp1_stream * stream,bool async)211 void disable_rsz(struct rkisp1_stream *stream, bool async)
212 {
213 	writel(0, stream->ispdev->base_addr + stream->config->rsz.ctrl);
214 
215 	if (!async)
216 		update_rsz_shadow(stream, async);
217 }
218 
config_mi_ctrl(struct rkisp1_stream * stream,u32 burst)219 void config_mi_ctrl(struct rkisp1_stream *stream, u32 burst)
220 {
221 	void __iomem *base = stream->ispdev->base_addr;
222 	void __iomem *addr = base + CIF_MI_CTRL;
223 	u32 reg;
224 
225 	reg = readl(addr) & ~GENMASK(19, 16);
226 	writel(reg | burst, addr);
227 	reg = readl(addr);
228 	writel(reg | CIF_MI_CTRL_INIT_BASE_EN, addr);
229 	reg = readl(addr);
230 	writel(reg | CIF_MI_CTRL_INIT_OFFSET_EN, addr);
231 }
232 
mp_is_stream_stopped(void __iomem * base)233 bool mp_is_stream_stopped(void __iomem *base)
234 {
235 	int en;
236 
237 	en = CIF_MI_CTRL_SHD_MP_IN_ENABLED | CIF_MI_CTRL_SHD_RAW_OUT_ENABLED;
238 	return !(readl(base + CIF_MI_CTRL_SHD) & en);
239 }
240 
sp_is_stream_stopped(void __iomem * base)241 bool sp_is_stream_stopped(void __iomem *base)
242 {
243 	return !(readl(base + CIF_MI_CTRL_SHD) & CIF_MI_CTRL_SHD_SP_IN_ENABLED);
244 }
245