Lines Matching +full:fifo +full:- +full:width

1 // SPDX-License-Identifier: GPL-2.0-only
3 * TC358746 - Parallel <-> CSI-2 Bridge
8 * - Currently only 'Parallel-in -> CSI-out' mode is supported!
13 #include <linux/clk-provider.h>
19 #include <linux/phy/phy-mipi-dphy.h>
24 #include <media/v4l2-ctrls.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-fwnode.h>
27 #include <media/v4l2-mc.h>
29 /* 16-bit registers */
80 /* 32-bit registers */
121 .width = 640,
257 /* Get n-th format for pad */
267 if ((pad == TC358746_SOURCE && fmt->csi_format) ||
275 return ERR_PTR(-EINVAL);
286 if (pad == TC358746_SINK && fmt->code == code)
289 if (pad == TC358746_SOURCE && !fmt->csi_format)
292 if (fmt->code == code)
296 return ERR_PTR(-EINVAL);
337 /* 32-bit registers starting from CLW_DPHYCONTTX */
340 err = regmap_bulk_write(tc358746->regmap, reg, &val, count);
342 dev_err(tc358746->sd.dev,
353 /* 32-bit registers starting from CLW_DPHYCONTTX */
357 err = regmap_bulk_read(tc358746->regmap, reg, val, count);
359 dev_err(tc358746->sd.dev,
407 u8 post = tc358746->pll_post_div;
408 u16 pre = tc358746->pll_pre_div;
409 u16 mul = tc358746->pll_mul;
421 /* Pre-div and Multiplicator have a internal +1 logic */
422 val = PLL_PRD(pre - 1) | PLL_FBD(mul - 1);
452 source_bitrate = source_link_freq * fmt->bus_width;
454 csi_bitrate = tc358746->dphy_cfg.lanes * tc358746->pll_rate;
456 dev_dbg(tc358746->sd.dev,
457 "Fifo settings params: source-bitrate:%lu csi-bitrate:%lu",
460 /* Avoid possible FIFO overflows */
462 return -EINVAL;
470 * Avoid possible FIFO underflow in case of
472 * fifo which can be used to delay the line output.
474 * Fifo size calculation (excluding precision):
476 * fifo-sz, image-width - in bits
477 * sbr - source_bitrate in bits/s
478 * csir - csi_bitrate in bits/s
480 * image-width / csir >= (image-width - fifo-sz) / sbr
481 * image-width * sbr / csir >= image-width - fifo-sz
482 * fifo-sz >= image-width - image-width * sbr / csir; with n = csir/sbr
483 * fifo-sz >= image-width - image-width / n
487 tmp = (mbusfmt->width * TC358746_VB_PRECISION) / n;
488 fifo_sz = mbusfmt->width - tmp;
489 fifo_sz *= fmt->bpp;
493 dev_dbg(tc358746->sd.dev,
494 "Found FIFO size[bits]:%u -> aligned to size[bits]:%u\n",
498 return -EINVAL;
506 struct v4l2_subdev *sd = &tc358746->sd;
509 struct device *dev = sd->dev;
519 fmt = tc358746_get_format_by_code(TC358746_SINK, mbusfmt->code);
521 source_pad = media_entity_remote_source_pad_unique(&sd->entity);
523 dev_err(dev, "Failed to get source pad of %s\n", sd->name);
531 /* Return -EINVAL in case of source_link_freq is 0 */
532 err = source_link_freq ?: -EINVAL;
537 val = PDFMT(fmt->pdformat);
543 val = PDATAF(fmt->pdataf);
544 dev_dbg(dev, "CONFCTL[PDATAF]: 0x%x\n", fmt->pdataf);
561 /* Total number of bytes for each line/width */
562 val = mbusfmt->width * fmt->bpp / 8;
575 return div64_u64((u64)cfg_val * clk_hz + time_base - 1, time_base);
590 struct phy_configure_opts_mipi_dphy *cfg = &tc358746->dphy_cfg;
591 bool non_cont_clk = !!(tc358746->csi_vep.bus.mipi_csi2.flags &
593 struct device *dev = tc358746->sd.dev;
599 hs_byte_clk = cfg->hs_clk_rate / 8;
602 val = tc358746_us_to_cnt(cfg->init, hf_clk) - 1;
608 val = tc358746_ps_to_cnt(cfg->lpx, hs_byte_clk) - 1;
615 val = tc358746_ps_to_cnt(cfg->clk_prepare, hs_byte_clk) - 1;
616 val2 = tc358746_ps_to_cnt(cfg->clk_zero, hs_byte_clk) - 1;
626 val = tc358746_ps_to_cnt(cfg->clk_trail, hs_byte_clk);
632 val = tc358746_ps_to_cnt(cfg->hs_prepare, hs_byte_clk) - 1;
633 val2 = tc358746_ps_to_cnt(cfg->hs_zero, hs_byte_clk) - 1;
644 val = tc358746_us_to_cnt(cfg->wakeup, hs_byte_clk);
645 val = val / (lptxcnt + 1) - 1;
651 val = tc358746_ps_to_cnt(cfg->clk_post, hs_byte_clk);
657 val = tc358746_ps_to_cnt(cfg->hs_trail, hs_byte_clk);
672 unsigned int lanes = tc358746->dphy_cfg.lanes;
678 lanes - 1);
684 dev_dbg(tc358746->sd.dev, "CLW_CNTRL: 0x%x\n", val);
694 dev_dbg(tc358746->sd.dev, "D%uW_CNTRL: 0x%x\n", lane, val);
710 dev_dbg(tc358746->sd.dev, "HSTXVREGEN: 0x%x\n", val);
717 unsigned int lanes = tc358746->dphy_cfg.lanes;
722 * required to put the lane state back into LP-11 state. The sw reset
740 DATA(CSI_MODE | TXHSMD | NOL(lanes - 1)));
772 return media_entity_to_v4l2_subdev(pad->entity);
781 dev_dbg(sd->dev, "%sable\n", enable ? "en" : "dis");
783 src = tc358746_get_remote_sd(&tc358746->pads[TC358746_SINK]);
785 return -EPIPE;
788 err = pm_runtime_resume_and_get(sd->dev);
819 pm_runtime_mark_last_busy(sd->dev);
820 pm_runtime_put_sync_autosuspend(sd->dev);
827 * LP-11 state is entered correctly.
841 pm_runtime_mark_last_busy(sd->dev);
842 pm_runtime_put_sync_autosuspend(sd->dev);
857 fmt->code = tc358746_src_mbus_code(tc358746_def_fmt.code);
868 fmt = tc358746_get_format_by_idx(code->pad, code->index);
872 code->code = fmt->code;
885 if (format->pad == TC358746_SOURCE)
890 fmt = tc358746_get_format_by_code(format->pad, format->format.code);
892 fmt = tc358746_get_format_by_code(format->pad, tc358746_def_fmt.code);
895 return -EINVAL;
898 format->format.code = fmt->code;
899 format->format.field = V4L2_FIELD_NONE;
901 dev_dbg(sd->dev, "Update format: %ux%u code:0x%x -> %ux%u code:0x%x",
902 sink_fmt->width, sink_fmt->height, sink_fmt->code,
903 format->format.width, format->format.height, format->format.code);
905 *sink_fmt = format->format;
909 src_fmt->code = tc358746_src_mbus_code(sink_fmt->code);
919 struct device *dev = tc358746->sd.dev;
929 dev_err(dev, "HS-Clock above 1 Ghz are not supported\n");
958 delta = abs(fout - tmp);
975 tc358746->pll_post_div = postdiv;
976 tc358746->pll_pre_div = p_best;
977 tc358746->pll_mul = m_best;
995 return -EINVAL;
997 config->type = V4L2_MBUS_CSI2_DPHY;
998 config->bus.mipi_csi2 = tc358746->csi_vep.bus.mipi_csi2;
1010 /* 32-bit registers starting from CLW_DPHYCONTTX */
1011 reg->size = reg->reg < CLW_DPHYCONTTX_REG ? 2 : 4;
1013 if (!pm_runtime_get_if_in_use(sd->dev))
1016 err = tc358746_read(tc358746, reg->reg, &val);
1017 reg->val = val;
1019 pm_runtime_mark_last_busy(sd->dev);
1020 pm_runtime_put_sync_autosuspend(sd->dev);
1030 if (!pm_runtime_get_if_in_use(sd->dev))
1033 tc358746_write(tc358746, (u32)reg->reg, (u32)reg->val);
1035 pm_runtime_mark_last_busy(sd->dev);
1036 pm_runtime_put_sync_autosuspend(sd->dev);
1082 div = tc358746->mclk_postdiv / 2;
1083 val = MCLK_HIGH(div - 1) | MCLK_LOW(div - 1);
1084 dev_dbg(tc358746->sd.dev, "MCLKCTL: %u (0x%x)\n", val, val);
1089 if (tc358746->mclk_prediv == 8)
1091 else if (tc358746->mclk_prediv == 4)
1096 dev_dbg(tc358746->sd.dev, "CLKCTL[MCLKDIV]: %u (0x%x)\n", val, val);
1111 unsigned long pll_rate = tc358746->pll_rate;
1114 struct device *dev = tc358746->sd.dev;
1120 * MCLK-Div
1121 * -------------------ยด`---------------------
1123 * +-------------+ +------------------------+
1124 * | MCLK-PreDiv | | MCLK-PostDiv |
1125 * PLL --> | (2/4/8) | --> | (mclk_low + mclk_high) | --> MCLK
1126 * +-------------+ +------------------------+
1129 * mclk_low/high = 1 --> 2 MCLK-Ref Counts
1130 * mclk_low/high = 255 --> 256 MCLK-Ref Counts == max.
1136 * MCLK = PLL / (MCLK-PreDiv * 2 * MCLK-PostDiv)
1139 if (mclk_rate == tc358746->mclk_rate)
1179 /* The MCLK <-> PLL gap is to high -> use largest possible div */
1185 tc358746->mclk_prediv = mclk_prediv;
1186 tc358746->mclk_postdiv = mclk_postdiv;
1187 tc358746->mclk_rate = best_mclk_rate;
1226 return tc358746->pll_rate / (prediv * postdiv);
1234 *parent_rate = tc358746->pll_rate;
1260 struct device *dev = tc358746->sd.dev;
1265 if (!device_property_present(dev, "#clock-cells"))
1269 tc358746->mclk_postdiv = 512;
1270 tc358746->mclk_prediv = 8;
1272 mclk_name = "tc358746-mclk";
1273 device_property_read_string(dev, "clock-output-names", &mclk_name);
1277 tc358746->mclk_hw.init = &mclk_initdata;
1279 err = devm_clk_hw_register(dev, &tc358746->mclk_hw);
1286 &tc358746->mclk_hw);
1296 struct v4l2_subdev *sd = &tc358746->sd;
1300 sd->internal_ops = &tc358746_internal_ops;
1301 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1302 sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
1303 sd->entity.ops = &tc358746_entity_ops;
1305 tc358746->pads[TC358746_SINK].flags = MEDIA_PAD_FL_SINK;
1306 tc358746->pads[TC358746_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
1307 err = media_entity_pads_init(&sd->entity, TC358746_NR_PADS,
1308 tc358746->pads);
1314 media_entity_cleanup(&sd->entity);
1322 struct device *dev = tc358746->sd.dev;
1333 return -EINVAL;
1336 /* Currently we only support 'parallel in' -> 'csi out' */
1337 vep = &tc358746->csi_vep;
1338 vep->bus_type = V4L2_MBUS_CSI2_DPHY;
1346 csi_lanes = vep->bus.mipi_csi2.num_data_lanes;
1348 vep->nr_of_link_frequencies == 0) {
1349 dev_err(dev, "error: Invalid CSI-2 settings\n");
1350 err = -EINVAL;
1355 csi_link_rate = (unsigned long)vep->link_frequencies[0];
1356 tc358746->pll_rate = tc358746_find_pll_settings(tc358746, refclk,
1358 if (!tc358746->pll_rate) {
1359 err = -EINVAL;
1363 err = phy_mipi_dphy_get_default_config_for_hsclk(tc358746->pll_rate,
1364 csi_lanes, &tc358746->dphy_cfg);
1378 struct device *dev = tc358746->sd.dev;
1389 /* Ensure that CSI interface is put into LP-11 state */
1401 return -ENODEV;
1406 return -ENODEV;
1414 u64 *link_frequencies = tc358746->csi_vep.link_frequencies;
1418 err = v4l2_ctrl_handler_init(&tc358746->ctrl_hdl, 1);
1423 * The driver currently supports only one link-frequency, regardless of
1428 ctrl = v4l2_ctrl_new_int_menu(&tc358746->ctrl_hdl, NULL,
1432 ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
1434 err = tc358746->ctrl_hdl.error;
1436 v4l2_ctrl_handler_free(&tc358746->ctrl_hdl);
1440 tc358746->sd.ctrl_handler = &tc358746->ctrl_hdl;
1452 struct media_pad *sink = &tc358746->pads[TC358746_SINK];
1470 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(tc358746->sd.dev),
1473 return -ENOTCONN;
1481 v4l2_async_subdev_nf_init(&tc358746->notifier, &tc358746->sd);
1482 asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep,
1491 tc358746->notifier.ops = &tc358746_notify_ops;
1493 err = v4l2_async_nf_register(&tc358746->notifier);
1497 err = v4l2_async_register_subdev(&tc358746->sd);
1504 v4l2_async_nf_unregister(&tc358746->notifier);
1506 v4l2_async_nf_cleanup(&tc358746->notifier);
1513 struct device *dev = &client->dev;
1519 tc358746 = devm_kzalloc(&client->dev, sizeof(*tc358746), GFP_KERNEL);
1521 return -ENOMEM;
1523 tc358746->regmap = devm_regmap_init_i2c(client, &tc358746_regmap_config);
1524 if (IS_ERR(tc358746->regmap))
1525 return dev_err_probe(dev, PTR_ERR(tc358746->regmap),
1528 tc358746->refclk = devm_clk_get(dev, "refclk");
1529 if (IS_ERR(tc358746->refclk))
1530 return dev_err_probe(dev, PTR_ERR(tc358746->refclk),
1533 err = clk_prepare_enable(tc358746->refclk);
1538 refclk = clk_get_rate(tc358746->refclk);
1539 clk_disable_unprepare(tc358746->refclk);
1542 return dev_err_probe(dev, -EINVAL, "Invalid refclk range\n");
1545 tc358746->supplies[i].supply = tc358746_supplies[i];
1548 tc358746->supplies);
1552 tc358746->reset_gpio = devm_gpiod_get_optional(dev, "reset",
1554 if (IS_ERR(tc358746->reset_gpio))
1555 return dev_err_probe(dev, PTR_ERR(tc358746->reset_gpio),
1556 "Failed to get reset-gpios\n");
1567 * Keep this order since we need the output port link-frequencies
1593 dev_dbg(dev, "%s found @ 0x%x (%s)\n", client->name,
1594 client->addr, client->adapter->name);
1602 v4l2_ctrl_handler_free(&tc358746->ctrl_hdl);
1604 v4l2_fwnode_endpoint_free(&tc358746->csi_vep);
1606 v4l2_subdev_cleanup(&tc358746->sd);
1607 media_entity_cleanup(&tc358746->sd.entity);
1618 v4l2_ctrl_handler_free(&tc358746->ctrl_hdl);
1619 v4l2_fwnode_endpoint_free(&tc358746->csi_vep);
1620 v4l2_async_nf_unregister(&tc358746->notifier);
1621 v4l2_async_nf_cleanup(&tc358746->notifier);
1623 media_entity_cleanup(&sd->entity);
1625 pm_runtime_disable(sd->dev);
1626 pm_runtime_set_suspended(sd->dev);
1627 pm_runtime_dont_use_autosuspend(sd->dev);
1637 clk_prepare_enable(tc358746->refclk);
1645 clk_disable_unprepare(tc358746->refclk);
1648 tc358746->supplies);
1660 gpiod_set_value(tc358746->reset_gpio, 1);
1663 tc358746->supplies);
1670 gpiod_set_value(tc358746->reset_gpio, 0);
1672 err = clk_prepare_enable(tc358746->refclk);
1680 * Enable the PLL here since it can be called by the clk-framework or by
1690 clk_disable_unprepare(tc358746->refclk);
1693 tc358746->supplies);
1718 MODULE_DESCRIPTION("Toshiba TC358746 Parallel to CSI-2 bridge driver");