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, "bus-width", &priv->pd_lines); in tc358768_dsi_host_attach()
466 ret = of_property_read_u32(ep, "data-lines", &priv->pd_lines); in tc358768_dsi_host_attach()
472 priv->pd_lines = priv->dsi_bpp; in tc358768_dsi_host_attach()
474 drm_bridge_add(&priv->bridge); in tc358768_dsi_host_attach()
484 drm_bridge_remove(&priv->bridge); in tc358768_dsi_host_detach()
485 if (priv->output.panel) in tc358768_dsi_host_detach()
486 drm_panel_bridge_remove(priv->output.bridge); in tc358768_dsi_host_detach()
498 if (!priv->enabled) { in tc358768_dsi_host_transfer()
499 dev_err(priv->dev, "Bridge is not enabled\n"); in tc358768_dsi_host_transfer()
500 return -ENODEV; in tc358768_dsi_host_transfer()
503 if (msg->rx_len) { in tc358768_dsi_host_transfer()
504 dev_warn(priv->dev, "MIPI rx is not supported\n"); in tc358768_dsi_host_transfer()
505 return -ENOTSUPP; in tc358768_dsi_host_transfer()
508 if (msg->tx_len > 8) { in tc358768_dsi_host_transfer()
509 dev_warn(priv->dev, "Maximum 8 byte MIPI tx is supported\n"); in tc358768_dsi_host_transfer()
510 return -ENOTSUPP; in tc358768_dsi_host_transfer()
517 if (mipi_dsi_packet_format_is_short(msg->type)) { in tc358768_dsi_host_transfer()
543 dev_warn(priv->dev, "Software disable failed: %d\n", ret); in tc358768_dsi_host_transfer()
561 if (!drm_core_check_feature(bridge->dev, DRIVER_ATOMIC)) { in tc358768_bridge_attach()
562 dev_err(priv->dev, "needs atomic updates support\n"); in tc358768_bridge_attach()
563 return -ENOTSUPP; in tc358768_bridge_attach()
566 return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge, in tc358768_bridge_attach()
602 dev_warn(priv->dev, "Software disable failed: %d\n", ret); in tc358768_bridge_disable()
620 dev_err(priv->dev, "PLL calculation failed: %d\n", ret); in tc358768_setup_pll()
624 fbd = priv->fbd; in tc358768_setup_pll()
625 prd = priv->prd; in tc358768_setup_pll()
626 frs = priv->frs; in tc358768_setup_pll()
628 dev_dbg(priv->dev, "PLL: refclk %lu, fbd %u, prd %u, frs %u\n", in tc358768_setup_pll()
629 clk_get_rate(priv->refclk), fbd, prd, frs); in tc358768_setup_pll()
630 dev_dbg(priv->dev, "PLL: pll_clk: %u, DSIClk %u, HSByteClk %u\n", in tc358768_setup_pll()
631 priv->dsiclk * 2, priv->dsiclk, priv->dsiclk / 4); in tc358768_setup_pll()
632 dev_dbg(priv->dev, "PLL: pclk %u (panel: %u)\n", in tc358768_setup_pll()
633 tc358768_pll_to_pclk(priv, priv->dsiclk * 2), in tc358768_setup_pll()
634 mode->clock * 1000); in tc358768_setup_pll()
637 tc358768_write(priv, TC358768_PLLCTL0, ((prd - 1) << 12) | (fbd - 1)); in tc358768_setup_pll()
671 u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes; in tc358768_dpi_to_dsi_bytes()
672 u64 n = priv->pclk; in tc358768_dpi_to_dsi_bytes()
674 return (u32)div_u64(m + n - 1, n); in tc358768_dpi_to_dsi_bytes()
680 u64 n = priv->dsiclk / 4 * priv->dsi_lanes; in tc358768_dsi_bytes_to_ns()
688 struct mipi_dsi_device *dsi_dev = priv->output.dev; in tc358768_bridge_pre_enable()
689 unsigned long mode_flags = dsi_dev->mode_flags; in tc358768_bridge_pre_enable()
697 struct device *dev = priv->dev; in tc358768_bridge_pre_enable()
709 dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n"); in tc358768_bridge_pre_enable()
722 mode = &bridge->encoder->crtc->state->adjusted_mode; in tc358768_bridge_pre_enable()
725 dev_err(dev, "PLL setup failed: %d\n", ret); in tc358768_bridge_pre_enable()
732 dsiclk = priv->dsiclk; in tc358768_bridge_pre_enable()
737 switch (dsi_dev->format) { in tc358768_bridge_pre_enable()
762 dsi_dev->format); in tc358768_bridge_pre_enable()
771 * 1. Keep the DPI line-time and the DSI line-time as close to each in tc358768_bridge_pre_enable()
804 if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { in tc358768_bridge_pre_enable()
822 dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; in tc358768_bridge_pre_enable()
839 * Seems like sometimes HSW has to be divisible by num-lanes, but in tc358768_bridge_pre_enable()
842 dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes); in tc358768_bridge_pre_enable()
844 dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; in tc358768_bridge_pre_enable()
872 dsi_vsdly *= priv->dsi_lanes; in tc358768_bridge_pre_enable()
876 dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp; in tc358768_bridge_pre_enable()
877 dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes); in tc358768_bridge_pre_enable()
892 dsi_vsdly /= priv->dsi_lanes; in tc358768_bridge_pre_enable()
906 if (dsi_vsdly - internal_dly > 0x3ff) { in tc358768_bridge_pre_enable()
912 tc358768_write(priv, TC358768_VSDLY, dsi_vsdly - internal_dly); in tc358768_bridge_pre_enable()
917 /* Enable D-PHY (HiZ->LP11) */ in tc358768_bridge_pre_enable()
920 for (i = 0; i < dsi_dev->lanes; i++) in tc358768_bridge_pre_enable()
930 /* LP11 > 100us for D-PHY Rx Init */ in tc358768_bridge_pre_enable()
931 val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
936 val = tc358768_ns_to_cnt(50, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
942 val = tc358768_ns_to_cnt(65, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
945 val2 = tc358768_ns_to_cnt(300 - tc358768_ps_to_ns(2 * ui_ps), in tc358768_bridge_pre_enable()
946 hsbyteclk_ps) - 2; in tc358768_bridge_pre_enable()
952 raw_val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(2 * ui_ps), hsbyteclk_ps) - 5; in tc358768_bridge_pre_enable()
959 val = tc358768_ns_to_cnt(val, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
962 raw_val = tc358768_ns_to_cnt(145 - tc358768_ps_to_ns(3 * ui_ps), hsbyteclk_ps) - 10; in tc358768_bridge_pre_enable()
970 val = val / (lptxcnt + 1) - 1; in tc358768_bridge_pre_enable()
976 hsbyteclk_ps) - 3; in tc358768_bridge_pre_enable()
982 hsbyteclk_ps) - 4; in tc358768_bridge_pre_enable()
988 for (i = 0; i < dsi_dev->lanes; i++) in tc358768_bridge_pre_enable()
997 val = tc358768_ns_to_cnt(val, hsbyteclk_ps) / 4 - 1; in tc358768_bridge_pre_enable()
1000 hsbyteclk_ps) - 2; in tc358768_bridge_pre_enable()
1008 if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { in tc358768_bridge_pre_enable()
1046 (mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(5) : 0); in tc358768_bridge_pre_enable()
1050 (mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(0) : 0); in tc358768_bridge_pre_enable()
1062 val |= (dsi_dev->lanes - 1) << 1; in tc358768_bridge_pre_enable()
1069 if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) in tc358768_bridge_pre_enable()
1091 if (!priv->enabled) { in tc358768_bridge_enable()
1092 dev_err(priv->dev, "Bridge is not enabled\n"); in tc358768_bridge_enable()
1104 dev_err(priv->dev, "Bridge enable failed: %d\n", ret); in tc358768_bridge_enable()
1130 switch (priv->pd_lines) { in tc358768_atomic_get_input_bus_fmts()
1154 if (!(adjusted_mode->flags & in tc358768_mode_fixup()
1156 adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; in tc358768_mode_fixup()
1158 if (!(adjusted_mode->flags & in tc358768_mode_fixup()
1160 adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; in tc358768_mode_fixup()
1264 for (i = 0; i < ARRAY_SIZE(priv->supplies); ++i) in tc358768_get_regulators()
1265 priv->supplies[i].supply = tc358768_supplies[i]; in tc358768_get_regulators()
1267 ret = devm_regulator_bulk_get(priv->dev, ARRAY_SIZE(priv->supplies), in tc358768_get_regulators()
1268 priv->supplies); in tc358768_get_regulators()
1270 dev_err(priv->dev, "failed to get regulators: %d\n", ret); in tc358768_get_regulators()
1278 struct device *dev = &client->dev; in tc358768_i2c_probe()
1279 struct device_node *np = dev->of_node; in tc358768_i2c_probe()
1283 return -ENODEV; in tc358768_i2c_probe()
1287 return -ENOMEM; in tc358768_i2c_probe()
1290 priv->dev = dev; in tc358768_i2c_probe()
1296 priv->refclk = devm_clk_get(dev, "refclk"); in tc358768_i2c_probe()
1297 if (IS_ERR(priv->refclk)) in tc358768_i2c_probe()
1298 return PTR_ERR(priv->refclk); in tc358768_i2c_probe()
1301 * RESX is low active, to disable tc358768 initially (keep in reset) in tc358768_i2c_probe()
1305 priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", in tc358768_i2c_probe()
1307 if (IS_ERR(priv->reset_gpio)) in tc358768_i2c_probe()
1308 return PTR_ERR(priv->reset_gpio); in tc358768_i2c_probe()
1310 priv->regmap = devm_regmap_init_i2c(client, &tc358768_regmap_config); in tc358768_i2c_probe()
1311 if (IS_ERR(priv->regmap)) { in tc358768_i2c_probe()
1313 return PTR_ERR(priv->regmap); in tc358768_i2c_probe()
1316 priv->dsi_host.dev = dev; in tc358768_i2c_probe()
1317 priv->dsi_host.ops = &tc358768_dsi_host_ops; in tc358768_i2c_probe()
1319 priv->bridge.funcs = &tc358768_bridge_funcs; in tc358768_i2c_probe()
1320 priv->bridge.timings = &default_tc358768_timings; in tc358768_i2c_probe()
1321 priv->bridge.of_node = np; in tc358768_i2c_probe()
1325 return mipi_dsi_host_register(&priv->dsi_host); in tc358768_i2c_probe()
1332 mipi_dsi_host_unregister(&priv->dsi_host); in tc358768_i2c_remove()