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:
Linus Torvalds 2015-02-11 08:45:40 -08:00
commit 3e63430a5c
357 changed files with 12185 additions and 21800 deletions

View File

@ -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>&nbsp;</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>

View File

@ -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

View File

@ -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

View File

@ -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

View 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 &times; 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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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>

View File

@ -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

View File

@ -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;

View File

@ -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:
-->

View File

@ -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:
-->

View 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>;
};
};
};
};

View File

@ -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";

View 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>;
};
};
};

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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
--------------------

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -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:
*/

View File

@ -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;

View File

@ -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.

View File

@ -91,8 +91,3 @@ enum au8522_audio_input {
};
#endif /* __AU8522_H__ */
/*
* Local variables:
* c-basic-offset: 8
*/

View File

@ -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:

View File

@ -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;

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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;
};

View File

@ -823,9 +823,3 @@ MODULE_AUTHOR("Wilson Michaels");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(lgdt330x_attach);
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@ -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:
*/

View File

@ -69,9 +69,3 @@ enum I2C_REG {
};
#endif /* _LGDT330X_PRIV_ */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@ -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,

View File

@ -33,6 +33,12 @@ struct mn88472_config {
* DVB frontend.
*/
struct dvb_frontend **fe;
/*
* Xtal frequency.
* Hz
*/
u32 xtal;
};
#endif

View File

@ -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:
*/

View File

@ -623,9 +623,3 @@ MODULE_AUTHOR("Trent Piepho");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(or51132_attach);
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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
*/

View File

@ -81,8 +81,3 @@ static inline struct dvb_frontend *s5h1409_attach(
#endif /* CONFIG_DVB_S5H1409 */
#endif /* __S5H1409_H__ */
/*
* Local variables:
* c-basic-offset: 8
*/

View File

@ -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
*/

View File

@ -83,8 +83,3 @@ static inline struct dvb_frontend *s5h1411_attach(
#endif /* CONFIG_DVB_S5H1411 */
#endif /* __S5H1411_H__ */
/*
* Local variables:
* c-basic-offset: 8
*/

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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" :

View File

@ -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:
*/

View File

@ -422,22 +422,25 @@ done:
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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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);

View File

@ -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;

View File

@ -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 = {

View File

@ -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>

View File

@ -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

View File

@ -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,
},

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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))

View File

@ -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_

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -590,9 +590,3 @@ module_init(bt878_init_module);
module_exit(bt878_cleanup_module);
MODULE_LICENSE("GPL");
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@ -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:
*/

View 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);

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -901,9 +901,3 @@ bttv_overlay_risc(struct bttv *btv,
buf->vb.field = ov->field;
return 0;
}
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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