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