1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com |
4 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> |
5 | */ |
6 | |
7 | #include <linux/clk.h> |
8 | #include <linux/device.h> |
9 | #include <linux/gpio/consumer.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/math64.h> |
13 | #include <linux/media-bus-format.h> |
14 | #include <linux/minmax.h> |
15 | #include <linux/module.h> |
16 | #include <linux/regmap.h> |
17 | #include <linux/regulator/consumer.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/units.h> |
20 | |
21 | #include <drm/drm_atomic_helper.h> |
22 | #include <drm/drm_drv.h> |
23 | #include <drm/drm_mipi_dsi.h> |
24 | #include <drm/drm_of.h> |
25 | #include <drm/drm_panel.h> |
26 | #include <video/mipi_display.h> |
27 | #include <video/videomode.h> |
28 | |
29 | /* Global (16-bit addressable) */ |
30 | #define TC358768_CHIPID 0x0000 |
31 | #define TC358768_SYSCTL 0x0002 |
32 | #define TC358768_CONFCTL 0x0004 |
33 | #define TC358768_VSDLY 0x0006 |
34 | #define TC358768_DATAFMT 0x0008 |
35 | #define TC358768_GPIOEN 0x000E |
36 | #define TC358768_GPIODIR 0x0010 |
37 | #define TC358768_GPIOIN 0x0012 |
38 | #define TC358768_GPIOOUT 0x0014 |
39 | #define TC358768_PLLCTL0 0x0016 |
40 | #define TC358768_PLLCTL1 0x0018 |
41 | #define TC358768_CMDBYTE 0x0022 |
42 | #define TC358768_PP_MISC 0x0032 |
43 | #define TC358768_DSITX_DT 0x0050 |
44 | #define TC358768_FIFOSTATUS 0x00F8 |
45 | |
46 | /* Debug (16-bit addressable) */ |
47 | #define TC358768_VBUFCTRL 0x00E0 |
48 | #define TC358768_DBG_WIDTH 0x00E2 |
49 | #define TC358768_DBG_VBLANK 0x00E4 |
50 | #define TC358768_DBG_DATA 0x00E8 |
51 | |
52 | /* TX PHY (32-bit addressable) */ |
53 | #define TC358768_CLW_DPHYCONTTX 0x0100 |
54 | #define TC358768_D0W_DPHYCONTTX 0x0104 |
55 | #define TC358768_D1W_DPHYCONTTX 0x0108 |
56 | #define TC358768_D2W_DPHYCONTTX 0x010C |
57 | #define TC358768_D3W_DPHYCONTTX 0x0110 |
58 | #define TC358768_CLW_CNTRL 0x0140 |
59 | #define TC358768_D0W_CNTRL 0x0144 |
60 | #define TC358768_D1W_CNTRL 0x0148 |
61 | #define TC358768_D2W_CNTRL 0x014C |
62 | #define TC358768_D3W_CNTRL 0x0150 |
63 | |
64 | /* TX PPI (32-bit addressable) */ |
65 | #define TC358768_STARTCNTRL 0x0204 |
66 | #define TC358768_DSITXSTATUS 0x0208 |
67 | #define TC358768_LINEINITCNT 0x0210 |
68 | #define TC358768_LPTXTIMECNT 0x0214 |
69 | #define 0x0218 |
70 | #define TC358768_TCLK_TRAILCNT 0x021C |
71 | #define 0x0220 |
72 | #define TC358768_TWAKEUP 0x0224 |
73 | #define TC358768_TCLK_POSTCNT 0x0228 |
74 | #define TC358768_THS_TRAILCNT 0x022C |
75 | #define TC358768_HSTXVREGCNT 0x0230 |
76 | #define TC358768_HSTXVREGEN 0x0234 |
77 | #define TC358768_TXOPTIONCNTRL 0x0238 |
78 | #define TC358768_BTACNTRL1 0x023C |
79 | |
80 | /* TX CTRL (32-bit addressable) */ |
81 | #define TC358768_DSI_CONTROL 0x040C |
82 | #define TC358768_DSI_STATUS 0x0410 |
83 | #define TC358768_DSI_INT 0x0414 |
84 | #define TC358768_DSI_INT_ENA 0x0418 |
85 | #define TC358768_DSICMD_RDFIFO 0x0430 |
86 | #define TC358768_DSI_ACKERR 0x0434 |
87 | #define TC358768_DSI_ACKERR_INTENA 0x0438 |
88 | #define TC358768_DSI_ACKERR_HALT 0x043c |
89 | #define TC358768_DSI_RXERR 0x0440 |
90 | #define TC358768_DSI_RXERR_INTENA 0x0444 |
91 | #define TC358768_DSI_RXERR_HALT 0x0448 |
92 | #define TC358768_DSI_ERR 0x044C |
93 | #define TC358768_DSI_ERR_INTENA 0x0450 |
94 | #define TC358768_DSI_ERR_HALT 0x0454 |
95 | #define TC358768_DSI_CONFW 0x0500 |
96 | #define TC358768_DSI_LPCMD 0x0500 |
97 | #define TC358768_DSI_RESET 0x0504 |
98 | #define TC358768_DSI_INT_CLR 0x050C |
99 | #define TC358768_DSI_START 0x0518 |
100 | |
101 | /* DSITX CTRL (16-bit addressable) */ |
102 | #define TC358768_DSICMD_TX 0x0600 |
103 | #define TC358768_DSICMD_TYPE 0x0602 |
104 | #define TC358768_DSICMD_WC 0x0604 |
105 | #define TC358768_DSICMD_WD0 0x0610 |
106 | #define TC358768_DSICMD_WD1 0x0612 |
107 | #define TC358768_DSICMD_WD2 0x0614 |
108 | #define TC358768_DSICMD_WD3 0x0616 |
109 | #define TC358768_DSI_EVENT 0x0620 |
110 | #define TC358768_DSI_VSW 0x0622 |
111 | #define TC358768_DSI_VBPR 0x0624 |
112 | #define TC358768_DSI_VACT 0x0626 |
113 | #define TC358768_DSI_HSW 0x0628 |
114 | #define TC358768_DSI_HBPR 0x062A |
115 | #define TC358768_DSI_HACT 0x062C |
116 | |
117 | /* TC358768_DSI_CONTROL (0x040C) register */ |
118 | #define TC358768_DSI_CONTROL_DIS_MODE BIT(15) |
119 | #define TC358768_DSI_CONTROL_TXMD BIT(7) |
120 | #define TC358768_DSI_CONTROL_HSCKMD BIT(5) |
121 | #define TC358768_DSI_CONTROL_EOTDIS BIT(0) |
122 | |
123 | /* TC358768_DSI_CONFW (0x0500) register */ |
124 | #define TC358768_DSI_CONFW_MODE_SET (5 << 29) |
125 | #define TC358768_DSI_CONFW_MODE_CLR (6 << 29) |
126 | #define TC358768_DSI_CONFW_ADDR_DSI_CONTROL (0x3 << 24) |
127 | |
128 | static const char * const tc358768_supplies[] = { |
129 | "vddc" , "vddmipi" , "vddio" |
130 | }; |
131 | |
132 | struct tc358768_dsi_output { |
133 | struct mipi_dsi_device *dev; |
134 | struct drm_panel *panel; |
135 | struct drm_bridge *bridge; |
136 | }; |
137 | |
138 | struct tc358768_priv { |
139 | struct device *dev; |
140 | struct regmap *regmap; |
141 | struct gpio_desc *reset_gpio; |
142 | struct regulator_bulk_data supplies[ARRAY_SIZE(tc358768_supplies)]; |
143 | struct clk *refclk; |
144 | int enabled; |
145 | int error; |
146 | |
147 | struct mipi_dsi_host dsi_host; |
148 | struct drm_bridge bridge; |
149 | struct tc358768_dsi_output output; |
150 | |
151 | u32 pd_lines; /* number of Parallel Port Input Data Lines */ |
152 | u32 dsi_lanes; /* number of DSI Lanes */ |
153 | u32 dsi_bpp; /* number of Bits Per Pixel over DSI */ |
154 | |
155 | /* Parameters for PLL programming */ |
156 | u32 fbd; /* PLL feedback divider */ |
157 | u32 prd; /* PLL input divider */ |
158 | u32 frs; /* PLL Freqency range for HSCK (post divider) */ |
159 | |
160 | u32 dsiclk; /* pll_clk / 2 */ |
161 | u32 pclk; /* incoming pclk rate */ |
162 | }; |
163 | |
164 | static inline struct tc358768_priv *dsi_host_to_tc358768(struct mipi_dsi_host |
165 | *host) |
166 | { |
167 | return container_of(host, struct tc358768_priv, dsi_host); |
168 | } |
169 | |
170 | static inline struct tc358768_priv *bridge_to_tc358768(struct drm_bridge |
171 | *bridge) |
172 | { |
173 | return container_of(bridge, struct tc358768_priv, bridge); |
174 | } |
175 | |
176 | static int tc358768_clear_error(struct tc358768_priv *priv) |
177 | { |
178 | int ret = priv->error; |
179 | |
180 | priv->error = 0; |
181 | return ret; |
182 | } |
183 | |
184 | static void tc358768_write(struct tc358768_priv *priv, u32 reg, u32 val) |
185 | { |
186 | /* work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ |
187 | int tmpval = val; |
188 | size_t count = 2; |
189 | |
190 | if (priv->error) |
191 | return; |
192 | |
193 | /* 16-bit register? */ |
194 | if (reg < 0x100 || reg >= 0x600) |
195 | count = 1; |
196 | |
197 | priv->error = regmap_bulk_write(map: priv->regmap, reg, val: &tmpval, val_count: count); |
198 | } |
199 | |
200 | static void tc358768_read(struct tc358768_priv *priv, u32 reg, u32 *val) |
201 | { |
202 | size_t count = 2; |
203 | |
204 | if (priv->error) |
205 | return; |
206 | |
207 | /* 16-bit register? */ |
208 | if (reg < 0x100 || reg >= 0x600) { |
209 | *val = 0; |
210 | count = 1; |
211 | } |
212 | |
213 | priv->error = regmap_bulk_read(map: priv->regmap, reg, val, val_count: count); |
214 | } |
215 | |
216 | static void tc358768_update_bits(struct tc358768_priv *priv, u32 reg, u32 mask, |
217 | u32 val) |
218 | { |
219 | u32 tmp, orig; |
220 | |
221 | tc358768_read(priv, reg, val: &orig); |
222 | |
223 | if (priv->error) |
224 | return; |
225 | |
226 | tmp = orig & ~mask; |
227 | tmp |= val & mask; |
228 | if (tmp != orig) |
229 | tc358768_write(priv, reg, val: tmp); |
230 | } |
231 | |
232 | static int tc358768_sw_reset(struct tc358768_priv *priv) |
233 | { |
234 | /* Assert Reset */ |
235 | tc358768_write(priv, TC358768_SYSCTL, val: 1); |
236 | /* Release Reset, Exit Sleep */ |
237 | tc358768_write(priv, TC358768_SYSCTL, val: 0); |
238 | |
239 | return tc358768_clear_error(priv); |
240 | } |
241 | |
242 | static void tc358768_hw_enable(struct tc358768_priv *priv) |
243 | { |
244 | int ret; |
245 | |
246 | if (priv->enabled) |
247 | return; |
248 | |
249 | ret = clk_prepare_enable(clk: priv->refclk); |
250 | if (ret < 0) |
251 | dev_err(priv->dev, "error enabling refclk (%d)\n" , ret); |
252 | |
253 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), consumers: priv->supplies); |
254 | if (ret < 0) |
255 | dev_err(priv->dev, "error enabling regulators (%d)\n" , ret); |
256 | |
257 | if (priv->reset_gpio) |
258 | usleep_range(min: 200, max: 300); |
259 | |
260 | /* |
261 | * The RESX is active low (GPIO_ACTIVE_LOW). |
262 | * DEASSERT (value = 0) the reset_gpio to enable the chip |
263 | */ |
264 | gpiod_set_value_cansleep(desc: priv->reset_gpio, value: 0); |
265 | |
266 | /* wait for encoder clocks to stabilize */ |
267 | usleep_range(min: 1000, max: 2000); |
268 | |
269 | priv->enabled = true; |
270 | } |
271 | |
272 | static void tc358768_hw_disable(struct tc358768_priv *priv) |
273 | { |
274 | int ret; |
275 | |
276 | if (!priv->enabled) |
277 | return; |
278 | |
279 | /* |
280 | * The RESX is active low (GPIO_ACTIVE_LOW). |
281 | * ASSERT (value = 1) the reset_gpio to disable the chip |
282 | */ |
283 | gpiod_set_value_cansleep(desc: priv->reset_gpio, value: 1); |
284 | |
285 | ret = regulator_bulk_disable(ARRAY_SIZE(priv->supplies), |
286 | consumers: priv->supplies); |
287 | if (ret < 0) |
288 | dev_err(priv->dev, "error disabling regulators (%d)\n" , ret); |
289 | |
290 | clk_disable_unprepare(clk: priv->refclk); |
291 | |
292 | priv->enabled = false; |
293 | } |
294 | |
295 | static u32 tc358768_pll_to_pclk(struct tc358768_priv *priv, u32 pll_clk) |
296 | { |
297 | return (u32)div_u64(dividend: (u64)pll_clk * priv->dsi_lanes, divisor: priv->dsi_bpp); |
298 | } |
299 | |
300 | static u32 tc358768_pclk_to_pll(struct tc358768_priv *priv, u32 pclk) |
301 | { |
302 | return (u32)div_u64(dividend: (u64)pclk * priv->dsi_bpp, divisor: priv->dsi_lanes); |
303 | } |
304 | |
305 | static int tc358768_calc_pll(struct tc358768_priv *priv, |
306 | const struct drm_display_mode *mode, |
307 | bool verify_only) |
308 | { |
309 | static const u32 frs_limits[] = { |
310 | 1000000000, |
311 | 500000000, |
312 | 250000000, |
313 | 125000000, |
314 | 62500000 |
315 | }; |
316 | unsigned long refclk; |
317 | u32 prd, target_pll, i, max_pll, min_pll; |
318 | u32 frs, best_diff, best_pll, best_prd, best_fbd; |
319 | |
320 | target_pll = tc358768_pclk_to_pll(priv, pclk: mode->clock * 1000); |
321 | |
322 | /* pll_clk = RefClk * FBD / PRD * (1 / (2^FRS)) */ |
323 | |
324 | for (i = 0; i < ARRAY_SIZE(frs_limits); i++) |
325 | if (target_pll >= frs_limits[i]) |
326 | break; |
327 | |
328 | if (i == ARRAY_SIZE(frs_limits) || i == 0) |
329 | return -EINVAL; |
330 | |
331 | frs = i - 1; |
332 | max_pll = frs_limits[i - 1]; |
333 | min_pll = frs_limits[i]; |
334 | |
335 | refclk = clk_get_rate(clk: priv->refclk); |
336 | |
337 | best_diff = UINT_MAX; |
338 | best_pll = 0; |
339 | best_prd = 0; |
340 | best_fbd = 0; |
341 | |
342 | for (prd = 1; prd <= 16; ++prd) { |
343 | u32 divisor = prd * (1 << frs); |
344 | u32 fbd; |
345 | |
346 | for (fbd = 1; fbd <= 512; ++fbd) { |
347 | u32 pll, diff, pll_in; |
348 | |
349 | pll = (u32)div_u64(dividend: (u64)refclk * fbd, divisor); |
350 | |
351 | if (pll >= max_pll || pll < min_pll) |
352 | continue; |
353 | |
354 | pll_in = (u32)div_u64(dividend: (u64)refclk, divisor: prd); |
355 | if (pll_in < 4000000) |
356 | continue; |
357 | |
358 | diff = max(pll, target_pll) - min(pll, target_pll); |
359 | |
360 | if (diff < best_diff) { |
361 | best_diff = diff; |
362 | best_pll = pll; |
363 | best_prd = prd; |
364 | best_fbd = fbd; |
365 | |
366 | if (best_diff == 0) |
367 | goto found; |
368 | } |
369 | } |
370 | } |
371 | |
372 | if (best_diff == UINT_MAX) { |
373 | dev_err(priv->dev, "could not find suitable PLL setup\n" ); |
374 | return -EINVAL; |
375 | } |
376 | |
377 | found: |
378 | if (verify_only) |
379 | return 0; |
380 | |
381 | priv->fbd = best_fbd; |
382 | priv->prd = best_prd; |
383 | priv->frs = frs; |
384 | priv->dsiclk = best_pll / 2; |
385 | priv->pclk = mode->clock * 1000; |
386 | |
387 | return 0; |
388 | } |
389 | |
390 | static int tc358768_dsi_host_attach(struct mipi_dsi_host *host, |
391 | struct mipi_dsi_device *dev) |
392 | { |
393 | struct tc358768_priv *priv = dsi_host_to_tc358768(host); |
394 | struct drm_bridge *bridge; |
395 | struct drm_panel *panel; |
396 | struct device_node *ep; |
397 | int ret; |
398 | |
399 | if (dev->lanes > 4) { |
400 | dev_err(priv->dev, "unsupported number of data lanes(%u)\n" , |
401 | dev->lanes); |
402 | return -EINVAL; |
403 | } |
404 | |
405 | /* |
406 | * tc358768 supports both Video and Pulse mode, but the driver only |
407 | * implements Video (event) mode currently |
408 | */ |
409 | if (!(dev->mode_flags & MIPI_DSI_MODE_VIDEO)) { |
410 | dev_err(priv->dev, "Only MIPI_DSI_MODE_VIDEO is supported\n" ); |
411 | return -ENOTSUPP; |
412 | } |
413 | |
414 | /* |
415 | * tc358768 supports RGB888, RGB666, RGB666_PACKED and RGB565, but only |
416 | * RGB888 is verified. |
417 | */ |
418 | if (dev->format != MIPI_DSI_FMT_RGB888) { |
419 | dev_warn(priv->dev, "Only MIPI_DSI_FMT_RGB888 tested!\n" ); |
420 | return -ENOTSUPP; |
421 | } |
422 | |
423 | ret = drm_of_find_panel_or_bridge(np: host->dev->of_node, port: 1, endpoint: 0, panel: &panel, |
424 | bridge: &bridge); |
425 | if (ret) |
426 | return ret; |
427 | |
428 | if (panel) { |
429 | bridge = drm_panel_bridge_add_typed(panel, |
430 | DRM_MODE_CONNECTOR_DSI); |
431 | if (IS_ERR(ptr: bridge)) |
432 | return PTR_ERR(ptr: bridge); |
433 | } |
434 | |
435 | priv->output.dev = dev; |
436 | priv->output.bridge = bridge; |
437 | priv->output.panel = panel; |
438 | |
439 | priv->dsi_lanes = dev->lanes; |
440 | priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(fmt: dev->format); |
441 | |
442 | /* get input ep (port0/endpoint0) */ |
443 | ret = -EINVAL; |
444 | ep = of_graph_get_endpoint_by_regs(parent: host->dev->of_node, port_reg: 0, reg: 0); |
445 | if (ep) { |
446 | ret = of_property_read_u32(np: ep, propname: "data-lines" , out_value: &priv->pd_lines); |
447 | |
448 | of_node_put(node: ep); |
449 | } |
450 | |
451 | if (ret) |
452 | priv->pd_lines = priv->dsi_bpp; |
453 | |
454 | drm_bridge_add(bridge: &priv->bridge); |
455 | |
456 | return 0; |
457 | } |
458 | |
459 | static int tc358768_dsi_host_detach(struct mipi_dsi_host *host, |
460 | struct mipi_dsi_device *dev) |
461 | { |
462 | struct tc358768_priv *priv = dsi_host_to_tc358768(host); |
463 | |
464 | drm_bridge_remove(bridge: &priv->bridge); |
465 | if (priv->output.panel) |
466 | drm_panel_bridge_remove(bridge: priv->output.bridge); |
467 | |
468 | return 0; |
469 | } |
470 | |
471 | static ssize_t tc358768_dsi_host_transfer(struct mipi_dsi_host *host, |
472 | const struct mipi_dsi_msg *msg) |
473 | { |
474 | struct tc358768_priv *priv = dsi_host_to_tc358768(host); |
475 | struct mipi_dsi_packet packet; |
476 | int ret; |
477 | |
478 | if (!priv->enabled) { |
479 | dev_err(priv->dev, "Bridge is not enabled\n" ); |
480 | return -ENODEV; |
481 | } |
482 | |
483 | if (msg->rx_len) { |
484 | dev_warn(priv->dev, "MIPI rx is not supported\n" ); |
485 | return -ENOTSUPP; |
486 | } |
487 | |
488 | if (msg->tx_len > 8) { |
489 | dev_warn(priv->dev, "Maximum 8 byte MIPI tx is supported\n" ); |
490 | return -ENOTSUPP; |
491 | } |
492 | |
493 | ret = mipi_dsi_create_packet(packet: &packet, msg); |
494 | if (ret) |
495 | return ret; |
496 | |
497 | if (mipi_dsi_packet_format_is_short(type: msg->type)) { |
498 | tc358768_write(priv, TC358768_DSICMD_TYPE, |
499 | val: (0x10 << 8) | (packet.header[0] & 0x3f)); |
500 | tc358768_write(priv, TC358768_DSICMD_WC, val: 0); |
501 | tc358768_write(priv, TC358768_DSICMD_WD0, |
502 | val: (packet.header[2] << 8) | packet.header[1]); |
503 | } else { |
504 | int i; |
505 | |
506 | tc358768_write(priv, TC358768_DSICMD_TYPE, |
507 | val: (0x40 << 8) | (packet.header[0] & 0x3f)); |
508 | tc358768_write(priv, TC358768_DSICMD_WC, val: packet.payload_length); |
509 | for (i = 0; i < packet.payload_length; i += 2) { |
510 | u16 val = packet.payload[i]; |
511 | |
512 | if (i + 1 < packet.payload_length) |
513 | val |= packet.payload[i + 1] << 8; |
514 | |
515 | tc358768_write(priv, TC358768_DSICMD_WD0 + i, val); |
516 | } |
517 | } |
518 | |
519 | /* start transfer */ |
520 | tc358768_write(priv, TC358768_DSICMD_TX, val: 1); |
521 | |
522 | ret = tc358768_clear_error(priv); |
523 | if (ret) |
524 | dev_warn(priv->dev, "Software disable failed: %d\n" , ret); |
525 | else |
526 | ret = packet.size; |
527 | |
528 | return ret; |
529 | } |
530 | |
531 | static const struct mipi_dsi_host_ops tc358768_dsi_host_ops = { |
532 | .attach = tc358768_dsi_host_attach, |
533 | .detach = tc358768_dsi_host_detach, |
534 | .transfer = tc358768_dsi_host_transfer, |
535 | }; |
536 | |
537 | static int tc358768_bridge_attach(struct drm_bridge *bridge, |
538 | enum drm_bridge_attach_flags flags) |
539 | { |
540 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
541 | |
542 | if (!drm_core_check_feature(dev: bridge->dev, feature: DRIVER_ATOMIC)) { |
543 | dev_err(priv->dev, "needs atomic updates support\n" ); |
544 | return -ENOTSUPP; |
545 | } |
546 | |
547 | return drm_bridge_attach(encoder: bridge->encoder, bridge: priv->output.bridge, previous: bridge, |
548 | flags); |
549 | } |
550 | |
551 | static enum drm_mode_status |
552 | tc358768_bridge_mode_valid(struct drm_bridge *bridge, |
553 | const struct drm_display_info *info, |
554 | const struct drm_display_mode *mode) |
555 | { |
556 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
557 | |
558 | if (tc358768_calc_pll(priv, mode, verify_only: true)) |
559 | return MODE_CLOCK_RANGE; |
560 | |
561 | return MODE_OK; |
562 | } |
563 | |
564 | static void tc358768_bridge_disable(struct drm_bridge *bridge) |
565 | { |
566 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
567 | int ret; |
568 | |
569 | /* set FrmStop */ |
570 | tc358768_update_bits(priv, TC358768_PP_MISC, BIT(15), BIT(15)); |
571 | |
572 | /* wait at least for one frame */ |
573 | msleep(msecs: 50); |
574 | |
575 | /* clear PP_en */ |
576 | tc358768_update_bits(priv, TC358768_CONFCTL, BIT(6), val: 0); |
577 | |
578 | /* set RstPtr */ |
579 | tc358768_update_bits(priv, TC358768_PP_MISC, BIT(14), BIT(14)); |
580 | |
581 | ret = tc358768_clear_error(priv); |
582 | if (ret) |
583 | dev_warn(priv->dev, "Software disable failed: %d\n" , ret); |
584 | } |
585 | |
586 | static void tc358768_bridge_post_disable(struct drm_bridge *bridge) |
587 | { |
588 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
589 | |
590 | tc358768_hw_disable(priv); |
591 | } |
592 | |
593 | static int tc358768_setup_pll(struct tc358768_priv *priv, |
594 | const struct drm_display_mode *mode) |
595 | { |
596 | u32 fbd, prd, frs; |
597 | int ret; |
598 | |
599 | ret = tc358768_calc_pll(priv, mode, verify_only: false); |
600 | if (ret) { |
601 | dev_err(priv->dev, "PLL calculation failed: %d\n" , ret); |
602 | return ret; |
603 | } |
604 | |
605 | fbd = priv->fbd; |
606 | prd = priv->prd; |
607 | frs = priv->frs; |
608 | |
609 | dev_dbg(priv->dev, "PLL: refclk %lu, fbd %u, prd %u, frs %u\n" , |
610 | clk_get_rate(priv->refclk), fbd, prd, frs); |
611 | dev_dbg(priv->dev, "PLL: pll_clk: %u, DSIClk %u, HSByteClk %u\n" , |
612 | priv->dsiclk * 2, priv->dsiclk, priv->dsiclk / 4); |
613 | dev_dbg(priv->dev, "PLL: pclk %u (panel: %u)\n" , |
614 | tc358768_pll_to_pclk(priv, priv->dsiclk * 2), |
615 | mode->clock * 1000); |
616 | |
617 | /* PRD[15:12] FBD[8:0] */ |
618 | tc358768_write(priv, TC358768_PLLCTL0, val: ((prd - 1) << 12) | (fbd - 1)); |
619 | |
620 | /* FRS[11:10] LBWS[9:8] CKEN[4] RESETB[1] EN[0] */ |
621 | tc358768_write(priv, TC358768_PLLCTL1, |
622 | val: (frs << 10) | (0x2 << 8) | BIT(1) | BIT(0)); |
623 | |
624 | /* wait for lock */ |
625 | usleep_range(min: 1000, max: 2000); |
626 | |
627 | /* FRS[11:10] LBWS[9:8] CKEN[4] PLL_CKEN[4] RESETB[1] EN[0] */ |
628 | tc358768_write(priv, TC358768_PLLCTL1, |
629 | val: (frs << 10) | (0x2 << 8) | BIT(4) | BIT(1) | BIT(0)); |
630 | |
631 | return tc358768_clear_error(priv); |
632 | } |
633 | |
634 | static u32 tc358768_ns_to_cnt(u32 ns, u32 period_ps) |
635 | { |
636 | return DIV_ROUND_UP(ns * 1000, period_ps); |
637 | } |
638 | |
639 | static u32 tc358768_ps_to_ns(u32 ps) |
640 | { |
641 | return ps / 1000; |
642 | } |
643 | |
644 | static u32 tc358768_dpi_to_ns(u32 val, u32 pclk) |
645 | { |
646 | return (u32)div_u64(dividend: (u64)val * NANO, divisor: pclk); |
647 | } |
648 | |
649 | /* Convert value in DPI pixel clock units to DSI byte count */ |
650 | static u32 tc358768_dpi_to_dsi_bytes(struct tc358768_priv *priv, u32 val) |
651 | { |
652 | u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes; |
653 | u64 n = priv->pclk; |
654 | |
655 | return (u32)div_u64(dividend: m + n - 1, divisor: n); |
656 | } |
657 | |
658 | static u32 tc358768_dsi_bytes_to_ns(struct tc358768_priv *priv, u32 val) |
659 | { |
660 | u64 m = (u64)val * NANO; |
661 | u64 n = priv->dsiclk / 4 * priv->dsi_lanes; |
662 | |
663 | return (u32)div_u64(dividend: m, divisor: n); |
664 | } |
665 | |
666 | static void tc358768_bridge_pre_enable(struct drm_bridge *bridge) |
667 | { |
668 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
669 | struct mipi_dsi_device *dsi_dev = priv->output.dev; |
670 | unsigned long mode_flags = dsi_dev->mode_flags; |
671 | u32 val, val2, lptxcnt, hact, data_type; |
672 | s32 raw_val; |
673 | const struct drm_display_mode *mode; |
674 | u32 hsbyteclk_ps, dsiclk_ps, ui_ps; |
675 | u32 dsiclk, hsbyteclk; |
676 | int ret, i; |
677 | struct videomode vm; |
678 | struct device *dev = priv->dev; |
679 | /* In pixelclock units */ |
680 | u32 dpi_htot, dpi_data_start; |
681 | /* In byte units */ |
682 | u32 dsi_dpi_htot, dsi_dpi_data_start; |
683 | u32 dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp; |
684 | const u32 dsi_hss = 4; /* HSS is a short packet (4 bytes) */ |
685 | /* In hsbyteclk units */ |
686 | u32 dsi_vsdly; |
687 | const u32 internal_dly = 40; |
688 | |
689 | if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { |
690 | dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n" ); |
691 | mode_flags &= ~MIPI_DSI_CLOCK_NON_CONTINUOUS; |
692 | } |
693 | |
694 | tc358768_hw_enable(priv); |
695 | |
696 | ret = tc358768_sw_reset(priv); |
697 | if (ret) { |
698 | dev_err(dev, "Software reset failed: %d\n" , ret); |
699 | tc358768_hw_disable(priv); |
700 | return; |
701 | } |
702 | |
703 | mode = &bridge->encoder->crtc->state->adjusted_mode; |
704 | ret = tc358768_setup_pll(priv, mode); |
705 | if (ret) { |
706 | dev_err(dev, "PLL setup failed: %d\n" , ret); |
707 | tc358768_hw_disable(priv); |
708 | return; |
709 | } |
710 | |
711 | drm_display_mode_to_videomode(dmode: mode, vm: &vm); |
712 | |
713 | dsiclk = priv->dsiclk; |
714 | hsbyteclk = dsiclk / 4; |
715 | |
716 | /* Data Format Control Register */ |
717 | val = BIT(2) | BIT(1) | BIT(0); /* rdswap_en | dsitx_en | txdt_en */ |
718 | switch (dsi_dev->format) { |
719 | case MIPI_DSI_FMT_RGB888: |
720 | val |= (0x3 << 4); |
721 | hact = vm.hactive * 3; |
722 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
723 | break; |
724 | case MIPI_DSI_FMT_RGB666: |
725 | val |= (0x4 << 4); |
726 | hact = vm.hactive * 3; |
727 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
728 | break; |
729 | |
730 | case MIPI_DSI_FMT_RGB666_PACKED: |
731 | val |= (0x4 << 4) | BIT(3); |
732 | hact = vm.hactive * 18 / 8; |
733 | data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
734 | break; |
735 | |
736 | case MIPI_DSI_FMT_RGB565: |
737 | val |= (0x5 << 4); |
738 | hact = vm.hactive * 2; |
739 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
740 | break; |
741 | default: |
742 | dev_err(dev, "Invalid data format (%u)\n" , |
743 | dsi_dev->format); |
744 | tc358768_hw_disable(priv); |
745 | return; |
746 | } |
747 | |
748 | /* |
749 | * There are three important things to make TC358768 work correctly, |
750 | * which are not trivial to manage: |
751 | * |
752 | * 1. Keep the DPI line-time and the DSI line-time as close to each |
753 | * other as possible. |
754 | * 2. TC358768 goes to LP mode after each line's active area. The DSI |
755 | * HFP period has to be long enough for entering and exiting LP mode. |
756 | * But it is not clear how to calculate this. |
757 | * 3. VSDly (video start delay) has to be long enough to ensure that the |
758 | * DSI TX does not start transmitting until we have started receiving |
759 | * pixel data from the DPI input. It is not clear how to calculate |
760 | * this either. |
761 | */ |
762 | |
763 | dpi_htot = vm.hactive + vm.hfront_porch + vm.hsync_len + vm.hback_porch; |
764 | dpi_data_start = vm.hsync_len + vm.hback_porch; |
765 | |
766 | dev_dbg(dev, "dpi horiz timing (pclk): %u + %u + %u + %u = %u\n" , |
767 | vm.hsync_len, vm.hback_porch, vm.hactive, vm.hfront_porch, |
768 | dpi_htot); |
769 | |
770 | dev_dbg(dev, "dpi horiz timing (ns): %u + %u + %u + %u = %u\n" , |
771 | tc358768_dpi_to_ns(vm.hsync_len, vm.pixelclock), |
772 | tc358768_dpi_to_ns(vm.hback_porch, vm.pixelclock), |
773 | tc358768_dpi_to_ns(vm.hactive, vm.pixelclock), |
774 | tc358768_dpi_to_ns(vm.hfront_porch, vm.pixelclock), |
775 | tc358768_dpi_to_ns(dpi_htot, vm.pixelclock)); |
776 | |
777 | dev_dbg(dev, "dpi data start (ns): %u + %u = %u\n" , |
778 | tc358768_dpi_to_ns(vm.hsync_len, vm.pixelclock), |
779 | tc358768_dpi_to_ns(vm.hback_porch, vm.pixelclock), |
780 | tc358768_dpi_to_ns(dpi_data_start, vm.pixelclock)); |
781 | |
782 | dsi_dpi_htot = tc358768_dpi_to_dsi_bytes(priv, val: dpi_htot); |
783 | dsi_dpi_data_start = tc358768_dpi_to_dsi_bytes(priv, val: dpi_data_start); |
784 | |
785 | if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { |
786 | dsi_hsw = tc358768_dpi_to_dsi_bytes(priv, val: vm.hsync_len); |
787 | dsi_hbp = tc358768_dpi_to_dsi_bytes(priv, val: vm.hback_porch); |
788 | } else { |
789 | /* HBP is included in HSW in event mode */ |
790 | dsi_hbp = 0; |
791 | dsi_hsw = tc358768_dpi_to_dsi_bytes(priv, |
792 | val: vm.hsync_len + |
793 | vm.hback_porch); |
794 | |
795 | /* |
796 | * The pixel packet includes the actual pixel data, and: |
797 | * DSI packet header = 4 bytes |
798 | * DCS code = 1 byte |
799 | * DSI packet footer = 2 bytes |
800 | */ |
801 | dsi_hact = hact + 4 + 1 + 2; |
802 | |
803 | dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; |
804 | |
805 | /* |
806 | * Here we should check if HFP is long enough for entering LP |
807 | * and exiting LP, but it's not clear how to calculate that. |
808 | * Instead, this is a naive algorithm that just adjusts the HFP |
809 | * and HSW so that HFP is (at least) roughly 2/3 of the total |
810 | * blanking time. |
811 | */ |
812 | if (dsi_hfp < (dsi_hfp + dsi_hsw + dsi_hss) * 2 / 3) { |
813 | u32 old_hfp = dsi_hfp; |
814 | u32 old_hsw = dsi_hsw; |
815 | u32 tot = dsi_hfp + dsi_hsw + dsi_hss; |
816 | |
817 | dsi_hsw = tot / 3; |
818 | |
819 | /* |
820 | * Seems like sometimes HSW has to be divisible by num-lanes, but |
821 | * not always... |
822 | */ |
823 | dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes); |
824 | |
825 | dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; |
826 | |
827 | dev_dbg(dev, |
828 | "hfp too short, adjusting dsi hfp and dsi hsw from %u, %u to %u, %u\n" , |
829 | old_hfp, old_hsw, dsi_hfp, dsi_hsw); |
830 | } |
831 | |
832 | dev_dbg(dev, |
833 | "dsi horiz timing (bytes): %u, %u + %u + %u + %u = %u\n" , |
834 | dsi_hss, dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp, |
835 | dsi_hss + dsi_hsw + dsi_hbp + dsi_hact + dsi_hfp); |
836 | |
837 | dev_dbg(dev, "dsi horiz timing (ns): %u + %u + %u + %u + %u = %u\n" , |
838 | tc358768_dsi_bytes_to_ns(priv, dsi_hss), |
839 | tc358768_dsi_bytes_to_ns(priv, dsi_hsw), |
840 | tc358768_dsi_bytes_to_ns(priv, dsi_hbp), |
841 | tc358768_dsi_bytes_to_ns(priv, dsi_hact), |
842 | tc358768_dsi_bytes_to_ns(priv, dsi_hfp), |
843 | tc358768_dsi_bytes_to_ns(priv, dsi_hss + dsi_hsw + |
844 | dsi_hbp + dsi_hact + dsi_hfp)); |
845 | } |
846 | |
847 | /* VSDly calculation */ |
848 | |
849 | /* Start with the HW internal delay */ |
850 | dsi_vsdly = internal_dly; |
851 | |
852 | /* Convert to byte units as the other variables are in byte units */ |
853 | dsi_vsdly *= priv->dsi_lanes; |
854 | |
855 | /* Do we need more delay, in addition to the internal? */ |
856 | if (dsi_dpi_data_start > dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp) { |
857 | dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp; |
858 | dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes); |
859 | } |
860 | |
861 | dev_dbg(dev, "dsi data start (bytes) %u + %u + %u + %u = %u\n" , |
862 | dsi_vsdly, dsi_hss, dsi_hsw, dsi_hbp, |
863 | dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp); |
864 | |
865 | dev_dbg(dev, "dsi data start (ns) %u + %u + %u + %u = %u\n" , |
866 | tc358768_dsi_bytes_to_ns(priv, dsi_vsdly), |
867 | tc358768_dsi_bytes_to_ns(priv, dsi_hss), |
868 | tc358768_dsi_bytes_to_ns(priv, dsi_hsw), |
869 | tc358768_dsi_bytes_to_ns(priv, dsi_hbp), |
870 | tc358768_dsi_bytes_to_ns(priv, dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp)); |
871 | |
872 | /* Convert back to hsbyteclk */ |
873 | dsi_vsdly /= priv->dsi_lanes; |
874 | |
875 | /* |
876 | * The docs say that there is an internal delay of 40 cycles. |
877 | * However, we get underflows if we follow that rule. If we |
878 | * instead ignore the internal delay, things work. So either |
879 | * the docs are wrong or the calculations are wrong. |
880 | * |
881 | * As a temporary fix, add the internal delay here, to counter |
882 | * the subtraction when writing the register. |
883 | */ |
884 | dsi_vsdly += internal_dly; |
885 | |
886 | /* Clamp to the register max */ |
887 | if (dsi_vsdly - internal_dly > 0x3ff) { |
888 | dev_warn(dev, "VSDly too high, underflows likely\n" ); |
889 | dsi_vsdly = 0x3ff + internal_dly; |
890 | } |
891 | |
892 | /* VSDly[9:0] */ |
893 | tc358768_write(priv, TC358768_VSDLY, val: dsi_vsdly - internal_dly); |
894 | |
895 | tc358768_write(priv, TC358768_DATAFMT, val); |
896 | tc358768_write(priv, TC358768_DSITX_DT, val: data_type); |
897 | |
898 | /* Enable D-PHY (HiZ->LP11) */ |
899 | tc358768_write(priv, TC358768_CLW_CNTRL, val: 0x0000); |
900 | /* Enable lanes */ |
901 | for (i = 0; i < dsi_dev->lanes; i++) |
902 | tc358768_write(priv, TC358768_D0W_CNTRL + i * 4, val: 0x0000); |
903 | |
904 | /* DSI Timings */ |
905 | hsbyteclk_ps = (u32)div_u64(PICO, divisor: hsbyteclk); |
906 | dsiclk_ps = (u32)div_u64(PICO, divisor: dsiclk); |
907 | ui_ps = dsiclk_ps / 2; |
908 | dev_dbg(dev, "dsiclk: %u ps, ui %u ps, hsbyteclk %u ps\n" , dsiclk_ps, |
909 | ui_ps, hsbyteclk_ps); |
910 | |
911 | /* LP11 > 100us for D-PHY Rx Init */ |
912 | val = tc358768_ns_to_cnt(ns: 100 * 1000, period_ps: hsbyteclk_ps) - 1; |
913 | dev_dbg(dev, "LINEINITCNT: %u\n" , val); |
914 | tc358768_write(priv, TC358768_LINEINITCNT, val); |
915 | |
916 | /* LPTimeCnt > 50ns */ |
917 | val = tc358768_ns_to_cnt(ns: 50, period_ps: hsbyteclk_ps) - 1; |
918 | lptxcnt = val; |
919 | dev_dbg(dev, "LPTXTIMECNT: %u\n" , val); |
920 | tc358768_write(priv, TC358768_LPTXTIMECNT, val); |
921 | |
922 | /* 38ns < TCLK_PREPARE < 95ns */ |
923 | val = tc358768_ns_to_cnt(ns: 65, period_ps: hsbyteclk_ps) - 1; |
924 | dev_dbg(dev, "TCLK_PREPARECNT %u\n" , val); |
925 | /* TCLK_PREPARE + TCLK_ZERO > 300ns */ |
926 | val2 = tc358768_ns_to_cnt(ns: 300 - tc358768_ps_to_ns(ps: 2 * ui_ps), |
927 | period_ps: hsbyteclk_ps) - 2; |
928 | dev_dbg(dev, "TCLK_ZEROCNT %u\n" , val2); |
929 | val |= val2 << 8; |
930 | tc358768_write(priv, TC358768_TCLK_HEADERCNT, val); |
931 | |
932 | /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ |
933 | raw_val = tc358768_ns_to_cnt(ns: 60 + tc358768_ps_to_ns(ps: 2 * ui_ps), period_ps: hsbyteclk_ps) - 5; |
934 | val = clamp(raw_val, 0, 127); |
935 | dev_dbg(dev, "TCLK_TRAILCNT: %u\n" , val); |
936 | tc358768_write(priv, TC358768_TCLK_TRAILCNT, val); |
937 | |
938 | /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ |
939 | val = 50 + tc358768_ps_to_ns(ps: 4 * ui_ps); |
940 | val = tc358768_ns_to_cnt(ns: val, period_ps: hsbyteclk_ps) - 1; |
941 | dev_dbg(dev, "THS_PREPARECNT %u\n" , val); |
942 | /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ |
943 | raw_val = tc358768_ns_to_cnt(ns: 145 - tc358768_ps_to_ns(ps: 3 * ui_ps), period_ps: hsbyteclk_ps) - 10; |
944 | val2 = clamp(raw_val, 0, 127); |
945 | dev_dbg(dev, "THS_ZEROCNT %u\n" , val2); |
946 | val |= val2 << 8; |
947 | tc358768_write(priv, TC358768_THS_HEADERCNT, val); |
948 | |
949 | /* TWAKEUP > 1ms in lptxcnt steps */ |
950 | val = tc358768_ns_to_cnt(ns: 1020000, period_ps: hsbyteclk_ps); |
951 | val = val / (lptxcnt + 1) - 1; |
952 | dev_dbg(dev, "TWAKEUP: %u\n" , val); |
953 | tc358768_write(priv, TC358768_TWAKEUP, val); |
954 | |
955 | /* TCLK_POSTCNT > 60ns + 52*UI */ |
956 | val = tc358768_ns_to_cnt(ns: 60 + tc358768_ps_to_ns(ps: 52 * ui_ps), |
957 | period_ps: hsbyteclk_ps) - 3; |
958 | dev_dbg(dev, "TCLK_POSTCNT: %u\n" , val); |
959 | tc358768_write(priv, TC358768_TCLK_POSTCNT, val); |
960 | |
961 | /* max(60ns + 4*UI, 8*UI) < THS_TRAILCNT < 105ns + 12*UI */ |
962 | raw_val = tc358768_ns_to_cnt(ns: 60 + tc358768_ps_to_ns(ps: 18 * ui_ps), |
963 | period_ps: hsbyteclk_ps) - 4; |
964 | val = clamp(raw_val, 0, 15); |
965 | dev_dbg(dev, "THS_TRAILCNT: %u\n" , val); |
966 | tc358768_write(priv, TC358768_THS_TRAILCNT, val); |
967 | |
968 | val = BIT(0); |
969 | for (i = 0; i < dsi_dev->lanes; i++) |
970 | val |= BIT(i + 1); |
971 | tc358768_write(priv, TC358768_HSTXVREGEN, val); |
972 | |
973 | tc358768_write(priv, TC358768_TXOPTIONCNTRL, |
974 | val: (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? 0 : BIT(0)); |
975 | |
976 | /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */ |
977 | val = tc358768_ps_to_ns(ps: (lptxcnt + 1) * hsbyteclk_ps * 4); |
978 | val = tc358768_ns_to_cnt(ns: val, period_ps: hsbyteclk_ps) / 4 - 1; |
979 | dev_dbg(dev, "TXTAGOCNT: %u\n" , val); |
980 | val2 = tc358768_ns_to_cnt(ns: tc358768_ps_to_ns(ps: (lptxcnt + 1) * hsbyteclk_ps), |
981 | period_ps: hsbyteclk_ps) - 2; |
982 | dev_dbg(dev, "RXTASURECNT: %u\n" , val2); |
983 | val = val << 16 | val2; |
984 | tc358768_write(priv, TC358768_BTACNTRL1, val); |
985 | |
986 | /* START[0] */ |
987 | tc358768_write(priv, TC358768_STARTCNTRL, val: 1); |
988 | |
989 | if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { |
990 | /* Set pulse mode */ |
991 | tc358768_write(priv, TC358768_DSI_EVENT, val: 0); |
992 | |
993 | /* vact */ |
994 | tc358768_write(priv, TC358768_DSI_VACT, val: vm.vactive); |
995 | |
996 | /* vsw */ |
997 | tc358768_write(priv, TC358768_DSI_VSW, val: vm.vsync_len); |
998 | |
999 | /* vbp */ |
1000 | tc358768_write(priv, TC358768_DSI_VBPR, val: vm.vback_porch); |
1001 | } else { |
1002 | /* Set event mode */ |
1003 | tc358768_write(priv, TC358768_DSI_EVENT, val: 1); |
1004 | |
1005 | /* vact */ |
1006 | tc358768_write(priv, TC358768_DSI_VACT, val: vm.vactive); |
1007 | |
1008 | /* vsw (+ vbp) */ |
1009 | tc358768_write(priv, TC358768_DSI_VSW, |
1010 | val: vm.vsync_len + vm.vback_porch); |
1011 | |
1012 | /* vbp (not used in event mode) */ |
1013 | tc358768_write(priv, TC358768_DSI_VBPR, val: 0); |
1014 | } |
1015 | |
1016 | /* hsw (bytes) */ |
1017 | tc358768_write(priv, TC358768_DSI_HSW, val: dsi_hsw); |
1018 | |
1019 | /* hbp (bytes) */ |
1020 | tc358768_write(priv, TC358768_DSI_HBPR, val: dsi_hbp); |
1021 | |
1022 | /* hact (bytes) */ |
1023 | tc358768_write(priv, TC358768_DSI_HACT, val: hact); |
1024 | |
1025 | /* VSYNC polarity */ |
1026 | tc358768_update_bits(priv, TC358768_CONFCTL, BIT(5), |
1027 | val: (mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(5) : 0); |
1028 | |
1029 | /* HSYNC polarity */ |
1030 | tc358768_update_bits(priv, TC358768_PP_MISC, BIT(0), |
1031 | val: (mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(0) : 0); |
1032 | |
1033 | /* Start DSI Tx */ |
1034 | tc358768_write(priv, TC358768_DSI_START, val: 0x1); |
1035 | |
1036 | /* Configure DSI_Control register */ |
1037 | val = TC358768_DSI_CONFW_MODE_CLR | TC358768_DSI_CONFW_ADDR_DSI_CONTROL; |
1038 | val |= TC358768_DSI_CONTROL_TXMD | TC358768_DSI_CONTROL_HSCKMD | |
1039 | 0x3 << 1 | TC358768_DSI_CONTROL_EOTDIS; |
1040 | tc358768_write(priv, TC358768_DSI_CONFW, val); |
1041 | |
1042 | val = TC358768_DSI_CONFW_MODE_SET | TC358768_DSI_CONFW_ADDR_DSI_CONTROL; |
1043 | val |= (dsi_dev->lanes - 1) << 1; |
1044 | |
1045 | val |= TC358768_DSI_CONTROL_TXMD; |
1046 | |
1047 | if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) |
1048 | val |= TC358768_DSI_CONTROL_HSCKMD; |
1049 | |
1050 | if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) |
1051 | val |= TC358768_DSI_CONTROL_EOTDIS; |
1052 | |
1053 | tc358768_write(priv, TC358768_DSI_CONFW, val); |
1054 | |
1055 | val = TC358768_DSI_CONFW_MODE_CLR | TC358768_DSI_CONFW_ADDR_DSI_CONTROL; |
1056 | val |= TC358768_DSI_CONTROL_DIS_MODE; /* DSI mode */ |
1057 | tc358768_write(priv, TC358768_DSI_CONFW, val); |
1058 | |
1059 | ret = tc358768_clear_error(priv); |
1060 | if (ret) { |
1061 | dev_err(dev, "Bridge pre_enable failed: %d\n" , ret); |
1062 | tc358768_bridge_disable(bridge); |
1063 | tc358768_bridge_post_disable(bridge); |
1064 | } |
1065 | } |
1066 | |
1067 | static void tc358768_bridge_enable(struct drm_bridge *bridge) |
1068 | { |
1069 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
1070 | int ret; |
1071 | |
1072 | if (!priv->enabled) { |
1073 | dev_err(priv->dev, "Bridge is not enabled\n" ); |
1074 | return; |
1075 | } |
1076 | |
1077 | /* clear FrmStop and RstPtr */ |
1078 | tc358768_update_bits(priv, TC358768_PP_MISC, mask: 0x3 << 14, val: 0); |
1079 | |
1080 | /* set PP_en */ |
1081 | tc358768_update_bits(priv, TC358768_CONFCTL, BIT(6), BIT(6)); |
1082 | |
1083 | ret = tc358768_clear_error(priv); |
1084 | if (ret) { |
1085 | dev_err(priv->dev, "Bridge enable failed: %d\n" , ret); |
1086 | tc358768_bridge_disable(bridge); |
1087 | tc358768_bridge_post_disable(bridge); |
1088 | } |
1089 | } |
1090 | |
1091 | #define MAX_INPUT_SEL_FORMATS 1 |
1092 | |
1093 | static u32 * |
1094 | tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge, |
1095 | struct drm_bridge_state *bridge_state, |
1096 | struct drm_crtc_state *crtc_state, |
1097 | struct drm_connector_state *conn_state, |
1098 | u32 output_fmt, |
1099 | unsigned int *num_input_fmts) |
1100 | { |
1101 | struct tc358768_priv *priv = bridge_to_tc358768(bridge); |
1102 | u32 *input_fmts; |
1103 | |
1104 | *num_input_fmts = 0; |
1105 | |
1106 | input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, size: sizeof(*input_fmts), |
1107 | GFP_KERNEL); |
1108 | if (!input_fmts) |
1109 | return NULL; |
1110 | |
1111 | switch (priv->pd_lines) { |
1112 | case 16: |
1113 | input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16; |
1114 | break; |
1115 | case 18: |
1116 | input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18; |
1117 | break; |
1118 | default: |
1119 | case 24: |
1120 | input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; |
1121 | break; |
1122 | } |
1123 | |
1124 | *num_input_fmts = MAX_INPUT_SEL_FORMATS; |
1125 | |
1126 | return input_fmts; |
1127 | } |
1128 | |
1129 | static bool tc358768_mode_fixup(struct drm_bridge *bridge, |
1130 | const struct drm_display_mode *mode, |
1131 | struct drm_display_mode *adjusted_mode) |
1132 | { |
1133 | /* Default to positive sync */ |
1134 | |
1135 | if (!(adjusted_mode->flags & |
1136 | (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC))) |
1137 | adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; |
1138 | |
1139 | if (!(adjusted_mode->flags & |
1140 | (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))) |
1141 | adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; |
1142 | |
1143 | return true; |
1144 | } |
1145 | |
1146 | static const struct drm_bridge_funcs tc358768_bridge_funcs = { |
1147 | .attach = tc358768_bridge_attach, |
1148 | .mode_valid = tc358768_bridge_mode_valid, |
1149 | .mode_fixup = tc358768_mode_fixup, |
1150 | .pre_enable = tc358768_bridge_pre_enable, |
1151 | .enable = tc358768_bridge_enable, |
1152 | .disable = tc358768_bridge_disable, |
1153 | .post_disable = tc358768_bridge_post_disable, |
1154 | |
1155 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
1156 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
1157 | .atomic_reset = drm_atomic_helper_bridge_reset, |
1158 | .atomic_get_input_bus_fmts = tc358768_atomic_get_input_bus_fmts, |
1159 | }; |
1160 | |
1161 | static const struct drm_bridge_timings default_tc358768_timings = { |
1162 | .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |
1163 | | DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE |
1164 | | DRM_BUS_FLAG_DE_HIGH, |
1165 | }; |
1166 | |
1167 | static bool tc358768_is_reserved_reg(unsigned int reg) |
1168 | { |
1169 | switch (reg) { |
1170 | case 0x114 ... 0x13f: |
1171 | case 0x200: |
1172 | case 0x20c: |
1173 | case 0x400 ... 0x408: |
1174 | case 0x41c ... 0x42f: |
1175 | return true; |
1176 | default: |
1177 | return false; |
1178 | } |
1179 | } |
1180 | |
1181 | static bool tc358768_writeable_reg(struct device *dev, unsigned int reg) |
1182 | { |
1183 | if (tc358768_is_reserved_reg(reg)) |
1184 | return false; |
1185 | |
1186 | switch (reg) { |
1187 | case TC358768_CHIPID: |
1188 | case TC358768_FIFOSTATUS: |
1189 | case TC358768_DSITXSTATUS ... (TC358768_DSITXSTATUS + 2): |
1190 | case TC358768_DSI_CONTROL ... (TC358768_DSI_INT_ENA + 2): |
1191 | case TC358768_DSICMD_RDFIFO ... (TC358768_DSI_ERR_HALT + 2): |
1192 | return false; |
1193 | default: |
1194 | return true; |
1195 | } |
1196 | } |
1197 | |
1198 | static bool tc358768_readable_reg(struct device *dev, unsigned int reg) |
1199 | { |
1200 | if (tc358768_is_reserved_reg(reg)) |
1201 | return false; |
1202 | |
1203 | switch (reg) { |
1204 | case TC358768_STARTCNTRL: |
1205 | case TC358768_DSI_CONFW ... (TC358768_DSI_CONFW + 2): |
1206 | case TC358768_DSI_INT_CLR ... (TC358768_DSI_INT_CLR + 2): |
1207 | case TC358768_DSI_START ... (TC358768_DSI_START + 2): |
1208 | case TC358768_DBG_DATA: |
1209 | return false; |
1210 | default: |
1211 | return true; |
1212 | } |
1213 | } |
1214 | |
1215 | static const struct regmap_config tc358768_regmap_config = { |
1216 | .name = "tc358768" , |
1217 | .reg_bits = 16, |
1218 | .val_bits = 16, |
1219 | .max_register = TC358768_DSI_HACT, |
1220 | .cache_type = REGCACHE_NONE, |
1221 | .writeable_reg = tc358768_writeable_reg, |
1222 | .readable_reg = tc358768_readable_reg, |
1223 | .reg_format_endian = REGMAP_ENDIAN_BIG, |
1224 | .val_format_endian = REGMAP_ENDIAN_BIG, |
1225 | }; |
1226 | |
1227 | static const struct i2c_device_id tc358768_i2c_ids[] = { |
1228 | { "tc358768" , 0 }, |
1229 | { "tc358778" , 0 }, |
1230 | { } |
1231 | }; |
1232 | MODULE_DEVICE_TABLE(i2c, tc358768_i2c_ids); |
1233 | |
1234 | static const struct of_device_id tc358768_of_ids[] = { |
1235 | { .compatible = "toshiba,tc358768" , }, |
1236 | { .compatible = "toshiba,tc358778" , }, |
1237 | { } |
1238 | }; |
1239 | MODULE_DEVICE_TABLE(of, tc358768_of_ids); |
1240 | |
1241 | static int tc358768_get_regulators(struct tc358768_priv *priv) |
1242 | { |
1243 | int i, ret; |
1244 | |
1245 | for (i = 0; i < ARRAY_SIZE(priv->supplies); ++i) |
1246 | priv->supplies[i].supply = tc358768_supplies[i]; |
1247 | |
1248 | ret = devm_regulator_bulk_get(dev: priv->dev, ARRAY_SIZE(priv->supplies), |
1249 | consumers: priv->supplies); |
1250 | if (ret < 0) |
1251 | dev_err(priv->dev, "failed to get regulators: %d\n" , ret); |
1252 | |
1253 | return ret; |
1254 | } |
1255 | |
1256 | static int tc358768_i2c_probe(struct i2c_client *client) |
1257 | { |
1258 | struct tc358768_priv *priv; |
1259 | struct device *dev = &client->dev; |
1260 | struct device_node *np = dev->of_node; |
1261 | int ret; |
1262 | |
1263 | if (!np) |
1264 | return -ENODEV; |
1265 | |
1266 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
1267 | if (!priv) |
1268 | return -ENOMEM; |
1269 | |
1270 | dev_set_drvdata(dev, data: priv); |
1271 | priv->dev = dev; |
1272 | |
1273 | ret = tc358768_get_regulators(priv); |
1274 | if (ret) |
1275 | return ret; |
1276 | |
1277 | priv->refclk = devm_clk_get(dev, id: "refclk" ); |
1278 | if (IS_ERR(ptr: priv->refclk)) |
1279 | return PTR_ERR(ptr: priv->refclk); |
1280 | |
1281 | /* |
1282 | * RESX is low active, to disable tc358768 initially (keep in reset) |
1283 | * the gpio line must be LOW. This is the ASSERTED state of |
1284 | * GPIO_ACTIVE_LOW (GPIOD_OUT_HIGH == ASSERTED). |
1285 | */ |
1286 | priv->reset_gpio = devm_gpiod_get_optional(dev, con_id: "reset" , |
1287 | flags: GPIOD_OUT_HIGH); |
1288 | if (IS_ERR(ptr: priv->reset_gpio)) |
1289 | return PTR_ERR(ptr: priv->reset_gpio); |
1290 | |
1291 | priv->regmap = devm_regmap_init_i2c(client, &tc358768_regmap_config); |
1292 | if (IS_ERR(ptr: priv->regmap)) { |
1293 | dev_err(dev, "Failed to init regmap\n" ); |
1294 | return PTR_ERR(ptr: priv->regmap); |
1295 | } |
1296 | |
1297 | priv->dsi_host.dev = dev; |
1298 | priv->dsi_host.ops = &tc358768_dsi_host_ops; |
1299 | |
1300 | priv->bridge.funcs = &tc358768_bridge_funcs; |
1301 | priv->bridge.timings = &default_tc358768_timings; |
1302 | priv->bridge.of_node = np; |
1303 | |
1304 | i2c_set_clientdata(client, data: priv); |
1305 | |
1306 | return mipi_dsi_host_register(host: &priv->dsi_host); |
1307 | } |
1308 | |
1309 | static void tc358768_i2c_remove(struct i2c_client *client) |
1310 | { |
1311 | struct tc358768_priv *priv = i2c_get_clientdata(client); |
1312 | |
1313 | mipi_dsi_host_unregister(host: &priv->dsi_host); |
1314 | } |
1315 | |
1316 | static struct i2c_driver tc358768_driver = { |
1317 | .driver = { |
1318 | .name = "tc358768" , |
1319 | .of_match_table = tc358768_of_ids, |
1320 | }, |
1321 | .id_table = tc358768_i2c_ids, |
1322 | .probe = tc358768_i2c_probe, |
1323 | .remove = tc358768_i2c_remove, |
1324 | }; |
1325 | module_i2c_driver(tc358768_driver); |
1326 | |
1327 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>" ); |
1328 | MODULE_DESCRIPTION("TC358768AXBG/TC358778XBG DSI bridge" ); |
1329 | MODULE_LICENSE("GPL v2" ); |
1330 | |