Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "This series contains: - Exynos s5p-mfc driver got support for VP8 encoder - Some SoC drivers gained support for asynchronous registration (needed for DT) - The RC subsystem gained support for RC activity LED; - New drivers added: a video decoder(adv7842), a video encoder (adv7511), a new GSPCA driver (stk1135) and support for Renesas R-Car (vsp1) - the first SDR kernel driver: mirics msi3101. Due to some troubles with the driver, and because the API is still under discussion, it will be merged at staging for 3.12. Need to rework on it - usual new boards additions, fixes, cleanups and driver improvements" * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (242 commits) [media] cx88: Fix regression: CX88_AUDIO_WM8775 can't be 0 [media] exynos4-is: Fix entity unregistration on error path [media] exynos-gsc: Register v4l2 device [media] exynos4-is: Fix fimc-lite bayer formats [media] em28xx: fix assignment of the eeprom data [media] hdpvr: fix iteration over uninitialized lists in hdpvr_probe() [media] usbtv: Throw corrupted frames away [media] usbtv: Fix deinterlacing [media] v4l2: added missing mutex.h include to v4l2-ctrls.h [media] DocBook: upgrade media_api DocBook version to 4.2 [media] ml86v7667: fix compile warning: 'ret' set but not used [media] s5p-g2d: Fix registration failure [media] media: coda: Fix DT driver data pointer for i.MX27 [media] s5p-mfc: Fix input/output format reporting [media] v4l: vsp1: Fix mutex double lock at streamon time [media] v4l: vsp1: Add support for RT clock [media] v4l: vsp1: Initialize media device bus_info field [media] davinci: vpif_capture: fix error return code in vpif_probe() [media] davinci: vpif_display: fix error return code in vpif_probe() [media] MAINTAINERS: add entries for adv7511 and adv7842 ...
This commit is contained in:
commit
27c053aa8d
|
@ -722,17 +722,22 @@ for more details.</para>
|
|||
</section>
|
||||
|
||||
<section id="mpeg-controls">
|
||||
<title>MPEG Control Reference</title>
|
||||
<title>Codec Control Reference</title>
|
||||
|
||||
<para>Below all controls within the MPEG control class are
|
||||
<para>Below all controls within the Codec control class are
|
||||
described. First the generic controls, then controls specific for
|
||||
certain hardware.</para>
|
||||
|
||||
<para>Note: These controls are applicable to all codecs and
|
||||
not just MPEG. The defines are prefixed with V4L2_CID_MPEG/V4L2_MPEG
|
||||
as the controls were originally made for MPEG codecs and later
|
||||
extended to cover all encoding formats.</para>
|
||||
|
||||
<section>
|
||||
<title>Generic MPEG Controls</title>
|
||||
<title>Generic Codec Controls</title>
|
||||
|
||||
<table pgwide="1" frame="none" id="mpeg-control-id">
|
||||
<title>MPEG Control IDs</title>
|
||||
<title>Codec Control IDs</title>
|
||||
<tgroup cols="4">
|
||||
<colspec colname="c1" colwidth="1*" />
|
||||
<colspec colname="c2" colwidth="6*" />
|
||||
|
@ -752,7 +757,7 @@ certain hardware.</para>
|
|||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_CLASS</constant> </entry>
|
||||
<entry>class</entry>
|
||||
</row><row><entry spanname="descr">The MPEG class
|
||||
</row><row><entry spanname="descr">The Codec class
|
||||
descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
|
||||
description of this control class. This description can be used as the
|
||||
caption of a Tab page in a GUI, for example.</entry>
|
||||
|
@ -3009,6 +3014,159 @@ in by the application. 0 = do not insert, 1 = insert packets.</entry>
|
|||
</tgroup>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>VPX Control Reference</title>
|
||||
|
||||
<para>The VPX controls include controls for encoding parameters
|
||||
of VPx video codec.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="vpx-control-id">
|
||||
<title>VPX Control IDs</title>
|
||||
|
||||
<tgroup cols="4">
|
||||
<colspec colname="c1" colwidth="1*" />
|
||||
<colspec colname="c2" colwidth="6*" />
|
||||
<colspec colname="c3" colwidth="2*" />
|
||||
<colspec colname="c4" colwidth="6*" />
|
||||
<spanspec namest="c1" nameend="c2" spanname="id" />
|
||||
<spanspec namest="c2" nameend="c4" spanname="descr" />
|
||||
<thead>
|
||||
<row>
|
||||
<entry spanname="id" align="left">ID</entry>
|
||||
<entry align="left">Type</entry>
|
||||
</row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody valign="top">
|
||||
<row><entry></entry></row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row id="v4l2-vpx-num-partitions">
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS</constant></entry>
|
||||
<entry>enum v4l2_vp8_num_partitions</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">The number of token partitions to use in VP8 encoder.
|
||||
Possible values are:</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entrytbl spanname="descr" cols="2">
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION</constant></entry>
|
||||
<entry>1 coefficient partition</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS</constant></entry>
|
||||
<entry>2 coefficient partitions</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS</constant></entry>
|
||||
<entry>4 coefficient partitions</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS</constant></entry>
|
||||
<entry>8 coefficient partitions</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</entrytbl>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4</constant></entry>
|
||||
<entry>boolean</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">Setting this prevents intra 4x4 mode in the intra mode decision.</entry>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row id="v4l2-vpx-num-ref-frames">
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES</constant></entry>
|
||||
<entry>enum v4l2_vp8_num_ref_frames</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">The number of reference pictures for encoding P frames.
|
||||
Possible values are:</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entrytbl spanname="descr" cols="2">
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME</constant></entry>
|
||||
<entry>Last encoded frame will be searched</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME</constant></entry>
|
||||
<entry>Two frames will be searched among the last encoded frame, the golden frame
|
||||
and the alternate reference (altref) frame. The encoder implementation will decide which two are chosen.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_3_REF_FRAME</constant></entry>
|
||||
<entry>The last encoded frame, the golden frame and the altref frame will be searched.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</entrytbl>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">Indicates the loop filter level. The adjustment of the loop
|
||||
filter level is done via a delta value against a baseline loop filter value.</entry>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">This parameter affects the loop filter. Anything above
|
||||
zero weakens the deblocking effect on the loop filter.</entry>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row>
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD</constant></entry>
|
||||
<entry>integer</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">Sets the refresh period for the golden frame. The period is defined
|
||||
in number of frames. For a value of 'n', every nth frame starting from the first key frame will be taken as a golden frame.
|
||||
For eg. for encoding sequence of 0, 1, 2, 3, 4, 5, 6, 7 where the golden frame refresh period is set as 4, the frames
|
||||
0, 4, 8 etc will be taken as the golden frames as frame 0 is always a key frame.</entry>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
<row id="v4l2-vpx-golden-frame-sel">
|
||||
<entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL</constant></entry>
|
||||
<entry>enum v4l2_vp8_golden_frame_sel</entry>
|
||||
</row>
|
||||
<row><entry spanname="descr">Selects the golden frame for encoding.
|
||||
Possible values are:</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entrytbl spanname="descr" cols="2">
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV</constant></entry>
|
||||
<entry>Use the (n-2)th frame as a golden frame, current frame index being 'n'.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD</constant></entry>
|
||||
<entry>Use the previous specific frame indicated by
|
||||
V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD as a golden frame.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</entrytbl>
|
||||
</row>
|
||||
|
||||
<row><entry></entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="camera-controls">
|
||||
|
|
|
@ -46,7 +46,9 @@ describing an IR signal are read from the chardev.</para>
|
|||
values. Pulses and spaces are only marked implicitly by their position. The
|
||||
data must start and end with a pulse, therefore, the data must always include
|
||||
an uneven number of samples. The write function must block until the data has
|
||||
been transmitted by the hardware.</para>
|
||||
been transmitted by the hardware. If more data is provided than the hardware
|
||||
can send, the driver returns EINVAL.</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="lirc_ioctl">
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
<refentry>
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_NV16M ('NM16'), V4L2_PIX_FMT_NV61M ('NM61')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname id="V4L2-PIX-FMT-NV16M"><constant>V4L2_PIX_FMT_NV16M</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-NV61M"><constant>V4L2_PIX_FMT_NV61M</constant></refname>
|
||||
<refpurpose>Variation of <constant>V4L2_PIX_FMT_NV16</constant> and <constant>V4L2_PIX_FMT_NV61</constant> with planes
|
||||
non contiguous in memory. </refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is a multi-planar, two-plane version of the YUV 4:2:0 format.
|
||||
The three components are separated into two sub-images or planes.
|
||||
<constant>V4L2_PIX_FMT_NV16M</constant> differs from <constant>V4L2_PIX_FMT_NV16
|
||||
</constant> in that the two planes are non-contiguous in memory, i.e. the chroma
|
||||
plane does not necessarily immediately follows the luma plane.
|
||||
The luminance data occupies the first plane. The Y plane has one byte per pixel.
|
||||
In the second plane there is chrominance data with alternating chroma samples.
|
||||
The CbCr plane is the same width and height, in bytes, as the Y plane.
|
||||
Each CbCr pair belongs to four pixels. For example,
|
||||
Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
|
||||
Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
|
||||
Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
|
||||
<constant>V4L2_PIX_FMT_NV61M</constant> is the same as <constant>V4L2_PIX_FMT_NV16M</constant>
|
||||
except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
|
||||
|
||||
<para><constant>V4L2_PIX_FMT_NV16M</constant> and
|
||||
<constant>V4L2_PIX_FMT_NV61M</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_NV16M</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>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cb<subscript>02</subscript></entry>
|
||||
<entry>Cr<subscript>02</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 4:</entry>
|
||||
<entry>Cb<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cb<subscript>12</subscript></entry>
|
||||
<entry>Cr<subscript>12</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 8:</entry>
|
||||
<entry>Cb<subscript>20</subscript></entry>
|
||||
<entry>Cr<subscript>20</subscript></entry>
|
||||
<entry>Cb<subscript>22</subscript></entry>
|
||||
<entry>Cr<subscript>22</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start1 + 12:</entry>
|
||||
<entry>Cb<subscript>30</subscript></entry>
|
||||
<entry>Cr<subscript>30</subscript></entry>
|
||||
<entry>Cb<subscript>32</subscript></entry>
|
||||
<entry>Cr<subscript>32</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>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>
|
||||
</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></entry><entry>C</entry><entry></entry><entry></entry>
|
||||
<entry></entry><entry>C</entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></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>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</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>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -391,9 +391,9 @@ clamp (double x)
|
|||
else return r;
|
||||
}
|
||||
|
||||
y1 = (255 / 219.0) * (Y1 - 16);
|
||||
pb = (255 / 224.0) * (Cb - 128);
|
||||
pr = (255 / 224.0) * (Cr - 128);
|
||||
y1 = (Y1 - 16) / 219.0;
|
||||
pb = (Cb - 128) / 224.0;
|
||||
pr = (Cr - 128) / 224.0;
|
||||
|
||||
r = 1.0 * y1 + 0 * pb + 1.402 * pr;
|
||||
g = 1.0 * y1 - 0.344 * pb - 0.714 * pr;
|
||||
|
@ -718,6 +718,7 @@ information.</para>
|
|||
&sub-nv12m;
|
||||
&sub-nv12mt;
|
||||
&sub-nv16;
|
||||
&sub-nv16m;
|
||||
&sub-nv24;
|
||||
&sub-m420;
|
||||
</section>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -62,18 +62,29 @@ addition to the <constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter
|
|||
control over buffers is required. This ioctl can be called multiple times to
|
||||
create buffers of different sizes.</para>
|
||||
|
||||
<para>To allocate device buffers applications initialize relevant fields of
|
||||
the <structname>v4l2_create_buffers</structname> structure. They set the
|
||||
<structfield>type</structfield> field in the
|
||||
&v4l2-format; structure, embedded in this
|
||||
structure, to the respective stream or buffer type.
|
||||
<structfield>count</structfield> must be set to the number of required buffers.
|
||||
<structfield>memory</structfield> specifies the required I/O method. The
|
||||
<structfield>format</structfield> field shall typically be filled in using
|
||||
either the <constant>VIDIOC_TRY_FMT</constant> or
|
||||
<constant>VIDIOC_G_FMT</constant> ioctl(). Additionally, applications can adjust
|
||||
<structfield>sizeimage</structfield> fields to fit their specific needs. The
|
||||
<structfield>reserved</structfield> array must be zeroed.</para>
|
||||
<para>To allocate the device buffers applications must initialize the
|
||||
relevant fields of the <structname>v4l2_create_buffers</structname> structure.
|
||||
The <structfield>count</structfield> field must be set to the number of
|
||||
requested buffers, the <structfield>memory</structfield> field specifies the
|
||||
requested I/O method and the <structfield>reserved</structfield> array must be
|
||||
zeroed.</para>
|
||||
|
||||
<para>The <structfield>format</structfield> field specifies the image format
|
||||
that the buffers must be able to handle. The application has to fill in this
|
||||
&v4l2-format;. Usually this will be done using the
|
||||
<constant>VIDIOC_TRY_FMT</constant> or <constant>VIDIOC_G_FMT</constant> ioctl()
|
||||
to ensure that the requested format is supported by the driver. Unsupported
|
||||
formats will result in an error.</para>
|
||||
|
||||
<para>The buffers created by this ioctl will have as minimum size the size
|
||||
defined by the <structfield>format.pix.sizeimage</structfield> field. If the
|
||||
<structfield>format.pix.sizeimage</structfield> field is less than the minimum
|
||||
required for the given format, then <structfield>sizeimage</structfield> will be
|
||||
increased by the driver to that minimum to allocate the buffers. If it is
|
||||
larger, then the value will be used as-is. The same applies to the
|
||||
<structfield>sizeimage</structfield> field of the
|
||||
<structname>v4l2_plane_pix_format</structname> structure in the case of
|
||||
multiplanar formats.</para>
|
||||
|
||||
<para>When the ioctl is called with a pointer to this structure the driver
|
||||
will attempt to allocate up to the requested number of buffers and store the
|
||||
|
@ -144,9 +155,9 @@ mapped</link> I/O.</para>
|
|||
<varlistentry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>The buffer type (<structfield>type</structfield> field) or the
|
||||
requested I/O method (<structfield>memory</structfield>) is not
|
||||
supported.</para>
|
||||
<para>The buffer type (<structfield>format.type</structfield> field),
|
||||
requested I/O method (<structfield>memory</structfield>) or format
|
||||
(<structfield>format</structfield> field) is not valid.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
|
|
@ -156,19 +156,19 @@ bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_H
|
|||
<entry>__u32</entry>
|
||||
<entry><structfield>il_vfrontporch</structfield></entry>
|
||||
<entry>Vertical front porch in lines for the even field (aka field 2) of
|
||||
interlaced field formats.</entry>
|
||||
interlaced field formats. Must be 0 for progressive formats.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>il_vsync</structfield></entry>
|
||||
<entry>Vertical sync length in lines for the even field (aka field 2) of
|
||||
interlaced field formats.</entry>
|
||||
interlaced field formats. Must be 0 for progressive formats.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>il_vbackporch</structfield></entry>
|
||||
<entry>Vertical back porch in lines for the even field (aka field 2) of
|
||||
interlaced field formats.</entry>
|
||||
interlaced field formats. Must be 0 for progressive formats.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
|
|
|
@ -92,8 +92,8 @@ to add them.</para>
|
|||
<entry>int</entry>
|
||||
<entry><structfield>quality</structfield></entry>
|
||||
<entry>Deprecated. If <link linkend="jpeg-quality-control"><constant>
|
||||
V4L2_CID_JPEG_IMAGE_QUALITY</constant></link> control is exposed by
|
||||
a driver applications should use it instead and ignore this field.
|
||||
V4L2_CID_JPEG_COMPRESSION_QUALITY</constant></link> control is exposed
|
||||
by a driver applications should use it instead and ignore this field.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
|
|
@ -22,8 +22,14 @@
|
|||
|
||||
<!-- LinuxTV v4l-dvb repository. -->
|
||||
<!ENTITY v4l-dvb "<ulink url='http://linuxtv.org/repo/'>http://linuxtv.org/repo/</ulink>">
|
||||
<!ENTITY dash-ent-8 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-10 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-12 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-14 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-16 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-20 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-22 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
<!ENTITY dash-ent-24 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
|
||||
]>
|
||||
|
||||
<book id="media_api">
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
* Analog Devices adv7343 video encoder
|
||||
|
||||
The ADV7343 are high speed, digital-to-analog video encoders in a 64-lead LQFP
|
||||
package. Six high speed, 3.3 V, 11-bit video DACs provide support for composite
|
||||
(CVBS), S-Video (Y-C), and component (YPrPb/RGB) analog outputs in standard
|
||||
definition (SD), enhanced definition (ED), or high definition (HD) video
|
||||
formats.
|
||||
|
||||
Required Properties :
|
||||
- compatible: Must be "adi,adv7343"
|
||||
|
||||
Optional Properties :
|
||||
- adi,power-mode-sleep-mode: on enable the current consumption is reduced to
|
||||
micro ampere level. All DACs and the internal PLL
|
||||
circuit are disabled.
|
||||
- adi,power-mode-pll-ctrl: PLL and oversampling control. This control allows
|
||||
internal PLL 1 circuit to be powered down and the
|
||||
oversampling to be switched off.
|
||||
- ad,adv7343-power-mode-dac: array configuring the power on/off DAC's 1..6,
|
||||
0 = OFF and 1 = ON, Default value when this
|
||||
property is not specified is <0 0 0 0 0 0>.
|
||||
- ad,adv7343-sd-config-dac-out: array configure SD DAC Output's 1 and 2, 0 = OFF
|
||||
and 1 = ON, Default value when this property is
|
||||
not specified is <0 0>.
|
||||
|
||||
Example:
|
||||
|
||||
i2c0@1c22000 {
|
||||
...
|
||||
...
|
||||
|
||||
adv7343@2a {
|
||||
compatible = "adi,adv7343";
|
||||
reg = <0x2a>;
|
||||
|
||||
port {
|
||||
adv7343_1: endpoint {
|
||||
adi,power-mode-sleep-mode;
|
||||
adi,power-mode-pll-ctrl;
|
||||
/* Use DAC1..3, DAC6 */
|
||||
adi,dac-enable = <1 1 1 0 0 1>;
|
||||
/* Use SD DAC output 1 */
|
||||
adi,sd-dac-enable = <1 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
* Texas Instruments THS8200 video encoder
|
||||
|
||||
The ths8200 device is a digital to analog converter used in DVD players, video
|
||||
recorders, set-top boxes.
|
||||
|
||||
Required Properties :
|
||||
- compatible : value must be "ti,ths8200"
|
||||
|
||||
Example:
|
||||
|
||||
i2c0@1c22000 {
|
||||
...
|
||||
...
|
||||
ths8200@5c {
|
||||
compatible = "ti,ths8200";
|
||||
reg = <0x5c>;
|
||||
};
|
||||
...
|
||||
};
|
|
@ -0,0 +1,53 @@
|
|||
* Texas Instruments TV7002 video decoder
|
||||
|
||||
The TVP7002 device supports digitizing of video and graphics signal in RGB and
|
||||
YPbPr color space.
|
||||
|
||||
Required Properties :
|
||||
- compatible : Must be "ti,tvp7002"
|
||||
|
||||
Optional Properties:
|
||||
- hsync-active: HSYNC Polarity configuration for the bus. Default value when
|
||||
this property is not specified is <0>.
|
||||
|
||||
- vsync-active: VSYNC Polarity configuration for the bus. Default value when
|
||||
this property is not specified is <0>.
|
||||
|
||||
- pclk-sample: Clock polarity of the bus. Default value when this property is
|
||||
not specified is <0>.
|
||||
|
||||
- sync-on-green-active: Active state of Sync-on-green signal property of the
|
||||
endpoint.
|
||||
0 = Normal Operation (Active Low, Default)
|
||||
1 = Inverted operation
|
||||
|
||||
- field-even-active: Active-high Field ID output polarity control of the bus.
|
||||
Under normal operation, the field ID output is set to logic 1 for an odd field
|
||||
(field 1) and set to logic 0 for an even field (field 0).
|
||||
0 = Normal Operation (Active Low, Default)
|
||||
1 = FID output polarity inverted
|
||||
|
||||
For further reading of port node refer Documentation/devicetree/bindings/media/
|
||||
video-interfaces.txt.
|
||||
|
||||
Example:
|
||||
|
||||
i2c0@1c22000 {
|
||||
...
|
||||
...
|
||||
tvp7002@5c {
|
||||
compatible = "ti,tvp7002";
|
||||
reg = <0x5c>;
|
||||
|
||||
port {
|
||||
tvp7002_1: endpoint {
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
pclk-sample = <0>;
|
||||
sync-on-green-active = <1>;
|
||||
field-even-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
};
|
|
@ -10,6 +10,7 @@ Required properties:
|
|||
- compatible : value should be either one among the following
|
||||
(a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs
|
||||
(b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
|
||||
(b) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
|
||||
|
||||
- reg : Physical base address of the IP registers and length of memory
|
||||
mapped region.
|
||||
|
|
|
@ -88,6 +88,8 @@ Optional endpoint properties
|
|||
- field-even-active: field signal level during the even field data transmission.
|
||||
- pclk-sample: sample data on rising (1) or falling (0) edge of the pixel clock
|
||||
signal.
|
||||
- sync-on-green-active: active state of Sync-on-green (SoG) signal, 0/1 for
|
||||
LOW/HIGH respectively.
|
||||
- data-lanes: an array of physical data lane indexes. Position of an entry
|
||||
determines the logical lane number, while the value of an entry indicates
|
||||
physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have
|
||||
|
|
|
@ -124,26 +124,27 @@ You add non-menu controls by calling v4l2_ctrl_new_std:
|
|||
const struct v4l2_ctrl_ops *ops,
|
||||
u32 id, s32 min, s32 max, u32 step, s32 def);
|
||||
|
||||
Menu controls are added by calling v4l2_ctrl_new_std_menu:
|
||||
Menu and integer menu controls are added by calling v4l2_ctrl_new_std_menu:
|
||||
|
||||
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
|
||||
const struct v4l2_ctrl_ops *ops,
|
||||
u32 id, s32 max, s32 skip_mask, s32 def);
|
||||
|
||||
Or alternatively for integer menu controls, by calling v4l2_ctrl_new_int_menu:
|
||||
Menu controls with a driver specific menu are added by calling
|
||||
v4l2_ctrl_new_std_menu_items:
|
||||
|
||||
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
|
||||
struct v4l2_ctrl_handler *hdl,
|
||||
const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
|
||||
s32 skip_mask, s32 def, const char * const *qmenu);
|
||||
|
||||
Integer menu controls with a driver specific menu can be added by calling
|
||||
v4l2_ctrl_new_int_menu:
|
||||
|
||||
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
|
||||
const struct v4l2_ctrl_ops *ops,
|
||||
u32 id, s32 max, s32 def, const s64 *qmenu_int);
|
||||
|
||||
Standard menu controls with a driver specific menu are added by calling
|
||||
v4l2_ctrl_new_std_menu_items:
|
||||
|
||||
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
|
||||
struct v4l2_ctrl_handler *hdl,
|
||||
const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
|
||||
s32 skip_mask, s32 def, const char * const *qmenu);
|
||||
|
||||
These functions are typically called right after the v4l2_ctrl_handler_init:
|
||||
|
||||
static const s64 exp_bias_qmenu[] = {
|
||||
|
|
26
MAINTAINERS
26
MAINTAINERS
|
@ -580,12 +580,24 @@ L: linux-media@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/media/i2c/ad9389b*
|
||||
|
||||
ANALOG DEVICES INC ADV7511 DRIVER
|
||||
M: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/media/i2c/adv7511*
|
||||
|
||||
ANALOG DEVICES INC ADV7604 DRIVER
|
||||
M: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/media/i2c/adv7604*
|
||||
|
||||
ANALOG DEVICES INC ADV7842 DRIVER
|
||||
M: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/media/i2c/adv7842*
|
||||
|
||||
ANALOG DEVICES INC ASOC CODEC DRIVERS
|
||||
M: Lars-Peter Clausen <lars@metafoo.de>
|
||||
L: device-drivers-devel@blackfin.uclinux.org
|
||||
|
@ -639,6 +651,12 @@ S: Maintained
|
|||
F: drivers/net/appletalk/
|
||||
F: net/appletalk/
|
||||
|
||||
APTINA CAMERA SENSOR PLL
|
||||
M: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/media/i2c/aptina-pll.*
|
||||
|
||||
ARASAN COMPACT FLASH PATA CONTROLLER
|
||||
M: Viresh Kumar <viresh.linux@gmail.com>
|
||||
L: linux-ide@vger.kernel.org
|
||||
|
@ -5518,7 +5536,7 @@ L: platform-driver-x86@vger.kernel.org
|
|||
S: Supported
|
||||
F: drivers/platform/x86/msi-wmi.c
|
||||
|
||||
MT9M032 SENSOR DRIVER
|
||||
MT9M032 APTINA SENSOR DRIVER
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
@ -5526,7 +5544,7 @@ S: Maintained
|
|||
F: drivers/media/i2c/mt9m032.c
|
||||
F: include/media/mt9m032.h
|
||||
|
||||
MT9P031 SENSOR DRIVER
|
||||
MT9P031 APTINA CAMERA SENSOR
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
@ -5534,7 +5552,7 @@ S: Maintained
|
|||
F: drivers/media/i2c/mt9p031.c
|
||||
F: include/media/mt9p031.h
|
||||
|
||||
MT9T001 SENSOR DRIVER
|
||||
MT9T001 APTINA CAMERA SENSOR
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
@ -5542,7 +5560,7 @@ S: Maintained
|
|||
F: drivers/media/i2c/mt9t001.c
|
||||
F: include/media/mt9t001.h
|
||||
|
||||
MT9V032 SENSOR DRIVER
|
||||
MT9V032 APTINA CAMERA SENSOR
|
||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
|
|
@ -82,6 +82,13 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
|
|||
# CONFIG_HWMON is not set
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2C_RCAR=y
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_MEDIA_CAMERA_SUPPORT=y
|
||||
CONFIG_V4L_PLATFORM_DRIVERS=y
|
||||
CONFIG_SOC_CAMERA=y
|
||||
CONFIG_VIDEO_RCAR_VIN=y
|
||||
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
|
||||
CONFIG_VIDEO_ML86V7667=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_SH_HSPI=y
|
||||
CONFIG_USB=y
|
||||
|
|
|
@ -84,6 +84,13 @@ CONFIG_GPIO_RCAR=y
|
|||
CONFIG_THERMAL=y
|
||||
CONFIG_RCAR_THERMAL=y
|
||||
CONFIG_SSB=y
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_MEDIA_CAMERA_SUPPORT=y
|
||||
CONFIG_V4L_PLATFORM_DRIVERS=y
|
||||
CONFIG_SOC_CAMERA=y
|
||||
CONFIG_VIDEO_RCAR_VIN=y
|
||||
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
|
||||
CONFIG_VIDEO_ADV7180=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_RCAR_PHY=y
|
||||
CONFIG_MMC=y
|
||||
|
|
|
@ -1249,12 +1249,10 @@ static struct vpif_capture_config da850_vpif_capture_config = {
|
|||
|
||||
static struct adv7343_platform_data adv7343_pdata = {
|
||||
.mode_config = {
|
||||
.dac_3 = 1,
|
||||
.dac_2 = 1,
|
||||
.dac_1 = 1,
|
||||
.dac = { 1, 1, 1 },
|
||||
},
|
||||
.sd_config = {
|
||||
.sd_dac_out1 = 1,
|
||||
.sd_dac_out = { 1 },
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2013 Renesas Solutions Corp.
|
||||
* Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
* Copyright (C) 2013 Cogent Embedded, Inc.
|
||||
*
|
||||
* 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
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include <linux/smsc911x.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
#include <media/soc_camera.h>
|
||||
#include <mach/common.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/r8a7778.h>
|
||||
|
@ -143,6 +145,25 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
|
|||
MMC_CAP_NEEDS_POLL,
|
||||
};
|
||||
|
||||
static struct rcar_vin_platform_data vin_platform_data __initdata = {
|
||||
.flags = RCAR_VIN_BT656,
|
||||
};
|
||||
|
||||
/* In the default configuration both decoders reside on I2C bus 0 */
|
||||
#define BOCKW_CAMERA(idx) \
|
||||
static struct i2c_board_info camera##idx##_info = { \
|
||||
I2C_BOARD_INFO("ml86v7667", 0x41 + 2 * (idx)), \
|
||||
}; \
|
||||
\
|
||||
static struct soc_camera_link iclink##idx##_ml86v7667 __initdata = { \
|
||||
.bus_id = idx, \
|
||||
.i2c_adapter_id = 0, \
|
||||
.board_info = &camera##idx##_info, \
|
||||
}
|
||||
|
||||
BOCKW_CAMERA(0);
|
||||
BOCKW_CAMERA(1);
|
||||
|
||||
static const struct pinctrl_map bockw_pinctrl_map[] = {
|
||||
/* Ether */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778",
|
||||
|
@ -174,6 +195,16 @@ static const struct pinctrl_map bockw_pinctrl_map[] = {
|
|||
"sdhi0_cd", "sdhi0"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
|
||||
"sdhi0_wp", "sdhi0"),
|
||||
/* VIN0 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778",
|
||||
"vin0_clk", "vin0"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.0", "pfc-r8a7778",
|
||||
"vin0_data8", "vin0"),
|
||||
/* VIN1 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778",
|
||||
"vin1_clk", "vin1"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7778-vin.1", "pfc-r8a7778",
|
||||
"vin1_data8", "vin1"),
|
||||
};
|
||||
|
||||
#define FPGA 0x18200000
|
||||
|
@ -192,6 +223,16 @@ static void __init bockw_init(void)
|
|||
r8a7778_add_i2c_device(0);
|
||||
r8a7778_add_hspi_device(0);
|
||||
r8a7778_add_mmc_device(&sh_mmcif_plat);
|
||||
r8a7778_add_vin_device(0, &vin_platform_data);
|
||||
/* VIN1 has a pin conflict with Ether */
|
||||
if (!IS_ENABLED(CONFIG_SH_ETH))
|
||||
r8a7778_add_vin_device(1, &vin_platform_data);
|
||||
platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
|
||||
&iclink0_ml86v7667,
|
||||
sizeof(iclink0_ml86v7667));
|
||||
platform_device_register_data(&platform_bus, "soc-camera-pdrv", 1,
|
||||
&iclink1_ml86v7667,
|
||||
sizeof(iclink1_ml86v7667));
|
||||
|
||||
i2c_register_board_info(0, i2c0_devices,
|
||||
ARRAY_SIZE(i2c0_devices));
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/*
|
||||
* marzen board support
|
||||
*
|
||||
* Copyright (C) 2011 Renesas Solutions Corp.
|
||||
* Copyright (C) 2011, 2013 Renesas Solutions Corp.
|
||||
* Copyright (C) 2011 Magnus Damm
|
||||
* Copyright (C) 2013 Cogent Embedded, Inc.
|
||||
*
|
||||
* 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
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sh_mobile_sdhi.h>
|
||||
#include <linux/mfd/tmio.h>
|
||||
#include <media/soc_camera.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/r8a7779.h>
|
||||
#include <mach/common.h>
|
||||
|
@ -178,12 +180,40 @@ static struct platform_device leds_device = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct rcar_vin_platform_data vin_platform_data __initdata = {
|
||||
.flags = RCAR_VIN_BT656,
|
||||
};
|
||||
|
||||
#define MARZEN_CAMERA(idx) \
|
||||
static struct i2c_board_info camera##idx##_info = { \
|
||||
I2C_BOARD_INFO("adv7180", 0x20 + (idx)), \
|
||||
}; \
|
||||
\
|
||||
static struct soc_camera_link iclink##idx##_adv7180 = { \
|
||||
.bus_id = 1 + 2 * (idx), \
|
||||
.i2c_adapter_id = 0, \
|
||||
.board_info = &camera##idx##_info, \
|
||||
}; \
|
||||
\
|
||||
static struct platform_device camera##idx##_device = { \
|
||||
.name = "soc-camera-pdrv", \
|
||||
.id = idx, \
|
||||
.dev = { \
|
||||
.platform_data = &iclink##idx##_adv7180, \
|
||||
}, \
|
||||
};
|
||||
|
||||
MARZEN_CAMERA(0);
|
||||
MARZEN_CAMERA(1);
|
||||
|
||||
static struct platform_device *marzen_devices[] __initdata = {
|
||||
ð_device,
|
||||
&sdhi0_device,
|
||||
&thermal_device,
|
||||
&hspi_device,
|
||||
&leds_device,
|
||||
&camera0_device,
|
||||
&camera1_device,
|
||||
};
|
||||
|
||||
static const struct pinctrl_map marzen_pinctrl_map[] = {
|
||||
|
@ -219,6 +249,16 @@ static const struct pinctrl_map marzen_pinctrl_map[] = {
|
|||
/* USB2 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform.1", "pfc-r8a7779",
|
||||
"usb2", "usb2"),
|
||||
/* VIN1 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779",
|
||||
"vin1_clk", "vin1"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.1", "pfc-r8a7779",
|
||||
"vin1_data8", "vin1"),
|
||||
/* VIN3 */
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779",
|
||||
"vin3_clk", "vin3"),
|
||||
PIN_MAP_MUX_GROUP_DEFAULT("r8a7779-vin.3", "pfc-r8a7779",
|
||||
"vin3_data8", "vin3"),
|
||||
};
|
||||
|
||||
static void __init marzen_init(void)
|
||||
|
@ -235,6 +275,8 @@ static void __init marzen_init(void)
|
|||
|
||||
r8a7779_add_standard_devices();
|
||||
r8a7779_add_usb_phy_device(&usb_phy_platform_data);
|
||||
r8a7779_add_vin_device(1, &vin_platform_data);
|
||||
r8a7779_add_vin_device(3, &vin_platform_data);
|
||||
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ enum {
|
|||
MSTP331,
|
||||
MSTP323, MSTP322, MSTP321,
|
||||
MSTP114,
|
||||
MSTP110, MSTP109,
|
||||
MSTP100,
|
||||
MSTP030,
|
||||
MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
|
||||
|
@ -119,6 +120,8 @@ static struct clk mstp_clks[MSTP_NR] = {
|
|||
[MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
|
||||
[MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
|
||||
[MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
|
||||
[MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
|
||||
[MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 9, 0), /* VIN1 */
|
||||
[MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 0, 0), /* USB0/1 */
|
||||
[MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */
|
||||
[MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */
|
||||
|
@ -146,6 +149,8 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
|
||||
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
|
||||
CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
|
||||
CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
|
||||
CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
|
||||
CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
|
||||
CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
|
||||
CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
|
||||
|
|
|
@ -112,7 +112,9 @@ static struct clk *main_clks[] = {
|
|||
};
|
||||
|
||||
enum { MSTP323, MSTP322, MSTP321, MSTP320,
|
||||
MSTP120,
|
||||
MSTP116, MSTP115, MSTP114,
|
||||
MSTP110, MSTP109, MSTP108,
|
||||
MSTP103, MSTP101, MSTP100,
|
||||
MSTP030,
|
||||
MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
|
||||
|
@ -125,9 +127,13 @@ static struct clk mstp_clks[MSTP_NR] = {
|
|||
[MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */
|
||||
[MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */
|
||||
[MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */
|
||||
[MSTP120] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 20, 0), /* VIN3 */
|
||||
[MSTP116] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 16, 0), /* PCIe */
|
||||
[MSTP115] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 15, 0), /* SATA */
|
||||
[MSTP114] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 14, 0), /* Ether */
|
||||
[MSTP110] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 10, 0), /* VIN0 */
|
||||
[MSTP109] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 9, 0), /* VIN1 */
|
||||
[MSTP108] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 8, 0), /* VIN2 */
|
||||
[MSTP103] = SH_CLK_MSTP32(&clks_clk, MSTPCR1, 3, 0), /* DU */
|
||||
[MSTP101] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 1, 0), /* USB2 */
|
||||
[MSTP100] = SH_CLK_MSTP32(&clkp_clk, MSTPCR1, 0, 0), /* USB0/1 */
|
||||
|
@ -162,10 +168,14 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_CON_ID("peripheral_clk", &clkp_clk),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_DEV_ID("r8a7779-vin.3", &mstp_clks[MSTP120]), /* VIN3 */
|
||||
CLKDEV_DEV_ID("rcar-pcie", &mstp_clks[MSTP116]), /* PCIe */
|
||||
CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
|
||||
CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
|
||||
CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
|
||||
CLKDEV_DEV_ID("r8a7779-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
|
||||
CLKDEV_DEV_ID("r8a7779-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
|
||||
CLKDEV_DEV_ID("r8a7779-vin.2", &mstp_clks[MSTP108]), /* VIN2 */
|
||||
CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
|
||||
CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
|
||||
CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/mmc/sh_mobile_sdhi.h>
|
||||
#include <linux/sh_eth.h>
|
||||
#include <linux/platform_data/usb-rcar-phy.h>
|
||||
#include <linux/platform_data/camera-rcar.h>
|
||||
|
||||
extern void r8a7778_add_standard_devices(void);
|
||||
extern void r8a7778_add_standard_devices_dt(void);
|
||||
|
@ -30,6 +31,8 @@ extern void r8a7778_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
|
|||
extern void r8a7778_add_i2c_device(int id);
|
||||
extern void r8a7778_add_hspi_device(int id);
|
||||
extern void r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info);
|
||||
extern void r8a7778_add_vin_device(int id,
|
||||
struct rcar_vin_platform_data *pdata);
|
||||
|
||||
extern void r8a7778_init_late(void);
|
||||
extern void r8a7778_init_delay(void);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/pm_domain.h>
|
||||
#include <linux/sh_eth.h>
|
||||
#include <linux/platform_data/usb-rcar-phy.h>
|
||||
#include <linux/platform_data/camera-rcar.h>
|
||||
|
||||
struct platform_device;
|
||||
|
||||
|
@ -35,6 +36,8 @@ extern void r8a7779_add_standard_devices(void);
|
|||
extern void r8a7779_add_standard_devices_dt(void);
|
||||
extern void r8a7779_add_ether_device(struct sh_eth_plat_data *pdata);
|
||||
extern void r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata);
|
||||
extern void r8a7779_add_vin_device(int idx,
|
||||
struct rcar_vin_platform_data *pdata);
|
||||
extern void r8a7779_init_late(void);
|
||||
extern void r8a7779_clock_init(void);
|
||||
extern void r8a7779_pinmux_init(void);
|
||||
|
|
|
@ -333,6 +333,40 @@ void __init r8a7778_add_mmc_device(struct sh_mmcif_plat_data *info)
|
|||
info, sizeof(*info));
|
||||
}
|
||||
|
||||
/* VIN */
|
||||
#define R8A7778_VIN(idx) \
|
||||
static struct resource vin##idx##_resources[] __initdata = { \
|
||||
DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \
|
||||
DEFINE_RES_IRQ(gic_iid(0x5a)), \
|
||||
}; \
|
||||
\
|
||||
static struct platform_device_info vin##idx##_info __initdata = { \
|
||||
.parent = &platform_bus, \
|
||||
.name = "r8a7778-vin", \
|
||||
.id = idx, \
|
||||
.res = vin##idx##_resources, \
|
||||
.num_res = ARRAY_SIZE(vin##idx##_resources), \
|
||||
.dma_mask = DMA_BIT_MASK(32), \
|
||||
}
|
||||
|
||||
R8A7778_VIN(0);
|
||||
R8A7778_VIN(1);
|
||||
|
||||
static struct platform_device_info *vin_info_table[] __initdata = {
|
||||
&vin0_info,
|
||||
&vin1_info,
|
||||
};
|
||||
|
||||
void __init r8a7778_add_vin_device(int id, struct rcar_vin_platform_data *pdata)
|
||||
{
|
||||
BUG_ON(id < 0 || id > 1);
|
||||
|
||||
vin_info_table[id]->data = pdata;
|
||||
vin_info_table[id]->size_data = sizeof(*pdata);
|
||||
|
||||
platform_device_register_full(vin_info_table[id]);
|
||||
}
|
||||
|
||||
void __init r8a7778_add_standard_devices(void)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -559,6 +559,33 @@ static struct resource ether_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
#define R8A7779_VIN(idx) \
|
||||
static struct resource vin##idx##_resources[] __initdata = { \
|
||||
DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000), \
|
||||
DEFINE_RES_IRQ(gic_iid(0x5f + (idx))), \
|
||||
}; \
|
||||
\
|
||||
static struct platform_device_info vin##idx##_info __initdata = { \
|
||||
.parent = &platform_bus, \
|
||||
.name = "r8a7779-vin", \
|
||||
.id = idx, \
|
||||
.res = vin##idx##_resources, \
|
||||
.num_res = ARRAY_SIZE(vin##idx##_resources), \
|
||||
.dma_mask = DMA_BIT_MASK(32), \
|
||||
}
|
||||
|
||||
R8A7779_VIN(0);
|
||||
R8A7779_VIN(1);
|
||||
R8A7779_VIN(2);
|
||||
R8A7779_VIN(3);
|
||||
|
||||
static struct platform_device_info *vin_info_table[] __initdata = {
|
||||
&vin0_info,
|
||||
&vin1_info,
|
||||
&vin2_info,
|
||||
&vin3_info,
|
||||
};
|
||||
|
||||
static struct platform_device *r8a7779_devices_dt[] __initdata = {
|
||||
&scif0_device,
|
||||
&scif1_device,
|
||||
|
@ -610,6 +637,16 @@ void __init r8a7779_add_usb_phy_device(struct rcar_phy_platform_data *pdata)
|
|||
pdata, sizeof(*pdata));
|
||||
}
|
||||
|
||||
void __init r8a7779_add_vin_device(int id, struct rcar_vin_platform_data *pdata)
|
||||
{
|
||||
BUG_ON(id < 0 || id > 3);
|
||||
|
||||
vin_info_table[id]->data = pdata;
|
||||
vin_info_table[id]->size_data = sizeof(*pdata);
|
||||
|
||||
platform_device_register_full(vin_info_table[id]);
|
||||
}
|
||||
|
||||
/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
|
||||
void __init __weak r8a7779_register_twd(void) { }
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ config SMS_SIANO_DEBUGFS
|
|||
depends on SMS_SIANO_MDTV
|
||||
depends on DEBUG_FS
|
||||
depends on SMS_USB_DRV
|
||||
depends on CONFIG_SMS_USB_DRV = CONFIG_SMS_SDIO_DRV
|
||||
|
||||
---help---
|
||||
Choose Y to enable visualizing a dump of the frontend
|
||||
statistics response packets via debugfs. Currently, works
|
||||
|
|
|
@ -276,7 +276,8 @@ static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
|
|||
|
||||
/* Legacy PER/BER */
|
||||
tmp = p->ets_packets * 65535;
|
||||
do_div(tmp, p->ts_packets + p->ets_packets);
|
||||
if (p->ts_packets + p->ets_packets)
|
||||
do_div(tmp, p->ts_packets + p->ets_packets);
|
||||
client->legacy_per = tmp;
|
||||
}
|
||||
|
||||
|
|
|
@ -369,4 +369,6 @@
|
|||
#define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500
|
||||
#define USB_PID_CPYTO_REDI_PC50A 0xa803
|
||||
#define USB_PID_CTVDIGDUAL_V2 0xe410
|
||||
#define USB_PID_PCTV_2002E 0x025c
|
||||
#define USB_PID_PCTV_2002E_SE 0x025d
|
||||
#endif
|
||||
|
|
|
@ -157,7 +157,6 @@ static struct regdata mb86a20s_init2[] = {
|
|||
{ 0x45, 0x04 }, /* CN symbol 4 */
|
||||
{ 0x48, 0x04 }, /* CN manual mode */
|
||||
|
||||
{ 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */
|
||||
{ 0x50, 0xd6 }, { 0x51, 0x1f },
|
||||
{ 0x50, 0xd2 }, { 0x51, 0x03 },
|
||||
{ 0x50, 0xd7 }, { 0x51, 0xbf },
|
||||
|
@ -1860,16 +1859,15 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
|
|||
dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n",
|
||||
__func__, state->if_freq, (long long)pll);
|
||||
|
||||
if (!state->config->is_serial) {
|
||||
if (!state->config->is_serial)
|
||||
regD5 &= ~1;
|
||||
|
||||
rc = mb86a20s_writereg(state, 0x50, 0xd5);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
rc = mb86a20s_writereg(state, 0x51, regD5);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
}
|
||||
rc = mb86a20s_writereg(state, 0x50, 0xd5);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
rc = mb86a20s_writereg(state, 0x51, regD5);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
rc = mb86a20s_writeregdata(state, mb86a20s_init2);
|
||||
if (rc < 0)
|
||||
|
|
|
@ -206,6 +206,18 @@ config VIDEO_ADV7604
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called adv7604.
|
||||
|
||||
config VIDEO_ADV7842
|
||||
tristate "Analog Devices ADV7842 decoder"
|
||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
---help---
|
||||
Support for the Analog Devices ADV7842 video decoder.
|
||||
|
||||
This is a Analog Devices Component/Graphics/SD Digitizer
|
||||
with 2:1 Multiplexed HDMI Receiver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called adv7842.
|
||||
|
||||
config VIDEO_BT819
|
||||
tristate "BT819A VideoStream decoder"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
|
@ -417,6 +429,17 @@ config VIDEO_ADV7393
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called adv7393.
|
||||
|
||||
config VIDEO_ADV7511
|
||||
tristate "Analog Devices ADV7511 encoder"
|
||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
---help---
|
||||
Support for the Analog Devices ADV7511 video encoder.
|
||||
|
||||
This is a Analog Devices HDMI transmitter.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called adv7511.
|
||||
|
||||
config VIDEO_AD9389B
|
||||
tristate "Analog Devices AD9389B encoder"
|
||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
|
|
|
@ -26,7 +26,9 @@ obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
|
|||
obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
|
||||
obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
|
||||
obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
|
||||
obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o
|
||||
obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
|
||||
obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o
|
||||
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
|
||||
obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
|
||||
obj-$(CONFIG_VIDEO_BT819) += bt819.o
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/v4l2-dv-timings.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-dv-timings.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/ad9389b.h>
|
||||
|
||||
|
@ -442,22 +443,11 @@ static int ad9389b_log_status(struct v4l2_subdev *sd)
|
|||
vic_detect, vic_sent);
|
||||
}
|
||||
}
|
||||
if (state->dv_timings.type == V4L2_DV_BT_656_1120) {
|
||||
struct v4l2_bt_timings *bt = bt = &state->dv_timings.bt;
|
||||
u32 frame_width = bt->width + bt->hfrontporch +
|
||||
bt->hsync + bt->hbackporch;
|
||||
u32 frame_height = bt->height + bt->vfrontporch +
|
||||
bt->vsync + bt->vbackporch;
|
||||
u32 frame_size = frame_width * frame_height;
|
||||
|
||||
v4l2_info(sd, "timings: %ux%u%s%u (%ux%u). Pix freq. = %u Hz. Polarities = 0x%x\n",
|
||||
bt->width, bt->height, bt->interlaced ? "i" : "p",
|
||||
frame_size > 0 ? (unsigned)bt->pixelclock / frame_size : 0,
|
||||
frame_width, frame_height,
|
||||
(unsigned)bt->pixelclock, bt->polarities);
|
||||
} else {
|
||||
if (state->dv_timings.type == V4L2_DV_BT_656_1120)
|
||||
v4l2_print_dv_timings(sd->name, "timings: ",
|
||||
&state->dv_timings, false);
|
||||
else
|
||||
v4l2_info(sd, "no timings set\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -636,95 +626,34 @@ static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_dv_timings ad9389b_timings[] = {
|
||||
V4L2_DV_BT_CEA_720X480P59_94,
|
||||
V4L2_DV_BT_CEA_720X576P50,
|
||||
V4L2_DV_BT_CEA_1280X720P24,
|
||||
V4L2_DV_BT_CEA_1280X720P25,
|
||||
V4L2_DV_BT_CEA_1280X720P30,
|
||||
V4L2_DV_BT_CEA_1280X720P50,
|
||||
V4L2_DV_BT_CEA_1280X720P60,
|
||||
V4L2_DV_BT_CEA_1920X1080P24,
|
||||
V4L2_DV_BT_CEA_1920X1080P25,
|
||||
V4L2_DV_BT_CEA_1920X1080P30,
|
||||
V4L2_DV_BT_CEA_1920X1080P50,
|
||||
V4L2_DV_BT_CEA_1920X1080P60,
|
||||
|
||||
V4L2_DV_BT_DMT_640X350P85,
|
||||
V4L2_DV_BT_DMT_640X400P85,
|
||||
V4L2_DV_BT_DMT_720X400P85,
|
||||
V4L2_DV_BT_DMT_640X480P60,
|
||||
V4L2_DV_BT_DMT_640X480P72,
|
||||
V4L2_DV_BT_DMT_640X480P75,
|
||||
V4L2_DV_BT_DMT_640X480P85,
|
||||
V4L2_DV_BT_DMT_800X600P56,
|
||||
V4L2_DV_BT_DMT_800X600P60,
|
||||
V4L2_DV_BT_DMT_800X600P72,
|
||||
V4L2_DV_BT_DMT_800X600P75,
|
||||
V4L2_DV_BT_DMT_800X600P85,
|
||||
V4L2_DV_BT_DMT_848X480P60,
|
||||
V4L2_DV_BT_DMT_1024X768P60,
|
||||
V4L2_DV_BT_DMT_1024X768P70,
|
||||
V4L2_DV_BT_DMT_1024X768P75,
|
||||
V4L2_DV_BT_DMT_1024X768P85,
|
||||
V4L2_DV_BT_DMT_1152X864P75,
|
||||
V4L2_DV_BT_DMT_1280X768P60_RB,
|
||||
V4L2_DV_BT_DMT_1280X768P60,
|
||||
V4L2_DV_BT_DMT_1280X768P75,
|
||||
V4L2_DV_BT_DMT_1280X768P85,
|
||||
V4L2_DV_BT_DMT_1280X800P60_RB,
|
||||
V4L2_DV_BT_DMT_1280X800P60,
|
||||
V4L2_DV_BT_DMT_1280X800P75,
|
||||
V4L2_DV_BT_DMT_1280X800P85,
|
||||
V4L2_DV_BT_DMT_1280X960P60,
|
||||
V4L2_DV_BT_DMT_1280X960P85,
|
||||
V4L2_DV_BT_DMT_1280X1024P60,
|
||||
V4L2_DV_BT_DMT_1280X1024P75,
|
||||
V4L2_DV_BT_DMT_1280X1024P85,
|
||||
V4L2_DV_BT_DMT_1360X768P60,
|
||||
V4L2_DV_BT_DMT_1400X1050P60_RB,
|
||||
V4L2_DV_BT_DMT_1400X1050P60,
|
||||
V4L2_DV_BT_DMT_1400X1050P75,
|
||||
V4L2_DV_BT_DMT_1400X1050P85,
|
||||
V4L2_DV_BT_DMT_1440X900P60_RB,
|
||||
V4L2_DV_BT_DMT_1440X900P60,
|
||||
V4L2_DV_BT_DMT_1600X1200P60,
|
||||
V4L2_DV_BT_DMT_1680X1050P60_RB,
|
||||
V4L2_DV_BT_DMT_1680X1050P60,
|
||||
V4L2_DV_BT_DMT_1792X1344P60,
|
||||
V4L2_DV_BT_DMT_1856X1392P60,
|
||||
V4L2_DV_BT_DMT_1920X1200P60_RB,
|
||||
V4L2_DV_BT_DMT_1366X768P60,
|
||||
V4L2_DV_BT_DMT_1920X1080P60,
|
||||
{},
|
||||
static const struct v4l2_dv_timings_cap ad9389b_timings_cap = {
|
||||
.type = V4L2_DV_BT_656_1120,
|
||||
.bt = {
|
||||
.max_width = 1920,
|
||||
.max_height = 1200,
|
||||
.min_pixelclock = 25000000,
|
||||
.max_pixelclock = 170000000,
|
||||
.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
|
||||
V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
|
||||
.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
|
||||
V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
|
||||
},
|
||||
};
|
||||
|
||||
static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
struct ad9389b_state *state = get_ad9389b_state(sd);
|
||||
int i;
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s:\n", __func__);
|
||||
|
||||
/* quick sanity check */
|
||||
if (timings->type != V4L2_DV_BT_656_1120)
|
||||
return -EINVAL;
|
||||
|
||||
if (timings->bt.interlaced)
|
||||
return -EINVAL;
|
||||
if (timings->bt.pixelclock < 27000000 ||
|
||||
timings->bt.pixelclock > 170000000)
|
||||
if (!v4l2_valid_dv_timings(timings, &ad9389b_timings_cap, NULL, NULL))
|
||||
return -EINVAL;
|
||||
|
||||
/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
|
||||
if the format is listed in ad9389b_timings[] */
|
||||
for (i = 0; ad9389b_timings[i].bt.width; i++) {
|
||||
if (v4l_match_dv_timings(timings, &ad9389b_timings[i], 0)) {
|
||||
*timings = ad9389b_timings[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if the format is one of the CEA or DMT timings. */
|
||||
v4l2_find_dv_timings_cap(timings, &ad9389b_timings_cap, 0, NULL, NULL);
|
||||
|
||||
timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
|
||||
|
||||
|
@ -762,26 +691,14 @@ static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
|
|||
static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_enum_dv_timings *timings)
|
||||
{
|
||||
if (timings->index >= ARRAY_SIZE(ad9389b_timings))
|
||||
return -EINVAL;
|
||||
|
||||
memset(timings->reserved, 0, sizeof(timings->reserved));
|
||||
timings->timings = ad9389b_timings[timings->index];
|
||||
return 0;
|
||||
return v4l2_enum_dv_timings_cap(timings, &ad9389b_timings_cap,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings_cap *cap)
|
||||
{
|
||||
cap->type = V4L2_DV_BT_656_1120;
|
||||
cap->bt.max_width = 1920;
|
||||
cap->bt.max_height = 1200;
|
||||
cap->bt.min_pixelclock = 27000000;
|
||||
cap->bt.max_pixelclock = 170000000;
|
||||
cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
|
||||
V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
|
||||
cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
|
||||
V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM;
|
||||
*cap = ad9389b_timings_cap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -930,8 +847,10 @@ static void ad9389b_edid_handler(struct work_struct *work)
|
|||
* (DVI connectors are particularly prone to this problem). */
|
||||
if (state->edid.read_retries) {
|
||||
state->edid.read_retries--;
|
||||
/* EDID read failed, trigger a retry */
|
||||
ad9389b_wr(sd, 0xc9, 0xf);
|
||||
v4l2_dbg(1, debug, sd, "%s: edid read failed\n", __func__);
|
||||
state->have_monitor = false;
|
||||
ad9389b_s_power(sd, false);
|
||||
ad9389b_s_power(sd, true);
|
||||
queue_delayed_work(state->work_queue,
|
||||
&state->edid_handler, EDID_DELAY);
|
||||
return;
|
||||
|
@ -967,11 +886,9 @@ static void ad9389b_setup(struct v4l2_subdev *sd)
|
|||
ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0);
|
||||
/* Output format: RGB 4:4:4 */
|
||||
ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0);
|
||||
/* CSC fixed point: +/-2, 1st order interpolation 4:2:2 -> 4:4:4 up
|
||||
conversion, Aspect ratio: 16:9 */
|
||||
ad9389b_wr_and_or(sd, 0x17, 0xe1, 0x0e);
|
||||
/* Disable pixel repetition and CSC */
|
||||
ad9389b_wr_and_or(sd, 0x3b, 0x9e, 0x0);
|
||||
/* 1st order interpolation 4:2:2 -> 4:4:4 up conversion,
|
||||
Aspect ratio: 16:9 */
|
||||
ad9389b_wr_and_or(sd, 0x17, 0xf9, 0x06);
|
||||
/* Output format: RGB 4:4:4, Active Format Information is valid. */
|
||||
ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08);
|
||||
/* Underscanned */
|
||||
|
@ -1056,12 +973,12 @@ static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd)
|
|||
|
||||
static bool edid_block_verify_crc(u8 *edid_block)
|
||||
{
|
||||
int i;
|
||||
u8 sum = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 127; i++)
|
||||
sum += *(edid_block + i);
|
||||
return ((255 - sum + 1) == edid_block[127]);
|
||||
for (i = 0; i < 128; i++)
|
||||
sum += edid_block[i];
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment)
|
||||
|
@ -1107,6 +1024,8 @@ static bool ad9389b_check_edid_status(struct v4l2_subdev *sd)
|
|||
}
|
||||
if (!edid_segment_verify_crc(sd, segment)) {
|
||||
/* edid crc error, force reread of edid segment */
|
||||
v4l2_err(sd, "%s: edid crc error\n", __func__);
|
||||
state->have_monitor = false;
|
||||
ad9389b_s_power(sd, false);
|
||||
ad9389b_s_power(sd, true);
|
||||
return false;
|
||||
|
@ -1190,27 +1109,27 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *
|
|||
state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
|
||||
V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
|
||||
0, V4L2_DV_TX_MODE_DVI_D);
|
||||
state->hdmi_mode_ctrl->is_private = true;
|
||||
state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL,
|
||||
V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0);
|
||||
state->hotplug_ctrl->is_private = true;
|
||||
state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL,
|
||||
V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0);
|
||||
state->rx_sense_ctrl->is_private = true;
|
||||
state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL,
|
||||
V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0);
|
||||
state->have_edid0_ctrl->is_private = true;
|
||||
state->rgb_quantization_range_ctrl =
|
||||
v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
|
||||
V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
|
||||
0, V4L2_DV_RGB_RANGE_AUTO);
|
||||
state->rgb_quantization_range_ctrl->is_private = true;
|
||||
sd->ctrl_handler = hdl;
|
||||
if (hdl->error) {
|
||||
err = hdl->error;
|
||||
|
||||
goto err_hdl;
|
||||
}
|
||||
state->hdmi_mode_ctrl->is_private = true;
|
||||
state->hotplug_ctrl->is_private = true;
|
||||
state->rx_sense_ctrl->is_private = true;
|
||||
state->have_edid0_ctrl->is_private = true;
|
||||
state->rgb_quantization_range_ctrl->is_private = true;
|
||||
|
||||
state->pad.flags = MEDIA_PAD_FL_SINK;
|
||||
err = media_entity_init(&sd->entity, 1, &state->pad, 0);
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
#include <linux/uaccess.h>
|
||||
|
||||
#include <media/adv7343.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-of.h>
|
||||
|
||||
#include "adv7343_regs.h"
|
||||
|
||||
|
@ -226,12 +228,12 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
|
|||
else
|
||||
val = state->pdata->mode_config.sleep_mode << 0 |
|
||||
state->pdata->mode_config.pll_control << 1 |
|
||||
state->pdata->mode_config.dac_3 << 2 |
|
||||
state->pdata->mode_config.dac_2 << 3 |
|
||||
state->pdata->mode_config.dac_1 << 4 |
|
||||
state->pdata->mode_config.dac_6 << 5 |
|
||||
state->pdata->mode_config.dac_5 << 6 |
|
||||
state->pdata->mode_config.dac_4 << 7;
|
||||
state->pdata->mode_config.dac[2] << 2 |
|
||||
state->pdata->mode_config.dac[1] << 3 |
|
||||
state->pdata->mode_config.dac[0] << 4 |
|
||||
state->pdata->mode_config.dac[5] << 5 |
|
||||
state->pdata->mode_config.dac[4] << 6 |
|
||||
state->pdata->mode_config.dac[3] << 7;
|
||||
|
||||
err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
|
||||
if (err < 0)
|
||||
|
@ -250,15 +252,15 @@ static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
|
|||
/* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
|
||||
val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
|
||||
|
||||
if (state->pdata && state->pdata->sd_config.sd_dac_out1)
|
||||
val = val | (state->pdata->sd_config.sd_dac_out1 << 1);
|
||||
else if (state->pdata && !state->pdata->sd_config.sd_dac_out1)
|
||||
val = val & ~(state->pdata->sd_config.sd_dac_out1 << 1);
|
||||
if (state->pdata && state->pdata->sd_config.sd_dac_out[0])
|
||||
val = val | (state->pdata->sd_config.sd_dac_out[0] << 1);
|
||||
else if (state->pdata && !state->pdata->sd_config.sd_dac_out[0])
|
||||
val = val & ~(state->pdata->sd_config.sd_dac_out[0] << 1);
|
||||
|
||||
if (state->pdata && state->pdata->sd_config.sd_dac_out2)
|
||||
val = val | (state->pdata->sd_config.sd_dac_out2 << 2);
|
||||
else if (state->pdata && !state->pdata->sd_config.sd_dac_out2)
|
||||
val = val & ~(state->pdata->sd_config.sd_dac_out2 << 2);
|
||||
if (state->pdata && state->pdata->sd_config.sd_dac_out[1])
|
||||
val = val | (state->pdata->sd_config.sd_dac_out[1] << 2);
|
||||
else if (state->pdata && !state->pdata->sd_config.sd_dac_out[1])
|
||||
val = val & ~(state->pdata->sd_config.sd_dac_out[1] << 2);
|
||||
|
||||
err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
|
||||
if (err < 0)
|
||||
|
@ -398,6 +400,40 @@ static int adv7343_initialize(struct v4l2_subdev *sd)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct adv7343_platform_data *
|
||||
adv7343_get_pdata(struct i2c_client *client)
|
||||
{
|
||||
struct adv7343_platform_data *pdata;
|
||||
struct device_node *np;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
|
||||
return client->dev.platform_data;
|
||||
|
||||
np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL);
|
||||
if (!np)
|
||||
return NULL;
|
||||
|
||||
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
goto done;
|
||||
|
||||
pdata->mode_config.sleep_mode =
|
||||
of_property_read_bool(np, "adi,power-mode-sleep-mode");
|
||||
|
||||
pdata->mode_config.pll_control =
|
||||
of_property_read_bool(np, "adi,power-mode-pll-ctrl");
|
||||
|
||||
of_property_read_u32_array(np, "adi,dac-enable",
|
||||
pdata->mode_config.dac, 6);
|
||||
|
||||
of_property_read_u32_array(np, "adi,sd-dac-enable",
|
||||
pdata->sd_config.sd_dac_out, 2);
|
||||
|
||||
done:
|
||||
of_node_put(np);
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static int adv7343_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -416,7 +452,7 @@ static int adv7343_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
|
||||
/* Copy board specific information here */
|
||||
state->pdata = client->dev.platform_data;
|
||||
state->pdata = adv7343_get_pdata(client);
|
||||
|
||||
state->reg00 = 0x80;
|
||||
state->reg01 = 0x00;
|
||||
|
@ -445,16 +481,21 @@ static int adv7343_probe(struct i2c_client *client,
|
|||
ADV7343_GAIN_DEF);
|
||||
state->sd.ctrl_handler = &state->hdl;
|
||||
if (state->hdl.error) {
|
||||
int err = state->hdl.error;
|
||||
|
||||
v4l2_ctrl_handler_free(&state->hdl);
|
||||
return err;
|
||||
err = state->hdl.error;
|
||||
goto done;
|
||||
}
|
||||
v4l2_ctrl_handler_setup(&state->hdl);
|
||||
|
||||
err = adv7343_initialize(&state->sd);
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
err = v4l2_async_register_subdev(&state->sd);
|
||||
|
||||
done:
|
||||
if (err < 0)
|
||||
v4l2_ctrl_handler_free(&state->hdl);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -463,6 +504,7 @@ static int adv7343_remove(struct i2c_client *client)
|
|||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct adv7343_state *state = to_state(sd);
|
||||
|
||||
v4l2_async_unregister_subdev(&state->sd);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
v4l2_ctrl_handler_free(&state->hdl);
|
||||
|
||||
|
@ -476,8 +518,17 @@ static const struct i2c_device_id adv7343_id[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(i2c, adv7343_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id adv7343_of_match[] = {
|
||||
{.compatible = "adi,adv7343", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adv7343_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver adv7343_driver = {
|
||||
.driver = {
|
||||
.of_match_table = of_match_ptr(adv7343_of_match),
|
||||
.owner = THIS_MODULE,
|
||||
.name = "adv7343",
|
||||
},
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,7 @@
|
|||
#include <linux/v4l2-dv-timings.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-dv-timings.h>
|
||||
#include <media/adv7604.h>
|
||||
|
||||
static int debug;
|
||||
|
@ -76,6 +77,7 @@ struct adv7604_state {
|
|||
struct delayed_work delayed_work_enable_hotplug;
|
||||
bool connector_hdmi;
|
||||
bool restart_stdi_once;
|
||||
u32 prev_input_status;
|
||||
|
||||
/* i2c clients */
|
||||
struct i2c_client *i2c_avlink;
|
||||
|
@ -260,22 +262,22 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
|
|||
|
||||
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->hfrontporch + t->hsync + t->hbackporch;
|
||||
return V4L2_DV_BT_BLANKING_WIDTH(t);
|
||||
}
|
||||
|
||||
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->width + t->hfrontporch + t->hsync + t->hbackporch;
|
||||
return V4L2_DV_BT_FRAME_WIDTH(t);
|
||||
}
|
||||
|
||||
static inline unsigned vblanking(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->vfrontporch + t->vsync + t->vbackporch;
|
||||
return V4L2_DV_BT_BLANKING_HEIGHT(t);
|
||||
}
|
||||
|
||||
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->height + t->vfrontporch + t->vsync + t->vbackporch;
|
||||
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
@ -761,7 +763,7 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
|
|||
int i;
|
||||
|
||||
for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
|
||||
if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings,
|
||||
if (!v4l2_match_dv_timings(timings, &predef_vid_timings[i].timings,
|
||||
DIGITAL_INPUT ? 250000 : 1000000))
|
||||
continue;
|
||||
io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
|
||||
|
@ -990,6 +992,11 @@ static inline bool no_lock_tmds(struct v4l2_subdev *sd)
|
|||
return (io_read(sd, 0x6a) & 0xe0) != 0xe0;
|
||||
}
|
||||
|
||||
static inline bool is_hdmi(struct v4l2_subdev *sd)
|
||||
{
|
||||
return hdmi_read(sd, 0x05) & 0x80;
|
||||
}
|
||||
|
||||
static inline bool no_lock_sspd(struct v4l2_subdev *sd)
|
||||
{
|
||||
/* TODO channel 2 */
|
||||
|
@ -1044,38 +1051,6 @@ static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status)
|
|||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
static void adv7604_print_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *timings, const char *txt, bool detailed)
|
||||
{
|
||||
struct v4l2_bt_timings *bt = &timings->bt;
|
||||
u32 htot, vtot;
|
||||
|
||||
if (timings->type != V4L2_DV_BT_656_1120)
|
||||
return;
|
||||
|
||||
htot = htotal(bt);
|
||||
vtot = vtotal(bt);
|
||||
|
||||
v4l2_info(sd, "%s %dx%d%s%d (%dx%d)",
|
||||
txt, bt->width, bt->height, bt->interlaced ? "i" : "p",
|
||||
(htot * vtot) > 0 ? ((u32)bt->pixelclock /
|
||||
(htot * vtot)) : 0,
|
||||
htot, vtot);
|
||||
|
||||
if (detailed) {
|
||||
v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n",
|
||||
bt->hfrontporch,
|
||||
(bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
|
||||
bt->hsync, bt->hbackporch);
|
||||
v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n",
|
||||
bt->vfrontporch,
|
||||
(bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
|
||||
bt->vsync, bt->vbackporch);
|
||||
v4l2_info(sd, " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n",
|
||||
bt->pixelclock, bt->flags, bt->standards);
|
||||
}
|
||||
}
|
||||
|
||||
struct stdi_readback {
|
||||
u16 bl, lcf, lcvs;
|
||||
u8 hs_pol, vs_pol;
|
||||
|
@ -1187,7 +1162,7 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
|
|||
cap->type = V4L2_DV_BT_656_1120;
|
||||
cap->bt.max_width = 1920;
|
||||
cap->bt.max_height = 1200;
|
||||
cap->bt.min_pixelclock = 27000000;
|
||||
cap->bt.min_pixelclock = 25000000;
|
||||
if (DIGITAL_INPUT)
|
||||
cap->bt.max_pixelclock = 225000000;
|
||||
else
|
||||
|
@ -1208,7 +1183,7 @@ static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
|
|||
int i;
|
||||
|
||||
for (i = 0; adv7604_timings[i].bt.width; i++) {
|
||||
if (v4l_match_dv_timings(timings, &adv7604_timings[i],
|
||||
if (v4l2_match_dv_timings(timings, &adv7604_timings[i],
|
||||
DIGITAL_INPUT ? 250000 : 1000000)) {
|
||||
*timings = adv7604_timings[i];
|
||||
break;
|
||||
|
@ -1242,12 +1217,21 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
|
|||
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
|
||||
|
||||
if (DIGITAL_INPUT) {
|
||||
uint32_t freq;
|
||||
|
||||
timings->type = V4L2_DV_BT_656_1120;
|
||||
|
||||
bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
|
||||
bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
|
||||
bt->pixelclock = (hdmi_read(sd, 0x06) * 1000000) +
|
||||
freq = (hdmi_read(sd, 0x06) * 1000000) +
|
||||
((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
|
||||
if (is_hdmi(sd)) {
|
||||
/* adjust for deep color mode */
|
||||
unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8;
|
||||
|
||||
freq = freq * 8 / bits_per_channel;
|
||||
}
|
||||
bt->pixelclock = freq;
|
||||
bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
|
||||
hdmi_read(sd, 0x21);
|
||||
bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 +
|
||||
|
@ -1329,8 +1313,8 @@ found:
|
|||
}
|
||||
|
||||
if (debug > 1)
|
||||
adv7604_print_timings(sd, timings,
|
||||
"adv7604_query_dv_timings:", true);
|
||||
v4l2_print_dv_timings(sd->name, "adv7604_query_dv_timings: ",
|
||||
timings, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1372,8 +1356,8 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
|
|||
|
||||
|
||||
if (debug > 1)
|
||||
adv7604_print_timings(sd, timings,
|
||||
"adv7604_s_dv_timings:", true);
|
||||
v4l2_print_dv_timings(sd->name, "adv7604_s_dv_timings: ",
|
||||
timings, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1534,6 +1518,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
|||
{
|
||||
struct adv7604_state *state = to_state(sd);
|
||||
u8 fmt_change, fmt_change_digital, tx_5v;
|
||||
u32 input_status;
|
||||
|
||||
/* format change */
|
||||
fmt_change = io_read(sd, 0x43) & 0x98;
|
||||
|
@ -1544,9 +1529,18 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
|||
io_write(sd, 0x6c, fmt_change_digital);
|
||||
if (fmt_change || fmt_change_digital) {
|
||||
v4l2_dbg(1, debug, sd,
|
||||
"%s: ADV7604_FMT_CHANGE, fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
|
||||
"%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
|
||||
__func__, fmt_change, fmt_change_digital);
|
||||
v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
|
||||
|
||||
adv7604_g_input_status(sd, &input_status);
|
||||
if (input_status != state->prev_input_status) {
|
||||
v4l2_dbg(1, debug, sd,
|
||||
"%s: input_status = 0x%x, prev_input_status = 0x%x\n",
|
||||
__func__, input_status, state->prev_input_status);
|
||||
state->prev_input_status = input_status;
|
||||
v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
|
||||
}
|
||||
|
||||
if (handled)
|
||||
*handled = true;
|
||||
}
|
||||
|
@ -1625,7 +1619,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
|
|||
u8 avi_len;
|
||||
u8 avi_ver;
|
||||
|
||||
if (!(hdmi_read(sd, 0x05) & 0x80)) {
|
||||
if (!is_hdmi(sd)) {
|
||||
v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
|
||||
return;
|
||||
}
|
||||
|
@ -1686,6 +1680,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
|
|||
"RGB limited range (16-235)",
|
||||
"RGB full range (0-255)",
|
||||
};
|
||||
char *deep_color_mode_txt[4] = {
|
||||
"8-bits per channel",
|
||||
"10-bits per channel",
|
||||
"12-bits per channel",
|
||||
"16-bits per channel (not supported)"
|
||||
};
|
||||
|
||||
v4l2_info(sd, "-----Chip status-----\n");
|
||||
v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
|
||||
|
@ -1723,8 +1723,13 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
|
|||
if (adv7604_query_dv_timings(sd, &timings))
|
||||
v4l2_info(sd, "No video detected\n");
|
||||
else
|
||||
adv7604_print_timings(sd, &timings, "Detected format:", true);
|
||||
adv7604_print_timings(sd, &state->timings, "Configured format:", true);
|
||||
v4l2_print_dv_timings(sd->name, "Detected format: ",
|
||||
&timings, true);
|
||||
v4l2_print_dv_timings(sd->name, "Configured format: ",
|
||||
&state->timings, true);
|
||||
|
||||
if (no_signal(sd))
|
||||
return 0;
|
||||
|
||||
v4l2_info(sd, "-----Color space-----\n");
|
||||
v4l2_info(sd, "RGB quantization range ctrl: %s\n",
|
||||
|
@ -1735,15 +1740,40 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
|
|||
(reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
|
||||
(reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)",
|
||||
((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ?
|
||||
"enabled" : "disabled");
|
||||
"enabled" : "disabled");
|
||||
v4l2_info(sd, "Color space conversion: %s\n",
|
||||
csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]);
|
||||
|
||||
/* Digital video */
|
||||
if (DIGITAL_INPUT) {
|
||||
v4l2_info(sd, "-----HDMI status-----\n");
|
||||
v4l2_info(sd, "HDCP encrypted content: %s\n",
|
||||
hdmi_read(sd, 0x05) & 0x40 ? "true" : "false");
|
||||
if (!DIGITAL_INPUT)
|
||||
return 0;
|
||||
|
||||
v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D");
|
||||
v4l2_info(sd, "HDCP encrypted content: %s\n", (hdmi_read(sd, 0x05) & 0x40) ? "true" : "false");
|
||||
v4l2_info(sd, "HDCP keys read: %s%s\n",
|
||||
(hdmi_read(sd, 0x04) & 0x20) ? "yes" : "no",
|
||||
(hdmi_read(sd, 0x04) & 0x10) ? "ERROR" : "");
|
||||
if (!is_hdmi(sd)) {
|
||||
bool audio_pll_locked = hdmi_read(sd, 0x04) & 0x01;
|
||||
bool audio_sample_packet_detect = hdmi_read(sd, 0x18) & 0x01;
|
||||
bool audio_mute = io_read(sd, 0x65) & 0x40;
|
||||
|
||||
v4l2_info(sd, "Audio: pll %s, samples %s, %s\n",
|
||||
audio_pll_locked ? "locked" : "not locked",
|
||||
audio_sample_packet_detect ? "detected" : "not detected",
|
||||
audio_mute ? "muted" : "enabled");
|
||||
if (audio_pll_locked && audio_sample_packet_detect) {
|
||||
v4l2_info(sd, "Audio format: %s\n",
|
||||
(hdmi_read(sd, 0x07) & 0x20) ? "multi-channel" : "stereo");
|
||||
}
|
||||
v4l2_info(sd, "Audio CTS: %u\n", (hdmi_read(sd, 0x5b) << 12) +
|
||||
(hdmi_read(sd, 0x5c) << 8) +
|
||||
(hdmi_read(sd, 0x5d) & 0xf0));
|
||||
v4l2_info(sd, "Audio N: %u\n", ((hdmi_read(sd, 0x5d) & 0x0f) << 16) +
|
||||
(hdmi_read(sd, 0x5e) << 8) +
|
||||
hdmi_read(sd, 0x5f));
|
||||
v4l2_info(sd, "AV Mute: %s\n", (hdmi_read(sd, 0x04) & 0x40) ? "on" : "off");
|
||||
|
||||
v4l2_info(sd, "Deep color mode: %s\n", deep_color_mode_txt[(hdmi_read(sd, 0x0b) & 0x60) >> 5]);
|
||||
|
||||
print_avi_infoframe(sd);
|
||||
}
|
||||
|
@ -1952,6 +1982,10 @@ static int adv7604_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* initialize variables */
|
||||
state->restart_stdi_once = true;
|
||||
state->prev_input_status = ~0;
|
||||
|
||||
/* platform data */
|
||||
if (!pdata) {
|
||||
v4l_err(client, "No platform data!\n");
|
||||
|
@ -1987,29 +2021,30 @@ static int adv7604_probe(struct i2c_client *client,
|
|||
/* private controls */
|
||||
state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
|
||||
V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0);
|
||||
state->detect_tx_5v_ctrl->is_private = true;
|
||||
state->rgb_quantization_range_ctrl =
|
||||
v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
|
||||
V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
|
||||
0, V4L2_DV_RGB_RANGE_AUTO);
|
||||
state->rgb_quantization_range_ctrl->is_private = true;
|
||||
|
||||
/* custom controls */
|
||||
state->analog_sampling_phase_ctrl =
|
||||
v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
|
||||
state->analog_sampling_phase_ctrl->is_private = true;
|
||||
state->free_run_color_manual_ctrl =
|
||||
v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL);
|
||||
state->free_run_color_manual_ctrl->is_private = true;
|
||||
state->free_run_color_ctrl =
|
||||
v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL);
|
||||
state->free_run_color_ctrl->is_private = true;
|
||||
|
||||
sd->ctrl_handler = hdl;
|
||||
if (hdl->error) {
|
||||
err = hdl->error;
|
||||
goto err_hdl;
|
||||
}
|
||||
state->detect_tx_5v_ctrl->is_private = true;
|
||||
state->rgb_quantization_range_ctrl->is_private = true;
|
||||
state->analog_sampling_phase_ctrl->is_private = true;
|
||||
state->free_run_color_manual_ctrl->is_private = true;
|
||||
state->free_run_color_ctrl->is_private = true;
|
||||
|
||||
if (adv7604_s_detect_tx_5v_ctrl(sd)) {
|
||||
err = -ENODEV;
|
||||
goto err_hdl;
|
||||
|
@ -2035,7 +2070,6 @@ static int adv7604_probe(struct i2c_client *client,
|
|||
v4l2_err(sd, "failed to create all i2c clients\n");
|
||||
goto err_i2c;
|
||||
}
|
||||
state->restart_stdi_once = true;
|
||||
|
||||
/* work queues */
|
||||
state->work_queues = create_singlethread_workqueue(client->name);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -209,7 +209,8 @@ static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd,
|
|||
|
||||
fmt->code = V4L2_MBUS_FMT_YUYV8_2X8;
|
||||
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
fmt->field = V4L2_FIELD_INTERLACED;
|
||||
/* The top field is always transferred first by the chip */
|
||||
fmt->field = V4L2_FIELD_INTERLACED_TB;
|
||||
fmt->width = 720;
|
||||
fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/log2.h>
|
||||
|
@ -135,6 +136,8 @@ struct mt9v032 {
|
|||
struct mutex power_lock;
|
||||
int power_count;
|
||||
|
||||
struct clk *clk;
|
||||
|
||||
struct mt9v032_platform_data *pdata;
|
||||
|
||||
u32 sysclk;
|
||||
|
@ -219,10 +222,9 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
|
|||
struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
int ret;
|
||||
|
||||
if (mt9v032->pdata->set_clock) {
|
||||
mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk);
|
||||
udelay(1);
|
||||
}
|
||||
clk_set_rate(mt9v032->clk, mt9v032->sysclk);
|
||||
clk_prepare_enable(mt9v032->clk);
|
||||
udelay(1);
|
||||
|
||||
/* Reset the chip and stop data read out */
|
||||
ret = mt9v032_write(client, MT9V032_RESET, 1);
|
||||
|
@ -238,8 +240,7 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
|
|||
|
||||
static void mt9v032_power_off(struct mt9v032 *mt9v032)
|
||||
{
|
||||
if (mt9v032->pdata->set_clock)
|
||||
mt9v032->pdata->set_clock(&mt9v032->subdev, 0);
|
||||
clk_disable_unprepare(mt9v032->clk);
|
||||
}
|
||||
|
||||
static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
|
||||
|
@ -748,6 +749,10 @@ static int mt9v032_probe(struct i2c_client *client,
|
|||
if (!mt9v032)
|
||||
return -ENOMEM;
|
||||
|
||||
mt9v032->clk = devm_clk_get(&client->dev, NULL);
|
||||
if (IS_ERR(mt9v032->clk))
|
||||
return PTR_ERR(mt9v032->clk);
|
||||
|
||||
mutex_init(&mt9v032->power_lock);
|
||||
mt9v032->pdata = pdata;
|
||||
|
||||
|
|
|
@ -1083,7 +1083,7 @@ static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd,
|
|||
{
|
||||
int i = ARRAY_SIZE(ov965x_formats);
|
||||
|
||||
if (fse->index > ARRAY_SIZE(ov965x_framesizes))
|
||||
if (fse->index >= ARRAY_SIZE(ov965x_framesizes))
|
||||
return -EINVAL;
|
||||
|
||||
while (--i)
|
||||
|
|
|
@ -1111,6 +1111,11 @@ static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd,
|
|||
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
|
||||
mf = v4l2_subdev_get_try_format(fh, fmt->pad);
|
||||
*mf = fmt->format;
|
||||
if (fmt->pad == OIF_ISP_PAD) {
|
||||
mf = v4l2_subdev_get_try_format(fh, OIF_SOURCE_PAD);
|
||||
mf->width = fmt->format.width;
|
||||
mf->height = fmt->format.height;
|
||||
}
|
||||
} else {
|
||||
switch (fmt->pad) {
|
||||
case OIF_ISP_PAD:
|
||||
|
|
|
@ -1003,7 +1003,7 @@ static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
|
|||
const struct s5k6aa_interval *fi;
|
||||
int ret = 0;
|
||||
|
||||
if (fie->index > ARRAY_SIZE(s5k6aa_intervals))
|
||||
if (fie->index >= ARRAY_SIZE(s5k6aa_intervals))
|
||||
return -EINVAL;
|
||||
|
||||
v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
|
||||
|
|
|
@ -225,19 +225,27 @@ static const unsigned char saa7111_init[] = {
|
|||
0x00, 0x00
|
||||
};
|
||||
|
||||
/* SAA7113/GM7113C init codes
|
||||
* It's important that R_14... R_17 == 0x00
|
||||
* for the gm7113c chip to deliver stable video
|
||||
/*
|
||||
* This table has one illegal value, and some values that are not
|
||||
* correct according to the datasheet initialization table.
|
||||
*
|
||||
* If you need a table with legal/default values tell the driver in
|
||||
* i2c_board_info.platform_data, and you will get the gm7113c_init
|
||||
* table instead.
|
||||
*/
|
||||
|
||||
/* SAA7113 Init codes */
|
||||
static const unsigned char saa7113_init[] = {
|
||||
R_01_INC_DELAY, 0x08,
|
||||
R_02_INPUT_CNTL_1, 0xc2,
|
||||
R_03_INPUT_CNTL_2, 0x30,
|
||||
R_04_INPUT_CNTL_3, 0x00,
|
||||
R_05_INPUT_CNTL_4, 0x00,
|
||||
R_06_H_SYNC_START, 0x89,
|
||||
R_06_H_SYNC_START, 0x89, /* Illegal value -119,
|
||||
* min. value = -108 (0x94) */
|
||||
R_07_H_SYNC_STOP, 0x0d,
|
||||
R_08_SYNC_CNTL, 0x88,
|
||||
R_08_SYNC_CNTL, 0x88, /* Not datasheet default.
|
||||
* HTC = VTR mode, should be 0x98 */
|
||||
R_09_LUMA_CNTL, 0x01,
|
||||
R_0A_LUMA_BRIGHT_CNTL, 0x80,
|
||||
R_0B_LUMA_CONTRAST_CNTL, 0x47,
|
||||
|
@ -245,9 +253,45 @@ static const unsigned char saa7113_init[] = {
|
|||
R_0D_CHROMA_HUE_CNTL, 0x00,
|
||||
R_0E_CHROMA_CNTL_1, 0x01,
|
||||
R_0F_CHROMA_GAIN_CNTL, 0x2a,
|
||||
R_10_CHROMA_CNTL_2, 0x08,
|
||||
R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default.
|
||||
* VRLN enabled, should be 0x00 */
|
||||
R_11_MODE_DELAY_CNTL, 0x0c,
|
||||
R_12_RT_SIGNAL_CNTL, 0x07,
|
||||
R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default,
|
||||
* should be 0x01 */
|
||||
R_13_RT_X_PORT_OUT_CNTL, 0x00,
|
||||
R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
|
||||
R_15_VGATE_START_FID_CHG, 0x00,
|
||||
R_16_VGATE_STOP, 0x00,
|
||||
R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
|
||||
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
/*
|
||||
* GM7113C is a clone of the SAA7113 chip
|
||||
* This init table is copied out of the saa7113 datasheet.
|
||||
* In R_08 we enable "Automatic Field Detection" [AUFD],
|
||||
* this is disabled when saa711x_set_v4lstd is called.
|
||||
*/
|
||||
static const unsigned char gm7113c_init[] = {
|
||||
R_01_INC_DELAY, 0x08,
|
||||
R_02_INPUT_CNTL_1, 0xc0,
|
||||
R_03_INPUT_CNTL_2, 0x33,
|
||||
R_04_INPUT_CNTL_3, 0x00,
|
||||
R_05_INPUT_CNTL_4, 0x00,
|
||||
R_06_H_SYNC_START, 0xe9,
|
||||
R_07_H_SYNC_STOP, 0x0d,
|
||||
R_08_SYNC_CNTL, 0x98,
|
||||
R_09_LUMA_CNTL, 0x01,
|
||||
R_0A_LUMA_BRIGHT_CNTL, 0x80,
|
||||
R_0B_LUMA_CONTRAST_CNTL, 0x47,
|
||||
R_0C_CHROMA_SAT_CNTL, 0x40,
|
||||
R_0D_CHROMA_HUE_CNTL, 0x00,
|
||||
R_0E_CHROMA_CNTL_1, 0x01,
|
||||
R_0F_CHROMA_GAIN_CNTL, 0x2a,
|
||||
R_10_CHROMA_CNTL_2, 0x00,
|
||||
R_11_MODE_DELAY_CNTL, 0x0c,
|
||||
R_12_RT_SIGNAL_CNTL, 0x01,
|
||||
R_13_RT_X_PORT_OUT_CNTL, 0x00,
|
||||
R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
|
||||
R_15_VGATE_START_FID_CHG, 0x00,
|
||||
|
@ -462,24 +506,6 @@ static const unsigned char saa7115_cfg_50hz_video[] = {
|
|||
|
||||
/* ============== SAA7715 VIDEO templates (end) ======= */
|
||||
|
||||
/* ============== GM7113C VIDEO templates ============= */
|
||||
static const unsigned char gm7113c_cfg_60hz_video[] = {
|
||||
R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
|
||||
R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
|
||||
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char gm7113c_cfg_50hz_video[] = {
|
||||
R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
|
||||
R_0E_CHROMA_CNTL_1, 0x07,
|
||||
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
/* ============== GM7113C VIDEO templates (end) ======= */
|
||||
|
||||
|
||||
static const unsigned char saa7115_cfg_vbi_on[] = {
|
||||
R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
|
||||
R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
|
||||
|
@ -964,17 +990,24 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
|
|||
// This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
|
||||
if (std & V4L2_STD_525_60) {
|
||||
v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
|
||||
if (state->ident == GM7113C)
|
||||
saa711x_writeregs(sd, gm7113c_cfg_60hz_video);
|
||||
else
|
||||
if (state->ident == GM7113C) {
|
||||
u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
|
||||
reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
|
||||
reg |= SAA7113_R_08_FSEL;
|
||||
saa711x_write(sd, R_08_SYNC_CNTL, reg);
|
||||
} else {
|
||||
saa711x_writeregs(sd, saa7115_cfg_60hz_video);
|
||||
}
|
||||
saa711x_set_size(sd, 720, 480);
|
||||
} else {
|
||||
v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
|
||||
if (state->ident == GM7113C)
|
||||
saa711x_writeregs(sd, gm7113c_cfg_50hz_video);
|
||||
else
|
||||
if (state->ident == GM7113C) {
|
||||
u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
|
||||
reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
|
||||
saa711x_write(sd, R_08_SYNC_CNTL, reg);
|
||||
} else {
|
||||
saa711x_writeregs(sd, saa7115_cfg_50hz_video);
|
||||
}
|
||||
saa711x_set_size(sd, 720, 576);
|
||||
}
|
||||
|
||||
|
@ -1596,6 +1629,65 @@ static const struct v4l2_subdev_ops saa711x_ops = {
|
|||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
static void saa711x_write_platform_data(struct saa711x_state *state,
|
||||
struct saa7115_platform_data *data)
|
||||
{
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
u8 work;
|
||||
|
||||
if (state->ident != GM7113C &&
|
||||
state->ident != SAA7113)
|
||||
return;
|
||||
|
||||
if (data->saa7113_r08_htc) {
|
||||
work = saa711x_read(sd, R_08_SYNC_CNTL);
|
||||
work &= ~SAA7113_R_08_HTC_MASK;
|
||||
work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET);
|
||||
saa711x_write(sd, R_08_SYNC_CNTL, work);
|
||||
}
|
||||
|
||||
if (data->saa7113_r10_vrln) {
|
||||
work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
|
||||
work &= ~SAA7113_R_10_VRLN_MASK;
|
||||
if (*data->saa7113_r10_vrln)
|
||||
work |= (1 << SAA7113_R_10_VRLN_OFFSET);
|
||||
saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
|
||||
}
|
||||
|
||||
if (data->saa7113_r10_ofts) {
|
||||
work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
|
||||
work &= ~SAA7113_R_10_OFTS_MASK;
|
||||
work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET);
|
||||
saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
|
||||
}
|
||||
|
||||
if (data->saa7113_r12_rts0) {
|
||||
work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
|
||||
work &= ~SAA7113_R_12_RTS0_MASK;
|
||||
work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET);
|
||||
|
||||
/* According to the datasheet,
|
||||
* SAA7113_RTS_DOT_IN should only be used on RTS1 */
|
||||
WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN);
|
||||
saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
|
||||
}
|
||||
|
||||
if (data->saa7113_r12_rts1) {
|
||||
work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
|
||||
work &= ~SAA7113_R_12_RTS1_MASK;
|
||||
work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET);
|
||||
saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
|
||||
}
|
||||
|
||||
if (data->saa7113_r13_adlsb) {
|
||||
work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL);
|
||||
work &= ~SAA7113_R_13_ADLSB_MASK;
|
||||
if (*data->saa7113_r13_adlsb)
|
||||
work |= (1 << SAA7113_R_13_ADLSB_OFFSET);
|
||||
saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* saa711x_detect_chip - Detects the saa711x (or clone) variant
|
||||
* @client: I2C client structure.
|
||||
|
@ -1704,6 +1796,7 @@ static int saa711x_probe(struct i2c_client *client,
|
|||
struct saa711x_state *state;
|
||||
struct v4l2_subdev *sd;
|
||||
struct v4l2_ctrl_handler *hdl;
|
||||
struct saa7115_platform_data *pdata;
|
||||
int ident;
|
||||
char name[CHIP_VER_SIZE + 1];
|
||||
|
||||
|
@ -1767,21 +1860,31 @@ static int saa711x_probe(struct i2c_client *client,
|
|||
|
||||
/* init to 60hz/48khz */
|
||||
state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
|
||||
pdata = client->dev.platform_data;
|
||||
switch (state->ident) {
|
||||
case SAA7111:
|
||||
case SAA7111A:
|
||||
saa711x_writeregs(sd, saa7111_init);
|
||||
break;
|
||||
case GM7113C:
|
||||
saa711x_writeregs(sd, gm7113c_init);
|
||||
break;
|
||||
case SAA7113:
|
||||
saa711x_writeregs(sd, saa7113_init);
|
||||
if (pdata && pdata->saa7113_force_gm7113c_init)
|
||||
saa711x_writeregs(sd, gm7113c_init);
|
||||
else
|
||||
saa711x_writeregs(sd, saa7113_init);
|
||||
break;
|
||||
default:
|
||||
state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
|
||||
saa711x_writeregs(sd, saa7115_init_auto_input);
|
||||
}
|
||||
if (state->ident > SAA7111A)
|
||||
if (state->ident > SAA7111A && state->ident != GM7113C)
|
||||
saa711x_writeregs(sd, saa7115_init_misc);
|
||||
|
||||
if (pdata)
|
||||
saa711x_write_platform_data(state, pdata);
|
||||
|
||||
saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
|
||||
v4l2_ctrl_handler_setup(hdl);
|
||||
|
||||
|
|
|
@ -201,6 +201,25 @@
|
|||
#define R_FB_PULSE_C_POS_MSB 0xfb
|
||||
#define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES 0xff
|
||||
|
||||
/* SAA7113 bit-masks */
|
||||
#define SAA7113_R_08_HTC_OFFSET 3
|
||||
#define SAA7113_R_08_HTC_MASK (0x3 << SAA7113_R_08_HTC_OFFSET)
|
||||
#define SAA7113_R_08_FSEL 0x40
|
||||
#define SAA7113_R_08_AUFD 0x80
|
||||
|
||||
#define SAA7113_R_10_VRLN_OFFSET 3
|
||||
#define SAA7113_R_10_VRLN_MASK (0x1 << SAA7113_R_10_VRLN_OFFSET)
|
||||
#define SAA7113_R_10_OFTS_OFFSET 6
|
||||
#define SAA7113_R_10_OFTS_MASK (0x3 << SAA7113_R_10_OFTS_OFFSET)
|
||||
|
||||
#define SAA7113_R_12_RTS0_OFFSET 0
|
||||
#define SAA7113_R_12_RTS0_MASK (0xf << SAA7113_R_12_RTS0_OFFSET)
|
||||
#define SAA7113_R_12_RTS1_OFFSET 4
|
||||
#define SAA7113_R_12_RTS1_MASK (0xf << SAA7113_R_12_RTS1_OFFSET)
|
||||
|
||||
#define SAA7113_R_13_ADLSB_OFFSET 7
|
||||
#define SAA7113_R_13_ADLSB_MASK (0x1 << SAA7113_R_13_ADLSB_OFFSET)
|
||||
|
||||
#if 0
|
||||
/* Those structs will be used in the future for debug purposes */
|
||||
struct saa711x_reg_descr {
|
||||
|
|
|
@ -87,6 +87,17 @@ static void print_pll(struct device *dev, struct smiapp_pll *pll)
|
|||
dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
|
||||
}
|
||||
|
||||
/*
|
||||
* Heuristically guess the PLL tree for a given common multiplier and
|
||||
* divisor. Begin with the operational timing and continue to video
|
||||
* timing once operational timing has been verified.
|
||||
*
|
||||
* @mul is the PLL multiplier and @div is the common divisor
|
||||
* (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
|
||||
* multiplier will be a multiple of @mul.
|
||||
*
|
||||
* @return Zero on success, error code on error.
|
||||
*/
|
||||
static int __smiapp_pll_calculate(struct device *dev,
|
||||
const struct smiapp_pll_limits *limits,
|
||||
struct smiapp_pll *pll, uint32_t mul,
|
||||
|
@ -95,6 +106,12 @@ static int __smiapp_pll_calculate(struct device *dev,
|
|||
uint32_t sys_div;
|
||||
uint32_t best_pix_div = INT_MAX >> 1;
|
||||
uint32_t vt_op_binning_div;
|
||||
/*
|
||||
* Higher multipliers (and divisors) are often required than
|
||||
* necessitated by the external clock and the output clocks.
|
||||
* There are limits for all values in the clock tree. These
|
||||
* are the minimum and maximum multiplier for mul.
|
||||
*/
|
||||
uint32_t more_mul_min, more_mul_max;
|
||||
uint32_t more_mul_factor;
|
||||
uint32_t min_vt_div, max_vt_div, vt_div;
|
||||
|
|
|
@ -1122,9 +1122,9 @@ static int smiapp_power_on(struct smiapp_sensor *sensor)
|
|||
rval = sensor->platform_data->set_xclk(
|
||||
&sensor->src->sd, sensor->platform_data->ext_clk);
|
||||
else
|
||||
rval = clk_enable(sensor->ext_clk);
|
||||
rval = clk_prepare_enable(sensor->ext_clk);
|
||||
if (rval < 0) {
|
||||
dev_dbg(&client->dev, "failed to set xclk\n");
|
||||
dev_dbg(&client->dev, "failed to enable xclk\n");
|
||||
goto out_xclk_fail;
|
||||
}
|
||||
usleep_range(1000, 1000);
|
||||
|
@ -1244,7 +1244,7 @@ out_cci_addr_fail:
|
|||
if (sensor->platform_data->set_xclk)
|
||||
sensor->platform_data->set_xclk(&sensor->src->sd, 0);
|
||||
else
|
||||
clk_disable(sensor->ext_clk);
|
||||
clk_disable_unprepare(sensor->ext_clk);
|
||||
|
||||
out_xclk_fail:
|
||||
regulator_disable(sensor->vana);
|
||||
|
@ -1270,7 +1270,7 @@ static void smiapp_power_off(struct smiapp_sensor *sensor)
|
|||
if (sensor->platform_data->set_xclk)
|
||||
sensor->platform_data->set_xclk(&sensor->src->sd, 0);
|
||||
else
|
||||
clk_disable(sensor->ext_clk);
|
||||
clk_disable_unprepare(sensor->ext_clk);
|
||||
usleep_range(5000, 5000);
|
||||
regulator_disable(sensor->vana);
|
||||
sensor->streaming = 0;
|
||||
|
@ -1835,12 +1835,12 @@ static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev,
|
|||
* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]
|
||||
/ sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE];
|
||||
|
||||
a = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
|
||||
max(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
|
||||
b = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
|
||||
max(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
|
||||
max_m = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
|
||||
max(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
|
||||
a = clamp(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
|
||||
sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
|
||||
b = clamp(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
|
||||
sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
|
||||
max_m = clamp(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN],
|
||||
sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX]);
|
||||
|
||||
dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m);
|
||||
|
||||
|
@ -2363,11 +2363,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
|||
}
|
||||
|
||||
if (!sensor->platform_data->set_xclk) {
|
||||
sensor->ext_clk = devm_clk_get(&client->dev,
|
||||
sensor->platform_data->ext_clk_name);
|
||||
sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk");
|
||||
if (IS_ERR(sensor->ext_clk)) {
|
||||
dev_err(&client->dev, "could not get clock %s\n",
|
||||
sensor->platform_data->ext_clk_name);
|
||||
dev_err(&client->dev, "could not get clock\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -2375,8 +2373,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
|||
sensor->platform_data->ext_clk);
|
||||
if (rval < 0) {
|
||||
dev_err(&client->dev,
|
||||
"unable to set clock %s freq to %u\n",
|
||||
sensor->platform_data->ext_clk_name,
|
||||
"unable to set clock freq to %u\n",
|
||||
sensor->platform_data->ext_clk);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -2839,7 +2836,7 @@ static int smiapp_remove(struct i2c_client *client)
|
|||
if (sensor->platform_data->set_xclk)
|
||||
sensor->platform_data->set_xclk(&sensor->src->sd, 0);
|
||||
else
|
||||
clk_disable(sensor->ext_clk);
|
||||
clk_disable_unprepare(sensor->ext_clk);
|
||||
sensor->power_count = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -946,6 +946,10 @@ static int mt9m111_probe(struct i2c_client *client,
|
|||
if (!mt9m111)
|
||||
return -ENOMEM;
|
||||
|
||||
mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
|
||||
if (IS_ERR(mt9m111->clk))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
/* Default HIGHPOWER context */
|
||||
mt9m111->ctx = &context_b;
|
||||
|
||||
|
@ -963,8 +967,10 @@ static int mt9m111_probe(struct i2c_client *client,
|
|||
&mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
|
||||
V4L2_EXPOSURE_AUTO);
|
||||
mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
|
||||
if (mt9m111->hdl.error)
|
||||
return mt9m111->hdl.error;
|
||||
if (mt9m111->hdl.error) {
|
||||
ret = mt9m111->hdl.error;
|
||||
goto out_clkput;
|
||||
}
|
||||
|
||||
/* Second stage probe - when a capture adapter is there */
|
||||
mt9m111->rect.left = MT9M111_MIN_DARK_COLS;
|
||||
|
@ -975,18 +981,25 @@ static int mt9m111_probe(struct i2c_client *client,
|
|||
mt9m111->lastpage = -1;
|
||||
mutex_init(&mt9m111->power_lock);
|
||||
|
||||
mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
|
||||
if (IS_ERR(mt9m111->clk)) {
|
||||
ret = PTR_ERR(mt9m111->clk);
|
||||
goto eclkget;
|
||||
}
|
||||
ret = soc_camera_power_init(&client->dev, ssdd);
|
||||
if (ret < 0)
|
||||
goto out_hdlfree;
|
||||
|
||||
ret = mt9m111_video_probe(client);
|
||||
if (ret) {
|
||||
v4l2_clk_put(mt9m111->clk);
|
||||
eclkget:
|
||||
v4l2_ctrl_handler_free(&mt9m111->hdl);
|
||||
}
|
||||
if (ret < 0)
|
||||
goto out_hdlfree;
|
||||
|
||||
mt9m111->subdev.dev = &client->dev;
|
||||
ret = v4l2_async_register_subdev(&mt9m111->subdev);
|
||||
if (ret < 0)
|
||||
goto out_hdlfree;
|
||||
|
||||
return 0;
|
||||
|
||||
out_hdlfree:
|
||||
v4l2_ctrl_handler_free(&mt9m111->hdl);
|
||||
out_clkput:
|
||||
v4l2_clk_put(mt9m111->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -995,6 +1008,7 @@ static int mt9m111_remove(struct i2c_client *client)
|
|||
{
|
||||
struct mt9m111 *mt9m111 = to_mt9m111(client);
|
||||
|
||||
v4l2_async_unregister_subdev(&mt9m111->subdev);
|
||||
v4l2_clk_put(mt9m111->clk);
|
||||
v4l2_device_unregister_subdev(&mt9m111->subdev);
|
||||
v4l2_ctrl_handler_free(&mt9m111->hdl);
|
||||
|
|
|
@ -594,9 +594,12 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
|
|||
ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
vdev->dev.type = &mt9t031_dev_type;
|
||||
if (vdev)
|
||||
/* Not needed during probing, when vdev isn't available yet */
|
||||
vdev->dev.type = &mt9t031_dev_type;
|
||||
} else {
|
||||
vdev->dev.type = NULL;
|
||||
if (vdev)
|
||||
vdev->dev.type = NULL;
|
||||
soc_camera_power_off(&client->dev, ssdd, mt9t031->clk);
|
||||
}
|
||||
|
||||
|
|
|
@ -291,10 +291,8 @@ static int ths7303_log_status(struct v4l2_subdev *sd)
|
|||
struct v4l2_bt_timings *bt = bt = &state->bt;
|
||||
u32 frame_width, frame_height;
|
||||
|
||||
frame_width = bt->width + bt->hfrontporch +
|
||||
bt->hsync + bt->hbackporch;
|
||||
frame_height = bt->height + bt->vfrontporch +
|
||||
bt->vsync + bt->vbackporch;
|
||||
frame_width = V4L2_DV_BT_FRAME_WIDTH(bt);
|
||||
frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt);
|
||||
v4l2_info(sd,
|
||||
"timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n",
|
||||
bt->width, bt->height, bt->interlaced ? "i" : "p",
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/v4l2-dv-timings.h>
|
||||
|
||||
#include <media/v4l2-dv-timings.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
#include "ths8200_regs.h"
|
||||
|
@ -42,18 +44,16 @@ struct ths8200_state {
|
|||
struct v4l2_dv_timings dv_timings;
|
||||
};
|
||||
|
||||
static const struct v4l2_dv_timings ths8200_timings[] = {
|
||||
V4L2_DV_BT_CEA_720X480P59_94,
|
||||
V4L2_DV_BT_CEA_1280X720P24,
|
||||
V4L2_DV_BT_CEA_1280X720P25,
|
||||
V4L2_DV_BT_CEA_1280X720P30,
|
||||
V4L2_DV_BT_CEA_1280X720P50,
|
||||
V4L2_DV_BT_CEA_1280X720P60,
|
||||
V4L2_DV_BT_CEA_1920X1080P24,
|
||||
V4L2_DV_BT_CEA_1920X1080P25,
|
||||
V4L2_DV_BT_CEA_1920X1080P30,
|
||||
V4L2_DV_BT_CEA_1920X1080P50,
|
||||
V4L2_DV_BT_CEA_1920X1080P60,
|
||||
static const struct v4l2_dv_timings_cap ths8200_timings_cap = {
|
||||
.type = V4L2_DV_BT_656_1120,
|
||||
.bt = {
|
||||
.max_width = 1920,
|
||||
.max_height = 1080,
|
||||
.min_pixelclock = 25000000,
|
||||
.max_pixelclock = 148500000,
|
||||
.standards = V4L2_DV_BT_STD_CEA861,
|
||||
.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE,
|
||||
},
|
||||
};
|
||||
|
||||
static inline struct ths8200_state *to_state(struct v4l2_subdev *sd)
|
||||
|
@ -63,22 +63,22 @@ static inline struct ths8200_state *to_state(struct v4l2_subdev *sd)
|
|||
|
||||
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->hfrontporch + t->hsync + t->hbackporch;
|
||||
return V4L2_DV_BT_BLANKING_WIDTH(t);
|
||||
}
|
||||
|
||||
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->width + t->hfrontporch + t->hsync + t->hbackporch;
|
||||
return V4L2_DV_BT_FRAME_WIDTH(t);
|
||||
}
|
||||
|
||||
static inline unsigned vblanking(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->vfrontporch + t->vsync + t->vbackporch;
|
||||
return V4L2_DV_BT_BLANKING_HEIGHT(t);
|
||||
}
|
||||
|
||||
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
||||
{
|
||||
return t->height + t->vfrontporch + t->vsync + t->vbackporch;
|
||||
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
||||
}
|
||||
|
||||
static int ths8200_read(struct v4l2_subdev *sd, u8 reg)
|
||||
|
@ -133,39 +133,6 @@ static int ths8200_s_register(struct v4l2_subdev *sd,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void ths8200_print_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *timings,
|
||||
const char *txt, bool detailed)
|
||||
{
|
||||
struct v4l2_bt_timings *bt = &timings->bt;
|
||||
u32 htot, vtot;
|
||||
|
||||
if (timings->type != V4L2_DV_BT_656_1120)
|
||||
return;
|
||||
|
||||
htot = htotal(bt);
|
||||
vtot = vtotal(bt);
|
||||
|
||||
v4l2_info(sd, "%s %dx%d%s%d (%dx%d)",
|
||||
txt, bt->width, bt->height, bt->interlaced ? "i" : "p",
|
||||
(htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0,
|
||||
htot, vtot);
|
||||
|
||||
if (detailed) {
|
||||
v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n",
|
||||
bt->hfrontporch,
|
||||
(bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
|
||||
bt->hsync, bt->hbackporch);
|
||||
v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n",
|
||||
bt->vfrontporch,
|
||||
(bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
|
||||
bt->vsync, bt->vbackporch);
|
||||
v4l2_info(sd,
|
||||
" pixelclock: %lld, flags: 0x%x, standards: 0x%x\n",
|
||||
bt->pixelclock, bt->flags, bt->standards);
|
||||
}
|
||||
}
|
||||
|
||||
static int ths8200_log_status(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct ths8200_state *state = to_state(sd);
|
||||
|
@ -182,9 +149,8 @@ static int ths8200_log_status(struct v4l2_subdev *sd)
|
|||
ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB),
|
||||
(ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 +
|
||||
ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB));
|
||||
ths8200_print_timings(sd, &state->dv_timings,
|
||||
"Configured format:", true);
|
||||
|
||||
v4l2_print_dv_timings(sd->name, "Configured format:",
|
||||
&state->dv_timings, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -409,25 +375,15 @@ static int ths8200_s_dv_timings(struct v4l2_subdev *sd,
|
|||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
struct ths8200_state *state = to_state(sd);
|
||||
int i;
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s:\n", __func__);
|
||||
|
||||
if (timings->type != V4L2_DV_BT_656_1120)
|
||||
if (!v4l2_valid_dv_timings(timings, &ths8200_timings_cap,
|
||||
NULL, NULL))
|
||||
return -EINVAL;
|
||||
|
||||
/* TODO Support interlaced formats */
|
||||
if (timings->bt.interlaced) {
|
||||
v4l2_dbg(1, debug, sd, "TODO Support interlaced formats\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ths8200_timings); i++) {
|
||||
if (v4l_match_dv_timings(&ths8200_timings[i], timings, 10))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(ths8200_timings)) {
|
||||
if (!v4l2_find_dv_timings_cap(timings, &ths8200_timings_cap, 10,
|
||||
NULL, NULL)) {
|
||||
v4l2_dbg(1, debug, sd, "Unsupported format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -457,26 +413,14 @@ static int ths8200_g_dv_timings(struct v4l2_subdev *sd,
|
|||
static int ths8200_enum_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_enum_dv_timings *timings)
|
||||
{
|
||||
/* Check requested format index is within range */
|
||||
if (timings->index >= ARRAY_SIZE(ths8200_timings))
|
||||
return -EINVAL;
|
||||
|
||||
timings->timings = ths8200_timings[timings->index];
|
||||
|
||||
return 0;
|
||||
return v4l2_enum_dv_timings_cap(timings, &ths8200_timings_cap,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static int ths8200_dv_timings_cap(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings_cap *cap)
|
||||
{
|
||||
cap->type = V4L2_DV_BT_656_1120;
|
||||
cap->bt.max_width = 1920;
|
||||
cap->bt.max_height = 1080;
|
||||
cap->bt.min_pixelclock = 27000000;
|
||||
cap->bt.max_pixelclock = 148500000;
|
||||
cap->bt.standards = V4L2_DV_BT_STD_CEA861;
|
||||
cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE;
|
||||
|
||||
*cap = ths8200_timings_cap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -500,6 +444,7 @@ static int ths8200_probe(struct i2c_client *client,
|
|||
{
|
||||
struct ths8200_state *state;
|
||||
struct v4l2_subdev *sd;
|
||||
int error;
|
||||
|
||||
/* Check if the adapter supports the needed features */
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
|
@ -517,6 +462,10 @@ static int ths8200_probe(struct i2c_client *client,
|
|||
|
||||
ths8200_core_init(sd);
|
||||
|
||||
error = v4l2_async_register_subdev(&state->sd);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
|
||||
client->addr << 1, client->adapter->name);
|
||||
|
||||
|
@ -526,12 +475,13 @@ static int ths8200_probe(struct i2c_client *client,
|
|||
static int ths8200_remove(struct i2c_client *client)
|
||||
{
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct ths8200_state *decoder = to_state(sd);
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
|
||||
client->addr << 1, client->adapter->name);
|
||||
|
||||
ths8200_s_power(sd, false);
|
||||
|
||||
v4l2_async_unregister_subdev(&decoder->sd);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
|
||||
return 0;
|
||||
|
@ -543,10 +493,19 @@ static struct i2c_device_id ths8200_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ths8200_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id ths8200_of_match[] = {
|
||||
{ .compatible = "ti,ths8200", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ths8200_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver ths8200_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ths8200",
|
||||
.of_match_table = of_match_ptr(ths8200_of_match),
|
||||
},
|
||||
.probe = ths8200_probe,
|
||||
.remove = ths8200_remove,
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
|
@ -1175,16 +1176,22 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
sd->ctrl_handler = &decoder->hdl;
|
||||
if (decoder->hdl.error) {
|
||||
ret = decoder->hdl.error;
|
||||
|
||||
v4l2_ctrl_handler_free(&decoder->hdl);
|
||||
return ret;
|
||||
goto done;
|
||||
}
|
||||
v4l2_ctrl_handler_setup(&decoder->hdl);
|
||||
|
||||
v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
|
||||
|
||||
return 0;
|
||||
ret = v4l2_async_register_subdev(&decoder->sd);
|
||||
if (!ret)
|
||||
v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
|
||||
|
||||
done:
|
||||
if (ret < 0) {
|
||||
v4l2_ctrl_handler_free(&decoder->hdl);
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
media_entity_cleanup(&decoder->sd.entity);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1199,6 +1206,7 @@ static int tvp514x_remove(struct i2c_client *client)
|
|||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct tvp514x_decoder *decoder = to_decoder(sd);
|
||||
|
||||
v4l2_async_unregister_subdev(&decoder->sd);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
media_entity_cleanup(&decoder->sd.entity);
|
||||
|
|
|
@ -31,9 +31,12 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/v4l2-dv-timings.h>
|
||||
#include <media/tvp7002.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-of.h>
|
||||
|
||||
#include "tvp7002_reg.h"
|
||||
|
||||
MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver");
|
||||
|
@ -942,6 +945,48 @@ static const struct v4l2_subdev_ops tvp7002_ops = {
|
|||
.pad = &tvp7002_pad_ops,
|
||||
};
|
||||
|
||||
static struct tvp7002_config *
|
||||
tvp7002_get_pdata(struct i2c_client *client)
|
||||
{
|
||||
struct v4l2_of_endpoint bus_cfg;
|
||||
struct tvp7002_config *pdata;
|
||||
struct device_node *endpoint;
|
||||
unsigned int flags;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
|
||||
return client->dev.platform_data;
|
||||
|
||||
endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL);
|
||||
if (!endpoint)
|
||||
return NULL;
|
||||
|
||||
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
goto done;
|
||||
|
||||
v4l2_of_parse_endpoint(endpoint, &bus_cfg);
|
||||
flags = bus_cfg.bus.parallel.flags;
|
||||
|
||||
if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
|
||||
pdata->hs_polarity = 1;
|
||||
|
||||
if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
|
||||
pdata->vs_polarity = 1;
|
||||
|
||||
if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
|
||||
pdata->clk_polarity = 1;
|
||||
|
||||
if (flags & V4L2_MBUS_FIELD_EVEN_HIGH)
|
||||
pdata->fid_polarity = 1;
|
||||
|
||||
if (flags & V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH)
|
||||
pdata->sog_polarity = 1;
|
||||
|
||||
done:
|
||||
of_node_put(endpoint);
|
||||
return pdata;
|
||||
}
|
||||
|
||||
/*
|
||||
* tvp7002_probe - Probe a TVP7002 device
|
||||
* @c: ptr to i2c_client struct
|
||||
|
@ -953,32 +998,32 @@ static const struct v4l2_subdev_ops tvp7002_ops = {
|
|||
*/
|
||||
static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
|
||||
{
|
||||
struct tvp7002_config *pdata = tvp7002_get_pdata(c);
|
||||
struct v4l2_subdev *sd;
|
||||
struct tvp7002 *device;
|
||||
struct v4l2_dv_timings timings;
|
||||
int polarity_a;
|
||||
int polarity_b;
|
||||
u8 revision;
|
||||
|
||||
int error;
|
||||
|
||||
if (pdata == NULL) {
|
||||
dev_err(&c->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check if the adapter supports the needed features */
|
||||
if (!i2c_check_functionality(c->adapter,
|
||||
I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
|
||||
return -EIO;
|
||||
|
||||
if (!c->dev.platform_data) {
|
||||
v4l_err(c, "No platform data!!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
device = devm_kzalloc(&c->dev, sizeof(struct tvp7002), GFP_KERNEL);
|
||||
|
||||
if (!device)
|
||||
return -ENOMEM;
|
||||
|
||||
sd = &device->sd;
|
||||
device->pdata = c->dev.platform_data;
|
||||
device->pdata = pdata;
|
||||
device->current_timings = tvp7002_timings;
|
||||
|
||||
/* Tell v4l2 the device is ready */
|
||||
|
@ -1039,6 +1084,10 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
|
|||
}
|
||||
v4l2_ctrl_handler_setup(&device->hdl);
|
||||
|
||||
error = v4l2_async_register_subdev(&device->sd);
|
||||
if (error)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -1063,6 +1112,7 @@ static int tvp7002_remove(struct i2c_client *c)
|
|||
|
||||
v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter"
|
||||
"on address 0x%x\n", c->addr);
|
||||
v4l2_async_unregister_subdev(&device->sd);
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
media_entity_cleanup(&device->sd.entity);
|
||||
#endif
|
||||
|
@ -1078,9 +1128,18 @@ static const struct i2c_device_id tvp7002_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tvp7002_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id tvp7002_of_match[] = {
|
||||
{ .compatible = "ti,tvp7002", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tvp7002_of_match);
|
||||
#endif
|
||||
|
||||
/* I2C driver data */
|
||||
static struct i2c_driver tvp7002_driver = {
|
||||
.driver = {
|
||||
.of_match_table = of_match_ptr(tvp7002_of_match),
|
||||
.owner = THIS_MODULE,
|
||||
.name = TVP7002_MODULE_NAME,
|
||||
},
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <media/media-entity.h>
|
||||
|
@ -121,7 +122,6 @@ static struct media_entity *stack_pop(struct media_entity_graph *graph)
|
|||
return entity;
|
||||
}
|
||||
|
||||
#define stack_peek(en) ((en)->stack[(en)->top - 1].entity)
|
||||
#define link_top(en) ((en)->stack[(en)->top].link)
|
||||
#define stack_top(en) ((en)->stack[(en)->top].entity)
|
||||
|
||||
|
@ -140,6 +140,12 @@ void media_entity_graph_walk_start(struct media_entity_graph *graph,
|
|||
{
|
||||
graph->top = 0;
|
||||
graph->stack[graph->top].entity = NULL;
|
||||
bitmap_zero(graph->entities, MEDIA_ENTITY_ENUM_MAX_ID);
|
||||
|
||||
if (WARN_ON(entity->id >= MEDIA_ENTITY_ENUM_MAX_ID))
|
||||
return;
|
||||
|
||||
__set_bit(entity->id, graph->entities);
|
||||
stack_push(graph, entity);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
|
||||
|
@ -180,9 +186,11 @@ media_entity_graph_walk_next(struct media_entity_graph *graph)
|
|||
|
||||
/* Get the entity in the other end of the link . */
|
||||
next = media_entity_other(entity, link);
|
||||
if (WARN_ON(next->id >= MEDIA_ENTITY_ENUM_MAX_ID))
|
||||
return NULL;
|
||||
|
||||
/* Was it the entity we came here from? */
|
||||
if (next == stack_peek(graph)) {
|
||||
/* Has the entity already been visited? */
|
||||
if (__test_and_set_bit(next->id, graph->entities)) {
|
||||
link_top(graph)++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -4441,9 +4441,7 @@ static void tibetCS16_init(struct bttv *btv)
|
|||
* is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
|
||||
* unit 3, the second (which is the master) is logical unit 0, etc.
|
||||
* We need to maintain the status of the analog switch (which of the 16
|
||||
* cameras is connected to which of the 4 controllers). Rather than
|
||||
* add to the bttv structure for this, we use the data reserved for
|
||||
* the mbox (unused for this card type).
|
||||
* cameras is connected to which of the 4 controllers) in sw_status array.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -4478,7 +4476,6 @@ static void kodicom4400r_write(struct bttv *btv,
|
|||
*/
|
||||
static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
|
||||
{
|
||||
char *sw_status;
|
||||
int xaddr, yaddr;
|
||||
struct bttv *mctlr;
|
||||
static unsigned char map[4] = {3, 0, 2, 1};
|
||||
|
@ -4489,14 +4486,13 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
|
|||
}
|
||||
yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
|
||||
yaddr = map[yaddr];
|
||||
sw_status = (char *)(&mctlr->mbox_we);
|
||||
xaddr = input & 0xf;
|
||||
/* Check if the controller/camera pair has changed, else ignore */
|
||||
if (sw_status[yaddr] != xaddr)
|
||||
if (mctlr->sw_status[yaddr] != xaddr)
|
||||
{
|
||||
/* "open" the old switch, "close" the new one, save the new */
|
||||
kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
|
||||
sw_status[yaddr] = xaddr;
|
||||
kodicom4400r_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0);
|
||||
mctlr->sw_status[yaddr] = xaddr;
|
||||
kodicom4400r_write(mctlr, xaddr, yaddr, 1);
|
||||
}
|
||||
}
|
||||
|
@ -4509,7 +4505,6 @@ static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
|
|||
*/
|
||||
static void kodicom4400r_init(struct bttv *btv)
|
||||
{
|
||||
char *sw_status = (char *)(&btv->mbox_we);
|
||||
int ix;
|
||||
|
||||
gpio_inout(0x0003ff, 0x0003ff);
|
||||
|
@ -4517,7 +4512,7 @@ static void kodicom4400r_init(struct bttv *btv)
|
|||
gpio_write(0);
|
||||
/* Preset camera 0 to the 4 controllers */
|
||||
for (ix = 0; ix < 4; ix++) {
|
||||
sw_status[ix] = ix;
|
||||
btv->sw_status[ix] = ix;
|
||||
kodicom4400r_write(btv, ix, ix, 1);
|
||||
}
|
||||
/*
|
||||
|
@ -4794,7 +4789,6 @@ static void gv800s_write(struct bttv *btv,
|
|||
static void gv800s_muxsel(struct bttv *btv, unsigned int input)
|
||||
{
|
||||
struct bttv *mctlr;
|
||||
char *sw_status;
|
||||
int xaddr, yaddr;
|
||||
static unsigned int map[4][4] = { { 0x0, 0x4, 0xa, 0x6 },
|
||||
{ 0x1, 0x5, 0xb, 0x7 },
|
||||
|
@ -4807,14 +4801,13 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input)
|
|||
return;
|
||||
}
|
||||
yaddr = (btv->c.nr - mctlr->c.nr) & 3;
|
||||
sw_status = (char *)(&mctlr->mbox_we);
|
||||
xaddr = map[yaddr][input] & 0xf;
|
||||
|
||||
/* Check if the controller/camera pair has changed, ignore otherwise */
|
||||
if (sw_status[yaddr] != xaddr) {
|
||||
if (mctlr->sw_status[yaddr] != xaddr) {
|
||||
/* disable the old switch, enable the new one and save status */
|
||||
gv800s_write(mctlr, sw_status[yaddr], yaddr, 0);
|
||||
sw_status[yaddr] = xaddr;
|
||||
gv800s_write(mctlr, mctlr->sw_status[yaddr], yaddr, 0);
|
||||
mctlr->sw_status[yaddr] = xaddr;
|
||||
gv800s_write(mctlr, xaddr, yaddr, 1);
|
||||
}
|
||||
}
|
||||
|
@ -4822,7 +4815,6 @@ static void gv800s_muxsel(struct bttv *btv, unsigned int input)
|
|||
/* GeoVision GV-800(S) "master" chip init */
|
||||
static void gv800s_init(struct bttv *btv)
|
||||
{
|
||||
char *sw_status = (char *)(&btv->mbox_we);
|
||||
int ix;
|
||||
|
||||
gpio_inout(0xf107f, 0xf107f);
|
||||
|
@ -4831,7 +4823,7 @@ static void gv800s_init(struct bttv *btv)
|
|||
|
||||
/* Preset camera 0 to the 4 controllers */
|
||||
for (ix = 0; ix < 4; ix++) {
|
||||
sw_status[ix] = ix;
|
||||
btv->sw_status[ix] = ix;
|
||||
gv800s_write(btv, ix, ix, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -459,6 +459,9 @@ struct bttv {
|
|||
int mbox_iow;
|
||||
int mbox_csel;
|
||||
|
||||
/* switch status for multi-controller cards */
|
||||
char sw_status[4];
|
||||
|
||||
/* risc memory management data
|
||||
- must acquire s_lock before changing these
|
||||
- only the irq handler is supported to touch top + bottom + vcurr */
|
||||
|
|
|
@ -29,6 +29,7 @@ config VIDEO_CX23885
|
|||
select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "cx23885.h"
|
||||
#include "cx23885-av.h"
|
||||
#include "cx23885-video.h"
|
||||
|
||||
void cx23885_av_work_handler(struct work_struct *work)
|
||||
{
|
||||
|
@ -32,5 +33,17 @@ void cx23885_av_work_handler(struct work_struct *work)
|
|||
|
||||
v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
|
||||
PCI_MSK_AV_CORE, &handled);
|
||||
|
||||
/* Getting here with the interrupt not handled
|
||||
then probbaly flatiron does have pending interrupts.
|
||||
*/
|
||||
if (!handled) {
|
||||
/* clear left and right adc channel interrupt request flag */
|
||||
cx23885_flatiron_write(dev, 0x1f,
|
||||
cx23885_flatiron_read(dev, 0x1f) | 0x80);
|
||||
cx23885_flatiron_write(dev, 0x23,
|
||||
cx23885_flatiron_read(dev, 0x23) | 0x80);
|
||||
}
|
||||
|
||||
cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
|
||||
}
|
||||
|
|
|
@ -528,11 +528,12 @@ struct cx23885_board cx23885_boards[] = {
|
|||
} },
|
||||
},
|
||||
[CX23885_BOARD_MYGICA_X8507] = {
|
||||
.name = "Mygica X8507",
|
||||
.name = "Mygica X8502/X8507 ISDB-T",
|
||||
.tuner_type = TUNER_XC5000,
|
||||
.tuner_addr = 0x61,
|
||||
.tuner_bus = 1,
|
||||
.porta = CX23885_ANALOG_VIDEO,
|
||||
.portb = CX23885_MPEG_DVB,
|
||||
.input = {
|
||||
{
|
||||
.type = CX23885_VMUX_TELEVISION,
|
||||
|
@ -1281,7 +1282,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
|||
case CX23885_BOARD_MYGICA_X8507:
|
||||
/* GPIO-0 (0)Analog / (1)Digital TV */
|
||||
/* GPIO-1 reset XC5000 */
|
||||
/* GPIO-2 reset LGS8GL5 / LGS8G75 */
|
||||
/* GPIO-2 demod reset */
|
||||
cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1);
|
||||
cx23885_gpio_clear(dev, GPIO_1 | GPIO_2);
|
||||
mdelay(100);
|
||||
|
@ -1677,6 +1678,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
|||
break;
|
||||
case CX23885_BOARD_MYGICA_X8506:
|
||||
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
ts1->gen_ctrl_val = 0x5; /* Parallel */
|
||||
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
|
|
|
@ -1941,10 +1941,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
|
|||
|
||||
if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) {
|
||||
cx23885_irq_disable(dev, PCI_MSK_AV_CORE);
|
||||
if (!schedule_work(&dev->cx25840_work))
|
||||
printk(KERN_ERR "%s: failed to set up deferred work for"
|
||||
" AV Core/IR interrupt. Interrupt is disabled"
|
||||
" and won't be re-enabled\n", dev->name);
|
||||
schedule_work(&dev->cx25840_work);
|
||||
handled++;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "stb6100_cfg.h"
|
||||
#include "tda10071.h"
|
||||
#include "a8293.h"
|
||||
#include "mb86a20s.h"
|
||||
|
||||
static unsigned int debug;
|
||||
|
||||
|
@ -119,8 +120,6 @@ static void dvb_buf_release(struct videobuf_queue *q,
|
|||
cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
|
||||
}
|
||||
|
||||
static int cx23885_dvb_set_frontend(struct dvb_frontend *fe);
|
||||
|
||||
static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open)
|
||||
{
|
||||
struct videobuf_dvb_frontends *f;
|
||||
|
@ -135,12 +134,6 @@ static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open)
|
|||
|
||||
if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
|
||||
fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
|
||||
|
||||
/*
|
||||
* FIXME: Improve this path to avoid calling the
|
||||
* cx23885_dvb_set_frontend() every time it passes here.
|
||||
*/
|
||||
cx23885_dvb_set_frontend(fe->dvb.frontend);
|
||||
}
|
||||
|
||||
static struct videobuf_queue_ops dvb_qops = {
|
||||
|
@ -500,6 +493,15 @@ static struct xc5000_config mygica_x8506_xc5000_config = {
|
|||
.if_khz = 5380,
|
||||
};
|
||||
|
||||
static struct mb86a20s_config mygica_x8507_mb86a20s_config = {
|
||||
.demod_address = 0x10,
|
||||
};
|
||||
|
||||
static struct xc5000_config mygica_x8507_xc5000_config = {
|
||||
.i2c_address = 0x61,
|
||||
.if_khz = 4000,
|
||||
};
|
||||
|
||||
static struct stv090x_config prof_8000_stv090x_config = {
|
||||
.device = STV0903,
|
||||
.demod_mode = STV090x_SINGLE,
|
||||
|
@ -556,14 +558,27 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
|
|||
}
|
||||
break;
|
||||
case CX23885_BOARD_MYGICA_X8506:
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
|
||||
/* Select Digital TV */
|
||||
cx23885_gpio_set(dev, GPIO_0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call the real set_frontend */
|
||||
if (port->set_frontend)
|
||||
return port->set_frontend(fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cx23885_set_frontend_hook(struct cx23885_tsport *port,
|
||||
struct dvb_frontend *fe)
|
||||
{
|
||||
port->set_frontend = fe->ops.set_frontend;
|
||||
fe->ops.set_frontend = cx23885_dvb_set_frontend;
|
||||
}
|
||||
|
||||
static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
|
||||
.prod = LGS8GXX_PROD_LGS8G75,
|
||||
.demod_address = 0x19,
|
||||
|
@ -771,6 +786,8 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
0x60, &dev->i2c_bus[1].i2c_adap,
|
||||
&hauppauge_hvr127x_config);
|
||||
}
|
||||
if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1275)
|
||||
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
|
||||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1255:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
|
||||
|
@ -1106,6 +1123,21 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
&i2c_bus2->i2c_adap,
|
||||
&mygica_x8506_xc5000_config);
|
||||
}
|
||||
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
|
||||
break;
|
||||
case CX23885_BOARD_MYGICA_X8507:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
i2c_bus2 = &dev->i2c_bus[1];
|
||||
fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
|
||||
&mygica_x8507_mb86a20s_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
dvb_attach(xc5000_attach,
|
||||
fe0->dvb.frontend,
|
||||
&i2c_bus2->i2c_adap,
|
||||
&mygica_x8507_xc5000_config);
|
||||
}
|
||||
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
|
||||
break;
|
||||
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
|
@ -1119,6 +1151,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
&i2c_bus2->i2c_adap,
|
||||
&magicpro_prohdtve2_xc5000_config);
|
||||
}
|
||||
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
|
||||
break;
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
|
@ -1249,6 +1282,10 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
fe0->dvb.frontend = dvb_attach(ds3000_attach,
|
||||
&tevii_ds3000_config,
|
||||
&i2c_bus->i2c_adap);
|
||||
if (fe0->dvb.frontend != NULL) {
|
||||
dvb_attach(ts2020_attach, fe0->dvb.frontend,
|
||||
&tevii_ts2020_config, &i2c_bus->i2c_adap);
|
||||
}
|
||||
break;
|
||||
case CX23885_BOARD_PROF_8000:
|
||||
i2c_bus = &dev->i2c_bus[0];
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <asm/div64.h>
|
||||
|
||||
#include "cx23885.h"
|
||||
#include "cx23885-video.h"
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include "cx23885-ioctl.h"
|
||||
|
@ -417,7 +418,7 @@ static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
|
|||
mutex_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
|
||||
int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
|
||||
{
|
||||
/* 8 bit registers, 8 bit values */
|
||||
u8 buf[] = { reg, data };
|
||||
|
@ -428,7 +429,7 @@ static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
|
|||
return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
|
||||
}
|
||||
|
||||
static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
|
||||
u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
|
||||
{
|
||||
/* 8 bit registers, 8 bit values */
|
||||
int ret;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Driver for the Conexant CX23885/7/8 PCIe bridge
|
||||
*
|
||||
* Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _CX23885_VIDEO_H_
|
||||
#define _CX23885_VIDEO_H_
|
||||
int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data);
|
||||
u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg);
|
||||
#endif
|
|
@ -320,6 +320,8 @@ struct cx23885_tsport {
|
|||
|
||||
/* Workaround for a temp dvb_frontend that the tuner can attached to */
|
||||
struct dvb_frontend analog_fe;
|
||||
|
||||
int (*set_frontend)(struct dvb_frontend *fe);
|
||||
};
|
||||
|
||||
struct cx23885_kernel_ir {
|
||||
|
|
|
@ -72,9 +72,9 @@ config VIDEO_CX88_DVB
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called cx88-dvb.
|
||||
|
||||
config VIDEO_CX88_VP3054
|
||||
tristate "VP-3054 Secondary I2C Bus Support"
|
||||
default m
|
||||
config VIDEO_CX88_ENABLE_VP3054
|
||||
bool "VP-3054 Secondary I2C Bus Support"
|
||||
default y
|
||||
depends on VIDEO_CX88_DVB && DVB_MT352
|
||||
---help---
|
||||
This adds DVB-T support for cards based on the
|
||||
|
@ -82,6 +82,11 @@ config VIDEO_CX88_VP3054
|
|||
which also require support for the VP-3054
|
||||
Secondary I2C bus, such at DNTV Live! DVB-T Pro.
|
||||
|
||||
config VIDEO_CX88_VP3054
|
||||
tristate
|
||||
depends on VIDEO_CX88_DVB && VIDEO_CX88_ENABLE_VP3054
|
||||
default y
|
||||
|
||||
config VIDEO_CX88_MPEG
|
||||
tristate
|
||||
depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
|
||||
|
|
|
@ -259,7 +259,7 @@ struct cx88_input {
|
|||
};
|
||||
|
||||
enum cx88_audio_chip {
|
||||
CX88_AUDIO_WM8775,
|
||||
CX88_AUDIO_WM8775 = 1,
|
||||
CX88_AUDIO_TVAUDIO,
|
||||
};
|
||||
|
||||
|
|
|
@ -203,13 +203,23 @@ config VIDEO_SAMSUNG_EXYNOS_GSC
|
|||
|
||||
config VIDEO_SH_VEU
|
||||
tristate "SuperH VEU mem2mem video processing driver"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS && HAS_DMA
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select V4L2_MEM2MEM_DEV
|
||||
help
|
||||
Support for the Video Engine Unit (VEU) on SuperH and
|
||||
SH-Mobile SoCs.
|
||||
|
||||
config VIDEO_RENESAS_VSP1
|
||||
tristate "Renesas VSP1 Video Processing Engine"
|
||||
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
---help---
|
||||
This is a V4L2 driver for the Renesas VSP1 video processing engine.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called vsp1.
|
||||
|
||||
endif # V4L_MEM2MEM_DRIVERS
|
||||
|
||||
menuconfig V4L_TEST_DRIVERS
|
||||
|
|
|
@ -46,6 +46,8 @@ obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o
|
|||
|
||||
obj-$(CONFIG_SOC_CAMERA) += soc_camera/
|
||||
|
||||
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
|
||||
|
||||
obj-y += davinci/
|
||||
|
||||
obj-$(CONFIG_ARCH_OMAP) += omap/
|
||||
|
|
|
@ -388,13 +388,8 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
|
||||
params.hdelay = bt->hsync + bt->hbackporch;
|
||||
params.vdelay = bt->vsync + bt->vbackporch;
|
||||
params.line = bt->hfrontporch + bt->hsync
|
||||
+ bt->hbackporch + bt->width;
|
||||
params.frame = bt->vfrontporch + bt->vsync
|
||||
+ bt->vbackporch + bt->height;
|
||||
if (bt->interlaced)
|
||||
params.frame += bt->il_vfrontporch + bt->il_vsync
|
||||
+ bt->il_vbackporch;
|
||||
params.line = V4L2_DV_BT_FRAME_WIDTH(bt);
|
||||
params.frame = V4L2_DV_BT_FRAME_HEIGHT(bt);
|
||||
} else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities
|
||||
& V4L2_IN_CAP_STD) {
|
||||
params.hdelay = 0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,14 +43,26 @@
|
|||
#define CODA_STREAM_ENDIAN_SELECT (1 << 0)
|
||||
#define CODA_REG_BIT_FRAME_MEM_CTRL 0x110
|
||||
#define CODA_IMAGE_ENDIAN_SELECT (1 << 0)
|
||||
#define CODA_REG_BIT_BIT_STREAM_PARAM 0x114
|
||||
#define CODA_BIT_STREAM_END_FLAG (1 << 2)
|
||||
#define CODA_BIT_DEC_SEQ_INIT_ESCAPE (1 << 0)
|
||||
#define CODA_REG_BIT_TEMP_BUF_ADDR 0x118
|
||||
#define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x))
|
||||
#define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x))
|
||||
#define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x))
|
||||
#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140
|
||||
#define CODA7_REG_BIT_AXI_SRAM_USE 0x140
|
||||
#define CODA7_USE_BIT_ENABLE (1 << 0)
|
||||
#define CODA7_USE_HOST_ME_ENABLE (1 << 11)
|
||||
#define CODA7_USE_HOST_OVL_ENABLE (1 << 10)
|
||||
#define CODA7_USE_HOST_DBK_ENABLE (1 << 9)
|
||||
#define CODA7_USE_HOST_IP_ENABLE (1 << 8)
|
||||
#define CODA7_USE_HOST_BIT_ENABLE (1 << 7)
|
||||
#define CODA7_USE_ME_ENABLE (1 << 4)
|
||||
#define CODA7_USE_HOST_ME_ENABLE (1 << 11)
|
||||
#define CODA7_USE_OVL_ENABLE (1 << 3)
|
||||
#define CODA7_USE_DBK_ENABLE (1 << 2)
|
||||
#define CODA7_USE_IP_ENABLE (1 << 1)
|
||||
#define CODA7_USE_BIT_ENABLE (1 << 0)
|
||||
|
||||
#define CODA_REG_BIT_BUSY 0x160
|
||||
#define CODA_REG_BIT_BUSY_FLAG 1
|
||||
#define CODA_REG_BIT_RUN_COMMAND 0x164
|
||||
|
@ -84,6 +96,15 @@
|
|||
#define CODA_MODE_INVALID 0xffff
|
||||
#define CODA_REG_BIT_INT_ENABLE 0x170
|
||||
#define CODA_INT_INTERRUPT_ENABLE (1 << 3)
|
||||
#define CODA_REG_BIT_INT_REASON 0x174
|
||||
#define CODA7_REG_BIT_RUN_AUX_STD 0x178
|
||||
#define CODA_MP4_AUX_MPEG4 0
|
||||
#define CODA_MP4_AUX_DIVX3 1
|
||||
#define CODA_VPX_AUX_THO 0
|
||||
#define CODA_VPX_AUX_VP6 1
|
||||
#define CODA_VPX_AUX_VP8 2
|
||||
#define CODA_H264_AUX_AVC 0
|
||||
#define CODA_H264_AUX_MVC 1
|
||||
|
||||
/*
|
||||
* Commands' mailbox:
|
||||
|
@ -92,15 +113,89 @@
|
|||
* issued.
|
||||
*/
|
||||
|
||||
/* Decoder Sequence Initialization */
|
||||
#define CODA_CMD_DEC_SEQ_BB_START 0x180
|
||||
#define CODA_CMD_DEC_SEQ_BB_SIZE 0x184
|
||||
#define CODA_CMD_DEC_SEQ_OPTION 0x188
|
||||
#define CODA_REORDER_ENABLE (1 << 1)
|
||||
#define CODADX6_QP_REPORT (1 << 0)
|
||||
#define CODA7_MP4_DEBLK_ENABLE (1 << 0)
|
||||
#define CODA_CMD_DEC_SEQ_SRC_SIZE 0x18c
|
||||
#define CODA_CMD_DEC_SEQ_START_BYTE 0x190
|
||||
#define CODA_CMD_DEC_SEQ_PS_BB_START 0x194
|
||||
#define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198
|
||||
#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c
|
||||
#define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c
|
||||
#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0
|
||||
|
||||
#define CODA7_RET_DEC_SEQ_ASPECT 0x1b0
|
||||
#define CODA_RET_DEC_SEQ_SUCCESS 0x1c0
|
||||
#define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */
|
||||
#define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4
|
||||
#define CODA_RET_DEC_SEQ_SRC_F_RATE 0x1c8
|
||||
#define CODA9_RET_DEC_SEQ_ASPECT 0x1c8
|
||||
#define CODA_RET_DEC_SEQ_FRAME_NEED 0x1cc
|
||||
#define CODA_RET_DEC_SEQ_FRAME_DELAY 0x1d0
|
||||
#define CODA_RET_DEC_SEQ_INFO 0x1d4
|
||||
#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT 0x1d8
|
||||
#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM 0x1dc
|
||||
#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM 0x1e0
|
||||
#define CODA_RET_DEC_SEQ_ERR_REASON 0x1e0
|
||||
#define CODA_RET_DEC_SEQ_FRATE_NR 0x1e4
|
||||
#define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8
|
||||
#define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4
|
||||
#define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8
|
||||
|
||||
/* Decoder Picture Run */
|
||||
#define CODA_CMD_DEC_PIC_ROT_MODE 0x180
|
||||
#define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184
|
||||
#define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188
|
||||
#define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c
|
||||
#define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190
|
||||
|
||||
#define CODA_CMD_DEC_PIC_OPTION 0x194
|
||||
#define CODA_PRE_SCAN_EN (1 << 0)
|
||||
#define CODA_PRE_SCAN_MODE_DECODE (0 << 1)
|
||||
#define CODA_PRE_SCAN_MODE_RETURN (1 << 1)
|
||||
#define CODA_IFRAME_SEARCH_EN (1 << 2)
|
||||
#define CODA_SKIP_FRAME_MODE (0x3 << 3)
|
||||
#define CODA_CMD_DEC_PIC_SKIP_NUM 0x198
|
||||
#define CODA_CMD_DEC_PIC_CHUNK_SIZE 0x19c
|
||||
#define CODA_CMD_DEC_PIC_BB_START 0x1a0
|
||||
#define CODA_CMD_DEC_PIC_START_BYTE 0x1a4
|
||||
#define CODA_RET_DEC_PIC_SIZE 0x1bc
|
||||
#define CODA_RET_DEC_PIC_FRAME_NUM 0x1c0
|
||||
#define CODA_RET_DEC_PIC_FRAME_IDX 0x1c4
|
||||
#define CODA_RET_DEC_PIC_ERR_MB 0x1c8
|
||||
#define CODA_RET_DEC_PIC_TYPE 0x1cc
|
||||
#define CODA_PIC_TYPE_MASK 0x7
|
||||
#define CODA_PIC_TYPE_MASK_VC1 0x3f
|
||||
#define CODA9_PIC_TYPE_FIRST_MASK (0x7 << 3)
|
||||
#define CODA9_PIC_TYPE_IDR_MASK (0x3 << 6)
|
||||
#define CODA7_PIC_TYPE_H264_NPF_MASK (0x3 << 16)
|
||||
#define CODA7_PIC_TYPE_INTERLACED (1 << 18)
|
||||
#define CODA_RET_DEC_PIC_POST 0x1d0
|
||||
#define CODA_RET_DEC_PIC_MVC_REPORT 0x1d0
|
||||
#define CODA_RET_DEC_PIC_OPTION 0x1d4
|
||||
#define CODA_RET_DEC_PIC_SUCCESS 0x1d8
|
||||
#define CODA_RET_DEC_PIC_CUR_IDX 0x1dc
|
||||
#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT 0x1e0
|
||||
#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4
|
||||
#define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec
|
||||
|
||||
/* Encoder Sequence Initialization */
|
||||
#define CODA_CMD_ENC_SEQ_BB_START 0x180
|
||||
#define CODA_CMD_ENC_SEQ_BB_SIZE 0x184
|
||||
#define CODA_CMD_ENC_SEQ_OPTION 0x188
|
||||
#define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9
|
||||
#define CODA7_OPTION_GAMMA_OFFSET 8
|
||||
#define CODA7_OPTION_RCQPMAX_OFFSET 7
|
||||
#define CODADX6_OPTION_GAMMA_OFFSET 7
|
||||
#define CODA7_OPTION_RCQPMIN_OFFSET 6
|
||||
#define CODA_OPTION_LIMITQP_OFFSET 6
|
||||
#define CODA_OPTION_RCINTRAQP_OFFSET 5
|
||||
#define CODA_OPTION_FMO_OFFSET 4
|
||||
#define CODA_OPTION_AVC_AUD_OFFSET 2
|
||||
#define CODA_OPTION_SLICEREPORT_OFFSET 1
|
||||
#define CODA_CMD_ENC_SEQ_COD_STD 0x18c
|
||||
#define CODA_STD_MPEG4 0
|
||||
|
@ -169,8 +264,10 @@
|
|||
#define CODA_FMOPARAM_TYPE_MASK 1
|
||||
#define CODA_FMOPARAM_SLICENUM_OFFSET 0
|
||||
#define CODA_FMOPARAM_SLICENUM_MASK 0x0f
|
||||
#define CODADX6_CMD_ENC_SEQ_INTRA_QP 0x1bc
|
||||
#define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8
|
||||
#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc
|
||||
#define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4
|
||||
#define CODA_CMD_ENC_SEQ_RC_QP_MAX 0x1c8
|
||||
#define CODA_QPMAX_OFFSET 0
|
||||
#define CODA_QPMAX_MASK 0x3f
|
||||
|
@ -197,18 +294,24 @@
|
|||
#define CODA_CMD_ENC_PIC_OPTION 0x194
|
||||
#define CODA_CMD_ENC_PIC_BB_START 0x198
|
||||
#define CODA_CMD_ENC_PIC_BB_SIZE 0x19c
|
||||
#define CODA_RET_ENC_FRAME_NUM 0x1c0
|
||||
#define CODA_RET_ENC_PIC_TYPE 0x1c4
|
||||
#define CODA_RET_ENC_PIC_FRAME_IDX 0x1c8
|
||||
#define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc
|
||||
#define CODA_RET_ENC_PIC_FLAG 0x1d0
|
||||
#define CODA_RET_ENC_PIC_SUCCESS 0x1d8
|
||||
|
||||
/* Set Frame Buffer */
|
||||
#define CODA_CMD_SET_FRAME_BUF_NUM 0x180
|
||||
#define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184
|
||||
#define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188
|
||||
#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c
|
||||
#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190
|
||||
#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194
|
||||
#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198
|
||||
#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c
|
||||
#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0
|
||||
#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4
|
||||
#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8
|
||||
|
||||
/* Encoder Header */
|
||||
|
|
|
@ -1743,11 +1743,10 @@ static int vpbe_display_probe(struct platform_device *pdev)
|
|||
|
||||
printk(KERN_DEBUG "vpbe_display_probe\n");
|
||||
/* Allocate memory for vpbe_display */
|
||||
disp_dev = kzalloc(sizeof(struct vpbe_display), GFP_KERNEL);
|
||||
if (!disp_dev) {
|
||||
printk(KERN_ERR "ran out of memory\n");
|
||||
disp_dev = devm_kzalloc(&pdev->dev, sizeof(struct vpbe_display),
|
||||
GFP_KERNEL);
|
||||
if (!disp_dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_init(&disp_dev->dma_queue_lock);
|
||||
/*
|
||||
|
@ -1786,26 +1785,24 @@ static int vpbe_display_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
irq = res->start;
|
||||
if (request_irq(irq, venc_isr, IRQF_DISABLED, VPBE_DISPLAY_DRIVER,
|
||||
disp_dev)) {
|
||||
err = devm_request_irq(&pdev->dev, irq, venc_isr, IRQF_DISABLED,
|
||||
VPBE_DISPLAY_DRIVER, disp_dev);
|
||||
if (err) {
|
||||
v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
|
||||
"Unable to request interrupt\n");
|
||||
err = -ENODEV;
|
||||
goto probe_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
|
||||
if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
|
||||
err = -ENODEV;
|
||||
goto probe_out_irq;
|
||||
goto probe_out;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
|
||||
return 0;
|
||||
|
||||
probe_out_irq:
|
||||
free_irq(res->start, disp_dev);
|
||||
probe_out:
|
||||
for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
|
||||
/* Get the pointer to the layer object */
|
||||
|
@ -1817,7 +1814,6 @@ probe_out:
|
|||
kfree(disp_dev->dev[k]);
|
||||
}
|
||||
}
|
||||
kfree(disp_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1830,15 +1826,10 @@ static int vpbe_display_remove(struct platform_device *pdev)
|
|||
struct vpbe_layer *vpbe_display_layer;
|
||||
struct vpbe_display *disp_dev = platform_get_drvdata(pdev);
|
||||
struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
|
||||
struct resource *res;
|
||||
int i;
|
||||
|
||||
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n");
|
||||
|
||||
/* unregister irq */
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
free_irq(res->start, disp_dev);
|
||||
|
||||
/* deinitialize the vpbe display controller */
|
||||
if (NULL != vpbe_dev->ops.deinitialize)
|
||||
vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev);
|
||||
|
|
|
@ -1547,61 +1547,36 @@ static int osd_probe(struct platform_device *pdev)
|
|||
const struct platform_device_id *pdev_id;
|
||||
struct osd_state *osd;
|
||||
struct resource *res;
|
||||
int ret = 0;
|
||||
|
||||
osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL);
|
||||
pdev_id = platform_get_device_id(pdev);
|
||||
if (!pdev_id)
|
||||
return -EINVAL;
|
||||
|
||||
osd = devm_kzalloc(&pdev->dev, sizeof(struct osd_state), GFP_KERNEL);
|
||||
if (osd == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev_id = platform_get_device_id(pdev);
|
||||
if (!pdev_id) {
|
||||
ret = -EINVAL;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
osd->dev = &pdev->dev;
|
||||
osd->vpbe_type = pdev_id->driver_data;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(osd->dev, "Unable to get OSD register address map\n");
|
||||
ret = -ENODEV;
|
||||
goto free_mem;
|
||||
}
|
||||
osd->osd_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(osd->osd_base))
|
||||
return PTR_ERR(osd->osd_base);
|
||||
|
||||
osd->osd_base_phys = res->start;
|
||||
osd->osd_size = resource_size(res);
|
||||
if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
|
||||
MODULE_NAME)) {
|
||||
dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
|
||||
ret = -ENODEV;
|
||||
goto free_mem;
|
||||
}
|
||||
osd->osd_base = ioremap_nocache(res->start, osd->osd_size);
|
||||
if (!osd->osd_base) {
|
||||
dev_err(osd->dev, "Unable to map the OSD region\n");
|
||||
ret = -ENODEV;
|
||||
goto release_mem_region;
|
||||
}
|
||||
spin_lock_init(&osd->lock);
|
||||
osd->ops = osd_ops;
|
||||
platform_set_drvdata(pdev, osd);
|
||||
dev_notice(osd->dev, "OSD sub device probe success\n");
|
||||
return ret;
|
||||
|
||||
release_mem_region:
|
||||
release_mem_region(osd->osd_base_phys, osd->osd_size);
|
||||
free_mem:
|
||||
kfree(osd);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osd_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct osd_state *osd = platform_get_drvdata(pdev);
|
||||
|
||||
iounmap((void *)osd->osd_base);
|
||||
release_mem_region(osd->osd_base_phys, osd->osd_size);
|
||||
kfree(osd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -639,105 +639,46 @@ static int venc_probe(struct platform_device *pdev)
|
|||
const struct platform_device_id *pdev_id;
|
||||
struct venc_state *venc;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL);
|
||||
if (!pdev->dev.platform_data) {
|
||||
dev_err(&pdev->dev, "No platform data for VENC sub device");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev_id = platform_get_device_id(pdev);
|
||||
if (!pdev_id)
|
||||
return -EINVAL;
|
||||
|
||||
venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL);
|
||||
if (venc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev_id = platform_get_device_id(pdev);
|
||||
if (!pdev_id) {
|
||||
ret = -EINVAL;
|
||||
goto free_mem;
|
||||
}
|
||||
venc->venc_type = pdev_id->driver_data;
|
||||
venc->pdev = &pdev->dev;
|
||||
venc->pdata = pdev->dev.platform_data;
|
||||
if (NULL == venc->pdata) {
|
||||
dev_err(venc->pdev, "Unable to get platform data for"
|
||||
" VENC sub device");
|
||||
ret = -ENOENT;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(venc->pdev,
|
||||
"Unable to get VENC register address map\n");
|
||||
ret = -ENODEV;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res), "venc")) {
|
||||
dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n");
|
||||
ret = -ENODEV;
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
venc->venc_base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!venc->venc_base) {
|
||||
dev_err(venc->pdev, "Unable to map VENC IO space\n");
|
||||
ret = -ENODEV;
|
||||
goto release_venc_mem_region;
|
||||
}
|
||||
venc->venc_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(venc->venc_base))
|
||||
return PTR_ERR(venc->venc_base);
|
||||
|
||||
if (venc->venc_type != VPBE_VERSION_1) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (!res) {
|
||||
dev_err(venc->pdev,
|
||||
"Unable to get VDAC_CONFIG address map\n");
|
||||
ret = -ENODEV;
|
||||
goto unmap_venc_io;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start,
|
||||
resource_size(res), "venc")) {
|
||||
dev_err(venc->pdev,
|
||||
"Unable to reserve VDAC_CONFIG MMIO region\n");
|
||||
ret = -ENODEV;
|
||||
goto unmap_venc_io;
|
||||
}
|
||||
|
||||
venc->vdaccfg_reg = ioremap_nocache(res->start,
|
||||
resource_size(res));
|
||||
if (!venc->vdaccfg_reg) {
|
||||
dev_err(venc->pdev,
|
||||
"Unable to map VDAC_CONFIG IO space\n");
|
||||
ret = -ENODEV;
|
||||
goto release_vdaccfg_mem_region;
|
||||
}
|
||||
venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(venc->vdaccfg_reg))
|
||||
return PTR_ERR(venc->vdaccfg_reg);
|
||||
}
|
||||
spin_lock_init(&venc->lock);
|
||||
platform_set_drvdata(pdev, venc);
|
||||
dev_notice(venc->pdev, "VENC sub device probe success\n");
|
||||
return 0;
|
||||
|
||||
release_vdaccfg_mem_region:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
unmap_venc_io:
|
||||
iounmap(venc->venc_base);
|
||||
release_venc_mem_region:
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
free_mem:
|
||||
kfree(venc);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int venc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct venc_state *venc = platform_get_drvdata(pdev);
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
iounmap((void *)venc->venc_base);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
if (venc->venc_type != VPBE_VERSION_1) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
iounmap((void *)venc->vdaccfg_reg);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
}
|
||||
kfree(venc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1799,19 +1799,15 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
|
|||
|
||||
/* Configure video port timings */
|
||||
|
||||
std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
|
||||
bt->hsync - 8;
|
||||
std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8;
|
||||
std_info->sav2eav = bt->width;
|
||||
|
||||
std_info->l1 = 1;
|
||||
std_info->l3 = bt->vsync + bt->vbackporch + 1;
|
||||
|
||||
std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt);
|
||||
if (bt->interlaced) {
|
||||
if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
|
||||
std_info->vsize = bt->height * 2 +
|
||||
bt->vfrontporch + bt->vsync + bt->vbackporch +
|
||||
bt->il_vfrontporch + bt->il_vsync +
|
||||
bt->il_vbackporch;
|
||||
std_info->l5 = std_info->vsize/2 -
|
||||
(bt->vfrontporch - 1);
|
||||
std_info->l7 = std_info->vsize/2 + 1;
|
||||
|
@ -1825,8 +1821,6 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
std_info->vsize = bt->height + bt->vfrontporch +
|
||||
bt->vsync + bt->vbackporch;
|
||||
std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
|
||||
}
|
||||
strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME);
|
||||
|
@ -1979,6 +1973,76 @@ vpif_init_free_channel_objects:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int vpif_async_bound(struct v4l2_async_notifier *notifier,
|
||||
struct v4l2_subdev *subdev,
|
||||
struct v4l2_async_subdev *asd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vpif_obj.config->subdev_count; i++)
|
||||
if (!strcmp(vpif_obj.config->subdev_info[i].name,
|
||||
subdev->name)) {
|
||||
vpif_obj.sd[i] = subdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vpif_probe_complete(void)
|
||||
{
|
||||
struct common_obj *common;
|
||||
struct channel_obj *ch;
|
||||
int i, j, err, k;
|
||||
|
||||
for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
ch->channel_id = j;
|
||||
common = &(ch->common[VPIF_VIDEO_INDEX]);
|
||||
spin_lock_init(&common->irqlock);
|
||||
mutex_init(&common->lock);
|
||||
ch->video_dev->lock = &common->lock;
|
||||
/* Initialize prio member of channel object */
|
||||
v4l2_prio_init(&ch->prio);
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
/* select input 0 */
|
||||
err = vpif_set_input(vpif_obj.config, ch, 0);
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
err = video_register_device(ch->video_dev,
|
||||
VFL_TYPE_GRABBER, (j ? 1 : 0));
|
||||
if (err)
|
||||
goto probe_out;
|
||||
}
|
||||
|
||||
v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
|
||||
return 0;
|
||||
|
||||
probe_out:
|
||||
for (k = 0; k < j; k++) {
|
||||
/* Get the pointer to the channel object */
|
||||
ch = vpif_obj.dev[k];
|
||||
/* Unregister video device */
|
||||
video_unregister_device(ch->video_dev);
|
||||
}
|
||||
kfree(vpif_obj.sd);
|
||||
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
|
||||
ch = vpif_obj.dev[i];
|
||||
/* Note: does nothing if ch->video_dev == NULL */
|
||||
video_device_release(ch->video_dev);
|
||||
}
|
||||
v4l2_device_unregister(&vpif_obj.v4l2_dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vpif_async_complete(struct v4l2_async_notifier *notifier)
|
||||
{
|
||||
return vpif_probe_complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* vpif_probe : This function probes the vpif capture driver
|
||||
* @pdev: platform device pointer
|
||||
|
@ -1989,12 +2053,10 @@ vpif_init_free_channel_objects:
|
|||
static __init int vpif_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vpif_subdev_info *subdevdata;
|
||||
struct vpif_capture_config *config;
|
||||
int i, j, k, err;
|
||||
int i, j, err;
|
||||
int res_idx = 0;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
struct channel_obj *ch;
|
||||
struct common_obj *common;
|
||||
struct video_device *vfd;
|
||||
struct resource *res;
|
||||
int subdev_count;
|
||||
|
@ -2068,10 +2130,9 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
config = pdev->dev.platform_data;
|
||||
vpif_obj.config = pdev->dev.platform_data;
|
||||
|
||||
subdev_count = config->subdev_count;
|
||||
subdev_count = vpif_obj.config->subdev_count;
|
||||
vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
|
||||
GFP_KERNEL);
|
||||
if (vpif_obj.sd == NULL) {
|
||||
|
@ -2080,54 +2141,43 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
goto vpif_sd_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
subdevdata = &config->subdev_info[i];
|
||||
vpif_obj.sd[i] =
|
||||
v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
|
||||
i2c_adap,
|
||||
&subdevdata->board_info,
|
||||
NULL);
|
||||
if (!vpif_obj.config->asd_sizes) {
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
subdevdata = &vpif_obj.config->subdev_info[i];
|
||||
vpif_obj.sd[i] =
|
||||
v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
|
||||
i2c_adap,
|
||||
&subdevdata->
|
||||
board_info,
|
||||
NULL);
|
||||
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
err = -ENODEV;
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
err = -ENOMEM;
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
v4l2_info(&vpif_obj.v4l2_dev,
|
||||
"registered sub device %s\n",
|
||||
subdevdata->name);
|
||||
}
|
||||
vpif_probe_complete();
|
||||
} else {
|
||||
vpif_obj.notifier.subdevs = vpif_obj.config->asd;
|
||||
vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
|
||||
vpif_obj.notifier.bound = vpif_async_bound;
|
||||
vpif_obj.notifier.complete = vpif_async_complete;
|
||||
err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
|
||||
&vpif_obj.notifier);
|
||||
if (err) {
|
||||
vpif_err("Error registering async notifier\n");
|
||||
err = -EINVAL;
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
|
||||
subdevdata->name);
|
||||
}
|
||||
|
||||
for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
ch->channel_id = j;
|
||||
common = &(ch->common[VPIF_VIDEO_INDEX]);
|
||||
spin_lock_init(&common->irqlock);
|
||||
mutex_init(&common->lock);
|
||||
ch->video_dev->lock = &common->lock;
|
||||
/* Initialize prio member of channel object */
|
||||
v4l2_prio_init(&ch->prio);
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
/* select input 0 */
|
||||
err = vpif_set_input(config, ch, 0);
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
err = video_register_device(ch->video_dev,
|
||||
VFL_TYPE_GRABBER, (j ? 1 : 0));
|
||||
if (err)
|
||||
goto probe_out;
|
||||
}
|
||||
v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
|
||||
return 0;
|
||||
|
||||
probe_out:
|
||||
for (k = 0; k < j; k++) {
|
||||
/* Get the pointer to the channel object */
|
||||
ch = vpif_obj.dev[k];
|
||||
/* Unregister video device */
|
||||
video_unregister_device(ch->video_dev);
|
||||
}
|
||||
probe_subdev_out:
|
||||
/* free sub devices memory */
|
||||
kfree(vpif_obj.sd);
|
||||
|
|
|
@ -142,6 +142,8 @@ struct vpif_device {
|
|||
struct v4l2_device v4l2_dev;
|
||||
struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS];
|
||||
struct v4l2_subdev **sd;
|
||||
struct v4l2_async_notifier notifier;
|
||||
struct vpif_capture_config *config;
|
||||
};
|
||||
|
||||
struct vpif_config_params {
|
||||
|
|
|
@ -1436,19 +1436,15 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
|
|||
|
||||
/* Configure video port timings */
|
||||
|
||||
std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
|
||||
bt->hsync - 8;
|
||||
std_info->eav2sav = V4L2_DV_BT_BLANKING_WIDTH(bt) - 8;
|
||||
std_info->sav2eav = bt->width;
|
||||
|
||||
std_info->l1 = 1;
|
||||
std_info->l3 = bt->vsync + bt->vbackporch + 1;
|
||||
|
||||
std_info->vsize = V4L2_DV_BT_FRAME_HEIGHT(bt);
|
||||
if (bt->interlaced) {
|
||||
if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
|
||||
std_info->vsize = bt->height * 2 +
|
||||
bt->vfrontporch + bt->vsync + bt->vbackporch +
|
||||
bt->il_vfrontporch + bt->il_vsync +
|
||||
bt->il_vbackporch;
|
||||
std_info->l5 = std_info->vsize/2 -
|
||||
(bt->vfrontporch - 1);
|
||||
std_info->l7 = std_info->vsize/2 + 1;
|
||||
|
@ -1462,8 +1458,6 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
std_info->vsize = bt->height + bt->vfrontporch +
|
||||
bt->vsync + bt->vbackporch;
|
||||
std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
|
||||
}
|
||||
strncpy(std_info->name, "Custom timings BT656/1120",
|
||||
|
@ -1618,6 +1612,102 @@ vpif_init_free_channel_objects:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int vpif_async_bound(struct v4l2_async_notifier *notifier,
|
||||
struct v4l2_subdev *subdev,
|
||||
struct v4l2_async_subdev *asd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vpif_obj.config->subdev_count; i++)
|
||||
if (!strcmp(vpif_obj.config->subdevinfo[i].name,
|
||||
subdev->name)) {
|
||||
vpif_obj.sd[i] = subdev;
|
||||
vpif_obj.sd[i]->grp_id = 1 << i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vpif_probe_complete(void)
|
||||
{
|
||||
struct common_obj *common;
|
||||
struct channel_obj *ch;
|
||||
int j, err, k;
|
||||
|
||||
for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
/* Initialize field of the channel objects */
|
||||
atomic_set(&ch->usrs, 0);
|
||||
for (k = 0; k < VPIF_NUMOBJECTS; k++) {
|
||||
ch->common[k].numbuffers = 0;
|
||||
common = &ch->common[k];
|
||||
common->io_usrs = 0;
|
||||
common->started = 0;
|
||||
spin_lock_init(&common->irqlock);
|
||||
mutex_init(&common->lock);
|
||||
common->numbuffers = 0;
|
||||
common->set_addr = NULL;
|
||||
common->ytop_off = 0;
|
||||
common->ybtm_off = 0;
|
||||
common->ctop_off = 0;
|
||||
common->cbtm_off = 0;
|
||||
common->cur_frm = NULL;
|
||||
common->next_frm = NULL;
|
||||
memset(&common->fmt, 0, sizeof(common->fmt));
|
||||
common->numbuffers = config_params.numbuffers[k];
|
||||
}
|
||||
ch->initialized = 0;
|
||||
if (vpif_obj.config->subdev_count)
|
||||
ch->sd = vpif_obj.sd[0];
|
||||
ch->channel_id = j;
|
||||
if (j < 2)
|
||||
ch->common[VPIF_VIDEO_INDEX].numbuffers =
|
||||
config_params.numbuffers[ch->channel_id];
|
||||
else
|
||||
ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
|
||||
|
||||
memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
|
||||
|
||||
/* Initialize prio member of channel object */
|
||||
v4l2_prio_init(&ch->prio);
|
||||
ch->common[VPIF_VIDEO_INDEX].fmt.type =
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
||||
ch->video_dev->lock = &common->lock;
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
/* select output 0 */
|
||||
err = vpif_set_output(vpif_obj.config, ch, 0);
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
/* register video device */
|
||||
vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
|
||||
(int)ch, (int)&ch->video_dev);
|
||||
|
||||
err = video_register_device(ch->video_dev,
|
||||
VFL_TYPE_GRABBER, (j ? 3 : 2));
|
||||
if (err < 0)
|
||||
goto probe_out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
probe_out:
|
||||
for (k = 0; k < j; k++) {
|
||||
ch = vpif_obj.dev[k];
|
||||
video_unregister_device(ch->video_dev);
|
||||
video_device_release(ch->video_dev);
|
||||
ch->video_dev = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vpif_async_complete(struct v4l2_async_notifier *notifier)
|
||||
{
|
||||
return vpif_probe_complete();
|
||||
}
|
||||
|
||||
/*
|
||||
* vpif_probe: This function creates device entries by register itself to the
|
||||
* V4L2 driver and initializes fields of each channel objects
|
||||
|
@ -1625,11 +1715,9 @@ vpif_init_free_channel_objects:
|
|||
static __init int vpif_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vpif_subdev_info *subdevdata;
|
||||
struct vpif_display_config *config;
|
||||
int i, j = 0, k, err = 0;
|
||||
int i, j = 0, err = 0;
|
||||
int res_idx = 0;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
struct common_obj *common;
|
||||
struct channel_obj *ch;
|
||||
struct video_device *vfd;
|
||||
struct resource *res;
|
||||
|
@ -1708,11 +1796,9 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
size/2;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
config = pdev->dev.platform_data;
|
||||
subdev_count = config->subdev_count;
|
||||
subdevdata = config->subdevinfo;
|
||||
vpif_obj.config = pdev->dev.platform_data;
|
||||
subdev_count = vpif_obj.config->subdev_count;
|
||||
subdevdata = vpif_obj.config->subdevinfo;
|
||||
vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
|
||||
GFP_KERNEL);
|
||||
if (vpif_obj.sd == NULL) {
|
||||
|
@ -1721,86 +1807,41 @@ static __init int vpif_probe(struct platform_device *pdev)
|
|||
goto vpif_sd_error;
|
||||
}
|
||||
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
|
||||
i2c_adap,
|
||||
&subdevdata[i].board_info,
|
||||
NULL);
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
err = -ENODEV;
|
||||
if (!vpif_obj.config->asd_sizes) {
|
||||
i2c_adap = i2c_get_adapter(1);
|
||||
for (i = 0; i < subdev_count; i++) {
|
||||
vpif_obj.sd[i] =
|
||||
v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
|
||||
i2c_adap,
|
||||
&subdevdata[i].
|
||||
board_info,
|
||||
NULL);
|
||||
if (!vpif_obj.sd[i]) {
|
||||
vpif_err("Error registering v4l2 subdevice\n");
|
||||
err = -ENODEV;
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
|
||||
if (vpif_obj.sd[i])
|
||||
vpif_obj.sd[i]->grp_id = 1 << i;
|
||||
}
|
||||
vpif_probe_complete();
|
||||
} else {
|
||||
vpif_obj.notifier.subdevs = vpif_obj.config->asd;
|
||||
vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0];
|
||||
vpif_obj.notifier.bound = vpif_async_bound;
|
||||
vpif_obj.notifier.complete = vpif_async_complete;
|
||||
err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev,
|
||||
&vpif_obj.notifier);
|
||||
if (err) {
|
||||
vpif_err("Error registering async notifier\n");
|
||||
err = -EINVAL;
|
||||
goto probe_subdev_out;
|
||||
}
|
||||
|
||||
if (vpif_obj.sd[i])
|
||||
vpif_obj.sd[i]->grp_id = 1 << i;
|
||||
}
|
||||
|
||||
for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
|
||||
ch = vpif_obj.dev[j];
|
||||
/* Initialize field of the channel objects */
|
||||
atomic_set(&ch->usrs, 0);
|
||||
for (k = 0; k < VPIF_NUMOBJECTS; k++) {
|
||||
ch->common[k].numbuffers = 0;
|
||||
common = &ch->common[k];
|
||||
common->io_usrs = 0;
|
||||
common->started = 0;
|
||||
spin_lock_init(&common->irqlock);
|
||||
mutex_init(&common->lock);
|
||||
common->numbuffers = 0;
|
||||
common->set_addr = NULL;
|
||||
common->ytop_off = common->ybtm_off = 0;
|
||||
common->ctop_off = common->cbtm_off = 0;
|
||||
common->cur_frm = common->next_frm = NULL;
|
||||
memset(&common->fmt, 0, sizeof(common->fmt));
|
||||
common->numbuffers = config_params.numbuffers[k];
|
||||
|
||||
}
|
||||
ch->initialized = 0;
|
||||
if (subdev_count)
|
||||
ch->sd = vpif_obj.sd[0];
|
||||
ch->channel_id = j;
|
||||
if (j < 2)
|
||||
ch->common[VPIF_VIDEO_INDEX].numbuffers =
|
||||
config_params.numbuffers[ch->channel_id];
|
||||
else
|
||||
ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
|
||||
|
||||
memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
|
||||
|
||||
/* Initialize prio member of channel object */
|
||||
v4l2_prio_init(&ch->prio);
|
||||
ch->common[VPIF_VIDEO_INDEX].fmt.type =
|
||||
V4L2_BUF_TYPE_VIDEO_OUTPUT;
|
||||
ch->video_dev->lock = &common->lock;
|
||||
video_set_drvdata(ch->video_dev, ch);
|
||||
|
||||
/* select output 0 */
|
||||
err = vpif_set_output(config, ch, 0);
|
||||
if (err)
|
||||
goto probe_out;
|
||||
|
||||
/* register video device */
|
||||
vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
|
||||
(int)ch, (int)&ch->video_dev);
|
||||
|
||||
err = video_register_device(ch->video_dev,
|
||||
VFL_TYPE_GRABBER, (j ? 3 : 2));
|
||||
if (err < 0)
|
||||
goto probe_out;
|
||||
}
|
||||
|
||||
v4l2_info(&vpif_obj.v4l2_dev,
|
||||
" VPIF display driver initialized\n");
|
||||
return 0;
|
||||
|
||||
probe_out:
|
||||
for (k = 0; k < j; k++) {
|
||||
ch = vpif_obj.dev[k];
|
||||
video_unregister_device(ch->video_dev);
|
||||
video_device_release(ch->video_dev);
|
||||
ch->video_dev = NULL;
|
||||
}
|
||||
probe_subdev_out:
|
||||
kfree(vpif_obj.sd);
|
||||
vpif_sd_error:
|
||||
|
|
|
@ -148,7 +148,8 @@ struct vpif_device {
|
|||
struct v4l2_device v4l2_dev;
|
||||
struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
|
||||
struct v4l2_subdev **sd;
|
||||
|
||||
struct v4l2_async_notifier notifier;
|
||||
struct vpif_display_config *config;
|
||||
};
|
||||
|
||||
struct vpif_config_params {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <media/davinci/vpss.h>
|
||||
|
||||
|
@ -404,9 +405,8 @@ EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size);
|
|||
|
||||
static int vpss_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *r1, *r2;
|
||||
struct resource *res;
|
||||
char *platform_name;
|
||||
int status;
|
||||
|
||||
if (!pdev->dev.platform_data) {
|
||||
dev_err(&pdev->dev, "no platform data\n");
|
||||
|
@ -427,38 +427,19 @@ static int vpss_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
dev_info(&pdev->dev, "%s vpss probed\n", platform_name);
|
||||
r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!r1)
|
||||
return -ENOENT;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
r1 = request_mem_region(r1->start, resource_size(r1), r1->name);
|
||||
if (!r1)
|
||||
return -EBUSY;
|
||||
|
||||
oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1));
|
||||
if (!oper_cfg.vpss_regs_base0) {
|
||||
status = -EBUSY;
|
||||
goto fail1;
|
||||
}
|
||||
oper_cfg.vpss_regs_base0 = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(oper_cfg.vpss_regs_base0))
|
||||
return PTR_ERR(oper_cfg.vpss_regs_base0);
|
||||
|
||||
if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
|
||||
r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (!r2) {
|
||||
status = -ENOENT;
|
||||
goto fail2;
|
||||
}
|
||||
r2 = request_mem_region(r2->start, resource_size(r2), r2->name);
|
||||
if (!r2) {
|
||||
status = -EBUSY;
|
||||
goto fail2;
|
||||
}
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
|
||||
oper_cfg.vpss_regs_base1 = ioremap(r2->start,
|
||||
resource_size(r2));
|
||||
if (!oper_cfg.vpss_regs_base1) {
|
||||
status = -EBUSY;
|
||||
goto fail3;
|
||||
}
|
||||
oper_cfg.vpss_regs_base1 = devm_ioremap_resource(&pdev->dev,
|
||||
res);
|
||||
if (IS_ERR(oper_cfg.vpss_regs_base1))
|
||||
return PTR_ERR(oper_cfg.vpss_regs_base1);
|
||||
}
|
||||
|
||||
if (oper_cfg.platform == DM355) {
|
||||
|
@ -493,30 +474,13 @@ static int vpss_probe(struct platform_device *pdev)
|
|||
|
||||
spin_lock_init(&oper_cfg.vpss_lock);
|
||||
dev_info(&pdev->dev, "%s vpss probe success\n", platform_name);
|
||||
return 0;
|
||||
|
||||
fail3:
|
||||
release_mem_region(r2->start, resource_size(r2));
|
||||
fail2:
|
||||
iounmap(oper_cfg.vpss_regs_base0);
|
||||
fail1:
|
||||
release_mem_region(r1->start, resource_size(r1));
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vpss_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
iounmap(oper_cfg.vpss_regs_base0);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
|
||||
iounmap(oper_cfg.vpss_regs_base1);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1122,10 +1122,14 @@ static int gsc_probe(struct platform_device *pdev)
|
|||
goto err_clk;
|
||||
}
|
||||
|
||||
ret = gsc_register_m2m_device(gsc);
|
||||
ret = v4l2_device_register(dev, &gsc->v4l2_dev);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
ret = gsc_register_m2m_device(gsc);
|
||||
if (ret)
|
||||
goto err_v4l2;
|
||||
|
||||
platform_set_drvdata(pdev, gsc);
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
|
@ -1147,6 +1151,8 @@ err_pm:
|
|||
pm_runtime_put(dev);
|
||||
err_m2m:
|
||||
gsc_unregister_m2m_device(gsc);
|
||||
err_v4l2:
|
||||
v4l2_device_unregister(&gsc->v4l2_dev);
|
||||
err_clk:
|
||||
gsc_clk_put(gsc);
|
||||
return ret;
|
||||
|
@ -1157,6 +1163,7 @@ static int gsc_remove(struct platform_device *pdev)
|
|||
struct gsc_dev *gsc = platform_get_drvdata(pdev);
|
||||
|
||||
gsc_unregister_m2m_device(gsc);
|
||||
v4l2_device_unregister(&gsc->v4l2_dev);
|
||||
|
||||
vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
@ -1210,12 +1217,12 @@ static int gsc_resume(struct device *dev)
|
|||
spin_unlock_irqrestore(&gsc->slock, flags);
|
||||
return 0;
|
||||
}
|
||||
gsc_hw_set_sw_reset(gsc);
|
||||
gsc_wait_reset(gsc);
|
||||
|
||||
spin_unlock_irqrestore(&gsc->slock, flags);
|
||||
|
||||
return gsc_m2m_resume(gsc);
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return gsc_runtime_resume(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsc_suspend(struct device *dev)
|
||||
|
@ -1227,7 +1234,10 @@ static int gsc_suspend(struct device *dev)
|
|||
if (test_and_set_bit(ST_SUSPEND, &gsc->state))
|
||||
return 0;
|
||||
|
||||
return gsc_m2m_suspend(gsc);
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return gsc_runtime_suspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops gsc_pm_ops = {
|
||||
|
|
|
@ -343,6 +343,7 @@ struct gsc_dev {
|
|||
unsigned long state;
|
||||
struct vb2_alloc_ctx *alloc_ctx;
|
||||
struct video_device vdev;
|
||||
struct v4l2_device v4l2_dev;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -751,6 +751,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc)
|
|||
gsc->vdev.release = video_device_release_empty;
|
||||
gsc->vdev.lock = &gsc->lock;
|
||||
gsc->vdev.vfl_dir = VFL_DIR_M2M;
|
||||
gsc->vdev.v4l2_dev = &gsc->v4l2_dev;
|
||||
snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m",
|
||||
GSC_MODULE_NAME, gsc->id);
|
||||
|
||||
|
|
|
@ -1110,6 +1110,8 @@ static int fimc_remove(struct platform_device *pdev)
|
|||
struct fimc_dev *fimc = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
if (!pm_runtime_status_suspended(&pdev->dev))
|
||||
clk_disable(fimc->clock[CLK_GATE]);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
|
||||
fimc_unregister_capture_subdev(fimc);
|
||||
|
|
|
@ -81,21 +81,46 @@ static int fimc_is_i2c_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fimc_is_i2c_suspend(struct device *dev)
|
||||
#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
|
||||
static int fimc_is_i2c_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(isp_i2c->clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fimc_is_i2c_resume(struct device *dev)
|
||||
static int fimc_is_i2c_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(isp_i2c->clock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend,
|
||||
fimc_is_i2c_resume, NULL);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int fimc_is_i2c_suspend(struct device *dev)
|
||||
{
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
return fimc_is_i2c_runtime_suspend(dev);
|
||||
}
|
||||
|
||||
static int fimc_is_i2c_resume(struct device *dev)
|
||||
{
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
return fimc_is_i2c_runtime_resume(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct dev_pm_ops fimc_is_i2c_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(fimc_is_i2c_runtime_suspend,
|
||||
fimc_is_i2c_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(fimc_is_i2c_suspend, fimc_is_i2c_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id fimc_is_i2c_of_match[] = {
|
||||
{ .compatible = FIMC_IS_I2C_COMPATIBLE },
|
||||
|
|
|
@ -56,7 +56,7 @@ static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is)
|
|||
__hw_param_copy(dst, src);
|
||||
}
|
||||
|
||||
int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset)
|
||||
static int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset)
|
||||
{
|
||||
struct is_param_region *par = &is->is_p_region->parameter;
|
||||
struct chain_config *cfg = &is->config[is->config_index];
|
||||
|
@ -287,7 +287,7 @@ void __is_set_sensor(struct fimc_is *is, int fps)
|
|||
fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT);
|
||||
}
|
||||
|
||||
void __is_set_init_isp_aa(struct fimc_is *is)
|
||||
static void __maybe_unused __is_set_init_isp_aa(struct fimc_is *is)
|
||||
{
|
||||
struct isp_param *isp;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ int fimc_is_hw_set_param(struct fimc_is *is)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fimc_is_hw_set_tune(struct fimc_is *is)
|
||||
static int __maybe_unused fimc_is_hw_set_tune(struct fimc_is *is)
|
||||
{
|
||||
fimc_is_hw_wait_intmsr0_intmsd0(is);
|
||||
|
||||
|
@ -236,7 +236,7 @@ int fimc_is_itf_mode_change(struct fimc_is *is)
|
|||
fimc_is_hw_change_mode(is);
|
||||
ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1,
|
||||
FIMC_IS_CONFIG_TIMEOUT);
|
||||
if (!ret < 0)
|
||||
if (ret < 0)
|
||||
dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n",
|
||||
__func__, is->config_index);
|
||||
return ret;
|
||||
|
|
|
@ -993,3 +993,4 @@ module_exit(fimc_is_module_exit);
|
|||
MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME);
|
||||
MODULE_AUTHOR("Younghwan Joo <yhwan.joo@samsung.com>");
|
||||
MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -672,6 +672,8 @@ int fimc_isp_subdev_create(struct fimc_isp *isp)
|
|||
mutex_init(&isp->subdev_lock);
|
||||
|
||||
v4l2_subdev_init(sd, &fimc_is_subdev_ops);
|
||||
|
||||
sd->owner = THIS_MODULE;
|
||||
sd->grp_id = GRP_ID_FIMC_IS;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP");
|
||||
|
|
|
@ -90,7 +90,7 @@ static const struct fimc_fmt fimc_lite_formats[] = {
|
|||
.name = "RAW10 (GRBG)",
|
||||
.fourcc = V4L2_PIX_FMT_SGRBG10,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.depth = { 10 },
|
||||
.depth = { 16 },
|
||||
.color = FIMC_FMT_RAW10,
|
||||
.memplanes = 1,
|
||||
.mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
|
||||
|
@ -99,7 +99,7 @@ static const struct fimc_fmt fimc_lite_formats[] = {
|
|||
.name = "RAW12 (GRBG)",
|
||||
.fourcc = V4L2_PIX_FMT_SGRBG12,
|
||||
.colorspace = V4L2_COLORSPACE_SRGB,
|
||||
.depth = { 12 },
|
||||
.depth = { 16 },
|
||||
.color = FIMC_FMT_RAW12,
|
||||
.memplanes = 1,
|
||||
.mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12,
|
||||
|
@ -1504,16 +1504,17 @@ static int fimc_lite_probe(struct platform_device *pdev)
|
|||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
if (!dev->of_node)
|
||||
return -ENODEV;
|
||||
|
||||
fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
|
||||
if (!fimc)
|
||||
return -ENOMEM;
|
||||
|
||||
if (dev->of_node) {
|
||||
of_id = of_match_node(flite_of_match, dev->of_node);
|
||||
if (of_id)
|
||||
drv_data = (struct flite_drvdata *)of_id->data;
|
||||
fimc->index = of_alias_get_id(dev->of_node, "fimc-lite");
|
||||
}
|
||||
of_id = of_match_node(flite_of_match, dev->of_node);
|
||||
if (of_id)
|
||||
drv_data = (struct flite_drvdata *)of_id->data;
|
||||
fimc->index = of_alias_get_id(dev->of_node, "fimc-lite");
|
||||
|
||||
if (!drv_data || fimc->index >= drv_data->num_instances ||
|
||||
fimc->index < 0) {
|
||||
|
|
|
@ -1149,7 +1149,6 @@ static void fimc_md_put_clocks(struct fimc_md *fmd)
|
|||
while (--i >= 0) {
|
||||
if (IS_ERR(fmd->camclk[i].clock))
|
||||
continue;
|
||||
clk_unprepare(fmd->camclk[i].clock);
|
||||
clk_put(fmd->camclk[i].clock);
|
||||
fmd->camclk[i].clock = ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
@ -1168,7 +1167,7 @@ static int fimc_md_get_clocks(struct fimc_md *fmd)
|
|||
struct device *dev = NULL;
|
||||
char clk_name[32];
|
||||
struct clk *clock;
|
||||
int ret, i;
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < FIMC_MAX_CAMCLKS; i++)
|
||||
fmd->camclk[i].clock = ERR_PTR(-EINVAL);
|
||||
|
@ -1186,12 +1185,6 @@ static int fimc_md_get_clocks(struct fimc_md *fmd)
|
|||
ret = PTR_ERR(clock);
|
||||
break;
|
||||
}
|
||||
ret = clk_prepare(clock);
|
||||
if (ret < 0) {
|
||||
clk_put(clock);
|
||||
fmd->camclk[i].clock = ERR_PTR(-EINVAL);
|
||||
break;
|
||||
}
|
||||
fmd->camclk[i].clock = clock;
|
||||
}
|
||||
if (ret)
|
||||
|
@ -1248,7 +1241,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
|
|||
ret = pm_runtime_get_sync(fmd->pmf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = clk_enable(camclk->clock);
|
||||
ret = clk_prepare_enable(camclk->clock);
|
||||
dbg("Enabled camclk %d: f: %lu", si->clk_id,
|
||||
clk_get_rate(camclk->clock));
|
||||
}
|
||||
|
@ -1259,7 +1252,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
|
|||
return 0;
|
||||
|
||||
if (--camclk->use_count == 0) {
|
||||
clk_disable(camclk->clock);
|
||||
clk_disable_unprepare(camclk->clock);
|
||||
pm_runtime_put(fmd->pmf);
|
||||
dbg("Disabled camclk %d", si->clk_id);
|
||||
}
|
||||
|
@ -1529,9 +1522,9 @@ static int fimc_md_probe(struct platform_device *pdev)
|
|||
err_unlock:
|
||||
mutex_unlock(&fmd->media_dev.graph_mutex);
|
||||
err_clk:
|
||||
media_device_unregister(&fmd->media_dev);
|
||||
fimc_md_put_clocks(fmd);
|
||||
fimc_md_unregister_entities(fmd);
|
||||
media_device_unregister(&fmd->media_dev);
|
||||
err_md:
|
||||
v4l2_device_unregister(&fmd->v4l2_dev);
|
||||
return ret;
|
||||
|
@ -1543,6 +1536,8 @@ static int fimc_md_remove(struct platform_device *pdev)
|
|||
|
||||
if (!fmd)
|
||||
return 0;
|
||||
|
||||
v4l2_device_unregister(&fmd->v4l2_dev);
|
||||
device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
|
||||
fimc_md_unregister_entities(fmd);
|
||||
fimc_md_pipelines_free(fmd);
|
||||
|
|
|
@ -399,7 +399,7 @@ static void cafe_ctlr_init(struct mcam_camera *mcam)
|
|||
}
|
||||
|
||||
|
||||
static void cafe_ctlr_power_up(struct mcam_camera *mcam)
|
||||
static int cafe_ctlr_power_up(struct mcam_camera *mcam)
|
||||
{
|
||||
/*
|
||||
* Part one of the sensor dance: turn the global
|
||||
|
@ -414,6 +414,8 @@ static void cafe_ctlr_power_up(struct mcam_camera *mcam)
|
|||
*/
|
||||
mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN); /* pwr up, reset */
|
||||
mcam_reg_write(mcam, REG_GPR, GPR_C1EN|GPR_C0EN|GPR_C0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cafe_ctlr_power_down(struct mcam_camera *mcam)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
|
@ -93,6 +94,9 @@ MODULE_PARM_DESC(buffer_mode,
|
|||
#define CF_CONFIG_NEEDED 4 /* Must configure hardware */
|
||||
#define CF_SINGLE_BUFFER 5 /* Running with a single buffer */
|
||||
#define CF_SG_RESTART 6 /* SG restart needed */
|
||||
#define CF_FRAME_SOF0 7 /* Frame 0 started */
|
||||
#define CF_FRAME_SOF1 8
|
||||
#define CF_FRAME_SOF2 9
|
||||
|
||||
#define sensor_call(cam, o, f, args...) \
|
||||
v4l2_subdev_call(cam->sensor, o, f, ##args)
|
||||
|
@ -101,6 +105,7 @@ static struct mcam_format_struct {
|
|||
__u8 *desc;
|
||||
__u32 pixelformat;
|
||||
int bpp; /* Bytes per pixel */
|
||||
bool planar;
|
||||
enum v4l2_mbus_pixelcode mbus_code;
|
||||
} mcam_formats[] = {
|
||||
{
|
||||
|
@ -108,24 +113,56 @@ static struct mcam_format_struct {
|
|||
.pixelformat = V4L2_PIX_FMT_YUYV,
|
||||
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||
.bpp = 2,
|
||||
.planar = false,
|
||||
},
|
||||
{
|
||||
.desc = "UYVY 4:2:2",
|
||||
.pixelformat = V4L2_PIX_FMT_UYVY,
|
||||
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||
.bpp = 2,
|
||||
.planar = false,
|
||||
},
|
||||
{
|
||||
.desc = "YUV 4:2:2 PLANAR",
|
||||
.pixelformat = V4L2_PIX_FMT_YUV422P,
|
||||
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||
.bpp = 2,
|
||||
.planar = true,
|
||||
},
|
||||
{
|
||||
.desc = "YUV 4:2:0 PLANAR",
|
||||
.pixelformat = V4L2_PIX_FMT_YUV420,
|
||||
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||
.bpp = 2,
|
||||
.planar = true,
|
||||
},
|
||||
{
|
||||
.desc = "YVU 4:2:0 PLANAR",
|
||||
.pixelformat = V4L2_PIX_FMT_YVU420,
|
||||
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||
.bpp = 2,
|
||||
.planar = true,
|
||||
},
|
||||
{
|
||||
.desc = "RGB 444",
|
||||
.pixelformat = V4L2_PIX_FMT_RGB444,
|
||||
.mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
|
||||
.bpp = 2,
|
||||
.planar = false,
|
||||
},
|
||||
{
|
||||
.desc = "RGB 565",
|
||||
.pixelformat = V4L2_PIX_FMT_RGB565,
|
||||
.mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
|
||||
.bpp = 2,
|
||||
.planar = false,
|
||||
},
|
||||
{
|
||||
.desc = "Raw RGB Bayer",
|
||||
.pixelformat = V4L2_PIX_FMT_SBGGR8,
|
||||
.mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||
.bpp = 1
|
||||
.bpp = 1,
|
||||
.planar = false,
|
||||
},
|
||||
};
|
||||
#define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
|
||||
|
@ -168,6 +205,12 @@ struct mcam_dma_desc {
|
|||
u32 segment_len;
|
||||
};
|
||||
|
||||
struct yuv_pointer_t {
|
||||
dma_addr_t y;
|
||||
dma_addr_t u;
|
||||
dma_addr_t v;
|
||||
};
|
||||
|
||||
/*
|
||||
* Our buffer type for working with videobuf2. Note that the vb2
|
||||
* developers have decreed that struct vb2_buffer must be at the
|
||||
|
@ -179,6 +222,7 @@ struct mcam_vb_buffer {
|
|||
struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
|
||||
dma_addr_t dma_desc_pa; /* Descriptor physical address */
|
||||
int dma_desc_nent; /* Number of mapped descriptors */
|
||||
struct yuv_pointer_t yuv_p;
|
||||
};
|
||||
|
||||
static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
|
||||
|
@ -219,8 +263,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam)
|
|||
int i;
|
||||
|
||||
cam->next_buf = -1;
|
||||
for (i = 0; i < cam->nbufs; i++)
|
||||
for (i = 0; i < cam->nbufs; i++) {
|
||||
clear_bit(i, &cam->flags);
|
||||
clear_bit(CF_FRAME_SOF0 + i, &cam->flags);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int mcam_needs_config(struct mcam_camera *cam)
|
||||
|
@ -253,6 +299,45 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
|
|||
mcam_reg_clear_bit(cam, REG_CTRL0, C0_ENABLE);
|
||||
}
|
||||
|
||||
static void mcam_enable_mipi(struct mcam_camera *mcam)
|
||||
{
|
||||
/* Using MIPI mode and enable MIPI */
|
||||
cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n",
|
||||
mcam->dphy[0], mcam->dphy[1], mcam->dphy[2]);
|
||||
mcam_reg_write(mcam, REG_CSI2_DPHY3, mcam->dphy[0]);
|
||||
mcam_reg_write(mcam, REG_CSI2_DPHY5, mcam->dphy[1]);
|
||||
mcam_reg_write(mcam, REG_CSI2_DPHY6, mcam->dphy[2]);
|
||||
|
||||
if (!mcam->mipi_enabled) {
|
||||
if (mcam->lane > 4 || mcam->lane <= 0) {
|
||||
cam_warn(mcam, "lane number error\n");
|
||||
mcam->lane = 1; /* set the default value */
|
||||
}
|
||||
/*
|
||||
* 0x41 actives 1 lane
|
||||
* 0x43 actives 2 lanes
|
||||
* 0x45 actives 3 lanes (never happen)
|
||||
* 0x47 actives 4 lanes
|
||||
*/
|
||||
mcam_reg_write(mcam, REG_CSI2_CTRL0,
|
||||
CSI2_C0_MIPI_EN | CSI2_C0_ACT_LANE(mcam->lane));
|
||||
mcam_reg_write(mcam, REG_CLKCTRL,
|
||||
(mcam->mclk_src << 29) | mcam->mclk_div);
|
||||
|
||||
mcam->mipi_enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void mcam_disable_mipi(struct mcam_camera *mcam)
|
||||
{
|
||||
/* Using Parallel mode or disable MIPI */
|
||||
mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0);
|
||||
mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0);
|
||||
mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0);
|
||||
mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0);
|
||||
mcam->mipi_enabled = false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#ifdef MCAM_MODE_VMALLOC
|
||||
|
@ -425,6 +510,15 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
|
|||
/*
|
||||
* DMA-contiguous code.
|
||||
*/
|
||||
|
||||
static bool mcam_fmt_is_planar(__u32 pfmt)
|
||||
{
|
||||
struct mcam_format_struct *f;
|
||||
|
||||
f = mcam_find_format(pfmt);
|
||||
return f->planar;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a contiguous buffer for the given frame. Here also is where
|
||||
* the underrun strategy is set: if there is no buffer available, reuse
|
||||
|
@ -436,27 +530,58 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
|
|||
static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
|
||||
{
|
||||
struct mcam_vb_buffer *buf;
|
||||
struct v4l2_pix_format *fmt = &cam->pix_format;
|
||||
dma_addr_t dma_handle;
|
||||
u32 pixel_count = fmt->width * fmt->height;
|
||||
struct vb2_buffer *vb;
|
||||
|
||||
/*
|
||||
* If there are no available buffers, go into single mode
|
||||
*/
|
||||
if (list_empty(&cam->buffers)) {
|
||||
buf = cam->vb_bufs[frame ^ 0x1];
|
||||
cam->vb_bufs[frame] = buf;
|
||||
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
|
||||
vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
|
||||
set_bit(CF_SINGLE_BUFFER, &cam->flags);
|
||||
cam->frame_state.singles++;
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* OK, we have a buffer we can use.
|
||||
*/
|
||||
buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
|
||||
queue);
|
||||
list_del_init(&buf->queue);
|
||||
clear_bit(CF_SINGLE_BUFFER, &cam->flags);
|
||||
}
|
||||
/*
|
||||
* OK, we have a buffer we can use.
|
||||
*/
|
||||
buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
|
||||
list_del_init(&buf->queue);
|
||||
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
|
||||
vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
|
||||
|
||||
cam->vb_bufs[frame] = buf;
|
||||
clear_bit(CF_SINGLE_BUFFER, &cam->flags);
|
||||
vb = &buf->vb_buf;
|
||||
|
||||
dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
|
||||
buf->yuv_p.y = dma_handle;
|
||||
|
||||
switch (cam->pix_format.pixelformat) {
|
||||
case V4L2_PIX_FMT_YUV422P:
|
||||
buf->yuv_p.u = buf->yuv_p.y + pixel_count;
|
||||
buf->yuv_p.v = buf->yuv_p.u + pixel_count / 2;
|
||||
break;
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
buf->yuv_p.u = buf->yuv_p.y + pixel_count;
|
||||
buf->yuv_p.v = buf->yuv_p.u + pixel_count / 4;
|
||||
break;
|
||||
case V4L2_PIX_FMT_YVU420:
|
||||
buf->yuv_p.v = buf->yuv_p.y + pixel_count;
|
||||
buf->yuv_p.u = buf->yuv_p.v + pixel_count / 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
|
||||
if (mcam_fmt_is_planar(fmt->pixelformat)) {
|
||||
mcam_reg_write(cam, frame == 0 ?
|
||||
REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
|
||||
mcam_reg_write(cam, frame == 0 ?
|
||||
REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -614,48 +739,90 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
|
|||
*/
|
||||
static void mcam_ctlr_image(struct mcam_camera *cam)
|
||||
{
|
||||
int imgsz;
|
||||
struct v4l2_pix_format *fmt = &cam->pix_format;
|
||||
u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
|
||||
|
||||
cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
|
||||
fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
|
||||
imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
|
||||
imgsz_w = (fmt->width * 2) & IMGSZ_H_MASK;
|
||||
|
||||
switch (fmt->pixelformat) {
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
case V4L2_PIX_FMT_UYVY:
|
||||
widthy = fmt->width * 2;
|
||||
widthuv = 0;
|
||||
break;
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
|
||||
widthy = fmt->bytesperline;
|
||||
widthuv = 0;
|
||||
break;
|
||||
case V4L2_PIX_FMT_YUV422P:
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
case V4L2_PIX_FMT_YVU420:
|
||||
widthy = fmt->width;
|
||||
widthuv = fmt->width / 2;
|
||||
break;
|
||||
default:
|
||||
widthy = fmt->bytesperline;
|
||||
widthuv = 0;
|
||||
}
|
||||
|
||||
mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
|
||||
IMGP_YP_MASK | IMGP_UVP_MASK);
|
||||
mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
|
||||
mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
|
||||
|
||||
imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
|
||||
(fmt->bytesperline & IMGSZ_H_MASK);
|
||||
mcam_reg_write(cam, REG_IMGSIZE, imgsz);
|
||||
mcam_reg_write(cam, REG_IMGOFFSET, 0);
|
||||
/* YPITCH just drops the last two bits */
|
||||
mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
|
||||
IMGP_YP_MASK);
|
||||
/*
|
||||
* Tell the controller about the image format we are using.
|
||||
*/
|
||||
switch (cam->pix_format.pixelformat) {
|
||||
switch (fmt->pixelformat) {
|
||||
case V4L2_PIX_FMT_YUV422P:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
|
||||
break;
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
case V4L2_PIX_FMT_YVU420:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
|
||||
break;
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
|
||||
C0_DF_MASK);
|
||||
break;
|
||||
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
|
||||
break;
|
||||
case V4L2_PIX_FMT_UYVY:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
|
||||
break;
|
||||
case V4L2_PIX_FMT_JPEG:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB444:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
|
||||
C0_DF_MASK);
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
|
||||
/* Alpha value? */
|
||||
break;
|
||||
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
|
||||
C0_DF_MASK);
|
||||
break;
|
||||
|
||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||
C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
|
||||
break;
|
||||
default:
|
||||
cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
|
||||
break;
|
||||
cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure it knows we want to use hsync/vsync.
|
||||
*/
|
||||
mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
|
||||
C0_SIFM_MASK);
|
||||
mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
|
||||
/*
|
||||
* This field controls the generation of EOF(DVP only)
|
||||
*/
|
||||
if (cam->bus_type != V4L2_MBUS_CSI2)
|
||||
mcam_reg_set_bit(cam, REG_CTRL0,
|
||||
C0_EOF_VSYNC | C0_VEDGE_CTRL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -753,15 +920,21 @@ static void mcam_ctlr_stop_dma(struct mcam_camera *cam)
|
|||
/*
|
||||
* Power up and down.
|
||||
*/
|
||||
static void mcam_ctlr_power_up(struct mcam_camera *cam)
|
||||
static int mcam_ctlr_power_up(struct mcam_camera *cam)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&cam->dev_lock, flags);
|
||||
cam->plat_power_up(cam);
|
||||
ret = cam->plat_power_up(cam);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&cam->dev_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
mcam_reg_clear_bit(cam, REG_CTRL1, C1_PWRDWN);
|
||||
spin_unlock_irqrestore(&cam->dev_lock, flags);
|
||||
msleep(5); /* Just to be sure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mcam_ctlr_power_down(struct mcam_camera *cam)
|
||||
|
@ -869,6 +1042,17 @@ static int mcam_read_setup(struct mcam_camera *cam)
|
|||
spin_lock_irqsave(&cam->dev_lock, flags);
|
||||
clear_bit(CF_DMA_ACTIVE, &cam->flags);
|
||||
mcam_reset_buffers(cam);
|
||||
/*
|
||||
* Update CSI2_DPHY value
|
||||
*/
|
||||
if (cam->calc_dphy)
|
||||
cam->calc_dphy(cam);
|
||||
cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
|
||||
cam->dphy[0], cam->dphy[1], cam->dphy[2]);
|
||||
if (cam->bus_type == V4L2_MBUS_CSI2)
|
||||
mcam_enable_mipi(cam);
|
||||
else
|
||||
mcam_disable_mipi(cam);
|
||||
mcam_ctlr_irq_enable(cam);
|
||||
cam->state = S_STREAMING;
|
||||
if (!test_bit(CF_SG_RESTART, &cam->flags))
|
||||
|
@ -943,6 +1127,7 @@ static void mcam_vb_wait_finish(struct vb2_queue *vq)
|
|||
static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
{
|
||||
struct mcam_camera *cam = vb2_get_drv_priv(vq);
|
||||
unsigned int frame;
|
||||
|
||||
if (cam->state != S_IDLE) {
|
||||
INIT_LIST_HEAD(&cam->buffers);
|
||||
|
@ -960,6 +1145,14 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|||
cam->state = S_BUFWAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure clear the left over frame flags
|
||||
* before every really start streaming
|
||||
*/
|
||||
for (frame = 0; frame < cam->nbufs; frame++)
|
||||
clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
|
||||
|
||||
return mcam_read_setup(cam);
|
||||
}
|
||||
|
||||
|
@ -976,6 +1169,12 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
|
|||
if (cam->state != S_STREAMING)
|
||||
return -EINVAL;
|
||||
mcam_ctlr_stop_dma(cam);
|
||||
/*
|
||||
* Reset the CCIC PHY after stopping streaming,
|
||||
* otherwise, the CCIC may be unstable.
|
||||
*/
|
||||
if (cam->ctlr_reset)
|
||||
cam->ctlr_reset(cam);
|
||||
/*
|
||||
* VB2 reclaims the buffers, so we need to forget
|
||||
* about them.
|
||||
|
@ -1087,6 +1286,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
|
|||
#ifdef MCAM_MODE_DMA_CONTIG
|
||||
vq->ops = &mcam_vb2_ops;
|
||||
vq->mem_ops = &vb2_dma_contig_memops;
|
||||
vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
|
||||
cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
|
||||
vq->io_modes = VB2_MMAP | VB2_USERPTR;
|
||||
cam->dma_setup = mcam_ctlr_dma_contig;
|
||||
|
@ -1097,6 +1297,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
|
|||
#ifdef MCAM_MODE_DMA_SG
|
||||
vq->ops = &mcam_vb2_sg_ops;
|
||||
vq->mem_ops = &vb2_dma_sg_memops;
|
||||
vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
|
||||
vq->io_modes = VB2_MMAP | VB2_USERPTR;
|
||||
cam->dma_setup = mcam_ctlr_dma_sg;
|
||||
cam->frame_complete = mcam_dma_sg_done;
|
||||
|
@ -1247,7 +1448,15 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
|
|||
ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
|
||||
mutex_unlock(&cam->s_mutex);
|
||||
v4l2_fill_pix_format(pix, &mbus_fmt);
|
||||
pix->bytesperline = pix->width * f->bpp;
|
||||
switch (f->pixelformat) {
|
||||
case V4L2_PIX_FMT_YUV420:
|
||||
case V4L2_PIX_FMT_YVU420:
|
||||
pix->bytesperline = pix->width * 3 / 2;
|
||||
break;
|
||||
default:
|
||||
pix->bytesperline = pix->width * f->bpp;
|
||||
break;
|
||||
}
|
||||
pix->sizeimage = pix->height * pix->bytesperline;
|
||||
return ret;
|
||||
}
|
||||
|
@ -1475,7 +1684,9 @@ static int mcam_v4l_open(struct file *filp)
|
|||
ret = mcam_setup_vb2(cam);
|
||||
if (ret)
|
||||
goto out;
|
||||
mcam_ctlr_power_up(cam);
|
||||
ret = mcam_ctlr_power_up(cam);
|
||||
if (ret)
|
||||
goto out;
|
||||
__mcam_cam_reset(cam);
|
||||
mcam_set_config_needed(cam, 1);
|
||||
}
|
||||
|
@ -1498,10 +1709,12 @@ static int mcam_v4l_release(struct file *filp)
|
|||
if (cam->users == 0) {
|
||||
mcam_ctlr_stop_dma(cam);
|
||||
mcam_cleanup_vb2(cam);
|
||||
mcam_disable_mipi(cam);
|
||||
mcam_ctlr_power_down(cam);
|
||||
if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
|
||||
mcam_free_dma_bufs(cam);
|
||||
}
|
||||
|
||||
mutex_unlock(&cam->s_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1617,9 +1830,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
|
|||
* each time.
|
||||
*/
|
||||
for (frame = 0; frame < cam->nbufs; frame++)
|
||||
if (irqs & (IRQ_EOF0 << frame)) {
|
||||
if (irqs & (IRQ_EOF0 << frame) &&
|
||||
test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) {
|
||||
mcam_frame_complete(cam, frame);
|
||||
handled = 1;
|
||||
clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
|
||||
if (cam->buffer_mode == B_DMA_sg)
|
||||
break;
|
||||
}
|
||||
|
@ -1628,9 +1843,15 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
|
|||
* code assumes that we won't get multiple frame interrupts
|
||||
* at once; may want to rethink that.
|
||||
*/
|
||||
if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) {
|
||||
for (frame = 0; frame < cam->nbufs; frame++) {
|
||||
if (irqs & (IRQ_SOF0 << frame)) {
|
||||
set_bit(CF_FRAME_SOF0 + frame, &cam->flags);
|
||||
handled = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (handled == IRQ_HANDLED) {
|
||||
set_bit(CF_DMA_ACTIVE, &cam->flags);
|
||||
handled = 1;
|
||||
if (cam->buffer_mode == B_DMA_sg)
|
||||
mcam_ctlr_stop(cam);
|
||||
}
|
||||
|
@ -1787,7 +2008,11 @@ int mccic_resume(struct mcam_camera *cam)
|
|||
|
||||
mutex_lock(&cam->s_mutex);
|
||||
if (cam->users > 0) {
|
||||
mcam_ctlr_power_up(cam);
|
||||
ret = mcam_ctlr_power_up(cam);
|
||||
if (ret) {
|
||||
mutex_unlock(&cam->s_mutex);
|
||||
return ret;
|
||||
}
|
||||
__mcam_cam_reset(cam);
|
||||
} else {
|
||||
mcam_ctlr_power_down(cam);
|
||||
|
|
|
@ -88,6 +88,8 @@ struct mcam_frame_state {
|
|||
unsigned int delivered;
|
||||
};
|
||||
|
||||
#define NR_MCAM_CLK 3
|
||||
|
||||
/*
|
||||
* A description of one of our devices.
|
||||
* Locking: controlled by s_mutex. Certain fields, however, require
|
||||
|
@ -108,11 +110,33 @@ struct mcam_camera {
|
|||
short int clock_speed; /* Sensor clock speed, default 30 */
|
||||
short int use_smbus; /* SMBUS or straight I2c? */
|
||||
enum mcam_buffer_mode buffer_mode;
|
||||
|
||||
int mclk_min; /* The minimal value of mclk */
|
||||
int mclk_src; /* which clock source the mclk derives from */
|
||||
int mclk_div; /* Clock Divider Value for MCLK */
|
||||
|
||||
int ccic_id;
|
||||
enum v4l2_mbus_type bus_type;
|
||||
/* MIPI support */
|
||||
/* The dphy config value, allocated in board file
|
||||
* dphy[0]: DPHY3
|
||||
* dphy[1]: DPHY5
|
||||
* dphy[2]: DPHY6
|
||||
*/
|
||||
int *dphy;
|
||||
bool mipi_enabled; /* flag whether mipi is enabled already */
|
||||
int lane; /* lane number */
|
||||
|
||||
/* clock tree support */
|
||||
struct clk *clk[NR_MCAM_CLK];
|
||||
|
||||
/*
|
||||
* Callbacks from the core to the platform code.
|
||||
*/
|
||||
void (*plat_power_up) (struct mcam_camera *cam);
|
||||
int (*plat_power_up) (struct mcam_camera *cam);
|
||||
void (*plat_power_down) (struct mcam_camera *cam);
|
||||
void (*calc_dphy) (struct mcam_camera *cam);
|
||||
void (*ctlr_reset) (struct mcam_camera *cam);
|
||||
|
||||
/*
|
||||
* Everything below here is private to the mcam core and
|
||||
|
@ -225,6 +249,23 @@ int mccic_resume(struct mcam_camera *cam);
|
|||
#define REG_Y0BAR 0x00
|
||||
#define REG_Y1BAR 0x04
|
||||
#define REG_Y2BAR 0x08
|
||||
#define REG_U0BAR 0x0c
|
||||
#define REG_U1BAR 0x10
|
||||
#define REG_U2BAR 0x14
|
||||
#define REG_V0BAR 0x18
|
||||
#define REG_V1BAR 0x1C
|
||||
#define REG_V2BAR 0x20
|
||||
|
||||
/*
|
||||
* register definitions for MIPI support
|
||||
*/
|
||||
#define REG_CSI2_CTRL0 0x100
|
||||
#define CSI2_C0_MIPI_EN (0x1 << 0)
|
||||
#define CSI2_C0_ACT_LANE(n) ((n-1) << 1)
|
||||
#define REG_CSI2_DPHY3 0x12c
|
||||
#define REG_CSI2_DPHY5 0x134
|
||||
#define REG_CSI2_DPHY6 0x138
|
||||
|
||||
/* ... */
|
||||
|
||||
#define REG_IMGPITCH 0x24 /* Image pitch register */
|
||||
|
@ -293,13 +334,16 @@ int mccic_resume(struct mcam_camera *cam);
|
|||
#define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */
|
||||
#define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */
|
||||
/* Bayer bits 18,19 if needed */
|
||||
#define C0_EOF_VSYNC 0x00400000 /* Generate EOF by VSYNC */
|
||||
#define C0_VEDGE_CTRL 0x00800000 /* Detect falling edge of VSYNC */
|
||||
#define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */
|
||||
#define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */
|
||||
#define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */
|
||||
#define C0_DOWNSCALE 0x08000000 /* Enable downscaler */
|
||||
#define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */
|
||||
/* SIFMODE */
|
||||
#define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */
|
||||
#define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */
|
||||
#define C0_SOF_NOSYNC 0x40000000 /* Use inband active signaling */
|
||||
#define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */
|
||||
|
||||
/* Bits below C1_444ALPHA are not present in Cafe */
|
||||
#define REG_CTRL1 0x40 /* Control 1 */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "mcam-core.h"
|
||||
|
||||
|
@ -33,11 +34,14 @@ MODULE_ALIAS("platform:mmp-camera");
|
|||
MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static char *mcam_clks[] = {"CCICAXICLK", "CCICFUNCLK", "CCICPHYCLK"};
|
||||
|
||||
struct mmp_camera {
|
||||
void *power_regs;
|
||||
struct platform_device *pdev;
|
||||
struct mcam_camera mcam;
|
||||
struct list_head devlist;
|
||||
struct clk *mipi_clk;
|
||||
int irq;
|
||||
};
|
||||
|
||||
|
@ -101,6 +105,27 @@ static struct mmp_camera *mmpcam_find_device(struct platform_device *pdev)
|
|||
#define CPU_SUBSYS_PMU_BASE 0xd4282800
|
||||
#define REG_CCIC_DCGCR 0x28 /* CCIC dyn clock gate ctrl reg */
|
||||
#define REG_CCIC_CRCR 0x50 /* CCIC clk reset ctrl reg */
|
||||
#define REG_CCIC2_CRCR 0xf4 /* CCIC2 clk reset ctrl reg */
|
||||
|
||||
static void mcam_clk_enable(struct mcam_camera *mcam)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NR_MCAM_CLK; i++) {
|
||||
if (!IS_ERR(mcam->clk[i]))
|
||||
clk_prepare_enable(mcam->clk[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void mcam_clk_disable(struct mcam_camera *mcam)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = NR_MCAM_CLK - 1; i >= 0; i--) {
|
||||
if (!IS_ERR(mcam->clk[i]))
|
||||
clk_disable_unprepare(mcam->clk[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Power control.
|
||||
|
@ -112,10 +137,17 @@ static void mmpcam_power_up_ctlr(struct mmp_camera *cam)
|
|||
mdelay(1);
|
||||
}
|
||||
|
||||
static void mmpcam_power_up(struct mcam_camera *mcam)
|
||||
static int mmpcam_power_up(struct mcam_camera *mcam)
|
||||
{
|
||||
struct mmp_camera *cam = mcam_to_cam(mcam);
|
||||
struct mmp_camera_platform_data *pdata;
|
||||
|
||||
if (mcam->bus_type == V4L2_MBUS_CSI2) {
|
||||
cam->mipi_clk = devm_clk_get(mcam->dev, "mipi");
|
||||
if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0))
|
||||
return PTR_ERR(cam->mipi_clk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn on power and clocks to the controller.
|
||||
*/
|
||||
|
@ -132,6 +164,10 @@ static void mmpcam_power_up(struct mcam_camera *mcam)
|
|||
mdelay(5);
|
||||
gpio_set_value(pdata->sensor_reset_gpio, 1); /* reset is active low */
|
||||
mdelay(5);
|
||||
|
||||
mcam_clk_enable(mcam);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmpcam_power_down(struct mcam_camera *mcam)
|
||||
|
@ -149,8 +185,133 @@ static void mmpcam_power_down(struct mcam_camera *mcam)
|
|||
pdata = cam->pdev->dev.platform_data;
|
||||
gpio_set_value(pdata->sensor_power_gpio, 0);
|
||||
gpio_set_value(pdata->sensor_reset_gpio, 0);
|
||||
|
||||
if (mcam->bus_type == V4L2_MBUS_CSI2 && !IS_ERR(cam->mipi_clk)) {
|
||||
if (cam->mipi_clk)
|
||||
devm_clk_put(mcam->dev, cam->mipi_clk);
|
||||
cam->mipi_clk = NULL;
|
||||
}
|
||||
|
||||
mcam_clk_disable(mcam);
|
||||
}
|
||||
|
||||
void mcam_ctlr_reset(struct mcam_camera *mcam)
|
||||
{
|
||||
unsigned long val;
|
||||
struct mmp_camera *cam = mcam_to_cam(mcam);
|
||||
|
||||
if (mcam->ccic_id) {
|
||||
/*
|
||||
* Using CCIC2
|
||||
*/
|
||||
val = ioread32(cam->power_regs + REG_CCIC2_CRCR);
|
||||
iowrite32(val & ~0x2, cam->power_regs + REG_CCIC2_CRCR);
|
||||
iowrite32(val | 0x2, cam->power_regs + REG_CCIC2_CRCR);
|
||||
} else {
|
||||
/*
|
||||
* Using CCIC1
|
||||
*/
|
||||
val = ioread32(cam->power_regs + REG_CCIC_CRCR);
|
||||
iowrite32(val & ~0x2, cam->power_regs + REG_CCIC_CRCR);
|
||||
iowrite32(val | 0x2, cam->power_regs + REG_CCIC_CRCR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* calc the dphy register values
|
||||
* There are three dphy registers being used.
|
||||
* dphy[0] - CSI2_DPHY3
|
||||
* dphy[1] - CSI2_DPHY5
|
||||
* dphy[2] - CSI2_DPHY6
|
||||
* CSI2_DPHY3 and CSI2_DPHY6 can be set with a default value
|
||||
* or be calculated dynamically
|
||||
*/
|
||||
void mmpcam_calc_dphy(struct mcam_camera *mcam)
|
||||
{
|
||||
struct mmp_camera *cam = mcam_to_cam(mcam);
|
||||
struct mmp_camera_platform_data *pdata = cam->pdev->dev.platform_data;
|
||||
struct device *dev = &cam->pdev->dev;
|
||||
unsigned long tx_clk_esc;
|
||||
|
||||
/*
|
||||
* If CSI2_DPHY3 is calculated dynamically,
|
||||
* pdata->lane_clk should be already set
|
||||
* either in the board driver statically
|
||||
* or in the sensor driver dynamically.
|
||||
*/
|
||||
/*
|
||||
* dphy[0] - CSI2_DPHY3:
|
||||
* bit 0 ~ bit 7: HS Term Enable.
|
||||
* defines the time that the DPHY
|
||||
* wait before enabling the data
|
||||
* lane termination after detecting
|
||||
* that the sensor has driven the data
|
||||
* lanes to the LP00 bridge state.
|
||||
* The value is calculated by:
|
||||
* (Max T(D_TERM_EN)/Period(DDR)) - 1
|
||||
* bit 8 ~ bit 15: HS_SETTLE
|
||||
* Time interval during which the HS
|
||||
* receiver shall ignore any Data Lane
|
||||
* HS transistions.
|
||||
* The vaule has been calibrated on
|
||||
* different boards. It seems to work well.
|
||||
*
|
||||
* More detail please refer
|
||||
* MIPI Alliance Spectification for D-PHY
|
||||
* document for explanation of HS-SETTLE
|
||||
* and D-TERM-EN.
|
||||
*/
|
||||
switch (pdata->dphy3_algo) {
|
||||
case DPHY3_ALGO_PXA910:
|
||||
/*
|
||||
* Calculate CSI2_DPHY3 algo for PXA910
|
||||
*/
|
||||
pdata->dphy[0] =
|
||||
(((1 + (pdata->lane_clk * 80) / 1000) & 0xff) << 8)
|
||||
| (1 + pdata->lane_clk * 35 / 1000);
|
||||
break;
|
||||
case DPHY3_ALGO_PXA2128:
|
||||
/*
|
||||
* Calculate CSI2_DPHY3 algo for PXA2128
|
||||
*/
|
||||
pdata->dphy[0] =
|
||||
(((2 + (pdata->lane_clk * 110) / 1000) & 0xff) << 8)
|
||||
| (1 + pdata->lane_clk * 35 / 1000);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Use default CSI2_DPHY3 value for PXA688/PXA988
|
||||
*/
|
||||
dev_dbg(dev, "camera: use the default CSI2_DPHY3 value\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* mipi_clk will never be changed, it is a fixed value on MMP
|
||||
*/
|
||||
if (IS_ERR(cam->mipi_clk))
|
||||
return;
|
||||
|
||||
/* get the escape clk, this is hard coded */
|
||||
tx_clk_esc = (clk_get_rate(cam->mipi_clk) / 1000000) / 12;
|
||||
|
||||
/*
|
||||
* dphy[2] - CSI2_DPHY6:
|
||||
* bit 0 ~ bit 7: CK Term Enable
|
||||
* Time for the Clock Lane receiver to enable the HS line
|
||||
* termination. The value is calculated similarly with
|
||||
* HS Term Enable
|
||||
* bit 8 ~ bit 15: CK Settle
|
||||
* Time interval during which the HS receiver shall ignore
|
||||
* any Clock Lane HS transitions.
|
||||
* The value is calibrated on the boards.
|
||||
*/
|
||||
pdata->dphy[2] =
|
||||
((((534 * tx_clk_esc) / 2000 - 1) & 0xff) << 8)
|
||||
| (((38 * tx_clk_esc) / 1000 - 1) & 0xff);
|
||||
|
||||
dev_dbg(dev, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
|
||||
pdata->dphy[0], pdata->dphy[1], pdata->dphy[2]);
|
||||
}
|
||||
|
||||
static irqreturn_t mmpcam_irq(int irq, void *data)
|
||||
{
|
||||
|
@ -164,6 +325,35 @@ static irqreturn_t mmpcam_irq(int irq, void *data)
|
|||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static void mcam_deinit_clk(struct mcam_camera *mcam)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NR_MCAM_CLK; i++) {
|
||||
if (!IS_ERR(mcam->clk[i])) {
|
||||
if (mcam->clk[i])
|
||||
devm_clk_put(mcam->dev, mcam->clk[i]);
|
||||
}
|
||||
mcam->clk[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void mcam_init_clk(struct mcam_camera *mcam)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NR_MCAM_CLK; i++) {
|
||||
if (mcam_clks[i] != NULL) {
|
||||
/* Some clks are not necessary on some boards
|
||||
* We still try to run even it fails getting clk
|
||||
*/
|
||||
mcam->clk[i] = devm_clk_get(mcam->dev, mcam_clks[i]);
|
||||
if (IS_ERR(mcam->clk[i]))
|
||||
dev_warn(mcam->dev, "Could not get clk: %s\n",
|
||||
mcam_clks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mmpcam_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -173,17 +363,32 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||
struct mmp_camera_platform_data *pdata;
|
||||
int ret;
|
||||
|
||||
cam = kzalloc(sizeof(*cam), GFP_KERNEL);
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
|
||||
cam = devm_kzalloc(&pdev->dev, sizeof(*cam), GFP_KERNEL);
|
||||
if (cam == NULL)
|
||||
return -ENOMEM;
|
||||
cam->pdev = pdev;
|
||||
cam->mipi_clk = NULL;
|
||||
INIT_LIST_HEAD(&cam->devlist);
|
||||
|
||||
mcam = &cam->mcam;
|
||||
mcam->plat_power_up = mmpcam_power_up;
|
||||
mcam->plat_power_down = mmpcam_power_down;
|
||||
mcam->ctlr_reset = mcam_ctlr_reset;
|
||||
mcam->calc_dphy = mmpcam_calc_dphy;
|
||||
mcam->dev = &pdev->dev;
|
||||
mcam->use_smbus = 0;
|
||||
mcam->ccic_id = pdev->id;
|
||||
mcam->mclk_min = pdata->mclk_min;
|
||||
mcam->mclk_src = pdata->mclk_src;
|
||||
mcam->mclk_div = pdata->mclk_div;
|
||||
mcam->bus_type = pdata->bus_type;
|
||||
mcam->dphy = pdata->dphy;
|
||||
mcam->mipi_enabled = false;
|
||||
mcam->lane = pdata->lane;
|
||||
mcam->chip_id = MCAM_ARMADA610;
|
||||
mcam->buffer_mode = B_DMA_sg;
|
||||
spin_lock_init(&mcam->dev_lock);
|
||||
|
@ -191,69 +396,58 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||
* Get our I/O memory.
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no iomem resource!\n");
|
||||
ret = -ENODEV;
|
||||
goto out_free;
|
||||
}
|
||||
mcam->regs = ioremap(res->start, resource_size(res));
|
||||
if (mcam->regs == NULL) {
|
||||
dev_err(&pdev->dev, "MMIO ioremap fail\n");
|
||||
ret = -ENODEV;
|
||||
goto out_free;
|
||||
}
|
||||
mcam->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(mcam->regs))
|
||||
return PTR_ERR(mcam->regs);
|
||||
mcam->regs_size = resource_size(res);
|
||||
/*
|
||||
* Power/clock memory is elsewhere; get it too. Perhaps this
|
||||
* should really be managed outside of this driver?
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no power resource!\n");
|
||||
ret = -ENODEV;
|
||||
goto out_unmap1;
|
||||
}
|
||||
cam->power_regs = ioremap(res->start, resource_size(res));
|
||||
if (cam->power_regs == NULL) {
|
||||
dev_err(&pdev->dev, "power MMIO ioremap fail\n");
|
||||
ret = -ENODEV;
|
||||
goto out_unmap1;
|
||||
}
|
||||
cam->power_regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(cam->power_regs))
|
||||
return PTR_ERR(cam->power_regs);
|
||||
/*
|
||||
* Find the i2c adapter. This assumes, of course, that the
|
||||
* i2c bus is already up and functioning.
|
||||
*/
|
||||
pdata = pdev->dev.platform_data;
|
||||
mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
|
||||
if (mcam->i2c_adapter == NULL) {
|
||||
ret = -ENODEV;
|
||||
dev_err(&pdev->dev, "No i2c adapter\n");
|
||||
goto out_unmap2;
|
||||
return -ENODEV;
|
||||
}
|
||||
/*
|
||||
* Sensor GPIO pins.
|
||||
*/
|
||||
ret = gpio_request(pdata->sensor_power_gpio, "cam-power");
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->sensor_power_gpio,
|
||||
"cam-power");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Can't get sensor power gpio %d",
|
||||
pdata->sensor_power_gpio);
|
||||
goto out_unmap2;
|
||||
return ret;
|
||||
}
|
||||
gpio_direction_output(pdata->sensor_power_gpio, 0);
|
||||
ret = gpio_request(pdata->sensor_reset_gpio, "cam-reset");
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->sensor_reset_gpio,
|
||||
"cam-reset");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Can't get sensor reset gpio %d",
|
||||
pdata->sensor_reset_gpio);
|
||||
goto out_gpio;
|
||||
return ret;
|
||||
}
|
||||
gpio_direction_output(pdata->sensor_reset_gpio, 0);
|
||||
|
||||
mcam_init_clk(mcam);
|
||||
|
||||
/*
|
||||
* Power the device up and hand it off to the core.
|
||||
*/
|
||||
mmpcam_power_up(mcam);
|
||||
ret = mmpcam_power_up(mcam);
|
||||
if (ret)
|
||||
goto out_deinit_clk;
|
||||
ret = mccic_register(mcam);
|
||||
if (ret)
|
||||
goto out_gpio2;
|
||||
goto out_power_down;
|
||||
/*
|
||||
* Finally, set up our IRQ now that the core is ready to
|
||||
* deal with it.
|
||||
|
@ -264,8 +458,8 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||
goto out_unregister;
|
||||
}
|
||||
cam->irq = res->start;
|
||||
ret = request_irq(cam->irq, mmpcam_irq, IRQF_SHARED,
|
||||
"mmp-camera", mcam);
|
||||
ret = devm_request_irq(&pdev->dev, cam->irq, mmpcam_irq, IRQF_SHARED,
|
||||
"mmp-camera", mcam);
|
||||
if (ret == 0) {
|
||||
mmpcam_add_device(cam);
|
||||
return 0;
|
||||
|
@ -273,17 +467,10 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||
|
||||
out_unregister:
|
||||
mccic_shutdown(mcam);
|
||||
out_gpio2:
|
||||
out_power_down:
|
||||
mmpcam_power_down(mcam);
|
||||
gpio_free(pdata->sensor_reset_gpio);
|
||||
out_gpio:
|
||||
gpio_free(pdata->sensor_power_gpio);
|
||||
out_unmap2:
|
||||
iounmap(cam->power_regs);
|
||||
out_unmap1:
|
||||
iounmap(mcam->regs);
|
||||
out_free:
|
||||
kfree(cam);
|
||||
out_deinit_clk:
|
||||
mcam_deinit_clk(mcam);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -300,6 +487,7 @@ static int mmpcam_remove(struct mmp_camera *cam)
|
|||
pdata = cam->pdev->dev.platform_data;
|
||||
gpio_free(pdata->sensor_reset_gpio);
|
||||
gpio_free(pdata->sensor_power_gpio);
|
||||
mcam_deinit_clk(mcam);
|
||||
iounmap(cam->power_regs);
|
||||
iounmap(mcam->regs);
|
||||
kfree(cam);
|
||||
|
|
|
@ -106,15 +106,15 @@ static const u32 src_pixfmt_map[8][2] = {
|
|||
void camif_hw_set_source_format(struct camif_dev *camif)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
|
||||
unsigned int i = ARRAY_SIZE(src_pixfmt_map);
|
||||
int i;
|
||||
u32 cfg;
|
||||
|
||||
while (i-- >= 0) {
|
||||
for (i = ARRAY_SIZE(src_pixfmt_map) - 1; i >= 0; i--) {
|
||||
if (src_pixfmt_map[i][0] == mf->code)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0 && src_pixfmt_map[i][0] != mf->code) {
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
dev_err(camif->dev,
|
||||
"Unsupported pixel code, falling back to %#08x\n",
|
||||
src_pixfmt_map[i][0]);
|
||||
|
|
|
@ -374,9 +374,9 @@
|
|||
#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6 16
|
||||
|
||||
/* Buffer size requirements defined by hardware */
|
||||
#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 1) * 8)
|
||||
#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h) (((w) + 1) * ((h) + 3) * 8)
|
||||
#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
|
||||
((DIV_ROUND_UP(imw, 64) * DIV_ROUND_UP(imh, 64) * 256) + \
|
||||
(((((imw + 127) / 64) * 16) * DIV_ROUND_UP(imh, 64) * 256) + \
|
||||
(DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h) (((w) * 192) + 64)
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Register definition file for Samsung MFC V7.x Interface (FIMV) driver
|
||||
*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _REGS_MFC_V7_H
|
||||
#define _REGS_MFC_V7_H
|
||||
|
||||
#include "regs-mfc-v6.h"
|
||||
|
||||
/* Additional features of v7 */
|
||||
#define S5P_FIMV_CODEC_VP8_ENC_V7 25
|
||||
|
||||
/* Additional registers for v7 */
|
||||
#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7 0xf47c
|
||||
|
||||
#define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7 0xf9e0
|
||||
#define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7 0xf9e4
|
||||
#define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7 0xf9e8
|
||||
#define S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7 0xf9ec
|
||||
#define S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7 0xf9f0
|
||||
#define S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7 0xf9f4
|
||||
|
||||
#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7 0xfa70
|
||||
#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7 0xfa74
|
||||
|
||||
#define S5P_FIMV_E_VP8_OPTIONS_V7 0xfdb0
|
||||
#define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7 0xfdb4
|
||||
#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION_V7 0xfdb8
|
||||
#define S5P_FIMV_E_VP8_NUM_T_LAYER_V7 0xfdc4
|
||||
|
||||
/* MFCv7 variant defines */
|
||||
#define MAX_FW_SIZE_V7 (SZ_1M) /* 1MB */
|
||||
#define MAX_CPB_SIZE_V7 (3 * SZ_1M) /* 3MB */
|
||||
#define MFC_VERSION_V7 0x72
|
||||
#define MFC_NUM_PORTS_V7 1
|
||||
|
||||
#define MFC_LUMA_PAD_BYTES_V7 256
|
||||
#define MFC_CHROMA_PAD_BYTES_V7 128
|
||||
|
||||
/* MFCv7 Context buffer sizes */
|
||||
#define MFC_CTX_BUF_SIZE_V7 (30 * SZ_1K) /* 30KB */
|
||||
#define MFC_H264_DEC_CTX_BUF_SIZE_V7 (2 * SZ_1M) /* 2MB */
|
||||
#define MFC_OTHER_DEC_CTX_BUF_SIZE_V7 (20 * SZ_1K) /* 20KB */
|
||||
#define MFC_H264_ENC_CTX_BUF_SIZE_V7 (100 * SZ_1K) /* 100KB */
|
||||
#define MFC_OTHER_ENC_CTX_BUF_SIZE_V7 (10 * SZ_1K) /* 10KB */
|
||||
|
||||
/* Buffer size defines */
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(w, h) \
|
||||
(SZ_1M + ((w) * 144) + (8192 * (h)) + 49216)
|
||||
|
||||
#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \
|
||||
(((w) * 48) + (((w) + 1) / 2 * 128) + 144 + 8192)
|
||||
|
||||
#endif /*_REGS_MFC_V7_H*/
|
|
@ -1391,6 +1391,32 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = {
|
|||
.fw_name = "s5p-mfc-v6.fw",
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
|
||||
.dev_ctx = MFC_CTX_BUF_SIZE_V7,
|
||||
.h264_dec_ctx = MFC_H264_DEC_CTX_BUF_SIZE_V7,
|
||||
.other_dec_ctx = MFC_OTHER_DEC_CTX_BUF_SIZE_V7,
|
||||
.h264_enc_ctx = MFC_H264_ENC_CTX_BUF_SIZE_V7,
|
||||
.other_enc_ctx = MFC_OTHER_ENC_CTX_BUF_SIZE_V7,
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_size buf_size_v7 = {
|
||||
.fw = MAX_FW_SIZE_V7,
|
||||
.cpb = MAX_CPB_SIZE_V7,
|
||||
.priv = &mfc_buf_size_v7,
|
||||
};
|
||||
|
||||
struct s5p_mfc_buf_align mfc_buf_align_v7 = {
|
||||
.base = 0,
|
||||
};
|
||||
|
||||
static struct s5p_mfc_variant mfc_drvdata_v7 = {
|
||||
.version = MFC_VERSION_V7,
|
||||
.port_num = MFC_NUM_PORTS_V7,
|
||||
.buf_size = &buf_size_v7,
|
||||
.buf_align = &mfc_buf_align_v7,
|
||||
.fw_name = "s5p-mfc-v7.fw",
|
||||
};
|
||||
|
||||
static struct platform_device_id mfc_driver_ids[] = {
|
||||
{
|
||||
.name = "s5p-mfc",
|
||||
|
@ -1401,6 +1427,9 @@ static struct platform_device_id mfc_driver_ids[] = {
|
|||
}, {
|
||||
.name = "s5p-mfc-v6",
|
||||
.driver_data = (unsigned long)&mfc_drvdata_v6,
|
||||
}, {
|
||||
.name = "s5p-mfc-v7",
|
||||
.driver_data = (unsigned long)&mfc_drvdata_v7,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
@ -1413,6 +1442,9 @@ static const struct of_device_id exynos_mfc_match[] = {
|
|||
}, {
|
||||
.compatible = "samsung,mfc-v6",
|
||||
.data = &mfc_drvdata_v6,
|
||||
}, {
|
||||
.compatible = "samsung,mfc-v7",
|
||||
.data = &mfc_drvdata_v7,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
|
|||
|
||||
void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
|
||||
{
|
||||
if (IS_MFCV6(dev))
|
||||
if (IS_MFCV6_PLUS(dev))
|
||||
s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
|
||||
else
|
||||
s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
|
||||
|
|
|
@ -108,6 +108,9 @@ static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
|
|||
case S5P_MFC_CODEC_H263_ENC:
|
||||
codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
|
||||
break;
|
||||
case S5P_MFC_CODEC_VP8_ENC:
|
||||
codec_type = S5P_FIMV_CODEC_VP8_ENC_V7;
|
||||
break;
|
||||
default:
|
||||
codec_type = S5P_FIMV_CODEC_NONE_V6;
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue