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