cron job: media_tree daily build: ERRORS

2016-04-20 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Thu Apr 21 04:00:20 CEST 2016
git branch: test
git hash:   e07d46e7e0da86c146f199dae76f879096bc436a
gcc version:i686-linux-gcc (GCC) 5.3.0
sparse version: v0.5.0-56-g7647c77
smatch version: v0.5.0-3413-g618cd5c
host hardware:  x86_64
host os:4.4.0-164

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-exynos: OK
linux-git-arm-mx: OK
linux-git-arm-omap: OK
linux-git-arm-omap1: OK
linux-git-arm-pxa: OK
linux-git-blackfin-bf561: OK
linux-git-i686: OK
linux-git-m32r: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
linux-2.6.36.4-i686: OK
linux-2.6.37.6-i686: OK
linux-2.6.38.8-i686: OK
linux-2.6.39.4-i686: OK
linux-3.0.60-i686: OK
linux-3.1.10-i686: OK
linux-3.2.37-i686: OK
linux-3.3.8-i686: OK
linux-3.4.27-i686: OK
linux-3.5.7-i686: OK
linux-3.6.11-i686: OK
linux-3.7.4-i686: OK
linux-3.8-i686: OK
linux-3.9.2-i686: OK
linux-3.10.1-i686: OK
linux-3.11.1-i686: OK
linux-3.12.23-i686: OK
linux-3.13.11-i686: OK
linux-3.14.9-i686: OK
linux-3.15.2-i686: OK
linux-3.16.7-i686: OK
linux-3.17.8-i686: OK
linux-3.18.7-i686: OK
linux-3.19-i686: OK
linux-4.0-i686: OK
linux-4.1.1-i686: OK
linux-4.2-i686: OK
linux-4.3-i686: OK
linux-4.4-i686: OK
linux-4.5-i686: WARNINGS
linux-4.6-rc1-i686: OK
linux-2.6.36.4-x86_64: OK
linux-2.6.37.6-x86_64: OK
linux-2.6.38.8-x86_64: OK
linux-2.6.39.4-x86_64: OK
linux-3.0.60-x86_64: OK
linux-3.1.10-x86_64: OK
linux-3.2.37-x86_64: OK
linux-3.3.8-x86_64: OK
linux-3.4.27-x86_64: OK
linux-3.5.7-x86_64: OK
linux-3.6.11-x86_64: OK
linux-3.7.4-x86_64: OK
linux-3.8-x86_64: OK
linux-3.9.2-x86_64: OK
linux-3.10.1-x86_64: OK
linux-3.11.1-x86_64: OK
linux-3.12.23-x86_64: OK
linux-3.13.11-x86_64: OK
linux-3.14.9-x86_64: OK
linux-3.15.2-x86_64: OK
linux-3.16.7-x86_64: OK
linux-3.17.8-x86_64: OK
linux-3.18.7-x86_64: OK
linux-3.19-x86_64: OK
linux-4.0-x86_64: OK
linux-4.1.1-x86_64: OK
linux-4.2-x86_64: OK
linux-4.3-x86_64: OK
linux-4.4-x86_64: OK
linux-4.5-x86_64: WARNINGS
linux-4.6-rc1-x86_64: OK
apps: OK
spec-git: OK
sparse: ERRORS
smatch: WARNINGS

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Thursday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Thursday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/media.html
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] Renesas R-Car Gen3 DU alpha and z-order support

2016-04-20 Thread Laurent Pinchart
Hello,

This patch series implement support for alpha and z-order configuration in the
R-Car DU driver for the Gen3 SoCs family.

The Gen3 SoCs delegate composition to an external IP core called VSP,
supported by a V4L2 driver. The DU driver interfaces with the VSP driver using
direct function calls. Alpha and z-order configuration is implemented in the
VSP driver, the DU driver thus just needs to pass the values using the VSP
API.

This series depends on a large VSP series that has been merged in the Linux
media git tree for v4.7. Dave, instead of merging the media tree in your tree
to pull the dependency in, it would be easier to get those two patches
upstream through the media tree. I don't expect any conflict related to the
DU driver for v4.7. If you're fine with that, could you ack the patches ?

Laurent Pinchart (2):
  drm: rcar-du: Add Z-order support for VSP planes
  drm: rcar-du: Add alpha support for VSP planes

 drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 16 
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h |  2 ++
 2 files changed, 14 insertions(+), 4 deletions(-)

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] drm: rcar-du: Add alpha support for VSP planes

2016-04-20 Thread Laurent Pinchart
Make the global alpha multiplier of VSP planes configurable through the
alpha property, exactly as for the native DU planes.

Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c 
b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index 62e9619eaea4..7a588f1f6d69 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -180,9 +180,9 @@ static void rcar_du_vsp_plane_setup(struct 
rcar_du_vsp_plane *plane)
 
WARN_ON(!pixelformat);
 
-   vsp1_du_atomic_update_zpos(plane->vsp->vsp, plane->index, pixelformat,
-  fb->pitches[0], paddr, , ,
-  state->zpos);
+   vsp1_du_atomic_update_ext(plane->vsp->vsp, plane->index, pixelformat,
+ fb->pitches[0], paddr, , ,
+ state->alpha, state->zpos);
 }
 
 static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
@@ -221,8 +221,8 @@ static void rcar_du_vsp_plane_atomic_update(struct 
drm_plane *plane,
if (plane->state->crtc)
rcar_du_vsp_plane_setup(rplane);
else
-   vsp1_du_atomic_update_zpos(rplane->vsp->vsp, rplane->index,
-  0, 0, 0, NULL, NULL, 0);
+   vsp1_du_atomic_update_ext(rplane->vsp->vsp, rplane->index,
+ 0, 0, 0, NULL, NULL, 0, 0);
 }
 
 static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] drm: rcar-du: Add Z-order support for VSP planes

2016-04-20 Thread Laurent Pinchart
Make the Z-order of VSP planes configurable through the zpos property,
exactly as for the native DU planes.

Signed-off-by: Laurent Pinchart 
---
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 16 
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h |  2 ++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c 
b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index de7ef041182b..62e9619eaea4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -180,8 +180,9 @@ static void rcar_du_vsp_plane_setup(struct 
rcar_du_vsp_plane *plane)
 
WARN_ON(!pixelformat);
 
-   vsp1_du_atomic_update(plane->vsp->vsp, plane->index, pixelformat,
- fb->pitches[0], paddr, , );
+   vsp1_du_atomic_update_zpos(plane->vsp->vsp, plane->index, pixelformat,
+  fb->pitches[0], paddr, , ,
+  state->zpos);
 }
 
 static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
@@ -220,8 +221,8 @@ static void rcar_du_vsp_plane_atomic_update(struct 
drm_plane *plane,
if (plane->state->crtc)
rcar_du_vsp_plane_setup(rplane);
else
-   vsp1_du_atomic_update(rplane->vsp->vsp, rplane->index, 0, 0, 0,
- NULL, NULL);
+   vsp1_du_atomic_update_zpos(rplane->vsp->vsp, rplane->index,
+  0, 0, 0, NULL, NULL, 0);
 }
 
 static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
@@ -269,6 +270,7 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
return;
 
state->alpha = 255;
+   state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
 
plane->state = >state;
plane->state->plane = plane;
@@ -283,6 +285,8 @@ static int rcar_du_vsp_plane_atomic_set_property(struct 
drm_plane *plane,
 
if (property == rcdu->props.alpha)
rstate->alpha = val;
+   else if (property == rcdu->props.zpos)
+   rstate->zpos = val;
else
return -EINVAL;
 
@@ -299,6 +303,8 @@ static int rcar_du_vsp_plane_atomic_get_property(struct 
drm_plane *plane,
 
if (property == rcdu->props.alpha)
*val = rstate->alpha;
+   else if (property == rcdu->props.zpos)
+   *val = rstate->zpos;
else
return -EINVAL;
 
@@ -378,6 +384,8 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
 
drm_object_attach_property(>plane.base,
   rcdu->props.alpha, 255);
+   drm_object_attach_property(>plane.base,
+  rcdu->props.zpos, 1);
}
 
return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h 
b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
index df3bf3805c69..510dcc9c6816 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -44,6 +44,7 @@ static inline struct rcar_du_vsp_plane 
*to_rcar_vsp_plane(struct drm_plane *p)
  * @state: base DRM plane state
  * @format: information about the pixel format used by the plane
  * @alpha: value of the plane alpha property
+ * @zpos: value of the plane zpos property
  */
 struct rcar_du_vsp_plane_state {
struct drm_plane_state state;
@@ -51,6 +52,7 @@ struct rcar_du_vsp_plane_state {
const struct rcar_du_format_info *format;
 
unsigned int alpha;
+   unsigned int zpos;
 };
 
 static inline struct rcar_du_vsp_plane_state *
-- 
2.7.3

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-20 Thread Antti Palosaari

On 04/20/2016 06:17 PM, Peter Rosin wrote:

Retested all the previously tested + now I tested also cx231xx with 
Hauppauge 930C HD device having eeprom other mux port and demod on the 
other port.



   [media] si2168: change the i2c gate to be mux-locked
   [media] m88ds3103: convert to use an explicit i2c mux core
   [media] rtl2830: convert to use an explicit i2c mux core
   [media] rtl2832: convert to use an explicit i2c mux core
   [media] si2168: convert to use an explicit i2c mux core
   [media] cx231xx: convert to use an explicit i2c mux core
   [media] rtl2832: change the i2c gate to be mux-locked
   [media] rtl2832_sdr: get rid of empty regmap wrappers
   [media] rtl2832: regmap is aware of lockdep, drop local locking hack


I really hope that this whole patch series will arrive asap to mainline.

regards
Antti

--
http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH/RFC 0/2] Meta-data video device type

2016-04-20 Thread Laurent Pinchart
Hello,

This RFC patch series is a first attempt at adding support for passing
statistics data to userspace using a standard API.

The two core requirements for statistics data capture is zero-copy and
decoupling statistics buffers from images buffers, in order to make statistics
data available to userspace as soon as they're captured. For those reasons the
early consensus we have reached is to use a video device node with a buffer
queue to pass statistics buffers using the V4L2 API.

This patch series extends support for statistics data to the more generic
concept of meta-data. It introduces a new video device type for meta-data,
along with a new format type and a new buffer type.

Patch 1/2 adds support for the meta-data video device type and contains
documentation that explains the concept in more details. Patch 2/2 is an
example of how a meta-data format can be defined and documented to support
histogram data generated by the Renesas R-Car VSP histogram engine (HGO).

Laurent Pinchart (2):
  v4l: Add meta-data video device type
  v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine

 Documentation/DocBook/media/v4l/dev-meta.xml   | 100 +++
 .../DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml | 307 +
 Documentation/DocBook/media/v4l/pixfmt.xml |   9 +
 Documentation/DocBook/media/v4l/v4l2.xml   |   1 +
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c  |  19 ++
 drivers/media/v4l2-core/v4l2-dev.c |  21 +-
 drivers/media/v4l2-core/v4l2-ioctl.c   |  40 +++
 drivers/media/v4l2-core/videobuf2-v4l2.c   |   3 +
 include/media/v4l2-dev.h   |   3 +-
 include/media/v4l2-ioctl.h |   8 +
 include/uapi/linux/media.h |   2 +
 include/uapi/linux/videodev2.h |  17 ++
 12 files changed, 528 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/DocBook/media/v4l/dev-meta.xml
 create mode 100644 Documentation/DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml

-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH/RFC 2/2] v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine

2016-04-20 Thread Laurent Pinchart
The format is used on the R-Car VSP1 video queues that carry
1-D histogram statistics data.

Signed-off-by: Laurent Pinchart 
---
 .../DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml | 307 +
 Documentation/DocBook/media/v4l/pixfmt.xml |   9 +
 drivers/media/v4l2-core/v4l2-ioctl.c   |   1 +
 include/uapi/linux/videodev2.h |   3 +
 4 files changed, 320 insertions(+)
 create mode 100644 Documentation/DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml

diff --git a/Documentation/DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml 
b/Documentation/DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml
new file mode 100644
index ..b40bd10695d2
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-meta-vsp1-hgo.xml
@@ -0,0 +1,307 @@
+
+  
+V4L2_META_FMT_VSP1_HGO ('VSPH')
+
+  
+  
+
+  V4L2_META_FMT_VSP1_HGO
+
+Renesas R-Car VSP1 1-D Histogram Data
+  
+  
+Description
+
+This format describes histogram data generated by the Renesas R-Car VSP1 1-D
+Histogram (HGO) engine.
+
+
+The VSP1 HGO is a histogram computation engine that can operate on RGB, YCrCb
+or HSV data. It operates on a possibly cropped and subsampled input image and
+computes the minimum, maximum and sum of all pixels as well as per-channel
+histograms.
+
+The HGO can compute histograms independently per channel, on the maximum of the
+three channels (RGB data only) or on the Y channel only (YCbCr only). It can
+additionally output the histogram with 64 or 256 bins, resulting in four
+possible modes of operation.
+  
+   
+ 
+   In 64 bins normal mode, the HGO operates
+   on the three channels independently to compute three 64-bins
+   histograms. RGB, YCbCr and HSV image formats are supported.
+ 
+   
+   
+ 
+   In 64 bins maximum mode, the HGO operates
+   on the maximum of the (R, G, B) channels to compute a single
+   64-bins histogram. Only the RGB image format is supported.
+ 
+   
+   
+ 
+   In 256 bins normal mode, the HGO operates
+   on the Y channel to compute a single 256-bins histogram. Only the
+   YCbCr image format is supported.
+ 
+   
+   
+ 
+   In 256 bins maximum mode, the HGO operates
+   on the maximum of the (R, G, B) channels to compute a single
+   256-bins histogram. Only the RGB image format is supported.
+ 
+   
+  
+
+
+
+All data is stored in memory in little endian format. Each cell in the tables
+below contains one byte.
+
+
+  VSP1 HGO Data - 64 Bins, Normal Mode (792 bytes)
+  
+   
+   
+   
+   
+   
+   
+   
+ 
+   Offset
+   Memory
+ 
+ 
+   
+   [31:24]
+   [23:16]
+   [15:8]
+   [7:0]
+ 
+   
+   
+ 
+   0
+   -
+   R/Cr/H max [7:0]
+   -
+   R/Cr/H min [7:0]
+ 
+ 
+   4
+   -
+   G/Y/S max [7:0]
+   -
+   G/Y/S min [7:0]
+ 
+ 
+   8
+   -
+   B/Cb/V max [7:0]
+   -
+   B/Cb/V min [7:0]
+ 
+ 
+   12
+   R/Cr/H sum [31:0]
+ 
+ 
+   16
+   G/Y/S sum [31:0]
+ 
+ 
+   20
+   B/Cb/V sum [31:0]
+ 
+ 
+   24
+   R/Cr/H bin 0 [31:0]
+ 
+ 
+   
+   ...
+ 
+ 
+   276
+   R/Cr/H bin 63 [31:0]
+ 
+ 
+   280
+   G/Y/S bin 0 [31:0]
+ 
+ 
+   
+   ...
+ 
+ 
+   532
+   G/Y/S bin 63 [31:0]
+ 
+ 
+   536
+   B/Cb/V bin 0 [31:0]
+ 
+ 
+   
+   ...
+ 
+ 
+   788
+   B/Cb/V bin 63 [31:0]
+ 
+   
+  
+
+
+  VSP1 HGO Data - 64 Bins, Max Mode (264 bytes)
+  
+   
+   
+   
+   
+   
+   
+   
+ 
+   Offset
+   Memory
+ 
+ 
+   
+   [31:24]
+   [23:16]
+   [15:8]
+   [7:0]
+ 
+   
+   
+ 
+   0
+   -
+   max(R,G,B) max [7:0]
+   -
+   max(R,G,B) min [7:0]
+ 
+ 
+   4
+   max(R,G,B) sum [31:0]
+ 
+ 
+   8
+   max(R,G,B) bin 0 [31:0]
+ 
+ 
+   
+   ...
+ 
+ 
+   260
+   max(R,G,B) bin 63 [31:0]
+ 
+   
+  
+
+
+  VSP1 HGO Data - 256 Bins, Normal Mode (1032 bytes)
+  

[PATCH/RFC 1/2] v4l: Add meta-data video device type

2016-04-20 Thread Laurent Pinchart
The meta-data video device is used to transfer meta-data between
userspace and kernelspace through a V4L2 buffers queue. It comes with a
new meta-data capture capability, buffer type and format description.

Signed-off-by: Laurent Pinchart 
---
 Documentation/DocBook/media/v4l/dev-meta.xml  | 100 ++
 Documentation/DocBook/media/v4l/v4l2.xml  |   1 +
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c |  19 +
 drivers/media/v4l2-core/v4l2-dev.c|  21 +-
 drivers/media/v4l2-core/v4l2-ioctl.c  |  39 ++
 drivers/media/v4l2-core/videobuf2-v4l2.c  |   3 +
 include/media/v4l2-dev.h  |   3 +-
 include/media/v4l2-ioctl.h|   8 +++
 include/uapi/linux/media.h|   2 +
 include/uapi/linux/videodev2.h|  14 
 10 files changed, 208 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/DocBook/media/v4l/dev-meta.xml

diff --git a/Documentation/DocBook/media/v4l/dev-meta.xml 
b/Documentation/DocBook/media/v4l/dev-meta.xml
new file mode 100644
index ..ddc685186015
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/dev-meta.xml
@@ -0,0 +1,100 @@
+  Meta-Data Interface
+
+  
+Experimental
+This is an  experimental 
+interface and may change in the future.
+  
+
+  
+Meta-data refers to any non-image data that supplements video frames with
+additional information. This may include statistics computed over the image
+or frame capture parameters supplied by the image source. This interface is
+intended for transfer of meta-data to userspace and control of that operation.
+  
+
+  
+Meta-data devices are accessed through character device special files named
+/dev/v4l-meta0 to /dev/v4l-meta255
+with major number 81 and dynamically allocated minor numbers 0 to 255.
+  
+
+  
+Querying Capabilities
+
+
+Devices supporting the meta-data interface set the
+V4L2_CAP_META_CAPTURE flag in the
+capabilities field of 
+returned by the  ioctl. That flag means the device can capture
+meta-data to memory.
+
+
+At least one of the read/write, streaming or asynchronous I/O methods must
+be supported.
+
+  
+
+  
+Data Format Negotiation
+
+
+The meta-data device uses the format ioctls to
+select the capture format. The meta-data buffer content format is bound to that
+selectable format. In addition to the basic
+format ioctls, the  ioctl
+must be supported as well.
+
+
+
+To use the format ioctls applications set the
+type field of a  to
+V4L2_BUF_TYPE_META_CAPTURE and use the 
+meta member of the fmt
+union as needed per the desired operation.
+Currently there are two fields, pixelformat and
+buffersize, of struct  that are
+used. Content of the pixelformat is the V4L2 FourCC
+code of the data format. The buffersize field is the
+maximum buffer size in bytes required for data transfer, set by the driver in
+order to inform applications.
+
+
+
+  struct v4l2_meta_format
+  
+
+
+  
+__u32
+pixelformat
+
+The data format or type of compression, set by the application. This is a
+little endian four character code.
+V4L2 defines meta-data formats in .
+   
+  
+  
+__u32
+buffersize
+
+Maximum size in bytes required for data. Value is set by the driver.
+   
+  
+  
+__u8
+reserved[24]
+This array is reserved for future extensions.
+Drivers and applications must set it to zero.
+  
+
+  
+
+
+
+A meta-data device may support read/write
+and/or streaming (memory mapping
+or user pointer) I/O.
+
+
+  
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml 
b/Documentation/DocBook/media/v4l/v4l2.xml
index 42e626d6c936..5c83b5d342dd 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -605,6 +605,7 @@ and discussions on the V4L mailing list.
   
   
   
+  
   
   
   
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index bacecbd68a6d..da2d836e8887 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -161,6 +161,20 @@ static inline int put_v4l2_sdr_format(struct 
v4l2_sdr_format *kp, struct v4l2_sd
return 0;
 }
 
+static inline int get_v4l2_meta_format(struct v4l2_meta_format *kp, struct 
v4l2_meta_format __user *up)
+{
+   if (copy_from_user(kp, up, sizeof(struct v4l2_meta_format)))
+   return -EFAULT;
+   return 0;
+}
+
+static inline int put_v4l2_meta_format(struct v4l2_meta_format *kp, struct 
v4l2_meta_format __user *up)
+{
+   if (copy_to_user(up, kp, sizeof(struct v4l2_meta_format)))
+   return -EFAULT;
+   return 0;
+}
+
 struct 

Re: [PATCH] [media] af9035: fix for MXL5007T devices with I2C read issues

2016-04-20 Thread Antti Palosaari

On 04/20/2016 12:13 PM, Alex Rad wrote:

On Wed, Apr 20, 2016 at 1:02 AM, Antti Palosaari  wrote:

Hello
I am not happy with that new module parameter as I cannot see real need for
it. So get rid of it.


My reasoning for this is:
1) We know of just two devices which may have the issue, but there are
probably more.  The module parameter allows a user to apply the
workaround to other devices we did not consider or test.  Should we
perhaps apply for all mxl5007t devices?


So what. It is easier for me add just new IDs to driver when problematic 
device is found than adding new module parameter which allows user to 
work-around issues and I will likely newer even hear about those issues.



2) Not all devices that match VID and PID have the issue, so it allows
the user to disable the workaround.


Due to that better to add three checks
1) it is Avermedia VID
2) it is known problematic Avermedia device PID
3) it has tuner MxL5007t

It is not surprise it is just only Avermedia which has this kind of 
problems. Not first time at all. I have added such Avermedia hacks for 
af9015 driver too and if you look af9035 there is tuner id hack - which 
was added also due to Avermedia.


Worst case there could be is some mxl5007t device having reference 
design ID. But even on that case returning fake values is pretty much OK.



regards
Antti



Better to compare both VID and PID when enabling that work-around. Driver
supports currently quite many different USB IDs and there is still small
risk duplicate PID will exists at some point enabling work-around for wrong
device.



OK.  Will wait for comments on above before a v2.

Thanks,
Alessandro


regards
Antti




On 04/15/2016 06:37 PM, Alessandro Radicati wrote:


The MXL5007T tuner will lock-up on some devices after an I2C read
transaction.  This patch adds a kernel module parameter "no_read" to work
around this issue by inhibiting such operations and emulating a 0x00
response.  The workaround is applied automatically to USB product IDs
known
to exhibit this flaw, unless the kernel module parameter is specified.

Signed-off-by: Alessandro Radicati 
---
   drivers/media/usb/dvb-usb-v2/af9035.c | 27 +++
   drivers/media/usb/dvb-usb-v2/af9035.h |  1 +
   2 files changed, 28 insertions(+)

diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c
b/drivers/media/usb/dvb-usb-v2/af9035.c
index 2638e32..8225403 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -24,6 +24,10 @@
   /* Max transfer size done by I2C transfer functions */
   #define MAX_XFER_SIZE  64

+static int dvb_usb_af9035_no_read = -1;
+module_param_named(no_read, dvb_usb_af9035_no_read, int, 0644);
+MODULE_PARM_DESC(no_read, "Emulate I2C reads for devices that do not
support them.");
+
   DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);

   static u16 af9035_checksum(const u8 *buf, size_t len)
@@ -348,6 +352,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter
*adap,

 ret = af9035_rd_regs(d, reg, [1].buf[0],
 msg[1].len);
+   } else if (state->no_read) {
+   memset(msg[1].buf, 0, msg[1].len);
+   ret = 0;
 } else {
 /* I2C write + read */
 u8 buf[MAX_XFER_SIZE];
@@ -421,6 +428,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter
*adap,
 if (msg[0].len > 40) {
 /* TODO: correct limits > 40 */
 ret = -EOPNOTSUPP;
+   } else if (state->no_read) {
+   memset(msg[0].buf, 0, msg[0].len);
+   ret = 0;
 } else {
 /* I2C read */
 u8 buf[5];
@@ -962,6 +972,23 @@ skip_eeprom:
 state->af9033_config[i].clock =
clock_lut_af9035[tmp];
 }

+   /* Some MXL5007T devices cannot properly handle tuner I2C read
ops. */
+   if (dvb_usb_af9035_no_read != -1) { /* Override with module param
*/
+   state->no_read = dvb_usb_af9035_no_read == 0 ? false :
true;
+   } else {
+   switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
+   case USB_PID_AVERMEDIA_A867:
+   case USB_PID_AVERMEDIA_TWINSTAR:
+   dev_info(>udev->dev,
+   "%s: Device may have issues with I2C read
operations. Enabling fix.\n",
+   KBUILD_MODNAME);
+   state->no_read = true;
+   break;
+   default:
+   state->no_read = false;
+   }
+   }
+
 return 0;

   err:
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h
b/drivers/media/usb/dvb-usb-v2/af9035.h
index df22001..a76dafa 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ 

Re: [PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-20 Thread Wolfram Sang

This was the diff of v6:

>  32 files changed, 1277 insertions(+), 915 deletions(-)

This is v7:

>  32 files changed, 1225 insertions(+), 916 deletions(-)

So, we gained a little overall. And while the individual drivers have a
few lines more now, I still think it is more readable.

So, thanks for doing that!

I'll give people some time for testing. I'll have a further look, too.
Hopefully, I can pick up patches 1-14 by the end of the week.

   Wolfram



signature.asc
Description: PGP signature


[PATCH] media: fix media_open() to not release lock too soon

2016-04-20 Thread Shuah Khan
media_open() releases media_devnode_lock before open is complete. Hold
the lock to call mdev->fops->open and release at the end.

Signed-off-by: Shuah Khan 
---
 drivers/media/media-devnode.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 29409f4..0934789 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -155,7 +155,7 @@ static long media_compat_ioctl(struct file *filp, unsigned 
int cmd,
 static int media_open(struct inode *inode, struct file *filp)
 {
struct media_devnode *mdev;
-   int ret;
+   int ret = 0;
 
/* Check if the media device is available. This needs to be done with
 * the media_devnode_lock held to prevent an open/unregister race:
@@ -173,7 +173,6 @@ static int media_open(struct inode *inode, struct file 
*filp)
}
/* and increase the device refcount */
get_device(>dev);
-   mutex_unlock(_devnode_lock);
 
filp->private_data = mdev;
 
@@ -182,11 +181,12 @@ static int media_open(struct inode *inode, struct file 
*filp)
if (ret) {
put_device(>dev);
filp->private_data = NULL;
-   return ret;
+   goto done;
}
}
-
-   return 0;
+done:
+   mutex_unlock(_devnode_lock);
+   return ret;
 }
 
 /* Override for the release function */
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [media] tw686x-kh: use the cached value

2016-04-20 Thread Mauro Carvalho Chehab
the dma_requests field is cached, but cache is not used:

drivers/staging/media/tw686x-kh/tw686x-kh-video.c: In function 
'tw686x_video_irq':
drivers/staging/media/tw686x-kh/tw686x-kh-video.c:622:6: warning: variable 
'requests' set but not used [-Wunused-but-set-variable]
  u32 requests;
  ^

Use the cache instead, as it seems reading it needs to be done
with spin lock taken.

Signed-off-by: Mauro Carvalho Chehab 
---
 drivers/staging/media/tw686x-kh/tw686x-kh-video.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c 
b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c
index 2fbc3cbd9eb0..0650c29f78eb 100644
--- a/drivers/staging/media/tw686x-kh/tw686x-kh-video.c
+++ b/drivers/staging/media/tw686x-kh/tw686x-kh-video.c
@@ -625,7 +625,7 @@ int tw686x_video_irq(struct tw686x_dev *dev)
requests = dev->dma_requests;
spin_unlock_irqrestore(>irq_lock, flags);
 
-   if (dev->dma_requests & dev->video_active) {
+   if (requests & dev->video_active) {
wake_up_interruptible_all(>video_thread_wait);
handled = 1;
}
-- 
2.5.5

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 6/7] media: rcar-vin: initialize EDID data

2016-04-20 Thread Ulrich Hecht
On Mon, Apr 18, 2016 at 12:13 PM, Hans Verkuil  wrote:
> Where does this EDID come from? I'm just wondering if it has been
> adjusted for the capabilities of the adv.

It's from the cobalt driver, with only the vendor ID changed.

CU
Uli
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 5/7] media: rcar-vin: add DV timings support

2016-04-20 Thread Ulrich Hecht
On Mon, Apr 18, 2016 at 12:04 PM, Hans Verkuil  wrote:
> Hi Ulrich,
>
> This isn't right: this just overwrites the adv7180 input with an HDMI input.
>
> I assume the intention is to have support for both adv7180 and HDMI input and
> to use VIDIOC_S_INPUT to select between the two.

I'm not quite sure what you mean.  The inputs are always hardwired to
one specific decoder, no switching possible.

CU
Uli
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] r8a7791-koelsch.dts: add HDMI input

2016-04-20 Thread Ulrich Hecht
On Mon, Apr 18, 2016 at 11:38 AM, Hans Verkuil  wrote:
> Add support in the dts for the HDMI input. Based on the Lager dts
> patch from Ultich Hecht.
>
> Signed-off-by: Hans Verkuil 
> ---
> Ulrich, can you add this patch to your r-car HDMI patch series?

Can do.

CU
Uli
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 22/24] [media] rtl2832: change the i2c gate to be mux-locked

2016-04-20 Thread Peter Rosin
The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the regmap overrides
that makes the i2c accesses unlocked and use plain old regmap
accesses. This also removes the need for the regmap wrappers used by
rtl2832_sdr, so deconvolute the code further and provide the regmap
handle directly instead of the wrapper functions.

Signed-off-by: Peter Rosin 
---
 Documentation/i2c/i2c-topology|   2 +-
 drivers/media/dvb-frontends/rtl2832.c | 190 --
 drivers/media/dvb-frontends/rtl2832.h |   4 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c |  13 +-
 drivers/media/dvb-frontends/rtl2832_sdr.h |   5 +-
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c   |   5 +-
 6 files changed, 37 insertions(+), 182 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 5e40802f0be2..e0aefeece551 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -55,7 +55,7 @@ imu/inv_mpu6050/  Mux-locked
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
-dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/rtl2832 Mux-locked
 dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 1b23788797b5..957523f07f61 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -153,43 +153,6 @@ static const struct rtl2832_reg_entry registers[] = {
[DVBT_REG_4MSEL]= {0x013,  0, 0},
 };
 
-/* Our regmap is bypassing I2C adapter lock, thus we do it! */
-static int rtl2832_bulk_write(struct i2c_client *client, unsigned int reg,
- const void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_update_bits(struct i2c_client *client, unsigned int reg,
-  unsigned int mask, unsigned int val)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_update_bits(dev->regmap, reg, mask, val);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
-static int rtl2832_bulk_read(struct i2c_client *client, unsigned int reg,
-void *val, size_t val_count)
-{
-   struct rtl2832_dev *dev = i2c_get_clientdata(client);
-   int ret;
-
-   i2c_lock_adapter(client->adapter);
-   ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
-   i2c_unlock_adapter(client->adapter);
-   return ret;
-}
-
 static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, int reg, u32 *val)
 {
struct i2c_client *client = dev->client;
@@ -204,7 +167,7 @@ static int rtl2832_rd_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 *val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -234,7 +197,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
len = (msb >> 3) + 1;
mask = REG_MASK(msb - lsb);
 
-   ret = rtl2832_bulk_read(client, reg_start_addr, reading, len);
+   ret = regmap_bulk_read(dev->regmap, reg_start_addr, reading, len);
if (ret)
goto err;
 
@@ -248,7 +211,7 @@ static int rtl2832_wr_demod_reg(struct rtl2832_dev *dev, 
int reg, u32 val)
for (i = 0; i < len; i++)
writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
 
-   ret = rtl2832_bulk_write(client, reg_start_addr, writing, len);
+   ret = regmap_bulk_write(dev->regmap, reg_start_addr, writing, len);
if (ret)
goto err;
 
@@ -525,7 +488,8 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
}
 
for (j = 0; j < sizeof(bw_params[0]); j++) {
-   ret = rtl2832_bulk_write(client, 0x11c + j, _params[i][j], 
1);
+   ret = regmap_bulk_write(dev->regmap,
+   0x11c + j, _params[i][j], 1);
if (ret)
goto err;
}
@@ -581,11 +545,11 @@ static int rtl2832_get_frontend(struct dvb_frontend *fe,
if (dev->sleeping)
return 0;
 
-   ret = rtl2832_bulk_read(client, 0x33c, buf, 2);
+   ret = regmap_bulk_read(dev->regmap, 0x33c, buf, 2);
if (ret)
   

[PATCH v7 06/24] i2c: i2c-mux-pca954x: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Add a mask to handle the case where not all child adapters should
cause a mux deselect to happen, now that there is a common deselect op
for all child adapters.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/muxes/i2c-mux-pca954x.c | 61 ++---
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c 
b/drivers/i2c/muxes/i2c-mux-pca954x.c
index acfcef3d4068..528e755c468f 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -60,9 +60,10 @@ enum pca_type {
 
 struct pca954x {
enum pca_type type;
-   struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
 
u8 last_chan;   /* last register value */
+   u8 deselect;
+   struct i2c_client *client;
 };
 
 struct chip_desc {
@@ -146,10 +147,10 @@ static int pca954x_reg_write(struct i2c_adapter *adap,
return ret;
 }
 
-static int pca954x_select_chan(struct i2c_adapter *adap,
-  void *client, u32 chan)
+static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct pca954x *data = i2c_get_clientdata(client);
+   struct pca954x *data = i2c_mux_priv(muxc);
+   struct i2c_client *client = data->client;
const struct chip_desc *chip = [data->type];
u8 regval;
int ret = 0;
@@ -162,21 +163,24 @@ static int pca954x_select_chan(struct i2c_adapter *adap,
 
/* Only select the channel if its different from the last channel */
if (data->last_chan != regval) {
-   ret = pca954x_reg_write(adap, client, regval);
+   ret = pca954x_reg_write(muxc->parent, client, regval);
data->last_chan = regval;
}
 
return ret;
 }
 
-static int pca954x_deselect_mux(struct i2c_adapter *adap,
-   void *client, u32 chan)
+static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct pca954x *data = i2c_get_clientdata(client);
+   struct pca954x *data = i2c_mux_priv(muxc);
+   struct i2c_client *client = data->client;
+
+   if (!(data->deselect & (1 << chan)))
+   return 0;
 
/* Deselect active channel */
data->last_chan = 0;
-   return pca954x_reg_write(adap, client, data->last_chan);
+   return pca954x_reg_write(muxc->parent, client, data->last_chan);
 }
 
 /*
@@ -191,17 +195,22 @@ static int pca954x_probe(struct i2c_client *client,
bool idle_disconnect_dt;
struct gpio_desc *gpio;
int num, force, class;
+   struct i2c_mux_core *muxc;
struct pca954x *data;
int ret;
 
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
return -ENODEV;
 
-   data = devm_kzalloc(>dev, sizeof(struct pca954x), GFP_KERNEL);
-   if (!data)
+   muxc = i2c_mux_alloc(adap, >dev,
+PCA954X_MAX_NCHANS, sizeof(*data), 0,
+pca954x_select_chan, pca954x_deselect_mux);
+   if (!muxc)
return -ENOMEM;
+   data = i2c_mux_priv(muxc);
 
-   i2c_set_clientdata(client, data);
+   i2c_set_clientdata(client, muxc);
+   data->client = client;
 
/* Get the mux out of reset if a reset GPIO is specified. */
gpio = devm_gpiod_get_optional(>dev, "reset", GPIOD_OUT_LOW);
@@ -238,16 +247,13 @@ static int pca954x_probe(struct i2c_client *client,
/* discard unconfigured channels */
break;
idle_disconnect_pd = pdata->modes[num].deselect_on_exit;
+   data->deselect |= (idle_disconnect_pd
+  || idle_disconnect_dt) << num;
}
 
-   data->virt_adaps[num] =
-   i2c_add_mux_adapter(adap, >dev, client,
-   force, num, class, pca954x_select_chan,
-   (idle_disconnect_pd || idle_disconnect_dt)
-   ? pca954x_deselect_mux : NULL);
+   ret = i2c_mux_add_adapter(muxc, force, num, class);
 
-   if (data->virt_adaps[num] == NULL) {
-   ret = -ENODEV;
+   if (ret) {
dev_err(>dev,
"failed to register multiplexed adapter"
" %d as bus %d\n", num, force);
@@ -263,23 +269,15 @@ static int pca954x_probe(struct i2c_client *client,
return 0;
 
 virt_reg_failed:
-   for (num--; num >= 0; num--)
-   i2c_del_mux_adapter(data->virt_adaps[num]);
+   i2c_mux_del_adapters(muxc);
return ret;
 }
 
 static int pca954x_remove(struct i2c_client *client)
 

[PATCH v7 16/24] i2c: allow adapter drivers to override the adapter locking

2016-04-20 Thread Peter Rosin
Add i2c_lock_bus() and i2c_unlock_bus(), which call the new lock_bus and
unlock_bus ops in the adapter. These funcs/ops take an additional flags
argument that indicates for what purpose the adapter is locked.

There are two flags, I2C_LOCK_ADAPTER and I2C_LOCK_SEGMENT, but they are
both implemented the same. For now. Locking the adapter means that the
whole bus is locked, locking the segment means that only the current bus
segment is locked (i.e. i2c traffic on the parent side of mux is still
allowed even if the child side of the mux is locked.

Also support a trylock_bus op (but no function to call it, as it is not
expected to be needed outside of the i2c core).

Implement i2c_lock_adapter/i2c_unlock_adapter in terms of the new locking
scheme (i.e. lock with the I2C_LOCK_ADAPTER flag).

Annotate some of the locking with explicit I2C_LOCK_SEGMENT flags.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/i2c-core.c | 46 --
 include/linux/i2c.h| 28 ++--
 2 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0f2f8484e8ec..21f46d011c33 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -960,10 +960,12 @@ static int i2c_check_addr_busy(struct i2c_adapter 
*adapter, int addr)
 }
 
 /**
- * i2c_lock_adapter - Get exclusive access to an I2C bus segment
+ * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
+ * locks only this branch in the adapter tree
  */
-void i2c_lock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, int flags)
 {
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
@@ -972,27 +974,30 @@ void i2c_lock_adapter(struct i2c_adapter *adapter)
else
rt_mutex_lock(>bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_lock_adapter);
 
 /**
- * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment
+ * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT
+ * trylocks only this branch in the adapter tree
  */
-static int i2c_trylock_adapter(struct i2c_adapter *adapter)
+static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter, int flags)
 {
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
if (parent)
-   return i2c_trylock_adapter(parent);
+   return parent->trylock_bus(parent, flags);
else
return rt_mutex_trylock(>bus_lock);
 }
 
 /**
- * i2c_unlock_adapter - Release exclusive access to an I2C bus segment
+ * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
+ * unlocks only this branch in the adapter tree
  */
-void i2c_unlock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter, int flags)
 {
struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
 
@@ -1001,7 +1006,6 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter)
else
rt_mutex_unlock(>bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
 struct i2c_client *client)
@@ -1547,6 +1551,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return -EINVAL;
}
 
+   if (!adap->lock_bus) {
+   adap->lock_bus = i2c_adapter_lock_bus;
+   adap->trylock_bus = i2c_adapter_trylock_bus;
+   adap->unlock_bus = i2c_adapter_unlock_bus;
+   }
+
rt_mutex_init(>bus_lock);
mutex_init(>userspace_clients_lock);
INIT_LIST_HEAD(>userspace_clients);
@@ -2315,16 +2325,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct 
i2c_msg *msgs, int num)
 #endif
 
if (in_atomic() || irqs_disabled()) {
-   ret = i2c_trylock_adapter(adap);
+   ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
-   i2c_lock_adapter(adap);
+   i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
}
 
ret = __i2c_transfer(adap, msgs, num);
-   i2c_unlock_adapter(adap);
+   i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
 
return ret;
} else {
@@ -3099,7 +3109,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, 
unsigned short flags,
flags &= 

[PATCH v7 19/24] i2c-mux: document i2c muxes and elaborate on parent-/mux-locked muxes

2016-04-20 Thread Peter Rosin
Signed-off-by: Peter Rosin 
---
 Documentation/i2c/i2c-topology | 370 +
 MAINTAINERS|   1 +
 2 files changed, 371 insertions(+)
 create mode 100644 Documentation/i2c/i2c-topology

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
new file mode 100644
index ..27bfd682808d
--- /dev/null
+++ b/Documentation/i2c/i2c-topology
@@ -0,0 +1,370 @@
+I2C topology
+
+
+There are a couple of reasons for building more complex i2c topologies
+than a straight-forward i2c bus with one adapter and one or more devices.
+
+1. A mux may be needed on the bus to prevent address collisions.
+
+2. The bus may be accessible from some external bus master, and arbitration
+   may be needed to determine if it is ok to access the bus.
+
+3. A device (particularly RF tuners) may want to avoid the digital noise
+   from the i2c bus, at least most of the time, and sits behind a gate
+   that has to be operated before the device can be accessed.
+
+Etc
+
+These constructs are represented as i2c adapter trees by Linux, where
+each adapter has a parent adapter (except the root adapter) and zero or
+more child adapters. The root adapter is the actual adapter that issues
+i2c transfers, and all adapters with a parent are part of an "i2c-mux"
+object (quoted, since it can also be an arbitrator or a gate).
+
+Depending of the particular mux driver, something happens when there is
+an i2c transfer on one of its child adapters. The mux driver can
+obviously operate a mux, but it can also do arbitration with an external
+bus master or open a gate. The mux driver has two operations for this,
+select and deselect. select is called before the transfer and (the
+optional) deselect is called after the transfer.
+
+
+Locking
+===
+
+There are two variants of locking available to i2c muxes, they can be
+mux-locked or parent-locked muxes. As is evident from below, it can be
+useful to know if a mux is mux-locked or if it is parent-locked. The
+following list was correct at the time of writing:
+
+In drivers/i2c/muxes/
+i2c-arb-gpio-challengeParent-locked
+i2c-mux-gpio  Normally parent-locked, mux-locked iff
+  all involved gpio pins are controlled by the
+  same i2c root adapter that they mux.
+i2c-mux-pca9541   Parent-locked
+i2c-mux-pca954x   Parent-locked
+i2c-mux-pinctrl   Normally parent-locked, mux-locked iff
+  all involved pinctrl devices are controlled
+  by the same i2c root adapter that they mux.
+i2c-mux-reg   Parent-locked
+
+In drivers/iio/
+imu/inv_mpu6050/  Parent-locked
+
+In drivers/media/
+dvb-frontends/m88ds3103   Parent-locked
+dvb-frontends/rtl2830 Parent-locked
+dvb-frontends/rtl2832 Parent-locked
+dvb-frontends/si2168  Parent-locked
+usb/cx231xx/  Parent-locked
+
+
+Mux-locked muxes
+
+
+Mux-locked muxes does not lock the entire parent adapter during the
+full select-transfer-deselect transaction, only the muxes on the parent
+adapter are locked. Mux-locked muxes are mostly interesting if the
+select and/or deselect operations must use i2c transfers to complete
+their tasks. Since the parent adapter is not fully locked during the
+full transaction, unrelated i2c transfers may interleave the different
+stages of the transaction. This has the benefit that the mux driver
+may be easier and cleaner to implement, but it has some caveats.
+
+ML1. If you build a topology with a mux-locked mux being the parent
+ of a parent-locked mux, this might break the expectation from the
+ parent-locked mux that the root adapter is locked during the
+ transaction.
+
+ML2. It is not safe to build arbitrary topologies with two (or more)
+ mux-locked muxes that are not siblings, when there are address
+ collisions between the devices on the child adapters of these
+ non-sibling muxes.
+
+ I.e. the select-transfer-deselect transaction targeting e.g. device
+ address 0x42 behind mux-one may be interleaved with a similar
+ operation targeting device address 0x42 behind mux-two. The
+ intension with such a topology would in this hypothetical example
+ be that mux-one and mux-two should not be selected simultaneously,
+ but mux-locked muxes do not guarantee that in all topologies.
+
+ML3. A mux-locked mux cannot be used by a driver for auto-closing
+ gates/muxes, i.e. something that closes automatically after a given
+ number (one, in most cases) of i2c transfers. Unrelated i2c transfers
+ may creep in and close prematurely.
+
+ML4. If any non-i2c operation in the mux driver changes the i2c mux state,
+ the driver has to lock the root adapter during that operation.
+ Otherwise garbage may appear on the bus as seen from devices
+ behind the mux, when an unrelated i2c 

[PATCH v7 11/24] [media] rtl2832: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Reviewed-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 drivers/media/dvb-frontends/rtl2832.c  | 25 ++---
 drivers/media/dvb-frontends/rtl2832_priv.h |  2 +-
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 7c96f7679669..1b23788797b5 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -847,9 +847,9 @@ err:
dev_dbg(>dev, "failed=%d\n", ret);
 }
 
-static int rtl2832_select(struct i2c_adapter *adap, void *mux_priv, u32 
chan_id)
+static int rtl2832_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct rtl2832_dev *dev = mux_priv;
+   struct rtl2832_dev *dev = i2c_mux_priv(muxc);
struct i2c_client *client = dev->client;
int ret;
 
@@ -870,10 +870,9 @@ err:
return ret;
 }
 
-static int rtl2832_deselect(struct i2c_adapter *adap, void *mux_priv,
-   u32 chan_id)
+static int rtl2832_deselect(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct rtl2832_dev *dev = mux_priv;
+   struct rtl2832_dev *dev = i2c_mux_priv(muxc);
 
schedule_delayed_work(>i2c_gate_work, usecs_to_jiffies(100));
return 0;
@@ -1059,7 +1058,7 @@ static struct i2c_adapter *rtl2832_get_i2c_adapter(struct 
i2c_client *client)
struct rtl2832_dev *dev = i2c_get_clientdata(client);
 
dev_dbg(>dev, "\n");
-   return dev->i2c_adapter_tuner;
+   return dev->muxc->adapter[0];
 }
 
 static int rtl2832_slave_ts_ctrl(struct i2c_client *client, bool enable)
@@ -1242,12 +1241,16 @@ static int rtl2832_probe(struct i2c_client *client,
goto err_regmap_exit;
 
/* create muxed i2c adapter for demod tuner bus */
-   dev->i2c_adapter_tuner = i2c_add_mux_adapter(i2c, >dev, dev,
-   0, 0, 0, rtl2832_select, rtl2832_deselect);
-   if (dev->i2c_adapter_tuner == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_alloc(i2c, >dev, 1, 0, 0,
+ rtl2832_select, rtl2832_deselect);
+   if (!dev->muxc) {
+   ret = -ENOMEM;
goto err_regmap_exit;
}
+   dev->muxc->priv = dev;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_regmap_exit;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
@@ -1282,7 +1285,7 @@ static int rtl2832_remove(struct i2c_client *client)
 
cancel_delayed_work_sync(>i2c_gate_work);
 
-   i2c_del_mux_adapter(dev->i2c_adapter_tuner);
+   i2c_mux_del_adapters(dev->muxc);
 
regmap_exit(dev->regmap);
 
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index 6b875f462f8b..d8f97d14f6fd 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -36,7 +36,7 @@ struct rtl2832_dev {
struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
-   struct i2c_adapter *i2c_adapter_tuner;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
enum fe_status fe_status;
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 21/24] [media] si2168: change the i2c gate to be mux-locked

2016-04-20 Thread Peter Rosin
From: Antti Palosaari 

The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
i2c accesses unlocked. But add a mutex so that firmware commands are
still serialized.

Signed-off-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/media/dvb-frontends/si2168.c  | 83 ---
 drivers/media/dvb-frontends/si2168_priv.h |  1 +
 3 files changed, 22 insertions(+), 64 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 69b008518454..5e40802f0be2 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -56,7 +56,7 @@ In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
 dvb-frontends/rtl2830 Parent-locked
 dvb-frontends/rtl2832 Parent-locked
-dvb-frontends/si2168  Parent-locked
+dvb-frontends/si2168  Mux-locked
 usb/cx231xx/  Parent-locked
 
 
diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 5583827c386e..108a069fa1ae 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -18,53 +18,23 @@
 
 static const struct dvb_frontend_ops si2168_ops;
 
-/* Own I2C adapter locking is needed because of I2C gate logic. */
-static int si2168_i2c_master_send_unlocked(const struct i2c_client *client,
-  const char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = 0,
-   .len = count,
-   .buf = (char *)buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, , 1);
-   return (ret == 1) ? count : ret;
-}
-
-static int si2168_i2c_master_recv_unlocked(const struct i2c_client *client,
-  char *buf, int count)
-{
-   int ret;
-   struct i2c_msg msg = {
-   .addr = client->addr,
-   .flags = I2C_M_RD,
-   .len = count,
-   .buf = buf,
-   };
-
-   ret = __i2c_transfer(client->adapter, , 1);
-   return (ret == 1) ? count : ret;
-}
-
 /* execute firmware command */
-static int si2168_cmd_execute_unlocked(struct i2c_client *client,
-  struct si2168_cmd *cmd)
+static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
 {
+   struct si2168_dev *dev = i2c_get_clientdata(client);
int ret;
unsigned long timeout;
 
+   mutex_lock(>i2c_mutex);
+
if (cmd->wlen) {
/* write cmd and args for firmware */
-   ret = si2168_i2c_master_send_unlocked(client, cmd->args,
- cmd->wlen);
+   ret = i2c_master_send(client, cmd->args, cmd->wlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
@@ -73,13 +43,12 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
#define TIMEOUT 70
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
while (!time_after(jiffies, timeout)) {
-   ret = si2168_i2c_master_recv_unlocked(client, cmd->args,
- cmd->rlen);
+   ret = i2c_master_recv(client, cmd->args, cmd->rlen);
if (ret < 0) {
-   goto err;
+   goto err_mutex_unlock;
} else if (ret != cmd->rlen) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
/* firmware ready? */
@@ -94,32 +63,23 @@ static int si2168_cmd_execute_unlocked(struct i2c_client 
*client,
/* error bit set? */
if ((cmd->args[0] >> 6) & 0x01) {
ret = -EREMOTEIO;
-   goto err;
+   goto err_mutex_unlock;
}
 
if (!((cmd->args[0] >> 7) & 0x01)) {
ret = -ETIMEDOUT;
-   goto err;
+   goto err_mutex_unlock;
}
}
 
+   mutex_unlock(>i2c_mutex);
return 0;
-err:
+err_mutex_unlock:
+   mutex_unlock(>i2c_mutex);
dev_dbg(>dev, "failed=%d\n", ret);
return ret;
 }

[PATCH v7 09/24] [media] m88ds3103: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Reviewed-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 drivers/media/dvb-frontends/m88ds3103.c  | 19 +++
 drivers/media/dvb-frontends/m88ds3103_priv.h |  2 +-
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/media/dvb-frontends/m88ds3103.c 
b/drivers/media/dvb-frontends/m88ds3103.c
index 76883600ec6f..5557ef8fc704 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1251,9 +1251,9 @@ static void m88ds3103_release(struct dvb_frontend *fe)
i2c_unregister_device(client);
 }
 
-static int m88ds3103_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int m88ds3103_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct m88ds3103_dev *dev = mux_priv;
+   struct m88ds3103_dev *dev = i2c_mux_priv(muxc);
struct i2c_client *client = dev->client;
int ret;
struct i2c_msg msg = {
@@ -1374,7 +1374,7 @@ static struct i2c_adapter 
*m88ds3103_get_i2c_adapter(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   return dev->i2c_adapter;
+   return dev->muxc->adapter[0];
 }
 
 static int m88ds3103_probe(struct i2c_client *client,
@@ -1467,13 +1467,16 @@ static int m88ds3103_probe(struct i2c_client *client,
goto err_kfree;
 
/* create mux i2c adapter for tuner */
-   dev->i2c_adapter = i2c_add_mux_adapter(client->adapter, >dev,
-  dev, 0, 0, 0, m88ds3103_select,
-  NULL);
-   if (dev->i2c_adapter == NULL) {
+   dev->muxc = i2c_mux_alloc(client->adapter, >dev, 1, 0, 0,
+ m88ds3103_select, NULL);
+   if (!dev->muxc) {
ret = -ENOMEM;
goto err_kfree;
}
+   dev->muxc->priv = dev;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_kfree;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
@@ -1502,7 +1505,7 @@ static int m88ds3103_remove(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   i2c_del_mux_adapter(dev->i2c_adapter);
+   i2c_mux_del_adapters(dev->muxc);
 
kfree(dev);
return 0;
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h 
b/drivers/media/dvb-frontends/m88ds3103_priv.h
index eee8c22c51ec..c5b4e177c6ea 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -42,7 +42,7 @@ struct m88ds3103_dev {
enum fe_status fe_status;
u32 dvbv3_ber; /* for old DVBv3 API read_ber */
bool warm; /* FW running */
-   struct i2c_adapter *i2c_adapter;
+   struct i2c_mux_core *muxc;
/* auto detect chip id to do different config */
u8 chip_id;
/* main mclk is calculated for M88RS6000 dynamically */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 20/24] iio: imu: inv_mpu6050: change the i2c gate to be mux-locked

2016-04-20 Thread Peter Rosin
The root i2c adapter lock is then no longer held by the i2c mux during
accesses behind the i2c gate, and such accesses need to take that lock
just like any other ordinary i2c accesses do.

So, declare the i2c gate mux-locked, and zap the code that makes the
unlocked i2c accesses and just use ordinary regmap_write accesses.

This also happens to fix the deadlock described in
http://patchwork.ozlabs.org/patch/584776/ authored by
Adriana Reus  and submitted by
Daniel Baluta 

--8<--
iio: imu: inv_mpu6050: Fix deadlock between i2c adapter lock and mpu lock

This deadlock occurs if the accel/gyro and the sensor on the auxiliary
I2C (in my setup it's an ak8975) are working at the same time.

Scenario:

  T1T2
   
inv_mpu6050_read_fifo  aux sensor op (eg. ak8975_read_raw)
| |
mutex_lock(_dev->mlock)   i2c_transfer
| |
i2c transaction i2c adapter lock
| |
i2c adapter locki2c_mux_master_xfer
  |
inv_mpu6050_select_bypass
  |
mutex_lock(_dev->mlock)

When we operate on an mpu sensor the order of locking is mpu lock
followed by the i2c adapter lock. However, when we operate the auxiliary
sensor the order of locking is the other way around.

...
--8<--

The reason this patch fixes the deadlock is that T2 does not grab the
i2c adapter lock until the very end (and grabs the newfangled i2c mux
lock where it previously grabbed the i2c adapter lock).

Acked-by: Jonathan Cameron 
Acked-by: Daniel Baluta 
Signed-off-by: Peter Rosin 
---
 Documentation/i2c/i2c-topology|  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 52 ++-
 2 files changed, 11 insertions(+), 43 deletions(-)

diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology
index 27bfd682808d..69b008518454 100644
--- a/Documentation/i2c/i2c-topology
+++ b/Documentation/i2c/i2c-topology
@@ -50,7 +50,7 @@ i2c-mux-pinctrl   Normally parent-locked, mux-locked 
iff
 i2c-mux-reg   Parent-locked
 
 In drivers/iio/
-imu/inv_mpu6050/  Parent-locked
+imu/inv_mpu6050/  Mux-locked
 
 In drivers/media/
 dvb-frontends/m88ds3103   Parent-locked
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 664a45082d39..2c4188db8634 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -24,45 +24,16 @@ static const struct regmap_config inv_mpu_regmap_config = {
.val_bits = 8,
 };
 
-/*
- * The i2c read/write needs to happen in unlocked mode. As the parent
- * adapter is common. If we use locked versions, it will fail as
- * the mux adapter will lock the parent i2c adapter, while calling
- * select/deselect functions.
- */
-static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
- u8 reg, u8 d)
-{
-   int ret;
-   u8 buf[2] = {reg, d};
-   struct i2c_msg msg[1] = {
-   {
-   .addr = client->addr,
-   .flags = 0,
-   .len = sizeof(buf),
-   .buf = buf,
-   }
-   };
-
-   ret = __i2c_transfer(client->adapter, msg, 1);
-   if (ret != 1)
-   return ret;
-
-   return 0;
-}
-
 static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = i2c_mux_priv(muxc);
-   struct iio_dev *indio_dev = dev_get_drvdata(>dev);
+   struct iio_dev *indio_dev = i2c_mux_priv(muxc);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
 
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(_dev->mlock);
if (!st->powerup_count) {
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->pwr_mgmt_1, 0);
+   ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (ret)
goto write_error;
 
@@ -71,10 +42,9 @@ static int inv_mpu6050_select_bypass(struct i2c_mux_core 
*muxc, u32 chan_id)
}
if (!ret) {
st->powerup_count++;
-   ret = inv_mpu6050_write_reg_unlocked(client,
-st->reg->int_pin_cfg,
-INV_MPU6050_INT_PIN_CFG |
- 

[PATCH v7 23/24] [media] rtl2832_sdr: get rid of empty regmap wrappers

2016-04-20 Thread Peter Rosin
Reviewed-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 drivers/media/dvb-frontends/rtl2832_sdr.c | 302 +-
 1 file changed, 132 insertions(+), 170 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 6a6b1debe277..47a480a7d46c 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -120,6 +120,7 @@ struct rtl2832_sdr_dev {
unsigned long flags;
 
struct platform_device *pdev;
+   struct regmap *regmap;
 
struct video_device vdev;
struct v4l2_device v4l2_dev;
@@ -164,47 +165,6 @@ struct rtl2832_sdr_dev {
unsigned long jiffies_next;
 };
 
-/* write multiple registers */
-static int rtl2832_sdr_wr_regs(struct rtl2832_sdr_dev *dev, u16 reg,
-   const u8 *val, int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_write(regmap, reg, val, len);
-}
-
-#if 0
-/* read multiple registers */
-static int rtl2832_sdr_rd_regs(struct rtl2832_sdr_dev *dev, u16 reg, u8 *val,
-   int len)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_bulk_read(regmap, reg, val, len);
-}
-#endif
-
-/* write single register */
-static int rtl2832_sdr_wr_reg(struct rtl2832_sdr_dev *dev, u16 reg, u8 val)
-{
-   return rtl2832_sdr_wr_regs(dev, reg, , 1);
-}
-
-/* write single register with mask */
-static int rtl2832_sdr_wr_reg_mask(struct rtl2832_sdr_dev *dev, u16 reg,
-   u8 val, u8 mask)
-{
-   struct platform_device *pdev = dev->pdev;
-   struct rtl2832_sdr_platform_data *pdata = pdev->dev.platform_data;
-   struct regmap *regmap = pdata->regmap;
-
-   return regmap_update_bits(regmap, reg, mask, val);
-}
-
 /* Private functions */
 static struct rtl2832_sdr_frame_buf *rtl2832_sdr_get_next_fill_buf(
struct rtl2832_sdr_dev *dev)
@@ -559,11 +519,11 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
 
f_sr = dev->f_adc;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x13e, "\x00\x00", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x13e, "\x00\x00", 2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x115, "\x00\x00\x00\x00", 4);
+   ret = regmap_bulk_write(dev->regmap, 0x115, "\x00\x00\x00\x00", 4);
if (ret)
goto err;
 
@@ -589,7 +549,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev *dev)
buf[1] = (u32tmp >>  8) & 0xff;
buf[2] = (u32tmp >>  0) & 0xff;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x119, buf, 3);
+   ret = regmap_bulk_write(dev->regmap, 0x119, buf, 3);
if (ret)
goto err;
 
@@ -603,15 +563,15 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
u8tmp2 = 0xcd; /* enable ADC I, ADC Q */
}
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x1b1, u8tmp1);
+   ret = regmap_write(dev->regmap, 0x1b1, u8tmp1);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x008, u8tmp2);
+   ret = regmap_write(dev->regmap, 0x008, u8tmp2);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_reg(dev, 0x006, 0x80);
+   ret = regmap_write(dev->regmap, 0x006, 0x80);
if (ret)
goto err;
 
@@ -622,168 +582,169 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_dev 
*dev)
buf[1] = (u32tmp >> 16) & 0xff;
buf[2] = (u32tmp >>  8) & 0xff;
buf[3] = (u32tmp >>  0) & 0xff;
-   ret = rtl2832_sdr_wr_regs(dev, 0x19f, buf, 4);
+   ret = regmap_bulk_write(dev->regmap, 0x19f, buf, 4);
if (ret)
goto err;
 
/* low-pass filter */
-   ret = rtl2832_sdr_wr_regs(dev, 0x11c,
-   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
-   20);
+   ret = regmap_bulk_write(dev->regmap, 0x11c,
+   
"\xca\xdc\xd7\xd8\xe0\xf2\x0e\x35\x06\x50\x9c\x0d\x71\x11\x14\x71\x74\x19\x41\xa5",
+   20);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x017, "\x11\x10", 2);
+   ret = regmap_bulk_write(dev->regmap, 0x017, "\x11\x10", 2);
if (ret)
goto err;
 
/* mode */
-   ret = rtl2832_sdr_wr_regs(dev, 0x019, "\x05", 1);
+   ret = regmap_write(dev->regmap, 0x019, 0x05);
if (ret)
goto err;
 
-   ret = rtl2832_sdr_wr_regs(dev, 0x01a, "\x1b\x16\x0d\x06\x01\xff", 6);
+   ret = regmap_bulk_write(dev->regmap, 0x01a,
+   

[PATCH v7 24/24] [media] rtl2832: regmap is aware of lockdep, drop local locking hack

2016-04-20 Thread Peter Rosin
Reviewed-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 drivers/media/dvb-frontends/rtl2832.c  | 30 --
 drivers/media/dvb-frontends/rtl2832_priv.h |  1 -
 2 files changed, 31 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832.c 
b/drivers/media/dvb-frontends/rtl2832.c
index 957523f07f61..bfb6beedd40b 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -890,32 +890,6 @@ static bool rtl2832_volatile_reg(struct device *dev, 
unsigned int reg)
return false;
 }
 
-/*
- * FIXME: Hack. Implement own regmap locking in order to silence lockdep
- * recursive lock warning. That happens when regmap I2C client calls I2C mux
- * adapter, which leads demod I2C repeater enable via demod regmap. Operation
- * takes two regmap locks recursively - but those are different regmap 
instances
- * in a two different I2C drivers, so it is not deadlock. Proper fix is to make
- * regmap aware of lockdep.
- */
-static void rtl2832_regmap_lock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_lock(>regmap_mutex);
-}
-
-static void rtl2832_regmap_unlock(void *__dev)
-{
-   struct rtl2832_dev *dev = __dev;
-   struct i2c_client *client = dev->client;
-
-   dev_dbg(>dev, "\n");
-   mutex_unlock(>regmap_mutex);
-}
-
 static struct dvb_frontend *rtl2832_get_dvb_frontend(struct i2c_client *client)
 {
struct rtl2832_dev *dev = i2c_get_clientdata(client);
@@ -1082,12 +1056,8 @@ static int rtl2832_probe(struct i2c_client *client,
dev->sleeping = true;
INIT_DELAYED_WORK(>i2c_gate_work, rtl2832_i2c_gate_work);
/* create regmap */
-   mutex_init(>regmap_mutex);
dev->regmap_config.reg_bits =  8,
dev->regmap_config.val_bits =  8,
-   dev->regmap_config.lock = rtl2832_regmap_lock,
-   dev->regmap_config.unlock = rtl2832_regmap_unlock,
-   dev->regmap_config.lock_arg = dev,
dev->regmap_config.volatile_reg = rtl2832_volatile_reg,
dev->regmap_config.max_register = 5 * 0x100,
dev->regmap_config.ranges = regmap_range_cfg,
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h 
b/drivers/media/dvb-frontends/rtl2832_priv.h
index d8f97d14f6fd..c1a8a69e9015 100644
--- a/drivers/media/dvb-frontends/rtl2832_priv.h
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -33,7 +33,6 @@
 struct rtl2832_dev {
struct rtl2832_platform_data *pdata;
struct i2c_client *client;
-   struct mutex regmap_mutex;
struct regmap_config regmap_config;
struct regmap *regmap;
struct i2c_mux_core *muxc;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 15/24] i2c-mux: drop old unused i2c-mux api

2016-04-20 Thread Peter Rosin
All i2c mux users are using an explicit i2c mux core, drop support
for implicit i2c mux cores.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/i2c-mux.c   | 63 -
 include/linux/i2c-mux.h | 15 
 2 files changed, 78 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 5ce1b0704cb5..25e9336b0e6e 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -28,12 +28,6 @@
 #include 
 
 /* multiplexer per channel data */
-struct i2c_mux_priv_old {
-   void *mux_priv;
-   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-};
-
 struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
@@ -104,53 +98,6 @@ static unsigned int i2c_mux_parent_classes(struct 
i2c_adapter *parent)
return class;
 }
 
-static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
-{
-   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
-
-   return priv->select(muxc->parent, priv->mux_priv, chan);
-}
-
-static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
-{
-   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
-
-   return priv->deselect(muxc->parent, priv->mux_priv, chan);
-}
-
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
-   struct device *mux_dev,
-   void *mux_priv, u32 force_nr, u32 chan_id,
-   unsigned int class,
-   int (*select) (struct i2c_adapter *,
-  void *, u32),
-   int (*deselect) (struct i2c_adapter *,
-void *, u32))
-{
-   struct i2c_mux_core *muxc;
-   struct i2c_mux_priv_old *priv;
-   int ret;
-
-   muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0,
-i2c_mux_select, i2c_mux_deselect);
-   if (!muxc)
-   return NULL;
-
-   priv = i2c_mux_priv(muxc);
-   priv->select = select;
-   priv->deselect = deselect;
-   priv->mux_priv = mux_priv;
-
-   ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class);
-   if (ret) {
-   devm_kfree(mux_dev, muxc);
-   return NULL;
-   }
-
-   return muxc->adapter[0];
-}
-EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
-
 struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
   struct device *dev, int max_adapters,
   int sizeof_priv, u32 flags,
@@ -305,16 +252,6 @@ void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 }
 EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap)
-{
-   struct i2c_mux_priv *priv = adap->algo_data;
-   struct i2c_mux_core *muxc = priv->muxc;
-
-   i2c_mux_del_adapters(muxc);
-   devm_kfree(muxc->dev, muxc);
-}
-EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
-
 MODULE_AUTHOR("Rodolfo Giometti ");
 MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/i2c-mux.h b/include/linux/i2c-mux.h
index 71ac1b3f4f68..2fa93fe1345e 100644
--- a/include/linux/i2c-mux.h
+++ b/include/linux/i2c-mux.h
@@ -53,20 +53,6 @@ static inline void *i2c_mux_priv(struct i2c_mux_core *muxc)
 }
 
 /*
- * Called to create a i2c bus on a multiplexed bus segment.
- * The mux_dev and chan_id parameters are passed to the select
- * and deselect callback functions to perform hardware-specific
- * mux control.
- */
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
-   struct device *mux_dev,
-   void *mux_priv, u32 force_nr, u32 chan_id,
-   unsigned int class,
-   int (*select) (struct i2c_adapter *,
-  void *mux_dev, u32 chan_id),
-   int (*deselect) (struct i2c_adapter *,
-void *mux_dev, u32 chan_id));
-/*
  * Called to create an i2c bus on a multiplexed bus segment.
  * The chan_id parameter is passed to the select and deselect
  * callback functions to perform hardware-specific mux control.
@@ -75,7 +61,6 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
u32 force_nr, u32 chan_id,
unsigned int class);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap);
 void i2c_mux_del_adapters(struct i2c_mux_core *muxc);
 
 #endif /* __KERNEL__ */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 13/24] [media] cx231xx: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/media/usb/cx231xx/cx231xx-core.c |  6 ++--
 drivers/media/usb/cx231xx/cx231xx-i2c.c  | 47 
 drivers/media/usb/cx231xx/cx231xx.h  |  4 ++-
 3 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c 
b/drivers/media/usb/cx231xx/cx231xx-core.c
index f497888d94bf..f7aac2abd783 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1304,6 +1304,9 @@ int cx231xx_dev_init(struct cx231xx *dev)
cx231xx_i2c_register(>i2c_bus[1]);
cx231xx_i2c_register(>i2c_bus[2]);
 
+   errCode = cx231xx_i2c_mux_create(dev);
+   if (errCode < 0)
+   return errCode;
cx231xx_i2c_mux_register(dev, 0);
cx231xx_i2c_mux_register(dev, 1);
 
@@ -1426,8 +1429,7 @@ EXPORT_SYMBOL_GPL(cx231xx_dev_init);
 void cx231xx_dev_uninit(struct cx231xx *dev)
 {
/* Un Initialize I2C bus */
-   cx231xx_i2c_mux_unregister(dev, 1);
-   cx231xx_i2c_mux_unregister(dev, 0);
+   cx231xx_i2c_mux_unregister(dev);
cx231xx_i2c_unregister(>i2c_bus[2]);
cx231xx_i2c_unregister(>i2c_bus[1]);
cx231xx_i2c_unregister(>i2c_bus[0]);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c 
b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index a29c345b027d..473cd3433fe5 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -557,40 +557,41 @@ int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
  * cx231xx_i2c_mux_select()
  * switch i2c master number 1 between port1 and port3
  */
-static int cx231xx_i2c_mux_select(struct i2c_adapter *adap,
-   void *mux_priv, u32 chan_id)
+static int cx231xx_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct cx231xx *dev = mux_priv;
+   struct cx231xx *dev = i2c_mux_priv(muxc);
 
return cx231xx_enable_i2c_port_3(dev, chan_id);
 }
 
+int cx231xx_i2c_mux_create(struct cx231xx *dev)
+{
+   dev->muxc = i2c_mux_alloc(>i2c_bus[1].i2c_adap, dev->dev, 2, 0, 0,
+ cx231xx_i2c_mux_select, NULL);
+   if (!dev->muxc)
+   return -ENOMEM;
+   dev->muxc->priv = dev;
+   return 0;
+}
+
 int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
 {
-   struct i2c_adapter *i2c_parent = >i2c_bus[1].i2c_adap;
-   /* what is the correct mux_dev? */
-   struct device *mux_dev = dev->dev;
-
-   dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
-   mux_dev,
-   dev /* mux_priv */,
-   0,
-   mux_no /* chan_id */,
-   0 /* class */,
-   _i2c_mux_select,
-   NULL);
-
-   if (!dev->i2c_mux_adap[mux_no])
+   int rc;
+
+   rc = i2c_mux_add_adapter(dev->muxc,
+0,
+mux_no /* chan_id */,
+0 /* class */);
+   if (rc)
dev_warn(dev->dev,
 "i2c mux %d register FAILED\n", mux_no);
 
-   return 0;
+   return rc;
 }
 
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no)
+void cx231xx_i2c_mux_unregister(struct cx231xx *dev)
 {
-   i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]);
-   dev->i2c_mux_adap[mux_no] = NULL;
+   i2c_mux_del_adapters(dev->muxc);
 }
 
 struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
@@ -603,9 +604,9 @@ struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx 
*dev, int i2c_port)
case I2C_2:
return >i2c_bus[2].i2c_adap;
case I2C_1_MUX_1:
-   return dev->i2c_mux_adap[0];
+   return dev->muxc->adapter[0];
case I2C_1_MUX_3:
-   return dev->i2c_mux_adap[1];
+   return dev->muxc->adapter[1];
default:
return NULL;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx.h 
b/drivers/media/usb/cx231xx/cx231xx.h
index 69f6d20870f5..90c867683076 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -624,6 +624,7 @@ struct cx231xx {
 
/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
struct cx231xx_i2c i2c_bus[3];
+   struct i2c_mux_core *muxc;
struct i2c_adapter *i2c_mux_adap[2];
 
unsigned int xc_fw_load_done:1;
@@ -760,8 +761,9 @@ int cx231xx_reset_analog_tuner(struct cx231xx *dev);
 void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port);
 int cx231xx_i2c_register(struct cx231xx_i2c *bus);
 int cx231xx_i2c_unregister(struct cx231xx_i2c 

[PATCH v7 14/24] of/unittest: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Acked-by: Rob Herring 
Signed-off-by: Peter Rosin 
---
 drivers/of/unittest.c | 37 -
 1 file changed, 12 insertions(+), 25 deletions(-)

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index e986e6ee52e0..c1ebbfb79453 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1692,13 +1692,7 @@ static struct i2c_driver unittest_i2c_dev_driver = {
 
 #if IS_BUILTIN(CONFIG_I2C_MUX)
 
-struct unittest_i2c_mux_data {
-   int nchans;
-   struct i2c_adapter *adap[];
-};
-
-static int unittest_i2c_mux_select_chan(struct i2c_adapter *adap,
-  void *client, u32 chan)
+static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
return 0;
 }
@@ -1706,11 +1700,11 @@ static int unittest_i2c_mux_select_chan(struct 
i2c_adapter *adap,
 static int unittest_i2c_mux_probe(struct i2c_client *client,
const struct i2c_device_id *id)
 {
-   int ret, i, nchans, size;
+   int ret, i, nchans;
struct device *dev = >dev;
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
struct device_node *np = client->dev.of_node, *child;
-   struct unittest_i2c_mux_data *stm;
+   struct i2c_mux_core *muxc;
u32 reg, max_reg;
 
dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name);
@@ -1734,25 +1728,20 @@ static int unittest_i2c_mux_probe(struct i2c_client 
*client,
return -EINVAL;
}
 
-   size = offsetof(struct unittest_i2c_mux_data, adap[nchans]);
-   stm = devm_kzalloc(dev, size, GFP_KERNEL);
-   if (!stm) {
-   dev_err(dev, "Out of memory\n");
+   muxc = i2c_mux_alloc(adap, dev, nchans, 0, 0,
+unittest_i2c_mux_select_chan, NULL);
+   if (!muxc)
return -ENOMEM;
-   }
-   stm->nchans = nchans;
for (i = 0; i < nchans; i++) {
-   stm->adap[i] = i2c_add_mux_adapter(adap, dev, client,
-   0, i, 0, unittest_i2c_mux_select_chan, NULL);
-   if (!stm->adap[i]) {
+   ret = i2c_mux_add_adapter(muxc, 0, i, 0);
+   if (ret) {
dev_err(dev, "Failed to register mux #%d\n", i);
-   for (i--; i >= 0; i--)
-   i2c_del_mux_adapter(stm->adap[i]);
+   i2c_mux_del_adapters(muxc);
return -ENODEV;
}
}
 
-   i2c_set_clientdata(client, stm);
+   i2c_set_clientdata(client, muxc);
 
return 0;
 };
@@ -1761,12 +1750,10 @@ static int unittest_i2c_mux_remove(struct i2c_client 
*client)
 {
struct device *dev = >dev;
struct device_node *np = client->dev.of_node;
-   struct unittest_i2c_mux_data *stm = i2c_get_clientdata(client);
-   int i;
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name);
-   for (i = stm->nchans - 1; i >= 0; i--)
-   i2c_del_mux_adapter(stm->adap[i]);
+   i2c_mux_del_adapters(muxc);
return 0;
 }
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 12/24] [media] si2168: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Reviewed-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 drivers/media/dvb-frontends/si2168.c  | 25 +++--
 drivers/media/dvb-frontends/si2168_priv.h |  2 +-
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index 821a8f481507..5583827c386e 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -615,9 +615,9 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe,
  * We must use unlocked I2C I/O because I2C adapter lock is already taken
  * by the caller (usually tuner driver).
  */
-static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int si2168_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
int ret;
struct si2168_cmd cmd;
 
@@ -635,9 +635,9 @@ err:
return ret;
 }
 
-static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
+static int si2168_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
int ret;
struct si2168_cmd cmd;
 
@@ -709,17 +709,22 @@ static int si2168_probe(struct i2c_client *client,
}
 
/* create mux i2c adapter for tuner */
-   dev->adapter = i2c_add_mux_adapter(client->adapter, >dev,
-   client, 0, 0, 0, si2168_select, si2168_deselect);
-   if (dev->adapter == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_alloc(client->adapter, >dev,
+ 1, 0, 0,
+ si2168_select, si2168_deselect);
+   if (!dev->muxc) {
+   ret = -ENOMEM;
goto err_kfree;
}
+   dev->muxc->priv = client;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_kfree;
 
/* create dvb_frontend */
memcpy(>fe.ops, _ops, sizeof(struct dvb_frontend_ops));
dev->fe.demodulator_priv = client;
-   *config->i2c_adapter = dev->adapter;
+   *config->i2c_adapter = dev->muxc->adapter[0];
*config->fe = >fe;
dev->ts_mode = config->ts_mode;
dev->ts_clock_inv = config->ts_clock_inv;
@@ -743,7 +748,7 @@ static int si2168_remove(struct i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   i2c_del_mux_adapter(dev->adapter);
+   i2c_mux_del_adapters(dev->muxc);
 
dev->fe.ops.release = NULL;
dev->fe.demodulator_priv = NULL;
diff --git a/drivers/media/dvb-frontends/si2168_priv.h 
b/drivers/media/dvb-frontends/si2168_priv.h
index c07e6fe2cb10..165bf1412063 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -29,7 +29,7 @@
 
 /* state struct */
 struct si2168_dev {
-   struct i2c_adapter *adapter;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
enum fe_delivery_system delivery_system;
enum fe_status fe_status;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 17/24] i2c: muxes always lock the parent adapter

2016-04-20 Thread Peter Rosin
Instead of checking for i2c parent adapters for every lock/unlock, simply
override the locking for muxes to always lock/unlock the parent adapter
directly.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/i2c-core.c | 21 +++--
 drivers/i2c/i2c-mux.c  | 27 +++
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 21f46d011c33..5314434c2b5d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -967,12 +967,7 @@ static int i2c_check_addr_busy(struct i2c_adapter 
*adapter, int addr)
  */
 static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, int flags)
 {
-   struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-   if (parent)
-   i2c_lock_adapter(parent);
-   else
-   rt_mutex_lock(>bus_lock);
+   rt_mutex_lock(>bus_lock);
 }
 
 /**
@@ -983,12 +978,7 @@ static void i2c_adapter_lock_bus(struct i2c_adapter 
*adapter, int flags)
  */
 static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter, int flags)
 {
-   struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-   if (parent)
-   return parent->trylock_bus(parent, flags);
-   else
-   return rt_mutex_trylock(>bus_lock);
+   return rt_mutex_trylock(>bus_lock);
 }
 
 /**
@@ -999,12 +989,7 @@ static int i2c_adapter_trylock_bus(struct i2c_adapter 
*adapter, int flags)
  */
 static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter, int flags)
 {
-   struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-   if (parent)
-   i2c_unlock_adapter(parent);
-   else
-   rt_mutex_unlock(>bus_lock);
+   rt_mutex_unlock(>bus_lock);
 }
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 25e9336b0e6e..dc958eebdbb4 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -98,6 +98,30 @@ static unsigned int i2c_mux_parent_classes(struct 
i2c_adapter *parent)
return class;
 }
 
+static void i2c_parent_lock_bus(struct i2c_adapter *adapter, int flags)
+{
+   struct i2c_mux_priv *priv = adapter->algo_data;
+   struct i2c_adapter *parent = priv->muxc->parent;
+
+   parent->lock_bus(parent, flags);
+}
+
+static int i2c_parent_trylock_bus(struct i2c_adapter *adapter, int flags)
+{
+   struct i2c_mux_priv *priv = adapter->algo_data;
+   struct i2c_adapter *parent = priv->muxc->parent;
+
+   return parent->trylock_bus(parent, flags);
+}
+
+static void i2c_parent_unlock_bus(struct i2c_adapter *adapter, int flags)
+{
+   struct i2c_mux_priv *priv = adapter->algo_data;
+   struct i2c_adapter *parent = priv->muxc->parent;
+
+   parent->unlock_bus(parent, flags);
+}
+
 struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
   struct device *dev, int max_adapters,
   int sizeof_priv, u32 flags,
@@ -165,6 +189,9 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
priv->adap.retries = parent->retries;
priv->adap.timeout = parent->timeout;
priv->adap.quirks = parent->quirks;
+   priv->adap.lock_bus = i2c_parent_lock_bus;
+   priv->adap.trylock_bus = i2c_parent_trylock_bus;
+   priv->adap.unlock_bus = i2c_parent_unlock_bus;
 
/* Sanity check on class */
if (i2c_mux_parent_classes(parent) & class)
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 18/24] i2c-mux: relax locking of the top i2c adapter during mux-locked muxing

2016-04-20 Thread Peter Rosin
With a i2c topology like the following

   GPIO ---|  -- BAT1
|  v /
   I2C  -+--+ MUX
 |   \
   EEPROM -- BAT2

there is a locking problem with the GPIO controller since it is a client
on the same i2c bus that it muxes. Transfers to the mux clients (e.g. BAT1)
will lock the whole i2c bus prior to attempting to switch the mux to the
correct i2c segment. In the above case, the GPIO device is an I/O expander
with an i2c interface, and since the GPIO subsystem knows nothing (and
rightfully so) about the lockless needs of the i2c mux code, this results
in a deadlock when the GPIO driver issues i2c transfers to modify the
mux.

So, observing that while it is needed to have the i2c bus locked during the
actual MUX update in order to avoid random garbage on the slave side, it
is not strictly a must to have it locked over the whole sequence of a full
select-transfer-deselect mux client operation. The mux itself needs to be
locked, so transfers to clients behind the mux are serialized, and the mux
needs to be stable during all i2c traffic (otherwise individual mux slave
segments might see garbage, or worse).

Introduce this new locking concept as "mux-locked" muxes, and call the
pre-existing mux locking scheme "parent-locked".

Modify the i2c mux locking so that muxes that are "mux-locked" locks only
the muxes on the parent adapter instead of the whole i2c bus when there is
a transfer to the slave side of the mux. This lock serializes transfers to
the slave side of the muxes on the parent adapter.

Add code to i2c-mux-gpio and i2c-mux-pinctrl that checks if all involved
gpio/pinctrl devices have a parent that is an i2c adapter in the same
adapter tree that is muxed, and request a "mux-locked mux" if that is the
case.

Modify the select-transfer-deselect code for "mux-locked" muxes so
that each of the select-transfer-deselect ops locks the mux parent
adapter individually.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/i2c-core.c  |   1 +
 drivers/i2c/i2c-mux.c   | 152 +---
 drivers/i2c/muxes/i2c-mux-gpio.c|  18 +
 drivers/i2c/muxes/i2c-mux-pinctrl.c |  38 +
 include/linux/i2c-mux.h |   6 ++
 include/linux/i2c.h |   1 +
 6 files changed, 203 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 5314434c2b5d..53514ea314cd 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1543,6 +1543,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
}
 
rt_mutex_init(>bus_lock);
+   rt_mutex_init(>mux_lock);
mutex_init(>userspace_clients_lock);
INIT_LIST_HEAD(>userspace_clients);
 
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index dc958eebdbb4..364319c3c95f 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -35,6 +35,25 @@ struct i2c_mux_priv {
u32 chan_id;
 };
 
+static int __i2c_mux_master_xfer(struct i2c_adapter *adap,
+struct i2c_msg msgs[], int num)
+{
+   struct i2c_mux_priv *priv = adap->algo_data;
+   struct i2c_mux_core *muxc = priv->muxc;
+   struct i2c_adapter *parent = muxc->parent;
+   int ret;
+
+   /* Switch to the right mux port and perform the transfer. */
+
+   ret = muxc->select(muxc, priv->chan_id);
+   if (ret >= 0)
+   ret = __i2c_transfer(parent, msgs, num);
+   if (muxc->deselect)
+   muxc->deselect(muxc, priv->chan_id);
+
+   return ret;
+}
+
 static int i2c_mux_master_xfer(struct i2c_adapter *adap,
   struct i2c_msg msgs[], int num)
 {
@@ -47,7 +66,29 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
-   ret = __i2c_transfer(parent, msgs, num);
+   ret = i2c_transfer(parent, msgs, num);
+   if (muxc->deselect)
+   muxc->deselect(muxc, priv->chan_id);
+
+   return ret;
+}
+
+static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
+   u16 addr, unsigned short flags,
+   char read_write, u8 command,
+   int size, union i2c_smbus_data *data)
+{
+   struct i2c_mux_priv *priv = adap->algo_data;
+   struct i2c_mux_core *muxc = priv->muxc;
+   struct i2c_adapter *parent = muxc->parent;
+   int ret;
+
+   /* Select the right mux port and perform the transfer. */
+
+   ret = muxc->select(muxc, priv->chan_id);
+   if (ret >= 0)
+   ret = parent->algo->smbus_xfer(parent, addr, flags,
+   read_write, command, size, data);
if (muxc->deselect)
muxc->deselect(muxc, priv->chan_id);
 
@@ -68,8 +109,8 @@ static int 

[PATCH v7 03/24] i2c: i2c-mux-pinctrl: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/muxes/i2c-mux-pinctrl.c | 83 ++---
 1 file changed, 30 insertions(+), 53 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c 
b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index b5a982ba8898..1b8dc711815e 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -26,34 +26,29 @@
 #include 
 
 struct i2c_mux_pinctrl {
-   struct device *dev;
struct i2c_mux_pinctrl_platform_data *pdata;
struct pinctrl *pinctrl;
struct pinctrl_state **states;
struct pinctrl_state *state_idle;
-   struct i2c_adapter *parent;
-   struct i2c_adapter **busses;
 };
 
-static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data,
- u32 chan)
+static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct i2c_mux_pinctrl *mux = data;
+   struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 
return pinctrl_select_state(mux->pinctrl, mux->states[chan]);
 }
 
-static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data,
-   u32 chan)
+static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct i2c_mux_pinctrl *mux = data;
+   struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 
return pinctrl_select_state(mux->pinctrl, mux->state_idle);
 }
 
 #ifdef CONFIG_OF
 static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
-   struct platform_device *pdev)
+   struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
int num_names, i, ret;
@@ -64,15 +59,12 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl 
*mux,
return 0;
 
mux->pdata = devm_kzalloc(>dev, sizeof(*mux->pdata), GFP_KERNEL);
-   if (!mux->pdata) {
-   dev_err(mux->dev,
-   "Cannot allocate i2c_mux_pinctrl_platform_data\n");
+   if (!mux->pdata)
return -ENOMEM;
-   }
 
num_names = of_property_count_strings(np, "pinctrl-names");
if (num_names < 0) {
-   dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+   dev_err(>dev, "Cannot parse pinctrl-names: %d\n",
num_names);
return num_names;
}
@@ -80,23 +72,22 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl 
*mux,
mux->pdata->pinctrl_states = devm_kzalloc(>dev,
sizeof(*mux->pdata->pinctrl_states) * num_names,
GFP_KERNEL);
-   if (!mux->pdata->pinctrl_states) {
-   dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
+   if (!mux->pdata->pinctrl_states)
return -ENOMEM;
-   }
 
for (i = 0; i < num_names; i++) {
ret = of_property_read_string_index(np, "pinctrl-names", i,
>pdata->pinctrl_states[mux->pdata->bus_count]);
if (ret < 0) {
-   dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+   dev_err(>dev, "Cannot parse pinctrl-names: %d\n",
ret);
return ret;
}
if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
"idle")) {
if (i != num_names - 1) {
-   dev_err(mux->dev, "idle state must be last\n");
+   dev_err(>dev,
+   "idle state must be last\n");
return -EINVAL;
}
mux->pdata->pinctrl_state_idle = "idle";
@@ -107,13 +98,13 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl 
*mux,
 
adapter_np = of_parse_phandle(np, "i2c-parent", 0);
if (!adapter_np) {
-   dev_err(mux->dev, "Cannot parse i2c-parent\n");
+   dev_err(>dev, "Cannot parse i2c-parent\n");
return -ENODEV;
}
adapter = of_find_i2c_adapter_by_node(adapter_np);
of_node_put(adapter_np);
if (!adapter) {
-   dev_err(mux->dev, "Cannot find parent bus\n");
+   dev_err(>dev, "Cannot find parent bus\n");
return -EPROBE_DEFER;
}
mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
@@ -131,19 +122,15 @@ static inline int i2c_mux_pinctrl_parse_dt(struct 
i2c_mux_pinctrl *mux,
 
 static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 {
+   struct i2c_mux_core *muxc;
struct i2c_mux_pinctrl *mux;
-   int 

[PATCH v7 02/24] i2c: i2c-mux-gpio: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/muxes/i2c-mux-gpio.c | 55 
 1 file changed, 22 insertions(+), 33 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index b8e11c16d98c..f6270ee934f9 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -18,8 +18,6 @@
 #include 
 
 struct gpiomux {
-   struct i2c_adapter *parent;
-   struct i2c_adapter **adap; /* child busses */
struct i2c_mux_gpio_platform_data data;
unsigned gpio_base;
 };
@@ -33,18 +31,18 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, 
unsigned val)
val & (1 << i));
 }
 
-static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct gpiomux *mux = data;
+   struct gpiomux *mux = i2c_mux_priv(muxc);
 
i2c_mux_gpio_set(mux, chan);
 
return 0;
 }
 
-static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 
chan)
+static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct gpiomux *mux = data;
+   struct gpiomux *mux = i2c_mux_priv(muxc);
 
i2c_mux_gpio_set(mux, mux->data.idle);
 
@@ -136,19 +134,15 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
 
 static int i2c_mux_gpio_probe(struct platform_device *pdev)
 {
+   struct i2c_mux_core *muxc;
struct gpiomux *mux;
struct i2c_adapter *parent;
-   int (*deselect) (struct i2c_adapter *, void *, u32);
unsigned initial_state, gpio_base;
int i, ret;
 
mux = devm_kzalloc(>dev, sizeof(*mux), GFP_KERNEL);
-   if (!mux) {
-   dev_err(>dev, "Cannot allocate gpiomux structure");
+   if (!mux)
return -ENOMEM;
-   }
-
-   platform_set_drvdata(pdev, mux);
 
if (!dev_get_platdata(>dev)) {
ret = i2c_mux_gpio_probe_dt(mux, pdev);
@@ -180,24 +174,23 @@ static int i2c_mux_gpio_probe(struct platform_device 
*pdev)
if (!parent)
return -EPROBE_DEFER;
 
-   mux->parent = parent;
-   mux->gpio_base = gpio_base;
-
-   mux->adap = devm_kzalloc(>dev,
-sizeof(*mux->adap) * mux->data.n_values,
-GFP_KERNEL);
-   if (!mux->adap) {
-   dev_err(>dev, "Cannot allocate i2c_adapter structure");
+   muxc = i2c_mux_alloc(parent, >dev, mux->data.n_values, 0, 0,
+i2c_mux_gpio_select, NULL);
+   if (!muxc) {
ret = -ENOMEM;
goto alloc_failed;
}
+   muxc->priv = mux;
+
+   platform_set_drvdata(pdev, muxc);
+
+   mux->gpio_base = gpio_base;
 
if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = mux->data.idle;
-   deselect = i2c_mux_gpio_deselect;
+   muxc->deselect = i2c_mux_gpio_deselect;
} else {
initial_state = mux->data.values[0];
-   deselect = NULL;
}
 
for (i = 0; i < mux->data.n_gpios; i++) {
@@ -223,11 +216,8 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
unsigned int class = mux->data.classes ? mux->data.classes[i] : 
0;
 
-   mux->adap[i] = i2c_add_mux_adapter(parent, >dev, mux, nr,
-  mux->data.values[i], class,
-  i2c_mux_gpio_select, 
deselect);
-   if (!mux->adap[i]) {
-   ret = -ENODEV;
+   ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
+   if (ret) {
dev_err(>dev, "Failed to add adapter %d\n", i);
goto add_adapter_failed;
}
@@ -239,8 +229,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
return 0;
 
 add_adapter_failed:
-   for (; i > 0; i--)
-   i2c_del_mux_adapter(mux->adap[i - 1]);
+   i2c_mux_del_adapters(muxc);
i = mux->data.n_gpios;
 err_request_gpio:
for (; i > 0; i--)
@@ -253,16 +242,16 @@ alloc_failed:
 
 static int i2c_mux_gpio_remove(struct platform_device *pdev)
 {
-   struct gpiomux *mux = platform_get_drvdata(pdev);
+   struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+   struct gpiomux *mux = i2c_mux_priv(muxc);
int i;
 
-   for (i = 0; i < mux->data.n_values; i++)
-   i2c_del_mux_adapter(mux->adap[i]);
+   i2c_mux_del_adapters(muxc);
 
for (i = 0; i < 

[PATCH v7 08/24] iio: imu: inv_mpu6050: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Acked-by: Jonathan Cameron 
Signed-off-by: Peter Rosin 
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c |  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c |  1 -
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c  | 35 +++---
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  |  3 ++-
 4 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index 2771106fd650..f62b8bd9ad7e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -183,7 +183,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client 
*client)
} else
return 0; /* no secondary addr, which is OK */
}
-   st->mux_client = i2c_new_device(st->mux_adapter, );
+   st->mux_client = i2c_new_device(st->muxc->adapter[0], );
if (!st->mux_client)
return -ENODEV;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index d192953e9a38..0c2bded2b5b7 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -23,7 +23,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include "inv_mpu_iio.h"
 
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index f581256d9d4c..664a45082d39 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -15,7 +15,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include "inv_mpu_iio.h"
@@ -52,10 +51,9 @@ static int inv_mpu6050_write_reg_unlocked(struct i2c_client 
*client,
return 0;
 }
 
-static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
-u32 chan_id)
+static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
struct iio_dev *indio_dev = dev_get_drvdata(>dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
@@ -84,10 +82,9 @@ write_error:
return ret;
 }
 
-static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
-  void *mux_priv, u32 chan_id)
+static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
struct iio_dev *indio_dev = dev_get_drvdata(>dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
@@ -136,16 +133,18 @@ static int inv_mpu_probe(struct i2c_client *client,
return result;
 
st = iio_priv(dev_get_drvdata(>dev));
-   st->mux_adapter = i2c_add_mux_adapter(client->adapter,
- >dev,
- client,
- 0, 0, 0,
- inv_mpu6050_select_bypass,
- inv_mpu6050_deselect_bypass);
-   if (!st->mux_adapter) {
-   result = -ENODEV;
+   st->muxc = i2c_mux_alloc(client->adapter, >dev,
+1, 0, 0,
+inv_mpu6050_select_bypass,
+inv_mpu6050_deselect_bypass);
+   if (!st->muxc) {
+   result = -ENOMEM;
goto out_unreg_device;
}
+   st->muxc->priv = dev_get_drvdata(>dev);
+   result = i2c_mux_add_adapter(st->muxc, 0, 0, 0);
+   if (result)
+   goto out_unreg_device;
 
result = inv_mpu_acpi_create_mux_client(client);
if (result)
@@ -154,7 +153,7 @@ static int inv_mpu_probe(struct i2c_client *client,
return 0;
 
 out_del_mux:
-   i2c_del_mux_adapter(st->mux_adapter);
+   i2c_mux_del_adapters(st->muxc);
 out_unreg_device:
inv_mpu_core_remove(>dev);
return result;
@@ -162,11 +161,11 @@ out_unreg_device:
 
 static int inv_mpu_remove(struct i2c_client *client)
 {
-   struct iio_dev *indio_dev = i2c_get_clientdata(client);
+   struct iio_dev *indio_dev = dev_get_drvdata(>dev);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
inv_mpu_acpi_delete_mux_client(client);
-   i2c_del_mux_adapter(st->mux_adapter);
+   i2c_mux_del_adapters(st->muxc);
 
return inv_mpu_core_remove(>dev);
 }
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 

[PATCH v7 10/24] [media] rtl2830: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select op to be in terms of the i2c mux core instead
of the child adapter.

Reviewed-by: Antti Palosaari 
Signed-off-by: Peter Rosin 
---
 drivers/media/dvb-frontends/rtl2830.c  | 20 
 drivers/media/dvb-frontends/rtl2830_priv.h |  2 +-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2830.c 
b/drivers/media/dvb-frontends/rtl2830.c
index 3f96429af0e5..d25d1e0cd4ca 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -677,9 +677,9 @@ err:
  * adapter lock is already taken by tuner driver.
  * Gate is closed automatically after single I2C transfer.
  */
-static int rtl2830_select(struct i2c_adapter *adap, void *mux_priv, u32 
chan_id)
+static int rtl2830_select(struct i2c_mux_core *muxc, u32 chan_id)
 {
-   struct i2c_client *client = mux_priv;
+   struct i2c_client *client = i2c_mux_priv(muxc);
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
 
@@ -712,7 +712,7 @@ static struct i2c_adapter *rtl2830_get_i2c_adapter(struct 
i2c_client *client)
 
dev_dbg(>dev, "\n");
 
-   return dev->adapter;
+   return dev->muxc->adapter[0];
 }
 
 /*
@@ -865,12 +865,16 @@ static int rtl2830_probe(struct i2c_client *client,
goto err_regmap_exit;
 
/* create muxed i2c adapter for tuner */
-   dev->adapter = i2c_add_mux_adapter(client->adapter, >dev,
-   client, 0, 0, 0, rtl2830_select, NULL);
-   if (dev->adapter == NULL) {
-   ret = -ENODEV;
+   dev->muxc = i2c_mux_alloc(client->adapter, >dev, 1, 0, 0,
+ rtl2830_select, NULL);
+   if (!dev->muxc) {
+   ret = -ENOMEM;
goto err_regmap_exit;
}
+   dev->muxc->priv = client;
+   ret = i2c_mux_add_adapter(dev->muxc, 0, 0, 0);
+   if (ret)
+   goto err_regmap_exit;
 
/* create dvb frontend */
memcpy(>fe.ops, _ops, sizeof(dev->fe.ops));
@@ -903,7 +907,7 @@ static int rtl2830_remove(struct i2c_client *client)
/* stop statistics polling */
cancel_delayed_work_sync(>stat_work);
 
-   i2c_del_mux_adapter(dev->adapter);
+   i2c_mux_del_adapters(dev->muxc);
regmap_exit(dev->regmap);
kfree(dev);
 
diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h 
b/drivers/media/dvb-frontends/rtl2830_priv.h
index cf793f39a09b..da4909543da2 100644
--- a/drivers/media/dvb-frontends/rtl2830_priv.h
+++ b/drivers/media/dvb-frontends/rtl2830_priv.h
@@ -29,7 +29,7 @@ struct rtl2830_dev {
struct rtl2830_platform_data *pdata;
struct i2c_client *client;
struct regmap *regmap;
-   struct i2c_adapter *adapter;
+   struct i2c_mux_core *muxc;
struct dvb_frontend fe;
bool sleeping;
unsigned long filters;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 05/24] i2c: i2c-mux-pca9541: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/muxes/i2c-mux-pca9541.c | 58 +
 1 file changed, 27 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c 
b/drivers/i2c/muxes/i2c-mux-pca9541.c
index d0ba424adebc..3cb8af635db5 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -73,7 +73,7 @@
 #define SELECT_DELAY_LONG  1000
 
 struct pca9541 {
-   struct i2c_adapter *mux_adap;
+   struct i2c_client *client;
unsigned long select_timeout;
unsigned long arb_timeout;
 };
@@ -217,7 +217,8 @@ static const u8 pca9541_control[16] = {
  */
 static int pca9541_arbitrate(struct i2c_client *client)
 {
-   struct pca9541 *data = i2c_get_clientdata(client);
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+   struct pca9541 *data = i2c_mux_priv(muxc);
int reg;
 
reg = pca9541_reg_read(client, PCA9541_CONTROL);
@@ -285,9 +286,10 @@ static int pca9541_arbitrate(struct i2c_client *client)
return 0;
 }
 
-static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 
chan)
+static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct pca9541 *data = i2c_get_clientdata(client);
+   struct pca9541 *data = i2c_mux_priv(muxc);
+   struct i2c_client *client = data->client;
int ret;
unsigned long timeout = jiffies + ARB2_TIMEOUT;
/* give up after this time */
@@ -309,9 +311,11 @@ static int pca9541_select_chan(struct i2c_adapter *adap, 
void *client, u32 chan)
return -ETIMEDOUT;
 }
 
-static int pca9541_release_chan(struct i2c_adapter *adap,
-   void *client, u32 chan)
+static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
 {
+   struct pca9541 *data = i2c_mux_priv(muxc);
+   struct i2c_client *client = data->client;
+
pca9541_release_bus(client);
return 0;
 }
@@ -324,20 +328,13 @@ static int pca9541_probe(struct i2c_client *client,
 {
struct i2c_adapter *adap = client->adapter;
struct pca954x_platform_data *pdata = dev_get_platdata(>dev);
+   struct i2c_mux_core *muxc;
struct pca9541 *data;
int force;
-   int ret = -ENODEV;
+   int ret;
 
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
-   goto err;
-
-   data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
-   if (!data) {
-   ret = -ENOMEM;
-   goto err;
-   }
-
-   i2c_set_clientdata(client, data);
+   return -ENODEV;
 
/*
 * I2C accesses are unprotected here.
@@ -352,34 +349,33 @@ static int pca9541_probe(struct i2c_client *client,
force = 0;
if (pdata)
force = pdata->modes[0].adap_id;
-   data->mux_adap = i2c_add_mux_adapter(adap, >dev, client,
-force, 0, 0,
-pca9541_select_chan,
-pca9541_release_chan);
+   muxc = i2c_mux_alloc(adap, >dev, 1, sizeof(*data), 0,
+pca9541_select_chan, pca9541_release_chan);
+   if (!muxc)
+   return -ENOMEM;
 
-   if (data->mux_adap == NULL) {
+   data = i2c_mux_priv(muxc);
+   data->client = client;
+
+   i2c_set_clientdata(client, muxc);
+
+   ret = i2c_mux_add_adapter(muxc, force, 0, 0);
+   if (ret) {
dev_err(>dev, "failed to register master selector\n");
-   goto exit_free;
+   return ret;
}
 
dev_info(>dev, "registered master selector for I2C %s\n",
 client->name);
 
return 0;
-
-exit_free:
-   kfree(data);
-err:
-   return ret;
 }
 
 static int pca9541_remove(struct i2c_client *client)
 {
-   struct pca9541 *data = i2c_get_clientdata(client);
-
-   i2c_del_mux_adapter(data->mux_adap);
+   struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
-   kfree(data);
+   i2c_mux_del_adapters(muxc);
return 0;
 }
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 04/24] i2c: i2c-arb-gpio-challenge: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 47 +-
 1 file changed, 20 insertions(+), 27 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c 
b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 402e3a6c671a..a90bbc4037dd 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -28,8 +28,6 @@
 /**
  * struct i2c_arbitrator_data - Driver data for I2C arbitrator
  *
- * @parent: Parent adapter
- * @child: Child bus
  * @our_gpio: GPIO we'll use to claim.
  * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
  *   this then consider it released.
@@ -42,8 +40,6 @@
  */
 
 struct i2c_arbitrator_data {
-   struct i2c_adapter *parent;
-   struct i2c_adapter *child;
int our_gpio;
int our_gpio_release;
int their_gpio;
@@ -59,9 +55,9 @@ struct i2c_arbitrator_data {
  *
  * Use the GPIO-based signalling protocol; return -EBUSY if we fail.
  */
-static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 
chan)
+static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   const struct i2c_arbitrator_data *arb = data;
+   const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
unsigned long stop_retry, stop_time;
 
/* Start a round of trying to claim the bus */
@@ -93,7 +89,7 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, 
void *data, u32 chan)
/* Give up, release our claim */
gpio_set_value(arb->our_gpio, arb->our_gpio_release);
udelay(arb->slew_delay_us);
-   dev_err(>dev, "Could not claim bus, timeout\n");
+   dev_err(muxc->dev, "Could not claim bus, timeout\n");
return -EBUSY;
 }
 
@@ -102,10 +98,9 @@ static int i2c_arbitrator_select(struct i2c_adapter *adap, 
void *data, u32 chan)
  *
  * Release the I2C bus using the GPIO-based signalling protocol.
  */
-static int i2c_arbitrator_deselect(struct i2c_adapter *adap, void *data,
-  u32 chan)
+static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-   const struct i2c_arbitrator_data *arb = data;
+   const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
 
/* Release the bus and wait for the other master to notice */
gpio_set_value(arb->our_gpio, arb->our_gpio_release);
@@ -119,6 +114,7 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
struct device *dev = >dev;
struct device_node *np = dev->of_node;
struct device_node *parent_np;
+   struct i2c_mux_core *muxc;
struct i2c_arbitrator_data *arb;
enum of_gpio_flags gpio_flags;
unsigned long out_init;
@@ -134,12 +130,13 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
return -EINVAL;
}
 
-   arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
-   if (!arb) {
-   dev_err(dev, "Cannot allocate i2c_arbitrator_data\n");
+   muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0,
+i2c_arbitrator_select, i2c_arbitrator_deselect);
+   if (!muxc)
return -ENOMEM;
-   }
-   platform_set_drvdata(pdev, arb);
+   arb = i2c_mux_priv(muxc);
+
+   platform_set_drvdata(pdev, muxc);
 
/* Request GPIOs */
ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, _flags);
@@ -196,21 +193,18 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
dev_err(dev, "Cannot parse i2c-parent\n");
return -EINVAL;
}
-   arb->parent = of_get_i2c_adapter_by_node(parent_np);
+   muxc->parent = of_get_i2c_adapter_by_node(parent_np);
of_node_put(parent_np);
-   if (!arb->parent) {
+   if (!muxc->parent) {
dev_err(dev, "Cannot find parent bus\n");
return -EPROBE_DEFER;
}
 
/* Actually add the mux adapter */
-   arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0,
-i2c_arbitrator_select,
-i2c_arbitrator_deselect);
-   if (!arb->child) {
+   ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
+   if (ret) {
dev_err(dev, "Failed to add adapter\n");
-   ret = -ENODEV;
-   i2c_put_adapter(arb->parent);
+   i2c_put_adapter(muxc->parent);
}
 
return ret;
@@ -218,11 +212,10 @@ static int i2c_arbitrator_probe(struct platform_device 
*pdev)
 
 static int i2c_arbitrator_remove(struct platform_device *pdev)
 {
-   struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev);
-
-   i2c_del_mux_adapter(arb->child);
-   

[PATCH v7 07/24] i2c: i2c-mux-reg: convert to use an explicit i2c mux core

2016-04-20 Thread Peter Rosin
Allocate an explicit i2c mux core to handle parent and child adapters
etc. Update the select/deselect ops to be in terms of the i2c mux core
instead of the child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/muxes/i2c-mux-reg.c | 69 +++--
 1 file changed, 25 insertions(+), 44 deletions(-)

diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index 5fbd5bd0878f..6773cadf7c9f 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -21,8 +21,6 @@
 #include 
 
 struct regmux {
-   struct i2c_adapter *parent;
-   struct i2c_adapter **adap; /* child busses */
struct i2c_mux_reg_platform_data data;
 };
 
@@ -64,18 +62,16 @@ static int i2c_mux_reg_set(const struct regmux *mux, 
unsigned int chan_id)
return 0;
 }
 
-static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data,
- unsigned int chan)
+static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct regmux *mux = data;
+   struct regmux *mux = i2c_mux_priv(muxc);
 
return i2c_mux_reg_set(mux, chan);
 }
 
-static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
-   unsigned int chan)
+static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-   struct regmux *mux = data;
+   struct regmux *mux = i2c_mux_priv(muxc);
 
if (mux->data.idle_in_use)
return i2c_mux_reg_set(mux, mux->data.idle);
@@ -85,7 +81,7 @@ static int i2c_mux_reg_deselect(struct i2c_adapter *adap, 
void *data,
 
 #ifdef CONFIG_OF
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
-   struct platform_device *pdev)
+   struct platform_device *pdev)
 {
struct device_node *np = pdev->dev.of_node;
struct device_node *adapter_np, *child;
@@ -107,7 +103,6 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
if (!adapter)
return -EPROBE_DEFER;
 
-   mux->parent = adapter;
mux->data.parent = i2c_adapter_id(adapter);
put_device(>dev);
 
@@ -161,7 +156,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
 }
 #else
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
-   struct platform_device *pdev)
+   struct platform_device *pdev)
 {
return 0;
 }
@@ -169,10 +164,10 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
 
 static int i2c_mux_reg_probe(struct platform_device *pdev)
 {
+   struct i2c_mux_core *muxc;
struct regmux *mux;
struct i2c_adapter *parent;
struct resource *res;
-   int (*deselect)(struct i2c_adapter *, void *, u32);
unsigned int class;
int i, ret, nr;
 
@@ -180,17 +175,9 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
if (!mux)
return -ENOMEM;
 
-   platform_set_drvdata(pdev, mux);
-
if (dev_get_platdata(>dev)) {
memcpy(>data, dev_get_platdata(>dev),
sizeof(mux->data));
-
-   parent = i2c_get_adapter(mux->data.parent);
-   if (!parent)
-   return -EPROBE_DEFER;
-
-   mux->parent = parent;
} else {
ret = i2c_mux_reg_probe_dt(mux, pdev);
if (ret < 0) {
@@ -199,6 +186,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
}
}
 
+   parent = i2c_get_adapter(mux->data.parent);
+   if (!parent)
+   return -EPROBE_DEFER;
+
if (!mux->data.reg) {
dev_info(>dev,
"Register not set, using platform resource\n");
@@ -215,55 +206,45 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
return -EINVAL;
}
 
-   mux->adap = devm_kzalloc(>dev,
-sizeof(*mux->adap) * mux->data.n_values,
-GFP_KERNEL);
-   if (!mux->adap) {
-   dev_err(>dev, "Cannot allocate i2c_adapter structure");
+   muxc = i2c_mux_alloc(parent, >dev, mux->data.n_values, 0, 0,
+i2c_mux_reg_select, NULL);
+   if (!muxc)
return -ENOMEM;
-   }
+   muxc->priv = mux;
+
+   platform_set_drvdata(pdev, muxc);
 
if (mux->data.idle_in_use)
-   deselect = i2c_mux_reg_deselect;
-   else
-   deselect = NULL;
+   muxc->deselect = i2c_mux_reg_deselect;
 
for (i = 0; i < mux->data.n_values; i++) {
nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
class = mux->data.classes ? mux->data.classes[i] : 0;
 
-   mux->adap[i] = i2c_add_mux_adapter(mux->parent, >dev, mux,
-  nr, mux->data.values[i],
-   

[PATCH v7 00/24] i2c mux cleanup and locking update

2016-04-20 Thread Peter Rosin
Hi!

I have a pair of boards with this i2c topology:

   GPIO ---|  -- BAT1
|  v /
   I2C  -+--B---+ MUX
 |   \
   EEPROM -- BAT2

(B denotes the boundary between the boards)

The problem with this is that the GPIO controller sits on the same i2c bus
that it MUXes. For pca954x devices this is worked around by using unlocked
transfers when updating the MUX. I have no such luck as the GPIO is a general
purpose IO expander and the MUX is just a random bidirectional MUX, unaware
of the fact that it is muxing an i2c bus. Extending unlocked transfers
into the GPIO subsystem is too ugly to even think about. But the general hw
approach is sane in my opinion, with the number of connections between the
two boards minimized. To put it plainly, I need support for it.

So, I observe that while it is needed to have the i2c bus locked during the
actual MUX update in order to avoid random garbage on the slave side, it
is not strictly a must to have it locked over the whole sequence of a full
select-transfer-deselect operation. The MUX itself needs to be locked, so
transfers to clients behind the mux are serialized, and the MUX needs to be
stable during all i2c traffic (otherwise individual mux slave segments
might see garbage).

This series accomplishes this by adding code to i2c-mux-gpio and
i2c-mux-pinctrl that determines if all involved devices used to update the
mux are controlled by the same root i2c adapter that is muxed. When this
is the case, the select-transfer-deselect operations should be locked
individually to avoid the deadlock. The i2c bus *is* still locked
during muxing, since the muxing happens as part of i2c transfers. This
is true even if the MUX is updated with several transfers to the GPIO (at
least as long as *all* MUX changes are using the i2c master bus). A lock
is added to i2c adapters that muxes on that adapter grab, so that transfers
through the muxes are serialized.

Concerns:
- The locking is perhaps too complex?
- I worry about the priority inheritance aspect of the adapter lock. When
  the transfers behind the mux are divided into select-transfer-deselect all
  locked individually, low priority transfers get more chances to interfere
  with high priority transfers.
- When doing an i2c_transfer() in_atomic() context or with irqs_disabled(),
  there is a higher possibility that the mux is not returned to its idle
  state after a failed (-EAGAIN) transfer due to trylock.
- Is the detection of i2c-controlled gpios and pinctrls sane (i.e. the
  usage of the new i2c_root_adapter() function in 18/24)?

To summarize the series, there's some i2c-mux infrastructure cleanup work
first (I think that part stands by itself as desireable regardless), the
locking changes are in 16/24 and after with the real meat in 18/24. There
is some documentation added in 19/24 while 20/24 and after are cleanups to
existing drivers utilizing the new stuff.

PS. needs a bunch of testing, I do not have access to all the involved hw.

Thanks to those who have ested this series so far. At this point, only
patches 01 through 15 are planned for 4.6, and the rest will hopefully
follow later, so lets focus of the cleanup work that enables the real
work later in the series.

Antti, you reviewed 09 through 12 for v5, and even though they changed
slightly due to the changes in v7 I have kept your reviewed tags, since
I classified the changes as mechanical. I hope this is ok.

Similarly, Jonathan and Rob acked patch 08 and 14 respectively, and these
patches have the same kind of mechanical changes so I have kept the acks.
I hope this is also ok.

I have also kept the acks and review tags on patches 20 and forward since
the fixups to adjust to the changes earlier in the series were completely
trivial.

This series can also be pulled from github, if that is preferred:

-
The following changes since commit f55532a0c0b8bb6148f4e07853b876ef73bc69ca:

  Linux 4.6-rc1 (2016-03-26 16:03:24 -0700)

are available in the git repository at:

  https://github.com/peda-r/i2c-mux.git mux-core-and-locking-7

for you to fetch changes up to f725ef789ff0eb2663f1cff2b29d8196a7f0fd0b:

  [media] rtl2832: regmap is aware of lockdep, drop local locking hack 
(2016-04-20 14:49:00 +0200)
-

v7 compared to v6:
- Removed i2c_mux_reserve_adapters, and all realloc attempts in
  i2c_mux_add_adapter. Supply a maximum number of adapters in i2c_mux_alloc
  instead.
- Removed i2c_mux_one_adapter since it is was hard to use correctly, which
  was evident from the crash in the mpu6050 driver (on a mpu9150 chip) reported
  by Crestez Dan Leonard. Also, it didn't make things all that much simpler
  anyway (even if used correctly).
- Rename i2c_mux_core:adapters into i2c_mux_core:num_adapters.
- Some grammar and spelling fixes.

v6 compared to v5:
- Rebase on top of v4.6-rc1
- Adjust to gpio subsystem 

[PATCH v7 01/24] i2c-mux: add common data for every i2c-mux instance

2016-04-20 Thread Peter Rosin
All i2c-muxes have a parent adapter and one or many child
adapters. A mux also has some means of selection. Previously,
this was stored per child adapter, but it is only needed
to keep track of this per mux.

Add an i2c mux core, that keeps track of this consistently.

Also add some glue for users of the old interface, which will
create one implicit mux core per child adapter.

Signed-off-by: Peter Rosin 
---
 drivers/i2c/i2c-mux.c   | 175 
 include/linux/i2c-mux.h |  34 ++
 2 files changed, 168 insertions(+), 41 deletions(-)

diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index d4022878b2f0..5ce1b0704cb5 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -28,33 +28,34 @@
 #include 
 
 /* multiplexer per channel data */
+struct i2c_mux_priv_old {
+   void *mux_priv;
+   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
+   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
+};
+
 struct i2c_mux_priv {
struct i2c_adapter adap;
struct i2c_algorithm algo;
-
-   struct i2c_adapter *parent;
-   struct device *mux_dev;
-   void *mux_priv;
+   struct i2c_mux_core *muxc;
u32 chan_id;
-
-   int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-   int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
 };
 
 static int i2c_mux_master_xfer(struct i2c_adapter *adap,
   struct i2c_msg msgs[], int num)
 {
struct i2c_mux_priv *priv = adap->algo_data;
-   struct i2c_adapter *parent = priv->parent;
+   struct i2c_mux_core *muxc = priv->muxc;
+   struct i2c_adapter *parent = muxc->parent;
int ret;
 
/* Switch to the right mux port and perform the transfer. */
 
-   ret = priv->select(parent, priv->mux_priv, priv->chan_id);
+   ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
ret = __i2c_transfer(parent, msgs, num);
-   if (priv->deselect)
-   priv->deselect(parent, priv->mux_priv, priv->chan_id);
+   if (muxc->deselect)
+   muxc->deselect(muxc, priv->chan_id);
 
return ret;
 }
@@ -65,17 +66,18 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
  int size, union i2c_smbus_data *data)
 {
struct i2c_mux_priv *priv = adap->algo_data;
-   struct i2c_adapter *parent = priv->parent;
+   struct i2c_mux_core *muxc = priv->muxc;
+   struct i2c_adapter *parent = muxc->parent;
int ret;
 
/* Select the right mux port and perform the transfer. */
 
-   ret = priv->select(parent, priv->mux_priv, priv->chan_id);
+   ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
ret = parent->algo->smbus_xfer(parent, addr, flags,
read_write, command, size, data);
-   if (priv->deselect)
-   priv->deselect(parent, priv->mux_priv, priv->chan_id);
+   if (muxc->deselect)
+   muxc->deselect(muxc, priv->chan_id);
 
return ret;
 }
@@ -84,7 +86,7 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 static u32 i2c_mux_functionality(struct i2c_adapter *adap)
 {
struct i2c_mux_priv *priv = adap->algo_data;
-   struct i2c_adapter *parent = priv->parent;
+   struct i2c_adapter *parent = priv->muxc->parent;
 
return parent->algo->functionality(parent);
 }
@@ -102,6 +104,20 @@ static unsigned int i2c_mux_parent_classes(struct 
i2c_adapter *parent)
return class;
 }
 
+static int i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
+
+   return priv->select(muxc->parent, priv->mux_priv, chan);
+}
+
+static int i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+   struct i2c_mux_priv_old *priv = i2c_mux_priv(muxc);
+
+   return priv->deselect(muxc->parent, priv->mux_priv, chan);
+}
+
 struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
@@ -111,21 +127,77 @@ struct i2c_adapter *i2c_add_mux_adapter(struct 
i2c_adapter *parent,
int (*deselect) (struct i2c_adapter *,
 void *, u32))
 {
+   struct i2c_mux_core *muxc;
+   struct i2c_mux_priv_old *priv;
+   int ret;
+
+   muxc = i2c_mux_alloc(parent, mux_dev, 1, sizeof(*priv), 0,
+i2c_mux_select, i2c_mux_deselect);
+   if (!muxc)
+   return NULL;
+
+   priv = i2c_mux_priv(muxc);
+   priv->select = select;
+   priv->deselect = deselect;
+   priv->mux_priv = mux_priv;
+
+   ret = i2c_mux_add_adapter(muxc, force_nr, chan_id, class);
+   if (ret) {
+   

Re: [media-workshop] [ANNOUNCE] Linux Media Summit 2016 Report – San Diego (draft)

2016-04-20 Thread Mauro Carvalho Chehab
Em Wed, 20 Apr 2016 08:45:51 -0300
Mauro Carvalho Chehab  escreveu:

> Em Wed, 20 Apr 2016 07:33:17 -0300
> Mauro Carvalho Chehab  escreveu:
> 
> > This is the draft of the media summit report. I'll be soon posting an online
> > version of it, with the group photo, at linuxtv.org.
> > 
> > Please review. Also, for the ones that presented a slide deck there, please
> > send me the slides, for me to post there too.  
> 
> I posted the draft, together with group photo and links to the slide decks I 
> have
> so far at:
>   https://linuxtv.org/news.php?entry=2016-04-20.mchehab
> 
> It is currently missing slides from Laurent's presentation at ELC, with was
> used as reference for the Request API status update discussions.

Update: Laurent's slides are now added too, and should be accessible
using the above link.

> 
> Regards,
> Mauro


-- 
Thanks,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [media-workshop] [ANNOUNCE] Linux Media Summit 2016 Report – San Diego (draft)

2016-04-20 Thread Mauro Carvalho Chehab
Em Wed, 20 Apr 2016 07:33:17 -0300
Mauro Carvalho Chehab  escreveu:

> This is the draft of the media summit report. I'll be soon posting an online
> version of it, with the group photo, at linuxtv.org.
> 
> Please review. Also, for the ones that presented a slide deck there, please
> send me the slides, for me to post there too.

I posted the draft, together with group photo and links to the slide decks I 
have
so far at:
https://linuxtv.org/news.php?entry=2016-04-20.mchehab

It is currently missing slides from Laurent's presentation at ELC, with was
used as reference for the Request API status update discussions.

Regards,
Mauro
-- 
Thanks,
Mauro
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[ANNOUNCE] Linux Media Summit 2016 Report – San Diego (draft)

2016-04-20 Thread Mauro Carvalho Chehab
This is the draft of the media summit report. I'll be soon posting an online
version of it, with the group photo, at linuxtv.org.

Please review. Also, for the ones that presented a slide deck there, please
send me the slides, for me to post there too.

Thanks!
Mauro

---

Linux Media Summit 2016 – San Diego
===

Attendees list:

 Mauro Carvalho Chehab  (Samsung)
 Lars-Peter Clausen  (Analog Devices)
 Magnus Damm  (Renesas)
 Shuah Khan  (Samsung)
 Guennadi Liakhovetski  (Intel)
 Kuninori Morimoto  (Renesas)
 Benoit Parrot  (Texas Instruments)
 Laurent Pinchart  (Ideas on Board)
 Niklas Söderland  (Ragnatech)
 Hans Verkuil  (Cisco)

1. CEC Framework Status update
==

First version of the framework close to completion. Will likely be
submitted for Kernel 4.7, although it could be merged only for 4.8.
 Independent framework, allows consumers in V4L2, DRM, ALSA, …

Driver support WIP for Pulse Eight USB dongle, omap4, adv7604/7842/7511.

Future plans:
-

-   ARC/CDC hotplug support
-   Implement high level protocol constraints (resend, timeout, rate
limiting of messages). Whether those constraints can be implemented
in the kernel remains to be analyzed, as the kernel to userspace API
might be at a much lower level than the constraints. A userspace
library might be another option.

2. Quick demo of the new qdisp utility that is in development
=

The qdisp utility is a simpler alternative to qv4l2 that handles video
capture and show the captured video only.

Currently, qdisp requires OpenGL, OpenGLES support is planned.

Color space and format conversion code is based on GPU shaders. It will
be split into a library to be shared with qv4l2. A CPU-based alternative
would be feasible but isn’t planned at the moment.

The qdisp code is currently available here:
.

3. Request API Status update


At the moment: Allows to chain multiple of the existing IOCTLs into a
request which will either be applied atomicly or not at all

Initial proposal


-   New IOCTL to start a commit
-   APPLY operation will apply changes in a request immediately. Useful
to change multiple controls at the same time
-   QUEUE operation will queue changes with a buffer and will be applied
when the buffer is processed

Alternative proposal


One new IOCTL that takes all state and applies it atomicly (like DRM
atomic modesetting)

Open question
-

How to perform atomic operations across subssytems? V4L2, DRM, ALSA, MC

Action item
---

Hans will contact Pawel to see what/when needs to be upstreamed for e.g.
the rockchip driver.

4. Stream multiplexing (Guennadi Liakhovetski)
==

CSI-2 has up to 4 virtual channels (2 bits), 6 bits for Data Type

Virtual channels do not have to be in sync with one another, so
different virtual channels can carry different framerates.

Within a virtual channel each line is tagged with a data type as well,
so it can be used to pass metadata + videodata in one virtual channel as
well.

Requirements


-   Pipeline validation
-   Format validation
-   Bandwidth/QoS
-   Routing (related to muxing/demuxing)
-   Sounds interesting to have a non-V4L2 specific solution to solve
cases where there a multiple entities linked into a bus or needing
switch. For example, the ALSA subsystem supports TDM.

Proposed solution
-

Introduce the concept of virtual channels which are routed on the top of
the physical links. A virtual channel has a route that goes through
multiple physical entities, with routing information at each entity on
how the data is forwarded.

Action item
---

Laurent will dig up old router entity code he posted in the past and
re-post it or provide a link to that code.

5. DT Bindings for flash & lens controllers
===

There are drivers that create their MC topology using the device tree
information, which works great for entities that transport data, but how
to detect entities that don’t transport data such as flash devices,
focusers, etc.?

How can those be deduced using the device tree?

Sensor DT node add phandle to focus controller.: add generic v4l binding
properties to reference such devices.

6. How to improve the linux-media patch and review process?
===

Submaintainership status


Currently, sub-maintainership is not working as expected. Also, we’re
currently 

Re: [PATCH] [media] af9035: fix for MXL5007T devices with I2C read issues

2016-04-20 Thread Alex Rad
On Wed, Apr 20, 2016 at 1:02 AM, Antti Palosaari  wrote:
> Hello
> I am not happy with that new module parameter as I cannot see real need for
> it. So get rid of it.

My reasoning for this is:
1) We know of just two devices which may have the issue, but there are
probably more.  The module parameter allows a user to apply the
workaround to other devices we did not consider or test.  Should we
perhaps apply for all mxl5007t devices?
2) Not all devices that match VID and PID have the issue, so it allows
the user to disable the workaround.

>
> Better to compare both VID and PID when enabling that work-around. Driver
> supports currently quite many different USB IDs and there is still small
> risk duplicate PID will exists at some point enabling work-around for wrong
> device.
>

OK.  Will wait for comments on above before a v2.

Thanks,
Alessandro

> regards
> Antti
>
>
>
>
> On 04/15/2016 06:37 PM, Alessandro Radicati wrote:
>>
>> The MXL5007T tuner will lock-up on some devices after an I2C read
>> transaction.  This patch adds a kernel module parameter "no_read" to work
>> around this issue by inhibiting such operations and emulating a 0x00
>> response.  The workaround is applied automatically to USB product IDs
>> known
>> to exhibit this flaw, unless the kernel module parameter is specified.
>>
>> Signed-off-by: Alessandro Radicati 
>> ---
>>   drivers/media/usb/dvb-usb-v2/af9035.c | 27 +++
>>   drivers/media/usb/dvb-usb-v2/af9035.h |  1 +
>>   2 files changed, 28 insertions(+)
>>
>> diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c
>> b/drivers/media/usb/dvb-usb-v2/af9035.c
>> index 2638e32..8225403 100644
>> --- a/drivers/media/usb/dvb-usb-v2/af9035.c
>> +++ b/drivers/media/usb/dvb-usb-v2/af9035.c
>> @@ -24,6 +24,10 @@
>>   /* Max transfer size done by I2C transfer functions */
>>   #define MAX_XFER_SIZE  64
>>
>> +static int dvb_usb_af9035_no_read = -1;
>> +module_param_named(no_read, dvb_usb_af9035_no_read, int, 0644);
>> +MODULE_PARM_DESC(no_read, "Emulate I2C reads for devices that do not
>> support them.");
>> +
>>   DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
>>
>>   static u16 af9035_checksum(const u8 *buf, size_t len)
>> @@ -348,6 +352,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter
>> *adap,
>>
>> ret = af9035_rd_regs(d, reg, [1].buf[0],
>> msg[1].len);
>> +   } else if (state->no_read) {
>> +   memset(msg[1].buf, 0, msg[1].len);
>> +   ret = 0;
>> } else {
>> /* I2C write + read */
>> u8 buf[MAX_XFER_SIZE];
>> @@ -421,6 +428,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter
>> *adap,
>> if (msg[0].len > 40) {
>> /* TODO: correct limits > 40 */
>> ret = -EOPNOTSUPP;
>> +   } else if (state->no_read) {
>> +   memset(msg[0].buf, 0, msg[0].len);
>> +   ret = 0;
>> } else {
>> /* I2C read */
>> u8 buf[5];
>> @@ -962,6 +972,23 @@ skip_eeprom:
>> state->af9033_config[i].clock =
>> clock_lut_af9035[tmp];
>> }
>>
>> +   /* Some MXL5007T devices cannot properly handle tuner I2C read
>> ops. */
>> +   if (dvb_usb_af9035_no_read != -1) { /* Override with module param
>> */
>> +   state->no_read = dvb_usb_af9035_no_read == 0 ? false :
>> true;
>> +   } else {
>> +   switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
>> +   case USB_PID_AVERMEDIA_A867:
>> +   case USB_PID_AVERMEDIA_TWINSTAR:
>> +   dev_info(>udev->dev,
>> +   "%s: Device may have issues with I2C read
>> operations. Enabling fix.\n",
>> +   KBUILD_MODNAME);
>> +   state->no_read = true;
>> +   break;
>> +   default:
>> +   state->no_read = false;
>> +   }
>> +   }
>> +
>> return 0;
>>
>>   err:
>> diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h
>> b/drivers/media/usb/dvb-usb-v2/af9035.h
>> index df22001..a76dafa 100644
>> --- a/drivers/media/usb/dvb-usb-v2/af9035.h
>> +++ b/drivers/media/usb/dvb-usb-v2/af9035.h
>> @@ -62,6 +62,7 @@ struct state {
>> u8 chip_version;
>> u16 chip_type;
>> u8 dual_mode:1;
>> +   u8 no_read:1;
>> u16 eeprom_addr;
>> u8 af9033_i2c_addr[2];
>> struct af9033_config af9033_config[2];
>>
>
> --
> http://palosaari.fi/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html