Skip to content

Commit 5cef078

Browse files
Jacopo Mondimchehab
authored andcommitted
media: rcar-csi2: Negotiate data lanes number
Use the newly introduced get_mbus_config() subdevice pad operation to retrieve the remote subdevice MIPI CSI-2 bus configuration and configure the number of active data lanes accordingly. In order to be able to call the remote subdevice operation cache the index of the remote pad connected to the single CSI-2 input port. Reviewed-by: Niklas Söderlund <[email protected]> Signed-off-by: Jacopo Mondi <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent a61b1b5 commit 5cef078

File tree

1 file changed

+68
-7
lines changed

1 file changed

+68
-7
lines changed

drivers/media/platform/rcar-vin/rcar-csi2.c

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ struct rcar_csi2 {
364364
struct v4l2_async_notifier notifier;
365365
struct v4l2_async_subdev asd;
366366
struct v4l2_subdev *remote;
367+
unsigned int remote_pad;
367368

368369
struct v4l2_mbus_framefmt mf;
369370

@@ -409,13 +410,14 @@ static void rcsi2_exit_standby(struct rcar_csi2 *priv)
409410
reset_control_deassert(priv->rstc);
410411
}
411412

412-
static int rcsi2_wait_phy_start(struct rcar_csi2 *priv)
413+
static int rcsi2_wait_phy_start(struct rcar_csi2 *priv,
414+
unsigned int lanes)
413415
{
414416
unsigned int timeout;
415417

416418
/* Wait for the clock and data lanes to enter LP-11 state. */
417419
for (timeout = 0; timeout <= 20; timeout++) {
418-
const u32 lane_mask = (1 << priv->lanes) - 1;
420+
const u32 lane_mask = (1 << lanes) - 1;
419421

420422
if ((rcsi2_read(priv, PHCLM_REG) & PHCLM_STOPSTATECKL) &&
421423
(rcsi2_read(priv, PHDLM_REG) & lane_mask) == lane_mask)
@@ -447,7 +449,8 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps)
447449
return 0;
448450
}
449451

450-
static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
452+
static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp,
453+
unsigned int lanes)
451454
{
452455
struct v4l2_subdev *source;
453456
struct v4l2_ctrl *ctrl;
@@ -472,15 +475,64 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
472475
* bps = link_freq * 2
473476
*/
474477
mbps = v4l2_ctrl_g_ctrl_int64(ctrl) * bpp;
475-
do_div(mbps, priv->lanes * 1000000);
478+
do_div(mbps, lanes * 1000000);
476479

477480
return mbps;
478481
}
479482

483+
static int rcsi2_get_active_lanes(struct rcar_csi2 *priv,
484+
unsigned int *lanes)
485+
{
486+
struct v4l2_mbus_config mbus_config = { 0 };
487+
unsigned int num_lanes = UINT_MAX;
488+
int ret;
489+
490+
*lanes = priv->lanes;
491+
492+
ret = v4l2_subdev_call(priv->remote, pad, get_mbus_config,
493+
priv->remote_pad, &mbus_config);
494+
if (ret == -ENOIOCTLCMD) {
495+
dev_dbg(priv->dev, "No remote mbus configuration available\n");
496+
return 0;
497+
}
498+
499+
if (ret) {
500+
dev_err(priv->dev, "Failed to get remote mbus configuration\n");
501+
return ret;
502+
}
503+
504+
if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) {
505+
dev_err(priv->dev, "Unsupported media bus type %u\n",
506+
mbus_config.type);
507+
return -EINVAL;
508+
}
509+
510+
if (mbus_config.flags & V4L2_MBUS_CSI2_1_LANE)
511+
num_lanes = 1;
512+
else if (mbus_config.flags & V4L2_MBUS_CSI2_2_LANE)
513+
num_lanes = 2;
514+
else if (mbus_config.flags & V4L2_MBUS_CSI2_3_LANE)
515+
num_lanes = 3;
516+
else if (mbus_config.flags & V4L2_MBUS_CSI2_4_LANE)
517+
num_lanes = 4;
518+
519+
if (num_lanes > priv->lanes) {
520+
dev_err(priv->dev,
521+
"Unsupported mbus config: too many data lanes %u\n",
522+
num_lanes);
523+
return -EINVAL;
524+
}
525+
526+
*lanes = num_lanes;
527+
528+
return 0;
529+
}
530+
480531
static int rcsi2_start_receiver(struct rcar_csi2 *priv)
481532
{
482533
const struct rcar_csi2_format *format;
483534
u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0;
535+
unsigned int lanes;
484536
unsigned int i;
485537
int mbps, ret;
486538

@@ -522,10 +574,18 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
522574
fld |= FLD_FLD_NUM(1);
523575
}
524576

577+
/*
578+
* Get the number of active data lanes inspecting the remote mbus
579+
* configuration.
580+
*/
581+
ret = rcsi2_get_active_lanes(priv, &lanes);
582+
if (ret)
583+
return ret;
584+
525585
phycnt = PHYCNT_ENABLECLK;
526-
phycnt |= (1 << priv->lanes) - 1;
586+
phycnt |= (1 << lanes) - 1;
527587

528-
mbps = rcsi2_calc_mbps(priv, format->bpp);
588+
mbps = rcsi2_calc_mbps(priv, format->bpp, lanes);
529589
if (mbps < 0)
530590
return mbps;
531591

@@ -572,7 +632,7 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv)
572632
rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ);
573633
rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ);
574634

575-
ret = rcsi2_wait_phy_start(priv);
635+
ret = rcsi2_wait_phy_start(priv, lanes);
576636
if (ret)
577637
return ret;
578638

@@ -749,6 +809,7 @@ static int rcsi2_notify_bound(struct v4l2_async_notifier *notifier,
749809
}
750810

751811
priv->remote = subdev;
812+
priv->remote_pad = pad;
752813

753814
dev_dbg(priv->dev, "Bound %s pad: %d\n", subdev->name, pad);
754815

0 commit comments

Comments
 (0)