static int rcsi2_calc_mbps(struct rcar_csi2 *priv,
struct v4l2_subdev_state *state)
{
- const struct rcar_csi2_format *format;
- struct v4l2_mbus_framefmt *fmt;
struct media_pad *remote_pad;
struct v4l2_subdev *source;
- unsigned int lanes;
- unsigned int bpp;
s64 freq;
u64 mbps;
- int ret;
if (!priv->remote)
return -ENODEV;
source = priv->remote;
remote_pad = &source->entity.pads[priv->remote_pad];
- ret = rcsi2_get_active_lanes(priv, &lanes);
- if (ret)
- return ret;
+ /*
+ * First try to get the real link freq. If that fails, try the heuristic
+ * method with bpp and lanes (but that only works for one route).
+ */
+ freq = v4l2_get_link_freq(remote_pad, 0, 0);
+ if (freq < 0) {
+ const struct rcar_csi2_format *format;
+ const struct v4l2_mbus_framefmt *fmt;
+ unsigned int lanes;
+ unsigned int bpp;
+ int ret;
- fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
- if (!fmt)
- return -EINVAL;
+ ret = rcsi2_get_active_lanes(priv, &lanes);
+ if (ret)
+ return ret;
- format = rcsi2_code_to_fmt(fmt->code);
- if (!format)
- return -EINVAL;
+ fmt = v4l2_subdev_state_get_format(state, RCAR_CSI2_SINK);
+ if (!fmt)
+ return -EINVAL;
- bpp = format->bpp;
+ format = rcsi2_code_to_fmt(fmt->code);
+ if (!format)
+ return -EINVAL;
- freq = v4l2_get_link_freq(remote_pad, bpp, 2 * lanes);
- if (freq < 0) {
- int ret = (int)freq;
+ bpp = format->bpp;
- dev_err(priv->dev, "failed to get link freq for %s: %d\n",
- source->name, ret);
+ freq = v4l2_get_link_freq(remote_pad, bpp, 2 * lanes);
+ if (freq < 0) {
+ int ret = (int)freq;
- return ret;
+ dev_err(priv->dev, "failed to get link freq for %s: %d\n",
+ source->name, ret);
+
+ return ret;
+ }
}
mbps = div_u64(freq * 2, MEGA);