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(®s->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(®s->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