* [PATCH v2 1/4] [media] tc358743: register v4l2 asynchronous subdevice
@ 2015-07-17 10:58 Philipp Zabel
2015-07-17 10:58 ` [PATCH v2 2/4] [media] tc358743: enable v4l2 subdevice devnode Philipp Zabel
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Philipp Zabel @ 2015-07-17 10:58 UTC (permalink / raw)
To: Hans Verkuil; +Cc: Mats Randgaard, linux-media, kernel, Philipp Zabel
Add support for registering the sensor subdevice using the v4l2-async API.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
Changes since v1:
- Added missing media_entity_cleanup
---
drivers/media/i2c/tc358743.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
index 34d4f32..8d9906b 100644
--- a/drivers/media/i2c/tc358743.c
+++ b/drivers/media/i2c/tc358743.c
@@ -1710,6 +1710,16 @@ static int tc358743_probe(struct i2c_client *client,
goto err_hdl;
}
+ state->pad.flags = MEDIA_PAD_FL_SOURCE;
+ err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+ if (err < 0)
+ goto err_hdl;
+
+ sd->dev = &client->dev;
+ err = v4l2_async_register_subdev(sd);
+ if (err < 0)
+ goto err_hdl;
+
mutex_init(&state->confctl_mutex);
INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
@@ -1740,6 +1750,7 @@ err_work_queues:
destroy_workqueue(state->work_queues);
mutex_destroy(&state->confctl_mutex);
err_hdl:
+ media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(&state->hdl);
return err;
}
@@ -1751,8 +1762,10 @@ static int tc358743_remove(struct i2c_client *client)
cancel_delayed_work(&state->delayed_work_enable_hotplug);
destroy_workqueue(state->work_queues);
+ v4l2_async_unregister_subdev(sd);
v4l2_device_unregister_subdev(sd);
mutex_destroy(&state->confctl_mutex);
+ media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(&state->hdl);
return 0;
--
2.1.4
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/4] [media] tc358743: enable v4l2 subdevice devnode 2015-07-17 10:58 [PATCH v2 1/4] [media] tc358743: register v4l2 asynchronous subdevice Philipp Zabel @ 2015-07-17 10:58 ` Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 3/4] [media] tc358743: support probe from device tree Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 4/4] [media] tc358743: add direct interrupt handling Philipp Zabel 2 siblings, 0 replies; 6+ messages in thread From: Philipp Zabel @ 2015-07-17 10:58 UTC (permalink / raw) To: Hans Verkuil; +Cc: Mats Randgaard, linux-media, kernel, Philipp Zabel Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> --- drivers/media/i2c/tc358743.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 8d9906b..a7542e5 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1668,7 +1668,7 @@ static int tc358743_probe(struct i2c_client *client, state->i2c_client = client; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &tc358743_ops); - sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; /* i2c access */ if ((i2c_rd16(sd, CHIPID) & MASK_CHIPID) != 0) { -- 2.1.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/4] [media] tc358743: support probe from device tree 2015-07-17 10:58 [PATCH v2 1/4] [media] tc358743: register v4l2 asynchronous subdevice Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 2/4] [media] tc358743: enable v4l2 subdevice devnode Philipp Zabel @ 2015-07-17 10:58 ` Philipp Zabel 2015-07-17 12:23 ` Hans Verkuil 2015-07-17 10:58 ` [PATCH v2 4/4] [media] tc358743: add direct interrupt handling Philipp Zabel 2 siblings, 1 reply; 6+ messages in thread From: Philipp Zabel @ 2015-07-17 10:58 UTC (permalink / raw) To: Hans Verkuil; +Cc: Mats Randgaard, linux-media, kernel, Philipp Zabel 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 <p.zabel@pengutronix.de> --- Changes since v1: - Added missing state->bus assignment for the device tree case - Initialized state->bus.flags to V4L2_MBUS_CSI2_CONTINUOUS_CLOCK in the platform data case. --- .../devicetree/bindings/media/i2c/tc358743.txt | 48 +++++++ drivers/media/i2c/tc358743.c | 156 ++++++++++++++++++++- 2 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/i2c/tc358743.txt diff --git a/Documentation/devicetree/bindings/media/i2c/tc358743.txt b/Documentation/devicetree/bindings/media/i2c/tc358743.txt new file mode 100644 index 0000000..5218921 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tc358743.txt @@ -0,0 +1,48 @@ +* Toshiba TC358743 HDMI-RX to MIPI CSI2-TX Bridge + +The Toshiba TC358743 HDMI-RX to MIPI CSI2-TX (H2C) is a bridge that converts +a HDMI stream to MIPI CSI-2 TX. It is programmable through I2C. + +Required Properties: + +- compatible: value should be "toshiba,tc358743" +- clocks, clock-names: should contain a phandle link to the reference clock + source, the clock input is named "refclk". + +Optional Properties: + +- reset-gpios: gpio phandle GPIO connected to the reset pin +- interrupts, interrupt-parent: GPIO connected to the interrupt pin +- data-lanes: should be <1 2 3 4> for four-lane operation, + or <1 2> for two-lane operation +- clock-lanes: should be <0> +- clock-noncontinuous: Presence of this boolean property decides whether the + MIPI CSI-2 clock is continuous or non-continuous. +- link-frequencies: List of allowed link frequencies in Hz. Each frequency is + expressed as a 64-bit big-endian integer. The frequency + is half of the bps per lane due to DDR transmission. + +For further information on the MIPI CSI-2 endpoint node properties, see +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + tc358743@0f { + compatible = "toshiba,tc358743"; + reg = <0x0f>; + clocks = <&hdmi_osc>; + clock-names = "refclk"; + reset-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>; + interrupt-parent = <&gpio2>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + + port { + tc358743_out: endpoint { + remote-endpoint = <&mipi_csi2_in>; + data-lanes = <1 2 3 4>; + clock-lanes = <0>; + clock-noncontinuous; + link-frequencies = /bits/ 64 <297000000>; + }; + }; + }; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index a7542e5..822f45b 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -29,7 +29,9 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/i2c.h> +#include <linux/clk.h> #include <linux/delay.h> +#include <linux/gpio/consumer.h> #include <linux/videodev2.h> #include <linux/workqueue.h> #include <linux/v4l2-dv-timings.h> @@ -37,6 +39,7 @@ #include <media/v4l2-dv-timings.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> +#include <media/v4l2-of.h> #include <media/tc358743.h> #include "tc358743_regs.h" @@ -69,6 +72,7 @@ static const struct v4l2_dv_timings_cap tc358743_timings_cap = { struct tc358743_state { struct tc358743_platform_data pdata; + struct v4l2_of_bus_mipi_csi2 bus; struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler hdl; @@ -90,6 +94,8 @@ struct tc358743_state { struct v4l2_dv_timings timings; u32 mbus_fmt_code; + + struct gpio_desc *reset_gpio; }; static void tc358743_enable_interrupts(struct v4l2_subdev *sd, @@ -700,7 +706,8 @@ static void tc358743_set_csi(struct v4l2_subdev *sd) ((lanes > 2) ? MASK_D2M_HSTXVREGEN : 0x0) | ((lanes > 3) ? MASK_D3M_HSTXVREGEN : 0x0)); - i2c_wr32(sd, TXOPTIONCNTRL, MASK_CONTCLKMODE); + i2c_wr32(sd, TXOPTIONCNTRL, (state->bus.flags & + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) ? MASK_CONTCLKMODE : 0); i2c_wr32(sd, STARTCNTRL, MASK_START); i2c_wr32(sd, CSI_START, MASK_STRT); @@ -1638,6 +1645,137 @@ static const struct v4l2_ctrl_config tc358743_ctrl_audio_present = { /* --------------- PROBE / REMOVE --------------- */ +#if CONFIG_OF +static void tc358743_gpio_reset(struct tc358743_state *state) +{ + gpiod_set_value(state->reset_gpio, 0); + usleep_range(5000, 10000); + gpiod_set_value(state->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value(state->reset_gpio, 0); + msleep(20); +} + +static int tc358743_probe_of(struct tc358743_state *state) +{ + struct device *dev = &state->i2c_client->dev; + struct device_node *np = dev->of_node; + struct v4l2_of_endpoint *endpoint; + struct device_node *ep; + struct clk *refclk; + u32 bps_pr_lane; + int ret = -EINVAL; + + refclk = devm_clk_get(dev, "refclk"); + if (IS_ERR(refclk)) { + if (PTR_ERR(refclk) != -EPROBE_DEFER) + dev_err(dev, "failed to get refclk: %ld\n", + PTR_ERR(refclk)); + return PTR_ERR(refclk); + } + + ep = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!ep) { + dev_err(dev, "missing endpoint node\n"); + return -EINVAL; + } + + endpoint = v4l2_of_alloc_parse_endpoint(ep); + if (IS_ERR(endpoint)) { + dev_err(dev, "failed to parse endpoint\n"); + return PTR_ERR(endpoint); + } + + if (endpoint->bus_type != V4L2_MBUS_CSI2 || + endpoint->bus.mipi_csi2.num_data_lanes == 0 || + endpoint->nr_of_link_frequencies == 0) { + dev_err(dev, "missing CSI-2 properties in endpoint\n"); + goto free_endpoint; + } + + state->bus = endpoint.bus.mipi_csi2; + + clk_prepare_enable(refclk); + + state->pdata.refclk_hz = clk_get_rate(refclk); + state->pdata.ddc5v_delay = DDC5V_DELAY_100_MS; + state->pdata.enable_hdcp = false; + /* A FIFO level of 16 should be enough for 2-lane 720p60 at 594 MHz. */ + state->pdata.fifo_level = 16; + /* + * The PLL input clock is obtained by dividing refclk by pll_prd. + * It must be between 6 MHz and 40 MHz, lower frequency is better. + */ + switch (state->pdata.refclk_hz) { + case 26000000: + case 27000000: + case 42000000: + state->pdata.pll_prd = state->pdata.refclk_hz / 6000000; + break; + default: + dev_err(dev, "unsupported refclk rate: %u Hz\n", + state->pdata.refclk_hz); + goto disable_clk; + } + + /* + * The CSI bps per lane must be between 62.5 Mbps and 1 Gbps. + * The default is 594 Mbps for 4-lane 1080p60 or 2-lane 720p60. + */ + bps_pr_lane = 2 * endpoint->link_frequencies[0]; + if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) { + dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane); + goto disable_clk; + } + + /* The CSI speed per lane is refclk / pll_prd * pll_fbd */ + state->pdata.pll_fbd = bps_pr_lane / + state->pdata.refclk_hz * state->pdata.pll_prd; + + /* + * FIXME: These timings are from REF_02 for 594 Mbps per lane (297 MHz + * link frequency). In principle it should be possible to calculate + * them based on link frequency and resolution. + */ + if (bps_pr_lane != 594000000U) + dev_warn(dev, "untested bps per lane: %u bps\n", bps_pr_lane); + state->pdata.lineinitcnt = 0xe80; + state->pdata.lptxtimecnt = 0x003; + /* tclk-preparecnt: 3, tclk-zerocnt: 20 */ + state->pdata.tclk_headercnt = 0x1403; + state->pdata.tclk_trailcnt = 0x00; + /* ths-preparecnt: 3, ths-zerocnt: 1 */ + state->pdata.ths_headercnt = 0x0103; + state->pdata.twakeup = 0x4882; + state->pdata.tclk_postcnt = 0x008; + state->pdata.ths_trailcnt = 0x2; + state->pdata.hstxvregcnt = 0; + + state->reset_gpio = devm_gpiod_get(dev, "reset"); + if (IS_ERR(state->reset_gpio)) { + dev_err(dev, "failed to get reset gpio\n"); + ret = PTR_ERR(state->reset_gpio); + goto disable_clk; + } + + tc358743_gpio_reset(state); + + ret = 0; + goto free_endpoint; + +disable_clk: + clk_disable_unprepare(refclk); +free_endpoint: + v4l2_of_free_endpoint(endpoint); + return ret; +} +#else +static inline int tc358743_probe_of(struct tc358743_state *state) +{ + return -ENODEV; +} +#endif + static int tc358743_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1658,14 +1796,20 @@ static int tc358743_probe(struct i2c_client *client, if (!state) return -ENOMEM; + state->i2c_client = client; + /* platform data */ - if (!pdata) { - v4l_err(client, "No platform data!\n"); - return -ENODEV; + if (pdata) { + state->pdata = *pdata; + state->bus.flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + } else { + err = tc358743_probe_of(state); + if (err == -ENODEV) + v4l_err(client, "No platform data!\n"); + if (err) + return err; } - state->pdata = *pdata; - state->i2c_client = client; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &tc358743_ops); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; -- 2.1.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 3/4] [media] tc358743: support probe from device tree 2015-07-17 10:58 ` [PATCH v2 3/4] [media] tc358743: support probe from device tree Philipp Zabel @ 2015-07-17 12:23 ` Hans Verkuil 2015-07-17 14:06 ` Philipp Zabel 0 siblings, 1 reply; 6+ messages in thread From: Hans Verkuil @ 2015-07-17 12:23 UTC (permalink / raw) To: Philipp Zabel, Hans Verkuil; +Cc: Mats Randgaard, linux-media, kernel On 07/17/2015 12:58 PM, Philipp Zabel wrote: > 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 <p.zabel@pengutronix.de> > --- > Changes since v1: > - Added missing state->bus assignment for the device tree case > - Initialized state->bus.flags to V4L2_MBUS_CSI2_CONTINUOUS_CLOCK > in the platform data case. > --- > .../devicetree/bindings/media/i2c/tc358743.txt | 48 +++++++ > drivers/media/i2c/tc358743.c | 156 ++++++++++++++++++++- > 2 files changed, 198 insertions(+), 6 deletions(-) > create mode 100644 Documentation/devicetree/bindings/media/i2c/tc358743.txt > > diff --git a/Documentation/devicetree/bindings/media/i2c/tc358743.txt b/Documentation/devicetree/bindings/media/i2c/tc358743.txt > new file mode 100644 > index 0000000..5218921 > --- /dev/null > +++ b/Documentation/devicetree/bindings/media/i2c/tc358743.txt > @@ -0,0 +1,48 @@ > +* Toshiba TC358743 HDMI-RX to MIPI CSI2-TX Bridge > + > +The Toshiba TC358743 HDMI-RX to MIPI CSI2-TX (H2C) is a bridge that converts > +a HDMI stream to MIPI CSI-2 TX. It is programmable through I2C. > + > +Required Properties: > + > +- compatible: value should be "toshiba,tc358743" > +- clocks, clock-names: should contain a phandle link to the reference clock > + source, the clock input is named "refclk". > + > +Optional Properties: > + > +- reset-gpios: gpio phandle GPIO connected to the reset pin > +- interrupts, interrupt-parent: GPIO connected to the interrupt pin > +- data-lanes: should be <1 2 3 4> for four-lane operation, > + or <1 2> for two-lane operation > +- clock-lanes: should be <0> > +- clock-noncontinuous: Presence of this boolean property decides whether the > + MIPI CSI-2 clock is continuous or non-continuous. > +- link-frequencies: List of allowed link frequencies in Hz. Each frequency is > + expressed as a 64-bit big-endian integer. The frequency > + is half of the bps per lane due to DDR transmission. > + > +For further information on the MIPI CSI-2 endpoint node properties, see > +Documentation/devicetree/bindings/media/video-interfaces.txt. > + > +Example: > + > + tc358743@0f { > + compatible = "toshiba,tc358743"; > + reg = <0x0f>; > + clocks = <&hdmi_osc>; > + clock-names = "refclk"; > + reset-gpios = <&gpio6 9 GPIO_ACTIVE_LOW>; > + interrupt-parent = <&gpio2>; > + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; > + > + port { > + tc358743_out: endpoint { > + remote-endpoint = <&mipi_csi2_in>; > + data-lanes = <1 2 3 4>; > + clock-lanes = <0>; > + clock-noncontinuous; > + link-frequencies = /bits/ 64 <297000000>; > + }; > + }; > + }; > diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c > index a7542e5..822f45b 100644 > --- a/drivers/media/i2c/tc358743.c > +++ b/drivers/media/i2c/tc358743.c > @@ -29,7 +29,9 @@ > #include <linux/module.h> > #include <linux/slab.h> > #include <linux/i2c.h> > +#include <linux/clk.h> > #include <linux/delay.h> > +#include <linux/gpio/consumer.h> > #include <linux/videodev2.h> > #include <linux/workqueue.h> > #include <linux/v4l2-dv-timings.h> > @@ -37,6 +39,7 @@ > #include <media/v4l2-dv-timings.h> > #include <media/v4l2-device.h> > #include <media/v4l2-ctrls.h> > +#include <media/v4l2-of.h> > #include <media/tc358743.h> > > #include "tc358743_regs.h" > @@ -69,6 +72,7 @@ static const struct v4l2_dv_timings_cap tc358743_timings_cap = { > > struct tc358743_state { > struct tc358743_platform_data pdata; > + struct v4l2_of_bus_mipi_csi2 bus; > struct v4l2_subdev sd; > struct media_pad pad; > struct v4l2_ctrl_handler hdl; > @@ -90,6 +94,8 @@ struct tc358743_state { > > struct v4l2_dv_timings timings; > u32 mbus_fmt_code; > + > + struct gpio_desc *reset_gpio; > }; > > static void tc358743_enable_interrupts(struct v4l2_subdev *sd, > @@ -700,7 +706,8 @@ static void tc358743_set_csi(struct v4l2_subdev *sd) > ((lanes > 2) ? MASK_D2M_HSTXVREGEN : 0x0) | > ((lanes > 3) ? MASK_D3M_HSTXVREGEN : 0x0)); > > - i2c_wr32(sd, TXOPTIONCNTRL, MASK_CONTCLKMODE); > + i2c_wr32(sd, TXOPTIONCNTRL, (state->bus.flags & > + V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) ? MASK_CONTCLKMODE : 0); > i2c_wr32(sd, STARTCNTRL, MASK_START); > i2c_wr32(sd, CSI_START, MASK_STRT); > > @@ -1638,6 +1645,137 @@ static const struct v4l2_ctrl_config tc358743_ctrl_audio_present = { > > /* --------------- PROBE / REMOVE --------------- */ > > +#if CONFIG_OF Should be #ifdef > +static void tc358743_gpio_reset(struct tc358743_state *state) > +{ > + gpiod_set_value(state->reset_gpio, 0); > + usleep_range(5000, 10000); > + gpiod_set_value(state->reset_gpio, 1); > + usleep_range(1000, 2000); > + gpiod_set_value(state->reset_gpio, 0); > + msleep(20); > +} > + > +static int tc358743_probe_of(struct tc358743_state *state) > +{ > + struct device *dev = &state->i2c_client->dev; > + struct device_node *np = dev->of_node; Unused variable? > + struct v4l2_of_endpoint *endpoint; > + struct device_node *ep; > + struct clk *refclk; > + u32 bps_pr_lane; > + int ret = -EINVAL; > + > + refclk = devm_clk_get(dev, "refclk"); > + if (IS_ERR(refclk)) { > + if (PTR_ERR(refclk) != -EPROBE_DEFER) > + dev_err(dev, "failed to get refclk: %ld\n", > + PTR_ERR(refclk)); > + return PTR_ERR(refclk); > + } > + > + ep = of_graph_get_next_endpoint(dev->of_node, NULL); > + if (!ep) { > + dev_err(dev, "missing endpoint node\n"); > + return -EINVAL; > + } > + > + endpoint = v4l2_of_alloc_parse_endpoint(ep); > + if (IS_ERR(endpoint)) { > + dev_err(dev, "failed to parse endpoint\n"); > + return PTR_ERR(endpoint); > + } > + > + if (endpoint->bus_type != V4L2_MBUS_CSI2 || > + endpoint->bus.mipi_csi2.num_data_lanes == 0 || > + endpoint->nr_of_link_frequencies == 0) { > + dev_err(dev, "missing CSI-2 properties in endpoint\n"); > + goto free_endpoint; > + } > + > + state->bus = endpoint.bus.mipi_csi2; This should be endpoint->bus. You clearly didn't compile it. Please make a v3, ensure that it compiles and please test it as well. Regards, Hans > + > + clk_prepare_enable(refclk); > + > + state->pdata.refclk_hz = clk_get_rate(refclk); > + state->pdata.ddc5v_delay = DDC5V_DELAY_100_MS; > + state->pdata.enable_hdcp = false; > + /* A FIFO level of 16 should be enough for 2-lane 720p60 at 594 MHz. */ > + state->pdata.fifo_level = 16; > + /* > + * The PLL input clock is obtained by dividing refclk by pll_prd. > + * It must be between 6 MHz and 40 MHz, lower frequency is better. > + */ > + switch (state->pdata.refclk_hz) { > + case 26000000: > + case 27000000: > + case 42000000: > + state->pdata.pll_prd = state->pdata.refclk_hz / 6000000; > + break; > + default: > + dev_err(dev, "unsupported refclk rate: %u Hz\n", > + state->pdata.refclk_hz); > + goto disable_clk; > + } > + > + /* > + * The CSI bps per lane must be between 62.5 Mbps and 1 Gbps. > + * The default is 594 Mbps for 4-lane 1080p60 or 2-lane 720p60. > + */ > + bps_pr_lane = 2 * endpoint->link_frequencies[0]; > + if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) { > + dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane); > + goto disable_clk; > + } > + > + /* The CSI speed per lane is refclk / pll_prd * pll_fbd */ > + state->pdata.pll_fbd = bps_pr_lane / > + state->pdata.refclk_hz * state->pdata.pll_prd; > + > + /* > + * FIXME: These timings are from REF_02 for 594 Mbps per lane (297 MHz > + * link frequency). In principle it should be possible to calculate > + * them based on link frequency and resolution. > + */ > + if (bps_pr_lane != 594000000U) > + dev_warn(dev, "untested bps per lane: %u bps\n", bps_pr_lane); > + state->pdata.lineinitcnt = 0xe80; > + state->pdata.lptxtimecnt = 0x003; > + /* tclk-preparecnt: 3, tclk-zerocnt: 20 */ > + state->pdata.tclk_headercnt = 0x1403; > + state->pdata.tclk_trailcnt = 0x00; > + /* ths-preparecnt: 3, ths-zerocnt: 1 */ > + state->pdata.ths_headercnt = 0x0103; > + state->pdata.twakeup = 0x4882; > + state->pdata.tclk_postcnt = 0x008; > + state->pdata.ths_trailcnt = 0x2; > + state->pdata.hstxvregcnt = 0; > + > + state->reset_gpio = devm_gpiod_get(dev, "reset"); > + if (IS_ERR(state->reset_gpio)) { > + dev_err(dev, "failed to get reset gpio\n"); > + ret = PTR_ERR(state->reset_gpio); > + goto disable_clk; > + } > + > + tc358743_gpio_reset(state); > + > + ret = 0; > + goto free_endpoint; > + > +disable_clk: > + clk_disable_unprepare(refclk); > +free_endpoint: > + v4l2_of_free_endpoint(endpoint); > + return ret; > +} > +#else > +static inline int tc358743_probe_of(struct tc358743_state *state) > +{ > + return -ENODEV; > +} > +#endif > + > static int tc358743_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > @@ -1658,14 +1796,20 @@ static int tc358743_probe(struct i2c_client *client, > if (!state) > return -ENOMEM; > > + state->i2c_client = client; > + > /* platform data */ > - if (!pdata) { > - v4l_err(client, "No platform data!\n"); > - return -ENODEV; > + if (pdata) { > + state->pdata = *pdata; > + state->bus.flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; > + } else { > + err = tc358743_probe_of(state); > + if (err == -ENODEV) > + v4l_err(client, "No platform data!\n"); > + if (err) > + return err; > } > - state->pdata = *pdata; > > - state->i2c_client = client; > sd = &state->sd; > v4l2_i2c_subdev_init(sd, client, &tc358743_ops); > sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 3/4] [media] tc358743: support probe from device tree 2015-07-17 12:23 ` Hans Verkuil @ 2015-07-17 14:06 ` Philipp Zabel 0 siblings, 0 replies; 6+ messages in thread From: Philipp Zabel @ 2015-07-17 14:06 UTC (permalink / raw) To: Hans Verkuil; +Cc: Hans Verkuil, Mats Randgaard, linux-media, kernel Hi Hans, Am Freitag, den 17.07.2015, 14:23 +0200 schrieb Hans Verkuil: [...] > > + endpoint = v4l2_of_alloc_parse_endpoint(ep); > > + if (IS_ERR(endpoint)) { > > + dev_err(dev, "failed to parse endpoint\n"); > > + return PTR_ERR(endpoint); > > + } > > + > > + if (endpoint->bus_type != V4L2_MBUS_CSI2 || > > + endpoint->bus.mipi_csi2.num_data_lanes == 0 || > > + endpoint->nr_of_link_frequencies == 0) { > > + dev_err(dev, "missing CSI-2 properties in endpoint\n"); > > + goto free_endpoint; > > + } > > + > > + state->bus = endpoint.bus.mipi_csi2; > > This should be endpoint->bus. You clearly didn't compile it. > > Please make a v3, ensure that it compiles and please test it as well. Sorry, fixed, tested, and resent. regards Philipp ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/4] [media] tc358743: add direct interrupt handling 2015-07-17 10:58 [PATCH v2 1/4] [media] tc358743: register v4l2 asynchronous subdevice Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 2/4] [media] tc358743: enable v4l2 subdevice devnode Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 3/4] [media] tc358743: support probe from device tree Philipp Zabel @ 2015-07-17 10:58 ` Philipp Zabel 2 siblings, 0 replies; 6+ messages in thread From: Philipp Zabel @ 2015-07-17 10:58 UTC (permalink / raw) To: Hans Verkuil; +Cc: Mats Randgaard, linux-media, kernel, Philipp Zabel When probed from device tree, the i2c client driver can handle the interrupt on its own. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> --- drivers/media/i2c/tc358743.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 822f45b..2a3e3bb 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -32,6 +32,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> +#include <linux/interrupt.h> #include <linux/videodev2.h> #include <linux/workqueue.h> #include <linux/v4l2-dv-timings.h> @@ -1306,6 +1307,16 @@ static int tc358743_isr(struct v4l2_subdev *sd, u32 status, bool *handled) return 0; } +static irqreturn_t tc358743_irq_handler(int irq, void *dev_id) +{ + struct tc358743_state *state = dev_id; + bool handled; + + tc358743_isr(&state->sd, 0, &handled); + + return handled ? IRQ_HANDLED : IRQ_NONE; +} + /* --------------- VIDEO OPS --------------- */ static int tc358743_g_input_status(struct v4l2_subdev *sd, u32 *status) @@ -1877,6 +1888,17 @@ static int tc358743_probe(struct i2c_client *client, tc358743_set_csi_color_space(sd); tc358743_init_interrupts(sd); + + if (state->i2c_client->irq) { + err = devm_request_threaded_irq(&client->dev, + state->i2c_client->irq, + NULL, tc358743_irq_handler, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "tc358743", state); + if (err) + goto err_work_queues; + } + tc358743_enable_interrupts(sd, tx_5v_power_present(sd)); i2c_wr16(sd, INTMASK, ~(MASK_HDMI_MSK | MASK_CSI_MSK) & 0xffff); -- 2.1.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-07-17 14:06 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-07-17 10:58 [PATCH v2 1/4] [media] tc358743: register v4l2 asynchronous subdevice Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 2/4] [media] tc358743: enable v4l2 subdevice devnode Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 3/4] [media] tc358743: support probe from device tree Philipp Zabel 2015-07-17 12:23 ` Hans Verkuil 2015-07-17 14:06 ` Philipp Zabel 2015-07-17 10:58 ` [PATCH v2 4/4] [media] tc358743: add direct interrupt handling Philipp Zabel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox