History

Merge branch 'topic/cec' into topic/docs-next

* topic/cec: [media] DocBook/media: add CEC documentation [media] s5p_cec: get rid of an unused var [media] move s5p-cec to staging [media] vivid: add CEC emulation [media] cec: s5p-cec: Add s5p-cec driver [media] cec: adv7511: add cec support [media] cec: adv7842: add cec support [media] cec: adv7604: add cec support [media] cec: add compat32 ioctl support [media] cec/TODO: add TODO file so we know why this is still in staging [media] cec: add HDMI CEC framework (api) [media] cec: add HDMI CEC framework (adapter) [media] cec: add HDMI CEC framework (core) [media] cec-funcs.h: static inlines to pack/unpack CEC messages [media] cec.h: add cec header [media] cec-edid: add module for EDID CEC helper functions [media] cec.txt: add CEC framework documentation [media] rc: Add HDMI CEC protocol handling Input: add HDMI CEC specific keycodes Input: add BUS_CEC type

Mauro Carvalho Chehab committed 10 years ago

Commit 6a6e8092 parents d2c6815 c7169ad62 files · +10460 −129Browse files

Unified · Split

62 files
  1. Documentation/DocBook/device-drivers.tmpl +3 −0
  2. Documentation/DocBook/media/Makefile +2 −0
  3. Documentation/DocBook/media/v4l/biblio.xml +10 −0
  4. Documentation/DocBook/media/v4l/cec-api.xml +75 −0
  5. Documentation/DocBook/media/v4l/cec-func-close.xml +64 −0
  6. Documentation/DocBook/media/v4l/cec-func-ioctl.xml +78 −0
  7. Documentation/DocBook/media/v4l/cec-func-open.xml +104 −0
  8. Documentation/DocBook/media/v4l/cec-func-poll.xml +94 −0
  9. Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml +151 −0
  10. Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml +329 −0
  11. Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml +86 −0
  12. Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml +202 −0
  13. Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml +255 −0
  14. Documentation/DocBook/media/v4l/cec-ioc-receive.xml +274 −0
  15. Documentation/DocBook/media_api.tmpl +5 −1
  16. Documentation/cec.txt +267 −0
  17. Documentation/devicetree/bindings/media/s5p-cec.txt +31 −0
  18. Documentation/video4linux/vivid.txt +31 −5
  19. MAINTAINERS +23 −0
  20. drivers/media/Kconfig +3 −0
  21. drivers/media/Makefile +2 −0
  22. drivers/media/cec-edid.c +168 −0
  23. drivers/media/i2c/Kconfig +24 −0
  24. drivers/media/i2c/adv7511.c +393 −8
  25. drivers/media/i2c/adv7604.c +296 −36
  26. drivers/media/i2c/adv7842.c +305 −63
  27. drivers/media/platform/vivid/Kconfig +8 −0
  28. drivers/media/platform/vivid/Makefile +4 −0
  29. drivers/media/platform/vivid/vivid-cec.c +255 −0
  30. drivers/media/platform/vivid/vivid-cec.h +33 −0
  31. drivers/media/platform/vivid/vivid-core.c +109 −9
  32. drivers/media/platform/vivid/vivid-core.h +27 −0
  33. drivers/media/platform/vivid/vivid-kthread-cap.c +13 −0
  34. drivers/media/platform/vivid/vivid-vid-cap.c +22 −1
  35. drivers/media/platform/vivid/vivid-vid-common.c +7 −0
  36. drivers/media/rc/rc-main.c +1 −0
  37. drivers/staging/media/Kconfig +4 −0
  38. drivers/staging/media/Makefile +2 −0
  39. drivers/staging/media/cec/Kconfig +14 −0
  40. drivers/staging/media/cec/Makefile +3 −0
  41. drivers/staging/media/cec/TODO +27 −0
  42. drivers/staging/media/cec/cec-adap.c +1627 −0
  43. drivers/staging/media/cec/cec-api.c +578 −0
  44. drivers/staging/media/cec/cec-core.c +409 −0
  45. drivers/staging/media/cec/cec-priv.h +56 −0
  46. drivers/staging/media/s5p-cec/Kconfig +9 −0
  47. drivers/staging/media/s5p-cec/Makefile +2 −0
  48. drivers/staging/media/s5p-cec/TODO +3 −0
  49. drivers/staging/media/s5p-cec/exynos_hdmi_cec.h +38 −0
  50. drivers/staging/media/s5p-cec/exynos_hdmi_cecctrl.c +209 −0
  51. drivers/staging/media/s5p-cec/regs-cec.h +96 −0
  52. drivers/staging/media/s5p-cec/s5p_cec.c +294 −0
  53. drivers/staging/media/s5p-cec/s5p_cec.h +76 −0
  54. fs/compat_ioctl.c +12 −0
  55. include/linux/cec-funcs.h +1881 −0
  56. include/linux/cec.h +993 −0
  57. include/media/cec-edid.h +104 −0
  58. include/media/cec.h +232 −0
  59. include/media/i2c/adv7511.h +1 −5
  60. include/media/rc-map.h +4 −1
  61. include/uapi/linux/input-event-codes.h +31 −0
  62. include/uapi/linux/input.h +1 −0
Documentation/DocBook/device-drivers.tmpl+3−0
@@ -272,6 +272,9 @@ X!Isound/sound_firmware.c · 271 unmodified lines
272!Iinclude/media/media-devnode.h272!Iinclude/media/media-devnode.h
273!Iinclude/media/media-entity.h273!Iinclude/media/media-entity.h
274 </sect1>274 </sect1>
275 <sect1><title>Consumer Electronics Control devices</title>
276!Iinclude/media/cec-edid.h
277 </sect1>
275 278
276 </chapter>279 </chapter>
277 280
Documentation/DocBook/media/Makefile+2−0
@@ -64,6 +64,7 @@ IOCTLS = \ · 63 unmodified lines
64 $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \64 $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \
65 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \65 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \
66 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \66 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \
67 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/cec.h) \
67 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \68 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
68 69
69DEFINES = \70DEFINES = \
@@ -100,6 +101,7 @@ STRUCTS = \ · 30 unmodified lines
100 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/ && !/_old/)' $(srctree)/include/uapi/linux/dvb/net.h) \101 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/ && !/_old/)' $(srctree)/include/uapi/linux/dvb/net.h) \
101 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \102 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \
102 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \103 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \
104 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/cec.h) \
103 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \105 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
104 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h)106 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h)
105 107
Documentation/DocBook/media/v4l/biblio.xml+10−0
@@ -342,6 +342,16 @@ in the frequency range from 87,5 to 108,0 MHz</title> · 341 unmodified lines
342 <subtitle>Specification Version 1.4a</subtitle>342 <subtitle>Specification Version 1.4a</subtitle>
343 </biblioentry>343 </biblioentry>
344 344
345 <biblioentry id="hdmi2">
346 <abbrev>HDMI2</abbrev>
347 <authorgroup>
348 <corpauthor>HDMI Licensing LLC
349(<ulink url="http://www.hdmi.org">http://www.hdmi.org</ulink>)</corpauthor>
350 </authorgroup>
351 <title>High-Definition Multimedia Interface</title>
352 <subtitle>Specification Version 2.0</subtitle>
353 </biblioentry>
354
345 <biblioentry id="dp">355 <biblioentry id="dp">
346 <abbrev>DP</abbrev>356 <abbrev>DP</abbrev>
347 <authorgroup>357 <authorgroup>
Documentation/DocBook/media/v4l/cec-api.xml+75−0
@@ -0,0 +1,75 @@
1<partinfo>
2 <authorgroup>
3 <author>
4 <firstname>Hans</firstname>
5 <surname>Verkuil</surname>
6 <affiliation><address><email>hans.verkuil@cisco.com</email></address></affiliation>
7 <contrib>Initial version.</contrib>
8 </author>
9 </authorgroup>
10 <copyright>
11 <year>2016</year>
12 <holder>Hans Verkuil</holder>
13 </copyright>
14
15 <revhistory>
16 <!-- Put document revisions here, newest first. -->
17 <revision>
18 <revnumber>1.0.0</revnumber>
19 <date>2016-03-17</date>
20 <authorinitials>hv</authorinitials>
21 <revremark>Initial revision</revremark>
22 </revision>
23 </revhistory>
24</partinfo>
25
26<title>CEC API</title>
27
28<chapter id="cec-api">
29 <title>CEC: Consumer Electronics Control</title>
30
31 <section id="cec-intro">
32 <title>Introduction</title>
33 <para>
34 Note: this documents the proposed CEC API. This API is not yet finalized and
35 is currently only available as a staging kernel module.
36 </para>
37 <para>HDMI connectors provide a single pin for use by the Consumer Electronics
38 Control protocol. This protocol allows different devices connected by an HDMI cable
39 to communicate. The protocol for CEC version 1.4 is defined in supplements 1 (CEC)
40 and 2 (HEAC or HDMI Ethernet and Audio Return Channel) of the HDMI 1.4a
41 (<xref linkend="hdmi" />) specification and the extensions added to CEC version 2.0
42 are defined in chapter 11 of the HDMI 2.0 (<xref linkend="hdmi2" />) specification.
43 </para>
44
45 <para>The bitrate is very slow (effectively no more than 36 bytes per second) and
46 is based on the ancient AV.link protocol used in old SCART connectors. The protocol
47 closely resembles a crazy Rube Goldberg contraption and is an unholy mix of low and
48 high level messages. Some messages, especially those part of the HEAC protocol layered
49 on top of CEC, need to be handled by the kernel, others can be handled either by the
50 kernel or by userspace.</para>
51
52 <para>In addition, CEC can be implemented in HDMI receivers, transmitters and in USB
53 devices that have an HDMI input and an HDMI output and that control just the CEC pin.</para>
54
55 <para>Drivers that support CEC will create a CEC device node (/dev/cecX)
56 to give userspace access to the CEC adapter. The &CEC-ADAP-G-CAPS; ioctl will tell userspace
57 what it is allowed to do.</para>
58 </section>
59</chapter>
60
61<appendix id="cec-user-func">
62 <title>Function Reference</title>
63 <!-- Keep this alphabetically sorted. -->
64 &sub-cec-func-open;
65 &sub-cec-func-close;
66 &sub-cec-func-ioctl;
67 &sub-cec-func-poll;
68 <!-- All ioctls go here. -->
69 &sub-cec-ioc-adap-g-caps;
70 &sub-cec-ioc-adap-g-log-addrs;
71 &sub-cec-ioc-adap-g-phys-addr;
72 &sub-cec-ioc-dqevent;
73 &sub-cec-ioc-g-mode;
74 &sub-cec-ioc-receive;
75</appendix>
Documentation/DocBook/media/v4l/cec-func-close.xml+64−0
@@ -0,0 +1,64 @@
1<refentry id="cec-func-close">
2 <refmeta>
3 <refentrytitle>cec close()</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>cec-close</refname>
9 <refpurpose>Close a cec device</refpurpose>
10 </refnamediv>
11
12 <refsynopsisdiv>
13 <funcsynopsis>
14 <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
15 <funcprototype>
16 <funcdef>int <function>close</function></funcdef>
17 <paramdef>int <parameter>fd</parameter></paramdef>
18 </funcprototype>
19 </funcsynopsis>
20 </refsynopsisdiv>
21
22 <refsect1>
23 <title>Arguments</title>
24
25 <variablelist>
26 <varlistentry>
27 <term><parameter>fd</parameter></term>
28 <listitem>
29 <para>&fd;</para>
30 </listitem>
31 </varlistentry>
32 </variablelist>
33 </refsect1>
34
35 <refsect1>
36 <title>Description</title>
37
38 <para>
39 Note: this documents the proposed CEC API. This API is not yet finalized and
40 is currently only available as a staging kernel module.
41 </para>
42
43 <para>Closes the cec device. Resources associated with the file descriptor
44 are freed. The device configuration remain unchanged.</para>
45 </refsect1>
46
47 <refsect1>
48 <title>Return Value</title>
49
50 <para><function>close</function> returns 0 on success. On error, -1 is
51 returned, and <varname>errno</varname> is set appropriately. Possible error
52 codes are:</para>
53
54 <variablelist>
55 <varlistentry>
56 <term><errorcode>EBADF</errorcode></term>
57 <listitem>
58 <para><parameter>fd</parameter> is not a valid open file descriptor.
59 </para>
60 </listitem>
61 </varlistentry>
62 </variablelist>
63 </refsect1>
64</refentry>
Documentation/DocBook/media/v4l/cec-func-ioctl.xml+78−0
@@ -0,0 +1,78 @@
1<refentry id="cec-func-ioctl">
2 <refmeta>
3 <refentrytitle>cec ioctl()</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>cec-ioctl</refname>
9 <refpurpose>Control a cec device</refpurpose>
10 </refnamediv>
11
12 <refsynopsisdiv>
13 <funcsynopsis>
14 <funcsynopsisinfo>#include &lt;sys/ioctl.h&gt;</funcsynopsisinfo>
15 <funcprototype>
16 <funcdef>int <function>ioctl</function></funcdef>
17 <paramdef>int <parameter>fd</parameter></paramdef>
18 <paramdef>int <parameter>request</parameter></paramdef>
19 <paramdef>void *<parameter>argp</parameter></paramdef>
20 </funcprototype>
21 </funcsynopsis>
22 </refsynopsisdiv>
23
24 <refsect1>
25 <title>Arguments</title>
26
27 <variablelist>
28 <varlistentry>
29 <term><parameter>fd</parameter></term>
30 <listitem>
31 <para>&fd;</para>
32 </listitem>
33 </varlistentry>
34 <varlistentry>
35 <term><parameter>request</parameter></term>
36 <listitem>
37 <para>CEC ioctl request code as defined in the cec.h header file,
38 for example CEC_ADAP_G_CAPS.</para>
39 </listitem>
40 </varlistentry>
41 <varlistentry>
42 <term><parameter>argp</parameter></term>
43 <listitem>
44 <para>Pointer to a request-specific structure.</para>
45 </listitem>
46 </varlistentry>
47 </variablelist>
48 </refsect1>
49
50 <refsect1>
51 <title>Description</title>
52 <para>
53 Note: this documents the proposed CEC API. This API is not yet finalized and
54 is currently only available as a staging kernel module.
55 </para>
56
57 <para>The <function>ioctl()</function> function manipulates cec device
58 parameters. The argument <parameter>fd</parameter> must be an open file
59 descriptor.</para>
60 <para>The ioctl <parameter>request</parameter> code specifies the cec
61 function to be called. It has encoded in it whether the argument is an
62 input, output or read/write parameter, and the size of the argument
63 <parameter>argp</parameter> in bytes.</para>
64 <para>Macros and structures definitions specifying cec ioctl requests and
65 their parameters are located in the cec.h header file. All cec ioctl
66 requests, their respective function and parameters are specified in
67 <xref linkend="cec-user-func" />.</para>
68 </refsect1>
69
70 <refsect1>
71 &return-value;
72
73 <para>Request-specific error codes are listed in the
74 individual requests descriptions.</para>
75 <para>When an ioctl that takes an output or read/write parameter fails,
76 the parameter remains unmodified.</para>
77 </refsect1>
78</refentry>
Documentation/DocBook/media/v4l/cec-func-open.xml+104−0
@@ -0,0 +1,104 @@
1<refentry id="cec-func-open">
2 <refmeta>
3 <refentrytitle>cec open()</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>cec-open</refname>
9 <refpurpose>Open a cec device</refpurpose>
10 </refnamediv>
11
12 <refsynopsisdiv>
13 <funcsynopsis>
14 <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
15 <funcprototype>
16 <funcdef>int <function>open</function></funcdef>
17 <paramdef>const char *<parameter>device_name</parameter></paramdef>
18 <paramdef>int <parameter>flags</parameter></paramdef>
19 </funcprototype>
20 </funcsynopsis>
21 </refsynopsisdiv>
22
23 <refsect1>
24 <title>Arguments</title>
25
26 <variablelist>
27 <varlistentry>
28 <term><parameter>device_name</parameter></term>
29 <listitem>
30 <para>Device to be opened.</para>
31 </listitem>
32 </varlistentry>
33 <varlistentry>
34 <term><parameter>flags</parameter></term>
35 <listitem>
36 <para>Open flags. Access mode must be <constant>O_RDWR</constant>.
37 </para>
38 <para>When the <constant>O_NONBLOCK</constant> flag is
39given, the &CEC-RECEIVE; ioctl will return &EAGAIN; when no message is
40available, and the &CEC-TRANSMIT;, &CEC-ADAP-S-PHYS-ADDR; and
41&CEC-ADAP-S-LOG-ADDRS; ioctls all act in non-blocking mode.</para>
42 <para>Other flags have no effect.</para>
43 </listitem>
44 </varlistentry>
45 </variablelist>
46 </refsect1>
47 <refsect1>
48 <title>Description</title>
49 <para>
50 Note: this documents the proposed CEC API. This API is not yet finalized and
51 is currently only available as a staging kernel module.
52 </para>
53
54 <para>To open a cec device applications call <function>open()</function>
55 with the desired device name. The function has no side effects; the device
56 configuration remain unchanged.</para>
57 <para>When the device is opened in read-only mode, attempts to modify its
58 configuration will result in an error, and <varname>errno</varname> will be
59 set to <errorcode>EBADF</errorcode>.</para>
60 </refsect1>
61 <refsect1>
62 <title>Return Value</title>
63
64 <para><function>open</function> returns the new file descriptor on success.
65 On error, -1 is returned, and <varname>errno</varname> is set appropriately.
66 Possible error codes include:</para>
67
68 <variablelist>
69 <varlistentry>
70 <term><errorcode>EACCES</errorcode></term>
71 <listitem>
72 <para>The requested access to the file is not allowed.</para>
73 </listitem>
74 </varlistentry>
75 <varlistentry>
76 <term><errorcode>EMFILE</errorcode></term>
77 <listitem>
78 <para>The process already has the maximum number of files open.
79 </para>
80 </listitem>
81 </varlistentry>
82 <varlistentry>
83 <term><errorcode>ENFILE</errorcode></term>
84 <listitem>
85 <para>The system limit on the total number of open files has been
86 reached.</para>
87 </listitem>
88 </varlistentry>
89 <varlistentry>
90 <term><errorcode>ENOMEM</errorcode></term>
91 <listitem>
92 <para>Insufficient kernel memory was available.</para>
93 </listitem>
94 </varlistentry>
95 <varlistentry>
96 <term><errorcode>ENXIO</errorcode></term>
97 <listitem>
98 <para>No device corresponding to this device special file exists.
99 </para>
100 </listitem>
101 </varlistentry>
102 </variablelist>
103 </refsect1>
104</refentry>
Documentation/DocBook/media/v4l/cec-func-poll.xml+94−0
@@ -0,0 +1,94 @@
1<refentry id="cec-func-poll">
2 <refmeta>
3 <refentrytitle>cec poll()</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>cec-poll</refname>
9 <refpurpose>Wait for some event on a file descriptor</refpurpose>
10 </refnamediv>
11
12 <refsynopsisdiv>
13 <funcsynopsis>
14 <funcsynopsisinfo>#include &lt;sys/poll.h&gt;</funcsynopsisinfo>
15 <funcprototype>
16 <funcdef>int <function>poll</function></funcdef>
17 <paramdef>struct pollfd *<parameter>ufds</parameter></paramdef>
18 <paramdef>unsigned int <parameter>nfds</parameter></paramdef>
19 <paramdef>int <parameter>timeout</parameter></paramdef>
20 </funcprototype>
21 </funcsynopsis>
22 </refsynopsisdiv>
23
24 <refsect1>
25 <title>Description</title>
26
27 <para>
28 Note: this documents the proposed CEC API. This API is not yet finalized and
29 is currently only available as a staging kernel module.
30 </para>
31
32 <para>With the <function>poll()</function> function applications
33can wait for CEC events.</para>
34
35 <para>On success <function>poll()</function> returns the number of
36file descriptors that have been selected (that is, file descriptors
37for which the <structfield>revents</structfield> field of the
38respective <structname>pollfd</structname> structure is non-zero).
39CEC devices set the <constant>POLLIN</constant> and
40<constant>POLLRDNORM</constant> flags in the
41<structfield>revents</structfield> field if there are messages in the
42receive queue. If the transmit queue has room for new messages, the
43<constant>POLLOUT</constant> and <constant>POLLWRNORM</constant>
44flags are set. If there are events in the event queue, then the
45<constant>POLLPRI</constant> flag is set.
46When the function timed out it returns a value of zero, on
47failure it returns <returnvalue>-1</returnvalue> and the
48<varname>errno</varname> variable is set appropriately.
49</para>
50
51 <para>For more details see the
52<function>poll()</function> manual page.</para>
53 </refsect1>
54
55 <refsect1>
56 <title>Return Value</title>
57
58 <para>On success, <function>poll()</function> returns the number
59structures which have non-zero <structfield>revents</structfield>
60fields, or zero if the call timed out. On error
61<returnvalue>-1</returnvalue> is returned, and the
62<varname>errno</varname> variable is set appropriately:</para>
63
64 <variablelist>
65 <varlistentry>
66 <term><errorcode>EBADF</errorcode></term>
67 <listitem>
68 <para>One or more of the <parameter>ufds</parameter> members
69specify an invalid file descriptor.</para>
70 </listitem>
71 </varlistentry>
72 <varlistentry>
73 <term><errorcode>EFAULT</errorcode></term>
74 <listitem>
75 <para><parameter>ufds</parameter> references an inaccessible
76memory area.</para>
77 </listitem>
78 </varlistentry>
79 <varlistentry>
80 <term><errorcode>EINTR</errorcode></term>
81 <listitem>
82 <para>The call was interrupted by a signal.</para>
83 </listitem>
84 </varlistentry>
85 <varlistentry>
86 <term><errorcode>EINVAL</errorcode></term>
87 <listitem>
88 <para>The <parameter>nfds</parameter> argument is greater
89than <constant>OPEN_MAX</constant>.</para>
90 </listitem>
91 </varlistentry>
92 </variablelist>
93 </refsect1>
94</refentry>
Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml+151−0
@@ -0,0 +1,151 @@
1<refentry id="cec-ioc-adap-g-caps">
2 <refmeta>
3 <refentrytitle>ioctl CEC_ADAP_G_CAPS</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>CEC_ADAP_G_CAPS</refname>
9 <refpurpose>Query device capabilities</refpurpose>
10 </refnamediv>
11
12 <refsynopsisdiv>
13 <funcsynopsis>
14 <funcprototype>
15 <funcdef>int <function>ioctl</function></funcdef>
16 <paramdef>int <parameter>fd</parameter></paramdef>
17 <paramdef>int <parameter>request</parameter></paramdef>
18 <paramdef>struct cec_caps *<parameter>argp</parameter></paramdef>
19 </funcprototype>
20 </funcsynopsis>
21 </refsynopsisdiv>
22
23 <refsect1>
24 <title>Arguments</title>
25
26 <variablelist>
27 <varlistentry>
28 <term><parameter>fd</parameter></term>
29 <listitem>
30 <para>File descriptor returned by
31 <link linkend='cec-func-open'><function>open()</function></link>.</para>
32 </listitem>
33 </varlistentry>
34 <varlistentry>
35 <term><parameter>request</parameter></term>
36 <listitem>
37 <para>CEC_ADAP_G_CAPS</para>
38 </listitem>
39 </varlistentry>
40 <varlistentry>
41 <term><parameter>argp</parameter></term>
42 <listitem>
43 <para></para>
44 </listitem>
45 </varlistentry>
46 </variablelist>
47 </refsect1>
48
49 <refsect1>
50 <title>Description</title>
51
52 <para>
53 Note: this documents the proposed CEC API. This API is not yet finalized and
54 is currently only available as a staging kernel module.
55 </para>
56
57 <para>All cec devices must support the <constant>CEC_ADAP_G_CAPS</constant>
58 ioctl. To query device information, applications call the ioctl with a
59 pointer to a &cec-caps;. The driver fills the structure and returns
60 the information to the application.
61 The ioctl never fails.</para>
62
63 <table pgwide="1" frame="none" id="cec-caps">
64 <title>struct <structname>cec_caps</structname></title>
65 <tgroup cols="3">
66 &cs-str;
67 <tbody valign="top">
68 <row>
69 <entry>char</entry>
70 <entry><structfield>driver[32]</structfield></entry>
71 <entry>The name of the cec adapter driver.</entry>
72 </row>
73 <row>
74 <entry>char</entry>
75 <entry><structfield>name[32]</structfield></entry>
76 <entry>The name of this CEC adapter. The combination <structfield>driver</structfield>
77 and <structfield>name</structfield> must be unique.</entry>
78 </row>
79 <row>
80 <entry>__u32</entry>
81 <entry><structfield>capabilities</structfield></entry>
82 <entry>The capabilities of the CEC adapter, see <xref
83 linkend="cec-capabilities" />.</entry>
84 </row>
85 <row>
86 <entry>__u32</entry>
87 <entry><structfield>version</structfield></entry>
88 <entry>CEC Framework API version, formatted with the
89 <constant>KERNEL_VERSION()</constant> macro.</entry>
90 </row>
91 </tbody>
92 </tgroup>
93 </table>
94
95 <table pgwide="1" frame="none" id="cec-capabilities">
96 <title>CEC Capabilities Flags</title>
97 <tgroup cols="3">
98 &cs-def;
99 <tbody valign="top">
100 <row>
101 <entry><constant>CEC_CAP_PHYS_ADDR</constant></entry>
102 <entry>0x00000001</entry>
103 <entry>Userspace has to configure the physical address by
104 calling &CEC-ADAP-S-PHYS-ADDR;. If this capability isn't set,
105 then setting the physical address is handled by the kernel
106 whenever the EDID is set (for an HDMI receiver) or read (for
107 an HDMI transmitter).</entry>
108 </row>
109 <row>
110 <entry><constant>CEC_CAP_LOG_ADDRS</constant></entry>
111 <entry>0x00000002</entry>
112 <entry>Userspace has to configure the logical addresses by
113 calling &CEC-ADAP-S-LOG-ADDRS;. If this capability isn't set,
114 then the kernel will have configured this.</entry>
115 </row>
116 <row>
117 <entry><constant>CEC_CAP_TRANSMIT</constant></entry>
118 <entry>0x00000004</entry>
119 <entry>Userspace can transmit CEC messages by calling &CEC-TRANSMIT;. This
120 implies that userspace can be a follower as well, since being able to
121 transmit messages is a prerequisite of becoming a follower. If this
122 capability isn't set, then the kernel will handle all CEC transmits
123 and process all CEC messages it receives.
124 </entry>
125 </row>
126 <row>
127 <entry><constant>CEC_CAP_PASSTHROUGH</constant></entry>
128 <entry>0x00000008</entry>
129 <entry>Userspace can use the passthrough mode by
130 calling &CEC-S-MODE;.</entry>
131 </row>
132 <row>
133 <entry><constant>CEC_CAP_RC</constant></entry>
134 <entry>0x00000010</entry>
135 <entry>This adapter supports the remote control protocol.</entry>
136 </row>
137 <row>
138 <entry><constant>CEC_CAP_MONITOR_ALL</constant></entry>
139 <entry>0x00000020</entry>
140 <entry>The CEC hardware can monitor all messages, not just directed and
141 broadcast messages.</entry>
142 </row>
143 </tbody>
144 </tgroup>
145 </table>
146 </refsect1>
147
148 <refsect1>
149 &return-value;
150 </refsect1>
151</refentry>
Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml+329−0
@@ -0,0 +1,329 @@
1<refentry id="cec-ioc-adap-g-log-addrs">
2 <refmeta>
3 <refentrytitle>ioctl CEC_ADAP_G_LOG_ADDRS, CEC_ADAP_S_LOG_ADDRS</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>CEC_ADAP_G_LOG_ADDRS</refname>
9 <refname>CEC_ADAP_S_LOG_ADDRS</refname>
10 <refpurpose>Get or set the logical addresses</refpurpose>
11 </refnamediv>
12
13 <refsynopsisdiv>
14 <funcsynopsis>
15 <funcprototype>
16 <funcdef>int <function>ioctl</function></funcdef>
17 <paramdef>int <parameter>fd</parameter></paramdef>
18 <paramdef>int <parameter>request</parameter></paramdef>
19 <paramdef>struct cec_log_addrs *<parameter>argp</parameter></paramdef>
20 </funcprototype>
21 </funcsynopsis>
22 </refsynopsisdiv>
23
24 <refsect1>
25 <title>Arguments</title>
26
27 <variablelist>
28 <varlistentry>
29 <term><parameter>fd</parameter></term>
30 <listitem>
31 <para>File descriptor returned by
32 <link linkend='cec-func-open'><function>open()</function></link>.</para>
33 </listitem>
34 </varlistentry>
35 <varlistentry>
36 <term><parameter>request</parameter></term>
37 <listitem>
38 <para>CEC_ADAP_G_LOG_ADDRS, CEC_ADAP_S_LOG_ADDRS</para>
39 </listitem>
40 </varlistentry>
41 <varlistentry>
42 <term><parameter>argp</parameter></term>
43 <listitem>
44 <para></para>
45 </listitem>
46 </varlistentry>
47 </variablelist>
48 </refsect1>
49
50 <refsect1>
51 <title>Description</title>
52
53 <para>
54 Note: this documents the proposed CEC API. This API is not yet finalized and
55 is currently only available as a staging kernel module.
56 </para>
57
58 <para>To query the current CEC logical addresses, applications call the
59<constant>CEC_ADAP_G_LOG_ADDRS</constant> ioctl with a pointer to a
60<structname>cec_log_addrs</structname> structure where the drivers stores the
61logical addresses.</para>
62
63 <para>To set new logical addresses, applications fill in struct <structname>cec_log_addrs</structname>
64and call the <constant>CEC_ADAP_S_LOG_ADDRS</constant> ioctl with a pointer to this struct.
65The <constant>CEC_ADAP_S_LOG_ADDRS</constant> ioctl is only available if
66<constant>CEC_CAP_LOG_ADDRS</constant> is set (&ENOTTY; is returned otherwise). This ioctl will block until all
67requested logical addresses have been claimed. <constant>CEC_ADAP_S_LOG_ADDRS</constant>
68can only be called by a file handle in initiator mode (see &CEC-S-MODE;).</para>
69
70 <table pgwide="1" frame="none" id="cec-log-addrs">
71 <title>struct <structname>cec_log_addrs</structname></title>
72 <tgroup cols="3">
73 &cs-str;
74 <tbody valign="top">
75 <row>
76 <entry>__u8</entry>
77 <entry><structfield>log_addr</structfield>[CEC_MAX_LOG_ADDRS]</entry>
78 <entry>The actual logical addresses that were claimed. This is set by the
79 driver. If no logical address could be claimed, then it is set to
80 <constant>CEC_LOG_ADDR_INVALID</constant>. If this adapter is Unregistered,
81 then <structfield>log_addr[0]</structfield> is set to 0xf and all others to
82 <constant>CEC_LOG_ADDR_INVALID</constant>.</entry>
83 </row>
84 <row>
85 <entry>__u16</entry>
86 <entry><structfield>log_addr_mask</structfield></entry>
87 <entry>The bitmask of all logical addresses this adapter has claimed.
88 If this adapter is Unregistered then <structfield>log_addr_mask</structfield>
89 sets bit 15 and clears all other bits. If this adapter is not configured at all, then
90 <structfield>log_addr_mask</structfield> is set to 0. Set by the driver.</entry>
91 </row>
92 <row>
93 <entry>__u8</entry>
94 <entry><structfield>cec_version</structfield></entry>
95 <entry>The CEC version that this adapter shall use. See
96 <xref linkend="cec-versions" />.
97 Used to implement the <constant>CEC_MSG_CEC_VERSION</constant> and
98 <constant>CEC_MSG_REPORT_FEATURES</constant> messages. Note that
99 <constant>CEC_OP_CEC_VERSION_1_3A</constant> is not allowed
100 by the CEC framework.
101 </entry>
102 </row>
103 <row>
104 <entry>__u8</entry>
105 <entry><structfield>num_log_addrs</structfield></entry>
106 <entry>Number of logical addresses to set up. Must be &le;
107 <structfield>available_log_addrs</structfield> as returned by
108 &CEC-ADAP-G-CAPS;. All arrays in this structure are only filled up to
109 index <structfield>available_log_addrs</structfield>-1. The remaining
110 array elements will be ignored. Note that the CEC 2.0 standard allows
111 for a maximum of 2 logical addresses, although some hardware has support
112 for more. <constant>CEC_MAX_LOG_ADDRS</constant> is 4. The driver will
113 return the actual number of logical addresses it could claim, which may
114 be less than what was requested. If this field is set to 0, then the
115 CEC adapter shall clear all claimed logical addresses and all other
116 fields will be ignored.</entry>
117 </row>
118 <row>
119 <entry>__u32</entry>
120 <entry><structfield>vendor_id</structfield></entry>
121 <entry>The vendor ID is a 24-bit number that identifies the specific
122 vendor or entity. Based on this ID vendor specific commands may be
123 defined. If you do not want a vendor ID then set it to
124 <constant>CEC_VENDOR_ID_NONE</constant>.</entry>
125 </row>
126 <row>
127 <entry>__u32</entry>
128 <entry><structfield>flags</structfield></entry>
129 <entry>Flags. No flags are defined yet, so set this to 0.</entry>
130 </row>
131 <row>
132 <entry>char</entry>
133 <entry><structfield>osd_name</structfield>[15]</entry>
134 <entry>The On-Screen Display name as is returned by the
135 <constant>CEC_MSG_SET_OSD_NAME</constant> message.</entry>
136 </row>
137 <row>
138 <entry>__u8</entry>
139 <entry><structfield>primary_device_type</structfield>[CEC_MAX_LOG_ADDRS]</entry>
140 <entry>Primary device type for each logical address. See
141 <xref linkend="cec-prim-dev-types" /> for possible types.</entry>
142 </row>
143 <row>
144 <entry>__u8</entry>
145 <entry><structfield>log_addr_type</structfield>[CEC_MAX_LOG_ADDRS]</entry>
146 <entry>Logical address types. See <xref linkend="cec-log-addr-types" /> for
147 possible types. The driver will update this with the actual logical address
148 type that it claimed (e.g. it may have to fallback to
149 <constant>CEC_LOG_ADDR_TYPE_UNREGISTERED</constant>).</entry>
150 </row>
151 <row>
152 <entry>__u8</entry>
153 <entry><structfield>all_device_types</structfield>[CEC_MAX_LOG_ADDRS]</entry>
154 <entry>CEC 2.0 specific: all device types. See <xref linkend="cec-all-dev-types-flags" />.
155 Used to implement the <constant>CEC_MSG_REPORT_FEATURES</constant> message.
156 This field is ignored if <structfield>cec_version</structfield> &lt;
157 <constant>CEC_OP_CEC_VERSION_2_0</constant>.</entry>
158 </row>
159 <row>
160 <entry>__u8</entry>
161 <entry><structfield>features</structfield>[CEC_MAX_LOG_ADDRS][12]</entry>
162 <entry>Features for each logical address. Used to implement the
163 <constant>CEC_MSG_REPORT_FEATURES</constant> message. The 12 bytes include
164 both the RC Profile and the Device Features.
165 This field is ignored if <structfield>cec_version</structfield> &lt;
166 <constant>CEC_OP_CEC_VERSION_2_0</constant>.</entry>
167 </row>
168 </tbody>
169 </tgroup>
170 </table>
171
172 <table pgwide="1" frame="none" id="cec-versions">
173 <title>CEC Versions</title>
174 <tgroup cols="3">
175 &cs-def;
176 <tbody valign="top">
177 <row>
178 <entry><constant>CEC_OP_CEC_VERSION_1_3A</constant></entry>
179 <entry>4</entry>
180 <entry>CEC version according to the HDMI 1.3a standard.</entry>
181 </row>
182 <row>
183 <entry><constant>CEC_OP_CEC_VERSION_1_4B</constant></entry>
184 <entry>5</entry>
185 <entry>CEC version according to the HDMI 1.4b standard.</entry>
186 </row>
187 <row>
188 <entry><constant>CEC_OP_CEC_VERSION_2_0</constant></entry>
189 <entry>6</entry>
190 <entry>CEC version according to the HDMI 2.0 standard.</entry>
191 </row>
192 </tbody>
193 </tgroup>
194 </table>
195
196 <table pgwide="1" frame="none" id="cec-prim-dev-types">
197 <title>CEC Primary Device Types</title>
198 <tgroup cols="3">
199 &cs-def;
200 <tbody valign="top">
201 <row>
202 <entry><constant>CEC_OP_PRIM_DEVTYPE_TV</constant></entry>
203 <entry>0</entry>
204 <entry>Use for a TV.</entry>
205 </row>
206 <row>
207 <entry><constant>CEC_OP_PRIM_DEVTYPE_RECORD</constant></entry>
208 <entry>1</entry>
209 <entry>Use for a recording device.</entry>
210 </row>
211 <row>
212 <entry><constant>CEC_OP_PRIM_DEVTYPE_TUNER</constant></entry>
213 <entry>3</entry>
214 <entry>Use for a device with a tuner.</entry>
215 </row>
216 <row>
217 <entry><constant>CEC_OP_PRIM_DEVTYPE_PLAYBACK</constant></entry>
218 <entry>4</entry>
219 <entry>Use for a playback device.</entry>
220 </row>
221 <row>
222 <entry><constant>CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM</constant></entry>
223 <entry>5</entry>
224 <entry>Use for an audio system (e.g. an audio/video receiver).</entry>
225 </row>
226 <row>
227 <entry><constant>CEC_OP_PRIM_DEVTYPE_SWITCH</constant></entry>
228 <entry>6</entry>
229 <entry>Use for a CEC switch.</entry>
230 </row>
231 <row>
232 <entry><constant>CEC_OP_PRIM_DEVTYPE_VIDEOPROC</constant></entry>
233 <entry>7</entry>
234 <entry>Use for a video processor device.</entry>
235 </row>
236 </tbody>
237 </tgroup>
238 </table>
239
240 <table pgwide="1" frame="none" id="cec-log-addr-types">
241 <title>CEC Logical Address Types</title>
242 <tgroup cols="3">
243 &cs-def;
244 <tbody valign="top">
245 <row>
246 <entry><constant>CEC_LOG_ADDR_TYPE_TV</constant></entry>
247 <entry>0</entry>
248 <entry>Use for a TV.</entry>
249 </row>
250 <row>
251 <entry><constant>CEC_LOG_ADDR_TYPE_RECORD</constant></entry>
252 <entry>1</entry>
253 <entry>Use for a recording device.</entry>
254 </row>
255 <row>
256 <entry><constant>CEC_LOG_ADDR_TYPE_TUNER</constant></entry>
257 <entry>2</entry>
258 <entry>Use for a tuner device.</entry>
259 </row>
260 <row>
261 <entry><constant>CEC_LOG_ADDR_TYPE_PLAYBACK</constant></entry>
262 <entry>3</entry>
263 <entry>Use for a playback device.</entry>
264 </row>
265 <row>
266 <entry><constant>CEC_LOG_ADDR_TYPE_AUDIOSYSTEM</constant></entry>
267 <entry>4</entry>
268 <entry>Use for an audio system device.</entry>
269 </row>
270 <row>
271 <entry><constant>CEC_LOG_ADDR_TYPE_SPECIFIC</constant></entry>
272 <entry>5</entry>
273 <entry>Use for a second TV or for a video processor device.</entry>
274 </row>
275 <row>
276 <entry><constant>CEC_LOG_ADDR_TYPE_UNREGISTERED</constant></entry>
277 <entry>6</entry>
278 <entry>Use this if you just want to remain unregistered.
279 Used for pure CEC switches or CDC-only devices (CDC:
280 Capability Discovery and Control).</entry>
281 </row>
282 </tbody>
283 </tgroup>
284 </table>
285
286 <table pgwide="1" frame="none" id="cec-all-dev-types-flags">
287 <title>CEC All Device Types Flags</title>
288 <tgroup cols="3">
289 &cs-def;
290 <tbody valign="top">
291 <row>
292 <entry><constant>CEC_OP_ALL_DEVTYPE_TV</constant></entry>
293 <entry>0x80</entry>
294 <entry>This supports the TV type.</entry>
295 </row>
296 <row>
297 <entry><constant>CEC_OP_ALL_DEVTYPE_RECORD</constant></entry>
298 <entry>0x40</entry>
299 <entry>This supports the Recording type.</entry>
300 </row>
301 <row>
302 <entry><constant>CEC_OP_ALL_DEVTYPE_TUNER</constant></entry>
303 <entry>0x20</entry>
304 <entry>This supports the Tuner type.</entry>
305 </row>
306 <row>
307 <entry><constant>CEC_OP_ALL_DEVTYPE_PLAYBACK</constant></entry>
308 <entry>0x10</entry>
309 <entry>This supports the Playback type.</entry>
310 </row>
311 <row>
312 <entry><constant>CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM</constant></entry>
313 <entry>0x08</entry>
314 <entry>This supports the Audio System type.</entry>
315 </row>
316 <row>
317 <entry><constant>CEC_OP_ALL_DEVTYPE_SWITCH</constant></entry>
318 <entry>0x04</entry>
319 <entry>This supports the CEC Switch or Video Processing type.</entry>
320 </row>
321 </tbody>
322 </tgroup>
323 </table>
324 </refsect1>
325
326 <refsect1>
327 &return-value;
328 </refsect1>
329</refentry>
Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml+86−0
@@ -0,0 +1,86 @@
1<refentry id="cec-ioc-adap-g-phys-addr">
2 <refmeta>
3 <refentrytitle>ioctl CEC_ADAP_G_PHYS_ADDR, CEC_ADAP_S_PHYS_ADDR</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>CEC_ADAP_G_PHYS_ADDR</refname>
9 <refname>CEC_ADAP_S_PHYS_ADDR</refname>
10 <refpurpose>Get or set the physical address</refpurpose>
11 </refnamediv>
12
13 <refsynopsisdiv>
14 <funcsynopsis>
15 <funcprototype>
16 <funcdef>int <function>ioctl</function></funcdef>
17 <paramdef>int <parameter>fd</parameter></paramdef>
18 <paramdef>int <parameter>request</parameter></paramdef>
19 <paramdef>__u16 *<parameter>argp</parameter></paramdef>
20 </funcprototype>
21 </funcsynopsis>
22 </refsynopsisdiv>
23
24 <refsect1>
25 <title>Arguments</title>
26
27 <variablelist>
28 <varlistentry>
29 <term><parameter>fd</parameter></term>
30 <listitem>
31 <para>File descriptor returned by
32 <link linkend='cec-func-open'><function>open()</function></link>.</para>
33 </listitem>
34 </varlistentry>
35 <varlistentry>
36 <term><parameter>request</parameter></term>
37 <listitem>
38 <para>CEC_ADAP_G_PHYS_ADDR, CEC_ADAP_S_PHYS_ADDR</para>
39 </listitem>
40 </varlistentry>
41 <varlistentry>
42 <term><parameter>argp</parameter></term>
43 <listitem>
44 <para></para>
45 </listitem>
46 </varlistentry>
47 </variablelist>
48 </refsect1>
49
50 <refsect1>
51 <title>Description</title>
52
53 <para>
54 Note: this documents the proposed CEC API. This API is not yet finalized and
55 is currently only available as a staging kernel module.
56 </para>
57
58 <para>To query the current physical address applications call the
59<constant>CEC_ADAP_G_PHYS_ADDR</constant> ioctl with a pointer to an __u16
60where the driver stores the physical address.</para>
61
62 <para>To set a new physical address applications store the physical address in
63an __u16 and call the <constant>CEC_ADAP_S_PHYS_ADDR</constant> ioctl with a
64pointer to this integer. <constant>CEC_ADAP_S_PHYS_ADDR</constant> is only
65available if <constant>CEC_CAP_PHYS_ADDR</constant> is set (&ENOTTY; will be returned
66otherwise). <constant>CEC_ADAP_S_PHYS_ADDR</constant>
67can only be called by a file handle in initiator mode (see &CEC-S-MODE;), if not
68&EBUSY; will be returned.</para>
69
70 <para>The physical address is a 16-bit number where each group of 4 bits
71represent a digit of the physical address a.b.c.d where the most significant
724 bits represent 'a'. The CEC root device (usually the TV) has address 0.0.0.0.
73Every device that is hooked up to an input of the TV has address a.0.0.0 (where
74'a' is &ge; 1), devices hooked up to those in turn have addresses a.b.0.0, etc.
75So a topology of up to 5 devices deep is supported. The physical address a
76device shall use is stored in the EDID of the sink.</para>
77
78<para>For example, the EDID for each HDMI input of the TV will have a different
79physical address of the form a.0.0.0 that the sources will read out and use as
80their physical address.</para>
81 </refsect1>
82
83 <refsect1>
84 &return-value;
85 </refsect1>
86</refentry>
Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml+202−0
@@ -0,0 +1,202 @@
1<refentry id="cec-ioc-g-event">
2 <refmeta>
3 <refentrytitle>ioctl CEC_DQEVENT</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>CEC_DQEVENT</refname>
9 <refpurpose>Dequeue a CEC event</refpurpose>
10 </refnamediv>
11
12 <refsynopsisdiv>
13 <funcsynopsis>
14 <funcprototype>
15 <funcdef>int <function>ioctl</function></funcdef>
16 <paramdef>int <parameter>fd</parameter></paramdef>
17 <paramdef>int <parameter>request</parameter></paramdef>
18 <paramdef>struct cec_event *<parameter>argp</parameter></paramdef>
19 </funcprototype>
20 </funcsynopsis>
21 </refsynopsisdiv>
22
23 <refsect1>
24 <title>Arguments</title>
25
26 <variablelist>
27 <varlistentry>
28 <term><parameter>fd</parameter></term>
29 <listitem>
30 <para>File descriptor returned by
31 <link linkend='cec-func-open'><function>open()</function></link>.</para>
32 </listitem>
33 </varlistentry>
34 <varlistentry>
35 <term><parameter>request</parameter></term>
36 <listitem>
37 <para>CEC_DQEVENT</para>
38 </listitem>
39 </varlistentry>
40 <varlistentry>
41 <term><parameter>argp</parameter></term>
42 <listitem>
43 <para></para>
44 </listitem>
45 </varlistentry>
46 </variablelist>
47 </refsect1>
48
49 <refsect1>
50 <title>Description</title>
51
52 <para>
53 Note: this documents the proposed CEC API. This API is not yet finalized and
54 is currently only available as a staging kernel module.
55 </para>
56
57 <para>CEC devices can send asynchronous events. These can be retrieved by calling
58 the <constant>CEC_DQEVENT</constant> ioctl. If the file descriptor is in non-blocking
59 mode and no event is pending, then it will return -1 and set errno to the &EAGAIN;.</para>
60
61 <para>The internal event queues are per-filehandle and per-event type. If there is
62 no more room in a queue then the last event is overwritten with the new one. This
63 means that intermediate results can be thrown away but that the latest event is always
64 available. This also means that is it possible to read two successive events that have
65 the same value (e.g. two CEC_EVENT_STATE_CHANGE events with the same state). In that
66 case the intermediate state changes were lost but it is guaranteed that the state
67 did change in between the two events.</para>
68
69 <table pgwide="1" frame="none" id="cec-event-state-change">
70 <title>struct <structname>cec_event_state_change</structname></title>
71 <tgroup cols="3">
72 &cs-str;
73 <tbody valign="top">
74 <row>
75 <entry>__u16</entry>
76 <entry><structfield>phys_addr</structfield></entry>
77 <entry>The current physical address.</entry>
78 </row>
79 <row>
80 <entry>__u16</entry>
81 <entry><structfield>log_addr_mask</structfield></entry>
82 <entry>The current set of claimed logical addresses.</entry>
83 </row>
84 </tbody>
85 </tgroup>
86 </table>
87
88 <table pgwide="1" frame="none" id="cec-event-lost-msgs">
89 <title>struct <structname>cec_event_lost_msgs</structname></title>
90 <tgroup cols="3">
91 &cs-str;
92 <tbody valign="top">
93 <row>
94 <entry>__u32</entry>
95 <entry><structfield>lost_msgs</structfield></entry>
96 <entry>Set to the number of lost messages since the filehandle
97 was opened or since the last time this event was dequeued for
98 this filehandle. The messages lost are the oldest messages. So
99 when a new message arrives and there is no more room, then the
100 oldest message is discarded to make room for the new one. The
101 internal size of the message queue guarantees that all messages
102 received in the last two seconds will be stored. Since messages
103 should be replied to within a second according to the CEC
104 specification, this is more than enough.
105 </entry>
106 </row>
107 </tbody>
108 </tgroup>
109 </table>
110
111 <table pgwide="1" frame="none" id="cec-event">
112 <title>struct <structname>cec_event</structname></title>
113 <tgroup cols="4">
114 &cs-str;
115 <tbody valign="top">
116 <row>
117 <entry>__u64</entry>
118 <entry><structfield>ts</structfield></entry>
119 <entry>Timestamp of the event in ns.</entry>
120 <entry></entry>
121 </row>
122 <row>
123 <entry>__u32</entry>
124 <entry><structfield>event</structfield></entry>
125 <entry>The CEC event type, see <xref linkend="cec-events" />.</entry>
126 <entry></entry>
127 </row>
128 <row>
129 <entry>__u32</entry>
130 <entry><structfield>flags</structfield></entry>
131 <entry>Event flags, see <xref linkend="cec-event-flags" />.</entry>
132 <entry></entry>
133 </row>
134 <row>
135 <entry>union</entry>
136 <entry>(anonymous)</entry>
137 <entry></entry>
138 <entry></entry>
139 </row>
140 <row>
141 <entry></entry>
142 <entry>struct cec_event_state_change</entry>
143 <entry><structfield>state_change</structfield></entry>
144 <entry>The new adapter state as sent by the <constant>CEC_EVENT_STATE_CHANGE</constant>
145 event.</entry>
146 </row>
147 <row>
148 <entry></entry>
149 <entry>struct cec_event_lost_msgs</entry>
150 <entry><structfield>lost_msgs</structfield></entry>
151 <entry>The number of lost messages as sent by the <constant>CEC_EVENT_LOST_MSGS</constant>
152 event.</entry>
153 </row>
154 </tbody>
155 </tgroup>
156 </table>
157
158 <table pgwide="1" frame="none" id="cec-events">
159 <title>CEC Events Types</title>
160 <tgroup cols="3">
161 &cs-def;
162 <tbody valign="top">
163 <row>
164 <entry><constant>CEC_EVENT_STATE_CHANGE</constant></entry>
165 <entry>1</entry>
166 <entry>Generated when the CEC Adapter's state changes. When open() is
167 called an initial event will be generated for that filehandle with the
168 CEC Adapter's state at that time.
169 </entry>
170 </row>
171 <row>
172 <entry><constant>CEC_EVENT_LOST_MSGS</constant></entry>
173 <entry>2</entry>
174 <entry>Generated if one or more CEC messages were lost because the
175 application didn't dequeue CEC messages fast enough.</entry>
176 </row>
177 </tbody>
178 </tgroup>
179 </table>
180
181 <table pgwide="1" frame="none" id="cec-event-flags">
182 <title>CEC Event Flags</title>
183 <tgroup cols="3">
184 &cs-def;
185 <tbody valign="top">
186 <row>
187 <entry><constant>CEC_EVENT_FL_INITIAL_VALUE</constant></entry>
188 <entry>1</entry>
189 <entry>Set for the initial events that are generated when the device is
190 opened. See the table above for which events do this. This allows
191 applications to learn the initial state of the CEC adapter at open()
192 time.</entry>
193 </row>
194 </tbody>
195 </tgroup>
196 </table>
197 </refsect1>
198
199 <refsect1>
200 &return-value;
201 </refsect1>
202</refentry>
Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml+255−0
@@ -0,0 +1,255 @@
1<refentry id="cec-ioc-g-mode">
2 <refmeta>
3 <refentrytitle>ioctl CEC_G_MODE, CEC_S_MODE</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>CEC_G_MODE</refname>
9 <refname>CEC_S_MODE</refname>
10 <refpurpose>Get or set exclusive use of the CEC adapter</refpurpose>
11 </refnamediv>
12
13 <refsynopsisdiv>
14 <funcsynopsis>
15 <funcprototype>
16 <funcdef>int <function>ioctl</function></funcdef>
17 <paramdef>int <parameter>fd</parameter></paramdef>
18 <paramdef>int <parameter>request</parameter></paramdef>
19 <paramdef>__u32 *<parameter>argp</parameter></paramdef>
20 </funcprototype>
21 </funcsynopsis>
22 </refsynopsisdiv>
23
24 <refsect1>
25 <title>Arguments</title>
26
27 <variablelist>
28 <varlistentry>
29 <term><parameter>fd</parameter></term>
30 <listitem>
31 <para>File descriptor returned by
32 <link linkend='cec-func-open'><function>open()</function></link>.</para>
33 </listitem>
34 </varlistentry>
35 <varlistentry>
36 <term><parameter>request</parameter></term>
37 <listitem>
38 <para>CEC_G_MODE, CEC_S_MODE</para>
39 </listitem>
40 </varlistentry>
41 <varlistentry>
42 <term><parameter>argp</parameter></term>
43 <listitem>
44 <para></para>
45 </listitem>
46 </varlistentry>
47 </variablelist>
48 </refsect1>
49
50 <refsect1>
51 <title>Description</title>
52
53 <para>
54 Note: this documents the proposed CEC API. This API is not yet finalized and
55 is currently only available as a staging kernel module.
56 </para>
57
58 <para>By default any filehandle can use &CEC-TRANSMIT; and &CEC-RECEIVE;, but
59in order to prevent applications from stepping on each others toes it must be possible
60to obtain exclusive access to the CEC adapter. This ioctl sets the filehandle
61to initiator and/or follower mode which can be exclusive depending on the chosen
62mode. The initiator is the filehandle that is used
63to initiate messages, i.e. it commands other CEC devices. The follower is the filehandle
64that receives messages sent to the CEC adapter and processes them. The same filehandle
65can be both initiator and follower, or this role can be taken by two different
66filehandles.</para>
67
68 <para>When a CEC message is received, then the CEC framework will decide how
69it will be processed. If the message is a reply to an earlier transmitted message,
70then the reply is sent back to the filehandle that is waiting for it. In addition
71the CEC framework will process it.</para>
72
73 <para>If the message is not a reply, then the CEC framework will process it
74first. If there is no follower, then the message is just discarded and a feature
75abort is sent back to the initiator if the framework couldn't process it. If there
76is a follower, then the message is passed on to the follower who will use
77&CEC-RECEIVE; to dequeue the new message. The framework expects the follower to
78make the right decisions.</para>
79
80 <para>The CEC framework will process core messages unless requested otherwise
81by the follower. The follower can enable the passthrough mode. In that case, the
82CEC framework will pass on most core messages without processing them and
83the follower will have to implement those messages. There are some messages
84that the core will always process, regardless of the passthrough mode. See
85<xref linkend="cec-core-processing" /> for details.</para>
86
87 <para>If there is no initiator, then any CEC filehandle can use &CEC-TRANSMIT;.
88If there is an exclusive initiator then only that initiator can call &CEC-TRANSMIT;.
89The follower can of course always call &CEC-TRANSMIT;.</para>
90
91 <para>Available initiator modes are:</para>
92
93 <table pgwide="1" frame="none" id="cec-mode-initiator">
94 <title>Initiator Modes</title>
95 <tgroup cols="3">
96 &cs-def;
97 <tbody valign="top">
98 <row>
99 <entry><constant>CEC_MODE_NO_INITIATOR</constant></entry>
100 <entry>0x0</entry>
101 <entry>This is not an initiator, i.e. it cannot transmit CEC messages
102 or make any other changes to the CEC adapter.</entry>
103 </row>
104 <row>
105 <entry><constant>CEC_MODE_INITIATOR</constant></entry>
106 <entry>0x1</entry>
107 <entry>This is an initiator (the default when the device is opened) and it
108 can transmit CEC messages and make changes to the CEC adapter, unless there
109 is an exclusive initiator.</entry>
110 </row>
111 <row>
112 <entry><constant>CEC_MODE_EXCL_INITIATOR</constant></entry>
113 <entry>0x2</entry>
114 <entry>This is an exclusive initiator and this file descriptor is the only one
115 that can transmit CEC messages and make changes to the CEC adapter. If someone
116 else is already the exclusive initiator then an attempt to become one will return
117 the &EBUSY; error.</entry>
118 </row>
119 </tbody>
120 </tgroup>
121 </table>
122
123 <para>Available follower modes are:</para>
124
125 <table pgwide="1" frame="none" id="cec-mode-follower">
126 <title>Follower Modes</title>
127 <tgroup cols="3">
128 &cs-def;
129 <tbody valign="top">
130 <row>
131 <entry><constant>CEC_MODE_NO_FOLLOWER</constant></entry>
132 <entry>0x00</entry>
133 <entry>This is not a follower (the default when the device is opened).</entry>
134 </row>
135 <row>
136 <entry><constant>CEC_MODE_FOLLOWER</constant></entry>
137 <entry>0x10</entry>
138 <entry>This is a follower and it will receive CEC messages unless there is
139 an exclusive follower. You cannot become a follower if <constant>CEC_CAP_TRANSMIT</constant>
140 is not set or if <constant>CEC_MODE_NO_INITIATOR</constant> was specified,
141 &EINVAL; is returned in that case.</entry>
142 </row>
143 <row>
144 <entry><constant>CEC_MODE_EXCL_FOLLOWER</constant></entry>
145 <entry>0x20</entry>
146 <entry>This is an exclusive follower and only this file descriptor will receive
147 CEC messages for processing. If someone else is already the exclusive follower
148 then an attempt to become one will return the &EBUSY; error. You cannot become
149 a follower if <constant>CEC_CAP_TRANSMIT</constant> is not set or if
150 <constant>CEC_MODE_NO_INITIATOR</constant> was specified, &EINVAL; is returned
151 in that case.</entry>
152 </row>
153 <row>
154 <entry><constant>CEC_MODE_EXCL_FOLLOWER_PASSTHRU</constant></entry>
155 <entry>0x30</entry>
156 <entry>This is an exclusive follower and only this file descriptor will receive
157 CEC messages for processing. In addition it will put the CEC device into
158 passthrough mode, allowing the exclusive follower to handle most core messages
159 instead of relying on the CEC framework for that. If someone else is already the
160 exclusive follower then an attempt to become one will return the &EBUSY; error.
161 You cannot become a follower if <constant>CEC_CAP_TRANSMIT</constant>
162 is not set or if <constant>CEC_MODE_NO_INITIATOR</constant> was specified,
163 &EINVAL; is returned in that case.</entry>
164 </row>
165 <row>
166 <entry><constant>CEC_MODE_MONITOR</constant></entry>
167 <entry>0xe0</entry>
168 <entry>Put the file descriptor into monitor mode. Can only be used in combination
169 with <constant>CEC_MODE_NO_INITIATOR</constant>, otherwise &EINVAL; will be
170 returned. In monitor mode all messages this CEC device transmits and all messages
171 it receives (both broadcast messages and directed messages for one its logical
172 addresses) will be reported. This is very useful for debugging. This is only
173 allowed if the process has the <constant>CAP_NET_ADMIN</constant>
174 capability. If that is not set, then &EPERM; is returned.</entry>
175 </row>
176 <row>
177 <entry><constant>CEC_MODE_MONITOR_ALL</constant></entry>
178 <entry>0xf0</entry>
179 <entry>Put the file descriptor into 'monitor all' mode. Can only be used in combination
180 with <constant>CEC_MODE_NO_INITIATOR</constant>, otherwise &EINVAL; will be
181 returned. In 'monitor all' mode all messages this CEC device transmits and all messages
182 it receives, including directed messages for other CEC devices will be reported. This
183 is very useful for debugging, but not all devices support this. This mode requires that
184 the <constant>CEC_CAP_MONITOR_ALL</constant> capability is set, otherwise &EINVAL; is
185 returned. This is only allowed if the process has the <constant>CAP_NET_ADMIN</constant>
186 capability. If that is not set, then &EPERM; is returned.</entry>
187 </row>
188 </tbody>
189 </tgroup>
190 </table>
191
192 <para>Core message processing details:</para>
193
194 <table pgwide="1" frame="none" id="cec-core-processing">
195 <title>Core Message Processing</title>
196 <tgroup cols="2">
197 &cs-def;
198 <tbody valign="top">
199 <row>
200 <entry><constant>CEC_MSG_GET_CEC_VERSION</constant></entry>
201 <entry>When in passthrough mode this message has to be handled by userspace,
202 otherwise the core will return the CEC version that was set with &CEC-ADAP-S-LOG-ADDRS;.</entry>
203 </row>
204 <row>
205 <entry><constant>CEC_MSG_GIVE_DEVICE_VENDOR_ID</constant></entry>
206 <entry>When in passthrough mode this message has to be handled by userspace,
207 otherwise the core will return the vendor ID that was set with &CEC-ADAP-S-LOG-ADDRS;.</entry>
208 </row>
209 <row>
210 <entry><constant>CEC_MSG_ABORT</constant></entry>
211 <entry>When in passthrough mode this message has to be handled by userspace,
212 otherwise the core will return a feature refused message as per the specification.</entry>
213 </row>
214 <row>
215 <entry><constant>CEC_MSG_GIVE_PHYSICAL_ADDR</constant></entry>
216 <entry>When in passthrough mode this message has to be handled by userspace,
217 otherwise the core will report the current physical address.</entry>
218 </row>
219 <row>
220 <entry><constant>CEC_MSG_GIVE_OSD_NAME</constant></entry>
221 <entry>When in passthrough mode this message has to be handled by userspace,
222 otherwise the core will report the current OSD name as was set with
223 &CEC-ADAP-S-LOG-ADDRS;.</entry>
224 </row>
225 <row>
226 <entry><constant>CEC_MSG_GIVE_FEATURES</constant></entry>
227 <entry>When in passthrough mode this message has to be handled by userspace,
228 otherwise the core will report the current features as was set with
229 &CEC-ADAP-S-LOG-ADDRS; or the message is ignore if the CEC version was
230 older than 2.0.</entry>
231 </row>
232 <row>
233 <entry><constant>CEC_MSG_USER_CONTROL_PRESSED</constant></entry>
234 <entry>If <constant>CEC_CAP_RC</constant> is set, then generate a remote control
235 key press. This message is always passed on to userspace.</entry>
236 </row>
237 <row>
238 <entry><constant>CEC_MSG_USER_CONTROL_RELEASED</constant></entry>
239 <entry>If <constant>CEC_CAP_RC</constant> is set, then generate a remote control
240 key release. This message is always passed on to userspace.</entry>
241 </row>
242 <row>
243 <entry><constant>CEC_MSG_REPORT_PHYSICAL_ADDR</constant></entry>
244 <entry>The CEC framework will make note of the reported physical address
245 and then just pass the message on to userspace.</entry>
246 </row>
247 </tbody>
248 </tgroup>
249 </table>
250 </refsect1>
251
252 <refsect1>
253 &return-value;
254 </refsect1>
255</refentry>
Documentation/DocBook/media/v4l/cec-ioc-receive.xml+274−0
@@ -0,0 +1,274 @@
1<refentry id="cec-ioc-receive">
2 <refmeta>
3 <refentrytitle>ioctl CEC_RECEIVE, CEC_TRANSMIT</refentrytitle>
4 &manvol;
5 </refmeta>
6
7 <refnamediv>
8 <refname>CEC_RECEIVE</refname>
9 <refname>CEC_TRANSMIT</refname>
10 <refpurpose>Receive or transmit a CEC message</refpurpose>
11 </refnamediv>
12
13 <refsynopsisdiv>
14 <funcsynopsis>
15 <funcprototype>
16 <funcdef>int <function>ioctl</function></funcdef>
17 <paramdef>int <parameter>fd</parameter></paramdef>
18 <paramdef>int <parameter>request</parameter></paramdef>
19 <paramdef>struct cec_msg *<parameter>argp</parameter></paramdef>
20 </funcprototype>
21 </funcsynopsis>
22 </refsynopsisdiv>
23
24 <refsect1>
25 <title>Arguments</title>
26
27 <variablelist>
28 <varlistentry>
29 <term><parameter>fd</parameter></term>
30 <listitem>
31 <para>File descriptor returned by
32 <link linkend='cec-func-open'><function>open()</function></link>.</para>
33 </listitem>
34 </varlistentry>
35 <varlistentry>
36 <term><parameter>request</parameter></term>
37 <listitem>
38 <para>CEC_RECEIVE, CEC_TRANSMIT</para>
39 </listitem>
40 </varlistentry>
41 <varlistentry>
42 <term><parameter>argp</parameter></term>
43 <listitem>
44 <para></para>
45 </listitem>
46 </varlistentry>
47 </variablelist>
48 </refsect1>
49
50 <refsect1>
51 <title>Description</title>
52
53 <para>
54 Note: this documents the proposed CEC API. This API is not yet finalized and
55 is currently only available as a staging kernel module.
56 </para>
57
58 <para>To receive a CEC message the application has to fill in the
59 <structname>cec_msg</structname> structure and pass it to the
60 <constant>CEC_RECEIVE</constant> ioctl. <constant>CEC_RECEIVE</constant> is
61 only available if <constant>CEC_CAP_RECEIVE</constant> is set. If the
62 file descriptor is in non-blocking mode and there are no received
63 messages pending, then it will return -1 and set errno to the &EAGAIN;.
64 If the file descriptor is in blocking mode and <structfield>timeout</structfield>
65 is non-zero and no message arrived within <structfield>timeout</structfield>
66 milliseconds, then it will return -1 and set errno to the &ETIMEDOUT;.</para>
67
68 <para>To send a CEC message the application has to fill in the
69 <structname>cec_msg</structname> structure and pass it to the
70 <constant>CEC_TRANSMIT</constant> ioctl. <constant>CEC_TRANSMIT</constant> is
71 only available if <constant>CEC_CAP_TRANSMIT</constant> is set.
72 If there is no more room in the transmit queue, then it will return
73 -1 and set errno to the &EBUSY;.</para>
74
75 <table pgwide="1" frame="none" id="cec-msg">
76 <title>struct <structname>cec_msg</structname></title>
77 <tgroup cols="3">
78 &cs-str;
79 <tbody valign="top">
80 <row>
81 <entry>__u64</entry>
82 <entry><structfield>ts</structfield></entry>
83 <entry>Timestamp of when the message was transmitted in ns in the case
84 of <constant>CEC_TRANSMIT</constant> with <structfield>reply</structfield>
85 set to 0, or the timestamp of the received message in all other cases.</entry>
86 </row>
87 <row>
88 <entry>__u32</entry>
89 <entry><structfield>len</structfield></entry>
90 <entry>The length of the message. For <constant>CEC_TRANSMIT</constant> this
91 is filled in by the application. The driver will fill this in for
92 <constant>CEC_RECEIVE</constant> and for <constant>CEC_TRANSMIT</constant>
93 it will be filled in with the length of the reply message if
94 <structfield>reply</structfield> was set.</entry>
95 </row>
96 <row>
97 <entry>__u32</entry>
98 <entry><structfield>timeout</structfield></entry>
99 <entry>The timeout in milliseconds. This is the time the device will wait for a message to
100 be received before timing out. If it is set to 0, then it will wait indefinitely when it
101 is called by <constant>CEC_RECEIVE</constant>. If it is 0 and it is called by
102 <constant>CEC_TRANSMIT</constant>, then it will be replaced by 1000 if the
103 <structfield>reply</structfield> is non-zero or ignored if <structfield>reply</structfield>
104 is 0.</entry>
105 </row>
106 <row>
107 <entry>__u32</entry>
108 <entry><structfield>sequence</structfield></entry>
109 <entry>The sequence number is automatically assigned by the CEC
110 framework for all transmitted messages. It can be later used by the
111 framework to generate an event if a reply for a message was
112 requested and the message was transmitted in a non-blocking mode.
113 </entry>
114 </row>
115 <row>
116 <entry>__u32</entry>
117 <entry><structfield>flags</structfield></entry>
118 <entry>Flags. No flags are defined yet, so set this to 0.</entry>
119 </row>
120 <row>
121 <entry>__u8</entry>
122 <entry><structfield>rx_status</structfield></entry>
123 <entry>The status bits of the received message. See <xref linkend="cec-rx-status" />
124 for the possible status values. It is 0 if this message was transmitted, not
125 received, unless this is the reply to a transmitted message. In that case both
126 <structfield>rx_status</structfield> and <structfield>tx_status</structfield>
127 are set.</entry>
128 </row>
129 <row>
130 <entry>__u8</entry>
131 <entry><structfield>tx_status</structfield></entry>
132 <entry>The status bits of the transmitted message. See <xref linkend="cec-tx-status" />
133 for the possible status values. It is 0 if this messages was received, not
134 transmitted.</entry>
135 </row>
136 <row>
137 <entry>__u8</entry>
138 <entry><structfield>msg</structfield>[16]</entry>
139 <entry>The message payload. For <constant>CEC_TRANSMIT</constant> this
140 is filled in by the application. The driver will fill this in for
141 <constant>CEC_RECEIVE</constant> and for <constant>CEC_TRANSMIT</constant>
142 it will be filled in with the payload of the reply message if
143 <structfield>reply</structfield> was set.</entry>
144 </row>
145 <row>
146 <entry>__u8</entry>
147 <entry><structfield>reply</structfield></entry>
148 <entry>Wait until this message is replied. If <structfield>reply</structfield>
149 is 0 and the <structfield>timeout</structfield> is 0, then don't wait for a reply but
150 return after transmitting the message. If there was an error as indicated by a non-zero
151 <structfield>tx_status</structfield> field, then <structfield>reply</structfield> and
152 <structfield>timeout</structfield> are both set to 0 by the driver. Ignored by
153 <constant>CEC_RECEIVE</constant>. The case where <structfield>reply</structfield> is 0
154 (this is the opcode for the Feature Abort message) and <structfield>timeout</structfield>
155 is non-zero is specifically allowed to send a message and wait up to <structfield>timeout</structfield>
156 milliseconds for a Feature Abort reply. In this case <structfield>rx_status</structfield>
157 will either be set to <constant>CEC_RX_STATUS_TIMEOUT</constant> or
158 <constant>CEC_RX_STATUS_FEATURE_ABORT</constant>.</entry>
159 </row>
160 <row>
161 <entry>__u8</entry>
162 <entry><structfield>tx_arb_lost_cnt</structfield></entry>
163 <entry>A counter of the number of transmit attempts that resulted in the
164 Arbitration Lost error. This is only set if the hardware supports this, otherwise
165 it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_ARB_LOST</constant>
166 status bit is set.</entry>
167 </row>
168 <row>
169 <entry>__u8</entry>
170 <entry><structfield>tx_nack_cnt</structfield></entry>
171 <entry>A counter of the number of transmit attempts that resulted in the
172 Not Acknowledged error. This is only set if the hardware supports this, otherwise
173 it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_NACK</constant>
174 status bit is set.</entry>
175 </row>
176 <row>
177 <entry>__u8</entry>
178 <entry><structfield>tx_low_drive_cnt</structfield></entry>
179 <entry>A counter of the number of transmit attempts that resulted in the
180 Arbitration Lost error. This is only set if the hardware supports this, otherwise
181 it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_LOW_DRIVE</constant>
182 status bit is set.</entry>
183 </row>
184 <row>
185 <entry>__u8</entry>
186 <entry><structfield>tx_error_cnt</structfield></entry>
187 <entry>A counter of the number of transmit errors other than Arbitration Lost
188 or Not Acknowledged. This is only set if the hardware supports this, otherwise
189 it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_ERROR</constant>
190 status bit is set.</entry>
191 </row>
192 </tbody>
193 </tgroup>
194 </table>
195
196 <table pgwide="1" frame="none" id="cec-tx-status">
197 <title>CEC Transmit Status</title>
198 <tgroup cols="3">
199 &cs-def;
200 <tbody valign="top">
201 <row>
202 <entry><constant>CEC_TX_STATUS_OK</constant></entry>
203 <entry>0x01</entry>
204 <entry>The message was transmitted successfully. This is mutually exclusive with
205 <constant>CEC_TX_STATUS_MAX_RETRIES</constant>. Other bits can still be set if
206 earlier attempts met with failure before the transmit was eventually successful.</entry>
207 </row>
208 <row>
209 <entry><constant>CEC_TX_STATUS_ARB_LOST</constant></entry>
210 <entry>0x02</entry>
211 <entry>CEC line arbitration was lost.</entry>
212 </row>
213 <row>
214 <entry><constant>CEC_TX_STATUS_NACK</constant></entry>
215 <entry>0x04</entry>
216 <entry>Message was not acknowledged.</entry>
217 </row>
218 <row>
219 <entry><constant>CEC_TX_STATUS_LOW_DRIVE</constant></entry>
220 <entry>0x08</entry>
221 <entry>Low drive was detected on the CEC bus. This indicates that a follower
222 detected an error on the bus and requests a retransmission.</entry>
223 </row>
224 <row>
225 <entry><constant>CEC_TX_STATUS_ERROR</constant></entry>
226 <entry>0x10</entry>
227 <entry>Some error occurred. This is used for any errors that do not
228 fit the previous two, either because the hardware could not tell
229 which error occurred, or because the hardware tested for other conditions
230 besides those two.</entry>
231 </row>
232 <row>
233 <entry><constant>CEC_TX_STATUS_MAX_RETRIES</constant></entry>
234 <entry>0x20</entry>
235 <entry>The transmit failed after one or more retries. This status bit is mutually
236 exclusive with <constant>CEC_TX_STATUS_OK</constant>. Other bits can still be set
237 to explain which failures were seen.</entry>
238 </row>
239 </tbody>
240 </tgroup>
241 </table>
242
243 <table pgwide="1" frame="none" id="cec-rx-status">
244 <title>CEC Receive Status</title>
245 <tgroup cols="3">
246 &cs-def;
247 <tbody valign="top">
248 <row>
249 <entry><constant>CEC_RX_STATUS_OK</constant></entry>
250 <entry>0x01</entry>
251 <entry>The message was received successfully.</entry>
252 </row>
253 <row>
254 <entry><constant>CEC_RX_STATUS_TIMEOUT</constant></entry>
255 <entry>0x02</entry>
256 <entry>The reply to an earlier transmitted message timed out.</entry>
257 </row>
258 <row>
259 <entry><constant>CEC_RX_STATUS_FEATURE_ABORT</constant></entry>
260 <entry>0x04</entry>
261 <entry>The message was received successfully but the reply was
262 <constant>CEC_MSG_FEATURE_ABORT</constant>. This status is only
263 set if this message was the reply to an earlier transmitted
264 message.</entry>
265 </row>
266 </tbody>
267 </tgroup>
268 </table>
269 </refsect1>
270
271 <refsect1>
272 &return-value;
273 </refsect1>
274</refentry>
Documentation/DocBook/media_api.tmpl+5−1
@@ -75,7 +75,7 @@ · 74 unmodified lines
75 </mediaobject>75 </mediaobject>
76 </figure>76 </figure>
77 <para>The media infrastructure API was designed to control such77 <para>The media infrastructure API was designed to control such
78 devices. It is divided into four parts.</para>78 devices. It is divided into five parts.</para>
79 <para>The first part covers radio, video capture and output,79 <para>The first part covers radio, video capture and output,
80 cameras, analog TV devices and codecs.</para>80 cameras, analog TV devices and codecs.</para>
81 <para>The second part covers the81 <para>The second part covers the
@@ -87,6 +87,7 @@ · 5 unmodified lines
87 <xref linkend="fe-delivery-system-t" />.</para>87 <xref linkend="fe-delivery-system-t" />.</para>
88 <para>The third part covers the Remote Controller API.</para>88 <para>The third part covers the Remote Controller API.</para>
89 <para>The fourth part covers the Media Controller API.</para>89 <para>The fourth part covers the Media Controller API.</para>
90 <para>The fifth part covers the CEC (Consumer Electronics Control) API.</para>
90 <para>It should also be noted that a media device may also have audio91 <para>It should also be noted that a media device may also have audio
91 components, like mixers, PCM capture, PCM playback, etc, which92 components, like mixers, PCM capture, PCM playback, etc, which
92 are controlled via ALSA API.</para>93 are controlled via ALSA API.</para>
@@ -107,6 +108,9 @@ · 14 unmodified lines
107<part id="media_common">108<part id="media_common">
108&sub-media-controller;109&sub-media-controller;
109</part>110</part>
111<part id="cec">
112&sub-cec-api;
113</part>
110 114
111<chapter id="gen_errors">115<chapter id="gen_errors">
112&sub-gen-errors;116&sub-gen-errors;
Documentation/cec.txt+267−0
@@ -0,0 +1,267 @@
1CEC Kernel Support
2==================
3
4The CEC framework provides a unified kernel interface for use with HDMI CEC
5hardware. It is designed to handle a multiple types of hardware (receivers,
6transmitters, USB dongles). The framework also gives the option to decide
7what to do in the kernel driver and what should be handled by userspace
8applications. In addition it integrates the remote control passthrough
9feature into the kernel's remote control framework.
10
11
12The CEC Protocol
13----------------
14
15The CEC protocol enables consumer electronic devices to communicate with each
16other through the HDMI connection. The protocol uses logical addresses in the
17communication. The logical address is strictly connected with the functionality
18provided by the device. The TV acting as the communication hub is always
19assigned address 0. The physical address is determined by the physical
20connection between devices.
21
22The CEC framework described here is up to date with the CEC 2.0 specification.
23It is documented in the HDMI 1.4 specification with the new 2.0 bits documented
24in the HDMI 2.0 specification. But for most of the features the freely available
25HDMI 1.3a specification is sufficient:
26
27http://www.microprocessor.org/HDMISpecification13a.pdf
28
29
30The Kernel Interface
31====================
32
33CEC Adapter
34-----------
35
36The struct cec_adapter represents the CEC adapter hardware. It is created by
37calling cec_allocate_adapter() and deleted by calling cec_delete_adapter():
38
39struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
40 void *priv, const char *name, u32 caps, u8 available_las,
41 struct device *parent);
42void cec_delete_adapter(struct cec_adapter *adap);
43
44To create an adapter you need to pass the following information:
45
46ops: adapter operations which are called by the CEC framework and that you
47have to implement.
48
49priv: will be stored in adap->priv and can be used by the adapter ops.
50
51name: the name of the CEC adapter. Note: this name will be copied.
52
53caps: capabilities of the CEC adapter. These capabilities determine the
54 capabilities of the hardware and which parts are to be handled
55 by userspace and which parts are handled by kernelspace. The
56 capabilities are returned by CEC_ADAP_G_CAPS.
57
58available_las: the number of simultaneous logical addresses that this
59 adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS.
60
61parent: the parent device.
62
63
64To register the /dev/cecX device node and the remote control device (if
65CEC_CAP_RC is set) you call:
66
67int cec_register_adapter(struct cec_adapter *adap);
68
69To unregister the devices call:
70
71void cec_unregister_adapter(struct cec_adapter *adap);
72
73Note: if cec_register_adapter() fails, then call cec_delete_adapter() to
74clean up. But if cec_register_adapter() succeeded, then only call
75cec_unregister_adapter() to clean up, never cec_delete_adapter(). The
76unregister function will delete the adapter automatically once the last user
77of that /dev/cecX device has closed its file handle.
78
79
80Implementing the Low-Level CEC Adapter
81--------------------------------------
82
83The following low-level adapter operations have to be implemented in
84your driver:
85
86struct cec_adap_ops {
87 /* Low-level callbacks */
88 int (*adap_enable)(struct cec_adapter *adap, bool enable);
89 int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
90 int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
91 int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
92 u32 signal_free_time, struct cec_msg *msg);
93 void (*adap_log_status)(struct cec_adapter *adap);
94
95 /* High-level callbacks */
96 ...
97};
98
99The three low-level ops deal with various aspects of controlling the CEC adapter
100hardware:
101
102
103To enable/disable the hardware:
104
105 int (*adap_enable)(struct cec_adapter *adap, bool enable);
106
107This callback enables or disables the CEC hardware. Enabling the CEC hardware
108means powering it up in a state where no logical addresses are claimed. This
109op assumes that the physical address (adap->phys_addr) is valid when enable is
110true and will not change while the CEC adapter remains enabled. The initial
111state of the CEC adapter after calling cec_allocate_adapter() is disabled.
112
113Note that adap_enable must return 0 if enable is false.
114
115
116To enable/disable the 'monitor all' mode:
117
118 int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
119
120If enabled, then the adapter should be put in a mode to also monitor messages
121that not for us. Not all hardware supports this and this function is only
122called if the CEC_CAP_MONITOR_ALL capability is set. This callback is optional
123(some hardware may always be in 'monitor all' mode).
124
125Note that adap_monitor_all_enable must return 0 if enable is false.
126
127
128To program a new logical address:
129
130 int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
131
132If logical_addr == CEC_LOG_ADDR_INVALID then all programmed logical addresses
133are to be erased. Otherwise the given logical address should be programmed.
134If the maximum number of available logical addresses is exceeded, then it
135should return -ENXIO. Once a logical address is programmed the CEC hardware
136can receive directed messages to that address.
137
138Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
139
140
141To transmit a new message:
142
143 int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
144 u32 signal_free_time, struct cec_msg *msg);
145
146This transmits a new message. The attempts argument is the suggested number of
147attempts for the transmit.
148
149The signal_free_time is the number of data bit periods that the adapter should
150wait when the line is free before attempting to send a message. This value
151depends on whether this transmit is a retry, a message from a new initiator or
152a new message for the same initiator. Most hardware will handle this
153automatically, but in some cases this information is needed.
154
155The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to
156microseconds (one data bit period is 2.4 ms).
157
158
159To log the current CEC hardware status:
160
161 void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
162
163This optional callback can be used to show the status of the CEC hardware.
164The status is available through debugfs: cat /sys/kernel/debug/cec/cecX/status
165
166
167Your adapter driver will also have to react to events (typically interrupt
168driven) by calling into the framework in the following situations:
169
170When a transmit finished (successfully or otherwise):
171
172void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
173 u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt);
174
175The status can be one of:
176
177CEC_TX_STATUS_OK: the transmit was successful.
178CEC_TX_STATUS_ARB_LOST: arbitration was lost: another CEC initiator
179took control of the CEC line and you lost the arbitration.
180CEC_TX_STATUS_NACK: the message was nacked (for a directed message) or
181acked (for a broadcast message). A retransmission is needed.
182CEC_TX_STATUS_LOW_DRIVE: low drive was detected on the CEC bus. This
183indicates that a follower detected an error on the bus and requested a
184retransmission.
185CEC_TX_STATUS_ERROR: some unspecified error occurred: this can be one of
186the previous two if the hardware cannot differentiate or something else
187entirely.
188CEC_TX_STATUS_MAX_RETRIES: could not transmit the message after
189trying multiple times. Should only be set by the driver if it has hardware
190support for retrying messages. If set, then the framework assumes that it
191doesn't have to make another attempt to transmit the message since the
192hardware did that already.
193
194The *_cnt arguments are the number of error conditions that were seen.
195This may be 0 if no information is available. Drivers that do not support
196hardware retry can just set the counter corresponding to the transmit error
197to 1, if the hardware does support retry then either set these counters to
1980 if the hardware provides no feedback of which errors occurred and how many
199times, or fill in the correct values as reported by the hardware.
200
201When a CEC message was received:
202
203void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
204
205Speaks for itself.
206
207Implementing the High-Level CEC Adapter
208---------------------------------------
209
210The low-level operations drive the hardware, the high-level operations are
211CEC protocol driven. The following high-level callbacks are available:
212
213struct cec_adap_ops {
214 /* Low-level callbacks */
215 ...
216
217 /* High-level CEC message callback */
218 int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
219};
220
221The received() callback allows the driver to optionally handle a newly
222received CEC message
223
224 int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
225
226If the driver wants to process a CEC message, then it can implement this
227callback. If it doesn't want to handle this message, then it should return
228-ENOMSG, otherwise the CEC framework assumes it processed this message and
229it will not no anything with it.
230
231
232CEC framework functions
233-----------------------
234
235CEC Adapter drivers can call the following CEC framework functions:
236
237int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
238 bool block);
239
240Transmit a CEC message. If block is true, then wait until the message has been
241transmitted, otherwise just queue it and return.
242
243void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
244
245Change the physical address. This function will set adap->phys_addr and
246send an event if it has changed. If cec_s_log_addrs() has been called and
247the physical address has become valid, then the CEC framework will start
248claiming the logical addresses. If block is true, then this function won't
249return until this process has finished.
250
251When the physical address is set to a valid value the CEC adapter will
252be enabled (see the adap_enable op). When it is set to CEC_PHYS_ADDR_INVALID,
253then the CEC adapter will be disabled. If you change a valid physical address
254to another valid physical address, then this function will first set the
255address to CEC_PHYS_ADDR_INVALID before enabling the new physical address.
256
257int cec_s_log_addrs(struct cec_adapter *adap,
258 struct cec_log_addrs *log_addrs, bool block);
259
260Claim the CEC logical addresses. Should never be called if CEC_CAP_LOG_ADDRS
261is set. If block is true, then wait until the logical addresses have been
262claimed, otherwise just queue it and return. To unconfigure all logical
263addresses call this function with log_addrs set to NULL or with
264log_addrs->num_log_addrs set to 0. The block argument is ignored when
265unconfiguring. This function will just return if the physical address is
266invalid. Once the physical address becomes valid, then the framework will
267attempt to claim these logical addresses.
Documentation/devicetree/bindings/media/s5p-cec.txt+31−0
@@ -0,0 +1,31 @@
1* Samsung HDMI CEC driver
2
3The HDMI CEC module is present is Samsung SoCs and its purpose is to
4handle communication between HDMI connected devices over the CEC bus.
5
6Required properties:
7 - compatible : value should be following
8 "samsung,s5p-cec"
9
10 - reg : Physical base address of the IP registers and length of memory
11 mapped region.
12
13 - interrupts : HDMI CEC interrupt number to the CPU.
14 - clocks : from common clock binding: handle to HDMI CEC clock.
15 - clock-names : from common clock binding: must contain "hdmicec",
16 corresponding to entry in the clocks property.
17 - samsung,syscon-phandle - phandle to the PMU system controller
18
19Example:
20
21hdmicec: cec@100B0000 {
22 compatible = "samsung,s5p-cec";
23 reg = <0x100B0000 0x200>;
24 interrupts = <0 114 0>;
25 clocks = <&clock CLK_HDMI_CEC>;
26 clock-names = "hdmicec";
27 samsung,syscon-phandle = <&pmu_system_controller>;
28 pinctrl-names = "default";
29 pinctrl-0 = <&hdmi_cec>;
30 status = "okay";
31};
Documentation/video4linux/vivid.txt+31−5
@@ -74,7 +74,8 @@ Section 11: Cropping, Composing, Scaling · 73 unmodified lines
74Section 12: Formats74Section 12: Formats
75Section 13: Capture Overlay75Section 13: Capture Overlay
76Section 14: Output Overlay76Section 14: Output Overlay
77Section 15: Some Future Improvements77Section 15: CEC (Consumer Electronics Control)
78Section 16: Some Future Improvements
78 79
79 80
80Section 1: Configuring the driver81Section 1: Configuring the driver
@@ -364,7 +365,11 @@ For HDMI inputs it is possible to set the EDID. By default a simple EDID · 283 unmodified lines
364is provided. You can only set the EDID for HDMI inputs. Internally, however,365is provided. You can only set the EDID for HDMI inputs. Internally, however,
365the EDID is shared between all HDMI inputs.366the EDID is shared between all HDMI inputs.
366 367
367No interpretation is done of the EDID data.368No interpretation is done of the EDID data with the exception of the
369physical address. See the CEC section for more details.
370
371There is a maximum of 15 HDMI inputs (if there are more, then they will be
372reduced to 15) since that's the limitation of the EDID physical address.
368 373
369 374
370Section 3: Video Output375Section 3: Video Output
@@ -409,6 +414,9 @@ standard, and for all others a 1:1 pixel aspect ratio is returned. · 38 unmodified lines
409 414
410An HDMI output has a valid EDID which can be obtained through VIDIOC_G_EDID.415An HDMI output has a valid EDID which can be obtained through VIDIOC_G_EDID.
411 416
417There is a maximum of 15 HDMI outputs (if there are more, then they will be
418reduced to 15) since that's the limitation of the EDID physical address. See
419also the CEC section for more details.
412 420
413Section 4: VBI Capture421Section 4: VBI Capture
414----------------------422----------------------
@@ -1108,7 +1116,26 @@ capabilities will slow down the video loop considerably as a lot of checks have · 693 unmodified lines
1108to be done per pixel.1116to be done per pixel.
1109 1117
1110 1118
1111Section 15: Some Future Improvements1119Section 15: CEC (Consumer Electronics Control)
1120----------------------------------------------
1121
1122If there are HDMI inputs then a CEC adapter will be created that has
1123the same number of input ports. This is the equivalent of e.g. a TV that
1124has that number of inputs. Each HDMI output will also create a
1125CEC adapter that is hooked up to the corresponding input port, or (if there
1126are more outputs than inputs) is not hooked up at all. In other words,
1127this is the equivalent of hooking up each output device to an input port of
1128the TV. Any remaining output devices remain unconnected.
1129
1130The EDID that each output reads reports a unique CEC physical address that is
1131based on the physical address of the EDID of the input. So if the EDID of the
1132receiver has physical address A.B.0.0, then each output will see an EDID
1133containing physical address A.B.C.0 where C is 1 to the number of inputs. If
1134there are more outputs than inputs then the remaining outputs have a CEC adapter
1135that is disabled and reports an invalid physical address.
1136
1137
1138Section 16: Some Future Improvements
1112------------------------------------1139------------------------------------
1113 1140
1114Just as a reminder and in no particular order:1141Just as a reminder and in no particular order:
@@ -1121,8 +1148,6 @@ Just as a reminder and in no particular order: · 6 unmodified lines
1121- Fix sequence/field numbering when looping of video with alternate fields1148- Fix sequence/field numbering when looping of video with alternate fields
1122- Add support for V4L2_CID_BG_COLOR for video outputs1149- Add support for V4L2_CID_BG_COLOR for video outputs
1123- Add ARGB888 overlay support: better testing of the alpha channel1150- Add ARGB888 overlay support: better testing of the alpha channel
1124- Add custom DV timings support
1125- Add support for V4L2_DV_FL_REDUCED_FPS
1126- Improve pixel aspect support in the tpg code by passing a real v4l2_fract1151- Improve pixel aspect support in the tpg code by passing a real v4l2_fract
1127- Use per-queue locks and/or per-device locks to improve throughput1152- Use per-queue locks and/or per-device locks to improve throughput
1128- Add support to loop from a specific output to a specific input across1153- Add support to loop from a specific output to a specific input across
@@ -1133,3 +1158,4 @@ Just as a reminder and in no particular order: · 4 unmodified lines
1133- Make a thread for the RDS generation, that would help in particular for the1158- Make a thread for the RDS generation, that would help in particular for the
1134 "Controls" RDS Rx I/O Mode as the read-only RDS controls could be updated1159 "Controls" RDS Rx I/O Mode as the read-only RDS controls could be updated
1135 in real-time.1160 in real-time.
1161- Changing the EDID should cause hotplug detect emulation to happen.
MAINTAINERS+23−0
@@ -1642,6 +1642,13 @@ L: linux-media@vger.kernel.org · 1641 unmodified lines
1642S: Maintained1642S: Maintained
1643F: drivers/media/platform/s5p-tv/1643F: drivers/media/platform/s5p-tv/
1644 1644
1645ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT
1646M: Kyungmin Park <kyungmin.park@samsung.com>
1647L: linux-arm-kernel@lists.infradead.org
1648L: linux-media@vger.kernel.org
1649S: Maintained
1650F: drivers/staging/media/platform/s5p-cec/
1651
1645ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT1652ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
1646M: Andrzej Pietrasiewicz <andrzej.p@samsung.com>1653M: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
1647M: Jacek Anaszewski <j.anaszewski@samsung.com>1654M: Jacek Anaszewski <j.anaszewski@samsung.com>
@@ -2847,6 +2854,22 @@ F: drivers/net/ieee802154/cc2520.c · 1199 unmodified lines
2847F: include/linux/spi/cc2520.h2854F: include/linux/spi/cc2520.h
2848F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt2855F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
2849 2856
2857CEC DRIVER
2858M: Hans Verkuil <hans.verkuil@cisco.com>
2859L: linux-media@vger.kernel.org
2860T: git git://linuxtv.org/media_tree.git
2861W: http://linuxtv.org
2862S: Supported
2863F: Documentation/cec.txt
2864F: Documentation/DocBook/media/v4l/cec*
2865F: drivers/staging/media/cec/
2866F: drivers/media/cec-edid.c
2867F: drivers/media/rc/keymaps/rc-cec.c
2868F: include/media/cec.h
2869F: include/media/cec-edid.h
2870F: include/linux/cec.h
2871F: include/linux/cec-funcs.h
2872
2850CELL BROADBAND ENGINE ARCHITECTURE2873CELL BROADBAND ENGINE ARCHITECTURE
2851M: Arnd Bergmann <arnd@arndb.de>2874M: Arnd Bergmann <arnd@arndb.de>
2852L: linuxppc-dev@lists.ozlabs.org2875L: linuxppc-dev@lists.ozlabs.org
drivers/media/Kconfig+3−0
@@ -80,6 +80,9 @@ config MEDIA_RC_SUPPORT · 79 unmodified lines
80 80
81 Say Y when you have a TV or an IR device.81 Say Y when you have a TV or an IR device.
82 82
83config MEDIA_CEC_EDID
84 tristate
85
83#86#
84# Media controller87# Media controller
85# Selectable only for webcam/grabbers, as other drivers don't use it88# Selectable only for webcam/grabbers, as other drivers don't use it
drivers/media/Makefile+2−0
@@ -2,6 +2,8 @@ · 1 unmodified line
2# Makefile for the kernel multimedia device drivers.2# Makefile for the kernel multimedia device drivers.
3#3#
4 4
5obj-$(CONFIG_MEDIA_CEC_EDID) += cec-edid.o
6
5media-objs := media-device.o media-devnode.o media-entity.o7media-objs := media-device.o media-devnode.o media-entity.o
6 8
7#9#
drivers/media/cec-edid.c+168−0
@@ -0,0 +1,168 @@
1/*
2 * cec-edid - HDMI Consumer Electronics Control EDID & CEC helper functions
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/types.h>
23#include <media/cec-edid.h>
24
25/*
26 * This EDID is expected to be a CEA-861 compliant, which means that there are
27 * at least two blocks and one or more of the extensions blocks are CEA-861
28 * blocks.
29 *
30 * The returned location is guaranteed to be < size - 1.
31 */
32static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size)
33{
34 unsigned int blocks = size / 128;
35 unsigned int block;
36 u8 d;
37
38 /* Sanity check: at least 2 blocks and a multiple of the block size */
39 if (blocks < 2 || size % 128)
40 return 0;
41
42 /*
43 * If there are fewer extension blocks than the size, then update
44 * 'blocks'. It is allowed to have more extension blocks than the size,
45 * since some hardware can only read e.g. 256 bytes of the EDID, even
46 * though more blocks are present. The first CEA-861 extension block
47 * should normally be in block 1 anyway.
48 */
49 if (edid[0x7e] + 1 < blocks)
50 blocks = edid[0x7e] + 1;
51
52 for (block = 1; block < blocks; block++) {
53 unsigned int offset = block * 128;
54
55 /* Skip any non-CEA-861 extension blocks */
56 if (edid[offset] != 0x02 || edid[offset + 1] != 0x03)
57 continue;
58
59 /* search Vendor Specific Data Block (tag 3) */
60 d = edid[offset + 2] & 0x7f;
61 /* Check if there are Data Blocks */
62 if (d <= 4)
63 continue;
64 if (d > 4) {
65 unsigned int i = offset + 4;
66 unsigned int end = offset + d;
67
68 /* Note: 'end' is always < 'size' */
69 do {
70 u8 tag = edid[i] >> 5;
71 u8 len = edid[i] & 0x1f;
72
73 if (tag == 3 && len >= 5 && i + len <= end)
74 return i + 4;
75 i += len + 1;
76 } while (i < end);
77 }
78 }
79 return 0;
80}
81
82u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
83 unsigned int *offset)
84{
85 unsigned int loc = cec_get_edid_spa_location(edid, size);
86
87 if (offset)
88 *offset = loc;
89 if (loc == 0)
90 return CEC_PHYS_ADDR_INVALID;
91 return (edid[loc] << 8) | edid[loc + 1];
92}
93EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr);
94
95void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr)
96{
97 unsigned int loc = cec_get_edid_spa_location(edid, size);
98 u8 sum = 0;
99 unsigned int i;
100
101 if (loc == 0)
102 return;
103 edid[loc] = phys_addr >> 8;
104 edid[loc + 1] = phys_addr & 0xff;
105 loc &= ~0x7f;
106
107 /* update the checksum */
108 for (i = loc; i < loc + 127; i++)
109 sum += edid[i];
110 edid[i] = 256 - sum;
111}
112EXPORT_SYMBOL_GPL(cec_set_edid_phys_addr);
113
114u16 cec_phys_addr_for_input(u16 phys_addr, u8 input)
115{
116 /* Check if input is sane */
117 if (WARN_ON(input == 0 || input > 0xf))
118 return CEC_PHYS_ADDR_INVALID;
119
120 if (phys_addr == 0)
121 return input << 12;
122
123 if ((phys_addr & 0x0fff) == 0)
124 return phys_addr | (input << 8);
125
126 if ((phys_addr & 0x00ff) == 0)
127 return phys_addr | (input << 4);
128
129 if ((phys_addr & 0x000f) == 0)
130 return phys_addr | input;
131
132 /*
133 * All nibbles are used so no valid physical addresses can be assigned
134 * to the input.
135 */
136 return CEC_PHYS_ADDR_INVALID;
137}
138EXPORT_SYMBOL_GPL(cec_phys_addr_for_input);
139
140int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
141{
142 int i;
143
144 if (parent)
145 *parent = phys_addr;
146 if (port)
147 *port = 0;
148 if (phys_addr == CEC_PHYS_ADDR_INVALID)
149 return 0;
150 for (i = 0; i < 16; i += 4)
151 if (phys_addr & (0xf << i))
152 break;
153 if (i == 16)
154 return 0;
155 if (parent)
156 *parent = phys_addr & (0xfff0 << i);
157 if (port)
158 *port = (phys_addr >> i) & 0xf;
159 for (i += 4; i < 16; i += 4)
160 if ((phys_addr & (0xf << i)) == 0)
161 return -EINVAL;
162 return 0;
163}
164EXPORT_SYMBOL_GPL(cec_phys_addr_validate);
165
166MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
167MODULE_DESCRIPTION("CEC EDID helper functions");
168MODULE_LICENSE("GPL");
drivers/media/i2c/Kconfig+24−0
@@ -209,6 +209,7 @@ config VIDEO_ADV7604 · 208 unmodified lines
209 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API209 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
210 depends on GPIOLIB || COMPILE_TEST210 depends on GPIOLIB || COMPILE_TEST
211 select HDMI211 select HDMI
212 select MEDIA_CEC_EDID
212 ---help---213 ---help---
213 Support for the Analog Devices ADV7604 video decoder.214 Support for the Analog Devices ADV7604 video decoder.
214 215
@@ -218,10 +219,18 @@ config VIDEO_ADV7604 · 3 unmodified lines
218 To compile this driver as a module, choose M here: the219 To compile this driver as a module, choose M here: the
219 module will be called adv7604.220 module will be called adv7604.
220 221
222config VIDEO_ADV7604_CEC
223 bool "Enable Analog Devices ADV7604 CEC support"
224 depends on VIDEO_ADV7604 && MEDIA_CEC
225 ---help---
226 When selected the adv7604 will support the optional
227 HDMI CEC feature.
228
221config VIDEO_ADV7842229config VIDEO_ADV7842
222 tristate "Analog Devices ADV7842 decoder"230 tristate "Analog Devices ADV7842 decoder"
223 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API231 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
224 select HDMI232 select HDMI
233 select MEDIA_CEC_EDID
225 ---help---234 ---help---
226 Support for the Analog Devices ADV7842 video decoder.235 Support for the Analog Devices ADV7842 video decoder.
227 236
@@ -231,6 +240,13 @@ config VIDEO_ADV7842 · 3 unmodified lines
231 To compile this driver as a module, choose M here: the240 To compile this driver as a module, choose M here: the
232 module will be called adv7842.241 module will be called adv7842.
233 242
243config VIDEO_ADV7842_CEC
244 bool "Enable Analog Devices ADV7842 CEC support"
245 depends on VIDEO_ADV7842 && MEDIA_CEC
246 ---help---
247 When selected the adv7842 will support the optional
248 HDMI CEC feature.
249
234config VIDEO_BT819250config VIDEO_BT819
235 tristate "BT819A VideoStream decoder"251 tristate "BT819A VideoStream decoder"
236 depends on VIDEO_V4L2 && I2C252 depends on VIDEO_V4L2 && I2C
@@ -447,6 +463,7 @@ config VIDEO_ADV7511 · 210 unmodified lines
447 tristate "Analog Devices ADV7511 encoder"463 tristate "Analog Devices ADV7511 encoder"
448 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API464 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
449 select HDMI465 select HDMI
466 select MEDIA_CEC_EDID
450 ---help---467 ---help---
451 Support for the Analog Devices ADV7511 video encoder.468 Support for the Analog Devices ADV7511 video encoder.
452 469
@@ -455,6 +472,13 @@ config VIDEO_ADV7511 · 2 unmodified lines
455 To compile this driver as a module, choose M here: the472 To compile this driver as a module, choose M here: the
456 module will be called adv7511.473 module will be called adv7511.
457 474
475config VIDEO_ADV7511_CEC
476 bool "Enable Analog Devices ADV7511 CEC support"
477 depends on VIDEO_ADV7511 && MEDIA_CEC
478 ---help---
479 When selected the adv7511 will support the optional
480 HDMI CEC feature.
481
458config VIDEO_AD9389B482config VIDEO_AD9389B
459 tristate "Analog Devices AD9389B encoder"483 tristate "Analog Devices AD9389B encoder"
460 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API484 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
drivers/media/i2c/adv7511.c+393−8
@@ -33,6 +33,7 @@ · 32 unmodified lines
33#include <media/v4l2-ctrls.h>33#include <media/v4l2-ctrls.h>
34#include <media/v4l2-dv-timings.h>34#include <media/v4l2-dv-timings.h>
35#include <media/i2c/adv7511.h>35#include <media/i2c/adv7511.h>
36#include <media/cec.h>
36 37
37static int debug;38static int debug;
38module_param(debug, int, 0644);39module_param(debug, int, 0644);
@@ -59,6 +60,8 @@ MODULE_LICENSE("GPL v2"); · 20 unmodified lines
59#define ADV7511_MIN_PIXELCLOCK 2000000060#define ADV7511_MIN_PIXELCLOCK 20000000
60#define ADV7511_MAX_PIXELCLOCK 22500000061#define ADV7511_MAX_PIXELCLOCK 225000000
61 62
63#define ADV7511_MAX_ADDRS (3)
64
62/*65/*
63**********************************************************************66**********************************************************************
64*67*
@@ -90,12 +93,20 @@ struct adv7511_state { · 25 unmodified lines
90 struct v4l2_ctrl_handler hdl;93 struct v4l2_ctrl_handler hdl;
91 int chip_revision;94 int chip_revision;
92 u8 i2c_edid_addr;95 u8 i2c_edid_addr;
93 u8 i2c_cec_addr;
94 u8 i2c_pktmem_addr;96 u8 i2c_pktmem_addr;
97 u8 i2c_cec_addr;
98
99 struct i2c_client *i2c_cec;
100 struct cec_adapter *cec_adap;
101 u8 cec_addr[ADV7511_MAX_ADDRS];
102 u8 cec_valid_addrs;
103 bool cec_enabled_adap;
104
95 /* Is the adv7511 powered on? */105 /* Is the adv7511 powered on? */
96 bool power_on;106 bool power_on;
97 /* Did we receive hotplug and rx-sense signals? */107 /* Did we receive hotplug and rx-sense signals? */
98 bool have_monitor;108 bool have_monitor;
109 bool enabled_irq;
99 /* timings from s_dv_timings */110 /* timings from s_dv_timings */
100 struct v4l2_dv_timings dv_timings;111 struct v4l2_dv_timings dv_timings;
101 u32 fmt_code;112 u32 fmt_code;
@@ -227,7 +238,7 @@ static int adv_smbus_read_i2c_block_data(struct i2c_client *client, · 125 unmodified lines
227 return ret;238 return ret;
228}239}
229 240
230static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)241static void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf)
231{242{
232 struct adv7511_state *state = get_adv7511_state(sd);243 struct adv7511_state *state = get_adv7511_state(sd);
233 int i;244 int i;
@@ -242,6 +253,34 @@ static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf) · 8 unmodified lines
242 v4l2_err(sd, "%s: i2c read error\n", __func__);253 v4l2_err(sd, "%s: i2c read error\n", __func__);
243}254}
244 255
256static inline int adv7511_cec_read(struct v4l2_subdev *sd, u8 reg)
257{
258 struct adv7511_state *state = get_adv7511_state(sd);
259
260 return i2c_smbus_read_byte_data(state->i2c_cec, reg);
261}
262
263static int adv7511_cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
264{
265 struct adv7511_state *state = get_adv7511_state(sd);
266 int ret;
267 int i;
268
269 for (i = 0; i < 3; i++) {
270 ret = i2c_smbus_write_byte_data(state->i2c_cec, reg, val);
271 if (ret == 0)
272 return 0;
273 }
274 v4l2_err(sd, "%s: I2C Write Problem\n", __func__);
275 return ret;
276}
277
278static inline int adv7511_cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask,
279 u8 val)
280{
281 return adv7511_cec_write(sd, reg, (adv7511_cec_read(sd, reg) & mask) | val);
282}
283
245static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)284static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
246{285{
247 struct adv7511_state *state = get_adv7511_state(sd);286 struct adv7511_state *state = get_adv7511_state(sd);
@@ -425,16 +464,28 @@ static const struct v4l2_ctrl_ops adv7511_ctrl_ops = { · 177 unmodified lines
425#ifdef CONFIG_VIDEO_ADV_DEBUG464#ifdef CONFIG_VIDEO_ADV_DEBUG
426static void adv7511_inv_register(struct v4l2_subdev *sd)465static void adv7511_inv_register(struct v4l2_subdev *sd)
427{466{
467 struct adv7511_state *state = get_adv7511_state(sd);
468
428 v4l2_info(sd, "0x000-0x0ff: Main Map\n");469 v4l2_info(sd, "0x000-0x0ff: Main Map\n");
470 if (state->i2c_cec)
471 v4l2_info(sd, "0x100-0x1ff: CEC Map\n");
429}472}
430 473
431static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)474static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
432{475{
476 struct adv7511_state *state = get_adv7511_state(sd);
477
433 reg->size = 1;478 reg->size = 1;
434 switch (reg->reg >> 8) {479 switch (reg->reg >> 8) {
435 case 0:480 case 0:
436 reg->val = adv7511_rd(sd, reg->reg & 0xff);481 reg->val = adv7511_rd(sd, reg->reg & 0xff);
437 break;482 break;
483 case 1:
484 if (state->i2c_cec) {
485 reg->val = adv7511_cec_read(sd, reg->reg & 0xff);
486 break;
487 }
488 /* fall through */
438 default:489 default:
439 v4l2_info(sd, "Register %03llx not supported\n", reg->reg);490 v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
440 adv7511_inv_register(sd);491 adv7511_inv_register(sd);
@@ -445,10 +496,18 @@ static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * · 4 unmodified lines
445 496
446static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)497static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
447{498{
499 struct adv7511_state *state = get_adv7511_state(sd);
500
448 switch (reg->reg >> 8) {501 switch (reg->reg >> 8) {
449 case 0:502 case 0:
450 adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff);503 adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff);
451 break;504 break;
505 case 1:
506 if (state->i2c_cec) {
507 adv7511_cec_write(sd, reg->reg & 0xff, reg->val & 0xff);
508 break;
509 }
510 /* fall through */
452 default:511 default:
453 v4l2_info(sd, "Register %03llx not supported\n", reg->reg);512 v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
454 adv7511_inv_register(sd);513 adv7511_inv_register(sd);
@@ -536,6 +595,7 @@ static int adv7511_log_status(struct v4l2_subdev *sd) · 81 unmodified lines
536{595{
537 struct adv7511_state *state = get_adv7511_state(sd);596 struct adv7511_state *state = get_adv7511_state(sd);
538 struct adv7511_state_edid *edid = &state->edid;597 struct adv7511_state_edid *edid = &state->edid;
598 int i;
539 599
540 static const char * const states[] = {600 static const char * const states[] = {
541 "in reset",601 "in reset",
@@ -605,7 +665,23 @@ static int adv7511_log_status(struct v4l2_subdev *sd) · 63 unmodified lines
605 else665 else
606 v4l2_info(sd, "no timings set\n");666 v4l2_info(sd, "no timings set\n");
607 v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr);667 v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr);
668
669 if (state->i2c_cec == NULL)
670 return 0;
671
608 v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr);672 v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr);
673
674 v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ?
675 "enabled" : "disabled");
676 if (state->cec_enabled_adap) {
677 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
678 bool is_valid = state->cec_valid_addrs & (1 << i);
679
680 if (is_valid)
681 v4l2_info(sd, "CEC Logical Address: 0x%x\n",
682 state->cec_addr[i]);
683 }
684 }
609 v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr);685 v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr);
610 return 0;686 return 0;
611}687}
@@ -663,15 +739,197 @@ static int adv7511_s_power(struct v4l2_subdev *sd, int on) · 51 unmodified lines
663 return true;739 return true;
664}740}
665 741
742#if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
743static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
744{
745 struct adv7511_state *state = adap->priv;
746 struct v4l2_subdev *sd = &state->sd;
747
748 if (state->i2c_cec == NULL)
749 return -EIO;
750
751 if (!state->cec_enabled_adap && enable) {
752 /* power up cec section */
753 adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x01);
754 /* legacy mode and clear all rx buffers */
755 adv7511_cec_write(sd, 0x4a, 0x07);
756 adv7511_cec_write(sd, 0x4a, 0);
757 adv7511_cec_write_and_or(sd, 0x11, 0xfe, 0); /* initially disable tx */
758 /* enabled irqs: */
759 /* tx: ready */
760 /* tx: arbitration lost */
761 /* tx: retry timeout */
762 /* rx: ready 1 */
763 if (state->enabled_irq)
764 adv7511_wr_and_or(sd, 0x95, 0xc0, 0x39);
765 } else if (state->cec_enabled_adap && !enable) {
766 if (state->enabled_irq)
767 adv7511_wr_and_or(sd, 0x95, 0xc0, 0x00);
768 /* disable address mask 1-3 */
769 adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0x00);
770 /* power down cec section */
771 adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x00);
772 state->cec_valid_addrs = 0;
773 }
774 state->cec_enabled_adap = enable;
775 return 0;
776}
777
778static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
779{
780 struct adv7511_state *state = adap->priv;
781 struct v4l2_subdev *sd = &state->sd;
782 unsigned int i, free_idx = ADV7511_MAX_ADDRS;
783
784 if (!state->cec_enabled_adap)
785 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
786
787 if (addr == CEC_LOG_ADDR_INVALID) {
788 adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0);
789 state->cec_valid_addrs = 0;
790 return 0;
791 }
792
793 for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
794 bool is_valid = state->cec_valid_addrs & (1 << i);
795
796 if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
797 free_idx = i;
798 if (is_valid && state->cec_addr[i] == addr)
799 return 0;
800 }
801 if (i == ADV7511_MAX_ADDRS) {
802 i = free_idx;
803 if (i == ADV7511_MAX_ADDRS)
804 return -ENXIO;
805 }
806 state->cec_addr[i] = addr;
807 state->cec_valid_addrs |= 1 << i;
808
809 switch (i) {
810 case 0:
811 /* enable address mask 0 */
812 adv7511_cec_write_and_or(sd, 0x4b, 0xef, 0x10);
813 /* set address for mask 0 */
814 adv7511_cec_write_and_or(sd, 0x4c, 0xf0, addr);
815 break;
816 case 1:
817 /* enable address mask 1 */
818 adv7511_cec_write_and_or(sd, 0x4b, 0xdf, 0x20);
819 /* set address for mask 1 */
820 adv7511_cec_write_and_or(sd, 0x4c, 0x0f, addr << 4);
821 break;
822 case 2:
823 /* enable address mask 2 */
824 adv7511_cec_write_and_or(sd, 0x4b, 0xbf, 0x40);
825 /* set address for mask 1 */
826 adv7511_cec_write_and_or(sd, 0x4d, 0xf0, addr);
827 break;
828 }
829 return 0;
830}
831
832static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
833 u32 signal_free_time, struct cec_msg *msg)
834{
835 struct adv7511_state *state = adap->priv;
836 struct v4l2_subdev *sd = &state->sd;
837 u8 len = msg->len;
838 unsigned int i;
839
840 v4l2_dbg(1, debug, sd, "%s: len %d\n", __func__, len);
841
842 if (len > 16) {
843 v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len);
844 return -EINVAL;
845 }
846
847 /*
848 * The number of retries is the number of attempts - 1, but retry
849 * at least once. It's not clear if a value of 0 is allowed, so
850 * let's do at least one retry.
851 */
852 adv7511_cec_write_and_or(sd, 0x12, ~0x70, max(1, attempts - 1) << 4);
853
854 /* blocking, clear cec tx irq status */
855 adv7511_wr_and_or(sd, 0x97, 0xc7, 0x38);
856
857 /* write data */
858 for (i = 0; i < len; i++)
859 adv7511_cec_write(sd, i, msg->msg[i]);
860
861 /* set length (data + header) */
862 adv7511_cec_write(sd, 0x10, len);
863 /* start transmit, enable tx */
864 adv7511_cec_write(sd, 0x11, 0x01);
865 return 0;
866}
867
868static void adv_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
869{
870 struct adv7511_state *state = get_adv7511_state(sd);
871
872 if ((adv7511_cec_read(sd, 0x11) & 0x01) == 0) {
873 v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__);
874 return;
875 }
876
877 if (tx_raw_status & 0x10) {
878 v4l2_dbg(1, debug, sd,
879 "%s: tx raw: arbitration lost\n", __func__);
880 cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST,
881 1, 0, 0, 0);
882 return;
883 }
884 if (tx_raw_status & 0x08) {
885 u8 status;
886 u8 nack_cnt;
887 u8 low_drive_cnt;
888
889 v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__);
890 /*
891 * We set this status bit since this hardware performs
892 * retransmissions.
893 */
894 status = CEC_TX_STATUS_MAX_RETRIES;
895 nack_cnt = adv7511_cec_read(sd, 0x14) & 0xf;
896 if (nack_cnt)
897 status |= CEC_TX_STATUS_NACK;
898 low_drive_cnt = adv7511_cec_read(sd, 0x14) >> 4;
899 if (low_drive_cnt)
900 status |= CEC_TX_STATUS_LOW_DRIVE;
901 cec_transmit_done(state->cec_adap, status,
902 0, nack_cnt, low_drive_cnt, 0);
903 return;
904 }
905 if (tx_raw_status & 0x20) {
906 v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__);
907 cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
908 return;
909 }
910}
911
912static const struct cec_adap_ops adv7511_cec_adap_ops = {
913 .adap_enable = adv7511_cec_adap_enable,
914 .adap_log_addr = adv7511_cec_adap_log_addr,
915 .adap_transmit = adv7511_cec_adap_transmit,
916};
917#endif
918
666/* Enable interrupts */919/* Enable interrupts */
667static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)920static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
668{921{
922 struct adv7511_state *state = get_adv7511_state(sd);
669 u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT;923 u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT;
670 u8 irqs_rd;924 u8 irqs_rd;
671 int retries = 100;925 int retries = 100;
672 926
673 v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable");927 v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable");
674 928
929 if (state->enabled_irq == enable)
930 return;
931 state->enabled_irq = enable;
932
675 /* The datasheet says that the EDID ready interrupt should be933 /* The datasheet says that the EDID ready interrupt should be
676 disabled if there is no hotplug. */934 disabled if there is no hotplug. */
677 if (!enable)935 if (!enable)
@@ -679,6 +937,9 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) · 1 unmodified line
679 else if (adv7511_have_hotplug(sd))937 else if (adv7511_have_hotplug(sd))
680 irqs |= MASK_ADV7511_EDID_RDY_INT;938 irqs |= MASK_ADV7511_EDID_RDY_INT;
681 939
940 adv7511_wr_and_or(sd, 0x95, 0xc0,
941 (state->cec_enabled_adap && enable) ? 0x39 : 0x00);
942
682 /*943 /*
683 * This i2c write can fail (approx. 1 in 1000 writes). But it944 * This i2c write can fail (approx. 1 in 1000 writes). But it
684 * is essential that this register is correct, so retry it945 * is essential that this register is correct, so retry it
@@ -701,20 +962,53 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) · 16 unmodified lines
701static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)962static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
702{963{
703 u8 irq_status;964 u8 irq_status;
965 u8 cec_irq;
704 966
705 /* disable interrupts to prevent a race condition */967 /* disable interrupts to prevent a race condition */
706 adv7511_set_isr(sd, false);968 adv7511_set_isr(sd, false);
707 irq_status = adv7511_rd(sd, 0x96);969 irq_status = adv7511_rd(sd, 0x96);
970 cec_irq = adv7511_rd(sd, 0x97);
708 /* clear detected interrupts */971 /* clear detected interrupts */
709 adv7511_wr(sd, 0x96, irq_status);972 adv7511_wr(sd, 0x96, irq_status);
973 adv7511_wr(sd, 0x97, cec_irq);
710 974
711 v4l2_dbg(1, debug, sd, "%s: irq 0x%x\n", __func__, irq_status);975 v4l2_dbg(1, debug, sd, "%s: irq 0x%x, cec-irq 0x%x\n", __func__,
976 irq_status, cec_irq);
712 977
713 if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT))978 if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT))
714 adv7511_check_monitor_present_status(sd);979 adv7511_check_monitor_present_status(sd);
715 if (irq_status & MASK_ADV7511_EDID_RDY_INT)980 if (irq_status & MASK_ADV7511_EDID_RDY_INT)
716 adv7511_check_edid_status(sd);981 adv7511_check_edid_status(sd);
717 982
983#if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
984 if (cec_irq & 0x38)
985 adv_cec_tx_raw_status(sd, cec_irq);
986
987 if (cec_irq & 1) {
988 struct adv7511_state *state = get_adv7511_state(sd);
989 struct cec_msg msg;
990
991 msg.len = adv7511_cec_read(sd, 0x25) & 0x1f;
992
993 v4l2_dbg(1, debug, sd, "%s: cec msg len %d\n", __func__,
994 msg.len);
995
996 if (msg.len > 16)
997 msg.len = 16;
998
999 if (msg.len) {
1000 u8 i;
1001
1002 for (i = 0; i < msg.len; i++)
1003 msg.msg[i] = adv7511_cec_read(sd, i + 0x15);
1004
1005 adv7511_cec_write(sd, 0x4a, 1); /* toggle to re-enable rx 1 */
1006 adv7511_cec_write(sd, 0x4a, 0);
1007 cec_received_msg(state->cec_adap, &msg);
1008 }
1009 }
1010#endif
1011
718 /* enable interrupts */1012 /* enable interrupts */
719 adv7511_set_isr(sd, true);1013 adv7511_set_isr(sd, true);
720 1014
@@ -1183,6 +1477,8 @@ static void adv7511_notify_no_edid(struct v4l2_subdev *sd) · 462 unmodified lines
1183 /* We failed to read the EDID, so send an event for this. */1477 /* We failed to read the EDID, so send an event for this. */
1184 ed.present = false;1478 ed.present = false;
1185 ed.segment = adv7511_rd(sd, 0xc4);1479 ed.segment = adv7511_rd(sd, 0xc4);
1480 ed.phys_addr = CEC_PHYS_ADDR_INVALID;
1481 cec_s_phys_addr(state->cec_adap, ed.phys_addr, false);
1186 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);1482 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
1187 v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0);1483 v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0);
1188}1484}
@@ -1406,13 +1702,16 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) · 217 unmodified lines
1406 1702
1407 v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments);1703 v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments);
1408 state->edid.complete = true;1704 state->edid.complete = true;
1409 1705 ed.phys_addr = cec_get_edid_phys_addr(state->edid.data,
1706 state->edid.segments * 256,
1707 NULL);
1410 /* report when we have all segments1708 /* report when we have all segments
1411 but report only for segment 01709 but report only for segment 0
1412 */1710 */
1413 ed.present = true;1711 ed.present = true;
1414 ed.segment = 0;1712 ed.segment = 0;
1415 state->edid_detect_counter++;1713 state->edid_detect_counter++;
1714 cec_s_phys_addr(state->cec_adap, ed.phys_addr, false);
1416 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);1715 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
1417 return ed.present;1716 return ed.present;
1418 }1717 }
@@ -1420,17 +1719,43 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) · 1 unmodified line
1420 return false;1719 return false;
1421}1720}
1422 1721
1722static int adv7511_registered(struct v4l2_subdev *sd)
1723{
1724 struct adv7511_state *state = get_adv7511_state(sd);
1725 int err;
1726
1727 err = cec_register_adapter(state->cec_adap);
1728 if (err)
1729 cec_delete_adapter(state->cec_adap);
1730 return err;
1731}
1732
1733static void adv7511_unregistered(struct v4l2_subdev *sd)
1734{
1735 struct adv7511_state *state = get_adv7511_state(sd);
1736
1737 cec_unregister_adapter(state->cec_adap);
1738}
1739
1740static const struct v4l2_subdev_internal_ops adv7511_int_ops = {
1741 .registered = adv7511_registered,
1742 .unregistered = adv7511_unregistered,
1743};
1744
1423/* ----------------------------------------------------------------------- */1745/* ----------------------------------------------------------------------- */
1424/* Setup ADV7511 */1746/* Setup ADV7511 */
1425static void adv7511_init_setup(struct v4l2_subdev *sd)1747static void adv7511_init_setup(struct v4l2_subdev *sd)
1426{1748{
1427 struct adv7511_state *state = get_adv7511_state(sd);1749 struct adv7511_state *state = get_adv7511_state(sd);
1428 struct adv7511_state_edid *edid = &state->edid;1750 struct adv7511_state_edid *edid = &state->edid;
1751 u32 cec_clk = state->pdata.cec_clk;
1752 u8 ratio;
1429 1753
1430 v4l2_dbg(1, debug, sd, "%s\n", __func__);1754 v4l2_dbg(1, debug, sd, "%s\n", __func__);
1431 1755
1432 /* clear all interrupts */1756 /* clear all interrupts */
1433 adv7511_wr(sd, 0x96, 0xff);1757 adv7511_wr(sd, 0x96, 0xff);
1758 adv7511_wr(sd, 0x97, 0xff);
1434 /*1759 /*
1435 * Stop HPD from resetting a lot of registers.1760 * Stop HPD from resetting a lot of registers.
1436 * It might leave the chip in a partly un-initialized state,1761 * It might leave the chip in a partly un-initialized state,
@@ -1442,6 +1767,25 @@ static void adv7511_init_setup(struct v4l2_subdev *sd) · 5 unmodified lines
1442 adv7511_set_isr(sd, false);1767 adv7511_set_isr(sd, false);
1443 adv7511_s_stream(sd, false);1768 adv7511_s_stream(sd, false);
1444 adv7511_s_audio_stream(sd, false);1769 adv7511_s_audio_stream(sd, false);
1770
1771 if (state->i2c_cec == NULL)
1772 return;
1773
1774 v4l2_dbg(1, debug, sd, "%s: cec_clk %d\n", __func__, cec_clk);
1775
1776 /* cec soft reset */
1777 adv7511_cec_write(sd, 0x50, 0x01);
1778 adv7511_cec_write(sd, 0x50, 0x00);
1779
1780 /* legacy mode */
1781 adv7511_cec_write(sd, 0x4a, 0x00);
1782
1783 if (cec_clk % 750000 != 0)
1784 v4l2_err(sd, "%s: cec_clk %d, not multiple of 750 Khz\n",
1785 __func__, cec_clk);
1786
1787 ratio = (cec_clk / 750000) - 1;
1788 adv7511_cec_write(sd, 0x4e, ratio << 2);
1445}1789}
1446 1790
1447static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id)1791static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -1476,6 +1820,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * · 28 unmodified lines
1476 client->addr << 1);1820 client->addr << 1);
1477 1821
1478 v4l2_i2c_subdev_init(sd, client, &adv7511_ops);1822 v4l2_i2c_subdev_init(sd, client, &adv7511_ops);
1823 sd->internal_ops = &adv7511_int_ops;
1479 1824
1480 hdl = &state->hdl;1825 hdl = &state->hdl;
1481 v4l2_ctrl_handler_init(hdl, 10);1826 v4l2_ctrl_handler_init(hdl, 10);
@@ -1516,26 +1861,47 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * · 34 unmodified lines
1516 chip_id[0] = adv7511_rd(sd, 0xf5);1861 chip_id[0] = adv7511_rd(sd, 0xf5);
1517 chip_id[1] = adv7511_rd(sd, 0xf6);1862 chip_id[1] = adv7511_rd(sd, 0xf6);
1518 if (chip_id[0] != 0x75 || chip_id[1] != 0x11) {1863 if (chip_id[0] != 0x75 || chip_id[1] != 0x11) {
1519 v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0], chip_id[1]);1864 v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0],
1865 chip_id[1]);
1520 err = -EIO;1866 err = -EIO;
1521 goto err_entity;1867 goto err_entity;
1522 }1868 }
1523 1869
1524 state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1);1870 state->i2c_edid = i2c_new_dummy(client->adapter,
1871 state->i2c_edid_addr >> 1);
1525 if (state->i2c_edid == NULL) {1872 if (state->i2c_edid == NULL) {
1526 v4l2_err(sd, "failed to register edid i2c client\n");1873 v4l2_err(sd, "failed to register edid i2c client\n");
1527 err = -ENOMEM;1874 err = -ENOMEM;
1528 goto err_entity;1875 goto err_entity;
1529 }1876 }
1530 1877
1878 adv7511_wr(sd, 0xe1, state->i2c_cec_addr);
1879 if (state->pdata.cec_clk < 3000000 ||
1880 state->pdata.cec_clk > 100000000) {
1881 v4l2_err(sd, "%s: cec_clk %u outside range, disabling cec\n",
1882 __func__, state->pdata.cec_clk);
1883 state->pdata.cec_clk = 0;
1884 }
1885
1886 if (state->pdata.cec_clk) {
1887 state->i2c_cec = i2c_new_dummy(client->adapter,
1888 state->i2c_cec_addr >> 1);
1889 if (state->i2c_cec == NULL) {
1890 v4l2_err(sd, "failed to register cec i2c client\n");
1891 goto err_unreg_edid;
1892 }
1893 adv7511_wr(sd, 0xe2, 0x00); /* power up cec section */
1894 } else {
1895 adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */
1896 }
1897
1531 state->i2c_pktmem = i2c_new_dummy(client->adapter, state->i2c_pktmem_addr >> 1);1898 state->i2c_pktmem = i2c_new_dummy(client->adapter, state->i2c_pktmem_addr >> 1);
1532 if (state->i2c_pktmem == NULL) {1899 if (state->i2c_pktmem == NULL) {
1533 v4l2_err(sd, "failed to register pktmem i2c client\n");1900 v4l2_err(sd, "failed to register pktmem i2c client\n");
1534 err = -ENOMEM;1901 err = -ENOMEM;
1535 goto err_unreg_edid;1902 goto err_unreg_cec;
1536 }1903 }
1537 1904
1538 adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */
1539 state->work_queue = create_singlethread_workqueue(sd->name);1905 state->work_queue = create_singlethread_workqueue(sd->name);
1540 if (state->work_queue == NULL) {1906 if (state->work_queue == NULL) {
1541 v4l2_err(sd, "could not create workqueue\n");1907 v4l2_err(sd, "could not create workqueue\n");
@@ -1546,6 +1912,19 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * · 4 unmodified lines
1546 INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);1912 INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);
1547 1913
1548 adv7511_init_setup(sd);1914 adv7511_init_setup(sd);
1915
1916#if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
1917 state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
1918 state, dev_name(&client->dev), CEC_CAP_TRANSMIT |
1919 CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | CEC_CAP_RC,
1920 ADV7511_MAX_ADDRS, &client->dev);
1921 err = PTR_ERR_OR_ZERO(state->cec_adap);
1922 if (err) {
1923 destroy_workqueue(state->work_queue);
1924 goto err_unreg_pktmem;
1925 }
1926#endif
1927
1549 adv7511_set_isr(sd, true);1928 adv7511_set_isr(sd, true);
1550 adv7511_check_monitor_present_status(sd);1929 adv7511_check_monitor_present_status(sd);
1551 1930
@@ -1555,6 +1934,9 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * · 3 unmodified lines
1555 1934
1556err_unreg_pktmem:1935err_unreg_pktmem:
1557 i2c_unregister_device(state->i2c_pktmem);1936 i2c_unregister_device(state->i2c_pktmem);
1937err_unreg_cec:
1938 if (state->i2c_cec)
1939 i2c_unregister_device(state->i2c_cec);
1558err_unreg_edid:1940err_unreg_edid:
1559 i2c_unregister_device(state->i2c_edid);1941 i2c_unregister_device(state->i2c_edid);
1560err_entity:1942err_entity:
@@ -1576,9 +1958,12 @@ static int adv7511_remove(struct i2c_client *client) · 15 unmodified lines
1576 v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,1958 v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
1577 client->addr << 1, client->adapter->name);1959 client->addr << 1, client->adapter->name);
1578 1960
1961 adv7511_set_isr(sd, false);
1579 adv7511_init_setup(sd);1962 adv7511_init_setup(sd);
1580 cancel_delayed_work(&state->edid_handler);1963 cancel_delayed_work(&state->edid_handler);
1581 i2c_unregister_device(state->i2c_edid);1964 i2c_unregister_device(state->i2c_edid);
1965 if (state->i2c_cec)
1966 i2c_unregister_device(state->i2c_cec);
1582 i2c_unregister_device(state->i2c_pktmem);1967 i2c_unregister_device(state->i2c_pktmem);
1583 destroy_workqueue(state->work_queue);1968 destroy_workqueue(state->work_queue);
1584 v4l2_device_unregister_subdev(sd);1969 v4l2_device_unregister_subdev(sd);
drivers/media/i2c/adv7604.c+296−36
@@ -40,6 +40,7 @@ · 39 unmodified lines
40#include <linux/regmap.h>40#include <linux/regmap.h>
41 41
42#include <media/i2c/adv7604.h>42#include <media/i2c/adv7604.h>
43#include <media/cec.h>
43#include <media/v4l2-ctrls.h>44#include <media/v4l2-ctrls.h>
44#include <media/v4l2-device.h>45#include <media/v4l2-device.h>
45#include <media/v4l2-event.h>46#include <media/v4l2-event.h>
@@ -80,6 +81,8 @@ MODULE_LICENSE("GPL"); · 34 unmodified lines
80 81
81#define ADV76XX_OP_SWAP_CB_CR (1 << 0)82#define ADV76XX_OP_SWAP_CB_CR (1 << 0)
82 83
84#define ADV76XX_MAX_ADDRS (3)
85
83enum adv76xx_type {86enum adv76xx_type {
84 ADV7604,87 ADV7604,
85 ADV7611,88 ADV7611,
@@ -184,6 +187,12 @@ struct adv76xx_state { · 98 unmodified lines
184 u16 spa_port_a[2];187 u16 spa_port_a[2];
185 struct v4l2_fract aspect_ratio;188 struct v4l2_fract aspect_ratio;
186 u32 rgb_quantization_range;189 u32 rgb_quantization_range;
190
191 struct cec_adapter *cec_adap;
192 u8 cec_addr[ADV76XX_MAX_ADDRS];
193 u8 cec_valid_addrs;
194 bool cec_enabled_adap;
195
187 struct workqueue_struct *work_queues;196 struct workqueue_struct *work_queues;
188 struct delayed_work delayed_work_enable_hotplug;197 struct delayed_work delayed_work_enable_hotplug;
189 bool restart_stdi_once;198 bool restart_stdi_once;
@@ -381,7 +390,8 @@ static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val) · 191 unmodified lines
381 return regmap_write(state->regmap[ADV76XX_PAGE_IO], reg, val);390 return regmap_write(state->regmap[ADV76XX_PAGE_IO], reg, val);
382}391}
383 392
384static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)393static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
394 u8 val)
385{395{
386 return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);396 return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
387}397}
@@ -414,6 +424,12 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) · 26 unmodified lines
414 return regmap_write(state->regmap[ADV76XX_PAGE_CEC], reg, val);424 return regmap_write(state->regmap[ADV76XX_PAGE_CEC], reg, val);
415}425}
416 426
427static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
428 u8 val)
429{
430 return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
431}
432
417static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)433static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
418{434{
419 struct adv76xx_state *state = to_state(sd);435 struct adv76xx_state *state = to_state(sd);
@@ -892,9 +908,9 @@ static int adv76xx_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) · 472 unmodified lines
892{908{
893 struct adv76xx_state *state = to_state(sd);909 struct adv76xx_state *state = to_state(sd);
894 const struct adv76xx_chip_info *info = state->info;910 const struct adv76xx_chip_info *info = state->info;
911 u16 cable_det = info->read_cable_det(sd);
895 912
896 return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,913 return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det);
897 info->read_cable_det(sd));
898}914}
899 915
900static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,916static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
@@ -1924,6 +1940,210 @@ static int adv76xx_set_format(struct v4l2_subdev *sd, · 1023 unmodified lines
1924 return 0;1940 return 0;
1925}1941}
1926 1942
1943#if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
1944static void adv76xx_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
1945{
1946 struct adv76xx_state *state = to_state(sd);
1947
1948 if ((cec_read(sd, 0x11) & 0x01) == 0) {
1949 v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__);
1950 return;
1951 }
1952
1953 if (tx_raw_status & 0x02) {
1954 v4l2_dbg(1, debug, sd, "%s: tx raw: arbitration lost\n",
1955 __func__);
1956 cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST,
1957 1, 0, 0, 0);
1958 }
1959 if (tx_raw_status & 0x04) {
1960 u8 status;
1961 u8 nack_cnt;
1962 u8 low_drive_cnt;
1963
1964 v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__);
1965 /*
1966 * We set this status bit since this hardware performs
1967 * retransmissions.
1968 */
1969 status = CEC_TX_STATUS_MAX_RETRIES;
1970 nack_cnt = cec_read(sd, 0x14) & 0xf;
1971 if (nack_cnt)
1972 status |= CEC_TX_STATUS_NACK;
1973 low_drive_cnt = cec_read(sd, 0x14) >> 4;
1974 if (low_drive_cnt)
1975 status |= CEC_TX_STATUS_LOW_DRIVE;
1976 cec_transmit_done(state->cec_adap, status,
1977 0, nack_cnt, low_drive_cnt, 0);
1978 return;
1979 }
1980 if (tx_raw_status & 0x01) {
1981 v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__);
1982 cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
1983 return;
1984 }
1985}
1986
1987static void adv76xx_cec_isr(struct v4l2_subdev *sd, bool *handled)
1988{
1989 struct adv76xx_state *state = to_state(sd);
1990 u8 cec_irq;
1991
1992 /* cec controller */
1993 cec_irq = io_read(sd, 0x4d) & 0x0f;
1994 if (!cec_irq)
1995 return;
1996
1997 v4l2_dbg(1, debug, sd, "%s: cec: irq 0x%x\n", __func__, cec_irq);
1998 adv76xx_cec_tx_raw_status(sd, cec_irq);
1999 if (cec_irq & 0x08) {
2000 struct cec_msg msg;
2001
2002 msg.len = cec_read(sd, 0x25) & 0x1f;
2003 if (msg.len > 16)
2004 msg.len = 16;
2005
2006 if (msg.len) {
2007 u8 i;
2008
2009 for (i = 0; i < msg.len; i++)
2010 msg.msg[i] = cec_read(sd, i + 0x15);
2011 cec_write(sd, 0x26, 0x01); /* re-enable rx */
2012 cec_received_msg(state->cec_adap, &msg);
2013 }
2014 }
2015
2016 /* note: the bit order is swapped between 0x4d and 0x4e */
2017 cec_irq = ((cec_irq & 0x08) >> 3) | ((cec_irq & 0x04) >> 1) |
2018 ((cec_irq & 0x02) << 1) | ((cec_irq & 0x01) << 3);
2019 io_write(sd, 0x4e, cec_irq);
2020
2021 if (handled)
2022 *handled = true;
2023}
2024
2025static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable)
2026{
2027 struct adv76xx_state *state = adap->priv;
2028 struct v4l2_subdev *sd = &state->sd;
2029
2030 if (!state->cec_enabled_adap && enable) {
2031 cec_write_clr_set(sd, 0x2a, 0x01, 0x01); /* power up cec */
2032 cec_write(sd, 0x2c, 0x01); /* cec soft reset */
2033 cec_write_clr_set(sd, 0x11, 0x01, 0); /* initially disable tx */
2034 /* enabled irqs: */
2035 /* tx: ready */
2036 /* tx: arbitration lost */
2037 /* tx: retry timeout */
2038 /* rx: ready */
2039 io_write_clr_set(sd, 0x50, 0x0f, 0x0f);
2040 cec_write(sd, 0x26, 0x01); /* enable rx */
2041 } else if (state->cec_enabled_adap && !enable) {
2042 /* disable cec interrupts */
2043 io_write_clr_set(sd, 0x50, 0x0f, 0x00);
2044 /* disable address mask 1-3 */
2045 cec_write_clr_set(sd, 0x27, 0x70, 0x00);
2046 /* power down cec section */
2047 cec_write_clr_set(sd, 0x2a, 0x01, 0x00);
2048 state->cec_valid_addrs = 0;
2049 }
2050 state->cec_enabled_adap = enable;
2051 adv76xx_s_detect_tx_5v_ctrl(sd);
2052 return 0;
2053}
2054
2055static int adv76xx_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
2056{
2057 struct adv76xx_state *state = adap->priv;
2058 struct v4l2_subdev *sd = &state->sd;
2059 unsigned int i, free_idx = ADV76XX_MAX_ADDRS;
2060
2061 if (!state->cec_enabled_adap)
2062 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
2063
2064 if (addr == CEC_LOG_ADDR_INVALID) {
2065 cec_write_clr_set(sd, 0x27, 0x70, 0);
2066 state->cec_valid_addrs = 0;
2067 return 0;
2068 }
2069
2070 for (i = 0; i < ADV76XX_MAX_ADDRS; i++) {
2071 bool is_valid = state->cec_valid_addrs & (1 << i);
2072
2073 if (free_idx == ADV76XX_MAX_ADDRS && !is_valid)
2074 free_idx = i;
2075 if (is_valid && state->cec_addr[i] == addr)
2076 return 0;
2077 }
2078 if (i == ADV76XX_MAX_ADDRS) {
2079 i = free_idx;
2080 if (i == ADV76XX_MAX_ADDRS)
2081 return -ENXIO;
2082 }
2083 state->cec_addr[i] = addr;
2084 state->cec_valid_addrs |= 1 << i;
2085
2086 switch (i) {
2087 case 0:
2088 /* enable address mask 0 */
2089 cec_write_clr_set(sd, 0x27, 0x10, 0x10);
2090 /* set address for mask 0 */
2091 cec_write_clr_set(sd, 0x28, 0x0f, addr);
2092 break;
2093 case 1:
2094 /* enable address mask 1 */
2095 cec_write_clr_set(sd, 0x27, 0x20, 0x20);
2096 /* set address for mask 1 */
2097 cec_write_clr_set(sd, 0x28, 0xf0, addr << 4);
2098 break;
2099 case 2:
2100 /* enable address mask 2 */
2101 cec_write_clr_set(sd, 0x27, 0x40, 0x40);
2102 /* set address for mask 1 */
2103 cec_write_clr_set(sd, 0x29, 0x0f, addr);
2104 break;
2105 }
2106 return 0;
2107}
2108
2109static int adv76xx_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
2110 u32 signal_free_time, struct cec_msg *msg)
2111{
2112 struct adv76xx_state *state = adap->priv;
2113 struct v4l2_subdev *sd = &state->sd;
2114 u8 len = msg->len;
2115 unsigned int i;
2116
2117 /*
2118 * The number of retries is the number of attempts - 1, but retry
2119 * at least once. It's not clear if a value of 0 is allowed, so
2120 * let's do at least one retry.
2121 */
2122 cec_write_clr_set(sd, 0x12, 0x70, max(1, attempts - 1) << 4);
2123
2124 if (len > 16) {
2125 v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len);
2126 return -EINVAL;
2127 }
2128
2129 /* write data */
2130 for (i = 0; i < len; i++)
2131 cec_write(sd, i, msg->msg[i]);
2132
2133 /* set length (data + header) */
2134 cec_write(sd, 0x10, len);
2135 /* start transmit, enable tx */
2136 cec_write(sd, 0x11, 0x01);
2137 return 0;
2138}
2139
2140static const struct cec_adap_ops adv76xx_cec_adap_ops = {
2141 .adap_enable = adv76xx_cec_adap_enable,
2142 .adap_log_addr = adv76xx_cec_adap_log_addr,
2143 .adap_transmit = adv76xx_cec_adap_transmit,
2144};
2145#endif
2146
1927static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)2147static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
1928{2148{
1929 struct adv76xx_state *state = to_state(sd);2149 struct adv76xx_state *state = to_state(sd);
@@ -1969,6 +2189,11 @@ static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled) · 39 unmodified lines
1969 *handled = true;2189 *handled = true;
1970 }2190 }
1971 2191
2192#if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
2193 /* cec */
2194 adv76xx_cec_isr(sd, handled);
2195#endif
2196
1972 /* tx 5v detect */2197 /* tx 5v detect */
1973 tx_5v = irq_reg_0x70 & info->cable_det_mask;2198 tx_5v = irq_reg_0x70 & info->cable_det_mask;
1974 if (tx_5v) {2199 if (tx_5v) {
@@ -2018,39 +2243,12 @@ static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 43 unmodified lines
2018 return 0;2243 return 0;
2019}2244}
2020 2245
2021static int get_edid_spa_location(const u8 *edid)
2022{
2023 u8 d;
2024
2025 if ((edid[0x7e] != 1) ||
2026 (edid[0x80] != 0x02) ||
2027 (edid[0x81] != 0x03)) {
2028 return -1;
2029 }
2030
2031 /* search Vendor Specific Data Block (tag 3) */
2032 d = edid[0x82] & 0x7f;
2033 if (d > 4) {
2034 int i = 0x84;
2035 int end = 0x80 + d;
2036
2037 do {
2038 u8 tag = edid[i] >> 5;
2039 u8 len = edid[i] & 0x1f;
2040
2041 if ((tag == 3) && (len >= 5))
2042 return i + 4;
2043 i += len + 1;
2044 } while (i < end);
2045 }
2046 return -1;
2047}
2048
2049static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)2246static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
2050{2247{
2051 struct adv76xx_state *state = to_state(sd);2248 struct adv76xx_state *state = to_state(sd);
2052 const struct adv76xx_chip_info *info = state->info;2249 const struct adv76xx_chip_info *info = state->info;
2053 int spa_loc;2250 unsigned int spa_loc;
2251 u16 pa;
2054 int err;2252 int err;
2055 int i;2253 int i;
2056 2254
@@ -2081,6 +2279,10 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 24 unmodified lines
2081 edid->blocks = 2;2279 edid->blocks = 2;
2082 return -E2BIG;2280 return -E2BIG;
2083 }2281 }
2282 pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc);
2283 err = cec_phys_addr_validate(pa, &pa, NULL);
2284 if (err)
2285 return err;
2084 2286
2085 v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",2287 v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
2086 __func__, edid->pad, state->edid.present);2288 __func__, edid->pad, state->edid.present);
@@ -2090,9 +2292,12 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 3 unmodified lines
2090 adv76xx_set_hpd(state, 0);2292 adv76xx_set_hpd(state, 0);
2091 rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);2293 rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
2092 2294
2093 spa_loc = get_edid_spa_location(edid->edid);2295 /*
2094 if (spa_loc < 0)2296 * Return an error if no location of the source physical address
2095 spa_loc = 0xc0; /* Default value [REF_02, p. 116] */2297 * was found.
2298 */
2299 if (spa_loc == 0)
2300 return -EINVAL;
2096 2301
2097 switch (edid->pad) {2302 switch (edid->pad) {
2098 case ADV76XX_PAD_HDMI_PORT_A:2303 case ADV76XX_PAD_HDMI_PORT_A:
@@ -2152,6 +2357,7 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 53 unmodified lines
2152 v4l2_err(sd, "error enabling edid (0x%x)\n", state->edid.present);2357 v4l2_err(sd, "error enabling edid (0x%x)\n", state->edid.present);
2153 return -EIO;2358 return -EIO;
2154 }2359 }
2360 cec_s_phys_addr(state->cec_adap, pa, false);
2155 2361
2156 /* enable hotplug after 100 ms */2362 /* enable hotplug after 100 ms */
2157 queue_delayed_work(state->work_queues,2363 queue_delayed_work(state->work_queues,
@@ -2276,8 +2482,19 @@ static int adv76xx_log_status(struct v4l2_subdev *sd) · 118 unmodified lines
2276 ((edid_enabled & 0x02) ? "Yes" : "No"),2482 ((edid_enabled & 0x02) ? "Yes" : "No"),
2277 ((edid_enabled & 0x04) ? "Yes" : "No"),2483 ((edid_enabled & 0x04) ? "Yes" : "No"),
2278 ((edid_enabled & 0x08) ? "Yes" : "No"));2484 ((edid_enabled & 0x08) ? "Yes" : "No"));
2279 v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?2485 v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ?
2280 "enabled" : "disabled");2486 "enabled" : "disabled");
2487 if (state->cec_enabled_adap) {
2488 int i;
2489
2490 for (i = 0; i < ADV76XX_MAX_ADDRS; i++) {
2491 bool is_valid = state->cec_valid_addrs & (1 << i);
2492
2493 if (is_valid)
2494 v4l2_info(sd, "CEC Logical Address: 0x%x\n",
2495 state->cec_addr[i]);
2496 }
2497 }
2281 2498
2282 v4l2_info(sd, "-----Signal status-----\n");2499 v4l2_info(sd, "-----Signal status-----\n");
2283 cable_det = info->read_cable_det(sd);2500 cable_det = info->read_cable_det(sd);
@@ -2387,6 +2604,24 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd, · 103 unmodified lines
2387 }2604 }
2388}2605}
2389 2606
2607static int adv76xx_registered(struct v4l2_subdev *sd)
2608{
2609 struct adv76xx_state *state = to_state(sd);
2610 int err;
2611
2612 err = cec_register_adapter(state->cec_adap);
2613 if (err)
2614 cec_delete_adapter(state->cec_adap);
2615 return err;
2616}
2617
2618static void adv76xx_unregistered(struct v4l2_subdev *sd)
2619{
2620 struct adv76xx_state *state = to_state(sd);
2621
2622 cec_unregister_adapter(state->cec_adap);
2623}
2624
2390/* ----------------------------------------------------------------------- */2625/* ----------------------------------------------------------------------- */
2391 2626
2392static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = {2627static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = {
@@ -2430,6 +2665,11 @@ static const struct v4l2_subdev_ops adv76xx_ops = { · 37 unmodified lines
2430 .pad = &adv76xx_pad_ops,2665 .pad = &adv76xx_pad_ops,
2431};2666};
2432 2667
2668static const struct v4l2_subdev_internal_ops adv76xx_int_ops = {
2669 .registered = adv76xx_registered,
2670 .unregistered = adv76xx_unregistered,
2671};
2672
2433/* -------------------------- custom ctrls ---------------------------------- */2673/* -------------------------- custom ctrls ---------------------------------- */
2434 2674
2435static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {2675static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {
@@ -3093,6 +3333,7 @@ static int adv76xx_probe(struct i2c_client *client, · 657 unmodified lines
3093 id->name, i2c_adapter_id(client->adapter),3333 id->name, i2c_adapter_id(client->adapter),
3094 client->addr);3334 client->addr);
3095 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;3335 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
3336 sd->internal_ops = &adv76xx_int_ops;
3096 3337
3097 /* Configure IO Regmap region */3338 /* Configure IO Regmap region */
3098 err = configure_regmap(state, ADV76XX_PAGE_IO);3339 err = configure_regmap(state, ADV76XX_PAGE_IO);
@@ -3236,6 +3477,18 @@ static int adv76xx_probe(struct i2c_client *client, · 137 unmodified lines
3236 err = adv76xx_core_init(sd);3477 err = adv76xx_core_init(sd);
3237 if (err)3478 if (err)
3238 goto err_entity;3479 goto err_entity;
3480
3481#if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
3482 state->cec_adap = cec_allocate_adapter(&adv76xx_cec_adap_ops,
3483 state, dev_name(&client->dev),
3484 CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
3485 CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV76XX_MAX_ADDRS,
3486 &client->dev);
3487 err = PTR_ERR_OR_ZERO(state->cec_adap);
3488 if (err)
3489 goto err_entity;
3490#endif
3491
3239 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,3492 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
3240 client->addr << 1, client->adapter->name);3493 client->addr << 1, client->adapter->name);
3241 3494
@@ -3264,6 +3517,13 @@ static int adv76xx_remove(struct i2c_client *client) · 22 unmodified lines
3264 struct v4l2_subdev *sd = i2c_get_clientdata(client);3517 struct v4l2_subdev *sd = i2c_get_clientdata(client);
3265 struct adv76xx_state *state = to_state(sd);3518 struct adv76xx_state *state = to_state(sd);
3266 3519
3520 /* disable interrupts */
3521 io_write(sd, 0x40, 0);
3522 io_write(sd, 0x41, 0);
3523 io_write(sd, 0x46, 0);
3524 io_write(sd, 0x6e, 0);
3525 io_write(sd, 0x73, 0);
3526
3267 cancel_delayed_work(&state->delayed_work_enable_hotplug);3527 cancel_delayed_work(&state->delayed_work_enable_hotplug);
3268 destroy_workqueue(state->work_queues);3528 destroy_workqueue(state->work_queues);
3269 v4l2_async_unregister_subdev(sd);3529 v4l2_async_unregister_subdev(sd);
drivers/media/i2c/adv7842.c+305−63
@@ -39,6 +39,7 @@ · 38 unmodified lines
39#include <linux/workqueue.h>39#include <linux/workqueue.h>
40#include <linux/v4l2-dv-timings.h>40#include <linux/v4l2-dv-timings.h>
41#include <linux/hdmi.h>41#include <linux/hdmi.h>
42#include <media/cec.h>
42#include <media/v4l2-device.h>43#include <media/v4l2-device.h>
43#include <media/v4l2-event.h>44#include <media/v4l2-event.h>
44#include <media/v4l2-ctrls.h>45#include <media/v4l2-ctrls.h>
@@ -79,6 +80,8 @@ MODULE_LICENSE("GPL"); · 34 unmodified lines
79 80
80#define ADV7842_OP_SWAP_CB_CR (1 << 0)81#define ADV7842_OP_SWAP_CB_CR (1 << 0)
81 82
83#define ADV7842_MAX_ADDRS (3)
84
82/*85/*
83**********************************************************************86**********************************************************************
84*87*
@@ -142,6 +145,11 @@ struct adv7842_state { · 57 unmodified lines
142 struct v4l2_ctrl *free_run_color_ctrl_manual;145 struct v4l2_ctrl *free_run_color_ctrl_manual;
143 struct v4l2_ctrl *free_run_color_ctrl;146 struct v4l2_ctrl *free_run_color_ctrl;
144 struct v4l2_ctrl *rgb_quantization_range_ctrl;147 struct v4l2_ctrl *rgb_quantization_range_ctrl;
148
149 struct cec_adapter *cec_adap;
150 u8 cec_addr[ADV7842_MAX_ADDRS];
151 u8 cec_valid_addrs;
152 bool cec_enabled_adap;
145};153};
146 154
147/* Unsupported timings. This device cannot support 720p30. */155/* Unsupported timings. This device cannot support 720p30. */
@@ -418,9 +426,9 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) · 270 unmodified lines
418 return adv_smbus_write_byte_data(state->i2c_cec, reg, val);426 return adv_smbus_write_byte_data(state->i2c_cec, reg, val);
419}427}
420 428
421static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)429static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
422{430{
423 return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);431 return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
424}432}
425 433
426static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)434static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
@@ -696,6 +704,18 @@ adv7842_get_dv_timings_cap(struct v4l2_subdev *sd) · 269 unmodified lines
696 704
697/* ----------------------------------------------------------------------- */705/* ----------------------------------------------------------------------- */
698 706
707static u16 adv7842_read_cable_det(struct v4l2_subdev *sd)
708{
709 u8 reg = io_read(sd, 0x6f);
710 u16 val = 0;
711
712 if (reg & 0x02)
713 val |= 1; /* port A */
714 if (reg & 0x01)
715 val |= 2; /* port B */
716 return val;
717}
718
699static void adv7842_delayed_work_enable_hotplug(struct work_struct *work)719static void adv7842_delayed_work_enable_hotplug(struct work_struct *work)
700{720{
701 struct delayed_work *dwork = to_delayed_work(work);721 struct delayed_work *dwork = to_delayed_work(work);
@@ -762,50 +782,18 @@ static int edid_write_vga_segment(struct v4l2_subdev *sd) · 60 unmodified lines
762 return 0;782 return 0;
763}783}
764 784
765static int edid_spa_location(const u8 *edid)
766{
767 u8 d;
768
769 /*
770 * TODO, improve and update for other CEA extensions
771 * currently only for 1 segment (256 bytes),
772 * i.e. 1 extension block and CEA revision 3.
773 */
774 if ((edid[0x7e] != 1) ||
775 (edid[0x80] != 0x02) ||
776 (edid[0x81] != 0x03)) {
777 return -EINVAL;
778 }
779 /*
780 * search Vendor Specific Data Block (tag 3)
781 */
782 d = edid[0x82] & 0x7f;
783 if (d > 4) {
784 int i = 0x84;
785 int end = 0x80 + d;
786 do {
787 u8 tag = edid[i]>>5;
788 u8 len = edid[i] & 0x1f;
789
790 if ((tag == 3) && (len >= 5))
791 return i + 4;
792 i += len + 1;
793 } while (i < end);
794 }
795 return -EINVAL;
796}
797
798static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port)785static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port)
799{786{
800 struct i2c_client *client = v4l2_get_subdevdata(sd);787 struct i2c_client *client = v4l2_get_subdevdata(sd);
801 struct adv7842_state *state = to_state(sd);788 struct adv7842_state *state = to_state(sd);
802 const u8 *val = state->hdmi_edid.edid;789 const u8 *edid = state->hdmi_edid.edid;
803 int spa_loc = edid_spa_location(val);790 int spa_loc;
791 u16 pa;
804 int err = 0;792 int err = 0;
805 int i;793 int i;
806 794
807 v4l2_dbg(2, debug, sd, "%s: write EDID on port %c (spa at 0x%x)\n",795 v4l2_dbg(2, debug, sd, "%s: write EDID on port %c\n",
808 __func__, (port == ADV7842_EDID_PORT_A) ? 'A' : 'B', spa_loc);796 __func__, (port == ADV7842_EDID_PORT_A) ? 'A' : 'B');
809 797
810 /* HPA disable on port A and B */798 /* HPA disable on port A and B */
811 io_write_and_or(sd, 0x20, 0xcf, 0x00);799 io_write_and_or(sd, 0x20, 0xcf, 0x00);
@@ -816,24 +804,33 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) · 4 unmodified lines
816 if (!state->hdmi_edid.present)804 if (!state->hdmi_edid.present)
817 return 0;805 return 0;
818 806
807 pa = cec_get_edid_phys_addr(edid, 256, &spa_loc);
808 err = cec_phys_addr_validate(pa, &pa, NULL);
809 if (err)
810 return err;
811
812 /*
813 * Return an error if no location of the source physical address
814 * was found.
815 */
816 if (spa_loc == 0)
817 return -EINVAL;
818
819 /* edid segment pointer '0' for HDMI ports */819 /* edid segment pointer '0' for HDMI ports */
820 rep_write_and_or(sd, 0x77, 0xef, 0x00);820 rep_write_and_or(sd, 0x77, 0xef, 0x00);
821 821
822 for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX)822 for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX)
823 err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,823 err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
824 I2C_SMBUS_BLOCK_MAX, val + i);824 I2C_SMBUS_BLOCK_MAX, edid + i);
825 if (err)825 if (err)
826 return err;826 return err;
827 827
828 if (spa_loc < 0)
829 spa_loc = 0xc0; /* Default value [REF_02, p. 199] */
830
831 if (port == ADV7842_EDID_PORT_A) {828 if (port == ADV7842_EDID_PORT_A) {
832 rep_write(sd, 0x72, val[spa_loc]);829 rep_write(sd, 0x72, edid[spa_loc]);
833 rep_write(sd, 0x73, val[spa_loc + 1]);830 rep_write(sd, 0x73, edid[spa_loc + 1]);
834 } else {831 } else {
835 rep_write(sd, 0x74, val[spa_loc]);832 rep_write(sd, 0x74, edid[spa_loc]);
836 rep_write(sd, 0x75, val[spa_loc + 1]);833 rep_write(sd, 0x75, edid[spa_loc + 1]);
837 }834 }
838 rep_write(sd, 0x76, spa_loc & 0xff);835 rep_write(sd, 0x76, spa_loc & 0xff);
839 rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40);836 rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40);
@@ -853,6 +850,7 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) · 13 unmodified lines
853 (port == ADV7842_EDID_PORT_A) ? 'A' : 'B');850 (port == ADV7842_EDID_PORT_A) ? 'A' : 'B');
854 return -EIO;851 return -EIO;
855 }852 }
853 cec_s_phys_addr(state->cec_adap, pa, false);
856 854
857 /* enable hotplug after 200 ms */855 /* enable hotplug after 200 ms */
858 queue_delayed_work(state->work_queues,856 queue_delayed_work(state->work_queues,
@@ -983,20 +981,11 @@ static int adv7842_s_register(struct v4l2_subdev *sd, · 124 unmodified lines
983static int adv7842_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)981static int adv7842_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
984{982{
985 struct adv7842_state *state = to_state(sd);983 struct adv7842_state *state = to_state(sd);
986 int prev = v4l2_ctrl_g_ctrl(state->detect_tx_5v_ctrl);984 u16 cable_det = adv7842_read_cable_det(sd);
987 u8 reg_io_6f = io_read(sd, 0x6f);
988 int val = 0;
989
990 if (reg_io_6f & 0x02)
991 val |= 1; /* port A */
992 if (reg_io_6f & 0x01)
993 val |= 2; /* port B */
994 985
995 v4l2_dbg(1, debug, sd, "%s: 0x%x -> 0x%x\n", __func__, prev, val);986 v4l2_dbg(1, debug, sd, "%s: 0x%x\n", __func__, cable_det);
996 987
997 if (val != prev)988 return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det);
998 return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, val);
999 return 0;
1000}989}
1001 990
1002static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,991static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
@@ -2170,6 +2159,207 @@ static void adv7842_irq_enable(struct v4l2_subdev *sd, bool enable) · 1167 unmodified lines
2170 }2159 }
2171}2160}
2172 2161
2162#if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC)
2163static void adv7842_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status)
2164{
2165 struct adv7842_state *state = to_state(sd);
2166
2167 if ((cec_read(sd, 0x11) & 0x01) == 0) {
2168 v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__);
2169 return;
2170 }
2171
2172 if (tx_raw_status & 0x02) {
2173 v4l2_dbg(1, debug, sd, "%s: tx raw: arbitration lost\n",
2174 __func__);
2175 cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST,
2176 1, 0, 0, 0);
2177 return;
2178 }
2179 if (tx_raw_status & 0x04) {
2180 u8 status;
2181 u8 nack_cnt;
2182 u8 low_drive_cnt;
2183
2184 v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__);
2185 /*
2186 * We set this status bit since this hardware performs
2187 * retransmissions.
2188 */
2189 status = CEC_TX_STATUS_MAX_RETRIES;
2190 nack_cnt = cec_read(sd, 0x14) & 0xf;
2191 if (nack_cnt)
2192 status |= CEC_TX_STATUS_NACK;
2193 low_drive_cnt = cec_read(sd, 0x14) >> 4;
2194 if (low_drive_cnt)
2195 status |= CEC_TX_STATUS_LOW_DRIVE;
2196 cec_transmit_done(state->cec_adap, status,
2197 0, nack_cnt, low_drive_cnt, 0);
2198 return;
2199 }
2200 if (tx_raw_status & 0x01) {
2201 v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__);
2202 cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
2203 return;
2204 }
2205}
2206
2207static void adv7842_cec_isr(struct v4l2_subdev *sd, bool *handled)
2208{
2209 u8 cec_irq;
2210
2211 /* cec controller */
2212 cec_irq = io_read(sd, 0x93) & 0x0f;
2213 if (!cec_irq)
2214 return;
2215
2216 v4l2_dbg(1, debug, sd, "%s: cec: irq 0x%x\n", __func__, cec_irq);
2217 adv7842_cec_tx_raw_status(sd, cec_irq);
2218 if (cec_irq & 0x08) {
2219 struct adv7842_state *state = to_state(sd);
2220 struct cec_msg msg;
2221
2222 msg.len = cec_read(sd, 0x25) & 0x1f;
2223 if (msg.len > 16)
2224 msg.len = 16;
2225
2226 if (msg.len) {
2227 u8 i;
2228
2229 for (i = 0; i < msg.len; i++)
2230 msg.msg[i] = cec_read(sd, i + 0x15);
2231 cec_write(sd, 0x26, 0x01); /* re-enable rx */
2232 cec_received_msg(state->cec_adap, &msg);
2233 }
2234 }
2235
2236 io_write(sd, 0x94, cec_irq);
2237
2238 if (handled)
2239 *handled = true;
2240}
2241
2242static int adv7842_cec_adap_enable(struct cec_adapter *adap, bool enable)
2243{
2244 struct adv7842_state *state = adap->priv;
2245 struct v4l2_subdev *sd = &state->sd;
2246
2247 if (!state->cec_enabled_adap && enable) {
2248 cec_write_clr_set(sd, 0x2a, 0x01, 0x01); /* power up cec */
2249 cec_write(sd, 0x2c, 0x01); /* cec soft reset */
2250 cec_write_clr_set(sd, 0x11, 0x01, 0); /* initially disable tx */
2251 /* enabled irqs: */
2252 /* tx: ready */
2253 /* tx: arbitration lost */
2254 /* tx: retry timeout */
2255 /* rx: ready */
2256 io_write_clr_set(sd, 0x96, 0x0f, 0x0f);
2257 cec_write(sd, 0x26, 0x01); /* enable rx */
2258 } else if (state->cec_enabled_adap && !enable) {
2259 /* disable cec interrupts */
2260 io_write_clr_set(sd, 0x96, 0x0f, 0x00);
2261 /* disable address mask 1-3 */
2262 cec_write_clr_set(sd, 0x27, 0x70, 0x00);
2263 /* power down cec section */
2264 cec_write_clr_set(sd, 0x2a, 0x01, 0x00);
2265 state->cec_valid_addrs = 0;
2266 }
2267 state->cec_enabled_adap = enable;
2268 return 0;
2269}
2270
2271static int adv7842_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
2272{
2273 struct adv7842_state *state = adap->priv;
2274 struct v4l2_subdev *sd = &state->sd;
2275 unsigned int i, free_idx = ADV7842_MAX_ADDRS;
2276
2277 if (!state->cec_enabled_adap)
2278 return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
2279
2280 if (addr == CEC_LOG_ADDR_INVALID) {
2281 cec_write_clr_set(sd, 0x27, 0x70, 0);
2282 state->cec_valid_addrs = 0;
2283 return 0;
2284 }
2285
2286 for (i = 0; i < ADV7842_MAX_ADDRS; i++) {
2287 bool is_valid = state->cec_valid_addrs & (1 << i);
2288
2289 if (free_idx == ADV7842_MAX_ADDRS && !is_valid)
2290 free_idx = i;
2291 if (is_valid && state->cec_addr[i] == addr)
2292 return 0;
2293 }
2294 if (i == ADV7842_MAX_ADDRS) {
2295 i = free_idx;
2296 if (i == ADV7842_MAX_ADDRS)
2297 return -ENXIO;
2298 }
2299 state->cec_addr[i] = addr;
2300 state->cec_valid_addrs |= 1 << i;
2301
2302 switch (i) {
2303 case 0:
2304 /* enable address mask 0 */
2305 cec_write_clr_set(sd, 0x27, 0x10, 0x10);
2306 /* set address for mask 0 */
2307 cec_write_clr_set(sd, 0x28, 0x0f, addr);
2308 break;
2309 case 1:
2310 /* enable address mask 1 */
2311 cec_write_clr_set(sd, 0x27, 0x20, 0x20);
2312 /* set address for mask 1 */
2313 cec_write_clr_set(sd, 0x28, 0xf0, addr << 4);
2314 break;
2315 case 2:
2316 /* enable address mask 2 */
2317 cec_write_clr_set(sd, 0x27, 0x40, 0x40);
2318 /* set address for mask 1 */
2319 cec_write_clr_set(sd, 0x29, 0x0f, addr);
2320 break;
2321 }
2322 return 0;
2323}
2324
2325static int adv7842_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
2326 u32 signal_free_time, struct cec_msg *msg)
2327{
2328 struct adv7842_state *state = adap->priv;
2329 struct v4l2_subdev *sd = &state->sd;
2330 u8 len = msg->len;
2331 unsigned int i;
2332
2333 /*
2334 * The number of retries is the number of attempts - 1, but retry
2335 * at least once. It's not clear if a value of 0 is allowed, so
2336 * let's do at least one retry.
2337 */
2338 cec_write_clr_set(sd, 0x12, 0x70, max(1, attempts - 1) << 4);
2339
2340 if (len > 16) {
2341 v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len);
2342 return -EINVAL;
2343 }
2344
2345 /* write data */
2346 for (i = 0; i < len; i++)
2347 cec_write(sd, i, msg->msg[i]);
2348
2349 /* set length (data + header) */
2350 cec_write(sd, 0x10, len);
2351 /* start transmit, enable tx */
2352 cec_write(sd, 0x11, 0x01);
2353 return 0;
2354}
2355
2356static const struct cec_adap_ops adv7842_cec_adap_ops = {
2357 .adap_enable = adv7842_cec_adap_enable,
2358 .adap_log_addr = adv7842_cec_adap_log_addr,
2359 .adap_transmit = adv7842_cec_adap_transmit,
2360};
2361#endif
2362
2173static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled)2363static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
2174{2364{
2175 struct adv7842_state *state = to_state(sd);2365 struct adv7842_state *state = to_state(sd);
@@ -2241,6 +2431,11 @@ static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled) · 65 unmodified lines
2241 *handled = true;2431 *handled = true;
2242 }2432 }
2243 2433
2434#if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC)
2435 /* cec */
2436 adv7842_cec_isr(sd, handled);
2437#endif
2438
2244 /* tx 5v detect */2439 /* tx 5v detect */
2245 if (irq_status[2] & 0x3) {2440 if (irq_status[2] & 0x3) {
2246 v4l2_dbg(1, debug, sd, "%s: irq tx_5v\n", __func__);2441 v4l2_dbg(1, debug, sd, "%s: irq tx_5v\n", __func__);
@@ -2321,10 +2516,12 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e) · 74 unmodified lines
2321 case ADV7842_EDID_PORT_A:2516 case ADV7842_EDID_PORT_A:
2322 case ADV7842_EDID_PORT_B:2517 case ADV7842_EDID_PORT_B:
2323 memset(&state->hdmi_edid.edid, 0, 256);2518 memset(&state->hdmi_edid.edid, 0, 256);
2324 if (e->blocks)2519 if (e->blocks) {
2325 state->hdmi_edid.present |= 0x04 << e->pad;2520 state->hdmi_edid.present |= 0x04 << e->pad;
2326 else2521 } else {
2327 state->hdmi_edid.present &= ~(0x04 << e->pad);2522 state->hdmi_edid.present &= ~(0x04 << e->pad);
2523 adv7842_s_detect_tx_5v_ctrl(sd);
2524 }
2328 memcpy(&state->hdmi_edid.edid, e->edid, 128 * e->blocks);2525 memcpy(&state->hdmi_edid.edid, e->edid, 128 * e->blocks);
2329 err = edid_write_hdmi_segment(sd, e->pad);2526 err = edid_write_hdmi_segment(sd, e->pad);
2330 break;2527 break;
@@ -2512,8 +2709,19 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd) · 181 unmodified lines
2512 v4l2_info(sd, "HPD A %s, B %s\n",2709 v4l2_info(sd, "HPD A %s, B %s\n",
2513 reg_io_0x21 & 0x02 ? "enabled" : "disabled",2710 reg_io_0x21 & 0x02 ? "enabled" : "disabled",
2514 reg_io_0x21 & 0x01 ? "enabled" : "disabled");2711 reg_io_0x21 & 0x01 ? "enabled" : "disabled");
2515 v4l2_info(sd, "CEC %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?2712 v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ?
2516 "enabled" : "disabled");2713 "enabled" : "disabled");
2714 if (state->cec_enabled_adap) {
2715 int i;
2716
2717 for (i = 0; i < ADV7842_MAX_ADDRS; i++) {
2718 bool is_valid = state->cec_valid_addrs & (1 << i);
2719
2720 if (is_valid)
2721 v4l2_info(sd, "CEC Logical Address: 0x%x\n",
2722 state->cec_addr[i]);
2723 }
2724 }
2517 2725
2518 v4l2_info(sd, "-----Signal status-----\n");2726 v4l2_info(sd, "-----Signal status-----\n");
2519 if (state->hdmi_port_a) {2727 if (state->hdmi_port_a) {
@@ -3034,6 +3242,24 @@ static int adv7842_subscribe_event(struct v4l2_subdev *sd, · 514 unmodified lines
3034 }3242 }
3035}3243}
3036 3244
3245static int adv7842_registered(struct v4l2_subdev *sd)
3246{
3247 struct adv7842_state *state = to_state(sd);
3248 int err;
3249
3250 err = cec_register_adapter(state->cec_adap);
3251 if (err)
3252 cec_delete_adapter(state->cec_adap);
3253 return err;
3254}
3255
3256static void adv7842_unregistered(struct v4l2_subdev *sd)
3257{
3258 struct adv7842_state *state = to_state(sd);
3259
3260 cec_unregister_adapter(state->cec_adap);
3261}
3262
3037/* ----------------------------------------------------------------------- */3263/* ----------------------------------------------------------------------- */
3038 3264
3039static const struct v4l2_ctrl_ops adv7842_ctrl_ops = {3265static const struct v4l2_ctrl_ops adv7842_ctrl_ops = {
@@ -3080,6 +3306,11 @@ static const struct v4l2_subdev_ops adv7842_ops = { · 40 unmodified lines
3080 .pad = &adv7842_pad_ops,3306 .pad = &adv7842_pad_ops,
3081};3307};
3082 3308
3309static const struct v4l2_subdev_internal_ops adv7842_int_ops = {
3310 .registered = adv7842_registered,
3311 .unregistered = adv7842_unregistered,
3312};
3313
3083/* -------------------------- custom ctrls ---------------------------------- */3314/* -------------------------- custom ctrls ---------------------------------- */
3084 3315
3085static const struct v4l2_ctrl_config adv7842_ctrl_analog_sampling_phase = {3316static const struct v4l2_ctrl_config adv7842_ctrl_analog_sampling_phase = {
@@ -3244,6 +3475,7 @@ static int adv7842_probe(struct i2c_client *client, · 158 unmodified lines
3244 sd = &state->sd;3475 sd = &state->sd;
3245 v4l2_i2c_subdev_init(sd, client, &adv7842_ops);3476 v4l2_i2c_subdev_init(sd, client, &adv7842_ops);
3246 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;3477 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
3478 sd->internal_ops = &adv7842_int_ops;
3247 state->mode = pdata->mode;3479 state->mode = pdata->mode;
3248 3480
3249 state->hdmi_port_a = pdata->input == ADV7842_SELECT_HDMI_PORT_A;3481 state->hdmi_port_a = pdata->input == ADV7842_SELECT_HDMI_PORT_A;
@@ -3334,6 +3566,17 @@ static int adv7842_probe(struct i2c_client *client, · 84 unmodified lines
3334 if (err)3566 if (err)
3335 goto err_entity;3567 goto err_entity;
3336 3568
3569#if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC)
3570 state->cec_adap = cec_allocate_adapter(&adv7842_cec_adap_ops,
3571 state, dev_name(&client->dev),
3572 CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
3573 CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV7842_MAX_ADDRS,
3574 &client->dev);
3575 err = PTR_ERR_OR_ZERO(state->cec_adap);
3576 if (err)
3577 goto err_entity;
3578#endif
3579
3337 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,3580 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
3338 client->addr << 1, client->adapter->name);3581 client->addr << 1, client->adapter->name);
3339 return 0;3582 return 0;
@@ -3358,7 +3601,6 @@ static int adv7842_remove(struct i2c_client *client) · 18 unmodified lines
3358 struct adv7842_state *state = to_state(sd);3601 struct adv7842_state *state = to_state(sd);
3359 3602
3360 adv7842_irq_enable(sd, false);3603 adv7842_irq_enable(sd, false);
3361
3362 cancel_delayed_work(&state->delayed_work_enable_hotplug);3604 cancel_delayed_work(&state->delayed_work_enable_hotplug);
3363 destroy_workqueue(state->work_queues);3605 destroy_workqueue(state->work_queues);
3364 v4l2_device_unregister_subdev(sd);3606 v4l2_device_unregister_subdev(sd);
drivers/media/platform/vivid/Kconfig+8−0
@@ -6,6 +6,7 @@ config VIDEO_VIVID · 5 unmodified lines
6 select FB_CFB_FILLRECT6 select FB_CFB_FILLRECT
7 select FB_CFB_COPYAREA7 select FB_CFB_COPYAREA
8 select FB_CFB_IMAGEBLIT8 select FB_CFB_IMAGEBLIT
9 select MEDIA_CEC_EDID
9 select VIDEOBUF2_VMALLOC10 select VIDEOBUF2_VMALLOC
10 select VIDEO_V4L2_TPG11 select VIDEO_V4L2_TPG
11 default n12 default n
@@ -22,6 +23,13 @@ config VIDEO_VIVID · 10 unmodified lines
22 Say Y here if you want to test video apps or debug V4L devices.23 Say Y here if you want to test video apps or debug V4L devices.
23 When in doubt, say N.24 When in doubt, say N.
24 25
26config VIDEO_VIVID_CEC
27 bool "Enable CEC emulation support"
28 depends on VIDEO_VIVID && MEDIA_CEC
29 ---help---
30 When selected the vivid module will emulate the optional
31 HDMI CEC feature.
32
25config VIDEO_VIVID_MAX_DEVS33config VIDEO_VIVID_MAX_DEVS
26 int "Maximum number of devices"34 int "Maximum number of devices"
27 depends on VIDEO_VIVID35 depends on VIDEO_VIVID
drivers/media/platform/vivid/Makefile+4−0
@@ -3,4 +3,8 @@ vivid-objs := vivid-core.o vivid-ctrls.o vivid-vid-common.o vivid-vbi-gen.o \ · 2 unmodified lines
3 vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \3 vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \
4 vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \4 vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \
5 vivid-osd.o5 vivid-osd.o
6ifeq ($(CONFIG_VIDEO_VIVID_CEC),y)
7 vivid-objs += vivid-cec.o
8endif
9
6obj-$(CONFIG_VIDEO_VIVID) += vivid.o10obj-$(CONFIG_VIDEO_VIVID) += vivid.o
drivers/media/platform/vivid/vivid-cec.c+255−0
@@ -0,0 +1,255 @@
1/*
2 * vivid-cec.c - A Virtual Video Test Driver, cec emulation
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#include <media/cec.h>
21
22#include "vivid-core.h"
23#include "vivid-cec.h"
24
25void vivid_cec_bus_free_work(struct vivid_dev *dev)
26{
27 spin_lock(&dev->cec_slock);
28 while (!list_empty(&dev->cec_work_list)) {
29 struct vivid_cec_work *cw =
30 list_first_entry(&dev->cec_work_list,
31 struct vivid_cec_work, list);
32
33 spin_unlock(&dev->cec_slock);
34 cancel_delayed_work_sync(&cw->work);
35 spin_lock(&dev->cec_slock);
36 list_del(&cw->list);
37 cec_transmit_done(cw->adap, CEC_TX_STATUS_LOW_DRIVE, 0, 0, 1, 0);
38 kfree(cw);
39 }
40 spin_unlock(&dev->cec_slock);
41}
42
43static struct cec_adapter *vivid_cec_find_dest_adap(struct vivid_dev *dev,
44 struct cec_adapter *adap,
45 u8 dest)
46{
47 unsigned int i;
48
49 if (dest >= 0xf)
50 return NULL;
51
52 if (adap != dev->cec_rx_adap && dev->cec_rx_adap &&
53 dev->cec_rx_adap->is_configured &&
54 cec_has_log_addr(dev->cec_rx_adap, dest))
55 return dev->cec_rx_adap;
56
57 for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) {
58 if (adap == dev->cec_tx_adap[i])
59 continue;
60 if (!dev->cec_tx_adap[i]->is_configured)
61 continue;
62 if (cec_has_log_addr(dev->cec_tx_adap[i], dest))
63 return dev->cec_tx_adap[i];
64 }
65 return NULL;
66}
67
68static void vivid_cec_xfer_done_worker(struct work_struct *work)
69{
70 struct vivid_cec_work *cw =
71 container_of(work, struct vivid_cec_work, work.work);
72 struct vivid_dev *dev = cw->dev;
73 struct cec_adapter *adap = cw->adap;
74 bool is_poll = cw->msg.len == 1;
75 u8 dest = cec_msg_destination(&cw->msg);
76 struct cec_adapter *dest_adap = NULL;
77 bool valid_dest;
78 unsigned int i;
79
80 valid_dest = cec_msg_is_broadcast(&cw->msg);
81 if (!valid_dest) {
82 dest_adap = vivid_cec_find_dest_adap(dev, adap, dest);
83 if (dest_adap)
84 valid_dest = true;
85 }
86 cw->tx_status = valid_dest ? CEC_TX_STATUS_OK : CEC_TX_STATUS_NACK;
87 spin_lock(&dev->cec_slock);
88 dev->cec_xfer_time_jiffies = 0;
89 dev->cec_xfer_start_jiffies = 0;
90 list_del(&cw->list);
91 spin_unlock(&dev->cec_slock);
92 cec_transmit_done(cw->adap, cw->tx_status, 0, valid_dest ? 0 : 1, 0, 0);
93
94 if (!is_poll && dest_adap) {
95 /* Directed message */
96 cec_received_msg(dest_adap, &cw->msg);
97 } else if (!is_poll && valid_dest) {
98 /* Broadcast message */
99 if (adap != dev->cec_rx_adap &&
100 dev->cec_rx_adap->log_addrs.log_addr_mask)
101 cec_received_msg(dev->cec_rx_adap, &cw->msg);
102 for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) {
103 if (adap == dev->cec_tx_adap[i] ||
104 !dev->cec_tx_adap[i]->log_addrs.log_addr_mask)
105 continue;
106 cec_received_msg(dev->cec_tx_adap[i], &cw->msg);
107 }
108 }
109 kfree(cw);
110}
111
112static void vivid_cec_xfer_try_worker(struct work_struct *work)
113{
114 struct vivid_cec_work *cw =
115 container_of(work, struct vivid_cec_work, work.work);
116 struct vivid_dev *dev = cw->dev;
117
118 spin_lock(&dev->cec_slock);
119 if (dev->cec_xfer_time_jiffies) {
120 list_del(&cw->list);
121 spin_unlock(&dev->cec_slock);
122 cec_transmit_done(cw->adap, CEC_TX_STATUS_ARB_LOST, 1, 0, 0, 0);
123 kfree(cw);
124 } else {
125 INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_done_worker);
126 dev->cec_xfer_start_jiffies = jiffies;
127 dev->cec_xfer_time_jiffies = usecs_to_jiffies(cw->usecs);
128 spin_unlock(&dev->cec_slock);
129 schedule_delayed_work(&cw->work, dev->cec_xfer_time_jiffies);
130 }
131}
132
133static int vivid_cec_adap_enable(struct cec_adapter *adap, bool enable)
134{
135 return 0;
136}
137
138static int vivid_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
139{
140 return 0;
141}
142
143/*
144 * One data bit takes 2400 us, each byte needs 10 bits so that's 24000 us
145 * per byte.
146 */
147#define USECS_PER_BYTE 24000
148
149static int vivid_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
150 u32 signal_free_time, struct cec_msg *msg)
151{
152 struct vivid_dev *dev = adap->priv;
153 struct vivid_cec_work *cw = kzalloc(sizeof(*cw), GFP_KERNEL);
154 long delta_jiffies = 0;
155
156 if (cw == NULL)
157 return -ENOMEM;
158 cw->dev = dev;
159 cw->adap = adap;
160 cw->usecs = CEC_FREE_TIME_TO_USEC(signal_free_time) +
161 msg->len * USECS_PER_BYTE;
162 cw->msg = *msg;
163
164 spin_lock(&dev->cec_slock);
165 list_add(&cw->list, &dev->cec_work_list);
166 if (dev->cec_xfer_time_jiffies == 0) {
167 INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_done_worker);
168 dev->cec_xfer_start_jiffies = jiffies;
169 dev->cec_xfer_time_jiffies = usecs_to_jiffies(cw->usecs);
170 delta_jiffies = dev->cec_xfer_time_jiffies;
171 } else {
172 INIT_DELAYED_WORK(&cw->work, vivid_cec_xfer_try_worker);
173 delta_jiffies = dev->cec_xfer_start_jiffies +
174 dev->cec_xfer_time_jiffies - jiffies;
175 }
176 spin_unlock(&dev->cec_slock);
177 schedule_delayed_work(&cw->work, delta_jiffies < 0 ? 0 : delta_jiffies);
178 return 0;
179}
180
181static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
182{
183 struct vivid_dev *dev = adap->priv;
184 struct cec_msg reply;
185 u8 dest = cec_msg_destination(msg);
186 u16 pa;
187 u8 disp_ctl;
188 char osd[14];
189
190 if (cec_msg_is_broadcast(msg))
191 dest = adap->log_addrs.log_addr[0];
192 cec_msg_init(&reply, dest, cec_msg_initiator(msg));
193
194 switch (cec_msg_opcode(msg)) {
195 case CEC_MSG_SET_STREAM_PATH:
196 if (cec_is_sink(adap))
197 return -ENOMSG;
198 cec_ops_set_stream_path(msg, &pa);
199 if (pa != adap->phys_addr)
200 return -ENOMSG;
201 cec_msg_active_source(&reply, adap->phys_addr);
202 cec_transmit_msg(adap, &reply, false);
203 break;
204 case CEC_MSG_SET_OSD_STRING:
205 if (!cec_is_sink(adap))
206 return -ENOMSG;
207 cec_ops_set_osd_string(msg, &disp_ctl, osd);
208 switch (disp_ctl) {
209 case CEC_OP_DISP_CTL_DEFAULT:
210 strcpy(dev->osd, osd);
211 dev->osd_jiffies = jiffies;
212 break;
213 case CEC_OP_DISP_CTL_UNTIL_CLEARED:
214 strcpy(dev->osd, osd);
215 dev->osd_jiffies = 0;
216 break;
217 case CEC_OP_DISP_CTL_CLEAR:
218 dev->osd[0] = 0;
219 dev->osd_jiffies = 0;
220 break;
221 default:
222 cec_msg_feature_abort(&reply, cec_msg_opcode(msg),
223 CEC_OP_ABORT_INVALID_OP);
224 cec_transmit_msg(adap, &reply, false);
225 break;
226 }
227 break;
228 default:
229 return -ENOMSG;
230 }
231 return 0;
232}
233
234static const struct cec_adap_ops vivid_cec_adap_ops = {
235 .adap_enable = vivid_cec_adap_enable,
236 .adap_log_addr = vivid_cec_adap_log_addr,
237 .adap_transmit = vivid_cec_adap_transmit,
238 .received = vivid_received,
239};
240
241struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
242 unsigned int idx,
243 struct device *parent,
244 bool is_source)
245{
246 char name[sizeof(dev->vid_out_dev.name) + 2];
247 u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
248 CEC_CAP_PASSTHROUGH | CEC_CAP_RC;
249
250 snprintf(name, sizeof(name), "%s%d",
251 is_source ? dev->vid_out_dev.name : dev->vid_cap_dev.name,
252 idx);
253 return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
254 name, caps, 1, parent);
255}
drivers/media/platform/vivid/vivid-cec.h+33−0
@@ -0,0 +1,33 @@
1/*
2 * vivid-cec.h - A Virtual Video Test Driver, cec emulation
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#ifdef CONFIG_VIDEO_VIVID_CEC
21struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
22 unsigned int idx,
23 struct device *parent,
24 bool is_source);
25void vivid_cec_bus_free_work(struct vivid_dev *dev);
26
27#else
28
29static inline void vivid_cec_bus_free_work(struct vivid_dev *dev)
30{
31}
32
33#endif
drivers/media/platform/vivid/vivid-core.c+109−9
@@ -46,6 +46,7 @@ · 45 unmodified lines
46#include "vivid-vbi-cap.h"46#include "vivid-vbi-cap.h"
47#include "vivid-vbi-out.h"47#include "vivid-vbi-out.h"
48#include "vivid-osd.h"48#include "vivid-osd.h"
49#include "vivid-cec.h"
49#include "vivid-ctrls.h"50#include "vivid-ctrls.h"
50 51
51#define VIVID_MODULE_NAME "vivid"52#define VIVID_MODULE_NAME "vivid"
@@ -684,6 +685,11 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 632 unmodified lines
684 dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++;685 dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++;
685 }686 }
686 dev->has_audio_inputs = in_type_counter[TV] && in_type_counter[SVID];687 dev->has_audio_inputs = in_type_counter[TV] && in_type_counter[SVID];
688 if (in_type_counter[HDMI] == 16) {
689 /* The CEC physical address only allows for max 15 inputs */
690 in_type_counter[HDMI]--;
691 dev->num_inputs--;
692 }
687 693
688 /* how many outputs do we have and of what type? */694 /* how many outputs do we have and of what type? */
689 dev->num_outputs = num_outputs[inst];695 dev->num_outputs = num_outputs[inst];
@@ -696,6 +702,15 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 6 unmodified lines
696 dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;702 dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;
697 }703 }
698 dev->has_audio_outputs = out_type_counter[SVID];704 dev->has_audio_outputs = out_type_counter[SVID];
705 if (out_type_counter[HDMI] == 16) {
706 /*
707 * The CEC physical address only allows for max 15 inputs,
708 * so outputs are also limited to 15 to allow for easy
709 * CEC output to input mapping.
710 */
711 out_type_counter[HDMI]--;
712 dev->num_outputs--;
713 }
699 714
700 /* do we create a video capture device? */715 /* do we create a video capture device? */
701 dev->has_vid_cap = node_type & 0x0001;716 dev->has_vid_cap = node_type & 0x0001;
@@ -1010,6 +1025,17 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 308 unmodified lines
1010 INIT_LIST_HEAD(&dev->vbi_out_active);1025 INIT_LIST_HEAD(&dev->vbi_out_active);
1011 INIT_LIST_HEAD(&dev->sdr_cap_active);1026 INIT_LIST_HEAD(&dev->sdr_cap_active);
1012 1027
1028 INIT_LIST_HEAD(&dev->cec_work_list);
1029 spin_lock_init(&dev->cec_slock);
1030 /*
1031 * Same as create_singlethread_workqueue, but now I can use the
1032 * string formatting of alloc_ordered_workqueue.
1033 */
1034 dev->cec_workqueue =
1035 alloc_ordered_workqueue("vivid-%03d-cec", WQ_MEM_RECLAIM, inst);
1036 if (!dev->cec_workqueue)
1037 goto unreg_dev;
1038
1013 /* start creating the vb2 queues */1039 /* start creating the vb2 queues */
1014 if (dev->has_vid_cap) {1040 if (dev->has_vid_cap) {
1015 /* initialize vid_cap queue */1041 /* initialize vid_cap queue */
@@ -1117,7 +1143,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 101 unmodified lines
1117 /* finally start creating the device nodes */1143 /* finally start creating the device nodes */
1118 if (dev->has_vid_cap) {1144 if (dev->has_vid_cap) {
1119 vfd = &dev->vid_cap_dev;1145 vfd = &dev->vid_cap_dev;
1120 strlcpy(vfd->name, "vivid-vid-cap", sizeof(vfd->name));1146 snprintf(vfd->name, sizeof(vfd->name),
1147 "vivid-%03d-vid-cap", inst);
1121 vfd->fops = &vivid_fops;1148 vfd->fops = &vivid_fops;
1122 vfd->ioctl_ops = &vivid_ioctl_ops;1149 vfd->ioctl_ops = &vivid_ioctl_ops;
1123 vfd->device_caps = dev->vid_cap_caps;1150 vfd->device_caps = dev->vid_cap_caps;
@@ -1133,6 +1160,27 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 9 unmodified lines
1133 vfd->lock = &dev->mutex;1160 vfd->lock = &dev->mutex;
1134 video_set_drvdata(vfd, dev);1161 video_set_drvdata(vfd, dev);
1135 1162
1163#ifdef CONFIG_VIDEO_VIVID_CEC
1164 if (in_type_counter[HDMI]) {
1165 struct cec_adapter *adap;
1166
1167 adap = vivid_cec_alloc_adap(dev, 0, &pdev->dev, false);
1168 ret = PTR_ERR_OR_ZERO(adap);
1169 if (ret < 0)
1170 goto unreg_dev;
1171 dev->cec_rx_adap = adap;
1172 ret = cec_register_adapter(adap);
1173 if (ret < 0) {
1174 cec_delete_adapter(adap);
1175 dev->cec_rx_adap = NULL;
1176 goto unreg_dev;
1177 }
1178 cec_s_phys_addr(adap, 0, false);
1179 v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input %d\n",
1180 dev_name(&adap->devnode.dev), i);
1181 }
1182#endif
1183
1136 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]);1184 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]);
1137 if (ret < 0)1185 if (ret < 0)
1138 goto unreg_dev;1186 goto unreg_dev;
@@ -1141,8 +1189,13 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 2 unmodified lines
1141 }1189 }
1142 1190
1143 if (dev->has_vid_out) {1191 if (dev->has_vid_out) {
1192#ifdef CONFIG_VIDEO_VIVID_CEC
1193 unsigned int bus_cnt = 0;
1194#endif
1195
1144 vfd = &dev->vid_out_dev;1196 vfd = &dev->vid_out_dev;
1145 strlcpy(vfd->name, "vivid-vid-out", sizeof(vfd->name));1197 snprintf(vfd->name, sizeof(vfd->name),
1198 "vivid-%03d-vid-out", inst);
1146 vfd->vfl_dir = VFL_DIR_TX;1199 vfd->vfl_dir = VFL_DIR_TX;
1147 vfd->fops = &vivid_fops;1200 vfd->fops = &vivid_fops;
1148 vfd->ioctl_ops = &vivid_ioctl_ops;1201 vfd->ioctl_ops = &vivid_ioctl_ops;
@@ -1159,6 +1212,35 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 10 unmodified lines
1159 vfd->lock = &dev->mutex;1212 vfd->lock = &dev->mutex;
1160 video_set_drvdata(vfd, dev);1213 video_set_drvdata(vfd, dev);
1161 1214
1215#ifdef CONFIG_VIDEO_VIVID_CEC
1216 for (i = 0; i < dev->num_outputs; i++) {
1217 struct cec_adapter *adap;
1218
1219 if (dev->output_type[i] != HDMI)
1220 continue;
1221 dev->cec_output2bus_map[i] = bus_cnt;
1222 adap = vivid_cec_alloc_adap(dev, bus_cnt,
1223 &pdev->dev, true);
1224 ret = PTR_ERR_OR_ZERO(adap);
1225 if (ret < 0)
1226 goto unreg_dev;
1227 dev->cec_tx_adap[bus_cnt] = adap;
1228 ret = cec_register_adapter(adap);
1229 if (ret < 0) {
1230 cec_delete_adapter(adap);
1231 dev->cec_tx_adap[bus_cnt] = NULL;
1232 goto unreg_dev;
1233 }
1234 bus_cnt++;
1235 if (bus_cnt <= in_type_counter[HDMI])
1236 cec_s_phys_addr(adap, bus_cnt << 12, false);
1237 else
1238 cec_s_phys_addr(adap, 0x1000, false);
1239 v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n",
1240 dev_name(&adap->devnode.dev), i);
1241 }
1242#endif
1243
1162 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_out_nr[inst]);1244 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_out_nr[inst]);
1163 if (ret < 0)1245 if (ret < 0)
1164 goto unreg_dev;1246 goto unreg_dev;
@@ -1168,7 +1250,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 3 unmodified lines
1168 1250
1169 if (dev->has_vbi_cap) {1251 if (dev->has_vbi_cap) {
1170 vfd = &dev->vbi_cap_dev;1252 vfd = &dev->vbi_cap_dev;
1171 strlcpy(vfd->name, "vivid-vbi-cap", sizeof(vfd->name));1253 snprintf(vfd->name, sizeof(vfd->name),
1254 "vivid-%03d-vbi-cap", inst);
1172 vfd->fops = &vivid_fops;1255 vfd->fops = &vivid_fops;
1173 vfd->ioctl_ops = &vivid_ioctl_ops;1256 vfd->ioctl_ops = &vivid_ioctl_ops;
1174 vfd->device_caps = dev->vbi_cap_caps;1257 vfd->device_caps = dev->vbi_cap_caps;
@@ -1191,7 +1274,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 16 unmodified lines
1191 1274
1192 if (dev->has_vbi_out) {1275 if (dev->has_vbi_out) {
1193 vfd = &dev->vbi_out_dev;1276 vfd = &dev->vbi_out_dev;
1194 strlcpy(vfd->name, "vivid-vbi-out", sizeof(vfd->name));1277 snprintf(vfd->name, sizeof(vfd->name),
1278 "vivid-%03d-vbi-out", inst);
1195 vfd->vfl_dir = VFL_DIR_TX;1279 vfd->vfl_dir = VFL_DIR_TX;
1196 vfd->fops = &vivid_fops;1280 vfd->fops = &vivid_fops;
1197 vfd->ioctl_ops = &vivid_ioctl_ops;1281 vfd->ioctl_ops = &vivid_ioctl_ops;
@@ -1215,7 +1299,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 17 unmodified lines
1215 1299
1216 if (dev->has_sdr_cap) {1300 if (dev->has_sdr_cap) {
1217 vfd = &dev->sdr_cap_dev;1301 vfd = &dev->sdr_cap_dev;
1218 strlcpy(vfd->name, "vivid-sdr-cap", sizeof(vfd->name));1302 snprintf(vfd->name, sizeof(vfd->name),
1303 "vivid-%03d-sdr-cap", inst);
1219 vfd->fops = &vivid_fops;1304 vfd->fops = &vivid_fops;
1220 vfd->ioctl_ops = &vivid_ioctl_ops;1305 vfd->ioctl_ops = &vivid_ioctl_ops;
1221 vfd->device_caps = dev->sdr_cap_caps;1306 vfd->device_caps = dev->sdr_cap_caps;
@@ -1234,7 +1319,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 12 unmodified lines
1234 1319
1235 if (dev->has_radio_rx) {1320 if (dev->has_radio_rx) {
1236 vfd = &dev->radio_rx_dev;1321 vfd = &dev->radio_rx_dev;
1237 strlcpy(vfd->name, "vivid-rad-rx", sizeof(vfd->name));1322 snprintf(vfd->name, sizeof(vfd->name),
1323 "vivid-%03d-rad-rx", inst);
1238 vfd->fops = &vivid_radio_fops;1324 vfd->fops = &vivid_radio_fops;
1239 vfd->ioctl_ops = &vivid_ioctl_ops;1325 vfd->ioctl_ops = &vivid_ioctl_ops;
1240 vfd->device_caps = dev->radio_rx_caps;1326 vfd->device_caps = dev->radio_rx_caps;
@@ -1252,7 +1338,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 11 unmodified lines
1252 1338
1253 if (dev->has_radio_tx) {1339 if (dev->has_radio_tx) {
1254 vfd = &dev->radio_tx_dev;1340 vfd = &dev->radio_tx_dev;
1255 strlcpy(vfd->name, "vivid-rad-tx", sizeof(vfd->name));1341 snprintf(vfd->name, sizeof(vfd->name),
1342 "vivid-%03d-rad-tx", inst);
1256 vfd->vfl_dir = VFL_DIR_TX;1343 vfd->vfl_dir = VFL_DIR_TX;
1257 vfd->fops = &vivid_radio_fops;1344 vfd->fops = &vivid_radio_fops;
1258 vfd->ioctl_ops = &vivid_ioctl_ops;1345 vfd->ioctl_ops = &vivid_ioctl_ops;
@@ -1282,6 +1369,13 @@ unreg_dev: · 23 unmodified lines
1282 video_unregister_device(&dev->vbi_cap_dev);1369 video_unregister_device(&dev->vbi_cap_dev);
1283 video_unregister_device(&dev->vid_out_dev);1370 video_unregister_device(&dev->vid_out_dev);
1284 video_unregister_device(&dev->vid_cap_dev);1371 video_unregister_device(&dev->vid_cap_dev);
1372 cec_unregister_adapter(dev->cec_rx_adap);
1373 for (i = 0; i < MAX_OUTPUTS; i++)
1374 cec_unregister_adapter(dev->cec_tx_adap[i]);
1375 if (dev->cec_workqueue) {
1376 vivid_cec_bus_free_work(dev);
1377 destroy_workqueue(dev->cec_workqueue);
1378 }
1285free_dev:1379free_dev:
1286 v4l2_device_put(&dev->v4l2_dev);1380 v4l2_device_put(&dev->v4l2_dev);
1287 return ret;1381 return ret;
@@ -1331,8 +1425,7 @@ static int vivid_probe(struct platform_device *pdev) · 43 unmodified lines
1331static int vivid_remove(struct platform_device *pdev)1425static int vivid_remove(struct platform_device *pdev)
1332{1426{
1333 struct vivid_dev *dev;1427 struct vivid_dev *dev;
1334 unsigned i;1428 unsigned int i, j;
1335
1336 1429
1337 for (i = 0; i < n_devs; i++) {1430 for (i = 0; i < n_devs; i++) {
1338 dev = vivid_devs[i];1431 dev = vivid_devs[i];
@@ -1380,6 +1473,13 @@ static int vivid_remove(struct platform_device *pdev) · 41 unmodified lines
1380 unregister_framebuffer(&dev->fb_info);1473 unregister_framebuffer(&dev->fb_info);
1381 vivid_fb_release_buffers(dev);1474 vivid_fb_release_buffers(dev);
1382 }1475 }
1476 cec_unregister_adapter(dev->cec_rx_adap);
1477 for (j = 0; j < MAX_OUTPUTS; j++)
1478 cec_unregister_adapter(dev->cec_tx_adap[j]);
1479 if (dev->cec_workqueue) {
1480 vivid_cec_bus_free_work(dev);
1481 destroy_workqueue(dev->cec_workqueue);
1482 }
1383 v4l2_device_put(&dev->v4l2_dev);1483 v4l2_device_put(&dev->v4l2_dev);
1384 vivid_devs[i] = NULL;1484 vivid_devs[i] = NULL;
1385 }1485 }
drivers/media/platform/vivid/vivid-core.h+27−0
@@ -21,6 +21,8 @@ · 20 unmodified lines
21#define _VIVID_CORE_H_21#define _VIVID_CORE_H_
22 22
23#include <linux/fb.h>23#include <linux/fb.h>
24#include <linux/workqueue.h>
25#include <media/cec.h>
24#include <media/videobuf2-v4l2.h>26#include <media/videobuf2-v4l2.h>
25#include <media/v4l2-device.h>27#include <media/v4l2-device.h>
26#include <media/v4l2-dev.h>28#include <media/v4l2-dev.h>
@@ -132,6 +134,17 @@ enum vivid_colorspace { · 105 unmodified lines
132#define VIVID_INVALID_SIGNAL(mode) \134#define VIVID_INVALID_SIGNAL(mode) \
133 ((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE)135 ((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE)
134 136
137struct vivid_cec_work {
138 struct list_head list;
139 struct delayed_work work;
140 struct cec_adapter *adap;
141 struct vivid_dev *dev;
142 unsigned int usecs;
143 unsigned int timeout_ms;
144 u8 tx_status;
145 struct cec_msg msg;
146};
147
135struct vivid_dev {148struct vivid_dev {
136 unsigned inst;149 unsigned inst;
137 struct v4l2_device v4l2_dev;150 struct v4l2_device v4l2_dev;
@@ -497,6 +510,20 @@ struct vivid_dev { · 359 unmodified lines
497 /* Shared between radio receiver and transmitter */510 /* Shared between radio receiver and transmitter */
498 bool radio_rds_loop;511 bool radio_rds_loop;
499 struct timespec radio_rds_init_ts;512 struct timespec radio_rds_init_ts;
513
514 /* CEC */
515 struct cec_adapter *cec_rx_adap;
516 struct cec_adapter *cec_tx_adap[MAX_OUTPUTS];
517 struct workqueue_struct *cec_workqueue;
518 spinlock_t cec_slock;
519 struct list_head cec_work_list;
520 unsigned int cec_xfer_time_jiffies;
521 unsigned long cec_xfer_start_jiffies;
522 u8 cec_output2bus_map[MAX_OUTPUTS];
523
524 /* CEC OSD String */
525 char osd[14];
526 unsigned long osd_jiffies;
500};527};
501 528
502static inline bool vivid_is_webcam(const struct vivid_dev *dev)529static inline bool vivid_is_webcam(const struct vivid_dev *dev)
drivers/media/platform/vivid/vivid-kthread-cap.c+13−0
@@ -552,6 +552,19 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) · 551 unmodified lines
552 snprintf(str, sizeof(str), " button pressed!");552 snprintf(str, sizeof(str), " button pressed!");
553 tpg_gen_text(tpg, basep, line++ * line_height, 16, str);553 tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
554 }554 }
555 if (dev->osd[0]) {
556 if (vivid_is_hdmi_cap(dev)) {
557 snprintf(str, sizeof(str),
558 " OSD \"%s\"", dev->osd);
559 tpg_gen_text(tpg, basep, line++ * line_height,
560 16, str);
561 }
562 if (dev->osd_jiffies &&
563 time_is_before_jiffies(dev->osd_jiffies + 5 * HZ)) {
564 dev->osd[0] = 0;
565 dev->osd_jiffies = 0;
566 }
567 }
555 }568 }
556 569
557 /*570 /*
drivers/media/platform/vivid/vivid-vid-cap.c+22−1
@@ -1700,6 +1700,9 @@ int vidioc_s_edid(struct file *file, void *_fh, · 1699 unmodified lines
1700 struct v4l2_edid *edid)1700 struct v4l2_edid *edid)
1701{1701{
1702 struct vivid_dev *dev = video_drvdata(file);1702 struct vivid_dev *dev = video_drvdata(file);
1703 u16 phys_addr;
1704 unsigned int i;
1705 int ret;
1703 1706
1704 memset(edid->reserved, 0, sizeof(edid->reserved));1707 memset(edid->reserved, 0, sizeof(edid->reserved));
1705 if (edid->pad >= dev->num_inputs)1708 if (edid->pad >= dev->num_inputs)
@@ -1708,14 +1711,32 @@ int vidioc_s_edid(struct file *file, void *_fh, · 2 unmodified lines
1708 return -EINVAL;1711 return -EINVAL;
1709 if (edid->blocks == 0) {1712 if (edid->blocks == 0) {
1710 dev->edid_blocks = 0;1713 dev->edid_blocks = 0;
1711 return 0;1714 phys_addr = CEC_PHYS_ADDR_INVALID;
1715 goto set_phys_addr;
1712 }1716 }
1713 if (edid->blocks > dev->edid_max_blocks) {1717 if (edid->blocks > dev->edid_max_blocks) {
1714 edid->blocks = dev->edid_max_blocks;1718 edid->blocks = dev->edid_max_blocks;
1715 return -E2BIG;1719 return -E2BIG;
1716 }1720 }
1721 phys_addr = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL);
1722 ret = cec_phys_addr_validate(phys_addr, &phys_addr, NULL);
1723 if (ret)
1724 return ret;
1725
1726 if (vb2_is_busy(&dev->vb_vid_cap_q))
1727 return -EBUSY;
1728
1717 dev->edid_blocks = edid->blocks;1729 dev->edid_blocks = edid->blocks;
1718 memcpy(dev->edid, edid->edid, edid->blocks * 128);1730 memcpy(dev->edid, edid->edid, edid->blocks * 128);
1731
1732set_phys_addr:
1733 /* TODO: a proper hotplug detect cycle should be emulated here */
1734 cec_s_phys_addr(dev->cec_rx_adap, phys_addr, false);
1735
1736 for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++)
1737 cec_s_phys_addr(dev->cec_tx_adap[i],
1738 cec_phys_addr_for_input(phys_addr, i + 1),
1739 false);
1719 return 0;1740 return 0;
1720}1741}
1721 1742
drivers/media/platform/vivid/vivid-vid-common.c+7−0
@@ -811,6 +811,7 @@ int vidioc_g_edid(struct file *file, void *_fh, · 810 unmodified lines
811{811{
812 struct vivid_dev *dev = video_drvdata(file);812 struct vivid_dev *dev = video_drvdata(file);
813 struct video_device *vdev = video_devdata(file);813 struct video_device *vdev = video_devdata(file);
814 struct cec_adapter *adap;
814 815
815 memset(edid->reserved, 0, sizeof(edid->reserved));816 memset(edid->reserved, 0, sizeof(edid->reserved));
816 if (vdev->vfl_dir == VFL_DIR_RX) {817 if (vdev->vfl_dir == VFL_DIR_RX) {
@@ -818,11 +819,16 @@ int vidioc_g_edid(struct file *file, void *_fh, · 1 unmodified line
818 return -EINVAL;819 return -EINVAL;
819 if (dev->input_type[edid->pad] != HDMI)820 if (dev->input_type[edid->pad] != HDMI)
820 return -EINVAL;821 return -EINVAL;
822 adap = dev->cec_rx_adap;
821 } else {823 } else {
824 unsigned int bus_idx;
825
822 if (edid->pad >= dev->num_outputs)826 if (edid->pad >= dev->num_outputs)
823 return -EINVAL;827 return -EINVAL;
824 if (dev->output_type[edid->pad] != HDMI)828 if (dev->output_type[edid->pad] != HDMI)
825 return -EINVAL;829 return -EINVAL;
830 bus_idx = dev->cec_output2bus_map[edid->pad];
831 adap = dev->cec_tx_adap[bus_idx];
826 }832 }
827 if (edid->start_block == 0 && edid->blocks == 0) {833 if (edid->start_block == 0 && edid->blocks == 0) {
828 edid->blocks = dev->edid_blocks;834 edid->blocks = dev->edid_blocks;
@@ -835,5 +841,6 @@ int vidioc_g_edid(struct file *file, void *_fh, · 6 unmodified lines
835 if (edid->start_block + edid->blocks > dev->edid_blocks)841 if (edid->start_block + edid->blocks > dev->edid_blocks)
836 edid->blocks = dev->edid_blocks - edid->start_block;842 edid->blocks = dev->edid_blocks - edid->start_block;
837 memcpy(edid->edid, dev->edid, edid->blocks * 128);843 memcpy(edid->edid, dev->edid, edid->blocks * 128);
844 cec_set_edid_phys_addr(edid->edid, edid->blocks * 128, adap->phys_addr);
838 return 0;845 return 0;
839}846}
drivers/media/rc/rc-main.c+1−0
@@ -804,6 +804,7 @@ static const struct { · 803 unmodified lines
804 { RC_BIT_SHARP, "sharp", "ir-sharp-decoder" },804 { RC_BIT_SHARP, "sharp", "ir-sharp-decoder" },
805 { RC_BIT_MCE_KBD, "mce_kbd", "ir-mce_kbd-decoder" },805 { RC_BIT_MCE_KBD, "mce_kbd", "ir-mce_kbd-decoder" },
806 { RC_BIT_XMP, "xmp", "ir-xmp-decoder" },806 { RC_BIT_XMP, "xmp", "ir-xmp-decoder" },
807 { RC_BIT_CEC, "cec", NULL },
807};808};
808 809
809/**810/**
drivers/staging/media/Kconfig+4−0
@@ -21,6 +21,8 @@ if STAGING_MEDIA · 20 unmodified lines
21# Please keep them in alphabetic order21# Please keep them in alphabetic order
22source "drivers/staging/media/bcm2048/Kconfig"22source "drivers/staging/media/bcm2048/Kconfig"
23 23
24source "drivers/staging/media/cec/Kconfig"
25
24source "drivers/staging/media/cxd2099/Kconfig"26source "drivers/staging/media/cxd2099/Kconfig"
25 27
26source "drivers/staging/media/davinci_vpfe/Kconfig"28source "drivers/staging/media/davinci_vpfe/Kconfig"
@@ -29,6 +31,8 @@ source "drivers/staging/media/omap4iss/Kconfig" · 2 unmodified lines
29 31
30source "drivers/staging/media/tw686x-kh/Kconfig"32source "drivers/staging/media/tw686x-kh/Kconfig"
31 33
34source "drivers/staging/media/s5p-cec/Kconfig"
35
32# Keep LIRC at the end, as it has sub-menus36# Keep LIRC at the end, as it has sub-menus
33source "drivers/staging/media/lirc/Kconfig"37source "drivers/staging/media/lirc/Kconfig"
34 38
drivers/staging/media/Makefile+2−0
@@ -1,4 +1,6 @@
1obj-$(CONFIG_I2C_BCM2048) += bcm2048/1obj-$(CONFIG_I2C_BCM2048) += bcm2048/
2obj-$(CONFIG_MEDIA_CEC) += cec/
3obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec/
2obj-$(CONFIG_DVB_CXD2099) += cxd2099/4obj-$(CONFIG_DVB_CXD2099) += cxd2099/
3obj-$(CONFIG_LIRC_STAGING) += lirc/5obj-$(CONFIG_LIRC_STAGING) += lirc/
4obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/6obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
drivers/staging/media/cec/Kconfig+14−0
@@ -0,0 +1,14 @@
1config MEDIA_CEC
2 tristate "CEC API (EXPERIMENTAL)"
3 select MEDIA_CEC_EDID
4 ---help---
5 Enable the CEC API.
6
7 To compile this driver as a module, choose M here: the
8 module will be called cec.
9
10config MEDIA_CEC_DEBUG
11 bool "CEC debugfs interface (EXPERIMENTAL)"
12 depends on MEDIA_CEC && DEBUG_FS
13 ---help---
14 Turns on the DebugFS interface for CEC devices.
drivers/staging/media/cec/Makefile+3−0
@@ -0,0 +1,3 @@
1cec-objs := cec-core.o cec-adap.o cec-api.o
2
3obj-$(CONFIG_MEDIA_CEC) += cec.o
drivers/staging/media/cec/TODO+27−0
@@ -0,0 +1,27 @@
1The reason why cec.c is still in staging is that I would like
2to have a bit more confidence in the uABI. The kABI is fine,
3no problem there, but I would like to let the public API mature
4a bit.
5
6Once I'm confident that I didn't miss anything then the cec.c source
7can move to drivers/media and the linux/cec.h and linux/cec-funcs.h
8headers can move to uapi/linux and added to uapi/linux/Kbuild to make
9them public.
10
11Hopefully this will happen later in 2016.
12
13Other TODOs:
14
15- Add a flag to inhibit passing CEC RC messages to the rc subsystem.
16 Applications should be able to choose this when calling S_LOG_ADDRS.
17- Convert cec.txt to sphinx.
18- If the reply field of cec_msg is set then when the reply arrives it
19 is only sent to the filehandle that transmitted the original message
20 and not to any followers. Should this behavior change or perhaps
21 controlled through a cec_msg flag?
22- Should CEC_LOG_ADDR_TYPE_SPECIFIC be replaced by TYPE_2ND_TV and TYPE_PROCESSOR?
23 And also TYPE_SWITCH and TYPE_CDC_ONLY in addition to the TYPE_UNREGISTERED?
24 This should give the framework more information about the device type
25 since SPECIFIC and UNREGISTERED give no useful information.
26
27Hans Verkuil <hans.verkuil@cisco.com>
drivers/staging/media/cec/cec-adap.c+1627−0
@@ -0,0 +1,1627 @@
1/*
2 * cec-adap.c - HDMI Consumer Electronics Control framework - CEC adapter
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/kmod.h>
25#include <linux/ktime.h>
26#include <linux/slab.h>
27#include <linux/mm.h>
28#include <linux/string.h>
29#include <linux/types.h>
30
31#include "cec-priv.h"
32
33static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx);
34static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx);
35
36/*
37 * 400 ms is the time it takes for one 16 byte message to be
38 * transferred and 5 is the maximum number of retries. Add
39 * another 100 ms as a margin. So if the transmit doesn't
40 * finish before that time something is really wrong and we
41 * have to time out.
42 *
43 * This is a sign that something it really wrong and a warning
44 * will be issued.
45 */
46#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
47
48#define call_op(adap, op, arg...) \
49 (adap->ops->op ? adap->ops->op(adap, ## arg) : 0)
50
51#define call_void_op(adap, op, arg...) \
52 do { \
53 if (adap->ops->op) \
54 adap->ops->op(adap, ## arg); \
55 } while (0)
56
57static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
58{
59 int i;
60
61 for (i = 0; i < adap->log_addrs.num_log_addrs; i++)
62 if (adap->log_addrs.log_addr[i] == log_addr)
63 return i;
64 return -1;
65}
66
67static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr)
68{
69 int i = cec_log_addr2idx(adap, log_addr);
70
71 return adap->log_addrs.primary_device_type[i < 0 ? 0 : i];
72}
73
74/*
75 * Queue a new event for this filehandle. If ts == 0, then set it
76 * to the current time.
77 *
78 * The two events that are currently defined do not need to keep track
79 * of intermediate events, so no actual queue of events is needed,
80 * instead just store the latest state and the total number of lost
81 * messages.
82 *
83 * Should new events be added in the future that require intermediate
84 * results to be queued as well, then a proper queue data structure is
85 * required. But until then, just keep it simple.
86 */
87void cec_queue_event_fh(struct cec_fh *fh,
88 const struct cec_event *new_ev, u64 ts)
89{
90 struct cec_event *ev = &fh->events[new_ev->event - 1];
91
92 if (ts == 0)
93 ts = ktime_get_ns();
94
95 mutex_lock(&fh->lock);
96 if (new_ev->event == CEC_EVENT_LOST_MSGS &&
97 fh->pending_events & (1 << new_ev->event)) {
98 /*
99 * If there is already a lost_msgs event, then just
100 * update the lost_msgs count. This effectively
101 * merges the old and new events into one.
102 */
103 ev->lost_msgs.lost_msgs += new_ev->lost_msgs.lost_msgs;
104 goto unlock;
105 }
106
107 /*
108 * Intermediate states are not interesting, so just
109 * overwrite any older event.
110 */
111 *ev = *new_ev;
112 ev->ts = ts;
113 fh->pending_events |= 1 << new_ev->event;
114
115unlock:
116 mutex_unlock(&fh->lock);
117 wake_up_interruptible(&fh->wait);
118}
119
120/* Queue a new event for all open filehandles. */
121static void cec_queue_event(struct cec_adapter *adap,
122 const struct cec_event *ev)
123{
124 u64 ts = ktime_get_ns();
125 struct cec_fh *fh;
126
127 mutex_lock(&adap->devnode.fhs_lock);
128 list_for_each_entry(fh, &adap->devnode.fhs, list)
129 cec_queue_event_fh(fh, ev, ts);
130 mutex_unlock(&adap->devnode.fhs_lock);
131}
132
133/*
134 * Queue a new message for this filehandle. If there is no more room
135 * in the queue, then send the LOST_MSGS event instead.
136 */
137static void cec_queue_msg_fh(struct cec_fh *fh, const struct cec_msg *msg)
138{
139 static const struct cec_event ev_lost_msg = {
140 .event = CEC_EVENT_LOST_MSGS,
141 .lost_msgs.lost_msgs = 1,
142 };
143 struct cec_msg_entry *entry;
144
145 mutex_lock(&fh->lock);
146 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
147 if (!entry)
148 goto lost_msgs;
149
150 entry->msg = *msg;
151 /* Add new msg at the end of the queue */
152 list_add_tail(&entry->list, &fh->msgs);
153
154 /*
155 * if the queue now has more than CEC_MAX_MSG_QUEUE_SZ
156 * messages, drop the oldest one and send a lost message event.
157 */
158 if (fh->queued_msgs == CEC_MAX_MSG_QUEUE_SZ) {
159 list_del(&entry->list);
160 goto lost_msgs;
161 }
162 fh->queued_msgs++;
163 mutex_unlock(&fh->lock);
164 wake_up_interruptible(&fh->wait);
165 return;
166
167lost_msgs:
168 mutex_unlock(&fh->lock);
169 cec_queue_event_fh(fh, &ev_lost_msg, 0);
170}
171
172/*
173 * Queue the message for those filehandles that are in monitor mode.
174 * If valid_la is true (this message is for us or was sent by us),
175 * then pass it on to any monitoring filehandle. If this message
176 * isn't for us or from us, then only give it to filehandles that
177 * are in MONITOR_ALL mode.
178 *
179 * This can only happen if the CEC_CAP_MONITOR_ALL capability is
180 * set and the CEC adapter was placed in 'monitor all' mode.
181 */
182static void cec_queue_msg_monitor(struct cec_adapter *adap,
183 const struct cec_msg *msg,
184 bool valid_la)
185{
186 struct cec_fh *fh;
187 u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
188 CEC_MODE_MONITOR_ALL;
189
190 mutex_lock(&adap->devnode.fhs_lock);
191 list_for_each_entry(fh, &adap->devnode.fhs, list) {
192 if (fh->mode_follower >= monitor_mode)
193 cec_queue_msg_fh(fh, msg);
194 }
195 mutex_unlock(&adap->devnode.fhs_lock);
196}
197
198/*
199 * Queue the message for follower filehandles.
200 */
201static void cec_queue_msg_followers(struct cec_adapter *adap,
202 const struct cec_msg *msg)
203{
204 struct cec_fh *fh;
205
206 mutex_lock(&adap->devnode.fhs_lock);
207 list_for_each_entry(fh, &adap->devnode.fhs, list) {
208 if (fh->mode_follower == CEC_MODE_FOLLOWER)
209 cec_queue_msg_fh(fh, msg);
210 }
211 mutex_unlock(&adap->devnode.fhs_lock);
212}
213
214/* Notify userspace of an adapter state change. */
215static void cec_post_state_event(struct cec_adapter *adap)
216{
217 struct cec_event ev = {
218 .event = CEC_EVENT_STATE_CHANGE,
219 };
220
221 ev.state_change.phys_addr = adap->phys_addr;
222 ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
223 cec_queue_event(adap, &ev);
224}
225
226/*
227 * A CEC transmit (and a possible wait for reply) completed.
228 * If this was in blocking mode, then complete it, otherwise
229 * queue the message for userspace to dequeue later.
230 *
231 * This function is called with adap->lock held.
232 */
233static void cec_data_completed(struct cec_data *data)
234{
235 /*
236 * Delete this transmit from the filehandle's xfer_list since
237 * we're done with it.
238 *
239 * Note that if the filehandle is closed before this transmit
240 * finished, then the release() function will set data->fh to NULL.
241 * Without that we would be referring to a closed filehandle.
242 */
243 if (data->fh)
244 list_del(&data->xfer_list);
245
246 if (data->blocking) {
247 /*
248 * Someone is blocking so mark the message as completed
249 * and call complete.
250 */
251 data->completed = true;
252 complete(&data->c);
253 } else {
254 /*
255 * No blocking, so just queue the message if needed and
256 * free the memory.
257 */
258 if (data->fh)
259 cec_queue_msg_fh(data->fh, &data->msg);
260 kfree(data);
261 }
262}
263
264/*
265 * A pending CEC transmit needs to be cancelled, either because the CEC
266 * adapter is disabled or the transmit takes an impossibly long time to
267 * finish.
268 *
269 * This function is called with adap->lock held.
270 */
271static void cec_data_cancel(struct cec_data *data)
272{
273 /*
274 * It's either the current transmit, or it is a pending
275 * transmit. Take the appropriate action to clear it.
276 */
277 if (data->adap->transmitting == data)
278 data->adap->transmitting = NULL;
279 else
280 list_del_init(&data->list);
281
282 /* Mark it as an error */
283 data->msg.ts = ktime_get_ns();
284 data->msg.tx_status = CEC_TX_STATUS_ERROR |
285 CEC_TX_STATUS_MAX_RETRIES;
286 data->attempts = 0;
287 data->msg.tx_error_cnt = 1;
288 data->msg.reply = 0;
289 /* Queue transmitted message for monitoring purposes */
290 cec_queue_msg_monitor(data->adap, &data->msg, 1);
291
292 cec_data_completed(data);
293}
294
295/*
296 * Main CEC state machine
297 *
298 * Wait until the thread should be stopped, or we are not transmitting and
299 * a new transmit message is queued up, in which case we start transmitting
300 * that message. When the adapter finished transmitting the message it will
301 * call cec_transmit_done().
302 *
303 * If the adapter is disabled, then remove all queued messages instead.
304 *
305 * If the current transmit times out, then cancel that transmit.
306 */
307int cec_thread_func(void *_adap)
308{
309 struct cec_adapter *adap = _adap;
310
311 for (;;) {
312 unsigned int signal_free_time;
313 struct cec_data *data;
314 bool timeout = false;
315 u8 attempts;
316
317 if (adap->transmitting) {
318 int err;
319
320 /*
321 * We are transmitting a message, so add a timeout
322 * to prevent the state machine to get stuck waiting
323 * for this message to finalize and add a check to
324 * see if the adapter is disabled in which case the
325 * transmit should be canceled.
326 */
327 err = wait_event_interruptible_timeout(adap->kthread_waitq,
328 kthread_should_stop() ||
329 adap->phys_addr == CEC_PHYS_ADDR_INVALID ||
330 (!adap->transmitting &&
331 !list_empty(&adap->transmit_queue)),
332 msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
333 timeout = err == 0;
334 } else {
335 /* Otherwise we just wait for something to happen. */
336 wait_event_interruptible(adap->kthread_waitq,
337 kthread_should_stop() ||
338 (!adap->transmitting &&
339 !list_empty(&adap->transmit_queue)));
340 }
341
342 mutex_lock(&adap->lock);
343
344 if (adap->phys_addr == CEC_PHYS_ADDR_INVALID ||
345 kthread_should_stop()) {
346 /*
347 * If the adapter is disabled, or we're asked to stop,
348 * then cancel any pending transmits.
349 */
350 while (!list_empty(&adap->transmit_queue)) {
351 data = list_first_entry(&adap->transmit_queue,
352 struct cec_data, list);
353 cec_data_cancel(data);
354 }
355 if (adap->transmitting)
356 cec_data_cancel(adap->transmitting);
357
358 /*
359 * Cancel the pending timeout work. We have to unlock
360 * the mutex when flushing the work since
361 * cec_wait_timeout() will take it. This is OK since
362 * no new entries can be added to wait_queue as long
363 * as adap->transmitting is NULL, which it is due to
364 * the cec_data_cancel() above.
365 */
366 while (!list_empty(&adap->wait_queue)) {
367 data = list_first_entry(&adap->wait_queue,
368 struct cec_data, list);
369
370 if (!cancel_delayed_work(&data->work)) {
371 mutex_unlock(&adap->lock);
372 flush_scheduled_work();
373 mutex_lock(&adap->lock);
374 }
375 cec_data_cancel(data);
376 }
377 goto unlock;
378 }
379
380 if (adap->transmitting && timeout) {
381 /*
382 * If we timeout, then log that. This really shouldn't
383 * happen and is an indication of a faulty CEC adapter
384 * driver, or the CEC bus is in some weird state.
385 */
386 dprintk(0, "message %*ph timed out!\n",
387 adap->transmitting->msg.len,
388 adap->transmitting->msg.msg);
389 /* Just give up on this. */
390 cec_data_cancel(adap->transmitting);
391 goto unlock;
392 }
393
394 /*
395 * If we are still transmitting, or there is nothing new to
396 * transmit, then just continue waiting.
397 */
398 if (adap->transmitting || list_empty(&adap->transmit_queue))
399 goto unlock;
400
401 /* Get a new message to transmit */
402 data = list_first_entry(&adap->transmit_queue,
403 struct cec_data, list);
404 list_del_init(&data->list);
405 /* Make this the current transmitting message */
406 adap->transmitting = data;
407
408 /*
409 * Suggested number of attempts as per the CEC 2.0 spec:
410 * 4 attempts is the default, except for 'secondary poll
411 * messages', i.e. poll messages not sent during the adapter
412 * configuration phase when it allocates logical addresses.
413 */
414 if (data->msg.len == 1 && adap->is_configured)
415 attempts = 2;
416 else
417 attempts = 4;
418
419 /* Set the suggested signal free time */
420 if (data->attempts) {
421 /* should be >= 3 data bit periods for a retry */
422 signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY;
423 } else if (data->new_initiator) {
424 /* should be >= 5 data bit periods for new initiator */
425 signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
426 } else {
427 /*
428 * should be >= 7 data bit periods for sending another
429 * frame immediately after another.
430 */
431 signal_free_time = CEC_SIGNAL_FREE_TIME_NEXT_XFER;
432 }
433 if (data->attempts == 0)
434 data->attempts = attempts;
435
436 /* Tell the adapter to transmit, cancel on error */
437 if (adap->ops->adap_transmit(adap, data->attempts,
438 signal_free_time, &data->msg))
439 cec_data_cancel(data);
440
441unlock:
442 mutex_unlock(&adap->lock);
443
444 if (kthread_should_stop())
445 break;
446 }
447 return 0;
448}
449
450/*
451 * Called by the CEC adapter if a transmit finished.
452 */
453void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
454 u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt)
455{
456 struct cec_data *data;
457 struct cec_msg *msg;
458
459 dprintk(2, "cec_transmit_done %02x\n", status);
460 mutex_lock(&adap->lock);
461 data = adap->transmitting;
462 if (!data) {
463 /*
464 * This can happen if a transmit was issued and the cable is
465 * unplugged while the transmit is ongoing. Ignore this
466 * transmit in that case.
467 */
468 dprintk(1, "cec_transmit_done without an ongoing transmit!\n");
469 goto unlock;
470 }
471
472 msg = &data->msg;
473
474 /* Drivers must fill in the status! */
475 WARN_ON(status == 0);
476 msg->ts = ktime_get_ns();
477 msg->tx_status |= status;
478 msg->tx_arb_lost_cnt += arb_lost_cnt;
479 msg->tx_nack_cnt += nack_cnt;
480 msg->tx_low_drive_cnt += low_drive_cnt;
481 msg->tx_error_cnt += error_cnt;
482
483 /* Mark that we're done with this transmit */
484 adap->transmitting = NULL;
485
486 /*
487 * If there are still retry attempts left and there was an error and
488 * the hardware didn't signal that it retried itself (by setting
489 * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
490 */
491 if (data->attempts > 1 &&
492 !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) {
493 /* Retry this message */
494 data->attempts--;
495 /* Add the message in front of the transmit queue */
496 list_add(&data->list, &adap->transmit_queue);
497 goto wake_thread;
498 }
499
500 data->attempts = 0;
501
502 /* Always set CEC_TX_STATUS_MAX_RETRIES on error */
503 if (!(status & CEC_TX_STATUS_OK))
504 msg->tx_status |= CEC_TX_STATUS_MAX_RETRIES;
505
506 /* Queue transmitted message for monitoring purposes */
507 cec_queue_msg_monitor(adap, msg, 1);
508
509 /*
510 * Clear reply and timeout on error or if the adapter is no longer
511 * configured. It makes no sense to wait for a reply in that case.
512 */
513 if (!(status & CEC_TX_STATUS_OK) || !adap->is_configured) {
514 msg->reply = 0;
515 msg->timeout = 0;
516 }
517
518 if (msg->timeout) {
519 /*
520 * Queue the message into the wait queue if we want to wait
521 * for a reply.
522 */
523 list_add_tail(&data->list, &adap->wait_queue);
524 schedule_delayed_work(&data->work,
525 msecs_to_jiffies(msg->timeout));
526 } else {
527 /* Otherwise we're done */
528 cec_data_completed(data);
529 }
530
531wake_thread:
532 /*
533 * Wake up the main thread to see if another message is ready
534 * for transmitting or to retry the current message.
535 */
536 wake_up_interruptible(&adap->kthread_waitq);
537unlock:
538 mutex_unlock(&adap->lock);
539}
540EXPORT_SYMBOL_GPL(cec_transmit_done);
541
542/*
543 * Called when waiting for a reply times out.
544 */
545static void cec_wait_timeout(struct work_struct *work)
546{
547 struct cec_data *data = container_of(work, struct cec_data, work.work);
548 struct cec_adapter *adap = data->adap;
549
550 mutex_lock(&adap->lock);
551 /*
552 * Sanity check in case the timeout and the arrival of the message
553 * happened at the same time.
554 */
555 if (list_empty(&data->list))
556 goto unlock;
557
558 /* Mark the message as timed out */
559 list_del_init(&data->list);
560 data->msg.ts = ktime_get_ns();
561 data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
562 cec_data_completed(data);
563unlock:
564 mutex_unlock(&adap->lock);
565}
566
567/*
568 * Transmit a message. The fh argument may be NULL if the transmit is not
569 * associated with a specific filehandle.
570 *
571 * This function is called with adap->lock held.
572 */
573int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
574 struct cec_fh *fh, bool block)
575{
576 struct cec_data *data;
577 u8 last_initiator = 0xff;
578 unsigned int timeout;
579 int res = 0;
580
581 if (msg->reply && msg->timeout == 0) {
582 /* Make sure the timeout isn't 0. */
583 msg->timeout = 1000;
584 }
585
586 /* Sanity checks */
587 if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) {
588 dprintk(1, "cec_transmit_msg: invalid length %d\n", msg->len);
589 return -EINVAL;
590 }
591 if (msg->timeout && msg->len == 1) {
592 dprintk(1, "cec_transmit_msg: can't reply for poll msg\n");
593 return -EINVAL;
594 }
595 if (msg->len == 1) {
596 if (cec_msg_initiator(msg) != 0xf ||
597 cec_msg_destination(msg) == 0xf) {
598 dprintk(1, "cec_transmit_msg: invalid poll message\n");
599 return -EINVAL;
600 }
601 if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
602 /*
603 * If the destination is a logical address our adapter
604 * has already claimed, then just NACK this.
605 * It depends on the hardware what it will do with a
606 * POLL to itself (some OK this), so it is just as
607 * easy to handle it here so the behavior will be
608 * consistent.
609 */
610 msg->tx_status = CEC_TX_STATUS_NACK |
611 CEC_TX_STATUS_MAX_RETRIES;
612 msg->tx_nack_cnt = 1;
613 return 0;
614 }
615 }
616 if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
617 cec_has_log_addr(adap, cec_msg_destination(msg))) {
618 dprintk(1, "cec_transmit_msg: destination is the adapter itself\n");
619 return -EINVAL;
620 }
621 if (cec_msg_initiator(msg) != 0xf &&
622 !cec_has_log_addr(adap, cec_msg_initiator(msg))) {
623 dprintk(1, "cec_transmit_msg: initiator has unknown logical address %d\n",
624 cec_msg_initiator(msg));
625 return -EINVAL;
626 }
627 if (!adap->is_configured && !adap->is_configuring)
628 return -ENONET;
629
630 data = kzalloc(sizeof(*data), GFP_KERNEL);
631 if (!data)
632 return -ENOMEM;
633
634 if (msg->len > 1 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
635 msg->msg[2] = adap->phys_addr >> 8;
636 msg->msg[3] = adap->phys_addr & 0xff;
637 }
638
639 if (msg->timeout)
640 dprintk(2, "cec_transmit_msg: %*ph (wait for 0x%02x%s)\n",
641 msg->len, msg->msg, msg->reply, !block ? ", nb" : "");
642 else
643 dprintk(2, "cec_transmit_msg: %*ph%s\n",
644 msg->len, msg->msg, !block ? " (nb)" : "");
645
646 msg->rx_status = 0;
647 msg->tx_status = 0;
648 msg->tx_arb_lost_cnt = 0;
649 msg->tx_nack_cnt = 0;
650 msg->tx_low_drive_cnt = 0;
651 msg->tx_error_cnt = 0;
652 data->msg = *msg;
653 data->fh = fh;
654 data->adap = adap;
655 data->blocking = block;
656
657 /*
658 * Determine if this message follows a message from the same
659 * initiator. Needed to determine the free signal time later on.
660 */
661 if (msg->len > 1) {
662 if (!(list_empty(&adap->transmit_queue))) {
663 const struct cec_data *last;
664
665 last = list_last_entry(&adap->transmit_queue,
666 const struct cec_data, list);
667 last_initiator = cec_msg_initiator(&last->msg);
668 } else if (adap->transmitting) {
669 last_initiator =
670 cec_msg_initiator(&adap->transmitting->msg);
671 }
672 }
673 data->new_initiator = last_initiator != cec_msg_initiator(msg);
674 init_completion(&data->c);
675 INIT_DELAYED_WORK(&data->work, cec_wait_timeout);
676
677 data->msg.sequence = adap->sequence++;
678 if (fh)
679 list_add_tail(&data->xfer_list, &fh->xfer_list);
680 list_add_tail(&data->list, &adap->transmit_queue);
681 if (!adap->transmitting)
682 wake_up_interruptible(&adap->kthread_waitq);
683
684 /* All done if we don't need to block waiting for completion */
685 if (!block)
686 return 0;
687
688 /*
689 * If we don't get a completion before this time something is really
690 * wrong and we time out.
691 */
692 timeout = CEC_XFER_TIMEOUT_MS;
693 /* Add the requested timeout if we have to wait for a reply as well */
694 if (msg->timeout)
695 timeout += msg->timeout;
696
697 /*
698 * Release the lock and wait, retake the lock afterwards.
699 */
700 mutex_unlock(&adap->lock);
701 res = wait_for_completion_killable_timeout(&data->c,
702 msecs_to_jiffies(timeout));
703 mutex_lock(&adap->lock);
704
705 if (data->completed) {
706 /* The transmit completed (possibly with an error) */
707 *msg = data->msg;
708 kfree(data);
709 return 0;
710 }
711 /*
712 * The wait for completion timed out or was interrupted, so mark this
713 * as non-blocking and disconnect from the filehandle since it is
714 * still 'in flight'. When it finally completes it will just drop the
715 * result silently.
716 */
717 data->blocking = false;
718 if (data->fh)
719 list_del(&data->xfer_list);
720 data->fh = NULL;
721
722 if (res == 0) { /* timed out */
723 /* Check if the reply or the transmit failed */
724 if (msg->timeout && (msg->tx_status & CEC_TX_STATUS_OK))
725 msg->rx_status = CEC_RX_STATUS_TIMEOUT;
726 else
727 msg->tx_status = CEC_TX_STATUS_MAX_RETRIES;
728 }
729 return res > 0 ? 0 : res;
730}
731
732/* Helper function to be used by drivers and this framework. */
733int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
734 bool block)
735{
736 int ret;
737
738 mutex_lock(&adap->lock);
739 ret = cec_transmit_msg_fh(adap, msg, NULL, block);
740 mutex_unlock(&adap->lock);
741 return ret;
742}
743EXPORT_SYMBOL_GPL(cec_transmit_msg);
744
745/*
746 * I don't like forward references but without this the low-level
747 * cec_received_msg() function would come after a bunch of high-level
748 * CEC protocol handling functions. That was very confusing.
749 */
750static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
751 bool is_reply);
752
753/* Called by the CEC adapter if a message is received */
754void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg)
755{
756 struct cec_data *data;
757 u8 msg_init = cec_msg_initiator(msg);
758 u8 msg_dest = cec_msg_destination(msg);
759 bool is_reply = false;
760 bool valid_la = true;
761
762 mutex_lock(&adap->lock);
763 msg->ts = ktime_get_ns();
764 msg->rx_status = CEC_RX_STATUS_OK;
765 msg->tx_status = 0;
766 msg->sequence = msg->reply = msg->timeout = 0;
767 msg->flags = 0;
768
769 dprintk(2, "cec_received_msg: %*ph\n", msg->len, msg->msg);
770
771 /* Check if this message was for us (directed or broadcast). */
772 if (!cec_msg_is_broadcast(msg))
773 valid_la = cec_has_log_addr(adap, msg_dest);
774
775 /* It's a valid message and not a poll or CDC message */
776 if (valid_la && msg->len > 1 && msg->msg[1] != CEC_MSG_CDC_MESSAGE) {
777 u8 cmd = msg->msg[1];
778 bool abort = cmd == CEC_MSG_FEATURE_ABORT;
779
780 /* The aborted command is in msg[2] */
781 if (abort)
782 cmd = msg->msg[2];
783
784 /*
785 * Walk over all transmitted messages that are waiting for a
786 * reply.
787 */
788 list_for_each_entry(data, &adap->wait_queue, list) {
789 struct cec_msg *dst = &data->msg;
790 u8 dst_reply;
791
792 /* Does the command match? */
793 if ((abort && cmd != dst->msg[1]) ||
794 (!abort && cmd != dst->reply))
795 continue;
796
797 /* Does the addressing match? */
798 if (msg_init != cec_msg_destination(dst) &&
799 !cec_msg_is_broadcast(dst))
800 continue;
801
802 /* We got a reply */
803 msg->sequence = dst->sequence;
804 dst_reply = dst->reply;
805 *dst = *msg;
806 dst->reply = dst_reply;
807 if (abort) {
808 dst->reply = 0;
809 dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT;
810 }
811 /* Remove it from the wait_queue */
812 list_del_init(&data->list);
813
814 /* Cancel the pending timeout work */
815 if (!cancel_delayed_work(&data->work)) {
816 mutex_unlock(&adap->lock);
817 flush_scheduled_work();
818 mutex_lock(&adap->lock);
819 }
820 /*
821 * Mark this as a reply, provided someone is still
822 * waiting for the answer.
823 */
824 if (data->fh)
825 is_reply = true;
826 cec_data_completed(data);
827 break;
828 }
829 }
830 mutex_unlock(&adap->lock);
831
832 /* Pass the message on to any monitoring filehandles */
833 cec_queue_msg_monitor(adap, msg, valid_la);
834
835 /* We're done if it is not for us or a poll message */
836 if (!valid_la || msg->len <= 1)
837 return;
838
839 /*
840 * Process the message on the protocol level. If is_reply is true,
841 * then cec_receive_notify() won't pass on the reply to the listener(s)
842 * since that was already done by cec_data_completed() above.
843 */
844 cec_receive_notify(adap, msg, is_reply);
845}
846EXPORT_SYMBOL_GPL(cec_received_msg);
847
848/* Logical Address Handling */
849
850/*
851 * Attempt to claim a specific logical address.
852 *
853 * This function is called with adap->lock held.
854 */
855static int cec_config_log_addr(struct cec_adapter *adap,
856 unsigned int idx,
857 unsigned int log_addr)
858{
859 struct cec_log_addrs *las = &adap->log_addrs;
860 struct cec_msg msg = { };
861 int err;
862
863 if (cec_has_log_addr(adap, log_addr))
864 return 0;
865
866 /* Send poll message */
867 msg.len = 1;
868 msg.msg[0] = 0xf0 | log_addr;
869 err = cec_transmit_msg_fh(adap, &msg, NULL, true);
870
871 /*
872 * While trying to poll the physical address was reset
873 * and the adapter was unconfigured, so bail out.
874 */
875 if (!adap->is_configuring)
876 return -EINTR;
877
878 if (err)
879 return err;
880
881 if (msg.tx_status & CEC_TX_STATUS_OK)
882 return 0;
883
884 /*
885 * Message not acknowledged, so this logical
886 * address is free to use.
887 */
888 err = adap->ops->adap_log_addr(adap, log_addr);
889 if (err)
890 return err;
891
892 las->log_addr[idx] = log_addr;
893 las->log_addr_mask |= 1 << log_addr;
894 adap->phys_addrs[log_addr] = adap->phys_addr;
895
896 dprintk(2, "claimed addr %d (%d)\n", log_addr,
897 las->primary_device_type[idx]);
898 return 1;
899}
900
901/*
902 * Unconfigure the adapter: clear all logical addresses and send
903 * the state changed event.
904 *
905 * This function is called with adap->lock held.
906 */
907static void cec_adap_unconfigure(struct cec_adapter *adap)
908{
909 WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
910 adap->log_addrs.log_addr_mask = 0;
911 adap->is_configuring = false;
912 adap->is_configured = false;
913 memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
914 wake_up_interruptible(&adap->kthread_waitq);
915 cec_post_state_event(adap);
916}
917
918/*
919 * Attempt to claim the required logical addresses.
920 */
921static int cec_config_thread_func(void *arg)
922{
923 /* The various LAs for each type of device */
924 static const u8 tv_log_addrs[] = {
925 CEC_LOG_ADDR_TV, CEC_LOG_ADDR_SPECIFIC,
926 CEC_LOG_ADDR_INVALID
927 };
928 static const u8 record_log_addrs[] = {
929 CEC_LOG_ADDR_RECORD_1, CEC_LOG_ADDR_RECORD_2,
930 CEC_LOG_ADDR_RECORD_3,
931 CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
932 CEC_LOG_ADDR_INVALID
933 };
934 static const u8 tuner_log_addrs[] = {
935 CEC_LOG_ADDR_TUNER_1, CEC_LOG_ADDR_TUNER_2,
936 CEC_LOG_ADDR_TUNER_3, CEC_LOG_ADDR_TUNER_4,
937 CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
938 CEC_LOG_ADDR_INVALID
939 };
940 static const u8 playback_log_addrs[] = {
941 CEC_LOG_ADDR_PLAYBACK_1, CEC_LOG_ADDR_PLAYBACK_2,
942 CEC_LOG_ADDR_PLAYBACK_3,
943 CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
944 CEC_LOG_ADDR_INVALID
945 };
946 static const u8 audiosystem_log_addrs[] = {
947 CEC_LOG_ADDR_AUDIOSYSTEM,
948 CEC_LOG_ADDR_INVALID
949 };
950 static const u8 specific_use_log_addrs[] = {
951 CEC_LOG_ADDR_SPECIFIC,
952 CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
953 CEC_LOG_ADDR_INVALID
954 };
955 static const u8 *type2addrs[6] = {
956 [CEC_LOG_ADDR_TYPE_TV] = tv_log_addrs,
957 [CEC_LOG_ADDR_TYPE_RECORD] = record_log_addrs,
958 [CEC_LOG_ADDR_TYPE_TUNER] = tuner_log_addrs,
959 [CEC_LOG_ADDR_TYPE_PLAYBACK] = playback_log_addrs,
960 [CEC_LOG_ADDR_TYPE_AUDIOSYSTEM] = audiosystem_log_addrs,
961 [CEC_LOG_ADDR_TYPE_SPECIFIC] = specific_use_log_addrs,
962 };
963 static const u16 type2mask[] = {
964 [CEC_LOG_ADDR_TYPE_TV] = CEC_LOG_ADDR_MASK_TV,
965 [CEC_LOG_ADDR_TYPE_RECORD] = CEC_LOG_ADDR_MASK_RECORD,
966 [CEC_LOG_ADDR_TYPE_TUNER] = CEC_LOG_ADDR_MASK_TUNER,
967 [CEC_LOG_ADDR_TYPE_PLAYBACK] = CEC_LOG_ADDR_MASK_PLAYBACK,
968 [CEC_LOG_ADDR_TYPE_AUDIOSYSTEM] = CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
969 [CEC_LOG_ADDR_TYPE_SPECIFIC] = CEC_LOG_ADDR_MASK_SPECIFIC,
970 };
971 struct cec_adapter *adap = arg;
972 struct cec_log_addrs *las = &adap->log_addrs;
973 int err;
974 int i, j;
975
976 mutex_lock(&adap->lock);
977 dprintk(1, "physical address: %x.%x.%x.%x, claim %d logical addresses\n",
978 cec_phys_addr_exp(adap->phys_addr), las->num_log_addrs);
979 las->log_addr_mask = 0;
980
981 if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED)
982 goto configured;
983
984 for (i = 0; i < las->num_log_addrs; i++) {
985 unsigned int type = las->log_addr_type[i];
986 const u8 *la_list;
987 u8 last_la;
988
989 /*
990 * The TV functionality can only map to physical address 0.
991 * For any other address, try the Specific functionality
992 * instead as per the spec.
993 */
994 if (adap->phys_addr && type == CEC_LOG_ADDR_TYPE_TV)
995 type = CEC_LOG_ADDR_TYPE_SPECIFIC;
996
997 la_list = type2addrs[type];
998 last_la = las->log_addr[i];
999 las->log_addr[i] = CEC_LOG_ADDR_INVALID;
1000 if (last_la == CEC_LOG_ADDR_INVALID ||
1001 last_la == CEC_LOG_ADDR_UNREGISTERED ||
1002 !(last_la & type2mask[type]))
1003 last_la = la_list[0];
1004
1005 err = cec_config_log_addr(adap, i, last_la);
1006 if (err > 0) /* Reused last LA */
1007 continue;
1008
1009 if (err < 0)
1010 goto unconfigure;
1011
1012 for (j = 0; la_list[j] != CEC_LOG_ADDR_INVALID; j++) {
1013 /* Tried this one already, skip it */
1014 if (la_list[j] == last_la)
1015 continue;
1016 /* The backup addresses are CEC 2.0 specific */
1017 if ((la_list[j] == CEC_LOG_ADDR_BACKUP_1 ||
1018 la_list[j] == CEC_LOG_ADDR_BACKUP_2) &&
1019 las->cec_version < CEC_OP_CEC_VERSION_2_0)
1020 continue;
1021
1022 err = cec_config_log_addr(adap, i, la_list[j]);
1023 if (err == 0) /* LA is in use */
1024 continue;
1025 if (err < 0)
1026 goto unconfigure;
1027 /* Done, claimed an LA */
1028 break;
1029 }
1030
1031 if (la_list[j] == CEC_LOG_ADDR_INVALID)
1032 dprintk(1, "could not claim LA %d\n", i);
1033 }
1034
1035configured:
1036 if (adap->log_addrs.log_addr_mask == 0) {
1037 /* Fall back to unregistered */
1038 las->log_addr[0] = CEC_LOG_ADDR_UNREGISTERED;
1039 las->log_addr_mask = 1 << las->log_addr[0];
1040 }
1041 adap->is_configured = true;
1042 adap->is_configuring = false;
1043 cec_post_state_event(adap);
1044 mutex_unlock(&adap->lock);
1045
1046 for (i = 0; i < las->num_log_addrs; i++) {
1047 if (las->log_addr[i] == CEC_LOG_ADDR_INVALID)
1048 continue;
1049
1050 /*
1051 * Report Features must come first according
1052 * to CEC 2.0
1053 */
1054 if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED)
1055 cec_report_features(adap, i);
1056 cec_report_phys_addr(adap, i);
1057 }
1058 mutex_lock(&adap->lock);
1059 adap->kthread_config = NULL;
1060 mutex_unlock(&adap->lock);
1061 complete(&adap->config_completion);
1062 return 0;
1063
1064unconfigure:
1065 for (i = 0; i < las->num_log_addrs; i++)
1066 las->log_addr[i] = CEC_LOG_ADDR_INVALID;
1067 cec_adap_unconfigure(adap);
1068 adap->kthread_config = NULL;
1069 mutex_unlock(&adap->lock);
1070 complete(&adap->config_completion);
1071 return 0;
1072}
1073
1074/*
1075 * Called from either __cec_s_phys_addr or __cec_s_log_addrs to claim the
1076 * logical addresses.
1077 *
1078 * This function is called with adap->lock held.
1079 */
1080static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
1081{
1082 if (WARN_ON(adap->is_configuring || adap->is_configured))
1083 return;
1084
1085 init_completion(&adap->config_completion);
1086
1087 /* Ready to kick off the thread */
1088 adap->is_configuring = true;
1089 adap->kthread_config = kthread_run(cec_config_thread_func, adap,
1090 "ceccfg-%s", adap->name);
1091 if (IS_ERR(adap->kthread_config)) {
1092 adap->kthread_config = NULL;
1093 } else if (block) {
1094 mutex_unlock(&adap->lock);
1095 wait_for_completion(&adap->config_completion);
1096 mutex_lock(&adap->lock);
1097 }
1098}
1099
1100/* Set a new physical address and send an event notifying userspace of this.
1101 *
1102 * This function is called with adap->lock held.
1103 */
1104void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
1105{
1106 if (phys_addr == adap->phys_addr)
1107 return;
1108
1109 if (phys_addr == CEC_PHYS_ADDR_INVALID ||
1110 adap->phys_addr != CEC_PHYS_ADDR_INVALID) {
1111 adap->phys_addr = CEC_PHYS_ADDR_INVALID;
1112 cec_post_state_event(adap);
1113 cec_adap_unconfigure(adap);
1114 /* Disabling monitor all mode should always succeed */
1115 if (adap->monitor_all_cnt)
1116 WARN_ON(call_op(adap, adap_monitor_all_enable, false));
1117 WARN_ON(adap->ops->adap_enable(adap, false));
1118 if (phys_addr == CEC_PHYS_ADDR_INVALID)
1119 return;
1120 }
1121
1122 if (adap->ops->adap_enable(adap, true))
1123 return;
1124
1125 if (adap->monitor_all_cnt &&
1126 call_op(adap, adap_monitor_all_enable, true)) {
1127 WARN_ON(adap->ops->adap_enable(adap, false));
1128 return;
1129 }
1130 adap->phys_addr = phys_addr;
1131 cec_post_state_event(adap);
1132 if (adap->log_addrs.num_log_addrs)
1133 cec_claim_log_addrs(adap, block);
1134}
1135
1136void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
1137{
1138 if (IS_ERR_OR_NULL(adap))
1139 return;
1140
1141 if (WARN_ON(adap->capabilities & CEC_CAP_PHYS_ADDR))
1142 return;
1143 mutex_lock(&adap->lock);
1144 __cec_s_phys_addr(adap, phys_addr, block);
1145 mutex_unlock(&adap->lock);
1146}
1147EXPORT_SYMBOL_GPL(cec_s_phys_addr);
1148
1149/*
1150 * Called from either the ioctl or a driver to set the logical addresses.
1151 *
1152 * This function is called with adap->lock held.
1153 */
1154int __cec_s_log_addrs(struct cec_adapter *adap,
1155 struct cec_log_addrs *log_addrs, bool block)
1156{
1157 u16 type_mask = 0;
1158 int i;
1159
1160 if (!log_addrs || log_addrs->num_log_addrs == 0) {
1161 adap->log_addrs.num_log_addrs = 0;
1162 cec_adap_unconfigure(adap);
1163 return 0;
1164 }
1165
1166 /* Ensure the osd name is 0-terminated */
1167 log_addrs->osd_name[sizeof(log_addrs->osd_name) - 1] = '\0';
1168
1169 /* Sanity checks */
1170 if (log_addrs->num_log_addrs > adap->available_log_addrs) {
1171 dprintk(1, "num_log_addrs > %d\n", adap->available_log_addrs);
1172 return -EINVAL;
1173 }
1174
1175 /*
1176 * Vendor ID is a 24 bit number, so check if the value is
1177 * within the correct range.
1178 */
1179 if (log_addrs->vendor_id != CEC_VENDOR_ID_NONE &&
1180 (log_addrs->vendor_id & 0xff000000) != 0)
1181 return -EINVAL;
1182
1183 if (log_addrs->cec_version != CEC_OP_CEC_VERSION_1_4 &&
1184 log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0)
1185 return -EINVAL;
1186
1187 if (log_addrs->num_log_addrs > 1)
1188 for (i = 0; i < log_addrs->num_log_addrs; i++)
1189 if (log_addrs->log_addr_type[i] ==
1190 CEC_LOG_ADDR_TYPE_UNREGISTERED) {
1191 dprintk(1, "num_log_addrs > 1 can't be combined with unregistered LA\n");
1192 return -EINVAL;
1193 }
1194
1195 if (log_addrs->cec_version < CEC_OP_CEC_VERSION_2_0) {
1196 memset(log_addrs->all_device_types, 0,
1197 sizeof(log_addrs->all_device_types));
1198 memset(log_addrs->features, 0, sizeof(log_addrs->features));
1199 }
1200
1201 for (i = 0; i < log_addrs->num_log_addrs; i++) {
1202 u8 *features = log_addrs->features[i];
1203 bool op_is_dev_features = false;
1204
1205 log_addrs->log_addr[i] = CEC_LOG_ADDR_INVALID;
1206 if (type_mask & (1 << log_addrs->log_addr_type[i])) {
1207 dprintk(1, "duplicate logical address type\n");
1208 return -EINVAL;
1209 }
1210 type_mask |= 1 << log_addrs->log_addr_type[i];
1211 if ((type_mask & (1 << CEC_LOG_ADDR_TYPE_RECORD)) &&
1212 (type_mask & (1 << CEC_LOG_ADDR_TYPE_PLAYBACK))) {
1213 /* Record already contains the playback functionality */
1214 dprintk(1, "invalid record + playback combination\n");
1215 return -EINVAL;
1216 }
1217 if (log_addrs->primary_device_type[i] >
1218 CEC_OP_PRIM_DEVTYPE_PROCESSOR) {
1219 dprintk(1, "unknown primary device type\n");
1220 return -EINVAL;
1221 }
1222 if (log_addrs->primary_device_type[i] == 2) {
1223 dprintk(1, "invalid primary device type\n");
1224 return -EINVAL;
1225 }
1226 if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
1227 dprintk(1, "unknown logical address type\n");
1228 return -EINVAL;
1229 }
1230 if (log_addrs->cec_version < CEC_OP_CEC_VERSION_2_0)
1231 continue;
1232
1233 for (i = 0; i < ARRAY_SIZE(log_addrs->features[0]); i++) {
1234 if ((features[i] & 0x80) == 0) {
1235 if (op_is_dev_features)
1236 break;
1237 op_is_dev_features = true;
1238 }
1239 }
1240 if (!op_is_dev_features ||
1241 i == ARRAY_SIZE(log_addrs->features[0])) {
1242 dprintk(1, "malformed features\n");
1243 return -EINVAL;
1244 }
1245 }
1246
1247 if (log_addrs->cec_version >= CEC_OP_CEC_VERSION_2_0) {
1248 if (log_addrs->num_log_addrs > 2) {
1249 dprintk(1, "CEC 2.0 allows no more than 2 logical addresses\n");
1250 return -EINVAL;
1251 }
1252 if (log_addrs->num_log_addrs == 2) {
1253 if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_AUDIOSYSTEM) |
1254 (1 << CEC_LOG_ADDR_TYPE_TV)))) {
1255 dprintk(1, "Two LAs is only allowed for audiosystem and TV\n");
1256 return -EINVAL;
1257 }
1258 if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_PLAYBACK) |
1259 (1 << CEC_LOG_ADDR_TYPE_RECORD)))) {
1260 dprintk(1, "An audiosystem/TV can only be combined with record or playback\n");
1261 return -EINVAL;
1262 }
1263 }
1264 }
1265
1266 log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
1267 adap->log_addrs = *log_addrs;
1268 if (adap->phys_addr != CEC_PHYS_ADDR_INVALID)
1269 cec_claim_log_addrs(adap, block);
1270 return 0;
1271}
1272
1273int cec_s_log_addrs(struct cec_adapter *adap,
1274 struct cec_log_addrs *log_addrs, bool block)
1275{
1276 int err;
1277
1278 if (WARN_ON(adap->capabilities & CEC_CAP_LOG_ADDRS))
1279 return -EINVAL;
1280 mutex_lock(&adap->lock);
1281 err = __cec_s_log_addrs(adap, log_addrs, block);
1282 mutex_unlock(&adap->lock);
1283 return err;
1284}
1285EXPORT_SYMBOL_GPL(cec_s_log_addrs);
1286
1287/* High-level core CEC message handling */
1288
1289/* Transmit the Report Features message */
1290static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx)
1291{
1292 struct cec_msg msg = { };
1293 const struct cec_log_addrs *las = &adap->log_addrs;
1294 const u8 *features = las->features[la_idx];
1295 bool op_is_dev_features = false;
1296 unsigned int idx;
1297
1298 /* This is 2.0 and up only */
1299 if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0)
1300 return 0;
1301
1302 /* Report Features */
1303 msg.msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
1304 msg.len = 4;
1305 msg.msg[1] = CEC_MSG_REPORT_FEATURES;
1306 msg.msg[2] = adap->log_addrs.cec_version;
1307 msg.msg[3] = las->all_device_types[la_idx];
1308
1309 /* Write RC Profiles first, then Device Features */
1310 for (idx = 0; idx < ARRAY_SIZE(las->features[0]); idx++) {
1311 msg.msg[msg.len++] = features[idx];
1312 if ((features[idx] & CEC_OP_FEAT_EXT) == 0) {
1313 if (op_is_dev_features)
1314 break;
1315 op_is_dev_features = true;
1316 }
1317 }
1318 return cec_transmit_msg(adap, &msg, false);
1319}
1320
1321/* Transmit the Report Physical Address message */
1322static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx)
1323{
1324 const struct cec_log_addrs *las = &adap->log_addrs;
1325 struct cec_msg msg = { };
1326
1327 /* Report Physical Address */
1328 msg.msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
1329 cec_msg_report_physical_addr(&msg, adap->phys_addr,
1330 las->primary_device_type[la_idx]);
1331 dprintk(2, "config: la %d pa %x.%x.%x.%x\n",
1332 las->log_addr[la_idx],
1333 cec_phys_addr_exp(adap->phys_addr));
1334 return cec_transmit_msg(adap, &msg, false);
1335}
1336
1337/* Transmit the Feature Abort message */
1338static int cec_feature_abort_reason(struct cec_adapter *adap,
1339 struct cec_msg *msg, u8 reason)
1340{
1341 struct cec_msg tx_msg = { };
1342
1343 /*
1344 * Don't reply with CEC_MSG_FEATURE_ABORT to a CEC_MSG_FEATURE_ABORT
1345 * message!
1346 */
1347 if (msg->msg[1] == CEC_MSG_FEATURE_ABORT)
1348 return 0;
1349 cec_msg_set_reply_to(&tx_msg, msg);
1350 cec_msg_feature_abort(&tx_msg, msg->msg[1], reason);
1351 return cec_transmit_msg(adap, &tx_msg, false);
1352}
1353
1354static int cec_feature_abort(struct cec_adapter *adap, struct cec_msg *msg)
1355{
1356 return cec_feature_abort_reason(adap, msg,
1357 CEC_OP_ABORT_UNRECOGNIZED_OP);
1358}
1359
1360static int cec_feature_refused(struct cec_adapter *adap, struct cec_msg *msg)
1361{
1362 return cec_feature_abort_reason(adap, msg,
1363 CEC_OP_ABORT_REFUSED);
1364}
1365
1366/*
1367 * Called when a CEC message is received. This function will do any
1368 * necessary core processing. The is_reply bool is true if this message
1369 * is a reply to an earlier transmit.
1370 *
1371 * The message is either a broadcast message or a valid directed message.
1372 */
1373static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
1374 bool is_reply)
1375{
1376 bool is_broadcast = cec_msg_is_broadcast(msg);
1377 u8 dest_laddr = cec_msg_destination(msg);
1378 u8 init_laddr = cec_msg_initiator(msg);
1379 u8 devtype = cec_log_addr2dev(adap, dest_laddr);
1380 int la_idx = cec_log_addr2idx(adap, dest_laddr);
1381 bool is_directed = la_idx >= 0;
1382 bool from_unregistered = init_laddr == 0xf;
1383 struct cec_msg tx_cec_msg = { };
1384
1385 dprintk(1, "cec_receive_notify: %*ph\n", msg->len, msg->msg);
1386
1387 if (adap->ops->received) {
1388 /* Allow drivers to process the message first */
1389 if (adap->ops->received(adap, msg) != -ENOMSG)
1390 return 0;
1391 }
1392
1393 /*
1394 * REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
1395 * CEC_MSG_USER_CONTROL_RELEASED messages always have to be
1396 * handled by the CEC core, even if the passthrough mode is on.
1397 * The others are just ignored if passthrough mode is on.
1398 */
1399 switch (msg->msg[1]) {
1400 case CEC_MSG_GET_CEC_VERSION:
1401 case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
1402 case CEC_MSG_ABORT:
1403 case CEC_MSG_GIVE_DEVICE_POWER_STATUS:
1404 case CEC_MSG_GIVE_PHYSICAL_ADDR:
1405 case CEC_MSG_GIVE_OSD_NAME:
1406 case CEC_MSG_GIVE_FEATURES:
1407 /*
1408 * Skip processing these messages if the passthrough mode
1409 * is on.
1410 */
1411 if (adap->passthrough)
1412 goto skip_processing;
1413 /* Ignore if addressing is wrong */
1414 if (is_broadcast || from_unregistered)
1415 return 0;
1416 break;
1417
1418 case CEC_MSG_USER_CONTROL_PRESSED:
1419 case CEC_MSG_USER_CONTROL_RELEASED:
1420 /* Wrong addressing mode: don't process */
1421 if (is_broadcast || from_unregistered)
1422 goto skip_processing;
1423 break;
1424
1425 case CEC_MSG_REPORT_PHYSICAL_ADDR:
1426 /*
1427 * This message is always processed, regardless of the
1428 * passthrough setting.
1429 *
1430 * Exception: don't process if wrong addressing mode.
1431 */
1432 if (!is_broadcast)
1433 goto skip_processing;
1434 break;
1435
1436 default:
1437 break;
1438 }
1439
1440 cec_msg_set_reply_to(&tx_cec_msg, msg);
1441
1442 switch (msg->msg[1]) {
1443 /* The following messages are processed but still passed through */
1444 case CEC_MSG_REPORT_PHYSICAL_ADDR:
1445 adap->phys_addrs[init_laddr] =
1446 (msg->msg[2] << 8) | msg->msg[3];
1447 dprintk(1, "Reported physical address %04x for logical address %d\n",
1448 adap->phys_addrs[init_laddr], init_laddr);
1449 break;
1450
1451 case CEC_MSG_USER_CONTROL_PRESSED:
1452 if (!(adap->capabilities & CEC_CAP_RC))
1453 break;
1454
1455#if IS_ENABLED(CONFIG_RC_CORE)
1456 switch (msg->msg[2]) {
1457 /*
1458 * Play function, this message can have variable length
1459 * depending on the specific play function that is used.
1460 */
1461 case 0x60:
1462 if (msg->len == 2)
1463 rc_keydown(adap->rc, RC_TYPE_CEC,
1464 msg->msg[2], 0);
1465 else
1466 rc_keydown(adap->rc, RC_TYPE_CEC,
1467 msg->msg[2] << 8 | msg->msg[3], 0);
1468 break;
1469 /*
1470 * Other function messages that are not handled.
1471 * Currently the RC framework does not allow to supply an
1472 * additional parameter to a keypress. These "keys" contain
1473 * other information such as channel number, an input number
1474 * etc.
1475 * For the time being these messages are not processed by the
1476 * framework and are simply forwarded to the user space.
1477 */
1478 case 0x56: case 0x57:
1479 case 0x67: case 0x68: case 0x69: case 0x6a:
1480 break;
1481 default:
1482 rc_keydown(adap->rc, RC_TYPE_CEC, msg->msg[2], 0);
1483 break;
1484 }
1485#endif
1486 break;
1487
1488 case CEC_MSG_USER_CONTROL_RELEASED:
1489 if (!(adap->capabilities & CEC_CAP_RC))
1490 break;
1491#if IS_ENABLED(CONFIG_RC_CORE)
1492 rc_keyup(adap->rc);
1493#endif
1494 break;
1495
1496 /*
1497 * The remaining messages are only processed if the passthrough mode
1498 * is off.
1499 */
1500 case CEC_MSG_GET_CEC_VERSION:
1501 cec_msg_cec_version(&tx_cec_msg, adap->log_addrs.cec_version);
1502 return cec_transmit_msg(adap, &tx_cec_msg, false);
1503
1504 case CEC_MSG_GIVE_PHYSICAL_ADDR:
1505 /* Do nothing for CEC switches using addr 15 */
1506 if (devtype == CEC_OP_PRIM_DEVTYPE_SWITCH && dest_laddr == 15)
1507 return 0;
1508 cec_msg_report_physical_addr(&tx_cec_msg, adap->phys_addr, devtype);
1509 return cec_transmit_msg(adap, &tx_cec_msg, false);
1510
1511 case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
1512 if (adap->log_addrs.vendor_id == CEC_VENDOR_ID_NONE)
1513 return cec_feature_abort(adap, msg);
1514 cec_msg_device_vendor_id(&tx_cec_msg, adap->log_addrs.vendor_id);
1515 return cec_transmit_msg(adap, &tx_cec_msg, false);
1516
1517 case CEC_MSG_ABORT:
1518 /* Do nothing for CEC switches */
1519 if (devtype == CEC_OP_PRIM_DEVTYPE_SWITCH)
1520 return 0;
1521 return cec_feature_refused(adap, msg);
1522
1523 case CEC_MSG_GIVE_OSD_NAME: {
1524 if (adap->log_addrs.osd_name[0] == 0)
1525 return cec_feature_abort(adap, msg);
1526 cec_msg_set_osd_name(&tx_cec_msg, adap->log_addrs.osd_name);
1527 return cec_transmit_msg(adap, &tx_cec_msg, false);
1528 }
1529
1530 case CEC_MSG_GIVE_FEATURES:
1531 if (adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0)
1532 return cec_report_features(adap, la_idx);
1533 return 0;
1534
1535 default:
1536 /*
1537 * Unprocessed messages are aborted if userspace isn't doing
1538 * any processing either.
1539 */
1540 if (is_directed && !is_reply && !adap->follower_cnt &&
1541 !adap->cec_follower && msg->msg[1] != CEC_MSG_FEATURE_ABORT)
1542 return cec_feature_abort(adap, msg);
1543 break;
1544 }
1545
1546skip_processing:
1547 /* If this was a reply, then we're done */
1548 if (is_reply)
1549 return 0;
1550
1551 /*
1552 * Send to the exclusive follower if there is one, otherwise send
1553 * to all followers.
1554 */
1555 if (adap->cec_follower)
1556 cec_queue_msg_fh(adap->cec_follower, msg);
1557 else
1558 cec_queue_msg_followers(adap, msg);
1559 return 0;
1560}
1561
1562/*
1563 * Helper functions to keep track of the 'monitor all' use count.
1564 *
1565 * These functions are called with adap->lock held.
1566 */
1567int cec_monitor_all_cnt_inc(struct cec_adapter *adap)
1568{
1569 int ret = 0;
1570
1571 if (adap->monitor_all_cnt == 0)
1572 ret = call_op(adap, adap_monitor_all_enable, 1);
1573 if (ret == 0)
1574 adap->monitor_all_cnt++;
1575 return ret;
1576}
1577
1578void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
1579{
1580 adap->monitor_all_cnt--;
1581 if (adap->monitor_all_cnt == 0)
1582 WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
1583}
1584
1585#ifdef CONFIG_MEDIA_CEC_DEBUG
1586/*
1587 * Log the current state of the CEC adapter.
1588 * Very useful for debugging.
1589 */
1590int cec_adap_status(struct seq_file *file, void *priv)
1591{
1592 struct cec_adapter *adap = dev_get_drvdata(file->private);
1593 struct cec_data *data;
1594
1595 mutex_lock(&adap->lock);
1596 seq_printf(file, "configured: %d\n", adap->is_configured);
1597 seq_printf(file, "configuring: %d\n", adap->is_configuring);
1598 seq_printf(file, "phys_addr: %x.%x.%x.%x\n",
1599 cec_phys_addr_exp(adap->phys_addr));
1600 seq_printf(file, "number of LAs: %d\n", adap->log_addrs.num_log_addrs);
1601 seq_printf(file, "LA mask: 0x%04x\n", adap->log_addrs.log_addr_mask);
1602 if (adap->cec_follower)
1603 seq_printf(file, "has CEC follower%s\n",
1604 adap->passthrough ? " (in passthrough mode)" : "");
1605 if (adap->cec_initiator)
1606 seq_puts(file, "has CEC initiator\n");
1607 if (adap->monitor_all_cnt)
1608 seq_printf(file, "file handles in Monitor All mode: %u\n",
1609 adap->monitor_all_cnt);
1610 data = adap->transmitting;
1611 if (data)
1612 seq_printf(file, "transmitting message: %*ph (reply: %02x)\n",
1613 data->msg.len, data->msg.msg, data->msg.reply);
1614 list_for_each_entry(data, &adap->transmit_queue, list) {
1615 seq_printf(file, "queued tx message: %*ph (reply: %02x)\n",
1616 data->msg.len, data->msg.msg, data->msg.reply);
1617 }
1618 list_for_each_entry(data, &adap->wait_queue, list) {
1619 seq_printf(file, "message waiting for reply: %*ph (reply: %02x)\n",
1620 data->msg.len, data->msg.msg, data->msg.reply);
1621 }
1622
1623 call_void_op(adap, adap_status, file);
1624 mutex_unlock(&adap->lock);
1625 return 0;
1626}
1627#endif
drivers/staging/media/cec/cec-api.c+578−0
@@ -0,0 +1,578 @@
1/*
2 * cec-api.c - HDMI Consumer Electronics Control framework - API
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/kmod.h>
25#include <linux/ktime.h>
26#include <linux/slab.h>
27#include <linux/mm.h>
28#include <linux/string.h>
29#include <linux/types.h>
30#include <linux/uaccess.h>
31#include <linux/version.h>
32
33#include "cec-priv.h"
34
35static inline struct cec_devnode *cec_devnode_data(struct file *filp)
36{
37 struct cec_fh *fh = filp->private_data;
38
39 return &fh->adap->devnode;
40}
41
42/* CEC file operations */
43
44static unsigned int cec_poll(struct file *filp,
45 struct poll_table_struct *poll)
46{
47 struct cec_devnode *devnode = cec_devnode_data(filp);
48 struct cec_fh *fh = filp->private_data;
49 struct cec_adapter *adap = fh->adap;
50 unsigned int res = 0;
51
52 if (!devnode->registered)
53 return POLLERR | POLLHUP;
54 mutex_lock(&adap->lock);
55 if (adap->is_configured)
56 res |= POLLOUT | POLLWRNORM;
57 if (fh->queued_msgs)
58 res |= POLLIN | POLLRDNORM;
59 if (fh->pending_events)
60 res |= POLLPRI;
61 poll_wait(filp, &fh->wait, poll);
62 mutex_unlock(&adap->lock);
63 return res;
64}
65
66static bool cec_is_busy(const struct cec_adapter *adap,
67 const struct cec_fh *fh)
68{
69 bool valid_initiator = adap->cec_initiator && adap->cec_initiator == fh;
70 bool valid_follower = adap->cec_follower && adap->cec_follower == fh;
71
72 /*
73 * Exclusive initiators and followers can always access the CEC adapter
74 */
75 if (valid_initiator || valid_follower)
76 return false;
77 /*
78 * All others can only access the CEC adapter if there is no
79 * exclusive initiator and they are in INITIATOR mode.
80 */
81 return adap->cec_initiator ||
82 fh->mode_initiator == CEC_MODE_NO_INITIATOR;
83}
84
85static long cec_adap_g_caps(struct cec_adapter *adap,
86 struct cec_caps __user *parg)
87{
88 struct cec_caps caps = {};
89
90 strlcpy(caps.driver, adap->devnode.parent->driver->name,
91 sizeof(caps.driver));
92 strlcpy(caps.name, adap->name, sizeof(caps.name));
93 caps.available_log_addrs = adap->available_log_addrs;
94 caps.capabilities = adap->capabilities;
95 caps.version = LINUX_VERSION_CODE;
96 if (copy_to_user(parg, &caps, sizeof(caps)))
97 return -EFAULT;
98 return 0;
99}
100
101static long cec_adap_g_phys_addr(struct cec_adapter *adap,
102 __u16 __user *parg)
103{
104 u16 phys_addr;
105
106 mutex_lock(&adap->lock);
107 phys_addr = adap->phys_addr;
108 mutex_unlock(&adap->lock);
109 if (copy_to_user(parg, &phys_addr, sizeof(phys_addr)))
110 return -EFAULT;
111 return 0;
112}
113
114static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh,
115 bool block, __u16 __user *parg)
116{
117 u16 phys_addr;
118 long err;
119
120 if (!(adap->capabilities & CEC_CAP_PHYS_ADDR))
121 return -ENOTTY;
122 if (copy_from_user(&phys_addr, parg, sizeof(phys_addr)))
123 return -EFAULT;
124
125 err = cec_phys_addr_validate(phys_addr, NULL, NULL);
126 if (err)
127 return err;
128 mutex_lock(&adap->lock);
129 if (cec_is_busy(adap, fh))
130 err = -EBUSY;
131 else
132 __cec_s_phys_addr(adap, phys_addr, block);
133 mutex_unlock(&adap->lock);
134 return err;
135}
136
137static long cec_adap_g_log_addrs(struct cec_adapter *adap,
138 struct cec_log_addrs __user *parg)
139{
140 struct cec_log_addrs log_addrs;
141
142 mutex_lock(&adap->lock);
143 log_addrs = adap->log_addrs;
144 if (!adap->is_configured)
145 memset(log_addrs.log_addr, CEC_LOG_ADDR_INVALID,
146 sizeof(log_addrs.log_addr));
147 mutex_unlock(&adap->lock);
148
149 if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
150 return -EFAULT;
151 return 0;
152}
153
154static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh,
155 bool block, struct cec_log_addrs __user *parg)
156{
157 struct cec_log_addrs log_addrs;
158 long err = -EBUSY;
159
160 if (!(adap->capabilities & CEC_CAP_LOG_ADDRS))
161 return -ENOTTY;
162 if (copy_from_user(&log_addrs, parg, sizeof(log_addrs)))
163 return -EFAULT;
164 log_addrs.flags = 0;
165 mutex_lock(&adap->lock);
166 if (!adap->is_configuring &&
167 (!log_addrs.num_log_addrs || !adap->is_configured) &&
168 !cec_is_busy(adap, fh)) {
169 err = __cec_s_log_addrs(adap, &log_addrs, block);
170 if (!err)
171 log_addrs = adap->log_addrs;
172 }
173 mutex_unlock(&adap->lock);
174 if (err)
175 return err;
176 if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
177 return -EFAULT;
178 return 0;
179}
180
181static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
182 bool block, struct cec_msg __user *parg)
183{
184 struct cec_msg msg = {};
185 long err = 0;
186
187 if (!(adap->capabilities & CEC_CAP_TRANSMIT))
188 return -ENOTTY;
189 if (copy_from_user(&msg, parg, sizeof(msg)))
190 return -EFAULT;
191 mutex_lock(&adap->lock);
192 if (!adap->is_configured) {
193 err = -ENONET;
194 } else if (cec_is_busy(adap, fh)) {
195 err = -EBUSY;
196 } else {
197 if (!block || !msg.reply)
198 fh = NULL;
199 err = cec_transmit_msg_fh(adap, &msg, fh, block);
200 }
201 mutex_unlock(&adap->lock);
202 if (err)
203 return err;
204 if (copy_to_user(parg, &msg, sizeof(msg)))
205 return -EFAULT;
206 return 0;
207}
208
209/* Called by CEC_RECEIVE: wait for a message to arrive */
210static int cec_receive_msg(struct cec_fh *fh, struct cec_msg *msg, bool block)
211{
212 int res;
213
214 do {
215 mutex_lock(&fh->lock);
216 /* Are there received messages queued up? */
217 if (fh->queued_msgs) {
218 /* Yes, return the first one */
219 struct cec_msg_entry *entry =
220 list_first_entry(&fh->msgs,
221 struct cec_msg_entry, list);
222
223 list_del(&entry->list);
224 *msg = entry->msg;
225 kfree(entry);
226 fh->queued_msgs--;
227 mutex_unlock(&fh->lock);
228 return 0;
229 }
230
231 /* No, return EAGAIN in non-blocking mode or wait */
232 mutex_unlock(&fh->lock);
233
234 /* Return when in non-blocking mode */
235 if (!block)
236 return -EAGAIN;
237
238 if (msg->timeout) {
239 /* The user specified a timeout */
240 res = wait_event_interruptible_timeout(fh->wait,
241 fh->queued_msgs,
242 msecs_to_jiffies(msg->timeout));
243 if (res == 0)
244 res = -ETIMEDOUT;
245 else if (res > 0)
246 res = 0;
247 } else {
248 /* Wait indefinitely */
249 res = wait_event_interruptible(fh->wait,
250 fh->queued_msgs);
251 }
252 /* Exit on error, otherwise loop to get the new message */
253 } while (!res);
254 return res;
255}
256
257static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh,
258 bool block, struct cec_msg __user *parg)
259{
260 struct cec_msg msg = {};
261 long err = 0;
262
263 if (copy_from_user(&msg, parg, sizeof(msg)))
264 return -EFAULT;
265 mutex_lock(&adap->lock);
266 if (!adap->is_configured)
267 err = -ENONET;
268 mutex_unlock(&adap->lock);
269 if (err)
270 return err;
271
272 err = cec_receive_msg(fh, &msg, block);
273 if (err)
274 return err;
275 if (copy_to_user(parg, &msg, sizeof(msg)))
276 return -EFAULT;
277 return 0;
278}
279
280static long cec_dqevent(struct cec_adapter *adap, struct cec_fh *fh,
281 bool block, struct cec_event __user *parg)
282{
283 struct cec_event *ev = NULL;
284 u64 ts = ~0ULL;
285 unsigned int i;
286 long err = 0;
287
288 mutex_lock(&fh->lock);
289 while (!fh->pending_events && block) {
290 mutex_unlock(&fh->lock);
291 err = wait_event_interruptible(fh->wait, fh->pending_events);
292 if (err)
293 return err;
294 mutex_lock(&fh->lock);
295 }
296
297 /* Find the oldest event */
298 for (i = 0; i < CEC_NUM_EVENTS; i++) {
299 if (fh->pending_events & (1 << (i + 1)) &&
300 fh->events[i].ts <= ts) {
301 ev = &fh->events[i];
302 ts = ev->ts;
303 }
304 }
305 if (!ev) {
306 err = -EAGAIN;
307 goto unlock;
308 }
309
310 if (copy_to_user(parg, ev, sizeof(*ev))) {
311 err = -EFAULT;
312 goto unlock;
313 }
314
315 fh->pending_events &= ~(1 << ev->event);
316
317unlock:
318 mutex_unlock(&fh->lock);
319 return err;
320}
321
322static long cec_g_mode(struct cec_adapter *adap, struct cec_fh *fh,
323 u32 __user *parg)
324{
325 u32 mode = fh->mode_initiator | fh->mode_follower;
326
327 if (copy_to_user(parg, &mode, sizeof(mode)))
328 return -EFAULT;
329 return 0;
330}
331
332static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
333 u32 __user *parg)
334{
335 u32 mode;
336 u8 mode_initiator;
337 u8 mode_follower;
338 long err = 0;
339
340 if (copy_from_user(&mode, parg, sizeof(mode)))
341 return -EFAULT;
342 if (mode & ~(CEC_MODE_INITIATOR_MSK | CEC_MODE_FOLLOWER_MSK))
343 return -EINVAL;
344
345 mode_initiator = mode & CEC_MODE_INITIATOR_MSK;
346 mode_follower = mode & CEC_MODE_FOLLOWER_MSK;
347
348 if (mode_initiator > CEC_MODE_EXCL_INITIATOR ||
349 mode_follower > CEC_MODE_MONITOR_ALL)
350 return -EINVAL;
351
352 if (mode_follower == CEC_MODE_MONITOR_ALL &&
353 !(adap->capabilities & CEC_CAP_MONITOR_ALL))
354 return -EINVAL;
355
356 /* Follower modes should always be able to send CEC messages */
357 if ((mode_initiator == CEC_MODE_NO_INITIATOR ||
358 !(adap->capabilities & CEC_CAP_TRANSMIT)) &&
359 mode_follower >= CEC_MODE_FOLLOWER &&
360 mode_follower <= CEC_MODE_EXCL_FOLLOWER_PASSTHRU)
361 return -EINVAL;
362
363 /* Monitor modes require CEC_MODE_NO_INITIATOR */
364 if (mode_initiator && mode_follower >= CEC_MODE_MONITOR)
365 return -EINVAL;
366
367 /* Monitor modes require CAP_NET_ADMIN */
368 if (mode_follower >= CEC_MODE_MONITOR && !capable(CAP_NET_ADMIN))
369 return -EPERM;
370
371 mutex_lock(&adap->lock);
372 /*
373 * You can't become exclusive follower if someone else already
374 * has that job.
375 */
376 if ((mode_follower == CEC_MODE_EXCL_FOLLOWER ||
377 mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) &&
378 adap->cec_follower && adap->cec_follower != fh)
379 err = -EBUSY;
380 /*
381 * You can't become exclusive initiator if someone else already
382 * has that job.
383 */
384 if (mode_initiator == CEC_MODE_EXCL_INITIATOR &&
385 adap->cec_initiator && adap->cec_initiator != fh)
386 err = -EBUSY;
387
388 if (!err) {
389 bool old_mon_all = fh->mode_follower == CEC_MODE_MONITOR_ALL;
390 bool new_mon_all = mode_follower == CEC_MODE_MONITOR_ALL;
391
392 if (old_mon_all != new_mon_all) {
393 if (new_mon_all)
394 err = cec_monitor_all_cnt_inc(adap);
395 else
396 cec_monitor_all_cnt_dec(adap);
397 }
398 }
399
400 if (err) {
401 mutex_unlock(&adap->lock);
402 return err;
403 }
404
405 if (fh->mode_follower == CEC_MODE_FOLLOWER)
406 adap->follower_cnt--;
407 if (mode_follower == CEC_MODE_FOLLOWER)
408 adap->follower_cnt++;
409 if (mode_follower == CEC_MODE_EXCL_FOLLOWER ||
410 mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) {
411 adap->passthrough =
412 mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU;
413 adap->cec_follower = fh;
414 } else if (adap->cec_follower == fh) {
415 adap->passthrough = false;
416 adap->cec_follower = NULL;
417 }
418 if (mode_initiator == CEC_MODE_EXCL_INITIATOR)
419 adap->cec_initiator = fh;
420 else if (adap->cec_initiator == fh)
421 adap->cec_initiator = NULL;
422 fh->mode_initiator = mode_initiator;
423 fh->mode_follower = mode_follower;
424 mutex_unlock(&adap->lock);
425 return 0;
426}
427
428static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
429{
430 struct cec_devnode *devnode = cec_devnode_data(filp);
431 struct cec_fh *fh = filp->private_data;
432 struct cec_adapter *adap = fh->adap;
433 bool block = !(filp->f_flags & O_NONBLOCK);
434 void __user *parg = (void __user *)arg;
435
436 if (!devnode->registered)
437 return -EIO;
438
439 switch (cmd) {
440 case CEC_ADAP_G_CAPS:
441 return cec_adap_g_caps(adap, parg);
442
443 case CEC_ADAP_G_PHYS_ADDR:
444 return cec_adap_g_phys_addr(adap, parg);
445
446 case CEC_ADAP_S_PHYS_ADDR:
447 return cec_adap_s_phys_addr(adap, fh, block, parg);
448
449 case CEC_ADAP_G_LOG_ADDRS:
450 return cec_adap_g_log_addrs(adap, parg);
451
452 case CEC_ADAP_S_LOG_ADDRS:
453 return cec_adap_s_log_addrs(adap, fh, block, parg);
454
455 case CEC_TRANSMIT:
456 return cec_transmit(adap, fh, block, parg);
457
458 case CEC_RECEIVE:
459 return cec_receive(adap, fh, block, parg);
460
461 case CEC_DQEVENT:
462 return cec_dqevent(adap, fh, block, parg);
463
464 case CEC_G_MODE:
465 return cec_g_mode(adap, fh, parg);
466
467 case CEC_S_MODE:
468 return cec_s_mode(adap, fh, parg);
469
470 default:
471 return -ENOTTY;
472 }
473}
474
475static int cec_open(struct inode *inode, struct file *filp)
476{
477 struct cec_devnode *devnode =
478 container_of(inode->i_cdev, struct cec_devnode, cdev);
479 struct cec_adapter *adap = to_cec_adapter(devnode);
480 struct cec_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
481 /*
482 * Initial events that are automatically sent when the cec device is
483 * opened.
484 */
485 struct cec_event ev_state = {
486 .event = CEC_EVENT_STATE_CHANGE,
487 .flags = CEC_EVENT_FL_INITIAL_STATE,
488 };
489 int err;
490
491 if (!fh)
492 return -ENOMEM;
493
494 INIT_LIST_HEAD(&fh->msgs);
495 INIT_LIST_HEAD(&fh->xfer_list);
496 mutex_init(&fh->lock);
497 init_waitqueue_head(&fh->wait);
498
499 fh->mode_initiator = CEC_MODE_INITIATOR;
500 fh->adap = adap;
501
502 err = cec_get_device(devnode);
503 if (err) {
504 kfree(fh);
505 return err;
506 }
507
508 filp->private_data = fh;
509
510 mutex_lock(&devnode->fhs_lock);
511 /* Queue up initial state events */
512 ev_state.state_change.phys_addr = adap->phys_addr;
513 ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
514 cec_queue_event_fh(fh, &ev_state, 0);
515
516 list_add(&fh->list, &devnode->fhs);
517 mutex_unlock(&devnode->fhs_lock);
518
519 return 0;
520}
521
522/* Override for the release function */
523static int cec_release(struct inode *inode, struct file *filp)
524{
525 struct cec_devnode *devnode = cec_devnode_data(filp);
526 struct cec_adapter *adap = to_cec_adapter(devnode);
527 struct cec_fh *fh = filp->private_data;
528
529 mutex_lock(&adap->lock);
530 if (adap->cec_initiator == fh)
531 adap->cec_initiator = NULL;
532 if (adap->cec_follower == fh) {
533 adap->cec_follower = NULL;
534 adap->passthrough = false;
535 }
536 if (fh->mode_follower == CEC_MODE_FOLLOWER)
537 adap->follower_cnt--;
538 if (fh->mode_follower == CEC_MODE_MONITOR_ALL)
539 cec_monitor_all_cnt_dec(adap);
540 mutex_unlock(&adap->lock);
541
542 mutex_lock(&devnode->fhs_lock);
543 list_del(&fh->list);
544 mutex_unlock(&devnode->fhs_lock);
545
546 /* Unhook pending transmits from this filehandle. */
547 mutex_lock(&adap->lock);
548 while (!list_empty(&fh->xfer_list)) {
549 struct cec_data *data =
550 list_first_entry(&fh->xfer_list, struct cec_data, xfer_list);
551
552 data->blocking = false;
553 data->fh = NULL;
554 list_del(&data->xfer_list);
555 }
556 mutex_unlock(&adap->lock);
557 while (!list_empty(&fh->msgs)) {
558 struct cec_msg_entry *entry =
559 list_first_entry(&fh->msgs, struct cec_msg_entry, list);
560
561 list_del(&entry->list);
562 kfree(entry);
563 }
564 kfree(fh);
565
566 cec_put_device(devnode);
567 filp->private_data = NULL;
568 return 0;
569}
570
571const struct file_operations cec_devnode_fops = {
572 .owner = THIS_MODULE,
573 .open = cec_open,
574 .unlocked_ioctl = cec_ioctl,
575 .release = cec_release,
576 .poll = cec_poll,
577 .llseek = no_llseek,
578};
drivers/staging/media/cec/cec-core.c+409−0
@@ -0,0 +1,409 @@
1/*
2 * cec-core.c - HDMI Consumer Electronics Control framework - Core
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#include <linux/errno.h>
21#include <linux/init.h>
22#include <linux/module.h>
23#include <linux/kernel.h>
24#include <linux/kmod.h>
25#include <linux/slab.h>
26#include <linux/mm.h>
27#include <linux/string.h>
28#include <linux/types.h>
29
30#include "cec-priv.h"
31
32#define CEC_NUM_DEVICES 256
33#define CEC_NAME "cec"
34
35int cec_debug;
36module_param_named(debug, cec_debug, int, 0644);
37MODULE_PARM_DESC(debug, "debug level (0-2)");
38
39static dev_t cec_dev_t;
40
41/* Active devices */
42static DEFINE_MUTEX(cec_devnode_lock);
43static DECLARE_BITMAP(cec_devnode_nums, CEC_NUM_DEVICES);
44
45static struct dentry *top_cec_dir;
46
47/* dev to cec_devnode */
48#define to_cec_devnode(cd) container_of(cd, struct cec_devnode, dev)
49
50int cec_get_device(struct cec_devnode *devnode)
51{
52 /*
53 * Check if the cec device is available. This needs to be done with
54 * the cec_devnode_lock held to prevent an open/unregister race:
55 * without the lock, the device could be unregistered and freed between
56 * the devnode->registered check and get_device() calls, leading to
57 * a crash.
58 */
59 mutex_lock(&cec_devnode_lock);
60 /*
61 * return ENXIO if the cec device has been removed
62 * already or if it is not registered anymore.
63 */
64 if (!devnode->registered) {
65 mutex_unlock(&cec_devnode_lock);
66 return -ENXIO;
67 }
68 /* and increase the device refcount */
69 get_device(&devnode->dev);
70 mutex_unlock(&cec_devnode_lock);
71 return 0;
72}
73
74void cec_put_device(struct cec_devnode *devnode)
75{
76 mutex_lock(&cec_devnode_lock);
77 put_device(&devnode->dev);
78 mutex_unlock(&cec_devnode_lock);
79}
80
81/* Called when the last user of the cec device exits. */
82static void cec_devnode_release(struct device *cd)
83{
84 struct cec_devnode *devnode = to_cec_devnode(cd);
85
86 mutex_lock(&cec_devnode_lock);
87
88 /* Mark device node number as free */
89 clear_bit(devnode->minor, cec_devnode_nums);
90
91 mutex_unlock(&cec_devnode_lock);
92 cec_delete_adapter(to_cec_adapter(devnode));
93}
94
95static struct bus_type cec_bus_type = {
96 .name = CEC_NAME,
97};
98
99/*
100 * Register a cec device node
101 *
102 * The registration code assigns minor numbers and registers the new device node
103 * with the kernel. An error is returned if no free minor number can be found,
104 * or if the registration of the device node fails.
105 *
106 * Zero is returned on success.
107 *
108 * Note that if the cec_devnode_register call fails, the release() callback of
109 * the cec_devnode structure is *not* called, so the caller is responsible for
110 * freeing any data.
111 */
112static int __must_check cec_devnode_register(struct cec_devnode *devnode,
113 struct module *owner)
114{
115 int minor;
116 int ret;
117
118 /* Initialization */
119 INIT_LIST_HEAD(&devnode->fhs);
120 mutex_init(&devnode->fhs_lock);
121
122 /* Part 1: Find a free minor number */
123 mutex_lock(&cec_devnode_lock);
124 minor = find_next_zero_bit(cec_devnode_nums, CEC_NUM_DEVICES, 0);
125 if (minor == CEC_NUM_DEVICES) {
126 mutex_unlock(&cec_devnode_lock);
127 pr_err("could not get a free minor\n");
128 return -ENFILE;
129 }
130
131 set_bit(minor, cec_devnode_nums);
132 mutex_unlock(&cec_devnode_lock);
133
134 devnode->minor = minor;
135 devnode->dev.bus = &cec_bus_type;
136 devnode->dev.devt = MKDEV(MAJOR(cec_dev_t), minor);
137 devnode->dev.release = cec_devnode_release;
138 devnode->dev.parent = devnode->parent;
139 dev_set_name(&devnode->dev, "cec%d", devnode->minor);
140 device_initialize(&devnode->dev);
141
142 /* Part 2: Initialize and register the character device */
143 cdev_init(&devnode->cdev, &cec_devnode_fops);
144 devnode->cdev.kobj.parent = &devnode->dev.kobj;
145 devnode->cdev.owner = owner;
146
147 ret = cdev_add(&devnode->cdev, devnode->dev.devt, 1);
148 if (ret < 0) {
149 pr_err("%s: cdev_add failed\n", __func__);
150 goto clr_bit;
151 }
152
153 ret = device_add(&devnode->dev);
154 if (ret)
155 goto cdev_del;
156
157 devnode->registered = true;
158 return 0;
159
160cdev_del:
161 cdev_del(&devnode->cdev);
162clr_bit:
163 clear_bit(devnode->minor, cec_devnode_nums);
164 return ret;
165}
166
167/*
168 * Unregister a cec device node
169 *
170 * This unregisters the passed device. Future open calls will be met with
171 * errors.
172 *
173 * This function can safely be called if the device node has never been
174 * registered or has already been unregistered.
175 */
176static void cec_devnode_unregister(struct cec_devnode *devnode)
177{
178 struct cec_fh *fh;
179
180 /* Check if devnode was never registered or already unregistered */
181 if (!devnode->registered || devnode->unregistered)
182 return;
183
184 mutex_lock(&devnode->fhs_lock);
185 list_for_each_entry(fh, &devnode->fhs, list)
186 wake_up_interruptible(&fh->wait);
187 mutex_unlock(&devnode->fhs_lock);
188
189 devnode->registered = false;
190 devnode->unregistered = true;
191 device_del(&devnode->dev);
192 cdev_del(&devnode->cdev);
193 put_device(&devnode->dev);
194}
195
196struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
197 void *priv, const char *name, u32 caps,
198 u8 available_las, struct device *parent)
199{
200 struct cec_adapter *adap;
201 int res;
202
203 if (WARN_ON(!parent))
204 return ERR_PTR(-EINVAL);
205 if (WARN_ON(!caps))
206 return ERR_PTR(-EINVAL);
207 if (WARN_ON(!ops))
208 return ERR_PTR(-EINVAL);
209 if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS))
210 return ERR_PTR(-EINVAL);
211 adap = kzalloc(sizeof(*adap), GFP_KERNEL);
212 if (!adap)
213 return ERR_PTR(-ENOMEM);
214 adap->owner = parent->driver->owner;
215 adap->devnode.parent = parent;
216 strlcpy(adap->name, name, sizeof(adap->name));
217 adap->phys_addr = CEC_PHYS_ADDR_INVALID;
218 adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
219 adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
220 adap->capabilities = caps;
221 adap->available_log_addrs = available_las;
222 adap->sequence = 0;
223 adap->ops = ops;
224 adap->priv = priv;
225 memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
226 mutex_init(&adap->lock);
227 INIT_LIST_HEAD(&adap->transmit_queue);
228 INIT_LIST_HEAD(&adap->wait_queue);
229 init_waitqueue_head(&adap->kthread_waitq);
230
231 adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
232 if (IS_ERR(adap->kthread)) {
233 pr_err("cec-%s: kernel_thread() failed\n", name);
234 res = PTR_ERR(adap->kthread);
235 kfree(adap);
236 return ERR_PTR(res);
237 }
238
239 if (!(caps & CEC_CAP_RC))
240 return adap;
241
242#if IS_ENABLED(CONFIG_RC_CORE)
243 /* Prepare the RC input device */
244 adap->rc = rc_allocate_device();
245 if (!adap->rc) {
246 pr_err("cec-%s: failed to allocate memory for rc_dev\n",
247 name);
248 kthread_stop(adap->kthread);
249 kfree(adap);
250 return ERR_PTR(-ENOMEM);
251 }
252
253 snprintf(adap->input_name, sizeof(adap->input_name),
254 "RC for %s", name);
255 snprintf(adap->input_phys, sizeof(adap->input_phys),
256 "%s/input0", name);
257
258 adap->rc->input_name = adap->input_name;
259 adap->rc->input_phys = adap->input_phys;
260 adap->rc->input_id.bustype = BUS_CEC;
261 adap->rc->input_id.vendor = 0;
262 adap->rc->input_id.product = 0;
263 adap->rc->input_id.version = 1;
264 adap->rc->dev.parent = parent;
265 adap->rc->driver_type = RC_DRIVER_SCANCODE;
266 adap->rc->driver_name = CEC_NAME;
267 adap->rc->allowed_protocols = RC_BIT_CEC;
268 adap->rc->priv = adap;
269 adap->rc->map_name = RC_MAP_CEC;
270 adap->rc->timeout = MS_TO_NS(100);
271#else
272 adap->capabilities &= ~CEC_CAP_RC;
273#endif
274 return adap;
275}
276EXPORT_SYMBOL_GPL(cec_allocate_adapter);
277
278int cec_register_adapter(struct cec_adapter *adap)
279{
280 int res;
281
282 if (IS_ERR_OR_NULL(adap))
283 return 0;
284
285#if IS_ENABLED(CONFIG_RC_CORE)
286 if (adap->capabilities & CEC_CAP_RC) {
287 res = rc_register_device(adap->rc);
288
289 if (res) {
290 pr_err("cec-%s: failed to prepare input device\n",
291 adap->name);
292 rc_free_device(adap->rc);
293 adap->rc = NULL;
294 return res;
295 }
296 }
297#endif
298
299 res = cec_devnode_register(&adap->devnode, adap->owner);
300 if (res) {
301#if IS_ENABLED(CONFIG_RC_CORE)
302 /* Note: rc_unregister also calls rc_free */
303 rc_unregister_device(adap->rc);
304 adap->rc = NULL;
305#endif
306 return res;
307 }
308
309 dev_set_drvdata(&adap->devnode.dev, adap);
310#ifdef CONFIG_MEDIA_CEC_DEBUG
311 if (!top_cec_dir)
312 return 0;
313
314 adap->cec_dir = debugfs_create_dir(dev_name(&adap->devnode.dev), top_cec_dir);
315 if (IS_ERR_OR_NULL(adap->cec_dir)) {
316 pr_warn("cec-%s: Failed to create debugfs dir\n", adap->name);
317 return 0;
318 }
319 adap->status_file = debugfs_create_devm_seqfile(&adap->devnode.dev,
320 "status", adap->cec_dir, cec_adap_status);
321 if (IS_ERR_OR_NULL(adap->status_file)) {
322 pr_warn("cec-%s: Failed to create status file\n", adap->name);
323 debugfs_remove_recursive(adap->cec_dir);
324 adap->cec_dir = NULL;
325 }
326#endif
327 return 0;
328}
329EXPORT_SYMBOL_GPL(cec_register_adapter);
330
331void cec_unregister_adapter(struct cec_adapter *adap)
332{
333 if (IS_ERR_OR_NULL(adap))
334 return;
335
336#if IS_ENABLED(CONFIG_RC_CORE)
337 /* Note: rc_unregister also calls rc_free */
338 rc_unregister_device(adap->rc);
339 adap->rc = NULL;
340#endif
341 debugfs_remove_recursive(adap->cec_dir);
342 cec_devnode_unregister(&adap->devnode);
343}
344EXPORT_SYMBOL_GPL(cec_unregister_adapter);
345
346void cec_delete_adapter(struct cec_adapter *adap)
347{
348 if (IS_ERR_OR_NULL(adap))
349 return;
350 mutex_lock(&adap->lock);
351 __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
352 mutex_unlock(&adap->lock);
353 kthread_stop(adap->kthread);
354 if (adap->kthread_config)
355 kthread_stop(adap->kthread_config);
356#if IS_ENABLED(CONFIG_RC_CORE)
357 if (adap->rc)
358 rc_free_device(adap->rc);
359#endif
360 kfree(adap);
361}
362EXPORT_SYMBOL_GPL(cec_delete_adapter);
363
364/*
365 * Initialise cec for linux
366 */
367static int __init cec_devnode_init(void)
368{
369 int ret;
370
371 pr_info("Linux cec interface: v0.10\n");
372 ret = alloc_chrdev_region(&cec_dev_t, 0, CEC_NUM_DEVICES,
373 CEC_NAME);
374 if (ret < 0) {
375 pr_warn("cec: unable to allocate major\n");
376 return ret;
377 }
378
379#ifdef CONFIG_MEDIA_CEC_DEBUG
380 top_cec_dir = debugfs_create_dir("cec", NULL);
381 if (IS_ERR_OR_NULL(top_cec_dir)) {
382 pr_warn("cec: Failed to create debugfs cec dir\n");
383 top_cec_dir = NULL;
384 }
385#endif
386
387 ret = bus_register(&cec_bus_type);
388 if (ret < 0) {
389 unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES);
390 pr_warn("cec: bus_register failed\n");
391 return -EIO;
392 }
393
394 return 0;
395}
396
397static void __exit cec_devnode_exit(void)
398{
399 debugfs_remove_recursive(top_cec_dir);
400 bus_unregister(&cec_bus_type);
401 unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES);
402}
403
404subsys_initcall(cec_devnode_init);
405module_exit(cec_devnode_exit)
406
407MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
408MODULE_DESCRIPTION("Device node registration for cec drivers");
409MODULE_LICENSE("GPL");
drivers/staging/media/cec/cec-priv.h+56−0
@@ -0,0 +1,56 @@
1/*
2 * cec-priv.h - HDMI Consumer Electronics Control internal header
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#ifndef _CEC_PRIV_H
21#define _CEC_PRIV_H
22
23#include <linux/cec-funcs.h>
24#include <media/cec.h>
25
26#define dprintk(lvl, fmt, arg...) \
27 do { \
28 if (lvl <= cec_debug) \
29 pr_info("cec-%s: " fmt, adap->name, ## arg); \
30 } while (0)
31
32/* devnode to cec_adapter */
33#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
34
35/* cec-core.c */
36extern int cec_debug;
37int cec_get_device(struct cec_devnode *devnode);
38void cec_put_device(struct cec_devnode *devnode);
39
40/* cec-adap.c */
41int cec_monitor_all_cnt_inc(struct cec_adapter *adap);
42void cec_monitor_all_cnt_dec(struct cec_adapter *adap);
43int cec_adap_status(struct seq_file *file, void *priv);
44int cec_thread_func(void *_adap);
45void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
46int __cec_s_log_addrs(struct cec_adapter *adap,
47 struct cec_log_addrs *log_addrs, bool block);
48int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
49 struct cec_fh *fh, bool block);
50void cec_queue_event_fh(struct cec_fh *fh,
51 const struct cec_event *new_ev, u64 ts);
52
53/* cec-api.c */
54extern const struct file_operations cec_devnode_fops;
55
56#endif
drivers/staging/media/s5p-cec/Kconfig+9−0
@@ -0,0 +1,9 @@
1config VIDEO_SAMSUNG_S5P_CEC
2 tristate "Samsung S5P CEC driver"
3 depends on VIDEO_DEV && MEDIA_CEC && (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST)
4 ---help---
5 This is a driver for Samsung S5P HDMI CEC interface. It uses the
6 generic CEC framework interface.
7 CEC bus is present in the HDMI connector and enables communication
8 between compatible devices.
9
drivers/staging/media/s5p-cec/Makefile+2−0
@@ -0,0 +1,2 @@
1obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec.o
2s5p-cec-y += s5p_cec.o exynos_hdmi_cecctrl.o
drivers/staging/media/s5p-cec/TODO+3−0
@@ -0,0 +1,3 @@
1There's nothing wrong on this driver, except that it depends on
2the media staging core, that it is currently at staging. So,
3this should be kept here while the core is not promoted.
drivers/staging/media/s5p-cec/exynos_hdmi_cec.h+38−0
@@ -0,0 +1,38 @@
1/* drivers/media/platform/s5p-cec/exynos_hdmi_cec.h
2 *
3 * Copyright (c) 2010, 2014 Samsung Electronics
4 * http://www.samsung.com/
5 *
6 * Header file for interface of Samsung Exynos hdmi cec hardware
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _EXYNOS_HDMI_CEC_H_
14#define _EXYNOS_HDMI_CEC_H_ __FILE__
15
16#include <linux/regmap.h>
17#include <linux/miscdevice.h>
18#include "s5p_cec.h"
19
20void s5p_cec_set_divider(struct s5p_cec_dev *cec);
21void s5p_cec_enable_rx(struct s5p_cec_dev *cec);
22void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec);
23void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec);
24void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec);
25void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec);
26void s5p_cec_reset(struct s5p_cec_dev *cec);
27void s5p_cec_tx_reset(struct s5p_cec_dev *cec);
28void s5p_cec_rx_reset(struct s5p_cec_dev *cec);
29void s5p_cec_threshold(struct s5p_cec_dev *cec);
30void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
31 size_t count, u8 retries);
32void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr);
33u32 s5p_cec_get_status(struct s5p_cec_dev *cec);
34void s5p_clr_pending_tx(struct s5p_cec_dev *cec);
35void s5p_clr_pending_rx(struct s5p_cec_dev *cec);
36void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer);
37
38#endif /* _EXYNOS_HDMI_CEC_H_ */
drivers/staging/media/s5p-cec/exynos_hdmi_cecctrl.c+209−0
@@ -0,0 +1,209 @@
1/* drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c
2 *
3 * Copyright (c) 2009, 2014 Samsung Electronics
4 * http://www.samsung.com/
5 *
6 * cec ftn file for Samsung TVOUT driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/io.h>
14#include <linux/device.h>
15
16#include "exynos_hdmi_cec.h"
17#include "regs-cec.h"
18
19#define S5P_HDMI_FIN 24000000
20#define CEC_DIV_RATIO 320000
21
22#define CEC_MESSAGE_BROADCAST_MASK 0x0F
23#define CEC_MESSAGE_BROADCAST 0x0F
24#define CEC_FILTER_THRESHOLD 0x15
25
26void s5p_cec_set_divider(struct s5p_cec_dev *cec)
27{
28 u32 div_ratio, div_val;
29 unsigned int reg;
30
31 div_ratio = S5P_HDMI_FIN / CEC_DIV_RATIO - 1;
32
33 if (regmap_read(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, &reg)) {
34 dev_err(cec->dev, "failed to read phy control\n");
35 return;
36 }
37
38 reg = (reg & ~(0x3FF << 16)) | (div_ratio << 16);
39
40 if (regmap_write(cec->pmu, EXYNOS_HDMI_PHY_CONTROL, reg)) {
41 dev_err(cec->dev, "failed to write phy control\n");
42 return;
43 }
44
45 div_val = CEC_DIV_RATIO * 0.00005 - 1;
46
47 writeb(0x0, cec->reg + S5P_CEC_DIVISOR_3);
48 writeb(0x0, cec->reg + S5P_CEC_DIVISOR_2);
49 writeb(0x0, cec->reg + S5P_CEC_DIVISOR_1);
50 writeb(div_val, cec->reg + S5P_CEC_DIVISOR_0);
51}
52
53void s5p_cec_enable_rx(struct s5p_cec_dev *cec)
54{
55 u8 reg;
56
57 reg = readb(cec->reg + S5P_CEC_RX_CTRL);
58 reg |= S5P_CEC_RX_CTRL_ENABLE;
59 writeb(reg, cec->reg + S5P_CEC_RX_CTRL);
60}
61
62void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec)
63{
64 u8 reg;
65
66 reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
67 reg |= S5P_CEC_IRQ_RX_DONE;
68 reg |= S5P_CEC_IRQ_RX_ERROR;
69 writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
70}
71
72void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec)
73{
74 u8 reg;
75
76 reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
77 reg &= ~S5P_CEC_IRQ_RX_DONE;
78 reg &= ~S5P_CEC_IRQ_RX_ERROR;
79 writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
80}
81
82void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec)
83{
84 u8 reg;
85
86 reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
87 reg |= S5P_CEC_IRQ_TX_DONE;
88 reg |= S5P_CEC_IRQ_TX_ERROR;
89 writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
90
91}
92
93void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec)
94{
95 u8 reg;
96
97 reg = readb(cec->reg + S5P_CEC_IRQ_MASK);
98 reg &= ~S5P_CEC_IRQ_TX_DONE;
99 reg &= ~S5P_CEC_IRQ_TX_ERROR;
100 writeb(reg, cec->reg + S5P_CEC_IRQ_MASK);
101}
102
103void s5p_cec_reset(struct s5p_cec_dev *cec)
104{
105 u8 reg;
106
107 writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
108 writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
109
110 reg = readb(cec->reg + 0xc4);
111 reg &= ~0x1;
112 writeb(reg, cec->reg + 0xc4);
113}
114
115void s5p_cec_tx_reset(struct s5p_cec_dev *cec)
116{
117 writeb(S5P_CEC_TX_CTRL_RESET, cec->reg + S5P_CEC_TX_CTRL);
118}
119
120void s5p_cec_rx_reset(struct s5p_cec_dev *cec)
121{
122 u8 reg;
123
124 writeb(S5P_CEC_RX_CTRL_RESET, cec->reg + S5P_CEC_RX_CTRL);
125
126 reg = readb(cec->reg + 0xc4);
127 reg &= ~0x1;
128 writeb(reg, cec->reg + 0xc4);
129}
130
131void s5p_cec_threshold(struct s5p_cec_dev *cec)
132{
133 writeb(CEC_FILTER_THRESHOLD, cec->reg + S5P_CEC_RX_FILTER_TH);
134 writeb(0, cec->reg + S5P_CEC_RX_FILTER_CTRL);
135}
136
137void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
138 size_t count, u8 retries)
139{
140 int i = 0;
141 u8 reg;
142
143 while (i < count) {
144 writeb(data[i], cec->reg + (S5P_CEC_TX_BUFF0 + (i * 4)));
145 i++;
146 }
147
148 writeb(count, cec->reg + S5P_CEC_TX_BYTES);
149 reg = readb(cec->reg + S5P_CEC_TX_CTRL);
150 reg |= S5P_CEC_TX_CTRL_START;
151 reg &= ~0x70;
152 reg |= retries << 4;
153
154 if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST) {
155 dev_dbg(cec->dev, "Broadcast");
156 reg |= S5P_CEC_TX_CTRL_BCAST;
157 } else {
158 dev_dbg(cec->dev, "No Broadcast");
159 reg &= ~S5P_CEC_TX_CTRL_BCAST;
160 }
161
162 writeb(reg, cec->reg + S5P_CEC_TX_CTRL);
163 dev_dbg(cec->dev, "cec-tx: cec count (%zu): %*ph", count,
164 (int)count, data);
165}
166
167void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr)
168{
169 writeb(addr & 0x0F, cec->reg + S5P_CEC_LOGIC_ADDR);
170}
171
172u32 s5p_cec_get_status(struct s5p_cec_dev *cec)
173{
174 u32 status = 0;
175
176 status = readb(cec->reg + S5P_CEC_STATUS_0);
177 status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8;
178 status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16;
179 status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24;
180
181 dev_dbg(cec->dev, "status = 0x%x!\n", status);
182
183 return status;
184}
185
186void s5p_clr_pending_tx(struct s5p_cec_dev *cec)
187{
188 writeb(S5P_CEC_IRQ_TX_DONE | S5P_CEC_IRQ_TX_ERROR,
189 cec->reg + S5P_CEC_IRQ_CLEAR);
190}
191
192void s5p_clr_pending_rx(struct s5p_cec_dev *cec)
193{
194 writeb(S5P_CEC_IRQ_RX_DONE | S5P_CEC_IRQ_RX_ERROR,
195 cec->reg + S5P_CEC_IRQ_CLEAR);
196}
197
198void s5p_cec_get_rx_buf(struct s5p_cec_dev *cec, u32 size, u8 *buffer)
199{
200 u32 i = 0;
201 char debug[40];
202
203 while (i < size) {
204 buffer[i] = readb(cec->reg + S5P_CEC_RX_BUFF0 + (i * 4));
205 sprintf(debug + i * 2, "%02x ", buffer[i]);
206 i++;
207 }
208 dev_dbg(cec->dev, "cec-rx: cec size(%d): %s", size, debug);
209}
drivers/staging/media/s5p-cec/regs-cec.h+96−0
@@ -0,0 +1,96 @@
1/* drivers/media/platform/s5p-cec/regs-cec.h
2 *
3 * Copyright (c) 2010 Samsung Electronics
4 * http://www.samsung.com/
5 *
6 * register header file for Samsung TVOUT driver
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __EXYNOS_REGS__H
14#define __EXYNOS_REGS__H
15
16/*
17 * Register part
18 */
19#define S5P_CEC_STATUS_0 (0x0000)
20#define S5P_CEC_STATUS_1 (0x0004)
21#define S5P_CEC_STATUS_2 (0x0008)
22#define S5P_CEC_STATUS_3 (0x000C)
23#define S5P_CEC_IRQ_MASK (0x0010)
24#define S5P_CEC_IRQ_CLEAR (0x0014)
25#define S5P_CEC_LOGIC_ADDR (0x0020)
26#define S5P_CEC_DIVISOR_0 (0x0030)
27#define S5P_CEC_DIVISOR_1 (0x0034)
28#define S5P_CEC_DIVISOR_2 (0x0038)
29#define S5P_CEC_DIVISOR_3 (0x003C)
30
31#define S5P_CEC_TX_CTRL (0x0040)
32#define S5P_CEC_TX_BYTES (0x0044)
33#define S5P_CEC_TX_STAT0 (0x0060)
34#define S5P_CEC_TX_STAT1 (0x0064)
35#define S5P_CEC_TX_BUFF0 (0x0080)
36#define S5P_CEC_TX_BUFF1 (0x0084)
37#define S5P_CEC_TX_BUFF2 (0x0088)
38#define S5P_CEC_TX_BUFF3 (0x008C)
39#define S5P_CEC_TX_BUFF4 (0x0090)
40#define S5P_CEC_TX_BUFF5 (0x0094)
41#define S5P_CEC_TX_BUFF6 (0x0098)
42#define S5P_CEC_TX_BUFF7 (0x009C)
43#define S5P_CEC_TX_BUFF8 (0x00A0)
44#define S5P_CEC_TX_BUFF9 (0x00A4)
45#define S5P_CEC_TX_BUFF10 (0x00A8)
46#define S5P_CEC_TX_BUFF11 (0x00AC)
47#define S5P_CEC_TX_BUFF12 (0x00B0)
48#define S5P_CEC_TX_BUFF13 (0x00B4)
49#define S5P_CEC_TX_BUFF14 (0x00B8)
50#define S5P_CEC_TX_BUFF15 (0x00BC)
51
52#define S5P_CEC_RX_CTRL (0x00C0)
53#define S5P_CEC_RX_STAT0 (0x00E0)
54#define S5P_CEC_RX_STAT1 (0x00E4)
55#define S5P_CEC_RX_BUFF0 (0x0100)
56#define S5P_CEC_RX_BUFF1 (0x0104)
57#define S5P_CEC_RX_BUFF2 (0x0108)
58#define S5P_CEC_RX_BUFF3 (0x010C)
59#define S5P_CEC_RX_BUFF4 (0x0110)
60#define S5P_CEC_RX_BUFF5 (0x0114)
61#define S5P_CEC_RX_BUFF6 (0x0118)
62#define S5P_CEC_RX_BUFF7 (0x011C)
63#define S5P_CEC_RX_BUFF8 (0x0120)
64#define S5P_CEC_RX_BUFF9 (0x0124)
65#define S5P_CEC_RX_BUFF10 (0x0128)
66#define S5P_CEC_RX_BUFF11 (0x012C)
67#define S5P_CEC_RX_BUFF12 (0x0130)
68#define S5P_CEC_RX_BUFF13 (0x0134)
69#define S5P_CEC_RX_BUFF14 (0x0138)
70#define S5P_CEC_RX_BUFF15 (0x013C)
71
72#define S5P_CEC_RX_FILTER_CTRL (0x0180)
73#define S5P_CEC_RX_FILTER_TH (0x0184)
74
75/*
76 * Bit definition part
77 */
78#define S5P_CEC_IRQ_TX_DONE (1<<0)
79#define S5P_CEC_IRQ_TX_ERROR (1<<1)
80#define S5P_CEC_IRQ_RX_DONE (1<<4)
81#define S5P_CEC_IRQ_RX_ERROR (1<<5)
82
83#define S5P_CEC_TX_CTRL_START (1<<0)
84#define S5P_CEC_TX_CTRL_BCAST (1<<1)
85#define S5P_CEC_TX_CTRL_RETRY (0x04<<4)
86#define S5P_CEC_TX_CTRL_RESET (1<<7)
87
88#define S5P_CEC_RX_CTRL_ENABLE (1<<0)
89#define S5P_CEC_RX_CTRL_RESET (1<<7)
90
91#define S5P_CEC_LOGIC_ADDR_MASK (0xF)
92
93/* PMU Registers for PHY */
94#define EXYNOS_HDMI_PHY_CONTROL 0x700
95
96#endif /* __EXYNOS_REGS__H */
drivers/staging/media/s5p-cec/s5p_cec.c+294−0
@@ -0,0 +1,294 @@
1/* drivers/media/platform/s5p-cec/s5p_cec.c
2 *
3 * Samsung S5P CEC driver
4 *
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This driver is based on the "cec interface driver for exynos soc" by
13 * SangPil Moon.
14 */
15
16#include <linux/clk.h>
17#include <linux/interrupt.h>
18#include <linux/kernel.h>
19#include <linux/mfd/syscon.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/platform_device.h>
23#include <linux/pm_runtime.h>
24#include <linux/timer.h>
25#include <linux/version.h>
26#include <linux/workqueue.h>
27#include <media/cec.h>
28
29#include "exynos_hdmi_cec.h"
30#include "regs-cec.h"
31#include "s5p_cec.h"
32
33#define CEC_NAME "s5p-cec"
34
35static int debug;
36module_param(debug, int, 0644);
37MODULE_PARM_DESC(debug, "debug level (0-2)");
38
39static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable)
40{
41 struct s5p_cec_dev *cec = adap->priv;
42
43 if (enable) {
44 pm_runtime_get_sync(cec->dev);
45
46 s5p_cec_reset(cec);
47
48 s5p_cec_set_divider(cec);
49 s5p_cec_threshold(cec);
50
51 s5p_cec_unmask_tx_interrupts(cec);
52 s5p_cec_unmask_rx_interrupts(cec);
53 s5p_cec_enable_rx(cec);
54 } else {
55 s5p_cec_mask_tx_interrupts(cec);
56 s5p_cec_mask_rx_interrupts(cec);
57 pm_runtime_disable(cec->dev);
58 }
59
60 return 0;
61}
62
63static int s5p_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
64{
65 struct s5p_cec_dev *cec = adap->priv;
66
67 s5p_cec_set_addr(cec, addr);
68 return 0;
69}
70
71static int s5p_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
72 u32 signal_free_time, struct cec_msg *msg)
73{
74 struct s5p_cec_dev *cec = adap->priv;
75
76 /*
77 * Unclear if 0 retries are allowed by the hardware, so have 1 as
78 * the minimum.
79 */
80 s5p_cec_copy_packet(cec, msg->msg, msg->len, max(1, attempts - 1));
81 return 0;
82}
83
84static irqreturn_t s5p_cec_irq_handler(int irq, void *priv)
85{
86 struct s5p_cec_dev *cec = priv;
87 u32 status = 0;
88
89 status = s5p_cec_get_status(cec);
90
91 dev_dbg(cec->dev, "irq received\n");
92
93 if (status & CEC_STATUS_TX_DONE) {
94 if (status & CEC_STATUS_TX_ERROR) {
95 dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n");
96 cec->tx = STATE_ERROR;
97 } else {
98 dev_dbg(cec->dev, "CEC_STATUS_TX_DONE\n");
99 cec->tx = STATE_DONE;
100 }
101 s5p_clr_pending_tx(cec);
102 }
103
104 if (status & CEC_STATUS_RX_DONE) {
105 if (status & CEC_STATUS_RX_ERROR) {
106 dev_dbg(cec->dev, "CEC_STATUS_RX_ERROR set\n");
107 s5p_cec_rx_reset(cec);
108 s5p_cec_enable_rx(cec);
109 } else {
110 dev_dbg(cec->dev, "CEC_STATUS_RX_DONE set\n");
111 if (cec->rx != STATE_IDLE)
112 dev_dbg(cec->dev, "Buffer overrun (worker did not process previous message)\n");
113 cec->rx = STATE_BUSY;
114 cec->msg.len = status >> 24;
115 cec->msg.rx_status = CEC_RX_STATUS_OK;
116 s5p_cec_get_rx_buf(cec, cec->msg.len,
117 cec->msg.msg);
118 cec->rx = STATE_DONE;
119 s5p_cec_enable_rx(cec);
120 }
121 /* Clear interrupt pending bit */
122 s5p_clr_pending_rx(cec);
123 }
124 return IRQ_WAKE_THREAD;
125}
126
127static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv)
128{
129 struct s5p_cec_dev *cec = priv;
130
131 dev_dbg(cec->dev, "irq processing thread\n");
132 switch (cec->tx) {
133 case STATE_DONE:
134 cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
135 cec->tx = STATE_IDLE;
136 break;
137 case STATE_ERROR:
138 cec_transmit_done(cec->adap,
139 CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR,
140 0, 0, 0, 1);
141 cec->tx = STATE_IDLE;
142 break;
143 case STATE_BUSY:
144 dev_err(cec->dev, "state set to busy, this should not occur here\n");
145 break;
146 default:
147 break;
148 }
149
150 switch (cec->rx) {
151 case STATE_DONE:
152 cec_received_msg(cec->adap, &cec->msg);
153 cec->rx = STATE_IDLE;
154 break;
155 default:
156 break;
157 }
158
159 return IRQ_HANDLED;
160}
161
162static const struct cec_adap_ops s5p_cec_adap_ops = {
163 .adap_enable = s5p_cec_adap_enable,
164 .adap_log_addr = s5p_cec_adap_log_addr,
165 .adap_transmit = s5p_cec_adap_transmit,
166};
167
168static int s5p_cec_probe(struct platform_device *pdev)
169{
170 struct device *dev = &pdev->dev;
171 struct resource *res;
172 struct s5p_cec_dev *cec;
173 int ret;
174
175 cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
176 if (!dev)
177 return -ENOMEM;
178
179 cec->dev = dev;
180
181 cec->irq = platform_get_irq(pdev, 0);
182 if (cec->irq < 0)
183 return cec->irq;
184
185 ret = devm_request_threaded_irq(dev, cec->irq, s5p_cec_irq_handler,
186 s5p_cec_irq_handler_thread, 0, pdev->name, cec);
187 if (ret)
188 return ret;
189
190 cec->clk = devm_clk_get(dev, "hdmicec");
191 if (IS_ERR(cec->clk))
192 return PTR_ERR(cec->clk);
193
194 cec->pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
195 "samsung,syscon-phandle");
196 if (IS_ERR(cec->pmu))
197 return -EPROBE_DEFER;
198
199 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
200 cec->reg = devm_ioremap_resource(dev, res);
201 if (IS_ERR(cec->reg))
202 return PTR_ERR(cec->reg);
203
204 cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec,
205 CEC_NAME,
206 CEC_CAP_PHYS_ADDR | CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT |
207 CEC_CAP_PASSTHROUGH | CEC_CAP_RC,
208 1, &pdev->dev);
209 ret = PTR_ERR_OR_ZERO(cec->adap);
210 if (ret)
211 return ret;
212 ret = cec_register_adapter(cec->adap);
213 if (ret) {
214 cec_delete_adapter(cec->adap);
215 return ret;
216 }
217
218 platform_set_drvdata(pdev, cec);
219 pm_runtime_enable(dev);
220
221 dev_dbg(dev, "successfuly probed\n");
222 return 0;
223}
224
225static int s5p_cec_remove(struct platform_device *pdev)
226{
227 struct s5p_cec_dev *cec = platform_get_drvdata(pdev);
228
229 cec_unregister_adapter(cec->adap);
230 pm_runtime_disable(&pdev->dev);
231 return 0;
232}
233
234static int s5p_cec_runtime_suspend(struct device *dev)
235{
236 struct s5p_cec_dev *cec = dev_get_drvdata(dev);
237
238 clk_disable_unprepare(cec->clk);
239 return 0;
240}
241
242static int s5p_cec_runtime_resume(struct device *dev)
243{
244 struct s5p_cec_dev *cec = dev_get_drvdata(dev);
245 int ret;
246
247 ret = clk_prepare_enable(cec->clk);
248 if (ret < 0)
249 return ret;
250 return 0;
251}
252
253static int s5p_cec_suspend(struct device *dev)
254{
255 if (pm_runtime_suspended(dev))
256 return 0;
257 return s5p_cec_runtime_suspend(dev);
258}
259
260static int s5p_cec_resume(struct device *dev)
261{
262 if (pm_runtime_suspended(dev))
263 return 0;
264 return s5p_cec_runtime_resume(dev);
265}
266
267static const struct dev_pm_ops s5p_cec_pm_ops = {
268 SET_SYSTEM_SLEEP_PM_OPS(s5p_cec_suspend, s5p_cec_resume)
269 SET_RUNTIME_PM_OPS(s5p_cec_runtime_suspend, s5p_cec_runtime_resume,
270 NULL)
271};
272
273static const struct of_device_id s5p_cec_match[] = {
274 {
275 .compatible = "samsung,s5p-cec",
276 },
277 {},
278};
279
280static struct platform_driver s5p_cec_pdrv = {
281 .probe = s5p_cec_probe,
282 .remove = s5p_cec_remove,
283 .driver = {
284 .name = CEC_NAME,
285 .of_match_table = s5p_cec_match,
286 .pm = &s5p_cec_pm_ops,
287 },
288};
289
290module_platform_driver(s5p_cec_pdrv);
291
292MODULE_AUTHOR("Kamil Debski <kamil@wypas.org>");
293MODULE_LICENSE("GPL");
294MODULE_DESCRIPTION("Samsung S5P CEC driver");
drivers/staging/media/s5p-cec/s5p_cec.h+76−0
@@ -0,0 +1,76 @@
1/* drivers/media/platform/s5p-cec/s5p_cec.h
2 *
3 * Samsung S5P HDMI CEC driver
4 *
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#ifndef _S5P_CEC_H_
14#define _S5P_CEC_H_ __FILE__
15
16#include <linux/clk.h>
17#include <linux/interrupt.h>
18#include <linux/kernel.h>
19#include <linux/mfd/syscon.h>
20#include <linux/module.h>
21#include <linux/of.h>
22#include <linux/platform_device.h>
23#include <linux/pm_runtime.h>
24#include <linux/timer.h>
25#include <linux/version.h>
26#include <linux/workqueue.h>
27#include <media/cec.h>
28
29#include "exynos_hdmi_cec.h"
30#include "regs-cec.h"
31#include "s5p_cec.h"
32
33#define CEC_NAME "s5p-cec"
34
35#define CEC_STATUS_TX_RUNNING (1 << 0)
36#define CEC_STATUS_TX_TRANSFERRING (1 << 1)
37#define CEC_STATUS_TX_DONE (1 << 2)
38#define CEC_STATUS_TX_ERROR (1 << 3)
39#define CEC_STATUS_TX_BYTES (0xFF << 8)
40#define CEC_STATUS_RX_RUNNING (1 << 16)
41#define CEC_STATUS_RX_RECEIVING (1 << 17)
42#define CEC_STATUS_RX_DONE (1 << 18)
43#define CEC_STATUS_RX_ERROR (1 << 19)
44#define CEC_STATUS_RX_BCAST (1 << 20)
45#define CEC_STATUS_RX_BYTES (0xFF << 24)
46
47#define CEC_WORKER_TX_DONE (1 << 0)
48#define CEC_WORKER_RX_MSG (1 << 1)
49
50/* CEC Rx buffer size */
51#define CEC_RX_BUFF_SIZE 16
52/* CEC Tx buffer size */
53#define CEC_TX_BUFF_SIZE 16
54
55enum cec_state {
56 STATE_IDLE,
57 STATE_BUSY,
58 STATE_DONE,
59 STATE_ERROR
60};
61
62struct s5p_cec_dev {
63 struct cec_adapter *adap;
64 struct clk *clk;
65 struct device *dev;
66 struct mutex lock;
67 struct regmap *pmu;
68 int irq;
69 void __iomem *reg;
70
71 enum cec_state rx;
72 enum cec_state tx;
73 struct cec_msg msg;
74};
75
76#endif /* _S5P_CEC_H_ */
fs/compat_ioctl.c+12−0
@@ -57,6 +57,7 @@ · 56 unmodified lines
57#include <linux/i2c-dev.h>57#include <linux/i2c-dev.h>
58#include <linux/atalk.h>58#include <linux/atalk.h>
59#include <linux/gfp.h>59#include <linux/gfp.h>
60#include <linux/cec.h>
60 61
61#include "internal.h"62#include "internal.h"
62 63
@@ -1377,6 +1378,17 @@ COMPATIBLE_IOCTL(VIDEO_GET_NAVI) · 1314 unmodified lines
1377COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)1378COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)
1378COMPATIBLE_IOCTL(VIDEO_GET_SIZE)1379COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
1379COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)1380COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)
1381/* cec */
1382COMPATIBLE_IOCTL(CEC_ADAP_G_CAPS)
1383COMPATIBLE_IOCTL(CEC_ADAP_G_LOG_ADDRS)
1384COMPATIBLE_IOCTL(CEC_ADAP_S_LOG_ADDRS)
1385COMPATIBLE_IOCTL(CEC_ADAP_G_PHYS_ADDR)
1386COMPATIBLE_IOCTL(CEC_ADAP_S_PHYS_ADDR)
1387COMPATIBLE_IOCTL(CEC_G_MODE)
1388COMPATIBLE_IOCTL(CEC_S_MODE)
1389COMPATIBLE_IOCTL(CEC_TRANSMIT)
1390COMPATIBLE_IOCTL(CEC_RECEIVE)
1391COMPATIBLE_IOCTL(CEC_DQEVENT)
1380 1392
1381/* joystick */1393/* joystick */
1382COMPATIBLE_IOCTL(JSIOCGVERSION)1394COMPATIBLE_IOCTL(JSIOCGVERSION)
include/linux/cec-funcs.h+1881−0
@@ -0,0 +1,1881 @@
1/*
2 * cec - HDMI Consumer Electronics Control message functions
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20/*
21 * Note: this framework is still in staging and it is likely the API
22 * will change before it goes out of staging.
23 *
24 * Once it is moved out of staging this header will move to uapi.
25 */
26#ifndef _CEC_UAPI_FUNCS_H
27#define _CEC_UAPI_FUNCS_H
28
29#include <linux/cec.h>
30
31/* One Touch Play Feature */
32static inline void cec_msg_active_source(struct cec_msg *msg, __u16 phys_addr)
33{
34 msg->len = 4;
35 msg->msg[0] |= 0xf; /* broadcast */
36 msg->msg[1] = CEC_MSG_ACTIVE_SOURCE;
37 msg->msg[2] = phys_addr >> 8;
38 msg->msg[3] = phys_addr & 0xff;
39}
40
41static inline void cec_ops_active_source(const struct cec_msg *msg,
42 __u16 *phys_addr)
43{
44 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
45}
46
47static inline void cec_msg_image_view_on(struct cec_msg *msg)
48{
49 msg->len = 2;
50 msg->msg[1] = CEC_MSG_IMAGE_VIEW_ON;
51}
52
53static inline void cec_msg_text_view_on(struct cec_msg *msg)
54{
55 msg->len = 2;
56 msg->msg[1] = CEC_MSG_TEXT_VIEW_ON;
57}
58
59
60/* Routing Control Feature */
61static inline void cec_msg_inactive_source(struct cec_msg *msg,
62 __u16 phys_addr)
63{
64 msg->len = 4;
65 msg->msg[1] = CEC_MSG_INACTIVE_SOURCE;
66 msg->msg[2] = phys_addr >> 8;
67 msg->msg[3] = phys_addr & 0xff;
68}
69
70static inline void cec_ops_inactive_source(const struct cec_msg *msg,
71 __u16 *phys_addr)
72{
73 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
74}
75
76static inline void cec_msg_request_active_source(struct cec_msg *msg,
77 bool reply)
78{
79 msg->len = 2;
80 msg->msg[0] |= 0xf; /* broadcast */
81 msg->msg[1] = CEC_MSG_REQUEST_ACTIVE_SOURCE;
82 msg->reply = reply ? CEC_MSG_ACTIVE_SOURCE : 0;
83}
84
85static inline void cec_msg_routing_information(struct cec_msg *msg,
86 __u16 phys_addr)
87{
88 msg->len = 4;
89 msg->msg[0] |= 0xf; /* broadcast */
90 msg->msg[1] = CEC_MSG_ROUTING_INFORMATION;
91 msg->msg[2] = phys_addr >> 8;
92 msg->msg[3] = phys_addr & 0xff;
93}
94
95static inline void cec_ops_routing_information(const struct cec_msg *msg,
96 __u16 *phys_addr)
97{
98 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
99}
100
101static inline void cec_msg_routing_change(struct cec_msg *msg,
102 bool reply,
103 __u16 orig_phys_addr,
104 __u16 new_phys_addr)
105{
106 msg->len = 6;
107 msg->msg[0] |= 0xf; /* broadcast */
108 msg->msg[1] = CEC_MSG_ROUTING_CHANGE;
109 msg->msg[2] = orig_phys_addr >> 8;
110 msg->msg[3] = orig_phys_addr & 0xff;
111 msg->msg[4] = new_phys_addr >> 8;
112 msg->msg[5] = new_phys_addr & 0xff;
113 msg->reply = reply ? CEC_MSG_ROUTING_INFORMATION : 0;
114}
115
116static inline void cec_ops_routing_change(const struct cec_msg *msg,
117 __u16 *orig_phys_addr,
118 __u16 *new_phys_addr)
119{
120 *orig_phys_addr = (msg->msg[2] << 8) | msg->msg[3];
121 *new_phys_addr = (msg->msg[4] << 8) | msg->msg[5];
122}
123
124static inline void cec_msg_set_stream_path(struct cec_msg *msg, __u16 phys_addr)
125{
126 msg->len = 4;
127 msg->msg[0] |= 0xf; /* broadcast */
128 msg->msg[1] = CEC_MSG_SET_STREAM_PATH;
129 msg->msg[2] = phys_addr >> 8;
130 msg->msg[3] = phys_addr & 0xff;
131}
132
133static inline void cec_ops_set_stream_path(const struct cec_msg *msg,
134 __u16 *phys_addr)
135{
136 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
137}
138
139
140/* Standby Feature */
141static inline void cec_msg_standby(struct cec_msg *msg)
142{
143 msg->len = 2;
144 msg->msg[1] = CEC_MSG_STANDBY;
145}
146
147
148/* One Touch Record Feature */
149static inline void cec_msg_record_off(struct cec_msg *msg)
150{
151 msg->len = 2;
152 msg->msg[1] = CEC_MSG_RECORD_OFF;
153}
154
155struct cec_op_arib_data {
156 __u16 transport_id;
157 __u16 service_id;
158 __u16 orig_network_id;
159};
160
161struct cec_op_atsc_data {
162 __u16 transport_id;
163 __u16 program_number;
164};
165
166struct cec_op_dvb_data {
167 __u16 transport_id;
168 __u16 service_id;
169 __u16 orig_network_id;
170};
171
172struct cec_op_channel_data {
173 __u8 channel_number_fmt;
174 __u16 major;
175 __u16 minor;
176};
177
178struct cec_op_digital_service_id {
179 __u8 service_id_method;
180 __u8 dig_bcast_system;
181 union {
182 struct cec_op_arib_data arib;
183 struct cec_op_atsc_data atsc;
184 struct cec_op_dvb_data dvb;
185 struct cec_op_channel_data channel;
186 };
187};
188
189struct cec_op_record_src {
190 __u8 type;
191 union {
192 struct cec_op_digital_service_id digital;
193 struct {
194 __u8 ana_bcast_type;
195 __u16 ana_freq;
196 __u8 bcast_system;
197 } analog;
198 struct {
199 __u8 plug;
200 } ext_plug;
201 struct {
202 __u16 phys_addr;
203 } ext_phys_addr;
204 };
205};
206
207static inline void cec_set_digital_service_id(__u8 *msg,
208 const struct cec_op_digital_service_id *digital)
209{
210 *msg++ = (digital->service_id_method << 7) | digital->dig_bcast_system;
211 if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
212 *msg++ = (digital->channel.channel_number_fmt << 2) |
213 (digital->channel.major >> 8);
214 *msg++ = digital->channel.major && 0xff;
215 *msg++ = digital->channel.minor >> 8;
216 *msg++ = digital->channel.minor & 0xff;
217 *msg++ = 0;
218 *msg++ = 0;
219 return;
220 }
221 switch (digital->dig_bcast_system) {
222 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
223 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
224 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
225 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
226 *msg++ = digital->atsc.transport_id >> 8;
227 *msg++ = digital->atsc.transport_id & 0xff;
228 *msg++ = digital->atsc.program_number >> 8;
229 *msg++ = digital->atsc.program_number & 0xff;
230 *msg++ = 0;
231 *msg++ = 0;
232 break;
233 default:
234 *msg++ = digital->dvb.transport_id >> 8;
235 *msg++ = digital->dvb.transport_id & 0xff;
236 *msg++ = digital->dvb.service_id >> 8;
237 *msg++ = digital->dvb.service_id & 0xff;
238 *msg++ = digital->dvb.orig_network_id >> 8;
239 *msg++ = digital->dvb.orig_network_id & 0xff;
240 break;
241 }
242}
243
244static inline void cec_get_digital_service_id(const __u8 *msg,
245 struct cec_op_digital_service_id *digital)
246{
247 digital->service_id_method = msg[0] >> 7;
248 digital->dig_bcast_system = msg[0] & 0x7f;
249 if (digital->service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL) {
250 digital->channel.channel_number_fmt = msg[1] >> 2;
251 digital->channel.major = ((msg[1] & 3) << 6) | msg[2];
252 digital->channel.minor = (msg[3] << 8) | msg[4];
253 return;
254 }
255 digital->dvb.transport_id = (msg[1] << 8) | msg[2];
256 digital->dvb.service_id = (msg[3] << 8) | msg[4];
257 digital->dvb.orig_network_id = (msg[5] << 8) | msg[6];
258}
259
260static inline void cec_msg_record_on_own(struct cec_msg *msg)
261{
262 msg->len = 3;
263 msg->msg[1] = CEC_MSG_RECORD_ON;
264 msg->msg[2] = CEC_OP_RECORD_SRC_OWN;
265}
266
267static inline void cec_msg_record_on_digital(struct cec_msg *msg,
268 const struct cec_op_digital_service_id *digital)
269{
270 msg->len = 10;
271 msg->msg[1] = CEC_MSG_RECORD_ON;
272 msg->msg[2] = CEC_OP_RECORD_SRC_DIGITAL;
273 cec_set_digital_service_id(msg->msg + 3, digital);
274}
275
276static inline void cec_msg_record_on_analog(struct cec_msg *msg,
277 __u8 ana_bcast_type,
278 __u16 ana_freq,
279 __u8 bcast_system)
280{
281 msg->len = 7;
282 msg->msg[1] = CEC_MSG_RECORD_ON;
283 msg->msg[2] = CEC_OP_RECORD_SRC_ANALOG;
284 msg->msg[3] = ana_bcast_type;
285 msg->msg[4] = ana_freq >> 8;
286 msg->msg[5] = ana_freq & 0xff;
287 msg->msg[6] = bcast_system;
288}
289
290static inline void cec_msg_record_on_plug(struct cec_msg *msg,
291 __u8 plug)
292{
293 msg->len = 4;
294 msg->msg[1] = CEC_MSG_RECORD_ON;
295 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PLUG;
296 msg->msg[3] = plug;
297}
298
299static inline void cec_msg_record_on_phys_addr(struct cec_msg *msg,
300 __u16 phys_addr)
301{
302 msg->len = 5;
303 msg->msg[1] = CEC_MSG_RECORD_ON;
304 msg->msg[2] = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR;
305 msg->msg[3] = phys_addr >> 8;
306 msg->msg[4] = phys_addr & 0xff;
307}
308
309static inline void cec_msg_record_on(struct cec_msg *msg,
310 const struct cec_op_record_src *rec_src)
311{
312 switch (rec_src->type) {
313 case CEC_OP_RECORD_SRC_OWN:
314 cec_msg_record_on_own(msg);
315 break;
316 case CEC_OP_RECORD_SRC_DIGITAL:
317 cec_msg_record_on_digital(msg, &rec_src->digital);
318 break;
319 case CEC_OP_RECORD_SRC_ANALOG:
320 cec_msg_record_on_analog(msg,
321 rec_src->analog.ana_bcast_type,
322 rec_src->analog.ana_freq,
323 rec_src->analog.bcast_system);
324 break;
325 case CEC_OP_RECORD_SRC_EXT_PLUG:
326 cec_msg_record_on_plug(msg, rec_src->ext_plug.plug);
327 break;
328 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
329 cec_msg_record_on_phys_addr(msg,
330 rec_src->ext_phys_addr.phys_addr);
331 break;
332 }
333}
334
335static inline void cec_ops_record_on(const struct cec_msg *msg,
336 struct cec_op_record_src *rec_src)
337{
338 rec_src->type = msg->msg[2];
339 switch (rec_src->type) {
340 case CEC_OP_RECORD_SRC_OWN:
341 break;
342 case CEC_OP_RECORD_SRC_DIGITAL:
343 cec_get_digital_service_id(msg->msg + 3, &rec_src->digital);
344 break;
345 case CEC_OP_RECORD_SRC_ANALOG:
346 rec_src->analog.ana_bcast_type = msg->msg[3];
347 rec_src->analog.ana_freq =
348 (msg->msg[4] << 8) | msg->msg[5];
349 rec_src->analog.bcast_system = msg->msg[6];
350 break;
351 case CEC_OP_RECORD_SRC_EXT_PLUG:
352 rec_src->ext_plug.plug = msg->msg[3];
353 break;
354 case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
355 rec_src->ext_phys_addr.phys_addr =
356 (msg->msg[3] << 8) | msg->msg[4];
357 break;
358 }
359}
360
361static inline void cec_msg_record_status(struct cec_msg *msg, __u8 rec_status)
362{
363 msg->len = 3;
364 msg->msg[1] = CEC_MSG_RECORD_STATUS;
365 msg->msg[2] = rec_status;
366}
367
368static inline void cec_ops_record_status(const struct cec_msg *msg,
369 __u8 *rec_status)
370{
371 *rec_status = msg->msg[2];
372}
373
374static inline void cec_msg_record_tv_screen(struct cec_msg *msg,
375 bool reply)
376{
377 msg->len = 2;
378 msg->msg[1] = CEC_MSG_RECORD_TV_SCREEN;
379 msg->reply = reply ? CEC_MSG_RECORD_ON : 0;
380}
381
382
383/* Timer Programming Feature */
384static inline void cec_msg_timer_status(struct cec_msg *msg,
385 __u8 timer_overlap_warning,
386 __u8 media_info,
387 __u8 prog_info,
388 __u8 prog_error,
389 __u8 duration_hr,
390 __u8 duration_min)
391{
392 msg->len = 3;
393 msg->msg[1] = CEC_MSG_TIMER_STATUS;
394 msg->msg[2] = (timer_overlap_warning << 7) |
395 (media_info << 5) |
396 (prog_info ? 0x10 : 0) |
397 (prog_info ? prog_info : prog_error);
398 if (prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
399 prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
400 prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
401 msg->len += 2;
402 msg->msg[3] = ((duration_hr / 10) << 4) | (duration_hr % 10);
403 msg->msg[4] = ((duration_min / 10) << 4) | (duration_min % 10);
404 }
405}
406
407static inline void cec_ops_timer_status(struct cec_msg *msg,
408 __u8 *timer_overlap_warning,
409 __u8 *media_info,
410 __u8 *prog_info,
411 __u8 *prog_error,
412 __u8 *duration_hr,
413 __u8 *duration_min)
414{
415 *timer_overlap_warning = msg->msg[2] >> 7;
416 *media_info = (msg->msg[2] >> 5) & 3;
417 if (msg->msg[2] & 0x10) {
418 *prog_info = msg->msg[2] & 0xf;
419 *prog_error = 0;
420 } else {
421 *prog_info = 0;
422 *prog_error = msg->msg[2] & 0xf;
423 }
424 if (*prog_info == CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE ||
425 *prog_info == CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE ||
426 *prog_error == CEC_OP_PROG_ERROR_DUPLICATE) {
427 *duration_hr = (msg->msg[3] >> 4) * 10 + (msg->msg[3] & 0xf);
428 *duration_min = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
429 } else {
430 *duration_hr = *duration_min = 0;
431 }
432}
433
434static inline void cec_msg_timer_cleared_status(struct cec_msg *msg,
435 __u8 timer_cleared_status)
436{
437 msg->len = 3;
438 msg->msg[1] = CEC_MSG_TIMER_CLEARED_STATUS;
439 msg->msg[2] = timer_cleared_status;
440}
441
442static inline void cec_ops_timer_cleared_status(struct cec_msg *msg,
443 __u8 *timer_cleared_status)
444{
445 *timer_cleared_status = msg->msg[2];
446}
447
448static inline void cec_msg_clear_analogue_timer(struct cec_msg *msg,
449 bool reply,
450 __u8 day,
451 __u8 month,
452 __u8 start_hr,
453 __u8 start_min,
454 __u8 duration_hr,
455 __u8 duration_min,
456 __u8 recording_seq,
457 __u8 ana_bcast_type,
458 __u16 ana_freq,
459 __u8 bcast_system)
460{
461 msg->len = 13;
462 msg->msg[1] = CEC_MSG_CLEAR_ANALOGUE_TIMER;
463 msg->msg[2] = day;
464 msg->msg[3] = month;
465 /* Hours and minutes are in BCD format */
466 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
467 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
468 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
469 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
470 msg->msg[8] = recording_seq;
471 msg->msg[9] = ana_bcast_type;
472 msg->msg[10] = ana_freq >> 8;
473 msg->msg[11] = ana_freq & 0xff;
474 msg->msg[12] = bcast_system;
475 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
476}
477
478static inline void cec_ops_clear_analogue_timer(struct cec_msg *msg,
479 __u8 *day,
480 __u8 *month,
481 __u8 *start_hr,
482 __u8 *start_min,
483 __u8 *duration_hr,
484 __u8 *duration_min,
485 __u8 *recording_seq,
486 __u8 *ana_bcast_type,
487 __u16 *ana_freq,
488 __u8 *bcast_system)
489{
490 *day = msg->msg[2];
491 *month = msg->msg[3];
492 /* Hours and minutes are in BCD format */
493 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
494 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
495 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
496 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
497 *recording_seq = msg->msg[8];
498 *ana_bcast_type = msg->msg[9];
499 *ana_freq = (msg->msg[10] << 8) | msg->msg[11];
500 *bcast_system = msg->msg[12];
501}
502
503static inline void cec_msg_clear_digital_timer(struct cec_msg *msg,
504 bool reply,
505 __u8 day,
506 __u8 month,
507 __u8 start_hr,
508 __u8 start_min,
509 __u8 duration_hr,
510 __u8 duration_min,
511 __u8 recording_seq,
512 const struct cec_op_digital_service_id *digital)
513{
514 msg->len = 16;
515 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
516 msg->msg[1] = CEC_MSG_CLEAR_DIGITAL_TIMER;
517 msg->msg[2] = day;
518 msg->msg[3] = month;
519 /* Hours and minutes are in BCD format */
520 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
521 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
522 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
523 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
524 msg->msg[8] = recording_seq;
525 cec_set_digital_service_id(msg->msg + 9, digital);
526}
527
528static inline void cec_ops_clear_digital_timer(struct cec_msg *msg,
529 __u8 *day,
530 __u8 *month,
531 __u8 *start_hr,
532 __u8 *start_min,
533 __u8 *duration_hr,
534 __u8 *duration_min,
535 __u8 *recording_seq,
536 struct cec_op_digital_service_id *digital)
537{
538 *day = msg->msg[2];
539 *month = msg->msg[3];
540 /* Hours and minutes are in BCD format */
541 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
542 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
543 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
544 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
545 *recording_seq = msg->msg[8];
546 cec_get_digital_service_id(msg->msg + 9, digital);
547}
548
549static inline void cec_msg_clear_ext_timer(struct cec_msg *msg,
550 bool reply,
551 __u8 day,
552 __u8 month,
553 __u8 start_hr,
554 __u8 start_min,
555 __u8 duration_hr,
556 __u8 duration_min,
557 __u8 recording_seq,
558 __u8 ext_src_spec,
559 __u8 plug,
560 __u16 phys_addr)
561{
562 msg->len = 13;
563 msg->msg[1] = CEC_MSG_CLEAR_EXT_TIMER;
564 msg->msg[2] = day;
565 msg->msg[3] = month;
566 /* Hours and minutes are in BCD format */
567 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
568 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
569 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
570 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
571 msg->msg[8] = recording_seq;
572 msg->msg[9] = ext_src_spec;
573 msg->msg[10] = plug;
574 msg->msg[11] = phys_addr >> 8;
575 msg->msg[12] = phys_addr & 0xff;
576 msg->reply = reply ? CEC_MSG_TIMER_CLEARED_STATUS : 0;
577}
578
579static inline void cec_ops_clear_ext_timer(struct cec_msg *msg,
580 __u8 *day,
581 __u8 *month,
582 __u8 *start_hr,
583 __u8 *start_min,
584 __u8 *duration_hr,
585 __u8 *duration_min,
586 __u8 *recording_seq,
587 __u8 *ext_src_spec,
588 __u8 *plug,
589 __u16 *phys_addr)
590{
591 *day = msg->msg[2];
592 *month = msg->msg[3];
593 /* Hours and minutes are in BCD format */
594 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
595 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
596 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
597 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
598 *recording_seq = msg->msg[8];
599 *ext_src_spec = msg->msg[9];
600 *plug = msg->msg[10];
601 *phys_addr = (msg->msg[11] << 8) | msg->msg[12];
602}
603
604static inline void cec_msg_set_analogue_timer(struct cec_msg *msg,
605 bool reply,
606 __u8 day,
607 __u8 month,
608 __u8 start_hr,
609 __u8 start_min,
610 __u8 duration_hr,
611 __u8 duration_min,
612 __u8 recording_seq,
613 __u8 ana_bcast_type,
614 __u16 ana_freq,
615 __u8 bcast_system)
616{
617 msg->len = 13;
618 msg->msg[1] = CEC_MSG_SET_ANALOGUE_TIMER;
619 msg->msg[2] = day;
620 msg->msg[3] = month;
621 /* Hours and minutes are in BCD format */
622 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
623 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
624 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
625 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
626 msg->msg[8] = recording_seq;
627 msg->msg[9] = ana_bcast_type;
628 msg->msg[10] = ana_freq >> 8;
629 msg->msg[11] = ana_freq & 0xff;
630 msg->msg[12] = bcast_system;
631 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
632}
633
634static inline void cec_ops_set_analogue_timer(struct cec_msg *msg,
635 __u8 *day,
636 __u8 *month,
637 __u8 *start_hr,
638 __u8 *start_min,
639 __u8 *duration_hr,
640 __u8 *duration_min,
641 __u8 *recording_seq,
642 __u8 *ana_bcast_type,
643 __u16 *ana_freq,
644 __u8 *bcast_system)
645{
646 *day = msg->msg[2];
647 *month = msg->msg[3];
648 /* Hours and minutes are in BCD format */
649 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
650 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
651 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
652 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
653 *recording_seq = msg->msg[8];
654 *ana_bcast_type = msg->msg[9];
655 *ana_freq = (msg->msg[10] << 8) | msg->msg[11];
656 *bcast_system = msg->msg[12];
657}
658
659static inline void cec_msg_set_digital_timer(struct cec_msg *msg,
660 bool reply,
661 __u8 day,
662 __u8 month,
663 __u8 start_hr,
664 __u8 start_min,
665 __u8 duration_hr,
666 __u8 duration_min,
667 __u8 recording_seq,
668 const struct cec_op_digital_service_id *digital)
669{
670 msg->len = 16;
671 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
672 msg->msg[1] = CEC_MSG_SET_DIGITAL_TIMER;
673 msg->msg[2] = day;
674 msg->msg[3] = month;
675 /* Hours and minutes are in BCD format */
676 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
677 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
678 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
679 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
680 msg->msg[8] = recording_seq;
681 cec_set_digital_service_id(msg->msg + 9, digital);
682}
683
684static inline void cec_ops_set_digital_timer(struct cec_msg *msg,
685 __u8 *day,
686 __u8 *month,
687 __u8 *start_hr,
688 __u8 *start_min,
689 __u8 *duration_hr,
690 __u8 *duration_min,
691 __u8 *recording_seq,
692 struct cec_op_digital_service_id *digital)
693{
694 *day = msg->msg[2];
695 *month = msg->msg[3];
696 /* Hours and minutes are in BCD format */
697 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
698 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
699 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
700 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
701 *recording_seq = msg->msg[8];
702 cec_get_digital_service_id(msg->msg + 9, digital);
703}
704
705static inline void cec_msg_set_ext_timer(struct cec_msg *msg,
706 bool reply,
707 __u8 day,
708 __u8 month,
709 __u8 start_hr,
710 __u8 start_min,
711 __u8 duration_hr,
712 __u8 duration_min,
713 __u8 recording_seq,
714 __u8 ext_src_spec,
715 __u8 plug,
716 __u16 phys_addr)
717{
718 msg->len = 13;
719 msg->msg[1] = CEC_MSG_SET_EXT_TIMER;
720 msg->msg[2] = day;
721 msg->msg[3] = month;
722 /* Hours and minutes are in BCD format */
723 msg->msg[4] = ((start_hr / 10) << 4) | (start_hr % 10);
724 msg->msg[5] = ((start_min / 10) << 4) | (start_min % 10);
725 msg->msg[6] = ((duration_hr / 10) << 4) | (duration_hr % 10);
726 msg->msg[7] = ((duration_min / 10) << 4) | (duration_min % 10);
727 msg->msg[8] = recording_seq;
728 msg->msg[9] = ext_src_spec;
729 msg->msg[10] = plug;
730 msg->msg[11] = phys_addr >> 8;
731 msg->msg[12] = phys_addr & 0xff;
732 msg->reply = reply ? CEC_MSG_TIMER_STATUS : 0;
733}
734
735static inline void cec_ops_set_ext_timer(struct cec_msg *msg,
736 __u8 *day,
737 __u8 *month,
738 __u8 *start_hr,
739 __u8 *start_min,
740 __u8 *duration_hr,
741 __u8 *duration_min,
742 __u8 *recording_seq,
743 __u8 *ext_src_spec,
744 __u8 *plug,
745 __u16 *phys_addr)
746{
747 *day = msg->msg[2];
748 *month = msg->msg[3];
749 /* Hours and minutes are in BCD format */
750 *start_hr = (msg->msg[4] >> 4) * 10 + (msg->msg[4] & 0xf);
751 *start_min = (msg->msg[5] >> 4) * 10 + (msg->msg[5] & 0xf);
752 *duration_hr = (msg->msg[6] >> 4) * 10 + (msg->msg[6] & 0xf);
753 *duration_min = (msg->msg[7] >> 4) * 10 + (msg->msg[7] & 0xf);
754 *recording_seq = msg->msg[8];
755 *ext_src_spec = msg->msg[9];
756 *plug = msg->msg[10];
757 *phys_addr = (msg->msg[11] << 8) | msg->msg[12];
758}
759
760static inline void cec_msg_set_timer_program_title(struct cec_msg *msg,
761 const char *prog_title)
762{
763 unsigned int len = strlen(prog_title);
764
765 if (len > 14)
766 len = 14;
767 msg->len = 2 + len;
768 msg->msg[1] = CEC_MSG_SET_TIMER_PROGRAM_TITLE;
769 memcpy(msg->msg + 2, prog_title, len);
770}
771
772static inline void cec_ops_set_timer_program_title(const struct cec_msg *msg,
773 char *prog_title)
774{
775 unsigned int len = msg->len - 2;
776
777 if (len > 14)
778 len = 14;
779 memcpy(prog_title, msg->msg + 2, len);
780 prog_title[len] = '\0';
781}
782
783/* System Information Feature */
784static inline void cec_msg_cec_version(struct cec_msg *msg, __u8 cec_version)
785{
786 msg->len = 3;
787 msg->msg[1] = CEC_MSG_CEC_VERSION;
788 msg->msg[2] = cec_version;
789}
790
791static inline void cec_ops_cec_version(const struct cec_msg *msg,
792 __u8 *cec_version)
793{
794 *cec_version = msg->msg[2];
795}
796
797static inline void cec_msg_get_cec_version(struct cec_msg *msg,
798 bool reply)
799{
800 msg->len = 2;
801 msg->msg[1] = CEC_MSG_GET_CEC_VERSION;
802 msg->reply = reply ? CEC_MSG_CEC_VERSION : 0;
803}
804
805static inline void cec_msg_report_physical_addr(struct cec_msg *msg,
806 __u16 phys_addr, __u8 prim_devtype)
807{
808 msg->len = 5;
809 msg->msg[0] |= 0xf; /* broadcast */
810 msg->msg[1] = CEC_MSG_REPORT_PHYSICAL_ADDR;
811 msg->msg[2] = phys_addr >> 8;
812 msg->msg[3] = phys_addr & 0xff;
813 msg->msg[4] = prim_devtype;
814}
815
816static inline void cec_ops_report_physical_addr(const struct cec_msg *msg,
817 __u16 *phys_addr, __u8 *prim_devtype)
818{
819 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
820 *prim_devtype = msg->msg[4];
821}
822
823static inline void cec_msg_give_physical_addr(struct cec_msg *msg,
824 bool reply)
825{
826 msg->len = 2;
827 msg->msg[1] = CEC_MSG_GIVE_PHYSICAL_ADDR;
828 msg->reply = reply ? CEC_MSG_REPORT_PHYSICAL_ADDR : 0;
829}
830
831static inline void cec_msg_set_menu_language(struct cec_msg *msg,
832 const char *language)
833{
834 msg->len = 5;
835 msg->msg[0] |= 0xf; /* broadcast */
836 msg->msg[1] = CEC_MSG_SET_MENU_LANGUAGE;
837 memcpy(msg->msg + 2, language, 3);
838}
839
840static inline void cec_ops_set_menu_language(struct cec_msg *msg,
841 char *language)
842{
843 memcpy(language, msg->msg + 2, 3);
844 language[3] = '\0';
845}
846
847static inline void cec_msg_get_menu_language(struct cec_msg *msg,
848 bool reply)
849{
850 msg->len = 2;
851 msg->msg[1] = CEC_MSG_GET_MENU_LANGUAGE;
852 msg->reply = reply ? CEC_MSG_SET_MENU_LANGUAGE : 0;
853}
854
855/*
856 * Assumes a single RC Profile byte and a single Device Features byte,
857 * i.e. no extended features are supported by this helper function.
858 *
859 * As of CEC 2.0 no extended features are defined, should those be added
860 * in the future, then this function needs to be adapted or a new function
861 * should be added.
862 */
863static inline void cec_msg_report_features(struct cec_msg *msg,
864 __u8 cec_version, __u8 all_device_types,
865 __u8 rc_profile, __u8 dev_features)
866{
867 msg->len = 6;
868 msg->msg[0] |= 0xf; /* broadcast */
869 msg->msg[1] = CEC_MSG_REPORT_FEATURES;
870 msg->msg[2] = cec_version;
871 msg->msg[3] = all_device_types;
872 msg->msg[4] = rc_profile;
873 msg->msg[5] = dev_features;
874}
875
876static inline void cec_ops_report_features(const struct cec_msg *msg,
877 __u8 *cec_version, __u8 *all_device_types,
878 const __u8 **rc_profile, const __u8 **dev_features)
879{
880 const __u8 *p = &msg->msg[4];
881
882 *cec_version = msg->msg[2];
883 *all_device_types = msg->msg[3];
884 *rc_profile = p;
885 while (p < &msg->msg[14] && (*p & CEC_OP_FEAT_EXT))
886 p++;
887 if (!(*p & CEC_OP_FEAT_EXT)) {
888 *dev_features = p + 1;
889 while (p < &msg->msg[15] && (*p & CEC_OP_FEAT_EXT))
890 p++;
891 }
892 if (*p & CEC_OP_FEAT_EXT)
893 *rc_profile = *dev_features = NULL;
894}
895
896static inline void cec_msg_give_features(struct cec_msg *msg,
897 bool reply)
898{
899 msg->len = 2;
900 msg->msg[1] = CEC_MSG_GIVE_FEATURES;
901 msg->reply = reply ? CEC_MSG_REPORT_FEATURES : 0;
902}
903
904/* Deck Control Feature */
905static inline void cec_msg_deck_control(struct cec_msg *msg,
906 __u8 deck_control_mode)
907{
908 msg->len = 3;
909 msg->msg[1] = CEC_MSG_DECK_CONTROL;
910 msg->msg[2] = deck_control_mode;
911}
912
913static inline void cec_ops_deck_control(struct cec_msg *msg,
914 __u8 *deck_control_mode)
915{
916 *deck_control_mode = msg->msg[2];
917}
918
919static inline void cec_msg_deck_status(struct cec_msg *msg,
920 __u8 deck_info)
921{
922 msg->len = 3;
923 msg->msg[1] = CEC_MSG_DECK_STATUS;
924 msg->msg[2] = deck_info;
925}
926
927static inline void cec_ops_deck_status(struct cec_msg *msg,
928 __u8 *deck_info)
929{
930 *deck_info = msg->msg[2];
931}
932
933static inline void cec_msg_give_deck_status(struct cec_msg *msg,
934 bool reply,
935 __u8 status_req)
936{
937 msg->len = 3;
938 msg->msg[1] = CEC_MSG_GIVE_DECK_STATUS;
939 msg->msg[2] = status_req;
940 msg->reply = reply ? CEC_MSG_DECK_STATUS : 0;
941}
942
943static inline void cec_ops_give_deck_status(struct cec_msg *msg,
944 __u8 *status_req)
945{
946 *status_req = msg->msg[2];
947}
948
949static inline void cec_msg_play(struct cec_msg *msg,
950 __u8 play_mode)
951{
952 msg->len = 3;
953 msg->msg[1] = CEC_MSG_PLAY;
954 msg->msg[2] = play_mode;
955}
956
957static inline void cec_ops_play(struct cec_msg *msg,
958 __u8 *play_mode)
959{
960 *play_mode = msg->msg[2];
961}
962
963
964/* Tuner Control Feature */
965struct cec_op_tuner_device_info {
966 __u8 rec_flag;
967 __u8 tuner_display_info;
968 bool is_analog;
969 union {
970 struct cec_op_digital_service_id digital;
971 struct {
972 __u8 ana_bcast_type;
973 __u16 ana_freq;
974 __u8 bcast_system;
975 } analog;
976 };
977};
978
979static inline void cec_msg_tuner_device_status_analog(struct cec_msg *msg,
980 __u8 rec_flag,
981 __u8 tuner_display_info,
982 __u8 ana_bcast_type,
983 __u16 ana_freq,
984 __u8 bcast_system)
985{
986 msg->len = 7;
987 msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
988 msg->msg[2] = (rec_flag << 7) | tuner_display_info;
989 msg->msg[3] = ana_bcast_type;
990 msg->msg[4] = ana_freq >> 8;
991 msg->msg[5] = ana_freq & 0xff;
992 msg->msg[6] = bcast_system;
993}
994
995static inline void cec_msg_tuner_device_status_digital(struct cec_msg *msg,
996 __u8 rec_flag, __u8 tuner_display_info,
997 const struct cec_op_digital_service_id *digital)
998{
999 msg->len = 10;
1000 msg->msg[1] = CEC_MSG_TUNER_DEVICE_STATUS;
1001 msg->msg[2] = (rec_flag << 7) | tuner_display_info;
1002 cec_set_digital_service_id(msg->msg + 3, digital);
1003}
1004
1005static inline void cec_msg_tuner_device_status(struct cec_msg *msg,
1006 const struct cec_op_tuner_device_info *tuner_dev_info)
1007{
1008 if (tuner_dev_info->is_analog)
1009 cec_msg_tuner_device_status_analog(msg,
1010 tuner_dev_info->rec_flag,
1011 tuner_dev_info->tuner_display_info,
1012 tuner_dev_info->analog.ana_bcast_type,
1013 tuner_dev_info->analog.ana_freq,
1014 tuner_dev_info->analog.bcast_system);
1015 else
1016 cec_msg_tuner_device_status_digital(msg,
1017 tuner_dev_info->rec_flag,
1018 tuner_dev_info->tuner_display_info,
1019 &tuner_dev_info->digital);
1020}
1021
1022static inline void cec_ops_tuner_device_status(struct cec_msg *msg,
1023 struct cec_op_tuner_device_info *tuner_dev_info)
1024{
1025 tuner_dev_info->is_analog = msg->len < 10;
1026 tuner_dev_info->rec_flag = msg->msg[2] >> 7;
1027 tuner_dev_info->tuner_display_info = msg->msg[2] & 0x7f;
1028 if (tuner_dev_info->is_analog) {
1029 tuner_dev_info->analog.ana_bcast_type = msg->msg[3];
1030 tuner_dev_info->analog.ana_freq = (msg->msg[4] << 8) | msg->msg[5];
1031 tuner_dev_info->analog.bcast_system = msg->msg[6];
1032 return;
1033 }
1034 cec_get_digital_service_id(msg->msg + 3, &tuner_dev_info->digital);
1035}
1036
1037static inline void cec_msg_give_tuner_device_status(struct cec_msg *msg,
1038 bool reply,
1039 __u8 status_req)
1040{
1041 msg->len = 3;
1042 msg->msg[1] = CEC_MSG_GIVE_TUNER_DEVICE_STATUS;
1043 msg->msg[2] = status_req;
1044 msg->reply = reply ? CEC_MSG_TUNER_DEVICE_STATUS : 0;
1045}
1046
1047static inline void cec_ops_give_tuner_device_status(struct cec_msg *msg,
1048 __u8 *status_req)
1049{
1050 *status_req = msg->msg[2];
1051}
1052
1053static inline void cec_msg_select_analogue_service(struct cec_msg *msg,
1054 __u8 ana_bcast_type,
1055 __u16 ana_freq,
1056 __u8 bcast_system)
1057{
1058 msg->len = 6;
1059 msg->msg[1] = CEC_MSG_SELECT_ANALOGUE_SERVICE;
1060 msg->msg[2] = ana_bcast_type;
1061 msg->msg[3] = ana_freq >> 8;
1062 msg->msg[4] = ana_freq & 0xff;
1063 msg->msg[5] = bcast_system;
1064}
1065
1066static inline void cec_ops_select_analogue_service(struct cec_msg *msg,
1067 __u8 *ana_bcast_type,
1068 __u16 *ana_freq,
1069 __u8 *bcast_system)
1070{
1071 *ana_bcast_type = msg->msg[2];
1072 *ana_freq = (msg->msg[3] << 8) | msg->msg[4];
1073 *bcast_system = msg->msg[5];
1074}
1075
1076static inline void cec_msg_select_digital_service(struct cec_msg *msg,
1077 const struct cec_op_digital_service_id *digital)
1078{
1079 msg->len = 9;
1080 msg->msg[1] = CEC_MSG_SELECT_DIGITAL_SERVICE;
1081 cec_set_digital_service_id(msg->msg + 2, digital);
1082}
1083
1084static inline void cec_ops_select_digital_service(struct cec_msg *msg,
1085 struct cec_op_digital_service_id *digital)
1086{
1087 cec_get_digital_service_id(msg->msg + 2, digital);
1088}
1089
1090static inline void cec_msg_tuner_step_decrement(struct cec_msg *msg)
1091{
1092 msg->len = 2;
1093 msg->msg[1] = CEC_MSG_TUNER_STEP_DECREMENT;
1094}
1095
1096static inline void cec_msg_tuner_step_increment(struct cec_msg *msg)
1097{
1098 msg->len = 2;
1099 msg->msg[1] = CEC_MSG_TUNER_STEP_INCREMENT;
1100}
1101
1102
1103/* Vendor Specific Commands Feature */
1104static inline void cec_msg_device_vendor_id(struct cec_msg *msg, __u32 vendor_id)
1105{
1106 msg->len = 5;
1107 msg->msg[0] |= 0xf; /* broadcast */
1108 msg->msg[1] = CEC_MSG_DEVICE_VENDOR_ID;
1109 msg->msg[2] = vendor_id >> 16;
1110 msg->msg[3] = (vendor_id >> 8) & 0xff;
1111 msg->msg[4] = vendor_id & 0xff;
1112}
1113
1114static inline void cec_ops_device_vendor_id(const struct cec_msg *msg,
1115 __u32 *vendor_id)
1116{
1117 *vendor_id = (msg->msg[2] << 16) | (msg->msg[3] << 8) | msg->msg[4];
1118}
1119
1120static inline void cec_msg_give_device_vendor_id(struct cec_msg *msg,
1121 bool reply)
1122{
1123 msg->len = 2;
1124 msg->msg[1] = CEC_MSG_GIVE_DEVICE_VENDOR_ID;
1125 msg->reply = reply ? CEC_MSG_DEVICE_VENDOR_ID : 0;
1126}
1127
1128static inline void cec_msg_vendor_remote_button_up(struct cec_msg *msg)
1129{
1130 msg->len = 2;
1131 msg->msg[1] = CEC_MSG_VENDOR_REMOTE_BUTTON_UP;
1132}
1133
1134
1135/* OSD Display Feature */
1136static inline void cec_msg_set_osd_string(struct cec_msg *msg,
1137 __u8 disp_ctl,
1138 const char *osd)
1139{
1140 unsigned int len = strlen(osd);
1141
1142 if (len > 13)
1143 len = 13;
1144 msg->len = 3 + len;
1145 msg->msg[1] = CEC_MSG_SET_OSD_STRING;
1146 msg->msg[2] = disp_ctl;
1147 memcpy(msg->msg + 3, osd, len);
1148}
1149
1150static inline void cec_ops_set_osd_string(const struct cec_msg *msg,
1151 __u8 *disp_ctl,
1152 char *osd)
1153{
1154 unsigned int len = msg->len - 3;
1155
1156 *disp_ctl = msg->msg[2];
1157 if (len > 13)
1158 len = 13;
1159 memcpy(osd, msg->msg + 3, len);
1160 osd[len] = '\0';
1161}
1162
1163
1164/* Device OSD Transfer Feature */
1165static inline void cec_msg_set_osd_name(struct cec_msg *msg, const char *name)
1166{
1167 unsigned int len = strlen(name);
1168
1169 if (len > 14)
1170 len = 14;
1171 msg->len = 2 + len;
1172 msg->msg[1] = CEC_MSG_SET_OSD_NAME;
1173 memcpy(msg->msg + 2, name, len);
1174}
1175
1176static inline void cec_ops_set_osd_name(const struct cec_msg *msg,
1177 char *name)
1178{
1179 unsigned int len = msg->len - 2;
1180
1181 if (len > 14)
1182 len = 14;
1183 memcpy(name, msg->msg + 2, len);
1184 name[len] = '\0';
1185}
1186
1187static inline void cec_msg_give_osd_name(struct cec_msg *msg,
1188 bool reply)
1189{
1190 msg->len = 2;
1191 msg->msg[1] = CEC_MSG_GIVE_OSD_NAME;
1192 msg->reply = reply ? CEC_MSG_SET_OSD_NAME : 0;
1193}
1194
1195
1196/* Device Menu Control Feature */
1197static inline void cec_msg_menu_status(struct cec_msg *msg,
1198 __u8 menu_state)
1199{
1200 msg->len = 3;
1201 msg->msg[1] = CEC_MSG_MENU_STATUS;
1202 msg->msg[2] = menu_state;
1203}
1204
1205static inline void cec_ops_menu_status(struct cec_msg *msg,
1206 __u8 *menu_state)
1207{
1208 *menu_state = msg->msg[2];
1209}
1210
1211static inline void cec_msg_menu_request(struct cec_msg *msg,
1212 bool reply,
1213 __u8 menu_req)
1214{
1215 msg->len = 3;
1216 msg->msg[1] = CEC_MSG_MENU_REQUEST;
1217 msg->msg[2] = menu_req;
1218 msg->reply = reply ? CEC_MSG_MENU_STATUS : 0;
1219}
1220
1221static inline void cec_ops_menu_request(struct cec_msg *msg,
1222 __u8 *menu_req)
1223{
1224 *menu_req = msg->msg[2];
1225}
1226
1227struct cec_op_ui_command {
1228 __u8 ui_cmd;
1229 bool has_opt_arg;
1230 union {
1231 struct cec_op_channel_data channel_identifier;
1232 __u8 ui_broadcast_type;
1233 __u8 ui_sound_presentation_control;
1234 __u8 play_mode;
1235 __u8 ui_function_media;
1236 __u8 ui_function_select_av_input;
1237 __u8 ui_function_select_audio_input;
1238 };
1239};
1240
1241static inline void cec_msg_user_control_pressed(struct cec_msg *msg,
1242 const struct cec_op_ui_command *ui_cmd)
1243{
1244 msg->len = 3;
1245 msg->msg[1] = CEC_MSG_USER_CONTROL_PRESSED;
1246 msg->msg[2] = ui_cmd->ui_cmd;
1247 if (!ui_cmd->has_opt_arg)
1248 return;
1249 switch (ui_cmd->ui_cmd) {
1250 case 0x56:
1251 case 0x57:
1252 case 0x60:
1253 case 0x68:
1254 case 0x69:
1255 case 0x6a:
1256 /* The optional operand is one byte for all these ui commands */
1257 msg->len++;
1258 msg->msg[3] = ui_cmd->play_mode;
1259 break;
1260 case 0x67:
1261 msg->len += 4;
1262 msg->msg[3] = (ui_cmd->channel_identifier.channel_number_fmt << 2) |
1263 (ui_cmd->channel_identifier.major >> 8);
1264 msg->msg[4] = ui_cmd->channel_identifier.major && 0xff;
1265 msg->msg[5] = ui_cmd->channel_identifier.minor >> 8;
1266 msg->msg[6] = ui_cmd->channel_identifier.minor & 0xff;
1267 break;
1268 }
1269}
1270
1271static inline void cec_ops_user_control_pressed(struct cec_msg *msg,
1272 struct cec_op_ui_command *ui_cmd)
1273{
1274 ui_cmd->ui_cmd = msg->msg[2];
1275 ui_cmd->has_opt_arg = false;
1276 if (msg->len == 3)
1277 return;
1278 switch (ui_cmd->ui_cmd) {
1279 case 0x56:
1280 case 0x57:
1281 case 0x60:
1282 case 0x68:
1283 case 0x69:
1284 case 0x6a:
1285 /* The optional operand is one byte for all these ui commands */
1286 ui_cmd->play_mode = msg->msg[3];
1287 ui_cmd->has_opt_arg = true;
1288 break;
1289 case 0x67:
1290 if (msg->len < 7)
1291 break;
1292 ui_cmd->has_opt_arg = true;
1293 ui_cmd->channel_identifier.channel_number_fmt = msg->msg[3] >> 2;
1294 ui_cmd->channel_identifier.major = ((msg->msg[3] & 3) << 6) | msg->msg[4];
1295 ui_cmd->channel_identifier.minor = (msg->msg[5] << 8) | msg->msg[6];
1296 break;
1297 }
1298}
1299
1300static inline void cec_msg_user_control_released(struct cec_msg *msg)
1301{
1302 msg->len = 2;
1303 msg->msg[1] = CEC_MSG_USER_CONTROL_RELEASED;
1304}
1305
1306/* Remote Control Passthrough Feature */
1307
1308/* Power Status Feature */
1309static inline void cec_msg_report_power_status(struct cec_msg *msg,
1310 __u8 pwr_state)
1311{
1312 msg->len = 3;
1313 msg->msg[1] = CEC_MSG_REPORT_POWER_STATUS;
1314 msg->msg[2] = pwr_state;
1315}
1316
1317static inline void cec_ops_report_power_status(const struct cec_msg *msg,
1318 __u8 *pwr_state)
1319{
1320 *pwr_state = msg->msg[2];
1321}
1322
1323static inline void cec_msg_give_device_power_status(struct cec_msg *msg,
1324 bool reply)
1325{
1326 msg->len = 2;
1327 msg->msg[1] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
1328 msg->reply = reply ? CEC_MSG_REPORT_POWER_STATUS : 0;
1329}
1330
1331/* General Protocol Messages */
1332static inline void cec_msg_feature_abort(struct cec_msg *msg,
1333 __u8 abort_msg, __u8 reason)
1334{
1335 msg->len = 4;
1336 msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1337 msg->msg[2] = abort_msg;
1338 msg->msg[3] = reason;
1339}
1340
1341static inline void cec_ops_feature_abort(const struct cec_msg *msg,
1342 __u8 *abort_msg, __u8 *reason)
1343{
1344 *abort_msg = msg->msg[2];
1345 *reason = msg->msg[3];
1346}
1347
1348/* This changes the current message into a feature abort message */
1349static inline void cec_msg_reply_feature_abort(struct cec_msg *msg, __u8 reason)
1350{
1351 cec_msg_set_reply_to(msg, msg);
1352 msg->len = 4;
1353 msg->msg[2] = msg->msg[1];
1354 msg->msg[3] = reason;
1355 msg->msg[1] = CEC_MSG_FEATURE_ABORT;
1356}
1357
1358static inline void cec_msg_abort(struct cec_msg *msg)
1359{
1360 msg->len = 2;
1361 msg->msg[1] = CEC_MSG_ABORT;
1362}
1363
1364
1365/* System Audio Control Feature */
1366static inline void cec_msg_report_audio_status(struct cec_msg *msg,
1367 __u8 aud_mute_status,
1368 __u8 aud_vol_status)
1369{
1370 msg->len = 3;
1371 msg->msg[1] = CEC_MSG_REPORT_AUDIO_STATUS;
1372 msg->msg[2] = (aud_mute_status << 7) | (aud_vol_status & 0x7f);
1373}
1374
1375static inline void cec_ops_report_audio_status(const struct cec_msg *msg,
1376 __u8 *aud_mute_status,
1377 __u8 *aud_vol_status)
1378{
1379 *aud_mute_status = msg->msg[2] >> 7;
1380 *aud_vol_status = msg->msg[2] & 0x7f;
1381}
1382
1383static inline void cec_msg_give_audio_status(struct cec_msg *msg,
1384 bool reply)
1385{
1386 msg->len = 2;
1387 msg->msg[1] = CEC_MSG_GIVE_AUDIO_STATUS;
1388 msg->reply = reply ? CEC_MSG_REPORT_AUDIO_STATUS : 0;
1389}
1390
1391static inline void cec_msg_set_system_audio_mode(struct cec_msg *msg,
1392 __u8 sys_aud_status)
1393{
1394 msg->len = 3;
1395 msg->msg[1] = CEC_MSG_SET_SYSTEM_AUDIO_MODE;
1396 msg->msg[2] = sys_aud_status;
1397}
1398
1399static inline void cec_ops_set_system_audio_mode(const struct cec_msg *msg,
1400 __u8 *sys_aud_status)
1401{
1402 *sys_aud_status = msg->msg[2];
1403}
1404
1405static inline void cec_msg_system_audio_mode_request(struct cec_msg *msg,
1406 bool reply,
1407 __u16 phys_addr)
1408{
1409 msg->len = phys_addr == 0xffff ? 2 : 4;
1410 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST;
1411 msg->msg[2] = phys_addr >> 8;
1412 msg->msg[3] = phys_addr & 0xff;
1413 msg->reply = reply ? CEC_MSG_SET_SYSTEM_AUDIO_MODE : 0;
1414
1415}
1416
1417static inline void cec_ops_system_audio_mode_request(const struct cec_msg *msg,
1418 __u16 *phys_addr)
1419{
1420 if (msg->len < 4)
1421 *phys_addr = 0xffff;
1422 else
1423 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1424}
1425
1426static inline void cec_msg_system_audio_mode_status(struct cec_msg *msg,
1427 __u8 sys_aud_status)
1428{
1429 msg->len = 3;
1430 msg->msg[1] = CEC_MSG_SYSTEM_AUDIO_MODE_STATUS;
1431 msg->msg[2] = sys_aud_status;
1432}
1433
1434static inline void cec_ops_system_audio_mode_status(const struct cec_msg *msg,
1435 __u8 *sys_aud_status)
1436{
1437 *sys_aud_status = msg->msg[2];
1438}
1439
1440static inline void cec_msg_give_system_audio_mode_status(struct cec_msg *msg,
1441 bool reply)
1442{
1443 msg->len = 2;
1444 msg->msg[1] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
1445 msg->reply = reply ? CEC_MSG_SYSTEM_AUDIO_MODE_STATUS : 0;
1446}
1447
1448static inline void cec_msg_report_short_audio_descriptor(struct cec_msg *msg,
1449 __u8 num_descriptors,
1450 const __u32 *descriptors)
1451{
1452 unsigned int i;
1453
1454 if (num_descriptors > 4)
1455 num_descriptors = 4;
1456 msg->len = 2 + num_descriptors * 3;
1457 msg->msg[1] = CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR;
1458 for (i = 0; i < num_descriptors; i++) {
1459 msg->msg[2 + i * 3] = (descriptors[i] >> 16) & 0xff;
1460 msg->msg[3 + i * 3] = (descriptors[i] >> 8) & 0xff;
1461 msg->msg[4 + i * 3] = descriptors[i] & 0xff;
1462 }
1463}
1464
1465static inline void cec_ops_report_short_audio_descriptor(const struct cec_msg *msg,
1466 __u8 *num_descriptors,
1467 __u32 *descriptors)
1468{
1469 unsigned int i;
1470
1471 *num_descriptors = (msg->len - 2) / 3;
1472 if (*num_descriptors > 4)
1473 *num_descriptors = 4;
1474 for (i = 0; i < *num_descriptors; i++)
1475 descriptors[i] = (msg->msg[2 + i * 3] << 16) |
1476 (msg->msg[3 + i * 3] << 8) |
1477 msg->msg[4 + i * 3];
1478}
1479
1480static inline void cec_msg_request_short_audio_descriptor(struct cec_msg *msg,
1481 __u8 num_descriptors,
1482 const __u8 *audio_format_id,
1483 const __u8 *audio_format_code)
1484{
1485 unsigned int i;
1486
1487 if (num_descriptors > 4)
1488 num_descriptors = 4;
1489 msg->len = 2 + num_descriptors;
1490 msg->msg[1] = CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR;
1491 for (i = 0; i < num_descriptors; i++)
1492 msg->msg[2 + i] = (audio_format_id[i] << 6) |
1493 (audio_format_code[i] & 0x3f);
1494}
1495
1496static inline void cec_ops_request_short_audio_descriptor(const struct cec_msg *msg,
1497 __u8 *num_descriptors,
1498 __u8 *audio_format_id,
1499 __u8 *audio_format_code)
1500{
1501 unsigned int i;
1502
1503 *num_descriptors = msg->len - 2;
1504 if (*num_descriptors > 4)
1505 *num_descriptors = 4;
1506 for (i = 0; i < *num_descriptors; i++) {
1507 audio_format_id[i] = msg->msg[2 + i] >> 6;
1508 audio_format_code[i] = msg->msg[2 + i] & 0x3f;
1509 }
1510}
1511
1512
1513/* Audio Rate Control Feature */
1514static inline void cec_msg_set_audio_rate(struct cec_msg *msg,
1515 __u8 audio_rate)
1516{
1517 msg->len = 3;
1518 msg->msg[1] = CEC_MSG_SET_AUDIO_RATE;
1519 msg->msg[2] = audio_rate;
1520}
1521
1522static inline void cec_ops_set_audio_rate(const struct cec_msg *msg,
1523 __u8 *audio_rate)
1524{
1525 *audio_rate = msg->msg[2];
1526}
1527
1528
1529/* Audio Return Channel Control Feature */
1530static inline void cec_msg_report_arc_initiated(struct cec_msg *msg)
1531{
1532 msg->len = 2;
1533 msg->msg[1] = CEC_MSG_REPORT_ARC_INITIATED;
1534}
1535
1536static inline void cec_msg_initiate_arc(struct cec_msg *msg,
1537 bool reply)
1538{
1539 msg->len = 2;
1540 msg->msg[1] = CEC_MSG_INITIATE_ARC;
1541 msg->reply = reply ? CEC_MSG_REPORT_ARC_INITIATED : 0;
1542}
1543
1544static inline void cec_msg_request_arc_initiation(struct cec_msg *msg,
1545 bool reply)
1546{
1547 msg->len = 2;
1548 msg->msg[1] = CEC_MSG_REQUEST_ARC_INITIATION;
1549 msg->reply = reply ? CEC_MSG_INITIATE_ARC : 0;
1550}
1551
1552static inline void cec_msg_report_arc_terminated(struct cec_msg *msg)
1553{
1554 msg->len = 2;
1555 msg->msg[1] = CEC_MSG_REPORT_ARC_TERMINATED;
1556}
1557
1558static inline void cec_msg_terminate_arc(struct cec_msg *msg,
1559 bool reply)
1560{
1561 msg->len = 2;
1562 msg->msg[1] = CEC_MSG_TERMINATE_ARC;
1563 msg->reply = reply ? CEC_MSG_REPORT_ARC_TERMINATED : 0;
1564}
1565
1566static inline void cec_msg_request_arc_termination(struct cec_msg *msg,
1567 bool reply)
1568{
1569 msg->len = 2;
1570 msg->msg[1] = CEC_MSG_REQUEST_ARC_TERMINATION;
1571 msg->reply = reply ? CEC_MSG_TERMINATE_ARC : 0;
1572}
1573
1574
1575/* Dynamic Audio Lipsync Feature */
1576/* Only for CEC 2.0 and up */
1577static inline void cec_msg_report_current_latency(struct cec_msg *msg,
1578 __u16 phys_addr,
1579 __u8 video_latency,
1580 __u8 low_latency_mode,
1581 __u8 audio_out_compensated,
1582 __u8 audio_out_delay)
1583{
1584 msg->len = 7;
1585 msg->msg[0] |= 0xf; /* broadcast */
1586 msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
1587 msg->msg[2] = phys_addr >> 8;
1588 msg->msg[3] = phys_addr & 0xff;
1589 msg->msg[4] = video_latency;
1590 msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
1591 msg->msg[6] = audio_out_delay;
1592}
1593
1594static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
1595 __u16 *phys_addr,
1596 __u8 *video_latency,
1597 __u8 *low_latency_mode,
1598 __u8 *audio_out_compensated,
1599 __u8 *audio_out_delay)
1600{
1601 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1602 *video_latency = msg->msg[4];
1603 *low_latency_mode = (msg->msg[5] >> 2) & 1;
1604 *audio_out_compensated = msg->msg[5] & 3;
1605 *audio_out_delay = msg->msg[6];
1606}
1607
1608static inline void cec_msg_request_current_latency(struct cec_msg *msg,
1609 bool reply,
1610 __u16 phys_addr)
1611{
1612 msg->len = 4;
1613 msg->msg[0] |= 0xf; /* broadcast */
1614 msg->msg[1] = CEC_MSG_REQUEST_CURRENT_LATENCY;
1615 msg->msg[2] = phys_addr >> 8;
1616 msg->msg[3] = phys_addr & 0xff;
1617 msg->reply = reply ? CEC_MSG_REPORT_CURRENT_LATENCY : 0;
1618}
1619
1620static inline void cec_ops_request_current_latency(const struct cec_msg *msg,
1621 __u16 *phys_addr)
1622{
1623 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1624}
1625
1626
1627/* Capability Discovery and Control Feature */
1628static inline void cec_msg_cdc_hec_inquire_state(struct cec_msg *msg,
1629 __u16 phys_addr1,
1630 __u16 phys_addr2)
1631{
1632 msg->len = 9;
1633 msg->msg[0] |= 0xf; /* broadcast */
1634 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1635 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1636 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1637 msg->msg[5] = phys_addr1 >> 8;
1638 msg->msg[6] = phys_addr1 & 0xff;
1639 msg->msg[7] = phys_addr2 >> 8;
1640 msg->msg[8] = phys_addr2 & 0xff;
1641}
1642
1643static inline void cec_ops_cdc_hec_inquire_state(const struct cec_msg *msg,
1644 __u16 *phys_addr,
1645 __u16 *phys_addr1,
1646 __u16 *phys_addr2)
1647{
1648 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1649 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1650 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1651}
1652
1653static inline void cec_msg_cdc_hec_report_state(struct cec_msg *msg,
1654 __u16 target_phys_addr,
1655 __u8 hec_func_state,
1656 __u8 host_func_state,
1657 __u8 enc_func_state,
1658 __u8 cdc_errcode,
1659 __u8 has_field,
1660 __u16 hec_field)
1661{
1662 msg->len = has_field ? 10 : 8;
1663 msg->msg[0] |= 0xf; /* broadcast */
1664 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1665 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1666 msg->msg[4] = CEC_MSG_CDC_HEC_REPORT_STATE;
1667 msg->msg[5] = target_phys_addr >> 8;
1668 msg->msg[6] = target_phys_addr & 0xff;
1669 msg->msg[7] = (hec_func_state << 6) |
1670 (host_func_state << 4) |
1671 (enc_func_state << 2) |
1672 cdc_errcode;
1673 if (has_field) {
1674 msg->msg[8] = hec_field >> 8;
1675 msg->msg[9] = hec_field & 0xff;
1676 }
1677}
1678
1679static inline void cec_ops_cdc_hec_report_state(const struct cec_msg *msg,
1680 __u16 *phys_addr,
1681 __u16 *target_phys_addr,
1682 __u8 *hec_func_state,
1683 __u8 *host_func_state,
1684 __u8 *enc_func_state,
1685 __u8 *cdc_errcode,
1686 __u8 *has_field,
1687 __u16 *hec_field)
1688{
1689 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1690 *target_phys_addr = (msg->msg[5] << 8) | msg->msg[6];
1691 *hec_func_state = msg->msg[7] >> 6;
1692 *host_func_state = (msg->msg[7] >> 4) & 3;
1693 *enc_func_state = (msg->msg[7] >> 4) & 3;
1694 *cdc_errcode = msg->msg[7] & 3;
1695 *has_field = msg->len >= 10;
1696 *hec_field = *has_field ? ((msg->msg[8] << 8) | msg->msg[9]) : 0;
1697}
1698
1699static inline void cec_msg_cdc_hec_set_state(struct cec_msg *msg,
1700 __u16 phys_addr1,
1701 __u16 phys_addr2,
1702 __u8 hec_set_state,
1703 __u16 phys_addr3,
1704 __u16 phys_addr4,
1705 __u16 phys_addr5)
1706{
1707 msg->len = 10;
1708 msg->msg[0] |= 0xf; /* broadcast */
1709 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1710 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1711 msg->msg[4] = CEC_MSG_CDC_HEC_INQUIRE_STATE;
1712 msg->msg[5] = phys_addr1 >> 8;
1713 msg->msg[6] = phys_addr1 & 0xff;
1714 msg->msg[7] = phys_addr2 >> 8;
1715 msg->msg[8] = phys_addr2 & 0xff;
1716 msg->msg[9] = hec_set_state;
1717 if (phys_addr3 != CEC_PHYS_ADDR_INVALID) {
1718 msg->msg[msg->len++] = phys_addr3 >> 8;
1719 msg->msg[msg->len++] = phys_addr3 & 0xff;
1720 if (phys_addr4 != CEC_PHYS_ADDR_INVALID) {
1721 msg->msg[msg->len++] = phys_addr4 >> 8;
1722 msg->msg[msg->len++] = phys_addr4 & 0xff;
1723 if (phys_addr5 != CEC_PHYS_ADDR_INVALID) {
1724 msg->msg[msg->len++] = phys_addr5 >> 8;
1725 msg->msg[msg->len++] = phys_addr5 & 0xff;
1726 }
1727 }
1728 }
1729}
1730
1731static inline void cec_ops_cdc_hec_set_state(const struct cec_msg *msg,
1732 __u16 *phys_addr,
1733 __u16 *phys_addr1,
1734 __u16 *phys_addr2,
1735 __u8 *hec_set_state,
1736 __u16 *phys_addr3,
1737 __u16 *phys_addr4,
1738 __u16 *phys_addr5)
1739{
1740 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1741 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1742 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1743 *hec_set_state = msg->msg[9];
1744 *phys_addr3 = *phys_addr4 = *phys_addr5 = CEC_PHYS_ADDR_INVALID;
1745 if (msg->len >= 12)
1746 *phys_addr3 = (msg->msg[10] << 8) | msg->msg[11];
1747 if (msg->len >= 14)
1748 *phys_addr4 = (msg->msg[12] << 8) | msg->msg[13];
1749 if (msg->len >= 16)
1750 *phys_addr5 = (msg->msg[14] << 8) | msg->msg[15];
1751}
1752
1753static inline void cec_msg_cdc_hec_set_state_adjacent(struct cec_msg *msg,
1754 __u16 phys_addr1,
1755 __u8 hec_set_state)
1756{
1757 msg->len = 8;
1758 msg->msg[0] |= 0xf; /* broadcast */
1759 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1760 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1761 msg->msg[4] = CEC_MSG_CDC_HEC_SET_STATE_ADJACENT;
1762 msg->msg[5] = phys_addr1 >> 8;
1763 msg->msg[6] = phys_addr1 & 0xff;
1764 msg->msg[7] = hec_set_state;
1765}
1766
1767static inline void cec_ops_cdc_hec_set_state_adjacent(const struct cec_msg *msg,
1768 __u16 *phys_addr,
1769 __u16 *phys_addr1,
1770 __u8 *hec_set_state)
1771{
1772 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1773 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1774 *hec_set_state = msg->msg[7];
1775}
1776
1777static inline void cec_msg_cdc_hec_request_deactivation(struct cec_msg *msg,
1778 __u16 phys_addr1,
1779 __u16 phys_addr2,
1780 __u16 phys_addr3)
1781{
1782 msg->len = 11;
1783 msg->msg[0] |= 0xf; /* broadcast */
1784 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1785 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1786 msg->msg[4] = CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION;
1787 msg->msg[5] = phys_addr1 >> 8;
1788 msg->msg[6] = phys_addr1 & 0xff;
1789 msg->msg[7] = phys_addr2 >> 8;
1790 msg->msg[8] = phys_addr2 & 0xff;
1791 msg->msg[9] = phys_addr3 >> 8;
1792 msg->msg[10] = phys_addr3 & 0xff;
1793}
1794
1795static inline void cec_ops_cdc_hec_request_deactivation(const struct cec_msg *msg,
1796 __u16 *phys_addr,
1797 __u16 *phys_addr1,
1798 __u16 *phys_addr2,
1799 __u16 *phys_addr3)
1800{
1801 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1802 *phys_addr1 = (msg->msg[5] << 8) | msg->msg[6];
1803 *phys_addr2 = (msg->msg[7] << 8) | msg->msg[8];
1804 *phys_addr3 = (msg->msg[9] << 8) | msg->msg[10];
1805}
1806
1807static inline void cec_msg_cdc_hec_notify_alive(struct cec_msg *msg)
1808{
1809 msg->len = 5;
1810 msg->msg[0] |= 0xf; /* broadcast */
1811 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1812 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1813 msg->msg[4] = CEC_MSG_CDC_HEC_NOTIFY_ALIVE;
1814}
1815
1816static inline void cec_ops_cdc_hec_notify_alive(const struct cec_msg *msg,
1817 __u16 *phys_addr)
1818{
1819 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1820}
1821
1822static inline void cec_msg_cdc_hec_discover(struct cec_msg *msg)
1823{
1824 msg->len = 5;
1825 msg->msg[0] |= 0xf; /* broadcast */
1826 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1827 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1828 msg->msg[4] = CEC_MSG_CDC_HEC_DISCOVER;
1829}
1830
1831static inline void cec_ops_cdc_hec_discover(const struct cec_msg *msg,
1832 __u16 *phys_addr)
1833{
1834 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1835}
1836
1837static inline void cec_msg_cdc_hpd_set_state(struct cec_msg *msg,
1838 __u8 input_port,
1839 __u8 hpd_state)
1840{
1841 msg->len = 6;
1842 msg->msg[0] |= 0xf; /* broadcast */
1843 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1844 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1845 msg->msg[4] = CEC_MSG_CDC_HPD_SET_STATE;
1846 msg->msg[5] = (input_port << 4) | hpd_state;
1847}
1848
1849static inline void cec_ops_cdc_hpd_set_state(const struct cec_msg *msg,
1850 __u16 *phys_addr,
1851 __u8 *input_port,
1852 __u8 *hpd_state)
1853{
1854 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1855 *input_port = msg->msg[5] >> 4;
1856 *hpd_state = msg->msg[5] & 0xf;
1857}
1858
1859static inline void cec_msg_cdc_hpd_report_state(struct cec_msg *msg,
1860 __u8 hpd_state,
1861 __u8 hpd_error)
1862{
1863 msg->len = 6;
1864 msg->msg[0] |= 0xf; /* broadcast */
1865 msg->msg[1] = CEC_MSG_CDC_MESSAGE;
1866 /* msg[2] and msg[3] (phys_addr) are filled in by the CEC framework */
1867 msg->msg[4] = CEC_MSG_CDC_HPD_REPORT_STATE;
1868 msg->msg[5] = (hpd_state << 4) | hpd_error;
1869}
1870
1871static inline void cec_ops_cdc_hpd_report_state(const struct cec_msg *msg,
1872 __u16 *phys_addr,
1873 __u8 *hpd_state,
1874 __u8 *hpd_error)
1875{
1876 *phys_addr = (msg->msg[2] << 8) | msg->msg[3];
1877 *hpd_state = msg->msg[5] >> 4;
1878 *hpd_error = msg->msg[5] & 0xf;
1879}
1880
1881#endif
include/linux/cec.h+993−0
@@ -0,0 +1,993 @@
1/*
2 * cec - HDMI Consumer Electronics Control public header
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20/*
21 * Note: this framework is still in staging and it is likely the API
22 * will change before it goes out of staging.
23 *
24 * Once it is moved out of staging this header will move to uapi.
25 */
26#ifndef _CEC_UAPI_H
27#define _CEC_UAPI_H
28
29#include <linux/types.h>
30
31#define CEC_MAX_MSG_SIZE 16
32
33/**
34 * struct cec_msg - CEC message structure.
35 * @ts: Timestamp in nanoseconds using CLOCK_MONOTONIC. Set by the
36 * driver. It is set when the message transmission has finished
37 * and it is set when a message was received.
38 * @len: Length in bytes of the message.
39 * @timeout: The timeout (in ms) that is used to timeout CEC_RECEIVE.
40 * Set to 0 if you want to wait forever. This timeout can also be
41 * used with CEC_TRANSMIT as the timeout for waiting for a reply.
42 * If 0, then it will use a 1 second timeout instead of waiting
43 * forever as is done with CEC_RECEIVE.
44 * @sequence: The framework assigns a sequence number to messages that are
45 * sent. This can be used to track replies to previously sent
46 * messages.
47 * @flags: Set to 0.
48 * @rx_status: The message receive status bits. Set by the driver.
49 * @tx_status: The message transmit status bits. Set by the driver.
50 * @msg: The message payload.
51 * @reply: This field is ignored with CEC_RECEIVE and is only used by
52 * CEC_TRANSMIT. If non-zero, then wait for a reply with this
53 * opcode. Set to CEC_MSG_FEATURE_ABORT if you want to wait for
54 * a possible ABORT reply. If there was an error when sending the
55 * msg or FeatureAbort was returned, then reply is set to 0.
56 * If reply is non-zero upon return, then len/msg are set to
57 * the received message.
58 * If reply is zero upon return and status has the
59 * CEC_TX_STATUS_FEATURE_ABORT bit set, then len/msg are set to
60 * the received feature abort message.
61 * If reply is zero upon return and status has the
62 * CEC_TX_STATUS_MAX_RETRIES bit set, then no reply was seen at
63 * all. If reply is non-zero for CEC_TRANSMIT and the message is a
64 * broadcast, then -EINVAL is returned.
65 * if reply is non-zero, then timeout is set to 1000 (the required
66 * maximum response time).
67 * @tx_arb_lost_cnt: The number of 'Arbitration Lost' events. Set by the driver.
68 * @tx_nack_cnt: The number of 'Not Acknowledged' events. Set by the driver.
69 * @tx_low_drive_cnt: The number of 'Low Drive Detected' events. Set by the
70 * driver.
71 * @tx_error_cnt: The number of 'Error' events. Set by the driver.
72 */
73struct cec_msg {
74 __u64 ts;
75 __u32 len;
76 __u32 timeout;
77 __u32 sequence;
78 __u32 flags;
79 __u8 rx_status;
80 __u8 tx_status;
81 __u8 msg[CEC_MAX_MSG_SIZE];
82 __u8 reply;
83 __u8 tx_arb_lost_cnt;
84 __u8 tx_nack_cnt;
85 __u8 tx_low_drive_cnt;
86 __u8 tx_error_cnt;
87};
88
89/**
90 * cec_msg_initiator - return the initiator's logical address.
91 * @msg: the message structure
92 */
93static inline __u8 cec_msg_initiator(const struct cec_msg *msg)
94{
95 return msg->msg[0] >> 4;
96}
97
98/**
99 * cec_msg_destination - return the destination's logical address.
100 * @msg: the message structure
101 */
102static inline __u8 cec_msg_destination(const struct cec_msg *msg)
103{
104 return msg->msg[0] & 0xf;
105}
106
107/**
108 * cec_msg_opcode - return the opcode of the message, -1 for poll
109 * @msg: the message structure
110 */
111static inline int cec_msg_opcode(const struct cec_msg *msg)
112{
113 return msg->len > 1 ? msg->msg[1] : -1;
114}
115
116/**
117 * cec_msg_is_broadcast - return true if this is a broadcast message.
118 * @msg: the message structure
119 */
120static inline bool cec_msg_is_broadcast(const struct cec_msg *msg)
121{
122 return (msg->msg[0] & 0xf) == 0xf;
123}
124
125/**
126 * cec_msg_init - initialize the message structure.
127 * @msg: the message structure
128 * @initiator: the logical address of the initiator
129 * @destination:the logical address of the destination (0xf for broadcast)
130 *
131 * The whole structure is zeroed, the len field is set to 1 (i.e. a poll
132 * message) and the initiator and destination are filled in.
133 */
134static inline void cec_msg_init(struct cec_msg *msg,
135 __u8 initiator, __u8 destination)
136{
137 memset(msg, 0, sizeof(*msg));
138 msg->msg[0] = (initiator << 4) | destination;
139 msg->len = 1;
140}
141
142/**
143 * cec_msg_set_reply_to - fill in destination/initiator in a reply message.
144 * @msg: the message structure for the reply
145 * @orig: the original message structure
146 *
147 * Set the msg destination to the orig initiator and the msg initiator to the
148 * orig destination. Note that msg and orig may be the same pointer, in which
149 * case the change is done in place.
150 */
151static inline void cec_msg_set_reply_to(struct cec_msg *msg,
152 struct cec_msg *orig)
153{
154 /* The destination becomes the initiator and vice versa */
155 msg->msg[0] = (cec_msg_destination(orig) << 4) |
156 cec_msg_initiator(orig);
157 msg->reply = msg->timeout = 0;
158}
159
160/* cec status field */
161#define CEC_TX_STATUS_OK (1 << 0)
162#define CEC_TX_STATUS_ARB_LOST (1 << 1)
163#define CEC_TX_STATUS_NACK (1 << 2)
164#define CEC_TX_STATUS_LOW_DRIVE (1 << 3)
165#define CEC_TX_STATUS_ERROR (1 << 4)
166#define CEC_TX_STATUS_MAX_RETRIES (1 << 5)
167
168#define CEC_RX_STATUS_OK (1 << 0)
169#define CEC_RX_STATUS_TIMEOUT (1 << 1)
170#define CEC_RX_STATUS_FEATURE_ABORT (1 << 2)
171
172static inline bool cec_msg_status_is_ok(const struct cec_msg *msg)
173{
174 if (msg->tx_status && !(msg->tx_status & CEC_TX_STATUS_OK))
175 return false;
176 if (msg->rx_status && !(msg->rx_status & CEC_RX_STATUS_OK))
177 return false;
178 if (!msg->tx_status && !msg->rx_status)
179 return false;
180 return !(msg->rx_status & CEC_RX_STATUS_FEATURE_ABORT);
181}
182
183#define CEC_LOG_ADDR_INVALID 0xff
184#define CEC_PHYS_ADDR_INVALID 0xffff
185
186/*
187 * The maximum number of logical addresses one device can be assigned to.
188 * The CEC 2.0 spec allows for only 2 logical addresses at the moment. The
189 * Analog Devices CEC hardware supports 3. So let's go wild and go for 4.
190 */
191#define CEC_MAX_LOG_ADDRS 4
192
193/* The logical addresses defined by CEC 2.0 */
194#define CEC_LOG_ADDR_TV 0
195#define CEC_LOG_ADDR_RECORD_1 1
196#define CEC_LOG_ADDR_RECORD_2 2
197#define CEC_LOG_ADDR_TUNER_1 3
198#define CEC_LOG_ADDR_PLAYBACK_1 4
199#define CEC_LOG_ADDR_AUDIOSYSTEM 5
200#define CEC_LOG_ADDR_TUNER_2 6
201#define CEC_LOG_ADDR_TUNER_3 7
202#define CEC_LOG_ADDR_PLAYBACK_2 8
203#define CEC_LOG_ADDR_RECORD_3 9
204#define CEC_LOG_ADDR_TUNER_4 10
205#define CEC_LOG_ADDR_PLAYBACK_3 11
206#define CEC_LOG_ADDR_BACKUP_1 12
207#define CEC_LOG_ADDR_BACKUP_2 13
208#define CEC_LOG_ADDR_SPECIFIC 14
209#define CEC_LOG_ADDR_UNREGISTERED 15 /* as initiator address */
210#define CEC_LOG_ADDR_BROADCAST 15 /* ad destination address */
211
212/* The logical address types that the CEC device wants to claim */
213#define CEC_LOG_ADDR_TYPE_TV 0
214#define CEC_LOG_ADDR_TYPE_RECORD 1
215#define CEC_LOG_ADDR_TYPE_TUNER 2
216#define CEC_LOG_ADDR_TYPE_PLAYBACK 3
217#define CEC_LOG_ADDR_TYPE_AUDIOSYSTEM 4
218#define CEC_LOG_ADDR_TYPE_SPECIFIC 5
219#define CEC_LOG_ADDR_TYPE_UNREGISTERED 6
220/*
221 * Switches should use UNREGISTERED.
222 * Processors should use SPECIFIC.
223 */
224
225#define CEC_LOG_ADDR_MASK_TV (1 << CEC_LOG_ADDR_TV)
226#define CEC_LOG_ADDR_MASK_RECORD ((1 << CEC_LOG_ADDR_RECORD_1) | \
227 (1 << CEC_LOG_ADDR_RECORD_2) | \
228 (1 << CEC_LOG_ADDR_RECORD_3))
229#define CEC_LOG_ADDR_MASK_TUNER ((1 << CEC_LOG_ADDR_TUNER_1) | \
230 (1 << CEC_LOG_ADDR_TUNER_2) | \
231 (1 << CEC_LOG_ADDR_TUNER_3) | \
232 (1 << CEC_LOG_ADDR_TUNER_4))
233#define CEC_LOG_ADDR_MASK_PLAYBACK ((1 << CEC_LOG_ADDR_PLAYBACK_1) | \
234 (1 << CEC_LOG_ADDR_PLAYBACK_2) | \
235 (1 << CEC_LOG_ADDR_PLAYBACK_3))
236#define CEC_LOG_ADDR_MASK_AUDIOSYSTEM (1 << CEC_LOG_ADDR_AUDIOSYSTEM)
237#define CEC_LOG_ADDR_MASK_BACKUP ((1 << CEC_LOG_ADDR_BACKUP_1) | \
238 (1 << CEC_LOG_ADDR_BACKUP_2))
239#define CEC_LOG_ADDR_MASK_SPECIFIC (1 << CEC_LOG_ADDR_SPECIFIC)
240#define CEC_LOG_ADDR_MASK_UNREGISTERED (1 << CEC_LOG_ADDR_UNREGISTERED)
241
242static inline bool cec_has_tv(__u16 log_addr_mask)
243{
244 return log_addr_mask & CEC_LOG_ADDR_MASK_TV;
245}
246
247static inline bool cec_has_record(__u16 log_addr_mask)
248{
249 return log_addr_mask & CEC_LOG_ADDR_MASK_RECORD;
250}
251
252static inline bool cec_has_tuner(__u16 log_addr_mask)
253{
254 return log_addr_mask & CEC_LOG_ADDR_MASK_TUNER;
255}
256
257static inline bool cec_has_playback(__u16 log_addr_mask)
258{
259 return log_addr_mask & CEC_LOG_ADDR_MASK_PLAYBACK;
260}
261
262static inline bool cec_has_audiosystem(__u16 log_addr_mask)
263{
264 return log_addr_mask & CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
265}
266
267static inline bool cec_has_backup(__u16 log_addr_mask)
268{
269 return log_addr_mask & CEC_LOG_ADDR_MASK_BACKUP;
270}
271
272static inline bool cec_has_specific(__u16 log_addr_mask)
273{
274 return log_addr_mask & CEC_LOG_ADDR_MASK_SPECIFIC;
275}
276
277static inline bool cec_is_unregistered(__u16 log_addr_mask)
278{
279 return log_addr_mask & CEC_LOG_ADDR_MASK_UNREGISTERED;
280}
281
282static inline bool cec_is_unconfigured(__u16 log_addr_mask)
283{
284 return log_addr_mask == 0;
285}
286
287/*
288 * Use this if there is no vendor ID (CEC_G_VENDOR_ID) or if the vendor ID
289 * should be disabled (CEC_S_VENDOR_ID)
290 */
291#define CEC_VENDOR_ID_NONE 0xffffffff
292
293/* The message handling modes */
294/* Modes for initiator */
295#define CEC_MODE_NO_INITIATOR (0x0 << 0)
296#define CEC_MODE_INITIATOR (0x1 << 0)
297#define CEC_MODE_EXCL_INITIATOR (0x2 << 0)
298#define CEC_MODE_INITIATOR_MSK 0x0f
299
300/* Modes for follower */
301#define CEC_MODE_NO_FOLLOWER (0x0 << 4)
302#define CEC_MODE_FOLLOWER (0x1 << 4)
303#define CEC_MODE_EXCL_FOLLOWER (0x2 << 4)
304#define CEC_MODE_EXCL_FOLLOWER_PASSTHRU (0x3 << 4)
305#define CEC_MODE_MONITOR (0xe << 4)
306#define CEC_MODE_MONITOR_ALL (0xf << 4)
307#define CEC_MODE_FOLLOWER_MSK 0xf0
308
309/* Userspace has to configure the physical address */
310#define CEC_CAP_PHYS_ADDR (1 << 0)
311/* Userspace has to configure the logical addresses */
312#define CEC_CAP_LOG_ADDRS (1 << 1)
313/* Userspace can transmit messages (and thus become follower as well) */
314#define CEC_CAP_TRANSMIT (1 << 2)
315/*
316 * Passthrough all messages instead of processing them.
317 */
318#define CEC_CAP_PASSTHROUGH (1 << 3)
319/* Supports remote control */
320#define CEC_CAP_RC (1 << 4)
321/* Hardware can monitor all messages, not just directed and broadcast. */
322#define CEC_CAP_MONITOR_ALL (1 << 5)
323
324/**
325 * struct cec_caps - CEC capabilities structure.
326 * @driver: name of the CEC device driver.
327 * @name: name of the CEC device. @driver + @name must be unique.
328 * @available_log_addrs: number of available logical addresses.
329 * @capabilities: capabilities of the CEC adapter.
330 * @version: version of the CEC adapter framework.
331 */
332struct cec_caps {
333 char driver[32];
334 char name[32];
335 __u32 available_log_addrs;
336 __u32 capabilities;
337 __u32 version;
338};
339
340/**
341 * struct cec_log_addrs - CEC logical addresses structure.
342 * @log_addr: the claimed logical addresses. Set by the driver.
343 * @log_addr_mask: current logical address mask. Set by the driver.
344 * @cec_version: the CEC version that the adapter should implement. Set by the
345 * caller.
346 * @num_log_addrs: how many logical addresses should be claimed. Set by the
347 * caller.
348 * @vendor_id: the vendor ID of the device. Set by the caller.
349 * @flags: set to 0.
350 * @osd_name: the OSD name of the device. Set by the caller.
351 * @primary_device_type: the primary device type for each logical address.
352 * Set by the caller.
353 * @log_addr_type: the logical address types. Set by the caller.
354 * @all_device_types: CEC 2.0: all device types represented by the logical
355 * address. Set by the caller.
356 * @features: CEC 2.0: The logical address features. Set by the caller.
357 */
358struct cec_log_addrs {
359 __u8 log_addr[CEC_MAX_LOG_ADDRS];
360 __u16 log_addr_mask;
361 __u8 cec_version;
362 __u8 num_log_addrs;
363 __u32 vendor_id;
364 __u32 flags;
365 char osd_name[15];
366 __u8 primary_device_type[CEC_MAX_LOG_ADDRS];
367 __u8 log_addr_type[CEC_MAX_LOG_ADDRS];
368
369 /* CEC 2.0 */
370 __u8 all_device_types[CEC_MAX_LOG_ADDRS];
371 __u8 features[CEC_MAX_LOG_ADDRS][12];
372};
373
374/* Events */
375
376/* Event that occurs when the adapter state changes */
377#define CEC_EVENT_STATE_CHANGE 1
378/*
379 * This event is sent when messages are lost because the application
380 * didn't empty the message queue in time
381 */
382#define CEC_EVENT_LOST_MSGS 2
383
384#define CEC_EVENT_FL_INITIAL_STATE (1 << 0)
385
386/**
387 * struct cec_event_state_change - used when the CEC adapter changes state.
388 * @phys_addr: the current physical address
389 * @log_addr_mask: the current logical address mask
390 */
391struct cec_event_state_change {
392 __u16 phys_addr;
393 __u16 log_addr_mask;
394};
395
396/**
397 * struct cec_event_lost_msgs - tells you how many messages were lost due.
398 * @lost_msgs: how many messages were lost.
399 */
400struct cec_event_lost_msgs {
401 __u32 lost_msgs;
402};
403
404/**
405 * struct cec_event - CEC event structure
406 * @ts: the timestamp of when the event was sent.
407 * @event: the event.
408 * array.
409 * @state_change: the event payload for CEC_EVENT_STATE_CHANGE.
410 * @lost_msgs: the event payload for CEC_EVENT_LOST_MSGS.
411 * @raw: array to pad the union.
412 */
413struct cec_event {
414 __u64 ts;
415 __u32 event;
416 __u32 flags;
417 union {
418 struct cec_event_state_change state_change;
419 struct cec_event_lost_msgs lost_msgs;
420 __u32 raw[16];
421 };
422};
423
424/* ioctls */
425
426/* Adapter capabilities */
427#define CEC_ADAP_G_CAPS _IOWR('a', 0, struct cec_caps)
428
429/*
430 * phys_addr is either 0 (if this is the CEC root device)
431 * or a valid physical address obtained from the sink's EDID
432 * as read by this CEC device (if this is a source device)
433 * or a physical address obtained and modified from a sink
434 * EDID and used for a sink CEC device.
435 * If nothing is connected, then phys_addr is 0xffff.
436 * See HDMI 1.4b, section 8.7 (Physical Address).
437 *
438 * The CEC_ADAP_S_PHYS_ADDR ioctl may not be available if that is handled
439 * internally.
440 */
441#define CEC_ADAP_G_PHYS_ADDR _IOR('a', 1, __u16)
442#define CEC_ADAP_S_PHYS_ADDR _IOW('a', 2, __u16)
443
444/*
445 * Configure the CEC adapter. It sets the device type and which
446 * logical types it will try to claim. It will return which
447 * logical addresses it could actually claim.
448 * An error is returned if the adapter is disabled or if there
449 * is no physical address assigned.
450 */
451
452#define CEC_ADAP_G_LOG_ADDRS _IOR('a', 3, struct cec_log_addrs)
453#define CEC_ADAP_S_LOG_ADDRS _IOWR('a', 4, struct cec_log_addrs)
454
455/* Transmit/receive a CEC command */
456#define CEC_TRANSMIT _IOWR('a', 5, struct cec_msg)
457#define CEC_RECEIVE _IOWR('a', 6, struct cec_msg)
458
459/* Dequeue CEC events */
460#define CEC_DQEVENT _IOWR('a', 7, struct cec_event)
461
462/*
463 * Get and set the message handling mode for this filehandle.
464 */
465#define CEC_G_MODE _IOR('a', 8, __u32)
466#define CEC_S_MODE _IOW('a', 9, __u32)
467
468/*
469 * The remainder of this header defines all CEC messages and operands.
470 * The format matters since it the cec-ctl utility parses it to generate
471 * code for implementing all these messages.
472 *
473 * Comments ending with 'Feature' group messages for each feature.
474 * If messages are part of multiple features, then the "Has also"
475 * comment is used to list the previously defined messages that are
476 * supported by the feature.
477 *
478 * Before operands are defined a comment is added that gives the
479 * name of the operand and in brackets the variable name of the
480 * corresponding argument in the cec-funcs.h function.
481 */
482
483/* Messages */
484
485/* One Touch Play Feature */
486#define CEC_MSG_ACTIVE_SOURCE 0x82
487#define CEC_MSG_IMAGE_VIEW_ON 0x04
488#define CEC_MSG_TEXT_VIEW_ON 0x0d
489
490
491/* Routing Control Feature */
492
493/*
494 * Has also:
495 * CEC_MSG_ACTIVE_SOURCE
496 */
497
498#define CEC_MSG_INACTIVE_SOURCE 0x9d
499#define CEC_MSG_REQUEST_ACTIVE_SOURCE 0x85
500#define CEC_MSG_ROUTING_CHANGE 0x80
501#define CEC_MSG_ROUTING_INFORMATION 0x81
502#define CEC_MSG_SET_STREAM_PATH 0x86
503
504
505/* Standby Feature */
506#define CEC_MSG_STANDBY 0x36
507
508
509/* One Touch Record Feature */
510#define CEC_MSG_RECORD_OFF 0x0b
511#define CEC_MSG_RECORD_ON 0x09
512/* Record Source Type Operand (rec_src_type) */
513#define CEC_OP_RECORD_SRC_OWN 1
514#define CEC_OP_RECORD_SRC_DIGITAL 2
515#define CEC_OP_RECORD_SRC_ANALOG 3
516#define CEC_OP_RECORD_SRC_EXT_PLUG 4
517#define CEC_OP_RECORD_SRC_EXT_PHYS_ADDR 5
518/* Service Identification Method Operand (service_id_method) */
519#define CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID 0
520#define CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL 1
521/* Digital Service Broadcast System Operand (dig_bcast_system) */
522#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_GEN 0x00
523#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN 0x01
524#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_GEN 0x02
525#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS 0x08
526#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_CS 0x09
527#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T 0x0a
528#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE 0x10
529#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT 0x11
530#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T 0x12
531#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_C 0x18
532#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S 0x19
533#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2 0x1a
534#define CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T 0x1b
535/* Analogue Broadcast Type Operand (ana_bcast_type) */
536#define CEC_OP_ANA_BCAST_TYPE_CABLE 0
537#define CEC_OP_ANA_BCAST_TYPE_SATELLITE 1
538#define CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL 2
539/* Broadcast System Operand (bcast_system) */
540#define CEC_OP_BCAST_SYSTEM_PAL_BG 0x00
541#define CEC_OP_BCAST_SYSTEM_SECAM_LQ 0x01 /* SECAM L' */
542#define CEC_OP_BCAST_SYSTEM_PAL_M 0x02
543#define CEC_OP_BCAST_SYSTEM_NTSC_M 0x03
544#define CEC_OP_BCAST_SYSTEM_PAL_I 0x04
545#define CEC_OP_BCAST_SYSTEM_SECAM_DK 0x05
546#define CEC_OP_BCAST_SYSTEM_SECAM_BG 0x06
547#define CEC_OP_BCAST_SYSTEM_SECAM_L 0x07
548#define CEC_OP_BCAST_SYSTEM_PAL_DK 0x08
549#define CEC_OP_BCAST_SYSTEM_OTHER 0x1f
550/* Channel Number Format Operand (channel_number_fmt) */
551#define CEC_OP_CHANNEL_NUMBER_FMT_1_PART 0x01
552#define CEC_OP_CHANNEL_NUMBER_FMT_2_PART 0x02
553
554#define CEC_MSG_RECORD_STATUS 0x0a
555/* Record Status Operand (rec_status) */
556#define CEC_OP_RECORD_STATUS_CUR_SRC 0x01
557#define CEC_OP_RECORD_STATUS_DIG_SERVICE 0x02
558#define CEC_OP_RECORD_STATUS_ANA_SERVICE 0x03
559#define CEC_OP_RECORD_STATUS_EXT_INPUT 0x04
560#define CEC_OP_RECORD_STATUS_NO_DIG_SERVICE 0x05
561#define CEC_OP_RECORD_STATUS_NO_ANA_SERVICE 0x06
562#define CEC_OP_RECORD_STATUS_NO_SERVICE 0x07
563#define CEC_OP_RECORD_STATUS_INVALID_EXT_PLUG 0x09
564#define CEC_OP_RECORD_STATUS_INVALID_EXT_PHYS_ADDR 0x0a
565#define CEC_OP_RECORD_STATUS_UNSUP_CA 0x0b
566#define CEC_OP_RECORD_STATUS_NO_CA_ENTITLEMENTS 0x0c
567#define CEC_OP_RECORD_STATUS_CANT_COPY_SRC 0x0d
568#define CEC_OP_RECORD_STATUS_NO_MORE_COPIES 0x0e
569#define CEC_OP_RECORD_STATUS_NO_MEDIA 0x10
570#define CEC_OP_RECORD_STATUS_PLAYING 0x11
571#define CEC_OP_RECORD_STATUS_ALREADY_RECORDING 0x12
572#define CEC_OP_RECORD_STATUS_MEDIA_PROT 0x13
573#define CEC_OP_RECORD_STATUS_NO_SIGNAL 0x14
574#define CEC_OP_RECORD_STATUS_MEDIA_PROBLEM 0x15
575#define CEC_OP_RECORD_STATUS_NO_SPACE 0x16
576#define CEC_OP_RECORD_STATUS_PARENTAL_LOCK 0x17
577#define CEC_OP_RECORD_STATUS_TERMINATED_OK 0x1a
578#define CEC_OP_RECORD_STATUS_ALREADY_TERM 0x1b
579#define CEC_OP_RECORD_STATUS_OTHER 0x1f
580
581#define CEC_MSG_RECORD_TV_SCREEN 0x0f
582
583
584/* Timer Programming Feature */
585#define CEC_MSG_CLEAR_ANALOGUE_TIMER 0x33
586/* Recording Sequence Operand (recording_seq) */
587#define CEC_OP_REC_SEQ_SUNDAY 0x01
588#define CEC_OP_REC_SEQ_MONDAY 0x02
589#define CEC_OP_REC_SEQ_TUESDAY 0x04
590#define CEC_OP_REC_SEQ_WEDNESDAY 0x08
591#define CEC_OP_REC_SEQ_THURSDAY 0x10
592#define CEC_OP_REC_SEQ_FRIDAY 0x20
593#define CEC_OP_REC_SEQ_SATERDAY 0x40
594#define CEC_OP_REC_SEQ_ONCE_ONLY 0x00
595
596#define CEC_MSG_CLEAR_DIGITAL_TIMER 0x99
597
598#define CEC_MSG_CLEAR_EXT_TIMER 0xa1
599/* External Source Specifier Operand (ext_src_spec) */
600#define CEC_OP_EXT_SRC_PLUG 0x04
601#define CEC_OP_EXT_SRC_PHYS_ADDR 0x05
602
603#define CEC_MSG_SET_ANALOGUE_TIMER 0x34
604#define CEC_MSG_SET_DIGITAL_TIMER 0x97
605#define CEC_MSG_SET_EXT_TIMER 0xa2
606
607#define CEC_MSG_SET_TIMER_PROGRAM_TITLE 0x67
608#define CEC_MSG_TIMER_CLEARED_STATUS 0x43
609/* Timer Cleared Status Data Operand (timer_cleared_status) */
610#define CEC_OP_TIMER_CLR_STAT_RECORDING 0x00
611#define CEC_OP_TIMER_CLR_STAT_NO_MATCHING 0x01
612#define CEC_OP_TIMER_CLR_STAT_NO_INFO 0x02
613#define CEC_OP_TIMER_CLR_STAT_CLEARED 0x80
614
615#define CEC_MSG_TIMER_STATUS 0x35
616/* Timer Overlap Warning Operand (timer_overlap_warning) */
617#define CEC_OP_TIMER_OVERLAP_WARNING_NO_OVERLAP 0
618#define CEC_OP_TIMER_OVERLAP_WARNING_OVERLAP 1
619/* Media Info Operand (media_info) */
620#define CEC_OP_MEDIA_INFO_UNPROT_MEDIA 0
621#define CEC_OP_MEDIA_INFO_PROT_MEDIA 1
622#define CEC_OP_MEDIA_INFO_NO_MEDIA 2
623/* Programmed Indicator Operand (prog_indicator) */
624#define CEC_OP_PROG_IND_NOT_PROGRAMMED 0
625#define CEC_OP_PROG_IND_PROGRAMMED 1
626/* Programmed Info Operand (prog_info) */
627#define CEC_OP_PROG_INFO_ENOUGH_SPACE 0x08
628#define CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE 0x09
629#define CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE 0x0b
630#define CEC_OP_PROG_INFO_NONE_AVAILABLE 0x0a
631/* Not Programmed Error Info Operand (prog_error) */
632#define CEC_OP_PROG_ERROR_NO_FREE_TIMER 0x01
633#define CEC_OP_PROG_ERROR_DATE_OUT_OF_RANGE 0x02
634#define CEC_OP_PROG_ERROR_REC_SEQ_ERROR 0x03
635#define CEC_OP_PROG_ERROR_INV_EXT_PLUG 0x04
636#define CEC_OP_PROG_ERROR_INV_EXT_PHYS_ADDR 0x05
637#define CEC_OP_PROG_ERROR_CA_UNSUPP 0x06
638#define CEC_OP_PROG_ERROR_INSUF_CA_ENTITLEMENTS 0x07
639#define CEC_OP_PROG_ERROR_RESOLUTION_UNSUPP 0x08
640#define CEC_OP_PROG_ERROR_PARENTAL_LOCK 0x09
641#define CEC_OP_PROG_ERROR_CLOCK_FAILURE 0x0a
642#define CEC_OP_PROG_ERROR_DUPLICATE 0x0e
643
644
645/* System Information Feature */
646#define CEC_MSG_CEC_VERSION 0x9e
647/* CEC Version Operand (cec_version) */
648#define CEC_OP_CEC_VERSION_1_3A 4
649#define CEC_OP_CEC_VERSION_1_4 5
650#define CEC_OP_CEC_VERSION_2_0 6
651
652#define CEC_MSG_GET_CEC_VERSION 0x9f
653#define CEC_MSG_GIVE_PHYSICAL_ADDR 0x83
654#define CEC_MSG_GET_MENU_LANGUAGE 0x91
655#define CEC_MSG_REPORT_PHYSICAL_ADDR 0x84
656/* Primary Device Type Operand (prim_devtype) */
657#define CEC_OP_PRIM_DEVTYPE_TV 0
658#define CEC_OP_PRIM_DEVTYPE_RECORD 1
659#define CEC_OP_PRIM_DEVTYPE_TUNER 3
660#define CEC_OP_PRIM_DEVTYPE_PLAYBACK 4
661#define CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM 5
662#define CEC_OP_PRIM_DEVTYPE_SWITCH 6
663#define CEC_OP_PRIM_DEVTYPE_PROCESSOR 7
664
665#define CEC_MSG_SET_MENU_LANGUAGE 0x32
666#define CEC_MSG_REPORT_FEATURES 0xa6 /* HDMI 2.0 */
667/* All Device Types Operand (all_device_types) */
668#define CEC_OP_ALL_DEVTYPE_TV 0x80
669#define CEC_OP_ALL_DEVTYPE_RECORD 0x40
670#define CEC_OP_ALL_DEVTYPE_TUNER 0x20
671#define CEC_OP_ALL_DEVTYPE_PLAYBACK 0x10
672#define CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM 0x08
673#define CEC_OP_ALL_DEVTYPE_SWITCH 0x04
674/*
675 * And if you wondering what happened to PROCESSOR devices: those should
676 * be mapped to a SWITCH.
677 */
678
679/* Valid for RC Profile and Device Feature operands */
680#define CEC_OP_FEAT_EXT 0x80 /* Extension bit */
681/* RC Profile Operand (rc_profile) */
682#define CEC_OP_FEAT_RC_TV_PROFILE_NONE 0x00
683#define CEC_OP_FEAT_RC_TV_PROFILE_1 0x02
684#define CEC_OP_FEAT_RC_TV_PROFILE_2 0x06
685#define CEC_OP_FEAT_RC_TV_PROFILE_3 0x0a
686#define CEC_OP_FEAT_RC_TV_PROFILE_4 0x0e
687#define CEC_OP_FEAT_RC_SRC_HAS_DEV_ROOT_MENU 0x50
688#define CEC_OP_FEAT_RC_SRC_HAS_DEV_SETUP_MENU 0x48
689#define CEC_OP_FEAT_RC_SRC_HAS_CONTENTS_MENU 0x44
690#define CEC_OP_FEAT_RC_SRC_HAS_MEDIA_TOP_MENU 0x42
691#define CEC_OP_FEAT_RC_SRC_HAS_MEDIA_CONTEXT_MENU 0x41
692/* Device Feature Operand (dev_features) */
693#define CEC_OP_FEAT_DEV_HAS_RECORD_TV_SCREEN 0x40
694#define CEC_OP_FEAT_DEV_HAS_SET_OSD_STRING 0x20
695#define CEC_OP_FEAT_DEV_HAS_DECK_CONTROL 0x10
696#define CEC_OP_FEAT_DEV_HAS_SET_AUDIO_RATE 0x08
697#define CEC_OP_FEAT_DEV_SINK_HAS_ARC_TX 0x04
698#define CEC_OP_FEAT_DEV_SOURCE_HAS_ARC_RX 0x02
699
700#define CEC_MSG_GIVE_FEATURES 0xa5 /* HDMI 2.0 */
701
702
703/* Deck Control Feature */
704#define CEC_MSG_DECK_CONTROL 0x42
705/* Deck Control Mode Operand (deck_control_mode) */
706#define CEC_OP_DECK_CTL_MODE_SKIP_FWD 1
707#define CEC_OP_DECK_CTL_MODE_SKIP_REV 2
708#define CEC_OP_DECK_CTL_MODE_STOP 3
709#define CEC_OP_DECK_CTL_MODE_EJECT 4
710
711#define CEC_MSG_DECK_STATUS 0x1b
712/* Deck Info Operand (deck_info) */
713#define CEC_OP_DECK_INFO_PLAY 0x11
714#define CEC_OP_DECK_INFO_RECORD 0x12
715#define CEC_OP_DECK_INFO_PLAY_REV 0x13
716#define CEC_OP_DECK_INFO_STILL 0x14
717#define CEC_OP_DECK_INFO_SLOW 0x15
718#define CEC_OP_DECK_INFO_SLOW_REV 0x16
719#define CEC_OP_DECK_INFO_FAST_FWD 0x17
720#define CEC_OP_DECK_INFO_FAST_REV 0x18
721#define CEC_OP_DECK_INFO_NO_MEDIA 0x19
722#define CEC_OP_DECK_INFO_STOP 0x1a
723#define CEC_OP_DECK_INFO_SKIP_FWD 0x1b
724#define CEC_OP_DECK_INFO_SKIP_REV 0x1c
725#define CEC_OP_DECK_INFO_INDEX_SEARCH_FWD 0x1d
726#define CEC_OP_DECK_INFO_INDEX_SEARCH_REV 0x1e
727#define CEC_OP_DECK_INFO_OTHER 0x1f
728
729#define CEC_MSG_GIVE_DECK_STATUS 0x1a
730/* Status Request Operand (status_req) */
731#define CEC_OP_STATUS_REQ_ON 1
732#define CEC_OP_STATUS_REQ_OFF 2
733#define CEC_OP_STATUS_REQ_ONCE 3
734
735#define CEC_MSG_PLAY 0x41
736/* Play Mode Operand (play_mode) */
737#define CEC_OP_PLAY_MODE_PLAY_FWD 0x24
738#define CEC_OP_PLAY_MODE_PLAY_REV 0x20
739#define CEC_OP_PLAY_MODE_PLAY_STILL 0x25
740#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MIN 0x05
741#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MED 0x06
742#define CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MAX 0x07
743#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MIN 0x09
744#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MED 0x0a
745#define CEC_OP_PLAY_MODE_PLAY_FAST_REV_MAX 0x0b
746#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MIN 0x15
747#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MED 0x16
748#define CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MAX 0x17
749#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MIN 0x19
750#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MED 0x1a
751#define CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MAX 0x1b
752
753
754/* Tuner Control Feature */
755#define CEC_MSG_GIVE_TUNER_DEVICE_STATUS 0x08
756#define CEC_MSG_SELECT_ANALOGUE_SERVICE 0x92
757#define CEC_MSG_SELECT_DIGITAL_SERVICE 0x93
758#define CEC_MSG_TUNER_DEVICE_STATUS 0x07
759/* Recording Flag Operand (rec_flag) */
760#define CEC_OP_REC_FLAG_USED 0
761#define CEC_OP_REC_FLAG_NOT_USED 1
762/* Tuner Display Info Operand (tuner_display_info) */
763#define CEC_OP_TUNER_DISPLAY_INFO_DIGITAL 0
764#define CEC_OP_TUNER_DISPLAY_INFO_NONE 1
765#define CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE 2
766
767#define CEC_MSG_TUNER_STEP_DECREMENT 0x06
768#define CEC_MSG_TUNER_STEP_INCREMENT 0x05
769
770
771/* Vendor Specific Commands Feature */
772
773/*
774 * Has also:
775 * CEC_MSG_CEC_VERSION
776 * CEC_MSG_GET_CEC_VERSION
777 */
778#define CEC_MSG_DEVICE_VENDOR_ID 0x87
779#define CEC_MSG_GIVE_DEVICE_VENDOR_ID 0x8c
780#define CEC_MSG_VENDOR_COMMAND 0x89
781#define CEC_MSG_VENDOR_COMMAND_WITH_ID 0xa0
782#define CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN 0x8a
783#define CEC_MSG_VENDOR_REMOTE_BUTTON_UP 0x8b
784
785
786/* OSD Display Feature */
787#define CEC_MSG_SET_OSD_STRING 0x64
788/* Display Control Operand (disp_ctl) */
789#define CEC_OP_DISP_CTL_DEFAULT 0x00
790#define CEC_OP_DISP_CTL_UNTIL_CLEARED 0x40
791#define CEC_OP_DISP_CTL_CLEAR 0x80
792
793
794/* Device OSD Transfer Feature */
795#define CEC_MSG_GIVE_OSD_NAME 0x46
796#define CEC_MSG_SET_OSD_NAME 0x47
797
798
799/* Device Menu Control Feature */
800#define CEC_MSG_MENU_REQUEST 0x8d
801/* Menu Request Type Operand (menu_req) */
802#define CEC_OP_MENU_REQUEST_ACTIVATE 0x00
803#define CEC_OP_MENU_REQUEST_DEACTIVATE 0x01
804#define CEC_OP_MENU_REQUEST_QUERY 0x02
805
806#define CEC_MSG_MENU_STATUS 0x8e
807/* Menu State Operand (menu_state) */
808#define CEC_OP_MENU_STATE_ACTIVATED 0x00
809#define CEC_OP_MENU_STATE_DEACTIVATED 0x01
810
811#define CEC_MSG_USER_CONTROL_PRESSED 0x44
812/* UI Broadcast Type Operand (ui_bcast_type) */
813#define CEC_OP_UI_BCAST_TYPE_TOGGLE_ALL 0x00
814#define CEC_OP_UI_BCAST_TYPE_TOGGLE_DIG_ANA 0x01
815#define CEC_OP_UI_BCAST_TYPE_ANALOGUE 0x10
816#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_T 0x20
817#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_CABLE 0x30
818#define CEC_OP_UI_BCAST_TYPE_ANALOGUE_SAT 0x40
819#define CEC_OP_UI_BCAST_TYPE_DIGITAL 0x50
820#define CEC_OP_UI_BCAST_TYPE_DIGITAL_T 0x60
821#define CEC_OP_UI_BCAST_TYPE_DIGITAL_CABLE 0x70
822#define CEC_OP_UI_BCAST_TYPE_DIGITAL_SAT 0x80
823#define CEC_OP_UI_BCAST_TYPE_DIGITAL_COM_SAT 0x90
824#define CEC_OP_UI_BCAST_TYPE_DIGITAL_COM_SAT2 0x91
825#define CEC_OP_UI_BCAST_TYPE_IP 0xa0
826/* UI Sound Presentation Control Operand (ui_snd_pres_ctl) */
827#define CEC_OP_UI_SND_PRES_CTL_DUAL_MONO 0x10
828#define CEC_OP_UI_SND_PRES_CTL_KARAOKE 0x20
829#define CEC_OP_UI_SND_PRES_CTL_DOWNMIX 0x80
830#define CEC_OP_UI_SND_PRES_CTL_REVERB 0x90
831#define CEC_OP_UI_SND_PRES_CTL_EQUALIZER 0xa0
832#define CEC_OP_UI_SND_PRES_CTL_BASS_UP 0xb1
833#define CEC_OP_UI_SND_PRES_CTL_BASS_NEUTRAL 0xb2
834#define CEC_OP_UI_SND_PRES_CTL_BASS_DOWN 0xb3
835#define CEC_OP_UI_SND_PRES_CTL_TREBLE_UP 0xc1
836#define CEC_OP_UI_SND_PRES_CTL_TREBLE_NEUTRAL 0xc2
837#define CEC_OP_UI_SND_PRES_CTL_TREBLE_DOWN 0xc3
838
839#define CEC_MSG_USER_CONTROL_RELEASED 0x45
840
841
842/* Remote Control Passthrough Feature */
843
844/*
845 * Has also:
846 * CEC_MSG_USER_CONTROL_PRESSED
847 * CEC_MSG_USER_CONTROL_RELEASED
848 */
849
850
851/* Power Status Feature */
852#define CEC_MSG_GIVE_DEVICE_POWER_STATUS 0x8f
853#define CEC_MSG_REPORT_POWER_STATUS 0x90
854/* Power Status Operand (pwr_state) */
855#define CEC_OP_POWER_STATUS_ON 0
856#define CEC_OP_POWER_STATUS_STANDBY 1
857#define CEC_OP_POWER_STATUS_TO_ON 2
858#define CEC_OP_POWER_STATUS_TO_STANDBY 3
859
860
861/* General Protocol Messages */
862#define CEC_MSG_FEATURE_ABORT 0x00
863/* Abort Reason Operand (reason) */
864#define CEC_OP_ABORT_UNRECOGNIZED_OP 0
865#define CEC_OP_ABORT_INCORRECT_MODE 1
866#define CEC_OP_ABORT_NO_SOURCE 2
867#define CEC_OP_ABORT_INVALID_OP 3
868#define CEC_OP_ABORT_REFUSED 4
869#define CEC_OP_ABORT_UNDETERMINED 5
870
871#define CEC_MSG_ABORT 0xff
872
873
874/* System Audio Control Feature */
875
876/*
877 * Has also:
878 * CEC_MSG_USER_CONTROL_PRESSED
879 * CEC_MSG_USER_CONTROL_RELEASED
880 */
881#define CEC_MSG_GIVE_AUDIO_STATUS 0x71
882#define CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS 0x7d
883#define CEC_MSG_REPORT_AUDIO_STATUS 0x7a
884/* Audio Mute Status Operand (aud_mute_status) */
885#define CEC_OP_AUD_MUTE_STATUS_OFF 0
886#define CEC_OP_AUD_MUTE_STATUS_ON 1
887
888#define CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR 0xa3
889#define CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR 0xa4
890#define CEC_MSG_SET_SYSTEM_AUDIO_MODE 0x72
891/* System Audio Status Operand (sys_aud_status) */
892#define CEC_OP_SYS_AUD_STATUS_OFF 0
893#define CEC_OP_SYS_AUD_STATUS_ON 1
894
895#define CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST 0x70
896#define CEC_MSG_SYSTEM_AUDIO_MODE_STATUS 0x7e
897/* Audio Format ID Operand (audio_format_id) */
898#define CEC_OP_AUD_FMT_ID_CEA861 0
899#define CEC_OP_AUD_FMT_ID_CEA861_CXT 1
900
901
902/* Audio Rate Control Feature */
903#define CEC_MSG_SET_AUDIO_RATE 0x9a
904/* Audio Rate Operand (audio_rate) */
905#define CEC_OP_AUD_RATE_OFF 0
906#define CEC_OP_AUD_RATE_WIDE_STD 1
907#define CEC_OP_AUD_RATE_WIDE_FAST 2
908#define CEC_OP_AUD_RATE_WIDE_SLOW 3
909#define CEC_OP_AUD_RATE_NARROW_STD 4
910#define CEC_OP_AUD_RATE_NARROW_FAST 5
911#define CEC_OP_AUD_RATE_NARROW_SLOW 6
912
913
914/* Audio Return Channel Control Feature */
915#define CEC_MSG_INITIATE_ARC 0xc0
916#define CEC_MSG_REPORT_ARC_INITIATED 0xc1
917#define CEC_MSG_REPORT_ARC_TERMINATED 0xc2
918#define CEC_MSG_REQUEST_ARC_INITIATION 0xc3
919#define CEC_MSG_REQUEST_ARC_TERMINATION 0xc4
920#define CEC_MSG_TERMINATE_ARC 0xc5
921
922
923/* Dynamic Audio Lipsync Feature */
924/* Only for CEC 2.0 and up */
925#define CEC_MSG_REQUEST_CURRENT_LATENCY 0xa7
926#define CEC_MSG_REPORT_CURRENT_LATENCY 0xa8
927/* Low Latency Mode Operand (low_latency_mode) */
928#define CEC_OP_LOW_LATENCY_MODE_OFF 0
929#define CEC_OP_LOW_LATENCY_MODE_ON 1
930/* Audio Output Compensated Operand (audio_out_compensated) */
931#define CEC_OP_AUD_OUT_COMPENSATED_NA 0
932#define CEC_OP_AUD_OUT_COMPENSATED_DELAY 1
933#define CEC_OP_AUD_OUT_COMPENSATED_NO_DELAY 2
934#define CEC_OP_AUD_OUT_COMPENSATED_PARTIAL_DELAY 3
935
936
937/* Capability Discovery and Control Feature */
938#define CEC_MSG_CDC_MESSAGE 0xf8
939/* Ethernet-over-HDMI: nobody ever does this... */
940#define CEC_MSG_CDC_HEC_INQUIRE_STATE 0x00
941#define CEC_MSG_CDC_HEC_REPORT_STATE 0x01
942/* HEC Functionality State Operand (hec_func_state) */
943#define CEC_OP_HEC_FUNC_STATE_NOT_SUPPORTED 0
944#define CEC_OP_HEC_FUNC_STATE_INACTIVE 1
945#define CEC_OP_HEC_FUNC_STATE_ACTIVE 2
946#define CEC_OP_HEC_FUNC_STATE_ACTIVATION_FIELD 3
947/* Host Functionality State Operand (host_func_state) */
948#define CEC_OP_HOST_FUNC_STATE_NOT_SUPPORTED 0
949#define CEC_OP_HOST_FUNC_STATE_INACTIVE 1
950#define CEC_OP_HOST_FUNC_STATE_ACTIVE 2
951/* ENC Functionality State Operand (enc_func_state) */
952#define CEC_OP_ENC_FUNC_STATE_EXT_CON_NOT_SUPPORTED 0
953#define CEC_OP_ENC_FUNC_STATE_EXT_CON_INACTIVE 1
954#define CEC_OP_ENC_FUNC_STATE_EXT_CON_ACTIVE 2
955/* CDC Error Code Operand (cdc_errcode) */
956#define CEC_OP_CDC_ERROR_CODE_NONE 0
957#define CEC_OP_CDC_ERROR_CODE_CAP_UNSUPPORTED 1
958#define CEC_OP_CDC_ERROR_CODE_WRONG_STATE 2
959#define CEC_OP_CDC_ERROR_CODE_OTHER 3
960/* HEC Support Operand (hec_support) */
961#define CEC_OP_HEC_SUPPORT_NO 0
962#define CEC_OP_HEC_SUPPORT_YES 1
963/* HEC Activation Operand (hec_activation) */
964#define CEC_OP_HEC_ACTIVATION_ON 0
965#define CEC_OP_HEC_ACTIVATION_OFF 1
966
967#define CEC_MSG_CDC_HEC_SET_STATE_ADJACENT 0x02
968#define CEC_MSG_CDC_HEC_SET_STATE 0x03
969/* HEC Set State Operand (hec_set_state) */
970#define CEC_OP_HEC_SET_STATE_DEACTIVATE 0
971#define CEC_OP_HEC_SET_STATE_ACTIVATE 1
972
973#define CEC_MSG_CDC_HEC_REQUEST_DEACTIVATION 0x04
974#define CEC_MSG_CDC_HEC_NOTIFY_ALIVE 0x05
975#define CEC_MSG_CDC_HEC_DISCOVER 0x06
976/* Hotplug Detect messages */
977#define CEC_MSG_CDC_HPD_SET_STATE 0x10
978/* HPD State Operand (hpd_state) */
979#define CEC_OP_HPD_STATE_CP_EDID_DISABLE 0
980#define CEC_OP_HPD_STATE_CP_EDID_ENABLE 1
981#define CEC_OP_HPD_STATE_CP_EDID_DISABLE_ENABLE 2
982#define CEC_OP_HPD_STATE_EDID_DISABLE 3
983#define CEC_OP_HPD_STATE_EDID_ENABLE 4
984#define CEC_OP_HPD_STATE_EDID_DISABLE_ENABLE 5
985#define CEC_MSG_CDC_HPD_REPORT_STATE 0x11
986/* HPD Error Code Operand (hpd_error) */
987#define CEC_OP_HPD_ERROR_NONE 0
988#define CEC_OP_HPD_ERROR_INITIATOR_NOT_CAPABLE 1
989#define CEC_OP_HPD_ERROR_INITIATOR_WRONG_STATE 2
990#define CEC_OP_HPD_ERROR_OTHER 3
991#define CEC_OP_HPD_ERROR_NONE_NO_VIDEO 4
992
993#endif
include/media/cec-edid.h+104−0
@@ -0,0 +1,104 @@
1/*
2 * cec-edid - HDMI Consumer Electronics Control & EDID helpers
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#ifndef _MEDIA_CEC_EDID_H
21#define _MEDIA_CEC_EDID_H
22
23#include <linux/types.h>
24
25#define CEC_PHYS_ADDR_INVALID 0xffff
26#define cec_phys_addr_exp(pa) \
27 ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf
28
29/**
30 * cec_get_edid_phys_addr() - find and return the physical address
31 *
32 * @edid: pointer to the EDID data
33 * @size: size in bytes of the EDID data
34 * @offset: If not %NULL then the location of the physical address
35 * bytes in the EDID will be returned here. This is set to 0
36 * if there is no physical address found.
37 *
38 * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none.
39 */
40u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
41 unsigned int *offset);
42
43/**
44 * cec_set_edid_phys_addr() - find and set the physical address
45 *
46 * @edid: pointer to the EDID data
47 * @size: size in bytes of the EDID data
48 * @phys_addr: the new physical address
49 *
50 * This function finds the location of the physical address in the EDID
51 * and fills in the given physical address and updates the checksum
52 * at the end of the EDID block. It does nothing if the EDID doesn't
53 * contain a physical address.
54 */
55void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr);
56
57/**
58 * cec_phys_addr_for_input() - calculate the PA for an input
59 *
60 * @phys_addr: the physical address of the parent
61 * @input: the number of the input port, must be between 1 and 15
62 *
63 * This function calculates a new physical address based on the input
64 * port number. For example:
65 *
66 * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0
67 *
68 * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0
69 *
70 * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5
71 *
72 * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth.
73 *
74 * Return: the new physical address or CEC_PHYS_ADDR_INVALID.
75 */
76u16 cec_phys_addr_for_input(u16 phys_addr, u8 input);
77
78/**
79 * cec_phys_addr_validate() - validate a physical address from an EDID
80 *
81 * @phys_addr: the physical address to validate
82 * @parent: if not %NULL, then this is filled with the parents PA.
83 * @port: if not %NULL, then this is filled with the input port.
84 *
85 * This validates a physical address as read from an EDID. If the
86 * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end),
87 * then it will return -EINVAL.
88 *
89 * The parent PA is passed into %parent and the input port is passed into
90 * %port. For example:
91 *
92 * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0.
93 *
94 * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1.
95 *
96 * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2.
97 *
98 * PA = f.f.f.f: has parent f.f.f.f and input port 0.
99 *
100 * Return: 0 if the PA is valid, -EINVAL if not.
101 */
102int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port);
103
104#endif /* _MEDIA_CEC_EDID_H */
include/media/cec.h+232−0
@@ -0,0 +1,232 @@
1/*
2 * cec - HDMI Consumer Electronics Control support header
3 *
4 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5 *
6 * This program is free software; you may redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17 * SOFTWARE.
18 */
19
20#ifndef _MEDIA_CEC_H
21#define _MEDIA_CEC_H
22
23#include <linux/poll.h>
24#include <linux/fs.h>
25#include <linux/debugfs.h>
26#include <linux/device.h>
27#include <linux/cdev.h>
28#include <linux/kthread.h>
29#include <linux/timer.h>
30#include <linux/cec-funcs.h>
31#include <media/rc-core.h>
32#include <media/cec-edid.h>
33
34/**
35 * struct cec_devnode - cec device node
36 * @dev: cec device
37 * @cdev: cec character device
38 * @parent: parent device
39 * @minor: device node minor number
40 * @registered: the device was correctly registered
41 * @unregistered: the device was unregistered
42 * @fhs_lock: lock to control access to the filehandle list
43 * @fhs: the list of open filehandles (cec_fh)
44 *
45 * This structure represents a cec-related device node.
46 *
47 * The @parent is a physical device. It must be set by core or device drivers
48 * before registering the node.
49 */
50struct cec_devnode {
51 /* sysfs */
52 struct device dev;
53 struct cdev cdev;
54 struct device *parent;
55
56 /* device info */
57 int minor;
58 bool registered;
59 bool unregistered;
60 struct mutex fhs_lock;
61 struct list_head fhs;
62};
63
64struct cec_adapter;
65struct cec_data;
66
67struct cec_data {
68 struct list_head list;
69 struct list_head xfer_list;
70 struct cec_adapter *adap;
71 struct cec_msg msg;
72 struct cec_fh *fh;
73 struct delayed_work work;
74 struct completion c;
75 u8 attempts;
76 bool new_initiator;
77 bool blocking;
78 bool completed;
79};
80
81struct cec_msg_entry {
82 struct list_head list;
83 struct cec_msg msg;
84};
85
86#define CEC_NUM_EVENTS CEC_EVENT_LOST_MSGS
87
88struct cec_fh {
89 struct list_head list;
90 struct list_head xfer_list;
91 struct cec_adapter *adap;
92 u8 mode_initiator;
93 u8 mode_follower;
94
95 /* Events */
96 wait_queue_head_t wait;
97 unsigned int pending_events;
98 struct cec_event events[CEC_NUM_EVENTS];
99 struct mutex lock;
100 struct list_head msgs; /* queued messages */
101 unsigned int queued_msgs;
102};
103
104#define CEC_SIGNAL_FREE_TIME_RETRY 3
105#define CEC_SIGNAL_FREE_TIME_NEW_INITIATOR 5
106#define CEC_SIGNAL_FREE_TIME_NEXT_XFER 7
107
108/* The nominal data bit period is 2.4 ms */
109#define CEC_FREE_TIME_TO_USEC(ft) ((ft) * 2400)
110
111struct cec_adap_ops {
112 /* Low-level callbacks */
113 int (*adap_enable)(struct cec_adapter *adap, bool enable);
114 int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
115 int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
116 int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
117 u32 signal_free_time, struct cec_msg *msg);
118 void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
119
120 /* High-level CEC message callback */
121 int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
122};
123
124/*
125 * The minimum message length you can receive (excepting poll messages) is 2.
126 * With a transfer rate of at most 36 bytes per second this makes 18 messages
127 * per second worst case.
128 *
129 * We queue at most 3 seconds worth of messages. The CEC specification requires
130 * that messages are replied to within a second, so 3 seconds should give more
131 * than enough margin. Since most messages are actually more than 2 bytes, this
132 * is in practice a lot more than 3 seconds.
133 */
134#define CEC_MAX_MSG_QUEUE_SZ (18 * 3)
135
136struct cec_adapter {
137 struct module *owner;
138 char name[32];
139 struct cec_devnode devnode;
140 struct mutex lock;
141 struct rc_dev *rc;
142
143 struct list_head transmit_queue;
144 struct list_head wait_queue;
145 struct cec_data *transmitting;
146
147 struct task_struct *kthread_config;
148 struct completion config_completion;
149
150 struct task_struct *kthread;
151 wait_queue_head_t kthread_waitq;
152 wait_queue_head_t waitq;
153
154 const struct cec_adap_ops *ops;
155 void *priv;
156 u32 capabilities;
157 u8 available_log_addrs;
158
159 u16 phys_addr;
160 bool is_configuring;
161 bool is_configured;
162 u32 monitor_all_cnt;
163 u32 follower_cnt;
164 struct cec_fh *cec_follower;
165 struct cec_fh *cec_initiator;
166 bool passthrough;
167 struct cec_log_addrs log_addrs;
168
169 struct dentry *cec_dir;
170 struct dentry *status_file;
171
172 u16 phys_addrs[15];
173 u32 sequence;
174
175 char input_name[32];
176 char input_phys[32];
177 char input_drv[32];
178};
179
180static inline bool cec_has_log_addr(const struct cec_adapter *adap, u8 log_addr)
181{
182 return adap->log_addrs.log_addr_mask & (1 << log_addr);
183}
184
185static inline bool cec_is_sink(const struct cec_adapter *adap)
186{
187 return adap->phys_addr == 0;
188}
189
190#if IS_ENABLED(CONFIG_MEDIA_CEC)
191struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
192 void *priv, const char *name, u32 caps, u8 available_las,
193 struct device *parent);
194int cec_register_adapter(struct cec_adapter *adap);
195void cec_unregister_adapter(struct cec_adapter *adap);
196void cec_delete_adapter(struct cec_adapter *adap);
197
198int cec_s_log_addrs(struct cec_adapter *adap, struct cec_log_addrs *log_addrs,
199 bool block);
200void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
201 bool block);
202int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
203 bool block);
204
205/* Called by the adapter */
206void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
207 u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt);
208void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
209
210#else
211
212static inline int cec_register_adapter(struct cec_adapter *adap)
213{
214 return 0;
215}
216
217static inline void cec_unregister_adapter(struct cec_adapter *adap)
218{
219}
220
221static inline void cec_delete_adapter(struct cec_adapter *adap)
222{
223}
224
225static inline void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
226 bool block)
227{
228}
229
230#endif
231
232#endif /* _MEDIA_CEC_H */
include/media/i2c/adv7511.h+1−5
@@ -32,11 +32,7 @@ struct adv7511_monitor_detect { · 31 unmodified lines
32struct adv7511_edid_detect {32struct adv7511_edid_detect {
33 int present;33 int present;
34 int segment;34 int segment;
35};35 uint16_t phys_addr;
36
37struct adv7511_cec_arg {
38 void *arg;
39 u32 f_flags;
40};36};
41 37
42struct adv7511_platform_data {38struct adv7511_platform_data {
include/media/rc-map.h+4−1
@@ -31,6 +31,7 @@ enum rc_type { · 30 unmodified lines
31 RC_TYPE_RC6_MCE = 16, /* MCE (Philips RC6-6A-32 subtype) protocol */31 RC_TYPE_RC6_MCE = 16, /* MCE (Philips RC6-6A-32 subtype) protocol */
32 RC_TYPE_SHARP = 17, /* Sharp protocol */32 RC_TYPE_SHARP = 17, /* Sharp protocol */
33 RC_TYPE_XMP = 18, /* XMP protocol */33 RC_TYPE_XMP = 18, /* XMP protocol */
34 RC_TYPE_CEC = 19, /* CEC protocol */
34};35};
35 36
36#define RC_BIT_NONE 0ULL37#define RC_BIT_NONE 0ULL
@@ -53,6 +54,7 @@ enum rc_type { · 16 unmodified lines
53#define RC_BIT_RC6_MCE (1ULL << RC_TYPE_RC6_MCE)54#define RC_BIT_RC6_MCE (1ULL << RC_TYPE_RC6_MCE)
54#define RC_BIT_SHARP (1ULL << RC_TYPE_SHARP)55#define RC_BIT_SHARP (1ULL << RC_TYPE_SHARP)
55#define RC_BIT_XMP (1ULL << RC_TYPE_XMP)56#define RC_BIT_XMP (1ULL << RC_TYPE_XMP)
57#define RC_BIT_CEC (1ULL << RC_TYPE_CEC)
56 58
57#define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \59#define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \
58 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \60 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
@@ -61,7 +63,7 @@ enum rc_type { · 2 unmodified lines
61 RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \63 RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \
62 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \64 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
63 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE | RC_BIT_SHARP | \65 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE | RC_BIT_SHARP | \
64 RC_BIT_XMP)66 RC_BIT_XMP | RC_BIT_CEC)
65 67
66 68
67#define RC_SCANCODE_UNKNOWN(x) (x)69#define RC_SCANCODE_UNKNOWN(x) (x)
@@ -123,6 +125,7 @@ void rc_map_init(void); · 55 unmodified lines
123#define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus"125#define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus"
124#define RC_MAP_BEHOLD "rc-behold"126#define RC_MAP_BEHOLD "rc-behold"
125#define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old"127#define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old"
128#define RC_MAP_CEC "rc-cec"
126#define RC_MAP_CINERGY_1400 "rc-cinergy-1400"129#define RC_MAP_CINERGY_1400 "rc-cinergy-1400"
127#define RC_MAP_CINERGY "rc-cinergy"130#define RC_MAP_CINERGY "rc-cinergy"
128#define RC_MAP_DELOCK_61959 "rc-delock-61959"131#define RC_MAP_DELOCK_61959 "rc-delock-61959"
include/uapi/linux/input-event-codes.h+31−0
@@ -611,6 +611,37 @@ · 610 unmodified lines
611#define KEY_KBDINPUTASSIST_ACCEPT 0x264611#define KEY_KBDINPUTASSIST_ACCEPT 0x264
612#define KEY_KBDINPUTASSIST_CANCEL 0x265612#define KEY_KBDINPUTASSIST_CANCEL 0x265
613 613
614/* Diagonal movement keys */
615#define KEY_RIGHT_UP 0x266
616#define KEY_RIGHT_DOWN 0x267
617#define KEY_LEFT_UP 0x268
618#define KEY_LEFT_DOWN 0x269
619
620#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */
621/* Show Top Menu of the Media (e.g. DVD) */
622#define KEY_MEDIA_TOP_MENU 0x26b
623#define KEY_NUMERIC_11 0x26c
624#define KEY_NUMERIC_12 0x26d
625/*
626 * Toggle Audio Description: refers to an audio service that helps blind and
627 * visually impaired consumers understand the action in a program. Note: in
628 * some countries this is referred to as "Video Description".
629 */
630#define KEY_AUDIO_DESC 0x26e
631#define KEY_3D_MODE 0x26f
632#define KEY_NEXT_FAVORITE 0x270
633#define KEY_STOP_RECORD 0x271
634#define KEY_PAUSE_RECORD 0x272
635#define KEY_VOD 0x273 /* Video on Demand */
636#define KEY_UNMUTE 0x274
637#define KEY_FASTREVERSE 0x275
638#define KEY_SLOWREVERSE 0x276
639/*
640 * Control a data application associated with the currently viewed channel,
641 * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
642 */
643#define KEY_DATA 0x275
644
614#define BTN_TRIGGER_HAPPY 0x2c0645#define BTN_TRIGGER_HAPPY 0x2c0
615#define BTN_TRIGGER_HAPPY1 0x2c0646#define BTN_TRIGGER_HAPPY1 0x2c0
616#define BTN_TRIGGER_HAPPY2 0x2c1647#define BTN_TRIGGER_HAPPY2 0x2c1
include/uapi/linux/input.h+1−0
@@ -247,6 +247,7 @@ struct input_mask { · 246 unmodified lines
247#define BUS_ATARI 0x1B247#define BUS_ATARI 0x1B
248#define BUS_SPI 0x1C248#define BUS_SPI 0x1C
249#define BUS_RMI 0x1D249#define BUS_RMI 0x1D
250#define BUS_CEC 0x1E
250 251
251/*252/*
252 * MT_TOOL types253 * MT_TOOL types

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t