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) */
144 int enabled; member
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) */
178 int ret = priv->error; in tc358768_clear_error()
180 priv->error = 0; in tc358768_clear_error()
190 if (priv->error) in tc358768_write()
193 /* 16-bit register? */ in tc358768_write()
197 priv->error = regmap_bulk_write(priv->regmap, reg, &tmpval, count); in tc358768_write()
204 if (priv->error) in tc358768_read()
207 /* 16-bit register? */ in tc358768_read()
213 priv->error = regmap_bulk_read(priv->regmap, reg, val, count); in tc358768_read()
223 if (priv->error) in tc358768_update_bits()
246 if (priv->enabled) in tc358768_hw_enable()
249 ret = clk_prepare_enable(priv->refclk); in tc358768_hw_enable()
251 dev_err(priv->dev, "error enabling refclk (%d)\n", ret); in tc358768_hw_enable()
253 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); in tc358768_hw_enable()
255 dev_err(priv->dev, "error enabling regulators (%d)\n", ret); in tc358768_hw_enable()
257 if (priv->reset_gpio) in tc358768_hw_enable()
264 gpiod_set_value_cansleep(priv->reset_gpio, 0); in tc358768_hw_enable()
269 priv->enabled = true; in tc358768_hw_enable()
276 if (!priv->enabled) in tc358768_hw_disable()
283 gpiod_set_value_cansleep(priv->reset_gpio, 1); in tc358768_hw_disable()
285 ret = regulator_bulk_disable(ARRAY_SIZE(priv->supplies), in tc358768_hw_disable()
286 priv->supplies); in tc358768_hw_disable()
288 dev_err(priv->dev, "error disabling regulators (%d)\n", ret); in tc358768_hw_disable()
290 clk_disable_unprepare(priv->refclk); in tc358768_hw_disable()
292 priv->enabled = false; in tc358768_hw_disable()
297 return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->dsi_bpp); in tc358768_pll_to_pclk()
302 return (u32)div_u64((u64)pclk * priv->dsi_bpp, priv->dsi_lanes); in tc358768_pclk_to_pll()
320 target_pll = tc358768_pclk_to_pll(priv, mode->clock * 1000); in tc358768_calc_pll()
329 return -EINVAL; in tc358768_calc_pll()
331 frs = i - 1; in tc358768_calc_pll()
332 max_pll = frs_limits[i - 1]; in tc358768_calc_pll()
335 refclk = clk_get_rate(priv->refclk); in tc358768_calc_pll()
347 u32 pll, diff, pll_in; in tc358768_calc_pll() local
349 pll = (u32)div_u64((u64)refclk * fbd, divisor); in tc358768_calc_pll()
351 if (pll >= max_pll || pll < min_pll) in tc358768_calc_pll()
358 diff = max(pll, target_pll) - min(pll, target_pll); in tc358768_calc_pll()
362 best_pll = pll; in tc358768_calc_pll()
373 dev_err(priv->dev, "could not find suitable PLL setup\n"); in tc358768_calc_pll()
374 return -EINVAL; in tc358768_calc_pll()
381 priv->fbd = best_fbd; in tc358768_calc_pll()
382 priv->prd = best_prd; in tc358768_calc_pll()
383 priv->frs = frs; in tc358768_calc_pll()
384 priv->dsiclk = best_pll / 2; in tc358768_calc_pll()
385 priv->pclk = mode->clock * 1000; in tc358768_calc_pll()
399 if (dev->lanes > 4) { in tc358768_dsi_host_attach()
400 dev_err(priv->dev, "unsupported number of data lanes(%u)\n", in tc358768_dsi_host_attach()
401 dev->lanes); in tc358768_dsi_host_attach()
402 return -EINVAL; in tc358768_dsi_host_attach()
409 if (!(dev->mode_flags & MIPI_DSI_MODE_VIDEO)) { in tc358768_dsi_host_attach()
410 dev_err(priv->dev, "Only MIPI_DSI_MODE_VIDEO is supported\n"); in tc358768_dsi_host_attach()
411 return -ENOTSUPP; in tc358768_dsi_host_attach()
418 if (dev->format != MIPI_DSI_FMT_RGB888) { in tc358768_dsi_host_attach()
419 dev_warn(priv->dev, "Only MIPI_DSI_FMT_RGB888 tested!\n"); in tc358768_dsi_host_attach()
420 return -ENOTSUPP; in tc358768_dsi_host_attach()
423 ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0, &panel, in tc358768_dsi_host_attach()
435 priv->output.dev = dev; in tc358768_dsi_host_attach()
436 priv->output.bridge = bridge; in tc358768_dsi_host_attach()
437 priv->output.panel = panel; in tc358768_dsi_host_attach()
439 priv->dsi_lanes = dev->lanes; in tc358768_dsi_host_attach()
440 priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(dev->format); in tc358768_dsi_host_attach()
443 ret = -EINVAL; in tc358768_dsi_host_attach()
444 ep = of_graph_get_endpoint_by_regs(host->dev->of_node, 0, 0); in tc358768_dsi_host_attach()
446 ret = of_property_read_u32(ep, "data-lines", &priv->pd_lines); in tc358768_dsi_host_attach()
452 priv->pd_lines = priv->dsi_bpp; in tc358768_dsi_host_attach()
454 drm_bridge_add(&priv->bridge); in tc358768_dsi_host_attach()
464 drm_bridge_remove(&priv->bridge); in tc358768_dsi_host_detach()
465 if (priv->output.panel) in tc358768_dsi_host_detach()
466 drm_panel_bridge_remove(priv->output.bridge); in tc358768_dsi_host_detach()
478 if (!priv->enabled) { in tc358768_dsi_host_transfer()
479 dev_err(priv->dev, "Bridge is not enabled\n"); in tc358768_dsi_host_transfer()
480 return -ENODEV; in tc358768_dsi_host_transfer()
483 if (msg->rx_len) { in tc358768_dsi_host_transfer()
484 dev_warn(priv->dev, "MIPI rx is not supported\n"); in tc358768_dsi_host_transfer()
485 return -ENOTSUPP; in tc358768_dsi_host_transfer()
488 if (msg->tx_len > 8) { in tc358768_dsi_host_transfer()
489 dev_warn(priv->dev, "Maximum 8 byte MIPI tx is supported\n"); in tc358768_dsi_host_transfer()
490 return -ENOTSUPP; in tc358768_dsi_host_transfer()
497 if (mipi_dsi_packet_format_is_short(msg->type)) { in tc358768_dsi_host_transfer()
524 dev_warn(priv->dev, "Software disable failed: %d\n", ret); in tc358768_dsi_host_transfer()
542 if (!drm_core_check_feature(bridge->dev, DRIVER_ATOMIC)) { in tc358768_bridge_attach()
543 dev_err(priv->dev, "needs atomic updates support\n"); in tc358768_bridge_attach()
544 return -ENOTSUPP; in tc358768_bridge_attach()
547 return drm_bridge_attach(bridge->encoder, priv->output.bridge, bridge, in tc358768_bridge_attach()
583 dev_warn(priv->dev, "Software disable failed: %d\n", ret); in tc358768_bridge_disable()
601 dev_err(priv->dev, "PLL calculation failed: %d\n", ret); in tc358768_setup_pll()
605 fbd = priv->fbd; in tc358768_setup_pll()
606 prd = priv->prd; in tc358768_setup_pll()
607 frs = priv->frs; in tc358768_setup_pll()
609 dev_dbg(priv->dev, "PLL: refclk %lu, fbd %u, prd %u, frs %u\n", in tc358768_setup_pll()
610 clk_get_rate(priv->refclk), fbd, prd, frs); in tc358768_setup_pll()
611 dev_dbg(priv->dev, "PLL: pll_clk: %u, DSIClk %u, HSByteClk %u\n", in tc358768_setup_pll()
612 priv->dsiclk * 2, priv->dsiclk, priv->dsiclk / 4); in tc358768_setup_pll()
613 dev_dbg(priv->dev, "PLL: pclk %u (panel: %u)\n", in tc358768_setup_pll()
614 tc358768_pll_to_pclk(priv, priv->dsiclk * 2), in tc358768_setup_pll()
615 mode->clock * 1000); in tc358768_setup_pll()
618 tc358768_write(priv, TC358768_PLLCTL0, ((prd - 1) << 12) | (fbd - 1)); in tc358768_setup_pll()
652 u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes; in tc358768_dpi_to_dsi_bytes()
653 u64 n = priv->pclk; in tc358768_dpi_to_dsi_bytes()
655 return (u32)div_u64(m + n - 1, n); in tc358768_dpi_to_dsi_bytes()
661 u64 n = priv->dsiclk / 4 * priv->dsi_lanes; in tc358768_dsi_bytes_to_ns()
669 struct mipi_dsi_device *dsi_dev = priv->output.dev; in tc358768_bridge_pre_enable()
670 unsigned long mode_flags = dsi_dev->mode_flags; in tc358768_bridge_pre_enable()
678 struct device *dev = priv->dev; in tc358768_bridge_pre_enable()
690 dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n"); in tc358768_bridge_pre_enable()
703 mode = &bridge->encoder->crtc->state->adjusted_mode; in tc358768_bridge_pre_enable()
706 dev_err(dev, "PLL setup failed: %d\n", ret); in tc358768_bridge_pre_enable()
713 dsiclk = priv->dsiclk; in tc358768_bridge_pre_enable()
718 switch (dsi_dev->format) { in tc358768_bridge_pre_enable()
743 dsi_dev->format); in tc358768_bridge_pre_enable()
752 * 1. Keep the DPI line-time and the DSI line-time as close to each in tc358768_bridge_pre_enable()
785 if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { in tc358768_bridge_pre_enable()
803 dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; in tc358768_bridge_pre_enable()
820 * Seems like sometimes HSW has to be divisible by num-lanes, but in tc358768_bridge_pre_enable()
823 dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes); in tc358768_bridge_pre_enable()
825 dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; in tc358768_bridge_pre_enable()
853 dsi_vsdly *= priv->dsi_lanes; in tc358768_bridge_pre_enable()
857 dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp; in tc358768_bridge_pre_enable()
858 dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes); in tc358768_bridge_pre_enable()
873 dsi_vsdly /= priv->dsi_lanes; in tc358768_bridge_pre_enable()
887 if (dsi_vsdly - internal_dly > 0x3ff) { in tc358768_bridge_pre_enable()
893 tc358768_write(priv, TC358768_VSDLY, dsi_vsdly - internal_dly); in tc358768_bridge_pre_enable()
898 /* Enable D-PHY (HiZ->LP11) */ in tc358768_bridge_pre_enable()
901 for (i = 0; i < dsi_dev->lanes; i++) in tc358768_bridge_pre_enable()
911 /* LP11 > 100us for D-PHY Rx Init */ in tc358768_bridge_pre_enable()
912 val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
917 val = tc358768_ns_to_cnt(50, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
923 val = tc358768_ns_to_cnt(65, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
926 val2 = tc358768_ns_to_cnt(300 - tc358768_ps_to_ns(2 * ui_ps), in tc358768_bridge_pre_enable()
927 hsbyteclk_ps) - 2; in tc358768_bridge_pre_enable()
933 raw_val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(2 * ui_ps), hsbyteclk_ps) - 5; in tc358768_bridge_pre_enable()
940 val = tc358768_ns_to_cnt(val, hsbyteclk_ps) - 1; in tc358768_bridge_pre_enable()
943 raw_val = tc358768_ns_to_cnt(145 - tc358768_ps_to_ns(3 * ui_ps), hsbyteclk_ps) - 10; in tc358768_bridge_pre_enable()
951 val = val / (lptxcnt + 1) - 1; in tc358768_bridge_pre_enable()
957 hsbyteclk_ps) - 3; in tc358768_bridge_pre_enable()
963 hsbyteclk_ps) - 4; in tc358768_bridge_pre_enable()
969 for (i = 0; i < dsi_dev->lanes; i++) in tc358768_bridge_pre_enable()
978 val = tc358768_ns_to_cnt(val, hsbyteclk_ps) / 4 - 1; in tc358768_bridge_pre_enable()
981 hsbyteclk_ps) - 2; in tc358768_bridge_pre_enable()
989 if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { in tc358768_bridge_pre_enable()
1027 (mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(5) : 0); in tc358768_bridge_pre_enable()
1031 (mode->flags & DRM_MODE_FLAG_PHSYNC) ? BIT(0) : 0); in tc358768_bridge_pre_enable()
1043 val |= (dsi_dev->lanes - 1) << 1; in tc358768_bridge_pre_enable()
1050 if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) in tc358768_bridge_pre_enable()
1072 if (!priv->enabled) { in tc358768_bridge_enable()
1073 dev_err(priv->dev, "Bridge is not enabled\n"); in tc358768_bridge_enable()
1085 dev_err(priv->dev, "Bridge enable failed: %d\n", ret); in tc358768_bridge_enable()
1111 switch (priv->pd_lines) { in tc358768_atomic_get_input_bus_fmts()
1135 if (!(adjusted_mode->flags & in tc358768_mode_fixup()
1137 adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; in tc358768_mode_fixup()
1139 if (!(adjusted_mode->flags & in tc358768_mode_fixup()
1141 adjusted_mode->flags |= DRM_MODE_FLAG_PVSYNC; in tc358768_mode_fixup()
1245 for (i = 0; i < ARRAY_SIZE(priv->supplies); ++i) in tc358768_get_regulators()
1246 priv->supplies[i].supply = tc358768_supplies[i]; in tc358768_get_regulators()
1248 ret = devm_regulator_bulk_get(priv->dev, ARRAY_SIZE(priv->supplies), in tc358768_get_regulators()
1249 priv->supplies); in tc358768_get_regulators()
1251 dev_err(priv->dev, "failed to get regulators: %d\n", ret); in tc358768_get_regulators()
1259 struct device *dev = &client->dev; in tc358768_i2c_probe()
1260 struct device_node *np = dev->of_node; in tc358768_i2c_probe()
1264 return -ENODEV; in tc358768_i2c_probe()
1268 return -ENOMEM; in tc358768_i2c_probe()
1271 priv->dev = dev; in tc358768_i2c_probe()
1277 priv->refclk = devm_clk_get(dev, "refclk"); in tc358768_i2c_probe()
1278 if (IS_ERR(priv->refclk)) in tc358768_i2c_probe()
1279 return PTR_ERR(priv->refclk); in tc358768_i2c_probe()
1282 * RESX is low active, to disable tc358768 initially (keep in reset) in tc358768_i2c_probe()
1286 priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", in tc358768_i2c_probe()
1288 if (IS_ERR(priv->reset_gpio)) in tc358768_i2c_probe()
1289 return PTR_ERR(priv->reset_gpio); in tc358768_i2c_probe()
1291 priv->regmap = devm_regmap_init_i2c(client, &tc358768_regmap_config); in tc358768_i2c_probe()
1292 if (IS_ERR(priv->regmap)) { in tc358768_i2c_probe()
1294 return PTR_ERR(priv->regmap); in tc358768_i2c_probe()
1297 priv->dsi_host.dev = dev; in tc358768_i2c_probe()
1298 priv->dsi_host.ops = &tc358768_dsi_host_ops; in tc358768_i2c_probe()
1300 priv->bridge.funcs = &tc358768_bridge_funcs; in tc358768_i2c_probe()
1301 priv->bridge.timings = &default_tc358768_timings; in tc358768_i2c_probe()
1302 priv->bridge.of_node = np; in tc358768_i2c_probe()
1306 return mipi_dsi_host_register(&priv->dsi_host); in tc358768_i2c_probe()
1313 mipi_dsi_host_unregister(&priv->dsi_host); in tc358768_i2c_remove()