xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rockchip_tve.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
3*4882a593Smuzhiyun  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun #include <common.h>
6*4882a593Smuzhiyun #include <malloc.h>
7*4882a593Smuzhiyun #include <fdtdec.h>
8*4882a593Smuzhiyun #include <fdt_support.h>
9*4882a593Smuzhiyun #include <asm/io.h>
10*4882a593Smuzhiyun #include <linux/media-bus-format.h>
11*4882a593Smuzhiyun #include <asm/arch-rockchip/clock.h>
12*4882a593Smuzhiyun #include <dm/device.h>
13*4882a593Smuzhiyun #include <dm/read.h>
14*4882a593Smuzhiyun #include <dm/uclass-internal.h>
15*4882a593Smuzhiyun #include <linux/fb.h>
16*4882a593Smuzhiyun #include <edid.h>
17*4882a593Smuzhiyun #include <syscon.h>
18*4882a593Smuzhiyun #include <boot_rkimg.h>
19*4882a593Smuzhiyun #include <mapmem.h>
20*4882a593Smuzhiyun #include <misc.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "rockchip_display.h"
23*4882a593Smuzhiyun #include "rockchip_crtc.h"
24*4882a593Smuzhiyun #include "rockchip_connector.h"
25*4882a593Smuzhiyun #include "rockchip_phy.h"
26*4882a593Smuzhiyun #include "rockchip_tve.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define RK322X_VDAC_STANDARD		0x15
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun static const struct drm_display_mode tve_modes[] = {
31*4882a593Smuzhiyun 	/* 0 - 720x576i@50Hz */
32*4882a593Smuzhiyun 	{ DRM_MODE(DRM_MODE_TYPE_DRIVER, 13500, 720, 753,
33*4882a593Smuzhiyun 		   816, 864, 576, 580, 586, 625, 0,
34*4882a593Smuzhiyun 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
35*4882a593Smuzhiyun 		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
36*4882a593Smuzhiyun 		   .vrefresh = 50, },
37*4882a593Smuzhiyun 	/* 1 - 720x480i@60Hz */
38*4882a593Smuzhiyun 	{ DRM_MODE(DRM_MODE_TYPE_DRIVER, 13500, 720, 753,
39*4882a593Smuzhiyun 		   815, 858, 480, 483, 486, 525, 0,
40*4882a593Smuzhiyun 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
41*4882a593Smuzhiyun 		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
42*4882a593Smuzhiyun 		   .vrefresh = 60, },
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun struct env_config {
46*4882a593Smuzhiyun 	u32 offset;
47*4882a593Smuzhiyun 	u32 value;
48*4882a593Smuzhiyun };
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun static struct env_config ntsc_bt656_config[] = {
51*4882a593Smuzhiyun 	{ BT656_DECODER_CROP, 0x00000000 },
52*4882a593Smuzhiyun 	{ BT656_DECODER_SIZE, 0x01e002d0 },
53*4882a593Smuzhiyun 	{ BT656_DECODER_HTOTAL_HS_END, 0x035a003e },
54*4882a593Smuzhiyun 	{ BT656_DECODER_VACT_ST_HACT_ST, 0x00160069 },
55*4882a593Smuzhiyun 	{ BT656_DECODER_VTOTAL_VS_END, 0x020d0003 },
56*4882a593Smuzhiyun 	{ BT656_DECODER_VS_ST_END_F1, 0x01060109 },
57*4882a593Smuzhiyun 	{ BT656_DECODER_DBG_REG, 0x024002d0 },
58*4882a593Smuzhiyun 	{ BT656_DECODER_CTRL, 0x00000009 },
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun static struct env_config ntsc_tve_config[] = {
62*4882a593Smuzhiyun 	{ TVE_MODE_CTRL, 0x000af906 },
63*4882a593Smuzhiyun 	{ TVE_HOR_TIMING1, 0x00c07a81 },
64*4882a593Smuzhiyun 	{ TVE_HOR_TIMING2, 0x169810fc },
65*4882a593Smuzhiyun 	{ TVE_HOR_TIMING3, 0x96b40000 },
66*4882a593Smuzhiyun 	{ TVE_SUB_CAR_FRQ, 0x21f07bd7 },
67*4882a593Smuzhiyun 	{ TVE_IMAGE_POSITION, 0x001500d6 },
68*4882a593Smuzhiyun 	{ TVE_ROUTING, 0x10088880 },
69*4882a593Smuzhiyun 	{ TVE_SYNC_ADJUST, 0x00000000 },
70*4882a593Smuzhiyun 	{ TVE_STATUS, 0x00000000 },
71*4882a593Smuzhiyun 	{ TVE_CTRL, 0x00000000 },
72*4882a593Smuzhiyun 	{ TVE_INTR_STATUS, 0x00000000 },
73*4882a593Smuzhiyun 	{ TVE_INTR_EN, 0x00000000 },
74*4882a593Smuzhiyun 	{ TVE_INTR_CLR, 0x00000000 },
75*4882a593Smuzhiyun 	{ TVE_COLOR_BUSRT_SAT, 0x0052543c },
76*4882a593Smuzhiyun 	{ TVE_CHROMA_BANDWIDTH, 0x00000002 },
77*4882a593Smuzhiyun 	{ TVE_BRIGHTNESS_CONTRAST, 0x00008300 },
78*4882a593Smuzhiyun 	{ TVE_CLAMP, 0x00000000 },
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun static struct env_config pal_bt656_config[] = {
82*4882a593Smuzhiyun 	{ BT656_DECODER_CROP, 0x00000000 },
83*4882a593Smuzhiyun 	{ BT656_DECODER_SIZE, 0x024002d0 },
84*4882a593Smuzhiyun 	{ BT656_DECODER_HTOTAL_HS_END, 0x0360003f },
85*4882a593Smuzhiyun 	{ BT656_DECODER_VACT_ST_HACT_ST, 0x0016006f },
86*4882a593Smuzhiyun 	{ BT656_DECODER_VTOTAL_VS_END, 0x02710003 },
87*4882a593Smuzhiyun 	{ BT656_DECODER_VS_ST_END_F1, 0x0138013b },
88*4882a593Smuzhiyun 	{ BT656_DECODER_DBG_REG, 0x024002d0 },
89*4882a593Smuzhiyun 	{ BT656_DECODER_CTRL, 0x00000009 },
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static struct env_config pal_tve_config[] = {
93*4882a593Smuzhiyun 	{ TVE_MODE_CTRL, 0x010ab906 },
94*4882a593Smuzhiyun 	{ TVE_HOR_TIMING1, 0x00c28381 },
95*4882a593Smuzhiyun 	{ TVE_HOR_TIMING2, 0x267d111d },
96*4882a593Smuzhiyun 	{ TVE_HOR_TIMING3, 0x66c00880 },
97*4882a593Smuzhiyun 	{ TVE_SUB_CAR_FRQ, 0x2a098acb },
98*4882a593Smuzhiyun 	{ TVE_IMAGE_POSITION, 0x001500f6 },
99*4882a593Smuzhiyun 	{ TVE_ROUTING, 0x10008882 },
100*4882a593Smuzhiyun 	{ TVE_SYNC_ADJUST, 0x00000000 },
101*4882a593Smuzhiyun 	{ TVE_STATUS, 0x000000b0 },
102*4882a593Smuzhiyun 	{ TVE_CTRL, 0x00000000 },
103*4882a593Smuzhiyun 	{ TVE_INTR_STATUS, 0x00000000 },
104*4882a593Smuzhiyun 	{ TVE_INTR_EN, 0x00000000 },
105*4882a593Smuzhiyun 	{ TVE_INTR_CLR, 0x00000000 },
106*4882a593Smuzhiyun 	{ TVE_COLOR_BUSRT_SAT, 0x00356245 },
107*4882a593Smuzhiyun 	{ TVE_CHROMA_BANDWIDTH, 0x00000022 },
108*4882a593Smuzhiyun 	{ TVE_BRIGHTNESS_CONTRAST, 0x0000aa00 },
109*4882a593Smuzhiyun 	{ TVE_CLAMP, 0x00000000 },
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun #define BT656_ENV_CONFIG_SIZE		(sizeof(ntsc_bt656_config) / sizeof(struct env_config))
113*4882a593Smuzhiyun #define TVE_ENV_CONFIG_SIZE		(sizeof(ntsc_tve_config) / sizeof(struct env_config))
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #define tve_writel(offset, v)		writel(v, tve->reg_base  + offset)
116*4882a593Smuzhiyun #define tve_readl(offset)		readl(tve->reg_base + offset)
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun #define tve_dac_writel(offset, v)	writel(v, tve->vdac_base + offset)
119*4882a593Smuzhiyun #define tve_dac_readl(offset)		readl(tve->vdac_base + offset)
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun #define tve_grf_writel(offset, v)	writel(v, tve->grf + offset)
122*4882a593Smuzhiyun #define tve_grf_readl(offset, v)	readl(tve->grf + offset)
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun struct rockchip_tve_data {
125*4882a593Smuzhiyun 	int	input_format;
126*4882a593Smuzhiyun 	int	soc_type;
127*4882a593Smuzhiyun };
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun struct rockchip_tve {
130*4882a593Smuzhiyun 	struct	rockchip_connector connector;
131*4882a593Smuzhiyun 	struct	udevice *dev;
132*4882a593Smuzhiyun 	void	*reg_base;
133*4882a593Smuzhiyun 	void	*vdac_base;
134*4882a593Smuzhiyun 	int	soc_type;
135*4882a593Smuzhiyun 	int	input_format;
136*4882a593Smuzhiyun 	int 	tv_format;
137*4882a593Smuzhiyun 	int	test_mode;
138*4882a593Smuzhiyun 	int	saturation;
139*4882a593Smuzhiyun 	int	brightcontrast;
140*4882a593Smuzhiyun 	int	adjtiming;
141*4882a593Smuzhiyun 	int	lumafilter0;
142*4882a593Smuzhiyun 	int	lumafilter1;
143*4882a593Smuzhiyun 	int	lumafilter2;
144*4882a593Smuzhiyun 	int	lumafilter3;
145*4882a593Smuzhiyun 	int	lumafilter4;
146*4882a593Smuzhiyun 	int	lumafilter5;
147*4882a593Smuzhiyun 	int	lumafilter6;
148*4882a593Smuzhiyun 	int	lumafilter7;
149*4882a593Smuzhiyun 	int	daclevel;
150*4882a593Smuzhiyun 	int	dac1level;
151*4882a593Smuzhiyun 	int	preferred_mode;
152*4882a593Smuzhiyun 	int	upsample_mode;
153*4882a593Smuzhiyun 	void	*grf;
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun 
tve_write_block(struct rockchip_tve * tve,struct env_config * config,int len)156*4882a593Smuzhiyun static void tve_write_block(struct rockchip_tve *tve, struct env_config *config, int len)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	int i;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	for (i = 0; i < len; i++)
161*4882a593Smuzhiyun 		tve_writel(config[i].offset, config[i].value);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
tve_set_mode(struct rockchip_tve * tve)164*4882a593Smuzhiyun static void tve_set_mode(struct rockchip_tve *tve)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	struct env_config *bt656_cfg, *tve_cfg;
167*4882a593Smuzhiyun 	int mode = tve->tv_format;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK3528) {
170*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER1, tve->lumafilter0);
171*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER2, tve->lumafilter1);
172*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER3, tve->lumafilter2);
173*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER4, tve->lumafilter3);
174*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER5, tve->lumafilter4);
175*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER6, tve->lumafilter5);
176*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER7, tve->lumafilter6);
177*4882a593Smuzhiyun 		tve_writel(TVE_LUMA_FILTER8, tve->lumafilter7);
178*4882a593Smuzhiyun 	} else {
179*4882a593Smuzhiyun 		if (tve->input_format == INPUT_FORMAT_RGB)
180*4882a593Smuzhiyun 			tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
181*4882a593Smuzhiyun 				v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
182*4882a593Smuzhiyun 				v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(0));
183*4882a593Smuzhiyun 		else
184*4882a593Smuzhiyun 			tve_writel(TV_CTRL, v_CVBS_MODE(mode) | v_CLK_UPSTREAM_EN(2) |
185*4882a593Smuzhiyun 				v_TIMING_EN(2) | v_LUMA_FILTER_GAIN(0) |
186*4882a593Smuzhiyun 				v_LUMA_FILTER_UPSAMPLE(1) | v_CSC_PATH(3));
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 		tve_writel(TV_LUMA_FILTER0, tve->lumafilter0);
189*4882a593Smuzhiyun 		tve_writel(TV_LUMA_FILTER1, tve->lumafilter1);
190*4882a593Smuzhiyun 		tve_writel(TV_LUMA_FILTER2, tve->lumafilter2);
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	if (mode == TVOUT_CVBS_NTSC) {
194*4882a593Smuzhiyun 		TVEDBG("tve set ntsc mode\n");
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 		if (tve->soc_type == SOC_RK3528) {
197*4882a593Smuzhiyun 			bt656_cfg = ntsc_bt656_config;
198*4882a593Smuzhiyun 			tve_cfg = ntsc_tve_config;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 			tve_write_block(tve, bt656_cfg, BT656_ENV_CONFIG_SIZE);
201*4882a593Smuzhiyun 			tve_write_block(tve, tve_cfg, TVE_ENV_CONFIG_SIZE);
202*4882a593Smuzhiyun 		} else {
203*4882a593Smuzhiyun 			tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(1) |
204*4882a593Smuzhiyun 				   v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
205*4882a593Smuzhiyun 				   v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
206*4882a593Smuzhiyun 			tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_NTSC) |
207*4882a593Smuzhiyun 				   v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
208*4882a593Smuzhiyun 			tve_writel(TV_SATURATION, 0x0042543C);
209*4882a593Smuzhiyun 			if (tve->test_mode)
210*4882a593Smuzhiyun 				tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00008300);
211*4882a593Smuzhiyun 			else
212*4882a593Smuzhiyun 				tve_writel(TV_BRIGHTNESS_CONTRAST, 0x00007900);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 			tve_writel(TV_FREQ_SC,	0x21F07BD7);
215*4882a593Smuzhiyun 			tve_writel(TV_SYNC_TIMING, 0x00C07a81);
216*4882a593Smuzhiyun 			tve_writel(TV_ADJ_TIMING, 0x96B40000 | 0x70);
217*4882a593Smuzhiyun 			tve_writel(TV_ACT_ST,	0x001500D6);
218*4882a593Smuzhiyun 			tve_writel(TV_ACT_TIMING, 0x069800FC | (1 << 12) | (1 << 28));
219*4882a593Smuzhiyun 		}
220*4882a593Smuzhiyun 	} else if (mode == TVOUT_CVBS_PAL) {
221*4882a593Smuzhiyun 		TVEDBG("tve set pal mode\n");
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 		if (tve->soc_type == SOC_RK3528) {
224*4882a593Smuzhiyun 			bt656_cfg = pal_bt656_config;
225*4882a593Smuzhiyun 			tve_cfg = pal_tve_config;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 			tve_write_block(tve, bt656_cfg, BT656_ENV_CONFIG_SIZE);
228*4882a593Smuzhiyun 			tve_write_block(tve, tve_cfg, TVE_ENV_CONFIG_SIZE);
229*4882a593Smuzhiyun 		} else {
230*4882a593Smuzhiyun 			tve_writel(TV_ROUTING, v_DAC_SENSE_EN(0) | v_Y_IRE_7_5(0) |
231*4882a593Smuzhiyun 				   v_Y_AGC_PULSE_ON(0) | v_Y_VIDEO_ON(1) |
232*4882a593Smuzhiyun 				   v_YPP_MODE(1) | v_Y_SYNC_ON(1) | v_PIC_MODE(mode));
233*4882a593Smuzhiyun 			tve_writel(TV_BW_CTRL, v_CHROMA_BW(BP_FILTER_PAL) |
234*4882a593Smuzhiyun 				   v_COLOR_DIFF_BW(COLOR_DIFF_FILTER_BW_1_3));
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 			tve_writel(TV_SATURATION, tve->saturation);
237*4882a593Smuzhiyun 			tve_writel(TV_BRIGHTNESS_CONTRAST, tve->brightcontrast);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 			tve_writel(TV_FREQ_SC,	0x2A098ACB);
240*4882a593Smuzhiyun 			tve_writel(TV_SYNC_TIMING, 0x00C28381);
241*4882a593Smuzhiyun 			tve_writel(TV_ADJ_TIMING, (0xc << 28) | 0x06c00800 | 0x80);
242*4882a593Smuzhiyun 			tve_writel(TV_ACT_ST,	0x001500F6);
243*4882a593Smuzhiyun 			tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 			tve_writel(TV_ADJ_TIMING, tve->adjtiming);
246*4882a593Smuzhiyun 			tve_writel(TV_ACT_TIMING, 0x0694011D | (1 << 12) | (2 << 28));
247*4882a593Smuzhiyun 		}
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK3528) {
251*4882a593Smuzhiyun 		u32 upsample_mode = 0;
252*4882a593Smuzhiyun 		u32 mask = 0;
253*4882a593Smuzhiyun 		u32 val = 0;
254*4882a593Smuzhiyun 		bool upsample_en;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 		upsample_en = tve->upsample_mode ? 1 : 0;
257*4882a593Smuzhiyun 		if (upsample_en)
258*4882a593Smuzhiyun 			upsample_mode = tve->upsample_mode - 1;
259*4882a593Smuzhiyun 		mask = m_TVE_DCLK_POL | m_TVE_DCLK_EN | m_DCLK_UPSAMPLE_2X4X |
260*4882a593Smuzhiyun 		       m_DCLK_UPSAMPLE_EN | m_TVE_MODE | m_TVE_EN;
261*4882a593Smuzhiyun 		val = v_TVE_DCLK_POL(0) | v_TVE_DCLK_EN(1) | v_DCLK_UPSAMPLE_2X4X(upsample_mode) |
262*4882a593Smuzhiyun 		      v_DCLK_UPSAMPLE_EN(upsample_en) | v_TVE_MODE(tve->tv_format) | v_TVE_EN(1);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 		tve_grf_writel(RK3528_VO_GRF_CVBS_CON, (mask << 16) | val);
265*4882a593Smuzhiyun 	}
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
dac_init(struct rockchip_tve * tve)268*4882a593Smuzhiyun static void dac_init(struct rockchip_tve *tve)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	tve_dac_writel(VDAC_VDAC1, v_CUR_REG(tve->dac1level) |
271*4882a593Smuzhiyun 				   m_DR_PWR_DOWN | m_BG_PWR_DOWN);
272*4882a593Smuzhiyun 	tve_dac_writel(VDAC_VDAC2, v_CUR_CTR(tve->daclevel));
273*4882a593Smuzhiyun 	tve_dac_writel(VDAC_VDAC3, v_CAB_EN(0));
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
dac_enable(struct rockchip_tve * tve,bool enable)276*4882a593Smuzhiyun static void dac_enable(struct rockchip_tve *tve, bool enable)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	u32 mask = 0;
279*4882a593Smuzhiyun 	u32 val = 0;
280*4882a593Smuzhiyun 	u32 grfreg = 0;
281*4882a593Smuzhiyun 	u32 offset = 0;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	if (enable) {
284*4882a593Smuzhiyun 		TVEDBG("tve enable\n");
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 		if (tve->soc_type == SOC_RK3036) {
287*4882a593Smuzhiyun 			mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN;
288*4882a593Smuzhiyun 			val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel);
289*4882a593Smuzhiyun 			grfreg = RK3036_GRF_SOC_CON3;
290*4882a593Smuzhiyun 		} else if (tve->soc_type == SOC_RK312X) {
291*4882a593Smuzhiyun 			mask = m_VBG_EN | m_DAC_EN | m_DAC_GAIN;
292*4882a593Smuzhiyun 			val = m_VBG_EN | m_DAC_EN | v_DAC_GAIN(tve->daclevel);
293*4882a593Smuzhiyun 			grfreg = RK312X_GRF_TVE_CON;
294*4882a593Smuzhiyun 		} else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
295*4882a593Smuzhiyun 			val = v_CUR_REG(tve->dac1level) | v_DR_PWR_DOWN(0) | v_BG_PWR_DOWN(0);
296*4882a593Smuzhiyun 		} else if (tve->soc_type == SOC_RK3528) {
297*4882a593Smuzhiyun 			/*
298*4882a593Smuzhiyun 			 * Reset the vdac
299*4882a593Smuzhiyun 			 */
300*4882a593Smuzhiyun 			tve_dac_writel(VDAC_CLK_RST, v_ANALOG_RST(0) | v_DIGITAL_RST(0));
301*4882a593Smuzhiyun 			mdelay(20);
302*4882a593Smuzhiyun 			tve_dac_writel(VDAC_CLK_RST, v_ANALOG_RST(1) | v_DIGITAL_RST(1));
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 			tve_dac_writel(VDAC_CURRENT_CTRL, v_OUT_CURRENT(0xd2));
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 			val = v_REF_VOLTAGE(7) | v_DAC_PWN(1) | v_BIAS_PWN(1);
307*4882a593Smuzhiyun 			offset = VDAC_PWM_REF_CTRL;
308*4882a593Smuzhiyun 		}
309*4882a593Smuzhiyun 	} else {
310*4882a593Smuzhiyun 		TVEDBG("tve disable\n");
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 		if (tve->soc_type == SOC_RK312X) {
313*4882a593Smuzhiyun 			mask = m_VBG_EN | m_DAC_EN;
314*4882a593Smuzhiyun 			grfreg = RK312X_GRF_TVE_CON;
315*4882a593Smuzhiyun 		} else if (tve->soc_type == SOC_RK3036) {
316*4882a593Smuzhiyun 			mask = m_VBG_EN | m_DAC_EN;
317*4882a593Smuzhiyun 			grfreg = RK3036_GRF_SOC_CON3;
318*4882a593Smuzhiyun 		} else if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
319*4882a593Smuzhiyun 			val = v_CUR_REG(tve->dac1level) | m_DR_PWR_DOWN | m_BG_PWR_DOWN;
320*4882a593Smuzhiyun 			offset = VDAC_VDAC1;
321*4882a593Smuzhiyun 		} else if (tve->soc_type == SOC_RK3528) {
322*4882a593Smuzhiyun 			val = v_DAC_PWN(0) | v_BIAS_PWN(0);
323*4882a593Smuzhiyun 			offset = VDAC_PWM_REF_CTRL;
324*4882a593Smuzhiyun 		}
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	if (grfreg)
328*4882a593Smuzhiyun 		tve_grf_writel(grfreg, (mask << 16) | val);
329*4882a593Smuzhiyun 	else if (tve->vdac_base)
330*4882a593Smuzhiyun 		tve_dac_writel(offset, val);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun 
rk_get_vdac_value(void)333*4882a593Smuzhiyun static u8 rk_get_vdac_value(void)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun 	u8 value = 0;
336*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_EFUSE
337*4882a593Smuzhiyun #if defined(CONFIG_ROCKCHIP_RK322X)
338*4882a593Smuzhiyun 	struct udevice *dev;
339*4882a593Smuzhiyun 	u32 regs[2] = {0};
340*4882a593Smuzhiyun 	u8 fuses[1];
341*4882a593Smuzhiyun 	ofnode node;
342*4882a593Smuzhiyun 	int ret;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(rockchip_efuse), &dev);
345*4882a593Smuzhiyun 	if (ret) {
346*4882a593Smuzhiyun 		printf("%s: no misc-device found\n", __func__);
347*4882a593Smuzhiyun 		return -EINVAL;
348*4882a593Smuzhiyun 	}
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	node = dev_read_subnode(dev, "tve_dac");
351*4882a593Smuzhiyun 	if (!ofnode_valid(node))
352*4882a593Smuzhiyun 		return -EINVAL;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	ret = ofnode_read_u32_array(node, "reg", regs, 2);
355*4882a593Smuzhiyun 	if (ret) {
356*4882a593Smuzhiyun 		printf("Cannot get efuse reg\n");
357*4882a593Smuzhiyun 		return -EINVAL;
358*4882a593Smuzhiyun 	}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	ret = misc_read(dev, regs[0], &fuses, regs[1]);
361*4882a593Smuzhiyun 	if (ret) {
362*4882a593Smuzhiyun 		printf("%s: misc_read failed\n", __func__);
363*4882a593Smuzhiyun 		return 0;
364*4882a593Smuzhiyun 	}
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	value = fuses[0];
367*4882a593Smuzhiyun 	value = (value >> 3) & 0x1f;
368*4882a593Smuzhiyun #endif
369*4882a593Smuzhiyun #endif /* CONFIG_RK_EFUSE */
370*4882a593Smuzhiyun 	if (value > 0)
371*4882a593Smuzhiyun 		value += 5;
372*4882a593Smuzhiyun 	TVEDBG("%s value = 0x%x\n", __func__, value);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	return value;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
tve_parse_dt(struct rockchip_tve * tve)377*4882a593Smuzhiyun static int tve_parse_dt(struct rockchip_tve *tve)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	tve->preferred_mode = dev_read_u32_default(tve->dev, "rockchip,tvemode", -1);
380*4882a593Smuzhiyun 	if (tve->preferred_mode < 0) {
381*4882a593Smuzhiyun 		tve->preferred_mode = 0;
382*4882a593Smuzhiyun 	} else if (tve->preferred_mode > 1) {
383*4882a593Smuzhiyun 		printf("tve mode value invalid\n");
384*4882a593Smuzhiyun 		return -EINVAL;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	tve->lumafilter0 = dev_read_u32_default(tve->dev, "rockchip,lumafilter0", 0);
388*4882a593Smuzhiyun 	if (tve->lumafilter0 == 0) {
389*4882a593Smuzhiyun 		printf("tve get lumafilter0 err\n");
390*4882a593Smuzhiyun 		return -EINVAL;
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	tve->lumafilter1 = dev_read_u32_default(tve->dev, "rockchip,lumafilter1", 0);
394*4882a593Smuzhiyun 	if (tve->lumafilter1 == 0) {
395*4882a593Smuzhiyun 		printf("tve get lumafilter1 err\n");
396*4882a593Smuzhiyun 		return -EINVAL;
397*4882a593Smuzhiyun 	}
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	tve->lumafilter2 = dev_read_u32_default(tve->dev, "rockchip,lumafilter2", 0);
400*4882a593Smuzhiyun 	if (tve->lumafilter2 == 0) {
401*4882a593Smuzhiyun 		printf("tve get lumafilter2 err\n");
402*4882a593Smuzhiyun 		return -EINVAL;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	tve->lumafilter3 = dev_read_u32_default(tve->dev, "rockchip,lumafilter3", 0);
406*4882a593Smuzhiyun 	if (tve->lumafilter3 == 0) {
407*4882a593Smuzhiyun 		printf("tve get lumafilter3 err\n");
408*4882a593Smuzhiyun 		return -EINVAL;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	tve->lumafilter4 = dev_read_u32_default(tve->dev, "rockchip,lumafilter4", 0);
412*4882a593Smuzhiyun 	if (tve->lumafilter4 == 0) {
413*4882a593Smuzhiyun 		printf("tve get lumafilter4 err\n");
414*4882a593Smuzhiyun 		return -EINVAL;
415*4882a593Smuzhiyun 	}
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	tve->lumafilter5 = dev_read_u32_default(tve->dev, "rockchip,lumafilter5", 0);
418*4882a593Smuzhiyun 	if (tve->lumafilter5 == 0) {
419*4882a593Smuzhiyun 		printf("tve get lumafilter5 err\n");
420*4882a593Smuzhiyun 		return -EINVAL;
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	tve->lumafilter6 = dev_read_u32_default(tve->dev, "rockchip,lumafilter6", 0);
424*4882a593Smuzhiyun 	if (tve->lumafilter6 == 0) {
425*4882a593Smuzhiyun 		printf("tve get lumafilter6 err\n");
426*4882a593Smuzhiyun 		return -EINVAL;
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	tve->lumafilter7 = dev_read_u32_default(tve->dev, "rockchip,lumafilter7", 0);
430*4882a593Smuzhiyun 	if (tve->lumafilter7 == 0) {
431*4882a593Smuzhiyun 		printf("tve get lumafilter7 err\n");
432*4882a593Smuzhiyun 		return -EINVAL;
433*4882a593Smuzhiyun 	}
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	tve->upsample_mode = dev_read_u32_default(tve->dev, "rockchip,tve-upsample", -1);
436*4882a593Smuzhiyun 	if (tve->upsample_mode < 0 || tve->upsample_mode > DCLK_UPSAMPLEx4) {
437*4882a593Smuzhiyun 		printf("tve get upsample_mode err\n");
438*4882a593Smuzhiyun 		return -EINVAL;
439*4882a593Smuzhiyun 	}
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	TVEDBG("tve->preferred_mode = 0x%x\n", tve->preferred_mode);
442*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter0 = 0x%x\n", tve->lumafilter0);
443*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter1 = 0x%x\n", tve->lumafilter1);
444*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter2 = 0x%x\n", tve->lumafilter2);
445*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter3 = 0x%x\n", tve->lumafilter3);
446*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter4 = 0x%x\n", tve->lumafilter4);
447*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter5 = 0x%x\n", tve->lumafilter5);
448*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter6 = 0x%x\n", tve->lumafilter6);
449*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter7 = 0x%x\n", tve->lumafilter7);
450*4882a593Smuzhiyun 	TVEDBG("tve->upsample_mode = 0x%x\n", tve->upsample_mode);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	return 0;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
tve_parse_dt_legacy(struct rockchip_tve * tve)455*4882a593Smuzhiyun static int tve_parse_dt_legacy(struct rockchip_tve *tve)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	int dac_value, getvdac;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK312X)
460*4882a593Smuzhiyun 		tve->test_mode = dev_read_u32_default(tve->dev, "test_mode", 0);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	tve->preferred_mode = dev_read_u32_default(tve->dev, "rockchip,tvemode", -1);
463*4882a593Smuzhiyun 	if (tve->preferred_mode < 0) {
464*4882a593Smuzhiyun 		tve->preferred_mode = 0;
465*4882a593Smuzhiyun 	} else if (tve->preferred_mode > 1) {
466*4882a593Smuzhiyun 		printf("tve mode value invalid\n");
467*4882a593Smuzhiyun 		return -EINVAL;
468*4882a593Smuzhiyun 	}
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	tve->saturation = dev_read_u32_default(tve->dev, "rockchip,saturation", 0);
471*4882a593Smuzhiyun 	if (tve->saturation == 0) {
472*4882a593Smuzhiyun 		printf("tve get saturation err\n");
473*4882a593Smuzhiyun 		return -EINVAL;
474*4882a593Smuzhiyun 	}
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	tve->brightcontrast = dev_read_u32_default(tve->dev, "rockchip,brightcontrast", 0);
477*4882a593Smuzhiyun 	if (tve->brightcontrast == 0) {
478*4882a593Smuzhiyun 		printf("tve get brightcontrast err\n");
479*4882a593Smuzhiyun 		return -EINVAL;
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	tve->adjtiming = dev_read_u32_default(tve->dev, "rockchip,adjtiming", 0);
483*4882a593Smuzhiyun 	if (tve->adjtiming == 0) {
484*4882a593Smuzhiyun 		printf("tve get adjtiming err\n");
485*4882a593Smuzhiyun 		return -EINVAL;
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	tve->lumafilter0 = dev_read_u32_default(tve->dev, "rockchip,lumafilter0", 0);
489*4882a593Smuzhiyun 	if (tve->lumafilter0 == 0) {
490*4882a593Smuzhiyun 		printf("tve get lumafilter0 err\n");
491*4882a593Smuzhiyun 		return -EINVAL;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	tve->lumafilter1 = dev_read_u32_default(tve->dev, "rockchip,lumafilter1", 0);
495*4882a593Smuzhiyun 	if (tve->lumafilter1 == 0) {
496*4882a593Smuzhiyun 		printf("tve get lumafilter1 err\n");
497*4882a593Smuzhiyun 		return -EINVAL;
498*4882a593Smuzhiyun 	}
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	tve->lumafilter2 = dev_read_u32_default(tve->dev, "rockchip,lumafilter2", 0);
501*4882a593Smuzhiyun 	if (tve->lumafilter2 == 0) {
502*4882a593Smuzhiyun 		printf("tve get lumafilter2 err\n");
503*4882a593Smuzhiyun 		return -EINVAL;
504*4882a593Smuzhiyun 	}
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	dac_value = dev_read_u32_default(tve->dev, "rockchip,daclevel", 0);
507*4882a593Smuzhiyun 	if (dac_value == 0) {
508*4882a593Smuzhiyun 		printf("tve get dac_value err\n");
509*4882a593Smuzhiyun 		return -EINVAL;
510*4882a593Smuzhiyun 	}
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	tve->daclevel = dac_value;
513*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
514*4882a593Smuzhiyun 		getvdac = rk_get_vdac_value();
515*4882a593Smuzhiyun 		if (getvdac > 0) {
516*4882a593Smuzhiyun 			tve->daclevel = dac_value + getvdac - RK322X_VDAC_STANDARD;
517*4882a593Smuzhiyun 			if (tve->daclevel > 0x3f || tve->daclevel < 0) {
518*4882a593Smuzhiyun 				printf("rk322x daclevel error!\n");
519*4882a593Smuzhiyun 				tve->daclevel = dac_value;
520*4882a593Smuzhiyun 			}
521*4882a593Smuzhiyun 		} else if (getvdac < 0) {
522*4882a593Smuzhiyun 			printf("get rk322x daclevel error\n");
523*4882a593Smuzhiyun 			return -EINVAL;
524*4882a593Smuzhiyun 		}
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328) {
528*4882a593Smuzhiyun 		tve->dac1level = dev_read_u32_default(tve->dev, "rockchip,dac1level", 0);
529*4882a593Smuzhiyun 		if (tve->dac1level == 0) {
530*4882a593Smuzhiyun 			printf("rk322x dac1level error!\n");
531*4882a593Smuzhiyun 			return -EINVAL;
532*4882a593Smuzhiyun 		}
533*4882a593Smuzhiyun 	}
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	TVEDBG("tve->test_mode = 0x%x\n", tve->test_mode);
536*4882a593Smuzhiyun 	TVEDBG("tve->saturation = 0x%x\n", tve->saturation);
537*4882a593Smuzhiyun 	TVEDBG("tve->brightcontrast = 0x%x\n", tve->brightcontrast);
538*4882a593Smuzhiyun 	TVEDBG("tve->adjtiming = 0x%x\n", tve->adjtiming);
539*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter0 = 0x%x\n", tve->lumafilter0);
540*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter1 = 0x%x\n", tve->lumafilter1);
541*4882a593Smuzhiyun 	TVEDBG("tve->lumafilter2 = 0x%x\n", tve->lumafilter2);
542*4882a593Smuzhiyun 	TVEDBG("tve->daclevel = 0x%x\n", tve->daclevel);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	return 0;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
rockchip_drm_tve_init(struct rockchip_connector * conn,struct display_state * state)547*4882a593Smuzhiyun static int rockchip_drm_tve_init(struct rockchip_connector *conn, struct display_state *state)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct rockchip_tve *tve = dev_get_priv(conn->dev);
550*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
551*4882a593Smuzhiyun 	fdt_addr_t addr;
552*4882a593Smuzhiyun 	int ret;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	conn_state->output_mode = ROCKCHIP_OUT_MODE_P888;
555*4882a593Smuzhiyun 	conn_state->bus_format = MEDIA_BUS_FMT_YUV8_1X24;
556*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK3528)
557*4882a593Smuzhiyun 		conn_state->output_if |= VOP_OUTPUT_IF_BT656;
558*4882a593Smuzhiyun 	conn_state->color_space = V4L2_COLORSPACE_SMPTE170M;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 	conn_state->disp_info = rockchip_get_disp_info(conn_state->type, 0);
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK3528)
563*4882a593Smuzhiyun 		ret = tve_parse_dt(tve);
564*4882a593Smuzhiyun 	else
565*4882a593Smuzhiyun 		ret = tve_parse_dt_legacy(tve);
566*4882a593Smuzhiyun 	if (ret) {
567*4882a593Smuzhiyun 		printf("tve parse dts error\n");
568*4882a593Smuzhiyun 		return -EINVAL;
569*4882a593Smuzhiyun 	}
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	addr = dev_read_addr_index(conn->dev, 0);
572*4882a593Smuzhiyun 	if (addr == FDT_ADDR_T_NONE) {
573*4882a593Smuzhiyun 		printf("failed to get tve reg_base\n");
574*4882a593Smuzhiyun 		return -EINVAL;
575*4882a593Smuzhiyun 	}
576*4882a593Smuzhiyun 	tve->reg_base = (void *)addr;
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328 ||
579*4882a593Smuzhiyun 	    tve->soc_type == SOC_RK3528) {
580*4882a593Smuzhiyun 		addr = dev_read_addr_index(conn->dev, 1);
581*4882a593Smuzhiyun 		if (addr == FDT_ADDR_T_NONE) {
582*4882a593Smuzhiyun 			printf("failed to get tve vdac_base\n");
583*4882a593Smuzhiyun 			return -EINVAL;
584*4882a593Smuzhiyun 		}
585*4882a593Smuzhiyun 		tve->vdac_base = (void *)addr;
586*4882a593Smuzhiyun 	}
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	tve->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	if (tve->soc_type == SOC_RK322X || tve->soc_type == SOC_RK3328)
591*4882a593Smuzhiyun 		dac_init(tve);
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	return 0;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun 
rockchip_drm_tve_enable(struct rockchip_connector * conn,struct display_state * state)596*4882a593Smuzhiyun static int rockchip_drm_tve_enable(struct rockchip_connector *conn, struct display_state *state)
597*4882a593Smuzhiyun {
598*4882a593Smuzhiyun 	struct rockchip_tve *tve = dev_get_priv(conn->dev);
599*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
600*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_INNO_HDMI_PHY
603*4882a593Smuzhiyun 	/* set inno hdmi phy clk. */
604*4882a593Smuzhiyun 	if (tve->soc_type != SOC_RK3528)
605*4882a593Smuzhiyun 		rockchip_phy_set_pll(conn->phy, 27000000);
606*4882a593Smuzhiyun #endif
607*4882a593Smuzhiyun 	if (mode->vdisplay == 576)
608*4882a593Smuzhiyun 		tve->tv_format = TVOUT_CVBS_PAL;
609*4882a593Smuzhiyun 	else
610*4882a593Smuzhiyun 		tve->tv_format = TVOUT_CVBS_NTSC;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	tve_set_mode(tve);
613*4882a593Smuzhiyun 	mdelay(1000);
614*4882a593Smuzhiyun 	dac_enable(tve, true);
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	return 0;
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun 
rockchip_drm_tve_deinit(struct rockchip_connector * conn,struct display_state * state)619*4882a593Smuzhiyun static void rockchip_drm_tve_deinit(struct rockchip_connector *conn, struct display_state *state)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun 	struct rockchip_tve *tve = dev_get_priv(conn->dev);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	dac_enable(tve, false);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun 
rockchip_drm_tve_prepare(struct rockchip_connector * conn,struct display_state * state)626*4882a593Smuzhiyun static int rockchip_drm_tve_prepare(struct rockchip_connector *conn, struct display_state *state)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun 	return 0;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun 
rockchip_drm_tve_disable(struct rockchip_connector * conn,struct display_state * state)631*4882a593Smuzhiyun static int rockchip_drm_tve_disable(struct rockchip_connector *conn, struct display_state *state)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	struct rockchip_tve *tve = dev_get_priv(conn->dev);
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	dac_enable(tve, false);
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	return 0;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun 
rockchip_drm_tve_detect(struct rockchip_connector * conn,struct display_state * state)640*4882a593Smuzhiyun static int rockchip_drm_tve_detect(struct rockchip_connector *conn, struct display_state *state)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun 	return 1;
643*4882a593Smuzhiyun }
644*4882a593Smuzhiyun 
tve_select_output(struct rockchip_tve * tve,struct connector_state * conn_state,struct drm_display_mode * mode)645*4882a593Smuzhiyun static void tve_select_output(struct rockchip_tve *tve, struct connector_state *conn_state,
646*4882a593Smuzhiyun 			      struct drm_display_mode *mode)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun 	int ret, i, screen_size;
649*4882a593Smuzhiyun 	struct base_screen_info *screen_info = NULL;
650*4882a593Smuzhiyun 	struct base2_screen_info *screen_info2 = NULL;
651*4882a593Smuzhiyun 	struct base_disp_info base_parameter;
652*4882a593Smuzhiyun 	struct base2_disp_info *base2_parameter = conn_state->disp_info;
653*4882a593Smuzhiyun 	struct drm_display_mode modes[2];
654*4882a593Smuzhiyun 	const struct base_overscan *scan;
655*4882a593Smuzhiyun 	struct overscan *overscan = &conn_state->overscan;
656*4882a593Smuzhiyun 	char baseparameter_buf[8 * RK_BLK_SIZE] __aligned(ARCH_DMA_MINALIGN);
657*4882a593Smuzhiyun 	struct blk_desc *dev_desc;
658*4882a593Smuzhiyun 	disk_partition_t part_info;
659*4882a593Smuzhiyun 	int max_scan = 100;
660*4882a593Smuzhiyun 	int min_scan = 50;
661*4882a593Smuzhiyun 	int offset = 0;
662*4882a593Smuzhiyun 	bool found = false;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	for (i = 0; i < 2; i++) {
665*4882a593Smuzhiyun 		modes[i] = tve_modes[i];
666*4882a593Smuzhiyun 		if (i == tve->preferred_mode)
667*4882a593Smuzhiyun 			modes[i].type |= DRM_MODE_TYPE_PREFERRED;
668*4882a593Smuzhiyun 	}
669*4882a593Smuzhiyun 	*mode = modes[tve->preferred_mode];
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	if (!base2_parameter) {
672*4882a593Smuzhiyun 		dev_desc = rockchip_get_bootdev();
673*4882a593Smuzhiyun 		if (!dev_desc) {
674*4882a593Smuzhiyun 			printf("%s: Could not find device\n", __func__);
675*4882a593Smuzhiyun 			goto null_basep;
676*4882a593Smuzhiyun 		}
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 		ret = part_get_info_by_name(dev_desc, "baseparameter",
679*4882a593Smuzhiyun 					    &part_info);
680*4882a593Smuzhiyun 		if (ret < 0) {
681*4882a593Smuzhiyun 			printf("Could not find baseparameter partition\n");
682*4882a593Smuzhiyun 			goto null_basep;
683*4882a593Smuzhiyun 		}
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun read_aux:
686*4882a593Smuzhiyun 		ret = blk_dread(dev_desc, part_info.start + offset, 1,
687*4882a593Smuzhiyun 				(void *)baseparameter_buf);
688*4882a593Smuzhiyun 		if (ret < 0) {
689*4882a593Smuzhiyun 			printf("read baseparameter failed\n");
690*4882a593Smuzhiyun 			goto null_basep;
691*4882a593Smuzhiyun 		}
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 		memcpy(&base_parameter, baseparameter_buf,
694*4882a593Smuzhiyun 		       sizeof(base_parameter));
695*4882a593Smuzhiyun 		scan = &base_parameter.scan;
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 		screen_size = sizeof(base_parameter.screen_list) /
698*4882a593Smuzhiyun 			sizeof(base_parameter.screen_list[0]);
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun 		for (i = 0; i < screen_size; i++) {
701*4882a593Smuzhiyun 			if (base_parameter.screen_list[i].type ==
702*4882a593Smuzhiyun 			    DRM_MODE_CONNECTOR_TV) {
703*4882a593Smuzhiyun 				found = true;
704*4882a593Smuzhiyun 				screen_info = &base_parameter.screen_list[i];
705*4882a593Smuzhiyun 				break;
706*4882a593Smuzhiyun 			}
707*4882a593Smuzhiyun 		}
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 		if (!found && !offset) {
710*4882a593Smuzhiyun 			printf("cvbs info isn't saved in main block\n");
711*4882a593Smuzhiyun 			offset += 16;
712*4882a593Smuzhiyun 			goto read_aux;
713*4882a593Smuzhiyun 		}
714*4882a593Smuzhiyun 	} else {
715*4882a593Smuzhiyun 		scan = &base2_parameter->overscan_info;
716*4882a593Smuzhiyun 		screen_size = sizeof(base2_parameter->screen_info) /
717*4882a593Smuzhiyun 			sizeof(base2_parameter->screen_info[0]);
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 		for (i = 0; i < screen_size; i++) {
720*4882a593Smuzhiyun 			if (base2_parameter->screen_info[i].type ==
721*4882a593Smuzhiyun 			    DRM_MODE_CONNECTOR_TV) {
722*4882a593Smuzhiyun 				screen_info2 =
723*4882a593Smuzhiyun 					&base2_parameter->screen_info[i];
724*4882a593Smuzhiyun 				break;
725*4882a593Smuzhiyun 			}
726*4882a593Smuzhiyun 		}
727*4882a593Smuzhiyun 		screen_info = malloc(sizeof(*screen_info));
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 		screen_info->type = screen_info2->type;
730*4882a593Smuzhiyun 		screen_info->mode = screen_info2->resolution;
731*4882a593Smuzhiyun 		screen_info->format = screen_info2->format;
732*4882a593Smuzhiyun 		screen_info->depth = screen_info2->depthc;
733*4882a593Smuzhiyun 		screen_info->feature = screen_info2->feature;
734*4882a593Smuzhiyun 	}
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	if (scan->leftscale < min_scan && scan->leftscale > 0)
737*4882a593Smuzhiyun 		overscan->left_margin = min_scan;
738*4882a593Smuzhiyun 	else if (scan->leftscale < max_scan && scan->leftscale > 0)
739*4882a593Smuzhiyun 		overscan->left_margin = scan->leftscale;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	if (scan->rightscale < min_scan && scan->rightscale > 0)
742*4882a593Smuzhiyun 		overscan->right_margin = min_scan;
743*4882a593Smuzhiyun 	else if (scan->rightscale < max_scan && scan->rightscale > 0)
744*4882a593Smuzhiyun 		overscan->right_margin = scan->rightscale;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 	if (scan->topscale < min_scan && scan->topscale > 0)
747*4882a593Smuzhiyun 		overscan->top_margin = min_scan;
748*4882a593Smuzhiyun 	else if (scan->topscale < max_scan && scan->topscale > 0)
749*4882a593Smuzhiyun 		overscan->top_margin = scan->topscale;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (scan->bottomscale < min_scan && scan->bottomscale > 0)
752*4882a593Smuzhiyun 		overscan->bottom_margin = min_scan;
753*4882a593Smuzhiyun 	else if (scan->bottomscale < max_scan && scan->bottomscale > 0)
754*4882a593Smuzhiyun 		overscan->bottom_margin = scan->bottomscale;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun null_basep:
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	if (screen_info)
759*4882a593Smuzhiyun 		printf("cvbs base_parameter.mode:%dx%d\n",
760*4882a593Smuzhiyun 		       screen_info->mode.hdisplay,
761*4882a593Smuzhiyun 		       screen_info->mode.vdisplay);
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	if (screen_info &&
764*4882a593Smuzhiyun 	    (screen_info->mode.hdisplay == 720 &&
765*4882a593Smuzhiyun 	     screen_info->mode.vdisplay == 576))
766*4882a593Smuzhiyun 		*mode = modes[0];
767*4882a593Smuzhiyun 	else if (screen_info &&
768*4882a593Smuzhiyun 		 (screen_info->mode.hdisplay == 720 &&
769*4882a593Smuzhiyun 		  screen_info->mode.vdisplay == 480))
770*4882a593Smuzhiyun 		*mode = modes[1];
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun 
rockchip_drm_tve_get_timing(struct rockchip_connector * conn,struct display_state * state)773*4882a593Smuzhiyun static int rockchip_drm_tve_get_timing(struct rockchip_connector *conn, struct display_state *state)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun 	struct rockchip_tve *tve = dev_get_priv(conn->dev);
776*4882a593Smuzhiyun 	struct connector_state *conn_state = &state->conn_state;
777*4882a593Smuzhiyun 	struct drm_display_mode *mode = &conn_state->mode;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	tve_select_output(tve, conn_state, mode);
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	return 0;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun const struct rockchip_connector_funcs rockchip_drm_tve_funcs = {
785*4882a593Smuzhiyun 	.init = rockchip_drm_tve_init,
786*4882a593Smuzhiyun 	.deinit = rockchip_drm_tve_deinit,
787*4882a593Smuzhiyun 	.prepare = rockchip_drm_tve_prepare,
788*4882a593Smuzhiyun 	.enable = rockchip_drm_tve_enable,
789*4882a593Smuzhiyun 	.disable = rockchip_drm_tve_disable,
790*4882a593Smuzhiyun 	.get_timing = rockchip_drm_tve_get_timing,
791*4882a593Smuzhiyun 	.detect = rockchip_drm_tve_detect,
792*4882a593Smuzhiyun };
793*4882a593Smuzhiyun 
rockchip_drm_tve_probe(struct udevice * dev)794*4882a593Smuzhiyun static int rockchip_drm_tve_probe(struct udevice *dev)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun 	struct rockchip_tve *tve = dev_get_priv(dev);
797*4882a593Smuzhiyun 	const struct rockchip_tve_data *data;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	tve->dev = dev;
800*4882a593Smuzhiyun 	data = (const struct rockchip_tve_data *)dev_get_driver_data(dev);
801*4882a593Smuzhiyun 	tve->soc_type = data->soc_type;
802*4882a593Smuzhiyun 	tve->input_format = data->input_format;
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	rockchip_connector_bind(&tve->connector, dev, 0, &rockchip_drm_tve_funcs, NULL, DRM_MODE_CONNECTOR_TV);
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	return 0;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun static const struct rockchip_tve_data rk3036_tve = {
810*4882a593Smuzhiyun 	.soc_type = SOC_RK3036,
811*4882a593Smuzhiyun 	.input_format = INPUT_FORMAT_RGB,
812*4882a593Smuzhiyun };
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun static const struct rockchip_tve_data rk312x_tve = {
815*4882a593Smuzhiyun 	.soc_type = SOC_RK312X,
816*4882a593Smuzhiyun 	.input_format = INPUT_FORMAT_RGB,
817*4882a593Smuzhiyun };
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun static const struct rockchip_tve_data rk322x_tve = {
820*4882a593Smuzhiyun 	.soc_type = SOC_RK322X,
821*4882a593Smuzhiyun 	.input_format = INPUT_FORMAT_YUV,
822*4882a593Smuzhiyun };
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun static const struct rockchip_tve_data rk3328_tve = {
825*4882a593Smuzhiyun 	.soc_type = SOC_RK3328,
826*4882a593Smuzhiyun 	.input_format = INPUT_FORMAT_YUV,
827*4882a593Smuzhiyun };
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun static const struct rockchip_tve_data rk3528_tve = {
830*4882a593Smuzhiyun 	.soc_type = SOC_RK3528,
831*4882a593Smuzhiyun 	.input_format = INPUT_FORMAT_YUV,
832*4882a593Smuzhiyun };
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun static const struct udevice_id rockchip_drm_tve_ids[] = {
835*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3036-tve", .data = (ulong)&rk3036_tve },
836*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk312x-tve", .data = (ulong)&rk312x_tve },
837*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk322x-tve", .data = (ulong)&rk322x_tve },
838*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3328-tve", .data = (ulong)&rk3328_tve },
839*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3528-tve", .data = (ulong)&rk3528_tve },
840*4882a593Smuzhiyun };
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_drm_tve) = {
843*4882a593Smuzhiyun 	.name = "rockchip_drm_tve",
844*4882a593Smuzhiyun 	.id = UCLASS_DISPLAY,
845*4882a593Smuzhiyun 	.of_match = rockchip_drm_tve_ids,
846*4882a593Smuzhiyun 	.probe	= rockchip_drm_tve_probe,
847*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rockchip_tve),
848*4882a593Smuzhiyun };
849