Lines Matching full:tc358746

3  * TC358746 - Parallel <-> CSI-2 Bridge
141 struct tc358746 { struct
171 static inline struct tc358746 *to_tc358746(struct v4l2_subdev *sd) in to_tc358746() argument
173 return container_of(sd, struct tc358746, sd); in to_tc358746()
176 static inline struct tc358746 *clk_hw_to_tc358746(struct clk_hw *hw) in clk_hw_to_tc358746()
178 return container_of(hw, struct tc358746, mclk_hw); in clk_hw_to_tc358746()
301 .name = "tc358746",
311 static int tc358746_write(struct tc358746 *tc358746, u32 reg, u32 val) in tc358746_write() argument
319 err = regmap_bulk_write(tc358746->regmap, reg, &val, count); in tc358746_write()
321 dev_err(tc358746->sd.dev, in tc358746_write()
327 static int tc358746_read(struct tc358746 *tc358746, u32 reg, u32 *val) in tc358746_read() argument
336 err = regmap_bulk_read(tc358746->regmap, reg, val, count); in tc358746_read()
338 dev_err(tc358746->sd.dev, in tc358746_read()
345 tc358746_update_bits(struct tc358746 *tc358746, u32 reg, u32 mask, u32 val) in tc358746_update_bits() argument
350 err = tc358746_read(tc358746, reg, &orig); in tc358746_update_bits()
357 return tc358746_write(tc358746, reg, tmp); in tc358746_update_bits()
360 static int tc358746_set_bits(struct tc358746 *tc358746, u32 reg, u32 bits) in tc358746_set_bits() argument
362 return tc358746_update_bits(tc358746, reg, bits, bits); in tc358746_set_bits()
365 static int tc358746_clear_bits(struct tc358746 *tc358746, u32 reg, u32 bits) in tc358746_clear_bits() argument
367 return tc358746_update_bits(tc358746, reg, bits, 0); in tc358746_clear_bits()
370 static int tc358746_sw_reset(struct tc358746 *tc358746) in tc358746_sw_reset() argument
374 err = tc358746_set_bits(tc358746, SYSCTL_REG, SRESET); in tc358746_sw_reset()
380 return tc358746_clear_bits(tc358746, SYSCTL_REG, SRESET); in tc358746_sw_reset()
384 tc358746_apply_pll_config(struct tc358746 *tc358746) in tc358746_apply_pll_config() argument
386 u8 post = tc358746->pll_post_div; in tc358746_apply_pll_config()
387 u16 pre = tc358746->pll_pre_div; in tc358746_apply_pll_config()
388 u16 mul = tc358746->pll_mul; in tc358746_apply_pll_config()
392 err = tc358746_read(tc358746, PLLCTL1_REG, &val); in tc358746_apply_pll_config()
403 err = tc358746_update_bits(tc358746, PLLCTL0_REG, mask, val); in tc358746_apply_pll_config()
409 err = tc358746_update_bits(tc358746, PLLCTL1_REG, mask, val); in tc358746_apply_pll_config()
415 return tc358746_set_bits(tc358746, PLLCTL1_REG, CKEN); in tc358746_apply_pll_config()
418 static int tc358746_apply_misc_config(struct tc358746 *tc358746) in tc358746_apply_misc_config() argument
421 struct v4l2_subdev *sd = &tc358746->sd; in tc358746_apply_misc_config()
436 err = tc358746_write(tc358746, DATAFMT_REG, val); in tc358746_apply_misc_config()
442 err = tc358746_update_bits(tc358746, CONFCTL_REG, PDATAF_MASK, val); in tc358746_apply_misc_config()
446 val = tc358746->vb_size / 32; in tc358746_apply_misc_config()
448 err = tc358746_write(tc358746, FIFOCTL_REG, val); in tc358746_apply_misc_config()
455 err = tc358746_write(tc358746, WORDCNT_REG, val); in tc358746_apply_misc_config()
483 static int tc358746_apply_dphy_config(struct tc358746 *tc358746) in tc358746_apply_dphy_config() argument
485 struct phy_configure_opts_mipi_dphy *cfg = &tc358746->dphy_cfg; in tc358746_apply_dphy_config()
486 bool non_cont_clk = !!(tc358746->csi_vep.bus.mipi_csi2.flags & in tc358746_apply_dphy_config()
488 struct device *dev = tc358746->sd.dev; in tc358746_apply_dphy_config()
500 err = tc358746_write(tc358746, LINEINITCNT_REG, val); in tc358746_apply_dphy_config()
507 err = tc358746_write(tc358746, LPTXTIMECNT_REG, val); in tc358746_apply_dphy_config()
517 err = tc358746_write(tc358746, TCLK_HEADERCNT_REG, in tc358746_apply_dphy_config()
524 err = tc358746_write(tc358746, TCLK_TRAILCNT_REG, val); in tc358746_apply_dphy_config()
534 err = tc358746_write(tc358746, THS_HEADERCNT_REG, in tc358746_apply_dphy_config()
543 err = tc358746_write(tc358746, TWAKEUP_REG, val); in tc358746_apply_dphy_config()
549 err = tc358746_write(tc358746, TCLK_POSTCNT_REG, val); in tc358746_apply_dphy_config()
555 err = tc358746_write(tc358746, THS_TRAILCNT_REG, val); in tc358746_apply_dphy_config()
561 return tc358746_write(tc358746, TXOPTIONCNTRL_REG, non_cont_clk ? 0 : 1); in tc358746_apply_dphy_config()
566 static int tc358746_enable_csi_lanes(struct tc358746 *tc358746, int enable) in tc358746_enable_csi_lanes() argument
568 unsigned int lanes = tc358746->dphy_cfg.lanes; in tc358746_enable_csi_lanes()
573 err = tc358746_update_bits(tc358746, CONFCTL_REG, DATALANE_MASK, in tc358746_enable_csi_lanes()
580 dev_dbg(tc358746->sd.dev, "CLW_CNTRL: 0x%x\n", val); in tc358746_enable_csi_lanes()
581 err = tc358746_write(tc358746, CLW_CNTRL_REG, val); in tc358746_enable_csi_lanes()
590 dev_dbg(tc358746->sd.dev, "D%uW_CNTRL: 0x%x\n", lane, val); in tc358746_enable_csi_lanes()
591 err = tc358746_write(tc358746, reg, val); in tc358746_enable_csi_lanes()
606 dev_dbg(tc358746->sd.dev, "HSTXVREGEN: 0x%x\n", val); in tc358746_enable_csi_lanes()
608 return tc358746_write(tc358746, HSTXVREGEN_REG, val); in tc358746_enable_csi_lanes()
611 static int tc358746_enable_csi_module(struct tc358746 *tc358746, int enable) in tc358746_enable_csi_module() argument
613 unsigned int lanes = tc358746->dphy_cfg.lanes; in tc358746_enable_csi_module()
622 return tc358746_sw_reset(tc358746); in tc358746_enable_csi_module()
624 err = tc358746_write(tc358746, STARTCNTRL_REG, START); in tc358746_enable_csi_module()
628 err = tc358746_write(tc358746, CSI_START_REG, STRT); in tc358746_enable_csi_module()
633 return tc358746_write(tc358746, CSI_CONFW_REG, in tc358746_enable_csi_module()
639 static int tc358746_enable_parallel_port(struct tc358746 *tc358746, int enable) in tc358746_enable_parallel_port() argument
644 err = tc358746_write(tc358746, PP_MISC_REG, 0); in tc358746_enable_parallel_port()
648 return tc358746_set_bits(tc358746, CONFCTL_REG, PPEN); in tc358746_enable_parallel_port()
651 err = tc358746_set_bits(tc358746, PP_MISC_REG, FRMSTOP); in tc358746_enable_parallel_port()
655 err = tc358746_clear_bits(tc358746, CONFCTL_REG, PPEN); in tc358746_enable_parallel_port()
659 return tc358746_set_bits(tc358746, PP_MISC_REG, RSTPTR); in tc358746_enable_parallel_port()
673 struct tc358746 *tc358746 = to_tc358746(sd); in tc358746_s_stream() local
679 src = tc358746_get_remote_sd(&tc358746->pads[TC358746_SINK]); in tc358746_s_stream()
688 err = tc358746_apply_dphy_config(tc358746); in tc358746_s_stream()
692 err = tc358746_apply_misc_config(tc358746); in tc358746_s_stream()
696 err = tc358746_enable_csi_lanes(tc358746, 1); in tc358746_s_stream()
700 err = tc358746_enable_csi_module(tc358746, 1); in tc358746_s_stream()
704 err = tc358746_enable_parallel_port(tc358746, 1); in tc358746_s_stream()
725 err = tc358746_enable_csi_lanes(tc358746, 0); in tc358746_s_stream()
729 err = tc358746_enable_csi_module(tc358746, 0); in tc358746_s_stream()
733 err = tc358746_enable_parallel_port(tc358746, 0); in tc358746_s_stream()
810 static unsigned long tc358746_find_pll_settings(struct tc358746 *tc358746, in tc358746_find_pll_settings() argument
815 struct device *dev = tc358746->sd.dev; in tc358746_find_pll_settings()
871 tc358746->pll_post_div = postdiv; in tc358746_find_pll_settings()
872 tc358746->pll_pre_div = p_best; in tc358746_find_pll_settings()
873 tc358746->pll_mul = m_best; in tc358746_find_pll_settings()
892 struct tc358746 *tc358746 = to_tc358746(sd); in tc358746_link_validate() local
915 dev_err(tc358746->sd.dev, in tc358746_link_validate()
923 csi_bitrate = tc358746->dphy_cfg.lanes * tc358746->pll_rate; in tc358746_link_validate()
925 dev_dbg(tc358746->sd.dev, in tc358746_link_validate()
938 tc358746->vb_size = TC358746_VB_DEFAULT_SIZE; in tc358746_link_validate()
964 tc358746->vb_size = round_up(fifo_sz, 32); in tc358746_link_validate()
967 dev_dbg(tc358746->sd.dev, in tc358746_link_validate()
969 fifo_sz, tc358746->vb_size); in tc358746_link_validate()
973 return tc358746->vb_size > TC358746_VB_MAX_SIZE ? -EINVAL : 0; in tc358746_link_validate()
979 struct tc358746 *tc358746 = to_tc358746(sd); in tc358746_get_mbus_config() local
985 config->bus.mipi_csi2 = tc358746->csi_vep.bus.mipi_csi2; in tc358746_get_mbus_config()
993 struct tc358746 *tc358746 = to_tc358746(sd); in tc358746_g_register() local
1003 err = tc358746_read(tc358746, reg->reg, &val); in tc358746_g_register()
1015 struct tc358746 *tc358746 = to_tc358746(sd); in tc358746_s_register() local
1020 tc358746_write(tc358746, (u32)reg->reg, (u32)reg->val); in tc358746_s_register()
1064 struct tc358746 *tc358746 = clk_hw_to_tc358746(hw); in tc358746_mclk_enable() local
1069 div = tc358746->mclk_postdiv / 2; in tc358746_mclk_enable()
1071 dev_dbg(tc358746->sd.dev, "MCLKCTL: %u (0x%x)\n", val, val); in tc358746_mclk_enable()
1072 err = tc358746_write(tc358746, MCLKCTL_REG, val); in tc358746_mclk_enable()
1076 if (tc358746->mclk_prediv == 8) in tc358746_mclk_enable()
1078 else if (tc358746->mclk_prediv == 4) in tc358746_mclk_enable()
1083 dev_dbg(tc358746->sd.dev, "CLKCTL[MCLKDIV]: %u (0x%x)\n", val, val); in tc358746_mclk_enable()
1085 return tc358746_update_bits(tc358746, CLKCTL_REG, MCLKDIV_MASK, val); in tc358746_mclk_enable()
1090 struct tc358746 *tc358746 = clk_hw_to_tc358746(hw); in tc358746_mclk_disable() local
1092 tc358746_write(tc358746, MCLKCTL_REG, 0); in tc358746_mclk_disable()
1096 tc358746_find_mclk_settings(struct tc358746 *tc358746, unsigned long mclk_rate) in tc358746_find_mclk_settings() argument
1098 unsigned long pll_rate = tc358746->pll_rate; in tc358746_find_mclk_settings()
1101 struct device *dev = tc358746->sd.dev; in tc358746_find_mclk_settings()
1126 if (mclk_rate == tc358746->mclk_rate) in tc358746_find_mclk_settings()
1172 tc358746->mclk_prediv = mclk_prediv; in tc358746_find_mclk_settings()
1173 tc358746->mclk_postdiv = mclk_postdiv; in tc358746_find_mclk_settings()
1174 tc358746->mclk_rate = best_mclk_rate; in tc358746_find_mclk_settings()
1189 struct tc358746 *tc358746 = clk_hw_to_tc358746(hw); in tc358746_recalc_rate() local
1194 err = tc358746_read(tc358746, MCLKCTL_REG, &val); in tc358746_recalc_rate()
1201 err = tc358746_read(tc358746, CLKCTL_REG, &val); in tc358746_recalc_rate()
1213 return tc358746->pll_rate / (prediv * postdiv); in tc358746_recalc_rate()
1219 struct tc358746 *tc358746 = clk_hw_to_tc358746(hw); in tc358746_mclk_round_rate() local
1221 *parent_rate = tc358746->pll_rate; in tc358746_mclk_round_rate()
1223 return tc358746_find_mclk_settings(tc358746, rate); in tc358746_mclk_round_rate()
1229 struct tc358746 *tc358746 = clk_hw_to_tc358746(hw); in tc358746_mclk_set_rate() local
1231 tc358746_find_mclk_settings(tc358746, rate); in tc358746_mclk_set_rate()
1244 static int tc358746_setup_mclk_provider(struct tc358746 *tc358746) in tc358746_setup_mclk_provider() argument
1247 struct device *dev = tc358746->sd.dev; in tc358746_setup_mclk_provider()
1256 tc358746->mclk_postdiv = 512; in tc358746_setup_mclk_provider()
1257 tc358746->mclk_prediv = 8; in tc358746_setup_mclk_provider()
1259 mclk_name = "tc358746-mclk"; in tc358746_setup_mclk_provider()
1264 tc358746->mclk_hw.init = &mclk_initdata; in tc358746_setup_mclk_provider()
1266 err = devm_clk_hw_register(dev, &tc358746->mclk_hw); in tc358746_setup_mclk_provider()
1273 &tc358746->mclk_hw); in tc358746_setup_mclk_provider()
1281 tc358746_init_subdev(struct tc358746 *tc358746, struct i2c_client *client) in tc358746_init_subdev() argument
1283 struct v4l2_subdev *sd = &tc358746->sd; in tc358746_init_subdev()
1292 tc358746->pads[TC358746_SINK].flags = MEDIA_PAD_FL_SINK; in tc358746_init_subdev()
1293 tc358746->pads[TC358746_SOURCE].flags = MEDIA_PAD_FL_SOURCE; in tc358746_init_subdev()
1295 tc358746->pads); in tc358746_init_subdev()
1307 tc358746_init_output_port(struct tc358746 *tc358746, unsigned long refclk) in tc358746_init_output_port() argument
1309 struct device *dev = tc358746->sd.dev; in tc358746_init_output_port()
1324 vep = &tc358746->csi_vep; in tc358746_init_output_port()
1343 tc358746->pll_rate = tc358746_find_pll_settings(tc358746, refclk, in tc358746_init_output_port()
1345 if (!tc358746->pll_rate) { in tc358746_init_output_port()
1350 err = phy_mipi_dphy_get_default_config_for_hsclk(tc358746->pll_rate, in tc358746_init_output_port()
1351 csi_lanes, &tc358746->dphy_cfg); in tc358746_init_output_port()
1355 tc358746->vb_size = TC358746_VB_DEFAULT_SIZE; in tc358746_init_output_port()
1365 static int tc358746_init_hw(struct tc358746 *tc358746) in tc358746_init_hw() argument
1367 struct device *dev = tc358746->sd.dev; in tc358746_init_hw()
1379 err = tc358746_sw_reset(tc358746); in tc358746_init_hw()
1386 err = tc358746_read(tc358746, CHIPID_REG, &val); in tc358746_init_hw()
1401 static int tc358746_init_controls(struct tc358746 *tc358746) in tc358746_init_controls() argument
1403 u64 *link_frequencies = tc358746->csi_vep.link_frequencies; in tc358746_init_controls()
1407 err = v4l2_ctrl_handler_init(&tc358746->ctrl_hdl, 1); in tc358746_init_controls()
1417 ctrl = v4l2_ctrl_new_int_menu(&tc358746->ctrl_hdl, NULL, in tc358746_init_controls()
1423 err = tc358746->ctrl_hdl.error; in tc358746_init_controls()
1425 v4l2_ctrl_handler_free(&tc358746->ctrl_hdl); in tc358746_init_controls()
1429 tc358746->sd.ctrl_handler = &tc358746->ctrl_hdl; in tc358746_init_controls()
1438 struct tc358746 *tc358746 = in tc358746_notify_bound() local
1439 container_of(notifier, struct tc358746, notifier); in tc358746_notify_bound()
1441 struct media_pad *sink = &tc358746->pads[TC358746_SINK]; in tc358746_notify_bound()
1450 static int tc358746_async_register(struct tc358746 *tc358746) in tc358746_async_register() argument
1459 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(tc358746->sd.dev), in tc358746_async_register()
1470 v4l2_async_subdev_nf_init(&tc358746->notifier, &tc358746->sd); in tc358746_async_register()
1471 asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep, in tc358746_async_register()
1480 tc358746->notifier.ops = &tc358746_notify_ops; in tc358746_async_register()
1482 err = v4l2_async_nf_register(&tc358746->notifier); in tc358746_async_register()
1486 err = v4l2_async_register_subdev(&tc358746->sd); in tc358746_async_register()
1493 v4l2_async_nf_unregister(&tc358746->notifier); in tc358746_async_register()
1495 v4l2_async_nf_cleanup(&tc358746->notifier); in tc358746_async_register()
1503 struct tc358746 *tc358746; in tc358746_probe() local
1508 tc358746 = devm_kzalloc(&client->dev, sizeof(*tc358746), GFP_KERNEL); in tc358746_probe()
1509 if (!tc358746) in tc358746_probe()
1512 tc358746->regmap = devm_regmap_init_i2c(client, &tc358746_regmap_config); in tc358746_probe()
1513 if (IS_ERR(tc358746->regmap)) in tc358746_probe()
1514 return dev_err_probe(dev, PTR_ERR(tc358746->regmap), in tc358746_probe()
1517 tc358746->refclk = devm_clk_get(dev, "refclk"); in tc358746_probe()
1518 if (IS_ERR(tc358746->refclk)) in tc358746_probe()
1519 return dev_err_probe(dev, PTR_ERR(tc358746->refclk), in tc358746_probe()
1522 err = clk_prepare_enable(tc358746->refclk); in tc358746_probe()
1527 refclk = clk_get_rate(tc358746->refclk); in tc358746_probe()
1528 clk_disable_unprepare(tc358746->refclk); in tc358746_probe()
1534 tc358746->supplies[i].supply = tc358746_supplies[i]; in tc358746_probe()
1537 tc358746->supplies); in tc358746_probe()
1541 tc358746->reset_gpio = devm_gpiod_get_optional(dev, "reset", in tc358746_probe()
1543 if (IS_ERR(tc358746->reset_gpio)) in tc358746_probe()
1544 return dev_err_probe(dev, PTR_ERR(tc358746->reset_gpio), in tc358746_probe()
1547 err = tc358746_init_subdev(tc358746, client); in tc358746_probe()
1551 err = tc358746_init_output_port(tc358746, refclk); in tc358746_probe()
1559 err = tc358746_init_controls(tc358746); in tc358746_probe()
1563 dev_set_drvdata(dev, tc358746); in tc358746_probe()
1570 err = tc358746_init_hw(tc358746); in tc358746_probe()
1574 err = tc358746_setup_mclk_provider(tc358746); in tc358746_probe()
1578 err = tc358746_async_register(tc358746); in tc358746_probe()
1591 v4l2_ctrl_handler_free(&tc358746->ctrl_hdl); in tc358746_probe()
1593 v4l2_fwnode_endpoint_free(&tc358746->csi_vep); in tc358746_probe()
1595 v4l2_subdev_cleanup(&tc358746->sd); in tc358746_probe()
1596 media_entity_cleanup(&tc358746->sd.entity); in tc358746_probe()
1604 struct tc358746 *tc358746 = to_tc358746(sd); in tc358746_remove() local
1607 v4l2_ctrl_handler_free(&tc358746->ctrl_hdl); in tc358746_remove()
1608 v4l2_fwnode_endpoint_free(&tc358746->csi_vep); in tc358746_remove()
1609 v4l2_async_nf_unregister(&tc358746->notifier); in tc358746_remove()
1610 v4l2_async_nf_cleanup(&tc358746->notifier); in tc358746_remove()
1624 static void tc358746_clk_enable(struct tc358746 *tc358746) in tc358746_clk_enable() argument
1626 clk_prepare_enable(tc358746->refclk); in tc358746_clk_enable()
1631 struct tc358746 *tc358746 = dev_get_drvdata(dev); in tc358746_suspend() local
1634 clk_disable_unprepare(tc358746->refclk); in tc358746_suspend()
1637 tc358746->supplies); in tc358746_suspend()
1639 tc358746_clk_enable(tc358746); in tc358746_suspend()
1646 struct tc358746 *tc358746 = dev_get_drvdata(dev); in tc358746_resume() local
1649 gpiod_set_value(tc358746->reset_gpio, 1); in tc358746_resume()
1652 tc358746->supplies); in tc358746_resume()
1659 gpiod_set_value(tc358746->reset_gpio, 0); in tc358746_resume()
1661 err = clk_prepare_enable(tc358746->refclk); in tc358746_resume()
1672 err = tc358746_apply_pll_config(tc358746); in tc358746_resume()
1679 clk_disable_unprepare(tc358746->refclk); in tc358746_resume()
1682 tc358746->supplies); in tc358746_resume()
1690 { .compatible = "toshiba,tc358746" },
1697 .name = "tc358746",
1707 MODULE_DESCRIPTION("Toshiba TC358746 Parallel to CSI-2 bridge driver");