Commit bf3cfaa7 authored by Steve Longerbeam's avatar Steve Longerbeam Committed by Mauro Carvalho Chehab

media: staging/imx: get CSI bus type from nearest upstream entity

The imx-media driver currently supports a device tree graph of
limited complexity. This patch is a first step in allowing imx-media
to work with more general OF graphs.

The CSI subdevice assumes the originating upstream subdevice (the
"sensor") is connected directly to either the CSI mux or the MIPI
CSI-2 receiver. But for more complex graphs, the sensor can be distant,
with possible bridge entities in between. Thus the sensor's bus type
could be quite different from what is entering the CSI. For example
a distant sensor could have a parallel interface, but the stream
entering the i.MX is MIPI CSI-2.

To remove this assumption, get the entering bus config from the entity
that is directly upstream from either the CSI mux, or the CSI-2 receiver.
If the CSI-2 receiver is not in the enabled pipeline, the bus type to the
CSI is parallel, otherwise the CSI is receiving MIPI CSI-2.

Note that we can't use the direct upstream source connected to CSI
(which is either the CSI mux or the CSI-2 receiver) to determine
bus type. The bus entering the CSI from the CSI-2 receiver is a 32-bit
parallel bus containing the demultiplexed MIPI CSI-2 virtual channels.
But the CSI and its IDMAC channels must be configured based on whether
it is receiving data from the CSI-2 receiver or from the CSI mux's
parallel interface pins.

The function csi_get_upstream_endpoint() is used to find this
endpoint. It makes use of a new utility function
imx_media_find_upstream_pad(), that if given a grp_id of 0, will
return the closest upstream pad from start_entity.

With these changes, imx_media_find_sensor() is no longer used and
is removed. As a result there is also no longer a need to identify
any sensor or set the sensor subdev's group id as a method to search
for it. So IMX_MEDIA_GRP_ID_SENSOR is removed. Also the video-mux group
id IMX_MEDIA_GRP_ID_VIDMUX was never used so that is removed as well.
The remaining IMX_MEDIA_GRP_ID_* definitions are entities internal
to the i.MX.

Another use of imx_media_find_sensor() in the CSI was to call the
sensor's g_skip_frames op to determine if a delay was needed before
enabling the CSI at stream on. If necessary this will have to be
re-addressed at a later time.
Signed-off-by: default avatarSteve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 3cd890db
This diff is collapsed.
......@@ -222,18 +222,6 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
ret = imx_media_get_ipu(imxmd, sd);
if (ret)
goto out_unlock;
} else if (sd->entity.function == MEDIA_ENT_F_VID_MUX) {
/* this is a video mux */
sd->grp_id = IMX_MEDIA_GRP_ID_VIDMUX;
} else if (imxsd->num_sink_pads == 0) {
/*
* this is an original source of video frames, it
* could be a camera sensor, an analog decoder, or
* a bridge device (HDMI -> MIPI CSI-2 for example).
* This group ID is used to locate the entity that
* is the original source of video in a pipeline.
*/
sd->grp_id = IMX_MEDIA_GRP_ID_SENSOR;
}
/* attach the subdev */
......
......@@ -34,20 +34,6 @@ static int of_add_pad_link(struct imx_media_dev *imxmd,
local_pad, remote_pad);
}
static void of_parse_sensor(struct imx_media_dev *imxmd,
struct imx_media_subdev *sensor,
struct device_node *sensor_np)
{
struct device_node *endpoint;
endpoint = of_graph_get_next_endpoint(sensor_np, NULL);
if (endpoint) {
v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
&sensor->sensor_ep);
of_node_put(endpoint);
}
}
static int of_get_port_count(const struct device_node *np)
{
struct device_node *ports, *child;
......@@ -172,13 +158,6 @@ of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np,
__func__, sd_np->name, num_pads,
imxsd->num_sink_pads, imxsd->num_src_pads);
/*
* With no sink, this subdev node is the original source
* of video, parse it's media bus for use by the pipeline.
*/
if (imxsd->num_sink_pads == 0)
of_parse_sensor(imxmd, imxsd, sd_np);
for (i = 0; i < num_pads; i++) {
struct device_node *epnode = NULL, *port, *remote_np;
struct imx_media_subdev *remote_imxsd;
......
......@@ -730,10 +730,11 @@ int imx_media_add_video_device(struct imx_media_dev *imxmd,
EXPORT_SYMBOL_GPL(imx_media_add_video_device);
/*
* Search upstream or downstream for a subdevice in the current pipeline
* Search upstream/downstream for a subdevice in the current pipeline
* with given grp_id, starting from start_entity. Returns the subdev's
* source/sink pad that it was reached from. Must be called with
* mdev->graph_mutex held.
* source/sink pad that it was reached from. If grp_id is zero, just
* returns the nearest source/sink pad to start_entity. Must be called
* with mdev->graph_mutex held.
*/
static struct media_pad *
find_pipeline_pad(struct imx_media_dev *imxmd,
......@@ -756,11 +757,16 @@ find_pipeline_pad(struct imx_media_dev *imxmd,
if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
continue;
sd = media_entity_to_v4l2_subdev(pad->entity);
if (sd->grp_id & grp_id)
return pad;
if (grp_id != 0) {
sd = media_entity_to_v4l2_subdev(pad->entity);
if (sd->grp_id & grp_id)
return pad;
return find_pipeline_pad(imxmd, pad->entity, grp_id, upstream);
return find_pipeline_pad(imxmd, pad->entity,
grp_id, upstream);
} else {
return pad;
}
}
return NULL;
......@@ -789,7 +795,6 @@ find_upstream_subdev(struct imx_media_dev *imxmd,
return pad ? media_entity_to_v4l2_subdev(pad->entity) : NULL;
}
/*
* Find the upstream mipi-csi2 virtual channel reached from the given
* start entity in the current pipeline.
......@@ -813,6 +818,25 @@ int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
}
EXPORT_SYMBOL_GPL(imx_media_find_mipi_csi2_channel);
/*
* Find a source pad reached upstream from the given start entity in
* the current pipeline. Must be called with mdev->graph_mutex held.
*/
struct media_pad *
imx_media_find_upstream_pad(struct imx_media_dev *imxmd,
struct media_entity *start_entity,
u32 grp_id)
{
struct media_pad *pad;
pad = find_pipeline_pad(imxmd, start_entity, grp_id, true);
if (!pad)
return ERR_PTR(-ENODEV);
return pad;
}
EXPORT_SYMBOL_GPL(imx_media_find_upstream_pad);
/*
* Find a subdev reached upstream from the given start entity in
* the current pipeline.
......@@ -833,29 +857,6 @@ imx_media_find_upstream_subdev(struct imx_media_dev *imxmd,
}
EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev);
struct imx_media_subdev *
__imx_media_find_sensor(struct imx_media_dev *imxmd,
struct media_entity *start_entity)
{
return imx_media_find_upstream_subdev(imxmd, start_entity,
IMX_MEDIA_GRP_ID_SENSOR);
}
EXPORT_SYMBOL_GPL(__imx_media_find_sensor);
struct imx_media_subdev *
imx_media_find_sensor(struct imx_media_dev *imxmd,
struct media_entity *start_entity)
{
struct imx_media_subdev *sensor;
mutex_lock(&imxmd->md.graph_mutex);
sensor = __imx_media_find_sensor(imxmd, start_entity);
mutex_unlock(&imxmd->md.graph_mutex);
return sensor;
}
EXPORT_SYMBOL_GPL(imx_media_find_sensor);
/*
* Turn current pipeline streaming on/off starting from entity.
*/
......
......@@ -158,9 +158,6 @@ struct imx_media_subdev {
struct platform_device *pdev;
/* the devname is needed for async devname match */
char devname[32];
/* if this is a sensor */
struct v4l2_fwnode_endpoint sensor_ep;
};
struct imx_media_dev {
......@@ -251,16 +248,14 @@ int imx_media_add_video_device(struct imx_media_dev *imxmd,
struct imx_media_video_dev *vdev);
int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
struct media_entity *start_entity);
struct media_pad *
imx_media_find_upstream_pad(struct imx_media_dev *imxmd,
struct media_entity *start_entity,
u32 grp_id);
struct imx_media_subdev *
imx_media_find_upstream_subdev(struct imx_media_dev *imxmd,
struct media_entity *start_entity,
u32 grp_id);
struct imx_media_subdev *
__imx_media_find_sensor(struct imx_media_dev *imxmd,
struct media_entity *start_entity);
struct imx_media_subdev *
imx_media_find_sensor(struct imx_media_dev *imxmd,
struct media_entity *start_entity);
struct imx_media_dma_buf {
void *virt;
......@@ -310,16 +305,14 @@ void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
void imx_media_capture_device_error(struct imx_media_video_dev *vdev);
/* subdev group ids */
#define IMX_MEDIA_GRP_ID_SENSOR BIT(8)
#define IMX_MEDIA_GRP_ID_VIDMUX BIT(9)
#define IMX_MEDIA_GRP_ID_CSI2 BIT(10)
#define IMX_MEDIA_GRP_ID_CSI_BIT 11
#define IMX_MEDIA_GRP_ID_CSI2 BIT(8)
#define IMX_MEDIA_GRP_ID_CSI_BIT 9
#define IMX_MEDIA_GRP_ID_CSI (0x3 << IMX_MEDIA_GRP_ID_CSI_BIT)
#define IMX_MEDIA_GRP_ID_CSI0 BIT(IMX_MEDIA_GRP_ID_CSI_BIT)
#define IMX_MEDIA_GRP_ID_CSI1 (2 << IMX_MEDIA_GRP_ID_CSI_BIT)
#define IMX_MEDIA_GRP_ID_VDIC BIT(13)
#define IMX_MEDIA_GRP_ID_IC_PRP BIT(14)
#define IMX_MEDIA_GRP_ID_IC_PRPENC BIT(15)
#define IMX_MEDIA_GRP_ID_IC_PRPVF BIT(16)
#define IMX_MEDIA_GRP_ID_VDIC BIT(11)
#define IMX_MEDIA_GRP_ID_IC_PRP BIT(12)
#define IMX_MEDIA_GRP_ID_IC_PRPENC BIT(13)
#define IMX_MEDIA_GRP_ID_IC_PRPVF BIT(14)
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment