[PATCH] thermal: rcar_gen3_thermal: Add Standby-mode function support

2018-11-01 Thread Nguyen An Hoan
From: Hoan Nguyen An 

According to the hardware manual, Gen3 supports Standby-mode,
Add this function, and we should use this function while
suspend to reduce the energy consumption.

Signed-off-by: Hoan Nguyen An 
---
 drivers/thermal/rcar_gen3_thermal.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/rcar_gen3_thermal.c 
b/drivers/thermal/rcar_gen3_thermal.c
index 7aed533..7f3bd7f 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -447,11 +447,30 @@ static int rcar_gen3_thermal_probe(struct platform_device 
*pdev)
return ret;
 }
 
+static int rcar_gen3_thermal_standby(struct rcar_gen3_thermal_priv* priv)
+{
+   unsigned int i;
+   u32 reg_val;
+
+   for (i = 0; i < TSC_MAX_NUM; i++) {
+   struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
+
+   rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, 0);
+   rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
+
+   reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
+   rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val & 
~THCTR_THSST);
+
+
+   usleep_range(1000, 2000);
+   }
+}
+
 static int __maybe_unused rcar_gen3_thermal_suspend(struct device *dev)
 {
struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
 
-   rcar_thermal_irq_set(priv, false);
+   rcar_gen3_thermal_standby(priv);
 
return 0;
 }
-- 
2.7.4



Re: [PATCH v3 2/3] mmc: tmio: fix reset operation

2018-11-01 Thread Masahiro Yamada
On Thu, Nov 1, 2018 at 8:53 AM Niklas Söderlund
 wrote:
>
> From: Niklas Söderlund 
>
> SD / MMC did not operate properly when suspend transition failed.
> Because the SCC was not reset at resume, issue of the command failed.
> Call the host specific reset function and reset the hardware in order to
> add reset of SCC. This change also fixes tuning on some stubborn cards
> on Gen2.
>
> Based on work from Masaharu Hayakawa.
>
> Signed-off-by: Niklas Söderlund 
>
> ---
> * Changes sine v1
> - Merge tmio_mmc_reset() into tmio_mmc_hw_reset() as it's now the only
>   caller.
>
> * Changes since v2
> - Rebased on mmc/next caused small refactoring of the code.
> ---
>  drivers/mmc/host/tmio_mmc_core.c | 26 +++---
>  1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mmc/host/tmio_mmc_core.c 
> b/drivers/mmc/host/tmio_mmc_core.c
> index 953562a12a0d6ebc..662161be03b6d52e 100644
> --- a/drivers/mmc/host/tmio_mmc_core.c
> +++ b/drivers/mmc/host/tmio_mmc_core.c
> @@ -171,6 +171,18 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host)
> }
>  }
>
> +static void tmio_mmc_hw_reset(struct mmc_host *mmc)
> +{
> +   struct tmio_mmc_host *host = mmc_priv(mmc);
> +
> +   host->reset(host);
> +
> +   tmio_mmc_abort_dma(host);
> +
> +   if (host->hw_reset)
> +   host->hw_reset(host);
> +}
> +
>  static void tmio_mmc_reset_work(struct work_struct *work)
>  {
> struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
> @@ -209,7 +221,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)
>
> spin_unlock_irqrestore(&host->lock, flags);
>
> -   host->reset(host);
> +   tmio_mmc_hw_reset(host->mmc);
>
> /* Ready for new calls */
> host->mrq = NULL;



I see tmio_mmc_abort_dma() a few lines below.

If you add tmio_mmc_abort_dma() into tmio_mmc_hw_reset(),
you do not need to abort DMA twice, don't you?




tmio_mmc_hw_reset(host->mmc);

/* Ready for new calls */
host->mrq = NULL;

tmio_mmc_abort_dma(host);  /* <-- abort DMA again? */
mmc_request_done(host->mmc, mrq);
}







> @@ -696,14 +708,6 @@ static int tmio_mmc_start_data(struct tmio_mmc_host 
> *host,
> return 0;
>  }
>
> -static void tmio_mmc_hw_reset(struct mmc_host *mmc)
> -{
> -   struct tmio_mmc_host *host = mmc_priv(mmc);
> -
> -   if (host->hw_reset)
> -   host->hw_reset(host);
> -}
> -
>  static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
>  {
> struct tmio_mmc_host *host = mmc_priv(mmc);
> @@ -1228,7 +1232,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host)
> _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
>
> _host->set_clock(_host, 0);
> -   _host->reset(_host);
> +   tmio_mmc_hw_reset(mmc);


I think it is weird to call tmio_mmc_abort_dma()
before tmio_mmc_request_dma().





> _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, 
> CTL_IRQ_MASK);
> tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
> @@ -1329,7 +1333,7 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
> struct tmio_mmc_host *host = dev_get_drvdata(dev);
>
> tmio_mmc_clk_enable(host);
> -   host->reset(host);
> +   tmio_mmc_hw_reset(host->mmc);
>
> if (host->clk_cache)
> host->set_clock(host, host->clk_cache);
> --
> 2.19.1
>


--
Best Regards
Masahiro Yamada


Re: [PATCH v3 1/3] mmc: tmio: enable module clock before resetting when resuming

2018-11-01 Thread Masahiro Yamada
On Thu, Nov 1, 2018 at 8:52 AM Niklas Söderlund
 wrote:
>
> From: Niklas Söderlund 
>
> On runtime power management resume, the host clock needs to be
> enabled before calling tmio_mmc_reset. If the mmc device has a power
> domain entry, the host clock is enabled via genpd_runtime_resume,
> running before tmio_mmc_host_runtime_resume. If the mmc device has no
> power domain entry, however, genpd_runtime_resume is not called. This
> patch changes tmio_mmc_host_runtime_resume to enable the host clock
> before calling tmio_mmc_reset.
>
> Based on work from Masaharu Hayakawa.
>
> Signed-off-by: Niklas Söderlund 


Reviewed-by: Masahiro Yamada 




> ---
>  drivers/mmc/host/tmio_mmc_core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/mmc/host/tmio_mmc_core.c 
> b/drivers/mmc/host/tmio_mmc_core.c
> index 8d64f6196f33e882..953562a12a0d6ebc 100644
> --- a/drivers/mmc/host/tmio_mmc_core.c
> +++ b/drivers/mmc/host/tmio_mmc_core.c
> @@ -1328,8 +1328,8 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
>  {
> struct tmio_mmc_host *host = dev_get_drvdata(dev);
>
> -   host->reset(host);
> tmio_mmc_clk_enable(host);
> +   host->reset(host);
>
> if (host->clk_cache)
> host->set_clock(host, host->clk_cache);
> --
> 2.19.1
>


--
Best Regards
Masahiro Yamada


[PATCH v2 15/30] media: entity: Look for indirect routes

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Two pads are considered having an active route for the purpose of
has_route() if an indirect active route can be found between the two pads.
An simple example of this is that a source pad has an active route to
another source pad if both of the pads have an active route to the same
sink pad.

Make media_entity_has_route() return true in that case, and do not rely on
drivers performing this by themselves.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 42977634d7102852..e45fc2549017615a 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -240,6 +240,9 @@ EXPORT_SYMBOL_GPL(media_entity_pads_init);
 bool media_entity_has_route(struct media_entity *entity, unsigned int pad0,
unsigned int pad1)
 {
+   unsigned int i;
+   bool has_route;
+
if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
return false;
 
@@ -253,7 +256,34 @@ bool media_entity_has_route(struct media_entity *entity, 
unsigned int pad0,
&& entity->pads[pad1].flags & MEDIA_PAD_FL_SINK)
swap(pad0, pad1);
 
-   return entity->ops->has_route(entity, pad0, pad1);
+   has_route = entity->ops->has_route(entity, pad0, pad1);
+   /* A direct route is returned immediately */
+   if (has_route ||
+   (entity->pads[pad0].flags & MEDIA_PAD_FL_SINK &&
+entity->pads[pad1].flags & MEDIA_PAD_FL_SOURCE))
+   return true;
+
+   /* Look for indirect routes */
+   for (i = 0; i < entity->num_pads; i++) {
+   if (i == pad0 || i == pad1)
+   continue;
+
+   /*
+* There are no direct routes between same types of
+* pads, so skip checking this route
+*/
+   if (!((entity->pads[pad0].flags ^ entity->pads[i].flags) &
+ (MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_SINK)))
+   continue;
+
+   /* Is there an indirect route? */
+   if (entity->ops->has_route(entity, i, pad0) &&
+   entity->ops->has_route(entity, i, pad1))
+   return true;
+   }
+
+   return false;
+
 }
 EXPORT_SYMBOL_GPL(media_entity_has_route);
 
-- 
2.19.1



[PATCH v2 17/30] v4l: subdev: compat: Implement handling for VIDIOC_SUBDEV_[GS]_ROUTING

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Implement compat IOCTL handling for VIDIOC_SUBDEV_G_ROUTING and
VIDIOC_SUBDEV_S_ROUTING IOCTLs.

Signed-off-by: Sakari Ailus 
Signed-off-by: Niklas Söderlund 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 77 +++
 1 file changed, 77 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 6481212fda772c73..83af332763f41a6b 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1045,6 +1045,66 @@ static int put_v4l2_event32(struct v4l2_event __user 
*p64,
return 0;
 }
 
+struct v4l2_subdev_routing32 {
+   compat_caddr_t routes;
+   __u32 num_routes;
+   __u32 reserved[5];
+};
+
+static int get_v4l2_subdev_routing(struct v4l2_subdev_routing __user *p64,
+  struct v4l2_subdev_routing32 __user *p32)
+{
+   struct v4l2_subdev_route __user *routes;
+   compat_caddr_t p;
+   u32 num_routes;
+
+   if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+   get_user(p, &p32->routes) ||
+   get_user(num_routes, &p32->num_routes) ||
+   put_user(num_routes, &p64->num_routes) ||
+   copy_in_user(&p64->reserved, &p32->reserved,
+sizeof(p64->reserved)) ||
+   num_routes > U32_MAX / sizeof(*p64->routes))
+   return -EFAULT;
+
+   routes = compat_ptr(p);
+
+   if (!access_ok(VERIFY_READ, routes,
+  num_routes * sizeof(*p64->routes)))
+   return -EFAULT;
+
+   if (put_user((__force struct v4l2_subdev_route *)routes,
+&p64->routes))
+   return -EFAULT;
+
+   return 0;
+}
+
+static int put_v4l2_subdev_routing(struct v4l2_subdev_routing __user *p64,
+  struct v4l2_subdev_routing32 __user *p32)
+{
+   struct v4l2_subdev_route __user *routes;
+   compat_caddr_t p;
+   u32 num_routes;
+
+   if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+   get_user(p, &p32->routes) ||
+   get_user(num_routes, &p64->num_routes) ||
+   put_user(num_routes, &p32->num_routes) ||
+   copy_in_user(&p32->reserved, &p64->reserved,
+sizeof(p64->reserved)) ||
+   num_routes > U32_MAX / sizeof(*p64->routes))
+   return -EFAULT;
+
+   routes = compat_ptr(p);
+
+   if (!access_ok(VERIFY_WRITE, routes,
+  num_routes * sizeof(*p64->routes)))
+   return -EFAULT;
+
+   return 0;
+}
+
 struct v4l2_edid32 {
__u32 pad;
__u32 start_block;
@@ -1117,6 +1177,8 @@ static int put_v4l2_edid32(struct v4l2_edid __user *p64,
 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
 #define VIDIOC_G_INPUT32   _IOR ('V', 38, s32)
 #define VIDIOC_S_INPUT32   _IOWR('V', 39, s32)
+#define VIDIOC_SUBDEV_G_ROUTING32 _IOWR('V', 38, struct v4l2_subdev_routing32)
+#define VIDIOC_SUBDEV_S_ROUTING32 _IOWR('V', 39, struct v4l2_subdev_routing32)
 #define VIDIOC_G_OUTPUT32  _IOR ('V', 46, s32)
 #define VIDIOC_S_OUTPUT32  _IOWR('V', 47, s32)
 
@@ -1195,6 +1257,8 @@ static long do_video_ioctl(struct file *file, unsigned 
int cmd, unsigned long ar
case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
+   case VIDIOC_SUBDEV_G_ROUTING32: cmd = VIDIOC_SUBDEV_G_ROUTING; break;
+   case VIDIOC_SUBDEV_S_ROUTING32: cmd = VIDIOC_SUBDEV_S_ROUTING; break;
case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
@@ -1227,6 +1291,15 @@ static long do_video_ioctl(struct file *file, unsigned 
int cmd, unsigned long ar
compatible_arg = 0;
break;
 
+   case VIDIOC_SUBDEV_G_ROUTING:
+   case VIDIOC_SUBDEV_S_ROUTING:
+   err = alloc_userspace(sizeof(struct v4l2_subdev_routing),
+ 0, &new_p64);
+   if (!err)
+   err = get_v4l2_subdev_routing(new_p64, p32);
+   compatible_arg = 0;
+   break;
+
case VIDIOC_G_EDID:
case VIDIOC_S_EDID:
err = alloc_userspace(sizeof(struct v4l2_edid), 0, &new_p64);
@@ -1368,6 +1441,10 @@ static long do_video_ioctl(struct file *file, unsigned 
int cmd, unsigned long ar
if (put_v4l2_edid32(new_p64, p32))
err = -EFAULT;
break;
+   case VIDIOC_SUBDEV_G_ROUTING:
+   case VIDIOC_SUBDEV_S_ROUTING:
+   err = put_v4l2_subdev_routing(new_p64, p32);
+   break;
}
if (err)
return err;
-- 
2.19.1



[PATCH v2 18/30] v4l: subdev: Take routing information into account in link validation

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

The routing information is essential in link validation for multiplexed
links: the pads at the ends of a multiplexed link have no single format
defined for them. Instead, the format is accessible in the sink (or
source) pads of the sub-devices at both ends of that link.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/v4l2-core/v4l2-subdev.c | 217 --
 1 file changed, 203 insertions(+), 14 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index 1d3b37cf548fa533..05684c796b184272 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -640,12 +640,17 @@ static int
 v4l2_subdev_link_validate_get_format(struct media_pad *pad,
 struct v4l2_subdev_format *fmt)
 {
+   dev_dbg(pad->entity->graph_obj.mdev->dev,
+   "obtaining format on \"%s\":%u\n", pad->entity->name,
+   pad->index);
+
if (is_media_entity_v4l2_subdev(pad->entity)) {
struct v4l2_subdev *sd =
media_entity_to_v4l2_subdev(pad->entity);
 
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
fmt->pad = pad->index;
+
return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
}
 
@@ -656,31 +661,215 @@ v4l2_subdev_link_validate_get_format(struct media_pad 
*pad,
return -EINVAL;
 }
 
-int v4l2_subdev_link_validate(struct media_link *link)
+static int v4l2_subdev_link_validate_one(struct media_link *link,
+struct v4l2_subdev_format *source_fmt,
+struct v4l2_subdev_format *sink_fmt)
 {
struct v4l2_subdev *sink;
-   struct v4l2_subdev_format sink_fmt, source_fmt;
int rval;
 
-   rval = v4l2_subdev_link_validate_get_format(
-   link->source, &source_fmt);
-   if (rval < 0)
-   return 0;
-
-   rval = v4l2_subdev_link_validate_get_format(
-   link->sink, &sink_fmt);
-   if (rval < 0)
-   return 0;
-
sink = media_entity_to_v4l2_subdev(link->sink->entity);
 
rval = v4l2_subdev_call(sink, pad, link_validate, link,
-   &source_fmt, &sink_fmt);
+   source_fmt, sink_fmt);
if (rval != -ENOIOCTLCMD)
return rval;
 
return v4l2_subdev_link_validate_default(
-   sink, link, &source_fmt, &sink_fmt);
+   sink, link, source_fmt, sink_fmt);
+}
+
+/* How many routes to assume there can be per a sub-device? */
+#define LINK_VALIDATE_ROUTES   8
+
+#define R_SRC  0
+#define R_SINK 1
+#define NR_R   2
+
+int v4l2_subdev_link_validate(struct media_link *link)
+{
+   struct v4l2_subdev *sink;
+   struct route_info {
+   struct v4l2_subdev_route routes[LINK_VALIDATE_ROUTES];
+   struct v4l2_subdev_routing routing;
+   bool has_route;
+   struct media_pad *pad;
+   /* Format for a non-multiplexed pad. */
+   struct v4l2_subdev_format fmt;
+   } r[NR_R] = {
+   {
+   /* Source end of the link */
+   .routing = {
+   .routes = r[R_SRC].routes,
+   .num_routes = ARRAY_SIZE(r[R_SRC].routes),
+   },
+   .pad = link->source,
+   },
+   {
+   /* Sink end of the link */
+   .routing = {
+   .routes = r[R_SINK].routes,
+   .num_routes = ARRAY_SIZE(r[R_SINK].routes),
+   },
+   .pad = link->sink,
+   },
+   };
+   unsigned int i, j;
+   int rval;
+
+   sink = media_entity_to_v4l2_subdev(link->sink->entity);
+
+   dev_dbg(sink->entity.graph_obj.mdev->dev,
+   "validating link \"%s\":%u -> \"%s\":%u\n",
+   link->source->entity->name, link->source->index,
+   sink->entity.name, link->sink->index);
+
+   for (i = 0; i < NR_R; i++) {
+   struct route_info *ri = &r[i];
+
+   ri->has_route = true;
+
+   rval = v4l2_subdev_call(
+   media_entity_to_v4l2_subdev(ri->pad->entity),
+   pad, get_routing, &ri->routing);
+
+   switch (rval) {
+   case 0:
+   break;
+   case -ENOIOCTLCMD:
+   dev_dbg(sink->entity.graph_obj.mdev->dev,
+   "no routing information on \"%s\":%u\n",
+   ri->pad->entity->name, ri->pad->index);
+   ri->has_route = false;
+   break;
+   default:
+

[PATCH v2 21/30] v4l: Add bus type to frame descriptors

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 include/media/v4l2-subdev.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 5acaeeb9b3cacefa..ac1f7ee4cdb978ad 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -349,12 +349,21 @@ struct v4l2_mbus_frame_desc_entry {
 
 #define V4L2_FRAME_DESC_ENTRY_MAX  4
 
+enum {
+   V4L2_MBUS_FRAME_DESC_TYPE_PLATFORM,
+   V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL,
+   V4L2_MBUS_FRAME_DESC_TYPE_CCP2,
+   V4L2_MBUS_FRAME_DESC_TYPE_CSI2,
+};
+
 /**
  * struct v4l2_mbus_frame_desc - media bus data frame description
+ * @type: type of the bus (V4L2_MBUS_FRAME_DESC_TYPE_*)
  * @entry: frame descriptors array
  * @num_entries: number of entries in @entry array
  */
 struct v4l2_mbus_frame_desc {
+   u32 type;
struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
unsigned short num_entries;
 };
-- 
2.19.1



[PATCH v2 12/30] media: entity: Add an iterator helper for connected pads

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Add a helper macro for iterating over pads that are connected through
enabled routes. This can be used to find all the connected pads within an
entity, for instance starting from the pad which has been obtained during
the graph walk.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 include/media/media-entity.h | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 9540d2af80f19805..4bb1b568e1ac4795 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -936,6 +936,33 @@ __must_check int media_graph_walk_init(
 bool media_entity_has_route(struct media_entity *entity, unsigned int pad0,
unsigned int pad1);
 
+static inline struct media_pad *__media_entity_for_routed_pads_next(
+   struct media_pad *start, struct media_pad *iter)
+{
+   struct media_entity *entity = start->entity;
+
+   while (iter < &entity->pads[entity->num_pads] &&
+  !media_entity_has_route(entity, start->index, iter->index))
+   iter++;
+
+   return iter;
+}
+
+/**
+ * media_entity_for_routed_pads - Iterate over entity pads connected by routes
+ *
+ * @start: The stating pad
+ * @iter: The iterator pad
+ *
+ * Iterate over all pads connected through routes from a given pad
+ * within an entity. The iteration will include the starting pad itself.
+ */
+#define media_entity_for_routed_pads(start, iter)  \
+   for (iter = __media_entity_for_routed_pads_next(\
+start, (start)->entity->pads); \
+iter < &(start)->entity->pads[(start)->entity->num_pads];  \
+iter = __media_entity_for_routed_pads_next(start, iter + 1))
+
 /**
  * media_graph_walk_cleanup - Release resources used by graph walk.
  *
-- 
2.19.1



[PATCH v2 20/30] v4l: mc: Add an S_ROUTING helper function for power state changes

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

With the addition of the has_route() media entity operation, all pads of an
entity are no longer interconnected. The S_ROUTING IOCTL for sub-devices can
be used to enable and disable routes for an entity. The consequence is that
the routing information has to be taken into account in use count
calculation: disabling a route has a very similar effect on use counts as
has disabling a link.

Add a helper function for drivers implementing VIDIOC_SUBDEV_S_ROUTING
IOCTL to take the change into account.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/v4l2-core/v4l2-mc.c | 34 +++
 include/media/v4l2-mc.h   | 22 
 2 files changed, 56 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-mc.c 
b/drivers/media/v4l2-core/v4l2-mc.c
index 208cd91ce57ff211..534c5ea4fab42244 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -482,3 +482,37 @@ int v4l2_pipeline_link_notify(struct media_link *link, u32 
flags,
return ret;
 }
 EXPORT_SYMBOL_GPL(v4l2_pipeline_link_notify);
+
+int v4l2_subdev_routing_pm_use(struct media_entity *entity,
+  struct v4l2_subdev_route *route)
+{
+   struct media_graph *graph =
+   &entity->graph_obj.mdev->pm_count_walk;
+   struct media_pad *source = &entity->pads[route->source_pad];
+   struct media_pad *sink = &entity->pads[route->sink_pad];
+   int source_use;
+   int sink_use;
+   int ret;
+
+   source_use = pipeline_pm_use_count(source, graph);
+   sink_use = pipeline_pm_use_count(sink, graph);
+
+   if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
+   /* Route disabled. */
+   pipeline_pm_power(source, -sink_use, graph);
+   pipeline_pm_power(sink, -source_use, graph);
+   return 0;
+   }
+
+   /* Route enabled. */
+   ret = pipeline_pm_power(source, sink_use, graph);
+   if (ret < 0)
+   return ret;
+
+   ret = pipeline_pm_power(sink, source_use, graph);
+   if (ret < 0)
+   pipeline_pm_power(source, -sink_use, graph);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_routing_pm_use);
diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
index bf5043c1ab6b3a32..730922636579a5fe 100644
--- a/include/media/v4l2-mc.h
+++ b/include/media/v4l2-mc.h
@@ -26,6 +26,7 @@
 /* We don't need to include pci.h or usb.h here */
 struct pci_dev;
 struct usb_device;
+struct v4l2_subdev_route;
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 /**
@@ -132,6 +133,22 @@ int v4l2_pipeline_pm_use(struct media_entity *entity, int 
use);
 int v4l2_pipeline_link_notify(struct media_link *link, u32 flags,
  unsigned int notification);
 
+/**
+ * v4l2_subdev_routing_pm_use - Handle power state changes due to S_ROUTING
+ * @entity: The entity
+ * @route: The new state of the route
+ *
+ * Propagate the use count across a route in a pipeline whenever the
+ * route is enabled or disabled. The function is called before
+ * changing the route state when enabling a route, and after changing
+ * the route state when disabling a route.
+ *
+ * Return 0 on success or a negative error code on failure. Powering entities
+ * off is assumed to never fail. This function will not fail for disconnection
+ * events.
+ */
+int v4l2_subdev_routing_pm_use(struct media_entity *entity,
+  struct v4l2_subdev_route *route);
 #else /* CONFIG_MEDIA_CONTROLLER */
 
 static inline int v4l2_mc_create_media_graph(struct media_device *mdev)
@@ -164,5 +181,10 @@ static inline int v4l2_pipeline_link_notify(struct 
media_link *link, u32 flags,
return 0;
 }
 
+static inline int v4l2_subdev_routing_pm_use(struct media_entity *entity,
+struct v4l2_subdev_route *route)
+{
+   return 0;
+}
 #endif /* CONFIG_MEDIA_CONTROLLER */
 #endif /* _V4L2_MC_H */
-- 
2.19.1



[PATCH v2 26/30] adv748x: csi2: describe the multiplexed stream

2018-11-01 Thread Niklas Söderlund
The adv748x CSI-2 transmitter can only transmit one stream over the
CSI-2 link, however it can choose which virtual channel is used. This
choice effects the CSI-2 receiver and needs to be captured in the frame
descriptor information, solve this by implementing .get_frame_desc().

Signed-off-by: Niklas Söderlund 
---
 drivers/media/i2c/adv748x/adv748x-csi2.c | 31 +++-
 drivers/media/i2c/adv748x/adv748x.h  |  1 +
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c 
b/drivers/media/i2c/adv748x/adv748x-csi2.c
index 9f2c49221a8ddebc..d83ae8e5d802a3bd 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -222,9 +222,37 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
return ret;
 }
 
+static int adv748x_csi2_get_frame_desc(struct v4l2_subdev *sd, unsigned int 
pad,
+  struct v4l2_mbus_frame_desc *fd)
+{
+   struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
+   struct v4l2_mbus_framefmt *mbusformat;
+
+   memset(fd, 0, sizeof(*fd));
+
+   if (pad != ADV748X_CSI2_SOURCE)
+   return -EINVAL;
+
+   mbusformat = adv748x_csi2_get_pad_format(sd, NULL, ADV748X_CSI2_SINK,
+V4L2_SUBDEV_FORMAT_ACTIVE);
+   if (!mbusformat)
+   return -EINVAL;
+
+   fd->entry->stream = tx->vc;
+   fd->entry->bus.csi2.channel = tx->vc;
+   fd->entry->bus.csi2.data_type =
+   adv748x_csi2_code_to_datatype(mbusformat->code);
+
+   fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+   fd->num_entries = 1;
+
+   return 0;
+}
+
 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
.get_fmt = adv748x_csi2_get_format,
.set_fmt = adv748x_csi2_set_format,
+   .get_frame_desc = adv748x_csi2_get_frame_desc,
 };
 
 /* 
-
@@ -291,7 +319,8 @@ int adv748x_csi2_init(struct adv748x_state *state, struct 
adv748x_csi2 *tx)
return 0;
 
/* Initialise the virtual channel */
-   adv748x_csi2_set_virtual_channel(tx, 0);
+   tx->vc = 0;
+   adv748x_csi2_set_virtual_channel(tx, tx->vc);
 
adv748x_subdev_init(&tx->sd, state, &adv748x_csi2_ops,
MEDIA_ENT_F_VID_IF_BRIDGE,
diff --git a/drivers/media/i2c/adv748x/adv748x.h 
b/drivers/media/i2c/adv748x/adv748x.h
index 39c2fdc3b41667d8..b24e5ea1fe0f8c8d 100644
--- a/drivers/media/i2c/adv748x/adv748x.h
+++ b/drivers/media/i2c/adv748x/adv748x.h
@@ -76,6 +76,7 @@ enum adv748x_csi2_pads {
 
 struct adv748x_csi2 {
struct adv748x_state *state;
+   unsigned int vc;
struct v4l2_mbus_framefmt format;
unsigned int page;
unsigned int port;
-- 
2.19.1



[PATCH v2 30/30] rcar-csi2: expose the subdevice internal routing

2018-11-01 Thread Niklas Söderlund
Expose the subdevice internal routing from the single multiplexed sink
pad to its source pads by implementing .get_routing(). This information
is used to do link validation at stream start and allows user-space to
view the route configuration.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/platform/rcar-vin/rcar-csi2.c | 53 +
 1 file changed, 53 insertions(+)

diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c 
b/drivers/media/platform/rcar-vin/rcar-csi2.c
index 00564c969dd021db..f51b6fbc6042ac1d 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -342,6 +342,14 @@ static int rcsi2_pad_to_vc(unsigned int pad)
return pad - RCAR_CSI2_SOURCE_VC0;
 }
 
+static int rcsi2_vc_to_pad(unsigned int vc)
+{
+   if (vc > 3)
+   return -EINVAL;
+
+   return vc + RCAR_CSI2_SOURCE_VC0;
+}
+
 struct rcar_csi2_info {
int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps);
int (*confirm_start)(struct rcar_csi2 *priv);
@@ -705,9 +713,54 @@ static const struct v4l2_subdev_video_ops 
rcar_csi2_video_ops = {
.s_stream = rcsi2_s_stream,
 };
 
+static int rcsi2_get_routing(struct v4l2_subdev *sd,
+struct v4l2_subdev_routing *routing)
+{
+   struct rcar_csi2 *priv = sd_to_csi2(sd);
+   struct v4l2_mbus_frame_desc fd;
+   struct v4l2_subdev_route *r = routing->routes;
+   unsigned int i;
+   int ret;
+
+   /* Get information about multiplexed link */
+   ret = rcsi2_get_remote_frame_desc(priv, &fd);
+   if (ret)
+   return ret;
+
+   if (routing->num_routes < fd.num_entries) {
+   routing->num_routes = fd.num_entries;
+   return -ENOSPC;
+   }
+
+   routing->num_routes = fd.num_entries;
+
+   for (i = 0; i < fd.num_entries; i++) {
+   struct v4l2_mbus_frame_desc_entry *entry = &fd.entry[i];
+   int source_pad;
+
+   source_pad = rcsi2_vc_to_pad(entry->bus.csi2.channel);
+   if (source_pad < 0) {
+   dev_err(priv->dev, "Virtual Channel out of range: %u\n",
+   entry->bus.csi2.channel);
+   return -ENOSPC;
+   }
+
+   r->sink_pad = RCAR_CSI2_SINK;
+   r->sink_stream = entry->stream;
+   r->source_pad = source_pad;
+   r->source_stream = 0;
+   r->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE |
+   V4L2_SUBDEV_ROUTE_FL_IMMUTABLE;
+   r++;
+   }
+
+   return 0;
+}
+
 static const struct v4l2_subdev_pad_ops rcar_csi2_pad_ops = {
.set_fmt = rcsi2_set_pad_format,
.get_fmt = rcsi2_get_pad_format,
+   .get_routing = rcsi2_get_routing,
 };
 
 static const struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
-- 
2.19.1



[PATCH v2 24/30] adv748x: csi2: add translation from pixelcode to CSI-2 datatype

2018-11-01 Thread Niklas Söderlund
Prepare to implement frame descriptors to support multiplexed streams by
adding a function to map pixelcode to CSI-2 datatype. This is needed to
properly be able to fill out the struct v4l2_mbus_frame_desc.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/i2c/adv748x/adv748x-csi2.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c 
b/drivers/media/i2c/adv748x/adv748x-csi2.c
index 6ce21542ed485811..8a7cc713c7adfcc1 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -14,6 +14,28 @@
 
 #include "adv748x.h"
 
+struct adv748x_csi2_format {
+   unsigned int code;
+   unsigned int datatype;
+};
+
+static const struct adv748x_csi2_format adv748x_csi2_formats[] = {
+   { .code = MEDIA_BUS_FMT_RGB888_1X24,.datatype = 0x24, },
+   { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, },
+   { .code = MEDIA_BUS_FMT_UYVY8_2X8,  .datatype = 0x1e, },
+   { .code = MEDIA_BUS_FMT_YUYV10_2X10,.datatype = 0x1e, },
+};
+
+static unsigned int adv748x_csi2_code_to_datatype(unsigned int code)
+{
+   unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(adv748x_csi2_formats); i++)
+   if (adv748x_csi2_formats[i].code == code)
+   return adv748x_csi2_formats[i].datatype;
+   return 0;
+}
+
 static int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx,
unsigned int vc)
 {
-- 
2.19.1



[PATCH v2 13/30] media: entity: Add only connected pads to the pipeline

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

A single entity may contain multiple pipelines. Only add pads that were
connected to the pad through which the entity was reached to the pipeline.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 20 ++--
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index cdf3805dec755ec5..a5bb257d5a68f755 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -460,15 +460,13 @@ __must_check int __media_pipeline_start(struct media_pad 
*pad,
 
while ((pad = media_graph_walk_next(graph))) {
struct media_entity *entity = pad->entity;
-   unsigned int i;
+   struct media_pad *iter;
bool skip_validation = pad->pipe;
 
DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
 
-   for (i = 0; i < entity->num_pads; i++) {
-   struct media_pad *iter = &entity->pads[i];
-
+   media_entity_for_routed_pads(pad, iter) {
if (iter->pipe && WARN_ON(iter->pipe != pipe))
ret = -EBUSY;
else
@@ -553,12 +551,9 @@ __must_check int __media_pipeline_start(struct media_pad 
*pad,
media_graph_walk_start(graph, pad_err);
 
while ((pad_err = media_graph_walk_next(graph))) {
-   struct media_entity *entity_err = pad_err->entity;
-   unsigned int i;
-
-   for (i = 0; i < entity_err->num_pads; i++) {
-   struct media_pad *iter = &entity_err->pads[i];
+   struct media_pad *iter;
 
+   media_entity_for_routed_pads(pad_err, iter) {
/* Sanity check for negative stream_count */
if (!WARN_ON_ONCE(iter->stream_count <= 0)) {
--iter->stream_count;
@@ -611,12 +606,9 @@ void __media_pipeline_stop(struct media_pad *pad)
media_graph_walk_start(graph, pad);
 
while ((pad = media_graph_walk_next(graph))) {
-   struct media_entity *entity = pad->entity;
-   unsigned int i;
-
-   for (i = 0; i < entity->num_pads; i++) {
-   struct media_pad *iter = &entity->pads[i];
+   struct media_pad *iter;
 
+   media_entity_for_routed_pads(pad, iter) {
/* Sanity check for negative stream_count */
if (!WARN_ON_ONCE(iter->stream_count <= 0)) {
iter->stream_count--;
-- 
2.19.1



[PATCH v2 19/30] v4l: subdev: Improve link format validation debug messages

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

The existing link format validation failure debug message in media-entity.c
helped to poinpoint the point of failure but provided no additional
information what's wrong. Tell the user exactly why the validation failed.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/v4l2-core/v4l2-subdev.c | 40 ++-
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index 05684c796b184272..5c1459d3661e1de6 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -618,21 +618,47 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev 
*sd,
  struct v4l2_subdev_format *source_fmt,
  struct v4l2_subdev_format *sink_fmt)
 {
+   bool pass = true;
+
/* The width, height and code must match. */
-   if (source_fmt->format.width != sink_fmt->format.width
-   || source_fmt->format.height != sink_fmt->format.height
-   || source_fmt->format.code != sink_fmt->format.code)
-   return -EPIPE;
+   if (source_fmt->format.width != sink_fmt->format.width) {
+   dev_dbg(sd->entity.graph_obj.mdev->dev,
+   "%s: width does not match (source %u, sink %u)\n",
+   __func__,
+   source_fmt->format.width, sink_fmt->format.width);
+   pass = false;
+   }
+
+   if (source_fmt->format.height != sink_fmt->format.height) {
+   dev_dbg(sd->entity.graph_obj.mdev->dev,
+   "%s: height does not match (source %u, sink %u)\n",
+   __func__,
+   source_fmt->format.height, sink_fmt->format.height);
+   pass = false;
+   }
+
+   if (source_fmt->format.code != sink_fmt->format.code) {
+   dev_dbg(sd->entity.graph_obj.mdev->dev,
+   "%s: media bus code does not match (source 0x%8.8x, 
sink 0x%8.8x)\n",
+   __func__,
+   source_fmt->format.code, sink_fmt->format.code);
+   pass = false;
+   }
 
/* The field order must match, or the sink field order must be NONE
 * to support interlaced hardware connected to bridges that support
 * progressive formats only.
 */
if (source_fmt->format.field != sink_fmt->format.field &&
-   sink_fmt->format.field != V4L2_FIELD_NONE)
-   return -EPIPE;
+   sink_fmt->format.field != V4L2_FIELD_NONE) {
+   dev_dbg(sd->entity.graph_obj.mdev->dev,
+   "%s: field does not match (source %u, sink %u)\n",
+   __func__,
+   source_fmt->format.field, sink_fmt->format.field);
+   pass = false;
+   }
 
-   return 0;
+   return pass ? 0 : -EPIPE;
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
 
-- 
2.19.1



[PATCH v2 22/30] v4l: Add CSI-2 bus configuration to frame descriptors

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Add CSI-2 bus specific configuration to the frame descriptors. This allows
obtaining the virtual channel and data type information for each stream
the transmitter is sending.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 include/media/v4l2-subdev.h | 16 
 1 file changed, 16 insertions(+)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index ac1f7ee4cdb978ad..ffd98e4f368358a6 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -317,6 +317,17 @@ struct v4l2_subdev_audio_ops {
int (*s_stream)(struct v4l2_subdev *sd, int enable);
 };
 
+/**
+ * struct v4l2_mbus_frame_desc_entry_csi2
+ *
+ * @channel: CSI-2 virtual channel
+ * @data_type: CSI-2 data type ID
+ */
+struct v4l2_mbus_frame_desc_entry_csi2 {
+   u8 channel;
+   u8 data_type;
+};
+
 /**
  * enum v4l2_mbus_frame_desc_entry - media bus frame description flags
  *
@@ -340,11 +351,16 @@ enum v4l2_mbus_frame_desc_flags {
  * %FRAME_DESC_FL_BLOB is not set.
  * @length:number of octets per frame, valid if @flags
  * %V4L2_MBUS_FRAME_DESC_FL_LEN_MAX is set.
+ * @bus:   Bus specific frame descriptor parameters
+ * @bus.csi2:  CSI-2 specific bus configuration
  */
 struct v4l2_mbus_frame_desc_entry {
enum v4l2_mbus_frame_desc_flags flags;
u32 pixelcode;
u32 length;
+   union {
+   struct v4l2_mbus_frame_desc_entry_csi2 csi2;
+   } bus;
 };
 
 #define V4L2_FRAME_DESC_ENTRY_MAX  4
-- 
2.19.1



[PATCH v2 23/30] v4l: Add stream to frame descriptor

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

The stream field identifies the stream this frame descriptor applies to in
routing configuration across a multiplexed link.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 include/media/v4l2-subdev.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index ffd98e4f368358a6..5fbce1932107a990 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -347,6 +347,7 @@ enum v4l2_mbus_frame_desc_flags {
  * struct v4l2_mbus_frame_desc_entry - media bus frame description structure
  *
  * @flags: bitmask flags, as defined by &enum v4l2_mbus_frame_desc_flags.
+ * @stream:stream in routing configuration
  * @pixelcode: media bus pixel code, valid if @flags
  * %FRAME_DESC_FL_BLOB is not set.
  * @length:number of octets per frame, valid if @flags
@@ -356,6 +357,7 @@ enum v4l2_mbus_frame_desc_flags {
  */
 struct v4l2_mbus_frame_desc_entry {
enum v4l2_mbus_frame_desc_flags flags;
+   u32 stream;
u32 pixelcode;
u32 length;
union {
-- 
2.19.1



[PATCH v2 29/30] rcar-csi2: use frame description information to configure CSI-2 bus

2018-11-01 Thread Niklas Söderlund
The driver can now access frame descriptor information, use it when
configuring the CSI-2 bus. Only enable the virtual channels which are
described in the frame descriptor and calculate the link based on all
enabled streams.

With multiplexed stream supported it's now meaningful to have different
formats on the different source pads. Make source formats independent
off each other and disallowing a format on the multiplexed sink pad.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/platform/rcar-vin/rcar-csi2.c | 135 ++--
 1 file changed, 98 insertions(+), 37 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c 
b/drivers/media/platform/rcar-vin/rcar-csi2.c
index b0044a08e71ed017..00564c969dd021db 100644
--- a/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ b/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -304,25 +304,22 @@ static const struct rcsi2_mbps_reg 
hsfreqrange_m3w_h3es1[] = {
 #define CSI0CLKFREQRANGE(n)((n & 0x3f) << 16)
 
 struct rcar_csi2_format {
-   u32 code;
unsigned int datatype;
unsigned int bpp;
 };
 
 static const struct rcar_csi2_format rcar_csi2_formats[] = {
-   { .code = MEDIA_BUS_FMT_RGB888_1X24,.datatype = 0x24, .bpp = 24 },
-   { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, .bpp = 16 },
-   { .code = MEDIA_BUS_FMT_YUYV8_1X16, .datatype = 0x1e, .bpp = 16 },
-   { .code = MEDIA_BUS_FMT_UYVY8_2X8,  .datatype = 0x1e, .bpp = 16 },
-   { .code = MEDIA_BUS_FMT_YUYV10_2X10,.datatype = 0x1e, .bpp = 20 },
+   { .datatype = 0x1e, .bpp = 16 },
+   { .datatype = 0x24, .bpp = 24 },
 };
 
-static const struct rcar_csi2_format *rcsi2_code_to_fmt(unsigned int code)
+static const struct rcar_csi2_format
+*rcsi2_datatype_to_fmt(unsigned int datatype)
 {
unsigned int i;
 
for (i = 0; i < ARRAY_SIZE(rcar_csi2_formats); i++)
-   if (rcar_csi2_formats[i].code == code)
+   if (rcar_csi2_formats[i].datatype == datatype)
return &rcar_csi2_formats[i];
 
return NULL;
@@ -337,6 +334,14 @@ enum rcar_csi2_pads {
NR_OF_RCAR_CSI2_PAD,
 };
 
+static int rcsi2_pad_to_vc(unsigned int pad)
+{
+   if (pad < RCAR_CSI2_SOURCE_VC0 || pad > RCAR_CSI2_SOURCE_VC3)
+   return -EINVAL;
+
+   return pad - RCAR_CSI2_SOURCE_VC0;
+}
+
 struct rcar_csi2_info {
int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps);
int (*confirm_start)(struct rcar_csi2 *priv);
@@ -357,7 +362,7 @@ struct rcar_csi2 {
struct v4l2_async_subdev asd;
struct v4l2_subdev *remote;
 
-   struct v4l2_mbus_framefmt mf;
+   struct v4l2_mbus_framefmt mf[4];
 
struct mutex lock;
int stream_count;
@@ -393,6 +398,32 @@ static void rcsi2_reset(struct rcar_csi2 *priv)
rcsi2_write(priv, SRST_REG, 0);
 }
 
+static int rcsi2_get_remote_frame_desc(struct rcar_csi2 *priv,
+  struct v4l2_mbus_frame_desc *fd)
+{
+   struct media_pad *pad;
+   int ret;
+
+   if (!priv->remote)
+   return -ENODEV;
+
+   pad = media_entity_remote_pad(&priv->pads[RCAR_CSI2_SINK]);
+   if (!pad)
+   return -ENODEV;
+
+   ret = v4l2_subdev_call(priv->remote, pad, get_frame_desc,
+  pad->index, fd);
+   if (ret)
+   return -ENODEV;
+
+   if (fd->type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
+   dev_err(priv->dev, "Frame desc do not describe CSI-2 link");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static int rcsi2_wait_phy_start(struct rcar_csi2 *priv)
 {
unsigned int timeout;
@@ -431,10 +462,12 @@ static int rcsi2_set_phypll(struct rcar_csi2 *priv, 
unsigned int mbps)
return 0;
 }
 
-static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp)
+static int rcsi2_calc_mbps(struct rcar_csi2 *priv,
+  struct v4l2_mbus_frame_desc *fd)
 {
struct v4l2_subdev *source;
struct v4l2_ctrl *ctrl;
+   unsigned int i, bpp = 0;
u64 mbps;
 
if (!priv->remote)
@@ -450,6 +483,21 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, 
unsigned int bpp)
return -EINVAL;
}
 
+   /* Calculate total bpp */
+   for (i = 0; i < fd->num_entries; i++) {
+   const struct rcar_csi2_format *format;
+
+   format = rcsi2_datatype_to_fmt(
+   fd->entry[i].bus.csi2.data_type);
+   if (!format) {
+   dev_err(priv->dev, "Unknown data type: %d\n",
+   fd->entry[i].bus.csi2.data_type);
+   return -EINVAL;
+   }
+
+   bpp += format->bpp;
+   }
+
/*
 * Calculate the phypll in mbps.
 * link_freq = (pixel_rate * bits_per_sample) / (2 * nr_of_lanes)
@@ -463,42 +511,40 @@ static int rcsi2_

[PATCH v2 11/30] media: entity: Skip link validation for pads to which there is no route to

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Links are validated along the pipeline which is about to start streaming.
Not all the pads in entities that are traversed along that pipeline are
part of the pipeline, however. Skip the link validation for such pads.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 4d10bc186e1e7a10..cdf3805dec755ec5 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -493,6 +493,11 @@ __must_check int __media_pipeline_start(struct media_pad 
*pad,
struct media_pad *other_pad = link->sink->entity == 
entity
? link->sink : link->source;
 
+   /* Ignore pads to which there is no route. */
+   if (!media_entity_has_route(entity, pad->index,
+   other_pad->index))
+   continue;
+
/* Mark that a pad is connected by a link. */
bitmap_clear(has_no_links, other_pad->index, 1);
 
-- 
2.19.1



[PATCH v2 09/30] media: entity: Swap pads if route is checked from source to sink

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

This way the pads are always passed to the has_route() op sink pad first.
Makes sense.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 3c0e7425c8983b45..33f00e35ccd92c6f 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -249,6 +249,10 @@ bool media_entity_has_route(struct media_entity *entity, 
unsigned int pad0,
if (!entity->ops || !entity->ops->has_route)
return true;
 
+   if (entity->pads[pad0].flags & MEDIA_PAD_FL_SOURCE
+   && entity->pads[pad1].flags & MEDIA_PAD_FL_SINK)
+   swap(pad0, pad1);
+
return entity->ops->has_route(entity, pad0, pad1);
 }
 EXPORT_SYMBOL_GPL(media_entity_has_route);
-- 
2.19.1



[PATCH v2 25/30] adv748x: csi2: only allow formats on sink pads

2018-11-01 Thread Niklas Söderlund
Once the CSI-2 subdevice of the ADV748X becomes aware of multiplexed
streams the format of the source pad is of no value as it carries
multiple streams. Prepare for this by explicitly denying setting a
format on anything but the sink pad.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/i2c/adv748x/adv748x-csi2.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c 
b/drivers/media/i2c/adv748x/adv748x-csi2.c
index 8a7cc713c7adfcc1..9f2c49221a8ddebc 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -163,6 +163,9 @@ static int adv748x_csi2_get_format(struct v4l2_subdev *sd,
struct adv748x_state *state = tx->state;
struct v4l2_mbus_framefmt *mbusformat;
 
+   if (sdformat->pad != ADV748X_CSI2_SINK)
+   return -EINVAL;
+
mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad,
 sdformat->which);
if (!mbusformat)
@@ -186,6 +189,9 @@ static int adv748x_csi2_set_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mbusformat;
int ret = 0;
 
+   if (sdformat->pad != ADV748X_CSI2_SINK)
+   return -EINVAL;
+
mbusformat = adv748x_csi2_get_pad_format(sd, cfg, sdformat->pad,
 sdformat->which);
if (!mbusformat)
-- 
2.19.1



[PATCH v2 27/30] adv748x: csi2: add internal routing configuration

2018-11-01 Thread Niklas Söderlund
Add support to get and set the internal routing between the adv748x
CSI-2 transmitters sink pad and its multiplexed source pad. This routing
includes which stream of the multiplexed pad to use, allowing the user
to select which CSI-2 virtual channel to use when transmitting the
stream.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/i2c/adv748x/adv748x-csi2.c | 65 
 1 file changed, 65 insertions(+)

diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c 
b/drivers/media/i2c/adv748x/adv748x-csi2.c
index d83ae8e5d802a3bd..ef588567313574c7 100644
--- a/drivers/media/i2c/adv748x/adv748x-csi2.c
+++ b/drivers/media/i2c/adv748x/adv748x-csi2.c
@@ -14,6 +14,8 @@
 
 #include "adv748x.h"
 
+#define ADV748X_CSI2_ROUTES_MAX 4
+
 struct adv748x_csi2_format {
unsigned int code;
unsigned int datatype;
@@ -249,10 +251,73 @@ static int adv748x_csi2_get_frame_desc(struct v4l2_subdev 
*sd, unsigned int pad,
return 0;
 }
 
+static int adv748x_csi2_get_routing(struct v4l2_subdev *sd,
+   struct v4l2_subdev_routing *routing)
+{
+   struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
+   struct v4l2_subdev_route *r = routing->routes;
+   unsigned int vc;
+
+   if (routing->num_routes < ADV748X_CSI2_ROUTES_MAX) {
+   routing->num_routes = ADV748X_CSI2_ROUTES_MAX;
+   return -ENOSPC;
+   }
+
+   routing->num_routes = ADV748X_CSI2_ROUTES_MAX;
+
+   for (vc = 0; vc < ADV748X_CSI2_ROUTES_MAX; vc++) {
+   r->sink_pad = ADV748X_CSI2_SINK;
+   r->sink_stream = 0;
+   r->source_pad = ADV748X_CSI2_SOURCE;
+   r->source_stream = vc;
+   r->flags = vc == tx->vc ? V4L2_SUBDEV_ROUTE_FL_ACTIVE : 0;
+   r++;
+   }
+
+   return 0;
+}
+
+static int adv748x_csi2_set_routing(struct v4l2_subdev *sd,
+   struct v4l2_subdev_routing *routing)
+{
+   struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd);
+   struct v4l2_subdev_route *r = routing->routes;
+   unsigned int i;
+   int vc = -1;
+
+   if (routing->num_routes > ADV748X_CSI2_ROUTES_MAX)
+   return -ENOSPC;
+
+   for (i = 0; i < routing->num_routes; i++) {
+   if (r->sink_pad != ADV748X_CSI2_SINK ||
+   r->sink_stream != 0 ||
+   r->source_pad != ADV748X_CSI2_SOURCE ||
+   r->source_stream >= ADV748X_CSI2_ROUTES_MAX)
+   return -EINVAL;
+
+   if (r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) {
+   if (vc != -1)
+   return -EMLINK;
+
+   vc = r->source_stream;
+   }
+   r++;
+   }
+
+   if (vc != -1)
+   tx->vc = vc;
+
+   adv748x_csi2_set_virtual_channel(tx, tx->vc);
+
+   return 0;
+}
+
 static const struct v4l2_subdev_pad_ops adv748x_csi2_pad_ops = {
.get_fmt = adv748x_csi2_get_format,
.set_fmt = adv748x_csi2_set_format,
.get_frame_desc = adv748x_csi2_get_frame_desc,
+   .get_routing = adv748x_csi2_get_routing,
+   .set_routing = adv748x_csi2_set_routing,
 };
 
 /* 
-
-- 
2.19.1



[PATCH v2 28/30] adv748x: afe: add routing support

2018-11-01 Thread Niklas Söderlund
The adv748x afe has eight analog sink pads, currently one of them is
chosen to be the active route based on device tree configuration. With
the new routing API it's possible to expose and change which of the
eight sink pads are routed to the source pad.

Signed-off-by: Niklas Söderlund 
---
 drivers/media/i2c/adv748x/adv748x-afe.c | 65 +
 1 file changed, 65 insertions(+)

diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c 
b/drivers/media/i2c/adv748x/adv748x-afe.c
index 71714634efb08bd4..6b7fd4685aa4c177 100644
--- a/drivers/media/i2c/adv748x/adv748x-afe.c
+++ b/drivers/media/i2c/adv748x/adv748x-afe.c
@@ -39,6 +39,9 @@
 #define ADV748X_AFE_STD_PAL_SECAM  0xe
 #define ADV748X_AFE_STD_PAL_SECAM_PED  0xf
 
+#define ADV748X_AFE_ROUTES_MAX ((ADV748X_AFE_SINK_AIN7 - \
+   ADV748X_AFE_SINK_AIN0) + 1)
+
 static int adv748x_afe_read_ro_map(struct adv748x_state *state, u8 reg)
 {
int ret;
@@ -383,10 +386,72 @@ static int adv748x_afe_set_format(struct v4l2_subdev *sd,
return 0;
 }
 
+static int adv748x_afe_get_routing(struct v4l2_subdev *sd,
+  struct v4l2_subdev_routing *routing)
+{
+   struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
+   struct v4l2_subdev_route *r = routing->routes;
+   unsigned int i;
+
+   /* There is one possible route from each sink */
+   if (routing->num_routes < ADV748X_AFE_ROUTES_MAX) {
+   routing->num_routes = ADV748X_AFE_ROUTES_MAX;
+   return -ENOSPC;
+   }
+
+   routing->num_routes = ADV748X_AFE_ROUTES_MAX;
+
+   for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++) {
+   r->sink_pad = i;
+   r->sink_stream = 0;
+   r->source_pad = ADV748X_AFE_SOURCE;
+   r->source_stream = 0;
+   r->flags = afe->input == i ? V4L2_SUBDEV_ROUTE_FL_ACTIVE : 0;
+   r++;
+   }
+
+   return 0;
+}
+
+static int adv748x_afe_set_routing(struct v4l2_subdev *sd,
+  struct v4l2_subdev_routing *routing)
+{
+   struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
+   struct v4l2_subdev_route *r = routing->routes;
+   int input = -1;
+   unsigned int i;
+
+   if (routing->num_routes > ADV748X_AFE_ROUTES_MAX)
+   return -ENOSPC;
+
+   for (i = 0; i < routing->num_routes; i++) {
+   if (r->sink_pad > ADV748X_AFE_SINK_AIN7 ||
+   r->sink_stream != 0 ||
+   r->source_pad != ADV748X_AFE_SOURCE ||
+   r->source_stream != 0)
+   return -EINVAL;
+
+   if (r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) {
+   if (input != -1)
+   return -EMLINK;
+
+   input = r->sink_pad;
+   }
+   r++;
+   }
+
+   if (input != -1)
+   afe->input = input;
+
+   return 0;
+}
+
 static const struct v4l2_subdev_pad_ops adv748x_afe_pad_ops = {
.enum_mbus_code = adv748x_afe_enum_mbus_code,
.set_fmt = adv748x_afe_set_format,
.get_fmt = adv748x_afe_get_format,
+   .get_routing = adv748x_afe_get_routing,
+   .set_routing = adv748x_afe_set_routing,
 };
 
 /* 
-
-- 
2.19.1



[PATCH v2 07/30] media: entity: Add has_route entity operation

2018-11-01 Thread Niklas Söderlund
From: Laurent Pinchart 

The optional operation can be used by entities to report whether two
pads are internally connected.

Signed-off-by: Laurent Pinchart 
Signed-off-by: Michal Simek 
Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 include/media/media-entity.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index 8378f700389635ea..cd482814654616b5 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -223,6 +223,9 @@ struct media_pad {
  * @link_validate: Return whether a link is valid from the entity point of
  * view. The media_pipeline_start() function
  * validates all links by calling this operation. Optional.
+ * @has_route: Return whether a route exists inside the entity between
+ * two given pads. Optional. If the operation isn't
+ * implemented all pads will be considered as connected.
  *
  * .. note::
  *
@@ -235,6 +238,8 @@ struct media_entity_operations {
  const struct media_pad *local,
  const struct media_pad *remote, u32 flags);
int (*link_validate)(struct media_link *link);
+   bool (*has_route)(struct media_entity *entity, unsigned int pad0,
+ unsigned int pad1);
 };
 
 /**
-- 
2.19.1



[PATCH v2 10/30] media: entity: Use routing information during graph traversal

2018-11-01 Thread Niklas Söderlund
From: Laurent Pinchart 

Take internal routing information as reported by the entity has_route
operation into account during graph traversal to avoid following
unrelated links.

Signed-off-by: Laurent Pinchart 
Signed-off-by: Michal Simek 
Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 44 ++--
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 33f00e35ccd92c6f..4d10bc186e1e7a10 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -257,15 +257,6 @@ bool media_entity_has_route(struct media_entity *entity, 
unsigned int pad0,
 }
 EXPORT_SYMBOL_GPL(media_entity_has_route);
 
-static struct media_pad *
-media_entity_other(struct media_pad *pad, struct media_link *link)
-{
-   if (link->source == pad)
-   return link->sink;
-   else
-   return link->source;
-}
-
 /* push an entity to traversal stack */
 static void stack_push(struct media_graph *graph, struct media_pad *pad)
 {
@@ -336,7 +327,8 @@ static void media_graph_walk_iter(struct media_graph *graph)
 {
struct media_pad *pad = stack_top(graph);
struct media_link *link;
-   struct media_pad *next;
+   struct media_pad *remote;
+   struct media_pad *local;
 
link = list_entry(link_top(graph), typeof(*link), list);
 
@@ -350,23 +342,41 @@ static void media_graph_walk_iter(struct media_graph 
*graph)
return;
}
 
-   /* Get the entity in the other end of the link . */
-   next = media_entity_other(pad, link);
+   /*
+* Get the local pad, the remote pad and the entity at the other
+* end of the link.
+*/
+   if (link->source->entity == pad->entity) {
+   remote = link->sink;
+   local = link->source;
+   } else {
+   remote = link->source;
+   local = link->sink;
+   }
+
+   /*
+* Are the local pad and the pad we came from connected
+* internally in the entity ?
+*/
+   if (!media_entity_has_route(pad->entity, pad->index, local->index)) {
+   link_top(graph) = link_top(graph)->next;
+   return;
+   }
 
/* Has the entity already been visited? */
-   if (media_entity_enum_test_and_set(&graph->ent_enum, next->entity)) {
+   if (media_entity_enum_test_and_set(&graph->ent_enum, remote->entity)) {
link_top(graph) = link_top(graph)->next;
dev_dbg(pad->graph_obj.mdev->dev,
"walk: skipping entity '%s' (already seen)\n",
-   next->entity->name);
+   remote->entity->name);
return;
}
 
/* Push the new entity to stack and start over. */
link_top(graph) = link_top(graph)->next;
-   stack_push(graph, next);
-   dev_dbg(next->graph_obj.mdev->dev, "walk: pushing '%s':%u on stack\n",
-   next->entity->name, next->index);
+   stack_push(graph, remote);
+   dev_dbg(remote->graph_obj.mdev->dev, "walk: pushing '%s':%u on stack\n",
+   remote->entity->name, remote->index);
 }
 
 struct media_pad *media_graph_walk_next(struct media_graph *graph)
-- 
2.19.1



[PATCH v2 05/30] media: entity: Move the pipeline from entity to pads

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

This moves the pipe and stream_count fields from struct media_entity to
struct media_pad. Effectively streams become pad-specific rather than
being stream specific, allowing several independent streams to traverse a
single entity.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c  | 61 ---
 drivers/media/platform/exynos4-is/fimc-isp.c  |  2 +-
 drivers/media/platform/exynos4-is/fimc-lite.c |  2 +-
 drivers/media/platform/omap3isp/isp.c |  2 +-
 drivers/media/platform/omap3isp/ispvideo.c|  2 +-
 drivers/media/platform/omap3isp/ispvideo.h|  2 +-
 drivers/media/platform/rcar-vin/rcar-dma.c|  2 +-
 drivers/media/platform/xilinx/xilinx-dma.c|  2 +-
 drivers/media/platform/xilinx/xilinx-dma.h|  2 +-
 drivers/staging/media/imx/imx-media-utils.c   |  2 +-
 drivers/staging/media/omap4iss/iss.c  |  2 +-
 drivers/staging/media/omap4iss/iss_video.c|  2 +-
 drivers/staging/media/omap4iss/iss_video.h|  2 +-
 include/media/media-entity.h  | 17 --
 14 files changed, 61 insertions(+), 41 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 70db03fa33a21db1..13260149c4dfc90c 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -419,7 +419,7 @@ __must_check int __media_pipeline_start(struct media_entity 
*entity,
struct media_pad *pad = entity->pads;
struct media_pad *pad_err = pad;
struct media_link *link;
-   int ret;
+   int ret = 0;
 
if (!pipe->streaming_count++) {
ret = media_graph_walk_init(&pipe->graph, mdev);
@@ -431,21 +431,27 @@ __must_check int __media_pipeline_start(struct 
media_entity *entity,
 
while ((pad = media_graph_walk_next(graph))) {
struct media_entity *entity = pad->entity;
+   unsigned int i;
+   bool skip_validation = pad->pipe;
 
DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
 
-   entity->stream_count++;
+   for (i = 0; i < entity->num_pads; i++) {
+   struct media_pad *iter = &entity->pads[i];
 
-   if (WARN_ON(entity->pipe && entity->pipe != pipe)) {
-   ret = -EBUSY;
-   goto error;
+   if (iter->pipe && WARN_ON(iter->pipe != pipe))
+   ret = -EBUSY;
+   else
+   iter->pipe = pipe;
+   iter->stream_count++;
}
 
-   entity->pipe = pipe;
+   if (ret)
+   goto error;
 
/* Already streaming --- no need to check. */
-   if (entity->stream_count > 1)
+   if (skip_validation)
continue;
 
if (!entity->ops || !entity->ops->link_validate)
@@ -514,19 +520,24 @@ __must_check int __media_pipeline_start(struct 
media_entity *entity,
 
while ((pad_err = media_graph_walk_next(graph))) {
struct media_entity *entity_err = pad_err->entity;
+   unsigned int i;
+
+   for (i = 0; i < entity_err->num_pads; i++) {
+   struct media_pad *iter = &entity_err->pads[i];
 
-   /* Sanity check for negative stream_count */
-   if (!WARN_ON_ONCE(entity_err->stream_count <= 0)) {
-   entity_err->stream_count--;
-   if (entity_err->stream_count == 0)
-   entity_err->pipe = NULL;
+   /* Sanity check for negative stream_count */
+   if (!WARN_ON_ONCE(iter->stream_count <= 0)) {
+   --iter->stream_count;
+   if (iter->stream_count == 0)
+   iter->pipe = NULL;
+   }
}
 
/*
 * We haven't increased stream_count further than this
 * so we quit here.
 */
-   if (pad_err == pad)
+   if (pad_err->entity == pad->entity)
break;
}
 
@@ -553,7 +564,7 @@ EXPORT_SYMBOL_GPL(media_pipeline_start);
 
 void __media_pipeline_stop(struct media_entity *entity)
 {
-   struct media_pipeline *pipe = entity->pipe;
+   struct media_pipeline *pipe = entity->pads->pipe;
struct media_graph *graph = &pipe->graph;
struct media_pad *pad;
 
@@ -567,13 +578,17 @@ void __media_pipeline_stop(struct media_entity *entity)
media_graph_walk_start(graph, entity->pads);
 
while ((pad = media_graph_walk_next(graph))) {
-   struct media_entity *entity = pad->entity;
+   unsigned int i;
 
-   /* Sanity che

[PATCH v2 06/30] media: entity: Use pad as the starting point for a pipeline

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

The pipeline will be moved from the entity to the pads; reflect this in
the media pipeline function API.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 Documentation/media/kapi/mc-core.rst  |  6 ++--
 drivers/media/media-entity.c  | 25 +++---
 drivers/media/pci/intel/ipu3/ipu3-cio2.c  |  6 ++--
 .../media/platform/exynos4-is/fimc-capture.c  |  8 ++---
 .../platform/exynos4-is/fimc-isp-video.c  |  8 ++---
 drivers/media/platform/exynos4-is/fimc-lite.c |  8 ++---
 drivers/media/platform/omap3isp/ispvideo.c|  6 ++--
 .../media/platform/qcom/camss/camss-video.c   |  6 ++--
 drivers/media/platform/rcar-vin/rcar-dma.c|  6 ++--
 .../media/platform/s3c-camif/camif-capture.c  |  6 ++--
 drivers/media/platform/vimc/vimc-capture.c|  6 ++--
 drivers/media/platform/vsp1/vsp1_video.c  |  6 ++--
 drivers/media/platform/xilinx/xilinx-dma.c|  6 ++--
 drivers/media/usb/au0828/au0828-core.c|  4 +--
 drivers/staging/media/imx/imx-media-utils.c   |  6 ++--
 drivers/staging/media/omap4iss/iss_video.c|  6 ++--
 include/media/media-entity.h  | 33 ++-
 17 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/Documentation/media/kapi/mc-core.rst 
b/Documentation/media/kapi/mc-core.rst
index 849b87439b7a9772..ede7e946f6a82ac0 100644
--- a/Documentation/media/kapi/mc-core.rst
+++ b/Documentation/media/kapi/mc-core.rst
@@ -211,11 +211,11 @@ When starting streaming, drivers must notify all entities 
in the pipeline to
 prevent link states from being modified during streaming by calling
 :c:func:`media_pipeline_start()`.
 
-The function will mark all entities connected to the given entity through
-enabled links, either directly or indirectly, as streaming.
+The function will mark all entities connected to the given pad through
+enabled routes and links, either directly or indirectly, as streaming.
 
 The struct :c:type:`media_pipeline` instance pointed to by
-the pipe argument will be stored in every entity in the pipeline.
+the pipe argument will be stored in every pad in the pipeline.
 Drivers should embed the struct :c:type:`media_pipeline`
 in higher-level pipeline structures and can then access the
 pipeline through the struct :c:type:`media_entity`
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 13260149c4dfc90c..f2fa0b7826dbc2f3 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -411,12 +411,11 @@ EXPORT_SYMBOL_GPL(media_entity_get_fwnode_pad);
  * Pipeline management
  */
 
-__must_check int __media_pipeline_start(struct media_entity *entity,
+__must_check int __media_pipeline_start(struct media_pad *pad,
struct media_pipeline *pipe)
 {
-   struct media_device *mdev = entity->graph_obj.mdev;
+   struct media_device *mdev = pad->graph_obj.mdev;
struct media_graph *graph = &pipe->graph;
-   struct media_pad *pad = entity->pads;
struct media_pad *pad_err = pad;
struct media_link *link;
int ret = 0;
@@ -549,24 +548,23 @@ __must_check int __media_pipeline_start(struct 
media_entity *entity,
 }
 EXPORT_SYMBOL_GPL(__media_pipeline_start);
 
-__must_check int media_pipeline_start(struct media_entity *entity,
+__must_check int media_pipeline_start(struct media_pad *pad,
  struct media_pipeline *pipe)
 {
-   struct media_device *mdev = entity->graph_obj.mdev;
+   struct media_device *mdev = pad->graph_obj.mdev;
int ret;
 
mutex_lock(&mdev->graph_mutex);
-   ret = __media_pipeline_start(entity, pipe);
+   ret = __media_pipeline_start(pad, pipe);
mutex_unlock(&mdev->graph_mutex);
return ret;
 }
 EXPORT_SYMBOL_GPL(media_pipeline_start);
 
-void __media_pipeline_stop(struct media_entity *entity)
+void __media_pipeline_stop(struct media_pad *pad)
 {
-   struct media_pipeline *pipe = entity->pads->pipe;
+   struct media_pipeline *pipe = pad->pipe;
struct media_graph *graph = &pipe->graph;
-   struct media_pad *pad;
 
/*
 * If the following check fails, the driver has performed an
@@ -575,9 +573,10 @@ void __media_pipeline_stop(struct media_entity *entity)
if (WARN_ON(!pipe))
return;
 
-   media_graph_walk_start(graph, entity->pads);
+   media_graph_walk_start(graph, pad);
 
while ((pad = media_graph_walk_next(graph))) {
+   struct media_entity *entity = pad->entity;
unsigned int i;
 
for (i = 0; i < entity->num_pads; i++) {
@@ -598,12 +597,12 @@ void __media_pipeline_stop(struct media_entity *entity)
 }
 EXPORT_SYMBOL_GPL(__media_pipeline_stop);
 
-void media_pipeline_stop(struct media_entity *entity)
+void media_pipeline_stop(struct media_pad *pad)
 {
-   struct media_device *mdev = entity->graph_obj.mdev;
+   struct media_device *mdev = pad->g

[PATCH v2 16/30] v4l: subdev: Add [GS]_ROUTING subdev ioctls and operations

2018-11-01 Thread Niklas Söderlund
From: Laurent Pinchart 

Signed-off-by: Laurent Pinchart 
Signed-off-by: Michal Simek 

- Add sink and source streams for multiplexed links
- Copy the argument back in case of an error. This is needed to let the
  caller know the number of routes.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/v4l2-core/v4l2-ioctl.c  | 20 +-
 drivers/media/v4l2-core/v4l2-subdev.c | 28 +++
 include/media/v4l2-subdev.h   |  7 +
 include/uapi/linux/v4l2-subdev.h  | 40 +++
 4 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 7de041bae84fb2f2..40406acb51ec0906 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #include 
@@ -2924,6 +2925,23 @@ static int check_array_args(unsigned int cmd, void 
*parg, size_t *array_size,
}
break;
}
+
+   case VIDIOC_SUBDEV_G_ROUTING:
+   case VIDIOC_SUBDEV_S_ROUTING: {
+   struct v4l2_subdev_routing *route = parg;
+
+   if (route->num_routes > 0) {
+   if (route->num_routes > 256)
+   return -EINVAL;
+
+   *user_ptr = (void __user *)route->routes;
+   *kernel_ptr = (void *)&route->routes;
+   *array_size = sizeof(struct v4l2_subdev_route)
+   * route->num_routes;
+   ret = 1;
+   }
+   break;
+   }
}
 
return ret;
@@ -3033,7 +3051,7 @@ video_usercopy(struct file *file, unsigned int cmd, 
unsigned long arg,
 * Some ioctls can return an error, but still have valid
 * results that must be returned.
 */
-   if (err < 0 && !always_copy)
+   if (err < 0 && !always_copy && cmd != VIDIOC_SUBDEV_G_ROUTING)
goto out;
 
 out_array_args:
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index 792f41dffe2329b9..1d3b37cf548fa533 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -516,7 +516,35 @@ static long subdev_do_ioctl(struct file *file, unsigned 
int cmd, void *arg)
 
case VIDIOC_SUBDEV_QUERYSTD:
return v4l2_subdev_call(sd, video, querystd, arg);
+
+   case VIDIOC_SUBDEV_G_ROUTING:
+   return v4l2_subdev_call(sd, pad, get_routing, arg);
+
+   case VIDIOC_SUBDEV_S_ROUTING: {
+   struct v4l2_subdev_routing *route = arg;
+   unsigned int i;
+
+   if (route->num_routes > sd->entity.num_pads)
+   return -EINVAL;
+
+   for (i = 0; i < route->num_routes; ++i) {
+   unsigned int sink = route->routes[i].sink_pad;
+   unsigned int source = route->routes[i].source_pad;
+   struct media_pad *pads = sd->entity.pads;
+
+   if (sink >= sd->entity.num_pads ||
+   source >= sd->entity.num_pads)
+   return -EINVAL;
+
+   if (!(pads[sink].flags & MEDIA_PAD_FL_SINK) ||
+   !(pads[source].flags & MEDIA_PAD_FL_SOURCE))
+   return -EINVAL;
+   }
+
+   return v4l2_subdev_call(sd, pad, set_routing, route);
+   }
 #endif
+
default:
return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
}
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 9102d6ca566e01f2..5acaeeb9b3cacefa 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -679,6 +679,9 @@ struct v4l2_subdev_pad_config {
  *
  * @set_frame_desc: set the low level media bus frame parameters, @fd array
  *  may be adjusted by the subdev driver to device 
capabilities.
+ *
+ * @get_routing: callback for VIDIOC_SUBDEV_G_ROUTING IOCTL handler.
+ * @set_routing: callback for VIDIOC_SUBDEV_S_ROUTING IOCTL handler.
  */
 struct v4l2_subdev_pad_ops {
int (*init_cfg)(struct v4l2_subdev *sd,
@@ -719,6 +722,10 @@ struct v4l2_subdev_pad_ops {
  struct v4l2_mbus_frame_desc *fd);
int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
  struct v4l2_mbus_frame_desc *fd);
+   int (*get_routing)(struct v4l2_subdev *sd,
+  struct v4l2_subdev_routing *route);
+   int (*set_routing)(struct v4l2_subdev *sd,
+  struct v4l2_subdev_routing *route);
 };
 
 /**
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 03970ce3074193e6..af069bfb10ca23a5 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/incl

[PATCH v2 08/30] media: entity: Add media_has_route() function

2018-11-01 Thread Niklas Söderlund
From: Laurent Pinchart 

This is a wrapper around the media entity has_route operation.

Signed-off-by: Laurent Pinchart 
Signed-off-by: Michal Simek 
Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 16 
 include/media/media-entity.h | 17 +
 2 files changed, 33 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index f2fa0b7826dbc2f3..3c0e7425c8983b45 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -237,6 +237,22 @@ EXPORT_SYMBOL_GPL(media_entity_pads_init);
  * Graph traversal
  */
 
+bool media_entity_has_route(struct media_entity *entity, unsigned int pad0,
+   unsigned int pad1)
+{
+   if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
+   return false;
+
+   if (pad0 == pad1)
+   return true;
+
+   if (!entity->ops || !entity->ops->has_route)
+   return true;
+
+   return entity->ops->has_route(entity, pad0, pad1);
+}
+EXPORT_SYMBOL_GPL(media_entity_has_route);
+
 static struct media_pad *
 media_entity_other(struct media_pad *pad, struct media_link *link)
 {
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index cd482814654616b5..9540d2af80f19805 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -919,6 +919,23 @@ int media_entity_get_fwnode_pad(struct media_entity 
*entity,
 __must_check int media_graph_walk_init(
struct media_graph *graph, struct media_device *mdev);
 
+/**
+ * media_entity_has_route - Check if two entity pads are connected internally
+ *
+ * @entity: The entity
+ * @pad0: The first pad index
+ * @pad1: The second pad index
+ *
+ * This function can be used to check whether two pads of an entity are
+ * connected internally in the entity.
+ *
+ * The caller must hold entity->graph_obj.mdev->mutex.
+ *
+ * Return: true if the pads are connected internally and false otherwise.
+ */
+bool media_entity_has_route(struct media_entity *entity, unsigned int pad0,
+   unsigned int pad1);
+
 /**
  * media_graph_walk_cleanup - Release resources used by graph walk.
  *
-- 
2.19.1



[PATCH v2 14/30] media: entity: Add debug information in graph walk route check

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index a5bb257d5a68f755..42977634d7102852 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -360,6 +360,9 @@ static void media_graph_walk_iter(struct media_graph *graph)
 */
if (!media_entity_has_route(pad->entity, pad->index, local->index)) {
link_top(graph) = link_top(graph)->next;
+   dev_dbg(pad->graph_obj.mdev->dev,
+   "walk: skipping \"%s\":%u -> %u (no route)\n",
+   pad->entity->name, pad->index, local->index);
return;
}
 
-- 
2.19.1



[PATCH v2 04/30] v4l: mc: Start walk from a specific pad in use count calculation

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

With the addition of the recent has_route() media entity op, the pads of a
media entity are no longer all interconnected. This has to be taken into
account in power management.

Prepare for the addition of a helper function supporting S_ROUTING.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/v4l2-core/v4l2-mc.c | 25 -
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mc.c 
b/drivers/media/v4l2-core/v4l2-mc.c
index 98edd47b2f0ae747..208cd91ce57ff211 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -332,17 +332,16 @@ EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
 
 /*
  * pipeline_pm_use_count - Count the number of users of a pipeline
- * @entity: The entity
+ * @pad: The pad
  *
  * Return the total number of users of all video device nodes in the pipeline.
  */
-static int pipeline_pm_use_count(struct media_entity *entity,
-   struct media_graph *graph)
+static int pipeline_pm_use_count(struct media_pad *pad,
+struct media_graph *graph)
 {
-   struct media_pad *pad;
int use = 0;
 
-   media_graph_walk_start(graph, entity->pads);
+   media_graph_walk_start(graph, pad);
 
while ((pad = media_graph_walk_next(graph))) {
if (is_media_entity_v4l2_video_device(pad->entity))
@@ -388,7 +387,7 @@ static int pipeline_pm_power_one(struct media_entity 
*entity, int change)
 
 /*
  * pipeline_pm_power - Apply power change to all entities in a pipeline
- * @entity: The entity
+ * @pad: The pad
  * @change: Use count change
  *
  * Walk the pipeline to update the use count and the power state of all 
non-node
@@ -396,16 +395,16 @@ static int pipeline_pm_power_one(struct media_entity 
*entity, int change)
  *
  * Return 0 on success or a negative error code on failure.
  */
-static int pipeline_pm_power(struct media_entity *entity, int change,
+static int pipeline_pm_power(struct media_pad *pad, int change,
struct media_graph *graph)
 {
-   struct media_pad *tmp_pad, *pad;
+   struct media_pad *tmp_pad, *first = pad;
int ret = 0;
 
if (!change)
return 0;
 
-   media_graph_walk_start(graph, entity->pads);
+   media_graph_walk_start(graph, pad);
 
while (!ret && (pad = media_graph_walk_next(graph)))
if (is_media_entity_v4l2_subdev(pad->entity))
@@ -414,7 +413,7 @@ static int pipeline_pm_power(struct media_entity *entity, 
int change,
if (!ret)
return ret;
 
-   media_graph_walk_start(graph, entity->pads);
+   media_graph_walk_start(graph, first);
 
while ((tmp_pad = media_graph_walk_next(graph))
   && tmp_pad != pad)
@@ -437,7 +436,7 @@ int v4l2_pipeline_pm_use(struct media_entity *entity, int 
use)
WARN_ON(entity->use_count < 0);
 
/* Apply power change to connected non-nodes. */
-   ret = pipeline_pm_power(entity, change, &mdev->pm_count_walk);
+   ret = pipeline_pm_power(entity->pads, change, &mdev->pm_count_walk);
if (ret < 0)
entity->use_count -= change;
 
@@ -451,8 +450,8 @@ int v4l2_pipeline_link_notify(struct media_link *link, u32 
flags,
  unsigned int notification)
 {
struct media_graph *graph = &link->graph_obj.mdev->pm_count_walk;
-   struct media_entity *source = link->source->entity;
-   struct media_entity *sink = link->sink->entity;
+   struct media_pad *source = link->source;
+   struct media_pad *sink = link->sink;
int source_use;
int sink_use;
int ret = 0;
-- 
2.19.1



[PATCH v2 02/30] media: entity: Use pads instead of entities in the media graph walk stack

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Change the media graph walk stack structure to use media pads instead of
using media entities. In addition to the entity, the pad contains the
information which pad in the entity are being dealt with.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 drivers/media/media-entity.c | 53 ++--
 include/media/media-entity.h |  6 ++--
 2 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 2bbc07de71aa5e6d..892e64a0a9d8ec42 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -237,40 +237,39 @@ EXPORT_SYMBOL_GPL(media_entity_pads_init);
  * Graph traversal
  */
 
-static struct media_entity *
-media_entity_other(struct media_entity *entity, struct media_link *link)
+static struct media_pad *
+media_entity_other(struct media_pad *pad, struct media_link *link)
 {
-   if (link->source->entity == entity)
-   return link->sink->entity;
+   if (link->source == pad)
+   return link->sink;
else
-   return link->source->entity;
+   return link->source;
 }
 
 /* push an entity to traversal stack */
-static void stack_push(struct media_graph *graph,
-  struct media_entity *entity)
+static void stack_push(struct media_graph *graph, struct media_pad *pad)
 {
if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
WARN_ON(1);
return;
}
graph->top++;
-   graph->stack[graph->top].link = entity->links.next;
-   graph->stack[graph->top].entity = entity;
+   graph->stack[graph->top].link = pad->entity->links.next;
+   graph->stack[graph->top].pad = pad;
 }
 
-static struct media_entity *stack_pop(struct media_graph *graph)
+static struct media_pad *stack_pop(struct media_graph *graph)
 {
-   struct media_entity *entity;
+   struct media_pad *pad;
 
-   entity = graph->stack[graph->top].entity;
+   pad = graph->stack[graph->top].pad;
graph->top--;
 
-   return entity;
+   return pad;
 }
 
 #define link_top(en)   ((en)->stack[(en)->top].link)
-#define stack_top(en)  ((en)->stack[(en)->top].entity)
+#define stack_top(en)  ((en)->stack[(en)->top].pad)
 
 /**
  * media_graph_walk_init - Allocate resources for graph walk
@@ -306,8 +305,8 @@ void media_graph_walk_start(struct media_graph *graph, 
struct media_pad *pad)
media_entity_enum_set(&graph->ent_enum, pad->entity);
 
graph->top = 0;
-   graph->stack[graph->top].entity = NULL;
-   stack_push(graph, pad->entity);
+   graph->stack[graph->top].pad = NULL;
+   stack_push(graph, pad);
dev_dbg(pad->graph_obj.mdev->dev,
"begin graph walk at '%s':%u\n", pad->entity->name, pad->index);
 }
@@ -315,16 +314,16 @@ EXPORT_SYMBOL_GPL(media_graph_walk_start);
 
 static void media_graph_walk_iter(struct media_graph *graph)
 {
-   struct media_entity *entity = stack_top(graph);
+   struct media_pad *pad = stack_top(graph);
struct media_link *link;
-   struct media_entity *next;
+   struct media_pad *next;
 
link = list_entry(link_top(graph), typeof(*link), list);
 
/* The link is not enabled so we do not follow. */
if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
link_top(graph) = link_top(graph)->next;
-   dev_dbg(entity->graph_obj.mdev->dev,
+   dev_dbg(pad->graph_obj.mdev->dev,
"walk: skipping disabled link '%s':%u -> '%s':%u\n",
link->source->entity->name, link->source->index,
link->sink->entity->name, link->sink->index);
@@ -332,22 +331,22 @@ static void media_graph_walk_iter(struct media_graph 
*graph)
}
 
/* Get the entity in the other end of the link . */
-   next = media_entity_other(entity, link);
+   next = media_entity_other(pad, link);
 
/* Has the entity already been visited? */
-   if (media_entity_enum_test_and_set(&graph->ent_enum, next)) {
+   if (media_entity_enum_test_and_set(&graph->ent_enum, next->entity)) {
link_top(graph) = link_top(graph)->next;
-   dev_dbg(entity->graph_obj.mdev->dev,
+   dev_dbg(pad->graph_obj.mdev->dev,
"walk: skipping entity '%s' (already seen)\n",
-   next->name);
+   next->entity->name);
return;
}
 
/* Push the new entity to stack and start over. */
link_top(graph) = link_top(graph)->next;
stack_push(graph, next);
-   dev_dbg(entity->graph_obj.mdev->dev, "walk: pushing '%s' on stack\n",
-   next->name);
+   dev_dbg(next->graph_obj.mdev->dev, "walk: pushing '%s':%u on stack\n",
+   next->entity->name, next->index);
 }
 
 struct media_entity *media_graph_walk_next(struct media_

[PATCH v2 01/30] media: entity: Use pad as a starting point for graph walk

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

With the upcoming use of the recently added has_route() media entity op, all
the pads in an entity will no longer be considered interconnected. This has
an effect where the media graph is traversed: the starting pad does make a
difference.

Prepare for this change by using pad instead of the entity as an argument
for the graph walk operations. The actual graph traversal algorithm change
is in further patches.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 Documentation/media/kapi/mc-core.rst|  2 +-
 drivers/media/media-entity.c| 17 -
 drivers/media/platform/exynos4-is/media-dev.c   |  4 ++--
 drivers/media/platform/omap3isp/ispvideo.c  |  2 +-
 drivers/media/platform/vsp1/vsp1_video.c|  2 +-
 drivers/media/platform/xilinx/xilinx-dma.c  |  2 +-
 drivers/media/v4l2-core/v4l2-mc.c   |  6 +++---
 drivers/staging/media/davinci_vpfe/vpfe_video.c |  6 +++---
 drivers/staging/media/omap4iss/iss_video.c  |  4 ++--
 include/media/media-entity.h| 10 --
 10 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/Documentation/media/kapi/mc-core.rst 
b/Documentation/media/kapi/mc-core.rst
index 0c05503eaf1fa6c7..27aefb9a778b2ad6 100644
--- a/Documentation/media/kapi/mc-core.rst
+++ b/Documentation/media/kapi/mc-core.rst
@@ -165,7 +165,7 @@ Drivers initiate a graph traversal by calling
 :c:func:`media_graph_walk_start()`
 
 The graph structure, provided by the caller, is initialized to start graph
-traversal at the given entity.
+traversal at the given pad in an entity.
 
 Drivers can then retrieve the next entity by calling
 :c:func:`media_graph_walk_next()`
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 0b1cb3559140a1fe..2bbc07de71aa5e6d 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -300,17 +300,16 @@ void media_graph_walk_cleanup(struct media_graph *graph)
 }
 EXPORT_SYMBOL_GPL(media_graph_walk_cleanup);
 
-void media_graph_walk_start(struct media_graph *graph,
-   struct media_entity *entity)
+void media_graph_walk_start(struct media_graph *graph, struct media_pad *pad)
 {
media_entity_enum_zero(&graph->ent_enum);
-   media_entity_enum_set(&graph->ent_enum, entity);
+   media_entity_enum_set(&graph->ent_enum, pad->entity);
 
graph->top = 0;
graph->stack[graph->top].entity = NULL;
-   stack_push(graph, entity);
-   dev_dbg(entity->graph_obj.mdev->dev,
-   "begin graph walk at '%s'\n", entity->name);
+   stack_push(graph, pad->entity);
+   dev_dbg(pad->graph_obj.mdev->dev,
+   "begin graph walk at '%s':%u\n", pad->entity->name, pad->index);
 }
 EXPORT_SYMBOL_GPL(media_graph_walk_start);
 
@@ -428,7 +427,7 @@ __must_check int __media_pipeline_start(struct media_entity 
*entity,
goto error_graph_walk_start;
}
 
-   media_graph_walk_start(&pipe->graph, entity);
+   media_graph_walk_start(&pipe->graph, entity->pads);
 
while ((entity = media_graph_walk_next(graph))) {
DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
@@ -509,7 +508,7 @@ __must_check int __media_pipeline_start(struct media_entity 
*entity,
 * Link validation on graph failed. We revert what we did and
 * return the error.
 */
-   media_graph_walk_start(graph, entity_err);
+   media_graph_walk_start(graph, entity_err->pads);
 
while ((entity_err = media_graph_walk_next(graph))) {
/* Sanity check for negative stream_count */
@@ -560,7 +559,7 @@ void __media_pipeline_stop(struct media_entity *entity)
if (WARN_ON(!pipe))
return;
 
-   media_graph_walk_start(graph, entity);
+   media_graph_walk_start(graph, entity->pads);
 
while ((entity = media_graph_walk_next(graph))) {
/* Sanity check for negative stream_count */
diff --git a/drivers/media/platform/exynos4-is/media-dev.c 
b/drivers/media/platform/exynos4-is/media-dev.c
index 870501b0f351addb..51d2a571c06db6a3 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -1144,7 +1144,7 @@ static int __fimc_md_modify_pipelines(struct media_entity 
*entity, bool enable,
 * through active links. This is needed as we cannot power on/off the
 * subdevs in random order.
 */
-   media_graph_walk_start(graph, entity);
+   media_graph_walk_start(graph, entity->pads);
 
while ((entity = media_graph_walk_next(graph))) {
if (!is_media_entity_v4l2_video_device(entity))
@@ -1159,7 +1159,7 @@ static int __fimc_md_modify_pipelines(struct media_entity 
*entity, bool enable,
return 0;
 
 err:
-   media_graph_walk_start(graph, entity_err);
+   media_graph_walk_start(graph, entity_err->pads);
 
while ((entity_err = me

[PATCH v2 03/30] media: entity: Walk the graph based on pads

2018-11-01 Thread Niklas Söderlund
From: Sakari Ailus 

Instead of iterating over graph entities during the walk, iterate the pads
through which the entity was first reached. This is required in order to
make the entity pipeline pad-based rather than entity based.

Signed-off-by: Sakari Ailus 
Reviewed-by: Niklas Söderlund 
---
 Documentation/media/kapi/mc-core.rst  |  7 ++-
 drivers/media/media-entity.c  | 46 ++
 drivers/media/platform/exynos4-is/media-dev.c | 20 
 drivers/media/platform/omap3isp/ispvideo.c| 17 +++
 drivers/media/platform/vsp1/vsp1_video.c  | 12 ++---
 drivers/media/platform/xilinx/xilinx-dma.c| 12 ++---
 drivers/media/v4l2-core/v4l2-mc.c | 25 +-
 .../staging/media/davinci_vpfe/vpfe_video.c   | 47 ++-
 drivers/staging/media/omap4iss/iss_video.c| 34 +++---
 include/media/media-entity.h  |  7 +--
 10 files changed, 122 insertions(+), 105 deletions(-)

diff --git a/Documentation/media/kapi/mc-core.rst 
b/Documentation/media/kapi/mc-core.rst
index 27aefb9a778b2ad6..849b87439b7a9772 100644
--- a/Documentation/media/kapi/mc-core.rst
+++ b/Documentation/media/kapi/mc-core.rst
@@ -167,8 +167,11 @@ Drivers initiate a graph traversal by calling
 The graph structure, provided by the caller, is initialized to start graph
 traversal at the given pad in an entity.
 
-Drivers can then retrieve the next entity by calling
-:c:func:`media_graph_walk_next()`
+Drivers can then retrieve the next pad by calling
+:c:func:`media_graph_walk_next()`. Only the pad through which the entity
+is first reached is returned. If the caller is interested in knowing which
+further pads would be connected, the :c:func:`media_entity_has_route()`
+function can be used for that.
 
 When the graph traversal is complete the function will return ``NULL``.
 
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 892e64a0a9d8ec42..70db03fa33a21db1 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -349,9 +349,9 @@ static void media_graph_walk_iter(struct media_graph *graph)
next->entity->name, next->index);
 }
 
-struct media_entity *media_graph_walk_next(struct media_graph *graph)
+struct media_pad *media_graph_walk_next(struct media_graph *graph)
 {
-   struct media_entity *entity;
+   struct media_pad *pad;
 
if (stack_top(graph) == NULL)
return NULL;
@@ -364,11 +364,11 @@ struct media_entity *media_graph_walk_next(struct 
media_graph *graph)
while (link_top(graph) != &stack_top(graph)->entity->links)
media_graph_walk_iter(graph);
 
-   entity = stack_pop(graph)->entity;
-   dev_dbg(entity->graph_obj.mdev->dev,
-   "walk: returning entity '%s'\n", entity->name);
+   pad = stack_pop(graph);
+   dev_dbg(pad->graph_obj.mdev->dev,
+   "walk: returning pad '%s':%u\n", pad->entity->name, pad->index);
 
-   return entity;
+   return pad;
 }
 EXPORT_SYMBOL_GPL(media_graph_walk_next);
 
@@ -416,7 +416,8 @@ __must_check int __media_pipeline_start(struct media_entity 
*entity,
 {
struct media_device *mdev = entity->graph_obj.mdev;
struct media_graph *graph = &pipe->graph;
-   struct media_entity *entity_err = entity;
+   struct media_pad *pad = entity->pads;
+   struct media_pad *pad_err = pad;
struct media_link *link;
int ret;
 
@@ -426,9 +427,11 @@ __must_check int __media_pipeline_start(struct 
media_entity *entity,
goto error_graph_walk_start;
}
 
-   media_graph_walk_start(&pipe->graph, entity->pads);
+   media_graph_walk_start(&pipe->graph, pad);
+
+   while ((pad = media_graph_walk_next(graph))) {
+   struct media_entity *entity = pad->entity;
 
-   while ((entity = media_graph_walk_next(graph))) {
DECLARE_BITMAP(active, MEDIA_ENTITY_MAX_PADS);
DECLARE_BITMAP(has_no_links, MEDIA_ENTITY_MAX_PADS);
 
@@ -452,11 +455,11 @@ __must_check int __media_pipeline_start(struct 
media_entity *entity,
bitmap_fill(has_no_links, entity->num_pads);
 
list_for_each_entry(link, &entity->links, list) {
-   struct media_pad *pad = link->sink->entity == entity
-   ? link->sink : link->source;
+   struct media_pad *other_pad = link->sink->entity == 
entity
+   ? link->sink : link->source;
 
/* Mark that a pad is connected by a link. */
-   bitmap_clear(has_no_links, pad->index, 1);
+   bitmap_clear(has_no_links, other_pad->index, 1);
 
/*
 * Pads that either do not need to connect or
@@ -465,13 +468,13 @@ __must_check int __media_pipeline_start(struct 
media_entity *entity,
 */

[PATCH v2 00/30] v4l: add support for multiplexed streams

2018-11-01 Thread Niklas Söderlund
Hi all,

This series adds support for multiplexed streams within a media device
link. The use-case addressed in this series covers CSI-2 Virtual
Channels on the Renesas R-Car Gen3 platforms. The v4l2 changes have been
a joint effort between Sakari and Laurent and floating around for some
time [1].

I have added driver support for the devices used on the Renesas Gen3
platforms, a ADV7482 connected to the R-Car CSI-2 receiver. With these
changes I can control which of the analog inputs of the ADV7482 the
video source is captured from and on which CSI-2 virtual channel the
video is transmitted on to the R-Car CSI-2 receiver.

The series adds two new subdev IOCTLs [GS]_ROUTING which allows
user-space to get and set routes inside a subdevice. I have added RFC
support for these to v4l-utils [2] which can be used to test this
series, example:

Check the internal routing of the adv748x csi-2 transmitter:
v4l2-ctl -d /dev/v4l-subdev24 --get-routing
0/0 -> 1/0 [ENABLED]
0/0 -> 1/1 []
0/0 -> 1/2 []
0/0 -> 1/3 []


Select that video should be outputed on VC 2 and check the result:
$ v4l2-ctl -d /dev/v4l-subdev24 --set-routing '0/0 -> 1/2 [1]'

$ v4l2-ctl -d /dev/v4l-subdev24 --get-routing
0/0 -> 1/0 []
0/0 -> 1/1 []
0/0 -> 1/2 [ENABLED]
0/0 -> 1/3 []

This series is tested on R-Car M3-N and for your testing needs this
series is available at

git://git.ragnatech.se/linux v4l2/mux

* Changes since v1
- Rebased on latest media-tree.
- Incorporated changes to patch 'v4l: subdev: compat: Implement handling 
  for VIDIOC_SUBDEV_[GS]_ROUTING' by Sakari.
- Added review tags.

Thanks.

1. git://linuxtv.org/sailus/media_tree.git vc
2. git://git.ragnatech.se/v4l-utils routing

Laurent Pinchart (4):
  media: entity: Add has_route entity operation
  media: entity: Add media_has_route() function
  media: entity: Use routing information during graph traversal
  v4l: subdev: Add [GS]_ROUTING subdev ioctls and operations

Niklas Söderlund (7):
  adv748x: csi2: add translation from pixelcode to CSI-2 datatype
  adv748x: csi2: only allow formats on sink pads
  adv748x: csi2: describe the multiplexed stream
  adv748x: csi2: add internal routing configuration
  adv748x: afe: add routing support
  rcar-csi2: use frame description information to configure CSI-2 bus
  rcar-csi2: expose the subdevice internal routing

Sakari Ailus (19):
  media: entity: Use pad as a starting point for graph walk
  media: entity: Use pads instead of entities in the media graph walk
stack
  media: entity: Walk the graph based on pads
  v4l: mc: Start walk from a specific pad in use count calculation
  media: entity: Move the pipeline from entity to pads
  media: entity: Use pad as the starting point for a pipeline
  media: entity: Swap pads if route is checked from source to sink
  media: entity: Skip link validation for pads to which there is no
route to
  media: entity: Add an iterator helper for connected pads
  media: entity: Add only connected pads to the pipeline
  media: entity: Add debug information in graph walk route check
  media: entity: Look for indirect routes
  v4l: subdev: compat: Implement handling for VIDIOC_SUBDEV_[GS]_ROUTING
  v4l: subdev: Take routing information into account in link validation
  v4l: subdev: Improve link format validation debug messages
  v4l: mc: Add an S_ROUTING helper function for power state changes
  v4l: Add bus type to frame descriptors
  v4l: Add CSI-2 bus configuration to frame descriptors
  v4l: Add stream to frame descriptor

 Documentation/media/kapi/mc-core.rst  |  15 +-
 drivers/media/i2c/adv748x/adv748x-afe.c   |  65 
 drivers/media/i2c/adv748x/adv748x-csi2.c  | 124 +++-
 drivers/media/i2c/adv748x/adv748x.h   |   1 +
 drivers/media/media-entity.c  | 252 ++--
 drivers/media/pci/intel/ipu3/ipu3-cio2.c  |   6 +-
 .../media/platform/exynos4-is/fimc-capture.c  |   8 +-
 .../platform/exynos4-is/fimc-isp-video.c  |   8 +-
 drivers/media/platform/exynos4-is/fimc-isp.c  |   2 +-
 drivers/media/platform/exynos4-is/fimc-lite.c |  10 +-
 drivers/media/platform/exynos4-is/media-dev.c |  20 +-
 drivers/media/platform/omap3isp/isp.c |   2 +-
 drivers/media/platform/omap3isp/ispvideo.c|  25 +-
 drivers/media/platform/omap3isp/ispvideo.h|   2 +-
 .../media/platform/qcom/camss/camss-video.c   |   6 +-
 drivers/media/platform/rcar-vin/rcar-csi2.c   | 188 +---
 drivers/media/platform/rcar-vin/rcar-dma.c|   8 +-
 .../media/platform/s3c-camif/camif-capture.c  |   6 +-
 drivers/media/platform/vimc/vimc-capture.c|   6 +-
 drivers/media/platform/vsp1/vsp1_video.c  |  18 +-
 drivers/media/platform/xilinx/xilinx-dma.c|  20 +-
 drivers/media/platform/xilinx/xilinx-dma.h|   2 +-
 drivers/media/usb/au0828/au0828-core.c|   4 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c |  77 +
 drivers/media/v4l2-core/v4l2-ioctl.c  |  20 +-
 drivers/media/v

Re: [PATCH] arm64: dts: renesas: enable HS400 on R-Car Gen3

2018-11-01 Thread Wolfram Sang

And this concludes my first patch review session while being on a ship
:) Thanks for this SDHI hackathon guys, and looking forward to seeing
you again!



signature.asc
Description: PGP signature


Re: [PATCH] arm64: dts: renesas: enable HS400 on R-Car Gen3

2018-11-01 Thread Wolfram Sang

> This patch have quiet a few dependencies I'm afraid, let me know if you 
> wish to be notified once they all upstream. I don't think it's a good 
> idea to pick this up before all dependencies are resolved.

Yes, we should do that. Ping Simon once all dependencies are in next. It
is still fine to have this patch here in case people want to test. BTW
did you mention your branch somewhere where you collected all these
patches to make HS400 working/enabled?

For this patch already:

Reviewed-by: Wolfram Sang 
Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH 0/2] renesas: rcar-gen3: add HS400 quirk for SD clock

2018-11-01 Thread Wolfram Sang

> This is the result of the SDHI hackathon for a possible solution to the 
> clock issue on early ES versions. It is based on the Gen2 solution where 
> a row of the possible clock settings are ignored on the effected SoC+ES 
> versions. The first row is not effected when reading settings left by 
> the bootloader, only when the setting the clock.

We really thought about exposing both clocks, SDn and SDHn. I got
convinced to use this less intrusive approach to get HS400 reliably to
work as a first step. "First make it work, then make it beautiful" so to
say...



signature.asc
Description: PGP signature


Re: [PATCH 2/2] clk: renesas: rcar-gen3: add HS400 quirk for SD clock

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:25:18AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> On H3 (ES1.0,ES2.0) and M3-W (ES1.0,ES1.1) the clock setting for HS400
> needs a quirk to function properly. The reason for the quirk is that
> there are two settings which produces same divider vale for the SDn
> clock. On the effected boards the one currently selected results in HS00
> not working.
> 
> This change uses the same method as the Gen2 CPG driver and simply
> ignores the first clock setting as this is the offending one when
> selecting the settings. Which of the two possible settings is used have
> no effect for SDR104.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 
Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH 1/2] clk: renesas: rcar-gen3: add documentation for SD clocks

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:25:17AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> Document the known use cases of the different clock settings. This is
> useful as different SoC and ES versions uses different settings to do
> the same thing as there are more then one combination to achieve the
> same SDn clock speed.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 
Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v2 0/3] mmc: renesas_sdhi: extend quirk selection to handle ES revisions

2018-11-01 Thread Wolfram Sang

All patches tested on M3N:

Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v3 0/3] mmc: tmio: fix reset operation

2018-11-01 Thread Wolfram Sang

All patches tested on M3N, H2, and E2.

Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH] mmc: renesas_sdhi: remove workaround for HS400 clock

2018-11-01 Thread Wolfram Sang
On Wed, Oct 31, 2018 at 11:59:44PM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> The driver sets an incorrect clock and depends on the clock driver
> knowledge of this incorrect setting to still set a 200Mhz SDn clock.
> Instead of spreading the workaround between the two drivers the clock
> driver should be made aware of the ES versions where the special clock
> handling is needed no need to keep this workaround in the SDHI driver.
> 
> Signed-off-by: Niklas Söderlund 

Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH] mmc: tmio: delete wait in tuning process

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:00:43AM +0100, Niklas Söderlund wrote:
> From: Masaharu Hayakawa 
> 
> The manual does not contain information that a wait is needed in the
> tuning process, this might be a leftover from early development.
> Removing the wait don't have any effect on operation so delete the wait
> to shorten the initialization time.
> 
> Signed-off-by: Masaharu Hayakawa 
> Signed-off-by: Takeshi Saito 
> [Niklas: fixup commit message]
> Signed-off-by: Niklas Söderlund 

Tested-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v2 0/3] mmc: renesas_sdhi: extend quirk selection to handle ES revisions

2018-11-01 Thread Wolfram Sang

> Patch 1/3 adds support to select quirks based on SoC + ES revision using 
> soc_device_match() and converts the only existing quirk. Patch 2/3 
> Removes the old method to select quirk based on compatibility string.  
> While Patch 3/3 adds a new quirk from the BSP which blacklists some 
> known problematic ES versions for HS400. HS400 is not yet enabled 
> upstream so blacklisting these ES versions is not a regression of 
> functionality.

This will allow us even to get rid of the TMIO_MMC_HAVE_4TAP_HS400 flag
entirely because we now use it only within the Renesas part of SDHI. We
want to do this incrementally, though, because we first want to get the
HS400 feature enabled as the first step.



signature.asc
Description: PGP signature


Re: [PATCH v2 2/3] mmc: renesas_sdhi: align compatibility properties for H3 and M3-W

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:13:39AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> It was though all ES revisions of H3 and M3-W SoCs required the
> TMIO_MMC_HAVE_4TAP_HS400 flag. Recent datasheet updates tells us this is
> not true, only early ES revisions of the SoC do.
> 
> Since quirk matching based on ES revisions is now used to handle the
> flag it's possible to align all Gen3 compatibility properties. This will
> allow later ES revisions of H3 and M3-W to use the correct 8-tap HS400
> mode.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v2 3/3] mmc: renesas_sdhi: disable HS400 on H3 ES1.x and M3-W ES1.x

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:13:40AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> The Renesas BSP confirms that H3 ES1.x and M3-W ES1.x do not properly
> support HS400. Add a quirk to indicate this and disable HS400 in the MMC
> capabilities if the quirk is set.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v2 1/3] mmc: renesas_sdhi: handle 4tap hs400 mode quirk based on SoC revision

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:13:38AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> Latest datasheet makes it clear that not all ES revisions of the H3 and
> M3-W have the 4-tap HS400 mode quirk, currently the quirk is set
> unconditionally for these two SoCs. Prepare to handle the quirk based on
> SoC revision instead of compatibility value by using soc_device_match()
> and set the TMIO_MMC_HAVE_4TAP_HS400 flag explicitly.
> 
> The reason for adding a new quirks struct instead of just a flag is that
> looking ahead it seems more quirks needs to be handled in a SoC revision
> basis.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v3 0/3] mmc: tmio: fix reset operation

2018-11-01 Thread Wolfram Sang

So, we agreed on this series during our Renesas SDHI hackathon.
Comments / testing from Yamada-san would be very welcome because we
really don't want to cause regressions on his hardware.



signature.asc
Description: PGP signature


Re: [PATCH v3 3/3] mmc: renesas_sdhi: add initial setting of interrupt mask register

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:05:54AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> The initial value of the interrupt mask register may be different from
> the H/W manual at the startup of the kernel by setting from the
> bootloader. Since the error interrupts may be unmasked, the driver sets
> initial value.
> 
> The initial value is only known for R-Car Gen2 and Gen3 platforms so
> limit the initialization to those platforms.
> 
> Based on work from Masaharu Hayakawa.
> 
> Signed-off-by: Niklas Söderlund 
> 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v3 2/3] mmc: tmio: fix reset operation

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:05:53AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> SD / MMC did not operate properly when suspend transition failed.
> Because the SCC was not reset at resume, issue of the command failed.
> Call the host specific reset function and reset the hardware in order to
> add reset of SCC. This change also fixes tuning on some stubborn cards
> on Gen2.
> 
> Based on work from Masaharu Hayakawa.
> 
> Signed-off-by: Niklas Söderlund 
> 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH] mmc: tmio: delete wait in tuning process

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:00:43AM +0100, Niklas Söderlund wrote:
> From: Masaharu Hayakawa 
> 
> The manual does not contain information that a wait is needed in the
> tuning process, this might be a leftover from early development.
> Removing the wait don't have any effect on operation so delete the wait
> to shorten the initialization time.
> 
> Signed-off-by: Masaharu Hayakawa 
> Signed-off-by: Takeshi Saito 
> [Niklas: fixup commit message]
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH v3 1/3] mmc: tmio: enable module clock before resetting when resuming

2018-11-01 Thread Wolfram Sang
On Thu, Nov 01, 2018 at 12:05:52AM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> On runtime power management resume, the host clock needs to be
> enabled before calling tmio_mmc_reset. If the mmc device has a power
> domain entry, the host clock is enabled via genpd_runtime_resume,
> running before tmio_mmc_host_runtime_resume. If the mmc device has no
> power domain entry, however, genpd_runtime_resume is not called. This
> patch changes tmio_mmc_host_runtime_resume to enable the host clock
> before calling tmio_mmc_reset.
> 
> Based on work from Masaharu Hayakawa.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


Re: [PATCH] mmc: renesas_sdhi: remove workaround for HS400 clock

2018-11-01 Thread Wolfram Sang
On Wed, Oct 31, 2018 at 11:59:44PM +0100, Niklas Söderlund wrote:
> From: Niklas Söderlund 
> 
> The driver sets an incorrect clock and depends on the clock driver
> knowledge of this incorrect setting to still set a 200Mhz SDn clock.
> Instead of spreading the workaround between the two drivers the clock
> driver should be made aware of the ES versions where the special clock
> handling is needed no need to keep this workaround in the SDHI driver.
> 
> Signed-off-by: Niklas Söderlund 

Reviewed-by: Wolfram Sang 



signature.asc
Description: PGP signature


RE: [RFC] drm/bridge/sii902x: Fix EDID readback

2018-11-01 Thread Fabrizio Castro
Hello Peter,

Thank you for your feedback!

> Subject: Re: [RFC] drm/bridge/sii902x: Fix EDID readback

snip

> >
> > To further detail the problem, the system is vulnerable from before the 
> > last write
> > performed by sii902x_i2c_bypass_select to after we confirm we need the 
> > switch
> > to be closed within sii902x_i2c_bypass_deselect, that's the minimum amount 
> > of time
> > we could keep the parent adapter locked for, I guess I am stuck with a 
> > parent-locking
> > architecture, aren't I?
>
> If that problem description is correct, then yes, I think the *only* solution
> is to combine the three parts "open bypass mode", "edid xfer" and "close 
> bypass
> mode", and to keep the i2c adapter locked during the procedure so that other
> xfers do not creep in and crap thing up from the side. And one way to combine
> the three parts is to use a parent-locked i2c gate. And since you need to keep
> the i2c adapter locked over the whole procedure, you need to use unlocked 
> xfers
> (as you have already discovered). But how do you know that this problem
> description is accurate?

I basically observed what was going on on the bus (with a logic analyser) while 
generating
traffic on the parent adapter

> Why is it not ok for unrelated xfers to creep in
> between opening the bypass mode and the edid xfer, and how do you know that
> this is not ok?

Because those transfers would come with no extra delay between STOP and START
conditions while the HDMI transmitter is in passthrough mode

>
> > But I guess I could release it when it's not actually needed,
>
> How would you figure out when it's not needed?

The moment you tell the HDMI transmitter you are going to talk to the monitor 
nothing else can
flow on the bus, up until you gracefully close the pass through session, which 
means I wouldn't
really need to hold the parent lock during the entire duration of the select 
callback, I would need
to hold the parent lock only from before the last write as that's when we tell 
the HDMI transmitter
to activate the passthrough mode, but I guess it would make the driver hard to 
maintain (as in
others would need to understand this properly before making any changes), 
wouldn't it?

>
> > or is this going to be a pain to maintain? Shall I just keep going with the 
> > parent-locking
> > but using bare i2c transactions only within select and deselect and leave 
> > regmap
> > to deal with everything else?
>
> That's a possibility. Take care to not mess up any cached state in regmap 
> though.

The original version of the driver wasn't using any caching, so I guess I would 
need to fallback
exactly to the same implementation.

So, what should I do? Should I keep the parent-locking, the unlocked flavours 
of rd/wr/rmw from
within select/deselect, and put back regmap based rd/wr/rmw with no caching for 
everything else?

Thank you!

Fab

> The registers you touch from select/deselect should probably be volatile or
> something like that?
>
> Cheers,
> Peter



Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, 
Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered 
No. 04586709.


Re: [RFC] drm/bridge/sii902x: Fix EDID readback

2018-11-01 Thread Peter Rosin
On 2018-11-01 17:04, Fabrizio Castro wrote:
> Hello Peter,
> 
> Thank you for your feedback!
> 
>>> The "mux-locked" implementation was the one I first tried and I discovered
>>> it doesn't work for me, as other traffic on the parent adapter can get in 
>>> the
>>> way. What we need for this device is no other traffic on the bus during the
>>> "select transaction deselect" procedure, that's why I went with the parent
>>> locking. Also this device needs a delay between stop and start conditions
>>> while addressing the monitor.
>>
>> Ok, I thought the problem was that a delay was needed between the STOP
>> of the command opening the gate and the START of the edid eeprom xfer, and
>> that everything else worked normally. Too bad this wasn't the actual problem.
>>
>> Hmm. If it is indeed true that other xfers must never creep into the "select
>> xfer deselect" procedure then you are indeed stuck with a parent-locking.
>> But is that really the case? Could it be that the extra delay between
>> STOP-START is only needed after the absolutely last xfer before the
>> command closing the gate?
>>
>> If that problem description is correct, it should be possible to go back to
>> a mux-locked gate, but then in your deselect implementation grab the i2c 
>> adapter
>> lock manually - with i2c_lock_bus(adapter, I2C_LOCK_ROOT_ADAPTER) - before 
>> the
>> 30 us delay, then open code the command to close the gate with an unlocked 
>> i2c
>> access, and finally release the i2c bus lock. That way you have ensured 
>> silence
>> on the bus for the required time before closing the gate. You would still 
>> need
>> to bypass regmap, but only in this one place (but maybe you should bypass
>> regmap for opening the gate too, for symmetry).
> 
> To further detail the problem, the system is vulnerable from before the last 
> write
> performed by sii902x_i2c_bypass_select to after we confirm we need the switch
> to be closed within sii902x_i2c_bypass_deselect, that's the minimum amount of 
> time
> we could keep the parent adapter locked for, I guess I am stuck with a 
> parent-locking
> architecture, aren't I?

If that problem description is correct, then yes, I think the *only* solution
is to combine the three parts "open bypass mode", "edid xfer" and "close bypass
mode", and to keep the i2c adapter locked during the procedure so that other
xfers do not creep in and crap thing up from the side. And one way to combine
the three parts is to use a parent-locked i2c gate. And since you need to keep
the i2c adapter locked over the whole procedure, you need to use unlocked xfers
(as you have already discovered). But how do you know that this problem
description is accurate? Why is it not ok for unrelated xfers to creep in
between opening the bypass mode and the edid xfer, and how do you know that
this is not ok?

> But I guess I could release it when it's not actually needed,

How would you figure out when it's not needed?

> or is this going to be a pain to maintain? Shall I just keep going with the 
> parent-locking
> but using bare i2c transactions only within select and deselect and leave 
> regmap
> to deal with everything else?

That's a possibility. Take care to not mess up any cached state in regmap 
though.
The registers you touch from select/deselect should probably be volatile or
something like that?

Cheers,
Peter


RE: [RFC] drm/bridge/sii902x: Fix EDID readback

2018-11-01 Thread Fabrizio Castro
Hello Peter,

Thank you for your feedback!

> > The "mux-locked" implementation was the one I first tried and I discovered
> > it doesn't work for me, as other traffic on the parent adapter can get in 
> > the
> > way. What we need for this device is no other traffic on the bus during the
> > "select transaction deselect" procedure, that's why I went with the parent
> > locking. Also this device needs a delay between stop and start conditions
> > while addressing the monitor.
>
> Ok, I thought the problem was that a delay was needed between the STOP
> of the command opening the gate and the START of the edid eeprom xfer, and
> that everything else worked normally. Too bad this wasn't the actual problem.
>
> Hmm. If it is indeed true that other xfers must never creep into the "select
> xfer deselect" procedure then you are indeed stuck with a parent-locking.
> But is that really the case? Could it be that the extra delay between
> STOP-START is only needed after the absolutely last xfer before the
> command closing the gate?
>
> If that problem description is correct, it should be possible to go back to
> a mux-locked gate, but then in your deselect implementation grab the i2c 
> adapter
> lock manually - with i2c_lock_bus(adapter, I2C_LOCK_ROOT_ADAPTER) - before the
> 30 us delay, then open code the command to close the gate with an unlocked i2c
> access, and finally release the i2c bus lock. That way you have ensured 
> silence
> on the bus for the required time before closing the gate. You would still need
> to bypass regmap, but only in this one place (but maybe you should bypass
> regmap for opening the gate too, for symmetry).

To further detail the problem, the system is vulnerable from before the last 
write
performed by sii902x_i2c_bypass_select to after we confirm we need the switch
to be closed within sii902x_i2c_bypass_deselect, that's the minimum amount of 
time
we could keep the parent adapter locked for, I guess I am stuck with a 
parent-locking
architecture, aren't I? But I guess I could release it when it's not actually 
needed,
or is this going to be a pain to maintain? Shall I just keep going with the 
parent-locking
but using bare i2c transactions only within select and deselect and leave regmap
to deal with everything else?

snip

> >
> > Ah, do you think the following is going to cause any issue in the future?
> > -edid = drm_get_edid(connector, sii902x->i2c->adapter);
> > +edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
>
> No, that was a critical part of the idea to use a gate to introduce the
> needed delay.

Again, thank you very much for spending your time looking into this, your
feedback  is very much appreciated.

Fab

>
> Cheers,
> Peter



Renesas Electronics Europe Ltd, Dukes Meadow, Millboard Road, Bourne End, 
Buckinghamshire, SL8 5FH, UK. Registered in England & Wales under Registered 
No. 04586709.


Re: [RFC] drm/bridge/sii902x: Fix EDID readback

2018-11-01 Thread Peter Rosin
On 2018-11-01 12:04, Fabrizio Castro wrote:
> Hello Peter,
> 
> Thank you for your feedback!
> 
> snip
> 
>>> Yeah, there is some issue with locking here, and that's coming down
>>> from the fact that when we call into drm_get_edid, we implicitly call
>>> i2c_transfer which ultimately locks the i2c adapter, and then calls
>>> into our sii902x_i2c_bypass_select, which in turn calls into the regmap
>>> functions and therefore we try and lock the same i2c adapter again,
>>> driving the system into a deadlock.
>>> Having the option of using "unlocked" flavours of reads and writes
>>> is what we need here, but looking at drivers/base/regmap/regmap-i2c.c
>>> I couldn't find anything suitable for my case, maybe Mark could advise
>>> on this one? I am sure I overlooked something here, is there a better
>>> way to address this?
>>
>> This recursive locking problem surfaces when an i2c mux is operated
>> by writing commands on the same i2c bus that is muxed. When this
>> happens for a typical i2c mux chip like nxp,pca9548 this can be kept
>> local to that driver. However, when there are interactions with other
>> parts of the kernel (e.g. if the i2c-mux is operated by gpio pins,
>> and those gpio pins in turn are operated by accesses to the i2c bus
>> that is muxed) this locked vs. unlocked thing would spread like
>> wildfire.
>>
>> Since I did not like that wildfire, I came up with the "mux-locked"
>> scheme. It is not appropriate everywhere, but in this case I think it
>> is a perfect fit. By using it, you should be able to dodge all locking
>> issues and it should be possible to keep the regmap usage as-is and the
>> patch would in all likelihood be much less intrusive.
>>
>> For some background on "mux-locked" vs. "parent-locked" (which is what
>> you have used in this RFC patch), see Documentation/i2c/i2c-topology.
> 
> The "mux-locked" implementation was the one I first tried and I discovered
> it doesn't work for me, as other traffic on the parent adapter can get in the
> way. What we need for this device is no other traffic on the bus during the
> "select transaction deselect" procedure, that's why I went with the parent
> locking. Also this device needs a delay between stop and start conditions
> while addressing the monitor.

Ok, I thought the problem was that a delay was needed between the STOP
of the command opening the gate and the START of the edid eeprom xfer, and
that everything else worked normally. Too bad this wasn't the actual problem.

Hmm. If it is indeed true that other xfers must never creep into the "select
xfer deselect" procedure then you are indeed stuck with a parent-locking.
But is that really the case? Could it be that the extra delay between
STOP-START is only needed after the absolutely last xfer before the
command closing the gate?

If that problem description is correct, it should be possible to go back to
a mux-locked gate, but then in your deselect implementation grab the i2c adapter
lock manually - with i2c_lock_bus(adapter, I2C_LOCK_ROOT_ADAPTER) - before the
30 us delay, then open code the command to close the gate with an unlocked i2c
access, and finally release the i2c bus lock. That way you have ensured silence
on the bus for the required time before closing the gate. You would still need
to bypass regmap, but only in this one place (but maybe you should bypass
regmap for opening the gate too, for symmetry).

Cheers,
Peter

>>
>> There are a couple of more comments below, inline.
>>
> 
> snip
> 
>
> +static int sii902x_i2c_bypass_select(struct i2c_mux_core *mux, u32 
> chan_id)
> +{
> +   struct sii902x *sii902x = i2c_mux_priv(mux);
> +   struct device *dev = &sii902x->i2c->dev;
> +   unsigned long timeout;
> +   u8 status;
> +   int ret;
> +
> +   ret = __sii902x_update_bits(sii902x->i2c, SII902X_SYS_CTRL_DATA,
> +   SII902X_SYS_CTRL_DDC_BUS_REQ,
> +   SII902X_SYS_CTRL_DDC_BUS_REQ);
> +
> +   timeout = jiffies +
> + 
> msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
> +   do {
> +   ret = __sii902x_read(sii902x->i2c, SII902X_SYS_CTRL_DATA,
> +&status);
> +   if (ret)
> +   return ret;
> +   } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
> +time_before(jiffies, timeout));
> +
> +   if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
> +   dev_err(dev, "Failed to acquire the i2c bus\n");
> +   return -ETIMEDOUT;
> +   }
> +
> +   ret = __sii902x_write(sii902x->i2c, SII902X_SYS_CTRL_DATA, 
> status);
> +   if (ret)
> +   return ret;
>>
>> Why do I not see a delay here? I thought the whole point of adding the i2c 
>> gate
>> was that it enabled the introduction of a dela

[PATCH 3/4] ARM: dts: r8a77470: Add QSPI support

2018-11-01 Thread Fabrizio Castro
Add QSPI[01] support to the RZ/G1C SoC specific device tree.

Signed-off-by: Fabrizio Castro 
---
 arch/arm/boot/dts/r8a77470.dtsi | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/r8a77470.dtsi
index e6407e5..04a8877 100644
--- a/arch/arm/boot/dts/r8a77470.dtsi
+++ b/arch/arm/boot/dts/r8a77470.dtsi
@@ -20,6 +20,8 @@
i2c2 = &i2c2;
i2c3 = &i2c3;
i2c4 = &i2c4;
+   spi0 = &qspi0;
+   spi1 = &qspi1;
};
 
cpus {
@@ -460,6 +462,38 @@
status = "disabled";
};
 
+   qspi0: spi@e6b1 {
+   compatible = "renesas,qspi-r8a77470", "renesas,qspi";
+   reg = <0 0xe6b1 0 0x2c>;
+   interrupts = ;
+   clocks = <&cpg CPG_MOD 918>;
+   dmas = <&dmac0 0x17>, <&dmac0 0x18>,
+  <&dmac1 0x17>, <&dmac1 0x18>;
+   dma-names = "tx", "rx", "tx", "rx";
+   power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+   num-cs = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   resets = <&cpg 918>;
+   status = "disabled";
+   };
+
+   qspi1: spi@ee20 {
+   compatible = "renesas,qspi-r8a77470", "renesas,qspi";
+   reg = <0 0xee20 0 0x2c>;
+   interrupts = ;
+   clocks = <&cpg CPG_MOD 917>;
+   dmas = <&dmac0 0xd1>, <&dmac0 0xd2>,
+  <&dmac1 0xd1>, <&dmac1 0xd2>;
+   dma-names = "tx", "rx", "tx", "rx";
+   power-domains = <&sysc R8A77470_PD_ALWAYS_ON>;
+   num-cs = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   resets = <&cpg 917>;
+   status = "disabled";
+   };
+
scif0: serial@e6e6 {
compatible = "renesas,scif-r8a77470",
 "renesas,rcar-gen2-scif", "renesas,scif";
-- 
2.7.4



[PATCH 1/4] spi: rspi: Add r8a77470 to the compatible list

2018-11-01 Thread Fabrizio Castro
Add r8a77470 to the list of examples with soctypes.
No driver change is needed as "renesas,qspi" will activate
the right code within the corresponding driver.

Signed-off-by: Fabrizio Castro 

---

As per Mark Brown's comment on patch "dt-bindings: spi: rspi: Add
r8a7744 to the compatible list", this patch doesn't come with the
"dt-bindings" prefix in the title.

 Documentation/devicetree/bindings/spi/spi-rspi.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/spi-rspi.txt 
b/Documentation/devicetree/bindings/spi/spi-rspi.txt
index fc97ad6..421722b 100644
--- a/Documentation/devicetree/bindings/spi/spi-rspi.txt
+++ b/Documentation/devicetree/bindings/spi/spi-rspi.txt
@@ -15,6 +15,7 @@ Required properties:
- "renesas,qspi-r8a7743" (RZ/G1M)
- "renesas,qspi-r8a7744" (RZ/G1N)
- "renesas,qspi-r8a7745" (RZ/G1E)
+   - "renesas,qspi-r8a77470" (RZ/G1C)
- "renesas,qspi-r8a7790" (R-Car H2)
- "renesas,qspi-r8a7791" (R-Car M2-W)
- "renesas,qspi-r8a7792" (R-Car V2H)
-- 
2.7.4



[PATCH 2/4] mtd: spi-nor: Add support for is25lp016d

2018-11-01 Thread Fabrizio Castro
The is25lp016d is found on the iwg23s from iWave, therefore
add driver support for it so that we can upstream board support.

Signed-off-by: Fabrizio Castro 
---
 drivers/mtd/spi-nor/spi-nor.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 9407ca5..85d869b 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1352,6 +1352,8 @@ static const struct flash_info spi_nor_ids[] = {
{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2, SECT_4K) },
{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+   { "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32,
+   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
-- 
2.7.4



[PATCH 4/4] ARM: dts: iwg23s-sbc: Add QSPI flash support

2018-11-01 Thread Fabrizio Castro
This commit adds QSPI flash support to the iwg23s board specific
device tree.

Signed-off-by: Fabrizio Castro 
---
 arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts 
b/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts
index 18d2263..5245a1e 100644
--- a/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts
+++ b/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts
@@ -88,6 +88,11 @@
power-source = <1800>;
};
 
+   qspi0_pins: qspi0 {
+   groups = "qspi0_ctrl", "qspi0_data2";
+   function = "qspi0";
+   };
+
scif1_pins: scif1 {
groups = "scif1_data_b";
function = "scif1";
@@ -106,6 +111,27 @@
};
 };
 
+&qspi0 {
+   pinctrl-0 = <&qspi0_pins>;
+   pinctrl-names = "default";
+
+   status = "okay";
+
+   /* WARNING - This device contains the bootloader. Handle with care. */
+   flash: flash@0 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "issi,is25lp016d", "jedec,spi-nor";
+   reg = <0>;
+   spi-max-frequency = <13300>;
+   spi-tx-bus-width = <1>;
+   spi-rx-bus-width = <1>;
+   m25p,fast-read;
+   spi-cpol;
+   spi-cpha;
+   };
+};
+
 &rwdt {
timeout-sec = <60>;
status = "okay";
-- 
2.7.4



[PATCH 0/4] Add QSPI flash support to iwg23s

2018-11-01 Thread Fabrizio Castro
Dear All,

this series includes all that is necessary to add QSPI flash
support to the iwg23s board powered by the RZ/G1C SoC (a.k.a.
r8a77470).

Thanks,
Fab

Fabrizio Castro (4):
  spi: rspi: Add r8a77470 to the compatible list
  mtd: spi-nor: Add support for is25lp016d
  ARM: dts: r8a77470: Add QSPI support
  ARM: dts: iwg23s-sbc: Add QSPI flash support

 Documentation/devicetree/bindings/spi/spi-rspi.txt |  1 +
 arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts  | 26 +
 arch/arm/boot/dts/r8a77470.dtsi| 34 ++
 drivers/mtd/spi-nor/spi-nor.c  |  2 ++
 4 files changed, 63 insertions(+)

-- 
2.7.4



Re: [RFC] drm/bridge/sii902x: Fix EDID readback

2018-11-01 Thread Mark Brown
On Wed, Oct 31, 2018 at 04:55:53PM +, Fabrizio Castro wrote:

> Having the option of using "unlocked" flavours of reads and writes
> is what we need here, but looking at drivers/base/regmap/regmap-i2c.c
> I couldn't find anything suitable for my case, maybe Mark could advise
> on this one? I am sure I overlooked something here, is there a better
> way to address this?

As Linus said you can go as far as writing your own read and write
functions if you want to.  That seems to be the easiest thing, though I
am suspicous that you're having to use the I2C framework in this way -
it doesn't sound terribly clever.  You could I guess also just have a
custom function for whatever register is doing all this stuff that just
ignores regmap and bodge things that way while using regmap as normal
for everything else.


signature.asc
Description: PGP signature


RE: [RFC] drm/bridge/sii902x: Fix EDID readback

2018-11-01 Thread Fabrizio Castro
Hello Peter,

Thank you for your feedback!

snip

> > Yeah, there is some issue with locking here, and that's coming down
> > from the fact that when we call into drm_get_edid, we implicitly call
> > i2c_transfer which ultimately locks the i2c adapter, and then calls
> > into our sii902x_i2c_bypass_select, which in turn calls into the regmap
> > functions and therefore we try and lock the same i2c adapter again,
> > driving the system into a deadlock.
> > Having the option of using "unlocked" flavours of reads and writes
> > is what we need here, but looking at drivers/base/regmap/regmap-i2c.c
> > I couldn't find anything suitable for my case, maybe Mark could advise
> > on this one? I am sure I overlooked something here, is there a better
> > way to address this?
>
> This recursive locking problem surfaces when an i2c mux is operated
> by writing commands on the same i2c bus that is muxed. When this
> happens for a typical i2c mux chip like nxp,pca9548 this can be kept
> local to that driver. However, when there are interactions with other
> parts of the kernel (e.g. if the i2c-mux is operated by gpio pins,
> and those gpio pins in turn are operated by accesses to the i2c bus
> that is muxed) this locked vs. unlocked thing would spread like
> wildfire.
>
> Since I did not like that wildfire, I came up with the "mux-locked"
> scheme. It is not appropriate everywhere, but in this case I think it
> is a perfect fit. By using it, you should be able to dodge all locking
> issues and it should be possible to keep the regmap usage as-is and the
> patch would in all likelihood be much less intrusive.
>
> For some background on "mux-locked" vs. "parent-locked" (which is what
> you have used in this RFC patch), see Documentation/i2c/i2c-topology.

The "mux-locked" implementation was the one I first tried and I discovered
it doesn't work for me, as other traffic on the parent adapter can get in the
way. What we need for this device is no other traffic on the bus during the
"select transaction deselect" procedure, that's why I went with the parent
locking. Also this device needs a delay between stop and start conditions
while addressing the monitor.

>
> There are a couple of more comments below, inline.
>

snip

> >>>
> >>> +static int sii902x_i2c_bypass_select(struct i2c_mux_core *mux, u32 
> >>> chan_id)
> >>> +{
> >>> +   struct sii902x *sii902x = i2c_mux_priv(mux);
> >>> +   struct device *dev = &sii902x->i2c->dev;
> >>> +   unsigned long timeout;
> >>> +   u8 status;
> >>> +   int ret;
> >>> +
> >>> +   ret = __sii902x_update_bits(sii902x->i2c, SII902X_SYS_CTRL_DATA,
> >>> +   SII902X_SYS_CTRL_DDC_BUS_REQ,
> >>> +   SII902X_SYS_CTRL_DDC_BUS_REQ);
> >>> +
> >>> +   timeout = jiffies +
> >>> + 
> >>> msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
> >>> +   do {
> >>> +   ret = __sii902x_read(sii902x->i2c, SII902X_SYS_CTRL_DATA,
> >>> +&status);
> >>> +   if (ret)
> >>> +   return ret;
> >>> +   } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
> >>> +time_before(jiffies, timeout));
> >>> +
> >>> +   if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
> >>> +   dev_err(dev, "Failed to acquire the i2c bus\n");
> >>> +   return -ETIMEDOUT;
> >>> +   }
> >>> +
> >>> +   ret = __sii902x_write(sii902x->i2c, SII902X_SYS_CTRL_DATA, 
> >>> status);
> >>> +   if (ret)
> >>> +   return ret;
>
> Why do I not see a delay here? I thought the whole point of adding the i2c 
> gate
> was that it enabled the introduction of a delay between opening for edid 
> reading
> and the actual edid reading?

The delay is needed between STOP and START condition while in passthrough mode.
__i2c_transfer gets called after the select callback (which enables the 
passthrough
mode), when __i2c_transfer is done it generates a STOP condition and then we 
call into
the deselect callback. We need a delay between __i2c_transfer and deselect.

>
> >>> +   return 0;
> >>> +}
> >>> +
> >>> +static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 
> >>> chan_id)
> >>> +{
> >>> +   struct sii902x *sii902x = i2c_mux_priv(mux);
> >>> +   struct device *dev = &sii902x->i2c->dev;
> >>> +   unsigned long timeout;
> >>> +   unsigned int retries;
> >>> +   u8 status;
> >>> +   int ret;
> >>> +
> >>> +   udelay(30);

Here is where we need the delay

snip

> >>> @@ -433,6 +558,22 @@ static int sii902x_probe(struct i2c_client *client,
> >>>
> >>> i2c_set_clientdata(client, sii902x);
> >>>
> >>> +   sii902x->i2cmux = i2c_mux_alloc(client->adapter, dev,
> >>> +   1, 0, I2C_MUX_GATE,
>
> Just use I2C_MUX_GATE | I2C_MUX_LOCKED for the flags argument, and you should 
> be
> able to make normal i2c accesses.