1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <boot_rkimg.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <i2c.h>
11*4882a593Smuzhiyun #include <video_bridge.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun #include <dm/device.h>
14*4882a593Smuzhiyun #include <dm/device-internal.h>
15*4882a593Smuzhiyun #include <linux/media-bus-format.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "rockchip_bridge.h"
18*4882a593Smuzhiyun #include "rockchip_display.h"
19*4882a593Smuzhiyun #include "rockchip_panel.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include "rk1000.h"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define TVE_POWCR 0x03
24*4882a593Smuzhiyun #define TVE_OFF 0X07
25*4882a593Smuzhiyun #define TVE_ON 0x03
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct rk1000_tve {
28*4882a593Smuzhiyun struct udevice *dev;
29*4882a593Smuzhiyun struct rk1000_ctl rk1000_ctl;
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun enum {
33*4882a593Smuzhiyun CVBS_NTSC = 0,
34*4882a593Smuzhiyun CVBS_PAL,
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
rk1000_tve_i2c_write(struct rk1000_tve * rk1000_tve,u8 reg,u8 val)37*4882a593Smuzhiyun int rk1000_tve_i2c_write(struct rk1000_tve *rk1000_tve, u8 reg, u8 val)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun struct dm_i2c_chip *chip = dev_get_parent_platdata(rk1000_tve->dev);
40*4882a593Smuzhiyun struct i2c_msg msg;
41*4882a593Smuzhiyun u8 buf[2];
42*4882a593Smuzhiyun int ret;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun buf[0] = reg;
45*4882a593Smuzhiyun buf[1] = val;
46*4882a593Smuzhiyun msg.addr = chip->chip_addr;
47*4882a593Smuzhiyun msg.flags = 0;
48*4882a593Smuzhiyun msg.len = 2;
49*4882a593Smuzhiyun msg.buf = buf;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun ret = dm_i2c_xfer(rk1000_tve->dev, &msg, 1);
52*4882a593Smuzhiyun if (ret) {
53*4882a593Smuzhiyun dev_err(rk1000_tve->dev,
54*4882a593Smuzhiyun "rk1000 tve i2c write failed: %d\n", ret);
55*4882a593Smuzhiyun return ret;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun return 0;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
rk1000_tve_i2c_read(struct rk1000_tve * rk1000_tve,u8 reg,u8 * val)61*4882a593Smuzhiyun int rk1000_tve_i2c_read(struct rk1000_tve *rk1000_tve, u8 reg, u8 *val)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun struct dm_i2c_chip *chip = dev_get_parent_platdata(rk1000_tve->dev);
64*4882a593Smuzhiyun u8 data;
65*4882a593Smuzhiyun struct i2c_msg msg[] = {
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun .addr = chip->chip_addr,
68*4882a593Smuzhiyun .flags = 0,
69*4882a593Smuzhiyun .buf = (u8 *)®,
70*4882a593Smuzhiyun .len = 1,
71*4882a593Smuzhiyun }, {
72*4882a593Smuzhiyun .addr = chip->chip_addr,
73*4882a593Smuzhiyun .flags = I2C_M_RD,
74*4882a593Smuzhiyun .buf = (u8 *)&data,
75*4882a593Smuzhiyun .len = 1,
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun int ret;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun ret = dm_i2c_xfer(rk1000_tve->dev, msg, 2);
81*4882a593Smuzhiyun if (ret) {
82*4882a593Smuzhiyun dev_err(rk1000_tve->dev,
83*4882a593Smuzhiyun "rk1000 tve i2c read failed: %d\n", ret);
84*4882a593Smuzhiyun return ret;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun *val = data;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun return 0;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
rk1000_tv_write_block(struct rk1000_tve * rk1000_tve,u8 reg,const u8 * buf,u8 len)92*4882a593Smuzhiyun static int rk1000_tv_write_block(struct rk1000_tve *rk1000_tve,
93*4882a593Smuzhiyun u8 reg, const u8 *buf, u8 len)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun int i, ret;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun for (i = 0; i < len; i++) {
98*4882a593Smuzhiyun ret = rk1000_tve_i2c_write(rk1000_tve, reg + i, buf[i]);
99*4882a593Smuzhiyun if (ret)
100*4882a593Smuzhiyun break;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return ret;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
rk1000_tve_probe(struct udevice * dev)106*4882a593Smuzhiyun static int rk1000_tve_probe(struct udevice *dev)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun struct rk1000_tve *rk1000_tve = dev_get_priv(dev);
109*4882a593Smuzhiyun struct rockchip_bridge *bridge =
110*4882a593Smuzhiyun (struct rockchip_bridge *)dev_get_driver_data(dev);
111*4882a593Smuzhiyun int ret;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun rk1000_tve->dev = dev;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun ret = uclass_get_device_by_name(UCLASS_I2C_GENERIC,
116*4882a593Smuzhiyun "rk1000-ctl@40",
117*4882a593Smuzhiyun &rk1000_tve->rk1000_ctl.dev);
118*4882a593Smuzhiyun if (ret)
119*4882a593Smuzhiyun return ret;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun bridge->dev = dev;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
rk1000_tve_bridge_enable(struct rockchip_bridge * bridge)126*4882a593Smuzhiyun static void rk1000_tve_bridge_enable(struct rockchip_bridge *bridge)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun u8 tv_encoder_regs_pal[] = {0x06, 0x00, 0x00, 0x03, 0x00, 0x00};
129*4882a593Smuzhiyun u8 tv_encoder_control_regs_pal[] = {0x41, 0x01};
130*4882a593Smuzhiyun u8 tv_encoder_regs_ntsc[] = {0x00, 0x00, 0x00, 0x03, 0x00, 0x00};
131*4882a593Smuzhiyun u8 tv_encoder_control_regs_ntsc[] = {0x43, 0x01};
132*4882a593Smuzhiyun char data[4] = {0x88, 0x00, 0x22, 0x00};
133*4882a593Smuzhiyun struct rk1000_tve *rk1000_tve = dev_get_priv(bridge->dev);
134*4882a593Smuzhiyun struct connector_state *conn_state = &bridge->state->conn_state;
135*4882a593Smuzhiyun struct drm_display_mode *mode = &conn_state->mode;
136*4882a593Smuzhiyun struct rk1000_ctl *rk1000_ctl = &rk1000_tve->rk1000_ctl;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun rk1000_ctl_write_block(rk1000_ctl, 0, (u8 *)data, 4);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* rk1000 power down output dac */
141*4882a593Smuzhiyun data[0] = 0x07;
142*4882a593Smuzhiyun rk1000_tv_write_block(rk1000_tve, 0x03, (u8 *)data, 1);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun if (mode->vdisplay == 576) {
145*4882a593Smuzhiyun rk1000_tv_write_block(rk1000_tve, 0, tv_encoder_regs_pal,
146*4882a593Smuzhiyun sizeof(tv_encoder_regs_pal));
147*4882a593Smuzhiyun rk1000_ctl_write_block(rk1000_ctl, 3,
148*4882a593Smuzhiyun tv_encoder_control_regs_pal,
149*4882a593Smuzhiyun sizeof(tv_encoder_control_regs_pal));
150*4882a593Smuzhiyun } else {
151*4882a593Smuzhiyun rk1000_tv_write_block(rk1000_tve, 0, tv_encoder_regs_ntsc,
152*4882a593Smuzhiyun sizeof(tv_encoder_regs_ntsc));
153*4882a593Smuzhiyun rk1000_ctl_write_block(rk1000_ctl, 3,
154*4882a593Smuzhiyun tv_encoder_control_regs_ntsc,
155*4882a593Smuzhiyun sizeof(tv_encoder_control_regs_ntsc));
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
rk1000_tve_bridge_disable(struct rockchip_bridge * bridge)159*4882a593Smuzhiyun static void rk1000_tve_bridge_disable(struct rockchip_bridge *bridge)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun struct rk1000_tve *rk1000_tve = dev_get_priv(bridge->dev);
162*4882a593Smuzhiyun char data[1] = {0x07};
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* rk1000 power down output dac */
165*4882a593Smuzhiyun rk1000_tv_write_block(rk1000_tve, 0x03, (u8 *)data, 1);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
drm_rk1000_select_output(struct overscan * overscan,struct drm_display_mode * mode)168*4882a593Smuzhiyun static void drm_rk1000_select_output(struct overscan *overscan,
169*4882a593Smuzhiyun struct drm_display_mode *mode)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
172*4882a593Smuzhiyun struct base_screen_info *screen_info = NULL;
173*4882a593Smuzhiyun struct base_disp_info base_parameter;
174*4882a593Smuzhiyun struct blk_desc *dev_desc;
175*4882a593Smuzhiyun const struct base_overscan *scan;
176*4882a593Smuzhiyun disk_partition_t part_info;
177*4882a593Smuzhiyun int ret, i, screen_size;
178*4882a593Smuzhiyun int max_scan = 100;
179*4882a593Smuzhiyun int min_scan = 51;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun overscan->left_margin = max_scan;
182*4882a593Smuzhiyun overscan->right_margin = max_scan;
183*4882a593Smuzhiyun overscan->top_margin = max_scan;
184*4882a593Smuzhiyun overscan->bottom_margin = max_scan;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun mode->hdisplay = 720;
187*4882a593Smuzhiyun mode->hsync_start = 732;
188*4882a593Smuzhiyun mode->hsync_end = 738;
189*4882a593Smuzhiyun mode->htotal = 864;
190*4882a593Smuzhiyun mode->vdisplay = 576;
191*4882a593Smuzhiyun mode->vsync_start = 582;
192*4882a593Smuzhiyun mode->vsync_end = 588;
193*4882a593Smuzhiyun mode->vtotal = 625;
194*4882a593Smuzhiyun mode->clock = 27000;
195*4882a593Smuzhiyun mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun dev_desc = rockchip_get_bootdev();
198*4882a593Smuzhiyun if (!dev_desc) {
199*4882a593Smuzhiyun printf("%s: Could not find device\n", __func__);
200*4882a593Smuzhiyun return;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (part_get_info_by_name(dev_desc, "baseparameter", &part_info) < 0) {
204*4882a593Smuzhiyun printf("Could not find baseparameter partition\n");
205*4882a593Smuzhiyun return;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun ret = blk_dread(dev_desc, part_info.start, 1,
209*4882a593Smuzhiyun (void *)baseparameter_buf);
210*4882a593Smuzhiyun if (ret < 0) {
211*4882a593Smuzhiyun printf("read baseparameter failed\n");
212*4882a593Smuzhiyun return;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun memcpy(&base_parameter, baseparameter_buf, sizeof(base_parameter));
216*4882a593Smuzhiyun scan = &base_parameter.scan;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun screen_size = sizeof(base_parameter.screen_list) /
219*4882a593Smuzhiyun sizeof(base_parameter.screen_list[0]);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun for (i = 0; i < screen_size; i++) {
222*4882a593Smuzhiyun if (base_parameter.screen_list[i].type ==
223*4882a593Smuzhiyun DRM_MODE_CONNECTOR_TV) {
224*4882a593Smuzhiyun screen_info = &base_parameter.screen_list[i];
225*4882a593Smuzhiyun break;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun if (scan->leftscale < min_scan && scan->leftscale > 0)
230*4882a593Smuzhiyun overscan->left_margin = min_scan;
231*4882a593Smuzhiyun else if (scan->leftscale < max_scan)
232*4882a593Smuzhiyun overscan->left_margin = scan->leftscale;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (scan->rightscale < min_scan && scan->rightscale > 0)
235*4882a593Smuzhiyun overscan->right_margin = min_scan;
236*4882a593Smuzhiyun else if (scan->rightscale < max_scan)
237*4882a593Smuzhiyun overscan->right_margin = scan->rightscale;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun if (scan->topscale < min_scan && scan->topscale > 0)
240*4882a593Smuzhiyun overscan->top_margin = min_scan;
241*4882a593Smuzhiyun else if (scan->topscale < max_scan)
242*4882a593Smuzhiyun overscan->top_margin = scan->topscale;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun if (scan->bottomscale < min_scan && scan->bottomscale > 0)
245*4882a593Smuzhiyun overscan->bottom_margin = min_scan;
246*4882a593Smuzhiyun else if (scan->bottomscale < max_scan)
247*4882a593Smuzhiyun overscan->bottom_margin = scan->bottomscale;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (screen_info &&
250*4882a593Smuzhiyun (screen_info->mode.hdisplay == 720 &&
251*4882a593Smuzhiyun screen_info->mode.hsync_end == 742 &&
252*4882a593Smuzhiyun screen_info->mode.vdisplay == 480)) {
253*4882a593Smuzhiyun mode->hdisplay = 720;
254*4882a593Smuzhiyun mode->hsync_start = 736;
255*4882a593Smuzhiyun mode->hsync_end = 742;
256*4882a593Smuzhiyun mode->htotal = 858;
257*4882a593Smuzhiyun mode->vdisplay = 480;
258*4882a593Smuzhiyun mode->vsync_start = 494;
259*4882a593Smuzhiyun mode->vsync_end = 500;
260*4882a593Smuzhiyun mode->vtotal = 525;
261*4882a593Smuzhiyun mode->clock = 27000;
262*4882a593Smuzhiyun } else {
263*4882a593Smuzhiyun mode->hdisplay = 720;
264*4882a593Smuzhiyun mode->hsync_start = 732;
265*4882a593Smuzhiyun mode->hsync_end = 738;
266*4882a593Smuzhiyun mode->htotal = 864;
267*4882a593Smuzhiyun mode->vdisplay = 576;
268*4882a593Smuzhiyun mode->vsync_start = 582;
269*4882a593Smuzhiyun mode->vsync_end = 588;
270*4882a593Smuzhiyun mode->vtotal = 625;
271*4882a593Smuzhiyun mode->clock = 27000;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
rk1000_tve_get_timing(struct udevice * dev)275*4882a593Smuzhiyun static int rk1000_tve_get_timing(struct udevice *dev)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct rockchip_bridge *bridge =
278*4882a593Smuzhiyun (struct rockchip_bridge *)dev_get_driver_data(dev);
279*4882a593Smuzhiyun struct connector_state *conn_state = &bridge->state->conn_state;
280*4882a593Smuzhiyun struct drm_display_mode *mode = &conn_state->mode;
281*4882a593Smuzhiyun struct overscan *overscan = &conn_state->overscan;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun drm_rk1000_select_output(overscan, mode);
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun return 0;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static const struct rockchip_bridge_funcs rk1000_tve_bridge_funcs = {
289*4882a593Smuzhiyun .enable = rk1000_tve_bridge_enable,
290*4882a593Smuzhiyun .disable = rk1000_tve_bridge_disable,
291*4882a593Smuzhiyun };
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun static struct rockchip_bridge rk1000_tve_driver_data = {
294*4882a593Smuzhiyun .funcs = &rk1000_tve_bridge_funcs,
295*4882a593Smuzhiyun };
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun struct video_bridge_ops rk1000_tve_ops = {
298*4882a593Smuzhiyun .get_timing = rk1000_tve_get_timing,
299*4882a593Smuzhiyun };
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun static const struct udevice_id rk1000_tve_ids[] = {
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun .compatible = "rockchip,rk1000-tve",
304*4882a593Smuzhiyun .data = (ulong)&rk1000_tve_driver_data,
305*4882a593Smuzhiyun },
306*4882a593Smuzhiyun { }
307*4882a593Smuzhiyun };
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun U_BOOT_DRIVER(rk1000_tve) = {
310*4882a593Smuzhiyun .name = "rk1000_tve",
311*4882a593Smuzhiyun .id = UCLASS_VIDEO_BRIDGE,
312*4882a593Smuzhiyun .of_match = rk1000_tve_ids,
313*4882a593Smuzhiyun .ops = &rk1000_tve_ops,
314*4882a593Smuzhiyun .probe = rk1000_tve_probe,
315*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct rk1000_tve),
316*4882a593Smuzhiyun };
317