]>
Commit | Line | Data |
---|---|---|
a355ece8 | 1 | // SPDX-License-Identifier: GPL-2.0 |
f680a91d | 2 | /* |
3 | * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd | |
4 | * Author: Eric Gao <[email protected]> | |
f680a91d | 5 | */ |
6 | ||
f680a91d | 7 | #include <clk.h> |
8 | #include <display.h> | |
9 | #include <dm.h> | |
f7ae49fc | 10 | #include <log.h> |
f680a91d | 11 | #include <panel.h> |
12 | #include <regmap.h> | |
13 | #include "rk_mipi.h" | |
14 | #include <syscon.h> | |
15 | #include <asm/gpio.h> | |
f680a91d | 16 | #include <dm/uclass-internal.h> |
61b29b82 | 17 | #include <linux/err.h> |
f680a91d | 18 | #include <linux/kernel.h> |
15f09a1a | 19 | #include <asm/arch-rockchip/clock.h> |
b52a199e | 20 | #include <asm/arch-rockchip/cru.h> |
15f09a1a KY |
21 | #include <asm/arch-rockchip/grf_rk3288.h> |
22 | #include <asm/arch-rockchip/hardware.h> | |
23 | #include <asm/arch-rockchip/rockchip_mipi_dsi.h> | |
f680a91d | 24 | |
f680a91d | 25 | #define MHz 1000000 |
26 | ||
27 | /* Select mipi dsi source, big or little vop */ | |
28 | static int rk_mipi_dsi_source_select(struct udevice *dev) | |
29 | { | |
30 | struct rk_mipi_priv *priv = dev_get_priv(dev); | |
31 | struct rk3288_grf *grf = priv->grf; | |
caa4daa2 | 32 | struct display_plat *disp_uc_plat = dev_get_uclass_plat(dev); |
f680a91d | 33 | |
34 | /* Select the video source */ | |
35 | switch (disp_uc_plat->source_id) { | |
36 | case VOP_B: | |
37 | rk_clrsetreg(&grf->soc_con6, RK3288_DSI0_LCDC_SEL_MASK, | |
38 | RK3288_DSI0_LCDC_SEL_BIG | |
39 | << RK3288_DSI0_LCDC_SEL_SHIFT); | |
40 | break; | |
41 | case VOP_L: | |
42 | rk_clrsetreg(&grf->soc_con6, RK3288_DSI0_LCDC_SEL_MASK, | |
43 | RK3288_DSI0_LCDC_SEL_LIT | |
44 | << RK3288_DSI0_LCDC_SEL_SHIFT); | |
45 | break; | |
46 | default: | |
47 | debug("%s: Invalid VOP id\n", __func__); | |
48 | return -EINVAL; | |
49 | } | |
50 | ||
51 | return 0; | |
52 | } | |
53 | ||
54 | /* Setup mipi dphy working mode */ | |
55 | static void rk_mipi_dphy_mode_set(struct udevice *dev) | |
56 | { | |
57 | struct rk_mipi_priv *priv = dev_get_priv(dev); | |
58 | struct rk3288_grf *grf = priv->grf; | |
59 | int val; | |
60 | ||
61 | /* Set Controller as TX mode */ | |
62 | val = RK3288_DPHY_TX0_RXMODE_DIS << RK3288_DPHY_TX0_RXMODE_SHIFT; | |
63 | rk_clrsetreg(&grf->soc_con8, RK3288_DPHY_TX0_RXMODE_MASK, val); | |
64 | ||
65 | /* Exit tx stop mode */ | |
66 | val |= RK3288_DPHY_TX0_TXSTOPMODE_EN | |
67 | << RK3288_DPHY_TX0_TXSTOPMODE_SHIFT; | |
68 | rk_clrsetreg(&grf->soc_con8, | |
69 | RK3288_DPHY_TX0_TXSTOPMODE_MASK, val); | |
70 | ||
71 | /* Disable turnequest */ | |
72 | val |= RK3288_DPHY_TX0_TURNREQUEST_EN | |
73 | << RK3288_DPHY_TX0_TURNREQUEST_SHIFT; | |
74 | rk_clrsetreg(&grf->soc_con8, | |
75 | RK3288_DPHY_TX0_TURNREQUEST_MASK, val); | |
76 | } | |
77 | ||
78 | /* | |
79 | * This function is called by rk_display_init() using rk_mipi_dsi_enable() and | |
80 | * rk_mipi_phy_enable() to initialize mipi controller and dphy. If success, | |
81 | * enable backlight. | |
82 | */ | |
83 | static int rk_mipi_enable(struct udevice *dev, int panel_bpp, | |
84 | const struct display_timing *timing) | |
85 | { | |
86 | int ret; | |
87 | struct rk_mipi_priv *priv = dev_get_priv(dev); | |
88 | ||
89 | /* Fill the mipi controller parameter */ | |
90 | priv->ref_clk = 24 * MHz; | |
91 | priv->sys_clk = priv->ref_clk; | |
92 | priv->pix_clk = timing->pixelclock.typ; | |
93 | priv->phy_clk = priv->pix_clk * 6; | |
94 | priv->txbyte_clk = priv->phy_clk / 8; | |
95 | priv->txesc_clk = 20 * MHz; | |
96 | ||
97 | /* Select vop port, big or little */ | |
98 | rk_mipi_dsi_source_select(dev); | |
99 | ||
100 | /* Set mipi dphy work mode */ | |
101 | rk_mipi_dphy_mode_set(dev); | |
102 | ||
103 | /* Config and enable mipi dsi according to timing */ | |
104 | ret = rk_mipi_dsi_enable(dev, timing); | |
105 | if (ret) { | |
106 | debug("%s: rk_mipi_dsi_enable() failed (err=%d)\n", | |
107 | __func__, ret); | |
108 | return ret; | |
109 | } | |
110 | ||
111 | /* Config and enable mipi phy */ | |
112 | ret = rk_mipi_phy_enable(dev); | |
113 | if (ret) { | |
114 | debug("%s: rk_mipi_phy_enable() failed (err=%d)\n", | |
115 | __func__, ret); | |
116 | return ret; | |
117 | } | |
118 | ||
119 | /* Enable backlight */ | |
120 | ret = panel_enable_backlight(priv->panel); | |
121 | if (ret) { | |
122 | debug("%s: panel_enable_backlight() failed (err=%d)\n", | |
123 | __func__, ret); | |
124 | return ret; | |
125 | } | |
126 | ||
127 | return 0; | |
128 | } | |
129 | ||
d1998a9f | 130 | static int rk_mipi_of_to_plat(struct udevice *dev) |
f680a91d | 131 | { |
132 | struct rk_mipi_priv *priv = dev_get_priv(dev); | |
133 | ||
134 | priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
6e607791 | 135 | if (IS_ERR_OR_NULL(priv->grf)) { |
f680a91d | 136 | debug("%s: Get syscon grf failed (ret=%p)\n", |
137 | __func__, priv->grf); | |
138 | return -ENXIO; | |
139 | } | |
140 | priv->regs = dev_read_addr(dev); | |
141 | if (priv->regs == FDT_ADDR_T_NONE) { | |
142 | debug("%s: Get MIPI dsi address failed (ret=%lu)\n", __func__, | |
143 | priv->regs); | |
144 | return -ENXIO; | |
145 | } | |
146 | ||
147 | return 0; | |
148 | } | |
149 | ||
150 | /* | |
151 | * Probe function: check panel existence and readingit's timing. Then config | |
152 | * mipi dsi controller and enable it according to the timing parameter. | |
153 | */ | |
154 | static int rk_mipi_probe(struct udevice *dev) | |
155 | { | |
156 | int ret; | |
157 | struct rk_mipi_priv *priv = dev_get_priv(dev); | |
158 | ||
159 | ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, "rockchip,panel", | |
160 | &priv->panel); | |
161 | if (ret) { | |
162 | debug("%s: Can not find panel (err=%d)\n", __func__, ret); | |
163 | return ret; | |
164 | } | |
165 | ||
166 | return 0; | |
167 | } | |
168 | ||
169 | static const struct dm_display_ops rk_mipi_dsi_ops = { | |
170 | .read_timing = rk_mipi_read_timing, | |
171 | .enable = rk_mipi_enable, | |
172 | }; | |
173 | ||
174 | static const struct udevice_id rk_mipi_dsi_ids[] = { | |
dcaaefdc | 175 | { .compatible = "rockchip,rk3288-mipi-dsi" }, |
f680a91d | 176 | { .compatible = "rockchip,rk3288_mipi_dsi" }, |
177 | { } | |
178 | }; | |
179 | ||
180 | U_BOOT_DRIVER(rk_mipi_dsi) = { | |
181 | .name = "rk_mipi_dsi", | |
182 | .id = UCLASS_DISPLAY, | |
183 | .of_match = rk_mipi_dsi_ids, | |
d1998a9f | 184 | .of_to_plat = rk_mipi_of_to_plat, |
f680a91d | 185 | .probe = rk_mipi_probe, |
186 | .ops = &rk_mipi_dsi_ops, | |
41575d8e | 187 | .priv_auto = sizeof(struct rk_mipi_priv), |
f680a91d | 188 | }; |