Skip to content

Commit 2561482

Browse files
pH5mchehab
authored andcommitted
[media] tc358743: support probe from device tree
Add support for probing the TC358743 subdevice from device tree. The reference clock must be supplied using the common clock bindings. MIPI CSI-2 specific properties are parsed from the OF graph endpoint node and support for a non-continuous MIPI CSI-2 clock is added. Signed-off-by: Philipp Zabel <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 8ec23da commit 2561482

File tree

2 files changed

+197
-6
lines changed

2 files changed

+197
-6
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
* Toshiba TC358743 HDMI-RX to MIPI CSI2-TX Bridge
2+
3+
The Toshiba TC358743 HDMI-RX to MIPI CSI2-TX (H2C) is a bridge that converts
4+
a HDMI stream to MIPI CSI-2 TX. It is programmable through I2C.
5+
6+
Required Properties:
7+
8+
- compatible: value should be "toshiba,tc358743"
9+
- clocks, clock-names: should contain a phandle link to the reference clock
10+
source, the clock input is named "refclk".
11+
12+
Optional Properties:
13+
14+
- reset-gpios: gpio phandle GPIO connected to the reset pin
15+
- interrupts, interrupt-parent: GPIO connected to the interrupt pin
16+
- data-lanes: should be <1 2 3 4> for four-lane operation,
17+
or <1 2> for two-lane operation
18+
- clock-lanes: should be <0>
19+
- clock-noncontinuous: Presence of this boolean property decides whether the
20+
MIPI CSI-2 clock is continuous or non-continuous.
21+
- link-frequencies: List of allowed link frequencies in Hz. Each frequency is
22+
expressed as a 64-bit big-endian integer. The frequency
23+
is half of the bps per lane due to DDR transmission.
24+
25+
For further information on the MIPI CSI-2 endpoint node properties, see
26+
Documentation/devicetree/bindings/media/video-interfaces.txt.
27+
28+
Example:
29+
30+
tc358743@0f {
31+
compatible = "toshiba,tc358743";
32+
reg = <0x0f>;
33+
clocks = <&hdmi_osc>;
34+
clock-names = "refclk";
35+
reset-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>;
36+
interrupt-parent = <&gpio2>;
37+
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
38+
39+
port {
40+
tc358743_out: endpoint {
41+
remote-endpoint = <&mipi_csi2_in>;
42+
data-lanes = <1 2 3 4>;
43+
clock-lanes = <0>;
44+
clock-noncontinuous;
45+
link-frequencies = /bits/ 64 <297000000>;
46+
};
47+
};
48+
};

drivers/media/i2c/tc358743.c

Lines changed: 149 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@
2929
#include <linux/module.h>
3030
#include <linux/slab.h>
3131
#include <linux/i2c.h>
32+
#include <linux/clk.h>
3233
#include <linux/delay.h>
34+
#include <linux/gpio/consumer.h>
3335
#include <linux/videodev2.h>
3436
#include <linux/workqueue.h>
3537
#include <linux/v4l2-dv-timings.h>
3638
#include <linux/hdmi.h>
3739
#include <media/v4l2-dv-timings.h>
3840
#include <media/v4l2-device.h>
3941
#include <media/v4l2-ctrls.h>
42+
#include <media/v4l2-of.h>
4043
#include <media/tc358743.h>
4144

4245
#include "tc358743_regs.h"
@@ -69,6 +72,7 @@ static const struct v4l2_dv_timings_cap tc358743_timings_cap = {
6972

7073
struct tc358743_state {
7174
struct tc358743_platform_data pdata;
75+
struct v4l2_of_bus_mipi_csi2 bus;
7276
struct v4l2_subdev sd;
7377
struct media_pad pad;
7478
struct v4l2_ctrl_handler hdl;
@@ -90,6 +94,8 @@ struct tc358743_state {
9094

9195
struct v4l2_dv_timings timings;
9296
u32 mbus_fmt_code;
97+
98+
struct gpio_desc *reset_gpio;
9399
};
94100

95101
static void tc358743_enable_interrupts(struct v4l2_subdev *sd,
@@ -700,7 +706,8 @@ static void tc358743_set_csi(struct v4l2_subdev *sd)
700706
((lanes > 2) ? MASK_D2M_HSTXVREGEN : 0x0) |
701707
((lanes > 3) ? MASK_D3M_HSTXVREGEN : 0x0));
702708

703-
i2c_wr32(sd, TXOPTIONCNTRL, MASK_CONTCLKMODE);
709+
i2c_wr32(sd, TXOPTIONCNTRL, (state->bus.flags &
710+
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) ? MASK_CONTCLKMODE : 0);
704711
i2c_wr32(sd, STARTCNTRL, MASK_START);
705712
i2c_wr32(sd, CSI_START, MASK_STRT);
706713

@@ -1638,6 +1645,136 @@ static const struct v4l2_ctrl_config tc358743_ctrl_audio_present = {
16381645

16391646
/* --------------- PROBE / REMOVE --------------- */
16401647

1648+
#ifdef CONFIG_OF
1649+
static void tc358743_gpio_reset(struct tc358743_state *state)
1650+
{
1651+
gpiod_set_value(state->reset_gpio, 0);
1652+
usleep_range(5000, 10000);
1653+
gpiod_set_value(state->reset_gpio, 1);
1654+
usleep_range(1000, 2000);
1655+
gpiod_set_value(state->reset_gpio, 0);
1656+
msleep(20);
1657+
}
1658+
1659+
static int tc358743_probe_of(struct tc358743_state *state)
1660+
{
1661+
struct device *dev = &state->i2c_client->dev;
1662+
struct v4l2_of_endpoint *endpoint;
1663+
struct device_node *ep;
1664+
struct clk *refclk;
1665+
u32 bps_pr_lane;
1666+
int ret = -EINVAL;
1667+
1668+
refclk = devm_clk_get(dev, "refclk");
1669+
if (IS_ERR(refclk)) {
1670+
if (PTR_ERR(refclk) != -EPROBE_DEFER)
1671+
dev_err(dev, "failed to get refclk: %ld\n",
1672+
PTR_ERR(refclk));
1673+
return PTR_ERR(refclk);
1674+
}
1675+
1676+
ep = of_graph_get_next_endpoint(dev->of_node, NULL);
1677+
if (!ep) {
1678+
dev_err(dev, "missing endpoint node\n");
1679+
return -EINVAL;
1680+
}
1681+
1682+
endpoint = v4l2_of_alloc_parse_endpoint(ep);
1683+
if (IS_ERR(endpoint)) {
1684+
dev_err(dev, "failed to parse endpoint\n");
1685+
return PTR_ERR(endpoint);
1686+
}
1687+
1688+
if (endpoint->bus_type != V4L2_MBUS_CSI2 ||
1689+
endpoint->bus.mipi_csi2.num_data_lanes == 0 ||
1690+
endpoint->nr_of_link_frequencies == 0) {
1691+
dev_err(dev, "missing CSI-2 properties in endpoint\n");
1692+
goto free_endpoint;
1693+
}
1694+
1695+
state->bus = endpoint->bus.mipi_csi2;
1696+
1697+
clk_prepare_enable(refclk);
1698+
1699+
state->pdata.refclk_hz = clk_get_rate(refclk);
1700+
state->pdata.ddc5v_delay = DDC5V_DELAY_100_MS;
1701+
state->pdata.enable_hdcp = false;
1702+
/* A FIFO level of 16 should be enough for 2-lane 720p60 at 594 MHz. */
1703+
state->pdata.fifo_level = 16;
1704+
/*
1705+
* The PLL input clock is obtained by dividing refclk by pll_prd.
1706+
* It must be between 6 MHz and 40 MHz, lower frequency is better.
1707+
*/
1708+
switch (state->pdata.refclk_hz) {
1709+
case 26000000:
1710+
case 27000000:
1711+
case 42000000:
1712+
state->pdata.pll_prd = state->pdata.refclk_hz / 6000000;
1713+
break;
1714+
default:
1715+
dev_err(dev, "unsupported refclk rate: %u Hz\n",
1716+
state->pdata.refclk_hz);
1717+
goto disable_clk;
1718+
}
1719+
1720+
/*
1721+
* The CSI bps per lane must be between 62.5 Mbps and 1 Gbps.
1722+
* The default is 594 Mbps for 4-lane 1080p60 or 2-lane 720p60.
1723+
*/
1724+
bps_pr_lane = 2 * endpoint->link_frequencies[0];
1725+
if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) {
1726+
dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane);
1727+
goto disable_clk;
1728+
}
1729+
1730+
/* The CSI speed per lane is refclk / pll_prd * pll_fbd */
1731+
state->pdata.pll_fbd = bps_pr_lane /
1732+
state->pdata.refclk_hz * state->pdata.pll_prd;
1733+
1734+
/*
1735+
* FIXME: These timings are from REF_02 for 594 Mbps per lane (297 MHz
1736+
* link frequency). In principle it should be possible to calculate
1737+
* them based on link frequency and resolution.
1738+
*/
1739+
if (bps_pr_lane != 594000000U)
1740+
dev_warn(dev, "untested bps per lane: %u bps\n", bps_pr_lane);
1741+
state->pdata.lineinitcnt = 0xe80;
1742+
state->pdata.lptxtimecnt = 0x003;
1743+
/* tclk-preparecnt: 3, tclk-zerocnt: 20 */
1744+
state->pdata.tclk_headercnt = 0x1403;
1745+
state->pdata.tclk_trailcnt = 0x00;
1746+
/* ths-preparecnt: 3, ths-zerocnt: 1 */
1747+
state->pdata.ths_headercnt = 0x0103;
1748+
state->pdata.twakeup = 0x4882;
1749+
state->pdata.tclk_postcnt = 0x008;
1750+
state->pdata.ths_trailcnt = 0x2;
1751+
state->pdata.hstxvregcnt = 0;
1752+
1753+
state->reset_gpio = devm_gpiod_get(dev, "reset");
1754+
if (IS_ERR(state->reset_gpio)) {
1755+
dev_err(dev, "failed to get reset gpio\n");
1756+
ret = PTR_ERR(state->reset_gpio);
1757+
goto disable_clk;
1758+
}
1759+
1760+
tc358743_gpio_reset(state);
1761+
1762+
ret = 0;
1763+
goto free_endpoint;
1764+
1765+
disable_clk:
1766+
clk_disable_unprepare(refclk);
1767+
free_endpoint:
1768+
v4l2_of_free_endpoint(endpoint);
1769+
return ret;
1770+
}
1771+
#else
1772+
static inline int tc358743_probe_of(struct tc358743_state *state)
1773+
{
1774+
return -ENODEV;
1775+
}
1776+
#endif
1777+
16411778
static int tc358743_probe(struct i2c_client *client,
16421779
const struct i2c_device_id *id)
16431780
{
@@ -1658,14 +1795,20 @@ static int tc358743_probe(struct i2c_client *client,
16581795
if (!state)
16591796
return -ENOMEM;
16601797

1798+
state->i2c_client = client;
1799+
16611800
/* platform data */
1662-
if (!pdata) {
1663-
v4l_err(client, "No platform data!\n");
1664-
return -ENODEV;
1801+
if (pdata) {
1802+
state->pdata = *pdata;
1803+
state->bus.flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
1804+
} else {
1805+
err = tc358743_probe_of(state);
1806+
if (err == -ENODEV)
1807+
v4l_err(client, "No platform data!\n");
1808+
if (err)
1809+
return err;
16651810
}
1666-
state->pdata = *pdata;
16671811

1668-
state->i2c_client = client;
16691812
sd = &state->sd;
16701813
v4l2_i2c_subdev_init(sd, client, &tc358743_ops);
16711814
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;

0 commit comments

Comments
 (0)