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
272272 !Iinclude/media/media-devnode.h
273273 !Iinclude/media/media-entity.h
274274 </sect1>
275+ <sect1><title>Consumer Electronics Control devices</title>
276+!Iinclude/media/cec-edid.h
277+ </sect1>
275278
276279 </chapter>
277280
Documentation/DocBook/media/Makefile+2−0
@@ -64,6 +64,7 @@ IOCTLS = \ · 63 unmodified lines
6464 $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \
6565 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \
6666 $(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) \
6768 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
6869
6970 DEFINES = \
@@ -100,6 +101,7 @@ STRUCTS = \ · 30 unmodified lines
100101 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/ && !/_old/)' $(srctree)/include/uapi/linux/dvb/net.h) \
101102 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \
102103 $(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) \
103105 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
104106 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h)
105107
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
342342 <subtitle>Specification Version 1.4a</subtitle>
343343 </biblioentry>
344344
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+
345355 <biblioentry id="dp">
346356 <abbrev>DP</abbrev>
347357 <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
39+given, the &CEC-RECEIVE; ioctl will return &EAGAIN; when no message is
40+available, 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
33+can wait for CEC events.</para>
34+
35+ <para>On success <function>poll()</function> returns the number of
36+file descriptors that have been selected (that is, file descriptors
37+for which the <structfield>revents</structfield> field of the
38+respective <structname>pollfd</structname> structure is non-zero).
39+CEC 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
42+receive queue. If the transmit queue has room for new messages, the
43+<constant>POLLOUT</constant> and <constant>POLLWRNORM</constant>
44+flags are set. If there are events in the event queue, then the
45+<constant>POLLPRI</constant> flag is set.
46+When the function timed out it returns a value of zero, on
47+failure 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
59+structures which have non-zero <structfield>revents</structfield>
60+fields, 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
69+specify 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
76+memory 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
89+than <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
61+logical addresses.</para>
62+
63+ <para>To set new logical addresses, applications fill in struct <structname>cec_log_addrs</structname>
64+and call the <constant>CEC_ADAP_S_LOG_ADDRS</constant> ioctl with a pointer to this struct.
65+The <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
67+requested logical addresses have been claimed. <constant>CEC_ADAP_S_LOG_ADDRS</constant>
68+can 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
60+where the driver stores the physical address.</para>
61+
62+ <para>To set a new physical address applications store the physical address in
63+an __u16 and call the <constant>CEC_ADAP_S_PHYS_ADDR</constant> ioctl with a
64+pointer to this integer. <constant>CEC_ADAP_S_PHYS_ADDR</constant> is only
65+available if <constant>CEC_CAP_PHYS_ADDR</constant> is set (&ENOTTY; will be returned
66+otherwise). <constant>CEC_ADAP_S_PHYS_ADDR</constant>
67+can 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
71+represent a digit of the physical address a.b.c.d where the most significant
72+4 bits represent 'a'. The CEC root device (usually the TV) has address 0.0.0.0.
73+Every 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.
75+So a topology of up to 5 devices deep is supported. The physical address a
76+device 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
79+physical address of the form a.0.0.0 that the sources will read out and use as
80+their 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
59+in order to prevent applications from stepping on each others toes it must be possible
60+to obtain exclusive access to the CEC adapter. This ioctl sets the filehandle
61+to initiator and/or follower mode which can be exclusive depending on the chosen
62+mode. The initiator is the filehandle that is used
63+to initiate messages, i.e. it commands other CEC devices. The follower is the filehandle
64+that receives messages sent to the CEC adapter and processes them. The same filehandle
65+can be both initiator and follower, or this role can be taken by two different
66+filehandles.</para>
67+
68+ <para>When a CEC message is received, then the CEC framework will decide how
69+it will be processed. If the message is a reply to an earlier transmitted message,
70+then the reply is sent back to the filehandle that is waiting for it. In addition
71+the CEC framework will process it.</para>
72+
73+ <para>If the message is not a reply, then the CEC framework will process it
74+first. If there is no follower, then the message is just discarded and a feature
75+abort is sent back to the initiator if the framework couldn't process it. If there
76+is 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
78+make the right decisions.</para>
79+
80+ <para>The CEC framework will process core messages unless requested otherwise
81+by the follower. The follower can enable the passthrough mode. In that case, the
82+CEC framework will pass on most core messages without processing them and
83+the follower will have to implement those messages. There are some messages
84+that 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;.
88+If there is an exclusive initiator then only that initiator can call &CEC-TRANSMIT;.
89+The 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
7575 </mediaobject>
7676 </figure>
7777 <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>
7979 <para>The first part covers radio, video capture and output,
8080 cameras, analog TV devices and codecs.</para>
8181 <para>The second part covers the
@@ -87,6 +87,7 @@ · 5 unmodified lines
8787 <xref linkend="fe-delivery-system-t" />.</para>
8888 <para>The third part covers the Remote Controller API.</para>
8989 <para>The fourth part covers the Media Controller API.</para>
90+ <para>The fifth part covers the CEC (Consumer Electronics Control) API.</para>
9091 <para>It should also be noted that a media device may also have audio
9192 components, like mixers, PCM capture, PCM playback, etc, which
9293 are controlled via ALSA API.</para>
@@ -107,6 +108,9 @@ · 14 unmodified lines
107108 <part id="media_common">
108109 &sub-media-controller;
109110 </part>
111+<part id="cec">
112+&sub-cec-api;
113+</part>
110114
111115 <chapter id="gen_errors">
112116 &sub-gen-errors;
Documentation/cec.txt+267−0
@@ -0,0 +1,267 @@
1+CEC Kernel Support
2+==================
3+
4+The CEC framework provides a unified kernel interface for use with HDMI CEC
5+hardware. It is designed to handle a multiple types of hardware (receivers,
6+transmitters, USB dongles). The framework also gives the option to decide
7+what to do in the kernel driver and what should be handled by userspace
8+applications. In addition it integrates the remote control passthrough
9+feature into the kernel's remote control framework.
10+
11+
12+The CEC Protocol
13+----------------
14+
15+The CEC protocol enables consumer electronic devices to communicate with each
16+other through the HDMI connection. The protocol uses logical addresses in the
17+communication. The logical address is strictly connected with the functionality
18+provided by the device. The TV acting as the communication hub is always
19+assigned address 0. The physical address is determined by the physical
20+connection between devices.
21+
22+The CEC framework described here is up to date with the CEC 2.0 specification.
23+It is documented in the HDMI 1.4 specification with the new 2.0 bits documented
24+in the HDMI 2.0 specification. But for most of the features the freely available
25+HDMI 1.3a specification is sufficient:
26+
27+http://www.microprocessor.org/HDMISpecification13a.pdf
28+
29+
30+The Kernel Interface
31+====================
32+
33+CEC Adapter
34+-----------
35+
36+The struct cec_adapter represents the CEC adapter hardware. It is created by
37+calling cec_allocate_adapter() and deleted by calling cec_delete_adapter():
38+
39+struct 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);
42+void cec_delete_adapter(struct cec_adapter *adap);
43+
44+To create an adapter you need to pass the following information:
45+
46+ops: adapter operations which are called by the CEC framework and that you
47+have to implement.
48+
49+priv: will be stored in adap->priv and can be used by the adapter ops.
50+
51+name: the name of the CEC adapter. Note: this name will be copied.
52+
53+caps: 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+
58+available_las: the number of simultaneous logical addresses that this
59+ adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS.
60+
61+parent: the parent device.
62+
63+
64+To register the /dev/cecX device node and the remote control device (if
65+CEC_CAP_RC is set) you call:
66+
67+int cec_register_adapter(struct cec_adapter *adap);
68+
69+To unregister the devices call:
70+
71+void cec_unregister_adapter(struct cec_adapter *adap);
72+
73+Note: if cec_register_adapter() fails, then call cec_delete_adapter() to
74+clean up. But if cec_register_adapter() succeeded, then only call
75+cec_unregister_adapter() to clean up, never cec_delete_adapter(). The
76+unregister function will delete the adapter automatically once the last user
77+of that /dev/cecX device has closed its file handle.
78+
79+
80+Implementing the Low-Level CEC Adapter
81+--------------------------------------
82+
83+The following low-level adapter operations have to be implemented in
84+your driver:
85+
86+struct 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+
99+The three low-level ops deal with various aspects of controlling the CEC adapter
100+hardware:
101+
102+
103+To enable/disable the hardware:
104+
105+ int (*adap_enable)(struct cec_adapter *adap, bool enable);
106+
107+This callback enables or disables the CEC hardware. Enabling the CEC hardware
108+means powering it up in a state where no logical addresses are claimed. This
109+op assumes that the physical address (adap->phys_addr) is valid when enable is
110+true and will not change while the CEC adapter remains enabled. The initial
111+state of the CEC adapter after calling cec_allocate_adapter() is disabled.
112+
113+Note that adap_enable must return 0 if enable is false.
114+
115+
116+To enable/disable the 'monitor all' mode:
117+
118+ int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
119+
120+If enabled, then the adapter should be put in a mode to also monitor messages
121+that not for us. Not all hardware supports this and this function is only
122+called if the CEC_CAP_MONITOR_ALL capability is set. This callback is optional
123+(some hardware may always be in 'monitor all' mode).
124+
125+Note that adap_monitor_all_enable must return 0 if enable is false.
126+
127+
128+To program a new logical address:
129+
130+ int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
131+
132+If logical_addr == CEC_LOG_ADDR_INVALID then all programmed logical addresses
133+are to be erased. Otherwise the given logical address should be programmed.
134+If the maximum number of available logical addresses is exceeded, then it
135+should return -ENXIO. Once a logical address is programmed the CEC hardware
136+can receive directed messages to that address.
137+
138+Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
139+
140+
141+To 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+
146+This transmits a new message. The attempts argument is the suggested number of
147+attempts for the transmit.
148+
149+The signal_free_time is the number of data bit periods that the adapter should
150+wait when the line is free before attempting to send a message. This value
151+depends on whether this transmit is a retry, a message from a new initiator or
152+a new message for the same initiator. Most hardware will handle this
153+automatically, but in some cases this information is needed.
154+
155+The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to
156+microseconds (one data bit period is 2.4 ms).
157+
158+
159+To log the current CEC hardware status:
160+
161+ void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
162+
163+This optional callback can be used to show the status of the CEC hardware.
164+The status is available through debugfs: cat /sys/kernel/debug/cec/cecX/status
165+
166+
167+Your adapter driver will also have to react to events (typically interrupt
168+driven) by calling into the framework in the following situations:
169+
170+When a transmit finished (successfully or otherwise):
171+
172+void 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+
175+The status can be one of:
176+
177+CEC_TX_STATUS_OK: the transmit was successful.
178+CEC_TX_STATUS_ARB_LOST: arbitration was lost: another CEC initiator
179+took control of the CEC line and you lost the arbitration.
180+CEC_TX_STATUS_NACK: the message was nacked (for a directed message) or
181+acked (for a broadcast message). A retransmission is needed.
182+CEC_TX_STATUS_LOW_DRIVE: low drive was detected on the CEC bus. This
183+indicates that a follower detected an error on the bus and requested a
184+retransmission.
185+CEC_TX_STATUS_ERROR: some unspecified error occurred: this can be one of
186+the previous two if the hardware cannot differentiate or something else
187+entirely.
188+CEC_TX_STATUS_MAX_RETRIES: could not transmit the message after
189+trying multiple times. Should only be set by the driver if it has hardware
190+support for retrying messages. If set, then the framework assumes that it
191+doesn't have to make another attempt to transmit the message since the
192+hardware did that already.
193+
194+The *_cnt arguments are the number of error conditions that were seen.
195+This may be 0 if no information is available. Drivers that do not support
196+hardware retry can just set the counter corresponding to the transmit error
197+to 1, if the hardware does support retry then either set these counters to
198+0 if the hardware provides no feedback of which errors occurred and how many
199+times, or fill in the correct values as reported by the hardware.
200+
201+When a CEC message was received:
202+
203+void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
204+
205+Speaks for itself.
206+
207+Implementing the High-Level CEC Adapter
208+---------------------------------------
209+
210+The low-level operations drive the hardware, the high-level operations are
211+CEC protocol driven. The following high-level callbacks are available:
212+
213+struct 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+
221+The received() callback allows the driver to optionally handle a newly
222+received CEC message
223+
224+ int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
225+
226+If the driver wants to process a CEC message, then it can implement this
227+callback. 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
229+it will not no anything with it.
230+
231+
232+CEC framework functions
233+-----------------------
234+
235+CEC Adapter drivers can call the following CEC framework functions:
236+
237+int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
238+ bool block);
239+
240+Transmit a CEC message. If block is true, then wait until the message has been
241+transmitted, otherwise just queue it and return.
242+
243+void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
244+
245+Change the physical address. This function will set adap->phys_addr and
246+send an event if it has changed. If cec_s_log_addrs() has been called and
247+the physical address has become valid, then the CEC framework will start
248+claiming the logical addresses. If block is true, then this function won't
249+return until this process has finished.
250+
251+When the physical address is set to a valid value the CEC adapter will
252+be enabled (see the adap_enable op). When it is set to CEC_PHYS_ADDR_INVALID,
253+then the CEC adapter will be disabled. If you change a valid physical address
254+to another valid physical address, then this function will first set the
255+address to CEC_PHYS_ADDR_INVALID before enabling the new physical address.
256+
257+int cec_s_log_addrs(struct cec_adapter *adap,
258+ struct cec_log_addrs *log_addrs, bool block);
259+
260+Claim the CEC logical addresses. Should never be called if CEC_CAP_LOG_ADDRS
261+is set. If block is true, then wait until the logical addresses have been
262+claimed, otherwise just queue it and return. To unconfigure all logical
263+addresses call this function with log_addrs set to NULL or with
264+log_addrs->num_log_addrs set to 0. The block argument is ignored when
265+unconfiguring. This function will just return if the physical address is
266+invalid. Once the physical address becomes valid, then the framework will
267+attempt to claim these logical addresses.
Documentation/devicetree/bindings/media/s5p-cec.txt+31−0
@@ -0,0 +1,31 @@
1+* Samsung HDMI CEC driver
2+
3+The HDMI CEC module is present is Samsung SoCs and its purpose is to
4+handle communication between HDMI connected devices over the CEC bus.
5+
6+Required 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+
19+Example:
20+
21+hdmicec: 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
7474 Section 12: Formats
7575 Section 13: Capture Overlay
7676 Section 14: Output Overlay
77−Section 15: Some Future Improvements
77+Section 15: CEC (Consumer Electronics Control)
78+Section 16: Some Future Improvements
7879
7980
8081 Section 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
364365 is provided. You can only set the EDID for HDMI inputs. Internally, however,
365366 the EDID is shared between all HDMI inputs.
366367
367−No interpretation is done of the EDID data.
368+No interpretation is done of the EDID data with the exception of the
369+physical address. See the CEC section for more details.
370+
371+There is a maximum of 15 HDMI inputs (if there are more, then they will be
372+reduced to 15) since that's the limitation of the EDID physical address.
368373
369374
370375 Section 3: Video Output
@@ -409,6 +414,9 @@ standard, and for all others a 1:1 pixel aspect ratio is returned. · 38 unmodified lines
409414
410415 An HDMI output has a valid EDID which can be obtained through VIDIOC_G_EDID.
411416
417+There is a maximum of 15 HDMI outputs (if there are more, then they will be
418+reduced to 15) since that's the limitation of the EDID physical address. See
419+also the CEC section for more details.
412420
413421 Section 4: VBI Capture
414422 ----------------------
@@ -1108,7 +1116,26 @@ capabilities will slow down the video loop considerably as a lot of checks have · 693 unmodified lines
11081116 to be done per pixel.
11091117
11101118
1111−Section 15: Some Future Improvements
1119+Section 15: CEC (Consumer Electronics Control)
1120+----------------------------------------------
1121+
1122+If there are HDMI inputs then a CEC adapter will be created that has
1123+the same number of input ports. This is the equivalent of e.g. a TV that
1124+has that number of inputs. Each HDMI output will also create a
1125+CEC adapter that is hooked up to the corresponding input port, or (if there
1126+are more outputs than inputs) is not hooked up at all. In other words,
1127+this is the equivalent of hooking up each output device to an input port of
1128+the TV. Any remaining output devices remain unconnected.
1129+
1130+The EDID that each output reads reports a unique CEC physical address that is
1131+based on the physical address of the EDID of the input. So if the EDID of the
1132+receiver has physical address A.B.0.0, then each output will see an EDID
1133+containing physical address A.B.C.0 where C is 1 to the number of inputs. If
1134+there are more outputs than inputs then the remaining outputs have a CEC adapter
1135+that is disabled and reports an invalid physical address.
1136+
1137+
1138+Section 16: Some Future Improvements
11121139 ------------------------------------
11131140
11141141 Just as a reminder and in no particular order:
@@ -1121,8 +1148,6 @@ Just as a reminder and in no particular order: · 6 unmodified lines
11211148 - Fix sequence/field numbering when looping of video with alternate fields
11221149 - Add support for V4L2_CID_BG_COLOR for video outputs
11231150 - 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
11261151 - Improve pixel aspect support in the tpg code by passing a real v4l2_fract
11271152 - Use per-queue locks and/or per-device locks to improve throughput
11281153 - 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
11331158 - Make a thread for the RDS generation, that would help in particular for the
11341159 "Controls" RDS Rx I/O Mode as the read-only RDS controls could be updated
11351160 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
16421642 S: Maintained
16431643 F: drivers/media/platform/s5p-tv/
16441644
1645+ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT
1646+M: Kyungmin Park <kyungmin.park@samsung.com>
1647+L: linux-arm-kernel@lists.infradead.org
1648+L: linux-media@vger.kernel.org
1649+S: Maintained
1650+F: drivers/staging/media/platform/s5p-cec/
1651+
16451652 ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
16461653 M: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
16471654 M: Jacek Anaszewski <j.anaszewski@samsung.com>
@@ -2847,6 +2854,22 @@ F: drivers/net/ieee802154/cc2520.c · 1199 unmodified lines
28472854 F: include/linux/spi/cc2520.h
28482855 F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
28492856
2857+CEC DRIVER
2858+M: Hans Verkuil <hans.verkuil@cisco.com>
2859+L: linux-media@vger.kernel.org
2860+T: git git://linuxtv.org/media_tree.git
2861+W: http://linuxtv.org
2862+S: Supported
2863+F: Documentation/cec.txt
2864+F: Documentation/DocBook/media/v4l/cec*
2865+F: drivers/staging/media/cec/
2866+F: drivers/media/cec-edid.c
2867+F: drivers/media/rc/keymaps/rc-cec.c
2868+F: include/media/cec.h
2869+F: include/media/cec-edid.h
2870+F: include/linux/cec.h
2871+F: include/linux/cec-funcs.h
2872+
28502873 CELL BROADBAND ENGINE ARCHITECTURE
28512874 M: Arnd Bergmann <arnd@arndb.de>
28522875 L: linuxppc-dev@lists.ozlabs.org
drivers/media/Kconfig+3−0
@@ -80,6 +80,9 @@ config MEDIA_RC_SUPPORT · 79 unmodified lines
8080
8181 Say Y when you have a TV or an IR device.
8282
83+config MEDIA_CEC_EDID
84+ tristate
85+
8386 #
8487 # Media controller
8588 # Selectable only for webcam/grabbers, as other drivers don't use it
drivers/media/Makefile+2−0
@@ -2,6 +2,8 @@ · 1 unmodified line
22 # Makefile for the kernel multimedia device drivers.
33 #
44
5+obj-$(CONFIG_MEDIA_CEC_EDID) += cec-edid.o
6+
57 media-objs := media-device.o media-devnode.o media-entity.o
68
79 #
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+ */
32+static 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+
82+u16 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+}
93+EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr);
94+
95+void 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+}
112+EXPORT_SYMBOL_GPL(cec_set_edid_phys_addr);
113+
114+u16 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+}
138+EXPORT_SYMBOL_GPL(cec_phys_addr_for_input);
139+
140+int 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+}
164+EXPORT_SYMBOL_GPL(cec_phys_addr_validate);
165+
166+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
167+MODULE_DESCRIPTION("CEC EDID helper functions");
168+MODULE_LICENSE("GPL");
drivers/media/i2c/Kconfig+24−0
@@ -209,6 +209,7 @@ config VIDEO_ADV7604 · 208 unmodified lines
209209 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
210210 depends on GPIOLIB || COMPILE_TEST
211211 select HDMI
212+ select MEDIA_CEC_EDID
212213 ---help---
213214 Support for the Analog Devices ADV7604 video decoder.
214215
@@ -218,10 +219,18 @@ config VIDEO_ADV7604 · 3 unmodified lines
218219 To compile this driver as a module, choose M here: the
219220 module will be called adv7604.
220221
222+config 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+
221229 config VIDEO_ADV7842
222230 tristate "Analog Devices ADV7842 decoder"
223231 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
224232 select HDMI
233+ select MEDIA_CEC_EDID
225234 ---help---
226235 Support for the Analog Devices ADV7842 video decoder.
227236
@@ -231,6 +240,13 @@ config VIDEO_ADV7842 · 3 unmodified lines
231240 To compile this driver as a module, choose M here: the
232241 module will be called adv7842.
233242
243+config 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+
234250 config VIDEO_BT819
235251 tristate "BT819A VideoStream decoder"
236252 depends on VIDEO_V4L2 && I2C
@@ -447,6 +463,7 @@ config VIDEO_ADV7511 · 210 unmodified lines
447463 tristate "Analog Devices ADV7511 encoder"
448464 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
449465 select HDMI
466+ select MEDIA_CEC_EDID
450467 ---help---
451468 Support for the Analog Devices ADV7511 video encoder.
452469
@@ -455,6 +472,13 @@ config VIDEO_ADV7511 · 2 unmodified lines
455472 To compile this driver as a module, choose M here: the
456473 module will be called adv7511.
457474
475+config 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+
458482 config VIDEO_AD9389B
459483 tristate "Analog Devices AD9389B encoder"
460484 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
drivers/media/i2c/adv7511.c+393−8
@@ -33,6 +33,7 @@ · 32 unmodified lines
3333 #include <media/v4l2-ctrls.h>
3434 #include <media/v4l2-dv-timings.h>
3535 #include <media/i2c/adv7511.h>
36+#include <media/cec.h>
3637
3738 static int debug;
3839 module_param(debug, int, 0644);
@@ -59,6 +60,8 @@ MODULE_LICENSE("GPL v2"); · 20 unmodified lines
5960 #define ADV7511_MIN_PIXELCLOCK 20000000
6061 #define ADV7511_MAX_PIXELCLOCK 225000000
6162
63+#define ADV7511_MAX_ADDRS (3)
64+
6265 /*
6366 **********************************************************************
6467 *
@@ -90,12 +93,20 @@ struct adv7511_state { · 25 unmodified lines
9093 struct v4l2_ctrl_handler hdl;
9194 int chip_revision;
9295 u8 i2c_edid_addr;
93− u8 i2c_cec_addr;
9496 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+
95105 /* Is the adv7511 powered on? */
96106 bool power_on;
97107 /* Did we receive hotplug and rx-sense signals? */
98108 bool have_monitor;
109+ bool enabled_irq;
99110 /* timings from s_dv_timings */
100111 struct v4l2_dv_timings dv_timings;
101112 u32 fmt_code;
@@ -227,7 +238,7 @@ static int adv_smbus_read_i2c_block_data(struct i2c_client *client, · 125 unmodified lines
227238 return ret;
228239 }
229240
230−static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
241+static void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf)
231242 {
232243 struct adv7511_state *state = get_adv7511_state(sd);
233244 int i;
@@ -242,6 +253,34 @@ static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf) · 8 unmodified lines
242253 v4l2_err(sd, "%s: i2c read error\n", __func__);
243254 }
244255
256+static 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+
263+static 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+
278+static 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+
245284 static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
246285 {
247286 struct adv7511_state *state = get_adv7511_state(sd);
@@ -425,16 +464,28 @@ static const struct v4l2_ctrl_ops adv7511_ctrl_ops = { · 177 unmodified lines
425464 #ifdef CONFIG_VIDEO_ADV_DEBUG
426465 static void adv7511_inv_register(struct v4l2_subdev *sd)
427466 {
467+ struct adv7511_state *state = get_adv7511_state(sd);
468+
428469 v4l2_info(sd, "0x000-0x0ff: Main Map\n");
470+ if (state->i2c_cec)
471+ v4l2_info(sd, "0x100-0x1ff: CEC Map\n");
429472 }
430473
431474 static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
432475 {
476+ struct adv7511_state *state = get_adv7511_state(sd);
477+
433478 reg->size = 1;
434479 switch (reg->reg >> 8) {
435480 case 0:
436481 reg->val = adv7511_rd(sd, reg->reg & 0xff);
437482 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 */
438489 default:
439490 v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
440491 adv7511_inv_register(sd);
@@ -445,10 +496,18 @@ static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * · 4 unmodified lines
445496
446497 static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
447498 {
499+ struct adv7511_state *state = get_adv7511_state(sd);
500+
448501 switch (reg->reg >> 8) {
449502 case 0:
450503 adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff);
451504 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 */
452511 default:
453512 v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
454513 adv7511_inv_register(sd);
@@ -536,6 +595,7 @@ static int adv7511_log_status(struct v4l2_subdev *sd) · 81 unmodified lines
536595 {
537596 struct adv7511_state *state = get_adv7511_state(sd);
538597 struct adv7511_state_edid *edid = &state->edid;
598+ int i;
539599
540600 static const char * const states[] = {
541601 "in reset",
@@ -605,7 +665,23 @@ static int adv7511_log_status(struct v4l2_subdev *sd) · 63 unmodified lines
605665 else
606666 v4l2_info(sd, "no timings set\n");
607667 v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr);
668+
669+ if (state->i2c_cec == NULL)
670+ return 0;
671+
608672 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+ }
609685 v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr);
610686 return 0;
611687 }
@@ -663,15 +739,197 @@ static int adv7511_s_power(struct v4l2_subdev *sd, int on) · 51 unmodified lines
663739 return true;
664740 }
665741
742+#if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
743+static 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+
778+static 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+
832+static 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+
868+static 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+
912+static 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+
666919 /* Enable interrupts */
667920 static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
668921 {
922+ struct adv7511_state *state = get_adv7511_state(sd);
669923 u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT;
670924 u8 irqs_rd;
671925 int retries = 100;
672926
673927 v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable");
674928
929+ if (state->enabled_irq == enable)
930+ return;
931+ state->enabled_irq = enable;
932+
675933 /* The datasheet says that the EDID ready interrupt should be
676934 disabled if there is no hotplug. */
677935 if (!enable)
@@ -679,6 +937,9 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) · 1 unmodified line
679937 else if (adv7511_have_hotplug(sd))
680938 irqs |= MASK_ADV7511_EDID_RDY_INT;
681939
940+ adv7511_wr_and_or(sd, 0x95, 0xc0,
941+ (state->cec_enabled_adap && enable) ? 0x39 : 0x00);
942+
682943 /*
683944 * This i2c write can fail (approx. 1 in 1000 writes). But it
684945 * 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
701962 static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
702963 {
703964 u8 irq_status;
965+ u8 cec_irq;
704966
705967 /* disable interrupts to prevent a race condition */
706968 adv7511_set_isr(sd, false);
707969 irq_status = adv7511_rd(sd, 0x96);
970+ cec_irq = adv7511_rd(sd, 0x97);
708971 /* clear detected interrupts */
709972 adv7511_wr(sd, 0x96, irq_status);
973+ adv7511_wr(sd, 0x97, cec_irq);
710974
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);
712977
713978 if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT))
714979 adv7511_check_monitor_present_status(sd);
715980 if (irq_status & MASK_ADV7511_EDID_RDY_INT)
716981 adv7511_check_edid_status(sd);
717982
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+
7181012 /* enable interrupts */
7191013 adv7511_set_isr(sd, true);
7201014
@@ -1183,6 +1477,8 @@ static void adv7511_notify_no_edid(struct v4l2_subdev *sd) · 462 unmodified lines
11831477 /* We failed to read the EDID, so send an event for this. */
11841478 ed.present = false;
11851479 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);
11861482 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
11871483 v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0);
11881484 }
@@ -1406,13 +1702,16 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) · 217 unmodified lines
14061702
14071703 v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments);
14081704 state->edid.complete = true;
1409−
1705+ ed.phys_addr = cec_get_edid_phys_addr(state->edid.data,
1706+ state->edid.segments * 256,
1707+ NULL);
14101708 /* report when we have all segments
14111709 but report only for segment 0
14121710 */
14131711 ed.present = true;
14141712 ed.segment = 0;
14151713 state->edid_detect_counter++;
1714+ cec_s_phys_addr(state->cec_adap, ed.phys_addr, false);
14161715 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed);
14171716 return ed.present;
14181717 }
@@ -1420,17 +1719,43 @@ static bool adv7511_check_edid_status(struct v4l2_subdev *sd) · 1 unmodified line
14201719 return false;
14211720 }
14221721
1722+static 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+
1733+static 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+
1740+static const struct v4l2_subdev_internal_ops adv7511_int_ops = {
1741+ .registered = adv7511_registered,
1742+ .unregistered = adv7511_unregistered,
1743+};
1744+
14231745 /* ----------------------------------------------------------------------- */
14241746 /* Setup ADV7511 */
14251747 static void adv7511_init_setup(struct v4l2_subdev *sd)
14261748 {
14271749 struct adv7511_state *state = get_adv7511_state(sd);
14281750 struct adv7511_state_edid *edid = &state->edid;
1751+ u32 cec_clk = state->pdata.cec_clk;
1752+ u8 ratio;
14291753
14301754 v4l2_dbg(1, debug, sd, "%s\n", __func__);
14311755
14321756 /* clear all interrupts */
14331757 adv7511_wr(sd, 0x96, 0xff);
1758+ adv7511_wr(sd, 0x97, 0xff);
14341759 /*
14351760 * Stop HPD from resetting a lot of registers.
14361761 * 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
14421767 adv7511_set_isr(sd, false);
14431768 adv7511_s_stream(sd, false);
14441769 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);
14451789 }
14461790
14471791 static 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
14761820 client->addr << 1);
14771821
14781822 v4l2_i2c_subdev_init(sd, client, &adv7511_ops);
1823+ sd->internal_ops = &adv7511_int_ops;
14791824
14801825 hdl = &state->hdl;
14811826 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
15161861 chip_id[0] = adv7511_rd(sd, 0xf5);
15171862 chip_id[1] = adv7511_rd(sd, 0xf6);
15181863 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]);
15201866 err = -EIO;
15211867 goto err_entity;
15221868 }
15231869
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);
15251872 if (state->i2c_edid == NULL) {
15261873 v4l2_err(sd, "failed to register edid i2c client\n");
15271874 err = -ENOMEM;
15281875 goto err_entity;
15291876 }
15301877
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+
15311898 state->i2c_pktmem = i2c_new_dummy(client->adapter, state->i2c_pktmem_addr >> 1);
15321899 if (state->i2c_pktmem == NULL) {
15331900 v4l2_err(sd, "failed to register pktmem i2c client\n");
15341901 err = -ENOMEM;
1535− goto err_unreg_edid;
1902+ goto err_unreg_cec;
15361903 }
15371904
1538− adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */
15391905 state->work_queue = create_singlethread_workqueue(sd->name);
15401906 if (state->work_queue == NULL) {
15411907 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
15461912 INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);
15471913
15481914 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+
15491928 adv7511_set_isr(sd, true);
15501929 adv7511_check_monitor_present_status(sd);
15511930
@@ -1555,6 +1934,9 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id * · 3 unmodified lines
15551934
15561935 err_unreg_pktmem:
15571936 i2c_unregister_device(state->i2c_pktmem);
1937+err_unreg_cec:
1938+ if (state->i2c_cec)
1939+ i2c_unregister_device(state->i2c_cec);
15581940 err_unreg_edid:
15591941 i2c_unregister_device(state->i2c_edid);
15601942 err_entity:
@@ -1576,9 +1958,12 @@ static int adv7511_remove(struct i2c_client *client) · 15 unmodified lines
15761958 v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
15771959 client->addr << 1, client->adapter->name);
15781960
1961+ adv7511_set_isr(sd, false);
15791962 adv7511_init_setup(sd);
15801963 cancel_delayed_work(&state->edid_handler);
15811964 i2c_unregister_device(state->i2c_edid);
1965+ if (state->i2c_cec)
1966+ i2c_unregister_device(state->i2c_cec);
15821967 i2c_unregister_device(state->i2c_pktmem);
15831968 destroy_workqueue(state->work_queue);
15841969 v4l2_device_unregister_subdev(sd);
drivers/media/i2c/adv7604.c+296−36
@@ -40,6 +40,7 @@ · 39 unmodified lines
4040 #include <linux/regmap.h>
4141
4242 #include <media/i2c/adv7604.h>
43+#include <media/cec.h>
4344 #include <media/v4l2-ctrls.h>
4445 #include <media/v4l2-device.h>
4546 #include <media/v4l2-event.h>
@@ -80,6 +81,8 @@ MODULE_LICENSE("GPL"); · 34 unmodified lines
8081
8182 #define ADV76XX_OP_SWAP_CB_CR (1 << 0)
8283
84+#define ADV76XX_MAX_ADDRS (3)
85+
8386 enum adv76xx_type {
8487 ADV7604,
8588 ADV7611,
@@ -184,6 +187,12 @@ struct adv76xx_state { · 98 unmodified lines
184187 u16 spa_port_a[2];
185188 struct v4l2_fract aspect_ratio;
186189 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+
187196 struct workqueue_struct *work_queues;
188197 struct delayed_work delayed_work_enable_hotplug;
189198 bool restart_stdi_once;
@@ -381,7 +390,8 @@ static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val) · 191 unmodified lines
381390 return regmap_write(state->regmap[ADV76XX_PAGE_IO], reg, val);
382391 }
383392
384−static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
393+static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
394+ u8 val)
385395 {
386396 return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
387397 }
@@ -414,6 +424,12 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) · 26 unmodified lines
414424 return regmap_write(state->regmap[ADV76XX_PAGE_CEC], reg, val);
415425 }
416426
427+static 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+
417433 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
418434 {
419435 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
892908 {
893909 struct adv76xx_state *state = to_state(sd);
894910 const struct adv76xx_chip_info *info = state->info;
911+ u16 cable_det = info->read_cable_det(sd);
895912
896− return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
897− info->read_cable_det(sd));
913+ return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det);
898914 }
899915
900916 static 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
19241940 return 0;
19251941 }
19261942
1943+#if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
1944+static 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+
1987+static 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+
2025+static 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+
2055+static 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+
2109+static 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+
2140+static 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+
19272147 static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
19282148 {
19292149 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
19692189 *handled = true;
19702190 }
19712191
2192+#if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC)
2193+ /* cec */
2194+ adv76xx_cec_isr(sd, handled);
2195+#endif
2196+
19722197 /* tx 5v detect */
19732198 tx_5v = irq_reg_0x70 & info->cable_det_mask;
19742199 if (tx_5v) {
@@ -2018,39 +2243,12 @@ static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 43 unmodified lines
20182243 return 0;
20192244 }
20202245
2021−static 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−
20492246 static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
20502247 {
20512248 struct adv76xx_state *state = to_state(sd);
20522249 const struct adv76xx_chip_info *info = state->info;
2053− int spa_loc;
2250+ unsigned int spa_loc;
2251+ u16 pa;
20542252 int err;
20552253 int i;
20562254
@@ -2081,6 +2279,10 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) · 24 unmodified lines
20812279 edid->blocks = 2;
20822280 return -E2BIG;
20832281 }
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;
20842286
20852287 v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n",
20862288 __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
20902292 adv76xx_set_hpd(state, 0);
20912293 rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
20922294
2093− spa_loc = get_edid_spa_location(edid->edid);
2094− if (spa_loc < 0)
2095− spa_loc = 0xc0; /* Default value [REF_02, p. 116] */
2295+ /*
2296+ * Return an error if no location of the source physical address
2297+ * was found.
2298+ */
2299+ if (spa_loc == 0)
2300+ return -EINVAL;
20962301
20972302 switch (edid->pad) {
20982303 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
21522357 v4l2_err(sd, "error enabling edid (0x%x)\n", state->edid.present);
21532358 return -EIO;
21542359 }
2360+ cec_s_phys_addr(state->cec_adap, pa, false);
21552361
21562362 /* enable hotplug after 100 ms */
21572363 queue_delayed_work(state->work_queues,
@@ -2276,8 +2482,19 @@ static int adv76xx_log_status(struct v4l2_subdev *sd) · 118 unmodified lines
22762482 ((edid_enabled & 0x02) ? "Yes" : "No"),
22772483 ((edid_enabled & 0x04) ? "Yes" : "No"),
22782484 ((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 ?
22802486 "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+ }
22812498
22822499 v4l2_info(sd, "-----Signal status-----\n");
22832500 cable_det = info->read_cable_det(sd);
@@ -2387,6 +2604,24 @@ static int adv76xx_subscribe_event(struct v4l2_subdev *sd, · 103 unmodified lines
23872604 }
23882605 }
23892606
2607+static 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+
2618+static 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+
23902625 /* ----------------------------------------------------------------------- */
23912626
23922627 static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = {
@@ -2430,6 +2665,11 @@ static const struct v4l2_subdev_ops adv76xx_ops = { · 37 unmodified lines
24302665 .pad = &adv76xx_pad_ops,
24312666 };
24322667
2668+static const struct v4l2_subdev_internal_ops adv76xx_int_ops = {
2669+ .registered = adv76xx_registered,
2670+ .unregistered = adv76xx_unregistered,
2671+};
2672+
24332673 /* -------------------------- custom ctrls ---------------------------------- */
24342674
24352675 static 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
30933333 id->name, i2c_adapter_id(client->adapter),
30943334 client->addr);
30953335 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
3336+ sd->internal_ops = &adv76xx_int_ops;
30963337
30973338 /* Configure IO Regmap region */
30983339 err = configure_regmap(state, ADV76XX_PAGE_IO);
@@ -3236,6 +3477,18 @@ static int adv76xx_probe(struct i2c_client *client, · 137 unmodified lines
32363477 err = adv76xx_core_init(sd);
32373478 if (err)
32383479 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+
32393492 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
32403493 client->addr << 1, client->adapter->name);
32413494
@@ -3264,6 +3517,13 @@ static int adv76xx_remove(struct i2c_client *client) · 22 unmodified lines
32643517 struct v4l2_subdev *sd = i2c_get_clientdata(client);
32653518 struct adv76xx_state *state = to_state(sd);
32663519
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+
32673527 cancel_delayed_work(&state->delayed_work_enable_hotplug);
32683528 destroy_workqueue(state->work_queues);
32693529 v4l2_async_unregister_subdev(sd);
drivers/media/i2c/adv7842.c+305−63
@@ -39,6 +39,7 @@ · 38 unmodified lines
3939 #include <linux/workqueue.h>
4040 #include <linux/v4l2-dv-timings.h>
4141 #include <linux/hdmi.h>
42+#include <media/cec.h>
4243 #include <media/v4l2-device.h>
4344 #include <media/v4l2-event.h>
4445 #include <media/v4l2-ctrls.h>
@@ -79,6 +80,8 @@ MODULE_LICENSE("GPL"); · 34 unmodified lines
7980
8081 #define ADV7842_OP_SWAP_CB_CR (1 << 0)
8182
83+#define ADV7842_MAX_ADDRS (3)
84+
8285 /*
8386 **********************************************************************
8487 *
@@ -142,6 +145,11 @@ struct adv7842_state { · 57 unmodified lines
142145 struct v4l2_ctrl *free_run_color_ctrl_manual;
143146 struct v4l2_ctrl *free_run_color_ctrl;
144147 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;
145153 };
146154
147155 /* 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
418426 return adv_smbus_write_byte_data(state->i2c_cec, reg, val);
419427 }
420428
421−static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
429+static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
422430 {
423− return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);
431+ return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
424432 }
425433
426434 static 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
696704
697705 /* ----------------------------------------------------------------------- */
698706
707+static 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+
699719 static void adv7842_delayed_work_enable_hotplug(struct work_struct *work)
700720 {
701721 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
762782 return 0;
763783 }
764784
765−static 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−
798785 static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port)
799786 {
800787 struct i2c_client *client = v4l2_get_subdevdata(sd);
801788 struct adv7842_state *state = to_state(sd);
802− const u8 *val = state->hdmi_edid.edid;
803− int spa_loc = edid_spa_location(val);
789+ const u8 *edid = state->hdmi_edid.edid;
790+ int spa_loc;
791+ u16 pa;
804792 int err = 0;
805793 int i;
806794
807− v4l2_dbg(2, debug, sd, "%s: write EDID on port %c (spa at 0x%x)\n",
808− __func__, (port == ADV7842_EDID_PORT_A) ? 'A' : 'B', spa_loc);
795+ v4l2_dbg(2, debug, sd, "%s: write EDID on port %c\n",
796+ __func__, (port == ADV7842_EDID_PORT_A) ? 'A' : 'B');
809797
810798 /* HPA disable on port A and B */
811799 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
816804 if (!state->hdmi_edid.present)
817805 return 0;
818806
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+
819819 /* edid segment pointer '0' for HDMI ports */
820820 rep_write_and_or(sd, 0x77, 0xef, 0x00);
821821
822822 for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX)
823823 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);
825825 if (err)
826826 return err;
827827
828− if (spa_loc < 0)
829− spa_loc = 0xc0; /* Default value [REF_02, p. 199] */
830−
831828 if (port == ADV7842_EDID_PORT_A) {
832− rep_write(sd, 0x72, val[spa_loc]);
833− rep_write(sd, 0x73, val[spa_loc + 1]);
829+ rep_write(sd, 0x72, edid[spa_loc]);
830+ rep_write(sd, 0x73, edid[spa_loc + 1]);
834831 } else {
835− rep_write(sd, 0x74, val[spa_loc]);
836− rep_write(sd, 0x75, val[spa_loc + 1]);
832+ rep_write(sd, 0x74, edid[spa_loc]);
833+ rep_write(sd, 0x75, edid[spa_loc + 1]);
837834 }
838835 rep_write(sd, 0x76, spa_loc & 0xff);
839836 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
853850 (port == ADV7842_EDID_PORT_A) ? 'A' : 'B');
854851 return -EIO;
855852 }
853+ cec_s_phys_addr(state->cec_adap, pa, false);
856854
857855 /* enable hotplug after 200 ms */
858856 queue_delayed_work(state->work_queues,
@@ -983,20 +981,11 @@ static int adv7842_s_register(struct v4l2_subdev *sd, · 124 unmodified lines
983981 static int adv7842_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
984982 {
985983 struct adv7842_state *state = to_state(sd);
986− int prev = v4l2_ctrl_g_ctrl(state->detect_tx_5v_ctrl);
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 */
984+ u16 cable_det = adv7842_read_cable_det(sd);
994985
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);
996987
997− if (val != prev)
998− return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, val);
999− return 0;
988+ return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det);
1000989 }
1001990
1002991 static 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
21702159 }
21712160 }
21722161
2162+#if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC)
2163+static 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+
2207+static 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+
2242+static 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+
2271+static 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+
2325+static 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+
2356+static 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+
21732363 static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
21742364 {
21752365 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
22412431 *handled = true;
22422432 }
22432433
2434+#if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC)
2435+ /* cec */
2436+ adv7842_cec_isr(sd, handled);
2437+#endif
2438+
22442439 /* tx 5v detect */
22452440 if (irq_status[2] & 0x3) {
22462441 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
23212516 case ADV7842_EDID_PORT_A:
23222517 case ADV7842_EDID_PORT_B:
23232518 memset(&state->hdmi_edid.edid, 0, 256);
2324− if (e->blocks)
2519+ if (e->blocks) {
23252520 state->hdmi_edid.present |= 0x04 << e->pad;
2326− else
2521+ } else {
23272522 state->hdmi_edid.present &= ~(0x04 << e->pad);
2523+ adv7842_s_detect_tx_5v_ctrl(sd);
2524+ }
23282525 memcpy(&state->hdmi_edid.edid, e->edid, 128 * e->blocks);
23292526 err = edid_write_hdmi_segment(sd, e->pad);
23302527 break;
@@ -2512,8 +2709,19 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd) · 181 unmodified lines
25122709 v4l2_info(sd, "HPD A %s, B %s\n",
25132710 reg_io_0x21 & 0x02 ? "enabled" : "disabled",
25142711 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 ?
25162713 "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+ }
25172725
25182726 v4l2_info(sd, "-----Signal status-----\n");
25192727 if (state->hdmi_port_a) {
@@ -3034,6 +3242,24 @@ static int adv7842_subscribe_event(struct v4l2_subdev *sd, · 514 unmodified lines
30343242 }
30353243 }
30363244
3245+static 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+
3256+static 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+
30373263 /* ----------------------------------------------------------------------- */
30383264
30393265 static const struct v4l2_ctrl_ops adv7842_ctrl_ops = {
@@ -3080,6 +3306,11 @@ static const struct v4l2_subdev_ops adv7842_ops = { · 40 unmodified lines
30803306 .pad = &adv7842_pad_ops,
30813307 };
30823308
3309+static const struct v4l2_subdev_internal_ops adv7842_int_ops = {
3310+ .registered = adv7842_registered,
3311+ .unregistered = adv7842_unregistered,
3312+};
3313+
30833314 /* -------------------------- custom ctrls ---------------------------------- */
30843315
30853316 static 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
32443475 sd = &state->sd;
32453476 v4l2_i2c_subdev_init(sd, client, &adv7842_ops);
32463477 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
3478+ sd->internal_ops = &adv7842_int_ops;
32473479 state->mode = pdata->mode;
32483480
32493481 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
33343566 if (err)
33353567 goto err_entity;
33363568
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+
33373580 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
33383581 client->addr << 1, client->adapter->name);
33393582 return 0;
@@ -3358,7 +3601,6 @@ static int adv7842_remove(struct i2c_client *client) · 18 unmodified lines
33583601 struct adv7842_state *state = to_state(sd);
33593602
33603603 adv7842_irq_enable(sd, false);
3361−
33623604 cancel_delayed_work(&state->delayed_work_enable_hotplug);
33633605 destroy_workqueue(state->work_queues);
33643606 v4l2_device_unregister_subdev(sd);
drivers/media/platform/vivid/Kconfig+8−0
@@ -6,6 +6,7 @@ config VIDEO_VIVID · 5 unmodified lines
66 select FB_CFB_FILLRECT
77 select FB_CFB_COPYAREA
88 select FB_CFB_IMAGEBLIT
9+ select MEDIA_CEC_EDID
910 select VIDEOBUF2_VMALLOC
1011 select VIDEO_V4L2_TPG
1112 default n
@@ -22,6 +23,13 @@ config VIDEO_VIVID · 10 unmodified lines
2223 Say Y here if you want to test video apps or debug V4L devices.
2324 When in doubt, say N.
2425
26+config 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+
2533 config VIDEO_VIVID_MAX_DEVS
2634 int "Maximum number of devices"
2735 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
33 vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \
44 vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \
55 vivid-osd.o
6+ifeq ($(CONFIG_VIDEO_VIVID_CEC),y)
7+ vivid-objs += vivid-cec.o
8+endif
9+
610 obj-$(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+
25+void 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+
43+static 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+
68+static 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+
112+static 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+
133+static int vivid_cec_adap_enable(struct cec_adapter *adap, bool enable)
134+{
135+ return 0;
136+}
137+
138+static 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+
149+static 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+
181+static 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+
234+static 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+
241+struct 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
21+struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
22+ unsigned int idx,
23+ struct device *parent,
24+ bool is_source);
25+void vivid_cec_bus_free_work(struct vivid_dev *dev);
26+
27+#else
28+
29+static 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
4646 #include "vivid-vbi-cap.h"
4747 #include "vivid-vbi-out.h"
4848 #include "vivid-osd.h"
49+#include "vivid-cec.h"
4950 #include "vivid-ctrls.h"
5051
5152 #define VIVID_MODULE_NAME "vivid"
@@ -684,6 +685,11 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 632 unmodified lines
684685 dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++;
685686 }
686687 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+ }
687693
688694 /* how many outputs do we have and of what type? */
689695 dev->num_outputs = num_outputs[inst];
@@ -696,6 +702,15 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 6 unmodified lines
696702 dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++;
697703 }
698704 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+ }
699714
700715 /* do we create a video capture device? */
701716 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
10101025 INIT_LIST_HEAD(&dev->vbi_out_active);
10111026 INIT_LIST_HEAD(&dev->sdr_cap_active);
10121027
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+
10131039 /* start creating the vb2 queues */
10141040 if (dev->has_vid_cap) {
10151041 /* initialize vid_cap queue */
@@ -1117,7 +1143,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 101 unmodified lines
11171143 /* finally start creating the device nodes */
11181144 if (dev->has_vid_cap) {
11191145 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);
11211148 vfd->fops = &vivid_fops;
11221149 vfd->ioctl_ops = &vivid_ioctl_ops;
11231150 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
11331160 vfd->lock = &dev->mutex;
11341161 video_set_drvdata(vfd, dev);
11351162
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+
11361184 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]);
11371185 if (ret < 0)
11381186 goto unreg_dev;
@@ -1141,8 +1189,13 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 2 unmodified lines
11411189 }
11421190
11431191 if (dev->has_vid_out) {
1192+#ifdef CONFIG_VIDEO_VIVID_CEC
1193+ unsigned int bus_cnt = 0;
1194+#endif
1195+
11441196 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);
11461199 vfd->vfl_dir = VFL_DIR_TX;
11471200 vfd->fops = &vivid_fops;
11481201 vfd->ioctl_ops = &vivid_ioctl_ops;
@@ -1159,6 +1212,35 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 10 unmodified lines
11591212 vfd->lock = &dev->mutex;
11601213 video_set_drvdata(vfd, dev);
11611214
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+
11621244 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_out_nr[inst]);
11631245 if (ret < 0)
11641246 goto unreg_dev;
@@ -1168,7 +1250,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 3 unmodified lines
11681250
11691251 if (dev->has_vbi_cap) {
11701252 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);
11721255 vfd->fops = &vivid_fops;
11731256 vfd->ioctl_ops = &vivid_ioctl_ops;
11741257 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
11911274
11921275 if (dev->has_vbi_out) {
11931276 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);
11951279 vfd->vfl_dir = VFL_DIR_TX;
11961280 vfd->fops = &vivid_fops;
11971281 vfd->ioctl_ops = &vivid_ioctl_ops;
@@ -1215,7 +1299,8 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) · 17 unmodified lines
12151299
12161300 if (dev->has_sdr_cap) {
12171301 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);
12191304 vfd->fops = &vivid_fops;
12201305 vfd->ioctl_ops = &vivid_ioctl_ops;
12211306 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
12341319
12351320 if (dev->has_radio_rx) {
12361321 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);
12381324 vfd->fops = &vivid_radio_fops;
12391325 vfd->ioctl_ops = &vivid_ioctl_ops;
12401326 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
12521338
12531339 if (dev->has_radio_tx) {
12541340 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);
12561343 vfd->vfl_dir = VFL_DIR_TX;
12571344 vfd->fops = &vivid_radio_fops;
12581345 vfd->ioctl_ops = &vivid_ioctl_ops;
@@ -1282,6 +1369,13 @@ unreg_dev: · 23 unmodified lines
12821369 video_unregister_device(&dev->vbi_cap_dev);
12831370 video_unregister_device(&dev->vid_out_dev);
12841371 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+ }
12851379 free_dev:
12861380 v4l2_device_put(&dev->v4l2_dev);
12871381 return ret;
@@ -1331,8 +1425,7 @@ static int vivid_probe(struct platform_device *pdev) · 43 unmodified lines
13311425 static int vivid_remove(struct platform_device *pdev)
13321426 {
13331427 struct vivid_dev *dev;
1334− unsigned i;
1335−
1428+ unsigned int i, j;
13361429
13371430 for (i = 0; i < n_devs; i++) {
13381431 dev = vivid_devs[i];
@@ -1380,6 +1473,13 @@ static int vivid_remove(struct platform_device *pdev) · 41 unmodified lines
13801473 unregister_framebuffer(&dev->fb_info);
13811474 vivid_fb_release_buffers(dev);
13821475 }
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+ }
13831483 v4l2_device_put(&dev->v4l2_dev);
13841484 vivid_devs[i] = NULL;
13851485 }
drivers/media/platform/vivid/vivid-core.h+27−0
@@ -21,6 +21,8 @@ · 20 unmodified lines
2121 #define _VIVID_CORE_H_
2222
2323 #include <linux/fb.h>
24+#include <linux/workqueue.h>
25+#include <media/cec.h>
2426 #include <media/videobuf2-v4l2.h>
2527 #include <media/v4l2-device.h>
2628 #include <media/v4l2-dev.h>
@@ -132,6 +134,17 @@ enum vivid_colorspace { · 105 unmodified lines
132134 #define VIVID_INVALID_SIGNAL(mode) \
133135 ((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE)
134136
137+struct 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+
135148 struct vivid_dev {
136149 unsigned inst;
137150 struct v4l2_device v4l2_dev;
@@ -497,6 +510,20 @@ struct vivid_dev { · 359 unmodified lines
497510 /* Shared between radio receiver and transmitter */
498511 bool radio_rds_loop;
499512 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;
500527 };
501528
502529 static 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
552552 snprintf(str, sizeof(str), " button pressed!");
553553 tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
554554 }
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+ }
555568 }
556569
557570 /*
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
17001700 struct v4l2_edid *edid)
17011701 {
17021702 struct vivid_dev *dev = video_drvdata(file);
1703+ u16 phys_addr;
1704+ unsigned int i;
1705+ int ret;
17031706
17041707 memset(edid->reserved, 0, sizeof(edid->reserved));
17051708 if (edid->pad >= dev->num_inputs)
@@ -1708,14 +1711,32 @@ int vidioc_s_edid(struct file *file, void *_fh, · 2 unmodified lines
17081711 return -EINVAL;
17091712 if (edid->blocks == 0) {
17101713 dev->edid_blocks = 0;
1711− return 0;
1714+ phys_addr = CEC_PHYS_ADDR_INVALID;
1715+ goto set_phys_addr;
17121716 }
17131717 if (edid->blocks > dev->edid_max_blocks) {
17141718 edid->blocks = dev->edid_max_blocks;
17151719 return -E2BIG;
17161720 }
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+
17171729 dev->edid_blocks = edid->blocks;
17181730 memcpy(dev->edid, edid->edid, edid->blocks * 128);
1731+
1732+set_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);
17191740 return 0;
17201741 }
17211742
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
811811 {
812812 struct vivid_dev *dev = video_drvdata(file);
813813 struct video_device *vdev = video_devdata(file);
814+ struct cec_adapter *adap;
814815
815816 memset(edid->reserved, 0, sizeof(edid->reserved));
816817 if (vdev->vfl_dir == VFL_DIR_RX) {
@@ -818,11 +819,16 @@ int vidioc_g_edid(struct file *file, void *_fh, · 1 unmodified line
818819 return -EINVAL;
819820 if (dev->input_type[edid->pad] != HDMI)
820821 return -EINVAL;
822+ adap = dev->cec_rx_adap;
821823 } else {
824+ unsigned int bus_idx;
825+
822826 if (edid->pad >= dev->num_outputs)
823827 return -EINVAL;
824828 if (dev->output_type[edid->pad] != HDMI)
825829 return -EINVAL;
830+ bus_idx = dev->cec_output2bus_map[edid->pad];
831+ adap = dev->cec_tx_adap[bus_idx];
826832 }
827833 if (edid->start_block == 0 && edid->blocks == 0) {
828834 edid->blocks = dev->edid_blocks;
@@ -835,5 +841,6 @@ int vidioc_g_edid(struct file *file, void *_fh, · 6 unmodified lines
835841 if (edid->start_block + edid->blocks > dev->edid_blocks)
836842 edid->blocks = dev->edid_blocks - edid->start_block;
837843 memcpy(edid->edid, dev->edid, edid->blocks * 128);
844+ cec_set_edid_phys_addr(edid->edid, edid->blocks * 128, adap->phys_addr);
838845 return 0;
839846 }
drivers/media/rc/rc-main.c+1−0
@@ -804,6 +804,7 @@ static const struct { · 803 unmodified lines
804804 { RC_BIT_SHARP, "sharp", "ir-sharp-decoder" },
805805 { RC_BIT_MCE_KBD, "mce_kbd", "ir-mce_kbd-decoder" },
806806 { RC_BIT_XMP, "xmp", "ir-xmp-decoder" },
807+ { RC_BIT_CEC, "cec", NULL },
807808 };
808809
809810 /**
drivers/staging/media/Kconfig+4−0
@@ -21,6 +21,8 @@ if STAGING_MEDIA · 20 unmodified lines
2121 # Please keep them in alphabetic order
2222 source "drivers/staging/media/bcm2048/Kconfig"
2323
24+source "drivers/staging/media/cec/Kconfig"
25+
2426 source "drivers/staging/media/cxd2099/Kconfig"
2527
2628 source "drivers/staging/media/davinci_vpfe/Kconfig"
@@ -29,6 +31,8 @@ source "drivers/staging/media/omap4iss/Kconfig" · 2 unmodified lines
2931
3032 source "drivers/staging/media/tw686x-kh/Kconfig"
3133
34+source "drivers/staging/media/s5p-cec/Kconfig"
35+
3236 # Keep LIRC at the end, as it has sub-menus
3337 source "drivers/staging/media/lirc/Kconfig"
3438
drivers/staging/media/Makefile+2−0
@@ -1,4 +1,6 @@
11 obj-$(CONFIG_I2C_BCM2048) += bcm2048/
2+obj-$(CONFIG_MEDIA_CEC) += cec/
3+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec/
24 obj-$(CONFIG_DVB_CXD2099) += cxd2099/
35 obj-$(CONFIG_LIRC_STAGING) += lirc/
46 obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
drivers/staging/media/cec/Kconfig+14−0
@@ -0,0 +1,14 @@
1+config 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+
10+config 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 @@
1+cec-objs := cec-core.o cec-adap.o cec-api.o
2+
3+obj-$(CONFIG_MEDIA_CEC) += cec.o
drivers/staging/media/cec/TODO+27−0
@@ -0,0 +1,27 @@
1+The reason why cec.c is still in staging is that I would like
2+to have a bit more confidence in the uABI. The kABI is fine,
3+no problem there, but I would like to let the public API mature
4+a bit.
5+
6+Once I'm confident that I didn't miss anything then the cec.c source
7+can move to drivers/media and the linux/cec.h and linux/cec-funcs.h
8+headers can move to uapi/linux and added to uapi/linux/Kbuild to make
9+them public.
10+
11+Hopefully this will happen later in 2016.
12+
13+Other 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+
27+Hans 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+
33+static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx);
34+static 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+
57+static 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+
67+static 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+ */
87+void 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+
115+unlock:
116+ mutex_unlock(&fh->lock);
117+ wake_up_interruptible(&fh->wait);
118+}
119+
120+/* Queue a new event for all open filehandles. */
121+static 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+ */
137+static 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+
167+lost_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+ */
182+static 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+ */
201+static 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. */
215+static 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+ */
233+static 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+ */
271+static 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+ */
307+int 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+
441+unlock:
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+ */
453+void 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+
531+wake_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);
537+unlock:
538+ mutex_unlock(&adap->lock);
539+}
540+EXPORT_SYMBOL_GPL(cec_transmit_done);
541+
542+/*
543+ * Called when waiting for a reply times out.
544+ */
545+static 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);
563+unlock:
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+ */
573+int 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. */
733+int 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+}
743+EXPORT_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+ */
750+static 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 */
754+void 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+}
846+EXPORT_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+ */
855+static 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+ */
907+static 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+ */
921+static 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+
1035+configured:
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+
1064+unconfigure:
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+ */
1080+static 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+ */
1104+void __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+
1136+void 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+}
1147+EXPORT_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+ */
1154+int __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+
1273+int 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+}
1285+EXPORT_SYMBOL_GPL(cec_s_log_addrs);
1286+
1287+/* High-level core CEC message handling */
1288+
1289+/* Transmit the Report Features message */
1290+static 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 */
1322+static 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 */
1338+static 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+
1354+static 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+
1360+static 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+ */
1373+static 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+
1546+skip_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+ */
1567+int 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+
1578+void 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+ */
1590+int 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+
35+static 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+
44+static 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+
66+static 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+
85+static 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+
101+static 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+
114+static 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+
137+static 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+
154+static 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+
181+static 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 */
210+static 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+
257+static 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+
280+static 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+
317+unlock:
318+ mutex_unlock(&fh->lock);
319+ return err;
320+}
321+
322+static 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+
332+static 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+
428+static 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+
475+static 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 */
523+static 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+
571+const 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+
35+int cec_debug;
36+module_param_named(debug, cec_debug, int, 0644);
37+MODULE_PARM_DESC(debug, "debug level (0-2)");
38+
39+static dev_t cec_dev_t;
40+
41+/* Active devices */
42+static DEFINE_MUTEX(cec_devnode_lock);
43+static DECLARE_BITMAP(cec_devnode_nums, CEC_NUM_DEVICES);
44+
45+static 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+
50+int 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+
74+void 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. */
82+static 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+
95+static 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+ */
112+static 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+
160+cdev_del:
161+ cdev_del(&devnode->cdev);
162+clr_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+ */
176+static 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+
196+struct 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+}
276+EXPORT_SYMBOL_GPL(cec_allocate_adapter);
277+
278+int 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+}
329+EXPORT_SYMBOL_GPL(cec_register_adapter);
330+
331+void 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+}
344+EXPORT_SYMBOL_GPL(cec_unregister_adapter);
345+
346+void 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+}
362+EXPORT_SYMBOL_GPL(cec_delete_adapter);
363+
364+/*
365+ * Initialise cec for linux
366+ */
367+static 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+
397+static 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+
404+subsys_initcall(cec_devnode_init);
405+module_exit(cec_devnode_exit)
406+
407+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
408+MODULE_DESCRIPTION("Device node registration for cec drivers");
409+MODULE_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 */
36+extern int cec_debug;
37+int cec_get_device(struct cec_devnode *devnode);
38+void cec_put_device(struct cec_devnode *devnode);
39+
40+/* cec-adap.c */
41+int cec_monitor_all_cnt_inc(struct cec_adapter *adap);
42+void cec_monitor_all_cnt_dec(struct cec_adapter *adap);
43+int cec_adap_status(struct seq_file *file, void *priv);
44+int cec_thread_func(void *_adap);
45+void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
46+int __cec_s_log_addrs(struct cec_adapter *adap,
47+ struct cec_log_addrs *log_addrs, bool block);
48+int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
49+ struct cec_fh *fh, bool block);
50+void cec_queue_event_fh(struct cec_fh *fh,
51+ const struct cec_event *new_ev, u64 ts);
52+
53+/* cec-api.c */
54+extern const struct file_operations cec_devnode_fops;
55+
56+#endif
drivers/staging/media/s5p-cec/Kconfig+9−0
@@ -0,0 +1,9 @@
1+config 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 @@
1+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec.o
2+s5p-cec-y += s5p_cec.o exynos_hdmi_cecctrl.o
drivers/staging/media/s5p-cec/TODO+3−0
@@ -0,0 +1,3 @@
1+There's nothing wrong on this driver, except that it depends on
2+the media staging core, that it is currently at staging. So,
3+this 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+
20+void s5p_cec_set_divider(struct s5p_cec_dev *cec);
21+void s5p_cec_enable_rx(struct s5p_cec_dev *cec);
22+void s5p_cec_mask_rx_interrupts(struct s5p_cec_dev *cec);
23+void s5p_cec_unmask_rx_interrupts(struct s5p_cec_dev *cec);
24+void s5p_cec_mask_tx_interrupts(struct s5p_cec_dev *cec);
25+void s5p_cec_unmask_tx_interrupts(struct s5p_cec_dev *cec);
26+void s5p_cec_reset(struct s5p_cec_dev *cec);
27+void s5p_cec_tx_reset(struct s5p_cec_dev *cec);
28+void s5p_cec_rx_reset(struct s5p_cec_dev *cec);
29+void s5p_cec_threshold(struct s5p_cec_dev *cec);
30+void s5p_cec_copy_packet(struct s5p_cec_dev *cec, char *data,
31+ size_t count, u8 retries);
32+void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr);
33+u32 s5p_cec_get_status(struct s5p_cec_dev *cec);
34+void s5p_clr_pending_tx(struct s5p_cec_dev *cec);
35+void s5p_clr_pending_rx(struct s5p_cec_dev *cec);
36+void 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+
26+void 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+
53+void 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+
62+void 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+
72+void 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+
82+void 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+
93+void 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+
103+void 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+
115+void 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+
120+void 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+
131+void 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+
137+void 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+
167+void s5p_cec_set_addr(struct s5p_cec_dev *cec, u32 addr)
168+{
169+ writeb(addr & 0x0F, cec->reg + S5P_CEC_LOGIC_ADDR);
170+}
171+
172+u32 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+
186+void 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+
192+void 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+
198+void 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+
35+static int debug;
36+module_param(debug, int, 0644);
37+MODULE_PARM_DESC(debug, "debug level (0-2)");
38+
39+static 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+
63+static 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+
71+static 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+
84+static 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+
127+static 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+
162+static 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+
168+static 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+
225+static 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+
234+static 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+
242+static 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+
253+static 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+
260+static 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+
267+static 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+
273+static const struct of_device_id s5p_cec_match[] = {
274+ {
275+ .compatible = "samsung,s5p-cec",
276+ },
277+ {},
278+};
279+
280+static 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+
290+module_platform_driver(s5p_cec_pdrv);
291+
292+MODULE_AUTHOR("Kamil Debski <kamil@wypas.org>");
293+MODULE_LICENSE("GPL");
294+MODULE_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+
55+enum cec_state {
56+ STATE_IDLE,
57+ STATE_BUSY,
58+ STATE_DONE,
59+ STATE_ERROR
60+};
61+
62+struct 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
5757 #include <linux/i2c-dev.h>
5858 #include <linux/atalk.h>
5959 #include <linux/gfp.h>
60+#include <linux/cec.h>
6061
6162 #include "internal.h"
6263
@@ -1377,6 +1378,17 @@ COMPATIBLE_IOCTL(VIDEO_GET_NAVI) · 1314 unmodified lines
13771378 COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)
13781379 COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
13791380 COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)
1381+/* cec */
1382+COMPATIBLE_IOCTL(CEC_ADAP_G_CAPS)
1383+COMPATIBLE_IOCTL(CEC_ADAP_G_LOG_ADDRS)
1384+COMPATIBLE_IOCTL(CEC_ADAP_S_LOG_ADDRS)
1385+COMPATIBLE_IOCTL(CEC_ADAP_G_PHYS_ADDR)
1386+COMPATIBLE_IOCTL(CEC_ADAP_S_PHYS_ADDR)
1387+COMPATIBLE_IOCTL(CEC_G_MODE)
1388+COMPATIBLE_IOCTL(CEC_S_MODE)
1389+COMPATIBLE_IOCTL(CEC_TRANSMIT)
1390+COMPATIBLE_IOCTL(CEC_RECEIVE)
1391+COMPATIBLE_IOCTL(CEC_DQEVENT)
13801392
13811393 /* joystick */
13821394 COMPATIBLE_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 */
32+static 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+
41+static 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+
47+static 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+
53+static 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 */
61+static 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+
70+static 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+
76+static 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+
85+static 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+
95+static 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+
101+static 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+
116+static 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+
124+static 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+
133+static 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 */
141+static 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 */
149+static 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+
155+struct cec_op_arib_data {
156+ __u16 transport_id;
157+ __u16 service_id;
158+ __u16 orig_network_id;
159+};
160+
161+struct cec_op_atsc_data {
162+ __u16 transport_id;
163+ __u16 program_number;
164+};
165+
166+struct cec_op_dvb_data {
167+ __u16 transport_id;
168+ __u16 service_id;
169+ __u16 orig_network_id;
170+};
171+
172+struct cec_op_channel_data {
173+ __u8 channel_number_fmt;
174+ __u16 major;
175+ __u16 minor;
176+};
177+
178+struct 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+
189+struct 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+
207+static 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+
244+static 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+
260+static 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+
267+static 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+
276+static 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+
290+static 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+
299+static 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+
309+static 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+
335+static 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+
361+static 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+
368+static inline void cec_ops_record_status(const struct cec_msg *msg,
369+ __u8 *rec_status)
370+{
371+ *rec_status = msg->msg[2];
372+}
373+
374+static 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 */
384+static 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+
407+static 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+
434+static 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+
442+static 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+
448+static 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+
478+static 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+
503+static 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+
528+static 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+
549+static 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+
579+static 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+
604+static 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+
634+static 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+
659+static 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+
684+static 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+
705+static 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+
735+static 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+
760+static 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+
772+static 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 */
784+static 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+
791+static inline void cec_ops_cec_version(const struct cec_msg *msg,
792+ __u8 *cec_version)
793+{
794+ *cec_version = msg->msg[2];
795+}
796+
797+static 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+
805+static 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+
816+static 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+
823+static 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+
831+static 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+
840+static 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+
847+static 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+ */
863+static 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+
876+static 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+
896+static 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 */
905+static 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+
913+static 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+
919+static 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+
927+static inline void cec_ops_deck_status(struct cec_msg *msg,
928+ __u8 *deck_info)
929+{
930+ *deck_info = msg->msg[2];
931+}
932+
933+static 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+
943+static inline void cec_ops_give_deck_status(struct cec_msg *msg,
944+ __u8 *status_req)
945+{
946+ *status_req = msg->msg[2];
947+}
948+
949+static 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+
957+static 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 */
965+struct 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+
979+static 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+
995+static 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+
1005+static 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+
1022+static 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+
1037+static 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+
1047+static 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+
1053+static 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+
1066+static 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+
1076+static 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+
1084+static 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+
1090+static 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+
1096+static 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 */
1104+static 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+
1114+static 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+
1120+static 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+
1128+static 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 */
1136+static 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+
1150+static 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 */
1165+static 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+
1176+static 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+
1187+static 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 */
1197+static 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+
1205+static inline void cec_ops_menu_status(struct cec_msg *msg,
1206+ __u8 *menu_state)
1207+{
1208+ *menu_state = msg->msg[2];
1209+}
1210+
1211+static 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+
1221+static inline void cec_ops_menu_request(struct cec_msg *msg,
1222+ __u8 *menu_req)
1223+{
1224+ *menu_req = msg->msg[2];
1225+}
1226+
1227+struct 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+
1241+static 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+
1271+static 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+
1300+static 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 */
1309+static 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+
1317+static 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+
1323+static 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 */
1332+static 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+
1341+static 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 */
1349+static 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+
1358+static 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 */
1366+static 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+
1375+static 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+
1383+static 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+
1391+static 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+
1399+static 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+
1405+static 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+
1417+static 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+
1426+static 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+
1434+static 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+
1440+static 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+
1448+static 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+
1465+static 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+
1480+static 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+
1496+static 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 */
1514+static 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+
1522+static 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 */
1530+static 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+
1536+static 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+
1544+static 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+
1552+static 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+
1558+static 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+
1566+static 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 */
1577+static 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+
1594+static 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+
1608+static 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+
1620+static 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 */
1628+static 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+
1643+static 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+
1653+static 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+
1679+static 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+
1699+static 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+
1731+static 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+
1753+static 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+
1767+static 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+
1777+static 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+
1795+static 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+
1807+static 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+
1816+static 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+
1822+static 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+
1831+static 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+
1837+static 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+
1849+static 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+
1859+static 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+
1871+static 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+ */
73+struct 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+ */
93+static 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+ */
102+static 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+ */
111+static 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+ */
120+static 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+ */
134+static 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+ */
151+static 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+
172+static 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+
242+static inline bool cec_has_tv(__u16 log_addr_mask)
243+{
244+ return log_addr_mask & CEC_LOG_ADDR_MASK_TV;
245+}
246+
247+static inline bool cec_has_record(__u16 log_addr_mask)
248+{
249+ return log_addr_mask & CEC_LOG_ADDR_MASK_RECORD;
250+}
251+
252+static inline bool cec_has_tuner(__u16 log_addr_mask)
253+{
254+ return log_addr_mask & CEC_LOG_ADDR_MASK_TUNER;
255+}
256+
257+static inline bool cec_has_playback(__u16 log_addr_mask)
258+{
259+ return log_addr_mask & CEC_LOG_ADDR_MASK_PLAYBACK;
260+}
261+
262+static inline bool cec_has_audiosystem(__u16 log_addr_mask)
263+{
264+ return log_addr_mask & CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
265+}
266+
267+static inline bool cec_has_backup(__u16 log_addr_mask)
268+{
269+ return log_addr_mask & CEC_LOG_ADDR_MASK_BACKUP;
270+}
271+
272+static inline bool cec_has_specific(__u16 log_addr_mask)
273+{
274+ return log_addr_mask & CEC_LOG_ADDR_MASK_SPECIFIC;
275+}
276+
277+static inline bool cec_is_unregistered(__u16 log_addr_mask)
278+{
279+ return log_addr_mask & CEC_LOG_ADDR_MASK_UNREGISTERED;
280+}
281+
282+static 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+ */
332+struct 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+ */
358+struct 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+ */
391+struct 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+ */
400+struct 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+ */
413+struct 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+ */
40+u16 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+ */
55+void 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+ */
76+u16 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+ */
102+int 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+ */
50+struct 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+
64+struct cec_adapter;
65+struct cec_data;
66+
67+struct 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+
81+struct 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+
88+struct 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+
111+struct 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+
136+struct 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+
180+static 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+
185+static 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)
191+struct 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);
194+int cec_register_adapter(struct cec_adapter *adap);
195+void cec_unregister_adapter(struct cec_adapter *adap);
196+void cec_delete_adapter(struct cec_adapter *adap);
197+
198+int cec_s_log_addrs(struct cec_adapter *adap, struct cec_log_addrs *log_addrs,
199+ bool block);
200+void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr,
201+ bool block);
202+int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
203+ bool block);
204+
205+/* Called by the adapter */
206+void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
207+ u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt);
208+void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg);
209+
210+#else
211+
212+static inline int cec_register_adapter(struct cec_adapter *adap)
213+{
214+ return 0;
215+}
216+
217+static inline void cec_unregister_adapter(struct cec_adapter *adap)
218+{
219+}
220+
221+static inline void cec_delete_adapter(struct cec_adapter *adap)
222+{
223+}
224+
225+static 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
3232 struct adv7511_edid_detect {
3333 int present;
3434 int segment;
35−};
36−
37−struct adv7511_cec_arg {
38− void *arg;
39− u32 f_flags;
35+ uint16_t phys_addr;
4036 };
4137
4238 struct adv7511_platform_data {
include/media/rc-map.h+4−1
@@ -31,6 +31,7 @@ enum rc_type { · 30 unmodified lines
3131 RC_TYPE_RC6_MCE = 16, /* MCE (Philips RC6-6A-32 subtype) protocol */
3232 RC_TYPE_SHARP = 17, /* Sharp protocol */
3333 RC_TYPE_XMP = 18, /* XMP protocol */
34+ RC_TYPE_CEC = 19, /* CEC protocol */
3435 };
3536
3637 #define RC_BIT_NONE 0ULL
@@ -53,6 +54,7 @@ enum rc_type { · 16 unmodified lines
5354 #define RC_BIT_RC6_MCE (1ULL << RC_TYPE_RC6_MCE)
5455 #define RC_BIT_SHARP (1ULL << RC_TYPE_SHARP)
5556 #define RC_BIT_XMP (1ULL << RC_TYPE_XMP)
57+#define RC_BIT_CEC (1ULL << RC_TYPE_CEC)
5658
5759 #define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \
5860 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \
@@ -61,7 +63,7 @@ enum rc_type { · 2 unmodified lines
6163 RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \
6264 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \
6365 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE | RC_BIT_SHARP | \
64− RC_BIT_XMP)
66+ RC_BIT_XMP | RC_BIT_CEC)
6567
6668
6769 #define RC_SCANCODE_UNKNOWN(x) (x)
@@ -123,6 +125,7 @@ void rc_map_init(void); · 55 unmodified lines
123125 #define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus"
124126 #define RC_MAP_BEHOLD "rc-behold"
125127 #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old"
128+#define RC_MAP_CEC "rc-cec"
126129 #define RC_MAP_CINERGY_1400 "rc-cinergy-1400"
127130 #define RC_MAP_CINERGY "rc-cinergy"
128131 #define RC_MAP_DELOCK_61959 "rc-delock-61959"
include/uapi/linux/input-event-codes.h+31−0
@@ -611,6 +611,37 @@ · 610 unmodified lines
611611 #define KEY_KBDINPUTASSIST_ACCEPT 0x264
612612 #define KEY_KBDINPUTASSIST_CANCEL 0x265
613613
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+
614645 #define BTN_TRIGGER_HAPPY 0x2c0
615646 #define BTN_TRIGGER_HAPPY1 0x2c0
616647 #define BTN_TRIGGER_HAPPY2 0x2c1
include/uapi/linux/input.h+1−0
@@ -247,6 +247,7 @@ struct input_mask { · 246 unmodified lines
247247 #define BUS_ATARI 0x1B
248248 #define BUS_SPI 0x1C
249249 #define BUS_RMI 0x1D
250+#define BUS_CEC 0x1E
250251
251252 /*
252253 * 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