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:
commit
0041ee4d36
342 changed files with 10735 additions and 3987 deletions
|
@ -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
|
||||
|
|
|
@ -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> </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> </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 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> </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> </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> </entry>
|
||||
<entry>Cinema content.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_GAME</constant> </entry>
|
||||
<entry>Game content. Audio and video latency should be minimized.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_DV_IT_CONTENT_TYPE_NO_ITC</constant> </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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
<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,
|
||||
|
@ -24,12 +27,17 @@ 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>
|
||||
|
||||
<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>
|
||||
|
||||
|
|
|
@ -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 ½ 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 × 4
|
||||
<title><constant>V4L2_PIX_FMT_YUV422M</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
|
@ -75,25 +80,45 @@ pixel image</title>
|
|||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry>start1 + 0:</entry>
|
||||
<entry>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cr<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 2:</entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>11</subscript></entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry>start2 + 0:</entry>
|
||||
<entry>Cb<subscript>00</subscript></entry>
|
||||
<entry>Cb<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start2 + 2:</entry>
|
||||
<entry>start1 + 2:</entry>
|
||||
<entry>Cb<subscript>10</subscript></entry>
|
||||
<entry>Cb<subscript>11</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 4:</entry>
|
||||
<entry>Cb<subscript>20</subscript></entry>
|
||||
<entry>Cb<subscript>21</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 6:</entry>
|
||||
<entry>Cb<subscript>30</subscript></entry>
|
||||
<entry>Cb<subscript>31</subscript></entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry>start2 + 0:</entry>
|
||||
<entry>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cr<subscript>01</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start2 + 2:</entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>11</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start2 + 4:</entry>
|
||||
<entry>Cr<subscript>20</subscript></entry>
|
||||
<entry>Cr<subscript>21</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start2 + 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>
|
177
Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml
Normal file
177
Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml
Normal 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 × 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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>
|
|
@ -1628,7 +1628,8 @@ information.</para>
|
|||
&sub-y41p;
|
||||
&sub-yuv420;
|
||||
&sub-yuv420m;
|
||||
&sub-yvu420m;
|
||||
&sub-yuv422m;
|
||||
&sub-yuv444m;
|
||||
&sub-yuv410;
|
||||
&sub-yuv422p;
|
||||
&sub-yuv411p;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
88
Documentation/devicetree/bindings/media/i2c/tvp5150.txt
Normal file
88
Documentation/devicetree/bindings/media/i2c/tvp5150.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -5,7 +5,8 @@ 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:
|
||||
- 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
|
||||
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
|
72
Documentation/devicetree/bindings/media/ti-cal.txt
Normal file
72
Documentation/devicetree/bindings/media/ti-cal.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,13 +446,16 @@ 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. */
|
||||
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];
|
||||
|
||||
|
@ -433,6 +464,7 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
|
|||
|
||||
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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 (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->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
|
||||
rgrp->index == 0)
|
||||
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,15 +576,35 @@ 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;
|
||||
|
||||
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. */
|
||||
for (i = 0; i < rcdu->num_crtcs; ++i) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
|
||||
unsigned int index,
|
||||
const struct rcar_du_plane_state *state)
|
||||
{
|
||||
rcar_du_plane_write(rgrp, index, PnMR,
|
||||
PnMR_SPIM_TP_OFF | state->format->pnmr);
|
||||
|
||||
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, 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);
|
||||
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_plane *plane)
|
||||
void __rcar_du_plane_setup(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 rcar_du_device *rcdu = rgrp->dev;
|
||||
|
||||
__rcar_du_plane_setup(plane, state->hwindex);
|
||||
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)
|
||||
return;
|
||||
|
||||
if (plane->state->crtc)
|
||||
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;
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
384
drivers/gpu/drm/rcar-du/rcar_du_vsp.c
Normal file
384
drivers/gpu/drm/rcar-du/rcar_du_vsp.c
Normal 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, ©->state);
|
||||
|
||||
return ©->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;
|
||||
}
|
76
drivers/gpu/drm/rcar-du/rcar_du_vsp.h
Normal file
76
drivers/gpu/drm/rcar-du/rcar_du_vsp.h
Normal 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__ */
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -140,8 +140,11 @@ 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,
|
||||
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,
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 .
|
||||
*
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue