mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 14:20:55 +07:00
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 spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE</constant> </entry>
|
||||
<entry>integer</entry>
|
||||
</row><row><entry spanname="descr">If the display delay is enabled then the decoder has to return a
|
||||
CAPTURE buffer after processing a certain number of OUTPUT buffers. If this number is low, then it may result in
|
||||
buffers not being dequeued in display order. In addition hardware may still use those buffers as reference, thus
|
||||
application should not write to those buffers. This feature can be used for example for generating thumbnails of videos.
|
||||
Applicable to the H264 decoder.
|
||||
<entry>boolean</entry>
|
||||
</row><row><entry spanname="descr">If the display delay is enabled then the decoder is forced to return a
|
||||
CAPTURE buffer (decoded frame) after processing a certain number of OUTPUT buffers. The delay can be set through
|
||||
<constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY</constant>. This feature can be used for example
|
||||
for generating thumbnails of videos. Applicable to the H264 decoder.
|
||||
</entry>
|
||||
</row>
|
||||
<row><entry></entry></row>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<refsect1>
|
||||
<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
|
||||
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
|
||||
|
@ -25,7 +25,7 @@
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<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,
|
||||
using the A-LAW algorithm. Each color component consumes 8
|
||||
bits of memory. In other respects this format is similar to
|
||||
|
@ -18,7 +18,7 @@
|
||||
<refsect1>
|
||||
<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
|
||||
compression. DPCM, differential pulse-code modulation, is lossy.
|
||||
Each colour component consumes 8 bits of memory. In other respects
|
||||
|
99
Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
Normal file
99
Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
Normal file
@ -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>
|
||||
<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
|
||||
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
|
||||
|
@ -1405,6 +1405,7 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
|
||||
&sub-srggb8;
|
||||
&sub-sbggr16;
|
||||
&sub-srggb10;
|
||||
&sub-srggb10p;
|
||||
&sub-srggb10alaw8;
|
||||
&sub-srggb10dpcm8;
|
||||
&sub-srggb12;
|
||||
|
@ -212,11 +212,3 @@ standards set in the <structfield>standards</structfield> field.
|
||||
&return-value;
|
||||
</refsect1>
|
||||
</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>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!--
|
||||
Local Variables:
|
||||
mode: sgml
|
||||
sgml-parent-document: "v4l2.sgml"
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
-->
|
||||
|
63
Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
Normal file
63
Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
Normal file
@ -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
|
||||
|
||||
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
|
||||
entries in clock-names property;
|
||||
- clock-names : should contain "apb" and "ir" entries;
|
||||
@ -10,6 +10,7 @@ Required properties:
|
||||
|
||||
Optional properties:
|
||||
- linux,rc-map-name : Remote control map name.
|
||||
- resets : phandle + reset specifier pair
|
||||
|
||||
Example:
|
||||
|
||||
@ -17,6 +18,7 @@ ir0: ir@01c21800 {
|
||||
compatible = "allwinner,sun4i-a10-ir";
|
||||
clocks = <&apb0_gates 6>, <&ir0_clk>;
|
||||
clock-names = "apb", "ir";
|
||||
resets = <&apb0_rst 1>;
|
||||
interrupts = <0 5 1>;
|
||||
reg = <0x01C21800 0x40>;
|
||||
linux,rc-map-name = "rc-rc6-mce";
|
||||
|
61
Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt
Normal file
61
Documentation/devicetree/bindings/media/ti-am437x-vpfe.txt
Normal file
@ -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.
|
||||
- clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
|
||||
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
|
||||
|
@ -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.
|
||||
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
|
||||
is the 'name' field of the video_device struct.
|
||||
video0 and you will see 'name', 'debug' and 'index' attributes. The 'name'
|
||||
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
|
||||
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
|
||||
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
|
||||
--------------------
|
||||
|
@ -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
|
||||
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
|
||||
M: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
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/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
|
||||
M: Kashyap Desai <kashyap.desai@avagotech.com>
|
||||
M: Sumit Saxena <sumit.saxena@avagotech.com>
|
||||
@ -7909,14 +7908,6 @@ T: git git://github.com/KrasnikovEugene/wcn36xx.git
|
||||
S: Supported
|
||||
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)
|
||||
M: Yehuda Sadeh <yehuda@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/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
|
||||
M: Zwane Mwaikambo <zwanem@gmail.com>
|
||||
S: Maintained
|
||||
@ -8825,6 +8810,15 @@ S: Maintained
|
||||
F: drivers/media/platform/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
|
||||
M: Francois Romieu <romieu@fr.zoreil.com>
|
||||
L: netdev@vger.kernel.org
|
||||
@ -8906,6 +8900,8 @@ F: drivers/media/i2c/smiapp/
|
||||
F: include/media/smiapp.h
|
||||
F: drivers/media/i2c/smiapp-pll.c
|
||||
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
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
@ -8972,6 +8968,7 @@ SOFTLOGIC 6x10 MPEG CODEC
|
||||
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
|
||||
M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
|
||||
M: Andrey Utkin <andrey.krieger.utkin@gmail.com>
|
||||
M: Ismael Luceno <ismael@iodev.co.uk>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/media/pci/solo6x10/
|
||||
|
@ -8,10 +8,6 @@ comment "common driver options"
|
||||
config VIDEO_CX2341X
|
||||
tristate
|
||||
|
||||
config VIDEO_BTCX
|
||||
depends on PCI
|
||||
tristate
|
||||
|
||||
config VIDEO_TVEEPROM
|
||||
tristate
|
||||
depends on I2C
|
||||
|
@ -1,5 +1,4 @@
|
||||
obj-y += b2c2/ saa7146/ siano/
|
||||
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
||||
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
|
||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.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,
|
||||
struct btcx_skiplist *skips, unsigned int *nskips,
|
||||
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_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 )
|
||||
{
|
||||
unsigned int j;
|
||||
@ -90,36 +83,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
|
||||
|
||||
#ifdef ULE_DEBUG
|
||||
|
||||
#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
|
||||
#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 )
|
||||
static void hexdump(const unsigned char *buf, unsigned short len)
|
||||
{
|
||||
char str[80], octet[10];
|
||||
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 );
|
||||
}
|
||||
print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -315,9 +281,9 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
|
||||
return l; /* Stop extension header processing and discard SNDU. */
|
||||
total_ext_len += l;
|
||||
#ifdef ULE_DEBUG
|
||||
dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
|
||||
"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
|
||||
(int) p->ule_sndu_type, l, total_ext_len);
|
||||
pr_debug("ule_next_hdr=%p, ule_sndu_type=%i, l=%i, total_ext_len=%i\n",
|
||||
p->ule_next_hdr, (int)p->ule_sndu_type,
|
||||
l, total_ext_len);
|
||||
#endif
|
||||
|
||||
} 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) {
|
||||
#ifdef ULE_DEBUG
|
||||
dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
|
||||
MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
|
||||
netdev_dbg(dev, "Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n",
|
||||
priv->ule_skb->data, dev->dev_addr);
|
||||
#endif
|
||||
dev_kfree_skb(priv->ule_skb);
|
||||
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[11]=mac_mask[0];
|
||||
|
||||
dprintk("%s: filter mac=%pM\n", dev->name, mac);
|
||||
dprintk("%s: filter mask=%pM\n", dev->name, mac_mask);
|
||||
netdev_dbg(dev, "filter mac=%pM mask=%pM\n", mac, mac_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -977,7 +942,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||
struct dmx_demux *demux = priv->demux;
|
||||
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);
|
||||
if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
|
||||
printk("%s: BUG %d\n", __func__, __LINE__);
|
||||
@ -987,7 +952,7 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||
priv->tsfeed = NULL;
|
||||
|
||||
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,
|
||||
dvb_net_sec_callback);
|
||||
if (ret<0) {
|
||||
@ -1005,38 +970,38 @@ static int dvb_net_feed_start(struct net_device *dev)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
switch (priv->rx_mode) {
|
||||
case RX_MODE_MULTI:
|
||||
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],
|
||||
priv->multi_macs[i], mask_normal);
|
||||
}
|
||||
break;
|
||||
case RX_MODE_ALL_MULTI:
|
||||
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],
|
||||
mac_allmulti, mask_allmulti);
|
||||
break;
|
||||
case RX_MODE_PROMISC:
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
dprintk("%s: start filtering\n", __func__);
|
||||
netdev_dbg(dev, "start filtering\n");
|
||||
priv->secfeed->start_filtering(priv->secfeed);
|
||||
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
|
||||
struct timespec timeout = { 0, 10000000 }; // 10 msec
|
||||
|
||||
/* 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);
|
||||
if (ret < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
dprintk("%s: start filtering\n", __func__);
|
||||
netdev_dbg(dev, "start filtering\n");
|
||||
priv->tsfeed->start_filtering(priv->tsfeed);
|
||||
} else
|
||||
ret = -EINVAL;
|
||||
@ -1075,17 +1040,16 @@ static int dvb_net_feed_stop(struct net_device *dev)
|
||||
struct dvb_net_priv *priv = netdev_priv(dev);
|
||||
int i, ret = 0;
|
||||
|
||||
dprintk("%s\n", __func__);
|
||||
mutex_lock(&priv->mutex);
|
||||
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
|
||||
if (priv->secfeed) {
|
||||
if (priv->secfeed->is_filtering) {
|
||||
dprintk("%s: stop secfeed\n", __func__);
|
||||
netdev_dbg(dev, "stop secfeed\n");
|
||||
priv->secfeed->stop_filtering(priv->secfeed);
|
||||
}
|
||||
|
||||
if (priv->secfilter) {
|
||||
dprintk("%s: release secfilter\n", __func__);
|
||||
netdev_dbg(dev, "release secfilter\n");
|
||||
priv->secfeed->release_filter(priv->secfeed,
|
||||
priv->secfilter);
|
||||
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++) {
|
||||
if (priv->multi_secfilter[i]) {
|
||||
dprintk("%s: release multi_filter[%d]\n",
|
||||
__func__, i);
|
||||
netdev_dbg(dev, "release multi_filter[%d]\n",
|
||||
i);
|
||||
priv->secfeed->release_filter(priv->secfeed,
|
||||
priv->multi_secfilter[i]);
|
||||
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) {
|
||||
if (priv->tsfeed) {
|
||||
if (priv->tsfeed->is_filtering) {
|
||||
dprintk("%s: stop tsfeed\n", __func__);
|
||||
netdev_dbg(dev, "stop tsfeed\n");
|
||||
priv->tsfeed->stop_filtering(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);
|
||||
|
||||
if (dev->flags & IFF_PROMISC) {
|
||||
dprintk("%s: promiscuous mode\n", dev->name);
|
||||
netdev_dbg(dev, "promiscuous mode\n");
|
||||
priv->rx_mode = RX_MODE_PROMISC;
|
||||
} 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;
|
||||
} else if (!netdev_mc_empty(dev)) {
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
dprintk("%s: set_mc_list, %d entries\n",
|
||||
dev->name, netdev_mc_count(dev));
|
||||
netdev_dbg(dev, "set_mc_list, %d entries\n",
|
||||
netdev_mc_count(dev));
|
||||
|
||||
priv->rx_mode = RX_MODE_MULTI;
|
||||
priv->multi_num = 0;
|
||||
|
@ -443,7 +443,8 @@ config DVB_CXD2820R
|
||||
|
||||
config DVB_RTL2830
|
||||
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
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
@ -451,6 +452,7 @@ config DVB_RTL2830
|
||||
config DVB_RTL2832
|
||||
tristate "Realtek RTL2832 DVB-T"
|
||||
depends on DVB_CORE && I2C && I2C_MUX
|
||||
select REGMAP
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
@ -91,8 +91,3 @@ enum au8522_audio_input {
|
||||
};
|
||||
|
||||
#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;
|
||||
enum frontend_tune_state *tune_state = &state->tune_state;
|
||||
int ret = 0;
|
||||
u16 reg, upd_demod_gain_period = 0x8000;
|
||||
u16 reg;
|
||||
u32 upd_demod_gain_period = 0x8000;
|
||||
|
||||
switch (*tune_state) {
|
||||
case CT_AGC_START:
|
||||
|
@ -22,20 +22,24 @@
|
||||
|
||||
#include "hd29l2_priv.h"
|
||||
|
||||
#define HD29L2_MAX_LEN (3)
|
||||
|
||||
/* write multiple registers */
|
||||
static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
|
||||
{
|
||||
int ret;
|
||||
u8 buf[2 + len];
|
||||
u8 buf[2 + HD29L2_MAX_LEN];
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
.addr = priv->cfg.i2c_addr,
|
||||
.flags = 0,
|
||||
.len = sizeof(buf),
|
||||
.len = 2 + len,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
if (len > HD29L2_MAX_LEN)
|
||||
return -EINVAL;
|
||||
buf[0] = 0x00;
|
||||
buf[1] = reg;
|
||||
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 */
|
||||
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;
|
||||
u8 tmp;
|
||||
|
@ -1456,9 +1456,3 @@ MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
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);
|
||||
}
|
||||
|
||||
static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
|
||||
enum lgdt3305_tp_clock_edge edge,
|
||||
enum lgdt3305_tp_valid_polarity valid)
|
||||
static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state)
|
||||
{
|
||||
u8 val;
|
||||
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);
|
||||
|
||||
@ -253,6 +254,8 @@ static int lgdt3305_mpeg_mode_polarity(struct lgdt3305_state *state,
|
||||
|
||||
if (edge)
|
||||
val |= 0x08;
|
||||
if (mode)
|
||||
val |= 0x40;
|
||||
if (valid)
|
||||
val |= 0x01;
|
||||
|
||||
@ -740,9 +743,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe)
|
||||
goto fail;
|
||||
|
||||
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
||||
ret = lgdt3305_mpeg_mode_polarity(state,
|
||||
state->cfg->tpclk_edge,
|
||||
state->cfg->tpvalid_polarity);
|
||||
ret = lgdt3305_mpeg_mode_polarity(state);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
@ -806,9 +807,7 @@ static int lgdt3305_set_parameters(struct dvb_frontend *fe)
|
||||
goto fail;
|
||||
|
||||
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
||||
ret = lgdt3305_mpeg_mode_polarity(state,
|
||||
state->cfg->tpclk_edge,
|
||||
state->cfg->tpvalid_polarity);
|
||||
ret = lgdt3305_mpeg_mode_polarity(state);
|
||||
fail:
|
||||
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_LICENSE("GPL");
|
||||
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,
|
||||
};
|
||||
|
||||
enum lgdt3305_tp_clock_mode {
|
||||
LGDT3305_TPCLK_GATED = 0,
|
||||
LGDT3305_TPCLK_FIXED = 1,
|
||||
};
|
||||
|
||||
enum lgdt3305_tp_valid_polarity {
|
||||
LGDT3305_TP_VALID_LOW = 0,
|
||||
LGDT3305_TP_VALID_HIGH = 1,
|
||||
@ -70,6 +75,7 @@ struct lgdt3305_config {
|
||||
|
||||
enum lgdt3305_mpeg_mode mpeg_mode;
|
||||
enum lgdt3305_tp_clock_edge tpclk_edge;
|
||||
enum lgdt3305_tp_clock_mode tpclk_mode;
|
||||
enum lgdt3305_tp_valid_polarity tpvalid_polarity;
|
||||
enum lgdt_demod_chip_type demod_chip;
|
||||
};
|
||||
|
@ -823,9 +823,3 @@ MODULE_AUTHOR("Wilson Michaels");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
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 /* LGDT330X_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -69,9 +69,3 @@ enum I2C_REG {
|
||||
};
|
||||
|
||||
#endif /* _LGDT330X_PRIV_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
#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 {
|
||||
MB86A20S_13SEG = 0,
|
||||
MB86A20S_13SEG_PARTIAL = 1,
|
||||
|
@ -33,6 +33,12 @@ struct mn88472_config {
|
||||
* DVB frontend.
|
||||
*/
|
||||
struct dvb_frontend **fe;
|
||||
|
||||
/*
|
||||
* Xtal frequency.
|
||||
* Hz
|
||||
*/
|
||||
u32 xtal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -55,9 +55,3 @@ static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* c
|
||||
#endif // CONFIG_DVB_NXT200X
|
||||
|
||||
#endif /* NXT200X_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -623,9 +623,3 @@ MODULE_AUTHOR("Trent Piepho");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
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 // 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
|
||||
* 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
|
||||
#define RTL2830_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
struct rtl2830_config {
|
||||
/*
|
||||
* Demodulator I2C address.
|
||||
*/
|
||||
u8 i2c_addr;
|
||||
/**
|
||||
* struct rtl2830_platform_data - Platform data for the rtl2830 driver
|
||||
* @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
|
||||
* @spec_inv: Spectrum inversion.
|
||||
* @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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Xtal frequency.
|
||||
* Hz
|
||||
* 4000000, 16000000, 25000000, 28800000
|
||||
*/
|
||||
u32 xtal;
|
||||
|
||||
/*
|
||||
* TS output mode.
|
||||
*/
|
||||
u8 ts_mode;
|
||||
|
||||
/*
|
||||
* Spectrum inversion.
|
||||
*/
|
||||
struct rtl2830_platform_data {
|
||||
u32 clk;
|
||||
bool spec_inv;
|
||||
|
||||
/*
|
||||
*/
|
||||
u8 vtop;
|
||||
|
||||
/*
|
||||
*/
|
||||
u8 krf;
|
||||
|
||||
/*
|
||||
*/
|
||||
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 */
|
||||
|
@ -13,9 +13,6 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef RTL2830_PRIV_H
|
||||
@ -24,16 +21,23 @@
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
#include "rtl2830.h"
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
struct rtl2830_priv {
|
||||
struct i2c_adapter *i2c;
|
||||
struct rtl2830_dev {
|
||||
struct rtl2830_platform_data *pdata;
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
struct i2c_adapter *adapter;
|
||||
struct dvb_frontend fe;
|
||||
struct rtl2830_config cfg;
|
||||
struct i2c_adapter tuner_i2c_adapter;
|
||||
|
||||
bool sleeping;
|
||||
|
||||
u8 page; /* active register page */
|
||||
unsigned long filters;
|
||||
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 {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
* Realtek RTL2832 DVB-T demodulator driver
|
||||
*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -21,86 +22,42 @@
|
||||
#ifndef RTL2832_H
|
||||
#define RTL2832_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
|
||||
struct rtl2832_config {
|
||||
/*
|
||||
* Demodulator I2C address.
|
||||
*/
|
||||
u8 i2c_addr;
|
||||
/**
|
||||
* struct rtl2832_platform_data - Platform data for the rtl2832 driver
|
||||
* @clk: Clock frequency (4000000, 16000000, 25000000, 28800000).
|
||||
* @tuner: Used tuner model.
|
||||
* @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.
|
||||
* Hz
|
||||
* 4000000, 16000000, 25000000, 28800000
|
||||
*/
|
||||
u32 xtal;
|
||||
|
||||
/*
|
||||
* tuner
|
||||
* XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver.
|
||||
* XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
|
||||
*/
|
||||
#define RTL2832_TUNER_TUA9001 0x24
|
||||
#define RTL2832_TUNER_FC0012 0x26
|
||||
#define RTL2832_TUNER_E4000 0x27
|
||||
#define RTL2832_TUNER_FC0013 0x29
|
||||
#define RTL2832_TUNER_R820T 0x2a
|
||||
#define RTL2832_TUNER_R828D 0x2b
|
||||
#define RTL2832_TUNER_R820T 0x2a
|
||||
#define RTL2832_TUNER_R828D 0x2b
|
||||
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 */
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Realtek RTL2832 DVB-T demodulator driver
|
||||
*
|
||||
* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -21,28 +22,34 @@
|
||||
#ifndef RTL2832_PRIV_H
|
||||
#define RTL2832_PRIV_H
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "rtl2832.h"
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
struct rtl2832_priv {
|
||||
struct i2c_adapter *i2c;
|
||||
struct i2c_adapter *i2c_adapter;
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
#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 dvb_frontend fe;
|
||||
struct rtl2832_config cfg;
|
||||
|
||||
bool i2c_gate_state;
|
||||
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;
|
||||
bool sleeping;
|
||||
|
||||
u8 tuner;
|
||||
u8 page; /* active register page */
|
||||
struct delayed_work i2c_gate_work;
|
||||
unsigned long filters; /* PID filter */
|
||||
};
|
||||
|
||||
struct rtl2832_reg_entry {
|
||||
u8 page;
|
||||
u8 start_address;
|
||||
u16 start_address;
|
||||
u8 msb;
|
||||
u8 lsb;
|
||||
};
|
||||
@ -52,7 +59,6 @@ struct rtl2832_reg_value {
|
||||
u32 value;
|
||||
};
|
||||
|
||||
|
||||
/* Demod register bit names */
|
||||
enum DVBT_REG_BIT_NAME {
|
||||
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:
|
||||
* 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
|
||||
#define RTL2832_SDR_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/i2c.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)
|
||||
extern struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
|
||||
struct v4l2_subdev *sd);
|
||||
#else
|
||||
static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
|
||||
struct v4l2_subdev *sd)
|
||||
{
|
||||
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
struct rtl2832_sdr_platform_data {
|
||||
u32 clk;
|
||||
/*
|
||||
* XXX: This list must be kept sync with dvb_usb_rtl28xxu USB IF driver.
|
||||
*/
|
||||
#define RTL2832_SDR_TUNER_TUA9001 0x24
|
||||
#define RTL2832_SDR_TUNER_FC0012 0x26
|
||||
#define RTL2832_SDR_TUNER_E4000 0x27
|
||||
#define RTL2832_SDR_TUNER_FC0013 0x29
|
||||
#define RTL2832_SDR_TUNER_R820T 0x2a
|
||||
#define RTL2832_SDR_TUNER_R828D 0x2b
|
||||
u8 tuner;
|
||||
|
||||
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 */
|
||||
|
@ -1021,9 +1021,3 @@ static struct dvb_frontend_ops s5h1409_ops = {
|
||||
MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
|
||||
MODULE_AUTHOR("Steven Toth");
|
||||
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 /* __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_AUTHOR("Steven Toth");
|
||||
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 /* __S5H1411_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
*/
|
||||
|
@ -19,16 +19,17 @@
|
||||
static const struct dvb_frontend_ops si2168_ops;
|
||||
|
||||
/* 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;
|
||||
unsigned long timeout;
|
||||
|
||||
mutex_lock(&s->i2c_mutex);
|
||||
mutex_lock(&dev->i2c_mutex);
|
||||
|
||||
if (cmd->wlen) {
|
||||
/* 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) {
|
||||
goto err_mutex_unlock;
|
||||
} else if (ret != cmd->wlen) {
|
||||
@ -39,10 +40,10 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
||||
|
||||
if (cmd->rlen) {
|
||||
/* wait cmd execution terminate */
|
||||
#define TIMEOUT 50
|
||||
#define TIMEOUT 70
|
||||
timeout = jiffies + msecs_to_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) {
|
||||
goto err_mutex_unlock;
|
||||
} else if (ret != cmd->rlen) {
|
||||
@ -55,7 +56,7 @@ static int si2168_cmd_execute(struct si2168 *s, struct si2168_cmd *cmd)
|
||||
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(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:
|
||||
mutex_unlock(&s->i2c_mutex);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
mutex_unlock(&dev->i2c_mutex);
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
struct si2168_cmd cmd;
|
||||
|
||||
*status = 0;
|
||||
|
||||
if (!s->active) {
|
||||
if (!dev->active) {
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
}
|
||||
@ -113,21 +111,10 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
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) {
|
||||
case 0x01:
|
||||
*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;
|
||||
}
|
||||
|
||||
s->fe_status = *status;
|
||||
dev->fe_status = *status;
|
||||
|
||||
if (*status & FE_HAS_LOCK) {
|
||||
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;
|
||||
}
|
||||
|
||||
dev_dbg(&s->client->dev, "status=%02x args=%*ph\n",
|
||||
dev_dbg(&client->dev, "status=%02x args=%*ph\n",
|
||||
*status, cmd.rlen, cmd.args);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
struct si2168_cmd cmd;
|
||||
u8 bandwidth, delivery_system;
|
||||
|
||||
dev_dbg(&s->client->dev,
|
||||
"delivery_system=%u modulation=%u frequency=%u bandwidth_hz=%u symbol_rate=%u inversion=%u, stream_id=%d\n",
|
||||
c->delivery_system, c->modulation,
|
||||
c->frequency, c->bandwidth_hz, c->symbol_rate,
|
||||
c->inversion, c->stream_id);
|
||||
dev_dbg(&client->dev,
|
||||
"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->frequency,
|
||||
c->bandwidth_hz, c->symbol_rate, c->inversion,
|
||||
c->stream_id);
|
||||
|
||||
if (!s->active) {
|
||||
if (!dev->active) {
|
||||
ret = -EAGAIN;
|
||||
goto err;
|
||||
}
|
||||
@ -192,7 +180,12 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
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;
|
||||
else if (c->bandwidth_hz <= 6000000)
|
||||
bandwidth = 0x06;
|
||||
@ -217,7 +210,7 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
|
||||
cmd.wlen = 5;
|
||||
cmd.rlen = 5;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
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);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 3;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
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.wlen = 3;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
@ -249,35 +242,35 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
memcpy(cmd.args, "\x51\x03", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 12;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x12\x08\x04", 3);
|
||||
cmd.wlen = 3;
|
||||
cmd.rlen = 3;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -285,18 +278,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
|
||||
cmd.args[4] = delivery_system | bandwidth;
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* set DVB-C symbol rate */
|
||||
if (c->delivery_system == SYS_DVBC_ANNEX_A) {
|
||||
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.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
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);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
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.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
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.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
|
||||
cmd.wlen = 6;
|
||||
cmd.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x85", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
s->delivery_system = c->delivery_system;
|
||||
dev->delivery_system = c->delivery_system;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
const struct firmware *fw = NULL;
|
||||
u8 *fw_file;
|
||||
const unsigned int i2c_wr_max = 8;
|
||||
const struct firmware *fw;
|
||||
const char *fw_name;
|
||||
struct si2168_cmd cmd;
|
||||
unsigned int chip_id;
|
||||
|
||||
dev_dbg(&s->client->dev, "\n");
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
/* initialize */
|
||||
memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
|
||||
cmd.wlen = 13;
|
||||
cmd.rlen = 0;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (s->fw_loaded) {
|
||||
if (dev->fw_loaded) {
|
||||
/* resume */
|
||||
memcpy(cmd.args, "\xc0\x06\x08\x0f\x00\x20\x21\x01", 8);
|
||||
cmd.wlen = 8;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
memcpy(cmd.args, "\x85", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
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);
|
||||
cmd.wlen = 8;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -404,7 +397,7 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
memcpy(cmd.args, "\x02", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 13;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -417,50 +410,48 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
|
||||
switch (chip_id) {
|
||||
case SI2168_A20:
|
||||
fw_file = SI2168_A20_FIRMWARE;
|
||||
fw_name = SI2168_A20_FIRMWARE;
|
||||
break;
|
||||
case SI2168_A30:
|
||||
fw_file = SI2168_A30_FIRMWARE;
|
||||
fw_name = SI2168_A30_FIRMWARE;
|
||||
break;
|
||||
case SI2168_B40:
|
||||
fw_file = SI2168_B40_FIRMWARE;
|
||||
fw_name = SI2168_B40_FIRMWARE;
|
||||
break;
|
||||
default:
|
||||
dev_err(&s->client->dev,
|
||||
"unknown chip version Si21%d-%c%c%c\n",
|
||||
dev_err(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
|
||||
cmd.args[2], cmd.args[1],
|
||||
cmd.args[3], cmd.args[4]);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* cold state - try to download firmware */
|
||||
dev_info(&s->client->dev, "found a '%s' in cold state\n",
|
||||
si2168_ops.info.name);
|
||||
dev_info(&client->dev, "found a 'Silicon Labs Si21%d-%c%c%c'\n",
|
||||
cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
|
||||
|
||||
/* 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) {
|
||||
/* fallback mechanism to handle old name for Si2168 B40 fw */
|
||||
if (chip_id == SI2168_B40) {
|
||||
fw_file = SI2168_B40_FIRMWARE_FALLBACK;
|
||||
ret = request_firmware(&fw, fw_file, &s->client->dev);
|
||||
fw_name = SI2168_B40_FIRMWARE_FALLBACK;
|
||||
ret = request_firmware(&fw, fw_name, &client->dev);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
dev_notice(&s->client->dev,
|
||||
dev_notice(&client->dev,
|
||||
"please install firmware file '%s'\n",
|
||||
SI2168_B40_FIRMWARE);
|
||||
} else {
|
||||
dev_err(&s->client->dev,
|
||||
dev_err(&client->dev,
|
||||
"firmware file '%s' not found\n",
|
||||
fw_file);
|
||||
goto error_fw_release;
|
||||
fw_name);
|
||||
goto err_release_firmware;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
|
||||
fw_file);
|
||||
dev_info(&client->dev, "downloading firmware from file '%s'\n",
|
||||
fw_name);
|
||||
|
||||
if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
|
||||
/* 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);
|
||||
cmd.wlen = len;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret) {
|
||||
dev_err(&s->client->dev,
|
||||
"firmware download failed=%d\n",
|
||||
ret);
|
||||
goto error_fw_release;
|
||||
}
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
} else if (fw->size % 8 == 0) {
|
||||
/* firmware is in the old format */
|
||||
for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
|
||||
len = remaining;
|
||||
if (len > i2c_wr_max)
|
||||
len = i2c_wr_max;
|
||||
|
||||
for (remaining = fw->size; remaining > 0; remaining -= 8) {
|
||||
len = 8;
|
||||
memcpy(cmd.args, &fw->data[fw->size - remaining], len);
|
||||
cmd.wlen = len;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
if (ret) {
|
||||
dev_err(&s->client->dev,
|
||||
"firmware download failed=%d\n",
|
||||
ret);
|
||||
goto error_fw_release;
|
||||
}
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
} 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);
|
||||
fw = NULL;
|
||||
|
||||
memcpy(cmd.args, "\x01\x01", 2);
|
||||
cmd.wlen = 2;
|
||||
cmd.rlen = 1;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -511,58 +498,56 @@ static int si2168_init(struct dvb_frontend *fe)
|
||||
memcpy(cmd.args, "\x11", 1);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 10;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
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]);
|
||||
|
||||
/* set ts mode */
|
||||
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.rlen = 4;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
s->fw_loaded = true;
|
||||
|
||||
dev_info(&s->client->dev, "found a '%s' in warm state\n",
|
||||
si2168_ops.info.name);
|
||||
dev->fw_loaded = true;
|
||||
warm:
|
||||
s->active = true;
|
||||
dev->active = true;
|
||||
|
||||
return 0;
|
||||
|
||||
error_fw_release:
|
||||
err_release_firmware:
|
||||
release_firmware(fw);
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
cmd.wlen = 1;
|
||||
cmd.rlen = 0;
|
||||
ret = si2168_cmd_execute(s, &cmd);
|
||||
ret = si2168_cmd_execute(client, &cmd);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&s->client->dev, "failed=%d\n", ret);
|
||||
dev_dbg(&client->dev, "failed=%d\n", 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)
|
||||
{
|
||||
struct si2168 *s = mux_priv;
|
||||
struct i2c_client *client = mux_priv;
|
||||
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
struct i2c_msg gate_open_msg = {
|
||||
.addr = s->client->addr,
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.len = 3,
|
||||
.buf = "\xc0\x0d\x01",
|
||||
};
|
||||
|
||||
mutex_lock(&s->i2c_mutex);
|
||||
mutex_lock(&dev->i2c_mutex);
|
||||
|
||||
/* 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) {
|
||||
dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
|
||||
dev_warn(&client->dev, "i2c write failed=%d\n", ret);
|
||||
if (ret >= 0)
|
||||
ret = -EREMOTEIO;
|
||||
} 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)
|
||||
{
|
||||
struct si2168 *s = mux_priv;
|
||||
struct i2c_client *client = mux_priv;
|
||||
struct si2168_dev *dev = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
struct i2c_msg gate_close_msg = {
|
||||
.addr = s->client->addr,
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.len = 3,
|
||||
.buf = "\xc0\x0d\x00",
|
||||
};
|
||||
|
||||
/* 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) {
|
||||
dev_warn(&s->client->dev, "i2c write failed=%d\n", ret);
|
||||
dev_warn(&client->dev, "i2c write failed=%d\n", ret);
|
||||
if (ret >= 0)
|
||||
ret = -EREMOTEIO;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&s->i2c_mutex);
|
||||
mutex_unlock(&dev->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -635,6 +622,8 @@ static const struct dvb_frontend_ops si2168_ops = {
|
||||
.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
|
||||
.info = {
|
||||
.name = "Silicon Labs Si2168",
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 7200000,
|
||||
.caps = FE_CAN_FEC_1_2 |
|
||||
FE_CAN_FEC_2_3 |
|
||||
FE_CAN_FEC_3_4 |
|
||||
@ -670,71 +659,69 @@ static int si2168_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct si2168_config *config = client->dev.platform_data;
|
||||
struct si2168 *s;
|
||||
struct si2168_dev *dev;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&client->dev, "\n");
|
||||
|
||||
s = kzalloc(sizeof(struct si2168), GFP_KERNEL);
|
||||
if (!s) {
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
ret = -ENOMEM;
|
||||
dev_err(&client->dev, "kzalloc() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->client = client;
|
||||
mutex_init(&s->i2c_mutex);
|
||||
mutex_init(&dev->i2c_mutex);
|
||||
|
||||
/* create mux i2c adapter for tuner */
|
||||
s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
|
||||
0, 0, 0, si2168_select, si2168_deselect);
|
||||
if (s->adapter == NULL) {
|
||||
dev->adapter = i2c_add_mux_adapter(client->adapter, &client->dev,
|
||||
client, 0, 0, 0, si2168_select, si2168_deselect);
|
||||
if (dev->adapter == NULL) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
goto err_kfree;
|
||||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
|
||||
s->fe.demodulator_priv = s;
|
||||
memcpy(&dev->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
|
||||
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;
|
||||
*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, dev);
|
||||
|
||||
i2c_set_clientdata(client, s);
|
||||
|
||||
dev_info(&s->client->dev,
|
||||
"Silicon Labs Si2168 successfully attached\n");
|
||||
dev_info(&client->dev, "Silicon Labs Si2168 successfully attached\n");
|
||||
return 0;
|
||||
err_kfree:
|
||||
kfree(dev);
|
||||
err:
|
||||
kfree(s);
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
i2c_del_mux_adapter(s->adapter);
|
||||
i2c_del_mux_adapter(dev->adapter);
|
||||
|
||||
s->fe.ops.release = NULL;
|
||||
s->fe.demodulator_priv = NULL;
|
||||
dev->fe.ops.release = NULL;
|
||||
dev->fe.demodulator_priv = NULL;
|
||||
|
||||
kfree(s);
|
||||
kfree(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id si2168_id[] = {
|
||||
static const struct i2c_device_id si2168_id_table[] = {
|
||||
{"si2168", 0},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, si2168_id);
|
||||
MODULE_DEVICE_TABLE(i2c, si2168_id_table);
|
||||
|
||||
static struct i2c_driver si2168_driver = {
|
||||
.driver = {
|
||||
@ -743,7 +730,7 @@ static struct i2c_driver si2168_driver = {
|
||||
},
|
||||
.probe = si2168_probe,
|
||||
.remove = si2168_remove,
|
||||
.id_table = si2168_id,
|
||||
.id_table = si2168_id_table,
|
||||
};
|
||||
|
||||
module_i2c_driver(si2168_driver);
|
||||
|
@ -36,14 +36,12 @@ struct si2168_config {
|
||||
struct i2c_adapter **i2c_adapter;
|
||||
|
||||
/* TS mode */
|
||||
#define SI2168_TS_PARALLEL 0x06
|
||||
#define SI2168_TS_SERIAL 0x03
|
||||
u8 ts_mode;
|
||||
|
||||
/* TS clock inverted */
|
||||
bool ts_clock_inv;
|
||||
|
||||
};
|
||||
|
||||
#define SI2168_TS_PARALLEL 0x06
|
||||
#define SI2168_TS_SERIAL 0x03
|
||||
|
||||
#endif
|
||||
|
@ -28,8 +28,7 @@
|
||||
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
|
||||
|
||||
/* state struct */
|
||||
struct si2168 {
|
||||
struct i2c_client *client;
|
||||
struct si2168_dev {
|
||||
struct i2c_adapter *adapter;
|
||||
struct mutex i2c_mutex;
|
||||
struct dvb_frontend fe;
|
||||
|
@ -19,6 +19,7 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include "stb0899_drv.h"
|
||||
#include "stb0899_priv.h"
|
||||
#include "stb0899_reg.h"
|
||||
@ -1490,9 +1491,7 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
|
||||
/* Store signal parameters */
|
||||
offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
|
||||
|
||||
/* sign extend 30 bit value before using it in calculations */
|
||||
if (offsetfreq & (1 << 29))
|
||||
offsetfreq |= -1 << 30;
|
||||
offsetfreq = sign_extend32(offsetfreq, 29);
|
||||
|
||||
offsetfreq = offsetfreq / ((1 << 30) / 1000);
|
||||
offsetfreq *= (internal->master_clk / 1000000);
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.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);
|
||||
if (!STB0899_GETFIELD(FIFOFULL, reg))
|
||||
break;
|
||||
if ((jiffies - start) > timeout) {
|
||||
if (time_after(jiffies, start + timeout)) {
|
||||
dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -733,7 +734,7 @@ static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
|
||||
|
||||
while (!STB0899_GETFIELD(RXEND, reg)) {
|
||||
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!!");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -782,7 +783,7 @@ static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
|
||||
|
||||
while (!STB0899_GETFIELD(TXIDLE, reg)) {
|
||||
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!!");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -214,6 +214,7 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe)
|
||||
state = fe->demodulator_priv;
|
||||
c = &fe->dtv_property_cache;
|
||||
c->delivery_system = SYS_ISDBS;
|
||||
c->symbol_rate = 28860000;
|
||||
|
||||
layers = 0;
|
||||
ret = reg_read(state, 0xe6, val, 5);
|
||||
|
@ -177,7 +177,7 @@ comment "Video decoders"
|
||||
|
||||
config VIDEO_ADV7180
|
||||
tristate "Analog Devices ADV7180 decoder"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
---help---
|
||||
Support for the Analog Devices ADV7180 video decoder.
|
||||
|
||||
@ -196,7 +196,7 @@ config VIDEO_ADV7183
|
||||
|
||||
config VIDEO_ADV7604
|
||||
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---
|
||||
Support for the Analog Devices ADV7604 video decoder.
|
||||
|
||||
@ -208,7 +208,8 @@ config VIDEO_ADV7604
|
||||
|
||||
config VIDEO_ADV7842
|
||||
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---
|
||||
Support for the Analog Devices ADV7842 video decoder.
|
||||
|
||||
@ -422,7 +423,7 @@ config VIDEO_ADV7393
|
||||
|
||||
config VIDEO_ADV7511
|
||||
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---
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct adv7604_state *state = to_state(sd);
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/v4l2-dv-timings.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ctrls.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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*********** avi info frame CEA-861-E **************/
|
||||
/* TODO move to common library */
|
||||
|
||||
struct avi_info_frame {
|
||||
uint8_t f17;
|
||||
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;
|
||||
struct adv7842_cfg_read_infoframe {
|
||||
const char *desc;
|
||||
u8 present_mask;
|
||||
u8 head_addr;
|
||||
u8 payload_addr;
|
||||
};
|
||||
|
||||
static const char *y10_txt[4] = {
|
||||
"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)
|
||||
static void log_infoframe(struct v4l2_subdev *sd, struct adv7842_cfg_read_infoframe *cri)
|
||||
{
|
||||
int i;
|
||||
uint8_t buf[14];
|
||||
u8 avi_len;
|
||||
u8 avi_ver;
|
||||
struct avi_info_frame avi;
|
||||
uint8_t buffer[32];
|
||||
union hdmi_infoframe frame;
|
||||
u8 len;
|
||||
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)) {
|
||||
v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
|
||||
return;
|
||||
}
|
||||
if (!(io_read(sd, 0x60) & 0x01)) {
|
||||
v4l2_info(sd, "AVI infoframe not received\n");
|
||||
v4l2_info(sd, "receive DVI-D signal, no infoframes\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (io_read(sd, 0x88) & 0x10) {
|
||||
v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
|
||||
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]);
|
||||
for (i = 0; i < ARRAY_SIZE(cri); i++)
|
||||
log_infoframe(sd, &cri[i]);
|
||||
}
|
||||
|
||||
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",
|
||||
deep_color_mode_txt[hdmi_read(sd, 0x0b) >> 6]);
|
||||
|
||||
print_avi_infoframe(sd);
|
||||
adv7842_log_infoframes(sd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -125,9 +125,9 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
|
||||
if (length == 1)
|
||||
return *data;
|
||||
else if (length == 2)
|
||||
return be16_to_cpu(*((u16 *)data));
|
||||
return be16_to_cpu(*((__be16 *)data));
|
||||
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;
|
||||
}
|
||||
|
||||
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",
|
||||
is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
|
||||
"Samsung Electro-Machanics" :
|
||||
|
@ -904,11 +904,3 @@ static struct 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;
|
||||
}
|
||||
|
||||
static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9m032 *sensor = to_mt9m032(subdev);
|
||||
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
return -EINVAL;
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9m032 *sensor = to_mt9m032(subdev);
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
@ -445,9 +448,12 @@ static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_rect rect;
|
||||
int ret = 0;
|
||||
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&sensor->lock);
|
||||
|
||||
if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||
if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||
ret = -EBUSY;
|
||||
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
|
||||
* 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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,
|
||||
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) {
|
||||
/* Reset the output image size if the crop rectangle size has
|
||||
* 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->height = rect.height;
|
||||
}
|
||||
|
||||
*__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);
|
||||
|
||||
done:
|
||||
@ -690,8 +696,8 @@ static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
|
||||
.enum_frame_size = mt9m032_enum_frame_size,
|
||||
.get_fmt = mt9m032_get_pad_format,
|
||||
.set_fmt = mt9m032_set_pad_format,
|
||||
.set_crop = mt9m032_set_pad_crop,
|
||||
.get_crop = mt9m032_get_pad_crop,
|
||||
.set_selection = mt9m032_set_pad_selection,
|
||||
.get_selection = mt9m032_get_pad_selection,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops mt9m032_ops = {
|
||||
|
@ -581,37 +581,42 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9p031_get_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9p031_get_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
|
||||
|
||||
crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
|
||||
crop->which);
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
return -EINVAL;
|
||||
|
||||
sel->r = *__mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9p031_set_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9p031_set_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9p031 *mt9p031 = to_mt9p031(subdev);
|
||||
struct v4l2_mbus_framefmt *__format;
|
||||
struct v4l2_rect *__crop;
|
||||
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
|
||||
* 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);
|
||||
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);
|
||||
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_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_MAX);
|
||||
|
||||
@ -620,20 +625,20 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
|
||||
rect.height = min_t(unsigned int, rect.height,
|
||||
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) {
|
||||
/* Reset the output image size if the crop rectangle size has
|
||||
* been modified.
|
||||
*/
|
||||
__format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
|
||||
crop->which);
|
||||
__format = __mt9p031_get_pad_format(mt9p031, fh, sel->pad,
|
||||
sel->which);
|
||||
__format->width = rect.width;
|
||||
__format->height = rect.height;
|
||||
}
|
||||
|
||||
*__crop = rect;
|
||||
crop->rect = rect;
|
||||
sel->r = rect;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -980,8 +985,8 @@ static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
|
||||
.enum_frame_size = mt9p031_enum_frame_size,
|
||||
.get_fmt = mt9p031_get_format,
|
||||
.set_fmt = mt9p031_set_format,
|
||||
.get_crop = mt9p031_get_crop,
|
||||
.set_crop = mt9p031_set_crop,
|
||||
.get_selection = mt9p031_get_selection,
|
||||
.set_selection = mt9p031_set_selection,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops mt9p031_subdev_ops = {
|
||||
|
@ -401,39 +401,44 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9t001_get_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9t001_get_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
|
||||
|
||||
crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
|
||||
crop->which);
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
return -EINVAL;
|
||||
|
||||
sel->r = *__mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9t001_set_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9t001_set_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9t001 *mt9t001 = to_mt9t001(subdev);
|
||||
struct v4l2_mbus_framefmt *__format;
|
||||
struct v4l2_rect *__crop;
|
||||
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
|
||||
* pixels.
|
||||
*/
|
||||
rect.left = clamp(ALIGN(crop->rect.left, 2),
|
||||
rect.left = clamp(ALIGN(sel->r.left, 2),
|
||||
MT9T001_COLUMN_START_MIN,
|
||||
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_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_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_MAX + 1);
|
||||
|
||||
@ -442,20 +447,20 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
|
||||
rect.height = min_t(unsigned int, rect.height,
|
||||
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) {
|
||||
/* Reset the output image size if the crop rectangle size has
|
||||
* been modified.
|
||||
*/
|
||||
__format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad,
|
||||
crop->which);
|
||||
__format = __mt9t001_get_pad_format(mt9t001, fh, sel->pad,
|
||||
sel->which);
|
||||
__format->width = rect.width;
|
||||
__format->height = rect.height;
|
||||
}
|
||||
|
||||
*__crop = rect;
|
||||
crop->rect = rect;
|
||||
sel->r = rect;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -819,8 +824,8 @@ static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
|
||||
.enum_frame_size = mt9t001_enum_frame_size,
|
||||
.get_fmt = mt9t001_get_format,
|
||||
.set_fmt = mt9t001_set_format,
|
||||
.get_crop = mt9t001_get_crop,
|
||||
.set_crop = mt9t001_set_crop,
|
||||
.get_selection = mt9t001_get_selection,
|
||||
.set_selection = mt9t001_set_selection,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops mt9t001_subdev_ops = {
|
||||
|
@ -552,39 +552,44 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9v032_get_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9v032_get_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
|
||||
crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
|
||||
crop->which);
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
return -EINVAL;
|
||||
|
||||
sel->r = *__mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int mt9v032_set_selection(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
struct v4l2_mbus_framefmt *__format;
|
||||
struct v4l2_rect *__crop;
|
||||
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
|
||||
* 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_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_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_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_MAX);
|
||||
|
||||
@ -593,17 +598,17 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||
rect.height = min_t(unsigned int,
|
||||
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) {
|
||||
/* Reset the output image size if the crop rectangle size has
|
||||
* been modified.
|
||||
*/
|
||||
__format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
|
||||
crop->which);
|
||||
__format = __mt9v032_get_pad_format(mt9v032, fh, sel->pad,
|
||||
sel->which);
|
||||
__format->width = rect.width;
|
||||
__format->height = rect.height;
|
||||
if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||
if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
|
||||
mt9v032->hratio = 1;
|
||||
mt9v032->vratio = 1;
|
||||
mt9v032_configure_pixel_rate(mt9v032);
|
||||
@ -611,7 +616,7 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||
}
|
||||
|
||||
*__crop = rect;
|
||||
crop->rect = rect;
|
||||
sel->r = rect;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -844,8 +849,8 @@ static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
|
||||
.enum_frame_size = mt9v032_enum_frame_size,
|
||||
.get_fmt = mt9v032_get_format,
|
||||
.set_fmt = mt9v032_set_format,
|
||||
.get_crop = mt9v032_get_crop,
|
||||
.set_crop = mt9v032_set_crop,
|
||||
.get_selection = mt9v032_get_selection,
|
||||
.set_selection = mt9v032_set_selection,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
@ -341,7 +341,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
|
||||
v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE);
|
||||
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",
|
||||
S5K4ECGX_FIRMWARE, fw->size, regs_num);
|
||||
@ -351,8 +351,7 @@ static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
|
||||
err = -EINVAL;
|
||||
goto fw_out;
|
||||
}
|
||||
crc_file = le32_to_cpu(get_unaligned_le32(fw->data +
|
||||
regs_num * FW_RECORD_SIZE));
|
||||
crc_file = get_unaligned_le32(fw->data + regs_num * FW_RECORD_SIZE);
|
||||
crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE);
|
||||
if (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;
|
||||
for (i = 1; i < regs_num; i++) {
|
||||
addr = le32_to_cpu(get_unaligned_le32(ptr));
|
||||
addr = get_unaligned_le32(ptr);
|
||||
ptr += sizeof(u32);
|
||||
val = le16_to_cpu(get_unaligned_le16(ptr));
|
||||
val = get_unaligned_le16(ptr);
|
||||
ptr += sizeof(u16);
|
||||
if (addr - addr_inc != 2)
|
||||
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,
|
||||
size_t count, const u16 *data)
|
||||
size_t count, const __le16 *data)
|
||||
{
|
||||
struct s5k5baf_fw *f;
|
||||
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);
|
||||
__be16 w, r;
|
||||
u16 res;
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = c->addr, .flags = 0,
|
||||
.len = 2, .buf = (u8 *)&w },
|
||||
@ -434,15 +435,15 @@ static u16 s5k5baf_i2c_read(struct s5k5baf *state, u16 addr)
|
||||
|
||||
w = cpu_to_be16(addr);
|
||||
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) {
|
||||
v4l2_err(c, "i2c_read: error during transfer (%d)\n", ret);
|
||||
state->error = ret;
|
||||
}
|
||||
return r;
|
||||
return res;
|
||||
}
|
||||
|
||||
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,
|
||||
(u16 *)fw->data);
|
||||
(__le16 *)fw->data);
|
||||
|
||||
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 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 s5k5baf_gpio *g = state->gpios;
|
||||
int ret, i;
|
||||
|
@ -348,7 +348,7 @@ static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
|
||||
msg[1].buf = rbuf;
|
||||
|
||||
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);
|
||||
|
||||
@ -1161,17 +1161,21 @@ static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int s5k6aa_get_selection(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
|
||||
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);
|
||||
rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
|
||||
crop->rect = *rect;
|
||||
rect = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
|
||||
sel->r = *rect;
|
||||
mutex_unlock(&s5k6aa->lock);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_crop *crop)
|
||||
static int s5k6aa_set_selection(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
{
|
||||
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
|
||||
struct v4l2_mbus_framefmt *mf;
|
||||
unsigned int max_x, max_y;
|
||||
struct v4l2_rect *crop_r;
|
||||
|
||||
mutex_lock(&s5k6aa->lock);
|
||||
crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
|
||||
if (sel->target != V4L2_SEL_TGT_CROP)
|
||||
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;
|
||||
s5k6aa->apply_crop = 1;
|
||||
} else {
|
||||
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,
|
||||
&crop->rect.height, mf->height,
|
||||
&sel->r.height, mf->height,
|
||||
S5K6AA_WIN_HEIGHT_MAX, 1, 0);
|
||||
|
||||
max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1;
|
||||
max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1;
|
||||
max_x = (S5K6AA_WIN_WIDTH_MAX - sel->r.width) & ~1;
|
||||
max_y = (S5K6AA_WIN_HEIGHT_MAX - sel->r.height) & ~1;
|
||||
|
||||
crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x);
|
||||
crop->rect.top = clamp_t(unsigned int, crop->rect.top, 0, max_y);
|
||||
sel->r.left = clamp_t(unsigned int, sel->r.left, 0, max_x);
|
||||
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);
|
||||
|
||||
@ -1224,8 +1232,8 @@ static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
|
||||
.enum_frame_interval = s5k6aa_enum_frame_interval,
|
||||
.get_fmt = s5k6aa_get_fmt,
|
||||
.set_fmt = s5k6aa_set_fmt,
|
||||
.get_crop = s5k6aa_get_crop,
|
||||
.set_crop = s5k6aa_set_crop,
|
||||
.get_selection = s5k6aa_get_selection,
|
||||
.set_selection = s5k6aa_set_selection,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
|
||||
|
@ -14,14 +14,9 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gcd.h>
|
||||
#include <linux/lcm.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -14,19 +14,11 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SMIAPP_PLL_H
|
||||
#define SMIAPP_PLL_H
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
/* CSI-2 or CCP-2 */
|
||||
#define SMIAPP_PLL_BUS_TYPE_CSI2 0x00
|
||||
#define SMIAPP_PLL_BUS_TYPE_PARALLEL 0x01
|
||||
|
@ -18,12 +18,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@ -31,11 +25,13 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smiapp.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-of.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)
|
||||
{
|
||||
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;
|
||||
|
||||
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12);
|
||||
if (rval)
|
||||
return rval;
|
||||
|
||||
sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
|
||||
|
||||
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,
|
||||
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) {
|
||||
dev_err(&client->dev,
|
||||
"pixel array controls initialization failed (%d)\n",
|
||||
sensor->pixel_array->ctrl_handler.error);
|
||||
rval = sensor->pixel_array->ctrl_handler.error;
|
||||
goto error;
|
||||
return sensor->pixel_array->ctrl_handler.error;
|
||||
}
|
||||
|
||||
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);
|
||||
if (rval)
|
||||
goto error;
|
||||
return rval;
|
||||
|
||||
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->src->ctrl_handler, &smiapp_ctrl_ops,
|
||||
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,
|
||||
"src controls initialization failed (%d)\n",
|
||||
sensor->src->ctrl_handler.error);
|
||||
rval = sensor->src->ctrl_handler.error;
|
||||
goto error;
|
||||
return sensor->src->ctrl_handler.error;
|
||||
}
|
||||
|
||||
sensor->src->sd.ctrl_handler =
|
||||
&sensor->src->ctrl_handler;
|
||||
sensor->src->sd.ctrl_handler = &sensor->src->ctrl_handler;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
error:
|
||||
v4l2_ctrl_handler_free(&sensor->pixel_array->ctrl_handler);
|
||||
v4l2_ctrl_handler_free(&sensor->src->ctrl_handler);
|
||||
/*
|
||||
* For controls that require information on available media bus codes
|
||||
* 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)
|
||||
@ -1487,7 +1486,7 @@ static int smiapp_start_streaming(struct smiapp_sensor *sensor)
|
||||
if (rval < 0)
|
||||
goto out;
|
||||
|
||||
if ((sensor->flash_capability &
|
||||
if ((sensor->limits[SMIAPP_LIMIT_FLASH_MODE_CAPABILITY] &
|
||||
(SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
|
||||
SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) &&
|
||||
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
|
||||
*/
|
||||
|
||||
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(subdev);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
struct smiapp_module_info *minfo = &sensor->minfo;
|
||||
unsigned int i;
|
||||
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->revision_number_major);
|
||||
|
||||
strlcpy(subdev->name, sensor->minfo.name, sizeof(subdev->name));
|
||||
|
||||
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 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(subdev);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
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_subdev *last = NULL;
|
||||
u32 tmp;
|
||||
unsigned int i;
|
||||
int rval;
|
||||
|
||||
@ -2490,7 +2544,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||
}
|
||||
|
||||
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)) {
|
||||
dev_err(&client->dev, "could not get clock\n");
|
||||
return PTR_ERR(sensor->ext_clk);
|
||||
@ -2522,7 +2576,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||
if (rval)
|
||||
return -ENODEV;
|
||||
|
||||
rval = smiapp_identify_module(subdev);
|
||||
rval = smiapp_identify_module(sensor);
|
||||
if (rval) {
|
||||
rval = -ENODEV;
|
||||
goto out_power_off;
|
||||
@ -2602,13 +2656,13 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||
if (sensor->nvm == NULL) {
|
||||
dev_err(&client->dev, "nvm buf allocation failed\n");
|
||||
rval = -ENOMEM;
|
||||
goto out_ident_release;
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
|
||||
dev_err(&client->dev, "sysfs nvm entry failed\n");
|
||||
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->csi2.lanes = sensor->platform_data->lanes;
|
||||
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];
|
||||
/* Profile 0 sensors have no separate OP clock branch. */
|
||||
if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
|
||||
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++) {
|
||||
struct {
|
||||
struct smiapp_subdev *ssd;
|
||||
@ -2711,34 +2758,6 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||
this->sd.owner = THIS_MODULE;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2750,40 +2769,66 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
|
||||
smiapp_read_frame_fmt(sensor);
|
||||
rval = smiapp_init_controls(sensor);
|
||||
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);
|
||||
rval = smiapp_update_mode(sensor);
|
||||
mutex_unlock(&sensor->mutex);
|
||||
if (rval) {
|
||||
dev_err(&client->dev, "update mode failed\n");
|
||||
goto out_nvm_release;
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
sensor->streaming = false;
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
||||
out_nvm_release:
|
||||
device_remove_file(&client->dev, &dev_attr_nvm);
|
||||
|
||||
out_ident_release:
|
||||
device_remove_file(&client->dev, &dev_attr_ident);
|
||||
out_cleanup:
|
||||
smiapp_cleanup(sensor);
|
||||
|
||||
out_power_off:
|
||||
smiapp_power_off(sensor);
|
||||
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)
|
||||
{
|
||||
struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
|
||||
@ -2927,19 +2972,125 @@ static int smiapp_resume(struct device *dev)
|
||||
|
||||
#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,
|
||||
const struct i2c_device_id *devid)
|
||||
{
|
||||
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;
|
||||
|
||||
sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
|
||||
if (sensor == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
sensor->platform_data = client->dev.platform_data;
|
||||
sensor->platform_data = pdata;
|
||||
mutex_init(&sensor->mutex);
|
||||
mutex_init(&sensor->power_mutex);
|
||||
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->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);
|
||||
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)
|
||||
@ -2960,6 +3130,8 @@ static int smiapp_remove(struct i2c_client *client)
|
||||
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
|
||||
unsigned int i;
|
||||
|
||||
v4l2_async_unregister_subdev(subdev);
|
||||
|
||||
if (sensor->power_count) {
|
||||
if (gpio_is_valid(sensor->platform_data->xshutdown))
|
||||
gpio_set_value(sensor->platform_data->xshutdown, 0);
|
||||
@ -2970,19 +3142,20 @@ static int smiapp_remove(struct i2c_client *client)
|
||||
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++) {
|
||||
v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
|
||||
media_entity_cleanup(&sensor->ssds[i].sd.entity);
|
||||
}
|
||||
smiapp_free_controls(sensor);
|
||||
smiapp_cleanup(sensor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id smiapp_of_table[] = {
|
||||
{ .compatible = "nokia,smia" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct i2c_device_id smiapp_id_table[] = {
|
||||
{ SMIAPP_NAME, 0 },
|
||||
{ },
|
||||
@ -2996,6 +3169,7 @@ static const struct dev_pm_ops smiapp_pm_ops = {
|
||||
|
||||
static struct i2c_driver smiapp_i2c_driver = {
|
||||
.driver = {
|
||||
.of_match_table = smiapp_of_table,
|
||||
.name = SMIAPP_NAME,
|
||||
.pm = &smiapp_pm_ops,
|
||||
},
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "smiapp.h"
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY 0
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@ -220,9 +214,11 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
|
||||
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 = {
|
||||
@ -230,7 +226,7 @@ const struct smiapp_quirk smiapp_jt8ev1_quirk = {
|
||||
.post_poweron = jt8ev1_post_poweron,
|
||||
.pre_streamon = jt8ev1_pre_streamon,
|
||||
.post_streamoff = jt8ev1_post_streamoff,
|
||||
.pll_flags = jt8ev1_pll_flags,
|
||||
.init = jt8ev1_init,
|
||||
};
|
||||
|
||||
static int tcm8500md_limits(struct smiapp_sensor *sensor)
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SMIAPP_QUIRK__
|
||||
@ -35,6 +29,9 @@ struct smiapp_sensor;
|
||||
* @post_poweron: Called always after the sensor has been fully powered on.
|
||||
* @pre_streamon: Called just before streaming is enabled.
|
||||
* @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
|
||||
* to another register, or no register at all.
|
||||
*
|
||||
@ -53,6 +50,7 @@ struct smiapp_quirk {
|
||||
int (*pre_streamon)(struct smiapp_sensor *sensor);
|
||||
int (*post_streamoff)(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,
|
||||
u32 *val);
|
||||
unsigned long flags;
|
||||
@ -74,14 +72,14 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
|
||||
.val = _val, \
|
||||
}
|
||||
|
||||
#define smiapp_call_quirk(_sensor, _quirk, ...) \
|
||||
(_sensor->minfo.quirk && \
|
||||
_sensor->minfo.quirk->_quirk ? \
|
||||
_sensor->minfo.quirk->_quirk(_sensor, ##__VA_ARGS__) : 0)
|
||||
#define smiapp_call_quirk(sensor, _quirk, ...) \
|
||||
((sensor)->minfo.quirk && \
|
||||
(sensor)->minfo.quirk->_quirk ? \
|
||||
(sensor)->minfo.quirk->_quirk(sensor, ##__VA_ARGS__) : 0)
|
||||
|
||||
#define smiapp_needs_quirk(_sensor, _quirk) \
|
||||
(_sensor->minfo.quirk ? \
|
||||
_sensor->minfo.quirk->flags & _quirk : 0)
|
||||
#define smiapp_needs_quirk(sensor, _quirk) \
|
||||
((sensor)->minfo.quirk ? \
|
||||
(sensor)->minfo.quirk->flags & _quirk : 0)
|
||||
|
||||
extern const struct smiapp_quirk smiapp_jt8ev1_quirk;
|
||||
extern const struct smiapp_quirk smiapp_imx125es_quirk;
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#define SMIAPP_REG_MK_U8(r) ((SMIAPP_REG_8BIT << 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
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SMIAPP_REG_H_
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SMIAPP_REGS_H
|
||||
|
@ -14,12 +14,6 @@
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SMIAPP_PRIV_H_
|
||||
@ -222,7 +216,6 @@ struct smiapp_sensor {
|
||||
u8 scaling_mode;
|
||||
|
||||
u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
|
||||
u8 flash_capability;
|
||||
u8 frame_skip;
|
||||
|
||||
int power_count;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
|
||||
#define VAL_SET(x, mask, rshift, lshift) \
|
||||
((((x) >> rshift) & mask) << lshift)
|
||||
@ -268,33 +269,10 @@ struct regval_list {
|
||||
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 {
|
||||
char *name;
|
||||
enum ov2640_width width;
|
||||
enum ov2640_height height;
|
||||
u32 width;
|
||||
u32 height;
|
||||
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[] = {
|
||||
{ BANK_SEL, BANK_SEL_DSP },
|
||||
{ RESET, RESET_DVP },
|
||||
{ HSIZE8, HSIZE8_SET(W_UXGA) },
|
||||
{ VSIZE8, VSIZE8_SET(H_UXGA) },
|
||||
{ HSIZE8, HSIZE8_SET(UXGA_WIDTH) },
|
||||
{ VSIZE8, VSIZE8_SET(UXGA_HEIGHT) },
|
||||
{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
|
||||
CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
|
||||
{ HSIZE, HSIZE_SET(W_UXGA) },
|
||||
{ VSIZE, VSIZE_SET(H_UXGA) },
|
||||
{ HSIZE, HSIZE_SET(UXGA_WIDTH) },
|
||||
{ VSIZE, VSIZE_SET(UXGA_HEIGHT) },
|
||||
{ XOFFL, XOFFL_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)},
|
||||
{ TEST, TEST_HSIZE_SET(W_UXGA) },
|
||||
{ TEST, TEST_HSIZE_SET(UXGA_WIDTH) },
|
||||
ENDMARKER,
|
||||
};
|
||||
|
||||
@ -519,45 +497,45 @@ static const struct regval_list ov2640_size_change_preamble_regs[] = {
|
||||
{ RESET, 0x00}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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},
|
||||
ENDMARKER,
|
||||
};
|
||||
|
||||
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},
|
||||
{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
|
||||
ENDMARKER,
|
||||
};
|
||||
|
||||
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},
|
||||
{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
|
||||
ENDMARKER,
|
||||
@ -567,14 +545,14 @@ static const struct regval_list ov2640_uxga_regs[] = {
|
||||
{.name = n, .width = w , .height = h, .regs = r }
|
||||
|
||||
static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
|
||||
OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs),
|
||||
OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs),
|
||||
OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs),
|
||||
OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs),
|
||||
OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs),
|
||||
OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs),
|
||||
OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs),
|
||||
OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs),
|
||||
OV2640_SIZE("QCIF", QCIF_WIDTH, QCIF_HEIGHT, ov2640_qcif_regs),
|
||||
OV2640_SIZE("QVGA", QVGA_WIDTH, QVGA_HEIGHT, ov2640_qvga_regs),
|
||||
OV2640_SIZE("CIF", CIF_WIDTH, CIF_HEIGHT, ov2640_cif_regs),
|
||||
OV2640_SIZE("VGA", VGA_WIDTH, VGA_HEIGHT, ov2640_vga_regs),
|
||||
OV2640_SIZE("SVGA", SVGA_WIDTH, SVGA_HEIGHT, ov2640_svga_regs),
|
||||
OV2640_SIZE("XGA", XGA_WIDTH, XGA_HEIGHT, ov2640_xga_regs),
|
||||
OV2640_SIZE("SXGA", SXGA_WIDTH, SXGA_HEIGHT, ov2640_sxga_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);
|
||||
|
||||
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->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.top = 0;
|
||||
a->c.width = W_UXGA;
|
||||
a->c.height = H_UXGA;
|
||||
a->c.width = UXGA_WIDTH;
|
||||
a->c.height = UXGA_HEIGHT;
|
||||
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
return 0;
|
||||
@ -965,8 +943,8 @@ static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
|
||||
{
|
||||
a->bounds.left = 0;
|
||||
a->bounds.top = 0;
|
||||
a->bounds.width = W_UXGA;
|
||||
a->bounds.height = H_UXGA;
|
||||
a->bounds.width = UXGA_WIDTH;
|
||||
a->bounds.height = UXGA_HEIGHT;
|
||||
a->defrect = a->bounds;
|
||||
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return V4L2_DV_BT_FRAME_HEIGHT(t);
|
||||
|
@ -6,6 +6,8 @@ config SMS_SDIO_DRV
|
||||
tristate "Siano SMS1xxx based MDTV via SDIO interface"
|
||||
depends on DVB_CORE && HAS_DMA
|
||||
depends on MMC
|
||||
depends on !RC_CORE || RC_CORE
|
||||
select MEDIA_COMMON_OPTIONS
|
||||
select SMS_SIANO_MDTV
|
||||
---help---
|
||||
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"
|
||||
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
|
||||
select I2C_ALGOBIT
|
||||
select VIDEO_BTCX
|
||||
select VIDEOBUF_DMA_SG
|
||||
depends on RC_CORE
|
||||
depends on MEDIA_RADIO_SUPPORT
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT
|
||||
select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select RADIO_ADAPTERS
|
||||
select RADIO_TEA575X
|
||||
---help---
|
||||
Support for BT848 based frame grabber/overlay boards. This includes
|
||||
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-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_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_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -32,13 +32,9 @@
|
||||
|
||||
#include "btcx-risc.h"
|
||||
|
||||
MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
|
||||
MODULE_AUTHOR("Gerd Knorr");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
|
||||
static unsigned int btcx_debug;
|
||||
module_param(btcx_debug, int, 0644);
|
||||
MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)");
|
||||
|
||||
/* ---------------------------------------------------------- */
|
||||
/* allocate/free risc memory */
|
||||
@ -50,7 +46,7 @@ void btcx_riscmem_free(struct pci_dev *pci,
|
||||
{
|
||||
if (NULL == risc->cpu)
|
||||
return;
|
||||
if (debug) {
|
||||
if (btcx_debug) {
|
||||
memcnt--;
|
||||
printk("btcx: riscmem free [%d] dma=%lx\n",
|
||||
memcnt, (unsigned long)risc->dma);
|
||||
@ -75,7 +71,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
|
||||
risc->cpu = cpu;
|
||||
risc->dma = dma;
|
||||
risc->size = size;
|
||||
if (debug) {
|
||||
if (btcx_debug) {
|
||||
memcnt++;
|
||||
printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
|
||||
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;
|
||||
win->left = nx;
|
||||
win->width = nw;
|
||||
if (debug)
|
||||
if (btcx_debug)
|
||||
printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
|
||||
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;
|
||||
clips[i].c.left = nx;
|
||||
clips[i].c.width = nw;
|
||||
if (debug)
|
||||
if (btcx_debug)
|
||||
printk(KERN_DEBUG "btcx: clip align %dx%d+%d+%d\n",
|
||||
clips[i].c.width, clips[i].c.height,
|
||||
clips[i].c.left, clips[i].c.top);
|
||||
@ -234,7 +230,7 @@ btcx_calc_skips(int line, int width, int *maxy,
|
||||
*nskips = skip;
|
||||
*maxy = maxline;
|
||||
|
||||
if (debug) {
|
||||
if (btcx_debug) {
|
||||
printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
|
||||
for (skip = 0; skip < *nskips; skip++) {
|
||||
printk(" %d-%d",skips[skip].start,skips[skip].end);
|
||||
@ -242,19 +238,3 @@ btcx_calc_skips(int line, int width, int *maxy,
|
||||
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:
|
||||
*/
|
26
drivers/media/pci/bt8xx/btcx-risc.h
Normal file
26
drivers/media/pci/bt8xx/btcx-risc.h
Normal file
@ -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 int terratec_active_radio_upgrade(struct bttv *btv);
|
||||
static int tea5757_read(struct bttv *btv);
|
||||
static int tea5757_write(struct bttv *btv, int value);
|
||||
static int tea575x_init(struct bttv *btv);
|
||||
static void identify_by_eeprom(struct bttv *btv,
|
||||
unsigned char eeprom_data[256]);
|
||||
static int pvr_boot(struct bttv *btv);
|
||||
@ -3085,12 +3084,12 @@ static void miro_pinnacle_gpio(struct bttv *btv)
|
||||
if (0 == (gpio & 0x20)) {
|
||||
btv->has_radio = 1;
|
||||
if (!miro_fmtuner[id]) {
|
||||
btv->has_matchbox = 1;
|
||||
btv->mbox_we = (1<<6);
|
||||
btv->mbox_most = (1<<7);
|
||||
btv->mbox_clk = (1<<8);
|
||||
btv->mbox_data = (1<<9);
|
||||
btv->mbox_mask = (1<<6)|(1<<7)|(1<<8)|(1<<9);
|
||||
btv->has_tea575x = 1;
|
||||
btv->tea_gpio.wren = 6;
|
||||
btv->tea_gpio.most = 7;
|
||||
btv->tea_gpio.clk = 8;
|
||||
btv->tea_gpio.data = 9;
|
||||
tea575x_init(btv);
|
||||
}
|
||||
} else {
|
||||
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",
|
||||
btv->c.nr, id+1, btv->tuner_type,
|
||||
!btv->has_radio ? "no" :
|
||||
(btv->has_matchbox ? "matchbox" : "fmtuner"),
|
||||
(btv->has_tea575x ? "tea575x" : "fmtuner"),
|
||||
(-1 == msp) ? "no" : "yes");
|
||||
} else {
|
||||
/* new cards with microtune tuner */
|
||||
@ -3382,12 +3381,12 @@ void bttv_init_card2(struct bttv *btv)
|
||||
break;
|
||||
case BTTV_BOARD_VHX:
|
||||
btv->has_radio = 1;
|
||||
btv->has_matchbox = 1;
|
||||
btv->mbox_we = 0x20;
|
||||
btv->mbox_most = 0;
|
||||
btv->mbox_clk = 0x08;
|
||||
btv->mbox_data = 0x10;
|
||||
btv->mbox_mask = 0x38;
|
||||
btv->has_tea575x = 1;
|
||||
btv->tea_gpio.wren = 5;
|
||||
btv->tea_gpio.most = 6;
|
||||
btv->tea_gpio.clk = 3;
|
||||
btv->tea_gpio.data = 4;
|
||||
tea575x_init(btv);
|
||||
break;
|
||||
case BTTV_BOARD_VOBIS_BOOSTAR:
|
||||
case BTTV_BOARD_TERRATV:
|
||||
@ -3745,33 +3744,112 @@ static void hauppauge_eeprom(struct bttv *btv)
|
||||
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)
|
||||
{
|
||||
int freq;
|
||||
|
||||
btv->has_radio = 1;
|
||||
btv->has_matchbox = 1;
|
||||
btv->mbox_we = 0x10;
|
||||
btv->mbox_most = 0x20;
|
||||
btv->mbox_clk = 0x08;
|
||||
btv->mbox_data = 0x04;
|
||||
btv->mbox_mask = 0x3c;
|
||||
btv->has_tea575x = 1;
|
||||
btv->tea_gpio.wren = 4;
|
||||
btv->tea_gpio.most = 5;
|
||||
btv->tea_gpio.clk = 3;
|
||||
btv->tea_gpio.data = 2;
|
||||
|
||||
btv->mbox_iow = 1 << 8;
|
||||
btv->mbox_ior = 1 << 9;
|
||||
btv->mbox_csel = 1 << 10;
|
||||
|
||||
freq=88000/62.5;
|
||||
tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
|
||||
if (0x1ed8 == tea5757_read(btv)) {
|
||||
if (!tea575x_init(btv)) {
|
||||
pr_info("%d: Terratec Active Radio Upgrade found\n", btv->c.nr);
|
||||
btv->has_radio = 1;
|
||||
btv->has_saa6588 = 1;
|
||||
btv->has_matchbox = 1;
|
||||
} else {
|
||||
btv->has_radio = 0;
|
||||
btv->has_matchbox = 0;
|
||||
btv->has_saa6588 = 1;
|
||||
}
|
||||
|
||||
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]
|
||||
*
|
||||
* 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);
|
||||
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) {
|
||||
radio_enable(btv);
|
||||
btv->radio_freq = new_freq.frequency;
|
||||
if (btv->has_matchbox)
|
||||
tea5757_set_freq(btv, btv->radio_freq);
|
||||
if (btv->has_tea575x) {
|
||||
btv->tea.freq = btv->radio_freq;
|
||||
snd_tea575x_set_freq(&btv->tea);
|
||||
}
|
||||
} else {
|
||||
btv->tv_freq = new_freq.frequency;
|
||||
}
|
||||
@ -2513,6 +2515,8 @@ static int bttv_querycap(struct file *file, void *priv,
|
||||
if (btv->has_saa6588)
|
||||
cap->device_caps |= V4L2_CAP_READWRITE |
|
||||
V4L2_CAP_RDS_CAPTURE;
|
||||
if (btv->has_tea575x)
|
||||
cap->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
|
||||
}
|
||||
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)
|
||||
btv->audio_mode_gpio(btv, t, 0);
|
||||
|
||||
if (btv->has_tea575x)
|
||||
return snd_tea575x_g_tuner(&btv->tea, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3259,6 +3266,30 @@ static int radio_s_tuner(struct file *file, void *priv,
|
||||
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,
|
||||
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_g_frequency = bttv_g_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_unsubscribe_event = v4l2_event_unsubscribe,
|
||||
};
|
||||
@ -3884,7 +3917,6 @@ static struct video_device *vdev_init(struct bttv *btv,
|
||||
*vfd = *template;
|
||||
vfd->v4l2_dev = &btv->c.v4l2_dev;
|
||||
vfd->release = video_device_release;
|
||||
vfd->debug = bttv_debug;
|
||||
video_set_drvdata(vfd, btv);
|
||||
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
|
||||
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_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);
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -901,9 +901,3 @@ bttv_overlay_risc(struct bttv *btv,
|
||||
buf->vb.field = ov->field;
|
||||
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(). */
|
||||
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);
|
||||
|
||||
#endif /* _BTTV_H_ */
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <media/tveeprom.h>
|
||||
#include <media/rc-core.h>
|
||||
#include <media/ir-kbd-i2c.h>
|
||||
#include <media/tea575x.h>
|
||||
|
||||
#include "bt848.h"
|
||||
#include "bttv.h"
|
||||
@ -359,6 +360,10 @@ struct bttv_suspend_state {
|
||||
struct bttv_buffer *vbi;
|
||||
};
|
||||
|
||||
struct bttv_tea575x_gpio {
|
||||
u8 data, clk, wren, most;
|
||||
};
|
||||
|
||||
struct bttv {
|
||||
struct bttv_core c;
|
||||
|
||||
@ -445,12 +450,9 @@ struct bttv {
|
||||
|
||||
/* miro/pinnacle + Aimslab VHX
|
||||
philips matchbox (tea5757 radio tuner) support */
|
||||
int has_matchbox;
|
||||
int mbox_we;
|
||||
int mbox_data;
|
||||
int mbox_clk;
|
||||
int mbox_most;
|
||||
int mbox_mask;
|
||||
int has_tea575x;
|
||||
struct bttv_tea575x_gpio tea_gpio;
|
||||
struct snd_tea575x tea;
|
||||
|
||||
/* ISA stuff (Terratec Active Radio Upgrade) */
|
||||
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)
|
||||
|
||||
#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_SI2157 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
|
||||
---help---
|
||||
This is a video4linux driver for Conexant 23885 based
|
||||
|
@ -710,6 +710,11 @@ struct cx23885_board cx23885_boards[] = {
|
||||
.portb = 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);
|
||||
|
||||
@ -993,6 +998,10 @@ struct cx23885_subid cx23885_subids[] = {
|
||||
.subvendor = 0x4254,
|
||||
.subdevice = 0x0982,
|
||||
.card = CX23885_BOARD_DVBSKY_T982,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0xf038,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR5525,
|
||||
},
|
||||
};
|
||||
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:
|
||||
/* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
|
||||
Dual channel ATSC and Basic analog */
|
||||
case 150329:
|
||||
/* WinTV-HVR5525 (PCIe, DVB-S/S2, DVB-T/T2/C) */
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: warning: "
|
||||
@ -1637,6 +1648,29 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
|
||||
msleep(100);
|
||||
cx23885_gpio_set(dev, GPIO_2);
|
||||
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_STARBURST:
|
||||
case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR5525:
|
||||
if (dev->i2c_bus[0].i2c_rc == 0)
|
||||
hauppauge_eeprom(dev, eeprom+0xc0);
|
||||
break;
|
||||
@ -2008,6 +2043,14 @@ void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
|
||||
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
|
||||
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_HVR1500:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "sp2.h"
|
||||
#include "m88ds3103.h"
|
||||
#include "m88ts2022.h"
|
||||
#include "m88rs6000t.h"
|
||||
|
||||
static unsigned int debug;
|
||||
|
||||
@ -915,6 +916,16 @@ static const struct m88ds3103_config dvbsky_s952_portc_m88ds3103_config = {
|
||||
.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)
|
||||
{
|
||||
struct cx23885_dev *dev = (struct cx23885_dev *)device;
|
||||
@ -1058,6 +1069,116 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
|
||||
.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)
|
||||
{
|
||||
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 si2168_config si2168_config;
|
||||
struct si2157_config si2157_config;
|
||||
struct sp2_config sp2_config;
|
||||
struct m88ts2022_config m88ts2022_config;
|
||||
struct i2c_board_info info;
|
||||
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;
|
||||
int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
|
||||
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);
|
||||
client_tuner = i2c_new_device(adapter, &info);
|
||||
if (client_tuner == NULL ||
|
||||
client_tuner->dev.driver == NULL) {
|
||||
module_put(client_demod->dev.driver->owner);
|
||||
i2c_unregister_device(client_demod);
|
||||
client_tuner->dev.driver == 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);
|
||||
goto frontend_detach;
|
||||
}
|
||||
port->i2c_client_tuner = client_tuner;
|
||||
@ -1832,8 +1948,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
info.platform_data = &si2168_config;
|
||||
request_module(info.type);
|
||||
client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
|
||||
if (client_demod == NULL ||
|
||||
client_demod->dev.driver == NULL)
|
||||
if (client_demod == NULL || client_demod->dev.driver == NULL)
|
||||
goto frontend_detach;
|
||||
if (!try_module_get(client_demod->dev.driver->owner)) {
|
||||
i2c_unregister_device(client_demod);
|
||||
@ -1851,15 +1966,10 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
request_module(info.type);
|
||||
client_tuner = i2c_new_device(adapter, &info);
|
||||
if (client_tuner == NULL ||
|
||||
client_tuner->dev.driver == NULL) {
|
||||
module_put(client_demod->dev.driver->owner);
|
||||
i2c_unregister_device(client_demod);
|
||||
client_tuner->dev.driver == 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);
|
||||
goto frontend_detach;
|
||||
}
|
||||
port->i2c_client_tuner = client_tuner;
|
||||
@ -1885,8 +1995,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
info.platform_data = &m88ts2022_config;
|
||||
request_module(info.type);
|
||||
client_tuner = i2c_new_device(adapter, &info);
|
||||
if (client_tuner == NULL ||
|
||||
client_tuner->dev.driver == NULL)
|
||||
if (client_tuner == NULL || client_tuner->dev.driver == NULL)
|
||||
goto frontend_detach;
|
||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||
i2c_unregister_device(client_tuner);
|
||||
@ -1932,8 +2041,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
info.platform_data = &m88ts2022_config;
|
||||
request_module(info.type);
|
||||
client_tuner = i2c_new_device(adapter, &info);
|
||||
if (client_tuner == NULL ||
|
||||
client_tuner->dev.driver == NULL)
|
||||
if (client_tuner == NULL || client_tuner->dev.driver == NULL)
|
||||
goto frontend_detach;
|
||||
if (!try_module_get(client_tuner->dev.driver->owner)) {
|
||||
i2c_unregister_device(client_tuner);
|
||||
@ -1978,8 +2086,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
info.platform_data = &si2168_config;
|
||||
request_module(info.type);
|
||||
client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
|
||||
if (client_demod == NULL ||
|
||||
client_demod->dev.driver == NULL)
|
||||
if (client_demod == NULL || client_demod->dev.driver == NULL)
|
||||
goto frontend_detach;
|
||||
if (!try_module_get(client_demod->dev.driver->owner)) {
|
||||
i2c_unregister_device(client_demod);
|
||||
@ -1997,20 +2104,101 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
request_module(info.type);
|
||||
client_tuner = i2c_new_device(adapter, &info);
|
||||
if (client_tuner == NULL ||
|
||||
client_tuner->dev.driver == NULL) {
|
||||
module_put(client_demod->dev.driver->owner);
|
||||
i2c_unregister_device(client_demod);
|
||||
client_tuner->dev.driver == 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;
|
||||
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:
|
||||
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
|
||||
" isn't supported yet\n",
|
||||
@ -2047,123 +2235,29 @@ static int dvb_register(struct cx23885_tsport *port)
|
||||
if (ret)
|
||||
goto frontend_detach;
|
||||
|
||||
/* init CI & MAC */
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
|
||||
static struct netup_card_info cinfo;
|
||||
ret = dvb_register_ci_mac(port);
|
||||
if (ret)
|
||||
goto frontend_detach;
|
||||
|
||||
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);
|
||||
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;
|
||||
return 0;
|
||||
|
||||
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;
|
||||
vb2_dvb_dealloc_frontends(&port->frontends);
|
||||
return -EINVAL;
|
||||
|
@ -300,8 +300,8 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
|
||||
rc = i2c_master_recv(c, &buf, 0);
|
||||
if (rc < 0)
|
||||
continue;
|
||||
printk(KERN_INFO "%s: i2c scan: found device @ 0x%x [%s]\n",
|
||||
name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
|
||||
printk(KERN_INFO "%s: i2c scan: found device @ 0x%04x [%s]\n",
|
||||
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
Block a user