Lines Matching +full:keep +full:- +full:pll +full:- +full:enabled
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com
13 #include <linux/media-bus-format.h>
29 /* Global (16-bit addressable) */
46 /* Debug (16-bit addressable) */
52 /* TX PHY (32-bit addressable) */
64 /* TX PPI (32-bit addressable) */
80 /* TX CTRL (32-bit addressable) */
101 /* DSITX CTRL (16-bit addressable) */
147 int enabled; member
158 /* Parameters for PLL programming */
159 u32 fbd; /* PLL feedback divider */
160 u32 prd; /* PLL input divider */
161 u32 frs; /* PLL Freqency range for HSCK (post divider) */
181 int ret = priv->error; in tc358768_clear_error()
183 priv->error = 0; in tc358768_clear_error()
193 if (priv->error) in tc358768_write()
196 /* 16-bit register? */ in tc358768_write()
200 priv->error = regmap_bulk_write(priv->regmap, reg, &tmpval, count); in tc358768_write()
207 if (priv->error) in tc358768_read()
210 /* 16-bit register? */ in tc358768_read()
216 priv->error = regmap_bulk_read(priv->regmap, reg, val, count); in tc358768_read()
226 if (priv->error) in tc358768_update_bits()
241 if (priv->error) in tc358768_dsicmd_tx()
245 priv->error = regmap_read_poll_timeout(priv->regmap, TC358768_DSICMD_TX, val, in tc358768_dsicmd_tx()
264 if (priv->enabled) in tc358768_hw_enable()
267 ret = clk_prepare_enable(priv->refclk); in tc358768_hw_enable()
269 dev_err(priv->dev, "error enabling refclk (%d)\n", ret); in tc358768_hw_enable()
271 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); in tc358768_hw_enable()
273 dev_err(priv->dev, "error enabling regulators (%d)\n", ret); in tc358768_hw_enable()
275 if (priv->reset_gpio) in tc358768_hw_enable()
282 gpiod_set_value_cansleep(priv->reset_gpio, 0); in tc358768_hw_enable()
287 priv->enabled = true; in tc358768_hw_enable()
294 if (!priv->enabled) in tc358768_hw_disable()
301 gpiod_set_value_cansleep(priv->reset_gpio, 1); in tc358768_hw_disable()
303 ret = regulator_bulk_disable(ARRAY_SIZE(priv->supplies), in tc358768_hw_disable()
304 priv->supplies); in tc358768_hw_disable()
306 dev_err(priv->dev, "error disabling regulators (%d)\n", ret); in tc358768_hw_disable()
308 clk_disable_unprepare(priv->refclk); in tc358768_hw_disable()
310 priv->enabled = false; in tc358768_hw_disable()
315 return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->dsi_bpp); in tc358768_pll_to_pclk()
320 return (u32)div_u64((u64)pclk * priv->dsi_bpp, priv->dsi_lanes); in tc358768_pclk_to_pll()
338 target_pll = tc358768_pclk_to_pll(priv, mode->clock * 1000); in tc358768_calc_pll()
347 return -EINVAL; in tc358768_calc_pll()
349 frs = i - 1; in tc358768_calc_pll()
350 max_pll = frs_limits[i - 1]; in tc358768_calc_pll()
353 refclk = clk_get_rate(priv->refclk); in tc358768_calc_pll()
365 u32 pll, diff, pll_in; in tc358768_calc_pll() local
367 pll = (u32)div_u64((u64)refclk * fbd, divisor); in tc358768_calc_pll()
369 if (pll >= max_pll || pll < min_pll) in tc358768_calc_pll()
376 diff = max(pll, target_pll) - min(pll, target_pll); in tc358768_calc_pll()
380 best_pll = pll; in tc358768_calc_pll()
391 dev_err(priv->dev, "could not find suitable PLL setup\n"); in tc358768_calc_pll()
392 return -EINVAL; in tc358768_calc_pll()
399 priv->fbd = best_fbd; in tc358768_calc_pll()
400 priv->prd = best_prd; in tc358768_calc_pll()
401 priv->frs = frs; in tc358768_calc_pll()
402 priv->dsiclk = best_pll / 2; in tc358768_calc_pll()
403 priv->pclk = mode->clock * 1000; in tc358768_calc_pll()
417 if (dev->lanes > 4) { in tc358768_dsi_host_attach()
418 dev_err(priv->dev, "unsupported number of data lanes(%u)\n", in tc358768_dsi_host_attach()
419 dev->lanes); in tc358768_dsi_host_attach()
420 return -EINVAL; in tc358768_dsi_host_attach()
427 if (!(dev->mode_flags & MIPI_DSI_MODE_VIDEO)) { in tc358768_dsi_host_attach()
428 dev_err(priv->dev, "Only MIPI_DSI_MODE_VIDEO is supported\n"); in tc358768_dsi_host_attach()
429 return -ENOTSUPP; in tc358768_dsi_host_attach()
436 if (dev->format != MIPI_DSI_FMT_RGB888) { in tc358768_dsi_host_attach()
437 dev_warn(priv->dev, "Only MIPI_DSI_FMT_RGB888 tested!\n"); in tc358768_dsi_host_attach()
438 return -ENOTSUPP; in tc358768_dsi_host_attach()
441 ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0, &panel, in tc358768_dsi_host_attach()
453 priv->output.dev = dev; in tc358768_dsi_host_attach()
454 priv->output.bridge = bridge; in tc358768_dsi_host_attach()
455 priv->output.panel = panel; in tc358768_dsi_host_attach()
457 priv->dsi_lanes = dev->lanes; in tc358768_dsi_host_attach()
458 priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(dev->format); in tc358768_dsi_host_attach()
461 ret = -EINVAL; in tc358768_dsi_host_attach()
462 ep = of_graph_get_endpoint_by_regs(host->dev->of_node, 0, 0); in tc358768_dsi_host_attach()
464 ret = of_property_read_u32(ep, "data-lines", &priv->pd_lines); in tc358768_dsi_host_attach()
470 priv->pd_lines = priv->dsi_bpp; in tc358768_dsi_host_attach()
472 drm_bridge_add(&priv->bridge); in tc358768_dsi_host_attach()
482 drm_bridge_remove(&priv->bridge); in tc358768_dsi_host_detach()
483 if (priv->output.panel) in tc358768_dsi_host_detach()
484 drm_panel_bridge_remove(priv->output.bridge); in tc358768_dsi_host_detach()
496 if (!priv->enabled) { in tc358768_dsi_host_transfer()
497 dev_err(priv->dev, "Bridge is not enabled\n"); in tc358768_dsi_host_transfer()
498 return -ENODEV; in tc358768_dsi_host_transfer()
501 if (msg->rx_len) { in tc358768_dsi_host_transfer()
502 dev_warn(priv->dev, "MIPI rx is not supported\n"); in tc358768_dsi_host_transfer()
503 return -ENOTSUPP; in tc358768_dsi_host_transfer()
506 if (msg->tx_len > 8) { in tc358768_dsi_host_transfer()
507 dev_warn(priv->dev, "Maximum 8 byte MIPI tx is supported\n"); in tc358768_dsi_host_transfer()
508 return -ENOTSUPP; in tc358768_dsi_host_transfer()
515 if (mipi_dsi_packet_format_is_short(msg->type)) { in tc358768_dsi_host_transfer()
541 dev_warn(priv->dev, "Software disable failed: %d\n", ret); in tc358768_dsi_host_transfer()
559 if (!drm_core_check_feature(bridge->dev, DRIVER_ATOMIC)) { in tc358768_bridge_attach()
560 dev_err(priv->dev, "needs atomic updates support\n"); in tc358768_bridge_attach()
561 return -ENOTSUPP; in tc358768_bridge_attach()
564 return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge, in tc358768_bridge_attach()
600 dev_warn(priv->dev, "Software disable failed: %d\n", ret); in tc358768_bridge_disable()
618 dev_err(priv->dev, "PLL calculation failed: %d\n", ret); in tc358768_setup_pll()
622 fbd = priv->fbd; in tc358768_setup_pll()
623 prd = priv->prd; in tc358768_setup_pll()
624 frs = priv->frs; in tc358768_setup_pll()
626 dev_dbg(priv->dev, "PLL: refclk %lu, fbd %u, prd %u, frs %u\n", in tc358768_setup_pll()
627 clk_get_rate(priv->refclk), fbd, prd, frs); in tc358768_setup_pll()
628 dev_dbg(priv->dev, "PLL: pll_clk: %u, DSIClk %u, HSByteClk %u\n", in tc358768_setup_pll()
629 priv->dsiclk * 2, priv->dsiclk, priv->dsiclk / 4); in tc358768_setup_pll()
630 dev_dbg(priv->dev, "PLL: pclk %u (panel: %u)\n", in tc358768_setup_pll()
631 tc358768_pll_to_pclk(priv, priv->dsiclk * 2), in tc358768_setup_pll()
632 mode->clock * 1000); in tc358768_setup_pll()
635 tc358768_write(priv, TC358768_PLLCTL0, ((prd - 1) << 12) | (fbd - 1)); in tc358768_setup_pll()
669 u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes; in tc358768_dpi_to_dsi_bytes()
670 u64 n = priv->pclk; in tc358768_dpi_to_dsi_bytes()
672 return (u32)div_u64(m + n - 1, n); in tc358768_dpi_to_dsi_bytes()
678 u64 n = priv->dsiclk / 4 * priv->dsi_lanes; in tc358768_dsi_bytes_to_ns()
686 struct mipi_dsi_device *dsi_dev = priv->output.dev; in tc358768_bridge_pre_enable()
687 unsigned long mode_flags = dsi_dev->mode_flags; in tc358768_bridge_pre_enable()
695 struct device *dev = priv->dev; in tc358768_bridge_pre_enable()
707 dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n"); in tc358768_bridge_pre_enable()
720 mode = &bridge->encoder->crtc->state->adjusted_mode; in tc358768_bridge_pre_enable()
723 dev_err(dev, "PLL setup failed: %d\n", ret); in tc358768_bridge_pre_enable()
730 dsiclk = priv->dsiclk; in tc358768_bridge_pre_enable()
735 switch (dsi_dev->format) { in tc358768_bridge_pre_enable()
760 dsi_dev->format); in tc358768_bridge_pre_enable()
769 * 1. Keep the DPI line-time and the DSI line-time as close to each in tc358768_bridge_pre_enable()
802 if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { in tc358768_bridge_pre_enable()
820 dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; in tc358768_bridge_pre_enable()
837 * Seems like sometimes HSW has to be divisible by num-lanes, but in tc358768_bridge_pre_enable()
840 dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes); in tc358768_bridge_pre_enable()
842 dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; in tc358768_bridge_pre_enable()
870 dsi_vsdly *= priv->dsi_lanes; in tc358768_bridge_pre_enable()
874 dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp; in tc358768_bridge_pre_enable()
875 dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes); in tc358768_bridge_pre_enable()
890 dsi_vsdly /= priv->dsi_lanes; in tc358768_bridge_pre_enable()
904 if (dsi_vsdly - internal_dly > 0x3ff) { in tc358768_bridge_pre_enable()
910 tc358768_write(priv, TC358768_VSDLY, dsi_vsdly - internal_dly); in tc358768_bridge_pre_enable()
915 /* Enable D-PHY (HiZ->LP11) */ in tc358768_bridge_pre_enable()
918 for (i = 0; i < dsi_dev->lanes; i++) in tc358768_bridge_pre_enable()
928 /* LP11 > 100us for D-PHY Rx Init */ in tc358768_bridge_pre_enable()
929 val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
934 val = tc358768_ns_to_cnt(50, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
940 val = tc358768_ns_to_cnt(65, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
943 val2 = tc358768_ns_to_cnt(300 - tc358768_ps_to_ns(2 * ui_ps), in tc358768_bridge_pre_enable()
944 hsbyteclk_ps) - 2; in tc358768_bridge_pre_enable()
950 raw_val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(2 * ui_ps), hsbyteclk_ps) - 5; in tc358768_bridge_pre_enable()
957 val = tc358768_ns_to_cnt(val, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
960 raw_val = tc358768_ns_to_cnt(145 - tc358768_ps_to_ns(3 * ui_ps), hsbyteclk_ps) - 10; in tc358768_bridge_pre_enable()
968 val = val / (lptxcnt + 1) - 1; in tc358768_bridge_pre_enable()
974 hsbyteclk_ps) - 3; in tc358768_bridge_pre_enable()
980 hsbyteclk_ps) - 4; in tc358768_bridge_pre_enable()
986 for (i = 0; i < dsi_dev->lanes; i++) in tc358768_bridge_pre_enable()
995 val = tc358768_ns_to_cnt(val, hsbyteclk_ps) / 4 - 1; in tc358768_bridge_pre_enable()
998 hsbyteclk_ps) - 2; in tc358768_bridge_pre_enable()
1006 if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { in tc358768_bridge_pre_enable()
1044 (mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(5) : 0); in tc358768_bridge_pre_enable()
1048 (mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(0) : 0); in tc358768_bridge_pre_enable()
1060 val |= (dsi_dev->lanes - 1) << 1; in tc358768_bridge_pre_enable()
1067 if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) in tc358768_bridge_pre_enable()
1089 if (!priv->enabled) { in tc358768_bridge_enable()
1090 dev_err(priv->dev, "Bridge is not enabled\n"); in tc358768_bridge_enable()
1102 dev_err(priv->dev, "Bridge enable failed: %d\n", ret); in tc358768_bridge_enable()
1128 switch (priv->pd_lines) { in tc358768_atomic_get_input_bus_fmts()
1152 if (!(adjusted_mode->flags & in tc358768_mode_fixup()
1154 adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; in tc358768_mode_fixup()
1156 if (!(adjusted_mode->flags & in tc358768_mode_fixup()
1158 adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; in tc358768_mode_fixup()
1262 for (i = 0; i < ARRAY_SIZE(priv->supplies); ++i) in tc358768_get_regulators()
1263 priv->supplies[i].supply = tc358768_supplies[i]; in tc358768_get_regulators()
1265 ret = devm_regulator_bulk_get(priv->dev, ARRAY_SIZE(priv->supplies), in tc358768_get_regulators()
1266 priv->supplies); in tc358768_get_regulators()
1268 dev_err(priv->dev, "failed to get regulators: %d\n", ret); in tc358768_get_regulators()
1276 struct device *dev = &client->dev; in tc358768_i2c_probe()
1277 struct device_node *np = dev->of_node; in tc358768_i2c_probe()
1281 return -ENODEV; in tc358768_i2c_probe()
1285 return -ENOMEM; in tc358768_i2c_probe()
1288 priv->dev = dev; in tc358768_i2c_probe()
1294 priv->refclk = devm_clk_get(dev, "refclk"); in tc358768_i2c_probe()
1295 if (IS_ERR(priv->refclk)) in tc358768_i2c_probe()
1296 return PTR_ERR(priv->refclk); in tc358768_i2c_probe()
1299 * RESX is low active, to disable tc358768 initially (keep in reset) in tc358768_i2c_probe()
1303 priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", in tc358768_i2c_probe()
1305 if (IS_ERR(priv->reset_gpio)) in tc358768_i2c_probe()
1306 return PTR_ERR(priv->reset_gpio); in tc358768_i2c_probe()
1308 priv->regmap = devm_regmap_init_i2c(client, &tc358768_regmap_config); in tc358768_i2c_probe()
1309 if (IS_ERR(priv->regmap)) { in tc358768_i2c_probe()
1311 return PTR_ERR(priv->regmap); in tc358768_i2c_probe()
1314 priv->dsi_host.dev = dev; in tc358768_i2c_probe()
1315 priv->dsi_host.ops = &tc358768_dsi_host_ops; in tc358768_i2c_probe()
1317 priv->bridge.funcs = &tc358768_bridge_funcs; in tc358768_i2c_probe()
1318 priv->bridge.timings = &default_tc358768_timings; in tc358768_i2c_probe()
1319 priv->bridge.of_node = np; in tc358768_i2c_probe()
1323 return mipi_dsi_host_register(&priv->dsi_host); in tc358768_i2c_probe()
1330 mipi_dsi_host_unregister(&priv->dsi_host); in tc358768_i2c_remove()