Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev into drm-next

rcar-du updates.

* 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev: (281 commits)
  drm: rcar-du: Add tri-planar memory formats support
  drm: rcar-du: Add probe deferral debug messages
  drm: rcar-du: lvds: Add R-Car Gen3 support
  drm: rcar-du: lvds: Rename PLLEN bit to PLLON
  drm: rcar-du: lvds: Fix PLL frequency-related configuration
  drm: rcar-du: lvds: Avoid duplication of clock clamp code
  drm: rcar-du: Add R8A7795 device support
  drm: rcar-du: Output the DISP signal on the ODDF pin
  drm: rcar-du: Output the DISP signal on the DISP pin
  drm: rcar-du: Support up to 4 CRTCs
  drm: rcar-du: Drop LVDS double dependency on OF
  drm: rcar-du: Enable compilation on ARM64
  drm: rcar-du: Fix compile warning on 64-bit platforms
  drm: rcar-du: Expose the VSP1 compositor through KMS planes
  drm: rcar-du: Move plane allocator to rcar_du_plane.c
  drm: rcar-du: Restart the DU group when a plane source changes
  drm: rcar-du: Add VSP1 compositor support
  drm: rcar-du: Add VSP1 support to the planes allocator
  drm: rcar-du: Refactor plane setup
  drm: rcar-du: Compute plane DDCR4 register value directly
  ...
This commit is contained in:
Dave Airlie 2016-02-25 10:30:59 +10:00
commit 0041ee4d36
342 changed files with 10735 additions and 3987 deletions

View file

@ -229,6 +229,7 @@ X!Isound/sound_firmware.c
!Iinclude/media/v4l2-dv-timings.h
!Iinclude/media/v4l2-event.h
!Iinclude/media/v4l2-flash-led-class.h
!Iinclude/media/v4l2-mc.h
!Iinclude/media/v4l2-mediabus.h
!Iinclude/media/v4l2-mem2mem.h
!Iinclude/media/v4l2-of.h

View file

@ -2329,6 +2329,14 @@ to search and match for the present Macroblock (MB) in the reference picture. Th
vertical search range for motion estimation module in video encoder.</entry>
</row>
<row><entry></entry></row>
<row id="v4l2-mpeg-video-force-key-frame">
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME</constant>&nbsp;</entry>
<entry>button</entry>
</row><row><entry spanname="descr">Force a key frame for the next queued buffer. Applicable to encoders.
This is a general, codec-agnostic keyframe control.</entry>
</row>
<row><entry></entry></row>
<row>
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE</constant>&nbsp;</entry>
@ -5069,6 +5077,46 @@ interface and may change in the future.</para>
This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
</entry>
</row>
<row>
<entry spanname="id"><constant>V4L2_CID_DV_TX_IT_CONTENT_TYPE</constant></entry>
<entry id="v4l2-dv-content-type">enum v4l2_dv_it_content_type</entry>
</row>
<row><entry spanname="descr">Configures the IT Content Type
of the transmitted video. This information is sent over HDMI and DisplayPort connectors
as part of the AVI InfoFrame. The term 'IT Content' is used for content that originates
from a computer as opposed to content from a TV broadcast or an analog source. The
enum&nbsp;v4l2_dv_it_content_type defines the possible content types:</entry>
</row>
<row>
<entrytbl spanname="descr" cols="2">
<tbody valign="top">
<row>
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_GRAPHICS</constant>&nbsp;</entry>
<entry>Graphics content. Pixel data should be passed unfiltered and without
analog reconstruction.</entry>
</row>
<row>
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_PHOTO</constant>&nbsp;</entry>
<entry>Photo content. The content is derived from digital still pictures.
The content should be passed through with minimal scaling and picture
enhancements.</entry>
</row>
<row>
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_CINEMA</constant>&nbsp;</entry>
<entry>Cinema content.</entry>
</row>
<row>
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_GAME</constant>&nbsp;</entry>
<entry>Game content. Audio and video latency should be minimized.</entry>
</row>
<row>
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_NO_ITC</constant>&nbsp;</entry>
<entry>No IT Content information is available and the ITC bit in the AVI
InfoFrame is set to 0.</entry>
</row>
</tbody>
</entrytbl>
</row>
<row>
<entry spanname="id"><constant>V4L2_CID_DV_RX_POWER_PRESENT</constant></entry>
<entry>bitmask</entry>
@ -5098,6 +5146,16 @@ interface and may change in the future.</para>
This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
</entry>
</row>
<row>
<entry spanname="id"><constant>V4L2_CID_DV_RX_IT_CONTENT_TYPE</constant></entry>
<entry>enum v4l2_dv_it_content_type</entry>
</row>
<row><entry spanname="descr">Reads the IT Content Type
of the received video. This information is sent over HDMI and DisplayPort connectors
as part of the AVI InfoFrame. The term 'IT Content' is used for content that originates
from a computer as opposed to content from a TV broadcast or an analog source. See
<constant>V4L2_CID_DV_TX_IT_CONTENT_TYPE</constant> for the available content types.</entry>
</row>
<row><entry></entry></row>
</tbody>
</tgroup>

View file

@ -48,9 +48,6 @@
<refsect1>
<title>Description</title>
<para><emphasis role="bold">NOTE:</emphasis> This new ioctl is programmed to be added on Kernel 4.6. Its definition/arguments may change until its final version.</para>
<para>The typical usage of this ioctl is to call it twice.
On the first call, the structure defined at &media-v2-topology; should
be zeroed. At return, if no errors happen, this ioctl will return the

View file

@ -56,10 +56,6 @@
<entry><constant>MEDIA_ENT_F_CONN_COMPOSITE</constant></entry>
<entry>Connector for a RGB composite signal.</entry>
</row>
<row>
<entry><constant>MEDIA_ENT_F_CONN_TEST</constant></entry>
<entry>Connector for a test generator.</entry>
</row>
<row>
<entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry>
<entry>Camera video sensor entity.</entry>
@ -84,7 +80,34 @@
</row>
<row>
<entry><constant>MEDIA_ENT_F_TUNER</constant></entry>
<entry>Digital TV, analog TV, radio and/or software radio tuner.</entry>
<entry>Digital TV, analog TV, radio and/or software radio tuner,
with consists on a PLL tuning stage that converts radio
frequency (RF) signal into an Intermediate Frequency (IF).
Modern tuners have internally IF-PLL decoders for audio
and video, but older models have those stages implemented
on separate entities.
</entry>
</row>
<row>
<entry><constant>MEDIA_ENT_F_IF_VID_DECODER</constant></entry>
<entry>IF-PLL video decoder. It receives the IF from a PLL
and decodes the analog TV video signal. This is commonly
found on some very old analog tuners, like Philips MK3
designs. They all contain a tda9887 (or some software
compatible similar chip, like tda9885). Those devices
use a different I2C address than the tuner PLL.
</entry>
</row>
<row>
<entry><constant>MEDIA_ENT_F_IF_AUD_DECODER</constant></entry>
<entry>IF-PLL sound decoder. It receives the IF from a PLL
and decodes the analog TV audio signal. This is commonly
found on some very old analog hardware, like Micronas
msp3400, Philips tda9840, tda985x, etc. Those devices
use a different I2C address than the tuner PLL and
should be controlled together with the IF-PLL video
decoder.
</entry>
</row>
</tbody>
</tgroup>

View file

@ -1,35 +1,43 @@
<refentry id="V4L2-PIX-FMT-YUV420M">
<refentry>
<refmeta>
<refentrytitle>V4L2_PIX_FMT_YUV420M ('YM12')</refentrytitle>
<refentrytitle>V4L2_PIX_FMT_YUV420M ('YM12'), V4L2_PIX_FMT_YVU420M ('YM21')</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname> <constant>V4L2_PIX_FMT_YUV420M</constant></refname>
<refpurpose>Variation of <constant>V4L2_PIX_FMT_YUV420</constant>
with planes non contiguous in memory. </refpurpose>
<refname id="V4L2-PIX-FMT-YUV420M"><constant>V4L2_PIX_FMT_YUV420M</constant></refname>
<refname id="V4L2-PIX-FMT-YVU420M"><constant>V4L2_PIX_FMT_YVU420M</constant></refname>
<refpurpose>Variation of <constant>V4L2_PIX_FMT_YUV420</constant> and
<constant>V4L2_PIX_FMT_YVU420</constant> with planes non contiguous
in memory.</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para>This is a multi-planar format, as opposed to a packed format.
The three components are separated into three sub- images or planes.
The three components are separated into three sub-images or planes.</para>
The Y plane is first. The Y plane has one byte per pixel. The Cb data
<para>The Y plane is first. The Y plane has one byte per pixel.
For <constant>V4L2_PIX_FMT_YUV420M</constant> the Cb data
constitutes the second plane which is half the width and half
the height of the Y plane (and of the image). Each Cb belongs to four
pixels, a two-by-two square of the image. For example,
Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
Y'<subscript>11</subscript>. The Cr data, just like the Cb plane, is
in the third plane. </para>
in the third plane.</para>
<para><constant>V4L2_PIX_FMT_YVU420M</constant> is the same except
the Cr data is stored in the second plane and the Cb data in the third plane.
</para>
<para>If the Y plane has pad bytes after each row, then the Cb
and Cr planes have half as many pad bytes after their rows. In other
words, two Cx rows (including padding) is exactly as long as one Y row
(including padding).</para>
<para><constant>V4L2_PIX_FMT_YUV420M</constant> is intended to be
<para><constant>V4L2_PIX_FMT_YUV420M</constant> and
<constant>V4L2_PIX_FMT_YVU420M</constant> are intended to be
used only in drivers and applications that support the multi-planar API,
described in <xref linkend="planar-apis"/>. </para>

View file

@ -1,40 +1,45 @@
<refentry id="V4L2-PIX-FMT-YVU420M">
<refentry>
<refmeta>
<refentrytitle>V4L2_PIX_FMT_YVU420M ('YM21')</refentrytitle>
<refentrytitle>V4L2_PIX_FMT_YUV422M ('YM16'), V4L2_PIX_FMT_YVU422M ('YM61')</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname> <constant>V4L2_PIX_FMT_YVU420M</constant></refname>
<refpurpose>Variation of <constant>V4L2_PIX_FMT_YVU420</constant>
with planes non contiguous in memory. </refpurpose>
<refname id="V4L2-PIX-FMT-YUV422M"><constant>V4L2_PIX_FMT_YUV422M</constant></refname>
<refname id="V4L2-PIX-FMT-YVU422M"><constant>V4L2_PIX_FMT_YVU422M</constant></refname>
<refpurpose>Planar formats with &frac12; horizontal resolution, also
known as YUV and YVU 4:2:2</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para>This is a multi-planar format, as opposed to a packed format.
The three components are separated into three sub-images or planes.
The three components are separated into three sub-images or planes.</para>
The Y plane is first. The Y plane has one byte per pixel. The Cr data
constitutes the second plane which is half the width and half
the height of the Y plane (and of the image). Each Cr belongs to four
pixels, a two-by-two square of the image. For example,
Cr<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
Y'<subscript>11</subscript>. The Cb data, just like the Cr plane, constitutes
the third plane. </para>
<para>The Y plane is first. The Y plane has one byte per pixel.
For <constant>V4L2_PIX_FMT_YUV422M</constant> the Cb data
constitutes the second plane which is half the width of the Y plane (and of the
image). Each Cb belongs to two pixels. For example,
Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
Y'<subscript>01</subscript>. The Cr data, just like the Cb plane, is
in the third plane. </para>
<para>If the Y plane has pad bytes after each row, then the Cr
and Cb planes have half as many pad bytes after their rows. In other
<para><constant>V4L2_PIX_FMT_YVU422M</constant> is the same except
the Cr data is stored in the second plane and the Cb data in the third plane.
</para>
<para>If the Y plane has pad bytes after each row, then the Cb
and Cr planes have half as many pad bytes after their rows. In other
words, two Cx rows (including padding) is exactly as long as one Y row
(including padding).</para>
<para><constant>V4L2_PIX_FMT_YVU420M</constant> is intended to be
<para><constant>V4L2_PIX_FMT_YUV422M</constant> and
<constant>V4L2_PIX_FMT_YVU422M</constant> are intended to be
used only in drivers and applications that support the multi-planar API,
described in <xref linkend="planar-apis"/>. </para>
<example>
<title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 &times; 4
<title><constant>V4L2_PIX_FMT_YUV422M</constant> 4 &times; 4
pixel image</title>
<formalpara>
@ -75,25 +80,45 @@ pixel image</title>
<row><entry></entry></row>
<row>
<entry>start1&nbsp;+&nbsp;0:</entry>
<entry>Cr<subscript>00</subscript></entry>
<entry>Cr<subscript>01</subscript></entry>
</row>
<row>
<entry>start1&nbsp;+&nbsp;2:</entry>
<entry>Cr<subscript>10</subscript></entry>
<entry>Cr<subscript>11</subscript></entry>
</row>
<row><entry></entry></row>
<row>
<entry>start2&nbsp;+&nbsp;0:</entry>
<entry>Cb<subscript>00</subscript></entry>
<entry>Cb<subscript>01</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;2:</entry>
<entry>start1&nbsp;+&nbsp;2:</entry>
<entry>Cb<subscript>10</subscript></entry>
<entry>Cb<subscript>11</subscript></entry>
</row>
<row>
<entry>start1&nbsp;+&nbsp;4:</entry>
<entry>Cb<subscript>20</subscript></entry>
<entry>Cb<subscript>21</subscript></entry>
</row>
<row>
<entry>start1&nbsp;+&nbsp;6:</entry>
<entry>Cb<subscript>30</subscript></entry>
<entry>Cb<subscript>31</subscript></entry>
</row>
<row><entry></entry></row>
<row>
<entry>start2&nbsp;+&nbsp;0:</entry>
<entry>Cr<subscript>00</subscript></entry>
<entry>Cr<subscript>01</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;2:</entry>
<entry>Cr<subscript>10</subscript></entry>
<entry>Cr<subscript>11</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;4:</entry>
<entry>Cr<subscript>20</subscript></entry>
<entry>Cr<subscript>21</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;6:</entry>
<entry>Cr<subscript>30</subscript></entry>
<entry>Cr<subscript>31</subscript></entry>
</row>
</tbody>
</tgroup>
</informaltable>
@ -113,36 +138,23 @@ pixel image</title>
</row>
<row>
<entry>0</entry>
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry></entry><entry>Y</entry>
</row>
<row>
<entry></entry>
<entry></entry><entry>C</entry><entry></entry><entry></entry>
<entry></entry><entry>C</entry><entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry>
</row>
<row>
<entry>1</entry>
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry></entry><entry>Y</entry>
</row>
<row>
<entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry>
</row>
<row>
<entry>2</entry>
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry></entry><entry>Y</entry>
</row>
<row>
<entry></entry>
<entry></entry><entry>C</entry><entry></entry><entry></entry>
<entry></entry><entry>C</entry><entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry>
</row>
<row>
<entry>3</entry>
<entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry></entry><entry>Y</entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
<entry>Y</entry><entry>C</entry><entry>Y</entry>
</row>
</tbody>
</tgroup>

View file

@ -0,0 +1,177 @@
<refentry>
<refmeta>
<refentrytitle>V4L2_PIX_FMT_YUV444M ('YM24'), V4L2_PIX_FMT_YVU444M ('YM42')</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname id="V4L2-PIX-FMT-YUV444M"><constant>V4L2_PIX_FMT_YUV444M</constant></refname>
<refname id="V4L2-PIX-FMT-YVU444M"><constant>V4L2_PIX_FMT_YVU444M</constant></refname>
<refpurpose>Planar formats with full horizontal resolution, also
known as YUV and YVU 4:4:4</refpurpose>
</refnamediv>
<refsect1>
<title>Description</title>
<para>This is a multi-planar format, as opposed to a packed format.
The three components are separated into three sub-images or planes.</para>
<para>The Y plane is first. The Y plane has one byte per pixel.
For <constant>V4L2_PIX_FMT_YUV444M</constant> the Cb data
constitutes the second plane which is the same width and height as the Y plane
(and as the image). The Cr data, just like the Cb plane, is in the third plane.
</para>
<para><constant>V4L2_PIX_FMT_YVU444M</constant> is the same except
the Cr data is stored in the second plane and the Cb data in the third plane.
</para>
<para>If the Y plane has pad bytes after each row, then the Cb
and Cr planes have the same number of pad bytes after their rows.</para>
<para><constant>V4L2_PIX_FMT_YUV444M</constant> and
<constant>V4L2_PIX_FMT_YUV444M</constant> are intended to be
used only in drivers and applications that support the multi-planar API,
described in <xref linkend="planar-apis"/>. </para>
<example>
<title><constant>V4L2_PIX_FMT_YUV444M</constant> 4 &times; 4
pixel image</title>
<formalpara>
<title>Byte Order.</title>
<para>Each cell is one byte.
<informaltable frame="none">
<tgroup cols="5" align="center">
<colspec align="left" colwidth="2*" />
<tbody valign="top">
<row>
<entry>start0&nbsp;+&nbsp;0:</entry>
<entry>Y'<subscript>00</subscript></entry>
<entry>Y'<subscript>01</subscript></entry>
<entry>Y'<subscript>02</subscript></entry>
<entry>Y'<subscript>03</subscript></entry>
</row>
<row>
<entry>start0&nbsp;+&nbsp;4:</entry>
<entry>Y'<subscript>10</subscript></entry>
<entry>Y'<subscript>11</subscript></entry>
<entry>Y'<subscript>12</subscript></entry>
<entry>Y'<subscript>13</subscript></entry>
</row>
<row>
<entry>start0&nbsp;+&nbsp;8:</entry>
<entry>Y'<subscript>20</subscript></entry>
<entry>Y'<subscript>21</subscript></entry>
<entry>Y'<subscript>22</subscript></entry>
<entry>Y'<subscript>23</subscript></entry>
</row>
<row>
<entry>start0&nbsp;+&nbsp;12:</entry>
<entry>Y'<subscript>30</subscript></entry>
<entry>Y'<subscript>31</subscript></entry>
<entry>Y'<subscript>32</subscript></entry>
<entry>Y'<subscript>33</subscript></entry>
</row>
<row><entry></entry></row>
<row>
<entry>start1&nbsp;+&nbsp;0:</entry>
<entry>Cb<subscript>00</subscript></entry>
<entry>Cb<subscript>01</subscript></entry>
<entry>Cb<subscript>02</subscript></entry>
<entry>Cb<subscript>03</subscript></entry>
</row>
<row>
<entry>start1&nbsp;+&nbsp;4:</entry>
<entry>Cb<subscript>10</subscript></entry>
<entry>Cb<subscript>11</subscript></entry>
<entry>Cb<subscript>12</subscript></entry>
<entry>Cb<subscript>13</subscript></entry>
</row>
<row>
<entry>start1&nbsp;+&nbsp;8:</entry>
<entry>Cb<subscript>20</subscript></entry>
<entry>Cb<subscript>21</subscript></entry>
<entry>Cb<subscript>22</subscript></entry>
<entry>Cb<subscript>23</subscript></entry>
</row>
<row>
<entry>start1&nbsp;+&nbsp;12:</entry>
<entry>Cb<subscript>20</subscript></entry>
<entry>Cb<subscript>21</subscript></entry>
<entry>Cb<subscript>32</subscript></entry>
<entry>Cb<subscript>33</subscript></entry>
</row>
<row><entry></entry></row>
<row>
<entry>start2&nbsp;+&nbsp;0:</entry>
<entry>Cr<subscript>00</subscript></entry>
<entry>Cr<subscript>01</subscript></entry>
<entry>Cr<subscript>02</subscript></entry>
<entry>Cr<subscript>03</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;4:</entry>
<entry>Cr<subscript>10</subscript></entry>
<entry>Cr<subscript>11</subscript></entry>
<entry>Cr<subscript>12</subscript></entry>
<entry>Cr<subscript>13</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;8:</entry>
<entry>Cr<subscript>20</subscript></entry>
<entry>Cr<subscript>21</subscript></entry>
<entry>Cr<subscript>22</subscript></entry>
<entry>Cr<subscript>23</subscript></entry>
</row>
<row>
<entry>start2&nbsp;+&nbsp;12:</entry>
<entry>Cr<subscript>30</subscript></entry>
<entry>Cr<subscript>31</subscript></entry>
<entry>Cr<subscript>32</subscript></entry>
<entry>Cr<subscript>33</subscript></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</formalpara>
<formalpara>
<title>Color Sample Location.</title>
<para>
<informaltable frame="none">
<tgroup cols="7" align="center">
<tbody valign="top">
<row>
<entry></entry>
<entry>0</entry><entry></entry><entry>1</entry><entry></entry>
<entry>2</entry><entry></entry><entry>3</entry>
</row>
<row>
<entry>0</entry>
<entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
<entry>YC</entry><entry></entry><entry>YC</entry>
</row>
<row>
<entry>1</entry>
<entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
<entry>YC</entry><entry></entry><entry>YC</entry>
</row>
<row>
<entry>2</entry>
<entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
<entry>YC</entry><entry></entry><entry>YC</entry>
</row>
<row>
<entry>3</entry>
<entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
<entry>YC</entry><entry></entry><entry>YC</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</formalpara>
</example>
</refsect1>
</refentry>

View file

@ -1628,7 +1628,8 @@ information.</para>
&sub-y41p;
&sub-yuv420;
&sub-yuv420m;
&sub-yvu420m;
&sub-yuv422m;
&sub-yuv444m;
&sub-yuv410;
&sub-yuv422p;
&sub-yuv411p;

View file

@ -60,9 +60,19 @@ input</refpurpose>
automatically, similar to sensing the video standard. To do so, applications
call <constant>VIDIOC_QUERY_DV_TIMINGS</constant> with a pointer to a
&v4l2-dv-timings;. Once the hardware detects the timings, it will fill in the
timings structure.
timings structure.</para>
If the timings could not be detected because there was no signal, then
<para>Please note that drivers shall <emphasis>not</emphasis> switch timings automatically
if new timings are detected. Instead, drivers should send the
<constant>V4L2_EVENT_SOURCE_CHANGE</constant> event (if they support this) and expect
that userspace will take action by calling <constant>VIDIOC_QUERY_DV_TIMINGS</constant>.
The reason is that new timings usually mean different buffer sizes as well, and you
cannot change buffer sizes on the fly. In general, applications that receive the
Source Change event will have to call <constant>VIDIOC_QUERY_DV_TIMINGS</constant>,
and if the detected timings are valid they will have to stop streaming, set the new
timings, allocate new buffers and start streaming again.</para>
<para>If the timings could not be detected because there was no signal, then
<errorcode>ENOLINK</errorcode> is returned. If a signal was detected, but
it was unstable and the receiver could not lock to the signal, then
<errorcode>ENOLCK</errorcode> is returned. If the receiver could lock to the signal,

View file

@ -59,6 +59,16 @@ then the driver will return V4L2_STD_UNKNOWN. When detection is not
possible or fails, the set must contain all standards supported by the
current video input or output.</para>
<para>Please note that drivers shall <emphasis>not</emphasis> switch the video standard
automatically if a new video standard is detected. Instead, drivers should send the
<constant>V4L2_EVENT_SOURCE_CHANGE</constant> event (if they support this) and expect
that userspace will take action by calling <constant>VIDIOC_QUERYSTD</constant>.
The reason is that a new video standard can mean different buffer sizes as well, and you
cannot change buffer sizes on the fly. In general, applications that receive the
Source Change event will have to call <constant>VIDIOC_QUERYSTD</constant>,
and if the detected video standard is valid they will have to stop streaming, set the new
standard, allocate new buffers and start streaming again.</para>
</refsect1>
<refsect1>

View file

@ -8,6 +8,7 @@ Required Properties:
- "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
- "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
- "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
- "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
- reg: A list of base address and length of each memory resource, one for
each entry in the reg-names property.
@ -24,7 +25,7 @@ Required Properties:
- clock-names: Name of the clocks. This property is model-dependent.
- R8A7779 uses a single functional clock. The clock doesn't need to be
named.
- R8A779[0134] use one functional clock per channel and one clock per LVDS
- R8A779[01345] use one functional clock per channel and one clock per LVDS
encoder (if available). The functional clocks must be named "du.x" with
"x" being the channel numerical index. The LVDS clocks must be named
"lvds.x" with "x" being the LVDS encoder numerical index.
@ -41,13 +42,14 @@ bindings specified in Documentation/devicetree/bindings/graph.txt.
The following table lists for each supported model the port number
corresponding to each DU output.
Port 0 Port1 Port2
Port 0 Port1 Port2 Port3
-----------------------------------------------------------------------------
R8A7779 (H1) DPAD 0 DPAD 1 -
R8A7790 (H2) DPAD LVDS 0 LVDS 1
R8A7791 (M2-W) DPAD LVDS 0 -
R8A7793 (M2-N) DPAD LVDS 0 -
R8A7794 (E2) DPAD 0 DPAD 1 -
R8A7779 (H1) DPAD 0 DPAD 1 - -
R8A7790 (H2) DPAD LVDS 0 LVDS 1 -
R8A7791 (M2-W) DPAD LVDS 0 - -
R8A7793 (M2-N) DPAD LVDS 0 - -
R8A7794 (E2) DPAD 0 DPAD 1 - -
R8A7795 (H3) DPAD HDMI 0 HDMI 1 LVDS
Example: R8A7790 (R-Car H2) DU

View file

@ -20,6 +20,8 @@ Optional Properties:
- link-frequencies: List of allowed link frequencies in Hz. Each frequency is
expressed as a 64-bit big-endian integer.
- reset-gpios: GPIO handle which is connected to the reset pin of the chip.
- standby-gpios: GPIO handle which is connected to the standby pin of the chip.
For further reading on port node refer to
Documentation/devicetree/bindings/media/video-interfaces.txt.

View file

@ -0,0 +1,88 @@
* Texas Instruments TVP5150 and TVP5151 video decoders
The TVP5150 and TVP5151 are video decoders that convert baseband NTSC and PAL
(and also SECAM in the TVP5151 case) video signals to either 8-bit 4:2:2 YUV
with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output formats.
Required Properties:
- compatible: value must be "ti,tvp5150"
- reg: I2C slave address
Optional Properties:
- pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
- reset-gpios: phandle for the GPIO connected to the RESETB pin, if any.
Optional nodes:
- connectors: The input connectors of tvp5150 have to be defined under
a subnode name "connectors" using the following format:
input-connector-name {
input connector properties
};
Each input connector must contain the following properties:
- label: a name for the connector.
- input: the input connector.
The possible values for the "input" property are:
0: Composite0
1: Composite1
2: S-Video
and on a tvp5150am1 and tvp5151 there is another:
4: Signal generator
The list of valid input connectors are defined in dt-bindings/media/tvp5150.h
header file and can be included by device tree source files.
Each input connector can be defined only once.
The device node must contain one 'port' child node for its digital output
video port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
Required Endpoint Properties for parallel synchronization:
- hsync-active: active state of the HSYNC signal. Must be <1> (HIGH).
- vsync-active: active state of the VSYNC signal. Must be <1> (HIGH).
- field-even-active: field signal level during the even field data
transmission. Must be <0>.
If none of hsync-active, vsync-active and field-even-active is specified,
the endpoint is assumed to use embedded BT.656 synchronization.
Example:
&i2c2 {
...
tvp5150@5c {
compatible = "ti,tvp5150";
reg = <0x5c>;
pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
connectors {
composite0 {
label = "Composite0";
input = <TVP5150_COMPOSITE0>;
};
composite1 {
label = "Composite1";
input = <TVP5150_COMPOSITE1>;
};
s-video {
label = "S-Video";
input = <TVP5150_SVIDEO>;
};
};
port {
tvp5150_1: endpoint {
remote-endpoint = <&ccdc_ep>;
};
};
};
};

View file

@ -6,6 +6,7 @@ family of devices. The current blocks are always slaves and suppot one input
channel which can be either RGB, YUYV or BT656.
- compatible: Must be one of the following
- "renesas,vin-r8a7795" for the R8A7795 device
- "renesas,vin-r8a7794" for the R8A7794 device
- "renesas,vin-r8a7793" for the R8A7793 device
- "renesas,vin-r8a7791" for the R8A7791 device

View file

@ -5,11 +5,12 @@ and decoding function conforming to the JPEG baseline process, so that the JPU
can encode image data and decode JPEG data quickly.
Required properties:
- compatible: should containg one of the following:
- "renesas,jpu-r8a7790" for R-Car H2
- "renesas,jpu-r8a7791" for R-Car M2-W
- "renesas,jpu-r8a7792" for R-Car V2H
- "renesas,jpu-r8a7793" for R-Car M2-N
- compatible: "renesas,jpu-<soctype>", "renesas,rcar-gen2-jpu" as fallback.
Examples with soctypes are:
- "renesas,jpu-r8a7790" for R-Car H2
- "renesas,jpu-r8a7791" for R-Car M2-W
- "renesas,jpu-r8a7792" for R-Car V2H
- "renesas,jpu-r8a7793" for R-Car M2-N
- reg: Base address and length of the registers block for the JPU.
- interrupts: JPU interrupt specifier.
@ -17,7 +18,7 @@ Required properties:
Example: R8A7790 (R-Car H2) JPU node
jpeg-codec@fe980000 {
compatible = "renesas,jpu-r8a7790";
compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu";
reg = <0 0xfe980000 0 0x10300>;
interrupts = <0 272 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7790_CLK_JPU>;

View file

@ -1,30 +1,18 @@
* Renesas VSP1 Video Processing Engine
* Renesas VSP Video Processing Engine
The VSP1 is a video processing engine that supports up-/down-scaling, alpha
The VSP is a video processing engine that supports up-/down-scaling, alpha
blending, color space conversion and various other image processing features.
It can be found in the Renesas R-Car second generation SoCs.
Required properties:
- compatible: Must contain "renesas,vsp1"
- compatible: Must contain one of the following values
- "renesas,vsp1" for the R-Car Gen2 VSP1
- "renesas,vsp2" for the R-Car Gen3 VSP2
- reg: Base address and length of the registers block for the VSP1.
- interrupts: VSP1 interrupt specifier.
- clocks: A phandle + clock-specifier pair for the VSP1 functional clock.
- renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP1.
- renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1.
- renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP1.
Optional properties:
- renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is
available.
- renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is
available.
- renesas,has-sru: Boolean, indicates that the Super Resolution Unit (SRU)
module is available.
- reg: Base address and length of the registers block for the VSP.
- interrupts: VSP interrupt specifier.
- clocks: A phandle + clock-specifier pair for the VSP functional clock.
Example: R8A7790 (R-Car H2) VSP1-S node
@ -34,10 +22,4 @@ Example: R8A7790 (R-Car H2) VSP1-S node
reg = <0 0xfe928000 0 0x8000>;
interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>;
renesas,has-lut;
renesas,has-sru;
renesas,#rpf = <5>;
renesas,#uds = <3>;
renesas,#wpf = <4>;
};

View file

@ -0,0 +1,72 @@
Texas Instruments DRA72x CAMERA ADAPTATION LAYER (CAL)
------------------------------------------------------
The Camera Adaptation Layer (CAL) is a key component for image capture
applications. The capture module provides the system interface and the
processing capability to connect CSI2 image-sensor modules to the
DRA72x device.
Required properties:
- compatible: must be "ti,dra72-cal"
- reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX
control address space
- reg-names: cal_top, cal_rx_core0, cal_rx_core1, and camerrx_control
registers
- interrupts: should contain IRQ line for the CAL;
CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes
should contain a 'port' child node with child 'endpoint' node. Please
refer to the bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
Example:
cal: cal@4845b000 {
compatible = "ti,dra72-cal";
ti,hwmods = "cal";
reg = <0x4845B000 0x400>,
<0x4845B800 0x40>,
<0x4845B900 0x40>,
<0x4A002e94 0x4>;
reg-names = "cal_top",
"cal_rx_core0",
"cal_rx_core1",
"camerrx_control";
interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
csi2_0: port@0 {
reg = <0>;
endpoint {
slave-mode;
remote-endpoint = <&ar0330_1>;
};
};
csi2_1: port@1 {
reg = <1>;
};
};
};
i2c5: i2c@4807c000 {
ar0330@10 {
compatible = "ti,ar0330";
reg = <0x10>;
port {
#address-cells = <1>;
#size-cells = <0>;
ar0330_1: endpoint {
reg = <0>;
clock-lanes = <1>;
data-lanes = <0 2 3 4>;
remote-endpoint = <&csi2_0>;
};
};
};
};

View file

@ -190,7 +190,7 @@ and watch another one.
Patches, comments and suggestions are very very welcome.
3. Acknowledgements
Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
Amaury Demol (Amaury.Demol@parrot.com) and Francois Kanounnikoff from DiBcom for
providing specs, code and help, on which the dvb-dibusb, dib3000mb and
dib3000mc are based.

View file

@ -647,7 +647,6 @@ Or you can add specific controls to a handler:
volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...);
v4l2_ctrl_add_ctrl(&radio_ctrl_handler, volume);
What you should not do is make two identical controls for two handlers.
For example:

View file

@ -10855,6 +10855,14 @@ L: linux-omap@vger.kernel.org
S: Maintained
F: drivers/thermal/ti-soc-thermal/
TI VPE/CAL DRIVERS
M: Benoit Parrot <bparrot@ti.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
S: Maintained
F: drivers/media/platform/ti-vpe/
TI CDCE706 CLOCK DRIVER
M: Max Filippov <jcmvbkbc@gmail.com>
S: Maintained

View file

@ -1,6 +1,7 @@
config DRM_RCAR_DU
tristate "DRM Support for R-Car Display Unit"
depends on DRM && ARM && OF
depends on DRM && OF
depends on ARM || ARM64
depends on ARCH_SHMOBILE || COMPILE_TEST
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
@ -14,14 +15,18 @@ config DRM_RCAR_DU
config DRM_RCAR_HDMI
bool "R-Car DU HDMI Encoder Support"
depends on DRM_RCAR_DU
depends on OF
help
Enable support for external HDMI encoders.
config DRM_RCAR_LVDS
bool "R-Car DU LVDS Encoder Support"
depends on DRM_RCAR_DU
depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST
help
Enable support for the R-Car Display Unit embedded LVDS encoders
(currently only on R8A7790 and R8A7791).
Enable support for the R-Car Display Unit embedded LVDS encoders.
config DRM_RCAR_VSP
bool "R-Car DU VSP Compositor Support"
depends on DRM_RCAR_DU
depends on VIDEO_RENESAS_VSP1
help
Enable support to expose the R-Car VSP Compositor as KMS planes.

View file

@ -11,4 +11,6 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI) += rcar_du_hdmicon.o \
rcar_du_hdmienc.o
rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o
rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o
obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o

View file

@ -1,7 +1,7 @@
/*
* rcar_du_crtc.c -- R-Car Display Unit CRTCs
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -28,6 +28,7 @@
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
#include "rcar_du_vsp.h"
static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
{
@ -150,7 +151,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
/* Signal polarities */
value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
| DSMR_DIPM_DE | DSMR_CSPM;
| DSMR_DIPM_DISP | DSMR_CSPM;
rcar_du_crtc_write(rcrtc, DSMR, value);
/* Display timings */
@ -207,6 +208,7 @@ plane_format(struct rcar_du_plane *plane)
static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
{
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
struct rcar_du_device *rcdu = rcrtc->group->dev;
unsigned int num_planes = 0;
unsigned int dptsr_planes;
unsigned int hwplanes = 0;
@ -250,6 +252,17 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
}
}
/* If VSP+DU integration is enabled the plane assignment is fixed. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
if (rcdu->info->gen < 3) {
dspr = (rcrtc->index % 2) + 1;
hwplanes = 1 << (rcrtc->index % 2);
} else {
dspr = (rcrtc->index % 2) ? 3 : 1;
hwplanes = 1 << ((rcrtc->index % 2) ? 2 : 0);
}
}
/* Update the planes to display timing and dot clock generator
* associations.
*
@ -272,6 +285,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
rcar_du_group_restart(rcrtc->group);
}
/* Restart the group if plane sources have changed. */
if (rcrtc->group->need_restart)
rcar_du_group_restart(rcrtc->group);
mutex_unlock(&rcrtc->group->lock);
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
@ -365,6 +382,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
rcar_du_group_start_stop(rcrtc->group, true);
/* Enable the VSP compositor. */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_enable(rcrtc);
/* Turn vertical blanking interrupt reporting back on. */
drm_crtc_vblank_on(crtc);
@ -398,6 +419,10 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_wait_page_flip(rcrtc);
drm_crtc_vblank_off(crtc);
/* Disable the VSP compositor. */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc);
/* Select switch sync mode. This stops display operation and configures
* the HSYNC and VSYNC signals as inputs.
*/
@ -410,6 +435,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
{
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc);
rcar_du_crtc_stop(rcrtc);
rcar_du_crtc_put(rcrtc);
}
@ -418,20 +446,24 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
{
unsigned int i;
if (!rcrtc->enabled)
if (!rcrtc->crtc.state->active)
return;
rcar_du_crtc_get(rcrtc);
rcar_du_crtc_start(rcrtc);
/* Commit the planes state. */
for (i = 0; i < rcrtc->group->num_planes; ++i) {
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) {
rcar_du_vsp_enable(rcrtc);
} else {
for (i = 0; i < rcrtc->group->num_planes; ++i) {
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
if (plane->plane.state->crtc != &rcrtc->crtc)
continue;
if (plane->plane.state->crtc != &rcrtc->crtc)
continue;
rcar_du_plane_setup(plane);
rcar_du_plane_setup(plane);
}
}
rcar_du_crtc_update_planes(rcrtc);
@ -445,26 +477,17 @@ static void rcar_du_crtc_enable(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
if (rcrtc->enabled)
return;
rcar_du_crtc_get(rcrtc);
rcar_du_crtc_start(rcrtc);
rcrtc->enabled = true;
}
static void rcar_du_crtc_disable(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
if (!rcrtc->enabled)
return;
rcar_du_crtc_stop(rcrtc);
rcar_du_crtc_put(rcrtc);
rcrtc->enabled = false;
rcrtc->outputs = 0;
}
@ -491,6 +514,9 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
rcrtc->event = event;
spin_unlock_irqrestore(&dev->event_lock, flags);
}
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_begin(rcrtc);
}
static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
@ -499,6 +525,9 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
rcar_du_crtc_update_planes(rcrtc);
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_flush(rcrtc);
}
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
@ -547,13 +576,14 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
{
static const unsigned int mmio_offsets[] = {
DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET
DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
};
struct rcar_du_device *rcdu = rgrp->dev;
struct platform_device *pdev = to_platform_device(rcdu->dev);
struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
struct drm_crtc *crtc = &rcrtc->crtc;
struct drm_plane *primary;
unsigned int irqflags;
struct clk *clk;
char clk_name[9];
@ -589,10 +619,13 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->group = rgrp;
rcrtc->mmio_offset = mmio_offsets[index];
rcrtc->index = index;
rcrtc->enabled = false;
ret = drm_crtc_init_with_planes(rcdu->ddev, crtc,
&rgrp->planes[index % 2].plane,
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
primary = &rcrtc->vsp->planes[0].plane;
else
primary = &rgrp->planes[index % 2].plane;
ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
NULL, &crtc_funcs, NULL);
if (ret < 0)
return ret;

View file

@ -21,6 +21,7 @@
#include <drm/drm_crtc.h>
struct rcar_du_group;
struct rcar_du_vsp;
/**
* struct rcar_du_crtc - the CRTC, representing a DU superposition processor
@ -33,7 +34,6 @@ struct rcar_du_group;
* @event: event to post when the pending page flip completes
* @flip_wait: wait queue used to signal page flip completion
* @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC
* @enabled: whether the CRTC is enabled, used to control system resume
* @group: CRTC group this CRTC belongs to
*/
struct rcar_du_crtc {
@ -49,9 +49,9 @@ struct rcar_du_crtc {
wait_queue_head_t flip_wait;
unsigned int outputs;
bool enabled;
struct rcar_du_group *group;
struct rcar_du_vsp *vsp;
};
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)

View file

@ -1,7 +1,7 @@
/*
* rcar_du_drv.c -- R-Car Display Unit DRM driver
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -36,6 +36,7 @@
*/
static const struct rcar_du_device_info rcar_du_r8a7779_info = {
.gen = 2,
.features = 0,
.num_crtcs = 2,
.routes = {
@ -57,6 +58,7 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
};
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
@ -86,6 +88,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2,
@ -108,6 +111,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
};
static const struct rcar_du_device_info rcar_du_r8a7794_info = {
.gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2,
@ -129,12 +133,37 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
.num_lvds = 0,
};
static const struct rcar_du_device_info rcar_du_r8a7795_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS
| RCAR_DU_FEATURE_VSP1_SOURCE,
.num_crtcs = 4,
.routes = {
/* R8A7795 has one RGB output, one LVDS output and two
* (currently unsupported) HDMI outputs.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(3),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_LVDS,
.port = 3,
},
},
.num_lvds = 1,
};
static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
{ }
};
@ -144,82 +173,6 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
* DRM operations
*/
static int rcar_du_unload(struct drm_device *dev)
{
struct rcar_du_device *rcdu = dev->dev_private;
if (rcdu->fbdev)
drm_fbdev_cma_fini(rcdu->fbdev);
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
drm_vblank_cleanup(dev);
dev->irq_enabled = 0;
dev->dev_private = NULL;
return 0;
}
static int rcar_du_load(struct drm_device *dev, unsigned long flags)
{
struct platform_device *pdev = dev->platformdev;
struct device_node *np = pdev->dev.of_node;
struct rcar_du_device *rcdu;
struct resource *mem;
int ret;
if (np == NULL) {
dev_err(dev->dev, "no platform data\n");
return -ENODEV;
}
rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
if (rcdu == NULL) {
dev_err(dev->dev, "failed to allocate private data\n");
return -ENOMEM;
}
init_waitqueue_head(&rcdu->commit.wait);
rcdu->dev = &pdev->dev;
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
rcdu->ddev = dev;
dev->dev_private = rcdu;
/* I/O resources */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rcdu->mmio))
return PTR_ERR(rcdu->mmio);
/* Initialize vertical blanking interrupts handling. Start with vblank
* disabled for all CRTCs.
*/
ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize vblank\n");
goto done;
}
/* DRM/KMS objects */
ret = rcar_du_modeset_init(rcdu);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
goto done;
}
dev->irq_enabled = 1;
platform_set_drvdata(pdev, rcdu);
done:
if (ret)
rcar_du_unload(dev);
return ret;
}
static void rcar_du_lastclose(struct drm_device *dev)
{
struct rcar_du_device *rcdu = dev->dev_private;
@ -260,10 +213,7 @@ static const struct file_operations rcar_du_fops = {
static struct drm_driver rcar_du_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
| DRIVER_ATOMIC,
.load = rcar_du_load,
.unload = rcar_du_unload,
.lastclose = rcar_du_lastclose,
.set_busid = drm_platform_set_busid,
.get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = rcar_du_enable_vblank,
.disable_vblank = rcar_du_disable_vblank,
@ -323,20 +273,118 @@ static const struct dev_pm_ops rcar_du_pm_ops = {
* Platform driver
*/
static int rcar_du_probe(struct platform_device *pdev)
{
return drm_platform_init(&rcar_du_driver, pdev);
}
static int rcar_du_remove(struct platform_device *pdev)
{
struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
struct drm_device *ddev = rcdu->ddev;
drm_put_dev(rcdu->ddev);
mutex_lock(&ddev->mode_config.mutex);
drm_connector_unplug_all(ddev);
mutex_unlock(&ddev->mode_config.mutex);
drm_dev_unregister(ddev);
if (rcdu->fbdev)
drm_fbdev_cma_fini(rcdu->fbdev);
drm_kms_helper_poll_fini(ddev);
drm_mode_config_cleanup(ddev);
drm_vblank_cleanup(ddev);
drm_dev_unref(ddev);
return 0;
}
static int rcar_du_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct rcar_du_device *rcdu;
struct drm_connector *connector;
struct drm_device *ddev;
struct resource *mem;
int ret;
if (np == NULL) {
dev_err(&pdev->dev, "no device tree node\n");
return -ENODEV;
}
/* Allocate and initialize the DRM and R-Car device structures. */
rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
if (rcdu == NULL)
return -ENOMEM;
init_waitqueue_head(&rcdu->commit.wait);
rcdu->dev = &pdev->dev;
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
if (!ddev)
return -ENOMEM;
drm_dev_set_unique(ddev, dev_name(&pdev->dev));
rcdu->ddev = ddev;
ddev->dev_private = rcdu;
platform_set_drvdata(pdev, rcdu);
/* I/O resources */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rcdu->mmio)) {
ret = PTR_ERR(rcdu->mmio);
goto error;
}
/* Initialize vertical blanking interrupts handling. Start with vblank
* disabled for all CRTCs.
*/
ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize vblank\n");
goto error;
}
/* DRM/KMS objects */
ret = rcar_du_modeset_init(rcdu);
if (ret < 0) {
dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
goto error;
}
ddev->irq_enabled = 1;
/* Register the DRM device with the core and the connectors with
* sysfs.
*/
ret = drm_dev_register(ddev, 0);
if (ret)
goto error;
mutex_lock(&ddev->mode_config.mutex);
drm_for_each_connector(connector, ddev) {
ret = drm_connector_register(connector);
if (ret < 0)
break;
}
mutex_unlock(&ddev->mode_config.mutex);
if (ret < 0)
goto error;
DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
return 0;
error:
rcar_du_remove(pdev);
return ret;
}
static struct platform_driver rcar_du_platform_driver = {
.probe = rcar_du_probe,
.remove = rcar_du_remove,

View file

@ -1,7 +1,7 @@
/*
* rcar_du_drv.h -- R-Car Display Unit DRM driver
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -19,6 +19,7 @@
#include "rcar_du_crtc.h"
#include "rcar_du_group.h"
#include "rcar_du_vsp.h"
struct clk;
struct device;
@ -29,6 +30,7 @@ struct rcar_du_lvdsenc;
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
#define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */
#define RCAR_DU_FEATURE_VSP1_SOURCE (1 << 2) /* Has inputs from VSP1 */
#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */
#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */
@ -51,6 +53,7 @@ struct rcar_du_output_routing {
/*
* struct rcar_du_device_info - DU model-specific information
* @gen: device generation (2 or 3)
* @features: device features (RCAR_DU_FEATURE_*)
* @quirks: device quirks (RCAR_DU_QUIRK_*)
* @num_crtcs: total number of CRTCs
@ -58,6 +61,7 @@ struct rcar_du_output_routing {
* @num_lvds: number of internal LVDS encoders
*/
struct rcar_du_device_info {
unsigned int gen;
unsigned int features;
unsigned int quirks;
unsigned int num_crtcs;
@ -65,9 +69,10 @@ struct rcar_du_device_info {
unsigned int num_lvds;
};
#define RCAR_DU_MAX_CRTCS 3
#define RCAR_DU_MAX_CRTCS 4
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
#define RCAR_DU_MAX_LVDS 2
#define RCAR_DU_MAX_VSPS 4
struct rcar_du_device {
struct device *dev;
@ -82,6 +87,7 @@ struct rcar_du_device {
unsigned int num_crtcs;
struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
struct {
struct drm_property *alpha;
@ -90,6 +96,8 @@ struct rcar_du_device {
} props;
unsigned int dpad0_source;
unsigned int vspd1_sink;
struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
struct {

View file

@ -89,12 +89,8 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
/* The flat panel mode is fixed, just copy it to the adjusted mode. */
drm_mode_copy(adjusted_mode, panel_mode);
/* The internal LVDS encoder has a clock frequency operating range of
* 30MHz to 150MHz. Clamp the clock accordingly.
*/
if (renc->lvds)
adjusted_mode->clock = clamp(adjusted_mode->clock,
30000, 150000);
rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);
return 0;
}

View file

@ -1,7 +1,7 @@
/*
* rcar_du_group.c -- R-Car Display Unit Channels Pair
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -44,29 +44,64 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data);
}
static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
{
u32 defr6 = DEFR6_CODE | DEFR6_ODPM12_DISP;
if (rgrp->num_crtcs > 1)
defr6 |= DEFR6_ODPM22_DISP;
rcar_du_group_write(rgrp, DEFR6, defr6);
}
static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
{
u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
struct rcar_du_device *rcdu = rgrp->dev;
unsigned int possible_crtcs =
rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
u32 defr8 = DEFR8_CODE;
/* The DEFR8 register for the first group also controls RGB output
* routing to DPAD0 for DU instances that support it.
*/
if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
rgrp->index == 0)
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
if (rcdu->info->gen < 3) {
defr8 |= DEFR8_DEFE8;
/* On Gen2 the DEFR8 register for the first group also controls
* RGB output routing to DPAD0 and VSPD1 routing to DU0/1/2 for
* DU instances that support it.
*/
if (rgrp->index == 0) {
if (possible_crtcs > 1)
defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
if (rgrp->dev->vspd1_sink == 2)
defr8 |= DEFR8_VSCS;
}
} else {
/* On Gen3 VSPD routing can't be configured, but DPAD routing
* needs to be set despite having a single option available.
*/
u32 crtc = ffs(possible_crtcs) - 1;
if (crtc / 2 == rgrp->index)
defr8 |= DEFR8_DRGBS_DU(crtc);
}
rcar_du_group_write(rgrp, DEFR8, defr8);
}
static void rcar_du_group_setup(struct rcar_du_group *rgrp)
{
struct rcar_du_device *rcdu = rgrp->dev;
/* Enable extended features */
rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
if (rcdu->info->gen < 3) {
rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
}
rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
rcar_du_group_setup_pins(rgrp);
if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
rcar_du_group_setup_defr8(rgrp);
@ -82,6 +117,9 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
DIDSR_PDCS_CLK(0, 0));
}
if (rcdu->info->gen >= 3)
rcar_du_group_write(rgrp, DEFR10, DEFR10_CODE | DEFR10_DEFE10);
/* Use DS1PR and DS2PR to configure planes priorities and connects the
* superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
*/
@ -158,21 +196,23 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
void rcar_du_group_restart(struct rcar_du_group *rgrp)
{
rgrp->need_restart = false;
__rcar_du_group_start_stop(rgrp, false);
__rcar_du_group_start_stop(rgrp, true);
}
static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
{
int ret;
if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
return 0;
/* RGB output routing to DPAD0 is configured in the DEFR8 register of
* the first group. As this function can be called with the DU0 and DU1
* CRTCs disabled, we need to enable the first group clock before
* accessing the register.
/* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
* configured in the DEFR8 register of the first group. As this function
* can be called with the DU0 and DU1 CRTCs disabled, we need to enable
* the first group clock before accessing the register.
*/
ret = clk_prepare_enable(rcdu->crtcs[0].clock);
if (ret < 0)
@ -203,5 +243,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
rcar_du_group_write(rgrp, DORCR, dorcr);
return rcar_du_set_dpad0_routing(rgrp->dev);
return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
}

View file

@ -32,6 +32,7 @@ struct rcar_du_device;
* @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
* @num_planes: number of planes in the group
* @planes: planes handled by the group
* @need_restart: the group needs to be restarted due to a configuration change
*/
struct rcar_du_group {
struct rcar_du_device *dev;
@ -47,6 +48,7 @@ struct rcar_du_group {
unsigned int num_planes;
struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
bool need_restart;
};
u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
@ -58,4 +60,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
void rcar_du_group_restart(struct rcar_du_group *rgrp);
int rcar_du_group_set_routing(struct rcar_du_group *rgrp);
int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);
#endif /* __RCAR_DU_GROUP_H__ */

View file

@ -55,12 +55,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.best_encoder = rcar_du_connector_best_encoder,
};
static void rcar_du_hdmi_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
static enum drm_connector_status
rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_hdmi_connector_destroy,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@ -108,9 +102,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
ret = drm_connector_register(connector);
if (ret < 0)
return ret;
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,

View file

@ -71,12 +71,9 @@ static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
const struct drm_display_mode *mode = &crtc_state->mode;
/* The internal LVDS encoder has a clock frequency operating range of
* 30MHz to 150MHz. Clamp the clock accordingly.
*/
if (hdmienc->renc->lvds)
adjusted_mode->clock = clamp(adjusted_mode->clock,
30000, 150000);
rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
adjusted_mode);
if (sfuncs->mode_fixup == NULL)
return 0;
@ -134,12 +131,19 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
/* Locate the slave I2C device and driver. */
i2c_slave = of_find_i2c_device_by_node(np);
if (!i2c_slave || !i2c_get_clientdata(i2c_slave))
if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
dev_dbg(rcdu->dev,
"can't get I2C slave for %s, deferring probe\n",
of_node_full_name(np));
return -EPROBE_DEFER;
}
hdmienc->dev = &i2c_slave->dev;
if (hdmienc->dev->driver == NULL) {
dev_dbg(rcdu->dev,
"I2C slave %s not probed yet, deferring probe\n",
dev_name(hdmienc->dev));
ret = -EPROBE_DEFER;
goto error;
}

View file

@ -1,7 +1,7 @@
/*
* rcar_du_kms.c -- R-Car Display Unit Mode Setting
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -28,6 +28,7 @@
#include "rcar_du_kms.h"
#include "rcar_du_lvdsenc.h"
#include "rcar_du_regs.h"
#include "rcar_du_vsp.h"
/* -----------------------------------------------------------------------------
* Format helpers
@ -89,13 +90,44 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
.edf = PnDDCR4_EDF_NONE,
}, {
/* In YUV 4:2:2, only NV16 is supported (NV61 isn't) */
.fourcc = DRM_FORMAT_NV16,
.bpp = 16,
.planes = 2,
.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
.edf = PnDDCR4_EDF_NONE,
},
/* The following formats are not supported on Gen2 and thus have no
* associated .pnmr or .edf settings.
*/
{
.fourcc = DRM_FORMAT_NV61,
.bpp = 16,
.planes = 2,
}, {
.fourcc = DRM_FORMAT_YUV420,
.bpp = 12,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YVU420,
.bpp = 12,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YUV422,
.bpp = 16,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YVU422,
.bpp = 16,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YUV444,
.bpp = 24,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YVU444,
.bpp = 24,
.planes = 3,
},
};
const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc)
@ -143,6 +175,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
unsigned int max_pitch;
unsigned int align;
unsigned int bpp;
unsigned int i;
format = rcar_du_format_info(mode_cmd->pixel_format);
if (format == NULL) {
@ -155,7 +188,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
* The pitch and alignment constraints are expressed in pixels on the
* hardware side and in bytes in the DRM API.
*/
bpp = format->planes == 2 ? 1 : format->bpp / 8;
bpp = format->planes == 1 ? format->bpp / 8 : 1;
max_pitch = 4096 * bpp;
if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
@ -170,8 +203,8 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(-EINVAL);
}
if (format->planes == 2) {
if (mode_cmd->pitches[1] != mode_cmd->pitches[0]) {
for (i = 1; i < format->planes; ++i) {
if (mode_cmd->pitches[i] != mode_cmd->pitches[0]) {
dev_dbg(dev->dev,
"luma and chroma pitches do not match\n");
return ERR_PTR(-EINVAL);
@ -192,252 +225,20 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
* Atomic Check and Update
*/
/*
* Atomic hardware plane allocator
*
* The hardware plane allocator is solely based on the atomic plane states
* without keeping any external state to avoid races between .atomic_check()
* and .atomic_commit().
*
* The core idea is to avoid using a free planes bitmask that would need to be
* shared between check and commit handlers with a collective knowledge based on
* the allocated hardware plane(s) for each KMS plane. The allocator then loops
* over all plane states to compute the free planes bitmask, allocates hardware
* planes based on that bitmask, and stores the result back in the plane states.
*
* For this to work we need to access the current state of planes not touched by
* the atomic update. To ensure that it won't be modified, we need to lock all
* planes using drm_atomic_get_plane_state(). This effectively serializes atomic
* updates from .atomic_check() up to completion (when swapping the states if
* the check step has succeeded) or rollback (when freeing the states if the
* check step has failed).
*
* Allocation is performed in the .atomic_check() handler and applied
* automatically when the core swaps the old and new states.
*/
static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
struct rcar_du_plane_state *state)
{
const struct rcar_du_format_info *cur_format;
cur_format = to_rcar_plane_state(plane->plane.state)->format;
/* Lowering the number of planes doesn't strictly require reallocation
* as the extra hardware plane will be freed when committing, but doing
* so could lead to more fragmentation.
*/
return !cur_format || cur_format->planes != state->format->planes;
}
static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
{
unsigned int mask;
if (state->hwindex == -1)
return 0;
mask = 1 << state->hwindex;
if (state->format->planes == 2)
mask |= 1 << ((state->hwindex + 1) % 8);
return mask;
}
static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
{
unsigned int i;
for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
if (!(free & (1 << i)))
continue;
if (num_planes == 1 || free & (1 << ((i + 1) % 8)))
break;
}
return i == RCAR_DU_NUM_HW_PLANES ? -EBUSY : i;
}
static int rcar_du_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
struct rcar_du_device *rcdu = dev->dev_private;
unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
bool needs_realloc = false;
unsigned int groups = 0;
unsigned int i;
int ret;
ret = drm_atomic_helper_check(dev, state);
if (ret < 0)
return ret;
/* Check if hardware planes need to be reallocated. */
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
struct rcar_du_plane_state *plane_state;
struct rcar_du_plane *plane;
unsigned int index;
if (!state->planes[i])
continue;
plane = to_rcar_plane(state->planes[i]);
plane_state = to_rcar_plane_state(state->plane_states[i]);
dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
plane->group->index, plane - plane->group->planes);
/* If the plane is being disabled we don't need to go through
* the full reallocation procedure. Just mark the hardware
* plane(s) as freed.
*/
if (!plane_state->format) {
dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
__func__);
index = plane - plane->group->planes;
group_freed_planes[plane->group->index] |= 1 << index;
plane_state->hwindex = -1;
continue;
}
/* If the plane needs to be reallocated mark it as such, and
* mark the hardware plane(s) as free.
*/
if (rcar_du_plane_needs_realloc(plane, plane_state)) {
dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
__func__);
groups |= 1 << plane->group->index;
needs_realloc = true;
index = plane - plane->group->planes;
group_freed_planes[plane->group->index] |= 1 << index;
plane_state->hwindex = -1;
}
}
if (!needs_realloc)
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
return 0;
/* Grab all plane states for the groups that need reallocation to ensure
* locking and avoid racy updates. This serializes the update operation,
* but there's not much we can do about it as that's the hardware
* design.
*
* Compute the used planes mask for each group at the same time to avoid
* looping over the planes separately later.
*/
while (groups) {
unsigned int index = ffs(groups) - 1;
struct rcar_du_group *group = &rcdu->groups[index];
unsigned int used_planes = 0;
dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
__func__, index);
for (i = 0; i < group->num_planes; ++i) {
struct rcar_du_plane *plane = &group->planes[i];
struct rcar_du_plane_state *plane_state;
struct drm_plane_state *s;
s = drm_atomic_get_plane_state(state, &plane->plane);
if (IS_ERR(s))
return PTR_ERR(s);
/* If the plane has been freed in the above loop its
* hardware planes must not be added to the used planes
* bitmask. However, the current state doesn't reflect
* the free state yet, as we've modified the new state
* above. Use the local freed planes list to check for
* that condition instead.
*/
if (group_freed_planes[index] & (1 << i)) {
dev_dbg(rcdu->dev,
"%s: plane (%u,%u) has been freed, skipping\n",
__func__, plane->group->index,
plane - plane->group->planes);
continue;
}
plane_state = to_rcar_plane_state(plane->plane.state);
used_planes |= rcar_du_plane_hwmask(plane_state);
dev_dbg(rcdu->dev,
"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
__func__, plane->group->index,
plane - plane->group->planes,
plane_state->format ?
plane_state->format->planes : 0,
plane_state->hwindex);
}
group_free_planes[index] = 0xff & ~used_planes;
groups &= ~(1 << index);
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
__func__, index, group_free_planes[index]);
}
/* Reallocate hardware planes for each plane that needs it. */
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
struct rcar_du_plane_state *plane_state;
struct rcar_du_plane *plane;
unsigned int crtc_planes;
unsigned int free;
int idx;
if (!state->planes[i])
continue;
plane = to_rcar_plane(state->planes[i]);
plane_state = to_rcar_plane_state(state->plane_states[i]);
dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
plane->group->index, plane - plane->group->planes);
/* Skip planes that are being disabled or don't need to be
* reallocated.
*/
if (!plane_state->format ||
!rcar_du_plane_needs_realloc(plane, plane_state))
continue;
/* Try to allocate the plane from the free planes currently
* associated with the target CRTC to avoid restarting the CRTC
* group and thus minimize flicker. If it fails fall back to
* allocating from all free planes.
*/
crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
? plane->group->dptsr_planes
: ~plane->group->dptsr_planes;
free = group_free_planes[plane->group->index];
idx = rcar_du_plane_hwalloc(plane_state->format->planes,
free & crtc_planes);
if (idx < 0)
idx = rcar_du_plane_hwalloc(plane_state->format->planes,
free);
if (idx < 0) {
dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
__func__);
return idx;
}
dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
__func__, plane_state->format->planes, idx);
plane_state->hwindex = idx;
group_free_planes[plane->group->index] &=
~rcar_du_plane_hwmask(plane_state);
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
__func__, plane->group->index,
group_free_planes[plane->group->index]);
}
return 0;
return rcar_du_atomic_check_planes(dev, state);
}
struct rcar_du_commit {
@ -456,7 +257,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
/* Apply the atomic update. */
drm_atomic_helper_commit_modeset_disables(dev, old_state);
drm_atomic_helper_commit_modeset_enables(dev, old_state);
drm_atomic_helper_commit_planes(dev, old_state, false);
drm_atomic_helper_commit_planes(dev, old_state, true);
drm_atomic_helper_wait_for_vblanks(dev, old_state);
@ -775,14 +576,34 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U);
/* If we have more than one CRTCs in this group pre-associate
* planes 0-3 with CRTC 0 and planes 4-7 with CRTC 1 to minimize
* flicker occurring when the association is changed.
* the low-order planes with CRTC 0 and the high-order planes
* with CRTC 1 to minimize flicker occurring when the
* association is changed.
*/
rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;
rgrp->dptsr_planes = rgrp->num_crtcs > 1
? (rcdu->info->gen >= 3 ? 0x04 : 0xf0)
: 0;
ret = rcar_du_planes_init(rgrp);
if (ret < 0)
return ret;
if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
ret = rcar_du_planes_init(rgrp);
if (ret < 0)
return ret;
}
}
/* Initialize the compositors. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
for (i = 0; i < rcdu->num_crtcs; ++i) {
struct rcar_du_vsp *vsp = &rcdu->vsps[i];
vsp->index = i;
vsp->dev = rcdu;
rcdu->crtcs[i].vsp = vsp;
ret = rcar_du_vsp_init(vsp);
if (ret < 0)
return ret;
}
}
/* Create the CRTCs. */

View file

@ -62,12 +62,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.best_encoder = rcar_du_connector_best_encoder,
};
static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
static enum drm_connector_status
rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
{
@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_lvds_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_lvds_connector_destroy,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@ -117,9 +111,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
ret = drm_connector_register(connector);
if (ret < 0)
return ret;
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,

View file

@ -38,14 +38,97 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
iowrite32(data, lvds->mmio + reg);
}
static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
struct rcar_du_crtc *rcrtc)
static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds,
struct rcar_du_crtc *rcrtc)
{
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
unsigned int freq = mode->clock;
u32 lvdcr0;
u32 lvdhcr;
u32 pllcr;
/* PLL clock configuration */
if (freq < 39000)
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
else if (freq < 61000)
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
else if (freq < 121000)
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
else
pllcr = LVDPLLCR_PLLDLYCNT_150M;
rcar_lvds_write(lvds, LVDPLLCR, pllcr);
/* Select the input, hardcode mode 0, enable LVDS operation and turn
* bias circuitry on.
*/
lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN;
if (rcrtc->index == 2)
lvdcr0 |= LVDCR0_DUSEL;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
/* Turn all the channels on. */
rcar_lvds_write(lvds, LVDCR1,
LVDCR1_CHSTBY_GEN2(3) | LVDCR1_CHSTBY_GEN2(2) |
LVDCR1_CHSTBY_GEN2(1) | LVDCR1_CHSTBY_GEN2(0) |
LVDCR1_CLKSTBY_GEN2);
/* Turn the PLL on, wait for the startup delay, and turn the output
* on.
*/
lvdcr0 |= LVDCR0_PLLON;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
usleep_range(100, 150);
lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
}
static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
struct rcar_du_crtc *rcrtc)
{
const struct drm_display_mode *mode = &rcrtc->crtc.mode;
unsigned int freq = mode->clock;
u32 lvdcr0;
u32 pllcr;
/* PLL clock configuration */
if (freq < 42000)
pllcr = LVDPLLCR_PLLDIVCNT_42M;
else if (freq < 85000)
pllcr = LVDPLLCR_PLLDIVCNT_85M;
else if (freq < 128000)
pllcr = LVDPLLCR_PLLDIVCNT_128M;
else
pllcr = LVDPLLCR_PLLDIVCNT_148M;
rcar_lvds_write(lvds, LVDPLLCR, pllcr);
/* Turn the PLL on, set it to LVDS normal mode, wait for the startup
* delay and turn the output on.
*/
lvdcr0 = LVDCR0_PLLON;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
lvdcr0 |= LVDCR0_PWD;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
usleep_range(100, 150);
lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
/* Turn all the channels on. */
rcar_lvds_write(lvds, LVDCR1,
LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
LVDCR1_CLKSTBY_GEN3);
}
static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
struct rcar_du_crtc *rcrtc)
{
u32 lvdhcr;
int ret;
if (lvds->enabled)
@ -55,18 +138,6 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
if (ret < 0)
return ret;
/* PLL clock configuration */
if (freq <= 38000)
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
else if (freq <= 60000)
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
else if (freq <= 121000)
pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
else
pllcr = LVDPLLCR_PLLDLYCNT_150M;
rcar_lvds_write(lvds, LVDPLLCR, pllcr);
/* Hardcode the channels and control signals routing for now.
*
* HSYNC -> CTRL0
@ -87,30 +158,14 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
/* Select the input, hardcode mode 0, enable LVDS operation and turn
* bias circuitry on.
*/
lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN;
if (rcrtc->index == 2)
lvdcr0 |= LVDCR0_DUSEL;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
/* Turn all the channels on. */
rcar_lvds_write(lvds, LVDCR1, LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
/* Turn the PLL on, wait for the startup delay, and turn the output
* on.
*/
lvdcr0 |= LVDCR0_PLLEN;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
usleep_range(100, 150);
lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
/* Perform generation-specific initialization. */
if (lvds->dev->info->gen < 3)
rcar_du_lvdsenc_start_gen2(lvds, rcrtc);
else
rcar_du_lvdsenc_start_gen3(lvds, rcrtc);
lvds->enabled = true;
return 0;
}
@ -140,6 +195,21 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
return -EINVAL;
}
void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
struct drm_display_mode *mode)
{
struct rcar_du_device *rcdu = lvds->dev;
/* The internal LVDS encoder has a restricted clock frequency operating
* range (30MHz to 150MHz on Gen2, 25.175MHz to 148.5MHz on Gen3). Clamp
* the clock accordingly.
*/
if (rcdu->info->gen < 3)
mode->clock = clamp(mode->clock, 30000, 150000);
else
mode->clock = clamp(mode->clock, 25175, 148500);
}
static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
struct platform_device *pdev)
{

View file

@ -30,6 +30,8 @@ enum rcar_lvds_input {
int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
struct drm_crtc *crtc, bool enable);
void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
struct drm_display_mode *mode);
#else
static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
{
@ -40,6 +42,10 @@ static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
{
return 0;
}
static inline void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
struct drm_display_mode *mode)
{
}
#endif
#endif /* __RCAR_DU_LVDSENC_H__ */

View file

@ -1,7 +1,7 @@
/*
* rcar_du_plane.c -- R-Car Display Unit Planes
*
* Copyright (C) 2013-2014 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -12,6 +12,7 @@
*/
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
@ -20,21 +21,300 @@
#include <drm/drm_plane_helper.h>
#include "rcar_du_drv.h"
#include "rcar_du_group.h"
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
/* -----------------------------------------------------------------------------
* Atomic hardware plane allocator
*
* The hardware plane allocator is solely based on the atomic plane states
* without keeping any external state to avoid races between .atomic_check()
* and .atomic_commit().
*
* The core idea is to avoid using a free planes bitmask that would need to be
* shared between check and commit handlers with a collective knowledge based on
* the allocated hardware plane(s) for each KMS plane. The allocator then loops
* over all plane states to compute the free planes bitmask, allocates hardware
* planes based on that bitmask, and stores the result back in the plane states.
*
* For this to work we need to access the current state of planes not touched by
* the atomic update. To ensure that it won't be modified, we need to lock all
* planes using drm_atomic_get_plane_state(). This effectively serializes atomic
* updates from .atomic_check() up to completion (when swapping the states if
* the check step has succeeded) or rollback (when freeing the states if the
* check step has failed).
*
* Allocation is performed in the .atomic_check() handler and applied
* automatically when the core swaps the old and new states.
*/
static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
struct rcar_du_plane_state *new_state)
{
struct rcar_du_plane_state *cur_state;
cur_state = to_rcar_plane_state(plane->plane.state);
/* Lowering the number of planes doesn't strictly require reallocation
* as the extra hardware plane will be freed when committing, but doing
* so could lead to more fragmentation.
*/
if (!cur_state->format ||
cur_state->format->planes != new_state->format->planes)
return true;
/* Reallocate hardware planes if the source has changed. */
if (cur_state->source != new_state->source)
return true;
return false;
}
static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
{
unsigned int mask;
if (state->hwindex == -1)
return 0;
mask = 1 << state->hwindex;
if (state->format->planes == 2)
mask |= 1 << ((state->hwindex + 1) % 8);
return mask;
}
/*
* The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
* VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
* DU0/1 plane 1.
*
* Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
* and allocate planes in reverse index order otherwise to ensure maximum
* availability of planes 0 and 1.
*
* The caller is responsible for ensuring that the requested source is
* compatible with the DU revision.
*/
static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
struct rcar_du_plane_state *state,
unsigned int free)
{
unsigned int num_planes = state->format->planes;
int fixed = -1;
int i;
if (state->source == RCAR_DU_PLANE_VSPD0) {
/* VSPD0 feeds plane 0 on DU0/1. */
if (plane->group->index != 0)
return -EINVAL;
fixed = 0;
} else if (state->source == RCAR_DU_PLANE_VSPD1) {
/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
fixed = plane->group->index == 0 ? 1 : 0;
}
if (fixed >= 0)
return free & (1 << fixed) ? fixed : -EBUSY;
for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
if (!(free & (1 << i)))
continue;
if (num_planes == 1 || free & (1 << ((i + 1) % 8)))
break;
}
return i < 0 ? -EBUSY : i;
}
int rcar_du_atomic_check_planes(struct drm_device *dev,
struct drm_atomic_state *state)
{
struct rcar_du_device *rcdu = dev->dev_private;
unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
bool needs_realloc = false;
unsigned int groups = 0;
unsigned int i;
/* Check if hardware planes need to be reallocated. */
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
struct rcar_du_plane_state *plane_state;
struct rcar_du_plane *plane;
unsigned int index;
if (!state->planes[i])
continue;
plane = to_rcar_plane(state->planes[i]);
plane_state = to_rcar_plane_state(state->plane_states[i]);
dev_dbg(rcdu->dev, "%s: checking plane (%u,%tu)\n", __func__,
plane->group->index, plane - plane->group->planes);
/* If the plane is being disabled we don't need to go through
* the full reallocation procedure. Just mark the hardware
* plane(s) as freed.
*/
if (!plane_state->format) {
dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
__func__);
index = plane - plane->group->planes;
group_freed_planes[plane->group->index] |= 1 << index;
plane_state->hwindex = -1;
continue;
}
/* If the plane needs to be reallocated mark it as such, and
* mark the hardware plane(s) as free.
*/
if (rcar_du_plane_needs_realloc(plane, plane_state)) {
dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
__func__);
groups |= 1 << plane->group->index;
needs_realloc = true;
index = plane - plane->group->planes;
group_freed_planes[plane->group->index] |= 1 << index;
plane_state->hwindex = -1;
}
}
if (!needs_realloc)
return 0;
/* Grab all plane states for the groups that need reallocation to ensure
* locking and avoid racy updates. This serializes the update operation,
* but there's not much we can do about it as that's the hardware
* design.
*
* Compute the used planes mask for each group at the same time to avoid
* looping over the planes separately later.
*/
while (groups) {
unsigned int index = ffs(groups) - 1;
struct rcar_du_group *group = &rcdu->groups[index];
unsigned int used_planes = 0;
dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
__func__, index);
for (i = 0; i < group->num_planes; ++i) {
struct rcar_du_plane *plane = &group->planes[i];
struct rcar_du_plane_state *plane_state;
struct drm_plane_state *s;
s = drm_atomic_get_plane_state(state, &plane->plane);
if (IS_ERR(s))
return PTR_ERR(s);
/* If the plane has been freed in the above loop its
* hardware planes must not be added to the used planes
* bitmask. However, the current state doesn't reflect
* the free state yet, as we've modified the new state
* above. Use the local freed planes list to check for
* that condition instead.
*/
if (group_freed_planes[index] & (1 << i)) {
dev_dbg(rcdu->dev,
"%s: plane (%u,%tu) has been freed, skipping\n",
__func__, plane->group->index,
plane - plane->group->planes);
continue;
}
plane_state = to_rcar_plane_state(plane->plane.state);
used_planes |= rcar_du_plane_hwmask(plane_state);
dev_dbg(rcdu->dev,
"%s: plane (%u,%tu) uses %u hwplanes (index %d)\n",
__func__, plane->group->index,
plane - plane->group->planes,
plane_state->format ?
plane_state->format->planes : 0,
plane_state->hwindex);
}
group_free_planes[index] = 0xff & ~used_planes;
groups &= ~(1 << index);
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
__func__, index, group_free_planes[index]);
}
/* Reallocate hardware planes for each plane that needs it. */
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
struct rcar_du_plane_state *plane_state;
struct rcar_du_plane *plane;
unsigned int crtc_planes;
unsigned int free;
int idx;
if (!state->planes[i])
continue;
plane = to_rcar_plane(state->planes[i]);
plane_state = to_rcar_plane_state(state->plane_states[i]);
dev_dbg(rcdu->dev, "%s: allocating plane (%u,%tu)\n", __func__,
plane->group->index, plane - plane->group->planes);
/* Skip planes that are being disabled or don't need to be
* reallocated.
*/
if (!plane_state->format ||
!rcar_du_plane_needs_realloc(plane, plane_state))
continue;
/* Try to allocate the plane from the free planes currently
* associated with the target CRTC to avoid restarting the CRTC
* group and thus minimize flicker. If it fails fall back to
* allocating from all free planes.
*/
crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
? plane->group->dptsr_planes
: ~plane->group->dptsr_planes;
free = group_free_planes[plane->group->index];
idx = rcar_du_plane_hwalloc(plane, plane_state,
free & crtc_planes);
if (idx < 0)
idx = rcar_du_plane_hwalloc(plane, plane_state,
free);
if (idx < 0) {
dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
__func__);
return idx;
}
dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
__func__, plane_state->format->planes, idx);
plane_state->hwindex = idx;
group_free_planes[plane->group->index] &=
~rcar_du_plane_hwmask(plane_state);
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
__func__, plane->group->index,
group_free_planes[plane->group->index]);
}
return 0;
}
/* -----------------------------------------------------------------------------
* Plane Setup
*/
#define RCAR_DU_COLORKEY_NONE (0 << 24)
#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
#define RCAR_DU_COLORKEY_MASK (1 << 24)
static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
unsigned int index, u32 reg)
{
return rcar_du_read(rgrp->dev,
rgrp->mmio_offset + index * PLANE_OFF + reg);
}
static void rcar_du_plane_write(struct rcar_du_group *rgrp,
unsigned int index, u32 reg, u32 data)
{
@ -42,34 +322,45 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
data);
}
static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);
struct drm_framebuffer *fb = plane->plane.state->fb;
struct rcar_du_group *rgrp = plane->group;
unsigned int src_x = state->state.src_x >> 16;
unsigned int src_y = state->state.src_y >> 16;
unsigned int index = state->hwindex;
struct drm_gem_cma_object *gem;
unsigned int pitch;
bool interlaced;
u32 mwr;
u32 dma[2];
interlaced = state->state.crtc->state->adjusted_mode.flags
& DRM_MODE_FLAG_INTERLACE;
if (state->source == RCAR_DU_PLANE_MEMORY) {
struct drm_framebuffer *fb = state->state.fb;
struct drm_gem_cma_object *gem;
unsigned int i;
if (state->format->planes == 2)
pitch = fb->pitches[0];
else
pitch = fb->pitches[0] * 8 / state->format->bpp;
for (i = 0; i < state->format->planes; ++i) {
gem = drm_fb_cma_get_gem_obj(fb, i);
dma[i] = gem->paddr + fb->offsets[i];
}
} else {
pitch = state->state.src_w >> 16;
dma[0] = 0;
dma[1] = 0;
}
/* Memory pitch (expressed in pixels). Must be doubled for interlaced
* operation with 32bpp formats.
*/
if (state->format->planes == 2)
mwr = fb->pitches[0];
else
mwr = fb->pitches[0] * 8 / state->format->bpp;
if (interlaced && state->format->bpp == 32)
mwr *= 2;
rcar_du_plane_write(rgrp, index, PnMWR, mwr);
rcar_du_plane_write(rgrp, index, PnMWR,
(interlaced && state->format->bpp == 32) ?
pitch * 2 : pitch);
/* The Y position is expressed in raster line units and must be doubled
* for 32bpp formats, according to the R8A7790 datasheet. No mention of
@ -87,30 +378,25 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(!interlaced && state->format->bpp == 32 ? 2 : 1));
gem = drm_fb_cma_get_gem_obj(fb, 0);
rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
rcar_du_plane_write(rgrp, index, PnDSA0R, dma[0]);
if (state->format->planes == 2) {
index = (index + 1) % 8;
rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
rcar_du_plane_write(rgrp, index, PnMWR, pitch);
rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(state->format->bpp == 16 ? 2 : 1) / 2);
gem = drm_fb_cma_get_gem_obj(fb, 1);
rcar_du_plane_write(rgrp, index, PnDSA0R,
gem->paddr + fb->offsets[1]);
rcar_du_plane_write(rgrp, index, PnDSA0R, dma[1]);
}
}
static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
unsigned int index)
static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
unsigned int index,
const struct rcar_du_plane_state *state)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);
struct rcar_du_group *rgrp = plane->group;
u32 colorkey;
u32 pnmr;
@ -168,12 +454,10 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
}
}
static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
unsigned int index)
static void rcar_du_plane_setup_format_gen2(struct rcar_du_group *rgrp,
unsigned int index,
const struct rcar_du_plane_state *state)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);
struct rcar_du_group *rgrp = plane->group;
u32 ddcr2 = PnDDCR2_CODE;
u32 ddcr4;
@ -182,11 +466,8 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
* The data format is selected by the DDDF field in PnMR and the EDF
* field in DDCR4.
*/
ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
ddcr4 &= ~PnDDCR4_EDF_MASK;
ddcr4 |= state->format->edf | PnDDCR4_CODE;
rcar_du_plane_setup_mode(plane, index);
rcar_du_plane_setup_mode(rgrp, index, state);
if (state->format->planes == 2) {
if (state->hwindex != index) {
@ -204,31 +485,72 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
}
rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
ddcr4 = state->format->edf | PnDDCR4_CODE;
if (state->source != RCAR_DU_PLANE_MEMORY)
ddcr4 |= PnDDCR4_VSPS;
rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
/* Destination position and size */
rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
/* Wrap-around and blinking, disabled */
rcar_du_plane_write(rgrp, index, PnWASPR, 0);
rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
rcar_du_plane_write(rgrp, index, PnBTR, 0);
rcar_du_plane_write(rgrp, index, PnMLR, 0);
}
void rcar_du_plane_setup(struct rcar_du_plane *plane)
static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
unsigned int index,
const struct rcar_du_plane_state *state)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);
rcar_du_plane_write(rgrp, index, PnMR,
PnMR_SPIM_TP_OFF | state->format->pnmr);
__rcar_du_plane_setup(plane, state->hwindex);
rcar_du_plane_write(rgrp, index, PnDDCR4,
state->format->edf | PnDDCR4_CODE);
}
static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
unsigned int index,
const struct rcar_du_plane_state *state)
{
struct rcar_du_device *rcdu = rgrp->dev;
if (rcdu->info->gen < 3)
rcar_du_plane_setup_format_gen2(rgrp, index, state);
else
rcar_du_plane_setup_format_gen3(rgrp, index, state);
/* Destination position and size */
rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
if (rcdu->info->gen < 3) {
/* Wrap-around and blinking, disabled */
rcar_du_plane_write(rgrp, index, PnWASPR, 0);
rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
rcar_du_plane_write(rgrp, index, PnBTR, 0);
rcar_du_plane_write(rgrp, index, PnMLR, 0);
}
}
void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state)
{
struct rcar_du_device *rcdu = rgrp->dev;
rcar_du_plane_setup_format(rgrp, state->hwindex, state);
if (state->format->planes == 2)
__rcar_du_plane_setup(plane, (state->hwindex + 1) % 8);
rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
state);
rcar_du_plane_setup_fb(plane);
if (rcdu->info->gen < 3)
rcar_du_plane_setup_scanout(rgrp, state);
if (state->source == RCAR_DU_PLANE_VSPD1) {
unsigned int vspd1_sink = rgrp->index ? 2 : 0;
if (rcdu->vspd1_sink != vspd1_sink) {
rcdu->vspd1_sink = vspd1_sink;
rcar_du_set_dpad0_vsp1_routing(rcdu);
}
}
}
static int rcar_du_plane_atomic_check(struct drm_plane *plane,
@ -263,9 +585,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_plane_state *old_rstate;
struct rcar_du_plane_state *new_rstate;
if (plane->state->crtc)
rcar_du_plane_setup(rplane);
if (!plane->state->crtc)
return;
rcar_du_plane_setup(rplane);
/* Check whether the source has changed from memory to live source or
* from live source to memory. The source has been configured by the
* VSPS bit in the PnDDCR4 register. Although the datasheet states that
* the bit is updated during vertical blanking, it seems that updates
* only occur when the DU group is held in reset through the DSYSR.DRES
* bit. We thus need to restart the group if the source changes.
*/
old_rstate = to_rcar_plane_state(old_state);
new_rstate = to_rcar_plane_state(plane->state);
if ((old_rstate->source == RCAR_DU_PLANE_MEMORY) !=
(new_rstate->source == RCAR_DU_PLANE_MEMORY))
rplane->group->need_restart = true;
}
static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
@ -313,6 +653,7 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
return;
state->hwindex = -1;
state->source = RCAR_DU_PLANE_MEMORY;
state->alpha = 255;
state->colorkey = RCAR_DU_COLORKEY_NONE;
state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;

View file

@ -28,6 +28,12 @@ struct rcar_du_group;
#define RCAR_DU_NUM_KMS_PLANES 9
#define RCAR_DU_NUM_HW_PLANES 8
enum rcar_du_plane_source {
RCAR_DU_PLANE_MEMORY,
RCAR_DU_PLANE_VSPD0,
RCAR_DU_PLANE_VSPD1,
};
struct rcar_du_plane {
struct drm_plane plane;
struct rcar_du_group *group;
@ -52,6 +58,7 @@ struct rcar_du_plane_state {
const struct rcar_du_format_info *format;
int hwindex;
enum rcar_du_plane_source source;
unsigned int alpha;
unsigned int colorkey;
@ -64,8 +71,20 @@ to_rcar_plane_state(struct drm_plane_state *state)
return container_of(state, struct rcar_du_plane_state, state);
}
int rcar_du_atomic_check_planes(struct drm_device *dev,
struct drm_atomic_state *state);
int rcar_du_planes_init(struct rcar_du_group *rgrp);
void rcar_du_plane_setup(struct rcar_du_plane *plane);
void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state);
static inline void rcar_du_plane_setup(struct rcar_du_plane *plane)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);
return __rcar_du_plane_setup(plane->group, state);
}
#endif /* __RCAR_DU_PLANE_H__ */

View file

@ -1,7 +1,7 @@
/*
* rcar_du_regs.h -- R-Car Display Unit Registers Definitions
*
* Copyright (C) 2013 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -16,6 +16,7 @@
#define DU0_REG_OFFSET 0x00000
#define DU1_REG_OFFSET 0x30000
#define DU2_REG_OFFSET 0x40000
#define DU3_REG_OFFSET 0x70000
/* -----------------------------------------------------------------------------
* Display Control Registers
@ -186,7 +187,7 @@
#define DEFR6 0x000e8
#define DEFR6_CODE (0x7778 << 16)
#define DEFR6_ODPM22_D2SMR (0 << 10)
#define DEFR6_ODPM22_DSMR (0 << 10)
#define DEFR6_ODPM22_DISP (2 << 10)
#define DEFR6_ODPM22_CDE (3 << 10)
#define DEFR6_ODPM22_MASK (3 << 10)
@ -260,6 +261,21 @@
#define DIDSR_PDCS_CLK(n, clk) (clk << ((n) * 2))
#define DIDSR_PDCS_MASK(n) (3 << ((n) * 2))
#define DEFR10 0x20038
#define DEFR10_CODE (0x7795 << 16)
#define DEFR10_VSPF1_RGB (0 << 14)
#define DEFR10_VSPF1_YC (1 << 14)
#define DEFR10_DOCF1_RGB (0 << 12)
#define DEFR10_DOCF1_YC (1 << 12)
#define DEFR10_YCDF0_YCBCR444 (0 << 11)
#define DEFR10_YCDF0_YCBCR422 (1 << 11)
#define DEFR10_VSPF0_RGB (0 << 10)
#define DEFR10_VSPF0_YC (1 << 10)
#define DEFR10_DOCF0_RGB (0 << 8)
#define DEFR10_DOCF0_YC (1 << 8)
#define DEFR10_TSEL_H3_TCON1 (0 << 1) /* DEFR102 register only (DU2/DU3) */
#define DEFR10_DEFE10 (1 << 0)
/* -----------------------------------------------------------------------------
* Display Timing Generation Registers
*/
@ -389,6 +405,7 @@
#define PnDDCR4 0x00190
#define PnDDCR4_CODE (0x7766 << 16)
#define PnDDCR4_VSPS (1 << 13)
#define PnDDCR4_SDFS_RGB (0 << 4)
#define PnDDCR4_SDFS_YC (5 << 4)
#define PnDDCR4_SDFS_MASK (7 << 4)

View file

@ -31,12 +31,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.best_encoder = rcar_du_connector_best_encoder,
};
static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
}
static enum drm_connector_status
rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
{
@ -48,7 +42,7 @@ static const struct drm_connector_funcs connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_vga_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rcar_du_vga_connector_destroy,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@ -76,9 +70,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
ret = drm_connector_register(connector);
if (ret < 0)
return ret;
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,

View file

@ -0,0 +1,384 @@
/*
* rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor
*
* Copyright (C) 2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h>
#include <linux/of_platform.h>
#include <linux/videodev2.h>
#include <media/vsp1.h>
#include "rcar_du_drv.h"
#include "rcar_du_kms.h"
#include "rcar_du_vsp.h"
void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
{
const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
struct rcar_du_device *rcdu = crtc->group->dev;
struct rcar_du_plane_state state = {
.state = {
.crtc = &crtc->crtc,
.crtc_x = 0,
.crtc_y = 0,
.crtc_w = mode->hdisplay,
.crtc_h = mode->vdisplay,
.src_x = 0,
.src_y = 0,
.src_w = mode->hdisplay << 16,
.src_h = mode->vdisplay << 16,
},
.format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
.source = RCAR_DU_PLANE_VSPD1,
.alpha = 255,
.colorkey = 0,
.zpos = 0,
};
if (rcdu->info->gen >= 3)
state.hwindex = (crtc->index % 2) ? 2 : 0;
else
state.hwindex = crtc->index % 2;
__rcar_du_plane_setup(crtc->group, &state);
/* Ensure that the plane source configuration takes effect by requesting
* a restart of the group. See rcar_du_plane_atomic_update() for a more
* detailed explanation.
*
* TODO: Check whether this is still needed on Gen3.
*/
crtc->group->need_restart = true;
vsp1_du_setup_lif(crtc->vsp->vsp, mode->hdisplay, mode->vdisplay);
}
void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
{
vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0);
}
void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
{
vsp1_du_atomic_begin(crtc->vsp->vsp);
}
void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
{
vsp1_du_atomic_flush(crtc->vsp->vsp);
}
/* Keep the two tables in sync. */
static const u32 formats_kms[] = {
DRM_FORMAT_RGB332,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR888,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_UYVY,
DRM_FORMAT_VYUY,
DRM_FORMAT_YUYV,
DRM_FORMAT_YVYU,
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
DRM_FORMAT_NV16,
DRM_FORMAT_NV61,
DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420,
DRM_FORMAT_YUV422,
DRM_FORMAT_YVU422,
DRM_FORMAT_YUV444,
DRM_FORMAT_YVU444,
};
static const u32 formats_v4l2[] = {
V4L2_PIX_FMT_RGB332,
V4L2_PIX_FMT_ARGB444,
V4L2_PIX_FMT_XRGB444,
V4L2_PIX_FMT_ARGB555,
V4L2_PIX_FMT_XRGB555,
V4L2_PIX_FMT_RGB565,
V4L2_PIX_FMT_RGB24,
V4L2_PIX_FMT_BGR24,
V4L2_PIX_FMT_ARGB32,
V4L2_PIX_FMT_XRGB32,
V4L2_PIX_FMT_ABGR32,
V4L2_PIX_FMT_XBGR32,
V4L2_PIX_FMT_UYVY,
V4L2_PIX_FMT_VYUY,
V4L2_PIX_FMT_YUYV,
V4L2_PIX_FMT_YVYU,
V4L2_PIX_FMT_NV12M,
V4L2_PIX_FMT_NV21M,
V4L2_PIX_FMT_NV16M,
V4L2_PIX_FMT_NV61M,
V4L2_PIX_FMT_YUV420M,
V4L2_PIX_FMT_YVU420M,
V4L2_PIX_FMT_YUV422M,
V4L2_PIX_FMT_YVU422M,
V4L2_PIX_FMT_YUV444M,
V4L2_PIX_FMT_YVU444M,
};
static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
{
struct rcar_du_vsp_plane_state *state =
to_rcar_vsp_plane_state(plane->plane.state);
struct drm_framebuffer *fb = plane->plane.state->fb;
struct v4l2_rect src;
struct v4l2_rect dst;
dma_addr_t paddr[2] = { 0, };
u32 pixelformat = 0;
unsigned int i;
src.left = state->state.src_x >> 16;
src.top = state->state.src_y >> 16;
src.width = state->state.src_w >> 16;
src.height = state->state.src_h >> 16;
dst.left = state->state.crtc_x;
dst.top = state->state.crtc_y;
dst.width = state->state.crtc_w;
dst.height = state->state.crtc_h;
for (i = 0; i < state->format->planes; ++i) {
struct drm_gem_cma_object *gem;
gem = drm_fb_cma_get_gem_obj(fb, i);
paddr[i] = gem->paddr + fb->offsets[i];
}
for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) {
if (formats_kms[i] == state->format->fourcc) {
pixelformat = formats_v4l2[i];
break;
}
}
WARN_ON(!pixelformat);
vsp1_du_atomic_update(plane->vsp->vsp, plane->index, pixelformat,
fb->pitches[0], paddr, &src, &dst);
}
static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
struct rcar_du_device *rcdu = rplane->vsp->dev;
if (!state->fb || !state->crtc) {
rstate->format = NULL;
return 0;
}
if (state->src_w >> 16 != state->crtc_w ||
state->src_h >> 16 != state->crtc_h) {
dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
return -EINVAL;
}
rstate->format = rcar_du_format_info(state->fb->pixel_format);
if (rstate->format == NULL) {
dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
state->fb->pixel_format);
return -EINVAL;
}
return 0;
}
static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
if (plane->state->crtc)
rcar_du_vsp_plane_setup(rplane);
else
vsp1_du_atomic_update(rplane->vsp->vsp, rplane->index, 0, 0, 0,
NULL, NULL);
}
static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
.atomic_check = rcar_du_vsp_plane_atomic_check,
.atomic_update = rcar_du_vsp_plane_atomic_update,
};
static struct drm_plane_state *
rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
{
struct rcar_du_vsp_plane_state *state;
struct rcar_du_vsp_plane_state *copy;
if (WARN_ON(!plane->state))
return NULL;
state = to_rcar_vsp_plane_state(plane->state);
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
if (copy == NULL)
return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
return &copy->state;
}
static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
__drm_atomic_helper_plane_destroy_state(plane, state);
kfree(to_rcar_vsp_plane_state(state));
}
static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
{
struct rcar_du_vsp_plane_state *state;
if (plane->state) {
rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state);
plane->state = NULL;
}
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
return;
state->alpha = 255;
plane->state = &state->state;
plane->state->plane = plane;
}
static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane,
struct drm_plane_state *state, struct drm_property *property,
uint64_t val)
{
struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev;
if (property == rcdu->props.alpha)
rstate->alpha = val;
else
return -EINVAL;
return 0;
}
static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane,
const struct drm_plane_state *state, struct drm_property *property,
uint64_t *val)
{
const struct rcar_du_vsp_plane_state *rstate =
container_of(state, const struct rcar_du_vsp_plane_state, state);
struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev;
if (property == rcdu->props.alpha)
*val = rstate->alpha;
else
return -EINVAL;
return 0;
}
static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.reset = rcar_du_vsp_plane_reset,
.set_property = drm_atomic_helper_plane_set_property,
.destroy = drm_plane_cleanup,
.atomic_duplicate_state = rcar_du_vsp_plane_atomic_duplicate_state,
.atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state,
.atomic_set_property = rcar_du_vsp_plane_atomic_set_property,
.atomic_get_property = rcar_du_vsp_plane_atomic_get_property,
};
int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
{
struct rcar_du_device *rcdu = vsp->dev;
struct platform_device *pdev;
struct device_node *np;
unsigned int i;
int ret;
/* Find the VSP device and initialize it. */
np = of_parse_phandle(rcdu->dev->of_node, "vsps", vsp->index);
if (!np) {
dev_err(rcdu->dev, "vsps node not found\n");
return -ENXIO;
}
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev)
return -ENXIO;
vsp->vsp = &pdev->dev;
ret = vsp1_du_init(vsp->vsp);
if (ret < 0)
return ret;
/* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
* 4 RPFs.
*/
vsp->num_planes = rcdu->info->gen >= 3 ? 5 : 4;
vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
sizeof(*vsp->planes), GFP_KERNEL);
if (!vsp->planes)
return -ENOMEM;
for (i = 0; i < vsp->num_planes; ++i) {
enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY
: DRM_PLANE_TYPE_PRIMARY;
struct rcar_du_vsp_plane *plane = &vsp->planes[i];
plane->vsp = vsp;
plane->index = i;
ret = drm_universal_plane_init(rcdu->ddev, &plane->plane,
1 << vsp->index,
&rcar_du_vsp_plane_funcs,
formats_kms,
ARRAY_SIZE(formats_kms), type,
NULL);
if (ret < 0)
return ret;
drm_plane_helper_add(&plane->plane,
&rcar_du_vsp_plane_helper_funcs);
if (type == DRM_PLANE_TYPE_PRIMARY)
continue;
drm_object_attach_property(&plane->plane.base,
rcdu->props.alpha, 255);
}
return 0;
}

View file

@ -0,0 +1,76 @@
/*
* rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor
*
* Copyright (C) 2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __RCAR_DU_VSP_H__
#define __RCAR_DU_VSP_H__
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
struct rcar_du_format_info;
struct rcar_du_vsp;
struct rcar_du_vsp_plane {
struct drm_plane plane;
struct rcar_du_vsp *vsp;
unsigned int index;
};
struct rcar_du_vsp {
unsigned int index;
struct device *vsp;
struct rcar_du_device *dev;
struct rcar_du_vsp_plane *planes;
unsigned int num_planes;
};
static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p)
{
return container_of(p, struct rcar_du_vsp_plane, plane);
}
/**
* struct rcar_du_vsp_plane_state - Driver-specific plane state
* @state: base DRM plane state
* @format: information about the pixel format used by the plane
* @alpha: value of the plane alpha property
*/
struct rcar_du_vsp_plane_state {
struct drm_plane_state state;
const struct rcar_du_format_info *format;
unsigned int alpha;
};
static inline struct rcar_du_vsp_plane_state *
to_rcar_vsp_plane_state(struct drm_plane_state *state)
{
return container_of(state, struct rcar_du_vsp_plane_state, state);
}
#ifdef CONFIG_DRM_RCAR_VSP
int rcar_du_vsp_init(struct rcar_du_vsp *vsp);
void rcar_du_vsp_enable(struct rcar_du_crtc *crtc);
void rcar_du_vsp_disable(struct rcar_du_crtc *crtc);
void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc);
void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc);
#else
static inline int rcar_du_vsp_init(struct rcar_du_vsp *vsp) { return 0; };
static inline void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { };
static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { };
static inline void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) { };
static inline void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { };
#endif
#endif /* __RCAR_DU_VSP_H__ */

View file

@ -1,7 +1,7 @@
/*
* rcar_lvds_regs.h -- R-Car LVDS Interface Registers Definitions
*
* Copyright (C) 2013 Renesas Electronics Corporation
* Copyright (C) 2013-2015 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
@ -15,28 +15,38 @@
#define LVDCR0 0x0000
#define LVDCR0_DUSEL (1 << 15)
#define LVDCR0_DMD (1 << 12)
#define LVDCR0_DMD (1 << 12) /* Gen2 only */
#define LVDCR0_LVMD_MASK (0xf << 8)
#define LVDCR0_LVMD_SHIFT 8
#define LVDCR0_PLLEN (1 << 4)
#define LVDCR0_BEN (1 << 2)
#define LVDCR0_LVEN (1 << 1)
#define LVDCR0_PLLON (1 << 4)
#define LVDCR0_PWD (1 << 2) /* Gen3 only */
#define LVDCR0_BEN (1 << 2) /* Gen2 only */
#define LVDCR0_LVEN (1 << 1) /* Gen2 only */
#define LVDCR0_LVRES (1 << 0)
#define LVDCR1 0x0004
#define LVDCR1_CKSEL (1 << 15)
#define LVDCR1_CHSTBY(n) (3 << (2 + (n) * 2))
#define LVDCR1_CLKSTBY (3 << 0)
#define LVDCR1_CKSEL (1 << 15) /* Gen2 only */
#define LVDCR1_CHSTBY_GEN2(n) (3 << (2 + (n) * 2)) /* Gen2 only */
#define LVDCR1_CHSTBY_GEN3(n) (1 << (2 + (n) * 2)) /* Gen3 only */
#define LVDCR1_CLKSTBY_GEN2 (3 << 0) /* Gen2 only */
#define LVDCR1_CLKSTBY_GEN3 (1 << 0) /* Gen3 only */
#define LVDPLLCR 0x0008
#define LVDPLLCR_CEEN (1 << 14)
#define LVDPLLCR_FBEN (1 << 13)
#define LVDPLLCR_COSEL (1 << 12)
/* Gen2 */
#define LVDPLLCR_PLLDLYCNT_150M (0x1bf << 0)
#define LVDPLLCR_PLLDLYCNT_121M (0x22c << 0)
#define LVDPLLCR_PLLDLYCNT_60M (0x77b << 0)
#define LVDPLLCR_PLLDLYCNT_38M (0x69a << 0)
#define LVDPLLCR_PLLDLYCNT_MASK (0x7ff << 0)
/* Gen3 */
#define LVDPLLCR_PLLDIVCNT_42M (0x014cb << 0)
#define LVDPLLCR_PLLDIVCNT_85M (0x00a45 << 0)
#define LVDPLLCR_PLLDIVCNT_128M (0x006c3 << 0)
#define LVDPLLCR_PLLDIVCNT_148M (0x046c1 << 0)
#define LVDPLLCR_PLLDIVCNT_MASK (0x7ffff << 0)
#define LVDCTRCR 0x000c
#define LVDCTRCR_CTR3SEL_ZERO (0 << 12)

View file

@ -38,7 +38,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
#endif
/* lnb control */
#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
#if (FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)) && FE_SUPPORTED(PLL)
static int flexcop_set_voltage(struct dvb_frontend *fe,
enum fe_sec_voltage voltage)
{
@ -68,7 +68,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe,
#endif
#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
static int flexcop_sleep(struct dvb_frontend* fe)
static int __maybe_unused flexcop_sleep(struct dvb_frontend* fe)
{
struct flexcop_device *fc = fe->dvb->priv;
if (fc->fe_sleep)

View file

@ -1,7 +1,7 @@
/*
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* flexcop.c - main module part
* Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de>
* Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@posteo.de>
* based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
*
* Acknowledgements:
@ -34,7 +34,7 @@
#include "flexcop.h"
#define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip"
#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de"
#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@posteo.de"
#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
#define DEBSTATUS ""

View file

@ -1,6 +1,6 @@
/* cypress_firmware.c is part of the DVB USB library.
*
* Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
* see dvb-usb-init.c for copyright information.
*
* This file contains functions for downloading the firmware to Cypress FX 1

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
* see dvb-usb-init.c for copyright information.
*
* This file contains functions for downloading the firmware to Cypress FX 1

View file

@ -1167,8 +1167,8 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
return rc;
}
pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size);
fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
GFP_KERNEL | GFP_DMA);
fw_buf = kmalloc(ALIGN(fw->size + sizeof(struct sms_firmware),
SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA);
if (!fw_buf) {
pr_err("failed to allocate firmware buffer\n");
rc = -ENOMEM;

View file

@ -1015,12 +1015,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe)
}
}
/* Nothing to do here, as stats are automatically updated */
static int smsdvb_get_frontend(struct dvb_frontend *fe)
{
return 0;
}
static int smsdvb_init(struct dvb_frontend *fe)
{
struct smsdvb_client_t *client =
@ -1069,7 +1063,6 @@ static struct dvb_frontend_ops smsdvb_fe_ops = {
.release = smsdvb_release,
.set_frontend = smsdvb_set_frontend,
.get_frontend = smsdvb_get_frontend,
.get_tune_settings = smsdvb_get_tune_settings,
.read_status = smsdvb_read_status,

View file

@ -1,6 +1,6 @@
/* dvb-usb-ids.h is part of the DVB USB library.
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) see
* dvb-usb-init.c for copyright information.
*
* a header file containing define's for the USB device supported by the
@ -118,6 +118,7 @@
#define USB_PID_DIBCOM_STK807XP 0x1f90
#define USB_PID_DIBCOM_STK807XPVR 0x1f98
#define USB_PID_DIBCOM_STK8096GP 0x1fa0
#define USB_PID_DIBCOM_STK8096PVR 0x1faa
#define USB_PID_DIBCOM_NIM8096MD 0x1fa8
#define USB_PID_DIBCOM_TFE8096P 0x1f9C
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
@ -247,6 +248,7 @@
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
#define USB_PID_TECHNOTREND_CONNECT_S2_4600 0x3011
#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012
#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2 0x3015
#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
@ -255,6 +257,10 @@
#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
#define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab
#define USB_PID_TERRATEC_CINERGY_S2_R1 0x00a8
#define USB_PID_TERRATEC_CINERGY_S2_R2 0x00b0
#define USB_PID_TERRATEC_CINERGY_S2_R3 0x0102
#define USB_PID_TERRATEC_CINERGY_S2_R4 0x0105
#define USB_PID_TERRATEC_H7 0x10b4
#define USB_PID_TERRATEC_H7_2 0x10a3
#define USB_PID_TERRATEC_H7_3 0x10a5

View file

@ -140,9 +140,12 @@ struct dvb_frontend_private {
static void dvb_frontend_wakeup(struct dvb_frontend *fe);
static int dtv_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c,
struct dvb_frontend_parameters *p_out);
static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p);
static int
dtv_property_legacy_params_sync(struct dvb_frontend *fe,
const struct dtv_frontend_properties *c,
struct dvb_frontend_parameters *p);
static bool has_get_frontend(struct dvb_frontend *fe)
{
@ -202,6 +205,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe,
enum fe_status status)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_fe_events *events = &fepriv->events;
struct dvb_frontend_event *e;
int wp;
@ -209,7 +213,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe,
dev_dbg(fe->dvb->device, "%s:\n", __func__);
if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
dtv_get_frontend(fe, &fepriv->parameters_out);
dtv_get_frontend(fe, c, &fepriv->parameters_out);
mutex_lock(&events->mtx);
@ -687,6 +691,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe)
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
enum fe_status s;
enum dvbfe_algo algo;
@ -807,7 +812,7 @@ restart:
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
fepriv->delay = HZ / 2;
}
dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out);
fe->ops.read_status(fe, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s); /* update event list */
@ -899,10 +904,10 @@ void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec)
s32 delta;
*waketime = ktime_add_us(*waketime, add_usec);
delta = ktime_us_delta(ktime_get_real(), *waketime);
delta = ktime_us_delta(ktime_get_boottime(), *waketime);
if (delta > 2500) {
msleep((delta - 1500) / 1000);
delta = ktime_us_delta(ktime_get_real(), *waketime);
delta = ktime_us_delta(ktime_get_boottime(), *waketime);
}
if (delta > 0)
udelay(delta);
@ -1162,18 +1167,24 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0),
};
static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
static void dtv_property_dump(struct dvb_frontend *fe,
bool is_set,
struct dtv_property *tvp)
{
int i;
if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n",
__func__, tvp->cmd);
dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n",
__func__,
is_set ? "SET" : "GET",
tvp->cmd);
return;
}
dev_dbg(fe->dvb->device, "%s: tvp.cmd = 0x%08x (%s)\n", __func__,
tvp->cmd, dtv_cmds[tvp->cmd].name);
dev_dbg(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x (%s)\n", __func__,
is_set ? "SET" : "GET",
tvp->cmd,
dtv_cmds[tvp->cmd].name);
if (dtv_cmds[tvp->cmd].buffer) {
dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n",
@ -1268,11 +1279,11 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
/* Ensure the cached values are set correctly in the frontend
* legacy tuning structures, for the advanced tuning API.
*/
static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
static int
dtv_property_legacy_params_sync(struct dvb_frontend *fe,
const struct dtv_frontend_properties *c,
struct dvb_frontend_parameters *p)
{
const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
p->frequency = c->frequency;
p->inversion = c->inversion;
@ -1344,16 +1355,17 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
* If p_out is not null, it will update the DVBv3 params pointed by it.
*/
static int dtv_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c,
struct dvb_frontend_parameters *p_out)
{
int r;
if (fe->ops.get_frontend) {
r = fe->ops.get_frontend(fe);
r = fe->ops.get_frontend(fe, c);
if (unlikely(r < 0))
return r;
if (p_out)
dtv_property_legacy_params_sync(fe, p_out);
dtv_property_legacy_params_sync(fe, c, p_out);
return 0;
}
@ -1589,7 +1601,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
return r;
}
dtv_property_dump(fe, tvp);
dtv_property_dump(fe, false, tvp);
return 0;
}
@ -1830,6 +1842,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
return r;
}
dtv_property_dump(fe, true, tvp);
switch(tvp->cmd) {
case DTV_CLEAR:
/*
@ -2073,6 +2087,8 @@ static int dvb_frontend_ioctl_properties(struct file *file,
dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
} else if (cmd == FE_GET_PROPERTY) {
struct dtv_frontend_properties getp = fe->dtv_property_cache;
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
@ -2094,17 +2110,18 @@ static int dvb_frontend_ioctl_properties(struct file *file,
}
/*
* Fills the cache out struct with the cache contents, plus
* the data retrieved from get_frontend, if the frontend
* is not idle. Otherwise, returns the cached content
* Let's use our own copy of property cache, in order to
* avoid mangling with DTV zigzag logic, as drivers might
* return crap, if they don't check if the data is available
* before updating the properties cache.
*/
if (fepriv->state != FESTATE_IDLE) {
err = dtv_get_frontend(fe, NULL);
err = dtv_get_frontend(fe, &getp, NULL);
if (err < 0)
goto out;
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_get(fe, c, tvp + i, file);
err = dtv_property_process_get(fe, &getp, tvp + i, file);
if (err < 0)
goto out;
(tvp + i)->result = err;
@ -2139,7 +2156,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
* the user. FE_SET_FRONTEND triggers an initial frontend event
* with status = 0, which copies output parameters to userspace.
*/
dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out);
/*
* Be sure that the bandwidth will be filled for all
@ -2451,7 +2468,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
u8 last = 1;
if (dvb_frontend_debug)
printk("%s switch command: 0x%04lx\n", __func__, swcmd);
nexttime = ktime_get_real();
nexttime = ktime_get_boottime();
if (dvb_frontend_debug)
tv[0] = nexttime;
/* before sending a command, initialize by sending
@ -2462,7 +2479,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
for (i = 0; i < 9; i++) {
if (dvb_frontend_debug)
tv[i+1] = ktime_get_real();
tv[i+1] = ktime_get_boottime();
if ((swcmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
@ -2509,10 +2526,18 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
err = dvb_frontend_get_event (fe, parg, file->f_flags);
break;
case FE_GET_FRONTEND:
err = dtv_get_frontend(fe, parg);
break;
case FE_GET_FRONTEND: {
struct dtv_frontend_properties getp = fe->dtv_property_cache;
/*
* Let's use our own copy of property cache, in order to
* avoid mangling with DTV zigzag logic, as drivers might
* return crap, if they don't check if the data is available
* before updating the properties cache.
*/
err = dtv_get_frontend(fe, &getp, parg);
break;
}
case FE_SET_FRONTEND_TUNE_MODE:
fepriv->tune_mode_flags = (unsigned long) parg;
err = 0;

View file

@ -449,7 +449,8 @@ struct dvb_frontend_ops {
int (*set_frontend)(struct dvb_frontend *fe);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
int (*get_frontend)(struct dvb_frontend *fe);
int (*get_frontend)(struct dvb_frontend *fe,
struct dtv_frontend_properties *props);
int (*read_status)(struct dvb_frontend *fe, enum fe_status *status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);

View file

@ -58,7 +58,7 @@ static const char * const dnames[] = {
#define DVB_MAX_IDS MAX_DVB_MINORS
#else
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type)
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
#endif
@ -85,7 +85,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
file->private_data = dvbdev;
replace_fops(file, new_fops);
if (file->f_op->open)
err = file->f_op->open(inode,file);
err = file->f_op->open(inode, file);
up_read(&minor_rwsem);
mutex_unlock(&dvbdev_mutex);
return err;
@ -352,7 +352,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev,
ret = media_device_register_entity(dvbdev->adapter->mdev,
dvbdev->entity);
if (ret)
return (ret);
return ret;
printk(KERN_DEBUG "%s: media entity '%s' registered.\n",
__func__, dvbdev->entity->name);
@ -620,8 +620,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
return -ENOMEM;
adap->conn = conn;
adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads),
GFP_KERNEL);
adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL);
if (!adap->conn_pads)
return -ENOMEM;
@ -661,7 +660,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
if (ntuner && ndemod) {
ret = media_create_pad_links(mdev,
MEDIA_ENT_F_TUNER,
tuner, TUNER_PAD_IF_OUTPUT,
tuner, TUNER_PAD_OUTPUT,
MEDIA_ENT_F_DTV_DEMOD,
demod, 0, MEDIA_LNK_FL_ENABLED,
false);
@ -868,7 +867,7 @@ int dvb_usercopy(struct file *file,
parg = sbuf;
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;

View file

@ -866,9 +866,9 @@ err:
return ret;
}
static int af9013_get_frontend(struct dvb_frontend *fe)
static int af9013_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct af9013_state *state = fe->demodulator_priv;
int ret;
u8 buf[3];
@ -1344,6 +1344,10 @@ err:
static void af9013_release(struct dvb_frontend *fe)
{
struct af9013_state *state = fe->demodulator_priv;
/* stop statistics polling */
cancel_delayed_work_sync(&state->statistics_work);
kfree(state);
}

View file

@ -691,10 +691,10 @@ err:
return ret;
}
static int af9033_get_frontend(struct dvb_frontend *fe)
static int af9033_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct af9033_dev *dev = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[8];
@ -1372,6 +1372,9 @@ static int af9033_remove(struct i2c_client *client)
dev_dbg(&dev->client->dev, "\n");
/* stop statistics polling */
cancel_delayed_work_sync(&dev->stat_work);
dev->fe.ops.release = NULL;
dev->fe.demodulator_priv = NULL;
kfree(dev);

View file

@ -190,10 +190,10 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe)
return state->ops->set_tune(state->priv, &tune_args);
}
static int as102_fe_get_frontend(struct dvb_frontend *fe)
static int as102_fe_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct as102_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret = 0;
struct as10x_tps tps = { 0 };

View file

@ -297,9 +297,9 @@ static int atbm8830_set_fe(struct dvb_frontend *fe)
return 0;
}
static int atbm8830_get_fe(struct dvb_frontend *fe)
static int atbm8830_get_fe(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
dprintk("%s\n", __func__);
/* TODO: get real readings from device */

View file

@ -816,9 +816,9 @@ static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
return au8522_read_ucblocks(fe, ber);
}
static int au8522_get_frontend(struct dvb_frontend *fe)
static int au8522_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct au8522_state *state = fe->demodulator_priv;
c->frequency = state->current_frequency;

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2001-5, B2C2 inc.
*
* GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
* GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@posteo.de>
*
* This driver is "hard-coded" to be used with the 1st generation of
* Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
@ -865,5 +865,5 @@ static struct dvb_frontend_ops bcm3510_ops = {
};
MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_LICENSE("GPL");

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2001-5, B2C2 inc.
*
* GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
* GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@posteo.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -3,7 +3,7 @@
*
* Copyright (C) 2001-5, B2C2 inc.
*
* GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
* GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@posteo.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View file

@ -345,9 +345,9 @@ static int cx22700_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int cx22700_get_frontend(struct dvb_frontend *fe)
static int cx22700_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx22700_state* state = fe->demodulator_priv;
u8 reg09 = cx22700_readreg (state, 0x09);

View file

@ -562,9 +562,9 @@ static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return 0;
}
static int cx22702_get_frontend(struct dvb_frontend *fe)
static int cx22702_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx22702_state *state = fe->demodulator_priv;
u8 reg0C = cx22702_readreg(state, 0x0C);

View file

@ -550,9 +550,9 @@ static int cx24110_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int cx24110_get_frontend(struct dvb_frontend *fe)
static int cx24110_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx24110_state *state = fe->demodulator_priv;
s32 afc; unsigned sclk;

View file

@ -1560,10 +1560,10 @@ static int cx24117_get_algo(struct dvb_frontend *fe)
return DVBFE_ALGO_HW;
}
static int cx24117_get_frontend(struct dvb_frontend *fe)
static int cx24117_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct cx24117_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx24117_cmd cmd;
u8 reg, st, inv;
int ret, idx;

View file

@ -1502,9 +1502,9 @@ static int cx24120_sleep(struct dvb_frontend *fe)
return 0;
}
static int cx24120_get_frontend(struct dvb_frontend *fe)
static int cx24120_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cx24120_state *state = fe->demodulator_priv;
u8 freq1, freq2, freq3;

View file

@ -945,9 +945,9 @@ static int cx24123_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int cx24123_get_frontend(struct dvb_frontend *fe)
static int cx24123_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct cx24123_state *state = fe->demodulator_priv;
dprintk("\n");

View file

@ -101,10 +101,10 @@ error:
return ret;
}
int cxd2820r_get_frontend_c(struct dvb_frontend *fe)
int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[2];

View file

@ -313,7 +313,8 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, enum fe_status *status)
return ret;
}
static int cxd2820r_get_frontend(struct dvb_frontend *fe)
static int cxd2820r_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret;
@ -326,13 +327,13 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe)
switch (fe->dtv_property_cache.delivery_system) {
case SYS_DVBT:
ret = cxd2820r_get_frontend_t(fe);
ret = cxd2820r_get_frontend_t(fe, p);
break;
case SYS_DVBT2:
ret = cxd2820r_get_frontend_t2(fe);
ret = cxd2820r_get_frontend_t2(fe, p);
break;
case SYS_DVBC_ANNEX_A:
ret = cxd2820r_get_frontend_c(fe);
ret = cxd2820r_get_frontend_c(fe, p);
break;
default:
ret = -EINVAL;
@ -606,8 +607,7 @@ static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr,
int val)
{
struct cxd2820r_priv *priv =
container_of(chip, struct cxd2820r_priv, gpio_chip);
struct cxd2820r_priv *priv = gpiochip_get_data(chip);
u8 gpio[GPIO_COUNT];
dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val);
@ -620,8 +620,7 @@ static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr,
static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
{
struct cxd2820r_priv *priv =
container_of(chip, struct cxd2820r_priv, gpio_chip);
struct cxd2820r_priv *priv = gpiochip_get_data(chip);
u8 gpio[GPIO_COUNT];
dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val);
@ -636,8 +635,7 @@ static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
static int cxd2820r_gpio_get(struct gpio_chip *chip, unsigned nr)
{
struct cxd2820r_priv *priv =
container_of(chip, struct cxd2820r_priv, gpio_chip);
struct cxd2820r_priv *priv = gpiochip_get_data(chip);
dev_dbg(&priv->i2c->dev, "%s: nr=%d\n", __func__, nr);
@ -731,7 +729,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
priv->gpio_chip.base = -1; /* dynamic allocation */
priv->gpio_chip.ngpio = GPIO_COUNT;
priv->gpio_chip.can_sleep = 1;
ret = gpiochip_add(&priv->gpio_chip);
ret = gpiochip_add_data(&priv->gpio_chip, priv);
if (ret)
goto error;

View file

@ -76,7 +76,8 @@ int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
/* cxd2820r_c.c */
int cxd2820r_get_frontend_c(struct dvb_frontend *fe);
int cxd2820r_get_frontend_c(struct dvb_frontend *fe,
struct dtv_frontend_properties *p);
int cxd2820r_set_frontend_c(struct dvb_frontend *fe);
@ -99,7 +100,8 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
/* cxd2820r_t.c */
int cxd2820r_get_frontend_t(struct dvb_frontend *fe);
int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
struct dtv_frontend_properties *p);
int cxd2820r_set_frontend_t(struct dvb_frontend *fe);
@ -122,7 +124,8 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
/* cxd2820r_t2.c */
int cxd2820r_get_frontend_t2(struct dvb_frontend *fe);
int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
struct dtv_frontend_properties *p);
int cxd2820r_set_frontend_t2(struct dvb_frontend *fe);

View file

@ -138,10 +138,10 @@ error:
return ret;
}
int cxd2820r_get_frontend_t(struct dvb_frontend *fe)
int cxd2820r_get_frontend_t(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[2];

View file

@ -23,8 +23,8 @@
int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct cxd2820r_priv *priv = fe->demodulator_priv;
int ret, i, bw_i;
u32 if_freq, if_ctl;
u64 num;
@ -169,10 +169,10 @@ error:
}
int cxd2820r_get_frontend_t2(struct dvb_frontend *fe)
int cxd2820r_get_frontend_t2(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct cxd2820r_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[2];

View file

@ -2090,13 +2090,13 @@ static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv,
return 0;
}
static int cxd2841er_get_frontend(struct dvb_frontend *fe)
static int cxd2841er_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
enum fe_status status = 0;
u16 strength = 0, snr = 0;
u32 errors = 0, ber = 0;
struct cxd2841er_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
if (priv->state == STATE_ACTIVE_S)

View file

@ -774,6 +774,6 @@ free_mem:
}
EXPORT_SYMBOL(dib0070_attach);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
MODULE_LICENSE("GPL");

View file

@ -2669,7 +2669,7 @@ free_mem:
}
EXPORT_SYMBOL(dib0090_fw_register);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
MODULE_LICENSE("GPL");

View file

@ -2,11 +2,11 @@
* public header file of the frontend drivers for mobile DVB-T demodulators
* DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
*
* based on GPL code from DibCom, which has
*
* Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
* Copyright (C) 2004 Amaury Demol for DiBcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -14,7 +14,7 @@
*
* Acknowledgements
*
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
* Amaury Demol from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
* see Documentation/dvb/README.dvb-usb for more information

View file

@ -2,11 +2,11 @@
* Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B
* DiBcom (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
*
* based on GPL code from DibCom, which has
*
* Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
* Copyright (C) 2004 Amaury Demol for DiBcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -14,7 +14,7 @@
*
* Acknowledgements
*
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
* Amaury Demol from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
* see Documentation/dvb/README.dvb-usb for more information
@ -36,7 +36,7 @@
/* Version information */
#define DRIVER_VERSION "0.1"
#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de"
static int debug;
module_param(debug, int, 0644);
@ -112,7 +112,8 @@ static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
}
};
static int dib3000mb_get_frontend(struct dvb_frontend* fe);
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
struct dtv_frontend_properties *c);
static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
{
@ -359,7 +360,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
if (search_state == 1) {
if (dib3000mb_get_frontend(fe) == 0) {
if (dib3000mb_get_frontend(fe, c) == 0) {
deb_setf("reading tuning data from frontend succeeded.\n");
return dib3000mb_set_frontend(fe, 0);
}
@ -450,9 +451,9 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
return 0;
}
static int dib3000mb_get_frontend(struct dvb_frontend* fe)
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dib3000_state* state = fe->demodulator_priv;
enum fe_code_rate *cr;
u16 tps_val;

View file

@ -1,7 +1,7 @@
/*
* dib3000mb_priv.h
*
* Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@posteo.de)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as

View file

@ -2,7 +2,7 @@
* Driver for DiBcom DiB3000MC/P-demodulator.
*
* Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
*
* This code is partially based on the previous dib3000mc.c .
*
@ -636,9 +636,9 @@ struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
static int dib3000mc_get_frontend(struct dvb_frontend* fe)
static int dib3000mc_get_frontend(struct dvb_frontend* fe,
struct dtv_frontend_properties *fep)
{
struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib3000mc_state *state = fe->demodulator_priv;
u16 tps = dib3000mc_read_word(state,458);
@ -726,7 +726,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend *fe)
if (found == 0 || found == 1)
return 0; // no channel found
dib3000mc_get_frontend(fe);
dib3000mc_get_frontend(fe, fep);
}
ret = dib3000mc_tune(fe);
@ -939,6 +939,6 @@ static struct dvb_frontend_ops dib3000mc_ops = {
.read_ucblocks = dib3000mc_read_unc_blocks,
};
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
MODULE_LICENSE("GPL");

View file

@ -2,7 +2,7 @@
* Driver for DiBcom DiB3000MC/P-demodulator.
*
* Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de)
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
*
* This code is partially based on the previous dib3000mc.c .
*

View file

@ -1151,9 +1151,9 @@ static int dib7000m_identify(struct dib7000m_state *state)
}
static int dib7000m_get_frontend(struct dvb_frontend* fe)
static int dib7000m_get_frontend(struct dvb_frontend* fe,
struct dtv_frontend_properties *fep)
{
struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib7000m_state *state = fe->demodulator_priv;
u16 tps = dib7000m_read_word(state,480);
@ -1246,7 +1246,7 @@ static int dib7000m_set_frontend(struct dvb_frontend *fe)
if (found == 0 || found == 1)
return 0; // no channel found
dib7000m_get_frontend(fe);
dib7000m_get_frontend(fe, fep);
}
ret = dib7000m_tune(fe);
@ -1465,6 +1465,6 @@ static struct dvb_frontend_ops dib7000m_ops = {
.read_ucblocks = dib7000m_read_unc_blocks,
};
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
MODULE_LICENSE("GPL");

View file

@ -1405,9 +1405,9 @@ static int dib7000p_identify(struct dib7000p_state *st)
return 0;
}
static int dib7000p_get_frontend(struct dvb_frontend *fe)
static int dib7000p_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *fep)
{
struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dib7000p_state *state = fe->demodulator_priv;
u16 tps = dib7000p_read_word(state, 463);
@ -1540,7 +1540,7 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe)
if (found == 0 || found == 1)
return 0;
dib7000p_get_frontend(fe);
dib7000p_get_frontend(fe, fep);
}
ret = dib7000p_tune(fe);
@ -2834,7 +2834,7 @@ static struct dvb_frontend_ops dib7000p_ops = {
.read_ucblocks = dib7000p_read_unc_blocks,
};
MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Olivier Grenie <olivie.grenie@parrot.com>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
MODULE_LICENSE("GPL");

View file

@ -3382,14 +3382,15 @@ static int dib8000_sleep(struct dvb_frontend *fe)
static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat);
static int dib8000_get_frontend(struct dvb_frontend *fe)
static int dib8000_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dib8000_state *state = fe->demodulator_priv;
u16 i, val = 0;
enum fe_status stat = 0;
u8 index_frontend, sub_index_frontend;
fe->dtv_property_cache.bandwidth_hz = 6000000;
c->bandwidth_hz = 6000000;
/*
* If called to early, get_frontend makes dib8000_tune to either
@ -3406,7 +3407,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
if (stat&FE_HAS_SYNC) {
dprintk("TMCC lock on the slave%i", index_frontend);
/* synchronize the cache with the other frontends */
state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c);
for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
if (sub_index_frontend != index_frontend) {
state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
@ -3426,57 +3427,57 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
}
}
fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
c->isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
if (state->revision == 0x8090)
val = dib8000_read_word(state, 572);
else
val = dib8000_read_word(state, 570);
fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
c->inversion = (val & 0x40) >> 6;
switch ((val & 0x30) >> 4) {
case 1:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
c->transmission_mode = TRANSMISSION_MODE_2K;
dprintk("dib8000_get_frontend: transmission mode 2K");
break;
case 2:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
c->transmission_mode = TRANSMISSION_MODE_4K;
dprintk("dib8000_get_frontend: transmission mode 4K");
break;
case 3:
default:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
c->transmission_mode = TRANSMISSION_MODE_8K;
dprintk("dib8000_get_frontend: transmission mode 8K");
break;
}
switch (val & 0x3) {
case 0:
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
c->guard_interval = GUARD_INTERVAL_1_32;
dprintk("dib8000_get_frontend: Guard Interval = 1/32 ");
break;
case 1:
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
c->guard_interval = GUARD_INTERVAL_1_16;
dprintk("dib8000_get_frontend: Guard Interval = 1/16 ");
break;
case 2:
dprintk("dib8000_get_frontend: Guard Interval = 1/8 ");
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
c->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
dprintk("dib8000_get_frontend: Guard Interval = 1/4 ");
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
c->guard_interval = GUARD_INTERVAL_1_4;
break;
}
val = dib8000_read_word(state, 505);
fe->dtv_property_cache.isdbt_partial_reception = val & 1;
dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
c->isdbt_partial_reception = val & 1;
dprintk("dib8000_get_frontend: partial_reception = %d ", c->isdbt_partial_reception);
for (i = 0; i < 3; i++) {
int show;
val = dib8000_read_word(state, 493 + i) & 0x0f;
fe->dtv_property_cache.layer[i].segment_count = val;
c->layer[i].segment_count = val;
if (val == 0 || val > 13)
show = 0;
@ -3485,41 +3486,41 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
if (show)
dprintk("dib8000_get_frontend: Layer %d segments = %d ",
i, fe->dtv_property_cache.layer[i].segment_count);
i, c->layer[i].segment_count);
val = dib8000_read_word(state, 499 + i) & 0x3;
/* Interleaving can be 0, 1, 2 or 4 */
if (val == 3)
val = 4;
fe->dtv_property_cache.layer[i].interleaving = val;
c->layer[i].interleaving = val;
if (show)
dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ",
i, fe->dtv_property_cache.layer[i].interleaving);
i, c->layer[i].interleaving);
val = dib8000_read_word(state, 481 + i);
switch (val & 0x7) {
case 1:
fe->dtv_property_cache.layer[i].fec = FEC_1_2;
c->layer[i].fec = FEC_1_2;
if (show)
dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i);
break;
case 2:
fe->dtv_property_cache.layer[i].fec = FEC_2_3;
c->layer[i].fec = FEC_2_3;
if (show)
dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i);
break;
case 3:
fe->dtv_property_cache.layer[i].fec = FEC_3_4;
c->layer[i].fec = FEC_3_4;
if (show)
dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i);
break;
case 5:
fe->dtv_property_cache.layer[i].fec = FEC_5_6;
c->layer[i].fec = FEC_5_6;
if (show)
dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i);
break;
default:
fe->dtv_property_cache.layer[i].fec = FEC_7_8;
c->layer[i].fec = FEC_7_8;
if (show)
dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i);
break;
@ -3528,23 +3529,23 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
val = dib8000_read_word(state, 487 + i);
switch (val & 0x3) {
case 0:
fe->dtv_property_cache.layer[i].modulation = DQPSK;
c->layer[i].modulation = DQPSK;
if (show)
dprintk("dib8000_get_frontend: Layer %d DQPSK ", i);
break;
case 1:
fe->dtv_property_cache.layer[i].modulation = QPSK;
c->layer[i].modulation = QPSK;
if (show)
dprintk("dib8000_get_frontend: Layer %d QPSK ", i);
break;
case 2:
fe->dtv_property_cache.layer[i].modulation = QAM_16;
c->layer[i].modulation = QAM_16;
if (show)
dprintk("dib8000_get_frontend: Layer %d QAM16 ", i);
break;
case 3:
default:
fe->dtv_property_cache.layer[i].modulation = QAM_64;
c->layer[i].modulation = QAM_64;
if (show)
dprintk("dib8000_get_frontend: Layer %d QAM64 ", i);
break;
@ -3553,16 +3554,16 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
/* synchronize the cache with the other frontends */
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode;
state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception;
state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = c->isdbt_sb_mode;
state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion;
state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode;
state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval;
state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = c->isdbt_partial_reception;
for (i = 0; i < 3; i++) {
state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count;
state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving;
state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec;
state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation;
state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = c->layer[i].segment_count;
state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = c->layer[i].interleaving;
state->fe[index_frontend]->dtv_property_cache.layer[i].fec = c->layer[i].fec;
state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = c->layer[i].modulation;
}
}
return 0;
@ -3671,7 +3672,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
if (state->channel_parameters_set == 0) { /* searching */
if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) {
dprintk("autosearch succeeded on fe%i", index_frontend);
dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */
dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */
state->channel_parameters_set = 1;
for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
@ -4516,6 +4517,6 @@ void *dib8000_attach(struct dib8000_ops *ops)
}
EXPORT_SYMBOL(dib8000_attach);
MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@parrot.com, Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
MODULE_LICENSE("GPL");

View file

@ -1889,7 +1889,8 @@ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_fron
return 0;
}
static int dib9000_get_frontend(struct dvb_frontend *fe)
static int dib9000_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dib9000_state *state = fe->demodulator_priv;
u8 index_frontend, sub_index_frontend;
@ -1909,7 +1910,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe)
dprintk("TPS lock on the slave%i", index_frontend);
/* synchronize the cache with the other frontends */
state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c);
for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
sub_index_frontend++) {
if (sub_index_frontend != index_frontend) {
@ -1943,14 +1944,14 @@ static int dib9000_get_frontend(struct dvb_frontend *fe)
/* synchronize the cache with the other frontends */
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation;
state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy;
state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP;
state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion;
state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode;
state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval;
state->fe[index_frontend]->dtv_property_cache.modulation = c->modulation;
state->fe[index_frontend]->dtv_property_cache.hierarchy = c->hierarchy;
state->fe[index_frontend]->dtv_property_cache.code_rate_HP = c->code_rate_HP;
state->fe[index_frontend]->dtv_property_cache.code_rate_LP = c->code_rate_LP;
state->fe[index_frontend]->dtv_property_cache.rolloff = c->rolloff;
}
ret = 0;
@ -2083,7 +2084,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe)
/* synchronize all the channel cache */
state->get_frontend_internal = 1;
dib9000_get_frontend(state->fe[0]);
dib9000_get_frontend(state->fe[0], &state->fe[0]->dtv_property_cache);
state->get_frontend_internal = 0;
/* retune the other frontends with the found channel */
@ -2589,7 +2590,7 @@ static struct dvb_frontend_ops dib9000_ops = {
.read_ucblocks = dib9000_read_unc_blocks,
};
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
MODULE_LICENSE("GPL");

View file

@ -510,6 +510,6 @@ u32 systime(void)
}
EXPORT_SYMBOL(systime);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
MODULE_LICENSE("GPL");

View file

@ -70,9 +70,12 @@ static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
}
/*
* Only needed if it actually reads something from the hardware
* Should only be implemented if it actually reads something from the hardware.
* Also, it should check for the locks, in order to avoid report wrong data
* to userspace.
*/
static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe)
static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
return 0;
}

View file

@ -560,11 +560,11 @@ static int hd29l2_get_frontend_algo(struct dvb_frontend *fe)
return DVBFE_ALGO_CUSTOM;
}
static int hd29l2_get_frontend(struct dvb_frontend *fe)
static int hd29l2_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
int ret;
struct hd29l2_priv *priv = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u8 buf[3];
u32 if_ctl;
char *str_constellation, *str_code_rate, *str_constellation_code_rate,

View file

@ -243,9 +243,9 @@ static int apply_frontend_param(struct dvb_frontend *fe)
return 0;
}
static int get_frontend(struct dvb_frontend *fe)
static int get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct l64781_state* state = fe->demodulator_priv;
int tmp;

View file

@ -942,101 +942,102 @@ static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
/* ------------------------------------------------------------------------ */
static int lg216x_get_frontend(struct dvb_frontend *fe)
static int lg216x_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct lg216x_state *state = fe->demodulator_priv;
int ret;
lg_dbg("\n");
fe->dtv_property_cache.modulation = VSB_8;
fe->dtv_property_cache.frequency = state->current_frequency;
fe->dtv_property_cache.delivery_system = SYS_ATSCMH;
c->modulation = VSB_8;
c->frequency = state->current_frequency;
c->delivery_system = SYS_ATSCMH;
ret = lg216x_get_fic_version(state,
&fe->dtv_property_cache.atscmh_fic_ver);
&c->atscmh_fic_ver);
if (lg_fail(ret))
goto fail;
if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) {
state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver;
if (state->fic_ver != c->atscmh_fic_ver) {
state->fic_ver = c->atscmh_fic_ver;
#if 0
ret = lg2160_get_parade_id(state,
&fe->dtv_property_cache.atscmh_parade_id);
&c->atscmh_parade_id);
if (lg_fail(ret))
goto fail;
/* #else */
fe->dtv_property_cache.atscmh_parade_id = state->parade_id;
c->atscmh_parade_id = state->parade_id;
#endif
ret = lg216x_get_nog(state,
&fe->dtv_property_cache.atscmh_nog);
&c->atscmh_nog);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_tnog(state,
&fe->dtv_property_cache.atscmh_tnog);
&c->atscmh_tnog);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_sgn(state,
&fe->dtv_property_cache.atscmh_sgn);
&c->atscmh_sgn);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_prc(state,
&fe->dtv_property_cache.atscmh_prc);
&c->atscmh_prc);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_rs_frame_mode(state,
(enum atscmh_rs_frame_mode *)
&fe->dtv_property_cache.atscmh_rs_frame_mode);
&c->atscmh_rs_frame_mode);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_rs_frame_ensemble(state,
(enum atscmh_rs_frame_ensemble *)
&fe->dtv_property_cache.atscmh_rs_frame_ensemble);
&c->atscmh_rs_frame_ensemble);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_rs_code_mode(state,
(enum atscmh_rs_code_mode *)
&fe->dtv_property_cache.atscmh_rs_code_mode_pri,
&c->atscmh_rs_code_mode_pri,
(enum atscmh_rs_code_mode *)
&fe->dtv_property_cache.atscmh_rs_code_mode_sec);
&c->atscmh_rs_code_mode_sec);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_sccc_block_mode(state,
(enum atscmh_sccc_block_mode *)
&fe->dtv_property_cache.atscmh_sccc_block_mode);
&c->atscmh_sccc_block_mode);
if (lg_fail(ret))
goto fail;
ret = lg216x_get_sccc_code_mode(state,
(enum atscmh_sccc_code_mode *)
&fe->dtv_property_cache.atscmh_sccc_code_mode_a,
&c->atscmh_sccc_code_mode_a,
(enum atscmh_sccc_code_mode *)
&fe->dtv_property_cache.atscmh_sccc_code_mode_b,
&c->atscmh_sccc_code_mode_b,
(enum atscmh_sccc_code_mode *)
&fe->dtv_property_cache.atscmh_sccc_code_mode_c,
&c->atscmh_sccc_code_mode_c,
(enum atscmh_sccc_code_mode *)
&fe->dtv_property_cache.atscmh_sccc_code_mode_d);
&c->atscmh_sccc_code_mode_d);
if (lg_fail(ret))
goto fail;
}
#if 0
ret = lg216x_read_fic_err_count(state,
(u8 *)&fe->dtv_property_cache.atscmh_fic_err);
(u8 *)&c->atscmh_fic_err);
if (lg_fail(ret))
goto fail;
ret = lg216x_read_crc_err_count(state,
&fe->dtv_property_cache.atscmh_crc_err);
&c->atscmh_crc_err);
if (lg_fail(ret))
goto fail;
ret = lg216x_read_rs_err_count(state,
&fe->dtv_property_cache.atscmh_rs_err);
&c->atscmh_rs_err);
if (lg_fail(ret))
goto fail;
switch (state->cfg->lg_chip) {
case LG2160:
if (((fe->dtv_property_cache.atscmh_rs_err >= 240) &&
(fe->dtv_property_cache.atscmh_crc_err >= 240)) &&
if (((c->atscmh_rs_err >= 240) &&
(c->atscmh_crc_err >= 240)) &&
((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
ret = lg216x_soft_reset(state);
break;
@ -1054,14 +1055,17 @@ fail:
static int lg216x_get_property(struct dvb_frontend *fe,
struct dtv_property *tvp)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
return (DTV_ATSCMH_FIC_VER == tvp->cmd) ?
lg216x_get_frontend(fe) : 0;
lg216x_get_frontend(fe, c) : 0;
}
static int lg2160_set_frontend(struct dvb_frontend *fe)
{
struct lg216x_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
@ -1129,7 +1133,7 @@ static int lg2160_set_frontend(struct dvb_frontend *fe)
ret = lg216x_enable_fic(state, 1);
lg_fail(ret);
lg216x_get_frontend(fe);
lg216x_get_frontend(fe, c);
fail:
return ret;
}

View file

@ -812,9 +812,9 @@ fail:
return ret;
}
static int lgdt3305_get_frontend(struct dvb_frontend *fe)
static int lgdt3305_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgdt3305_state *state = fe->demodulator_priv;
lg_dbg("\n");

View file

@ -1040,10 +1040,10 @@ fail:
return ret;
}
static int lgdt3306a_get_frontend(struct dvb_frontend *fe)
static int lgdt3306a_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct lgdt3306a_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
dbg_info("(%u, %d)\n",
state->current_frequency, state->current_modulation);

View file

@ -439,10 +439,11 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe)
return 0;
}
static int lgdt330x_get_frontend(struct dvb_frontend *fe)
static int lgdt330x_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgdt330x_state *state = fe->demodulator_priv;
p->frequency = state->current_frequency;
return 0;
}

View file

@ -336,10 +336,11 @@ lgs8gl5_set_frontend(struct dvb_frontend *fe)
static int
lgs8gl5_get_frontend(struct dvb_frontend *fe)
lgs8gl5_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct lgs8gl5_state *state = fe->demodulator_priv;
u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;

View file

@ -672,7 +672,7 @@ static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len)
static int lgs8gxx_set_fe(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
struct lgs8gxx_state *priv = fe->demodulator_priv;
dprintk("%s\n", __func__);
@ -689,17 +689,7 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe)
msleep(10);
return 0;
}
static int lgs8gxx_get_fe(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
dprintk("%s\n", __func__);
/* TODO: get real readings from device */
/* inversion status */
fe_params->inversion = INVERSION_OFF;
/* bandwidth */
fe_params->bandwidth_hz = 8000000;
@ -1016,7 +1006,6 @@ static struct dvb_frontend_ops lgs8gxx_ops = {
.i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
.set_frontend = lgs8gxx_set_fe,
.get_frontend = lgs8gxx_get_fe,
.get_tune_settings = lgs8gxx_get_tune_settings,
.read_status = lgs8gxx_read_status,

View file

@ -791,11 +791,11 @@ err:
return ret;
}
static int m88ds3103_get_frontend(struct dvb_frontend *fe)
static int m88ds3103_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct m88ds3103_dev *dev = fe->demodulator_priv;
struct i2c_client *client = dev->client;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[3];

View file

@ -708,10 +708,11 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int m88rs2000_get_frontend(struct dvb_frontend *fe)
static int m88rs2000_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct m88rs2000_state *state = fe->demodulator_priv;
c->fec_inner = state->fec_inner;
c->frequency = state->tuner_frequency;
c->symbol_rate = state->symbol_rate;

View file

@ -2028,16 +2028,6 @@ static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe,
return 0;
}
static int mb86a20s_get_frontend_dummy(struct dvb_frontend *fe)
{
/*
* get_frontend is now handled together with other stats
* retrival, when read_status() is called, as some statistics
* will depend on the layers detection.
*/
return 0;
};
static int mb86a20s_tune(struct dvb_frontend *fe,
bool re_tune,
unsigned int mode_flags,
@ -2136,7 +2126,6 @@ static struct dvb_frontend_ops mb86a20s_ops = {
.init = mb86a20s_initfe,
.set_frontend = mb86a20s_set_frontend,
.get_frontend = mb86a20s_get_frontend_dummy,
.read_status = mb86a20s_read_status_and_stats,
.read_signal_strength = mb86a20s_read_signal_strength_from_cache,
.tune = mb86a20s_tune,

View file

@ -647,9 +647,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int mt312_get_frontend(struct dvb_frontend *fe)
static int mt312_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct mt312_state *state = fe->demodulator_priv;
int ret;

View file

@ -311,9 +311,9 @@ static int mt352_set_parameters(struct dvb_frontend *fe)
return 0;
}
static int mt352_get_parameters(struct dvb_frontend* fe)
static int mt352_get_parameters(struct dvb_frontend* fe,
struct dtv_frontend_properties *op)
{
struct dtv_frontend_properties *op = &fe->dtv_property_cache;
struct mt352_state* state = fe->demodulator_priv;
u16 tps;
u16 div;

View file

@ -375,9 +375,9 @@ static int or51132_set_parameters(struct dvb_frontend *fe)
return 0;
}
static int or51132_get_parameters(struct dvb_frontend* fe)
static int or51132_get_parameters(struct dvb_frontend* fe,
struct dtv_frontend_properties *p)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
struct or51132_state* state = fe->demodulator_priv;
int status;
int retry = 1;

View file

@ -279,11 +279,11 @@ err:
return ret;
}
static int rtl2830_get_frontend(struct dvb_frontend *fe)
static int rtl2830_get_frontend(struct dvb_frontend *fe,
struct dtv_frontend_properties *c)
{
struct i2c_client *client = fe->demodulator_priv;
struct rtl2830_dev *dev = i2c_get_clientdata(client);
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
u8 buf[3];
@ -900,6 +900,9 @@ static int rtl2830_remove(struct i2c_client *client)
dev_dbg(&client->dev, "\n");
/* stop statistics polling */
cancel_delayed_work_sync(&dev->stat_work);
i2c_del_mux_adapter(dev->adapter);
regmap_exit(dev->regmap);
kfree(dev);

Some files were not shown because too many files have changed in this diff Show more