xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/rockchip/rk618/rk618_scaler.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
4  *
5  * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/err.h>
11 #include <linux/mfd/rk618.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/regmap.h>
16 
17 #include <drm/drm_of.h>
18 #include <drm/drm_encoder.h>
19 #include <drm/drm_print.h>
20 #include <video/videomode.h>
21 
22 #define RK618_SCALER_REG0		0x0030
23 #define SCL_VER_DOWN_MODE(x)		HIWORD_UPDATE(x, 8, 8)
24 #define SCL_HOR_DOWN_MODE(x)		HIWORD_UPDATE(x, 7, 7)
25 #define SCL_BIC_COE_SEL(x)		HIWORD_UPDATE(x, 6, 5)
26 #define SCL_VER_MODE(x)			HIWORD_UPDATE(x, 4, 3)
27 #define SCL_HOR_MODE(x)			HIWORD_UPDATE(x, 2, 1)
28 #define SCL_ENABLE			HIWORD_UPDATE(1, 0, 0)
29 #define SCL_DISABLE			HIWORD_UPDATE(0, 0, 0)
30 #define RK618_SCALER_REG1		0x0034
31 #define SCL_V_FACTOR(x)			UPDATE(x, 31, 16)
32 #define SCL_H_FACTOR(x)			UPDATE(x, 15, 0)
33 #define RK618_SCALER_REG2		0x0038
34 #define DSP_FRAME_VST(x)		UPDATE(x, 27, 16)
35 #define DSP_FRAME_HST(x)		UPDATE(x, 11, 0)
36 #define RK618_SCALER_REG3		0x003c
37 #define DSP_HS_END(x)			UPDATE(x, 23, 16)
38 #define DSP_HTOTAL(x)			UPDATE(x, 11, 0)
39 #define RK618_SCALER_REG4		0x0040
40 #define DSP_HACT_END(x)			UPDATE(x, 27, 16)
41 #define DSP_HACT_ST(x)			UPDATE(x, 11, 0)
42 #define RK618_SCALER_REG5		0x0044
43 #define DSP_VS_END(x)			UPDATE(x, 23, 16)
44 #define DSP_VTOTAL(x)			UPDATE(x, 11, 0)
45 #define RK618_SCALER_REG6		0x0048
46 #define DSP_VACT_END(x)			UPDATE(x, 27, 16)
47 #define DSP_VACT_ST(x)			UPDATE(x, 11, 0)
48 #define RK618_SCALER_REG7		0x004c
49 #define DSP_HBOR_END(x)			UPDATE(x, 27, 16)
50 #define DSP_HBOR_ST(x)			UPDATE(x, 11, 0)
51 #define RK618_SCALER_REG8		0x0050
52 #define DSP_VBOR_END(x)			UPDATE(x, 27, 16)
53 #define DSP_VBOR_ST(x)			UPDATE(x, 11, 0)
54 
55 struct rk618_scaler {
56 	struct drm_bridge base;
57 	struct drm_bridge *bridge;
58 	struct drm_display_mode src;
59 	struct drm_display_mode dst;
60 	struct device *dev;
61 	struct regmap *regmap;
62 	struct clk *vif_clk;
63 	struct clk *dither_clk;
64 	struct clk *scaler_clk;
65 };
66 
bridge_to_scaler(struct drm_bridge * bridge)67 static inline struct rk618_scaler *bridge_to_scaler(struct drm_bridge *bridge)
68 {
69 	return container_of(bridge, struct rk618_scaler, base);
70 }
71 
rk618_scaler_enable(struct rk618_scaler * scl)72 static void rk618_scaler_enable(struct rk618_scaler *scl)
73 {
74 	regmap_write(scl->regmap, RK618_SCALER_REG0, SCL_ENABLE);
75 }
76 
rk618_scaler_disable(struct rk618_scaler * scl)77 static void rk618_scaler_disable(struct rk618_scaler *scl)
78 {
79 	regmap_write(scl->regmap, RK618_SCALER_REG0, SCL_DISABLE);
80 }
81 
calc_dsp_frm_hst_vst(const struct videomode * src,const struct videomode * dst,u32 * dsp_frame_hst,u32 * dsp_frame_vst)82 static void calc_dsp_frm_hst_vst(const struct videomode *src,
83 				 const struct videomode *dst,
84 				 u32 *dsp_frame_hst, u32 *dsp_frame_vst)
85 {
86 	u32 bp_in, bp_out;
87 	u32 v_scale_ratio;
88 	u64 t_frm_st;
89 	u64 t_bp_in, t_bp_out, t_delta, tin;
90 	u32 src_pixclock, dst_pixclock;
91 	u32 dsp_htotal, src_htotal, src_vtotal;
92 
93 	src_pixclock = div_u64(1000000000000llu, src->pixelclock);
94 	dst_pixclock = div_u64(1000000000000llu, dst->pixelclock);
95 
96 	src_htotal = src->hsync_len + src->hback_porch + src->hactive +
97 		     src->hfront_porch;
98 	src_vtotal = src->vsync_len + src->vback_porch + src->vactive +
99 		     src->vfront_porch;
100 	dsp_htotal = dst->hsync_len + dst->hback_porch + dst->hactive +
101 		     dst->hfront_porch;
102 
103 	bp_in = (src->vback_porch + src->vsync_len) * src_htotal +
104 		src->hsync_len + src->hback_porch;
105 	bp_out = (dst->vback_porch + dst->vsync_len) * dsp_htotal +
106 		 dst->hsync_len + dst->hback_porch;
107 
108 	t_bp_in = bp_in * src_pixclock;
109 	t_bp_out = bp_out * dst_pixclock;
110 	tin = src_vtotal * src_htotal * src_pixclock;
111 
112 	v_scale_ratio = src->vactive / dst->vactive;
113 	if (v_scale_ratio <= 2)
114 		t_delta = 5 * src_htotal * src_pixclock;
115 	else
116 		t_delta = 12 * src_htotal * src_pixclock;
117 
118 	if (t_bp_in + t_delta > t_bp_out)
119 		t_frm_st = (t_bp_in + t_delta - t_bp_out);
120 	else
121 		t_frm_st = tin - (t_bp_out - (t_bp_in + t_delta));
122 
123 	do_div(t_frm_st, src_pixclock);
124 	*dsp_frame_hst = do_div(t_frm_st, src_htotal);
125 	*dsp_frame_vst = t_frm_st;
126 }
127 
rk618_scaler_init(struct rk618_scaler * scl,const struct drm_display_mode * s,const struct drm_display_mode * d)128 static void rk618_scaler_init(struct rk618_scaler *scl,
129 			      const struct drm_display_mode *s,
130 			      const struct drm_display_mode *d)
131 {
132 	struct videomode src, dst;
133 	u32 dsp_frame_hst, dsp_frame_vst;
134 	u32 scl_hor_mode, scl_ver_mode;
135 	u32 scl_v_factor, scl_h_factor;
136 	u32 dsp_htotal, dsp_hs_end, dsp_hact_st, dsp_hact_end;
137 	u32 dsp_vtotal, dsp_vs_end, dsp_vact_st, dsp_vact_end;
138 	u32 dsp_hbor_end, dsp_hbor_st, dsp_vbor_end, dsp_vbor_st;
139 	u16 bor_right = 0, bor_left = 0, bor_up = 0, bor_down = 0;
140 	u8 hor_down_mode = 0, ver_down_mode = 0;
141 
142 	drm_display_mode_to_videomode(s, &src);
143 	drm_display_mode_to_videomode(d, &dst);
144 
145 	dsp_htotal = dst.hsync_len + dst.hback_porch + dst.hactive +
146 		     dst.hfront_porch;
147 	dsp_vtotal = dst.vsync_len + dst.vback_porch + dst.vactive +
148 		     dst.vfront_porch;
149 	dsp_hs_end = dst.hsync_len;
150 	dsp_vs_end = dst.vsync_len;
151 	dsp_hbor_end = dst.hsync_len + dst.hback_porch + dst.hactive;
152 	dsp_hbor_st = dst.hsync_len + dst.hback_porch;
153 	dsp_vbor_end = dst.vsync_len + dst.vback_porch + dst.vactive;
154 	dsp_vbor_st = dst.vsync_len + dst.vback_porch;
155 	dsp_hact_st = dsp_hbor_st + bor_left;
156 	dsp_hact_end = dsp_hbor_end - bor_right;
157 	dsp_vact_st = dsp_vbor_st + bor_up;
158 	dsp_vact_end = dsp_vbor_end - bor_down;
159 
160 	calc_dsp_frm_hst_vst(&src, &dst, &dsp_frame_hst, &dsp_frame_vst);
161 	dev_dbg(scl->dev, "dsp_frame_vst=%d, dsp_frame_hst=%d\n",
162 		dsp_frame_vst, dsp_frame_hst);
163 
164 	if (src.hactive > dst.hactive) {
165 		scl_hor_mode = 2;
166 
167 		if (hor_down_mode == 0) {
168 			if ((src.hactive - 1) / (dst.hactive - 1) > 2)
169 				scl_h_factor = ((src.hactive - 1) << 14) /
170 					       (dst.hactive - 1);
171 			else
172 				scl_h_factor = ((src.hactive - 2) << 14) /
173 					       (dst.hactive - 1);
174 		} else {
175 			scl_h_factor = (dst.hactive << 16) /
176 				       (src.hactive - 1);
177 		}
178 
179 		dev_dbg(scl->dev, "horizontal scale down\n");
180 	} else if (src.hactive == dst.hactive) {
181 		scl_hor_mode = 0;
182 		scl_h_factor = 0;
183 
184 		dev_dbg(scl->dev, "horizontal no scale\n");
185 	} else {
186 		scl_hor_mode = 1;
187 		scl_h_factor = ((src.hactive - 1) << 16) / (dst.hactive - 1);
188 
189 		dev_dbg(scl->dev, "horizontal scale up\n");
190 	}
191 
192 	if (src.vactive > dst.vactive) {
193 		scl_ver_mode = 2;
194 
195 		if (ver_down_mode == 0) {
196 			if ((src.vactive - 1) / (dst.vactive - 1) > 2)
197 				scl_v_factor = ((src.vactive - 1) << 14) /
198 					       (dst.vactive - 1);
199 			else
200 				scl_v_factor = ((src.vactive - 2) << 14) /
201 					       (dst.vactive - 1);
202 		} else {
203 			scl_v_factor = (dst.vactive << 16) /
204 				       (src.vactive - 1);
205 		}
206 
207 		dev_dbg(scl->dev, "vertical scale down\n");
208 	} else if (src.vactive == dst.vactive) {
209 		scl_ver_mode = 0;
210 		scl_v_factor = 0;
211 
212 		dev_dbg(scl->dev, "vertical no scale\n");
213 	} else {
214 		scl_ver_mode = 1;
215 		scl_v_factor = ((src.vactive - 1) << 16) / (dst.vactive - 1);
216 
217 		dev_dbg(scl->dev, "vertical scale up\n");
218 	}
219 
220 	regmap_write(scl->regmap, RK618_SCALER_REG0,
221 		     SCL_VER_MODE(scl_ver_mode) | SCL_HOR_MODE(scl_hor_mode));
222 	regmap_write(scl->regmap, RK618_SCALER_REG1,
223 		     SCL_V_FACTOR(scl_v_factor) | SCL_H_FACTOR(scl_h_factor));
224 	regmap_write(scl->regmap, RK618_SCALER_REG2,
225 		     DSP_FRAME_VST(dsp_frame_vst) |
226 		     DSP_FRAME_HST(dsp_frame_hst));
227 	regmap_write(scl->regmap, RK618_SCALER_REG3,
228 		     DSP_HS_END(dsp_hs_end) | DSP_HTOTAL(dsp_htotal));
229 	regmap_write(scl->regmap, RK618_SCALER_REG4,
230 		     DSP_HACT_END(dsp_hact_end) | DSP_HACT_ST(dsp_hact_st));
231 	regmap_write(scl->regmap, RK618_SCALER_REG5,
232 		     DSP_VS_END(dsp_vs_end) | DSP_VTOTAL(dsp_vtotal));
233 	regmap_write(scl->regmap, RK618_SCALER_REG6,
234 		     DSP_VACT_END(dsp_vact_end) | DSP_VACT_ST(dsp_vact_st));
235 	regmap_write(scl->regmap, RK618_SCALER_REG7,
236 		     DSP_HBOR_END(dsp_hbor_end) | DSP_HBOR_ST(dsp_hbor_st));
237 	regmap_write(scl->regmap, RK618_SCALER_REG8,
238 		     DSP_VBOR_END(dsp_vbor_end) | DSP_VBOR_ST(dsp_vbor_st));
239 }
240 
rk618_scaler_bridge_enable(struct drm_bridge * bridge)241 static void rk618_scaler_bridge_enable(struct drm_bridge *bridge)
242 {
243 	struct rk618_scaler *scl = bridge_to_scaler(bridge);
244 	struct drm_display_mode *src = &scl->src;
245 	struct drm_display_mode *dst = &scl->dst;
246 	long rate;
247 
248 	clk_set_parent(scl->dither_clk, scl->scaler_clk);
249 
250 	rate = clk_round_rate(scl->scaler_clk, dst->clock * 1000);
251 	clk_set_rate(scl->scaler_clk, rate);
252 	clk_prepare_enable(scl->scaler_clk);
253 
254 	rk618_scaler_init(scl, src, dst);
255 	rk618_scaler_enable(scl);
256 }
257 
rk618_scaler_bridge_disable(struct drm_bridge * bridge)258 static void rk618_scaler_bridge_disable(struct drm_bridge *bridge)
259 {
260 	struct rk618_scaler *scl = bridge_to_scaler(bridge);
261 
262 	rk618_scaler_disable(scl);
263 	clk_disable_unprepare(scl->scaler_clk);
264 	clk_set_parent(scl->dither_clk, scl->vif_clk);
265 }
266 
rk618_scaler_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted)267 static void rk618_scaler_bridge_mode_set(struct drm_bridge *bridge,
268 					 const struct drm_display_mode *mode,
269 					 const struct drm_display_mode *adjusted)
270 {
271 	struct rk618_scaler *scl = bridge_to_scaler(bridge);
272 	struct drm_connector *connector;
273 	struct drm_display_mode *src = &scl->src;
274 	struct drm_display_mode *dst = &scl->dst;
275 	unsigned long dclk_rate;
276 	u64 sclk_rate;
277 	struct drm_connector_list_iter conn_iter;
278 
279 	drm_mode_copy(&scl->src, adjusted);
280 
281 	drm_connector_list_iter_begin(bridge->dev, &conn_iter);
282 	drm_for_each_connector_iter(connector, &conn_iter) {
283 		const struct drm_display_mode *mode;
284 
285 		if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
286 			continue;
287 
288 		if (!drm_connector_has_possible_encoder(connector, bridge->encoder))
289 			continue;
290 
291 		list_for_each_entry(mode, &connector->modes, head) {
292 			if (mode->type & DRM_MODE_TYPE_PREFERRED) {
293 				drm_mode_copy(&scl->dst, mode);
294 				break;
295 			}
296 		}
297 	}
298 	drm_connector_list_iter_end(&conn_iter);
299 
300 	dclk_rate = src->clock * 1000;
301 	sclk_rate = (u64)dclk_rate * dst->vdisplay * dst->htotal;
302 	do_div(sclk_rate, src->vdisplay * src->htotal);
303 	sclk_rate = div_u64(sclk_rate, 1000);
304 	dst->clock = sclk_rate;
305 	sclk_rate = sclk_rate * 1000;
306 	scl->bridge->driver_private = dst;
307 
308 	DRM_DEV_INFO(scl->dev, "src=%s, dst=%s\n", src->name, dst->name);
309 	DRM_DEV_INFO(scl->dev, "dclk rate: %ld, sclk rate: %lld\n",
310 		     dclk_rate, sclk_rate);
311 }
312 
rk618_scaler_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)313 static int rk618_scaler_bridge_attach(struct drm_bridge *bridge,
314 				      enum drm_bridge_attach_flags flags)
315 {
316 	struct rk618_scaler *scl = bridge_to_scaler(bridge);
317 	struct device *dev = scl->dev;
318 	struct device_node *endpoint;
319 	int ret;
320 
321 	endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
322 	if (endpoint && of_device_is_available(endpoint)) {
323 		struct device_node *remote;
324 
325 		remote = of_graph_get_remote_port_parent(endpoint);
326 		of_node_put(endpoint);
327 		if (!remote || !of_device_is_available(remote))
328 			return -ENODEV;
329 
330 		scl->bridge = of_drm_find_bridge(remote);
331 		of_node_put(remote);
332 		if (!scl->bridge)
333 			return -EPROBE_DEFER;
334 
335 		ret = drm_bridge_attach(bridge->encoder, scl->bridge, bridge, 0);
336 		if (ret) {
337 			dev_err(dev, "failed to attach bridge\n");
338 			return ret;
339 		}
340 	}
341 
342 	return 0;
343 }
344 
345 static const struct drm_bridge_funcs rk618_scaler_bridge_funcs = {
346 	.enable = rk618_scaler_bridge_enable,
347 	.disable = rk618_scaler_bridge_disable,
348 	.mode_set = rk618_scaler_bridge_mode_set,
349 	.attach = rk618_scaler_bridge_attach,
350 };
351 
rk618_scaler_probe(struct platform_device * pdev)352 static int rk618_scaler_probe(struct platform_device *pdev)
353 {
354 	struct rk618 *rk618 = dev_get_drvdata(pdev->dev.parent);
355 	struct device *dev = &pdev->dev;
356 	struct rk618_scaler *scl;
357 	int ret;
358 
359 	if (!of_device_is_available(dev->of_node))
360 		return -ENODEV;
361 
362 	scl = devm_kzalloc(dev, sizeof(*scl), GFP_KERNEL);
363 	if (!scl)
364 		return -ENOMEM;
365 
366 	scl->dev = dev;
367 	scl->regmap = rk618->regmap;
368 	platform_set_drvdata(pdev, scl);
369 
370 	scl->vif_clk = devm_clk_get(dev, "vif");
371 	if (IS_ERR(scl->vif_clk)) {
372 		ret = PTR_ERR(scl->vif_clk);
373 		dev_err(dev, "failed to get vif clock: %d\n", ret);
374 		return ret;
375 	}
376 
377 	scl->dither_clk = devm_clk_get(dev, "dither");
378 	if (IS_ERR(scl->dither_clk)) {
379 		ret = PTR_ERR(scl->dither_clk);
380 		dev_err(dev, "failed to get dither clock: %d\n", ret);
381 		return ret;
382 	}
383 
384 	scl->scaler_clk = devm_clk_get(dev, "scaler");
385 	if (IS_ERR(scl->scaler_clk)) {
386 		ret = PTR_ERR(scl->scaler_clk);
387 		dev_err(dev, "failed to get scaler clock: %d\n", ret);
388 		return ret;
389 	}
390 
391 	scl->base.funcs = &rk618_scaler_bridge_funcs;
392 	scl->base.of_node = dev->of_node;
393 	drm_bridge_add(&scl->base);
394 
395 	return 0;
396 }
397 
rk618_scaler_remove(struct platform_device * pdev)398 static int rk618_scaler_remove(struct platform_device *pdev)
399 {
400 	struct rk618_scaler *scl = platform_get_drvdata(pdev);
401 
402 	drm_bridge_remove(&scl->base);
403 
404 	return 0;
405 }
406 
407 static const struct of_device_id rk618_scaler_of_match[] = {
408 	{ .compatible = "rockchip,rk618-scaler", },
409 	{},
410 };
411 MODULE_DEVICE_TABLE(of, rk618_scaler_of_match);
412 
413 static struct platform_driver rk618_scaler_driver = {
414 	.driver = {
415 		.name = "rk618-scaler",
416 		.of_match_table = of_match_ptr(rk618_scaler_of_match),
417 	},
418 	.probe = rk618_scaler_probe,
419 	.remove = rk618_scaler_remove,
420 };
421 module_platform_driver(rk618_scaler_driver);
422 
423 MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
424 MODULE_DESCRIPTION("Rockchip RK618 SCALER driver");
425 MODULE_LICENSE("GPL v2");
426