Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'topic/cec' into patchwork

* 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

+10428 -129
+3
Documentation/DocBook/device-drivers.tmpl
··· 300 300 !Iinclude/media/media-devnode.h 301 301 !Iinclude/media/media-entity.h 302 302 </sect1> 303 + <sect1><title>Consumer Electronics Control devices</title> 304 + !Iinclude/media/cec-edid.h 305 + </sect1> 303 306 304 307 </chapter> 305 308
+2
Documentation/DocBook/media/Makefile
··· 64 64 $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \ 65 65 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \ 66 66 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \ 67 + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/cec.h) \ 67 68 $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \ 68 69 69 70 DEFINES = \ ··· 101 100 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/ && !/_old/)' $(srctree)/include/uapi/linux/dvb/net.h) \ 102 101 $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \ 103 102 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \ 103 + $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/cec.h) \ 104 104 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \ 105 105 $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h) 106 106
+10
Documentation/DocBook/media/v4l/biblio.xml
··· 342 342 <subtitle>Specification Version 1.4a</subtitle> 343 343 </biblioentry> 344 344 345 + <biblioentry id="hdmi2"> 346 + <abbrev>HDMI2</abbrev> 347 + <authorgroup> 348 + <corpauthor>HDMI Licensing LLC 349 + (<ulink url="http://www.hdmi.org">http://www.hdmi.org</ulink>)</corpauthor> 350 + </authorgroup> 351 + <title>High-Definition Multimedia Interface</title> 352 + <subtitle>Specification Version 2.0</subtitle> 353 + </biblioentry> 354 + 345 355 <biblioentry id="dp"> 346 356 <abbrev>DP</abbrev> 347 357 <authorgroup>
+75
Documentation/DocBook/media/v4l/cec-api.xml
··· 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>
+64
Documentation/DocBook/media/v4l/cec-func-close.xml
··· 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>
+78
Documentation/DocBook/media/v4l/cec-func-ioctl.xml
··· 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>
+104
Documentation/DocBook/media/v4l/cec-func-open.xml
··· 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>
+94
Documentation/DocBook/media/v4l/cec-func-poll.xml
··· 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>
+151
Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml
··· 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>
+329
Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml
··· 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>
+86
Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml
··· 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>
+202
Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml
··· 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>
+255
Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml
··· 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>
+274
Documentation/DocBook/media/v4l/cec-ioc-receive.xml
··· 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>
+5 -1
Documentation/DocBook/media_api.tmpl
··· 75 75 </mediaobject> 76 76 </figure> 77 77 <para>The media infrastructure API was designed to control such 78 - devices. It is divided into four parts.</para> 78 + devices. It is divided into five parts.</para> 79 79 <para>The first part covers radio, video capture and output, 80 80 cameras, analog TV devices and codecs.</para> 81 81 <para>The second part covers the ··· 87 87 <xref linkend="fe-delivery-system-t" />.</para> 88 88 <para>The third part covers the Remote Controller API.</para> 89 89 <para>The fourth part covers the Media Controller API.</para> 90 + <para>The fifth part covers the CEC (Consumer Electronics Control) API.</para> 90 91 <para>It should also be noted that a media device may also have audio 91 92 components, like mixers, PCM capture, PCM playback, etc, which 92 93 are controlled via ALSA API.</para> ··· 107 106 </part> 108 107 <part id="media_common"> 109 108 &sub-media-controller; 109 + </part> 110 + <part id="cec"> 111 + &sub-cec-api; 110 112 </part> 111 113 112 114 <chapter id="gen_errors">
+267
Documentation/cec.txt
··· 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.
+31
Documentation/devicetree/bindings/media/s5p-cec.txt
··· 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 + };
+31 -5
Documentation/video4linux/vivid.txt
··· 74 74 Section 12: Formats 75 75 Section 13: Capture Overlay 76 76 Section 14: Output Overlay 77 - Section 15: Some Future Improvements 77 + Section 15: CEC (Consumer Electronics Control) 78 + Section 16: Some Future Improvements 78 79 79 80 80 81 Section 1: Configuring the driver ··· 365 364 is provided. You can only set the EDID for HDMI inputs. Internally, however, 366 365 the EDID is shared between all HDMI inputs. 367 366 368 - No interpretation is done of the EDID data. 367 + No interpretation is done of the EDID data with the exception of the 368 + physical address. See the CEC section for more details. 369 + 370 + There is a maximum of 15 HDMI inputs (if there are more, then they will be 371 + reduced to 15) since that's the limitation of the EDID physical address. 369 372 370 373 371 374 Section 3: Video Output ··· 414 409 415 410 An HDMI output has a valid EDID which can be obtained through VIDIOC_G_EDID. 416 411 412 + There is a maximum of 15 HDMI outputs (if there are more, then they will be 413 + reduced to 15) since that's the limitation of the EDID physical address. See 414 + also the CEC section for more details. 417 415 418 416 Section 4: VBI Capture 419 417 ---------------------- ··· 1116 1108 to be done per pixel. 1117 1109 1118 1110 1119 - Section 15: Some Future Improvements 1111 + Section 15: CEC (Consumer Electronics Control) 1112 + ---------------------------------------------- 1113 + 1114 + If there are HDMI inputs then a CEC adapter will be created that has 1115 + the same number of input ports. This is the equivalent of e.g. a TV that 1116 + has that number of inputs. Each HDMI output will also create a 1117 + CEC adapter that is hooked up to the corresponding input port, or (if there 1118 + are more outputs than inputs) is not hooked up at all. In other words, 1119 + this is the equivalent of hooking up each output device to an input port of 1120 + the TV. Any remaining output devices remain unconnected. 1121 + 1122 + The EDID that each output reads reports a unique CEC physical address that is 1123 + based on the physical address of the EDID of the input. So if the EDID of the 1124 + receiver has physical address A.B.0.0, then each output will see an EDID 1125 + containing physical address A.B.C.0 where C is 1 to the number of inputs. If 1126 + there are more outputs than inputs then the remaining outputs have a CEC adapter 1127 + that is disabled and reports an invalid physical address. 1128 + 1129 + 1130 + Section 16: Some Future Improvements 1120 1131 ------------------------------------ 1121 1132 1122 1133 Just as a reminder and in no particular order: ··· 1148 1121 - Fix sequence/field numbering when looping of video with alternate fields 1149 1122 - Add support for V4L2_CID_BG_COLOR for video outputs 1150 1123 - Add ARGB888 overlay support: better testing of the alpha channel 1151 - - Add custom DV timings support 1152 - - Add support for V4L2_DV_FL_REDUCED_FPS 1153 1124 - Improve pixel aspect support in the tpg code by passing a real v4l2_fract 1154 1125 - Use per-queue locks and/or per-device locks to improve throughput 1155 1126 - Add support to loop from a specific output to a specific input across ··· 1158 1133 - Make a thread for the RDS generation, that would help in particular for the 1159 1134 "Controls" RDS Rx I/O Mode as the read-only RDS controls could be updated 1160 1135 in real-time. 1136 + - Changing the EDID should cause hotplug detect emulation to happen.
+23
MAINTAINERS
··· 1647 1647 S: Maintained 1648 1648 F: drivers/media/platform/s5p-tv/ 1649 1649 1650 + ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT 1651 + M: Kyungmin Park <kyungmin.park@samsung.com> 1652 + L: linux-arm-kernel@lists.infradead.org 1653 + L: linux-media@vger.kernel.org 1654 + S: Maintained 1655 + F: drivers/staging/media/platform/s5p-cec/ 1656 + 1650 1657 ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT 1651 1658 M: Andrzej Pietrasiewicz <andrzej.p@samsung.com> 1652 1659 M: Jacek Anaszewski <j.anaszewski@samsung.com> ··· 2858 2851 F: drivers/net/ieee802154/cc2520.c 2859 2852 F: include/linux/spi/cc2520.h 2860 2853 F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt 2854 + 2855 + CEC DRIVER 2856 + M: Hans Verkuil <hans.verkuil@cisco.com> 2857 + L: linux-media@vger.kernel.org 2858 + T: git git://linuxtv.org/media_tree.git 2859 + W: http://linuxtv.org 2860 + S: Supported 2861 + F: Documentation/cec.txt 2862 + F: Documentation/DocBook/media/v4l/cec* 2863 + F: drivers/staging/media/cec/ 2864 + F: drivers/media/cec-edid.c 2865 + F: drivers/media/rc/keymaps/rc-cec.c 2866 + F: include/media/cec.h 2867 + F: include/media/cec-edid.h 2868 + F: include/linux/cec.h 2869 + F: include/linux/cec-funcs.h 2861 2870 2862 2871 CELL BROADBAND ENGINE ARCHITECTURE 2863 2872 M: Arnd Bergmann <arnd@arndb.de>
+3
drivers/media/Kconfig
··· 80 80 81 81 Say Y when you have a TV or an IR device. 82 82 83 + config MEDIA_CEC_EDID 84 + tristate 85 + 83 86 # 84 87 # Media controller 85 88 # Selectable only for webcam/grabbers, as other drivers don't use it
+2
drivers/media/Makefile
··· 2 2 # Makefile for the kernel multimedia device drivers. 3 3 # 4 4 5 + obj-$(CONFIG_MEDIA_CEC_EDID) += cec-edid.o 6 + 5 7 media-objs := media-device.o media-devnode.o media-entity.o 6 8 7 9 #
+168
drivers/media/cec-edid.c
··· 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");
+24
drivers/media/i2c/Kconfig
··· 209 209 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API 210 210 depends on GPIOLIB || COMPILE_TEST 211 211 select HDMI 212 + select MEDIA_CEC_EDID 212 213 ---help--- 213 214 Support for the Analog Devices ADV7604 video decoder. 214 215 ··· 219 218 To compile this driver as a module, choose M here: the 220 219 module will be called adv7604. 221 220 221 + config VIDEO_ADV7604_CEC 222 + bool "Enable Analog Devices ADV7604 CEC support" 223 + depends on VIDEO_ADV7604 && MEDIA_CEC 224 + ---help--- 225 + When selected the adv7604 will support the optional 226 + HDMI CEC feature. 227 + 222 228 config VIDEO_ADV7842 223 229 tristate "Analog Devices ADV7842 decoder" 224 230 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API 225 231 select HDMI 232 + select MEDIA_CEC_EDID 226 233 ---help--- 227 234 Support for the Analog Devices ADV7842 video decoder. 228 235 ··· 239 230 240 231 To compile this driver as a module, choose M here: the 241 232 module will be called adv7842. 233 + 234 + config VIDEO_ADV7842_CEC 235 + bool "Enable Analog Devices ADV7842 CEC support" 236 + depends on VIDEO_ADV7842 && MEDIA_CEC 237 + ---help--- 238 + When selected the adv7842 will support the optional 239 + HDMI CEC feature. 242 240 243 241 config VIDEO_BT819 244 242 tristate "BT819A VideoStream decoder" ··· 463 447 tristate "Analog Devices ADV7511 encoder" 464 448 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API 465 449 select HDMI 450 + select MEDIA_CEC_EDID 466 451 ---help--- 467 452 Support for the Analog Devices ADV7511 video encoder. 468 453 ··· 471 454 472 455 To compile this driver as a module, choose M here: the 473 456 module will be called adv7511. 457 + 458 + config VIDEO_ADV7511_CEC 459 + bool "Enable Analog Devices ADV7511 CEC support" 460 + depends on VIDEO_ADV7511 && MEDIA_CEC 461 + ---help--- 462 + When selected the adv7511 will support the optional 463 + HDMI CEC feature. 474 464 475 465 config VIDEO_AD9389B 476 466 tristate "Analog Devices AD9389B encoder"
+393 -8
drivers/media/i2c/adv7511.c
··· 33 33 #include <media/v4l2-ctrls.h> 34 34 #include <media/v4l2-dv-timings.h> 35 35 #include <media/i2c/adv7511.h> 36 + #include <media/cec.h> 36 37 37 38 static int debug; 38 39 module_param(debug, int, 0644); ··· 59 58 #define ADV7511_MAX_HEIGHT 1200 60 59 #define ADV7511_MIN_PIXELCLOCK 20000000 61 60 #define ADV7511_MAX_PIXELCLOCK 225000000 61 + 62 + #define ADV7511_MAX_ADDRS (3) 62 63 63 64 /* 64 65 ********************************************************************** ··· 93 90 struct v4l2_ctrl_handler hdl; 94 91 int chip_revision; 95 92 u8 i2c_edid_addr; 96 - u8 i2c_cec_addr; 97 93 u8 i2c_pktmem_addr; 94 + u8 i2c_cec_addr; 95 + 96 + struct i2c_client *i2c_cec; 97 + struct cec_adapter *cec_adap; 98 + u8 cec_addr[ADV7511_MAX_ADDRS]; 99 + u8 cec_valid_addrs; 100 + bool cec_enabled_adap; 101 + 98 102 /* Is the adv7511 powered on? */ 99 103 bool power_on; 100 104 /* Did we receive hotplug and rx-sense signals? */ 101 105 bool have_monitor; 106 + bool enabled_irq; 102 107 /* timings from s_dv_timings */ 103 108 struct v4l2_dv_timings dv_timings; 104 109 u32 fmt_code; ··· 238 227 return ret; 239 228 } 240 229 241 - static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf) 230 + static void adv7511_edid_rd(struct v4l2_subdev *sd, uint16_t len, uint8_t *buf) 242 231 { 243 232 struct adv7511_state *state = get_adv7511_state(sd); 244 233 int i; ··· 251 240 I2C_SMBUS_BLOCK_MAX, buf + i); 252 241 if (err) 253 242 v4l2_err(sd, "%s: i2c read error\n", __func__); 243 + } 244 + 245 + static inline int adv7511_cec_read(struct v4l2_subdev *sd, u8 reg) 246 + { 247 + struct adv7511_state *state = get_adv7511_state(sd); 248 + 249 + return i2c_smbus_read_byte_data(state->i2c_cec, reg); 250 + } 251 + 252 + static int adv7511_cec_write(struct v4l2_subdev *sd, u8 reg, u8 val) 253 + { 254 + struct adv7511_state *state = get_adv7511_state(sd); 255 + int ret; 256 + int i; 257 + 258 + for (i = 0; i < 3; i++) { 259 + ret = i2c_smbus_write_byte_data(state->i2c_cec, reg, val); 260 + if (ret == 0) 261 + return 0; 262 + } 263 + v4l2_err(sd, "%s: I2C Write Problem\n", __func__); 264 + return ret; 265 + } 266 + 267 + static inline int adv7511_cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, 268 + u8 val) 269 + { 270 + return adv7511_cec_write(sd, reg, (adv7511_cec_read(sd, reg) & mask) | val); 254 271 } 255 272 256 273 static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg) ··· 464 425 #ifdef CONFIG_VIDEO_ADV_DEBUG 465 426 static void adv7511_inv_register(struct v4l2_subdev *sd) 466 427 { 428 + struct adv7511_state *state = get_adv7511_state(sd); 429 + 467 430 v4l2_info(sd, "0x000-0x0ff: Main Map\n"); 431 + if (state->i2c_cec) 432 + v4l2_info(sd, "0x100-0x1ff: CEC Map\n"); 468 433 } 469 434 470 435 static int adv7511_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 471 436 { 437 + struct adv7511_state *state = get_adv7511_state(sd); 438 + 472 439 reg->size = 1; 473 440 switch (reg->reg >> 8) { 474 441 case 0: 475 442 reg->val = adv7511_rd(sd, reg->reg & 0xff); 476 443 break; 444 + case 1: 445 + if (state->i2c_cec) { 446 + reg->val = adv7511_cec_read(sd, reg->reg & 0xff); 447 + break; 448 + } 449 + /* fall through */ 477 450 default: 478 451 v4l2_info(sd, "Register %03llx not supported\n", reg->reg); 479 452 adv7511_inv_register(sd); ··· 496 445 497 446 static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) 498 447 { 448 + struct adv7511_state *state = get_adv7511_state(sd); 449 + 499 450 switch (reg->reg >> 8) { 500 451 case 0: 501 452 adv7511_wr(sd, reg->reg & 0xff, reg->val & 0xff); 502 453 break; 454 + case 1: 455 + if (state->i2c_cec) { 456 + adv7511_cec_write(sd, reg->reg & 0xff, reg->val & 0xff); 457 + break; 458 + } 459 + /* fall through */ 503 460 default: 504 461 v4l2_info(sd, "Register %03llx not supported\n", reg->reg); 505 462 adv7511_inv_register(sd); ··· 595 536 { 596 537 struct adv7511_state *state = get_adv7511_state(sd); 597 538 struct adv7511_state_edid *edid = &state->edid; 539 + int i; 598 540 599 541 static const char * const states[] = { 600 542 "in reset", ··· 665 605 else 666 606 v4l2_info(sd, "no timings set\n"); 667 607 v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr); 608 + 609 + if (state->i2c_cec == NULL) 610 + return 0; 611 + 668 612 v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr); 613 + 614 + v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ? 615 + "enabled" : "disabled"); 616 + if (state->cec_enabled_adap) { 617 + for (i = 0; i < ADV7511_MAX_ADDRS; i++) { 618 + bool is_valid = state->cec_valid_addrs & (1 << i); 619 + 620 + if (is_valid) 621 + v4l2_info(sd, "CEC Logical Address: 0x%x\n", 622 + state->cec_addr[i]); 623 + } 624 + } 669 625 v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr); 670 626 return 0; 671 627 } ··· 739 663 return true; 740 664 } 741 665 666 + #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC) 667 + static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable) 668 + { 669 + struct adv7511_state *state = adap->priv; 670 + struct v4l2_subdev *sd = &state->sd; 671 + 672 + if (state->i2c_cec == NULL) 673 + return -EIO; 674 + 675 + if (!state->cec_enabled_adap && enable) { 676 + /* power up cec section */ 677 + adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x01); 678 + /* legacy mode and clear all rx buffers */ 679 + adv7511_cec_write(sd, 0x4a, 0x07); 680 + adv7511_cec_write(sd, 0x4a, 0); 681 + adv7511_cec_write_and_or(sd, 0x11, 0xfe, 0); /* initially disable tx */ 682 + /* enabled irqs: */ 683 + /* tx: ready */ 684 + /* tx: arbitration lost */ 685 + /* tx: retry timeout */ 686 + /* rx: ready 1 */ 687 + if (state->enabled_irq) 688 + adv7511_wr_and_or(sd, 0x95, 0xc0, 0x39); 689 + } else if (state->cec_enabled_adap && !enable) { 690 + if (state->enabled_irq) 691 + adv7511_wr_and_or(sd, 0x95, 0xc0, 0x00); 692 + /* disable address mask 1-3 */ 693 + adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0x00); 694 + /* power down cec section */ 695 + adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x00); 696 + state->cec_valid_addrs = 0; 697 + } 698 + state->cec_enabled_adap = enable; 699 + return 0; 700 + } 701 + 702 + static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) 703 + { 704 + struct adv7511_state *state = adap->priv; 705 + struct v4l2_subdev *sd = &state->sd; 706 + unsigned int i, free_idx = ADV7511_MAX_ADDRS; 707 + 708 + if (!state->cec_enabled_adap) 709 + return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO; 710 + 711 + if (addr == CEC_LOG_ADDR_INVALID) { 712 + adv7511_cec_write_and_or(sd, 0x4b, 0x8f, 0); 713 + state->cec_valid_addrs = 0; 714 + return 0; 715 + } 716 + 717 + for (i = 0; i < ADV7511_MAX_ADDRS; i++) { 718 + bool is_valid = state->cec_valid_addrs & (1 << i); 719 + 720 + if (free_idx == ADV7511_MAX_ADDRS && !is_valid) 721 + free_idx = i; 722 + if (is_valid && state->cec_addr[i] == addr) 723 + return 0; 724 + } 725 + if (i == ADV7511_MAX_ADDRS) { 726 + i = free_idx; 727 + if (i == ADV7511_MAX_ADDRS) 728 + return -ENXIO; 729 + } 730 + state->cec_addr[i] = addr; 731 + state->cec_valid_addrs |= 1 << i; 732 + 733 + switch (i) { 734 + case 0: 735 + /* enable address mask 0 */ 736 + adv7511_cec_write_and_or(sd, 0x4b, 0xef, 0x10); 737 + /* set address for mask 0 */ 738 + adv7511_cec_write_and_or(sd, 0x4c, 0xf0, addr); 739 + break; 740 + case 1: 741 + /* enable address mask 1 */ 742 + adv7511_cec_write_and_or(sd, 0x4b, 0xdf, 0x20); 743 + /* set address for mask 1 */ 744 + adv7511_cec_write_and_or(sd, 0x4c, 0x0f, addr << 4); 745 + break; 746 + case 2: 747 + /* enable address mask 2 */ 748 + adv7511_cec_write_and_or(sd, 0x4b, 0xbf, 0x40); 749 + /* set address for mask 1 */ 750 + adv7511_cec_write_and_or(sd, 0x4d, 0xf0, addr); 751 + break; 752 + } 753 + return 0; 754 + } 755 + 756 + static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, 757 + u32 signal_free_time, struct cec_msg *msg) 758 + { 759 + struct adv7511_state *state = adap->priv; 760 + struct v4l2_subdev *sd = &state->sd; 761 + u8 len = msg->len; 762 + unsigned int i; 763 + 764 + v4l2_dbg(1, debug, sd, "%s: len %d\n", __func__, len); 765 + 766 + if (len > 16) { 767 + v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len); 768 + return -EINVAL; 769 + } 770 + 771 + /* 772 + * The number of retries is the number of attempts - 1, but retry 773 + * at least once. It's not clear if a value of 0 is allowed, so 774 + * let's do at least one retry. 775 + */ 776 + adv7511_cec_write_and_or(sd, 0x12, ~0x70, max(1, attempts - 1) << 4); 777 + 778 + /* blocking, clear cec tx irq status */ 779 + adv7511_wr_and_or(sd, 0x97, 0xc7, 0x38); 780 + 781 + /* write data */ 782 + for (i = 0; i < len; i++) 783 + adv7511_cec_write(sd, i, msg->msg[i]); 784 + 785 + /* set length (data + header) */ 786 + adv7511_cec_write(sd, 0x10, len); 787 + /* start transmit, enable tx */ 788 + adv7511_cec_write(sd, 0x11, 0x01); 789 + return 0; 790 + } 791 + 792 + static void adv_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status) 793 + { 794 + struct adv7511_state *state = get_adv7511_state(sd); 795 + 796 + if ((adv7511_cec_read(sd, 0x11) & 0x01) == 0) { 797 + v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__); 798 + return; 799 + } 800 + 801 + if (tx_raw_status & 0x10) { 802 + v4l2_dbg(1, debug, sd, 803 + "%s: tx raw: arbitration lost\n", __func__); 804 + cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST, 805 + 1, 0, 0, 0); 806 + return; 807 + } 808 + if (tx_raw_status & 0x08) { 809 + u8 status; 810 + u8 nack_cnt; 811 + u8 low_drive_cnt; 812 + 813 + v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__); 814 + /* 815 + * We set this status bit since this hardware performs 816 + * retransmissions. 817 + */ 818 + status = CEC_TX_STATUS_MAX_RETRIES; 819 + nack_cnt = adv7511_cec_read(sd, 0x14) & 0xf; 820 + if (nack_cnt) 821 + status |= CEC_TX_STATUS_NACK; 822 + low_drive_cnt = adv7511_cec_read(sd, 0x14) >> 4; 823 + if (low_drive_cnt) 824 + status |= CEC_TX_STATUS_LOW_DRIVE; 825 + cec_transmit_done(state->cec_adap, status, 826 + 0, nack_cnt, low_drive_cnt, 0); 827 + return; 828 + } 829 + if (tx_raw_status & 0x20) { 830 + v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__); 831 + cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); 832 + return; 833 + } 834 + } 835 + 836 + static const struct cec_adap_ops adv7511_cec_adap_ops = { 837 + .adap_enable = adv7511_cec_adap_enable, 838 + .adap_log_addr = adv7511_cec_adap_log_addr, 839 + .adap_transmit = adv7511_cec_adap_transmit, 840 + }; 841 + #endif 842 + 742 843 /* Enable interrupts */ 743 844 static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable) 744 845 { 846 + struct adv7511_state *state = get_adv7511_state(sd); 745 847 u8 irqs = MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT; 746 848 u8 irqs_rd; 747 849 int retries = 100; 748 850 749 851 v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? "enable" : "disable"); 852 + 853 + if (state->enabled_irq == enable) 854 + return; 855 + state->enabled_irq = enable; 750 856 751 857 /* The datasheet says that the EDID ready interrupt should be 752 858 disabled if there is no hotplug. */ ··· 936 678 irqs = 0; 937 679 else if (adv7511_have_hotplug(sd)) 938 680 irqs |= MASK_ADV7511_EDID_RDY_INT; 681 + 682 + adv7511_wr_and_or(sd, 0x95, 0xc0, 683 + (state->cec_enabled_adap && enable) ? 0x39 : 0x00); 939 684 940 685 /* 941 686 * This i2c write can fail (approx. 1 in 1000 writes). But it ··· 962 701 static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled) 963 702 { 964 703 u8 irq_status; 704 + u8 cec_irq; 965 705 966 706 /* disable interrupts to prevent a race condition */ 967 707 adv7511_set_isr(sd, false); 968 708 irq_status = adv7511_rd(sd, 0x96); 709 + cec_irq = adv7511_rd(sd, 0x97); 969 710 /* clear detected interrupts */ 970 711 adv7511_wr(sd, 0x96, irq_status); 712 + adv7511_wr(sd, 0x97, cec_irq); 971 713 972 - v4l2_dbg(1, debug, sd, "%s: irq 0x%x\n", __func__, irq_status); 714 + v4l2_dbg(1, debug, sd, "%s: irq 0x%x, cec-irq 0x%x\n", __func__, 715 + irq_status, cec_irq); 973 716 974 717 if (irq_status & (MASK_ADV7511_HPD_INT | MASK_ADV7511_MSEN_INT)) 975 718 adv7511_check_monitor_present_status(sd); 976 719 if (irq_status & MASK_ADV7511_EDID_RDY_INT) 977 720 adv7511_check_edid_status(sd); 721 + 722 + #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC) 723 + if (cec_irq & 0x38) 724 + adv_cec_tx_raw_status(sd, cec_irq); 725 + 726 + if (cec_irq & 1) { 727 + struct adv7511_state *state = get_adv7511_state(sd); 728 + struct cec_msg msg; 729 + 730 + msg.len = adv7511_cec_read(sd, 0x25) & 0x1f; 731 + 732 + v4l2_dbg(1, debug, sd, "%s: cec msg len %d\n", __func__, 733 + msg.len); 734 + 735 + if (msg.len > 16) 736 + msg.len = 16; 737 + 738 + if (msg.len) { 739 + u8 i; 740 + 741 + for (i = 0; i < msg.len; i++) 742 + msg.msg[i] = adv7511_cec_read(sd, i + 0x15); 743 + 744 + adv7511_cec_write(sd, 0x4a, 1); /* toggle to re-enable rx 1 */ 745 + adv7511_cec_write(sd, 0x4a, 0); 746 + cec_received_msg(state->cec_adap, &msg); 747 + } 748 + } 749 + #endif 978 750 979 751 /* enable interrupts */ 980 752 adv7511_set_isr(sd, true); ··· 1477 1183 /* We failed to read the EDID, so send an event for this. */ 1478 1184 ed.present = false; 1479 1185 ed.segment = adv7511_rd(sd, 0xc4); 1186 + ed.phys_addr = CEC_PHYS_ADDR_INVALID; 1187 + cec_s_phys_addr(state->cec_adap, ed.phys_addr, false); 1480 1188 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); 1481 1189 v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, 0x0); 1482 1190 } ··· 1702 1406 1703 1407 v4l2_dbg(1, debug, sd, "%s: edid complete with %d segment(s)\n", __func__, state->edid.segments); 1704 1408 state->edid.complete = true; 1705 - 1409 + ed.phys_addr = cec_get_edid_phys_addr(state->edid.data, 1410 + state->edid.segments * 256, 1411 + NULL); 1706 1412 /* report when we have all segments 1707 1413 but report only for segment 0 1708 1414 */ 1709 1415 ed.present = true; 1710 1416 ed.segment = 0; 1711 1417 state->edid_detect_counter++; 1418 + cec_s_phys_addr(state->cec_adap, ed.phys_addr, false); 1712 1419 v4l2_subdev_notify(sd, ADV7511_EDID_DETECT, (void *)&ed); 1713 1420 return ed.present; 1714 1421 } ··· 1719 1420 return false; 1720 1421 } 1721 1422 1423 + static int adv7511_registered(struct v4l2_subdev *sd) 1424 + { 1425 + struct adv7511_state *state = get_adv7511_state(sd); 1426 + int err; 1427 + 1428 + err = cec_register_adapter(state->cec_adap); 1429 + if (err) 1430 + cec_delete_adapter(state->cec_adap); 1431 + return err; 1432 + } 1433 + 1434 + static void adv7511_unregistered(struct v4l2_subdev *sd) 1435 + { 1436 + struct adv7511_state *state = get_adv7511_state(sd); 1437 + 1438 + cec_unregister_adapter(state->cec_adap); 1439 + } 1440 + 1441 + static const struct v4l2_subdev_internal_ops adv7511_int_ops = { 1442 + .registered = adv7511_registered, 1443 + .unregistered = adv7511_unregistered, 1444 + }; 1445 + 1722 1446 /* ----------------------------------------------------------------------- */ 1723 1447 /* Setup ADV7511 */ 1724 1448 static void adv7511_init_setup(struct v4l2_subdev *sd) 1725 1449 { 1726 1450 struct adv7511_state *state = get_adv7511_state(sd); 1727 1451 struct adv7511_state_edid *edid = &state->edid; 1452 + u32 cec_clk = state->pdata.cec_clk; 1453 + u8 ratio; 1728 1454 1729 1455 v4l2_dbg(1, debug, sd, "%s\n", __func__); 1730 1456 1731 1457 /* clear all interrupts */ 1732 1458 adv7511_wr(sd, 0x96, 0xff); 1459 + adv7511_wr(sd, 0x97, 0xff); 1733 1460 /* 1734 1461 * Stop HPD from resetting a lot of registers. 1735 1462 * It might leave the chip in a partly un-initialized state, ··· 1767 1442 adv7511_set_isr(sd, false); 1768 1443 adv7511_s_stream(sd, false); 1769 1444 adv7511_s_audio_stream(sd, false); 1445 + 1446 + if (state->i2c_cec == NULL) 1447 + return; 1448 + 1449 + v4l2_dbg(1, debug, sd, "%s: cec_clk %d\n", __func__, cec_clk); 1450 + 1451 + /* cec soft reset */ 1452 + adv7511_cec_write(sd, 0x50, 0x01); 1453 + adv7511_cec_write(sd, 0x50, 0x00); 1454 + 1455 + /* legacy mode */ 1456 + adv7511_cec_write(sd, 0x4a, 0x00); 1457 + 1458 + if (cec_clk % 750000 != 0) 1459 + v4l2_err(sd, "%s: cec_clk %d, not multiple of 750 Khz\n", 1460 + __func__, cec_clk); 1461 + 1462 + ratio = (cec_clk / 750000) - 1; 1463 + adv7511_cec_write(sd, 0x4e, ratio << 2); 1770 1464 } 1771 1465 1772 1466 static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id) ··· 1820 1476 client->addr << 1); 1821 1477 1822 1478 v4l2_i2c_subdev_init(sd, client, &adv7511_ops); 1479 + sd->internal_ops = &adv7511_int_ops; 1823 1480 1824 1481 hdl = &state->hdl; 1825 1482 v4l2_ctrl_handler_init(hdl, 10); ··· 1861 1516 chip_id[0] = adv7511_rd(sd, 0xf5); 1862 1517 chip_id[1] = adv7511_rd(sd, 0xf6); 1863 1518 if (chip_id[0] != 0x75 || chip_id[1] != 0x11) { 1864 - v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0], chip_id[1]); 1519 + v4l2_err(sd, "chip_id != 0x7511, read 0x%02x%02x\n", chip_id[0], 1520 + chip_id[1]); 1865 1521 err = -EIO; 1866 1522 goto err_entity; 1867 1523 } 1868 1524 1869 - state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1); 1525 + state->i2c_edid = i2c_new_dummy(client->adapter, 1526 + state->i2c_edid_addr >> 1); 1870 1527 if (state->i2c_edid == NULL) { 1871 1528 v4l2_err(sd, "failed to register edid i2c client\n"); 1872 1529 err = -ENOMEM; 1873 1530 goto err_entity; 1874 1531 } 1875 1532 1533 + adv7511_wr(sd, 0xe1, state->i2c_cec_addr); 1534 + if (state->pdata.cec_clk < 3000000 || 1535 + state->pdata.cec_clk > 100000000) { 1536 + v4l2_err(sd, "%s: cec_clk %u outside range, disabling cec\n", 1537 + __func__, state->pdata.cec_clk); 1538 + state->pdata.cec_clk = 0; 1539 + } 1540 + 1541 + if (state->pdata.cec_clk) { 1542 + state->i2c_cec = i2c_new_dummy(client->adapter, 1543 + state->i2c_cec_addr >> 1); 1544 + if (state->i2c_cec == NULL) { 1545 + v4l2_err(sd, "failed to register cec i2c client\n"); 1546 + goto err_unreg_edid; 1547 + } 1548 + adv7511_wr(sd, 0xe2, 0x00); /* power up cec section */ 1549 + } else { 1550 + adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */ 1551 + } 1552 + 1876 1553 state->i2c_pktmem = i2c_new_dummy(client->adapter, state->i2c_pktmem_addr >> 1); 1877 1554 if (state->i2c_pktmem == NULL) { 1878 1555 v4l2_err(sd, "failed to register pktmem i2c client\n"); 1879 1556 err = -ENOMEM; 1880 - goto err_unreg_edid; 1557 + goto err_unreg_cec; 1881 1558 } 1882 1559 1883 - adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */ 1884 1560 state->work_queue = create_singlethread_workqueue(sd->name); 1885 1561 if (state->work_queue == NULL) { 1886 1562 v4l2_err(sd, "could not create workqueue\n"); ··· 1912 1546 INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler); 1913 1547 1914 1548 adv7511_init_setup(sd); 1549 + 1550 + #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC) 1551 + state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops, 1552 + state, dev_name(&client->dev), CEC_CAP_TRANSMIT | 1553 + CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | CEC_CAP_RC, 1554 + ADV7511_MAX_ADDRS, &client->dev); 1555 + err = PTR_ERR_OR_ZERO(state->cec_adap); 1556 + if (err) { 1557 + destroy_workqueue(state->work_queue); 1558 + goto err_unreg_pktmem; 1559 + } 1560 + #endif 1561 + 1915 1562 adv7511_set_isr(sd, true); 1916 1563 adv7511_check_monitor_present_status(sd); 1917 1564 ··· 1934 1555 1935 1556 err_unreg_pktmem: 1936 1557 i2c_unregister_device(state->i2c_pktmem); 1558 + err_unreg_cec: 1559 + if (state->i2c_cec) 1560 + i2c_unregister_device(state->i2c_cec); 1937 1561 err_unreg_edid: 1938 1562 i2c_unregister_device(state->i2c_edid); 1939 1563 err_entity: ··· 1958 1576 v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, 1959 1577 client->addr << 1, client->adapter->name); 1960 1578 1579 + adv7511_set_isr(sd, false); 1961 1580 adv7511_init_setup(sd); 1962 1581 cancel_delayed_work(&state->edid_handler); 1963 1582 i2c_unregister_device(state->i2c_edid); 1583 + if (state->i2c_cec) 1584 + i2c_unregister_device(state->i2c_cec); 1964 1585 i2c_unregister_device(state->i2c_pktmem); 1965 1586 destroy_workqueue(state->work_queue); 1966 1587 v4l2_device_unregister_subdev(sd);
+296 -36
drivers/media/i2c/adv7604.c
··· 40 40 #include <linux/regmap.h> 41 41 42 42 #include <media/i2c/adv7604.h> 43 + #include <media/cec.h> 43 44 #include <media/v4l2-ctrls.h> 44 45 #include <media/v4l2-device.h> 45 46 #include <media/v4l2-event.h> ··· 80 79 #define ADV76XX_OP_CH_SEL_RBG (5 << 5) 81 80 82 81 #define ADV76XX_OP_SWAP_CB_CR (1 << 0) 82 + 83 + #define ADV76XX_MAX_ADDRS (3) 83 84 84 85 enum adv76xx_type { 85 86 ADV7604, ··· 190 187 u32 rgb_quantization_range; 191 188 struct delayed_work delayed_work_enable_hotplug; 192 189 bool restart_stdi_once; 190 + 191 + /* CEC */ 192 + struct cec_adapter *cec_adap; 193 + u8 cec_addr[ADV76XX_MAX_ADDRS]; 194 + u8 cec_valid_addrs; 195 + bool cec_enabled_adap; 193 196 194 197 /* i2c clients */ 195 198 struct i2c_client *i2c_clients[ADV76XX_PAGE_MAX]; ··· 390 381 return regmap_write(state->regmap[ADV76XX_PAGE_IO], reg, val); 391 382 } 392 383 393 - static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) 384 + static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, 385 + u8 val) 394 386 { 395 387 return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val); 396 388 } ··· 422 412 struct adv76xx_state *state = to_state(sd); 423 413 424 414 return regmap_write(state->regmap[ADV76XX_PAGE_CEC], reg, val); 415 + } 416 + 417 + static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, 418 + u8 val) 419 + { 420 + return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val); 425 421 } 426 422 427 423 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) ··· 908 892 { 909 893 struct adv76xx_state *state = to_state(sd); 910 894 const struct adv76xx_chip_info *info = state->info; 895 + u16 cable_det = info->read_cable_det(sd); 911 896 912 - return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, 913 - info->read_cable_det(sd)); 897 + return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det); 914 898 } 915 899 916 900 static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, ··· 1940 1924 return 0; 1941 1925 } 1942 1926 1927 + #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC) 1928 + static void adv76xx_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status) 1929 + { 1930 + struct adv76xx_state *state = to_state(sd); 1931 + 1932 + if ((cec_read(sd, 0x11) & 0x01) == 0) { 1933 + v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__); 1934 + return; 1935 + } 1936 + 1937 + if (tx_raw_status & 0x02) { 1938 + v4l2_dbg(1, debug, sd, "%s: tx raw: arbitration lost\n", 1939 + __func__); 1940 + cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST, 1941 + 1, 0, 0, 0); 1942 + } 1943 + if (tx_raw_status & 0x04) { 1944 + u8 status; 1945 + u8 nack_cnt; 1946 + u8 low_drive_cnt; 1947 + 1948 + v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__); 1949 + /* 1950 + * We set this status bit since this hardware performs 1951 + * retransmissions. 1952 + */ 1953 + status = CEC_TX_STATUS_MAX_RETRIES; 1954 + nack_cnt = cec_read(sd, 0x14) & 0xf; 1955 + if (nack_cnt) 1956 + status |= CEC_TX_STATUS_NACK; 1957 + low_drive_cnt = cec_read(sd, 0x14) >> 4; 1958 + if (low_drive_cnt) 1959 + status |= CEC_TX_STATUS_LOW_DRIVE; 1960 + cec_transmit_done(state->cec_adap, status, 1961 + 0, nack_cnt, low_drive_cnt, 0); 1962 + return; 1963 + } 1964 + if (tx_raw_status & 0x01) { 1965 + v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__); 1966 + cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); 1967 + return; 1968 + } 1969 + } 1970 + 1971 + static void adv76xx_cec_isr(struct v4l2_subdev *sd, bool *handled) 1972 + { 1973 + struct adv76xx_state *state = to_state(sd); 1974 + u8 cec_irq; 1975 + 1976 + /* cec controller */ 1977 + cec_irq = io_read(sd, 0x4d) & 0x0f; 1978 + if (!cec_irq) 1979 + return; 1980 + 1981 + v4l2_dbg(1, debug, sd, "%s: cec: irq 0x%x\n", __func__, cec_irq); 1982 + adv76xx_cec_tx_raw_status(sd, cec_irq); 1983 + if (cec_irq & 0x08) { 1984 + struct cec_msg msg; 1985 + 1986 + msg.len = cec_read(sd, 0x25) & 0x1f; 1987 + if (msg.len > 16) 1988 + msg.len = 16; 1989 + 1990 + if (msg.len) { 1991 + u8 i; 1992 + 1993 + for (i = 0; i < msg.len; i++) 1994 + msg.msg[i] = cec_read(sd, i + 0x15); 1995 + cec_write(sd, 0x26, 0x01); /* re-enable rx */ 1996 + cec_received_msg(state->cec_adap, &msg); 1997 + } 1998 + } 1999 + 2000 + /* note: the bit order is swapped between 0x4d and 0x4e */ 2001 + cec_irq = ((cec_irq & 0x08) >> 3) | ((cec_irq & 0x04) >> 1) | 2002 + ((cec_irq & 0x02) << 1) | ((cec_irq & 0x01) << 3); 2003 + io_write(sd, 0x4e, cec_irq); 2004 + 2005 + if (handled) 2006 + *handled = true; 2007 + } 2008 + 2009 + static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable) 2010 + { 2011 + struct adv76xx_state *state = adap->priv; 2012 + struct v4l2_subdev *sd = &state->sd; 2013 + 2014 + if (!state->cec_enabled_adap && enable) { 2015 + cec_write_clr_set(sd, 0x2a, 0x01, 0x01); /* power up cec */ 2016 + cec_write(sd, 0x2c, 0x01); /* cec soft reset */ 2017 + cec_write_clr_set(sd, 0x11, 0x01, 0); /* initially disable tx */ 2018 + /* enabled irqs: */ 2019 + /* tx: ready */ 2020 + /* tx: arbitration lost */ 2021 + /* tx: retry timeout */ 2022 + /* rx: ready */ 2023 + io_write_clr_set(sd, 0x50, 0x0f, 0x0f); 2024 + cec_write(sd, 0x26, 0x01); /* enable rx */ 2025 + } else if (state->cec_enabled_adap && !enable) { 2026 + /* disable cec interrupts */ 2027 + io_write_clr_set(sd, 0x50, 0x0f, 0x00); 2028 + /* disable address mask 1-3 */ 2029 + cec_write_clr_set(sd, 0x27, 0x70, 0x00); 2030 + /* power down cec section */ 2031 + cec_write_clr_set(sd, 0x2a, 0x01, 0x00); 2032 + state->cec_valid_addrs = 0; 2033 + } 2034 + state->cec_enabled_adap = enable; 2035 + adv76xx_s_detect_tx_5v_ctrl(sd); 2036 + return 0; 2037 + } 2038 + 2039 + static int adv76xx_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) 2040 + { 2041 + struct adv76xx_state *state = adap->priv; 2042 + struct v4l2_subdev *sd = &state->sd; 2043 + unsigned int i, free_idx = ADV76XX_MAX_ADDRS; 2044 + 2045 + if (!state->cec_enabled_adap) 2046 + return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO; 2047 + 2048 + if (addr == CEC_LOG_ADDR_INVALID) { 2049 + cec_write_clr_set(sd, 0x27, 0x70, 0); 2050 + state->cec_valid_addrs = 0; 2051 + return 0; 2052 + } 2053 + 2054 + for (i = 0; i < ADV76XX_MAX_ADDRS; i++) { 2055 + bool is_valid = state->cec_valid_addrs & (1 << i); 2056 + 2057 + if (free_idx == ADV76XX_MAX_ADDRS && !is_valid) 2058 + free_idx = i; 2059 + if (is_valid && state->cec_addr[i] == addr) 2060 + return 0; 2061 + } 2062 + if (i == ADV76XX_MAX_ADDRS) { 2063 + i = free_idx; 2064 + if (i == ADV76XX_MAX_ADDRS) 2065 + return -ENXIO; 2066 + } 2067 + state->cec_addr[i] = addr; 2068 + state->cec_valid_addrs |= 1 << i; 2069 + 2070 + switch (i) { 2071 + case 0: 2072 + /* enable address mask 0 */ 2073 + cec_write_clr_set(sd, 0x27, 0x10, 0x10); 2074 + /* set address for mask 0 */ 2075 + cec_write_clr_set(sd, 0x28, 0x0f, addr); 2076 + break; 2077 + case 1: 2078 + /* enable address mask 1 */ 2079 + cec_write_clr_set(sd, 0x27, 0x20, 0x20); 2080 + /* set address for mask 1 */ 2081 + cec_write_clr_set(sd, 0x28, 0xf0, addr << 4); 2082 + break; 2083 + case 2: 2084 + /* enable address mask 2 */ 2085 + cec_write_clr_set(sd, 0x27, 0x40, 0x40); 2086 + /* set address for mask 1 */ 2087 + cec_write_clr_set(sd, 0x29, 0x0f, addr); 2088 + break; 2089 + } 2090 + return 0; 2091 + } 2092 + 2093 + static int adv76xx_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, 2094 + u32 signal_free_time, struct cec_msg *msg) 2095 + { 2096 + struct adv76xx_state *state = adap->priv; 2097 + struct v4l2_subdev *sd = &state->sd; 2098 + u8 len = msg->len; 2099 + unsigned int i; 2100 + 2101 + /* 2102 + * The number of retries is the number of attempts - 1, but retry 2103 + * at least once. It's not clear if a value of 0 is allowed, so 2104 + * let's do at least one retry. 2105 + */ 2106 + cec_write_clr_set(sd, 0x12, 0x70, max(1, attempts - 1) << 4); 2107 + 2108 + if (len > 16) { 2109 + v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len); 2110 + return -EINVAL; 2111 + } 2112 + 2113 + /* write data */ 2114 + for (i = 0; i < len; i++) 2115 + cec_write(sd, i, msg->msg[i]); 2116 + 2117 + /* set length (data + header) */ 2118 + cec_write(sd, 0x10, len); 2119 + /* start transmit, enable tx */ 2120 + cec_write(sd, 0x11, 0x01); 2121 + return 0; 2122 + } 2123 + 2124 + static const struct cec_adap_ops adv76xx_cec_adap_ops = { 2125 + .adap_enable = adv76xx_cec_adap_enable, 2126 + .adap_log_addr = adv76xx_cec_adap_log_addr, 2127 + .adap_transmit = adv76xx_cec_adap_transmit, 2128 + }; 2129 + #endif 2130 + 1943 2131 static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled) 1944 2132 { 1945 2133 struct adv76xx_state *state = to_state(sd); ··· 2188 1968 if (handled) 2189 1969 *handled = true; 2190 1970 } 1971 + 1972 + #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC) 1973 + /* cec */ 1974 + adv76xx_cec_isr(sd, handled); 1975 + #endif 2191 1976 2192 1977 /* tx 5v detect */ 2193 1978 tx_5v = irq_reg_0x70 & info->cable_det_mask; ··· 2243 2018 return 0; 2244 2019 } 2245 2020 2246 - static int get_edid_spa_location(const u8 *edid) 2247 - { 2248 - u8 d; 2249 - 2250 - if ((edid[0x7e] != 1) || 2251 - (edid[0x80] != 0x02) || 2252 - (edid[0x81] != 0x03)) { 2253 - return -1; 2254 - } 2255 - 2256 - /* search Vendor Specific Data Block (tag 3) */ 2257 - d = edid[0x82] & 0x7f; 2258 - if (d > 4) { 2259 - int i = 0x84; 2260 - int end = 0x80 + d; 2261 - 2262 - do { 2263 - u8 tag = edid[i] >> 5; 2264 - u8 len = edid[i] & 0x1f; 2265 - 2266 - if ((tag == 3) && (len >= 5)) 2267 - return i + 4; 2268 - i += len + 1; 2269 - } while (i < end); 2270 - } 2271 - return -1; 2272 - } 2273 - 2274 2021 static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) 2275 2022 { 2276 2023 struct adv76xx_state *state = to_state(sd); 2277 2024 const struct adv76xx_chip_info *info = state->info; 2278 - int spa_loc; 2025 + unsigned int spa_loc; 2026 + u16 pa; 2279 2027 int err; 2280 2028 int i; 2281 2029 ··· 2279 2081 edid->blocks = 2; 2280 2082 return -E2BIG; 2281 2083 } 2084 + pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc); 2085 + err = cec_phys_addr_validate(pa, &pa, NULL); 2086 + if (err) 2087 + return err; 2282 2088 2283 2089 v4l2_dbg(2, debug, sd, "%s: write EDID pad %d, edid.present = 0x%x\n", 2284 2090 __func__, edid->pad, state->edid.present); ··· 2292 2090 adv76xx_set_hpd(state, 0); 2293 2091 rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00); 2294 2092 2295 - spa_loc = get_edid_spa_location(edid->edid); 2296 - if (spa_loc < 0) 2297 - spa_loc = 0xc0; /* Default value [REF_02, p. 116] */ 2093 + /* 2094 + * Return an error if no location of the source physical address 2095 + * was found. 2096 + */ 2097 + if (spa_loc == 0) 2098 + return -EINVAL; 2298 2099 2299 2100 switch (edid->pad) { 2300 2101 case ADV76XX_PAD_HDMI_PORT_A: ··· 2357 2152 v4l2_err(sd, "error enabling edid (0x%x)\n", state->edid.present); 2358 2153 return -EIO; 2359 2154 } 2155 + cec_s_phys_addr(state->cec_adap, pa, false); 2360 2156 2361 2157 /* enable hotplug after 100 ms */ 2362 2158 schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 10); ··· 2481 2275 ((edid_enabled & 0x02) ? "Yes" : "No"), 2482 2276 ((edid_enabled & 0x04) ? "Yes" : "No"), 2483 2277 ((edid_enabled & 0x08) ? "Yes" : "No")); 2484 - v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ? 2278 + v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ? 2485 2279 "enabled" : "disabled"); 2280 + if (state->cec_enabled_adap) { 2281 + int i; 2282 + 2283 + for (i = 0; i < ADV76XX_MAX_ADDRS; i++) { 2284 + bool is_valid = state->cec_valid_addrs & (1 << i); 2285 + 2286 + if (is_valid) 2287 + v4l2_info(sd, "CEC Logical Address: 0x%x\n", 2288 + state->cec_addr[i]); 2289 + } 2290 + } 2486 2291 2487 2292 v4l2_info(sd, "-----Signal status-----\n"); 2488 2293 cable_det = info->read_cable_det(sd); ··· 2603 2386 } 2604 2387 } 2605 2388 2389 + static int adv76xx_registered(struct v4l2_subdev *sd) 2390 + { 2391 + struct adv76xx_state *state = to_state(sd); 2392 + int err; 2393 + 2394 + err = cec_register_adapter(state->cec_adap); 2395 + if (err) 2396 + cec_delete_adapter(state->cec_adap); 2397 + return err; 2398 + } 2399 + 2400 + static void adv76xx_unregistered(struct v4l2_subdev *sd) 2401 + { 2402 + struct adv76xx_state *state = to_state(sd); 2403 + 2404 + cec_unregister_adapter(state->cec_adap); 2405 + } 2406 + 2606 2407 /* ----------------------------------------------------------------------- */ 2607 2408 2608 2409 static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = { ··· 2662 2427 .core = &adv76xx_core_ops, 2663 2428 .video = &adv76xx_video_ops, 2664 2429 .pad = &adv76xx_pad_ops, 2430 + }; 2431 + 2432 + static const struct v4l2_subdev_internal_ops adv76xx_int_ops = { 2433 + .registered = adv76xx_registered, 2434 + .unregistered = adv76xx_unregistered, 2665 2435 }; 2666 2436 2667 2437 /* -------------------------- custom ctrls ---------------------------------- */ ··· 3351 3111 id->name, i2c_adapter_id(client->adapter), 3352 3112 client->addr); 3353 3113 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; 3114 + sd->internal_ops = &adv76xx_int_ops; 3354 3115 3355 3116 /* Configure IO Regmap region */ 3356 3117 err = configure_regmap(state, ADV76XX_PAGE_IO); ··· 3487 3246 err = adv76xx_core_init(sd); 3488 3247 if (err) 3489 3248 goto err_entity; 3249 + 3250 + #if IS_ENABLED(CONFIG_VIDEO_ADV7604_CEC) 3251 + state->cec_adap = cec_allocate_adapter(&adv76xx_cec_adap_ops, 3252 + state, dev_name(&client->dev), 3253 + CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | 3254 + CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV76XX_MAX_ADDRS, 3255 + &client->dev); 3256 + err = PTR_ERR_OR_ZERO(state->cec_adap); 3257 + if (err) 3258 + goto err_entity; 3259 + #endif 3260 + 3490 3261 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, 3491 3262 client->addr << 1, client->adapter->name); 3492 3263 ··· 3525 3272 { 3526 3273 struct v4l2_subdev *sd = i2c_get_clientdata(client); 3527 3274 struct adv76xx_state *state = to_state(sd); 3275 + 3276 + /* disable interrupts */ 3277 + io_write(sd, 0x40, 0); 3278 + io_write(sd, 0x41, 0); 3279 + io_write(sd, 0x46, 0); 3280 + io_write(sd, 0x6e, 0); 3281 + io_write(sd, 0x73, 0); 3528 3282 3529 3283 cancel_delayed_work(&state->delayed_work_enable_hotplug); 3530 3284 v4l2_async_unregister_subdev(sd);
+305 -63
drivers/media/i2c/adv7842.c
··· 39 39 #include <linux/workqueue.h> 40 40 #include <linux/v4l2-dv-timings.h> 41 41 #include <linux/hdmi.h> 42 + #include <media/cec.h> 42 43 #include <media/v4l2-device.h> 43 44 #include <media/v4l2-event.h> 44 45 #include <media/v4l2-ctrls.h> ··· 79 78 #define ADV7842_OP_CH_SEL_RBG (5 << 5) 80 79 81 80 #define ADV7842_OP_SWAP_CB_CR (1 << 0) 81 + 82 + #define ADV7842_MAX_ADDRS (3) 82 83 83 84 /* 84 85 ********************************************************************** ··· 144 141 struct v4l2_ctrl *free_run_color_ctrl_manual; 145 142 struct v4l2_ctrl *free_run_color_ctrl; 146 143 struct v4l2_ctrl *rgb_quantization_range_ctrl; 144 + 145 + struct cec_adapter *cec_adap; 146 + u8 cec_addr[ADV7842_MAX_ADDRS]; 147 + u8 cec_valid_addrs; 148 + bool cec_enabled_adap; 147 149 }; 148 150 149 151 /* Unsupported timings. This device cannot support 720p30. */ ··· 425 417 return adv_smbus_write_byte_data(state->i2c_cec, reg, val); 426 418 } 427 419 428 - static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) 420 + static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val) 429 421 { 430 - return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val); 422 + return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val); 431 423 } 432 424 433 425 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg) ··· 703 695 704 696 /* ----------------------------------------------------------------------- */ 705 697 698 + static u16 adv7842_read_cable_det(struct v4l2_subdev *sd) 699 + { 700 + u8 reg = io_read(sd, 0x6f); 701 + u16 val = 0; 702 + 703 + if (reg & 0x02) 704 + val |= 1; /* port A */ 705 + if (reg & 0x01) 706 + val |= 2; /* port B */ 707 + return val; 708 + } 709 + 706 710 static void adv7842_delayed_work_enable_hotplug(struct work_struct *work) 707 711 { 708 712 struct delayed_work *dwork = to_delayed_work(work); ··· 780 760 return 0; 781 761 } 782 762 783 - static int edid_spa_location(const u8 *edid) 784 - { 785 - u8 d; 786 - 787 - /* 788 - * TODO, improve and update for other CEA extensions 789 - * currently only for 1 segment (256 bytes), 790 - * i.e. 1 extension block and CEA revision 3. 791 - */ 792 - if ((edid[0x7e] != 1) || 793 - (edid[0x80] != 0x02) || 794 - (edid[0x81] != 0x03)) { 795 - return -EINVAL; 796 - } 797 - /* 798 - * search Vendor Specific Data Block (tag 3) 799 - */ 800 - d = edid[0x82] & 0x7f; 801 - if (d > 4) { 802 - int i = 0x84; 803 - int end = 0x80 + d; 804 - do { 805 - u8 tag = edid[i]>>5; 806 - u8 len = edid[i] & 0x1f; 807 - 808 - if ((tag == 3) && (len >= 5)) 809 - return i + 4; 810 - i += len + 1; 811 - } while (i < end); 812 - } 813 - return -EINVAL; 814 - } 815 - 816 763 static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) 817 764 { 818 765 struct i2c_client *client = v4l2_get_subdevdata(sd); 819 766 struct adv7842_state *state = to_state(sd); 820 - const u8 *val = state->hdmi_edid.edid; 821 - int spa_loc = edid_spa_location(val); 767 + const u8 *edid = state->hdmi_edid.edid; 768 + int spa_loc; 769 + u16 pa; 822 770 int err = 0; 823 771 int i; 824 772 825 - v4l2_dbg(2, debug, sd, "%s: write EDID on port %c (spa at 0x%x)\n", 826 - __func__, (port == ADV7842_EDID_PORT_A) ? 'A' : 'B', spa_loc); 773 + v4l2_dbg(2, debug, sd, "%s: write EDID on port %c\n", 774 + __func__, (port == ADV7842_EDID_PORT_A) ? 'A' : 'B'); 827 775 828 776 /* HPA disable on port A and B */ 829 777 io_write_and_or(sd, 0x20, 0xcf, 0x00); ··· 802 814 if (!state->hdmi_edid.present) 803 815 return 0; 804 816 817 + pa = cec_get_edid_phys_addr(edid, 256, &spa_loc); 818 + err = cec_phys_addr_validate(pa, &pa, NULL); 819 + if (err) 820 + return err; 821 + 822 + /* 823 + * Return an error if no location of the source physical address 824 + * was found. 825 + */ 826 + if (spa_loc == 0) 827 + return -EINVAL; 828 + 805 829 /* edid segment pointer '0' for HDMI ports */ 806 830 rep_write_and_or(sd, 0x77, 0xef, 0x00); 807 831 808 832 for (i = 0; !err && i < 256; i += I2C_SMBUS_BLOCK_MAX) 809 833 err = adv_smbus_write_i2c_block_data(state->i2c_edid, i, 810 - I2C_SMBUS_BLOCK_MAX, val + i); 834 + I2C_SMBUS_BLOCK_MAX, edid + i); 811 835 if (err) 812 836 return err; 813 837 814 - if (spa_loc < 0) 815 - spa_loc = 0xc0; /* Default value [REF_02, p. 199] */ 816 - 817 838 if (port == ADV7842_EDID_PORT_A) { 818 - rep_write(sd, 0x72, val[spa_loc]); 819 - rep_write(sd, 0x73, val[spa_loc + 1]); 839 + rep_write(sd, 0x72, edid[spa_loc]); 840 + rep_write(sd, 0x73, edid[spa_loc + 1]); 820 841 } else { 821 - rep_write(sd, 0x74, val[spa_loc]); 822 - rep_write(sd, 0x75, val[spa_loc + 1]); 842 + rep_write(sd, 0x74, edid[spa_loc]); 843 + rep_write(sd, 0x75, edid[spa_loc + 1]); 823 844 } 824 845 rep_write(sd, 0x76, spa_loc & 0xff); 825 846 rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40); ··· 848 851 (port == ADV7842_EDID_PORT_A) ? 'A' : 'B'); 849 852 return -EIO; 850 853 } 854 + cec_s_phys_addr(state->cec_adap, pa, false); 851 855 852 856 /* enable hotplug after 200 ms */ 853 857 schedule_delayed_work(&state->delayed_work_enable_hotplug, HZ / 5); ··· 978 980 static int adv7842_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) 979 981 { 980 982 struct adv7842_state *state = to_state(sd); 981 - int prev = v4l2_ctrl_g_ctrl(state->detect_tx_5v_ctrl); 982 - u8 reg_io_6f = io_read(sd, 0x6f); 983 - int val = 0; 983 + u16 cable_det = adv7842_read_cable_det(sd); 984 984 985 - if (reg_io_6f & 0x02) 986 - val |= 1; /* port A */ 987 - if (reg_io_6f & 0x01) 988 - val |= 2; /* port B */ 985 + v4l2_dbg(1, debug, sd, "%s: 0x%x\n", __func__, cable_det); 989 986 990 - v4l2_dbg(1, debug, sd, "%s: 0x%x -> 0x%x\n", __func__, prev, val); 991 - 992 - if (val != prev) 993 - return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, val); 994 - return 0; 987 + return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, cable_det); 995 988 } 996 989 997 990 static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, ··· 2156 2167 } 2157 2168 } 2158 2169 2170 + #if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC) 2171 + static void adv7842_cec_tx_raw_status(struct v4l2_subdev *sd, u8 tx_raw_status) 2172 + { 2173 + struct adv7842_state *state = to_state(sd); 2174 + 2175 + if ((cec_read(sd, 0x11) & 0x01) == 0) { 2176 + v4l2_dbg(1, debug, sd, "%s: tx raw: tx disabled\n", __func__); 2177 + return; 2178 + } 2179 + 2180 + if (tx_raw_status & 0x02) { 2181 + v4l2_dbg(1, debug, sd, "%s: tx raw: arbitration lost\n", 2182 + __func__); 2183 + cec_transmit_done(state->cec_adap, CEC_TX_STATUS_ARB_LOST, 2184 + 1, 0, 0, 0); 2185 + return; 2186 + } 2187 + if (tx_raw_status & 0x04) { 2188 + u8 status; 2189 + u8 nack_cnt; 2190 + u8 low_drive_cnt; 2191 + 2192 + v4l2_dbg(1, debug, sd, "%s: tx raw: retry failed\n", __func__); 2193 + /* 2194 + * We set this status bit since this hardware performs 2195 + * retransmissions. 2196 + */ 2197 + status = CEC_TX_STATUS_MAX_RETRIES; 2198 + nack_cnt = cec_read(sd, 0x14) & 0xf; 2199 + if (nack_cnt) 2200 + status |= CEC_TX_STATUS_NACK; 2201 + low_drive_cnt = cec_read(sd, 0x14) >> 4; 2202 + if (low_drive_cnt) 2203 + status |= CEC_TX_STATUS_LOW_DRIVE; 2204 + cec_transmit_done(state->cec_adap, status, 2205 + 0, nack_cnt, low_drive_cnt, 0); 2206 + return; 2207 + } 2208 + if (tx_raw_status & 0x01) { 2209 + v4l2_dbg(1, debug, sd, "%s: tx raw: ready ok\n", __func__); 2210 + cec_transmit_done(state->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); 2211 + return; 2212 + } 2213 + } 2214 + 2215 + static void adv7842_cec_isr(struct v4l2_subdev *sd, bool *handled) 2216 + { 2217 + u8 cec_irq; 2218 + 2219 + /* cec controller */ 2220 + cec_irq = io_read(sd, 0x93) & 0x0f; 2221 + if (!cec_irq) 2222 + return; 2223 + 2224 + v4l2_dbg(1, debug, sd, "%s: cec: irq 0x%x\n", __func__, cec_irq); 2225 + adv7842_cec_tx_raw_status(sd, cec_irq); 2226 + if (cec_irq & 0x08) { 2227 + struct adv7842_state *state = to_state(sd); 2228 + struct cec_msg msg; 2229 + 2230 + msg.len = cec_read(sd, 0x25) & 0x1f; 2231 + if (msg.len > 16) 2232 + msg.len = 16; 2233 + 2234 + if (msg.len) { 2235 + u8 i; 2236 + 2237 + for (i = 0; i < msg.len; i++) 2238 + msg.msg[i] = cec_read(sd, i + 0x15); 2239 + cec_write(sd, 0x26, 0x01); /* re-enable rx */ 2240 + cec_received_msg(state->cec_adap, &msg); 2241 + } 2242 + } 2243 + 2244 + io_write(sd, 0x94, cec_irq); 2245 + 2246 + if (handled) 2247 + *handled = true; 2248 + } 2249 + 2250 + static int adv7842_cec_adap_enable(struct cec_adapter *adap, bool enable) 2251 + { 2252 + struct adv7842_state *state = adap->priv; 2253 + struct v4l2_subdev *sd = &state->sd; 2254 + 2255 + if (!state->cec_enabled_adap && enable) { 2256 + cec_write_clr_set(sd, 0x2a, 0x01, 0x01); /* power up cec */ 2257 + cec_write(sd, 0x2c, 0x01); /* cec soft reset */ 2258 + cec_write_clr_set(sd, 0x11, 0x01, 0); /* initially disable tx */ 2259 + /* enabled irqs: */ 2260 + /* tx: ready */ 2261 + /* tx: arbitration lost */ 2262 + /* tx: retry timeout */ 2263 + /* rx: ready */ 2264 + io_write_clr_set(sd, 0x96, 0x0f, 0x0f); 2265 + cec_write(sd, 0x26, 0x01); /* enable rx */ 2266 + } else if (state->cec_enabled_adap && !enable) { 2267 + /* disable cec interrupts */ 2268 + io_write_clr_set(sd, 0x96, 0x0f, 0x00); 2269 + /* disable address mask 1-3 */ 2270 + cec_write_clr_set(sd, 0x27, 0x70, 0x00); 2271 + /* power down cec section */ 2272 + cec_write_clr_set(sd, 0x2a, 0x01, 0x00); 2273 + state->cec_valid_addrs = 0; 2274 + } 2275 + state->cec_enabled_adap = enable; 2276 + return 0; 2277 + } 2278 + 2279 + static int adv7842_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) 2280 + { 2281 + struct adv7842_state *state = adap->priv; 2282 + struct v4l2_subdev *sd = &state->sd; 2283 + unsigned int i, free_idx = ADV7842_MAX_ADDRS; 2284 + 2285 + if (!state->cec_enabled_adap) 2286 + return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO; 2287 + 2288 + if (addr == CEC_LOG_ADDR_INVALID) { 2289 + cec_write_clr_set(sd, 0x27, 0x70, 0); 2290 + state->cec_valid_addrs = 0; 2291 + return 0; 2292 + } 2293 + 2294 + for (i = 0; i < ADV7842_MAX_ADDRS; i++) { 2295 + bool is_valid = state->cec_valid_addrs & (1 << i); 2296 + 2297 + if (free_idx == ADV7842_MAX_ADDRS && !is_valid) 2298 + free_idx = i; 2299 + if (is_valid && state->cec_addr[i] == addr) 2300 + return 0; 2301 + } 2302 + if (i == ADV7842_MAX_ADDRS) { 2303 + i = free_idx; 2304 + if (i == ADV7842_MAX_ADDRS) 2305 + return -ENXIO; 2306 + } 2307 + state->cec_addr[i] = addr; 2308 + state->cec_valid_addrs |= 1 << i; 2309 + 2310 + switch (i) { 2311 + case 0: 2312 + /* enable address mask 0 */ 2313 + cec_write_clr_set(sd, 0x27, 0x10, 0x10); 2314 + /* set address for mask 0 */ 2315 + cec_write_clr_set(sd, 0x28, 0x0f, addr); 2316 + break; 2317 + case 1: 2318 + /* enable address mask 1 */ 2319 + cec_write_clr_set(sd, 0x27, 0x20, 0x20); 2320 + /* set address for mask 1 */ 2321 + cec_write_clr_set(sd, 0x28, 0xf0, addr << 4); 2322 + break; 2323 + case 2: 2324 + /* enable address mask 2 */ 2325 + cec_write_clr_set(sd, 0x27, 0x40, 0x40); 2326 + /* set address for mask 1 */ 2327 + cec_write_clr_set(sd, 0x29, 0x0f, addr); 2328 + break; 2329 + } 2330 + return 0; 2331 + } 2332 + 2333 + static int adv7842_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, 2334 + u32 signal_free_time, struct cec_msg *msg) 2335 + { 2336 + struct adv7842_state *state = adap->priv; 2337 + struct v4l2_subdev *sd = &state->sd; 2338 + u8 len = msg->len; 2339 + unsigned int i; 2340 + 2341 + /* 2342 + * The number of retries is the number of attempts - 1, but retry 2343 + * at least once. It's not clear if a value of 0 is allowed, so 2344 + * let's do at least one retry. 2345 + */ 2346 + cec_write_clr_set(sd, 0x12, 0x70, max(1, attempts - 1) << 4); 2347 + 2348 + if (len > 16) { 2349 + v4l2_err(sd, "%s: len exceeded 16 (%d)\n", __func__, len); 2350 + return -EINVAL; 2351 + } 2352 + 2353 + /* write data */ 2354 + for (i = 0; i < len; i++) 2355 + cec_write(sd, i, msg->msg[i]); 2356 + 2357 + /* set length (data + header) */ 2358 + cec_write(sd, 0x10, len); 2359 + /* start transmit, enable tx */ 2360 + cec_write(sd, 0x11, 0x01); 2361 + return 0; 2362 + } 2363 + 2364 + static const struct cec_adap_ops adv7842_cec_adap_ops = { 2365 + .adap_enable = adv7842_cec_adap_enable, 2366 + .adap_log_addr = adv7842_cec_adap_log_addr, 2367 + .adap_transmit = adv7842_cec_adap_transmit, 2368 + }; 2369 + #endif 2370 + 2159 2371 static int adv7842_isr(struct v4l2_subdev *sd, u32 status, bool *handled) 2160 2372 { 2161 2373 struct adv7842_state *state = to_state(sd); ··· 2427 2237 if (handled) 2428 2238 *handled = true; 2429 2239 } 2240 + 2241 + #if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC) 2242 + /* cec */ 2243 + adv7842_cec_isr(sd, handled); 2244 + #endif 2430 2245 2431 2246 /* tx 5v detect */ 2432 2247 if (irq_status[2] & 0x3) { ··· 2513 2318 case ADV7842_EDID_PORT_A: 2514 2319 case ADV7842_EDID_PORT_B: 2515 2320 memset(&state->hdmi_edid.edid, 0, 256); 2516 - if (e->blocks) 2321 + if (e->blocks) { 2517 2322 state->hdmi_edid.present |= 0x04 << e->pad; 2518 - else 2323 + } else { 2519 2324 state->hdmi_edid.present &= ~(0x04 << e->pad); 2325 + adv7842_s_detect_tx_5v_ctrl(sd); 2326 + } 2520 2327 memcpy(&state->hdmi_edid.edid, e->edid, 128 * e->blocks); 2521 2328 err = edid_write_hdmi_segment(sd, e->pad); 2522 2329 break; ··· 2706 2509 v4l2_info(sd, "HPD A %s, B %s\n", 2707 2510 reg_io_0x21 & 0x02 ? "enabled" : "disabled", 2708 2511 reg_io_0x21 & 0x01 ? "enabled" : "disabled"); 2709 - v4l2_info(sd, "CEC %s\n", !!(cec_read(sd, 0x2a) & 0x01) ? 2512 + v4l2_info(sd, "CEC: %s\n", state->cec_enabled_adap ? 2710 2513 "enabled" : "disabled"); 2514 + if (state->cec_enabled_adap) { 2515 + int i; 2516 + 2517 + for (i = 0; i < ADV7842_MAX_ADDRS; i++) { 2518 + bool is_valid = state->cec_valid_addrs & (1 << i); 2519 + 2520 + if (is_valid) 2521 + v4l2_info(sd, "CEC Logical Address: 0x%x\n", 2522 + state->cec_addr[i]); 2523 + } 2524 + } 2711 2525 2712 2526 v4l2_info(sd, "-----Signal status-----\n"); 2713 2527 if (state->hdmi_port_a) { ··· 3239 3031 } 3240 3032 } 3241 3033 3034 + static int adv7842_registered(struct v4l2_subdev *sd) 3035 + { 3036 + struct adv7842_state *state = to_state(sd); 3037 + int err; 3038 + 3039 + err = cec_register_adapter(state->cec_adap); 3040 + if (err) 3041 + cec_delete_adapter(state->cec_adap); 3042 + return err; 3043 + } 3044 + 3045 + static void adv7842_unregistered(struct v4l2_subdev *sd) 3046 + { 3047 + struct adv7842_state *state = to_state(sd); 3048 + 3049 + cec_unregister_adapter(state->cec_adap); 3050 + } 3051 + 3242 3052 /* ----------------------------------------------------------------------- */ 3243 3053 3244 3054 static const struct v4l2_ctrl_ops adv7842_ctrl_ops = { ··· 3301 3075 .core = &adv7842_core_ops, 3302 3076 .video = &adv7842_video_ops, 3303 3077 .pad = &adv7842_pad_ops, 3078 + }; 3079 + 3080 + static const struct v4l2_subdev_internal_ops adv7842_int_ops = { 3081 + .registered = adv7842_registered, 3082 + .unregistered = adv7842_unregistered, 3304 3083 }; 3305 3084 3306 3085 /* -------------------------- custom ctrls ---------------------------------- */ ··· 3472 3241 sd = &state->sd; 3473 3242 v4l2_i2c_subdev_init(sd, client, &adv7842_ops); 3474 3243 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; 3244 + sd->internal_ops = &adv7842_int_ops; 3475 3245 state->mode = pdata->mode; 3476 3246 3477 3247 state->hdmi_port_a = pdata->input == ADV7842_SELECT_HDMI_PORT_A; ··· 3556 3324 if (err) 3557 3325 goto err_entity; 3558 3326 3327 + #if IS_ENABLED(CONFIG_VIDEO_ADV7842_CEC) 3328 + state->cec_adap = cec_allocate_adapter(&adv7842_cec_adap_ops, 3329 + state, dev_name(&client->dev), 3330 + CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | 3331 + CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV7842_MAX_ADDRS, 3332 + &client->dev); 3333 + err = PTR_ERR_OR_ZERO(state->cec_adap); 3334 + if (err) 3335 + goto err_entity; 3336 + #endif 3337 + 3559 3338 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, 3560 3339 client->addr << 1, client->adapter->name); 3561 3340 return 0; ··· 3590 3347 struct adv7842_state *state = to_state(sd); 3591 3348 3592 3349 adv7842_irq_enable(sd, false); 3593 - 3594 3350 cancel_delayed_work(&state->delayed_work_enable_hotplug); 3595 3351 v4l2_device_unregister_subdev(sd); 3596 3352 media_entity_cleanup(&sd->entity);
+8
drivers/media/platform/vivid/Kconfig
··· 6 6 select FB_CFB_FILLRECT 7 7 select FB_CFB_COPYAREA 8 8 select FB_CFB_IMAGEBLIT 9 + select MEDIA_CEC_EDID 9 10 select VIDEOBUF2_VMALLOC 10 11 select VIDEO_V4L2_TPG 11 12 default n ··· 22 21 23 22 Say Y here if you want to test video apps or debug V4L devices. 24 23 When in doubt, say N. 24 + 25 + config VIDEO_VIVID_CEC 26 + bool "Enable CEC emulation support" 27 + depends on VIDEO_VIVID && MEDIA_CEC 28 + ---help--- 29 + When selected the vivid module will emulate the optional 30 + HDMI CEC feature. 25 31 26 32 config VIDEO_VIVID_MAX_DEVS 27 33 int "Maximum number of devices"
+4
drivers/media/platform/vivid/Makefile
··· 3 3 vivid-radio-rx.o vivid-radio-tx.o vivid-radio-common.o \ 4 4 vivid-rds-gen.o vivid-sdr-cap.o vivid-vbi-cap.o vivid-vbi-out.o \ 5 5 vivid-osd.o 6 + ifeq ($(CONFIG_VIDEO_VIVID_CEC),y) 7 + vivid-objs += vivid-cec.o 8 + endif 9 + 6 10 obj-$(CONFIG_VIDEO_VIVID) += vivid.o
+255
drivers/media/platform/vivid/vivid-cec.c
··· 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 + }
+33
drivers/media/platform/vivid/vivid-cec.h
··· 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
+109 -9
drivers/media/platform/vivid/vivid-core.c
··· 46 46 #include "vivid-vbi-cap.h" 47 47 #include "vivid-vbi-out.h" 48 48 #include "vivid-osd.h" 49 + #include "vivid-cec.h" 49 50 #include "vivid-ctrls.h" 50 51 51 52 #define VIVID_MODULE_NAME "vivid" ··· 685 684 dev->input_name_counter[i] = in_type_counter[dev->input_type[i]]++; 686 685 } 687 686 dev->has_audio_inputs = in_type_counter[TV] && in_type_counter[SVID]; 687 + if (in_type_counter[HDMI] == 16) { 688 + /* The CEC physical address only allows for max 15 inputs */ 689 + in_type_counter[HDMI]--; 690 + dev->num_inputs--; 691 + } 688 692 689 693 /* how many outputs do we have and of what type? */ 690 694 dev->num_outputs = num_outputs[inst]; ··· 702 696 dev->output_name_counter[i] = out_type_counter[dev->output_type[i]]++; 703 697 } 704 698 dev->has_audio_outputs = out_type_counter[SVID]; 699 + if (out_type_counter[HDMI] == 16) { 700 + /* 701 + * The CEC physical address only allows for max 15 inputs, 702 + * so outputs are also limited to 15 to allow for easy 703 + * CEC output to input mapping. 704 + */ 705 + out_type_counter[HDMI]--; 706 + dev->num_outputs--; 707 + } 705 708 706 709 /* do we create a video capture device? */ 707 710 dev->has_vid_cap = node_type & 0x0001; ··· 1025 1010 INIT_LIST_HEAD(&dev->vbi_out_active); 1026 1011 INIT_LIST_HEAD(&dev->sdr_cap_active); 1027 1012 1013 + INIT_LIST_HEAD(&dev->cec_work_list); 1014 + spin_lock_init(&dev->cec_slock); 1015 + /* 1016 + * Same as create_singlethread_workqueue, but now I can use the 1017 + * string formatting of alloc_ordered_workqueue. 1018 + */ 1019 + dev->cec_workqueue = 1020 + alloc_ordered_workqueue("vivid-%03d-cec", WQ_MEM_RECLAIM, inst); 1021 + if (!dev->cec_workqueue) 1022 + goto unreg_dev; 1023 + 1028 1024 /* start creating the vb2 queues */ 1029 1025 if (dev->has_vid_cap) { 1030 1026 /* initialize vid_cap queue */ ··· 1143 1117 /* finally start creating the device nodes */ 1144 1118 if (dev->has_vid_cap) { 1145 1119 vfd = &dev->vid_cap_dev; 1146 - strlcpy(vfd->name, "vivid-vid-cap", sizeof(vfd->name)); 1120 + snprintf(vfd->name, sizeof(vfd->name), 1121 + "vivid-%03d-vid-cap", inst); 1147 1122 vfd->fops = &vivid_fops; 1148 1123 vfd->ioctl_ops = &vivid_ioctl_ops; 1149 1124 vfd->device_caps = dev->vid_cap_caps; ··· 1160 1133 vfd->lock = &dev->mutex; 1161 1134 video_set_drvdata(vfd, dev); 1162 1135 1136 + #ifdef CONFIG_VIDEO_VIVID_CEC 1137 + if (in_type_counter[HDMI]) { 1138 + struct cec_adapter *adap; 1139 + 1140 + adap = vivid_cec_alloc_adap(dev, 0, &pdev->dev, false); 1141 + ret = PTR_ERR_OR_ZERO(adap); 1142 + if (ret < 0) 1143 + goto unreg_dev; 1144 + dev->cec_rx_adap = adap; 1145 + ret = cec_register_adapter(adap); 1146 + if (ret < 0) { 1147 + cec_delete_adapter(adap); 1148 + dev->cec_rx_adap = NULL; 1149 + goto unreg_dev; 1150 + } 1151 + cec_s_phys_addr(adap, 0, false); 1152 + v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI input %d\n", 1153 + dev_name(&adap->devnode.dev), i); 1154 + } 1155 + #endif 1156 + 1163 1157 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]); 1164 1158 if (ret < 0) 1165 1159 goto unreg_dev; ··· 1189 1141 } 1190 1142 1191 1143 if (dev->has_vid_out) { 1144 + #ifdef CONFIG_VIDEO_VIVID_CEC 1145 + unsigned int bus_cnt = 0; 1146 + #endif 1147 + 1192 1148 vfd = &dev->vid_out_dev; 1193 - strlcpy(vfd->name, "vivid-vid-out", sizeof(vfd->name)); 1149 + snprintf(vfd->name, sizeof(vfd->name), 1150 + "vivid-%03d-vid-out", inst); 1194 1151 vfd->vfl_dir = VFL_DIR_TX; 1195 1152 vfd->fops = &vivid_fops; 1196 1153 vfd->ioctl_ops = &vivid_ioctl_ops; ··· 1212 1159 vfd->lock = &dev->mutex; 1213 1160 video_set_drvdata(vfd, dev); 1214 1161 1162 + #ifdef CONFIG_VIDEO_VIVID_CEC 1163 + for (i = 0; i < dev->num_outputs; i++) { 1164 + struct cec_adapter *adap; 1165 + 1166 + if (dev->output_type[i] != HDMI) 1167 + continue; 1168 + dev->cec_output2bus_map[i] = bus_cnt; 1169 + adap = vivid_cec_alloc_adap(dev, bus_cnt, 1170 + &pdev->dev, true); 1171 + ret = PTR_ERR_OR_ZERO(adap); 1172 + if (ret < 0) 1173 + goto unreg_dev; 1174 + dev->cec_tx_adap[bus_cnt] = adap; 1175 + ret = cec_register_adapter(adap); 1176 + if (ret < 0) { 1177 + cec_delete_adapter(adap); 1178 + dev->cec_tx_adap[bus_cnt] = NULL; 1179 + goto unreg_dev; 1180 + } 1181 + bus_cnt++; 1182 + if (bus_cnt <= in_type_counter[HDMI]) 1183 + cec_s_phys_addr(adap, bus_cnt << 12, false); 1184 + else 1185 + cec_s_phys_addr(adap, 0x1000, false); 1186 + v4l2_info(&dev->v4l2_dev, "CEC adapter %s registered for HDMI output %d\n", 1187 + dev_name(&adap->devnode.dev), i); 1188 + } 1189 + #endif 1190 + 1215 1191 ret = video_register_device(vfd, VFL_TYPE_GRABBER, vid_out_nr[inst]); 1216 1192 if (ret < 0) 1217 1193 goto unreg_dev; ··· 1250 1168 1251 1169 if (dev->has_vbi_cap) { 1252 1170 vfd = &dev->vbi_cap_dev; 1253 - strlcpy(vfd->name, "vivid-vbi-cap", sizeof(vfd->name)); 1171 + snprintf(vfd->name, sizeof(vfd->name), 1172 + "vivid-%03d-vbi-cap", inst); 1254 1173 vfd->fops = &vivid_fops; 1255 1174 vfd->ioctl_ops = &vivid_ioctl_ops; 1256 1175 vfd->device_caps = dev->vbi_cap_caps; ··· 1274 1191 1275 1192 if (dev->has_vbi_out) { 1276 1193 vfd = &dev->vbi_out_dev; 1277 - strlcpy(vfd->name, "vivid-vbi-out", sizeof(vfd->name)); 1194 + snprintf(vfd->name, sizeof(vfd->name), 1195 + "vivid-%03d-vbi-out", inst); 1278 1196 vfd->vfl_dir = VFL_DIR_TX; 1279 1197 vfd->fops = &vivid_fops; 1280 1198 vfd->ioctl_ops = &vivid_ioctl_ops; ··· 1299 1215 1300 1216 if (dev->has_sdr_cap) { 1301 1217 vfd = &dev->sdr_cap_dev; 1302 - strlcpy(vfd->name, "vivid-sdr-cap", sizeof(vfd->name)); 1218 + snprintf(vfd->name, sizeof(vfd->name), 1219 + "vivid-%03d-sdr-cap", inst); 1303 1220 vfd->fops = &vivid_fops; 1304 1221 vfd->ioctl_ops = &vivid_ioctl_ops; 1305 1222 vfd->device_caps = dev->sdr_cap_caps; ··· 1319 1234 1320 1235 if (dev->has_radio_rx) { 1321 1236 vfd = &dev->radio_rx_dev; 1322 - strlcpy(vfd->name, "vivid-rad-rx", sizeof(vfd->name)); 1237 + snprintf(vfd->name, sizeof(vfd->name), 1238 + "vivid-%03d-rad-rx", inst); 1323 1239 vfd->fops = &vivid_radio_fops; 1324 1240 vfd->ioctl_ops = &vivid_ioctl_ops; 1325 1241 vfd->device_caps = dev->radio_rx_caps; ··· 1338 1252 1339 1253 if (dev->has_radio_tx) { 1340 1254 vfd = &dev->radio_tx_dev; 1341 - strlcpy(vfd->name, "vivid-rad-tx", sizeof(vfd->name)); 1255 + snprintf(vfd->name, sizeof(vfd->name), 1256 + "vivid-%03d-rad-tx", inst); 1342 1257 vfd->vfl_dir = VFL_DIR_TX; 1343 1258 vfd->fops = &vivid_radio_fops; 1344 1259 vfd->ioctl_ops = &vivid_ioctl_ops; ··· 1369 1282 video_unregister_device(&dev->vbi_cap_dev); 1370 1283 video_unregister_device(&dev->vid_out_dev); 1371 1284 video_unregister_device(&dev->vid_cap_dev); 1285 + cec_unregister_adapter(dev->cec_rx_adap); 1286 + for (i = 0; i < MAX_OUTPUTS; i++) 1287 + cec_unregister_adapter(dev->cec_tx_adap[i]); 1288 + if (dev->cec_workqueue) { 1289 + vivid_cec_bus_free_work(dev); 1290 + destroy_workqueue(dev->cec_workqueue); 1291 + } 1372 1292 free_dev: 1373 1293 v4l2_device_put(&dev->v4l2_dev); 1374 1294 return ret; ··· 1425 1331 static int vivid_remove(struct platform_device *pdev) 1426 1332 { 1427 1333 struct vivid_dev *dev; 1428 - unsigned i; 1429 - 1334 + unsigned int i, j; 1430 1335 1431 1336 for (i = 0; i < n_devs; i++) { 1432 1337 dev = vivid_devs[i]; ··· 1472 1379 dev->fb_info.node); 1473 1380 unregister_framebuffer(&dev->fb_info); 1474 1381 vivid_fb_release_buffers(dev); 1382 + } 1383 + cec_unregister_adapter(dev->cec_rx_adap); 1384 + for (j = 0; j < MAX_OUTPUTS; j++) 1385 + cec_unregister_adapter(dev->cec_tx_adap[j]); 1386 + if (dev->cec_workqueue) { 1387 + vivid_cec_bus_free_work(dev); 1388 + destroy_workqueue(dev->cec_workqueue); 1475 1389 } 1476 1390 v4l2_device_put(&dev->v4l2_dev); 1477 1391 vivid_devs[i] = NULL;
+27
drivers/media/platform/vivid/vivid-core.h
··· 21 21 #define _VIVID_CORE_H_ 22 22 23 23 #include <linux/fb.h> 24 + #include <linux/workqueue.h> 25 + #include <media/cec.h> 24 26 #include <media/videobuf2-v4l2.h> 25 27 #include <media/v4l2-device.h> 26 28 #include <media/v4l2-dev.h> ··· 133 131 134 132 #define VIVID_INVALID_SIGNAL(mode) \ 135 133 ((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE) 134 + 135 + struct vivid_cec_work { 136 + struct list_head list; 137 + struct delayed_work work; 138 + struct cec_adapter *adap; 139 + struct vivid_dev *dev; 140 + unsigned int usecs; 141 + unsigned int timeout_ms; 142 + u8 tx_status; 143 + struct cec_msg msg; 144 + }; 136 145 137 146 struct vivid_dev { 138 147 unsigned inst; ··· 510 497 /* Shared between radio receiver and transmitter */ 511 498 bool radio_rds_loop; 512 499 struct timespec radio_rds_init_ts; 500 + 501 + /* CEC */ 502 + struct cec_adapter *cec_rx_adap; 503 + struct cec_adapter *cec_tx_adap[MAX_OUTPUTS]; 504 + struct workqueue_struct *cec_workqueue; 505 + spinlock_t cec_slock; 506 + struct list_head cec_work_list; 507 + unsigned int cec_xfer_time_jiffies; 508 + unsigned long cec_xfer_start_jiffies; 509 + u8 cec_output2bus_map[MAX_OUTPUTS]; 510 + 511 + /* CEC OSD String */ 512 + char osd[14]; 513 + unsigned long osd_jiffies; 513 514 }; 514 515 515 516 static inline bool vivid_is_webcam(const struct vivid_dev *dev)
+13
drivers/media/platform/vivid/vivid-kthread-cap.c
··· 552 552 snprintf(str, sizeof(str), " button pressed!"); 553 553 tpg_gen_text(tpg, basep, line++ * line_height, 16, str); 554 554 } 555 + if (dev->osd[0]) { 556 + if (vivid_is_hdmi_cap(dev)) { 557 + snprintf(str, sizeof(str), 558 + " OSD \"%s\"", dev->osd); 559 + tpg_gen_text(tpg, basep, line++ * line_height, 560 + 16, str); 561 + } 562 + if (dev->osd_jiffies && 563 + time_is_before_jiffies(dev->osd_jiffies + 5 * HZ)) { 564 + dev->osd[0] = 0; 565 + dev->osd_jiffies = 0; 566 + } 567 + } 555 568 } 556 569 557 570 /*
+22 -1
drivers/media/platform/vivid/vivid-vid-cap.c
··· 1695 1695 struct v4l2_edid *edid) 1696 1696 { 1697 1697 struct vivid_dev *dev = video_drvdata(file); 1698 + u16 phys_addr; 1699 + unsigned int i; 1700 + int ret; 1698 1701 1699 1702 memset(edid->reserved, 0, sizeof(edid->reserved)); 1700 1703 if (edid->pad >= dev->num_inputs) ··· 1706 1703 return -EINVAL; 1707 1704 if (edid->blocks == 0) { 1708 1705 dev->edid_blocks = 0; 1709 - return 0; 1706 + phys_addr = CEC_PHYS_ADDR_INVALID; 1707 + goto set_phys_addr; 1710 1708 } 1711 1709 if (edid->blocks > dev->edid_max_blocks) { 1712 1710 edid->blocks = dev->edid_max_blocks; 1713 1711 return -E2BIG; 1714 1712 } 1713 + phys_addr = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL); 1714 + ret = cec_phys_addr_validate(phys_addr, &phys_addr, NULL); 1715 + if (ret) 1716 + return ret; 1717 + 1718 + if (vb2_is_busy(&dev->vb_vid_cap_q)) 1719 + return -EBUSY; 1720 + 1715 1721 dev->edid_blocks = edid->blocks; 1716 1722 memcpy(dev->edid, edid->edid, edid->blocks * 128); 1723 + 1724 + set_phys_addr: 1725 + /* TODO: a proper hotplug detect cycle should be emulated here */ 1726 + cec_s_phys_addr(dev->cec_rx_adap, phys_addr, false); 1727 + 1728 + for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) 1729 + cec_s_phys_addr(dev->cec_tx_adap[i], 1730 + cec_phys_addr_for_input(phys_addr, i + 1), 1731 + false); 1717 1732 return 0; 1718 1733 } 1719 1734
+7
drivers/media/platform/vivid/vivid-vid-common.c
··· 811 811 { 812 812 struct vivid_dev *dev = video_drvdata(file); 813 813 struct video_device *vdev = video_devdata(file); 814 + struct cec_adapter *adap; 814 815 815 816 memset(edid->reserved, 0, sizeof(edid->reserved)); 816 817 if (vdev->vfl_dir == VFL_DIR_RX) { ··· 819 818 return -EINVAL; 820 819 if (dev->input_type[edid->pad] != HDMI) 821 820 return -EINVAL; 821 + adap = dev->cec_rx_adap; 822 822 } else { 823 + unsigned int bus_idx; 824 + 823 825 if (edid->pad >= dev->num_outputs) 824 826 return -EINVAL; 825 827 if (dev->output_type[edid->pad] != HDMI) 826 828 return -EINVAL; 829 + bus_idx = dev->cec_output2bus_map[edid->pad]; 830 + adap = dev->cec_tx_adap[bus_idx]; 827 831 } 828 832 if (edid->start_block == 0 && edid->blocks == 0) { 829 833 edid->blocks = dev->edid_blocks; ··· 841 835 if (edid->start_block + edid->blocks > dev->edid_blocks) 842 836 edid->blocks = dev->edid_blocks - edid->start_block; 843 837 memcpy(edid->edid, dev->edid, edid->blocks * 128); 838 + cec_set_edid_phys_addr(edid->edid, edid->blocks * 128, adap->phys_addr); 844 839 return 0; 845 840 }
+1
drivers/media/rc/rc-main.c
··· 810 810 { RC_BIT_SHARP, "sharp", "ir-sharp-decoder" }, 811 811 { RC_BIT_MCE_KBD, "mce_kbd", "ir-mce_kbd-decoder" }, 812 812 { RC_BIT_XMP, "xmp", "ir-xmp-decoder" }, 813 + { RC_BIT_CEC, "cec", NULL }, 813 814 }; 814 815 815 816 /**
+4
drivers/staging/media/Kconfig
··· 21 21 # Please keep them in alphabetic order 22 22 source "drivers/staging/media/bcm2048/Kconfig" 23 23 24 + source "drivers/staging/media/cec/Kconfig" 25 + 24 26 source "drivers/staging/media/cxd2099/Kconfig" 25 27 26 28 source "drivers/staging/media/davinci_vpfe/Kconfig" ··· 30 28 source "drivers/staging/media/omap4iss/Kconfig" 31 29 32 30 source "drivers/staging/media/tw686x-kh/Kconfig" 31 + 32 + source "drivers/staging/media/s5p-cec/Kconfig" 33 33 34 34 # Keep LIRC at the end, as it has sub-menus 35 35 source "drivers/staging/media/lirc/Kconfig"
+2
drivers/staging/media/Makefile
··· 1 1 obj-$(CONFIG_I2C_BCM2048) += bcm2048/ 2 + obj-$(CONFIG_MEDIA_CEC) += cec/ 3 + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec/ 2 4 obj-$(CONFIG_DVB_CXD2099) += cxd2099/ 3 5 obj-$(CONFIG_LIRC_STAGING) += lirc/ 4 6 obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
+14
drivers/staging/media/cec/Kconfig
··· 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.
+3
drivers/staging/media/cec/Makefile
··· 1 + cec-objs := cec-core.o cec-adap.o cec-api.o 2 + 3 + obj-$(CONFIG_MEDIA_CEC) += cec.o
+27
drivers/staging/media/cec/TODO
··· 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>
+1627
drivers/staging/media/cec/cec-adap.c
··· 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
+578
drivers/staging/media/cec/cec-api.c
··· 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 + };
+409
drivers/staging/media/cec/cec-core.c
··· 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");
+56
drivers/staging/media/cec/cec-priv.h
··· 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
+9
drivers/staging/media/s5p-cec/Kconfig
··· 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 +
+2
drivers/staging/media/s5p-cec/Makefile
··· 1 + obj-$(CONFIG_VIDEO_SAMSUNG_S5P_CEC) += s5p-cec.o 2 + s5p-cec-y += s5p_cec.o exynos_hdmi_cecctrl.o
+3
drivers/staging/media/s5p-cec/TODO
··· 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.
+38
drivers/staging/media/s5p-cec/exynos_hdmi_cec.h
··· 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_ */
+209
drivers/staging/media/s5p-cec/exynos_hdmi_cecctrl.c
··· 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 + }
+96
drivers/staging/media/s5p-cec/regs-cec.h
··· 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 */
+294
drivers/staging/media/s5p-cec/s5p_cec.c
··· 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");
+76
drivers/staging/media/s5p-cec/s5p_cec.h
··· 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_ */
+12
fs/compat_ioctl.c
··· 57 57 #include <linux/i2c-dev.h> 58 58 #include <linux/atalk.h> 59 59 #include <linux/gfp.h> 60 + #include <linux/cec.h> 60 61 61 62 #include "internal.h" 62 63 ··· 1378 1377 COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES) 1379 1378 COMPATIBLE_IOCTL(VIDEO_GET_SIZE) 1380 1379 COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE) 1380 + /* cec */ 1381 + COMPATIBLE_IOCTL(CEC_ADAP_G_CAPS) 1382 + COMPATIBLE_IOCTL(CEC_ADAP_G_LOG_ADDRS) 1383 + COMPATIBLE_IOCTL(CEC_ADAP_S_LOG_ADDRS) 1384 + COMPATIBLE_IOCTL(CEC_ADAP_G_PHYS_ADDR) 1385 + COMPATIBLE_IOCTL(CEC_ADAP_S_PHYS_ADDR) 1386 + COMPATIBLE_IOCTL(CEC_G_MODE) 1387 + COMPATIBLE_IOCTL(CEC_S_MODE) 1388 + COMPATIBLE_IOCTL(CEC_TRANSMIT) 1389 + COMPATIBLE_IOCTL(CEC_RECEIVE) 1390 + COMPATIBLE_IOCTL(CEC_DQEVENT) 1381 1391 1382 1392 /* joystick */ 1383 1393 COMPATIBLE_IOCTL(JSIOCGVERSION)
+1881
include/linux/cec-funcs.h
··· 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
+993
include/linux/cec.h
··· 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
+104
include/media/cec-edid.h
··· 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 */
+232
include/media/cec.h
··· 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 */
+1 -5
include/media/i2c/adv7511.h
··· 32 32 struct adv7511_edid_detect { 33 33 int present; 34 34 int segment; 35 - }; 36 - 37 - struct adv7511_cec_arg { 38 - void *arg; 39 - u32 f_flags; 35 + uint16_t phys_addr; 40 36 }; 41 37 42 38 struct adv7511_platform_data {
+4 -1
include/media/rc-map.h
··· 31 31 RC_TYPE_RC6_MCE = 16, /* MCE (Philips RC6-6A-32 subtype) protocol */ 32 32 RC_TYPE_SHARP = 17, /* Sharp protocol */ 33 33 RC_TYPE_XMP = 18, /* XMP protocol */ 34 + RC_TYPE_CEC = 19, /* CEC protocol */ 34 35 }; 35 36 36 37 #define RC_BIT_NONE 0ULL ··· 54 53 #define RC_BIT_RC6_MCE (1ULL << RC_TYPE_RC6_MCE) 55 54 #define RC_BIT_SHARP (1ULL << RC_TYPE_SHARP) 56 55 #define RC_BIT_XMP (1ULL << RC_TYPE_XMP) 56 + #define RC_BIT_CEC (1ULL << RC_TYPE_CEC) 57 57 58 58 #define RC_BIT_ALL (RC_BIT_UNKNOWN | RC_BIT_OTHER | \ 59 59 RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ | \ ··· 63 61 RC_BIT_NEC | RC_BIT_SANYO | RC_BIT_MCE_KBD | \ 64 62 RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | \ 65 63 RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE | RC_BIT_SHARP | \ 66 - RC_BIT_XMP) 64 + RC_BIT_XMP | RC_BIT_CEC) 67 65 68 66 69 67 #define RC_SCANCODE_UNKNOWN(x) (x) ··· 125 123 #define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus" 126 124 #define RC_MAP_BEHOLD "rc-behold" 127 125 #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old" 126 + #define RC_MAP_CEC "rc-cec" 128 127 #define RC_MAP_CINERGY_1400 "rc-cinergy-1400" 129 128 #define RC_MAP_CINERGY "rc-cinergy" 130 129 #define RC_MAP_DELOCK_61959 "rc-delock-61959"