xref: /OK3568_Linux_fs/u-boot/drivers/video/rockchip/rk3288_vop.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
3*4882a593Smuzhiyun  * Copyright (c) 2015 Google, Inc
4*4882a593Smuzhiyun  * Copyright 2014 Rockchip Inc.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <display.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <regmap.h>
13*4882a593Smuzhiyun #include <syscon.h>
14*4882a593Smuzhiyun #include <video.h>
15*4882a593Smuzhiyun #include <asm/hardware.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <asm/arch/clock.h>
18*4882a593Smuzhiyun #include <asm/arch/grf_rk3288.h>
19*4882a593Smuzhiyun #include "rk_vop.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
22*4882a593Smuzhiyun 
rk3288_set_pin_polarity(struct udevice * dev,enum vop_modes mode,u32 polarity)23*4882a593Smuzhiyun static void rk3288_set_pin_polarity(struct udevice *dev,
24*4882a593Smuzhiyun 				    enum vop_modes mode, u32 polarity)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	struct rk_vop_priv *priv = dev_get_priv(dev);
27*4882a593Smuzhiyun 	struct rk3288_vop *regs = priv->regs;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	/* The RK3328 VOP (v3.1) has its polarity configuration in ctrl0 */
30*4882a593Smuzhiyun 	clrsetbits_le32(&regs->dsp_ctrl0,
31*4882a593Smuzhiyun 			M_DSP_DCLK_POL | M_DSP_DEN_POL |
32*4882a593Smuzhiyun 			M_DSP_VSYNC_POL | M_DSP_HSYNC_POL,
33*4882a593Smuzhiyun 			V_DSP_PIN_POL(polarity));
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
rk3288_set_io_vsel(struct udevice * dev)36*4882a593Smuzhiyun static void rk3288_set_io_vsel(struct udevice *dev)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	struct rk3288_grf *grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	/* lcdc(vop) iodomain select 1.8V */
41*4882a593Smuzhiyun 	rk_setreg(&grf->io_vsel, 1 << 0);
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /*
45*4882a593Smuzhiyun  * Try some common regulators. We should really get these from the
46*4882a593Smuzhiyun  * device tree somehow.
47*4882a593Smuzhiyun  */
48*4882a593Smuzhiyun static const char * const rk3288_regulator_names[] = {
49*4882a593Smuzhiyun 	"vcc18_lcd",
50*4882a593Smuzhiyun 	"VCC18_LCD",
51*4882a593Smuzhiyun 	"vdd10_lcd_pwren_h",
52*4882a593Smuzhiyun 	"vdd10_lcd",
53*4882a593Smuzhiyun 	"VDD10_LCD",
54*4882a593Smuzhiyun 	"vcc33_lcd"
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun 
rk3288_vop_probe(struct udevice * dev)57*4882a593Smuzhiyun static int rk3288_vop_probe(struct udevice *dev)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	/* Before relocation we don't need to do anything */
60*4882a593Smuzhiyun 	if (!(gd->flags & GD_FLG_RELOC))
61*4882a593Smuzhiyun 		return 0;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/* Set the LCDC(vop) iodomain to 1.8V */
64*4882a593Smuzhiyun 	rk3288_set_io_vsel(dev);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	/* Probe regulators required for the RK3288 VOP */
67*4882a593Smuzhiyun 	rk_vop_probe_regulators(dev, rk3288_regulator_names,
68*4882a593Smuzhiyun 				ARRAY_SIZE(rk3288_regulator_names));
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return rk_vop_probe(dev);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
rk_vop_remove(struct udevice * dev)73*4882a593Smuzhiyun static int rk_vop_remove(struct udevice *dev)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct rk_vop_priv *priv = dev_get_priv(dev);
76*4882a593Smuzhiyun         struct rk3288_vop *regs = priv->regs;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	setbits_le32(&regs->sys_ctrl, V_STANDBY_EN(1));
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	/* wait frame complete (60Hz) to enter standby */
81*4882a593Smuzhiyun 	mdelay(17);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	return 0;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun struct rkvop_driverdata rk3288_driverdata = {
87*4882a593Smuzhiyun 	.features = VOP_FEATURE_OUTPUT_10BIT,
88*4882a593Smuzhiyun 	.set_pin_polarity = rk3288_set_pin_polarity,
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun static const struct udevice_id rk3288_vop_ids[] = {
92*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3288-vop",
93*4882a593Smuzhiyun 	  .data = (ulong)&rk3288_driverdata },
94*4882a593Smuzhiyun 	{ }
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun static const struct video_ops rk3288_vop_ops = {
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun U_BOOT_DRIVER(rk_vop) = {
101*4882a593Smuzhiyun 	.name	= "rk3288_vop",
102*4882a593Smuzhiyun 	.id	= UCLASS_VIDEO,
103*4882a593Smuzhiyun 	.of_match = rk3288_vop_ids,
104*4882a593Smuzhiyun 	.ops	= &rk3288_vop_ops,
105*4882a593Smuzhiyun 	.bind	= rk_vop_bind,
106*4882a593Smuzhiyun 	.probe	= rk3288_vop_probe,
107*4882a593Smuzhiyun         .remove = rk_vop_remove,
108*4882a593Smuzhiyun 	.priv_auto_alloc_size	= sizeof(struct rk_vop_priv),
109*4882a593Smuzhiyun };
110