media updates for v3.20-rc1
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJU2NQQAAoJEAhfPr2O5OEV5BgQAIja/XsIgpeNhfN8kJ3GrdhL Z+QRTcHNc6AWGm1dkI+YTl4B38/xLlmxhUYPKsDl19N7n1oKkqdUxYtLe1mLdecW dvqMXMVBKQSCgyDP5sgZNHKlavEX1ZPTTtkrY8zYWaXbkcf4dOZyisbNQrmFdO3T wt4zwaO8+ziCEYbotLsaI1VpEDKFZV6AVhKnLsWxc4ZoCnAqJbmA31jtANxrQ0tw UgXRjJmf1uWrS+MWM5xFDi+v+FmZiUAHMJ5iksqWhp2pKj41geIqy7lAueytEN+Q vQHZ9cfhnoF/7VrqDtqq5CaJZPKfA80PSxml9mbjc4wytvWLevoc4UxFtU+lohOf YbM3nB5J3nAcq0bNF/cSpuYUoiGnK86FazuM6YAQy2CaucrVKALKHHmziWbK6gBv 1yA4qnDuRYKps3SQSQQKuNlv8dmcVTD/sVhf8EIx62son6xxeXf21nas61lw8k5P lrUVH9nJxkwTkRJ7wMjlAZeh0pTyB/Ag1bSn81myziv0r4AsNyWJT5qxN8szmZDe nXGIdQ1h5JkMQ0kCfhhLqgdIUwhx7dMXIlXcCfR/8a9uYm4StegPNCEZDybIi6co 8Ok3rPYt15PlrCyfMjXFOG/TYi/cZ/xIbffLbSFMOqnCUZElaA7RNpOnswNc9fc6 2WsY54Lb4ftC4bQ7hM90 =VH6m -----END PGP SIGNATURE----- Merge tag 'media/v3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: - Some documentation updates and a few new pixel formats - Stop btcx-risc abuse by cx88 and move it to bt8xx driver - New platform driver: am437x - New webcam driver: toptek - New remote controller hardware protocols added to img-ir driver - Removal of a few very old drivers that relies on old kABIs and are for very hard to find hardware: parallel port webcam drivers (bw-qcam, c-cam, pms and w9966), tlg2300, Video In/Out for SGI (vino) - Removal of the USB Telegent driver (tlg2300). The company that developed this driver has long gone and the hardware is hard to find. As it relies on a legacy set of kABI symbols and nobody seems to care about it, remove it. - several improvements at rtl2832 driver - conversion on cx28521 and au0828 to use videobuf2 (VB2) - several improvements, fixups and board additions * tag 'media/v3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (321 commits) [media] dvb_net: Convert local hex dump to print_hex_dump_debug [media] dvb_net: Use standard debugging facilities [media] dvb_net: Use vsprintf %pM extension to print Ethernet addresses [media] staging: lirc_serial: adjust boolean assignments [media] stb0899: use sign_extend32() for sign extension [media] si2168: add support for 1.7MHz bandwidth [media] si2168: return error if set_frontend is called with invalid parameters [media] lirc_dev: avoid potential null-dereference [media] mn88472: simplify bandwidth registers setting code [media] dvb: tc90522: re-add symbol-rate report [media] lmedm04: add read snr, signal strength and ber call backs [media] lmedm04: Create frontend call back for read status [media] lmedm04: create frontend callbacks for signal/snr/ber/ucblocks [media] lmedm04: Fix usb_submit_urb BOGUS urb xfer, pipe 1 != type 3 in interrupt urb [media] lmedm04: Increase Interupt due time to 200 msec [media] cx88-dvb: whitespace cleanup [media] rtl28xxu: properly initialize pdata [media] rtl2832: declare functions as static [media] rtl2830: declare functions as static [media] rtl2832_sdr: add kernel-doc comments for platform_data ...
This commit is contained in:
commit
3e63430a5c
|
@ -2692,12 +2692,11 @@ in the S5P family of SoCs by Samsung.
|
||||||
<row><entry></entry></row>
|
<row><entry></entry></row>
|
||||||
<row>
|
<row>
|
||||||
<entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE</constant> </entry>
|
<entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE</constant> </entry>
|
||||||
<entry>integer</entry>
|
<entry>boolean</entry>
|
||||||
</row><row><entry spanname="descr">If the display delay is enabled then the decoder has to return a
|
</row><row><entry spanname="descr">If the display delay is enabled then the decoder is forced to return a
|
||||||
CAPTURE buffer after processing a certain number of OUTPUT buffers. If this number is low, then it may result in
|
CAPTURE buffer (decoded frame) after processing a certain number of OUTPUT buffers. The delay can be set through
|
||||||
buffers not being dequeued in display order. In addition hardware may still use those buffers as reference, thus
|
<constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY</constant>. This feature can be used for example
|
||||||
application should not write to those buffers. This feature can be used for example for generating thumbnails of videos.
|
for generating thumbnails of videos. Applicable to the H264 decoder.
|
||||||
Applicable to the H264 decoder.
|
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
<row><entry></entry></row>
|
<row><entry></entry></row>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para>The following four pixel formats are raw sRGB / Bayer formats with
|
<para>These four pixel formats are raw sRGB / Bayer formats with
|
||||||
10 bits per colour. Each colour component is stored in a 16-bit word, with 6
|
10 bits per colour. Each colour component is stored in a 16-bit word, with 6
|
||||||
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
|
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
|
||||||
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
|
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
<para>The following four pixel formats are raw sRGB / Bayer
|
<para>These four pixel formats are raw sRGB / Bayer
|
||||||
formats with 10 bits per color compressed to 8 bits each,
|
formats with 10 bits per color compressed to 8 bits each,
|
||||||
using the A-LAW algorithm. Each color component consumes 8
|
using the A-LAW algorithm. Each color component consumes 8
|
||||||
bits of memory. In other respects this format is similar to
|
bits of memory. In other respects this format is similar to
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para>The following four pixel formats are raw sRGB / Bayer formats
|
<para>These four pixel formats are raw sRGB / Bayer formats
|
||||||
with 10 bits per colour compressed to 8 bits each, using DPCM
|
with 10 bits per colour compressed to 8 bits each, using DPCM
|
||||||
compression. DPCM, differential pulse-code modulation, is lossy.
|
compression. DPCM, differential pulse-code modulation, is lossy.
|
||||||
Each colour component consumes 8 bits of memory. In other respects
|
Each colour component consumes 8 bits of memory. In other respects
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
<refentry id="pixfmt-srggb10p">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>V4L2_PIX_FMT_SRGGB10P ('pRAA'),
|
||||||
|
V4L2_PIX_FMT_SGRBG10P ('pgAA'),
|
||||||
|
V4L2_PIX_FMT_SGBRG10P ('pGAA'),
|
||||||
|
V4L2_PIX_FMT_SBGGR10P ('pBAA'),
|
||||||
|
</refentrytitle>
|
||||||
|
&manvol;
|
||||||
|
</refmeta>
|
||||||
|
<refnamediv>
|
||||||
|
<refname id="V4L2-PIX-FMT-SRGGB10P"><constant>V4L2_PIX_FMT_SRGGB10P</constant></refname>
|
||||||
|
<refname id="V4L2-PIX-FMT-SGRBG10P"><constant>V4L2_PIX_FMT_SGRBG10P</constant></refname>
|
||||||
|
<refname id="V4L2-PIX-FMT-SGBRG10P"><constant>V4L2_PIX_FMT_SGBRG10P</constant></refname>
|
||||||
|
<refname id="V4L2-PIX-FMT-SBGGR10P"><constant>V4L2_PIX_FMT_SBGGR10P</constant></refname>
|
||||||
|
<refpurpose>10-bit packed Bayer formats</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>These four pixel formats are packed raw sRGB /
|
||||||
|
Bayer formats with 10 bits per colour. Every four consecutive
|
||||||
|
colour components are packed into 5 bytes. Each of the first 4
|
||||||
|
bytes contain the 8 high order bits of the pixels, and the
|
||||||
|
fifth byte contains the two least significants bits of each
|
||||||
|
pixel, in the same order.</para>
|
||||||
|
|
||||||
|
<para>Each n-pixel row contains n/2 green samples and n/2 blue
|
||||||
|
or red samples, with alternating green-red and green-blue
|
||||||
|
rows. They are conventionally described as GRGR... BGBG...,
|
||||||
|
RGRG... GBGB..., etc. Below is an example of one of these
|
||||||
|
formats:</para>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title><constant>V4L2_PIX_FMT_SBGGR10P</constant> 4 × 4
|
||||||
|
pixel image</title>
|
||||||
|
|
||||||
|
<formalpara>
|
||||||
|
<title>Byte Order.</title>
|
||||||
|
<para>Each cell is one byte.
|
||||||
|
<informaltable frame="topbot" colsep="1" rowsep="1">
|
||||||
|
<tgroup cols="5" align="center" border="1">
|
||||||
|
<colspec align="left" colwidth="2*" />
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry>start + 0:</entry>
|
||||||
|
<entry>B<subscript>00high</subscript></entry>
|
||||||
|
<entry>G<subscript>01high</subscript></entry>
|
||||||
|
<entry>B<subscript>02high</subscript></entry>
|
||||||
|
<entry>G<subscript>03high</subscript></entry>
|
||||||
|
<entry>B<subscript>00low</subscript>(bits 7--6)
|
||||||
|
G<subscript>01low</subscript>(bits 5--4)
|
||||||
|
B<subscript>02low</subscript>(bits 3--2)
|
||||||
|
G<subscript>03low</subscript>(bits 1--0)
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>start + 5:</entry>
|
||||||
|
<entry>G<subscript>10high</subscript></entry>
|
||||||
|
<entry>R<subscript>11high</subscript></entry>
|
||||||
|
<entry>G<subscript>12high</subscript></entry>
|
||||||
|
<entry>R<subscript>13high</subscript></entry>
|
||||||
|
<entry>G<subscript>10low</subscript>(bits 7--6)
|
||||||
|
R<subscript>11low</subscript>(bits 5--4)
|
||||||
|
G<subscript>12low</subscript>(bits 3--2)
|
||||||
|
R<subscript>13low</subscript>(bits 1--0)
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>start + 10:</entry>
|
||||||
|
<entry>B<subscript>20high</subscript></entry>
|
||||||
|
<entry>G<subscript>21high</subscript></entry>
|
||||||
|
<entry>B<subscript>22high</subscript></entry>
|
||||||
|
<entry>G<subscript>23high</subscript></entry>
|
||||||
|
<entry>B<subscript>20low</subscript>(bits 7--6)
|
||||||
|
G<subscript>21low</subscript>(bits 5--4)
|
||||||
|
B<subscript>22low</subscript>(bits 3--2)
|
||||||
|
G<subscript>23low</subscript>(bits 1--0)
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>start + 15:</entry>
|
||||||
|
<entry>G<subscript>30high</subscript></entry>
|
||||||
|
<entry>R<subscript>31high</subscript></entry>
|
||||||
|
<entry>G<subscript>32high</subscript></entry>
|
||||||
|
<entry>R<subscript>33high</subscript></entry>
|
||||||
|
<entry>G<subscript>30low</subscript>(bits 7--6)
|
||||||
|
R<subscript>31low</subscript>(bits 5--4)
|
||||||
|
G<subscript>32low</subscript>(bits 3--2)
|
||||||
|
R<subscript>33low</subscript>(bits 1--0)
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</informaltable>
|
||||||
|
</para>
|
||||||
|
</formalpara>
|
||||||
|
</example>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
|
@ -17,7 +17,7 @@
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para>The following four pixel formats are raw sRGB / Bayer formats with
|
<para>These four pixel formats are raw sRGB / Bayer formats with
|
||||||
12 bits per colour. Each colour component is stored in a 16-bit word, with 4
|
12 bits per colour. Each colour component is stored in a 16-bit word, with 4
|
||||||
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
|
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
|
||||||
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
|
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
|
||||||
|
|
|
@ -1405,6 +1405,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
|
||||||
&sub-srggb8;
|
&sub-srggb8;
|
||||||
&sub-sbggr16;
|
&sub-sbggr16;
|
||||||
&sub-srggb10;
|
&sub-srggb10;
|
||||||
|
&sub-srggb10p;
|
||||||
&sub-srggb10alaw8;
|
&sub-srggb10alaw8;
|
||||||
&sub-srggb10dpcm8;
|
&sub-srggb10dpcm8;
|
||||||
&sub-srggb12;
|
&sub-srggb12;
|
||||||
|
|
|
@ -212,11 +212,3 @@ standards set in the <structfield>standards</structfield> field.
|
||||||
&return-value;
|
&return-value;
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
<!--
|
|
||||||
Local Variables:
|
|
||||||
mode: sgml
|
|
||||||
sgml-parent-document: "v4l2.sgml"
|
|
||||||
indent-tabs-mode: nil
|
|
||||||
End:
|
|
||||||
-->
|
|
||||||
|
|
|
@ -131,11 +131,3 @@ is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
<!--
|
|
||||||
Local Variables:
|
|
||||||
mode: sgml
|
|
||||||
sgml-parent-document: "v4l2.sgml"
|
|
||||||
indent-tabs-mode: nil
|
|
||||||
End:
|
|
||||||
-->
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
SMIA/SMIA++ sensor
|
||||||
|
|
||||||
|
SMIA (Standard Mobile Imaging Architecture) is an image sensor standard
|
||||||
|
defined jointly by Nokia and ST. SMIA++, defined by Nokia, is an extension
|
||||||
|
of that. These definitions are valid for both types of sensors.
|
||||||
|
|
||||||
|
More detailed documentation can be found in
|
||||||
|
Documentation/devicetree/bindings/media/video-interfaces.txt .
|
||||||
|
|
||||||
|
|
||||||
|
Mandatory properties
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- compatible: "nokia,smia"
|
||||||
|
- reg: I2C address (0x10, or an alternative address)
|
||||||
|
- vana-supply: Analogue voltage supply (VANA), typically 2,8 volts (sensor
|
||||||
|
dependent).
|
||||||
|
- clocks: External clock to the sensor
|
||||||
|
- clock-frequency: Frequency of the external clock to the sensor
|
||||||
|
- link-frequencies: List of allowed data link frequencies. An array of
|
||||||
|
64-bit elements.
|
||||||
|
|
||||||
|
|
||||||
|
Optional properties
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- nokia,nvm-size: The size of the NVM, in bytes. If the size is not given,
|
||||||
|
the NVM contents will not be read.
|
||||||
|
- reset-gpios: XSHUTDOWN GPIO
|
||||||
|
|
||||||
|
|
||||||
|
Endpoint node mandatory properties
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
- clock-lanes: <0>
|
||||||
|
- data-lanes: <1..n>
|
||||||
|
- remote-endpoint: A phandle to the bus receiver's endpoint node.
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
&i2c2 {
|
||||||
|
clock-frequency = <400000>;
|
||||||
|
|
||||||
|
smiapp_1: camera@10 {
|
||||||
|
compatible = "nokia,smia";
|
||||||
|
reg = <0x10>;
|
||||||
|
reset-gpios = <&gpio3 20 0>;
|
||||||
|
vana-supply = <&vaux3>;
|
||||||
|
clocks = <&omap3_isp 0>;
|
||||||
|
clock-frequency = <9600000>;
|
||||||
|
nokia,nvm-size = <512>; /* 8 * 64 */
|
||||||
|
link-frequencies = /bits/ 64 <199200000 210000000 499200000>;
|
||||||
|
port {
|
||||||
|
smiapp_1_1: endpoint {
|
||||||
|
clock-lanes = <0>;
|
||||||
|
data-lanes = <1 2>;
|
||||||
|
remote-endpoint = <&csi2a_ep>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,7 +1,7 @@
|
||||||
Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
|
Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : should be "allwinner,sun4i-a10-ir";
|
- compatible : "allwinner,sun4i-a10-ir" or "allwinner,sun5i-a13-ir"
|
||||||
- clocks : list of clock specifiers, corresponding to
|
- clocks : list of clock specifiers, corresponding to
|
||||||
entries in clock-names property;
|
entries in clock-names property;
|
||||||
- clock-names : should contain "apb" and "ir" entries;
|
- clock-names : should contain "apb" and "ir" entries;
|
||||||
|
@ -10,6 +10,7 @@ Required properties:
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- linux,rc-map-name : Remote control map name.
|
- linux,rc-map-name : Remote control map name.
|
||||||
|
- resets : phandle + reset specifier pair
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ ir0: ir@01c21800 {
|
||||||
compatible = "allwinner,sun4i-a10-ir";
|
compatible = "allwinner,sun4i-a10-ir";
|
||||||
clocks = <&apb0_gates 6>, <&ir0_clk>;
|
clocks = <&apb0_gates 6>, <&ir0_clk>;
|
||||||
clock-names = "apb", "ir";
|
clock-names = "apb", "ir";
|
||||||
|
resets = <&apb0_rst 1>;
|
||||||
interrupts = <0 5 1>;
|
interrupts = <0 5 1>;
|
||||||
reg = <0x01C21800 0x40>;
|
reg = <0x01C21800 0x40>;
|
||||||
linux,rc-map-name = "rc-rc6-mce";
|
linux,rc-map-name = "rc-rc6-mce";
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
Texas Instruments AM437x CAMERA (VPFE)
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
The Video Processing Front End (VPFE) is a key component for image capture
|
||||||
|
applications. The capture module provides the system interface and the
|
||||||
|
processing capability to connect RAW image-sensor modules and video decoders
|
||||||
|
to the AM437x device.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: must be "ti,am437x-vpfe"
|
||||||
|
- reg: physical base address and length of the registers set for the device;
|
||||||
|
- interrupts: should contain IRQ line for the VPFE;
|
||||||
|
- ti,am437x-vpfe-interface: can be one of the following,
|
||||||
|
0 - Raw Bayer Interface.
|
||||||
|
1 - 8 Bit BT656 Interface.
|
||||||
|
2 - 10 Bit BT656 Interface.
|
||||||
|
3 - YCbCr 8 Bit Interface.
|
||||||
|
4 - YCbCr 16 Bit Interface.
|
||||||
|
|
||||||
|
VPFE supports a single port node with parallel bus. It should contain one
|
||||||
|
'port' child node with child 'endpoint' node. Please refer to the bindings
|
||||||
|
defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
vpfe: vpfe@f0034000 {
|
||||||
|
compatible = "ti,am437x-vpfe";
|
||||||
|
reg = <0x48328000 0x2000>;
|
||||||
|
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
|
||||||
|
pinctrl-names = "default", "sleep";
|
||||||
|
pinctrl-0 = <&vpfe_pins_default>;
|
||||||
|
pinctrl-1 = <&vpfe_pins_sleep>;
|
||||||
|
|
||||||
|
port {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
vpfe0_ep: endpoint {
|
||||||
|
remote-endpoint = <&ov2659_1>;
|
||||||
|
ti,am437x-vpfe-interface = <0>;
|
||||||
|
bus-width = <8>;
|
||||||
|
hsync-active = <0>;
|
||||||
|
vsync-active = <0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c1: i2c@4802a000 {
|
||||||
|
|
||||||
|
ov2659@30 {
|
||||||
|
compatible = "ti,ov2659";
|
||||||
|
reg = <0x30>;
|
||||||
|
|
||||||
|
port {
|
||||||
|
ov2659_1: endpoint {
|
||||||
|
remote-endpoint = <&vpfe0_ep>;
|
||||||
|
bus-width = <8>;
|
||||||
|
mclk-frequency = <12000000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -103,6 +103,9 @@ Optional endpoint properties
|
||||||
array contains only one entry.
|
array contains only one entry.
|
||||||
- clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
|
- clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
|
||||||
clock mode.
|
clock mode.
|
||||||
|
- link-frequencies: Allowed data bus frequencies. For MIPI CSI-2, for
|
||||||
|
instance, this is the actual frequency of the bus, not bits per clock per
|
||||||
|
lane value. An array of 64-bit unsigned integers.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
|
|
|
@ -1,205 +0,0 @@
|
||||||
c-qcam - Connectix Color QuickCam video4linux kernel driver
|
|
||||||
|
|
||||||
Copyright (C) 1999 Dave Forrest <drf5n@virginia.edu>
|
|
||||||
released under GNU GPL.
|
|
||||||
|
|
||||||
1999-12-08 Dave Forrest, written with kernel version 2.2.12 in mind
|
|
||||||
|
|
||||||
|
|
||||||
Table of Contents
|
|
||||||
|
|
||||||
1.0 Introduction
|
|
||||||
2.0 Compilation, Installation, and Configuration
|
|
||||||
3.0 Troubleshooting
|
|
||||||
4.0 Future Work / current work arounds
|
|
||||||
9.0 Sample Program, v4lgrab
|
|
||||||
10.0 Other Information
|
|
||||||
|
|
||||||
|
|
||||||
1.0 Introduction
|
|
||||||
|
|
||||||
The file ../../drivers/media/parport/c-qcam.c is a device driver for
|
|
||||||
the Logitech (nee Connectix) parallel port interface color CCD camera.
|
|
||||||
This is a fairly inexpensive device for capturing images. Logitech
|
|
||||||
does not currently provide information for developers, but many people
|
|
||||||
have engineered several solutions for non-Microsoft use of the Color
|
|
||||||
Quickcam.
|
|
||||||
|
|
||||||
1.1 Motivation
|
|
||||||
|
|
||||||
I spent a number of hours trying to get my camera to work, and I
|
|
||||||
hope this document saves you some time. My camera will not work with
|
|
||||||
the 2.2.13 kernel as distributed, but with a few patches to the
|
|
||||||
module, I was able to grab some frames. See 4.0, Future Work.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2.0 Compilation, Installation, and Configuration
|
|
||||||
|
|
||||||
The c-qcam depends on parallel port support, video4linux, and the
|
|
||||||
Color Quickcam. It is also nice to have the parallel port readback
|
|
||||||
support enabled. I enabled these as modules during the kernel
|
|
||||||
configuration. The appropriate flags are:
|
|
||||||
|
|
||||||
CONFIG_PRINTER M for lp.o, parport.o parport_pc.o modules
|
|
||||||
CONFIG_PNP_PARPORT M for autoprobe.o IEEE1284 readback module
|
|
||||||
CONFIG_PRINTER_READBACK M for parport_probe.o IEEE1284 readback module
|
|
||||||
CONFIG_VIDEO_DEV M for videodev.o video4linux module
|
|
||||||
CONFIG_VIDEO_CQCAM M for c-qcam.o Color Quickcam module
|
|
||||||
|
|
||||||
With these flags, the kernel should compile and install the modules.
|
|
||||||
To record and monitor the compilation, I use:
|
|
||||||
|
|
||||||
(make zlilo ; \
|
|
||||||
make modules; \
|
|
||||||
make modules_install ;
|
|
||||||
depmod -a ) &>log &
|
|
||||||
less log # then a capital 'F' to watch the progress
|
|
||||||
|
|
||||||
But that is my personal preference.
|
|
||||||
|
|
||||||
2.2 Configuration
|
|
||||||
|
|
||||||
The configuration requires module configuration and device
|
|
||||||
configuration. The following sections detail these procedures.
|
|
||||||
|
|
||||||
|
|
||||||
2.1 Module Configuration
|
|
||||||
|
|
||||||
Using modules requires a bit of work to install and pass the
|
|
||||||
parameters. Understand that entries in /etc/modprobe.d/*.conf of:
|
|
||||||
|
|
||||||
alias parport_lowlevel parport_pc
|
|
||||||
options parport_pc io=0x378 irq=none
|
|
||||||
alias char-major-81 videodev
|
|
||||||
alias char-major-81-0 c-qcam
|
|
||||||
|
|
||||||
2.2 Device Configuration
|
|
||||||
|
|
||||||
At this point, we need to ensure that the device files exist.
|
|
||||||
Video4linux used the /dev/video* files, and we want to attach the
|
|
||||||
Quickcam to one of these.
|
|
||||||
|
|
||||||
ls -lad /dev/video* # should produce a list of the video devices
|
|
||||||
|
|
||||||
If the video devices do not exist, you can create them with:
|
|
||||||
|
|
||||||
su
|
|
||||||
cd /dev
|
|
||||||
for ii in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
|
|
||||||
mknod video$ii c 81 $ii # char-major-81-[0-16]
|
|
||||||
chown root.root video$ii # owned by root
|
|
||||||
chmod 600 video$ii # read/writable by root only
|
|
||||||
done
|
|
||||||
|
|
||||||
Lots of people connect video0 to video and bttv, but you might want
|
|
||||||
your c-qcam to mean something more:
|
|
||||||
|
|
||||||
ln -s video0 c-qcam # make /dev/c-qcam a working file
|
|
||||||
ln -s c-qcam video # make /dev/c-qcam your default video source
|
|
||||||
|
|
||||||
But these are conveniences. The important part is to make the proper
|
|
||||||
special character files with the right major and minor numbers. All
|
|
||||||
of the special device files are listed in ../devices.txt. If you
|
|
||||||
would like the c-qcam readable by non-root users, you will need to
|
|
||||||
change the permissions.
|
|
||||||
|
|
||||||
3.0 Troubleshooting
|
|
||||||
|
|
||||||
If the sample program below, v4lgrab, gives you output then
|
|
||||||
everything is working.
|
|
||||||
|
|
||||||
v4lgrab | wc # should give you a count of characters
|
|
||||||
|
|
||||||
Otherwise, you have some problem.
|
|
||||||
|
|
||||||
The c-qcam is IEEE1284 compatible, so if you are using the proc file
|
|
||||||
system (CONFIG_PROC_FS), the parallel printer support
|
|
||||||
(CONFIG_PRINTER), the IEEE 1284 system,(CONFIG_PRINTER_READBACK), you
|
|
||||||
should be able to read some identification from your quickcam with
|
|
||||||
|
|
||||||
modprobe -v parport
|
|
||||||
modprobe -v parport_probe
|
|
||||||
cat /proc/parport/PORTNUMBER/autoprobe
|
|
||||||
Returns:
|
|
||||||
CLASS:MEDIA;
|
|
||||||
MODEL:Color QuickCam 2.0;
|
|
||||||
MANUFACTURER:Connectix;
|
|
||||||
|
|
||||||
A good response to this indicates that your color quickcam is alive
|
|
||||||
and well. A common problem is that the current driver does not
|
|
||||||
reliably detect a c-qcam, even though one is attached. In this case,
|
|
||||||
|
|
||||||
modprobe -v c-qcam
|
|
||||||
or
|
|
||||||
insmod -v c-qcam
|
|
||||||
|
|
||||||
Returns a message saying "Device or resource busy" Development is
|
|
||||||
currently underway, but a workaround is to patch the module to skip
|
|
||||||
the detection code and attach to a defined port. Check the
|
|
||||||
video4linux mailing list and archive for more current information.
|
|
||||||
|
|
||||||
3.1 Checklist:
|
|
||||||
|
|
||||||
Can you get an image?
|
|
||||||
v4lgrab >qcam.ppm ; wc qcam.ppm ; xv qcam.ppm
|
|
||||||
|
|
||||||
Is a working c-qcam connected to the port?
|
|
||||||
grep ^ /proc/parport/?/autoprobe
|
|
||||||
|
|
||||||
Do the /dev/video* files exist?
|
|
||||||
ls -lad /dev/video
|
|
||||||
|
|
||||||
Is the c-qcam module loaded?
|
|
||||||
modprobe -v c-qcam ; lsmod
|
|
||||||
|
|
||||||
Does the camera work with alternate programs? cqcam, etc?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
4.0 Future Work / current workarounds
|
|
||||||
|
|
||||||
It is hoped that this section will soon become obsolete, but if it
|
|
||||||
isn't, you might try patching the c-qcam module to add a parport=xxx
|
|
||||||
option as in the bw-qcam module so you can specify the parallel port:
|
|
||||||
|
|
||||||
insmod -v c-qcam parport=0
|
|
||||||
|
|
||||||
And bypass the detection code, see ../../drivers/char/c-qcam.c and
|
|
||||||
look for the 'qc_detect' code and call.
|
|
||||||
|
|
||||||
Note that there is work in progress to change the video4linux API,
|
|
||||||
this work is documented at the video4linux2 site listed below.
|
|
||||||
|
|
||||||
|
|
||||||
9.0 --- A sample program using v4lgrabber,
|
|
||||||
|
|
||||||
v4lgrab is a simple image grabber that will copy a frame from the
|
|
||||||
first video device, /dev/video0 to standard output in portable pixmap
|
|
||||||
format (.ppm) To produce .jpg output, you can use it like this:
|
|
||||||
'v4lgrab | convert - c-qcam.jpg'
|
|
||||||
|
|
||||||
|
|
||||||
10.0 --- Other Information
|
|
||||||
|
|
||||||
Use the ../../Maintainers file, particularly the VIDEO FOR LINUX and PARALLEL
|
|
||||||
PORT SUPPORT sections
|
|
||||||
|
|
||||||
The video4linux page:
|
|
||||||
http://linuxtv.org
|
|
||||||
|
|
||||||
The V4L2 API spec:
|
|
||||||
http://v4l2spec.bytesex.org/
|
|
||||||
|
|
||||||
Some web pages about the quickcams:
|
|
||||||
http://www.pingouin-land.com/howto/QuickCam-HOWTO.html
|
|
||||||
|
|
||||||
http://www.crynwr.com/qcpc/ QuickCam Third-Party Drivers
|
|
||||||
http://www.crynwr.com/qcpc/re.html Some Reverse Engineering
|
|
||||||
http://www.wirelesscouch.net/software/gqcam/ v4l client
|
|
||||||
http://phobos.illtel.denver.co.us/pub/qcread/ doesn't use v4l
|
|
||||||
ftp://ftp.cs.unm.edu/pub/chris/quickcam/ Has lots of drivers
|
|
||||||
http://www.cs.duke.edu/~reynolds/quickcam/ Has lots of information
|
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
tlg2300 release notes
|
|
||||||
====================
|
|
||||||
|
|
||||||
This is a v4l2/dvb device driver for the tlg2300 chip.
|
|
||||||
|
|
||||||
|
|
||||||
current status
|
|
||||||
==============
|
|
||||||
|
|
||||||
video
|
|
||||||
- support mmap and read().(no overlay)
|
|
||||||
|
|
||||||
audio
|
|
||||||
- The driver will register a ALSA card for the audio input.
|
|
||||||
|
|
||||||
vbi
|
|
||||||
- Works for almost TV norms.
|
|
||||||
|
|
||||||
dvb-t
|
|
||||||
- works for DVB-T
|
|
||||||
|
|
||||||
FM
|
|
||||||
- Works for radio.
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
TESTED APPLICATIONS:
|
|
||||||
|
|
||||||
-VLC1.0.4 test the video and dvb. The GUI is friendly to use.
|
|
||||||
|
|
||||||
-Mplayer test the video.
|
|
||||||
|
|
||||||
-Mplayer test the FM. The mplayer should be compiled with --enable-radio and
|
|
||||||
--enable-radio-capture.
|
|
||||||
The command runs as this(The alsa audio registers to card 1):
|
|
||||||
#mplayer radio://103.7/capture/ -radio adevice=hw=1,0:arate=48000 \
|
|
||||||
-rawaudio rate=48000:channels=2
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
KNOWN PROBLEMS:
|
|
||||||
about preemphasis:
|
|
||||||
You can set the preemphasis for radio by the following command:
|
|
||||||
#v4l2-ctl -d /dev/radio0 --set-ctrl=pre_emphasis_settings=1
|
|
||||||
|
|
||||||
"pre_emphasis_settings=1" means that you select the 50us. If you want
|
|
||||||
to select the 75us, please use "pre_emphasis_settings=2"
|
|
||||||
|
|
||||||
|
|
|
@ -793,8 +793,10 @@ video_register_device_no_warn() instead.
|
||||||
|
|
||||||
Whenever a device node is created some attributes are also created for you.
|
Whenever a device node is created some attributes are also created for you.
|
||||||
If you look in /sys/class/video4linux you see the devices. Go into e.g.
|
If you look in /sys/class/video4linux you see the devices. Go into e.g.
|
||||||
video0 and you will see 'name' and 'index' attributes. The 'name' attribute
|
video0 and you will see 'name', 'debug' and 'index' attributes. The 'name'
|
||||||
is the 'name' field of the video_device struct.
|
attribute is the 'name' field of the video_device struct. The 'debug' attribute
|
||||||
|
can be used to enable core debugging. See the next section for more detailed
|
||||||
|
information on this.
|
||||||
|
|
||||||
The 'index' attribute is the index of the device node: for each call to
|
The 'index' attribute is the index of the device node: for each call to
|
||||||
video_register_device() the index is just increased by 1. The first video
|
video_register_device() the index is just increased by 1. The first video
|
||||||
|
@ -816,6 +818,25 @@ video_device was embedded in it. The vdev->release() callback will never
|
||||||
be called if the registration failed, nor should you ever attempt to
|
be called if the registration failed, nor should you ever attempt to
|
||||||
unregister the device if the registration failed.
|
unregister the device if the registration failed.
|
||||||
|
|
||||||
|
video device debugging
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
The 'debug' attribute that is created for each video, vbi, radio or swradio
|
||||||
|
device in /sys/class/video4linux/<devX>/ allows you to enable logging of
|
||||||
|
file operations.
|
||||||
|
|
||||||
|
It is a bitmask and the following bits can be set:
|
||||||
|
|
||||||
|
0x01: Log the ioctl name and error code. VIDIOC_(D)QBUF ioctls are only logged
|
||||||
|
if bit 0x08 is also set.
|
||||||
|
0x02: Log the ioctl name arguments and error code. VIDIOC_(D)QBUF ioctls are
|
||||||
|
only logged if bit 0x08 is also set.
|
||||||
|
0x04: Log the file operations open, release, read, write, mmap and
|
||||||
|
get_unmapped_area. The read and write operations are only logged if
|
||||||
|
bit 0x08 is also set.
|
||||||
|
0x08: Log the read and write file operations and the VIDIOC_QBUF and
|
||||||
|
VIDIOC_DQBUF ioctls.
|
||||||
|
0x10: Log the poll file operation.
|
||||||
|
|
||||||
video_device cleanup
|
video_device cleanup
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
W9966 Camera driver, written by Jakob Kemi (jakob.kemi@telia.com)
|
|
||||||
|
|
||||||
After a lot of work in softice & wdasm, reading .pdf-files and tiresome
|
|
||||||
trial-and-error work I've finally got everything to work. I needed vision for a
|
|
||||||
robotics project so I borrowed this camera from a friend and started hacking.
|
|
||||||
Anyway I've converted my original code from the AVR 8bit RISC C/ASM code into
|
|
||||||
a working Linux driver.
|
|
||||||
|
|
||||||
To get it working simply configure your kernel to support
|
|
||||||
parport, ieee1284, video4linux and w9966
|
|
||||||
|
|
||||||
If w9966 is statically linked it will always perform aggressive probing for
|
|
||||||
the camera. If built as a module you'll have more configuration options.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
modprobe w9966.o pardev=parport0(or whatever) parmode=0 (0=auto, 1=ecp, 2=epp)
|
|
||||||
voila!
|
|
||||||
|
|
||||||
you can also type 'modinfo -p w9966.o' for option usage
|
|
||||||
(or checkout w9966.c)
|
|
||||||
|
|
||||||
The only thing to keep in mind is that the image format is in Y-U-Y-V format
|
|
||||||
where every two pixels take 4 bytes. In SDL (www.libsdl.org) this format
|
|
||||||
is called VIDEO_PALETTE_YUV422 (16 bpp).
|
|
||||||
|
|
||||||
A minimal test application (with source) is available from:
|
|
||||||
http://www.slackwaresupport.com/howtos/Webcam-HOWTO
|
|
||||||
|
|
||||||
The slow framerate is due to missing DMA ECP read support in the
|
|
||||||
parport drivers. I might add working EPP support later.
|
|
||||||
|
|
||||||
Good luck!
|
|
||||||
/Jakob Kemi
|
|
41
MAINTAINERS
41
MAINTAINERS
|
@ -659,6 +659,13 @@ L: linux-media@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/media/i2c/ad9389b*
|
F: drivers/media/i2c/ad9389b*
|
||||||
|
|
||||||
|
ANALOG DEVICES INC ADV7180 DRIVER
|
||||||
|
M: Lars-Peter Clausen <lars@metafoo.de>
|
||||||
|
L: linux-media@vger.kernel.org
|
||||||
|
W: http://ez.analog.com/community/linux-device-drivers
|
||||||
|
S: Supported
|
||||||
|
F: drivers/media/i2c/adv7180.c
|
||||||
|
|
||||||
ANALOG DEVICES INC ADV7511 DRIVER
|
ANALOG DEVICES INC ADV7511 DRIVER
|
||||||
M: Hans Verkuil <hans.verkuil@cisco.com>
|
M: Hans Verkuil <hans.verkuil@cisco.com>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
|
@ -6202,14 +6209,6 @@ F: include/uapi/linux/meye.h
|
||||||
F: include/uapi/linux/ivtv*
|
F: include/uapi/linux/ivtv*
|
||||||
F: include/uapi/linux/uvcvideo.h
|
F: include/uapi/linux/uvcvideo.h
|
||||||
|
|
||||||
MEDIAVISION PRO MOVIE STUDIO DRIVER
|
|
||||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
|
||||||
L: linux-media@vger.kernel.org
|
|
||||||
T: git git://linuxtv.org/media_tree.git
|
|
||||||
W: http://linuxtv.org
|
|
||||||
S: Odd Fixes
|
|
||||||
F: drivers/media/parport/pms*
|
|
||||||
|
|
||||||
MEGARAID SCSI/SAS DRIVERS
|
MEGARAID SCSI/SAS DRIVERS
|
||||||
M: Kashyap Desai <kashyap.desai@avagotech.com>
|
M: Kashyap Desai <kashyap.desai@avagotech.com>
|
||||||
M: Sumit Saxena <sumit.saxena@avagotech.com>
|
M: Sumit Saxena <sumit.saxena@avagotech.com>
|
||||||
|
@ -7909,14 +7908,6 @@ T: git git://github.com/KrasnikovEugene/wcn36xx.git
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/wireless/ath/wcn36xx/
|
F: drivers/net/wireless/ath/wcn36xx/
|
||||||
|
|
||||||
QUICKCAM PARALLEL PORT WEBCAMS
|
|
||||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
|
||||||
L: linux-media@vger.kernel.org
|
|
||||||
T: git git://linuxtv.org/media_tree.git
|
|
||||||
W: http://linuxtv.org
|
|
||||||
S: Odd Fixes
|
|
||||||
F: drivers/media/parport/*-qcam*
|
|
||||||
|
|
||||||
RADOS BLOCK DEVICE (RBD)
|
RADOS BLOCK DEVICE (RBD)
|
||||||
M: Yehuda Sadeh <yehuda@inktank.com>
|
M: Yehuda Sadeh <yehuda@inktank.com>
|
||||||
M: Sage Weil <sage@inktank.com>
|
M: Sage Weil <sage@inktank.com>
|
||||||
|
@ -8454,12 +8445,6 @@ F: kernel/time/clocksource.c
|
||||||
F: kernel/time/time*.c
|
F: kernel/time/time*.c
|
||||||
F: kernel/time/ntp.c
|
F: kernel/time/ntp.c
|
||||||
|
|
||||||
TLG2300 VIDEO4LINUX-2 DRIVER
|
|
||||||
M: Huang Shijie <shijie8@gmail.com>
|
|
||||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
|
||||||
S: Odd Fixes
|
|
||||||
F: drivers/media/usb/tlg2300/
|
|
||||||
|
|
||||||
SC1200 WDT DRIVER
|
SC1200 WDT DRIVER
|
||||||
M: Zwane Mwaikambo <zwanem@gmail.com>
|
M: Zwane Mwaikambo <zwanem@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
@ -8825,6 +8810,15 @@ S: Maintained
|
||||||
F: drivers/media/platform/davinci/
|
F: drivers/media/platform/davinci/
|
||||||
F: include/media/davinci/
|
F: include/media/davinci/
|
||||||
|
|
||||||
|
TI AM437X VPFE DRIVER
|
||||||
|
M: Lad, Prabhakar <prabhakar.csengg@gmail.com>
|
||||||
|
L: linux-media@vger.kernel.org
|
||||||
|
W: http://linuxtv.org/
|
||||||
|
Q: http://patchwork.linuxtv.org/project/linux-media/list/
|
||||||
|
T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/media/platform/am437x/
|
||||||
|
|
||||||
SIS 190 ETHERNET DRIVER
|
SIS 190 ETHERNET DRIVER
|
||||||
M: Francois Romieu <romieu@fr.zoreil.com>
|
M: Francois Romieu <romieu@fr.zoreil.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
|
@ -8906,6 +8900,8 @@ F: drivers/media/i2c/smiapp/
|
||||||
F: include/media/smiapp.h
|
F: include/media/smiapp.h
|
||||||
F: drivers/media/i2c/smiapp-pll.c
|
F: drivers/media/i2c/smiapp-pll.c
|
||||||
F: drivers/media/i2c/smiapp-pll.h
|
F: drivers/media/i2c/smiapp-pll.h
|
||||||
|
F: include/uapi/linux/smiapp.h
|
||||||
|
F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
|
||||||
|
|
||||||
SMM665 HARDWARE MONITOR DRIVER
|
SMM665 HARDWARE MONITOR DRIVER
|
||||||
M: Guenter Roeck <linux@roeck-us.net>
|
M: Guenter Roeck <linux@roeck-us.net>
|
||||||
|
@ -8972,6 +8968,7 @@ SOFTLOGIC 6x10 MPEG CODEC
|
||||||
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
|
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
|
||||||
M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
|
M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
|
||||||
M: Andrey Utkin <andrey.krieger.utkin@gmail.com>
|
M: Andrey Utkin <andrey.krieger.utkin@gmail.com>
|
||||||
|
M: Ismael Luceno <ismael@iodev.co.uk>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/media/pci/solo6x10/
|
F: drivers/media/pci/solo6x10/
|
||||||
|
|
|
@ -8,10 +8,6 @@ comment "common driver options"
|
||||||
config VIDEO_CX2341X
|
config VIDEO_CX2341X
|
||||||
tristate
|
tristate
|
||||||
|
|
||||||
config VIDEO_BTCX
|
|
||||||
depends on PCI
|
|
||||||
tristate
|
|
||||||
|
|
||||||
config VIDEO_TVEEPROM
|
config VIDEO_TVEEPROM
|
||||||
tristate
|
tristate
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
obj-y += b2c2/ saa7146/ siano/
|
obj-y += b2c2/ saa7146/ siano/
|
||||||
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
||||||
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
|
|
||||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
||||||
obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o
|
obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o
|
||||||
|
|
|
@ -26,9 +26,3 @@ void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
|
||||||
void btcx_calc_skips(int line, int width, int *maxy,
|
void btcx_calc_skips(int line, int width, int *maxy,
|
||||||
struct btcx_skiplist *skips, unsigned int *nskips,
|
struct btcx_skiplist *skips, unsigned int *nskips,
|
||||||
const struct v4l2_clip *clips, unsigned int nclips);
|
const struct v4l2_clip *clips, unsigned int nclips);
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -68,13 +68,6 @@
|
||||||
#include "dvb_demux.h"
|
#include "dvb_demux.h"
|
||||||
#include "dvb_net.h"
|
#include "dvb_net.h"
|
||||||
|
|
||||||
static int dvb_net_debug;
|
|
||||||
module_param(dvb_net_debug, int, 0444);
|
|
||||||
MODULE_PARM_DESC(dvb_net_debug, "enable debug messages");
|
|
||||||
|
|
||||||
#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0)
|
|
||||||
|
|
||||||
|
|
||||||
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
||||||
{
|
{
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
@ -90,36 +83,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
||||||
|
|
||||||
#ifdef ULE_DEBUG
|
#ifdef ULE_DEBUG
|
||||||
|
|
||||||
#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
|
static void hexdump(const unsigned char *buf, unsigned short len)
|
||||||
#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
|
|
||||||
|
|
||||||
#define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
|
|
||||||
|
|
||||||
static void hexdump( const unsigned char *buf, unsigned short len )
|
|
||||||
{
|
{
|
||||||
char str[80], octet[10];
|
print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
|
||||||
int ofs, i, l;
|
|
||||||
|
|
||||||
for (ofs = 0; ofs < len; ofs += 16) {
|
|
||||||
sprintf( str, "%03d: ", ofs );
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
if ((i + ofs) < len)
|
|
||||||
sprintf( octet, "%02x ", buf[ofs + i] );
|
|
||||||
else
|
|
||||||
strcpy( octet, " " );
|
|
||||||
|
|
||||||
strcat( str, octet );
|
|
||||||
}
|
|
||||||
strcat( str, " " );
|
|
||||||
l = strlen( str );
|
|
||||||
|
|
||||||
for (i = 0; (i < 16) && ((i + ofs) < len); i++)
|
|
||||||
str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.';
|
|
||||||
|
|
||||||
str[l] = '\0';
|
|
||||||
printk( KERN_WARNING "%s\n", str );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -315,9 +281,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
|
||||||
return l; /* Stop extension header processing and discard SNDU. */
|
return l; /* Stop extension header processing and discard SNDU. */
|
||||||
total_ext_len += l;
|
total_ext_len += l;
|
||||||
#ifdef ULE_DEBUG
|
#ifdef ULE_DEBUG
|
||||||
dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
|
pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n",
|
||||||
"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
|
p->ule_next_hdr, (int)p->ule_sndu_type,
|
||||||
(int) p->ule_sndu_type, l, total_ext_len);
|
l, total_ext_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} while (p->ule_sndu_type < ETH_P_802_3_MIN);
|
} while (p->ule_sndu_type < ETH_P_802_3_MIN);
|
||||||
|
@ -700,8 +666,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
|
||||||
|
|
||||||
if (drop) {
|
if (drop) {
|
||||||
#ifdef ULE_DEBUG
|
#ifdef ULE_DEBUG
|
||||||
dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
|
netdev_dbg(dev, "Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n",
|
||||||
MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
|
priv->ule_skb->data, dev->dev_addr);
|
||||||
#endif
|
#endif
|
||||||
dev_kfree_skb(priv->ule_skb);
|
dev_kfree_skb(priv->ule_skb);
|
||||||
goto sndu_done;
|
goto sndu_done;
|
||||||
|
@ -964,8 +930,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev,
|
||||||
(*secfilter)->filter_mask[10] = mac_mask[1];
|
(*secfilter)->filter_mask[10] = mac_mask[1];
|
||||||
(*secfilter)->filter_mask[11]=mac_mask[0];
|
(*secfilter)->filter_mask[11]=mac_mask[0];
|
||||||
|
|
||||||
dprintk("%s: filter mac=%pM\n", dev->name, mac);
|
netdev_dbg(dev, "filter mac=%pM mask=%pM\n", mac, mac_mask);
|
||||||
dprintk("%s: filter mask=%pM\n", dev->name, mac_mask);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -977,7 +942,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||||
struct dmx_demux *demux = priv->demux;
|
struct dmx_demux *demux = priv->demux;
|
||||||
unsigned char *mac = (unsigned char *) dev->dev_addr;
|
unsigned char *mac = (unsigned char *) dev->dev_addr;
|
||||||
|
|
||||||
dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
|
netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
|
if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
|
||||||
printk("%s: BUG %d\n", __func__, __LINE__);
|
printk("%s: BUG %d\n", __func__, __LINE__);
|
||||||
|
@ -987,7 +952,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||||
priv->tsfeed = NULL;
|
priv->tsfeed = NULL;
|
||||||
|
|
||||||
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
|
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
|
||||||
dprintk("%s: alloc secfeed\n", __func__);
|
netdev_dbg(dev, "alloc secfeed\n");
|
||||||
ret=demux->allocate_section_feed(demux, &priv->secfeed,
|
ret=demux->allocate_section_feed(demux, &priv->secfeed,
|
||||||
dvb_net_sec_callback);
|
dvb_net_sec_callback);
|
||||||
if (ret<0) {
|
if (ret<0) {
|
||||||
|
@ -1005,38 +970,38 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->rx_mode != RX_MODE_PROMISC) {
|
if (priv->rx_mode != RX_MODE_PROMISC) {
|
||||||
dprintk("%s: set secfilter\n", __func__);
|
netdev_dbg(dev, "set secfilter\n");
|
||||||
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
|
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (priv->rx_mode) {
|
switch (priv->rx_mode) {
|
||||||
case RX_MODE_MULTI:
|
case RX_MODE_MULTI:
|
||||||
for (i = 0; i < priv->multi_num; i++) {
|
for (i = 0; i < priv->multi_num; i++) {
|
||||||
dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
|
netdev_dbg(dev, "set multi_secfilter[%d]\n", i);
|
||||||
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
|
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
|
||||||
priv->multi_macs[i], mask_normal);
|
priv->multi_macs[i], mask_normal);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RX_MODE_ALL_MULTI:
|
case RX_MODE_ALL_MULTI:
|
||||||
priv->multi_num=1;
|
priv->multi_num=1;
|
||||||
dprintk("%s: set multi_secfilter[0]\n", __func__);
|
netdev_dbg(dev, "set multi_secfilter[0]\n");
|
||||||
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
|
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
|
||||||
mac_allmulti, mask_allmulti);
|
mac_allmulti, mask_allmulti);
|
||||||
break;
|
break;
|
||||||
case RX_MODE_PROMISC:
|
case RX_MODE_PROMISC:
|
||||||
priv->multi_num=0;
|
priv->multi_num=0;
|
||||||
dprintk("%s: set secfilter\n", __func__);
|
netdev_dbg(dev, "set secfilter\n");
|
||||||
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
|
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintk("%s: start filtering\n", __func__);
|
netdev_dbg(dev, "start filtering\n");
|
||||||
priv->secfeed->start_filtering(priv->secfeed);
|
priv->secfeed->start_filtering(priv->secfeed);
|
||||||
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
|
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
|
||||||
struct timespec timeout = { 0, 10000000 }; // 10 msec
|
struct timespec timeout = { 0, 10000000 }; // 10 msec
|
||||||
|
|
||||||
/* we have payloads encapsulated in TS */
|
/* we have payloads encapsulated in TS */
|
||||||
dprintk("%s: alloc tsfeed\n", __func__);
|
netdev_dbg(dev, "alloc tsfeed\n");
|
||||||
ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
|
ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk("%s: could not allocate ts feed\n", dev->name);
|
printk("%s: could not allocate ts feed\n", dev->name);
|
||||||
|
@ -1060,7 +1025,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintk("%s: start filtering\n", __func__);
|
netdev_dbg(dev, "start filtering\n");
|
||||||
priv->tsfeed->start_filtering(priv->tsfeed);
|
priv->tsfeed->start_filtering(priv->tsfeed);
|
||||||
} else
|
} else
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -1075,17 +1040,16 @@ static int dvb_net_feed_stop(struct net_device *dev)
|
||||||
struct dvb_net_priv *priv = netdev_priv(dev);
|
struct dvb_net_priv *priv = netdev_priv(dev);
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
|
||||||
dprintk("%s\n", __func__);
|
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
|
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
|
||||||
if (priv->secfeed) {
|
if (priv->secfeed) {
|
||||||
if (priv->secfeed->is_filtering) {
|
if (priv->secfeed->is_filtering) {
|
||||||
dprintk("%s: stop secfeed\n", __func__);
|
netdev_dbg(dev, "stop secfeed\n");
|
||||||
priv->secfeed->stop_filtering(priv->secfeed);
|
priv->secfeed->stop_filtering(priv->secfeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->secfilter) {
|
if (priv->secfilter) {
|
||||||
dprintk("%s: release secfilter\n", __func__);
|
netdev_dbg(dev, "release secfilter\n");
|
||||||
priv->secfeed->release_filter(priv->secfeed,
|
priv->secfeed->release_filter(priv->secfeed,
|
||||||
priv->secfilter);
|
priv->secfilter);
|
||||||
priv->secfilter=NULL;
|
priv->secfilter=NULL;
|
||||||
|
@ -1093,8 +1057,8 @@ static int dvb_net_feed_stop(struct net_device *dev)
|
||||||
|
|
||||||
for (i=0; i<priv->multi_num; i++) {
|
for (i=0; i<priv->multi_num; i++) {
|
||||||
if (priv->multi_secfilter[i]) {
|
if (priv->multi_secfilter[i]) {
|
||||||
dprintk("%s: release multi_filter[%d]\n",
|
netdev_dbg(dev, "release multi_filter[%d]\n",
|
||||||
__func__, i);
|
i);
|
||||||
priv->secfeed->release_filter(priv->secfeed,
|
priv->secfeed->release_filter(priv->secfeed,
|
||||||
priv->multi_secfilter[i]);
|
priv->multi_secfilter[i]);
|
||||||
priv->multi_secfilter[i] = NULL;
|
priv->multi_secfilter[i] = NULL;
|
||||||
|
@ -1108,7 +1072,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
|
||||||
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
|
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
|
||||||
if (priv->tsfeed) {
|
if (priv->tsfeed) {
|
||||||
if (priv->tsfeed->is_filtering) {
|
if (priv->tsfeed->is_filtering) {
|
||||||
dprintk("%s: stop tsfeed\n", __func__);
|
netdev_dbg(dev, "stop tsfeed\n");
|
||||||
priv->tsfeed->stop_filtering(priv->tsfeed);
|
priv->tsfeed->stop_filtering(priv->tsfeed);
|
||||||
}
|
}
|
||||||
priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
|
priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
|
||||||
|
@ -1148,16 +1112,16 @@ static void wq_set_multicast_list (struct work_struct *work)
|
||||||
netif_addr_lock_bh(dev);
|
netif_addr_lock_bh(dev);
|
||||||
|
|
||||||
if (dev->flags & IFF_PROMISC) {
|
if (dev->flags & IFF_PROMISC) {
|
||||||
dprintk("%s: promiscuous mode\n", dev->name);
|
netdev_dbg(dev, "promiscuous mode\n");
|
||||||
priv->rx_mode = RX_MODE_PROMISC;
|
priv->rx_mode = RX_MODE_PROMISC;
|
||||||
} else if ((dev->flags & IFF_ALLMULTI)) {
|
} else if ((dev->flags & IFF_ALLMULTI)) {
|
||||||
dprintk("%s: allmulti mode\n", dev->name);
|
netdev_dbg(dev, "allmulti mode\n");
|
||||||
priv->rx_mode = RX_MODE_ALL_MULTI;
|
priv->rx_mode = RX_MODE_ALL_MULTI;
|
||||||
} else if (!netdev_mc_empty(dev)) {
|
} else if (!netdev_mc_empty(dev)) {
|
||||||
struct netdev_hw_addr *ha;
|
struct netdev_hw_addr *ha;
|
||||||
|
|
||||||
dprintk("%s: set_mc_list, %d entries\n",
|
netdev_dbg(dev, "set_mc_list, %d entries\n",
|
||||||
dev->name, netdev_mc_count(dev));
|
netdev_mc_count(dev));
|
||||||
|
|
||||||
priv->rx_mode = RX_MODE_MULTI;
|
priv->rx_mode = RX_MODE_MULTI;
|
||||||
priv->multi_num = 0;
|
priv->multi_num = 0;
|
||||||
|
|
|
@ -443,7 +443,8 @@ config DVB_CXD2820R
|
||||||
|
|
||||||
config DVB_RTL2830
|
config DVB_RTL2830
|
||||||
tristate "Realtek RTL2830 DVB-T"
|
tristate "Realtek RTL2830 DVB-T"
|
||||||
depends on DVB_CORE && I2C
|
depends on DVB_CORE && I2C && I2C_MUX
|
||||||
|
select REGMAP
|
||||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||||
help
|
help
|
||||||
Say Y when you want to support this frontend.
|
Say Y when you want to support this frontend.
|
||||||
|
@ -451,6 +452,7 @@ config DVB_RTL2830
|
||||||
config DVB_RTL2832
|
config DVB_RTL2832
|
||||||
tristate "Realtek RTL2832 DVB-T"
|
tristate "Realtek RTL2832 DVB-T"
|
||||||
depends on DVB_CORE && I2C && I2C_MUX
|
depends on DVB_CORE && I2C && I2C_MUX
|
||||||
|
select REGMAP
|
||||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||||
help
|
help
|
||||||
Say Y when you want to support this frontend.
|
Say Y when you want to support this frontend.
|
||||||
|
|
|
@ -91,8 +91,3 @@ enum au8522_audio_input {
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AU8522_H__ */
|
#endif /* __AU8522_H__ */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1263,7 +1263,8 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
|
||||||
struct dib8000_state *state = fe->demodulator_priv;
|
struct dib8000_state *state = fe->demodulator_priv;
|
||||||
enum frontend_tune_state *tune_state = &state->tune_state;
|
enum frontend_tune_state *tune_state = &state->tune_state;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u16 reg, upd_demod_gain_period = 0x8000;
|
u16 reg;
|
||||||
|
u32 upd_demod_gain_period = 0x8000;
|
||||||
|
|
||||||
switch (*tune_state) {
|
switch (*tune_state) {
|
||||||
case CT_AGC_START:
|
case CT_AGC_START:
|
||||||
|
|
|
@ -22,20 +22,24 @@
|
||||||
|
|
||||||
#include "hd29l2_priv.h"
|
#include "hd29l2_priv.h"
|
||||||
|
|
||||||
|
#define HD29L2_MAX_LEN (3)
|
||||||
|
|
||||||
/* write multiple registers */
|
/* write multiple registers */
|
||||||
static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
|
static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u8 buf[2 + len];
|
u8 buf[2 + HD29L2_MAX_LEN];
|
||||||
struct i2c_msg msg[1] = {
|
struct i2c_msg msg[1] = {
|
||||||
{
|
{
|
||||||
.addr = priv->cfg.i2c_addr,
|
.addr = priv->cfg.i2c_addr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.len = sizeof(buf),
|
.len = 2 + len,
|
||||||
.buf = buf,
|
.buf = buf,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (len > HD29L2_MAX_LEN)
|
||||||
|
return -EINVAL;
|
||||||
buf[0] = 0x00;
|
buf[0] = 0x00;
|
||||||
buf[1] = reg;
|
buf[1] = reg;
|
||||||
memcpy(&buf[2], val, len);
|
memcpy(&buf[2], val, len);
|
||||||
|
@ -118,7 +122,7 @@ static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read single register with mask */
|
/* read single register with mask */
|
||||||
int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
|
static int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
|
|
|
@ -1456,9 +1456,3 @@ MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
|
||||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION("0.3");
|
MODULE_VERSION("0.3");
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -236,12 +236,13 @@ static inline int lgdt3305_mpeg_mode(struct lgdt3305_state *state,
|
||||||
return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
|
return lgdt3305_set_reg_bit(state, LGDT3305_TP_CTRL_1, 5, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
|
static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state)
|
||||||
enum lgdt3305_tp_clock_edge edge,
|
|
||||||
enum lgdt3305_tp_valid_polarity valid)
|
|
||||||
{
|
{
|
||||||
u8 val;
|
u8 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
enum lgdt3305_tp_clock_edge edge = state->cfg->tpclk_edge;
|
||||||
|
enum lgdt3305_tp_clock_mode mode = state->cfg->tpclk_mode;
|
||||||
|
enum lgdt3305_tp_valid_polarity valid = state->cfg->tpvalid_polarity;
|
||||||
|
|
||||||
lg_dbg("edge = %d, valid = %d\n", edge, valid);
|
lg_dbg("edge = %d, valid = %d\n", edge, valid);
|
||||||
|
|
||||||
|
@ -253,6 +254,8 @@ static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
|
||||||
|
|
||||||
if (edge)
|
if (edge)
|
||||||
val |= 0x08;
|
val |= 0x08;
|
||||||
|
if (mode)
|
||||||
|
val |= 0x40;
|
||||||
if (valid)
|
if (valid)
|
||||||
val |= 0x01;
|
val |= 0x01;
|
||||||
|
|
||||||
|
@ -740,9 +743,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
||||||
ret = lgdt3305_mpeg_mode_polarity(state,
|
ret = lgdt3305_mpeg_mode_polarity(state);
|
||||||
state->cfg->tpclk_edge,
|
|
||||||
state->cfg->tpvalid_polarity);
|
|
||||||
fail:
|
fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -806,9 +807,7 @@ static int lgdt3305_set_parameters(struct dvb_frontend *fe)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
||||||
ret = lgdt3305_mpeg_mode_polarity(state,
|
ret = lgdt3305_mpeg_mode_polarity(state);
|
||||||
state->cfg->tpclk_edge,
|
|
||||||
state->cfg->tpvalid_polarity);
|
|
||||||
fail:
|
fail:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1215,9 +1214,3 @@ MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
|
||||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION("0.2");
|
MODULE_VERSION("0.2");
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -37,6 +37,11 @@ enum lgdt3305_tp_clock_edge {
|
||||||
LGDT3305_TPCLK_FALLING_EDGE = 1,
|
LGDT3305_TPCLK_FALLING_EDGE = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum lgdt3305_tp_clock_mode {
|
||||||
|
LGDT3305_TPCLK_GATED = 0,
|
||||||
|
LGDT3305_TPCLK_FIXED = 1,
|
||||||
|
};
|
||||||
|
|
||||||
enum lgdt3305_tp_valid_polarity {
|
enum lgdt3305_tp_valid_polarity {
|
||||||
LGDT3305_TP_VALID_LOW = 0,
|
LGDT3305_TP_VALID_LOW = 0,
|
||||||
LGDT3305_TP_VALID_HIGH = 1,
|
LGDT3305_TP_VALID_HIGH = 1,
|
||||||
|
@ -70,6 +75,7 @@ struct lgdt3305_config {
|
||||||
|
|
||||||
enum lgdt3305_mpeg_mode mpeg_mode;
|
enum lgdt3305_mpeg_mode mpeg_mode;
|
||||||
enum lgdt3305_tp_clock_edge tpclk_edge;
|
enum lgdt3305_tp_clock_edge tpclk_edge;
|
||||||
|
enum lgdt3305_tp_clock_mode tpclk_mode;
|
||||||
enum lgdt3305_tp_valid_polarity tpvalid_polarity;
|
enum lgdt3305_tp_valid_polarity tpvalid_polarity;
|
||||||
enum lgdt_demod_chip_type demod_chip;
|
enum lgdt_demod_chip_type demod_chip;
|
||||||
};
|
};
|
||||||
|
|
|
@ -823,9 +823,3 @@ MODULE_AUTHOR("Wilson Michaels");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
EXPORT_SYMBOL(lgdt330x_attach);
|
EXPORT_SYMBOL(lgdt330x_attach);
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -65,9 +65,3 @@ static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config*
|
||||||
#endif // CONFIG_DVB_LGDT330X
|
#endif // CONFIG_DVB_LGDT330X
|
||||||
|
|
||||||
#endif /* LGDT330X_H */
|
#endif /* LGDT330X_H */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -69,9 +69,3 @@ enum I2C_REG {
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _LGDT330X_PRIV_ */
|
#endif /* _LGDT330X_PRIV_ */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -22,10 +22,6 @@
|
||||||
|
|
||||||
#define NUM_LAYERS 3
|
#define NUM_LAYERS 3
|
||||||
|
|
||||||
static int debug = 1;
|
|
||||||
module_param(debug, int, 0644);
|
|
||||||
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
|
|
||||||
|
|
||||||
enum mb86a20s_bandwidth {
|
enum mb86a20s_bandwidth {
|
||||||
MB86A20S_13SEG = 0,
|
MB86A20S_13SEG = 0,
|
||||||
MB86A20S_13SEG_PARTIAL = 1,
|
MB86A20S_13SEG_PARTIAL = 1,
|
||||||
|
|
|
@ -33,6 +33,12 @@ struct mn88472_config {
|
||||||
* DVB frontend.
|
* DVB frontend.
|
||||||
*/
|
*/
|
||||||
struct dvb_frontend **fe;
|
struct dvb_frontend **fe;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Xtal frequency.
|
||||||
|
* Hz
|
||||||
|
*/
|
||||||
|
u32 xtal;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -55,9 +55,3 @@ static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* c
|
||||||
#endif // CONFIG_DVB_NXT200X
|
#endif // CONFIG_DVB_NXT200X
|
||||||
|
|
||||||
#endif /* NXT200X_H */
|
#endif /* NXT200X_H */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -623,9 +623,3 @@ MODULE_AUTHOR("Trent Piepho");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
EXPORT_SYMBOL(or51132_attach);
|
EXPORT_SYMBOL(or51132_attach);
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -47,9 +47,3 @@ static inline struct dvb_frontend* or51132_attach(const struct or51132_config* c
|
||||||
#endif // CONFIG_DVB_OR51132
|
#endif // CONFIG_DVB_OR51132
|
||||||
|
|
||||||
#endif // OR51132_H
|
#endif // OR51132_H
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -13,78 +13,37 @@
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* 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 RTL2830_H
|
#ifndef RTL2830_H
|
||||||
#define RTL2830_H
|
#define RTL2830_H
|
||||||
|
|
||||||
#include <linux/kconfig.h>
|
|
||||||
#include <linux/dvb/frontend.h>
|
#include <linux/dvb/frontend.h>
|
||||||
|
|
||||||
struct rtl2830_config {
|
/**
|
||||||
/*
|
* struct rtl2830_platform_data - Platform data for the rtl2830 driver
|
||||||
* Demodulator I2C address.
|
* @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
|
||||||
*/
|
* @spec_inv: Spectrum inversion.
|
||||||
u8 i2c_addr;
|
* @vtop: AGC take-over point.
|
||||||
|
* @krf: AGC ratio.
|
||||||
|
* @agc_targ_val: AGC.
|
||||||
|
* @get_dvb_frontend: Get DVB frontend.
|
||||||
|
* @get_i2c_adapter: Get I2C adapter.
|
||||||
|
* @pid_filter: Set PID to PID filter.
|
||||||
|
* @pid_filter_ctrl: Control PID filter.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
struct rtl2830_platform_data {
|
||||||
* Xtal frequency.
|
u32 clk;
|
||||||
* Hz
|
|
||||||
* 4000000, 16000000, 25000000, 28800000
|
|
||||||
*/
|
|
||||||
u32 xtal;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TS output mode.
|
|
||||||
*/
|
|
||||||
u8 ts_mode;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Spectrum inversion.
|
|
||||||
*/
|
|
||||||
bool spec_inv;
|
bool spec_inv;
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
u8 vtop;
|
u8 vtop;
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
u8 krf;
|
u8 krf;
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
u8 agc_targ_val;
|
u8 agc_targ_val;
|
||||||
|
|
||||||
|
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
|
||||||
|
struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
|
||||||
|
int (*pid_filter)(struct dvb_frontend *, u8, u16, int);
|
||||||
|
int (*pid_filter_ctrl)(struct dvb_frontend *, int);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_DVB_RTL2830)
|
|
||||||
extern struct dvb_frontend *rtl2830_attach(
|
|
||||||
const struct rtl2830_config *config,
|
|
||||||
struct i2c_adapter *i2c
|
|
||||||
);
|
|
||||||
|
|
||||||
extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
static inline struct dvb_frontend *rtl2830_attach(
|
|
||||||
const struct rtl2830_config *config,
|
|
||||||
struct i2c_adapter *i2c
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* RTL2830_H */
|
#endif /* RTL2830_H */
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* 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 RTL2830_PRIV_H
|
#ifndef RTL2830_PRIV_H
|
||||||
|
@ -24,16 +21,23 @@
|
||||||
#include "dvb_frontend.h"
|
#include "dvb_frontend.h"
|
||||||
#include "dvb_math.h"
|
#include "dvb_math.h"
|
||||||
#include "rtl2830.h"
|
#include "rtl2830.h"
|
||||||
|
#include <linux/i2c-mux.h>
|
||||||
|
#include <linux/math64.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
struct rtl2830_priv {
|
struct rtl2830_dev {
|
||||||
struct i2c_adapter *i2c;
|
struct rtl2830_platform_data *pdata;
|
||||||
|
struct i2c_client *client;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct i2c_adapter *adapter;
|
||||||
struct dvb_frontend fe;
|
struct dvb_frontend fe;
|
||||||
struct rtl2830_config cfg;
|
|
||||||
struct i2c_adapter tuner_i2c_adapter;
|
|
||||||
|
|
||||||
bool sleeping;
|
bool sleeping;
|
||||||
|
unsigned long filters;
|
||||||
u8 page; /* active register page */
|
struct delayed_work stat_work;
|
||||||
|
fe_status_t fe_status;
|
||||||
|
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
|
||||||
|
u64 post_bit_error;
|
||||||
|
u64 post_bit_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rtl2830_reg_val_mask {
|
struct rtl2830_reg_val_mask {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@
|
||||||
* Realtek RTL2832 DVB-T demodulator driver
|
* Realtek RTL2832 DVB-T demodulator driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
||||||
|
* Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,86 +22,42 @@
|
||||||
#ifndef RTL2832_H
|
#ifndef RTL2832_H
|
||||||
#define RTL2832_H
|
#define RTL2832_H
|
||||||
|
|
||||||
#include <linux/kconfig.h>
|
|
||||||
#include <linux/dvb/frontend.h>
|
#include <linux/dvb/frontend.h>
|
||||||
|
#include <linux/i2c-mux.h>
|
||||||
|
|
||||||
struct rtl2832_config {
|
/**
|
||||||
/*
|
* struct rtl2832_platform_data - Platform data for the rtl2832 driver
|
||||||
* Demodulator I2C address.
|
* @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
|
||||||
*/
|
* @tuner: Used tuner model.
|
||||||
u8 i2c_addr;
|
* @get_dvb_frontend: Get DVB frontend.
|
||||||
|
* @get_i2c_adapter: Get I2C adapter.
|
||||||
|
* @enable_slave_ts: Enable slave TS IF.
|
||||||
|
* @pid_filter: Set PID to PID filter.
|
||||||
|
* @pid_filter_ctrl: Control PID filter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct rtl2832_platform_data {
|
||||||
|
u32 clk;
|
||||||
/*
|
/*
|
||||||
* Xtal frequency.
|
* XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
|
||||||
* Hz
|
|
||||||
* 4000000, 16000000, 25000000, 28800000
|
|
||||||
*/
|
|
||||||
u32 xtal;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* tuner
|
|
||||||
* XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver.
|
|
||||||
*/
|
*/
|
||||||
#define RTL2832_TUNER_TUA9001 0x24
|
#define RTL2832_TUNER_TUA9001 0x24
|
||||||
#define RTL2832_TUNER_FC0012 0x26
|
#define RTL2832_TUNER_FC0012 0x26
|
||||||
#define RTL2832_TUNER_E4000 0x27
|
#define RTL2832_TUNER_E4000 0x27
|
||||||
#define RTL2832_TUNER_FC0013 0x29
|
#define RTL2832_TUNER_FC0013 0x29
|
||||||
#define RTL2832_TUNER_R820T 0x2a
|
#define RTL2832_TUNER_R820T 0x2a
|
||||||
#define RTL2832_TUNER_R828D 0x2b
|
#define RTL2832_TUNER_R828D 0x2b
|
||||||
u8 tuner;
|
u8 tuner;
|
||||||
|
|
||||||
|
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
|
||||||
|
struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
|
||||||
|
int (*enable_slave_ts)(struct i2c_client *);
|
||||||
|
int (*pid_filter)(struct dvb_frontend *, u8, u16, int);
|
||||||
|
int (*pid_filter_ctrl)(struct dvb_frontend *, int);
|
||||||
|
/* private: Register access for SDR module use only */
|
||||||
|
int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t);
|
||||||
|
int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t);
|
||||||
|
int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_DVB_RTL2832)
|
|
||||||
struct dvb_frontend *rtl2832_attach(
|
|
||||||
const struct rtl2832_config *cfg,
|
|
||||||
struct i2c_adapter *i2c
|
|
||||||
);
|
|
||||||
|
|
||||||
extern struct i2c_adapter *rtl2832_get_i2c_adapter(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
);
|
|
||||||
|
|
||||||
extern struct i2c_adapter *rtl2832_get_private_i2c_adapter(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
);
|
|
||||||
|
|
||||||
extern int rtl2832_enable_external_ts_if(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static inline struct dvb_frontend *rtl2832_attach(
|
|
||||||
const struct rtl2832_config *config,
|
|
||||||
struct i2c_adapter *i2c
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pr_warn("%s: driver disabled by Kconfig\n", __func__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct i2c_adapter *rtl2832_get_i2c_adapter(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct i2c_adapter *rtl2832_get_private_i2c_adapter(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int rtl2832_enable_external_ts_if(
|
|
||||||
struct dvb_frontend *fe
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* RTL2832_H */
|
#endif /* RTL2832_H */
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* Realtek RTL2832 DVB-T demodulator driver
|
* Realtek RTL2832 DVB-T demodulator driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
||||||
|
* Copyright (C) 2012-2014 Antti Palosaari <crope@iki.fi>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,28 +22,34 @@
|
||||||
#ifndef RTL2832_PRIV_H
|
#ifndef RTL2832_PRIV_H
|
||||||
#define RTL2832_PRIV_H
|
#define RTL2832_PRIV_H
|
||||||
|
|
||||||
#include "dvb_frontend.h"
|
#include <linux/regmap.h>
|
||||||
#include "rtl2832.h"
|
#include <linux/math64.h>
|
||||||
#include <linux/i2c-mux.h>
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
struct rtl2832_priv {
|
#include "dvb_frontend.h"
|
||||||
struct i2c_adapter *i2c;
|
#include "dvb_math.h"
|
||||||
struct i2c_adapter *i2c_adapter;
|
#include "rtl2832.h"
|
||||||
|
|
||||||
|
struct rtl2832_dev {
|
||||||
|
struct rtl2832_platform_data *pdata;
|
||||||
|
struct i2c_client *client;
|
||||||
|
struct mutex regmap_mutex;
|
||||||
|
struct regmap_config regmap_config;
|
||||||
|
struct regmap *regmap;
|
||||||
struct i2c_adapter *i2c_adapter_tuner;
|
struct i2c_adapter *i2c_adapter_tuner;
|
||||||
struct dvb_frontend fe;
|
struct dvb_frontend fe;
|
||||||
struct rtl2832_config cfg;
|
struct delayed_work stat_work;
|
||||||
|
fe_status_t fe_status;
|
||||||
bool i2c_gate_state;
|
u64 post_bit_error_prev; /* for old DVBv3 read_ber() calculation */
|
||||||
|
u64 post_bit_error;
|
||||||
|
u64 post_bit_count;
|
||||||
bool sleeping;
|
bool sleeping;
|
||||||
|
|
||||||
u8 tuner;
|
|
||||||
u8 page; /* active register page */
|
|
||||||
struct delayed_work i2c_gate_work;
|
struct delayed_work i2c_gate_work;
|
||||||
|
unsigned long filters; /* PID filter */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rtl2832_reg_entry {
|
struct rtl2832_reg_entry {
|
||||||
u8 page;
|
u16 start_address;
|
||||||
u8 start_address;
|
|
||||||
u8 msb;
|
u8 msb;
|
||||||
u8 lsb;
|
u8 lsb;
|
||||||
};
|
};
|
||||||
|
@ -52,7 +59,6 @@ struct rtl2832_reg_value {
|
||||||
u32 value;
|
u32 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Demod register bit names */
|
/* Demod register bit names */
|
||||||
enum DVBT_REG_BIT_NAME {
|
enum DVBT_REG_BIT_NAME {
|
||||||
DVBT_SOFT_RST,
|
DVBT_SOFT_RST,
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,35 +20,48 @@
|
||||||
* GNU Radio plugin "gr-kernel" for device usage will be on:
|
* GNU Radio plugin "gr-kernel" for device usage will be on:
|
||||||
* http://git.linuxtv.org/anttip/gr-kernel.git
|
* http://git.linuxtv.org/anttip/gr-kernel.git
|
||||||
*
|
*
|
||||||
* TODO:
|
|
||||||
* Help is very highly welcome for these + all the others you could imagine:
|
|
||||||
* - move controls to V4L2 API
|
|
||||||
* - use libv4l2 for stream format conversions
|
|
||||||
* - gr-kernel: switch to v4l2_mmap (current read eats a lot of cpu)
|
|
||||||
* - SDRSharp support
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RTL2832_SDR_H
|
#ifndef RTL2832_SDR_H
|
||||||
#define RTL2832_SDR_H
|
#define RTL2832_SDR_H
|
||||||
|
|
||||||
#include <linux/kconfig.h>
|
#include <linux/i2c.h>
|
||||||
#include <media/v4l2-subdev.h>
|
#include <media/v4l2-subdev.h>
|
||||||
|
#include "dvb_frontend.h"
|
||||||
|
|
||||||
/* for config struct */
|
/**
|
||||||
#include "rtl2832.h"
|
* struct rtl2832_sdr_platform_data - Platform data for the rtl2832_sdr driver
|
||||||
|
* @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
|
||||||
|
* @tuner: Used tuner model.
|
||||||
|
* @i2c_client: rtl2832 demod driver I2C client.
|
||||||
|
* @bulk_read: rtl2832 driver private I/O interface.
|
||||||
|
* @bulk_write: rtl2832 driver private I/O interface.
|
||||||
|
* @update_bits: rtl2832 driver private I/O interface.
|
||||||
|
* @dvb_frontend: rtl2832 DVB frontend.
|
||||||
|
* @v4l2_subdev: Tuner v4l2 controls.
|
||||||
|
* @dvb_usb_device: DVB USB interface for USB streaming.
|
||||||
|
*/
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
|
struct rtl2832_sdr_platform_data {
|
||||||
extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
u32 clk;
|
||||||
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
|
/*
|
||||||
struct v4l2_subdev *sd);
|
* XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
|
||||||
#else
|
*/
|
||||||
static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
#define RTL2832_SDR_TUNER_TUA9001 0x24
|
||||||
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
|
#define RTL2832_SDR_TUNER_FC0012 0x26
|
||||||
struct v4l2_subdev *sd)
|
#define RTL2832_SDR_TUNER_E4000 0x27
|
||||||
{
|
#define RTL2832_SDR_TUNER_FC0013 0x29
|
||||||
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
|
#define RTL2832_SDR_TUNER_R820T 0x2a
|
||||||
return NULL;
|
#define RTL2832_SDR_TUNER_R828D 0x2b
|
||||||
}
|
u8 tuner;
|
||||||
#endif
|
|
||||||
|
struct i2c_client *i2c_client;
|
||||||
|
int (*bulk_read)(struct i2c_client *, unsigned int, void *, size_t);
|
||||||
|
int (*bulk_write)(struct i2c_client *, unsigned int, const void *, size_t);
|
||||||
|
int (*update_bits)(struct i2c_client *, unsigned int, unsigned int, unsigned int);
|
||||||
|
struct dvb_frontend *dvb_frontend;
|
||||||
|
struct v4l2_subdev *v4l2_subdev;
|
||||||
|
struct dvb_usb_device *dvb_usb_device;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* RTL2832_SDR_H */
|
#endif /* RTL2832_SDR_H */
|
||||||
|
|
|
@ -1021,9 +1021,3 @@ static struct dvb_frontend_ops s5h1409_ops = {
|
||||||
MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
|
MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
|
||||||
MODULE_AUTHOR("Steven Toth");
|
MODULE_AUTHOR("Steven Toth");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
*/
|
|
||||||
|
|
|
@ -81,8 +81,3 @@ static inline struct dvb_frontend *s5h1409_attach(
|
||||||
#endif /* CONFIG_DVB_S5H1409 */
|
#endif /* CONFIG_DVB_S5H1409 */
|
||||||
|
|
||||||
#endif /* __S5H1409_H__ */
|
#endif /* __S5H1409_H__ */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
*/
|
|
||||||
|
|
|
@ -944,8 +944,3 @@ MODULE_PARM_DESC(debug, "Enable verbose debug messages");
|
||||||
MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
|
MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
|
||||||
MODULE_AUTHOR("Steven Toth");
|
MODULE_AUTHOR("Steven Toth");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
*/
|
|
||||||
|
|
|
@ -83,8 +83,3 @@ static inline struct dvb_frontend *s5h1411_attach(
|
||||||
#endif /* CONFIG_DVB_S5H1411 */
|
#endif /* CONFIG_DVB_S5H1411 */
|
||||||
|
|
||||||
#endif /* __S5H1411_H__ */
|
#endif /* __S5H1411_H__ */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
*/
|
|
||||||
|
|
|
@ -19,16 +19,17 @@
|
||||||
static const struct dvb_frontend_ops si2168_ops;
|
static const struct dvb_frontend_ops si2168_ops;
|
||||||
|
|
||||||
/* execute firmware command */
|
/* execute firmware command */
|
||||||
static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd *cmd)
|
||||||
{
|
{
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
mutex_lock(&s->i2c_mutex);
|
mutex_lock(&dev->i2c_mutex);
|
||||||
|
|
||||||
if (cmd->wlen) {
|
if (cmd->wlen) {
|
||||||
/* write cmd and args for firmware */
|
/* write cmd and args for firmware */
|
||||||
ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
|
ret = i2c_master_send(client, cmd->args, cmd->wlen);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto err_mutex_unlock;
|
goto err_mutex_unlock;
|
||||||
} else if (ret != cmd->wlen) {
|
} else if (ret != cmd->wlen) {
|
||||||
|
@ -39,10 +40,10 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
||||||
|
|
||||||
if (cmd->rlen) {
|
if (cmd->rlen) {
|
||||||
/* wait cmd execution terminate */
|
/* wait cmd execution terminate */
|
||||||
#define TIMEOUT 50
|
#define TIMEOUT 70
|
||||||
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
|
timeout = jiffies + msecs_to_jiffies(TIMEOUT);
|
||||||
while (!time_after(jiffies, timeout)) {
|
while (!time_after(jiffies, timeout)) {
|
||||||
ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
|
ret = i2c_master_recv(client, cmd->args, cmd->rlen);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto err_mutex_unlock;
|
goto err_mutex_unlock;
|
||||||
} else if (ret != cmd->rlen) {
|
} else if (ret != cmd->rlen) {
|
||||||
|
@ -55,7 +56,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&s->client->dev, "cmd execution took %d ms\n",
|
dev_dbg(&client->dev, "cmd execution took %d ms\n",
|
||||||
jiffies_to_msecs(jiffies) -
|
jiffies_to_msecs(jiffies) -
|
||||||
(jiffies_to_msecs(timeout) - TIMEOUT));
|
(jiffies_to_msecs(timeout) - TIMEOUT));
|
||||||
|
|
||||||
|
@ -65,29 +66,26 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
mutex_unlock(&dev->i2c_mutex);
|
||||||
|
return 0;
|
||||||
|
|
||||||
err_mutex_unlock:
|
err_mutex_unlock:
|
||||||
mutex_unlock(&s->i2c_mutex);
|
mutex_unlock(&dev->i2c_mutex);
|
||||||
if (ret)
|
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||||
goto err;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
err:
|
|
||||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
{
|
{
|
||||||
struct si2168 *s = fe->demodulator_priv;
|
struct i2c_client *client = fe->demodulator_priv;
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
int ret;
|
int ret;
|
||||||
struct si2168_cmd cmd;
|
struct si2168_cmd cmd;
|
||||||
|
|
||||||
*status = 0;
|
*status = 0;
|
||||||
|
|
||||||
if (!s->active) {
|
if (!dev->active) {
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -113,21 +111,10 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/*
|
|
||||||
* Possible values seen, in order from strong signal to weak:
|
|
||||||
* 16 0001 0110 full lock
|
|
||||||
* 1e 0001 1110 partial lock
|
|
||||||
* 1a 0001 1010 partial lock
|
|
||||||
* 18 0001 1000 no lock
|
|
||||||
*
|
|
||||||
* [b3:b1] lock bits
|
|
||||||
* [b4] statistics ready? Set in a few secs after lock is gained.
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch ((cmd.args[2] >> 1) & 0x03) {
|
switch ((cmd.args[2] >> 1) & 0x03) {
|
||||||
case 0x01:
|
case 0x01:
|
||||||
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||||
|
@ -138,7 +125,7 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->fe_status = *status;
|
dev->fe_status = *status;
|
||||||
|
|
||||||
if (*status & FE_HAS_LOCK) {
|
if (*status & FE_HAS_LOCK) {
|
||||||
c->cnr.len = 1;
|
c->cnr.len = 1;
|
||||||
|
@ -149,30 +136,31 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&s->client->dev, "status=%02x args=%*ph\n",
|
dev_dbg(&client->dev, "status=%02x args=%*ph\n",
|
||||||
*status, cmd.rlen, cmd.args);
|
*status, cmd.rlen, cmd.args);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int si2168_set_frontend(struct dvb_frontend *fe)
|
static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct si2168 *s = fe->demodulator_priv;
|
struct i2c_client *client = fe->demodulator_priv;
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
int ret;
|
int ret;
|
||||||
struct si2168_cmd cmd;
|
struct si2168_cmd cmd;
|
||||||
u8 bandwidth, delivery_system;
|
u8 bandwidth, delivery_system;
|
||||||
|
|
||||||
dev_dbg(&s->client->dev,
|
dev_dbg(&client->dev,
|
||||||
"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n",
|
"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u stream_id=%u\n",
|
||||||
c->delivery_system, c->modulation,
|
c->delivery_system, c->modulation, c->frequency,
|
||||||
c->frequency, c->bandwidth_hz, c->symbol_rate,
|
c->bandwidth_hz, c->symbol_rate, c->inversion,
|
||||||
c->inversion, c->stream_id);
|
c->stream_id);
|
||||||
|
|
||||||
if (!s->active) {
|
if (!dev->active) {
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +180,12 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->bandwidth_hz <= 5000000)
|
if (c->bandwidth_hz == 0) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
} else if (c->bandwidth_hz <= 2000000)
|
||||||
|
bandwidth = 0x02;
|
||||||
|
else if (c->bandwidth_hz <= 5000000)
|
||||||
bandwidth = 0x05;
|
bandwidth = 0x05;
|
||||||
else if (c->bandwidth_hz <= 6000000)
|
else if (c->bandwidth_hz <= 6000000)
|
||||||
bandwidth = 0x06;
|
bandwidth = 0x06;
|
||||||
|
@ -217,7 +210,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
|
memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
|
||||||
cmd.wlen = 5;
|
cmd.wlen = 5;
|
||||||
cmd.rlen = 5;
|
cmd.rlen = 5;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -230,7 +223,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
|
memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 3;
|
cmd.rlen = 3;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -241,7 +234,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
|
cmd.args[2] = c->stream_id == NO_STREAM_ID_FILTER ? 0 : 1;
|
||||||
cmd.wlen = 3;
|
cmd.wlen = 3;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -249,35 +242,35 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\x51\x03", 2);
|
memcpy(cmd.args, "\x51\x03", 2);
|
||||||
cmd.wlen = 2;
|
cmd.wlen = 2;
|
||||||
cmd.rlen = 12;
|
cmd.rlen = 12;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x12\x08\x04", 3);
|
memcpy(cmd.args, "\x12\x08\x04", 3);
|
||||||
cmd.wlen = 3;
|
cmd.wlen = 3;
|
||||||
cmd.rlen = 3;
|
cmd.rlen = 3;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
|
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
|
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
|
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -285,18 +278,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
cmd.args[4] = delivery_system | bandwidth;
|
cmd.args[4] = delivery_system | bandwidth;
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* set DVB-C symbol rate */
|
/* set DVB-C symbol rate */
|
||||||
if (c->delivery_system == SYS_DVBC_ANNEX_A) {
|
if (c->delivery_system == SYS_DVBC_ANNEX_A) {
|
||||||
memcpy(cmd.args, "\x14\x00\x02\x11", 4);
|
memcpy(cmd.args, "\x14\x00\x02\x11", 4);
|
||||||
cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
|
cmd.args[4] = ((c->symbol_rate / 1000) >> 0) & 0xff;
|
||||||
cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -304,88 +297,88 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
|
memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6);
|
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6);
|
||||||
cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
|
cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6);
|
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6);
|
||||||
cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
|
cmd.args[5] |= dev->ts_clock_inv ? 0x00 : 0x10;
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
|
memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
|
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x85", 1);
|
memcpy(cmd.args, "\x85", 1);
|
||||||
cmd.wlen = 1;
|
cmd.wlen = 1;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
s->delivery_system = c->delivery_system;
|
dev->delivery_system = c->delivery_system;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int si2168_init(struct dvb_frontend *fe)
|
static int si2168_init(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct si2168 *s = fe->demodulator_priv;
|
struct i2c_client *client = fe->demodulator_priv;
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
int ret, len, remaining;
|
int ret, len, remaining;
|
||||||
const struct firmware *fw = NULL;
|
const struct firmware *fw;
|
||||||
u8 *fw_file;
|
const char *fw_name;
|
||||||
const unsigned int i2c_wr_max = 8;
|
|
||||||
struct si2168_cmd cmd;
|
struct si2168_cmd cmd;
|
||||||
unsigned int chip_id;
|
unsigned int chip_id;
|
||||||
|
|
||||||
dev_dbg(&s->client->dev, "\n");
|
dev_dbg(&client->dev, "\n");
|
||||||
|
|
||||||
/* initialize */
|
/* initialize */
|
||||||
memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
|
memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
|
||||||
cmd.wlen = 13;
|
cmd.wlen = 13;
|
||||||
cmd.rlen = 0;
|
cmd.rlen = 0;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (s->fw_loaded) {
|
if (dev->fw_loaded) {
|
||||||
/* resume */
|
/* resume */
|
||||||
memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
|
memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
|
||||||
cmd.wlen = 8;
|
cmd.wlen = 8;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x85", 1);
|
memcpy(cmd.args, "\x85", 1);
|
||||||
cmd.wlen = 1;
|
cmd.wlen = 1;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -396,7 +389,7 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
|
memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
|
||||||
cmd.wlen = 8;
|
cmd.wlen = 8;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -404,7 +397,7 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\x02", 1);
|
memcpy(cmd.args, "\x02", 1);
|
||||||
cmd.wlen = 1;
|
cmd.wlen = 1;
|
||||||
cmd.rlen = 13;
|
cmd.rlen = 13;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -417,50 +410,48 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||||
|
|
||||||
switch (chip_id) {
|
switch (chip_id) {
|
||||||
case SI2168_A20:
|
case SI2168_A20:
|
||||||
fw_file = SI2168_A20_FIRMWARE;
|
fw_name = SI2168_A20_FIRMWARE;
|
||||||
break;
|
break;
|
||||||
case SI2168_A30:
|
case SI2168_A30:
|
||||||
fw_file = SI2168_A30_FIRMWARE;
|
fw_name = SI2168_A30_FIRMWARE;
|
||||||
break;
|
break;
|
||||||
case SI2168_B40:
|
case SI2168_B40:
|
||||||
fw_file = SI2168_B40_FIRMWARE;
|
fw_name = SI2168_B40_FIRMWARE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&s->client->dev,
|
dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
|
||||||
"unknown chip version Si21%d-%c%c%c\n",
|
|
||||||
cmd.args[2], cmd.args[1],
|
cmd.args[2], cmd.args[1],
|
||||||
cmd.args[3], cmd.args[4]);
|
cmd.args[3], cmd.args[4]);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cold state - try to download firmware */
|
dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
|
||||||
dev_info(&s->client->dev, "found a '%s' in cold state\n",
|
cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
|
||||||
si2168_ops.info.name);
|
|
||||||
|
|
||||||
/* request the firmware, this will block and timeout */
|
/* request the firmware, this will block and timeout */
|
||||||
ret = request_firmware(&fw, fw_file, &s->client->dev);
|
ret = request_firmware(&fw, fw_name, &client->dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* fallback mechanism to handle old name for Si2168 B40 fw */
|
/* fallback mechanism to handle old name for Si2168 B40 fw */
|
||||||
if (chip_id == SI2168_B40) {
|
if (chip_id == SI2168_B40) {
|
||||||
fw_file = SI2168_B40_FIRMWARE_FALLBACK;
|
fw_name = SI2168_B40_FIRMWARE_FALLBACK;
|
||||||
ret = request_firmware(&fw, fw_file, &s->client->dev);
|
ret = request_firmware(&fw, fw_name, &client->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
dev_notice(&s->client->dev,
|
dev_notice(&client->dev,
|
||||||
"please install firmware file '%s'\n",
|
"please install firmware file '%s'\n",
|
||||||
SI2168_B40_FIRMWARE);
|
SI2168_B40_FIRMWARE);
|
||||||
} else {
|
} else {
|
||||||
dev_err(&s->client->dev,
|
dev_err(&client->dev,
|
||||||
"firmware file '%s' not found\n",
|
"firmware file '%s' not found\n",
|
||||||
fw_file);
|
fw_name);
|
||||||
goto error_fw_release;
|
goto err_release_firmware;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
|
dev_info(&client->dev, "downloading firmware from file '%s'\n",
|
||||||
fw_file);
|
fw_name);
|
||||||
|
|
||||||
if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
|
if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
|
||||||
/* firmware is in the new format */
|
/* firmware is in the new format */
|
||||||
|
@ -469,41 +460,37 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
|
memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
|
||||||
cmd.wlen = len;
|
cmd.wlen = len;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_err(&s->client->dev,
|
break;
|
||||||
"firmware download failed=%d\n",
|
|
||||||
ret);
|
|
||||||
goto error_fw_release;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else if (fw->size % 8 == 0) {
|
||||||
/* firmware is in the old format */
|
/* firmware is in the old format */
|
||||||
for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
|
for (remaining = fw->size; remaining > 0; remaining -= 8) {
|
||||||
len = remaining;
|
len = 8;
|
||||||
if (len > i2c_wr_max)
|
|
||||||
len = i2c_wr_max;
|
|
||||||
|
|
||||||
memcpy(cmd.args, &fw->data[fw->size - remaining], len);
|
memcpy(cmd.args, &fw->data[fw->size - remaining], len);
|
||||||
cmd.wlen = len;
|
cmd.wlen = len;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret) {
|
if (ret)
|
||||||
dev_err(&s->client->dev,
|
break;
|
||||||
"firmware download failed=%d\n",
|
|
||||||
ret);
|
|
||||||
goto error_fw_release;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* bad or unknown firmware format */
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&client->dev, "firmware download failed %d\n", ret);
|
||||||
|
goto err_release_firmware;
|
||||||
}
|
}
|
||||||
|
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
fw = NULL;
|
|
||||||
|
|
||||||
memcpy(cmd.args, "\x01\x01", 2);
|
memcpy(cmd.args, "\x01\x01", 2);
|
||||||
cmd.wlen = 2;
|
cmd.wlen = 2;
|
||||||
cmd.rlen = 1;
|
cmd.rlen = 1;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -511,58 +498,56 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||||
memcpy(cmd.args, "\x11", 1);
|
memcpy(cmd.args, "\x11", 1);
|
||||||
cmd.wlen = 1;
|
cmd.wlen = 1;
|
||||||
cmd.rlen = 10;
|
cmd.rlen = 10;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
dev_dbg(&s->client->dev, "firmware version: %c.%c.%d\n",
|
dev_info(&client->dev, "firmware version: %c.%c.%d\n",
|
||||||
cmd.args[6], cmd.args[7], cmd.args[8]);
|
cmd.args[6], cmd.args[7], cmd.args[8]);
|
||||||
|
|
||||||
/* set ts mode */
|
/* set ts mode */
|
||||||
memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
|
memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
|
||||||
cmd.args[4] |= s->ts_mode;
|
cmd.args[4] |= dev->ts_mode;
|
||||||
cmd.wlen = 6;
|
cmd.wlen = 6;
|
||||||
cmd.rlen = 4;
|
cmd.rlen = 4;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
s->fw_loaded = true;
|
dev->fw_loaded = true;
|
||||||
|
|
||||||
dev_info(&s->client->dev, "found a '%s' in warm state\n",
|
|
||||||
si2168_ops.info.name);
|
|
||||||
warm:
|
warm:
|
||||||
s->active = true;
|
dev->active = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_fw_release:
|
err_release_firmware:
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
err:
|
err:
|
||||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int si2168_sleep(struct dvb_frontend *fe)
|
static int si2168_sleep(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct si2168 *s = fe->demodulator_priv;
|
struct i2c_client *client = fe->demodulator_priv;
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
int ret;
|
int ret;
|
||||||
struct si2168_cmd cmd;
|
struct si2168_cmd cmd;
|
||||||
|
|
||||||
dev_dbg(&s->client->dev, "\n");
|
dev_dbg(&client->dev, "\n");
|
||||||
|
|
||||||
s->active = false;
|
dev->active = false;
|
||||||
|
|
||||||
memcpy(cmd.args, "\x13", 1);
|
memcpy(cmd.args, "\x13", 1);
|
||||||
cmd.wlen = 1;
|
cmd.wlen = 1;
|
||||||
cmd.rlen = 0;
|
cmd.rlen = 0;
|
||||||
ret = si2168_cmd_execute(s, &cmd);
|
ret = si2168_cmd_execute(client, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,21 +566,22 @@ static int si2168_get_tune_settings(struct dvb_frontend *fe,
|
||||||
*/
|
*/
|
||||||
static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
||||||
{
|
{
|
||||||
struct si2168 *s = mux_priv;
|
struct i2c_client *client = mux_priv;
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
int ret;
|
int ret;
|
||||||
struct i2c_msg gate_open_msg = {
|
struct i2c_msg gate_open_msg = {
|
||||||
.addr = s->client->addr,
|
.addr = client->addr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.len = 3,
|
.len = 3,
|
||||||
.buf = "\xc0\x0d\x01",
|
.buf = "\xc0\x0d\x01",
|
||||||
};
|
};
|
||||||
|
|
||||||
mutex_lock(&s->i2c_mutex);
|
mutex_lock(&dev->i2c_mutex);
|
||||||
|
|
||||||
/* open tuner I2C gate */
|
/* open tuner I2C gate */
|
||||||
ret = __i2c_transfer(s->client->adapter, &gate_open_msg, 1);
|
ret = __i2c_transfer(client->adapter, &gate_open_msg, 1);
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
|
dev_warn(&client->dev, "i2c write failed=%d\n", ret);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
ret = -EREMOTEIO;
|
ret = -EREMOTEIO;
|
||||||
} else {
|
} else {
|
||||||
|
@ -607,26 +593,27 @@ static int si2168_select(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
||||||
|
|
||||||
static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
static int si2168_deselect(struct i2c_adapter *adap, void *mux_priv, u32 chan)
|
||||||
{
|
{
|
||||||
struct si2168 *s = mux_priv;
|
struct i2c_client *client = mux_priv;
|
||||||
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
int ret;
|
int ret;
|
||||||
struct i2c_msg gate_close_msg = {
|
struct i2c_msg gate_close_msg = {
|
||||||
.addr = s->client->addr,
|
.addr = client->addr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.len = 3,
|
.len = 3,
|
||||||
.buf = "\xc0\x0d\x00",
|
.buf = "\xc0\x0d\x00",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* close tuner I2C gate */
|
/* close tuner I2C gate */
|
||||||
ret = __i2c_transfer(s->client->adapter, &gate_close_msg, 1);
|
ret = __i2c_transfer(client->adapter, &gate_close_msg, 1);
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
|
dev_warn(&client->dev, "i2c write failed=%d\n", ret);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
ret = -EREMOTEIO;
|
ret = -EREMOTEIO;
|
||||||
} else {
|
} else {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&s->i2c_mutex);
|
mutex_unlock(&dev->i2c_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -635,6 +622,8 @@ static const struct dvb_frontend_ops si2168_ops = {
|
||||||
.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
|
.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
|
||||||
.info = {
|
.info = {
|
||||||
.name = "Silicon Labs Si2168",
|
.name = "Silicon Labs Si2168",
|
||||||
|
.symbol_rate_min = 1000000,
|
||||||
|
.symbol_rate_max = 7200000,
|
||||||
.caps = FE_CAN_FEC_1_2 |
|
.caps = FE_CAN_FEC_1_2 |
|
||||||
FE_CAN_FEC_2_3 |
|
FE_CAN_FEC_2_3 |
|
||||||
FE_CAN_FEC_3_4 |
|
FE_CAN_FEC_3_4 |
|
||||||
|
@ -670,71 +659,69 @@ static int si2168_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct si2168_config *config = client->dev.platform_data;
|
struct si2168_config *config = client->dev.platform_data;
|
||||||
struct si2168 *s;
|
struct si2168_dev *dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_dbg(&client->dev, "\n");
|
dev_dbg(&client->dev, "\n");
|
||||||
|
|
||||||
s = kzalloc(sizeof(struct si2168), GFP_KERNEL);
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
if (!s) {
|
if (!dev) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
dev_err(&client->dev, "kzalloc() failed\n");
|
dev_err(&client->dev, "kzalloc() failed\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->client = client;
|
mutex_init(&dev->i2c_mutex);
|
||||||
mutex_init(&s->i2c_mutex);
|
|
||||||
|
|
||||||
/* create mux i2c adapter for tuner */
|
/* create mux i2c adapter for tuner */
|
||||||
s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
|
dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
|
||||||
0, 0, 0, si2168_select, si2168_deselect);
|
client, 0, 0, 0, si2168_select, si2168_deselect);
|
||||||
if (s->adapter == NULL) {
|
if (dev->adapter == NULL) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
goto err_kfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create dvb_frontend */
|
/* create dvb_frontend */
|
||||||
memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
|
memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
|
||||||
s->fe.demodulator_priv = s;
|
dev->fe.demodulator_priv = client;
|
||||||
|
*config->i2c_adapter = dev->adapter;
|
||||||
|
*config->fe = &dev->fe;
|
||||||
|
dev->ts_mode = config->ts_mode;
|
||||||
|
dev->ts_clock_inv = config->ts_clock_inv;
|
||||||
|
dev->fw_loaded = false;
|
||||||
|
|
||||||
*config->i2c_adapter = s->adapter;
|
i2c_set_clientdata(client, dev);
|
||||||
*config->fe = &s->fe;
|
|
||||||
s->ts_mode = config->ts_mode;
|
|
||||||
s->ts_clock_inv = config->ts_clock_inv;
|
|
||||||
s->fw_loaded = false;
|
|
||||||
|
|
||||||
i2c_set_clientdata(client, s);
|
dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n");
|
||||||
|
|
||||||
dev_info(&s->client->dev,
|
|
||||||
"Silicon Labs Si2168 successfully attached\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
|
err_kfree:
|
||||||
|
kfree(dev);
|
||||||
err:
|
err:
|
||||||
kfree(s);
|
|
||||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int si2168_remove(struct i2c_client *client)
|
static int si2168_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct si2168 *s = i2c_get_clientdata(client);
|
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||||
|
|
||||||
dev_dbg(&client->dev, "\n");
|
dev_dbg(&client->dev, "\n");
|
||||||
|
|
||||||
i2c_del_mux_adapter(s->adapter);
|
i2c_del_mux_adapter(dev->adapter);
|
||||||
|
|
||||||
s->fe.ops.release = NULL;
|
dev->fe.ops.release = NULL;
|
||||||
s->fe.demodulator_priv = NULL;
|
dev->fe.demodulator_priv = NULL;
|
||||||
|
|
||||||
kfree(s);
|
kfree(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id si2168_id[] = {
|
static const struct i2c_device_id si2168_id_table[] = {
|
||||||
{"si2168", 0},
|
{"si2168", 0},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, si2168_id);
|
MODULE_DEVICE_TABLE(i2c, si2168_id_table);
|
||||||
|
|
||||||
static struct i2c_driver si2168_driver = {
|
static struct i2c_driver si2168_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
|
@ -743,7 +730,7 @@ static struct i2c_driver si2168_driver = {
|
||||||
},
|
},
|
||||||
.probe = si2168_probe,
|
.probe = si2168_probe,
|
||||||
.remove = si2168_remove,
|
.remove = si2168_remove,
|
||||||
.id_table = si2168_id,
|
.id_table = si2168_id_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_i2c_driver(si2168_driver);
|
module_i2c_driver(si2168_driver);
|
||||||
|
|
|
@ -36,14 +36,12 @@ struct si2168_config {
|
||||||
struct i2c_adapter **i2c_adapter;
|
struct i2c_adapter **i2c_adapter;
|
||||||
|
|
||||||
/* TS mode */
|
/* TS mode */
|
||||||
|
#define SI2168_TS_PARALLEL 0x06
|
||||||
|
#define SI2168_TS_SERIAL 0x03
|
||||||
u8 ts_mode;
|
u8 ts_mode;
|
||||||
|
|
||||||
/* TS clock inverted */
|
/* TS clock inverted */
|
||||||
bool ts_clock_inv;
|
bool ts_clock_inv;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SI2168_TS_PARALLEL 0x06
|
|
||||||
#define SI2168_TS_SERIAL 0x03
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,8 +28,7 @@
|
||||||
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
|
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
|
||||||
|
|
||||||
/* state struct */
|
/* state struct */
|
||||||
struct si2168 {
|
struct si2168_dev {
|
||||||
struct i2c_client *client;
|
|
||||||
struct i2c_adapter *adapter;
|
struct i2c_adapter *adapter;
|
||||||
struct mutex i2c_mutex;
|
struct mutex i2c_mutex;
|
||||||
struct dvb_frontend fe;
|
struct dvb_frontend fe;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
#include "stb0899_drv.h"
|
#include "stb0899_drv.h"
|
||||||
#include "stb0899_priv.h"
|
#include "stb0899_priv.h"
|
||||||
#include "stb0899_reg.h"
|
#include "stb0899_reg.h"
|
||||||
|
@ -1490,9 +1491,7 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
|
||||||
/* Store signal parameters */
|
/* Store signal parameters */
|
||||||
offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
|
offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
|
||||||
|
|
||||||
/* sign extend 30 bit value before using it in calculations */
|
offsetfreq = sign_extend32(offsetfreq, 29);
|
||||||
if (offsetfreq & (1 << 29))
|
|
||||||
offsetfreq |= -1 << 30;
|
|
||||||
|
|
||||||
offsetfreq = offsetfreq / ((1 << 30) / 1000);
|
offsetfreq = offsetfreq / ((1 << 30) / 1000);
|
||||||
offsetfreq *= (internal->master_clk / 1000000);
|
offsetfreq *= (internal->master_clk / 1000000);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -691,7 +692,7 @@ static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeo
|
||||||
reg = stb0899_read_reg(state, STB0899_DISSTATUS);
|
reg = stb0899_read_reg(state, STB0899_DISSTATUS);
|
||||||
if (!STB0899_GETFIELD(FIFOFULL, reg))
|
if (!STB0899_GETFIELD(FIFOFULL, reg))
|
||||||
break;
|
break;
|
||||||
if ((jiffies - start) > timeout) {
|
if (time_after(jiffies, start + timeout)) {
|
||||||
dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
|
dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
@ -733,7 +734,7 @@ static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
|
||||||
|
|
||||||
while (!STB0899_GETFIELD(RXEND, reg)) {
|
while (!STB0899_GETFIELD(RXEND, reg)) {
|
||||||
reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
|
reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
|
||||||
if (jiffies - start > timeout) {
|
if (time_after(jiffies, start + timeout)) {
|
||||||
dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
|
dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
@ -782,7 +783,7 @@ static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
|
||||||
|
|
||||||
while (!STB0899_GETFIELD(TXIDLE, reg)) {
|
while (!STB0899_GETFIELD(TXIDLE, reg)) {
|
||||||
reg = stb0899_read_reg(state, STB0899_DISSTATUS);
|
reg = stb0899_read_reg(state, STB0899_DISSTATUS);
|
||||||
if (jiffies - start > timeout) {
|
if (time_after(jiffies, start + timeout)) {
|
||||||
dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
|
dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe)
|
||||||
state = fe->demodulator_priv;
|
state = fe->demodulator_priv;
|
||||||
c = &fe->dtv_property_cache;
|
c = &fe->dtv_property_cache;
|
||||||
c->delivery_system = SYS_ISDBS;
|
c->delivery_system = SYS_ISDBS;
|
||||||
|
c->symbol_rate = 28860000;
|
||||||
|
|
||||||
layers = 0;
|
layers = 0;
|
||||||
ret = reg_read(state, 0xe6, val, 5);
|
ret = reg_read(state, 0xe6, val, 5);
|
||||||
|
|
|
@ -177,7 +177,7 @@ comment "Video decoders"
|
||||||
|
|
||||||
config VIDEO_ADV7180
|
config VIDEO_ADV7180
|
||||||
tristate "Analog Devices ADV7180 decoder"
|
tristate "Analog Devices ADV7180 decoder"
|
||||||
depends on VIDEO_V4L2 && I2C
|
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||||
---help---
|
---help---
|
||||||
Support for the Analog Devices ADV7180 video decoder.
|
Support for the Analog Devices ADV7180 video decoder.
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ config VIDEO_ADV7183
|
||||||
|
|
||||||
config VIDEO_ADV7604
|
config VIDEO_ADV7604
|
||||||
tristate "Analog Devices ADV7604 decoder"
|
tristate "Analog Devices ADV7604 decoder"
|
||||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
|
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||||
---help---
|
---help---
|
||||||
Support for the Analog Devices ADV7604 video decoder.
|
Support for the Analog Devices ADV7604 video decoder.
|
||||||
|
|
||||||
|
@ -208,7 +208,8 @@ config VIDEO_ADV7604
|
||||||
|
|
||||||
config VIDEO_ADV7842
|
config VIDEO_ADV7842
|
||||||
tristate "Analog Devices ADV7842 decoder"
|
tristate "Analog Devices ADV7842 decoder"
|
||||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
|
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||||
|
select HDMI
|
||||||
---help---
|
---help---
|
||||||
Support for the Analog Devices ADV7842 video decoder.
|
Support for the Analog Devices ADV7842 video decoder.
|
||||||
|
|
||||||
|
@ -422,7 +423,7 @@ config VIDEO_ADV7393
|
||||||
|
|
||||||
config VIDEO_ADV7511
|
config VIDEO_ADV7511
|
||||||
tristate "Analog Devices ADV7511 encoder"
|
tristate "Analog Devices ADV7511 encoder"
|
||||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
|
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||||
---help---
|
---help---
|
||||||
Support for the Analog Devices ADV7511 video encoder.
|
Support for the Analog Devices ADV7511 video encoder.
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -333,21 +333,11 @@ static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
|
||||||
return container_of(sd, struct adv7604_state, sd);
|
return container_of(sd, struct adv7604_state, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
|
|
||||||
{
|
|
||||||
return V4L2_DV_BT_BLANKING_WIDTH(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
||||||
{
|
{
|
||||||
return V4L2_DV_BT_FRAME_WIDTH(t);
|
return V4L2_DV_BT_FRAME_WIDTH(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned vblanking(const struct v4l2_bt_timings *t)
|
|
||||||
{
|
|
||||||
return V4L2_DV_BT_BLANKING_HEIGHT(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
||||||
{
|
{
|
||||||
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
||||||
|
@ -466,11 +456,6 @@ static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
||||||
return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
|
return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
|
|
||||||
{
|
|
||||||
return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
|
static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
|
||||||
{
|
{
|
||||||
struct adv7604_state *state = to_state(sd);
|
struct adv7604_state *state = to_state(sd);
|
||||||
|
@ -486,34 +471,6 @@ static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
||||||
reg, val);
|
reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int esdp_read(struct v4l2_subdev *sd, u8 reg)
|
|
||||||
{
|
|
||||||
struct adv7604_state *state = to_state(sd);
|
|
||||||
|
|
||||||
return adv_smbus_read_byte_data(state, ADV7604_PAGE_ESDP, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
|
||||||
{
|
|
||||||
struct adv7604_state *state = to_state(sd);
|
|
||||||
|
|
||||||
return adv_smbus_write_byte_data(state, ADV7604_PAGE_ESDP, reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int dpp_read(struct v4l2_subdev *sd, u8 reg)
|
|
||||||
{
|
|
||||||
struct adv7604_state *state = to_state(sd);
|
|
||||||
|
|
||||||
return adv_smbus_read_byte_data(state, ADV7604_PAGE_DPP, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
|
||||||
{
|
|
||||||
struct adv7604_state *state = to_state(sd);
|
|
||||||
|
|
||||||
return adv_smbus_write_byte_data(state, ADV7604_PAGE_DPP, reg, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
|
static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
|
||||||
{
|
{
|
||||||
struct adv7604_state *state = to_state(sd);
|
struct adv7604_state *state = to_state(sd);
|
||||||
|
@ -561,32 +518,6 @@ static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
||||||
return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val);
|
return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
|
|
||||||
{
|
|
||||||
struct adv7604_state *state = to_state(sd);
|
|
||||||
struct i2c_client *client = state->i2c_clients[ADV7604_PAGE_EDID];
|
|
||||||
u8 msgbuf0[1] = { 0 };
|
|
||||||
u8 msgbuf1[256];
|
|
||||||
struct i2c_msg msg[2] = {
|
|
||||||
{
|
|
||||||
.addr = client->addr,
|
|
||||||
.len = 1,
|
|
||||||
.buf = msgbuf0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.addr = client->addr,
|
|
||||||
.flags = I2C_M_RD,
|
|
||||||
.len = len,
|
|
||||||
.buf = msgbuf1
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (i2c_transfer(client->adapter, msg, 2) < 0)
|
|
||||||
return -EIO;
|
|
||||||
memcpy(val, msgbuf1, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int edid_write_block(struct v4l2_subdev *sd,
|
static inline int edid_write_block(struct v4l2_subdev *sd,
|
||||||
unsigned len, const u8 *val)
|
unsigned len, const u8 *val)
|
||||||
{
|
{
|
||||||
|
@ -652,13 +583,6 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
|
||||||
return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
|
return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int test_read(struct v4l2_subdev *sd, u8 reg)
|
|
||||||
{
|
|
||||||
struct adv7604_state *state = to_state(sd);
|
|
||||||
|
|
||||||
return adv_smbus_read_byte_data(state, ADV7604_PAGE_TEST, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
|
||||||
{
|
{
|
||||||
struct adv7604_state *state = to_state(sd);
|
struct adv7604_state *state = to_state(sd);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/v4l2-dv-timings.h>
|
#include <linux/v4l2-dv-timings.h>
|
||||||
|
#include <linux/hdmi.h>
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-ctrls.h>
|
||||||
#include <media/v4l2-dv-timings.h>
|
#include <media/v4l2-dv-timings.h>
|
||||||
|
@ -220,21 +221,11 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
|
||||||
return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
|
return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
|
|
||||||
{
|
|
||||||
return V4L2_DV_BT_BLANKING_WIDTH(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
||||||
{
|
{
|
||||||
return V4L2_DV_BT_FRAME_WIDTH(t);
|
return V4L2_DV_BT_FRAME_WIDTH(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned vblanking(const struct v4l2_bt_timings *t)
|
|
||||||
{
|
|
||||||
return V4L2_DV_BT_BLANKING_HEIGHT(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
||||||
{
|
{
|
||||||
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
||||||
|
@ -2108,149 +2099,65 @@ static int adv7842_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *e)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********** avi info frame CEA-861-E **************/
|
struct adv7842_cfg_read_infoframe {
|
||||||
/* TODO move to common library */
|
const char *desc;
|
||||||
|
u8 present_mask;
|
||||||
struct avi_info_frame {
|
u8 head_addr;
|
||||||
uint8_t f17;
|
u8 payload_addr;
|
||||||
uint8_t y10;
|
|
||||||
uint8_t a0;
|
|
||||||
uint8_t b10;
|
|
||||||
uint8_t s10;
|
|
||||||
uint8_t c10;
|
|
||||||
uint8_t m10;
|
|
||||||
uint8_t r3210;
|
|
||||||
uint8_t itc;
|
|
||||||
uint8_t ec210;
|
|
||||||
uint8_t q10;
|
|
||||||
uint8_t sc10;
|
|
||||||
uint8_t f47;
|
|
||||||
uint8_t vic;
|
|
||||||
uint8_t yq10;
|
|
||||||
uint8_t cn10;
|
|
||||||
uint8_t pr3210;
|
|
||||||
uint16_t etb;
|
|
||||||
uint16_t sbb;
|
|
||||||
uint16_t elb;
|
|
||||||
uint16_t srb;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *y10_txt[4] = {
|
static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infoframe *cri)
|
||||||
"RGB",
|
|
||||||
"YCbCr 4:2:2",
|
|
||||||
"YCbCr 4:4:4",
|
|
||||||
"Future",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *c10_txt[4] = {
|
|
||||||
"No Data",
|
|
||||||
"SMPTE 170M",
|
|
||||||
"ITU-R 709",
|
|
||||||
"Extended Colorimetry information valied",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *itc_txt[2] = {
|
|
||||||
"No Data",
|
|
||||||
"IT content",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *ec210_txt[8] = {
|
|
||||||
"xvYCC601",
|
|
||||||
"xvYCC709",
|
|
||||||
"sYCC601",
|
|
||||||
"AdobeYCC601",
|
|
||||||
"AdobeRGB",
|
|
||||||
"5 reserved",
|
|
||||||
"6 reserved",
|
|
||||||
"7 reserved",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *q10_txt[4] = {
|
|
||||||
"Default",
|
|
||||||
"Limited Range",
|
|
||||||
"Full Range",
|
|
||||||
"Reserved",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void parse_avi_infoframe(struct v4l2_subdev *sd, uint8_t *buf,
|
|
||||||
struct avi_info_frame *avi)
|
|
||||||
{
|
|
||||||
avi->f17 = (buf[1] >> 7) & 0x1;
|
|
||||||
avi->y10 = (buf[1] >> 5) & 0x3;
|
|
||||||
avi->a0 = (buf[1] >> 4) & 0x1;
|
|
||||||
avi->b10 = (buf[1] >> 2) & 0x3;
|
|
||||||
avi->s10 = buf[1] & 0x3;
|
|
||||||
avi->c10 = (buf[2] >> 6) & 0x3;
|
|
||||||
avi->m10 = (buf[2] >> 4) & 0x3;
|
|
||||||
avi->r3210 = buf[2] & 0xf;
|
|
||||||
avi->itc = (buf[3] >> 7) & 0x1;
|
|
||||||
avi->ec210 = (buf[3] >> 4) & 0x7;
|
|
||||||
avi->q10 = (buf[3] >> 2) & 0x3;
|
|
||||||
avi->sc10 = buf[3] & 0x3;
|
|
||||||
avi->f47 = (buf[4] >> 7) & 0x1;
|
|
||||||
avi->vic = buf[4] & 0x7f;
|
|
||||||
avi->yq10 = (buf[5] >> 6) & 0x3;
|
|
||||||
avi->cn10 = (buf[5] >> 4) & 0x3;
|
|
||||||
avi->pr3210 = buf[5] & 0xf;
|
|
||||||
avi->etb = buf[6] + 256*buf[7];
|
|
||||||
avi->sbb = buf[8] + 256*buf[9];
|
|
||||||
avi->elb = buf[10] + 256*buf[11];
|
|
||||||
avi->srb = buf[12] + 256*buf[13];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_avi_infoframe(struct v4l2_subdev *sd)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint8_t buf[14];
|
uint8_t buffer[32];
|
||||||
u8 avi_len;
|
union hdmi_infoframe frame;
|
||||||
u8 avi_ver;
|
u8 len;
|
||||||
struct avi_info_frame avi;
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||||
|
struct device *dev = &client->dev;
|
||||||
|
|
||||||
|
if (!(io_read(sd, 0x60) & cri->present_mask)) {
|
||||||
|
v4l2_info(sd, "%s infoframe not received\n", cri->desc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
buffer[i] = infoframe_read(sd, cri->head_addr + i);
|
||||||
|
|
||||||
|
len = buffer[2] + 1;
|
||||||
|
|
||||||
|
if (len + 3 > sizeof(buffer)) {
|
||||||
|
v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i);
|
||||||
|
|
||||||
|
if (hdmi_infoframe_unpack(&frame, buffer) < 0) {
|
||||||
|
v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi_infoframe_log(KERN_INFO, dev, &frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adv7842_log_infoframes(struct v4l2_subdev *sd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct adv7842_cfg_read_infoframe cri[] = {
|
||||||
|
{ "AVI", 0x01, 0xe0, 0x00 },
|
||||||
|
{ "Audio", 0x02, 0xe3, 0x1c },
|
||||||
|
{ "SDP", 0x04, 0xe6, 0x2a },
|
||||||
|
{ "Vendor", 0x10, 0xec, 0x54 }
|
||||||
|
};
|
||||||
|
|
||||||
if (!(hdmi_read(sd, 0x05) & 0x80)) {
|
if (!(hdmi_read(sd, 0x05) & 0x80)) {
|
||||||
v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
|
v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(io_read(sd, 0x60) & 0x01)) {
|
|
||||||
v4l2_info(sd, "AVI infoframe not received\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (io_read(sd, 0x88) & 0x10) {
|
for (i = 0; i < ARRAY_SIZE(cri); i++)
|
||||||
v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
|
log_infoframe(sd, &cri[i]);
|
||||||
io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */
|
|
||||||
if (io_read(sd, 0x88) & 0x10) {
|
|
||||||
v4l2_info(sd, "AVI infoframe checksum error still present\n");
|
|
||||||
io_write(sd, 0x8a, 0x10); /* clear AVI_INF_CKS_ERR_RAW */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avi_len = infoframe_read(sd, 0xe2);
|
|
||||||
avi_ver = infoframe_read(sd, 0xe1);
|
|
||||||
v4l2_info(sd, "AVI infoframe version %d (%d byte)\n",
|
|
||||||
avi_ver, avi_len);
|
|
||||||
|
|
||||||
if (avi_ver != 0x02)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < 14; i++)
|
|
||||||
buf[i] = infoframe_read(sd, i);
|
|
||||||
|
|
||||||
v4l2_info(sd, "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
|
||||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
|
||||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
|
|
||||||
|
|
||||||
parse_avi_infoframe(sd, buf, &avi);
|
|
||||||
|
|
||||||
if (avi.vic)
|
|
||||||
v4l2_info(sd, "\tVIC: %d\n", avi.vic);
|
|
||||||
if (avi.itc)
|
|
||||||
v4l2_info(sd, "\t%s\n", itc_txt[avi.itc]);
|
|
||||||
|
|
||||||
if (avi.y10)
|
|
||||||
v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], !avi.c10 ? "" :
|
|
||||||
(avi.c10 == 0x3 ? ec210_txt[avi.ec210] : c10_txt[avi.c10]));
|
|
||||||
else
|
|
||||||
v4l2_info(sd, "\t%s %s\n", y10_txt[avi.y10], q10_txt[avi.q10]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const prim_mode_txt[] = {
|
static const char * const prim_mode_txt[] = {
|
||||||
|
@ -2464,7 +2371,8 @@ static int adv7842_cp_log_status(struct v4l2_subdev *sd)
|
||||||
v4l2_info(sd, "Deep color mode: %s\n",
|
v4l2_info(sd, "Deep color mode: %s\n",
|
||||||
deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]);
|
deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]);
|
||||||
|
|
||||||
print_avi_infoframe(sd);
|
adv7842_log_infoframes(sd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,9 +125,9 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
|
||||||
if (length == 1)
|
if (length == 1)
|
||||||
return *data;
|
return *data;
|
||||||
else if (length == 2)
|
else if (length == 2)
|
||||||
return be16_to_cpu(*((u16 *)data));
|
return be16_to_cpu(*((__be16 *)data));
|
||||||
else
|
else
|
||||||
return be32_to_cpu(*((u32 *)data));
|
return be32_to_cpu(*((__be32 *)data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,11 +454,6 @@ static int m5mols_get_version(struct v4l2_subdev *sd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ver->fw = be16_to_cpu(ver->fw);
|
|
||||||
ver->hw = be16_to_cpu(ver->hw);
|
|
||||||
ver->param = be16_to_cpu(ver->param);
|
|
||||||
ver->awb = be16_to_cpu(ver->awb);
|
|
||||||
|
|
||||||
v4l2_info(sd, "Manufacturer\t[%s]\n",
|
v4l2_info(sd, "Manufacturer\t[%s]\n",
|
||||||
is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
|
is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
|
||||||
"Samsung Electro-Machanics" :
|
"Samsung Electro-Machanics" :
|
||||||
|
|
|
@ -904,11 +904,3 @@ static struct i2c_driver msp_driver = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module_i2c_driver(msp_driver);
|
module_i2c_driver(msp_driver);
|
||||||
|
|
||||||
/*
|
|
||||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
|
||||||
* ---------------------------------------------------------------------------
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -422,22 +422,25 @@ static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev,
|
static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9m032 *sensor = to_mt9m032(subdev);
|
struct mt9m032 *sensor = to_mt9m032(subdev);
|
||||||
|
|
||||||
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&sensor->lock);
|
mutex_lock(&sensor->lock);
|
||||||
crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which);
|
sel->r = *__mt9m032_get_pad_crop(sensor, fh, sel->which);
|
||||||
mutex_unlock(&sensor->lock);
|
mutex_unlock(&sensor->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
|
static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9m032 *sensor = to_mt9m032(subdev);
|
struct mt9m032 *sensor = to_mt9m032(subdev);
|
||||||
struct v4l2_mbus_framefmt *format;
|
struct v4l2_mbus_framefmt *format;
|
||||||
|
@ -445,9 +448,12 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_rect rect;
|
struct v4l2_rect rect;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&sensor->lock);
|
mutex_lock(&sensor->lock);
|
||||||
|
|
||||||
if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -455,13 +461,13 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
|
||||||
/* Clamp the crop rectangle boundaries and align them to a multiple of 2
|
/* Clamp the crop rectangle boundaries and align them to a multiple of 2
|
||||||
* pixels to ensure a GRBG Bayer pattern.
|
* pixels to ensure a GRBG Bayer pattern.
|
||||||
*/
|
*/
|
||||||
rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN,
|
rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN,
|
||||||
MT9M032_COLUMN_START_MAX);
|
MT9M032_COLUMN_START_MAX);
|
||||||
rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN,
|
rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN,
|
||||||
MT9M032_ROW_START_MAX);
|
MT9M032_ROW_START_MAX);
|
||||||
rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
|
rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
|
||||||
MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX);
|
MT9M032_COLUMN_SIZE_MIN, MT9M032_COLUMN_SIZE_MAX);
|
||||||
rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
|
rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
|
||||||
MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX);
|
MT9M032_ROW_SIZE_MIN, MT9M032_ROW_SIZE_MAX);
|
||||||
|
|
||||||
rect.width = min_t(unsigned int, rect.width,
|
rect.width = min_t(unsigned int, rect.width,
|
||||||
|
@ -469,21 +475,21 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
|
||||||
rect.height = min_t(unsigned int, rect.height,
|
rect.height = min_t(unsigned int, rect.height,
|
||||||
MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
|
MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
|
||||||
|
|
||||||
__crop = __mt9m032_get_pad_crop(sensor, fh, crop->which);
|
__crop = __mt9m032_get_pad_crop(sensor, fh, sel->which);
|
||||||
|
|
||||||
if (rect.width != __crop->width || rect.height != __crop->height) {
|
if (rect.width != __crop->width || rect.height != __crop->height) {
|
||||||
/* Reset the output image size if the crop rectangle size has
|
/* Reset the output image size if the crop rectangle size has
|
||||||
* been modified.
|
* been modified.
|
||||||
*/
|
*/
|
||||||
format = __mt9m032_get_pad_format(sensor, fh, crop->which);
|
format = __mt9m032_get_pad_format(sensor, fh, sel->which);
|
||||||
format->width = rect.width;
|
format->width = rect.width;
|
||||||
format->height = rect.height;
|
format->height = rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
*__crop = rect;
|
*__crop = rect;
|
||||||
crop->rect = rect;
|
sel->r = rect;
|
||||||
|
|
||||||
if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||||
ret = mt9m032_update_geom_timing(sensor);
|
ret = mt9m032_update_geom_timing(sensor);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -690,8 +696,8 @@ static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
|
||||||
.enum_frame_size = mt9m032_enum_frame_size,
|
.enum_frame_size = mt9m032_enum_frame_size,
|
||||||
.get_fmt = mt9m032_get_pad_format,
|
.get_fmt = mt9m032_get_pad_format,
|
||||||
.set_fmt = mt9m032_set_pad_format,
|
.set_fmt = mt9m032_set_pad_format,
|
||||||
.set_crop = mt9m032_set_pad_crop,
|
.set_selection = mt9m032_set_pad_selection,
|
||||||
.get_crop = mt9m032_get_pad_crop,
|
.get_selection = mt9m032_get_pad_selection,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct v4l2_subdev_ops mt9m032_ops = {
|
static const struct v4l2_subdev_ops mt9m032_ops = {
|
||||||
|
|
|
@ -581,37 +581,42 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9p031_get_crop(struct v4l2_subdev *subdev,
|
static int mt9p031_get_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
|
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
|
||||||
|
|
||||||
crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
crop->which);
|
return -EINVAL;
|
||||||
|
|
||||||
|
sel->r = *__mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9p031_set_crop(struct v4l2_subdev *subdev,
|
static int mt9p031_set_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
|
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
|
||||||
struct v4l2_mbus_framefmt *__format;
|
struct v4l2_mbus_framefmt *__format;
|
||||||
struct v4l2_rect *__crop;
|
struct v4l2_rect *__crop;
|
||||||
struct v4l2_rect rect;
|
struct v4l2_rect rect;
|
||||||
|
|
||||||
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Clamp the crop rectangle boundaries and align them to a multiple of 2
|
/* Clamp the crop rectangle boundaries and align them to a multiple of 2
|
||||||
* pixels to ensure a GRBG Bayer pattern.
|
* pixels to ensure a GRBG Bayer pattern.
|
||||||
*/
|
*/
|
||||||
rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN,
|
rect.left = clamp(ALIGN(sel->r.left, 2), MT9P031_COLUMN_START_MIN,
|
||||||
MT9P031_COLUMN_START_MAX);
|
MT9P031_COLUMN_START_MAX);
|
||||||
rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN,
|
rect.top = clamp(ALIGN(sel->r.top, 2), MT9P031_ROW_START_MIN,
|
||||||
MT9P031_ROW_START_MAX);
|
MT9P031_ROW_START_MAX);
|
||||||
rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
|
rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
|
||||||
MT9P031_WINDOW_WIDTH_MIN,
|
MT9P031_WINDOW_WIDTH_MIN,
|
||||||
MT9P031_WINDOW_WIDTH_MAX);
|
MT9P031_WINDOW_WIDTH_MAX);
|
||||||
rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
|
rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
|
||||||
MT9P031_WINDOW_HEIGHT_MIN,
|
MT9P031_WINDOW_HEIGHT_MIN,
|
||||||
MT9P031_WINDOW_HEIGHT_MAX);
|
MT9P031_WINDOW_HEIGHT_MAX);
|
||||||
|
|
||||||
|
@ -620,20 +625,20 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
|
||||||
rect.height = min_t(unsigned int, rect.height,
|
rect.height = min_t(unsigned int, rect.height,
|
||||||
MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
|
MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
|
||||||
|
|
||||||
__crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
|
__crop = __mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
|
||||||
|
|
||||||
if (rect.width != __crop->width || rect.height != __crop->height) {
|
if (rect.width != __crop->width || rect.height != __crop->height) {
|
||||||
/* Reset the output image size if the crop rectangle size has
|
/* Reset the output image size if the crop rectangle size has
|
||||||
* been modified.
|
* been modified.
|
||||||
*/
|
*/
|
||||||
__format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
|
__format = __mt9p031_get_pad_format(mt9p031, fh, sel->pad,
|
||||||
crop->which);
|
sel->which);
|
||||||
__format->width = rect.width;
|
__format->width = rect.width;
|
||||||
__format->height = rect.height;
|
__format->height = rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
*__crop = rect;
|
*__crop = rect;
|
||||||
crop->rect = rect;
|
sel->r = rect;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -980,8 +985,8 @@ static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
|
||||||
.enum_frame_size = mt9p031_enum_frame_size,
|
.enum_frame_size = mt9p031_enum_frame_size,
|
||||||
.get_fmt = mt9p031_get_format,
|
.get_fmt = mt9p031_get_format,
|
||||||
.set_fmt = mt9p031_set_format,
|
.set_fmt = mt9p031_set_format,
|
||||||
.get_crop = mt9p031_get_crop,
|
.get_selection = mt9p031_get_selection,
|
||||||
.set_crop = mt9p031_set_crop,
|
.set_selection = mt9p031_set_selection,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9p031_subdev_ops = {
|
static struct v4l2_subdev_ops mt9p031_subdev_ops = {
|
||||||
|
|
|
@ -401,39 +401,44 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9t001_get_crop(struct v4l2_subdev *subdev,
|
static int mt9t001_get_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
|
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
|
||||||
|
|
||||||
crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
crop->which);
|
return -EINVAL;
|
||||||
|
|
||||||
|
sel->r = *__mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9t001_set_crop(struct v4l2_subdev *subdev,
|
static int mt9t001_set_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
|
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
|
||||||
struct v4l2_mbus_framefmt *__format;
|
struct v4l2_mbus_framefmt *__format;
|
||||||
struct v4l2_rect *__crop;
|
struct v4l2_rect *__crop;
|
||||||
struct v4l2_rect rect;
|
struct v4l2_rect rect;
|
||||||
|
|
||||||
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Clamp the crop rectangle boundaries and align them to a multiple of 2
|
/* Clamp the crop rectangle boundaries and align them to a multiple of 2
|
||||||
* pixels.
|
* pixels.
|
||||||
*/
|
*/
|
||||||
rect.left = clamp(ALIGN(crop->rect.left, 2),
|
rect.left = clamp(ALIGN(sel->r.left, 2),
|
||||||
MT9T001_COLUMN_START_MIN,
|
MT9T001_COLUMN_START_MIN,
|
||||||
MT9T001_COLUMN_START_MAX);
|
MT9T001_COLUMN_START_MAX);
|
||||||
rect.top = clamp(ALIGN(crop->rect.top, 2),
|
rect.top = clamp(ALIGN(sel->r.top, 2),
|
||||||
MT9T001_ROW_START_MIN,
|
MT9T001_ROW_START_MIN,
|
||||||
MT9T001_ROW_START_MAX);
|
MT9T001_ROW_START_MAX);
|
||||||
rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
|
rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
|
||||||
MT9T001_WINDOW_WIDTH_MIN + 1,
|
MT9T001_WINDOW_WIDTH_MIN + 1,
|
||||||
MT9T001_WINDOW_WIDTH_MAX + 1);
|
MT9T001_WINDOW_WIDTH_MAX + 1);
|
||||||
rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
|
rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
|
||||||
MT9T001_WINDOW_HEIGHT_MIN + 1,
|
MT9T001_WINDOW_HEIGHT_MIN + 1,
|
||||||
MT9T001_WINDOW_HEIGHT_MAX + 1);
|
MT9T001_WINDOW_HEIGHT_MAX + 1);
|
||||||
|
|
||||||
|
@ -442,20 +447,20 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
|
||||||
rect.height = min_t(unsigned int, rect.height,
|
rect.height = min_t(unsigned int, rect.height,
|
||||||
MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
|
MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
|
||||||
|
|
||||||
__crop = __mt9t001_get_pad_crop(mt9t001, fh, crop->pad, crop->which);
|
__crop = __mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
|
||||||
|
|
||||||
if (rect.width != __crop->width || rect.height != __crop->height) {
|
if (rect.width != __crop->width || rect.height != __crop->height) {
|
||||||
/* Reset the output image size if the crop rectangle size has
|
/* Reset the output image size if the crop rectangle size has
|
||||||
* been modified.
|
* been modified.
|
||||||
*/
|
*/
|
||||||
__format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad,
|
__format = __mt9t001_get_pad_format(mt9t001, fh, sel->pad,
|
||||||
crop->which);
|
sel->which);
|
||||||
__format->width = rect.width;
|
__format->width = rect.width;
|
||||||
__format->height = rect.height;
|
__format->height = rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
*__crop = rect;
|
*__crop = rect;
|
||||||
crop->rect = rect;
|
sel->r = rect;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -819,8 +824,8 @@ static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
|
||||||
.enum_frame_size = mt9t001_enum_frame_size,
|
.enum_frame_size = mt9t001_enum_frame_size,
|
||||||
.get_fmt = mt9t001_get_format,
|
.get_fmt = mt9t001_get_format,
|
||||||
.set_fmt = mt9t001_set_format,
|
.set_fmt = mt9t001_set_format,
|
||||||
.get_crop = mt9t001_get_crop,
|
.get_selection = mt9t001_get_selection,
|
||||||
.set_crop = mt9t001_set_crop,
|
.set_selection = mt9t001_set_selection,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9t001_subdev_ops = {
|
static struct v4l2_subdev_ops mt9t001_subdev_ops = {
|
||||||
|
|
|
@ -552,39 +552,44 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9v032_get_crop(struct v4l2_subdev *subdev,
|
static int mt9v032_get_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||||
|
|
||||||
crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
crop->which);
|
return -EINVAL;
|
||||||
|
|
||||||
|
sel->r = *__mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
static int mt9v032_set_selection(struct v4l2_subdev *subdev,
|
||||||
struct v4l2_subdev_fh *fh,
|
struct v4l2_subdev_fh *fh,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||||
struct v4l2_mbus_framefmt *__format;
|
struct v4l2_mbus_framefmt *__format;
|
||||||
struct v4l2_rect *__crop;
|
struct v4l2_rect *__crop;
|
||||||
struct v4l2_rect rect;
|
struct v4l2_rect rect;
|
||||||
|
|
||||||
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* Clamp the crop rectangle boundaries and align them to a non multiple
|
/* Clamp the crop rectangle boundaries and align them to a non multiple
|
||||||
* of 2 pixels to ensure a GRBG Bayer pattern.
|
* of 2 pixels to ensure a GRBG Bayer pattern.
|
||||||
*/
|
*/
|
||||||
rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
|
rect.left = clamp(ALIGN(sel->r.left + 1, 2) - 1,
|
||||||
MT9V032_COLUMN_START_MIN,
|
MT9V032_COLUMN_START_MIN,
|
||||||
MT9V032_COLUMN_START_MAX);
|
MT9V032_COLUMN_START_MAX);
|
||||||
rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
|
rect.top = clamp(ALIGN(sel->r.top + 1, 2) - 1,
|
||||||
MT9V032_ROW_START_MIN,
|
MT9V032_ROW_START_MIN,
|
||||||
MT9V032_ROW_START_MAX);
|
MT9V032_ROW_START_MAX);
|
||||||
rect.width = clamp_t(unsigned int, ALIGN(crop->rect.width, 2),
|
rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2),
|
||||||
MT9V032_WINDOW_WIDTH_MIN,
|
MT9V032_WINDOW_WIDTH_MIN,
|
||||||
MT9V032_WINDOW_WIDTH_MAX);
|
MT9V032_WINDOW_WIDTH_MAX);
|
||||||
rect.height = clamp_t(unsigned int, ALIGN(crop->rect.height, 2),
|
rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2),
|
||||||
MT9V032_WINDOW_HEIGHT_MIN,
|
MT9V032_WINDOW_HEIGHT_MIN,
|
||||||
MT9V032_WINDOW_HEIGHT_MAX);
|
MT9V032_WINDOW_HEIGHT_MAX);
|
||||||
|
|
||||||
|
@ -593,17 +598,17 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||||
rect.height = min_t(unsigned int,
|
rect.height = min_t(unsigned int,
|
||||||
rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
|
rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
|
||||||
|
|
||||||
__crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
|
__crop = __mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
|
||||||
|
|
||||||
if (rect.width != __crop->width || rect.height != __crop->height) {
|
if (rect.width != __crop->width || rect.height != __crop->height) {
|
||||||
/* Reset the output image size if the crop rectangle size has
|
/* Reset the output image size if the crop rectangle size has
|
||||||
* been modified.
|
* been modified.
|
||||||
*/
|
*/
|
||||||
__format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
|
__format = __mt9v032_get_pad_format(mt9v032, fh, sel->pad,
|
||||||
crop->which);
|
sel->which);
|
||||||
__format->width = rect.width;
|
__format->width = rect.width;
|
||||||
__format->height = rect.height;
|
__format->height = rect.height;
|
||||||
if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||||
mt9v032->hratio = 1;
|
mt9v032->hratio = 1;
|
||||||
mt9v032->vratio = 1;
|
mt9v032->vratio = 1;
|
||||||
mt9v032_configure_pixel_rate(mt9v032);
|
mt9v032_configure_pixel_rate(mt9v032);
|
||||||
|
@ -611,7 +616,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
*__crop = rect;
|
*__crop = rect;
|
||||||
crop->rect = rect;
|
sel->r = rect;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -844,8 +849,8 @@ static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
|
||||||
.enum_frame_size = mt9v032_enum_frame_size,
|
.enum_frame_size = mt9v032_enum_frame_size,
|
||||||
.get_fmt = mt9v032_get_format,
|
.get_fmt = mt9v032_get_format,
|
||||||
.set_fmt = mt9v032_set_format,
|
.set_fmt = mt9v032_set_format,
|
||||||
.get_crop = mt9v032_get_crop,
|
.get_selection = mt9v032_get_selection,
|
||||||
.set_crop = mt9v032_set_crop,
|
.set_selection = mt9v032_set_selection,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_subdev_ops mt9v032_subdev_ops = {
|
static struct v4l2_subdev_ops mt9v032_subdev_ops = {
|
||||||
|
|
|
@ -220,7 +220,7 @@ static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
|
||||||
msg[1].buf = rbuf;
|
msg[1].buf = rbuf;
|
||||||
|
|
||||||
ret = i2c_transfer(client->adapter, msg, 2);
|
ret = i2c_transfer(client->adapter, msg, 2);
|
||||||
*val = be16_to_cpu(*((u16 *)rbuf));
|
*val = be16_to_cpu(*((__be16 *)rbuf));
|
||||||
|
|
||||||
v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
|
v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
|
||||||
v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE);
|
v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
regs_num = le32_to_cpu(get_unaligned_le32(fw->data));
|
regs_num = get_unaligned_le32(fw->data);
|
||||||
|
|
||||||
v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
|
v4l2_dbg(3, debug, sd, "FW: %s size %zu register sets %d\n",
|
||||||
S5K4ECGX_FIRMWARE, fw->size, regs_num);
|
S5K4ECGX_FIRMWARE, fw->size, regs_num);
|
||||||
|
@ -351,8 +351,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto fw_out;
|
goto fw_out;
|
||||||
}
|
}
|
||||||
crc_file = le32_to_cpu(get_unaligned_le32(fw->data +
|
crc_file = get_unaligned_le32(fw->data + regs_num * FW_RECORD_SIZE);
|
||||||
regs_num * FW_RECORD_SIZE));
|
|
||||||
crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE);
|
crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE);
|
||||||
if (crc != crc_file) {
|
if (crc != crc_file) {
|
||||||
v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file);
|
v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file);
|
||||||
|
@ -361,9 +360,9 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
|
||||||
}
|
}
|
||||||
ptr = fw->data + FW_RECORD_SIZE;
|
ptr = fw->data + FW_RECORD_SIZE;
|
||||||
for (i = 1; i < regs_num; i++) {
|
for (i = 1; i < regs_num; i++) {
|
||||||
addr = le32_to_cpu(get_unaligned_le32(ptr));
|
addr = get_unaligned_le32(ptr);
|
||||||
ptr += sizeof(u32);
|
ptr += sizeof(u32);
|
||||||
val = le16_to_cpu(get_unaligned_le16(ptr));
|
val = get_unaligned_le16(ptr);
|
||||||
ptr += sizeof(u16);
|
ptr += sizeof(u16);
|
||||||
if (addr - addr_inc != 2)
|
if (addr - addr_inc != 2)
|
||||||
err = s5k4ecgx_write(client, addr, val);
|
err = s5k4ecgx_write(client, addr, val);
|
||||||
|
|
|
@ -353,7 +353,7 @@ static struct v4l2_rect s5k5baf_cis_rect = {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw,
|
static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw,
|
||||||
size_t count, const u16 *data)
|
size_t count, const __le16 *data)
|
||||||
{
|
{
|
||||||
struct s5k5baf_fw *f;
|
struct s5k5baf_fw *f;
|
||||||
u16 *d, i, *end;
|
u16 *d, i, *end;
|
||||||
|
@ -421,6 +421,7 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr)
|
||||||
{
|
{
|
||||||
struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
|
struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
|
||||||
__be16 w, r;
|
__be16 w, r;
|
||||||
|
u16 res;
|
||||||
struct i2c_msg msg[] = {
|
struct i2c_msg msg[] = {
|
||||||
{ .addr = c->addr, .flags = 0,
|
{ .addr = c->addr, .flags = 0,
|
||||||
.len = 2, .buf = (u8 *)&w },
|
.len = 2, .buf = (u8 *)&w },
|
||||||
|
@ -434,15 +435,15 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr)
|
||||||
|
|
||||||
w = cpu_to_be16(addr);
|
w = cpu_to_be16(addr);
|
||||||
ret = i2c_transfer(c->adapter, msg, 2);
|
ret = i2c_transfer(c->adapter, msg, 2);
|
||||||
r = be16_to_cpu(r);
|
res = be16_to_cpu(r);
|
||||||
|
|
||||||
v4l2_dbg(3, debug, c, "i2c_read: 0x%04x : 0x%04x\n", addr, r);
|
v4l2_dbg(3, debug, c, "i2c_read: 0x%04x : 0x%04x\n", addr, res);
|
||||||
|
|
||||||
if (ret != 2) {
|
if (ret != 2) {
|
||||||
v4l2_err(c, "i2c_read: error during transfer (%d)\n", ret);
|
v4l2_err(c, "i2c_read: error during transfer (%d)\n", ret);
|
||||||
state->error = ret;
|
state->error = ret;
|
||||||
}
|
}
|
||||||
return r;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void s5k5baf_i2c_write(struct s5k5baf *state, u16 addr, u16 val)
|
static void s5k5baf_i2c_write(struct s5k5baf *state, u16 addr, u16 val)
|
||||||
|
@ -1037,7 +1038,7 @@ static int s5k5baf_load_setfile(struct s5k5baf *state)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = s5k5baf_fw_parse(&c->dev, &state->fw, fw->size / 2,
|
ret = s5k5baf_fw_parse(&c->dev, &state->fw, fw->size / 2,
|
||||||
(u16 *)fw->data);
|
(__le16 *)fw->data);
|
||||||
|
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
|
||||||
|
@ -1793,7 +1794,7 @@ static const struct v4l2_subdev_ops s5k5baf_subdev_ops = {
|
||||||
|
|
||||||
static int s5k5baf_configure_gpios(struct s5k5baf *state)
|
static int s5k5baf_configure_gpios(struct s5k5baf *state)
|
||||||
{
|
{
|
||||||
static const char const *name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" };
|
static const char * const name[] = { "S5K5BAF_STBY", "S5K5BAF_RST" };
|
||||||
struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
|
struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
|
||||||
struct s5k5baf_gpio *g = state->gpios;
|
struct s5k5baf_gpio *g = state->gpios;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
|
@ -348,7 +348,7 @@ static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
|
||||||
msg[1].buf = rbuf;
|
msg[1].buf = rbuf;
|
||||||
|
|
||||||
ret = i2c_transfer(client->adapter, msg, 2);
|
ret = i2c_transfer(client->adapter, msg, 2);
|
||||||
*val = be16_to_cpu(*((u16 *)rbuf));
|
*val = be16_to_cpu(*((__be16 *)rbuf));
|
||||||
|
|
||||||
v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
|
v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
|
||||||
|
|
||||||
|
@ -1161,17 +1161,21 @@ static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
static int s5k6aa_get_selection(struct v4l2_subdev *sd,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_fh *fh,
|
||||||
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
|
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
|
||||||
struct v4l2_rect *rect;
|
struct v4l2_rect *rect;
|
||||||
|
|
||||||
memset(crop->reserved, 0, sizeof(crop->reserved));
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memset(sel->reserved, 0, sizeof(sel->reserved));
|
||||||
|
|
||||||
mutex_lock(&s5k6aa->lock);
|
mutex_lock(&s5k6aa->lock);
|
||||||
rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
|
rect = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
|
||||||
crop->rect = *rect;
|
sel->r = *rect;
|
||||||
mutex_unlock(&s5k6aa->lock);
|
mutex_unlock(&s5k6aa->lock);
|
||||||
|
|
||||||
v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
|
v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
|
||||||
|
@ -1180,35 +1184,39 @@ static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
static int s5k6aa_set_selection(struct v4l2_subdev *sd,
|
||||||
struct v4l2_subdev_crop *crop)
|
struct v4l2_subdev_fh *fh,
|
||||||
|
struct v4l2_subdev_selection *sel)
|
||||||
{
|
{
|
||||||
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
|
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
|
||||||
struct v4l2_mbus_framefmt *mf;
|
struct v4l2_mbus_framefmt *mf;
|
||||||
unsigned int max_x, max_y;
|
unsigned int max_x, max_y;
|
||||||
struct v4l2_rect *crop_r;
|
struct v4l2_rect *crop_r;
|
||||||
|
|
||||||
mutex_lock(&s5k6aa->lock);
|
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||||
crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
|
return -EINVAL;
|
||||||
|
|
||||||
if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
mutex_lock(&s5k6aa->lock);
|
||||||
|
crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
|
||||||
|
|
||||||
|
if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||||
mf = &s5k6aa->preset->mbus_fmt;
|
mf = &s5k6aa->preset->mbus_fmt;
|
||||||
s5k6aa->apply_crop = 1;
|
s5k6aa->apply_crop = 1;
|
||||||
} else {
|
} else {
|
||||||
mf = v4l2_subdev_get_try_format(fh, 0);
|
mf = v4l2_subdev_get_try_format(fh, 0);
|
||||||
}
|
}
|
||||||
v4l_bound_align_image(&crop->rect.width, mf->width,
|
v4l_bound_align_image(&sel->r.width, mf->width,
|
||||||
S5K6AA_WIN_WIDTH_MAX, 1,
|
S5K6AA_WIN_WIDTH_MAX, 1,
|
||||||
&crop->rect.height, mf->height,
|
&sel->r.height, mf->height,
|
||||||
S5K6AA_WIN_HEIGHT_MAX, 1, 0);
|
S5K6AA_WIN_HEIGHT_MAX, 1, 0);
|
||||||
|
|
||||||
max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1;
|
max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1;
|
||||||
max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1;
|
max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1;
|
||||||
|
|
||||||
crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x);
|
sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x);
|
||||||
crop->rect.top = clamp_t(unsigned int, crop->rect.top, 0, max_y);
|
sel->r.top = clamp_t(unsigned int, sel->r.top, 0, max_y);
|
||||||
|
|
||||||
*crop_r = crop->rect;
|
*crop_r = sel->r;
|
||||||
|
|
||||||
mutex_unlock(&s5k6aa->lock);
|
mutex_unlock(&s5k6aa->lock);
|
||||||
|
|
||||||
|
@ -1224,8 +1232,8 @@ static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
|
||||||
.enum_frame_interval = s5k6aa_enum_frame_interval,
|
.enum_frame_interval = s5k6aa_enum_frame_interval,
|
||||||
.get_fmt = s5k6aa_get_fmt,
|
.get_fmt = s5k6aa_get_fmt,
|
||||||
.set_fmt = s5k6aa_set_fmt,
|
.set_fmt = s5k6aa_set_fmt,
|
||||||
.get_crop = s5k6aa_get_crop,
|
.get_selection = s5k6aa_get_selection,
|
||||||
.set_crop = s5k6aa_set_crop,
|
.set_selection = s5k6aa_set_selection,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
|
static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
|
||||||
|
|
|
@ -14,14 +14,9 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
#include <linux/gcd.h>
|
#include <linux/gcd.h>
|
||||||
#include <linux/lcm.h>
|
#include <linux/lcm.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
|
@ -14,19 +14,11 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SMIAPP_PLL_H
|
#ifndef SMIAPP_PLL_H
|
||||||
#define SMIAPP_PLL_H
|
#define SMIAPP_PLL_H
|
||||||
|
|
||||||
#include <linux/device.h>
|
|
||||||
|
|
||||||
/* CSI-2 or CCP-2 */
|
/* CSI-2 or CCP-2 */
|
||||||
#define SMIAPP_PLL_BUS_TYPE_CSI2 0x00
|
#define SMIAPP_PLL_BUS_TYPE_CSI2 0x00
|
||||||
#define SMIAPP_PLL_BUS_TYPE_PARALLEL 0x01
|
#define SMIAPP_PLL_BUS_TYPE_PARALLEL 0x01
|
||||||
|
|
|
@ -18,12 +18,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
@ -31,11 +25,13 @@
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/smiapp.h>
|
#include <linux/smiapp.h>
|
||||||
#include <linux/v4l2-mediabus.h>
|
#include <linux/v4l2-mediabus.h>
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
|
#include <media/v4l2-of.h>
|
||||||
|
|
||||||
#include "smiapp.h"
|
#include "smiapp.h"
|
||||||
|
|
||||||
|
@ -523,14 +519,12 @@ static const struct v4l2_ctrl_ops smiapp_ctrl_ops = {
|
||||||
static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
||||||
{
|
{
|
||||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||||
unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
|
|
||||||
sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
|
|
||||||
unsigned int max, i;
|
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12);
|
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12);
|
||||||
if (rval)
|
if (rval)
|
||||||
return rval;
|
return rval;
|
||||||
|
|
||||||
sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
|
sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
|
||||||
|
|
||||||
sensor->analog_gain = v4l2_ctrl_new_std(
|
sensor->analog_gain = v4l2_ctrl_new_std(
|
||||||
|
@ -576,21 +570,11 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
||||||
ARRAY_SIZE(smiapp_test_patterns) - 1,
|
ARRAY_SIZE(smiapp_test_patterns) - 1,
|
||||||
0, 0, smiapp_test_patterns);
|
0, 0, smiapp_test_patterns);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
|
|
||||||
int max_value = (1 << sensor->csi_format->width) - 1;
|
|
||||||
sensor->test_data[i] =
|
|
||||||
v4l2_ctrl_new_std(
|
|
||||||
&sensor->pixel_array->ctrl_handler,
|
|
||||||
&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i,
|
|
||||||
0, max_value, 1, max_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sensor->pixel_array->ctrl_handler.error) {
|
if (sensor->pixel_array->ctrl_handler.error) {
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"pixel array controls initialization failed (%d)\n",
|
"pixel array controls initialization failed (%d)\n",
|
||||||
sensor->pixel_array->ctrl_handler.error);
|
sensor->pixel_array->ctrl_handler.error);
|
||||||
rval = sensor->pixel_array->ctrl_handler.error;
|
return sensor->pixel_array->ctrl_handler.error;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor->pixel_array->sd.ctrl_handler =
|
sensor->pixel_array->sd.ctrl_handler =
|
||||||
|
@ -600,16 +584,10 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
||||||
|
|
||||||
rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
|
rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
|
||||||
if (rval)
|
if (rval)
|
||||||
goto error;
|
return rval;
|
||||||
|
|
||||||
sensor->src->ctrl_handler.lock = &sensor->mutex;
|
sensor->src->ctrl_handler.lock = &sensor->mutex;
|
||||||
|
|
||||||
for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++);
|
|
||||||
|
|
||||||
sensor->link_freq = v4l2_ctrl_new_int_menu(
|
|
||||||
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
|
|
||||||
V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
|
|
||||||
__ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock);
|
|
||||||
|
|
||||||
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
|
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
|
||||||
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
|
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
|
||||||
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
|
V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
|
||||||
|
@ -618,20 +596,41 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"src controls initialization failed (%d)\n",
|
"src controls initialization failed (%d)\n",
|
||||||
sensor->src->ctrl_handler.error);
|
sensor->src->ctrl_handler.error);
|
||||||
rval = sensor->src->ctrl_handler.error;
|
return sensor->src->ctrl_handler.error;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor->src->sd.ctrl_handler =
|
sensor->src->sd.ctrl_handler = &sensor->src->ctrl_handler;
|
||||||
&sensor->src->ctrl_handler;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
/*
|
||||||
v4l2_ctrl_handler_free(&sensor->pixel_array->ctrl_handler);
|
* For controls that require information on available media bus codes
|
||||||
v4l2_ctrl_handler_free(&sensor->src->ctrl_handler);
|
* and linke frequencies.
|
||||||
|
*/
|
||||||
|
static int smiapp_init_late_controls(struct smiapp_sensor *sensor)
|
||||||
|
{
|
||||||
|
unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
|
||||||
|
sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
|
||||||
|
unsigned int max, i;
|
||||||
|
|
||||||
return rval;
|
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
|
||||||
|
int max_value = (1 << sensor->csi_format->width) - 1;
|
||||||
|
|
||||||
|
sensor->test_data[i] = v4l2_ctrl_new_std(
|
||||||
|
&sensor->pixel_array->ctrl_handler,
|
||||||
|
&smiapp_ctrl_ops, V4L2_CID_TEST_PATTERN_RED + i,
|
||||||
|
0, max_value, 1, max_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++);
|
||||||
|
|
||||||
|
sensor->link_freq = v4l2_ctrl_new_int_menu(
|
||||||
|
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
|
||||||
|
V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
|
||||||
|
__ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock);
|
||||||
|
|
||||||
|
return sensor->src->ctrl_handler.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smiapp_free_controls(struct smiapp_sensor *sensor)
|
static void smiapp_free_controls(struct smiapp_sensor *sensor)
|
||||||
|
@ -1487,7 +1486,7 @@ static int smiapp_start_streaming(struct smiapp_sensor *sensor)
|
||||||
if (rval < 0)
|
if (rval < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if ((sensor->flash_capability &
|
if ((sensor->limits[SMIAPP_LIMIT_FLASH_MODE_CAPABILITY] &
|
||||||
(SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
|
(SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
|
||||||
SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) &&
|
SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) &&
|
||||||
sensor->platform_data->strobe_setup != NULL &&
|
sensor->platform_data->strobe_setup != NULL &&
|
||||||
|
@ -2338,10 +2337,9 @@ static DEVICE_ATTR(ident, S_IRUGO, smiapp_sysfs_ident_read, NULL);
|
||||||
* V4L2 subdev core operations
|
* V4L2 subdev core operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int smiapp_identify_module(struct v4l2_subdev *subdev)
|
static int smiapp_identify_module(struct smiapp_sensor *sensor)
|
||||||
{
|
{
|
||||||
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
|
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||||
struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
|
||||||
struct smiapp_module_info *minfo = &sensor->minfo;
|
struct smiapp_module_info *minfo = &sensor->minfo;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
|
@ -2464,8 +2462,6 @@ static int smiapp_identify_module(struct v4l2_subdev *subdev)
|
||||||
minfo->name, minfo->manufacturer_id, minfo->model_id,
|
minfo->name, minfo->manufacturer_id, minfo->model_id,
|
||||||
minfo->revision_number_major);
|
minfo->revision_number_major);
|
||||||
|
|
||||||
strlcpy(subdev->name, sensor->minfo.name, sizeof(subdev->name));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2473,13 +2469,71 @@ static const struct v4l2_subdev_ops smiapp_ops;
|
||||||
static const struct v4l2_subdev_internal_ops smiapp_internal_ops;
|
static const struct v4l2_subdev_internal_ops smiapp_internal_ops;
|
||||||
static const struct media_entity_operations smiapp_entity_ops;
|
static const struct media_entity_operations smiapp_entity_ops;
|
||||||
|
|
||||||
static int smiapp_registered(struct v4l2_subdev *subdev)
|
static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
|
||||||
{
|
{
|
||||||
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
|
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||||
struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
struct smiapp_subdev *ssds[] = {
|
||||||
|
sensor->scaler,
|
||||||
|
sensor->binner,
|
||||||
|
sensor->pixel_array,
|
||||||
|
};
|
||||||
|
unsigned int i;
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
for (i = 0; i < SMIAPP_SUBDEVS - 1; i++) {
|
||||||
|
struct smiapp_subdev *this = ssds[i + 1];
|
||||||
|
struct smiapp_subdev *last = ssds[i];
|
||||||
|
|
||||||
|
if (!last)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rval = media_entity_init(&this->sd.entity,
|
||||||
|
this->npads, this->pads, 0);
|
||||||
|
if (rval) {
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"media_entity_init failed\n");
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = media_entity_create_link(&this->sd.entity,
|
||||||
|
this->source_pad,
|
||||||
|
&last->sd.entity,
|
||||||
|
last->sink_pad,
|
||||||
|
MEDIA_LNK_FL_ENABLED |
|
||||||
|
MEDIA_LNK_FL_IMMUTABLE);
|
||||||
|
if (rval) {
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"media_entity_create_link failed\n");
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
|
||||||
|
&this->sd);
|
||||||
|
if (rval) {
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"v4l2_device_register_subdev failed\n");
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smiapp_cleanup(struct smiapp_sensor *sensor)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||||
|
|
||||||
|
device_remove_file(&client->dev, &dev_attr_nvm);
|
||||||
|
device_remove_file(&client->dev, &dev_attr_ident);
|
||||||
|
|
||||||
|
smiapp_free_controls(sensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int smiapp_init(struct smiapp_sensor *sensor)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||||
struct smiapp_pll *pll = &sensor->pll;
|
struct smiapp_pll *pll = &sensor->pll;
|
||||||
struct smiapp_subdev *last = NULL;
|
struct smiapp_subdev *last = NULL;
|
||||||
u32 tmp;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
|
@ -2490,7 +2544,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sensor->platform_data->set_xclk) {
|
if (!sensor->platform_data->set_xclk) {
|
||||||
sensor->ext_clk = devm_clk_get(&client->dev, "ext_clk");
|
sensor->ext_clk = devm_clk_get(&client->dev, NULL);
|
||||||
if (IS_ERR(sensor->ext_clk)) {
|
if (IS_ERR(sensor->ext_clk)) {
|
||||||
dev_err(&client->dev, "could not get clock\n");
|
dev_err(&client->dev, "could not get clock\n");
|
||||||
return PTR_ERR(sensor->ext_clk);
|
return PTR_ERR(sensor->ext_clk);
|
||||||
|
@ -2522,7 +2576,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
if (rval)
|
if (rval)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
rval = smiapp_identify_module(subdev);
|
rval = smiapp_identify_module(sensor);
|
||||||
if (rval) {
|
if (rval) {
|
||||||
rval = -ENODEV;
|
rval = -ENODEV;
|
||||||
goto out_power_off;
|
goto out_power_off;
|
||||||
|
@ -2602,13 +2656,13 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
if (sensor->nvm == NULL) {
|
if (sensor->nvm == NULL) {
|
||||||
dev_err(&client->dev, "nvm buf allocation failed\n");
|
dev_err(&client->dev, "nvm buf allocation failed\n");
|
||||||
rval = -ENOMEM;
|
rval = -ENOMEM;
|
||||||
goto out_ident_release;
|
goto out_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
|
if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
|
||||||
dev_err(&client->dev, "sysfs nvm entry failed\n");
|
dev_err(&client->dev, "sysfs nvm entry failed\n");
|
||||||
rval = -EBUSY;
|
rval = -EBUSY;
|
||||||
goto out_ident_release;
|
goto out_cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2643,18 +2697,11 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
|
pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
|
||||||
pll->csi2.lanes = sensor->platform_data->lanes;
|
pll->csi2.lanes = sensor->platform_data->lanes;
|
||||||
pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
|
pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
|
||||||
pll->flags = smiapp_call_quirk(sensor, pll_flags);
|
|
||||||
pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
|
pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
|
||||||
/* Profile 0 sensors have no separate OP clock branch. */
|
/* Profile 0 sensors have no separate OP clock branch. */
|
||||||
if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
|
if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
|
||||||
pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
|
pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
|
||||||
|
|
||||||
rval = smiapp_get_mbus_formats(sensor);
|
|
||||||
if (rval) {
|
|
||||||
rval = -ENODEV;
|
|
||||||
goto out_nvm_release;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < SMIAPP_SUBDEVS; i++) {
|
for (i = 0; i < SMIAPP_SUBDEVS; i++) {
|
||||||
struct {
|
struct {
|
||||||
struct smiapp_subdev *ssd;
|
struct smiapp_subdev *ssd;
|
||||||
|
@ -2711,34 +2758,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
this->sd.owner = THIS_MODULE;
|
this->sd.owner = THIS_MODULE;
|
||||||
v4l2_set_subdevdata(&this->sd, client);
|
v4l2_set_subdevdata(&this->sd, client);
|
||||||
|
|
||||||
rval = media_entity_init(&this->sd.entity,
|
|
||||||
this->npads, this->pads, 0);
|
|
||||||
if (rval) {
|
|
||||||
dev_err(&client->dev,
|
|
||||||
"media_entity_init failed\n");
|
|
||||||
goto out_nvm_release;
|
|
||||||
}
|
|
||||||
|
|
||||||
rval = media_entity_create_link(&this->sd.entity,
|
|
||||||
this->source_pad,
|
|
||||||
&last->sd.entity,
|
|
||||||
last->sink_pad,
|
|
||||||
MEDIA_LNK_FL_ENABLED |
|
|
||||||
MEDIA_LNK_FL_IMMUTABLE);
|
|
||||||
if (rval) {
|
|
||||||
dev_err(&client->dev,
|
|
||||||
"media_entity_create_link failed\n");
|
|
||||||
goto out_nvm_release;
|
|
||||||
}
|
|
||||||
|
|
||||||
rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
|
|
||||||
&this->sd);
|
|
||||||
if (rval) {
|
|
||||||
dev_err(&client->dev,
|
|
||||||
"v4l2_device_register_subdev failed\n");
|
|
||||||
goto out_nvm_release;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = this;
|
last = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2750,40 +2769,66 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
smiapp_read_frame_fmt(sensor);
|
smiapp_read_frame_fmt(sensor);
|
||||||
rval = smiapp_init_controls(sensor);
|
rval = smiapp_init_controls(sensor);
|
||||||
if (rval < 0)
|
if (rval < 0)
|
||||||
goto out_nvm_release;
|
goto out_cleanup;
|
||||||
|
|
||||||
|
rval = smiapp_call_quirk(sensor, init);
|
||||||
|
if (rval)
|
||||||
|
goto out_cleanup;
|
||||||
|
|
||||||
|
rval = smiapp_get_mbus_formats(sensor);
|
||||||
|
if (rval) {
|
||||||
|
rval = -ENODEV;
|
||||||
|
goto out_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = smiapp_init_late_controls(sensor);
|
||||||
|
if (rval) {
|
||||||
|
rval = -ENODEV;
|
||||||
|
goto out_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_lock(&sensor->mutex);
|
mutex_lock(&sensor->mutex);
|
||||||
rval = smiapp_update_mode(sensor);
|
rval = smiapp_update_mode(sensor);
|
||||||
mutex_unlock(&sensor->mutex);
|
mutex_unlock(&sensor->mutex);
|
||||||
if (rval) {
|
if (rval) {
|
||||||
dev_err(&client->dev, "update mode failed\n");
|
dev_err(&client->dev, "update mode failed\n");
|
||||||
goto out_nvm_release;
|
goto out_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor->streaming = false;
|
sensor->streaming = false;
|
||||||
sensor->dev_init_done = true;
|
sensor->dev_init_done = true;
|
||||||
|
|
||||||
/* check flash capability */
|
|
||||||
rval = smiapp_read(sensor, SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, &tmp);
|
|
||||||
sensor->flash_capability = tmp;
|
|
||||||
if (rval)
|
|
||||||
goto out_nvm_release;
|
|
||||||
|
|
||||||
smiapp_power_off(sensor);
|
smiapp_power_off(sensor);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_nvm_release:
|
out_cleanup:
|
||||||
device_remove_file(&client->dev, &dev_attr_nvm);
|
smiapp_cleanup(sensor);
|
||||||
|
|
||||||
out_ident_release:
|
|
||||||
device_remove_file(&client->dev, &dev_attr_ident);
|
|
||||||
|
|
||||||
out_power_off:
|
out_power_off:
|
||||||
smiapp_power_off(sensor);
|
smiapp_power_off(sensor);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||||
|
{
|
||||||
|
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
if (!client->dev.of_node) {
|
||||||
|
rval = smiapp_init(sensor);
|
||||||
|
if (rval)
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = smiapp_register_subdevs(sensor);
|
||||||
|
if (rval)
|
||||||
|
smiapp_cleanup(sensor);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||||
{
|
{
|
||||||
struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
|
struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
|
||||||
|
@ -2927,19 +2972,125 @@ static int smiapp_resume(struct device *dev)
|
||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
|
||||||
|
{
|
||||||
|
struct smiapp_platform_data *pdata;
|
||||||
|
struct v4l2_of_endpoint bus_cfg;
|
||||||
|
struct device_node *ep;
|
||||||
|
struct property *prop;
|
||||||
|
__be32 *val;
|
||||||
|
uint32_t asize;
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
unsigned int i;
|
||||||
|
#endif
|
||||||
|
int rval;
|
||||||
|
|
||||||
|
if (!dev->of_node)
|
||||||
|
return dev->platform_data;
|
||||||
|
|
||||||
|
ep = of_graph_get_next_endpoint(dev->of_node, NULL);
|
||||||
|
if (!ep)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||||
|
if (!pdata) {
|
||||||
|
rval = -ENOMEM;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
v4l2_of_parse_endpoint(ep, &bus_cfg);
|
||||||
|
|
||||||
|
switch (bus_cfg.bus_type) {
|
||||||
|
case V4L2_MBUS_CSI2:
|
||||||
|
pdata->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2;
|
||||||
|
break;
|
||||||
|
/* FIXME: add CCP2 support. */
|
||||||
|
default:
|
||||||
|
rval = -EINVAL;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdata->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
|
||||||
|
dev_dbg(dev, "lanes %u\n", pdata->lanes);
|
||||||
|
|
||||||
|
/* xshutdown GPIO is optional */
|
||||||
|
pdata->xshutdown = of_get_named_gpio(dev->of_node, "reset-gpios", 0);
|
||||||
|
|
||||||
|
/* NVM size is not mandatory */
|
||||||
|
of_property_read_u32(dev->of_node, "nokia,nvm-size",
|
||||||
|
&pdata->nvm_size);
|
||||||
|
|
||||||
|
rval = of_property_read_u32(dev->of_node, "clock-frequency",
|
||||||
|
&pdata->ext_clk);
|
||||||
|
if (rval) {
|
||||||
|
dev_warn(dev, "can't get clock-frequency\n");
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown,
|
||||||
|
pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode);
|
||||||
|
|
||||||
|
rval = of_get_property(
|
||||||
|
dev->of_node, "link-frequencies", &asize) ? 0 : -ENOENT;
|
||||||
|
if (rval) {
|
||||||
|
dev_warn(dev, "can't get link-frequencies array size\n");
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdata->op_sys_clock = devm_kzalloc(dev, asize, GFP_KERNEL);
|
||||||
|
if (!pdata->op_sys_clock) {
|
||||||
|
rval = -ENOMEM;
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
asize /= sizeof(*pdata->op_sys_clock);
|
||||||
|
/*
|
||||||
|
* Read a 64-bit array --- this will be replaced with a
|
||||||
|
* of_property_read_u64_array() once it's merged.
|
||||||
|
*/
|
||||||
|
prop = of_find_property(dev->of_node, "link-frequencies", NULL);
|
||||||
|
if (!prop)
|
||||||
|
goto out_err;
|
||||||
|
if (!prop->value)
|
||||||
|
goto out_err;
|
||||||
|
if (asize * sizeof(*pdata->op_sys_clock) > prop->length)
|
||||||
|
goto out_err;
|
||||||
|
val = prop->value;
|
||||||
|
if (IS_ERR(val))
|
||||||
|
goto out_err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
for (i = 0; i < asize; i++)
|
||||||
|
pdata->op_sys_clock[i] = of_read_number(val + i * 2, 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; asize > 0; asize--)
|
||||||
|
dev_dbg(dev, "freq %d: %lld\n", asize - 1,
|
||||||
|
pdata->op_sys_clock[asize - 1]);
|
||||||
|
|
||||||
|
of_node_put(ep);
|
||||||
|
return pdata;
|
||||||
|
|
||||||
|
out_err:
|
||||||
|
of_node_put(ep);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int smiapp_probe(struct i2c_client *client,
|
static int smiapp_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *devid)
|
const struct i2c_device_id *devid)
|
||||||
{
|
{
|
||||||
struct smiapp_sensor *sensor;
|
struct smiapp_sensor *sensor;
|
||||||
|
struct smiapp_platform_data *pdata = smiapp_get_pdata(&client->dev);
|
||||||
|
int rval;
|
||||||
|
|
||||||
if (client->dev.platform_data == NULL)
|
if (pdata == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
|
sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
|
||||||
if (sensor == NULL)
|
if (sensor == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
sensor->platform_data = client->dev.platform_data;
|
sensor->platform_data = pdata;
|
||||||
mutex_init(&sensor->mutex);
|
mutex_init(&sensor->mutex);
|
||||||
mutex_init(&sensor->power_mutex);
|
mutex_init(&sensor->power_mutex);
|
||||||
sensor->src = &sensor->ssds[sensor->ssds_used];
|
sensor->src = &sensor->ssds[sensor->ssds_used];
|
||||||
|
@ -2950,8 +3101,27 @@ static int smiapp_probe(struct i2c_client *client,
|
||||||
sensor->src->sensor = sensor;
|
sensor->src->sensor = sensor;
|
||||||
|
|
||||||
sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
|
sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
|
||||||
return media_entity_init(&sensor->src->sd.entity, 2,
|
rval = media_entity_init(&sensor->src->sd.entity, 2,
|
||||||
sensor->src->pads, 0);
|
sensor->src->pads, 0);
|
||||||
|
if (rval < 0)
|
||||||
|
return rval;
|
||||||
|
|
||||||
|
if (client->dev.of_node) {
|
||||||
|
rval = smiapp_init(sensor);
|
||||||
|
if (rval)
|
||||||
|
goto out_media_entity_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rval = v4l2_async_register_subdev(&sensor->src->sd);
|
||||||
|
if (rval < 0)
|
||||||
|
goto out_media_entity_cleanup;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_media_entity_cleanup:
|
||||||
|
media_entity_cleanup(&sensor->src->sd.entity);
|
||||||
|
|
||||||
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smiapp_remove(struct i2c_client *client)
|
static int smiapp_remove(struct i2c_client *client)
|
||||||
|
@ -2960,6 +3130,8 @@ static int smiapp_remove(struct i2c_client *client)
|
||||||
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
|
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
v4l2_async_unregister_subdev(subdev);
|
||||||
|
|
||||||
if (sensor->power_count) {
|
if (sensor->power_count) {
|
||||||
if (gpio_is_valid(sensor->platform_data->xshutdown))
|
if (gpio_is_valid(sensor->platform_data->xshutdown))
|
||||||
gpio_set_value(sensor->platform_data->xshutdown, 0);
|
gpio_set_value(sensor->platform_data->xshutdown, 0);
|
||||||
|
@ -2970,19 +3142,20 @@ static int smiapp_remove(struct i2c_client *client)
|
||||||
sensor->power_count = 0;
|
sensor->power_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_remove_file(&client->dev, &dev_attr_ident);
|
|
||||||
if (sensor->nvm)
|
|
||||||
device_remove_file(&client->dev, &dev_attr_nvm);
|
|
||||||
|
|
||||||
for (i = 0; i < sensor->ssds_used; i++) {
|
for (i = 0; i < sensor->ssds_used; i++) {
|
||||||
v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
|
v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
|
||||||
media_entity_cleanup(&sensor->ssds[i].sd.entity);
|
media_entity_cleanup(&sensor->ssds[i].sd.entity);
|
||||||
}
|
}
|
||||||
smiapp_free_controls(sensor);
|
smiapp_cleanup(sensor);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id smiapp_of_table[] = {
|
||||||
|
{ .compatible = "nokia,smia" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
static const struct i2c_device_id smiapp_id_table[] = {
|
static const struct i2c_device_id smiapp_id_table[] = {
|
||||||
{ SMIAPP_NAME, 0 },
|
{ SMIAPP_NAME, 0 },
|
||||||
{ },
|
{ },
|
||||||
|
@ -2996,6 +3169,7 @@ static const struct dev_pm_ops smiapp_pm_ops = {
|
||||||
|
|
||||||
static struct i2c_driver smiapp_i2c_driver = {
|
static struct i2c_driver smiapp_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
|
.of_match_table = smiapp_of_table,
|
||||||
.name = SMIAPP_NAME,
|
.name = SMIAPP_NAME,
|
||||||
.pm = &smiapp_pm_ops,
|
.pm = &smiapp_pm_ops,
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "smiapp.h"
|
#include "smiapp.h"
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY 0
|
#define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY 0
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
@ -220,9 +214,11 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
|
||||||
return smiapp_write_8(sensor, 0x3328, 0x80);
|
return smiapp_write_8(sensor, 0x3328, 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long jt8ev1_pll_flags(struct smiapp_sensor *sensor)
|
static int jt8ev1_init(struct smiapp_sensor *sensor)
|
||||||
{
|
{
|
||||||
return SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
|
sensor->pll.flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct smiapp_quirk smiapp_jt8ev1_quirk = {
|
const struct smiapp_quirk smiapp_jt8ev1_quirk = {
|
||||||
|
@ -230,7 +226,7 @@ const struct smiapp_quirk smiapp_jt8ev1_quirk = {
|
||||||
.post_poweron = jt8ev1_post_poweron,
|
.post_poweron = jt8ev1_post_poweron,
|
||||||
.pre_streamon = jt8ev1_pre_streamon,
|
.pre_streamon = jt8ev1_pre_streamon,
|
||||||
.post_streamoff = jt8ev1_post_streamoff,
|
.post_streamoff = jt8ev1_post_streamoff,
|
||||||
.pll_flags = jt8ev1_pll_flags,
|
.init = jt8ev1_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tcm8500md_limits(struct smiapp_sensor *sensor)
|
static int tcm8500md_limits(struct smiapp_sensor *sensor)
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SMIAPP_QUIRK__
|
#ifndef __SMIAPP_QUIRK__
|
||||||
|
@ -35,6 +29,9 @@ struct smiapp_sensor;
|
||||||
* @post_poweron: Called always after the sensor has been fully powered on.
|
* @post_poweron: Called always after the sensor has been fully powered on.
|
||||||
* @pre_streamon: Called just before streaming is enabled.
|
* @pre_streamon: Called just before streaming is enabled.
|
||||||
* @post_streamon: Called right after stopping streaming.
|
* @post_streamon: Called right after stopping streaming.
|
||||||
|
* @pll_flags: Return flags for the PLL calculator.
|
||||||
|
* @init: Quirk initialisation, called the last in probe(). This is
|
||||||
|
* also appropriate for adding sensor specific controls, for instance.
|
||||||
* @reg_access: Register access quirk. The quirk may divert the access
|
* @reg_access: Register access quirk. The quirk may divert the access
|
||||||
* to another register, or no register at all.
|
* to another register, or no register at all.
|
||||||
*
|
*
|
||||||
|
@ -53,6 +50,7 @@ struct smiapp_quirk {
|
||||||
int (*pre_streamon)(struct smiapp_sensor *sensor);
|
int (*pre_streamon)(struct smiapp_sensor *sensor);
|
||||||
int (*post_streamoff)(struct smiapp_sensor *sensor);
|
int (*post_streamoff)(struct smiapp_sensor *sensor);
|
||||||
unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
|
unsigned long (*pll_flags)(struct smiapp_sensor *sensor);
|
||||||
|
int (*init)(struct smiapp_sensor *sensor);
|
||||||
int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg,
|
int (*reg_access)(struct smiapp_sensor *sensor, bool write, u32 *reg,
|
||||||
u32 *val);
|
u32 *val);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -74,14 +72,14 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
|
||||||
.val = _val, \
|
.val = _val, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define smiapp_call_quirk(_sensor, _quirk, ...) \
|
#define smiapp_call_quirk(sensor, _quirk, ...) \
|
||||||
(_sensor->minfo.quirk && \
|
((sensor)->minfo.quirk && \
|
||||||
_sensor->minfo.quirk->_quirk ? \
|
(sensor)->minfo.quirk->_quirk ? \
|
||||||
_sensor->minfo.quirk->_quirk(_sensor, ##__VA_ARGS__) : 0)
|
(sensor)->minfo.quirk->_quirk(sensor, ##__VA_ARGS__) : 0)
|
||||||
|
|
||||||
#define smiapp_needs_quirk(_sensor, _quirk) \
|
#define smiapp_needs_quirk(sensor, _quirk) \
|
||||||
(_sensor->minfo.quirk ? \
|
((sensor)->minfo.quirk ? \
|
||||||
_sensor->minfo.quirk->flags & _quirk : 0)
|
(sensor)->minfo.quirk->flags & _quirk : 0)
|
||||||
|
|
||||||
extern const struct smiapp_quirk smiapp_jt8ev1_quirk;
|
extern const struct smiapp_quirk smiapp_jt8ev1_quirk;
|
||||||
extern const struct smiapp_quirk smiapp_imx125es_quirk;
|
extern const struct smiapp_quirk smiapp_imx125es_quirk;
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
#define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r))
|
#define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 16) | (r))
|
||||||
#define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r))
|
#define SMIAPP_REG_MK_U16(r) ((SMIAPP_REG_16BIT << 16) | (r))
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SMIAPP_REG_H_
|
#ifndef __SMIAPP_REG_H_
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SMIAPP_REGS_H
|
#ifndef SMIAPP_REGS_H
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* 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 St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SMIAPP_PRIV_H_
|
#ifndef __SMIAPP_PRIV_H_
|
||||||
|
@ -222,7 +216,6 @@ struct smiapp_sensor {
|
||||||
u8 scaling_mode;
|
u8 scaling_mode;
|
||||||
|
|
||||||
u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
|
u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
|
||||||
u8 flash_capability;
|
|
||||||
u8 frame_skip;
|
u8 frame_skip;
|
||||||
|
|
||||||
int power_count;
|
int power_count;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <media/v4l2-clk.h>
|
#include <media/v4l2-clk.h>
|
||||||
#include <media/v4l2-subdev.h>
|
#include <media/v4l2-subdev.h>
|
||||||
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-ctrls.h>
|
||||||
|
#include <media/v4l2-image-sizes.h>
|
||||||
|
|
||||||
#define VAL_SET(x, mask, rshift, lshift) \
|
#define VAL_SET(x, mask, rshift, lshift) \
|
||||||
((((x) >> rshift) & mask) << lshift)
|
((((x) >> rshift) & mask) << lshift)
|
||||||
|
@ -268,33 +269,10 @@ struct regval_list {
|
||||||
u8 value;
|
u8 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Supported resolutions */
|
|
||||||
enum ov2640_width {
|
|
||||||
W_QCIF = 176,
|
|
||||||
W_QVGA = 320,
|
|
||||||
W_CIF = 352,
|
|
||||||
W_VGA = 640,
|
|
||||||
W_SVGA = 800,
|
|
||||||
W_XGA = 1024,
|
|
||||||
W_SXGA = 1280,
|
|
||||||
W_UXGA = 1600,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ov2640_height {
|
|
||||||
H_QCIF = 144,
|
|
||||||
H_QVGA = 240,
|
|
||||||
H_CIF = 288,
|
|
||||||
H_VGA = 480,
|
|
||||||
H_SVGA = 600,
|
|
||||||
H_XGA = 768,
|
|
||||||
H_SXGA = 1024,
|
|
||||||
H_UXGA = 1200,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ov2640_win_size {
|
struct ov2640_win_size {
|
||||||
char *name;
|
char *name;
|
||||||
enum ov2640_width width;
|
u32 width;
|
||||||
enum ov2640_height height;
|
u32 height;
|
||||||
const struct regval_list *regs;
|
const struct regval_list *regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -495,17 +473,17 @@ static const struct regval_list ov2640_init_regs[] = {
|
||||||
static const struct regval_list ov2640_size_change_preamble_regs[] = {
|
static const struct regval_list ov2640_size_change_preamble_regs[] = {
|
||||||
{ BANK_SEL, BANK_SEL_DSP },
|
{ BANK_SEL, BANK_SEL_DSP },
|
||||||
{ RESET, RESET_DVP },
|
{ RESET, RESET_DVP },
|
||||||
{ HSIZE8, HSIZE8_SET(W_UXGA) },
|
{ HSIZE8, HSIZE8_SET(UXGA_WIDTH) },
|
||||||
{ VSIZE8, VSIZE8_SET(H_UXGA) },
|
{ VSIZE8, VSIZE8_SET(UXGA_HEIGHT) },
|
||||||
{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
|
{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
|
||||||
CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
|
CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
|
||||||
{ HSIZE, HSIZE_SET(W_UXGA) },
|
{ HSIZE, HSIZE_SET(UXGA_WIDTH) },
|
||||||
{ VSIZE, VSIZE_SET(H_UXGA) },
|
{ VSIZE, VSIZE_SET(UXGA_HEIGHT) },
|
||||||
{ XOFFL, XOFFL_SET(0) },
|
{ XOFFL, XOFFL_SET(0) },
|
||||||
{ YOFFL, YOFFL_SET(0) },
|
{ YOFFL, YOFFL_SET(0) },
|
||||||
{ VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) |
|
{ VHYX, VHYX_HSIZE_SET(UXGA_WIDTH) | VHYX_VSIZE_SET(UXGA_HEIGHT) |
|
||||||
VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},
|
VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},
|
||||||
{ TEST, TEST_HSIZE_SET(W_UXGA) },
|
{ TEST, TEST_HSIZE_SET(UXGA_WIDTH) },
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -519,45 +497,45 @@ static const struct regval_list ov2640_size_change_preamble_regs[] = {
|
||||||
{ RESET, 0x00}
|
{ RESET, 0x00}
|
||||||
|
|
||||||
static const struct regval_list ov2640_qcif_regs[] = {
|
static const struct regval_list ov2640_qcif_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4),
|
PER_SIZE_REG_SEQ(QCIF_WIDTH, QCIF_HEIGHT, 3, 3, 4),
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_qvga_regs[] = {
|
static const struct regval_list ov2640_qvga_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4),
|
PER_SIZE_REG_SEQ(QVGA_WIDTH, QVGA_HEIGHT, 2, 2, 4),
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_cif_regs[] = {
|
static const struct regval_list ov2640_cif_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8),
|
PER_SIZE_REG_SEQ(CIF_WIDTH, CIF_HEIGHT, 2, 2, 8),
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_vga_regs[] = {
|
static const struct regval_list ov2640_vga_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2),
|
PER_SIZE_REG_SEQ(VGA_WIDTH, VGA_HEIGHT, 0, 0, 2),
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_svga_regs[] = {
|
static const struct regval_list ov2640_svga_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2),
|
PER_SIZE_REG_SEQ(SVGA_WIDTH, SVGA_HEIGHT, 1, 1, 2),
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_xga_regs[] = {
|
static const struct regval_list ov2640_xga_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2),
|
PER_SIZE_REG_SEQ(XGA_WIDTH, XGA_HEIGHT, 0, 0, 2),
|
||||||
{ CTRLI, 0x00},
|
{ CTRLI, 0x00},
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_sxga_regs[] = {
|
static const struct regval_list ov2640_sxga_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2),
|
PER_SIZE_REG_SEQ(SXGA_WIDTH, SXGA_HEIGHT, 0, 0, 2),
|
||||||
{ CTRLI, 0x00},
|
{ CTRLI, 0x00},
|
||||||
{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
|
{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regval_list ov2640_uxga_regs[] = {
|
static const struct regval_list ov2640_uxga_regs[] = {
|
||||||
PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0),
|
PER_SIZE_REG_SEQ(UXGA_WIDTH, UXGA_HEIGHT, 0, 0, 0),
|
||||||
{ CTRLI, 0x00},
|
{ CTRLI, 0x00},
|
||||||
{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
|
{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
|
||||||
ENDMARKER,
|
ENDMARKER,
|
||||||
|
@ -567,14 +545,14 @@ static const struct regval_list ov2640_uxga_regs[] = {
|
||||||
{.name = n, .width = w , .height = h, .regs = r }
|
{.name = n, .width = w , .height = h, .regs = r }
|
||||||
|
|
||||||
static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
|
static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
|
||||||
OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs),
|
OV2640_SIZE("QCIF", QCIF_WIDTH, QCIF_HEIGHT, ov2640_qcif_regs),
|
||||||
OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs),
|
OV2640_SIZE("QVGA", QVGA_WIDTH, QVGA_HEIGHT, ov2640_qvga_regs),
|
||||||
OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs),
|
OV2640_SIZE("CIF", CIF_WIDTH, CIF_HEIGHT, ov2640_cif_regs),
|
||||||
OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs),
|
OV2640_SIZE("VGA", VGA_WIDTH, VGA_HEIGHT, ov2640_vga_regs),
|
||||||
OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs),
|
OV2640_SIZE("SVGA", SVGA_WIDTH, SVGA_HEIGHT, ov2640_svga_regs),
|
||||||
OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs),
|
OV2640_SIZE("XGA", XGA_WIDTH, XGA_HEIGHT, ov2640_xga_regs),
|
||||||
OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs),
|
OV2640_SIZE("SXGA", SXGA_WIDTH, SXGA_HEIGHT, ov2640_sxga_regs),
|
||||||
OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs),
|
OV2640_SIZE("UXGA", UXGA_WIDTH, UXGA_HEIGHT, ov2640_uxga_regs),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -867,7 +845,7 @@ static int ov2640_g_fmt(struct v4l2_subdev *sd,
|
||||||
struct ov2640_priv *priv = to_ov2640(client);
|
struct ov2640_priv *priv = to_ov2640(client);
|
||||||
|
|
||||||
if (!priv->win) {
|
if (!priv->win) {
|
||||||
u32 width = W_SVGA, height = H_SVGA;
|
u32 width = SVGA_WIDTH, height = SVGA_HEIGHT;
|
||||||
priv->win = ov2640_select_win(&width, &height);
|
priv->win = ov2640_select_win(&width, &height);
|
||||||
priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
|
priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
|
||||||
}
|
}
|
||||||
|
@ -954,8 +932,8 @@ static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
|
||||||
{
|
{
|
||||||
a->c.left = 0;
|
a->c.left = 0;
|
||||||
a->c.top = 0;
|
a->c.top = 0;
|
||||||
a->c.width = W_UXGA;
|
a->c.width = UXGA_WIDTH;
|
||||||
a->c.height = H_UXGA;
|
a->c.height = UXGA_HEIGHT;
|
||||||
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -965,8 +943,8 @@ static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
|
||||||
{
|
{
|
||||||
a->bounds.left = 0;
|
a->bounds.left = 0;
|
||||||
a->bounds.top = 0;
|
a->bounds.top = 0;
|
||||||
a->bounds.width = W_UXGA;
|
a->bounds.width = UXGA_WIDTH;
|
||||||
a->bounds.height = H_UXGA;
|
a->bounds.height = UXGA_HEIGHT;
|
||||||
a->defrect = a->bounds;
|
a->defrect = a->bounds;
|
||||||
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||||
a->pixelaspect.numerator = 1;
|
a->pixelaspect.numerator = 1;
|
||||||
|
|
|
@ -58,21 +58,11 @@ static inline struct ths8200_state *to_state(struct v4l2_subdev *sd)
|
||||||
return container_of(sd, struct ths8200_state, sd);
|
return container_of(sd, struct ths8200_state, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
|
|
||||||
{
|
|
||||||
return V4L2_DV_BT_BLANKING_WIDTH(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
static inline unsigned htotal(const struct v4l2_bt_timings *t)
|
||||||
{
|
{
|
||||||
return V4L2_DV_BT_FRAME_WIDTH(t);
|
return V4L2_DV_BT_FRAME_WIDTH(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned vblanking(const struct v4l2_bt_timings *t)
|
|
||||||
{
|
|
||||||
return V4L2_DV_BT_BLANKING_HEIGHT(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
|
||||||
{
|
{
|
||||||
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
||||||
|
|
|
@ -6,6 +6,8 @@ config SMS_SDIO_DRV
|
||||||
tristate "Siano SMS1xxx based MDTV via SDIO interface"
|
tristate "Siano SMS1xxx based MDTV via SDIO interface"
|
||||||
depends on DVB_CORE && HAS_DMA
|
depends on DVB_CORE && HAS_DMA
|
||||||
depends on MMC
|
depends on MMC
|
||||||
|
depends on !RC_CORE || RC_CORE
|
||||||
select MEDIA_COMMON_OPTIONS
|
select MEDIA_COMMON_OPTIONS
|
||||||
|
select SMS_SIANO_MDTV
|
||||||
---help---
|
---help---
|
||||||
Choose if you would like to have Siano's support for SDIO interface
|
Choose if you would like to have Siano's support for SDIO interface
|
||||||
|
|
|
@ -2,15 +2,17 @@ config VIDEO_BT848
|
||||||
tristate "BT848 Video For Linux"
|
tristate "BT848 Video For Linux"
|
||||||
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
|
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
select VIDEO_BTCX
|
|
||||||
select VIDEOBUF_DMA_SG
|
select VIDEOBUF_DMA_SG
|
||||||
depends on RC_CORE
|
depends on RC_CORE
|
||||||
|
depends on MEDIA_RADIO_SUPPORT
|
||||||
select VIDEO_TUNER
|
select VIDEO_TUNER
|
||||||
select VIDEO_TVEEPROM
|
select VIDEO_TVEEPROM
|
||||||
select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
|
select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT
|
select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT
|
||||||
select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT
|
select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
|
select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
|
select RADIO_ADAPTERS
|
||||||
|
select RADIO_TEA575X
|
||||||
---help---
|
---help---
|
||||||
Support for BT848 based frame grabber/overlay boards. This includes
|
Support for BT848 based frame grabber/overlay boards. This includes
|
||||||
the Miro, Hauppauge and STB boards. Please read the material in
|
the Miro, Hauppauge and STB boards. Please read the material in
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
|
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
|
||||||
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
|
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
|
||||||
bttv-input.o bttv-audio-hook.o
|
bttv-input.o bttv-audio-hook.o btcx-risc.o
|
||||||
|
|
||||||
obj-$(CONFIG_VIDEO_BT848) += bttv.o
|
obj-$(CONFIG_VIDEO_BT848) += bttv.o
|
||||||
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
|
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
|
||||||
|
|
|
@ -590,9 +590,3 @@ module_init(bt878_init_module);
|
||||||
module_exit(bt878_cleanup_module);
|
module_exit(bt878_cleanup_module);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -32,13 +32,9 @@
|
||||||
|
|
||||||
#include "btcx-risc.h"
|
#include "btcx-risc.h"
|
||||||
|
|
||||||
MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
|
static unsigned int btcx_debug;
|
||||||
MODULE_AUTHOR("Gerd Knorr");
|
module_param(btcx_debug, int, 0644);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)");
|
||||||
|
|
||||||
static unsigned int debug;
|
|
||||||
module_param(debug, int, 0644);
|
|
||||||
MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------- */
|
/* ---------------------------------------------------------- */
|
||||||
/* allocate/free risc memory */
|
/* allocate/free risc memory */
|
||||||
|
@ -50,7 +46,7 @@ void btcx_riscmem_free(struct pci_dev *pci,
|
||||||
{
|
{
|
||||||
if (NULL == risc->cpu)
|
if (NULL == risc->cpu)
|
||||||
return;
|
return;
|
||||||
if (debug) {
|
if (btcx_debug) {
|
||||||
memcnt--;
|
memcnt--;
|
||||||
printk("btcx: riscmem free [%d] dma=%lx\n",
|
printk("btcx: riscmem free [%d] dma=%lx\n",
|
||||||
memcnt, (unsigned long)risc->dma);
|
memcnt, (unsigned long)risc->dma);
|
||||||
|
@ -75,7 +71,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
|
||||||
risc->cpu = cpu;
|
risc->cpu = cpu;
|
||||||
risc->dma = dma;
|
risc->dma = dma;
|
||||||
risc->size = size;
|
risc->size = size;
|
||||||
if (debug) {
|
if (btcx_debug) {
|
||||||
memcnt++;
|
memcnt++;
|
||||||
printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
|
printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
|
||||||
memcnt, (unsigned long)dma, cpu, size);
|
memcnt, (unsigned long)dma, cpu, size);
|
||||||
|
@ -141,7 +137,7 @@ btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int m
|
||||||
dx = nx - win->left;
|
dx = nx - win->left;
|
||||||
win->left = nx;
|
win->left = nx;
|
||||||
win->width = nw;
|
win->width = nw;
|
||||||
if (debug)
|
if (btcx_debug)
|
||||||
printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
|
printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
|
||||||
win->width, win->height, win->left, win->top, dx);
|
win->width, win->height, win->left, win->top, dx);
|
||||||
|
|
||||||
|
@ -153,7 +149,7 @@ btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int m
|
||||||
nw += mask+1;
|
nw += mask+1;
|
||||||
clips[i].c.left = nx;
|
clips[i].c.left = nx;
|
||||||
clips[i].c.width = nw;
|
clips[i].c.width = nw;
|
||||||
if (debug)
|
if (btcx_debug)
|
||||||
printk(KERN_DEBUG "btcx: clip align %dx%d+%d+%d\n",
|
printk(KERN_DEBUG "btcx: clip align %dx%d+%d+%d\n",
|
||||||
clips[i].c.width, clips[i].c.height,
|
clips[i].c.width, clips[i].c.height,
|
||||||
clips[i].c.left, clips[i].c.top);
|
clips[i].c.left, clips[i].c.top);
|
||||||
|
@ -234,7 +230,7 @@ btcx_calc_skips(int line, int width, int *maxy,
|
||||||
*nskips = skip;
|
*nskips = skip;
|
||||||
*maxy = maxline;
|
*maxy = maxline;
|
||||||
|
|
||||||
if (debug) {
|
if (btcx_debug) {
|
||||||
printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
|
printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
|
||||||
for (skip = 0; skip < *nskips; skip++) {
|
for (skip = 0; skip < *nskips; skip++) {
|
||||||
printk(" %d-%d",skips[skip].start,skips[skip].end);
|
printk(" %d-%d",skips[skip].start,skips[skip].end);
|
||||||
|
@ -242,19 +238,3 @@ btcx_calc_skips(int line, int width, int *maxy,
|
||||||
printk("\n");
|
printk("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------- */
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(btcx_riscmem_alloc);
|
|
||||||
EXPORT_SYMBOL(btcx_riscmem_free);
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(btcx_screen_clips);
|
|
||||||
EXPORT_SYMBOL(btcx_align);
|
|
||||||
EXPORT_SYMBOL(btcx_sort_clips);
|
|
||||||
EXPORT_SYMBOL(btcx_calc_skips);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
struct btcx_riscmem {
|
||||||
|
unsigned int size;
|
||||||
|
__le32 *cpu;
|
||||||
|
__le32 *jmp;
|
||||||
|
dma_addr_t dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct btcx_skiplist {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
};
|
||||||
|
|
||||||
|
int btcx_riscmem_alloc(struct pci_dev *pci,
|
||||||
|
struct btcx_riscmem *risc,
|
||||||
|
unsigned int size);
|
||||||
|
void btcx_riscmem_free(struct pci_dev *pci,
|
||||||
|
struct btcx_riscmem *risc);
|
||||||
|
|
||||||
|
int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
|
||||||
|
struct v4l2_clip *clips, unsigned int n);
|
||||||
|
int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
|
||||||
|
unsigned int n, int mask);
|
||||||
|
void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
|
||||||
|
void btcx_calc_skips(int line, int width, int *maxy,
|
||||||
|
struct btcx_skiplist *skips, unsigned int *nskips,
|
||||||
|
const struct v4l2_clip *clips, unsigned int nclips);
|
|
@ -84,8 +84,7 @@ static void gv800s_init(struct bttv *btv);
|
||||||
static void td3116_muxsel(struct bttv *btv, unsigned int input);
|
static void td3116_muxsel(struct bttv *btv, unsigned int input);
|
||||||
|
|
||||||
static int terratec_active_radio_upgrade(struct bttv *btv);
|
static int terratec_active_radio_upgrade(struct bttv *btv);
|
||||||
static int tea5757_read(struct bttv *btv);
|
static int tea575x_init(struct bttv *btv);
|
||||||
static int tea5757_write(struct bttv *btv, int value);
|
|
||||||
static void identify_by_eeprom(struct bttv *btv,
|
static void identify_by_eeprom(struct bttv *btv,
|
||||||
unsigned char eeprom_data[256]);
|
unsigned char eeprom_data[256]);
|
||||||
static int pvr_boot(struct bttv *btv);
|
static int pvr_boot(struct bttv *btv);
|
||||||
|
@ -3085,12 +3084,12 @@ static void miro_pinnacle_gpio(struct bttv *btv)
|
||||||
if (0 == (gpio & 0x20)) {
|
if (0 == (gpio & 0x20)) {
|
||||||
btv->has_radio = 1;
|
btv->has_radio = 1;
|
||||||
if (!miro_fmtuner[id]) {
|
if (!miro_fmtuner[id]) {
|
||||||
btv->has_matchbox = 1;
|
btv->has_tea575x = 1;
|
||||||
btv->mbox_we = (1<<6);
|
btv->tea_gpio.wren = 6;
|
||||||
btv->mbox_most = (1<<7);
|
btv->tea_gpio.most = 7;
|
||||||
btv->mbox_clk = (1<<8);
|
btv->tea_gpio.clk = 8;
|
||||||
btv->mbox_data = (1<<9);
|
btv->tea_gpio.data = 9;
|
||||||
btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9);
|
tea575x_init(btv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
btv->has_radio = 0;
|
btv->has_radio = 0;
|
||||||
|
@ -3104,7 +3103,7 @@ static void miro_pinnacle_gpio(struct bttv *btv)
|
||||||
pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
|
pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
|
||||||
btv->c.nr, id+1, btv->tuner_type,
|
btv->c.nr, id+1, btv->tuner_type,
|
||||||
!btv->has_radio ? "no" :
|
!btv->has_radio ? "no" :
|
||||||
(btv->has_matchbox ? "matchbox" : "fmtuner"),
|
(btv->has_tea575x ? "tea575x" : "fmtuner"),
|
||||||
(-1 == msp) ? "no" : "yes");
|
(-1 == msp) ? "no" : "yes");
|
||||||
} else {
|
} else {
|
||||||
/* new cards with microtune tuner */
|
/* new cards with microtune tuner */
|
||||||
|
@ -3382,12 +3381,12 @@ void bttv_init_card2(struct bttv *btv)
|
||||||
break;
|
break;
|
||||||
case BTTV_BOARD_VHX:
|
case BTTV_BOARD_VHX:
|
||||||
btv->has_radio = 1;
|
btv->has_radio = 1;
|
||||||
btv->has_matchbox = 1;
|
btv->has_tea575x = 1;
|
||||||
btv->mbox_we = 0x20;
|
btv->tea_gpio.wren = 5;
|
||||||
btv->mbox_most = 0;
|
btv->tea_gpio.most = 6;
|
||||||
btv->mbox_clk = 0x08;
|
btv->tea_gpio.clk = 3;
|
||||||
btv->mbox_data = 0x10;
|
btv->tea_gpio.data = 4;
|
||||||
btv->mbox_mask = 0x38;
|
tea575x_init(btv);
|
||||||
break;
|
break;
|
||||||
case BTTV_BOARD_VOBIS_BOOSTAR:
|
case BTTV_BOARD_VOBIS_BOOSTAR:
|
||||||
case BTTV_BOARD_TERRATV:
|
case BTTV_BOARD_TERRATV:
|
||||||
|
@ -3745,33 +3744,112 @@ static void hauppauge_eeprom(struct bttv *btv)
|
||||||
btv->radio_uses_msp_demodulator = 1;
|
btv->radio_uses_msp_demodulator = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void bttv_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
|
||||||
|
{
|
||||||
|
struct bttv *btv = tea->private_data;
|
||||||
|
struct bttv_tea575x_gpio gpio = btv->tea_gpio;
|
||||||
|
u16 val = 0;
|
||||||
|
|
||||||
|
val |= (pins & TEA575X_DATA) ? (1 << gpio.data) : 0;
|
||||||
|
val |= (pins & TEA575X_CLK) ? (1 << gpio.clk) : 0;
|
||||||
|
val |= (pins & TEA575X_WREN) ? (1 << gpio.wren) : 0;
|
||||||
|
|
||||||
|
gpio_bits((1 << gpio.data) | (1 << gpio.clk) | (1 << gpio.wren), val);
|
||||||
|
if (btv->mbox_ior) {
|
||||||
|
/* IOW and CSEL active */
|
||||||
|
gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
|
||||||
|
udelay(5);
|
||||||
|
/* all inactive */
|
||||||
|
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
||||||
|
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 bttv_tea575x_get_pins(struct snd_tea575x *tea)
|
||||||
|
{
|
||||||
|
struct bttv *btv = tea->private_data;
|
||||||
|
struct bttv_tea575x_gpio gpio = btv->tea_gpio;
|
||||||
|
u8 ret = 0;
|
||||||
|
u16 val;
|
||||||
|
|
||||||
|
if (btv->mbox_ior) {
|
||||||
|
/* IOR and CSEL active */
|
||||||
|
gpio_bits(btv->mbox_ior | btv->mbox_csel, 0);
|
||||||
|
udelay(5);
|
||||||
|
}
|
||||||
|
val = gpio_read();
|
||||||
|
if (btv->mbox_ior) {
|
||||||
|
/* all inactive */
|
||||||
|
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
||||||
|
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val & (1 << gpio.data))
|
||||||
|
ret |= TEA575X_DATA;
|
||||||
|
if (val & (1 << gpio.most))
|
||||||
|
ret |= TEA575X_MOST;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bttv_tea575x_set_direction(struct snd_tea575x *tea, bool output)
|
||||||
|
{
|
||||||
|
struct bttv *btv = tea->private_data;
|
||||||
|
struct bttv_tea575x_gpio gpio = btv->tea_gpio;
|
||||||
|
u32 mask = (1 << gpio.clk) | (1 << gpio.wren) | (1 << gpio.data) |
|
||||||
|
(1 << gpio.most);
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
gpio_inout(mask, (1 << gpio.data) | (1 << gpio.clk) |
|
||||||
|
(1 << gpio.wren));
|
||||||
|
else
|
||||||
|
gpio_inout(mask, (1 << gpio.clk) | (1 << gpio.wren));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct snd_tea575x_ops bttv_tea_ops = {
|
||||||
|
.set_pins = bttv_tea575x_set_pins,
|
||||||
|
.get_pins = bttv_tea575x_get_pins,
|
||||||
|
.set_direction = bttv_tea575x_set_direction,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tea575x_init(struct bttv *btv)
|
||||||
|
{
|
||||||
|
btv->tea.private_data = btv;
|
||||||
|
btv->tea.ops = &bttv_tea_ops;
|
||||||
|
if (!snd_tea575x_hw_init(&btv->tea)) {
|
||||||
|
pr_info("%d: detected TEA575x radio\n", btv->c.nr);
|
||||||
|
btv->tea.mute = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
btv->has_tea575x = 0;
|
||||||
|
btv->has_radio = 0;
|
||||||
|
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int terratec_active_radio_upgrade(struct bttv *btv)
|
static int terratec_active_radio_upgrade(struct bttv *btv)
|
||||||
{
|
{
|
||||||
int freq;
|
|
||||||
|
|
||||||
btv->has_radio = 1;
|
btv->has_radio = 1;
|
||||||
btv->has_matchbox = 1;
|
btv->has_tea575x = 1;
|
||||||
btv->mbox_we = 0x10;
|
btv->tea_gpio.wren = 4;
|
||||||
btv->mbox_most = 0x20;
|
btv->tea_gpio.most = 5;
|
||||||
btv->mbox_clk = 0x08;
|
btv->tea_gpio.clk = 3;
|
||||||
btv->mbox_data = 0x04;
|
btv->tea_gpio.data = 2;
|
||||||
btv->mbox_mask = 0x3c;
|
|
||||||
|
|
||||||
btv->mbox_iow = 1 << 8;
|
btv->mbox_iow = 1 << 8;
|
||||||
btv->mbox_ior = 1 << 9;
|
btv->mbox_ior = 1 << 9;
|
||||||
btv->mbox_csel = 1 << 10;
|
btv->mbox_csel = 1 << 10;
|
||||||
|
|
||||||
freq=88000/62.5;
|
if (!tea575x_init(btv)) {
|
||||||
tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
|
|
||||||
if (0x1ed8 == tea5757_read(btv)) {
|
|
||||||
pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
|
pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
|
||||||
btv->has_radio = 1;
|
btv->has_saa6588 = 1;
|
||||||
btv->has_saa6588 = 1;
|
|
||||||
btv->has_matchbox = 1;
|
|
||||||
} else {
|
|
||||||
btv->has_radio = 0;
|
|
||||||
btv->has_matchbox = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4292,181 +4370,6 @@ init_PCI8604PW(struct bttv *btv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
|
|
||||||
* This code is placed under the terms of the GNU General Public License
|
|
||||||
*
|
|
||||||
* Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void bus_low(struct bttv *btv, int bit)
|
|
||||||
{
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
|
||||||
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_bits(bit,0);
|
|
||||||
udelay(5);
|
|
||||||
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bus_high(struct bttv *btv, int bit)
|
|
||||||
{
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
|
||||||
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_bits(bit,bit);
|
|
||||||
udelay(5);
|
|
||||||
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bus_in(struct bttv *btv, int bit)
|
|
||||||
{
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
|
||||||
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
|
||||||
udelay(5);
|
|
||||||
|
|
||||||
gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
return gpio_read() & (bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TEA5757 register bits */
|
|
||||||
#define TEA_FREQ 0:14
|
|
||||||
#define TEA_BUFFER 15:15
|
|
||||||
|
|
||||||
#define TEA_SIGNAL_STRENGTH 16:17
|
|
||||||
|
|
||||||
#define TEA_PORT1 18:18
|
|
||||||
#define TEA_PORT0 19:19
|
|
||||||
|
|
||||||
#define TEA_BAND 20:21
|
|
||||||
#define TEA_BAND_FM 0
|
|
||||||
#define TEA_BAND_MW 1
|
|
||||||
#define TEA_BAND_LW 2
|
|
||||||
#define TEA_BAND_SW 3
|
|
||||||
|
|
||||||
#define TEA_MONO 22:22
|
|
||||||
#define TEA_ALLOW_STEREO 0
|
|
||||||
#define TEA_FORCE_MONO 1
|
|
||||||
|
|
||||||
#define TEA_SEARCH_DIRECTION 23:23
|
|
||||||
#define TEA_SEARCH_DOWN 0
|
|
||||||
#define TEA_SEARCH_UP 1
|
|
||||||
|
|
||||||
#define TEA_STATUS 24:24
|
|
||||||
#define TEA_STATUS_TUNED 0
|
|
||||||
#define TEA_STATUS_SEARCHING 1
|
|
||||||
|
|
||||||
/* Low-level stuff */
|
|
||||||
static int tea5757_read(struct bttv *btv)
|
|
||||||
{
|
|
||||||
unsigned long timeout;
|
|
||||||
int value = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* better safe than sorry */
|
|
||||||
gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
|
|
||||||
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
|
||||||
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bttv_gpio)
|
|
||||||
bttv_gpio_tracking(btv,"tea5757 read");
|
|
||||||
|
|
||||||
bus_low(btv,btv->mbox_we);
|
|
||||||
bus_low(btv,btv->mbox_clk);
|
|
||||||
|
|
||||||
udelay(10);
|
|
||||||
timeout= jiffies + msecs_to_jiffies(1000);
|
|
||||||
|
|
||||||
/* wait for DATA line to go low; error if it doesn't */
|
|
||||||
while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
|
|
||||||
schedule();
|
|
||||||
if (bus_in(btv,btv->mbox_data)) {
|
|
||||||
pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dprintk("%d: tea5757:", btv->c.nr);
|
|
||||||
for (i = 0; i < 24; i++) {
|
|
||||||
udelay(5);
|
|
||||||
bus_high(btv,btv->mbox_clk);
|
|
||||||
udelay(5);
|
|
||||||
dprintk_cont("%c",
|
|
||||||
bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
|
|
||||||
bus_low(btv,btv->mbox_clk);
|
|
||||||
value <<= 1;
|
|
||||||
value |= (bus_in(btv,btv->mbox_data) == 0)?0:1; /* MSB first */
|
|
||||||
dprintk_cont("%c",
|
|
||||||
bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
|
|
||||||
}
|
|
||||||
dprintk_cont("\n");
|
|
||||||
dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tea5757_write(struct bttv *btv, int value)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int reg = value;
|
|
||||||
|
|
||||||
gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
|
|
||||||
|
|
||||||
if (btv->mbox_ior) {
|
|
||||||
gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
|
|
||||||
btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
|
|
||||||
udelay(5);
|
|
||||||
}
|
|
||||||
if (bttv_gpio)
|
|
||||||
bttv_gpio_tracking(btv,"tea5757 write");
|
|
||||||
|
|
||||||
dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
|
|
||||||
bus_low(btv,btv->mbox_clk);
|
|
||||||
bus_high(btv,btv->mbox_we);
|
|
||||||
for (i = 0; i < 25; i++) {
|
|
||||||
if (reg & 0x1000000)
|
|
||||||
bus_high(btv,btv->mbox_data);
|
|
||||||
else
|
|
||||||
bus_low(btv,btv->mbox_data);
|
|
||||||
reg <<= 1;
|
|
||||||
bus_high(btv,btv->mbox_clk);
|
|
||||||
udelay(10);
|
|
||||||
bus_low(btv,btv->mbox_clk);
|
|
||||||
udelay(10);
|
|
||||||
}
|
|
||||||
bus_low(btv,btv->mbox_we); /* unmute !!! */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tea5757_set_freq(struct bttv *btv, unsigned short freq)
|
|
||||||
{
|
|
||||||
dprintk("tea5757_set_freq %d\n",freq);
|
|
||||||
tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
|
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
|
||||||
*
|
*
|
||||||
* This is needed because rv605 don't use a normal multiplex, but a crosspoint
|
* This is needed because rv605 don't use a normal multiplex, but a crosspoint
|
||||||
|
@ -5048,10 +4951,3 @@ int bttv_handle_chipset(struct bttv *btv)
|
||||||
pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency);
|
pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1874,8 +1874,10 @@ static void bttv_set_frequency(struct bttv *btv, const struct v4l2_frequency *f)
|
||||||
if (new_freq.type == V4L2_TUNER_RADIO) {
|
if (new_freq.type == V4L2_TUNER_RADIO) {
|
||||||
radio_enable(btv);
|
radio_enable(btv);
|
||||||
btv->radio_freq = new_freq.frequency;
|
btv->radio_freq = new_freq.frequency;
|
||||||
if (btv->has_matchbox)
|
if (btv->has_tea575x) {
|
||||||
tea5757_set_freq(btv, btv->radio_freq);
|
btv->tea.freq = btv->radio_freq;
|
||||||
|
snd_tea575x_set_freq(&btv->tea);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
btv->tv_freq = new_freq.frequency;
|
btv->tv_freq = new_freq.frequency;
|
||||||
}
|
}
|
||||||
|
@ -2513,6 +2515,8 @@ static int bttv_querycap(struct file *file, void *priv,
|
||||||
if (btv->has_saa6588)
|
if (btv->has_saa6588)
|
||||||
cap->device_caps |= V4L2_CAP_READWRITE |
|
cap->device_caps |= V4L2_CAP_READWRITE |
|
||||||
V4L2_CAP_RDS_CAPTURE;
|
V4L2_CAP_RDS_CAPTURE;
|
||||||
|
if (btv->has_tea575x)
|
||||||
|
cap->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3242,6 +3246,9 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
|
||||||
if (btv->audio_mode_gpio)
|
if (btv->audio_mode_gpio)
|
||||||
btv->audio_mode_gpio(btv, t, 0);
|
btv->audio_mode_gpio(btv, t, 0);
|
||||||
|
|
||||||
|
if (btv->has_tea575x)
|
||||||
|
return snd_tea575x_g_tuner(&btv->tea, t);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3259,6 +3266,30 @@ static int radio_s_tuner(struct file *file, void *priv,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int radio_s_hw_freq_seek(struct file *file, void *priv,
|
||||||
|
const struct v4l2_hw_freq_seek *a)
|
||||||
|
{
|
||||||
|
struct bttv_fh *fh = priv;
|
||||||
|
struct bttv *btv = fh->btv;
|
||||||
|
|
||||||
|
if (btv->has_tea575x)
|
||||||
|
return snd_tea575x_s_hw_freq_seek(file, &btv->tea, a);
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int radio_enum_freq_bands(struct file *file, void *priv,
|
||||||
|
struct v4l2_frequency_band *band)
|
||||||
|
{
|
||||||
|
struct bttv_fh *fh = priv;
|
||||||
|
struct bttv *btv = fh->btv;
|
||||||
|
|
||||||
|
if (btv->has_tea575x)
|
||||||
|
return snd_tea575x_enum_freq_bands(&btv->tea, band);
|
||||||
|
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t radio_read(struct file *file, char __user *data,
|
static ssize_t radio_read(struct file *file, char __user *data,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
|
@ -3316,6 +3347,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
|
||||||
.vidioc_s_tuner = radio_s_tuner,
|
.vidioc_s_tuner = radio_s_tuner,
|
||||||
.vidioc_g_frequency = bttv_g_frequency,
|
.vidioc_g_frequency = bttv_g_frequency,
|
||||||
.vidioc_s_frequency = bttv_s_frequency,
|
.vidioc_s_frequency = bttv_s_frequency,
|
||||||
|
.vidioc_s_hw_freq_seek = radio_s_hw_freq_seek,
|
||||||
|
.vidioc_enum_freq_bands = radio_enum_freq_bands,
|
||||||
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
||||||
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||||
};
|
};
|
||||||
|
@ -3884,7 +3917,6 @@ static struct video_device *vdev_init(struct bttv *btv,
|
||||||
*vfd = *template;
|
*vfd = *template;
|
||||||
vfd->v4l2_dev = &btv->c.v4l2_dev;
|
vfd->v4l2_dev = &btv->c.v4l2_dev;
|
||||||
vfd->release = video_device_release;
|
vfd->release = video_device_release;
|
||||||
vfd->debug = bttv_debug;
|
|
||||||
video_set_drvdata(vfd, btv);
|
video_set_drvdata(vfd, btv);
|
||||||
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
|
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
|
||||||
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
|
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
|
||||||
|
@ -4429,9 +4461,3 @@ static void __exit bttv_cleanup_module(void)
|
||||||
|
|
||||||
module_init(bttv_init_module);
|
module_init(bttv_init_module);
|
||||||
module_exit(bttv_cleanup_module);
|
module_exit(bttv_cleanup_module);
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -181,9 +181,3 @@ void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
|
||||||
btwrite(data,BT848_GPIO_DATA);
|
btwrite(data,BT848_GPIO_DATA);
|
||||||
spin_unlock_irqrestore(&btv->gpio_lock,flags);
|
spin_unlock_irqrestore(&btv->gpio_lock,flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -113,9 +113,3 @@ int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
|
||||||
bttv_gpio_tracking(btv,"extern write");
|
bttv_gpio_tracking(btv,"extern write");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -901,9 +901,3 @@ bttv_overlay_risc(struct bttv *btv,
|
||||||
buf->vb.field = ov->field;
|
buf->vb.field = ov->field;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -450,10 +450,3 @@ void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
|
||||||
/* See bttv_vbi_fmt_set(). */
|
/* See bttv_vbi_fmt_set(). */
|
||||||
f->end = tvnorm->vbistart[0] * 2 + 2;
|
f->end = tvnorm->vbistart[0] * 2 + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -378,8 +378,3 @@ extern void bttv_input_fini(struct bttv *dev);
|
||||||
extern void bttv_input_irq(struct bttv *dev);
|
extern void bttv_input_irq(struct bttv *dev);
|
||||||
|
|
||||||
#endif /* _BTTV_H_ */
|
#endif /* _BTTV_H_ */
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <media/tveeprom.h>
|
#include <media/tveeprom.h>
|
||||||
#include <media/rc-core.h>
|
#include <media/rc-core.h>
|
||||||
#include <media/ir-kbd-i2c.h>
|
#include <media/ir-kbd-i2c.h>
|
||||||
|
#include <media/tea575x.h>
|
||||||
|
|
||||||
#include "bt848.h"
|
#include "bt848.h"
|
||||||
#include "bttv.h"
|
#include "bttv.h"
|
||||||
|
@ -359,6 +360,10 @@ struct bttv_suspend_state {
|
||||||
struct bttv_buffer *vbi;
|
struct bttv_buffer *vbi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bttv_tea575x_gpio {
|
||||||
|
u8 data, clk, wren, most;
|
||||||
|
};
|
||||||
|
|
||||||
struct bttv {
|
struct bttv {
|
||||||
struct bttv_core c;
|
struct bttv_core c;
|
||||||
|
|
||||||
|
@ -445,12 +450,9 @@ struct bttv {
|
||||||
|
|
||||||
/* miro/pinnacle + Aimslab VHX
|
/* miro/pinnacle + Aimslab VHX
|
||||||
philips matchbox (tea5757 radio tuner) support */
|
philips matchbox (tea5757 radio tuner) support */
|
||||||
int has_matchbox;
|
int has_tea575x;
|
||||||
int mbox_we;
|
struct bttv_tea575x_gpio tea_gpio;
|
||||||
int mbox_data;
|
struct snd_tea575x tea;
|
||||||
int mbox_clk;
|
|
||||||
int mbox_most;
|
|
||||||
int mbox_mask;
|
|
||||||
|
|
||||||
/* ISA stuff (Terratec Active Radio Upgrade) */
|
/* ISA stuff (Terratec Active Radio Upgrade) */
|
||||||
int mbox_ior;
|
int mbox_ior;
|
||||||
|
@ -531,9 +533,3 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv,
|
||||||
#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
|
#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
|
||||||
|
|
||||||
#endif /* _BTTVP_H_ */
|
#endif /* _BTTVP_H_ */
|
||||||
|
|
||||||
/*
|
|
||||||
* Local variables:
|
|
||||||
* c-basic-offset: 8
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ config VIDEO_CX23885
|
||||||
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
|
select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
|
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
|
select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
|
select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
|
||||||
select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
|
select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
|
||||||
---help---
|
---help---
|
||||||
This is a video4linux driver for Conexant 23885 based
|
This is a video4linux driver for Conexant 23885 based
|
||||||
|
|
|
@ -710,6 +710,11 @@ struct cx23885_board cx23885_boards[] = {
|
||||||
.portb = CX23885_MPEG_DVB,
|
.portb = CX23885_MPEG_DVB,
|
||||||
.portc = CX23885_MPEG_DVB,
|
.portc = CX23885_MPEG_DVB,
|
||||||
},
|
},
|
||||||
|
[CX23885_BOARD_HAUPPAUGE_HVR5525] = {
|
||||||
|
.name = "Hauppauge WinTV-HVR5525",
|
||||||
|
.portb = CX23885_MPEG_DVB,
|
||||||
|
.portc = CX23885_MPEG_DVB,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
|
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
|
||||||
|
|
||||||
|
@ -993,6 +998,10 @@ struct cx23885_subid cx23885_subids[] = {
|
||||||
.subvendor = 0x4254,
|
.subvendor = 0x4254,
|
||||||
.subdevice = 0x0982,
|
.subdevice = 0x0982,
|
||||||
.card = CX23885_BOARD_DVBSKY_T982,
|
.card = CX23885_BOARD_DVBSKY_T982,
|
||||||
|
}, {
|
||||||
|
.subvendor = 0x0070,
|
||||||
|
.subdevice = 0xf038,
|
||||||
|
.card = CX23885_BOARD_HAUPPAUGE_HVR5525,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
|
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
|
||||||
|
@ -1165,6 +1174,8 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
|
||||||
case 85721:
|
case 85721:
|
||||||
/* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
|
/* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
|
||||||
Dual channel ATSC and Basic analog */
|
Dual channel ATSC and Basic analog */
|
||||||
|
case 150329:
|
||||||
|
/* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_WARNING "%s: warning: "
|
printk(KERN_WARNING "%s: warning: "
|
||||||
|
@ -1637,6 +1648,29 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
||||||
msleep(100);
|
msleep(100);
|
||||||
cx23885_gpio_set(dev, GPIO_2);
|
cx23885_gpio_set(dev, GPIO_2);
|
||||||
break;
|
break;
|
||||||
|
case CX23885_BOARD_HAUPPAUGE_HVR5525:
|
||||||
|
/*
|
||||||
|
* GPIO-00 IR_WIDE
|
||||||
|
* GPIO-02 wake#
|
||||||
|
* GPIO-03 VAUX Pres.
|
||||||
|
* GPIO-07 PROG#
|
||||||
|
* GPIO-08 SAT_RESN
|
||||||
|
* GPIO-09 TER_RESN
|
||||||
|
* GPIO-10 B2_SENSE
|
||||||
|
* GPIO-11 B1_SENSE
|
||||||
|
* GPIO-15 IR_LED_STATUS
|
||||||
|
* GPIO-19 IR_NARROW
|
||||||
|
* GPIO-20 Blauster1
|
||||||
|
* ALTGPIO VAUX_SWITCH
|
||||||
|
* AUX_PLL_CLK : Blaster2
|
||||||
|
*/
|
||||||
|
/* Put the parts into reset and back */
|
||||||
|
cx23885_gpio_enable(dev, GPIO_8 | GPIO_9, 1);
|
||||||
|
cx23885_gpio_clear(dev, GPIO_8 | GPIO_9);
|
||||||
|
msleep(100);
|
||||||
|
cx23885_gpio_set(dev, GPIO_8 | GPIO_9);
|
||||||
|
msleep(100);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1879,6 +1913,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||||
case CX23885_BOARD_HAUPPAUGE_HVR4400:
|
case CX23885_BOARD_HAUPPAUGE_HVR4400:
|
||||||
case CX23885_BOARD_HAUPPAUGE_STARBURST:
|
case CX23885_BOARD_HAUPPAUGE_STARBURST:
|
||||||
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
|
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
|
||||||
|
case CX23885_BOARD_HAUPPAUGE_HVR5525:
|
||||||
if (dev->i2c_bus[0].i2c_rc == 0)
|
if (dev->i2c_bus[0].i2c_rc == 0)
|
||||||
hauppauge_eeprom(dev, eeprom+0xc0);
|
hauppauge_eeprom(dev, eeprom+0xc0);
|
||||||
break;
|
break;
|
||||||
|
@ -2008,6 +2043,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||||
break;
|
break;
|
||||||
|
case CX23885_BOARD_HAUPPAUGE_HVR5525:
|
||||||
|
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;
|
||||||
|
ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
|
||||||
|
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||||
|
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||||
|
break;
|
||||||
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
case CX23885_BOARD_HAUPPAUGE_HVR1250:
|
||||||
case CX23885_BOARD_HAUPPAUGE_HVR1500:
|
case CX23885_BOARD_HAUPPAUGE_HVR1500:
|
||||||
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
|
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
#include "sp2.h"
|
#include "sp2.h"
|
||||||
#include "m88ds3103.h"
|
#include "m88ds3103.h"
|
||||||
#include "m88ts2022.h"
|
#include "m88ts2022.h"
|
||||||
|
#include "m88rs6000t.h"
|
||||||
|
|
||||||
static unsigned int debug;
|
static unsigned int debug;
|
||||||
|
|
||||||
|
@ -915,6 +916,16 @@ static const struct m88ds3103_config dvbsky_s952_portc_m88ds3103_config = {
|
||||||
.agc = 0x99,
|
.agc = 0x99,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct m88ds3103_config hauppauge_hvr5525_m88ds3103_config = {
|
||||||
|
.i2c_addr = 0x69,
|
||||||
|
.clock = 27000000,
|
||||||
|
.i2c_wr_max = 33,
|
||||||
|
.ts_mode = M88DS3103_TS_PARALLEL,
|
||||||
|
.ts_clk = 16000,
|
||||||
|
.ts_clk_pol = 1,
|
||||||
|
.agc = 0x99,
|
||||||
|
};
|
||||||
|
|
||||||
static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
|
static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
|
||||||
{
|
{
|
||||||
struct cx23885_dev *dev = (struct cx23885_dev *)device;
|
struct cx23885_dev *dev = (struct cx23885_dev *)device;
|
||||||
|
@ -1058,6 +1069,116 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
|
||||||
.hostbus_diversity = 1,
|
.hostbus_diversity = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int dvb_register_ci_mac(struct cx23885_tsport *port)
|
||||||
|
{
|
||||||
|
struct cx23885_dev *dev = port->dev;
|
||||||
|
struct i2c_client *client_ci = NULL;
|
||||||
|
struct vb2_dvb_frontend *fe0;
|
||||||
|
|
||||||
|
fe0 = vb2_dvb_get_frontend(&port->frontends, 1);
|
||||||
|
if (!fe0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (dev->board) {
|
||||||
|
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
|
||||||
|
static struct netup_card_info cinfo;
|
||||||
|
|
||||||
|
netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
|
||||||
|
memcpy(port->frontends.adapter.proposed_mac,
|
||||||
|
cinfo.port[port->nr - 1].mac, 6);
|
||||||
|
printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
|
||||||
|
port->nr, port->frontends.adapter.proposed_mac);
|
||||||
|
|
||||||
|
netup_ci_init(port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
|
||||||
|
struct altera_ci_config netup_ci_cfg = {
|
||||||
|
.dev = dev,/* magic number to identify*/
|
||||||
|
.adapter = &port->frontends.adapter,/* for CI */
|
||||||
|
.demux = &fe0->dvb.demux,/* for hw pid filter */
|
||||||
|
.fpga_rw = netup_altera_fpga_rw,
|
||||||
|
};
|
||||||
|
|
||||||
|
altera_ci_init(&netup_ci_cfg, port->nr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CX23885_BOARD_TEVII_S470: {
|
||||||
|
u8 eeprom[256]; /* 24C02 i2c eeprom */
|
||||||
|
|
||||||
|
if (port->nr != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Read entire EEPROM */
|
||||||
|
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
|
||||||
|
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
|
||||||
|
printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
|
||||||
|
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CX23885_BOARD_DVBSKY_T9580:
|
||||||
|
case CX23885_BOARD_DVBSKY_S950:
|
||||||
|
case CX23885_BOARD_DVBSKY_S952:
|
||||||
|
case CX23885_BOARD_DVBSKY_T982: {
|
||||||
|
u8 eeprom[256]; /* 24C02 i2c eeprom */
|
||||||
|
|
||||||
|
if (port->nr > 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Read entire EEPROM */
|
||||||
|
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
|
||||||
|
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
|
||||||
|
sizeof(eeprom));
|
||||||
|
printk(KERN_INFO "%s port %d MAC address: %pM\n",
|
||||||
|
cx23885_boards[dev->board].name, port->nr,
|
||||||
|
eeprom + 0xc0 + (port->nr-1) * 8);
|
||||||
|
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
|
||||||
|
(port->nr-1) * 8, 6);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CX23885_BOARD_DVBSKY_S950C:
|
||||||
|
case CX23885_BOARD_DVBSKY_T980C:
|
||||||
|
case CX23885_BOARD_TT_CT2_4500_CI: {
|
||||||
|
u8 eeprom[256]; /* 24C02 i2c eeprom */
|
||||||
|
struct sp2_config sp2_config;
|
||||||
|
struct i2c_board_info info;
|
||||||
|
struct cx23885_i2c *i2c_bus2 = &dev->i2c_bus[1];
|
||||||
|
|
||||||
|
/* attach CI */
|
||||||
|
memset(&sp2_config, 0, sizeof(sp2_config));
|
||||||
|
sp2_config.dvb_adap = &port->frontends.adapter;
|
||||||
|
sp2_config.priv = port;
|
||||||
|
sp2_config.ci_control = cx23885_sp2_ci_ctrl;
|
||||||
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||||
|
strlcpy(info.type, "sp2", I2C_NAME_SIZE);
|
||||||
|
info.addr = 0x40;
|
||||||
|
info.platform_data = &sp2_config;
|
||||||
|
request_module(info.type);
|
||||||
|
client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
|
||||||
|
if (client_ci == NULL || client_ci->dev.driver == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
if (!try_module_get(client_ci->dev.driver->owner)) {
|
||||||
|
i2c_unregister_device(client_ci);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
port->i2c_client_ci = client_ci;
|
||||||
|
|
||||||
|
if (port->nr != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Read entire EEPROM */
|
||||||
|
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
|
||||||
|
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
|
||||||
|
sizeof(eeprom));
|
||||||
|
printk(KERN_INFO "%s MAC address: %pM\n",
|
||||||
|
cx23885_boards[dev->board].name, eeprom + 0xc0);
|
||||||
|
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dvb_register(struct cx23885_tsport *port)
|
static int dvb_register(struct cx23885_tsport *port)
|
||||||
{
|
{
|
||||||
struct dib7000p_ops dib7000p_ops;
|
struct dib7000p_ops dib7000p_ops;
|
||||||
|
@ -1066,11 +1187,10 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
struct vb2_dvb_frontend *fe0, *fe1 = NULL;
|
struct vb2_dvb_frontend *fe0, *fe1 = NULL;
|
||||||
struct si2168_config si2168_config;
|
struct si2168_config si2168_config;
|
||||||
struct si2157_config si2157_config;
|
struct si2157_config si2157_config;
|
||||||
struct sp2_config sp2_config;
|
|
||||||
struct m88ts2022_config m88ts2022_config;
|
struct m88ts2022_config m88ts2022_config;
|
||||||
struct i2c_board_info info;
|
struct i2c_board_info info;
|
||||||
struct i2c_adapter *adapter;
|
struct i2c_adapter *adapter;
|
||||||
struct i2c_client *client_demod = NULL, *client_tuner = NULL, *client_ci = NULL;
|
struct i2c_client *client_demod = NULL, *client_tuner = NULL;
|
||||||
const struct m88ds3103_config *p_m88ds3103_config = NULL;
|
const struct m88ds3103_config *p_m88ds3103_config = NULL;
|
||||||
int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
|
int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
|
||||||
int mfe_shared = 0; /* bus not shared by default */
|
int mfe_shared = 0; /* bus not shared by default */
|
||||||
|
@ -1801,15 +1921,11 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_tuner = i2c_new_device(adapter, &info);
|
client_tuner = i2c_new_device(adapter, &info);
|
||||||
if (client_tuner == NULL ||
|
if (client_tuner == NULL ||
|
||||||
client_tuner->dev.driver == NULL) {
|
client_tuner->dev.driver == NULL)
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
}
|
|
||||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_tuner);
|
i2c_unregister_device(client_tuner);
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
}
|
}
|
||||||
port->i2c_client_tuner = client_tuner;
|
port->i2c_client_tuner = client_tuner;
|
||||||
|
@ -1832,8 +1948,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
info.platform_data = &si2168_config;
|
info.platform_data = &si2168_config;
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
|
client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
|
||||||
if (client_demod == NULL ||
|
if (client_demod == NULL || client_demod->dev.driver == NULL)
|
||||||
client_demod->dev.driver == NULL)
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
if (!try_module_get(client_demod->dev.driver->owner)) {
|
if (!try_module_get(client_demod->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_demod);
|
i2c_unregister_device(client_demod);
|
||||||
|
@ -1851,15 +1966,10 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_tuner = i2c_new_device(adapter, &info);
|
client_tuner = i2c_new_device(adapter, &info);
|
||||||
if (client_tuner == NULL ||
|
if (client_tuner == NULL ||
|
||||||
client_tuner->dev.driver == NULL) {
|
client_tuner->dev.driver == NULL)
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
}
|
|
||||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_tuner);
|
i2c_unregister_device(client_tuner);
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
}
|
}
|
||||||
port->i2c_client_tuner = client_tuner;
|
port->i2c_client_tuner = client_tuner;
|
||||||
|
@ -1885,8 +1995,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
info.platform_data = &m88ts2022_config;
|
info.platform_data = &m88ts2022_config;
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_tuner = i2c_new_device(adapter, &info);
|
client_tuner = i2c_new_device(adapter, &info);
|
||||||
if (client_tuner == NULL ||
|
if (client_tuner == NULL || client_tuner->dev.driver == NULL)
|
||||||
client_tuner->dev.driver == NULL)
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_tuner);
|
i2c_unregister_device(client_tuner);
|
||||||
|
@ -1932,8 +2041,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
info.platform_data = &m88ts2022_config;
|
info.platform_data = &m88ts2022_config;
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_tuner = i2c_new_device(adapter, &info);
|
client_tuner = i2c_new_device(adapter, &info);
|
||||||
if (client_tuner == NULL ||
|
if (client_tuner == NULL || client_tuner->dev.driver == NULL)
|
||||||
client_tuner->dev.driver == NULL)
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_tuner);
|
i2c_unregister_device(client_tuner);
|
||||||
|
@ -1978,8 +2086,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
info.platform_data = &si2168_config;
|
info.platform_data = &si2168_config;
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
|
client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
|
||||||
if (client_demod == NULL ||
|
if (client_demod == NULL || client_demod->dev.driver == NULL)
|
||||||
client_demod->dev.driver == NULL)
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
if (!try_module_get(client_demod->dev.driver->owner)) {
|
if (!try_module_get(client_demod->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_demod);
|
i2c_unregister_device(client_demod);
|
||||||
|
@ -1997,20 +2104,101 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
request_module(info.type);
|
request_module(info.type);
|
||||||
client_tuner = i2c_new_device(adapter, &info);
|
client_tuner = i2c_new_device(adapter, &info);
|
||||||
if (client_tuner == NULL ||
|
if (client_tuner == NULL ||
|
||||||
client_tuner->dev.driver == NULL) {
|
client_tuner->dev.driver == NULL)
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
}
|
|
||||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
i2c_unregister_device(client_tuner);
|
i2c_unregister_device(client_tuner);
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
port->i2c_client_demod = NULL;
|
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
}
|
}
|
||||||
port->i2c_client_tuner = client_tuner;
|
port->i2c_client_tuner = client_tuner;
|
||||||
break;
|
break;
|
||||||
|
case CX23885_BOARD_HAUPPAUGE_HVR5525:
|
||||||
|
switch (port->nr) {
|
||||||
|
struct m88rs6000t_config m88rs6000t_config;
|
||||||
|
|
||||||
|
/* port b - satellite */
|
||||||
|
case 1:
|
||||||
|
/* attach frontend */
|
||||||
|
fe0->dvb.frontend = dvb_attach(m88ds3103_attach,
|
||||||
|
&hauppauge_hvr5525_m88ds3103_config,
|
||||||
|
&dev->i2c_bus[0].i2c_adap, &adapter);
|
||||||
|
if (fe0->dvb.frontend == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* attach SEC */
|
||||||
|
if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
|
||||||
|
&dev->i2c_bus[0].i2c_adap,
|
||||||
|
&hauppauge_a8293_config))
|
||||||
|
goto frontend_detach;
|
||||||
|
|
||||||
|
/* attach tuner */
|
||||||
|
memset(&m88rs6000t_config, 0, sizeof(m88rs6000t_config));
|
||||||
|
m88rs6000t_config.fe = fe0->dvb.frontend;
|
||||||
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||||
|
strlcpy(info.type, "m88rs6000t", I2C_NAME_SIZE);
|
||||||
|
info.addr = 0x21;
|
||||||
|
info.platform_data = &m88rs6000t_config;
|
||||||
|
request_module("%s", info.type);
|
||||||
|
client_tuner = i2c_new_device(adapter, &info);
|
||||||
|
if (!client_tuner || !client_tuner->dev.driver)
|
||||||
|
goto frontend_detach;
|
||||||
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
|
i2c_unregister_device(client_tuner);
|
||||||
|
goto frontend_detach;
|
||||||
|
}
|
||||||
|
port->i2c_client_tuner = client_tuner;
|
||||||
|
|
||||||
|
/* delegate signal strength measurement to tuner */
|
||||||
|
fe0->dvb.frontend->ops.read_signal_strength =
|
||||||
|
fe0->dvb.frontend->ops.tuner_ops.get_rf_strength;
|
||||||
|
break;
|
||||||
|
/* port c - terrestrial/cable */
|
||||||
|
case 2:
|
||||||
|
/* attach frontend */
|
||||||
|
memset(&si2168_config, 0, sizeof(si2168_config));
|
||||||
|
si2168_config.i2c_adapter = &adapter;
|
||||||
|
si2168_config.fe = &fe0->dvb.frontend;
|
||||||
|
si2168_config.ts_mode = SI2168_TS_SERIAL;
|
||||||
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||||
|
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
|
||||||
|
info.addr = 0x64;
|
||||||
|
info.platform_data = &si2168_config;
|
||||||
|
request_module("%s", info.type);
|
||||||
|
client_demod = i2c_new_device(&dev->i2c_bus[0].i2c_adap, &info);
|
||||||
|
if (!client_demod || !client_demod->dev.driver)
|
||||||
|
goto frontend_detach;
|
||||||
|
if (!try_module_get(client_demod->dev.driver->owner)) {
|
||||||
|
i2c_unregister_device(client_demod);
|
||||||
|
goto frontend_detach;
|
||||||
|
}
|
||||||
|
port->i2c_client_demod = client_demod;
|
||||||
|
|
||||||
|
/* attach tuner */
|
||||||
|
memset(&si2157_config, 0, sizeof(si2157_config));
|
||||||
|
si2157_config.fe = fe0->dvb.frontend;
|
||||||
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||||
|
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||||
|
info.addr = 0x60;
|
||||||
|
info.platform_data = &si2157_config;
|
||||||
|
request_module("%s", info.type);
|
||||||
|
client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap, &info);
|
||||||
|
if (!client_tuner || !client_tuner->dev.driver) {
|
||||||
|
module_put(client_demod->dev.driver->owner);
|
||||||
|
i2c_unregister_device(client_demod);
|
||||||
|
port->i2c_client_demod = NULL;
|
||||||
|
goto frontend_detach;
|
||||||
|
}
|
||||||
|
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||||
|
i2c_unregister_device(client_tuner);
|
||||||
|
module_put(client_demod->dev.driver->owner);
|
||||||
|
i2c_unregister_device(client_demod);
|
||||||
|
port->i2c_client_demod = NULL;
|
||||||
|
goto frontend_detach;
|
||||||
|
}
|
||||||
|
port->i2c_client_tuner = client_tuner;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
|
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
|
||||||
" isn't supported yet\n",
|
" isn't supported yet\n",
|
||||||
|
@ -2047,123 +2235,29 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto frontend_detach;
|
goto frontend_detach;
|
||||||
|
|
||||||
/* init CI & MAC */
|
ret = dvb_register_ci_mac(port);
|
||||||
switch (dev->board) {
|
if (ret)
|
||||||
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
|
goto frontend_detach;
|
||||||
static struct netup_card_info cinfo;
|
|
||||||
|
|
||||||
netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
|
return 0;
|
||||||
memcpy(port->frontends.adapter.proposed_mac,
|
|
||||||
cinfo.port[port->nr - 1].mac, 6);
|
|
||||||
printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
|
|
||||||
port->nr, port->frontends.adapter.proposed_mac);
|
|
||||||
|
|
||||||
netup_ci_init(port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
|
|
||||||
struct altera_ci_config netup_ci_cfg = {
|
|
||||||
.dev = dev,/* magic number to identify*/
|
|
||||||
.adapter = &port->frontends.adapter,/* for CI */
|
|
||||||
.demux = &fe0->dvb.demux,/* for hw pid filter */
|
|
||||||
.fpga_rw = netup_altera_fpga_rw,
|
|
||||||
};
|
|
||||||
|
|
||||||
altera_ci_init(&netup_ci_cfg, port->nr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CX23885_BOARD_TEVII_S470: {
|
|
||||||
u8 eeprom[256]; /* 24C02 i2c eeprom */
|
|
||||||
|
|
||||||
if (port->nr != 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Read entire EEPROM */
|
|
||||||
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
|
|
||||||
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
|
|
||||||
printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
|
|
||||||
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CX23885_BOARD_DVBSKY_T9580:
|
|
||||||
case CX23885_BOARD_DVBSKY_S950:
|
|
||||||
case CX23885_BOARD_DVBSKY_S952:
|
|
||||||
case CX23885_BOARD_DVBSKY_T982: {
|
|
||||||
u8 eeprom[256]; /* 24C02 i2c eeprom */
|
|
||||||
|
|
||||||
if (port->nr > 2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Read entire EEPROM */
|
|
||||||
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
|
|
||||||
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
|
|
||||||
sizeof(eeprom));
|
|
||||||
printk(KERN_INFO "%s port %d MAC address: %pM\n",
|
|
||||||
cx23885_boards[dev->board].name, port->nr,
|
|
||||||
eeprom + 0xc0 + (port->nr-1) * 8);
|
|
||||||
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
|
|
||||||
(port->nr-1) * 8, 6);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CX23885_BOARD_DVBSKY_S950C:
|
|
||||||
case CX23885_BOARD_DVBSKY_T980C:
|
|
||||||
case CX23885_BOARD_TT_CT2_4500_CI: {
|
|
||||||
u8 eeprom[256]; /* 24C02 i2c eeprom */
|
|
||||||
|
|
||||||
/* attach CI */
|
|
||||||
memset(&sp2_config, 0, sizeof(sp2_config));
|
|
||||||
sp2_config.dvb_adap = &port->frontends.adapter;
|
|
||||||
sp2_config.priv = port;
|
|
||||||
sp2_config.ci_control = cx23885_sp2_ci_ctrl;
|
|
||||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
|
||||||
strlcpy(info.type, "sp2", I2C_NAME_SIZE);
|
|
||||||
info.addr = 0x40;
|
|
||||||
info.platform_data = &sp2_config;
|
|
||||||
request_module(info.type);
|
|
||||||
client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
|
|
||||||
if (client_ci == NULL ||
|
|
||||||
client_ci->dev.driver == NULL) {
|
|
||||||
if (client_tuner) {
|
|
||||||
module_put(client_tuner->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_tuner);
|
|
||||||
}
|
|
||||||
if (client_demod) {
|
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
}
|
|
||||||
goto frontend_detach;
|
|
||||||
}
|
|
||||||
if (!try_module_get(client_ci->dev.driver->owner)) {
|
|
||||||
i2c_unregister_device(client_ci);
|
|
||||||
if (client_tuner) {
|
|
||||||
module_put(client_tuner->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_tuner);
|
|
||||||
}
|
|
||||||
if (client_demod) {
|
|
||||||
module_put(client_demod->dev.driver->owner);
|
|
||||||
i2c_unregister_device(client_demod);
|
|
||||||
}
|
|
||||||
goto frontend_detach;
|
|
||||||
}
|
|
||||||
port->i2c_client_ci = client_ci;
|
|
||||||
|
|
||||||
if (port->nr != 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Read entire EEPROM */
|
|
||||||
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
|
|
||||||
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
|
|
||||||
sizeof(eeprom));
|
|
||||||
printk(KERN_INFO "%s MAC address: %pM\n",
|
|
||||||
cx23885_boards[dev->board].name, eeprom + 0xc0);
|
|
||||||
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
frontend_detach:
|
frontend_detach:
|
||||||
|
/* remove I2C client for tuner */
|
||||||
|
client_tuner = port->i2c_client_tuner;
|
||||||
|
if (client_tuner) {
|
||||||
|
module_put(client_tuner->dev.driver->owner);
|
||||||
|
i2c_unregister_device(client_tuner);
|
||||||
|
port->i2c_client_tuner = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove I2C client for demodulator */
|
||||||
|
client_demod = port->i2c_client_demod;
|
||||||
|
if (client_demod) {
|
||||||
|
module_put(client_demod->dev.driver->owner);
|
||||||
|
i2c_unregister_device(client_demod);
|
||||||
|
port->i2c_client_demod = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
port->gate_ctrl = NULL;
|
port->gate_ctrl = NULL;
|
||||||
vb2_dvb_dealloc_frontends(&port->frontends);
|
vb2_dvb_dealloc_frontends(&port->frontends);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -300,8 +300,8 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
|
||||||
rc = i2c_master_recv(c, &buf, 0);
|
rc = i2c_master_recv(c, &buf, 0);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
continue;
|
continue;
|
||||||
printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
|
printk(KERN_INFO "%s: i2c scan: found device @ 0x%04x [%s]\n",
|
||||||
name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
|
name, i, i2c_devs[i] ? i2c_devs[i] : "???");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue