Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (116 commits)
  V4L/DVB (13698): pms: replace asm/uaccess.h to linux/uaccess.h
  V4L/DVB (13690): radio/si470x: #include <sched.h>
  V4L/DVB (13688): au8522: modify the attributes of local filter coefficients
  V4L/DVB (13687): cx231xx: use NULL when pointer is needed
  V4L/DVB: Davinci VPFE Capture: remove unused #include <linux/version.h>
  V4L/DVB (13685): Correct code taking the size of a pointer
  V4L/DVB (13684): Fix some cut-and-paste noise in dib0090.h
  V4L/DVB (13683): sanio-ms: clean up init, exit and id_table
  V4L/DVB (13682): dib8000: make some constant static
  V4L/DVB: lgs8gxx: Use shifts rather than multiply/divide when possible
  V4L/DVB (13680b): DocBook/media: create links for included sources
  V4L/DVB (13680a): DocBook/media: copy images after building HTML
  V4L/DVB (13678): Add support for yet another DvbWorld, TeVii and Prof USB devices
  V4L/DVB (13676): configurable IRQ mode on NetUP Dual DVB-S2 CI; IRQ from CAM processing (CI interface works faster)
  V4L/DVB (13674): stv090x: Add DiSEqC envelope mode
  V4L/DVB (13673): lnbp21: Implement 22 kHz tone control
  V4L/DVB (13671): sh_mobile_ceu_camera: Remove frame size page alignment
  V4L/DVB (13670): soc-camera: Add mt9t112 camera driver
  V4L/DVB (13669): tw9910: Add sync polarity support
  V4L/DVB (13668): tw9910: remove cropping
  ...
This commit is contained in:
Linus Torvalds 2009-12-16 10:09:16 -08:00
commit 6a5df38f5f
227 changed files with 10404 additions and 4051 deletions

View file

@ -32,10 +32,10 @@ PS_METHOD = $(prefer-db2x)
###
# The targets that may be used.
PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs media
PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
xmldocs: $(BOOKS)
xmldocs: $(BOOKS) xmldoclinks
sgmldocs: xmldocs
PS := $(patsubst %.xml, %.ps, $(BOOKS))
@ -45,15 +45,24 @@ PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
pdfdocs: $(PDF)
HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
htmldocs: media $(HTML)
htmldocs: $(HTML)
$(call build_main_index)
$(call build_images)
MAN := $(patsubst %.xml, %.9, $(BOOKS))
mandocs: $(MAN)
media:
mkdir -p $(srctree)/Documentation/DocBook/media/
cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(srctree)/Documentation/DocBook/media/
build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
xmldoclinks:
ifneq ($(objtree),$(srctree))
for dep in dvb media-entities.tmpl media-indices.tmpl v4l; do \
rm -f $(objtree)/Documentation/DocBook/$$dep \
&& ln -s $(srctree)/Documentation/DocBook/$$dep $(objtree)/Documentation/DocBook/ \
|| exit; \
done
endif
installmandocs: mandocs
mkdir -p /usr/local/man/man9/

View file

@ -23,6 +23,7 @@
<!ENTITY VIDIOC-ENUMINPUT "<link linkend='vidioc-enuminput'><constant>VIDIOC_ENUMINPUT</constant></link>">
<!ENTITY VIDIOC-ENUMOUTPUT "<link linkend='vidioc-enumoutput'><constant>VIDIOC_ENUMOUTPUT</constant></link>">
<!ENTITY VIDIOC-ENUMSTD "<link linkend='vidioc-enumstd'><constant>VIDIOC_ENUMSTD</constant></link>">
<!ENTITY VIDIOC-ENUM-DV-PRESETS "<link linkend='vidioc-enum-dv-presets'><constant>VIDIOC_ENUM_DV_PRESETS</constant></link>">
<!ENTITY VIDIOC-ENUM-FMT "<link linkend='vidioc-enum-fmt'><constant>VIDIOC_ENUM_FMT</constant></link>">
<!ENTITY VIDIOC-ENUM-FRAMEINTERVALS "<link linkend='vidioc-enum-frameintervals'><constant>VIDIOC_ENUM_FRAMEINTERVALS</constant></link>">
<!ENTITY VIDIOC-ENUM-FRAMESIZES "<link linkend='vidioc-enum-framesizes'><constant>VIDIOC_ENUM_FRAMESIZES</constant></link>">
@ -30,6 +31,8 @@
<!ENTITY VIDIOC-G-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_G_AUDOUT</constant></link>">
<!ENTITY VIDIOC-G-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_G_CROP</constant></link>">
<!ENTITY VIDIOC-G-CTRL "<link linkend='vidioc-g-ctrl'><constant>VIDIOC_G_CTRL</constant></link>">
<!ENTITY VIDIOC-G-DV-PRESET "<link linkend='vidioc-g-dv-preset'><constant>VIDIOC_G_DV_PRESET</constant></link>">
<!ENTITY VIDIOC-G-DV-TIMINGS "<link linkend='vidioc-g-dv-timings'><constant>VIDIOC_G_DV_TIMINGS</constant></link>">
<!ENTITY VIDIOC-G-ENC-INDEX "<link linkend='vidioc-g-enc-index'><constant>VIDIOC_G_ENC_INDEX</constant></link>">
<!ENTITY VIDIOC-G-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_G_EXT_CTRLS</constant></link>">
<!ENTITY VIDIOC-G-FBUF "<link linkend='vidioc-g-fbuf'><constant>VIDIOC_G_FBUF</constant></link>">
@ -53,6 +56,7 @@
<!ENTITY VIDIOC-QUERYCTRL "<link linkend='vidioc-queryctrl'><constant>VIDIOC_QUERYCTRL</constant></link>">
<!ENTITY VIDIOC-QUERYMENU "<link linkend='vidioc-queryctrl'><constant>VIDIOC_QUERYMENU</constant></link>">
<!ENTITY VIDIOC-QUERYSTD "<link linkend='vidioc-querystd'><constant>VIDIOC_QUERYSTD</constant></link>">
<!ENTITY VIDIOC-QUERY-DV-PRESET "<link linkend='vidioc-query-dv-preset'><constant>VIDIOC_QUERY_DV_PRESET</constant></link>">
<!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>">
<!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>">
<!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>">
@ -60,6 +64,8 @@
<!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>">
<!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>">
<!ENTITY VIDIOC-S-CTRL "<link linkend='vidioc-g-ctrl'><constant>VIDIOC_S_CTRL</constant></link>">
<!ENTITY VIDIOC-S-DV-PRESET "<link linkend='vidioc-g-dv-preset'><constant>VIDIOC_S_DV_PRESET</constant></link>">
<!ENTITY VIDIOC-S-DV-TIMINGS "<link linkend='vidioc-g-dv-timings'><constant>VIDIOC_S_DV_TIMINGS</constant></link>">
<!ENTITY VIDIOC-S-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_S_EXT_CTRLS</constant></link>">
<!ENTITY VIDIOC-S-FBUF "<link linkend='vidioc-g-fbuf'><constant>VIDIOC_S_FBUF</constant></link>">
<!ENTITY VIDIOC-S-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_S_FMT</constant></link>">
@ -118,6 +124,7 @@
<!-- Structures -->
<!ENTITY v4l2-audio "struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link>">
<!ENTITY v4l2-audioout "struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link>">
<!ENTITY v4l2-bt-timings "struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link>">
<!ENTITY v4l2-buffer "struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link>">
<!ENTITY v4l2-capability "struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link>">
<!ENTITY v4l2-captureparm "struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link>">
@ -128,6 +135,9 @@
<!ENTITY v4l2-dbg-chip-ident "struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link>">
<!ENTITY v4l2-dbg-match "struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link>">
<!ENTITY v4l2-dbg-register "struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link>">
<!ENTITY v4l2-dv-enum-preset "struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link>">
<!ENTITY v4l2-dv-preset "struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link>">
<!ENTITY v4l2-dv-timings "struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link>">
<!ENTITY v4l2-enc-idx "struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>">
<!ENTITY v4l2-enc-idx-entry "struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>">
<!ENTITY v4l2-encoder-cmd "struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>">
@ -243,6 +253,10 @@
<!ENTITY sub-enumaudioout SYSTEM "v4l/vidioc-enumaudioout.xml">
<!ENTITY sub-enuminput SYSTEM "v4l/vidioc-enuminput.xml">
<!ENTITY sub-enumoutput SYSTEM "v4l/vidioc-enumoutput.xml">
<!ENTITY sub-enum-dv-presets SYSTEM "v4l/vidioc-enum-dv-presets.xml">
<!ENTITY sub-g-dv-preset SYSTEM "v4l/vidioc-g-dv-preset.xml">
<!ENTITY sub-query-dv-preset SYSTEM "v4l/vidioc-query-dv-preset.xml">
<!ENTITY sub-g-dv-timings SYSTEM "v4l/vidioc-g-dv-timings.xml">
<!ENTITY sub-enumstd SYSTEM "v4l/vidioc-enumstd.xml">
<!ENTITY sub-g-audio SYSTEM "v4l/vidioc-g-audio.xml">
<!ENTITY sub-g-audioout SYSTEM "v4l/vidioc-g-audioout.xml">
@ -333,6 +347,10 @@
<!ENTITY enumaudioout SYSTEM "v4l/vidioc-enumaudioout.xml">
<!ENTITY enuminput SYSTEM "v4l/vidioc-enuminput.xml">
<!ENTITY enumoutput SYSTEM "v4l/vidioc-enumoutput.xml">
<!ENTITY enum-dv-presets SYSTEM "v4l/vidioc-enum-dv-presets.xml">
<!ENTITY g-dv-preset SYSTEM "v4l/vidioc-g-dv-preset.xml">
<!ENTITY query-dv-preset SYSTEM "v4l/vidioc-query-dv-preset.xml">
<!ENTITY g-dv-timings SYSTEM "v4l/vidioc-g-dv-timings.xml">
<!ENTITY enumstd SYSTEM "v4l/vidioc-enumstd.xml">
<!ENTITY g-audio SYSTEM "v4l/vidioc-g-audio.xml">
<!ENTITY g-audioout SYSTEM "v4l/vidioc-g-audioout.xml">

View file

@ -36,6 +36,7 @@
<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-preemphasis'>v4l2_preemphasis</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link></primaryie></indexentry>
@ -46,6 +47,9 @@
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link></primaryie></indexentry>
<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link></primaryie></indexentry>

View file

@ -716,6 +716,41 @@ if (-1 == ioctl (fd, &VIDIOC-S-STD;, &amp;std_id)) {
}
</programlisting>
</example>
<section id="dv-timings">
<title>Digital Video (DV) Timings</title>
<para>
The video standards discussed so far has been dealing with Analog TV and the
corresponding video timings. Today there are many more different hardware interfaces
such as High Definition TV interfaces (HDMI), VGA, DVI connectors etc., that carry
video signals and there is a need to extend the API to select the video timings
for these interfaces. Since it is not possible to extend the &v4l2-std-id; due to
the limited bits available, a new set of IOCTLs is added to set/get video timings at
the input and output: </para><itemizedlist>
<listitem>
<para>DV Presets: Digital Video (DV) presets. These are IDs representing a
video timing at the input/output. Presets are pre-defined timings implemented
by the hardware according to video standards. A __u32 data type is used to represent
a preset unlike the bit mask that is used in &v4l2-std-id; allowing future extensions
to support as many different presets as needed.</para>
</listitem>
<listitem>
<para>Custom DV Timings: This will allow applications to define more detailed
custom video timings for the interface. This includes parameters such as width, height,
polarities, frontporch, backporch etc.
</para>
</listitem>
</itemizedlist>
<para>To enumerate and query the attributes of DV presets supported by a device,
applications use the &VIDIOC-ENUM-DV-PRESETS; ioctl. To get the current DV preset,
applications use the &VIDIOC-G-DV-PRESET; ioctl and to set a preset they use the
&VIDIOC-S-DV-PRESET; ioctl.</para>
<para>To set custom DV timings for the device, applications use the
&VIDIOC-S-DV-TIMINGS; ioctl and to get current custom DV timings they use the
&VIDIOC-G-DV-TIMINGS; ioctl.</para>
<para>Applications can make use of the <xref linkend="input-capabilities" /> and
<xref linkend="output-capabilities"/> flags to decide what ioctls are available to set the
video timings for the device.</para>
</section>
</section>
&sub-controls;

View file

@ -2291,8 +2291,8 @@ was renamed to <structname id="v4l2-chip-ident-old">v4l2_chip_ident_old</structn
<listitem>
<para>New control <constant>V4L2_CID_COLORFX</constant> was added.</para>
</listitem>
</orderedlist>
</section>
</orderedlist>
</section>
<section>
<title>V4L2 in Linux 2.6.32</title>
<orderedlist>
@ -2322,8 +2322,16 @@ more information.</para>
<listitem>
<para>Added Remote Controller chapter, describing the default Remote Controller mapping for media devices.</para>
</listitem>
</orderedlist>
</section>
</orderedlist>
</section>
<section>
<title>V4L2 in Linux 2.6.33</title>
<orderedlist>
<listitem>
<para>Added support for Digital Video timings in order to support HDTV receivers and transmitters.</para>
</listitem>
</orderedlist>
</section>
</section>
<section id="other">

View file

@ -74,6 +74,17 @@ Remote Controller chapter.</contrib>
</address>
</affiliation>
</author>
<author>
<firstname>Muralidharan</firstname>
<surname>Karicheri</surname>
<contrib>Documented the Digital Video timings API.</contrib>
<affiliation>
<address>
<email>m-karicheri2@ti.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
@ -89,7 +100,7 @@ Remote Controller chapter.</contrib>
<year>2008</year>
<year>2009</year>
<holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
Rubli, Andy Walls, Mauro Carvalho Chehab</holder>
Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
</copyright>
<legalnotice>
<para>Except when explicitly stated as GPL, programming examples within
@ -102,6 +113,13 @@ structs, ioctls) must be noted in more detail in the history chapter
(compat.sgml), along with the possible impact on existing drivers and
applications. -->
<revision>
<revnumber>2.6.33</revnumber>
<date>2009-12-03</date>
<authorinitials>mk</authorinitials>
<revremark>Added documentation for the Digital Video timings API.</revremark>
</revision>
<revision>
<revnumber>2.6.32</revnumber>
<date>2009-08-31</date>
@ -355,7 +373,7 @@ and discussions on the V4L mailing list.</revremark>
</partinfo>
<title>Video for Linux Two API Specification</title>
<subtitle>Revision 2.6.32</subtitle>
<subtitle>Revision 2.6.33</subtitle>
<chapter id="common">
&sub-common;
@ -411,6 +429,7 @@ and discussions on the V4L mailing list.</revremark>
&sub-encoder-cmd;
&sub-enumaudio;
&sub-enumaudioout;
&sub-enum-dv-presets;
&sub-enum-fmt;
&sub-enum-framesizes;
&sub-enum-frameintervals;
@ -421,6 +440,8 @@ and discussions on the V4L mailing list.</revremark>
&sub-g-audioout;
&sub-g-crop;
&sub-g-ctrl;
&sub-g-dv-preset;
&sub-g-dv-timings;
&sub-g-enc-index;
&sub-g-ext-ctrls;
&sub-g-fbuf;
@ -441,6 +462,7 @@ and discussions on the V4L mailing list.</revremark>
&sub-querybuf;
&sub-querycap;
&sub-queryctrl;
&sub-query-dv-preset;
&sub-querystd;
&sub-reqbufs;
&sub-s-hw-freq-seek;

View file

@ -733,6 +733,99 @@ struct <link linkend="v4l2-standard">v4l2_standard</link> {
__u32 reserved[4];
};
/*
* V I D E O T I M I N G S D V P R E S E T
*/
struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link> {
__u32 preset;
__u32 reserved[4];
};
/*
* D V P R E S E T S E N U M E R A T I O N
*/
struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link> {
__u32 index;
__u32 preset;
__u8 name[32]; /* Name of the preset timing */
__u32 width;
__u32 height;
__u32 reserved[4];
};
/*
* D V P R E S E T V A L U E S
*/
#define V4L2_DV_INVALID 0
#define V4L2_DV_480P59_94 1 /* BT.1362 */
#define V4L2_DV_576P50 2 /* BT.1362 */
#define V4L2_DV_720P24 3 /* SMPTE 296M */
#define V4L2_DV_720P25 4 /* SMPTE 296M */
#define V4L2_DV_720P30 5 /* SMPTE 296M */
#define V4L2_DV_720P50 6 /* SMPTE 296M */
#define V4L2_DV_720P59_94 7 /* SMPTE 274M */
#define V4L2_DV_720P60 8 /* SMPTE 274M/296M */
#define V4L2_DV_1080I29_97 9 /* BT.1120/ SMPTE 274M */
#define V4L2_DV_1080I30 10 /* BT.1120/ SMPTE 274M */
#define V4L2_DV_1080I25 11 /* BT.1120 */
#define V4L2_DV_1080I50 12 /* SMPTE 296M */
#define V4L2_DV_1080I60 13 /* SMPTE 296M */
#define V4L2_DV_1080P24 14 /* SMPTE 296M */
#define V4L2_DV_1080P25 15 /* SMPTE 296M */
#define V4L2_DV_1080P30 16 /* SMPTE 296M */
#define V4L2_DV_1080P50 17 /* BT.1120 */
#define V4L2_DV_1080P60 18 /* BT.1120 */
/*
* D V B T T I M I N G S
*/
/* BT.656/BT.1120 timing data */
struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link> {
__u32 width; /* width in pixels */
__u32 height; /* height in lines */
__u32 interlaced; /* Interlaced or progressive */
__u32 polarities; /* Positive or negative polarity */
__u64 pixelclock; /* Pixel clock in HZ. Ex. 74.25MHz-&gt;74250000 */
__u32 hfrontporch; /* Horizpontal front porch in pixels */
__u32 hsync; /* Horizontal Sync length in pixels */
__u32 hbackporch; /* Horizontal back porch in pixels */
__u32 vfrontporch; /* Vertical front porch in pixels */
__u32 vsync; /* Vertical Sync length in lines */
__u32 vbackporch; /* Vertical back porch in lines */
__u32 il_vfrontporch; /* Vertical front porch for bottom field of
* interlaced field formats
*/
__u32 il_vsync; /* Vertical sync length for bottom field of
* interlaced field formats
*/
__u32 il_vbackporch; /* Vertical back porch for bottom field of
* interlaced field formats
*/
__u32 reserved[16];
} __attribute__ ((packed));
/* Interlaced or progressive format */
#define V4L2_DV_PROGRESSIVE 0
#define V4L2_DV_INTERLACED 1
/* Polarities. If bit is not set, it is assumed to be negative polarity */
#define V4L2_DV_VSYNC_POS_POL 0x00000001
#define V4L2_DV_HSYNC_POS_POL 0x00000002
/* DV timings */
struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link> {
__u32 type;
union {
struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link> bt;
__u32 reserved[32];
};
} __attribute__ ((packed));
/* Values for the type field */
#define V4L2_DV_BT_656_1120 0 /* BT.656/1120 timing type */
/*
* V I D E O I N P U T S
*/
@ -744,7 +837,8 @@ struct <link linkend="v4l2-input">v4l2_input</link> {
__u32 tuner; /* Associated tuner */
v4l2_std_id std;
__u32 status;
__u32 reserved[4];
__u32 capabilities;
__u32 reserved[3];
};
/* Values for the 'type' field */
@ -775,6 +869,11 @@ struct <link linkend="v4l2-input">v4l2_input</link> {
#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */
#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
/* capabilities flags */
#define V4L2_IN_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */
#define V4L2_IN_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */
#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */
/*
* V I D E O O U T P U T S
*/
@ -785,13 +884,19 @@ struct <link linkend="v4l2-output">v4l2_output</link> {
__u32 audioset; /* Associated audios (bitfield) */
__u32 modulator; /* Associated modulator */
v4l2_std_id std;
__u32 reserved[4];
__u32 capabilities;
__u32 reserved[3];
};
/* Values for the 'type' field */
#define V4L2_OUTPUT_TYPE_MODULATOR 1
#define V4L2_OUTPUT_TYPE_ANALOG 2
#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
/* capabilities flags */
#define V4L2_OUT_CAP_PRESETS 0x00000001 /* Supports S_DV_PRESET */
#define V4L2_OUT_CAP_CUSTOM_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */
#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */
/*
* C O N T R O L S
*/
@ -1626,6 +1731,13 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
#endif
#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link>)
#define VIDIOC_ENUM_DV_PRESETS _IOWR('V', 83, struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link>)
#define VIDIOC_S_DV_PRESET _IOWR('V', 84, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
#define VIDIOC_G_DV_PRESET _IOWR('V', 85, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
#define VIDIOC_QUERY_DV_PRESET _IOR('V', 86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
#define VIDIOC_G_DV_TIMINGS _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
/* Reminder: when adding new ioctls please add support for them to
drivers/media/video/v4l2-compat-ioctl32.c as well! */

View file

@ -0,0 +1,238 @@
<refentry id="vidioc-enum-dv-presets">
<refmeta>
<refentrytitle>ioctl VIDIOC_ENUM_DV_PRESETS</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname>VIDIOC_ENUM_DV_PRESETS</refname>
<refpurpose>Enumerate supported Digital Video presets</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>ioctl</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>request</parameter></paramdef>
<paramdef>struct v4l2_dv_enum_preset *<parameter>argp</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Arguments</title>
<variablelist>
<varlistentry>
<term><parameter>fd</parameter></term>
<listitem>
<para>&fd;</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>request</parameter></term>
<listitem>
<para>VIDIOC_ENUM_DV_PRESETS</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>argp</parameter></term>
<listitem>
<para></para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Description</title>
<para>To query the attributes of a DV preset, applications initialize the
<structfield>index</structfield> field and zero the reserved array of &v4l2-dv-enum-preset;
and call the <constant>VIDIOC_ENUM_DV_PRESETS</constant> ioctl with a pointer to this
structure. Drivers fill the rest of the structure or return an
&EINVAL; when the index is out of bounds. To enumerate all DV Presets supported,
applications shall begin at index zero, incrementing by one until the
driver returns <errorcode>EINVAL</errorcode>. Drivers may enumerate a
different set of DV presets after switching the video input or
output.</para>
<table pgwide="1" frame="none" id="v4l2-dv-enum-preset">
<title>struct <structname>v4l2_dv_enum_presets</structname></title>
<tgroup cols="3">
&cs-str;
<tbody valign="top">
<row>
<entry>__u32</entry>
<entry><structfield>index</structfield></entry>
<entry>Number of the DV preset, set by the
application.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>preset</structfield></entry>
<entry>This field identifies one of the DV preset values listed in <xref linkend="v4l2-dv-presets-vals"/>.</entry>
</row>
<row>
<entry>__u8</entry>
<entry><structfield>name</structfield>[24]</entry>
<entry>Name of the preset, a NUL-terminated ASCII string, for example: "720P-60", "1080I-60". This information is
intended for the user.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>width</structfield></entry>
<entry>Width of the active video in pixels for the DV preset.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>height</structfield></entry>
<entry>Height of the active video in lines for the DV preset.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>reserved</structfield>[4]</entry>
<entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
</row>
</tbody>
</tgroup>
</table>
<table pgwide="1" frame="none" id="v4l2-dv-presets-vals">
<title>struct <structname>DV Presets</structname></title>
<tgroup cols="3">
&cs-str;
<tbody valign="top">
<row>
<entry>Preset</entry>
<entry>Preset value</entry>
<entry>Description</entry>
</row>
<row>
<entry></entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry>V4L2_DV_INVALID</entry>
<entry>0</entry>
<entry>Invalid preset value.</entry>
</row>
<row>
<entry>V4L2_DV_480P59_94</entry>
<entry>1</entry>
<entry>720x480 progressive video at 59.94 fps as per BT.1362.</entry>
</row>
<row>
<entry>V4L2_DV_576P50</entry>
<entry>2</entry>
<entry>720x576 progressive video at 50 fps as per BT.1362.</entry>
</row>
<row>
<entry>V4L2_DV_720P24</entry>
<entry>3</entry>
<entry>1280x720 progressive video at 24 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_720P25</entry>
<entry>4</entry>
<entry>1280x720 progressive video at 25 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_720P30</entry>
<entry>5</entry>
<entry>1280x720 progressive video at 30 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_720P50</entry>
<entry>6</entry>
<entry>1280x720 progressive video at 50 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_720P59_94</entry>
<entry>7</entry>
<entry>1280x720 progressive video at 59.94 fps as per SMPTE 274M.</entry>
</row>
<row>
<entry>V4L2_DV_720P60</entry>
<entry>8</entry>
<entry>1280x720 progressive video at 60 fps as per SMPTE 274M/296M.</entry>
</row>
<row>
<entry>V4L2_DV_1080I29_97</entry>
<entry>9</entry>
<entry>1920x1080 interlaced video at 29.97 fps as per BT.1120/SMPTE 274M.</entry>
</row>
<row>
<entry>V4L2_DV_1080I30</entry>
<entry>10</entry>
<entry>1920x1080 interlaced video at 30 fps as per BT.1120/SMPTE 274M.</entry>
</row>
<row>
<entry>V4L2_DV_1080I25</entry>
<entry>11</entry>
<entry>1920x1080 interlaced video at 25 fps as per BT.1120.</entry>
</row>
<row>
<entry>V4L2_DV_1080I50</entry>
<entry>12</entry>
<entry>1920x1080 interlaced video at 50 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_1080I60</entry>
<entry>13</entry>
<entry>1920x1080 interlaced video at 60 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_1080P24</entry>
<entry>14</entry>
<entry>1920x1080 progressive video at 24 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_1080P25</entry>
<entry>15</entry>
<entry>1920x1080 progressive video at 25 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_1080P30</entry>
<entry>16</entry>
<entry>1920x1080 progressive video at 30 fps as per SMPTE 296M.</entry>
</row>
<row>
<entry>V4L2_DV_1080P50</entry>
<entry>17</entry>
<entry>1920x1080 progressive video at 50 fps as per BT.1120.</entry>
</row>
<row>
<entry>V4L2_DV_1080P60</entry>
<entry>18</entry>
<entry>1920x1080 progressive video at 60 fps as per BT.1120.</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<refsect1>
&return-value;
<variablelist>
<varlistentry>
<term><errorcode>EINVAL</errorcode></term>
<listitem>
<para>The &v4l2-dv-enum-preset; <structfield>index</structfield>
is out of bounds.</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>
<!--
Local Variables:
mode: sgml
sgml-parent-document: "v4l2.sgml"
indent-tabs-mode: nil
End:
-->

View file

@ -124,7 +124,13 @@ current input.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>reserved</structfield>[4]</entry>
<entry><structfield>capabilities</structfield></entry>
<entry>This field provides capabilities for the
input. See <xref linkend="input-capabilities" /> for flags.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>reserved</structfield>[3]</entry>
<entry>Reserved for future extensions. Drivers must set
the array to zero.</entry>
</row>
@ -261,6 +267,34 @@ flag is set Macrovision has been detected.</entry>
</tbody>
</tgroup>
</table>
<!-- Capability flags based on video timings RFC by Muralidharan
Karicheri, titled RFC (v1.2): V4L - Support for video timings at the
input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
-->
<table frame="none" pgwide="1" id="input-capabilities">
<title>Input capabilities</title>
<tgroup cols="3">
&cs-def;
<tbody valign="top">
<row>
<entry><constant>V4L2_IN_CAP_PRESETS</constant></entry>
<entry>0x00000001</entry>
<entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
</row>
<row>
<entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry>
<entry>0x00000002</entry>
<entry>This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry>
</row>
<row>
<entry><constant>V4L2_IN_CAP_STD</constant></entry>
<entry>0x00000004</entry>
<entry>This input supports setting the TV standard by using VIDIOC_S_STD.</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<refsect1>

View file

@ -114,7 +114,13 @@ details on video standards and how to switch see <xref
</row>
<row>
<entry>__u32</entry>
<entry><structfield>reserved</structfield>[4]</entry>
<entry><structfield>capabilities</structfield></entry>
<entry>This field provides capabilities for the
output. See <xref linkend="output-capabilities" /> for flags.</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>reserved</structfield>[3]</entry>
<entry>Reserved for future extensions. Drivers must set
the array to zero.</entry>
</row>
@ -147,6 +153,34 @@ CVBS, S-Video, RGB.</entry>
</tgroup>
</table>
<!-- Capabilities flags based on video timings RFC by Muralidharan
Karicheri, titled RFC (v1.2): V4L - Support for video timings at the
input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
-->
<table frame="none" pgwide="1" id="output-capabilities">
<title>Output capabilities</title>
<tgroup cols="3">
&cs-def;
<tbody valign="top">
<row>
<entry><constant>V4L2_OUT_CAP_PRESETS</constant></entry>
<entry>0x00000001</entry>
<entry>This output supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
</row>
<row>
<entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry>
<entry>0x00000002</entry>
<entry>This output supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry>
</row>
<row>
<entry><constant>V4L2_OUT_CAP_STD</constant></entry>
<entry>0x00000004</entry>
<entry>This output supports setting the TV standard by using VIDIOC_S_STD.</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<refsect1>
&return-value;

View file

@ -0,0 +1,111 @@
<refentry id="vidioc-g-dv-preset">
<refmeta>
<refentrytitle>ioctl VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname>VIDIOC_G_DV_PRESET</refname>
<refname>VIDIOC_S_DV_PRESET</refname>
<refpurpose>Query or select the DV preset of the current input or output</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>ioctl</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>request</parameter></paramdef>
<paramdef>&v4l2-dv-preset;
*<parameter>argp</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Arguments</title>
<variablelist>
<varlistentry>
<term><parameter>fd</parameter></term>
<listitem>
<para>&fd;</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>request</parameter></term>
<listitem>
<para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>argp</parameter></term>
<listitem>
<para></para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Description</title>
<para>To query and select the current DV preset, applications
use the <constant>VIDIOC_G_DV_PRESET</constant> and <constant>VIDIOC_S_DV_PRESET</constant>
ioctls which take a pointer to a &v4l2-dv-preset; type as argument.
Applications must zero the reserved array in &v4l2-dv-preset;.
<constant>VIDIOC_G_DV_PRESET</constant> returns a dv preset in the field
<structfield>preset</structfield> of &v4l2-dv-preset;.</para>
<para><constant>VIDIOC_S_DV_PRESET</constant> accepts a pointer to a &v4l2-dv-preset;
that has the preset value to be set. Applications must zero the reserved array in &v4l2-dv-preset;.
If the preset is not supported, it returns an &EINVAL; </para>
</refsect1>
<refsect1>
&return-value;
<variablelist>
<varlistentry>
<term><errorcode>EINVAL</errorcode></term>
<listitem>
<para>This ioctl is not supported, or the
<constant>VIDIOC_S_DV_PRESET</constant>,<constant>VIDIOC_S_DV_PRESET</constant> parameter was unsuitable.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>The device is busy and therefore can not change the preset.</para>
</listitem>
</varlistentry>
</variablelist>
<table pgwide="1" frame="none" id="v4l2-dv-preset">
<title>struct <structname>v4l2_dv_preset</structname></title>
<tgroup cols="3">
&cs-str;
<tbody valign="top">
<row>
<entry>__u32</entry>
<entry><structfield>preset</structfield></entry>
<entry>Preset value to represent the digital video timings</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>reserved[4]</structfield></entry>
<entry>Reserved fields for future use</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
</refentry>
<!--
Local Variables:
mode: sgml
sgml-parent-document: "v4l2.sgml"
indent-tabs-mode: nil
End:
-->

View file

@ -0,0 +1,224 @@
<refentry id="vidioc-g-dv-timings">
<refmeta>
<refentrytitle>ioctl VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname>VIDIOC_G_DV_TIMINGS</refname>
<refname>VIDIOC_S_DV_TIMINGS</refname>
<refpurpose>Get or set custom DV timings for input or output</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>ioctl</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>request</parameter></paramdef>
<paramdef>&v4l2-dv-timings;
*<parameter>argp</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Arguments</title>
<variablelist>
<varlistentry>
<term><parameter>fd</parameter></term>
<listitem>
<para>&fd;</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>request</parameter></term>
<listitem>
<para>VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>argp</parameter></term>
<listitem>
<para></para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Description</title>
<para>To set custom DV timings for the input or output, applications use the
<constant>VIDIOC_S_DV_TIMINGS</constant> ioctl and to get the current custom timings,
applications use the <constant>VIDIOC_G_DV_TIMINGS</constant> ioctl. The detailed timing
information is filled in using the structure &v4l2-dv-timings;. These ioctls take
a pointer to the &v4l2-dv-timings; structure as argument. If the ioctl is not supported
or the timing values are not correct, the driver returns &EINVAL;.</para>
</refsect1>
<refsect1>
&return-value;
<variablelist>
<varlistentry>
<term><errorcode>EINVAL</errorcode></term>
<listitem>
<para>This ioctl is not supported, or the
<constant>VIDIOC_S_DV_TIMINGS</constant> parameter was unsuitable.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>The device is busy and therefore can not change the timings.</para>
</listitem>
</varlistentry>
</variablelist>
<table pgwide="1" frame="none" id="v4l2-bt-timings">
<title>struct <structname>v4l2_bt_timings</structname></title>
<tgroup cols="3">
&cs-str;
<tbody valign="top">
<row>
<entry>__u32</entry>
<entry><structfield>width</structfield></entry>
<entry>Width of the active video in pixels</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>height</structfield></entry>
<entry>Height of the active video in lines</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>interlaced</structfield></entry>
<entry>Progressive (0) or interlaced (1)</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>polarities</structfield></entry>
<entry>This is a bit mask that defines polarities of sync signals.
bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_HSYNC_POS_POL) is for horizontal sync polarity. If the bit is set
(1) it is positive polarity and if is cleared (0), it is negative polarity.</entry>
</row>
<row>
<entry>__u64</entry>
<entry><structfield>pixelclock</structfield></entry>
<entry>Pixel clock in Hz. Ex. 74.25MHz->74250000</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>hfrontporch</structfield></entry>
<entry>Horizontal front porch in pixels</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>hsync</structfield></entry>
<entry>Horizontal sync length in pixels</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>hbackporch</structfield></entry>
<entry>Horizontal back porch in pixels</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>vfrontporch</structfield></entry>
<entry>Vertical front porch in lines</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>vsync</structfield></entry>
<entry>Vertical sync length in lines</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>vbackporch</structfield></entry>
<entry>Vertical back porch in lines</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>il_vfrontporch</structfield></entry>
<entry>Vertical front porch in lines for bottom field of interlaced field formats</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>il_vsync</structfield></entry>
<entry>Vertical sync length in lines for bottom field of interlaced field formats</entry>
</row>
<row>
<entry>__u32</entry>
<entry><structfield>il_vbackporch</structfield></entry>
<entry>Vertical back porch in lines for bottom field of interlaced field formats</entry>
</row>
</tbody>
</tgroup>
</table>
<table pgwide="1" frame="none" id="v4l2-dv-timings">
<title>struct <structname>v4l2_dv_timings</structname></title>
<tgroup cols="4">
&cs-str;
<tbody valign="top">
<row>
<entry>__u32</entry>
<entry><structfield>type</structfield></entry>
<entry></entry>
<entry>Type of DV timings as listed in <xref linkend="dv-timing-types"/>.</entry>
</row>
<row>
<entry>union</entry>
<entry><structfield></structfield></entry>
<entry></entry>
</row>
<row>
<entry></entry>
<entry>&v4l2-bt-timings;</entry>
<entry><structfield>bt</structfield></entry>
<entry>Timings defined by BT.656/1120 specifications</entry>
</row>
<row>
<entry></entry>
<entry>__u32</entry>
<entry><structfield>reserved</structfield>[32]</entry>
<entry></entry>
</row>
</tbody>
</tgroup>
</table>
<table pgwide="1" frame="none" id="dv-timing-types">
<title>DV Timing types</title>
<tgroup cols="3">
&cs-str;
<tbody valign="top">
<row>
<entry>Timing type</entry>
<entry>value</entry>
<entry>Description</entry>
</row>
<row>
<entry></entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry>V4L2_DV_BT_656_1120</entry>
<entry>0</entry>
<entry>BT.656/1120 timings</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
</refentry>
<!--
Local Variables:
mode: sgml
sgml-parent-document: "v4l2.sgml"
indent-tabs-mode: nil
End:
-->

View file

@ -86,6 +86,12 @@ standards.</para>
<constant>VIDIOC_S_STD</constant> parameter was unsuitable.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>The device is busy and therefore can not change the standard</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View file

@ -0,0 +1,85 @@
<refentry id="vidioc-query-dv-preset">
<refmeta>
<refentrytitle>ioctl VIDIOC_QUERY_DV_PRESET</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname>VIDIOC_QUERY_DV_PRESET</refname>
<refpurpose>Sense the DV preset received by the current
input</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
<funcdef>int <function>ioctl</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>request</parameter></paramdef>
<paramdef>&v4l2-dv-preset; *<parameter>argp</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Arguments</title>
<variablelist>
<varlistentry>
<term><parameter>fd</parameter></term>
<listitem>
<para>&fd;</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>request</parameter></term>
<listitem>
<para>VIDIOC_QUERY_DV_PRESET</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>argp</parameter></term>
<listitem>
<para></para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Description</title>
<para>The hardware may be able to detect the current DV preset
automatically, similar to sensing the video standard. To do so, applications
call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
returned in the preset field of &v4l2-dv-preset;. When detection is not
possible or fails, the value V4L2_DV_INVALID is returned.</para>
</refsect1>
<refsect1>
&return-value;
<variablelist>
<varlistentry>
<term><errorcode>EINVAL</errorcode></term>
<listitem>
<para>This ioctl is not supported.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>The device is busy and therefore can not sense the preset</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>
<!--
Local Variables:
mode: sgml
sgml-parent-document: "v4l2.sgml"
indent-tabs-mode: nil
End:
-->

View file

@ -70,6 +70,12 @@ current video input or output.</para>
<para>This ioctl is not supported.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>The device is busy and therefore can not detect the standard</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View file

@ -12,6 +12,7 @@ m5602 0402:5602 ALi Video Camera Controller
spca501 040a:0002 Kodak DVC-325
spca500 040a:0300 Kodak EZ200
zc3xx 041e:041e Creative WebCam Live!
ov519 041e:4003 Video Blaster WebCam Go Plus
spca500 041e:400a Creative PC-CAM 300
sunplus 041e:400b Creative PC-CAM 600
sunplus 041e:4012 PC-Cam350
@ -168,10 +169,14 @@ sunplus 055f:c650 Mustek MDC5500Z
zc3xx 055f:d003 Mustek WCam300A
zc3xx 055f:d004 Mustek WCam300 AN
conex 0572:0041 Creative Notebook cx11646
ov519 05a9:0511 Video Blaster WebCam 3/WebCam Plus, D-Link USB Digital Video Camera
ov519 05a9:0518 Creative WebCam
ov519 05a9:0519 OV519 Microphone
ov519 05a9:0530 OmniVision
ov519 05a9:2800 OmniVision SuperCAM
ov519 05a9:4519 Webcam Classic
ov519 05a9:8519 OmniVision
ov519 05a9:a511 D-Link USB Digital Video Camera
ov519 05a9:a518 D-Link DSB-C310 Webcam
sunplus 05da:1018 Digital Dream Enigma 1.3
stk014 05e1:0893 Syntek DV4000
@ -187,7 +192,7 @@ ov534 06f8:3002 Hercules Blog Webcam
ov534 06f8:3003 Hercules Dualpix HD Weblog
sonixj 06f8:3004 Hercules Classic Silver
sonixj 06f8:3008 Hercules Deluxe Optical Glass
pac7311 06f8:3009 Hercules Classic Link
pac7302 06f8:3009 Hercules Classic Link
spca508 0733:0110 ViewQuest VQ110
spca501 0733:0401 Intel Create and Share
spca501 0733:0402 ViewQuest M318B
@ -199,6 +204,7 @@ sunplus 0733:2221 Mercury Digital Pro 3.1p
sunplus 0733:3261 Concord 3045 spca536a
sunplus 0733:3281 Cyberpix S550V
spca506 0734:043b 3DeMon USB Capture aka
ov519 0813:0002 Dual Mode USB Camera Plus
spca500 084d:0003 D-Link DSC-350
spca500 08ca:0103 Aiptek PocketDV
sunplus 08ca:0104 Aiptek PocketDVII 1.3
@ -236,15 +242,15 @@ pac7311 093a:2603 Philips SPC 500 NC
pac7311 093a:2608 Trust WB-3300p
pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
pac7311 093a:260f SnakeCam
pac7311 093a:2620 Apollo AC-905
pac7311 093a:2621 PAC731x
pac7311 093a:2622 Genius Eye 312
pac7311 093a:2624 PAC7302
pac7311 093a:2626 Labtec 2200
pac7311 093a:2628 Genius iLook 300
pac7311 093a:2629 Genious iSlim 300
pac7311 093a:262a Webcam 300k
pac7311 093a:262c Philips SPC 230 NC
pac7302 093a:2620 Apollo AC-905
pac7302 093a:2621 PAC731x
pac7302 093a:2622 Genius Eye 312
pac7302 093a:2624 PAC7302
pac7302 093a:2626 Labtec 2200
pac7302 093a:2628 Genius iLook 300
pac7302 093a:2629 Genious iSlim 300
pac7302 093a:262a Webcam 300k
pac7302 093a:262c Philips SPC 230 NC
jeilinj 0979:0280 Sakar 57379
zc3xx 0ac8:0302 Z-star Vimicro zc0302
vc032x 0ac8:0321 Vimicro generic vc0321
@ -259,6 +265,7 @@ vc032x 0ac8:c002 Sony embedded vimicro
vc032x 0ac8:c301 Samsung Q1 Ultra Premium
spca508 0af9:0010 Hama USB Sightcam 100
spca508 0af9:0011 Hama USB Sightcam 100
ov519 0b62:0059 iBOT2 Webcam
sonixb 0c45:6001 Genius VideoCAM NB
sonixb 0c45:6005 Microdia Sweex Mini Webcam
sonixb 0c45:6007 Sonix sn9c101 + Tas5110D
@ -318,8 +325,10 @@ sn9c20x 0c45:62b3 PC Camera (SN9C202 + OV9655)
sn9c20x 0c45:62bb PC Camera (SN9C202 + OV7660)
sn9c20x 0c45:62bc PC Camera (SN9C202 + HV7131R)
sunplus 0d64:0303 Sunplus FashionCam DXG
ov519 0e96:c001 TRUST 380 USB2 SPACEC@M
etoms 102c:6151 Qcam Sangha CIF
etoms 102c:6251 Qcam xxxxxx VGA
ov519 1046:9967 W9967CF/W9968CF WebCam IC, Video Blaster WebCam Go
zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128
spca561 10fd:7e50 FlyCam Usb 100
zc3xx 10fd:8050 Typhoon Webshot II USB 300k
@ -332,7 +341,12 @@ spca501 1776:501c Arowana 300K CMOS Camera
t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
pac207 2001:f115 D-Link DSB-C120
sq905c 2770:9050 sq905c
sq905c 2770:905c DualCamera
sq905 2770:9120 Argus Digital Camera DC1512
sq905c 2770:913d sq905c
spca500 2899:012c Toptro Industrial
ov519 8020:ef04 ov519
spca508 8086:0110 Intel Easy PC Camera
spca500 8086:0630 Intel Pocket PC Camera
spca506 99fa:8988 Grandtec V.cap

View file

@ -0,0 +1,157 @@
Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver
=======================================================================
Terminology
-----------
sensor scales: horizontal and vertical scales, configured by the sensor driver
host scales: -"- host driver
combined scales: sensor_scale * host_scale
Generic scaling / cropping scheme
---------------------------------
-1--
|
-2-- -\
| --\
| --\
+-5-- -\ -- -3--
| ---\
| --- -4-- -\
| -\
| - -6--
|
| - -6'-
| -/
| --- -4'- -/
| ---/
+-5'- -/
| -- -3'-
| --/
| --/
-2'- -/
|
|
-1'-
Produced by user requests:
S_CROP(left / top = (5) - (1), width / height = (5') - (5))
S_FMT(width / height = (6') - (6))
Here:
(1) to (1') - whole max width or height
(1) to (2) - sensor cropped left or top
(2) to (2') - sensor cropped width or height
(3) to (3') - sensor scale
(3) to (4) - CEU cropped left or top
(4) to (4') - CEU cropped width or height
(5) to (5') - reverse sensor scale applied to CEU cropped width or height
(2) to (5) - reverse sensor scale applied to CEU cropped left or top
(6) to (6') - CEU scale - user window
S_FMT
-----
Do not touch input rectangle - it is already optimal.
1. Calculate current sensor scales:
scale_s = ((3') - (3)) / ((2') - (2))
2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
current sensor scales onto input window - this is user S_CROP:
width_u = (5') - (5) = ((4') - (4)) * scale_s
3. Calculate new combined scales from "effective" input window to requested user
window:
scale_comb = width_u / ((6') - (6))
4. Calculate sensor output window by applying combined scales to real input
window:
width_s_out = ((2') - (2)) / scale_comb
5. Apply iterative sensor S_FMT for sensor output window.
subdev->video_ops->s_fmt(.width = width_s_out)
6. Retrieve sensor output window (g_fmt)
7. Calculate new sensor scales:
scale_s_new = ((3')_new - (3)_new) / ((2') - (2))
8. Calculate new CEU crop - apply sensor scales to previously calculated
"effective" crop:
width_ceu = (4')_new - (4)_new = width_u / scale_s_new
left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new
9. Use CEU cropping to crop to the new window:
ceu_crop(.width = width_ceu, .left = left_ceu)
10. Use CEU scaling to scale to the requested user window:
scale_ceu = width_ceu / width
S_CROP
------
If old scale applied to new crop is invalid produce nearest new scale possible
1. Calculate current combined scales.
scale_comb = (((4') - (4)) / ((6') - (6))) * (((2') - (2)) / ((3') - (3)))
2. Apply iterative sensor S_CROP for new input window.
3. If old combined scales applied to new crop produce an impossible user window,
adjust scales to produce nearest possible window.
width_u_out = ((5') - (5)) / scale_comb
if (width_u_out > max)
scale_comb = ((5') - (5)) / max;
else if (width_u_out < min)
scale_comb = ((5') - (5)) / min;
4. Issue G_CROP to retrieve actual input window.
5. Using actual input window and calculated combined scales calculate sensor
target output window.
width_s_out = ((3') - (3)) = ((2') - (2)) / scale_comb
6. Apply iterative S_FMT for new sensor target output window.
7. Issue G_FMT to retrieve the actual sensor output window.
8. Calculate sensor scales.
scale_s = ((3') - (3)) / ((2') - (2))
9. Calculate sensor output subwindow to be cropped on CEU by applying sensor
scales to the requested window.
width_ceu = ((5') - (5)) / scale_s
10. Use CEU cropping for above calculated window.
11. Calculate CEU scales from sensor scales from results of (10) and user window
from (3)
scale_ceu = calc_scale(((5') - (5)), &width_u_out)
12. Apply CEU scales.
--
Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

View file

@ -561,6 +561,8 @@ video_device helper functions
There are a few useful helper functions:
- file/video_device private data
You can set/get driver private data in the video_device struct using:
void *video_get_drvdata(struct video_device *vdev);
@ -575,8 +577,7 @@ struct video_device *video_devdata(struct file *file);
returns the video_device belonging to the file struct.
The final helper function combines video_get_drvdata with
video_devdata:
The video_drvdata function combines video_get_drvdata with video_devdata:
void *video_drvdata(struct file *file);
@ -584,6 +585,17 @@ You can go from a video_device struct to the v4l2_device struct using:
struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
- Device node name
The video_device node kernel name can be retrieved using
const char *video_device_node_name(struct video_device *vdev);
The name is used as a hint by userspace tools such as udev. The function
should be used where possible instead of accessing the video_device::num and
video_device::minor fields.
video buffer helper functions
-----------------------------

View file

@ -316,20 +316,23 @@ static struct soc_camera_platform_info camera_info = {
.format_name = "UYVY",
.format_depth = 16,
.format = {
.pixelformat = V4L2_PIX_FMT_UYVY,
.code = V4L2_MBUS_FMT_YUYV8_2X8_BE,
.colorspace = V4L2_COLORSPACE_SMPTE170M,
.field = V4L2_FIELD_NONE,
.width = 640,
.height = 480,
},
.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
.set_capture = camera_set_capture,
.link = {
.bus_id = 0,
.add_device = ap325rxa_camera_add,
.del_device = ap325rxa_camera_del,
.module_name = "soc_camera_platform",
},
};
struct soc_camera_link camera_link = {
.bus_id = 0,
.add_device = ap325rxa_camera_add,
.del_device = ap325rxa_camera_del,
.module_name = "soc_camera_platform",
.priv = &camera_info,
};
static void dummy_release(struct device *dev)
@ -347,7 +350,7 @@ static struct platform_device camera_device = {
static int ap325rxa_camera_add(struct soc_camera_link *icl,
struct device *dev)
{
if (icl != &camera_info.link || camera_probe() <= 0)
if (icl != &camera_link || camera_probe() <= 0)
return -ENODEV;
camera_info.dev = dev;
@ -357,7 +360,7 @@ static int ap325rxa_camera_add(struct soc_camera_link *icl,
static void ap325rxa_camera_del(struct soc_camera_link *icl)
{
if (icl != &camera_info.link)
if (icl != &camera_link)
return;
platform_device_unregister(&camera_device);
@ -470,13 +473,15 @@ static struct ov772x_camera_info ov7725_info = {
.buswidth = SOCAM_DATAWIDTH_8,
.flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
.edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0),
.link = {
.bus_id = 0,
.power = ov7725_power,
.board_info = &ap325rxa_i2c_camera[0],
.i2c_adapter_id = 0,
.module_name = "ov772x",
},
};
static struct soc_camera_link ov7725_link = {
.bus_id = 0,
.power = ov7725_power,
.board_info = &ap325rxa_i2c_camera[0],
.i2c_adapter_id = 0,
.module_name = "ov772x",
.priv = &ov7725_info,
};
static struct platform_device ap325rxa_camera[] = {
@ -484,13 +489,13 @@ static struct platform_device ap325rxa_camera[] = {
.name = "soc-camera-pdrv",
.id = 0,
.dev = {
.platform_data = &ov7725_info.link,
.platform_data = &ov7725_link,
},
}, {
.name = "soc-camera-pdrv",
.id = 1,
.dev = {
.platform_data = &camera_info.link,
.platform_data = &camera_link,
},
},
};

View file

@ -19,6 +19,7 @@
#include <linux/input/sh_keysc.h>
#include <linux/i2c.h>
#include <linux/usb/r8a66597.h>
#include <media/rj54n1cb0c.h>
#include <media/soc_camera.h>
#include <media/sh_mobile_ceu.h>
#include <video/sh_mobile_lcdc.h>
@ -255,6 +256,9 @@ static struct i2c_board_info kfr2r09_i2c_camera = {
static struct clk *camera_clk;
/* set VIO_CKO clock to 25MHz */
#define CEU_MCLK_FREQ 25000000
#define DRVCRB 0xA405018C
static int camera_power(struct device *dev, int mode)
{
@ -267,8 +271,7 @@ static int camera_power(struct device *dev, int mode)
if (IS_ERR(camera_clk))
return PTR_ERR(camera_clk);
/* set VIO_CKO clock to 25MHz */
rate = clk_round_rate(camera_clk, 25000000);
rate = clk_round_rate(camera_clk, CEU_MCLK_FREQ);
ret = clk_set_rate(camera_clk, rate);
if (ret < 0)
goto eclkrate;
@ -318,11 +321,17 @@ eclkrate:
return ret;
}
static struct rj54n1_pdata rj54n1_priv = {
.mclk_freq = CEU_MCLK_FREQ,
.ioctl_high = false,
};
static struct soc_camera_link rj54n1_link = {
.power = camera_power,
.board_info = &kfr2r09_i2c_camera,
.i2c_adapter_id = 1,
.module_name = "rj54n1cb0c",
.priv = &rj54n1_priv,
};
static struct platform_device kfr2r09_camera = {

View file

@ -432,23 +432,27 @@ static struct i2c_board_info migor_i2c_camera[] = {
static struct ov772x_camera_info ov7725_info = {
.buswidth = SOCAM_DATAWIDTH_8,
.link = {
.power = ov7725_power,
.board_info = &migor_i2c_camera[0],
.i2c_adapter_id = 0,
.module_name = "ov772x",
},
};
static struct soc_camera_link ov7725_link = {
.power = ov7725_power,
.board_info = &migor_i2c_camera[0],
.i2c_adapter_id = 0,
.module_name = "ov772x",
.priv = &ov7725_info,
};
static struct tw9910_video_info tw9910_info = {
.buswidth = SOCAM_DATAWIDTH_8,
.mpout = TW9910_MPO_FIELD,
.link = {
.power = tw9910_power,
.board_info = &migor_i2c_camera[1],
.i2c_adapter_id = 0,
.module_name = "tw9910",
}
};
static struct soc_camera_link tw9910_link = {
.power = tw9910_power,
.board_info = &migor_i2c_camera[1],
.i2c_adapter_id = 0,
.module_name = "tw9910",
.priv = &tw9910_info,
};
static struct platform_device migor_camera[] = {
@ -456,13 +460,13 @@ static struct platform_device migor_camera[] = {
.name = "soc-camera-pdrv",
.id = 0,
.dev = {
.platform_data = &ov7725_info.link,
.platform_data = &ov7725_link,
},
}, {
.name = "soc-camera-pdrv",
.id = 1,
.dev = {
.platform_data = &tw9910_info.link,
.platform_data = &tw9910_link,
},
},
};

9
drivers/media/IR/Kconfig Normal file
View file

@ -0,0 +1,9 @@
config IR_CORE
tristate
depends on INPUT
default INPUT
config VIDEO_IR
tristate
depends on IR_CORE
default IR_CORE

View file

@ -0,0 +1,5 @@
ir-common-objs := ir-functions.o ir-keymaps.o
ir-core-objs := ir-keytable.o
obj-$(CONFIG_IR_CORE) += ir-core.o
obj-$(CONFIG_VIDEO_IR) += ir-common.o

View file

@ -34,9 +34,6 @@ static int repeat = 1;
module_param(repeat, int, 0444);
MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
int media_ir_debug; /* media_ir_debug level (0,1,2) */
module_param_named(debug, media_ir_debug, int, 0644);
/* -------------------------------------------------------------------------- */
static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
@ -55,25 +52,10 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
/* -------------------------------------------------------------------------- */
int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
int ir_type, struct ir_scancode_table *ir_codes)
int ir_type)
{
ir->ir_type = ir_type;
ir->keytable.size = ir_roundup_tablesize(ir_codes->size);
ir->keytable.scan = kzalloc(ir->keytable.size *
sizeof(struct ir_scancode), GFP_KERNEL);
if (!ir->keytable.scan)
return -ENOMEM;
IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
ir->keytable.size,
ir->keytable.size * sizeof(ir->keytable.scan));
ir_copy_table(&ir->keytable, ir_codes);
ir_set_keycode_table(dev, &ir->keytable);
clear_bit(0, dev->keybit);
set_bit(EV_KEY, dev->evbit);
if (repeat)
set_bit(EV_REP, dev->evbit);

View file

@ -1847,76 +1847,6 @@ struct ir_scancode_table ir_codes_hauppauge_new_table = {
};
EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table);
/*
* Hauppauge:the newer, gray remotes (seems there are multiple
* slightly different versions), shipped with cx88+ivtv cards.
*
* This table contains the complete RC5 code, instead of just the data part
*/
static struct ir_scancode ir_codes_rc5_hauppauge_new[] = {
/* Keys 0 to 9 */
{ 0x1e00, KEY_0 },
{ 0x1e01, KEY_1 },
{ 0x1e02, KEY_2 },
{ 0x1e03, KEY_3 },
{ 0x1e04, KEY_4 },
{ 0x1e05, KEY_5 },
{ 0x1e06, KEY_6 },
{ 0x1e07, KEY_7 },
{ 0x1e08, KEY_8 },
{ 0x1e09, KEY_9 },
{ 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */
{ 0x1e0b, KEY_RED }, /* red button */
{ 0x1e0c, KEY_RADIO },
{ 0x1e0d, KEY_MENU },
{ 0x1e0e, KEY_SUBTITLE }, /* also the # key */
{ 0x1e0f, KEY_MUTE },
{ 0x1e10, KEY_VOLUMEUP },
{ 0x1e11, KEY_VOLUMEDOWN },
{ 0x1e12, KEY_PREVIOUS }, /* previous channel */
{ 0x1e14, KEY_UP },
{ 0x1e15, KEY_DOWN },
{ 0x1e16, KEY_LEFT },
{ 0x1e17, KEY_RIGHT },
{ 0x1e18, KEY_VIDEO }, /* Videos */
{ 0x1e19, KEY_AUDIO }, /* Music */
/* 0x1e1a: Pictures - presume this means
"Multimedia Home Platform" -
no "PICTURES" key in input.h
*/
{ 0x1e1a, KEY_MHP },
{ 0x1e1b, KEY_EPG }, /* Guide */
{ 0x1e1c, KEY_TV },
{ 0x1e1e, KEY_NEXTSONG }, /* skip >| */
{ 0x1e1f, KEY_EXIT }, /* back/exit */
{ 0x1e20, KEY_CHANNELUP }, /* channel / program + */
{ 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x1e22, KEY_CHANNEL }, /* source (old black remote) */
{ 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */
{ 0x1e25, KEY_ENTER }, /* OK */
{ 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */
{ 0x1e29, KEY_BLUE }, /* blue key */
{ 0x1e2e, KEY_GREEN }, /* green button */
{ 0x1e30, KEY_PAUSE }, /* pause */
{ 0x1e32, KEY_REWIND }, /* backward << */
{ 0x1e34, KEY_FASTFORWARD }, /* forward >> */
{ 0x1e35, KEY_PLAY },
{ 0x1e36, KEY_STOP },
{ 0x1e37, KEY_RECORD }, /* recording */
{ 0x1e38, KEY_YELLOW }, /* yellow key */
{ 0x1e3b, KEY_SELECT }, /* top right button */
{ 0x1e3c, KEY_ZOOM }, /* full */
{ 0x1e3d, KEY_POWER }, /* system power (green button) */
};
struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = {
.scan = ir_codes_rc5_hauppauge_new,
.size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new),
};
EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table);
static struct ir_scancode ir_codes_npgtech[] = {
{ 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */
{ 0x2a, KEY_FRONT },
@ -3314,3 +3244,152 @@ struct ir_scancode_table ir_codes_gadmei_rm008z_table = {
};
EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table);
/*************************************************************
* COMPLETE SCANCODE TABLES
* Instead of just a partial scancode, the tables bellow
* contains the complete scancode and the receiver protocol
*************************************************************/
/*
* Hauppauge:the newer, gray remotes (seems there are multiple
* slightly different versions), shipped with cx88+ivtv cards.
*
* This table contains the complete RC5 code, instead of just the data part
*/
static struct ir_scancode ir_codes_rc5_hauppauge_new[] = {
/* Keys 0 to 9 */
{ 0x1e00, KEY_0 },
{ 0x1e01, KEY_1 },
{ 0x1e02, KEY_2 },
{ 0x1e03, KEY_3 },
{ 0x1e04, KEY_4 },
{ 0x1e05, KEY_5 },
{ 0x1e06, KEY_6 },
{ 0x1e07, KEY_7 },
{ 0x1e08, KEY_8 },
{ 0x1e09, KEY_9 },
{ 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */
{ 0x1e0b, KEY_RED }, /* red button */
{ 0x1e0c, KEY_RADIO },
{ 0x1e0d, KEY_MENU },
{ 0x1e0e, KEY_SUBTITLE }, /* also the # key */
{ 0x1e0f, KEY_MUTE },
{ 0x1e10, KEY_VOLUMEUP },
{ 0x1e11, KEY_VOLUMEDOWN },
{ 0x1e12, KEY_PREVIOUS }, /* previous channel */
{ 0x1e14, KEY_UP },
{ 0x1e15, KEY_DOWN },
{ 0x1e16, KEY_LEFT },
{ 0x1e17, KEY_RIGHT },
{ 0x1e18, KEY_VIDEO }, /* Videos */
{ 0x1e19, KEY_AUDIO }, /* Music */
/* 0x1e1a: Pictures - presume this means
"Multimedia Home Platform" -
no "PICTURES" key in input.h
*/
{ 0x1e1a, KEY_MHP },
{ 0x1e1b, KEY_EPG }, /* Guide */
{ 0x1e1c, KEY_TV },
{ 0x1e1e, KEY_NEXTSONG }, /* skip >| */
{ 0x1e1f, KEY_EXIT }, /* back/exit */
{ 0x1e20, KEY_CHANNELUP }, /* channel / program + */
{ 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x1e22, KEY_CHANNEL }, /* source (old black remote) */
{ 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */
{ 0x1e25, KEY_ENTER }, /* OK */
{ 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */
{ 0x1e29, KEY_BLUE }, /* blue key */
{ 0x1e2e, KEY_GREEN }, /* green button */
{ 0x1e30, KEY_PAUSE }, /* pause */
{ 0x1e32, KEY_REWIND }, /* backward << */
{ 0x1e34, KEY_FASTFORWARD }, /* forward >> */
{ 0x1e35, KEY_PLAY },
{ 0x1e36, KEY_STOP },
{ 0x1e37, KEY_RECORD }, /* recording */
{ 0x1e38, KEY_YELLOW }, /* yellow key */
{ 0x1e3b, KEY_SELECT }, /* top right button */
{ 0x1e3c, KEY_ZOOM }, /* full */
{ 0x1e3d, KEY_POWER }, /* system power (green button) */
};
struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = {
.scan = ir_codes_rc5_hauppauge_new,
.size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new),
.ir_type = IR_TYPE_RC5,
};
EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table);
/* Terratec Cinergy Hybrid T USB XS FM
Mauro Carvalho Chehab <mchehab@redhat.com>
*/
static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = {
{ 0x1441, KEY_HOME},
{ 0x1401, KEY_POWER2},
{ 0x1442, KEY_MENU}, /* DVD menu */
{ 0x1443, KEY_SUBTITLE},
{ 0x1444, KEY_TEXT}, /* Teletext */
{ 0x1445, KEY_DELETE},
{ 0x1402, KEY_1},
{ 0x1403, KEY_2},
{ 0x1404, KEY_3},
{ 0x1405, KEY_4},
{ 0x1406, KEY_5},
{ 0x1407, KEY_6},
{ 0x1408, KEY_7},
{ 0x1409, KEY_8},
{ 0x140a, KEY_9},
{ 0x140c, KEY_0},
{ 0x140b, KEY_TUNER}, /* AV */
{ 0x140d, KEY_MODE}, /* A.B */
{ 0x1446, KEY_TV},
{ 0x1447, KEY_DVD},
{ 0x1449, KEY_VIDEO},
{ 0x144a, KEY_RADIO}, /* Music */
{ 0x144b, KEY_CAMERA}, /* PIC */
{ 0x1410, KEY_UP},
{ 0x1411, KEY_LEFT},
{ 0x1412, KEY_OK},
{ 0x1413, KEY_RIGHT},
{ 0x1414, KEY_DOWN},
{ 0x140f, KEY_EPG},
{ 0x1416, KEY_INFO},
{ 0x144d, KEY_BACKSPACE},
{ 0x141c, KEY_VOLUMEUP},
{ 0x141e, KEY_VOLUMEDOWN},
{ 0x144c, KEY_PLAY},
{ 0x141d, KEY_MUTE},
{ 0x141b, KEY_CHANNELUP},
{ 0x141f, KEY_CHANNELDOWN},
{ 0x1417, KEY_RED},
{ 0x1418, KEY_GREEN},
{ 0x1419, KEY_YELLOW},
{ 0x141a, KEY_BLUE},
{ 0x1458, KEY_RECORD},
{ 0x1448, KEY_STOP},
{ 0x1440, KEY_PAUSE},
{ 0x1454, KEY_LAST},
{ 0x144e, KEY_REWIND},
{ 0x144f, KEY_FASTFORWARD},
{ 0x145c, KEY_NEXT},
};
struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = {
.scan = ir_codes_nec_terratec_cinergy_xs,
.size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs),
.ir_type = IR_TYPE_NEC,
};
EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table);

View file

@ -1,10 +1,19 @@
/* ir-register.c - handle IR scancode->keycode tables
*
* Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/usb/input.h>
#include <linux/usb/input.h>
#include <media/ir-common.h>
#define IR_TAB_MIN_SIZE 32
@ -72,6 +81,7 @@ int ir_roundup_tablesize(int n_elems)
return n_elems;
}
EXPORT_SYMBOL_GPL(ir_roundup_tablesize);
/**
* ir_copy_table() - copies a keytable, discarding the unused entries
@ -100,6 +110,7 @@ int ir_copy_table(struct ir_scancode_table *destin,
return 0;
}
EXPORT_SYMBOL_GPL(ir_copy_table);
/**
* ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
@ -114,7 +125,8 @@ static int ir_getkeycode(struct input_dev *dev,
int scancode, int *keycode)
{
int elem;
struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
elem = ir_seek_table(rc_tab, scancode);
if (elem >= 0) {
@ -136,7 +148,6 @@ static int ir_getkeycode(struct input_dev *dev,
return 0;
}
/**
* ir_is_resize_needed() - Check if the table needs rezise
* @table: keycode table that may need to resize
@ -286,7 +297,8 @@ static int ir_setkeycode(struct input_dev *dev,
int scancode, int keycode)
{
int rc = 0;
struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
struct ir_scancode *keymap = rc_tab->scan;
unsigned long flags;
@ -360,7 +372,8 @@ static int ir_setkeycode(struct input_dev *dev,
*/
u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
{
struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
struct ir_scancode *keymap = rc_tab->scan;
int elem;
@ -378,9 +391,10 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
/* Reports userspace that an unknown keycode were got */
return KEY_RESERVED;
}
EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
/**
* ir_set_keycode_table() - sets the IR keycode table and add the handlers
* ir_input_register() - sets the IR keycode table and add the handlers
* for keymap table get/set
* @input_dev: the struct input_dev descriptor of the device
* @rc_tab: the struct ir_scancode_table table of scancode/keymap
@ -389,17 +403,34 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
* an IR.
* It should be called before registering the IR device.
*/
int ir_set_keycode_table(struct input_dev *input_dev,
struct ir_scancode_table *rc_tab)
int ir_input_register(struct input_dev *input_dev,
struct ir_scancode_table *rc_tab)
{
struct ir_scancode *keymap = rc_tab->scan;
int i;
spin_lock_init(&rc_tab->lock);
struct ir_input_dev *ir_dev;
struct ir_scancode *keymap = rc_tab->scan;
int i, rc;
if (rc_tab->scan == NULL || !rc_tab->size)
return -EINVAL;
ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
if (!ir_dev)
return -ENOMEM;
spin_lock_init(&rc_tab->lock);
ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size);
ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size *
sizeof(struct ir_scancode), GFP_KERNEL);
if (!ir_dev->rc_tab.scan)
return -ENOMEM;
IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
ir_dev->rc_tab.size,
ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan));
ir_copy_table(&ir_dev->rc_tab, rc_tab);
/* set the bits for the keys */
IR_dprintk(1, "key map size: %d\n", rc_tab->size);
for (i = 0; i < rc_tab->size; i++) {
@ -407,23 +438,48 @@ int ir_set_keycode_table(struct input_dev *input_dev,
i, keymap[i].keycode);
set_bit(keymap[i].keycode, input_dev->keybit);
}
clear_bit(0, input_dev->keybit);
set_bit(EV_KEY, input_dev->evbit);
input_dev->getkeycode = ir_getkeycode;
input_dev->setkeycode = ir_setkeycode;
input_set_drvdata(input_dev, rc_tab);
input_set_drvdata(input_dev, ir_dev);
return 0;
rc = input_register_device(input_dev);
if (rc < 0) {
kfree(rc_tab->scan);
kfree(ir_dev);
input_set_drvdata(input_dev, NULL);
}
return rc;
}
EXPORT_SYMBOL_GPL(ir_input_register);
void ir_input_free(struct input_dev *dev)
void ir_input_unregister(struct input_dev *dev)
{
struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab;
if (!ir_dev)
return;
IR_dprintk(1, "Freed keycode table\n");
rc_tab = &ir_dev->rc_tab;
rc_tab->size = 0;
kfree(rc_tab->scan);
rc_tab->scan = NULL;
}
EXPORT_SYMBOL_GPL(ir_input_free);
kfree(ir_dev);
input_unregister_device(dev);
}
EXPORT_SYMBOL_GPL(ir_input_unregister);
int ir_core_debug; /* ir_debug level (0,1,2) */
EXPORT_SYMBOL_GPL(ir_core_debug);
module_param_named(debug, ir_core_debug, int, 0644);
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_LICENSE("GPL");

View file

@ -99,6 +99,7 @@ config VIDEO_MEDIA
comment "Multimedia drivers"
source "drivers/media/common/Kconfig"
source "drivers/media/IR/Kconfig"
#
# Tuner drivers for DVB and V4L

View file

@ -2,7 +2,7 @@
# Makefile for the kernel multimedia device drivers.
#
obj-y += common/ video/
obj-y += common/ IR/ video/
obj-$(CONFIG_VIDEO_DEV) += radio/
obj-$(CONFIG_DVB_CORE) += dvb/

View file

@ -1,8 +1,6 @@
saa7146-objs := saa7146_i2c.o saa7146_core.o
saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
ir-common-objs := ir-functions.o ir-keymaps.o ir-keytable.o
obj-y += tuners/
obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
obj-$(CONFIG_VIDEO_IR) += ir-common.o

View file

@ -1,7 +1,5 @@
#include <media/saa7146_vv.h>
#define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
/****************************************************************************/
/* resource management functions, shamelessly stolen from saa7134 driver */
@ -194,43 +192,24 @@ void saa7146_buffer_timeout(unsigned long data)
static int fops_open(struct file *file)
{
unsigned int minor = video_devdata(file)->minor;
struct saa7146_dev *h = NULL, *dev = NULL;
struct list_head *list;
struct video_device *vdev = video_devdata(file);
struct saa7146_dev *dev = video_drvdata(file);
struct saa7146_fh *fh = NULL;
int result = 0;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
enum v4l2_buf_type type;
DEB_EE(("file:%p, minor:%d\n", file, minor));
DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
list_for_each(list,&saa7146_devices) {
h = list_entry(list, struct saa7146_dev, item);
if( NULL == h->vv_data ) {
DEB_D(("device %p has not registered video devices.\n",h));
continue;
}
DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor));
if (h->vv_data->video_minor == minor) {
dev = h;
}
if (h->vv_data->vbi_minor == minor) {
type = V4L2_BUF_TYPE_VBI_CAPTURE;
dev = h;
}
}
if (NULL == dev) {
DEB_S(("no such video device.\n"));
result = -ENODEV;
goto out;
}
DEB_D(("using: %p\n",dev));
type = vdev->vfl_type == VFL_TYPE_GRABBER
? V4L2_BUF_TYPE_VIDEO_CAPTURE
: V4L2_BUF_TYPE_VBI_CAPTURE;
/* check if an extension is registered */
if( NULL == dev->ext ) {
DEB_S(("no extension registered for this device.\n"));
@ -474,9 +453,6 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
configuration data) */
dev->ext_vv_data = ext_vv;
vv->video_minor = -1;
vv->vbi_minor = -1;
vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
if( NULL == vv->d_clipping.cpu_addr ) {
ERR(("out of memory. aborting.\n"));
@ -515,7 +491,6 @@ EXPORT_SYMBOL_GPL(saa7146_vv_release);
int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
char *name, int type)
{
struct saa7146_vv *vv = dev->vv_data;
struct video_device *vfd;
int err;
int i;
@ -543,15 +518,8 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
return err;
}
if( VFL_TYPE_GRABBER == type ) {
vv->video_minor = vfd->minor;
INFO(("%s: registered device video%d [v4l2]\n",
dev->name, vfd->num));
} else {
vv->vbi_minor = vfd->minor;
INFO(("%s: registered device vbi%d [v4l2]\n",
dev->name, vfd->num));
}
INFO(("%s: registered device %s [v4l2]\n",
dev->name, video_device_node_name(vfd)));
*vid = vfd;
return 0;
@ -560,16 +528,8 @@ EXPORT_SYMBOL_GPL(saa7146_register_device);
int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
{
struct saa7146_vv *vv = dev->vv_data;
DEB_EE(("dev:%p\n",dev));
if ((*vid)->vfl_type == VFL_TYPE_GRABBER) {
vv->video_minor = -1;
} else {
vv->vbi_minor = -1;
}
video_unregister_device(*vid);
*vid = NULL;

View file

@ -589,7 +589,7 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
"pci-%s/ir0", pci_name(dm1105->pdev));
err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes);
err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type);
if (err < 0) {
input_free_device(input_dev);
return err;
@ -611,20 +611,14 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
err = input_register_device(input_dev);
if (err) {
ir_input_free(input_dev);
input_free_device(input_dev);
return err;
}
err = ir_input_register(input_dev, ir_codes);
return 0;
return err;
}
void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
{
ir_input_free(dm1105->ir.input_dev);
input_unregister_device(dm1105->ir.input_dev);
ir_input_unregister(dm1105->ir.input_dev);
}
static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)

View file

@ -265,9 +265,13 @@ config DVB_USB_DW2102
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
select DVB_MT312 if !DVB_FE_CUSTOMISE
select DVB_ZL10039 if !DVB_FE_CUSTOMISE
select DVB_DS3000 if !DVB_FE_CUSTOMISE
select DVB_STB6100 if !DVB_FE_CUSTOMISE
select DVB_STV6110 if !DVB_FE_CUSTOMISE
select DVB_STV0900 if !DVB_FE_CUSTOMISE
help
Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
and the TeVii S650, S630.
Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0
receivers.
config DVB_USB_CINERGY_T2
tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"

View file

@ -20,20 +20,22 @@ extern int dvb_usb_dib0700_debug;
#define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args)
#define deb_data(args...) dprintk(dvb_usb_dib0700_debug,0x08,args)
#define REQUEST_I2C_READ 0x2
#define REQUEST_I2C_WRITE 0x3
#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */
#define REQUEST_JUMPRAM 0x8
#define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC
#define REQUEST_ENABLE_VIDEO 0xF
#define REQUEST_SET_USB_XFER_LEN 0x0 /* valid only for firmware version */
/* higher than 1.21 */
#define REQUEST_I2C_READ 0x2
#define REQUEST_I2C_WRITE 0x3
#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */
#define REQUEST_JUMPRAM 0x8
#define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC
#define REQUEST_ENABLE_VIDEO 0xF
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
#define REQUEST_SET_RC 0x11
#define REQUEST_NEW_I2C_READ 0x12
#define REQUEST_NEW_I2C_WRITE 0x13
#define REQUEST_GET_VERSION 0x15
#define REQUEST_SET_RC 0x11
#define REQUEST_NEW_I2C_READ 0x12
#define REQUEST_NEW_I2C_WRITE 0x13
#define REQUEST_GET_VERSION 0x15
struct dib0700_state {
u8 channel_state;
@ -44,6 +46,8 @@ struct dib0700_state {
u8 is_dib7000pc;
u8 fw_use_new_i2c_api;
u8 disable_streaming_master_mode;
u32 fw_version;
u32 nb_packet_buffer_size;
};
extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,

View file

@ -17,6 +17,14 @@ int dvb_usb_dib0700_ir_proto = 1;
module_param(dvb_usb_dib0700_ir_proto, int, 0644);
MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
static int nb_packet_buffer_size = 21;
module_param(nb_packet_buffer_size, int, 0644);
MODULE_PARM_DESC(nb_packet_buffer_size,
"Set the dib0700 driver data buffer size. This parameter "
"corresponds to the number of TS packets. The actual size of "
"the data buffer corresponds to this parameter "
"multiplied by 188 (default: 21)");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@ -28,10 +36,14 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
*hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
*romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
*ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
*fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
if (hwversion != NULL)
*hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
if (romversion != NULL)
*romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7];
if (ramversion != NULL)
*ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
if (fwtype != NULL)
*fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
return ret;
}
@ -97,6 +109,27 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
return dib0700_ctrl_wr(d,buf,3);
}
static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
{
struct dib0700_state *st = d->priv;
u8 b[3];
int ret;
if (st->fw_version >= 0x10201) {
b[0] = REQUEST_SET_USB_XFER_LEN;
b[1] = (nb_ts_packets >> 8)&0xff;
b[2] = nb_ts_packets & 0xff;
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
ret = dib0700_ctrl_wr(d, b, 3);
} else {
deb_info("this firmware does not allow to change the USB xfer len\n");
ret = -EIO;
}
return ret;
}
/*
* I2C master xfer function (supported in 1.20 firmware)
*/
@ -328,7 +361,9 @@ static int dib0700_jumpram(struct usb_device *udev, u32 address)
int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
{
struct hexline hx;
int pos = 0, ret, act_len;
int pos = 0, ret, act_len, i, adap_num;
u8 b[16];
u32 fw_version;
u8 buf[260];
@ -364,6 +399,34 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
} else
ret = -EIO;
/* the number of ts packet has to be at least 1 */
if (nb_packet_buffer_size < 1)
nb_packet_buffer_size = 1;
/* get the fimware version */
usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
/* set the buffer size - DVB-USB is allocating URB buffers
* only after the firwmare download was successful */
for (i = 0; i < dib0700_device_count; i++) {
for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
adap_num++) {
if (fw_version >= 0x10201)
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
else {
/* for fw version older than 1.20.1,
* the buffersize has to be n times 512 */
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
}
}
}
return ret;
}
@ -371,6 +434,18 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
struct dib0700_state *st = adap->dev->priv;
u8 b[4];
int ret;
if ((onoff != 0) && (st->fw_version >= 0x10201)) {
/* for firmware later than 1.20.1,
* the USB xfer length can be set */
ret = dib0700_set_usb_xfer_len(adap->dev,
st->nb_packet_buffer_size);
if (ret < 0) {
deb_info("can not set the USB xfer len\n");
return ret;
}
}
b[0] = REQUEST_ENABLE_VIDEO;
b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
@ -415,9 +490,21 @@ static int dib0700_probe(struct usb_interface *intf,
for (i = 0; i < dib0700_device_count; i++)
if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
&dev, adapter_nr) == 0)
{
&dev, adapter_nr) == 0) {
struct dib0700_state *st = dev->priv;
u32 hwversion, romversion, fw_version, fwtype;
dib0700_get_version(dev, &hwversion, &romversion,
&fw_version, &fwtype);
deb_info("Firmware version: %x, %d, 0x%x, %d\n",
hwversion, romversion, fw_version, fwtype);
st->fw_version = fw_version;
st->nb_packet_buffer_size = (u32)nb_packet_buffer_size;
dib0700_rc_setup(dev);
return 0;
}

View file

@ -18,6 +18,7 @@
#include "xc5000.h"
#include "s5h1411.h"
#include "dib0070.h"
#include "dib0090.h"
#include "lgdt3305.h"
#include "mxl5007t.h"
@ -130,93 +131,95 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
/* MT226x */
static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = {
{
BAND_UHF, // band_caps
BAND_UHF,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
1130, // inv_gain
21, // time_stabiliz
1130,
21,
0, // alpha_level
118, // thlock
0,
118,
0, // wbd_inv
3530, // wbd_ref
1, // wbd_sel
0, // wbd_alpha
0,
3530,
1,
0,
65535, // agc1_max
33770, // agc1_min
65535, // agc2_max
23592, // agc2_min
65535,
33770,
65535,
23592,
0, // agc1_pt1
62, // agc1_pt2
255, // agc1_pt3
64, // agc1_slope1
64, // agc1_slope2
132, // agc2_pt1
192, // agc2_pt2
80, // agc2_slope1
80, // agc2_slope2
0,
62,
255,
64,
64,
132,
192,
80,
80,
17, // alpha_mant
27, // alpha_exp
23, // beta_mant
51, // beta_exp
17,
27,
23,
51,
1, // perform_agc_softsplit
1,
}, {
BAND_VHF | BAND_LBAND, // band_caps
BAND_VHF | BAND_LBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
2372, // inv_gain
21, // time_stabiliz
2372,
21,
0, // alpha_level
118, // thlock
0,
118,
0, // wbd_inv
3530, // wbd_ref
1, // wbd_sel
0, // wbd_alpha
0,
3530,
1,
0,
65535, // agc1_max
0, // agc1_min
65535, // agc2_max
23592, // agc2_min
65535,
0,
65535,
23592,
0, // agc1_pt1
128, // agc1_pt2
128, // agc1_pt3
128, // agc1_slope1
0, // agc1_slope2
128, // agc2_pt1
253, // agc2_pt2
81, // agc2_slope1
0, // agc2_slope2
0,
128,
128,
128,
0,
128,
253,
81,
0,
17, // alpha_mant
27, // alpha_exp
23, // beta_mant
51, // beta_exp
17,
27,
23,
51,
1, // perform_agc_softsplit
1,
}
};
static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = {
60000, 30000, // internal, sampling
1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
0, // ifreq
20452225, // timf
60000, 30000,
1, 8, 3, 1, 0,
0, 0, 1, 1, 2,
(3 << 14) | (1 << 12) | (524 << 0),
0,
20452225,
};
static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = {
@ -605,17 +608,17 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
}
break;
default:
if (actlen != sizeof(buf)) {
/* We didn't get back the 6 byte message we expected */
err("Unexpected RC response size [%d]", actlen);
return -1;
}
if (actlen != sizeof(buf)) {
/* We didn't get back the 6 byte message we expected */
err("Unexpected RC response size [%d]", actlen);
return -1;
}
poll_reply.report_id = buf[0];
poll_reply.data_state = buf[1];
poll_reply.report_id = buf[0];
poll_reply.data_state = buf[1];
poll_reply.system = (buf[2] << 8) | buf[3];
poll_reply.data = buf[4];
poll_reply.not_data = buf[5];
poll_reply.data = buf[4];
poll_reply.not_data = buf[5];
break;
}
@ -632,7 +635,7 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
/* Find the key in the map */
for (i = 0; i < d->props.rc_key_map_size; i++) {
if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
rc5_data(&keymap[i]) == poll_reply.data) {
rc5_data(&keymap[i]) == poll_reply.data) {
*event = keymap[i].event;
found = 1;
break;
@ -641,8 +644,8 @@ static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
if (found == 0) {
err("Unknown remote controller key: %04x %02x %02x",
poll_reply.system,
poll_reply.data, poll_reply.not_data);
poll_reply.system,
poll_reply.data, poll_reply.not_data);
d->last_event = 0;
return 0;
}
@ -933,47 +936,48 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = {
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
BAND_UHF | BAND_VHF, // band_caps
BAND_UHF | BAND_VHF,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
712, // inv_gain
41, // time_stabiliz
712,
41,
0, // alpha_level
118, // thlock
0,
118,
0, // wbd_inv
4095, // wbd_ref
0, // wbd_sel
0, // wbd_alpha
0,
4095,
0,
0,
42598, // agc1_max
17694, // agc1_min
45875, // agc2_max
2621, // agc2_min
0, // agc1_pt1
76, // agc1_pt2
139, // agc1_pt3
52, // agc1_slope1
59, // agc1_slope2
107, // agc2_pt1
172, // agc2_pt2
57, // agc2_slope1
70, // agc2_slope2
42598,
17694,
45875,
2621,
0,
76,
139,
52,
59,
107,
172,
57,
70,
21, // alpha_mant
25, // alpha_exp
28, // beta_mant
48, // beta_exp
21,
25,
28,
48,
1, // perform_agc_softsplit
{ 0, // split_min
107, // split_max
51800, // global_split_min
24700 // global_split_max
1,
{ 0,
107,
51800,
24700
},
};
@ -982,54 +986,55 @@ static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
712, // inv_gain
41, // time_stabiliz
712,
41,
0, // alpha_level
118, // thlock
0,
118,
0, // wbd_inv
4095, // wbd_ref
0, // wbd_sel
0, // wbd_alpha
0,
4095,
0,
0,
42598, // agc1_max
16384, // agc1_min
42598, // agc2_max
0, // agc2_min
42598,
16384,
42598,
0,
0, // agc1_pt1
137, // agc1_pt2
255, // agc1_pt3
0,
137,
255,
0, // agc1_slope1
255, // agc1_slope2
0,
255,
0, // agc2_pt1
0, // agc2_pt2
0,
0,
0, // agc2_slope1
41, // agc2_slope2
0,
41,
15, // alpha_mant
25, // alpha_exp
15,
25,
28, // beta_mant
48, // beta_exp
28,
48,
0, // perform_agc_softsplit
0,
};
static struct dibx000_bandwidth_config stk7700p_pll_config = {
60000, 30000, // internal, sampling
1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
60258167, // ifreq
20452225, // timf
30000000, // xtal
60000, 30000,
1, 8, 3, 1, 0,
0, 0, 1, 1, 0,
(3 << 14) | (1 << 12) | (524 << 0),
60258167,
20452225,
30000000,
};
static struct dib7000m_config stk7700p_dib7000m_config = {
@ -1115,41 +1120,42 @@ static struct dibx000_agc_config dib7070_agc_config = {
BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
600, // inv_gain
10, // time_stabiliz
600,
10,
0, // alpha_level
118, // thlock
0,
118,
0, // wbd_inv
3530, // wbd_ref
1, // wbd_sel
5, // wbd_alpha
0,
3530,
1,
5,
65535, // agc1_max
0, // agc1_min
65535,
0,
65535, // agc2_max
0, // agc2_min
65535,
0,
0, // agc1_pt1
40, // agc1_pt2
183, // agc1_pt3
206, // agc1_slope1
255, // agc1_slope2
72, // agc2_pt1
152, // agc2_pt2
88, // agc2_slope1
90, // agc2_slope2
0,
40,
183,
206,
255,
72,
152,
88,
90,
17, // alpha_mant
27, // alpha_exp
23, // beta_mant
51, // beta_exp
17,
27,
23,
51,
0, // perform_agc_softsplit
0,
};
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
@ -1276,13 +1282,13 @@ static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
}
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
60000, 15000, // internal, sampling
1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
(0 << 25) | 0, // ifreq = 0.000000 MHz
20452225, // timf
12000000, // xtal_hz
60000, 15000,
1, 20, 3, 1, 0,
0, 0, 1, 1, 2,
(3 << 14) | (1 << 12) | (524 << 0),
(0 << 25) | 0,
20452225,
12000000,
};
static struct dib7000p_config dib7070p_dib7000p_config = {
@ -1476,12 +1482,12 @@ static struct dib8000_config dib807x_dib8000_config[2] = {
}
};
static int dib807x_tuner_reset(struct dvb_frontend *fe, int onoff)
static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
{
return dib8000_set_gpio(fe, 5, 0, !onoff);
}
static int dib807x_tuner_sleep(struct dvb_frontend *fe, int onoff)
static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
return dib8000_set_gpio(fe, 0, 0, onoff);
}
@ -1494,8 +1500,8 @@ static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = {
static struct dib0070_config dib807x_dib0070_config[2] = {
{
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
.reset = dib807x_tuner_reset,
.sleep = dib807x_tuner_sleep,
.reset = dib80xx_tuner_reset,
.sleep = dib80xx_tuner_sleep,
.clock_khz = 12000,
.clock_pad_drive = 4,
.vga_filter = 1,
@ -1508,8 +1514,8 @@ static struct dib0070_config dib807x_dib0070_config[2] = {
.freq_offset_khz_vhf = -100,
}, {
.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
.reset = dib807x_tuner_reset,
.sleep = dib807x_tuner_sleep,
.reset = dib80xx_tuner_reset,
.sleep = dib80xx_tuner_sleep,
.clock_khz = 12000,
.clock_pad_drive = 2,
.vga_filter = 1,
@ -1566,12 +1572,14 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
static int stk807x_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
return dib8000_pid_filter(adapter->fe, index, pid, onoff);
}
static int stk807x_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
int onoff)
{
return dib8000_pid_filter_ctrl(adapter->fe, onoff);
}
@ -1624,7 +1632,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
/* initialize IC 0 */
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x80);
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
@ -1635,7 +1643,7 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
{
/* initialize IC 1 */
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x82);
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
&dib807x_dib8000_config[1]);
@ -1643,6 +1651,245 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
return adap->fe == NULL ? -ENODEV : 0;
}
/* STK8096GP */
struct dibx000_agc_config dib8090_agc_config[2] = {
{
BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
787,
10,
0,
118,
0,
3530,
1,
5,
65535,
0,
65535,
0,
0,
32,
114,
143,
144,
114,
227,
116,
117,
28,
26,
31,
51,
0,
},
{
BAND_CBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
787,
10,
0,
118,
0,
3530,
1,
5,
0,
0,
65535,
0,
0,
32,
114,
143,
144,
114,
227,
116,
117,
28,
26,
31,
51,
0,
}
};
static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
54000, 13500,
1, 18, 3, 1, 0,
0, 0, 1, 1, 2,
(3 << 14) | (1 << 12) | (599 << 0),
(0 << 25) | 0,
20199727,
12000000,
};
static int dib8090_get_adc_power(struct dvb_frontend *fe)
{
return dib8000_get_adc_power(fe, 1);
}
static struct dib8000_config dib809x_dib8000_config = {
.output_mpeg2_in_188_bytes = 1,
.agc_config_count = 2,
.agc = dib8090_agc_config,
.agc_control = dib0090_dcc_freq,
.pll = &dib8090_pll_config_12mhz,
.tuner_is_baseband = 1,
.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
.hostbus_diversity = 1,
.div_cfg = 0x31,
.output_mode = OUTMODE_MPEG2_FIFO,
.drives = 0x2d98,
.diversity_delay = 144,
.refclksel = 3,
};
static struct dib0090_config dib809x_dib0090_config = {
.io.pll_bypass = 1,
.io.pll_range = 1,
.io.pll_prediv = 1,
.io.pll_loopdiv = 20,
.io.adc_clock_ratio = 8,
.io.pll_int_loop_filt = 0,
.io.clock_khz = 12000,
.reset = dib80xx_tuner_reset,
.sleep = dib80xx_tuner_sleep,
.clkouttobamse = 1,
.analog_output = 1,
.i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
.wbd_vhf_offset = 100,
.wbd_cband_offset = 450,
.use_pwm_agc = 1,
.clkoutdrive = 1,
.get_adc_power = dib8090_get_adc_power,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = -143,
};
static int dib8096_set_param_override(struct dvb_frontend *fe,
struct dvb_frontend_parameters *fep)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
u16 offset;
int ret = 0;
enum frontend_tune_state tune_state = CT_SHUTDOWN;
u16 ltgain, rf_gain_limit;
ret = state->set_param_save(fe, fep);
if (ret < 0)
return ret;
switch (band) {
case BAND_VHF:
offset = 100;
break;
case BAND_UHF:
offset = 550;
break;
default:
offset = 0;
break;
}
offset += (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
dib8000_set_wbd_ref(fe, offset);
if (band == BAND_CBAND) {
deb_info("tuning in CBAND - soft-AGC startup\n");
/* TODO specific wbd target for dib0090 - needed for startup ? */
dib0090_set_tune_state(fe, CT_AGC_START);
do {
ret = dib0090_gain_control(fe);
msleep(ret);
tune_state = dib0090_get_tune_state(fe);
if (tune_state == CT_AGC_STEP_0)
dib8000_set_gpio(fe, 6, 0, 1);
else if (tune_state == CT_AGC_STEP_1) {
dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
if (rf_gain_limit == 0)
dib8000_set_gpio(fe, 6, 0, 0);
}
} while (tune_state < CT_AGC_STOP);
dib0090_pwm_gain_reset(fe);
dib8000_pwm_agc_reset(fe);
dib8000_set_tune_state(fe, CT_DEMOD_START);
} else {
deb_info("not tuning in CBAND - standard AGC startup\n");
dib0090_pwm_gain_reset(fe);
}
return 0;
}
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
st->set_param_save = adap->fe->ops.tuner_ops.set_params;
adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
return 0;
}
static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
{
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
dib0700_ctrl_clock(adap->dev, 72, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config);
return adap->fe == NULL ? -ENODEV : 0;
}
/* STK7070PD */
static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
@ -1929,14 +2176,17 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D) },
/* 55 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_STK7700D_2) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73A) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) },
{ USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV73ESE) },
{ USB_DEVICE(USB_VID_PCTV, USB_PID_PINNACLE_PCTV282E) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7770P) },
/* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) },
{ USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) },
{ USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
/* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) },
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK8096GP) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@ -2238,11 +2488,11 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ NULL },
},
{ "Pinnacle PCTV 73e SE",
{ &dib0700_usb_id_table[57], NULL },
{ &dib0700_usb_id_table[57], &dib0700_usb_id_table[65], NULL },
{ NULL },
},
{ "Pinnacle PCTV 282e",
{ &dib0700_usb_id_table[58], NULL },
{ &dib0700_usb_id_table[58], &dib0700_usb_id_table[66], NULL },
{ NULL },
},
},
@ -2471,8 +2721,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk807x_pid_filter,
.pid_filter_ctrl = stk807x_pid_filter_ctrl,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk807x_frontend_attach,
.tuner_attach = dib807x_tuner_attach,
@ -2510,8 +2760,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk807x_pid_filter,
.pid_filter_ctrl = stk807x_pid_filter_ctrl,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk807xpvr_frontend_attach0,
.tuner_attach = dib807x_tuner_attach,
@ -2523,8 +2773,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk807x_pid_filter,
.pid_filter_ctrl = stk807x_pid_filter_ctrl,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk807xpvr_frontend_attach1,
.tuner_attach = dib807x_tuner_attach,
@ -2543,6 +2793,37 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
.rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
.adapter = {
{
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
.pid_filter_count = 32,
.pid_filter = stk80xx_pid_filter,
.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
.frontend_attach = stk809x_frontend_attach,
.tuner_attach = dib809x_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv =
sizeof(struct dib0700_adapter_state),
},
},
.num_device_descs = 1,
.devices = {
{ "DiBcom STK8096GP reference design",
{ &dib0700_usb_id_table[67], NULL },
{ NULL },
},
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),

View file

@ -142,8 +142,13 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
} else if ((msg[i].flags & I2C_M_RD) == 0) {
if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
break;
} else
break;
} else if (msg[i].addr != 0x50) {
/* 0x50 is the address of the eeprom - we need to protect it
* from dibusb's bad i2c implementation: reads without
* writing the offset before are forbidden */
if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0)
break;
}
}
mutex_unlock(&d->i2c_mutex);
@ -243,6 +248,12 @@ static struct dib3000mc_config mod3000p_dib3000p_config = {
int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
{
if (adap->dev->udev->descriptor.idVendor == USB_VID_LITEON &&
adap->dev->udev->descriptor.idProduct ==
USB_PID_LITEON_DVB_T_WARM) {
msleep(1000);
}
if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL ||
(adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
if (adap->priv != NULL) {

View file

@ -47,6 +47,7 @@
#define USB_VID_MSI_2 0x1462
#define USB_VID_OPERA1 0x695c
#define USB_VID_PINNACLE 0x2304
#define USB_VID_PCTV 0x2013
#define USB_VID_PIXELVIEW 0x1554
#define USB_VID_TECHNOTREND 0x0b48
#define USB_VID_TERRATEC 0x0ccd
@ -101,6 +102,7 @@
#define USB_PID_DIBCOM_STK7070PD 0x1ebe
#define USB_PID_DIBCOM_STK807XP 0x1f90
#define USB_PID_DIBCOM_STK807XPVR 0x1f98
#define USB_PID_DIBCOM_STK8096GP 0x1fa0
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
#define USB_PID_DIBCOM_STK7770P 0x1e80
#define USB_PID_DPOSH_M9206_COLD 0x9206
@ -211,6 +213,7 @@
#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
#define USB_PID_PINNACLE_PCTV73A 0x0243
#define USB_PID_PINNACLE_PCTV73ESE 0x0245
#define USB_PID_PINNACLE_PCTV74E 0x0246
#define USB_PID_PINNACLE_PCTV282E 0x0248
#define USB_PID_PIXELVIEW_SBTVD 0x5010
#define USB_PID_PCTV_200E 0x020e

View file

@ -20,6 +20,11 @@
#include "tda1002x.h"
#include "mt312.h"
#include "zl10039.h"
#include "ds3000.h"
#include "stv0900.h"
#include "stv6110.h"
#include "stb6100.h"
#include "stb6100_proc.h"
#ifndef USB_PID_DW2102
#define USB_PID_DW2102 0x2102
@ -37,12 +42,20 @@
#define USB_PID_CINERGY_S 0x0064
#endif
#ifndef USB_PID_TEVII_S630
#define USB_PID_TEVII_S630 0xd630
#endif
#ifndef USB_PID_TEVII_S650
#define USB_PID_TEVII_S650 0xd650
#endif
#ifndef USB_PID_TEVII_S630
#define USB_PID_TEVII_S630 0xd630
#ifndef USB_PID_TEVII_S660
#define USB_PID_TEVII_S660 0xd660
#endif
#ifndef USB_PID_PROF_1100
#define USB_PID_PROF_1100 0xb012
#endif
#define DW210X_READ_MSG 0
@ -55,6 +68,10 @@
#define DW2102_VOLTAGE_CTRL (0x1800)
#define DW2102_RC_QUERY (0x1a00)
#define err_str "did not find the firmware file. (%s) " \
"Please see linux/Documentation/dvb/ for more details " \
"on firmware-problems."
struct dvb_usb_rc_keys_table {
struct dvb_usb_rc_key *rc_keys;
int rc_keys_size;
@ -71,6 +88,12 @@ static int ir_keymap;
module_param_named(keymap, ir_keymap, int, 0644);
MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs ...");
/* demod probe */
static int demod_probe = 1;
module_param_named(demod, demod_probe, int, 0644);
MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
"4=stv0903+stb6100(or-able)).");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
@ -183,7 +206,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
switch (num) {
case 2:
/* read si2109 register by number */
buf6[0] = 0xd0;
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
buf6[2] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@ -198,7 +221,7 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
switch (msg[0].addr) {
case 0x68:
/* write to si2109 register */
buf6[0] = 0xd0;
buf6[0] = msg[0].addr << 1;
buf6[1] = msg[0].len;
memcpy(buf6 + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
@ -239,7 +262,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
/* read */
/* first write first register number */
u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xd0;
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@ -256,7 +279,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case 0x68: {
/* write to register */
u8 obuf[msg[0].len + 2];
obuf[0] = 0xd0;
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@ -266,7 +289,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case 0x61: {
/* write to tuner */
u8 obuf[msg[0].len + 2];
obuf[0] = 0xc2;
obuf[0] = msg[0].addr << 1;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@ -301,78 +324,78 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int ret = 0;
int len, i;
int len, i, j;
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2: {
/* read */
/* first write first register number */
u8 ibuf[msg[1].len + 2], obuf[3];
obuf[0] = 0xaa;
obuf[1] = msg[0].len;
obuf[2] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
/* second read registers */
ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0,
ibuf, msg[1].len + 2, DW210X_READ_MSG);
memcpy(msg[1].buf, ibuf + 2, msg[1].len);
break;
}
case 1:
switch (msg[0].addr) {
case 0x55: {
if (msg[0].buf[0] == 0xf7) {
/* firmware */
/* Write in small blocks */
u8 obuf[19];
obuf[0] = 0xaa;
obuf[1] = 0x11;
obuf[2] = 0xf7;
len = msg[0].len - 1;
i = 1;
do {
memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len));
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG);
i += 16;
len -= 16;
} while (len > 0);
} else {
/* write to register */
u8 obuf[msg[0].len + 2];
obuf[0] = 0xaa;
obuf[1] = msg[0].len;
memcpy(obuf + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
}
break;
}
for (j = 0; j < num; j++) {
switch (msg[j].addr) {
case(DW2102_RC_QUERY): {
u8 ibuf[2];
ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[0].buf, ibuf , 2);
memcpy(msg[j].buf, ibuf , 2);
break;
}
case(DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
obuf[0] = 0x30;
obuf[1] = msg[0].buf[0];
obuf[1] = msg[j].buf[0];
ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
/*case 0x55: cx24116
case 0x6a: stv0903
case 0x68: ds3000, stv0903
case 0x60: ts2020, stv6110, stb6100 */
default: {
if (msg[j].flags == I2C_M_RD) {
/* read registers */
u8 ibuf[msg[j].len + 2];
ret = dw210x_op_rw(d->udev, 0xc3,
(msg[j].addr << 1) + 1, 0,
ibuf, msg[j].len + 2,
DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf + 2, msg[j].len);
mdelay(10);
} else if (((msg[j].buf[0] == 0xb0) &&
(msg[j].addr == 0x68)) ||
((msg[j].buf[0] == 0xf7) &&
(msg[j].addr == 0x55))) {
/* write firmware */
u8 obuf[19];
obuf[0] = msg[j].addr << 1;
obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
obuf[2] = msg[j].buf[0];
len = msg[j].len - 1;
i = 1;
do {
memcpy(obuf + 3, msg[j].buf + i,
(len > 16 ? 16 : len));
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, (len > 16 ? 16 : len) + 3,
DW210X_WRITE_MSG);
i += 16;
len -= 16;
} while (len > 0);
} else {
/* write registers */
u8 obuf[msg[j].len + 2];
obuf[0] = msg[j].addr << 1;
obuf[1] = msg[j].len;
memcpy(obuf + 2, msg[j].buf, msg[j].len);
ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
obuf, msg[j].len + 2,
DW210X_WRITE_MSG);
}
break;
}
}
break;
}
mutex_unlock(&d->i2c_mutex);
@ -442,63 +465,85 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
return num;
}
static int s630_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int ret = 0;
int len, i, j;
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2: { /* read */
u8 ibuf[msg[1].len], obuf[3];
obuf[0] = msg[1].len;
obuf[1] = (msg[0].addr << 1);
obuf[2] = msg[0].buf[0];
ret = dw210x_op_rw(d->udev, 0x90, 0, 0,
obuf, 3, DW210X_WRITE_MSG);
msleep(5);
ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
ibuf, msg[1].len, DW210X_READ_MSG);
memcpy(msg[1].buf, ibuf, msg[1].len);
break;
}
case 1:
switch (msg[0].addr) {
case 0x60:
case 0x0e: {
/* write to zl10313, zl10039 register, */
u8 obuf[msg[0].len + 2];
obuf[0] = msg[0].len + 1;
obuf[1] = (msg[0].addr << 1);
memcpy(obuf + 2, msg[0].buf, msg[0].len);
ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
obuf, msg[0].len + 2, DW210X_WRITE_MSG);
break;
}
for (j = 0; j < num; j++) {
switch (msg[j].addr) {
case (DW2102_RC_QUERY): {
u8 ibuf[4];
ret = dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 4, DW210X_READ_MSG);
msg[0].buf[0] = ibuf[3];
memcpy(msg[j].buf, ibuf + 1, 2);
break;
}
case (DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
obuf[0] = 0x03;
obuf[1] = msg[0].buf[0];
obuf[0] = 3;
obuf[1] = msg[j].buf[0];
ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
obuf, 2, DW210X_WRITE_MSG);
break;
}
/*case 0x55: cx24116
case 0x6a: stv0903
case 0x68: ds3000, stv0903
case 0x60: ts2020, stv6110, stb6100
case 0xa0: eeprom */
default: {
if (msg[j].flags == I2C_M_RD) {
/* read registers */
u8 ibuf[msg[j].len];
ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
ibuf, msg[j].len,
DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf, msg[j].len);
break;
} else if ((msg[j].buf[0] == 0xb0) &&
(msg[j].addr == 0x68)) {
/* write firmware */
u8 obuf[19];
obuf[0] = (msg[j].len > 16 ?
18 : msg[j].len + 1);
obuf[1] = msg[j].addr << 1;
obuf[2] = msg[j].buf[0];
len = msg[j].len - 1;
i = 1;
do {
memcpy(obuf + 3, msg[j].buf + i,
(len > 16 ? 16 : len));
ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
obuf, (len > 16 ? 16 : len) + 3,
DW210X_WRITE_MSG);
i += 16;
len -= 16;
} while (len > 0);
} else {
/* write registers */
u8 obuf[msg[j].len + 2];
obuf[0] = msg[j].len + 1;
obuf[1] = (msg[j].addr << 1);
memcpy(obuf + 2, msg[j].buf, msg[j].len);
ret = dw210x_op_rw(d->udev,
(num > 1 ? 0x90 : 0x80), 0, 0,
obuf, msg[j].len + 2,
DW210X_WRITE_MSG);
break;
}
break;
}
}
break;
msleep(3);
}
mutex_unlock(&d->i2c_mutex);
@ -535,8 +580,8 @@ static struct i2c_algorithm dw3101_i2c_algo = {
.functionality = dw210x_i2c_func,
};
static struct i2c_algorithm s630_i2c_algo = {
.master_xfer = s630_i2c_transfer,
static struct i2c_algorithm s6x0_i2c_algo = {
.master_xfer = s6x0_i2c_transfer,
.functionality = dw210x_i2c_func,
};
@ -564,25 +609,34 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
return 0;
};
static int s630_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i, ret;
u8 buf[3], eeprom[256], eepromline[16];
u8 ibuf[] = { 0 }, obuf[] = { 0 };
u8 eeprom[256], eepromline[16];
struct i2c_msg msg[] = {
{
.addr = 0xa0 >> 1,
.flags = 0,
.buf = obuf,
.len = 1,
}, {
.addr = 0xa0 >> 1,
.flags = I2C_M_RD,
.buf = ibuf,
.len = 1,
}
};
for (i = 0; i < 256; i++) {
buf[0] = 1;
buf[1] = 0xa0;
buf[2] = i;
ret = dw210x_op_rw(d->udev, 0x90, 0, 0,
buf, 3, DW210X_WRITE_MSG);
ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
buf, 1, DW210X_READ_MSG);
if (ret < 0) {
obuf[0] = i;
ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
if (ret != 2) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i % 16] = buf[0];
eeprom[i] = buf[0];
eepromline[i % 16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
@ -644,19 +698,104 @@ static struct mt312_config zl313_config = {
.demod_address = 0x0e,
};
static struct ds3000_config dw2104_ds3000_config = {
.demod_address = 0x68,
};
static struct stv0900_config dw2104a_stv0900_config = {
.demod_address = 0x6a,
.demod_mode = 0,
.xtal = 27000000,
.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
.diseqc_mode = 2,/* 2/3 PWM */
.tun1_maddress = 0,/* 0x60 */
.tun1_adc = 0,/* 2 Vpp */
.path1_mode = 3,
};
static struct stb6100_config dw2104a_stb6100_config = {
.tuner_address = 0x60,
.refclock = 27000000,
};
static struct stv0900_config dw2104_stv0900_config = {
.demod_address = 0x68,
.demod_mode = 0,
.xtal = 8000000,
.clkmode = 3,
.diseqc_mode = 2,
.tun1_maddress = 0,
.tun1_adc = 1,/* 1 Vpp */
.path1_mode = 3,
};
static struct stv6110_config dw2104_stv6110_config = {
.i2c_address = 0x60,
.mclk = 16000000,
.clk_div = 1,
};
static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
{
if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
&d->dev->i2c_adap)) != NULL) {
struct dvb_tuner_ops *tuner_ops = NULL;
if (demod_probe & 4) {
d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
&d->dev->i2c_adap, 0);
if (d->fe != NULL) {
if (dvb_attach(stb6100_attach, d->fe,
&dw2104a_stb6100_config,
&d->dev->i2c_adap)) {
tuner_ops = &d->fe->ops.tuner_ops;
tuner_ops->set_frequency = stb6100_set_freq;
tuner_ops->get_frequency = stb6100_get_freq;
tuner_ops->set_bandwidth = stb6100_set_bandw;
tuner_ops->get_bandwidth = stb6100_get_bandw;
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached STV0900+STB6100!\n");
return 0;
}
}
}
if (demod_probe & 2) {
d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
&d->dev->i2c_adap, 0);
if (d->fe != NULL) {
if (dvb_attach(stv6110_attach, d->fe,
&dw2104_stv6110_config,
&d->dev->i2c_adap)) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached STV0900+STV6110A!\n");
return 0;
}
}
}
if (demod_probe & 1) {
d->fe = dvb_attach(cx24116_attach, &dw2104_config,
&d->dev->i2c_adap);
if (d->fe != NULL) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached cx24116!\n");
return 0;
}
}
d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
&d->dev->i2c_adap);
if (d->fe != NULL) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached cx24116!\n");
info("Attached DS3000!\n");
return 0;
}
return -EIO;
}
static struct dvb_usb_device_properties dw2102_properties;
static struct dvb_usb_device_properties dw2104_properties;
static struct dvb_usb_device_properties s6x0_properties;
static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
{
@ -670,14 +809,17 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
return 0;
}
}
if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
d->fe = dvb_attach(stv0288_attach, &earda_config,
&d->dev->i2c_adap);
if (d->fe != NULL) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0288!\n");
return 0;
if (dvb_attach(stb6000_attach, d->fe, 0x61,
&d->dev->i2c_adap)) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0288!\n");
return 0;
}
}
}
@ -705,15 +847,38 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
return -EIO;
}
static int s630_frontend_attach(struct dvb_usb_adapter *d)
static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
{
d->fe = dvb_attach(mt312_attach, &zl313_config,
&d->dev->i2c_adap);
&d->dev->i2c_adap);
if (d->fe != NULL) {
if (dvb_attach(zl10039_attach, d->fe, 0x60,
&d->dev->i2c_adap)) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached zl100313+zl10039!\n");
return 0;
}
}
d->fe = dvb_attach(stv0288_attach, &earda_config,
&d->dev->i2c_adap);
if (d->fe != NULL) {
if (dvb_attach(stb6000_attach, d->fe, 0x61,
&d->dev->i2c_adap)) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached stv0288+stb6000!\n");
return 0;
}
}
d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
&d->dev->i2c_adap);
if (d->fe != NULL) {
d->fe->ops.set_voltage = dw210x_set_voltage;
info("Attached zl10313!\n");
info("Attached ds3000+ds2020!\n");
return 0;
}
return -EIO;
}
@ -724,14 +889,6 @@ static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(stb6000_attach, adap->fe, 0x61,
&adap->dev->i2c_adap);
return 0;
}
static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@ -740,14 +897,6 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap)
{
dvb_attach(zl10039_attach, adap->fe, 0x60,
&adap->dev->i2c_adap);
return 0;
}
static struct dvb_usb_rc_key dw210x_rc_keys[] = {
{ 0xf80a, KEY_Q }, /*power*/
{ 0xf80c, KEY_M }, /*mute*/
@ -922,6 +1071,8 @@ static struct usb_device_id dw2102_table[] = {
{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
{USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
{USB_DEVICE(0x3011, USB_PID_PROF_1100)},
{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
{ }
};
@ -935,15 +1086,13 @@ static int dw2102_load_firmware(struct usb_device *dev,
u8 reset;
u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
const struct firmware *fw;
const char *filename = "dvb-usb-dw2101.fw";
const char *fw_2101 = "dvb-usb-dw2101.fw";
switch (dev->descriptor.idProduct) {
case 0x2101:
ret = request_firmware(&fw, filename, &dev->dev);
ret = request_firmware(&fw, fw_2101, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", filename);
err(err_str, fw_2101);
return ret;
}
break;
@ -983,6 +1132,11 @@ static int dw2102_load_firmware(struct usb_device *dev,
}
/* init registers */
switch (dev->descriptor.idProduct) {
case USB_PID_PROF_1100:
s6x0_properties.rc_key_map = tbs_rc_keys;
s6x0_properties.rc_key_map_size =
ARRAY_SIZE(tbs_rc_keys);
break;
case USB_PID_TEVII_S650:
dw2104_properties.rc_key_map = tevii_rc_keys;
dw2104_properties.rc_key_map_size =
@ -1021,7 +1175,6 @@ static int dw2102_load_firmware(struct usb_device *dev,
DW210X_READ_MSG);
if (reset16[2] == 0x11) {
dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach;
break;
}
}
@ -1184,13 +1337,13 @@ static struct dvb_usb_device_properties dw3101_properties = {
}
};
static struct dvb_usb_device_properties s630_properties = {
static struct dvb_usb_device_properties s6x0_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-s630.fw",
.no_reconnect = 1,
.i2c_algo = &s630_i2c_algo,
.i2c_algo = &s6x0_i2c_algo,
.rc_key_map = tevii_rc_keys,
.rc_key_map_size = ARRAY_SIZE(tevii_rc_keys),
.rc_interval = 150,
@ -1199,12 +1352,12 @@ static struct dvb_usb_device_properties s630_properties = {
.generic_bulk_ctrl_endpoint = 0x81,
.num_adapters = 1,
.download_firmware = dw2102_load_firmware,
.read_mac_address = s630_read_mac_address,
.read_mac_address = s6x0_read_mac_address,
.adapter = {
{
.frontend_attach = s630_frontend_attach,
.frontend_attach = s6x0_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = s630_zl10039_tuner_attach,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
@ -1217,12 +1370,20 @@ static struct dvb_usb_device_properties s630_properties = {
},
}
},
.num_device_descs = 1,
.num_device_descs = 3,
.devices = {
{"TeVii S630 USB",
{&dw2102_table[6], NULL},
{NULL},
},
{"Prof 1100 USB ",
{&dw2102_table[7], NULL},
{NULL},
},
{"TeVii S660 USB",
{&dw2102_table[8], NULL},
{NULL},
},
}
};
@ -1235,10 +1396,10 @@ static int dw2102_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &dw3101_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &s630_properties,
THIS_MODULE, NULL, adapter_nr)) {
0 == dvb_usb_device_init(intf, &s6x0_properties,
THIS_MODULE, NULL, adapter_nr))
return 0;
}
return -ENODEV;
}
@ -1269,6 +1430,7 @@ module_exit(dw2102_module_exit);
MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
" DVB-C 3101 USB2.0,"
" TeVii S600, S630, S650 USB2.0 devices");
" TeVii S600, S630, S650, S660 USB2.0,"
" Prof 1100 USB2.0 devices");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");

View file

@ -134,11 +134,13 @@ static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq)
deb_fe("%s: freq=%d, step=%d\n", __func__, freq,
state->frontend.ops.info.frequency_stepsize);
/* freq -> oscilator frequency conversion. */
/* freq: 473,000,000 + n*6,000,000 (no 1/7MHz shift to center freq) */
/* add 400[1/7 MHZ] = 57.142857MHz. 57MHz for the IF, */
/* 1/7MHz for center freq shift */
/* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */
f = freq / state->frontend.ops.info.frequency_stepsize;
f += 400;
/* add 399[1/7 MHZ] = 57MHz for the IF */
f += 399;
/* add center frequency shift if necessary */
if (f % 7 == 0)
f++;
pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */
pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1;
pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F;

View file

@ -146,8 +146,8 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
switch (c->delivery_system) {
case SYS_DVBS:
/* Only QPSK is supported for DVB-S */
if (c->modulation != QPSK) {
/* Allow QPSK and 8PSK (even for DVB-S) */
if (c->modulation != QPSK && c->modulation != PSK_8) {
deb_fe("%s: unsupported modulation selected (%d)\n",
__func__, c->modulation);
return -EOPNOTSUPP;

View file

@ -526,6 +526,15 @@ config DVB_TUNER_DIB0070
This device is only used inside a SiP called together with a
demodulator for now.
config DVB_TUNER_DIB0090
tristate "DiBcom DiB0090 silicon base-band tuner"
depends on I2C
default m if DVB_FE_CUSTOMISE
help
A driver for the silicon baseband tuner DiB0090 from DiBcom.
This device is only used inside a SiP called together with a
demodulator for now.
comment "SEC control devices for DVB-S"
depends on DVB_CORE

View file

@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TDA8261) += tda8261.o
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o

View file

@ -62,7 +62,7 @@ struct au8522_register_config {
The values are as follows from left to right
0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
*/
struct au8522_register_config filter_coef[] = {
static const struct au8522_register_config filter_coef[] = {
{AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
@ -104,7 +104,7 @@ struct au8522_register_config filter_coef[] = {
0="SIF" 1="ATVRF/ATVRF13"
Note: the "ATVRF/ATVRF13" mode has never been tested
*/
struct au8522_register_config lpfilter_coef[] = {
static const struct au8522_register_config lpfilter_coef[] = {
{0x060b, {0x21, 0x0b} },
{0x060c, {0xad, 0xad} },
{0x060d, {0x70, 0xf0} },

View file

@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define DIB0070_P1G 0x03
#define DIB0070S_P1A 0x02
enum frontend_tune_state {
CT_TUNER_START = 10,
CT_TUNER_STEP_0,
CT_TUNER_STEP_1,
CT_TUNER_STEP_2,
CT_TUNER_STEP_3,
CT_TUNER_STEP_4,
CT_TUNER_STEP_5,
CT_TUNER_STEP_6,
CT_TUNER_STEP_7,
CT_TUNER_STOP,
};
#define FE_CALLBACK_TIME_NEVER 0xffffffff
struct dib0070_state {
struct i2c_adapter *i2c;
struct dvb_frontend *fe;
@ -71,10 +56,10 @@ struct dib0070_state {
u16 wbd_ff_offset;
u8 revision;
enum frontend_tune_state tune_state;
u32 current_rf;
enum frontend_tune_state tune_state;
u32 current_rf;
/* for the captrim binary search */
/* for the captrim binary search */
s8 step;
u16 adc_diff;
@ -85,7 +70,7 @@ struct dib0070_state {
const struct dib0070_tuning *current_tune_table_index;
const struct dib0070_lna_match *lna_match;
u8 wbd_gain_current;
u8 wbd_gain_current;
u16 wbd_offset_3_3[2];
};
@ -93,8 +78,8 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
{
u8 b[2];
struct i2c_msg msg[2] = {
{.addr = state->cfg->i2c_address,.flags = 0,.buf = &reg,.len = 1},
{.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2},
{ .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
};
if (i2c_transfer(state->i2c, msg, 2) != 2) {
printk(KERN_WARNING "DiB0070 I2C read failed\n");
@ -106,7 +91,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
{
u8 b[3] = { reg, val >> 8, val & 0xff };
struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 };
struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
if (i2c_transfer(state->i2c, &msg, 1) != 1) {
printk(KERN_WARNING "DiB0070 I2C write failed\n");
return -EREMOTEIO;
@ -124,30 +109,30 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
{
struct dib0070_state *state = fe->tuner_priv;
u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
struct dib0070_state *state = fe->tuner_priv;
u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000)
tmp |= (0 << 14);
else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000)
tmp |= (1 << 14);
else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000)
tmp |= (2 << 14);
else
tmp |= (3 << 14);
if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
tmp |= (0 << 14);
else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
tmp |= (1 << 14);
else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
tmp |= (2 << 14);
else
tmp |= (3 << 14);
dib0070_write_reg(state, 0x02, tmp);
dib0070_write_reg(state, 0x02, tmp);
/* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
u16 value = dib0070_read_reg(state, 0x17);
/* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
u16 value = dib0070_read_reg(state, 0x17);
dib0070_write_reg(state, 0x17, value & 0xfffc);
tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
dib0070_write_reg(state, 0x01, tmp | (60 << 9));
dib0070_write_reg(state, 0x17, value & 0xfffc);
tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
dib0070_write_reg(state, 0x01, tmp | (60 << 9));
dib0070_write_reg(state, 0x17, value);
}
dib0070_write_reg(state, 0x17, value);
}
return 0;
}
@ -160,14 +145,14 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
if (*tune_state == CT_TUNER_STEP_0) {
dib0070_write_reg(state, 0x0f, 0xed10);
dib0070_write_reg(state, 0x17, 0x0034);
dib0070_write_reg(state, 0x17, 0x0034);
dib0070_write_reg(state, 0x18, 0x0032);
state->step = state->captrim = state->fcaptrim = 64;
state->adc_diff = 3000;
ret = 20;
*tune_state = CT_TUNER_STEP_1;
*tune_state = CT_TUNER_STEP_1;
} else if (*tune_state == CT_TUNER_STEP_1) {
state->step /= 2;
dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
@ -178,7 +163,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
adc = dib0070_read_reg(state, 0x19);
dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024);
dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
if (adc >= 400) {
adc -= 400;
@ -193,6 +178,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
state->adc_diff = adc;
state->fcaptrim = state->captrim;
}
state->captrim += (step_sign * state->step);
@ -213,7 +200,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
{
struct dib0070_state *state = fe->tuner_priv;
u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
dprintk("CTRL_LO5: 0x%x", lo5);
return dib0070_write_reg(state, 0x15, lo5);
}
@ -227,99 +214,99 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
dib0070_write_reg(state, 0x1a, 0x0000);
} else {
dib0070_write_reg(state, 0x1b, 0x4112);
if (state->cfg->vga_filter != 0) {
dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
dprintk("vga filter register is set to %x", state->cfg->vga_filter);
} else
dib0070_write_reg(state, 0x1a, 0x0009);
if (state->cfg->vga_filter != 0) {
dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
dprintk("vga filter register is set to %x", state->cfg->vga_filter);
} else
dib0070_write_reg(state, 0x1a, 0x0009);
}
}
EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
struct dib0070_tuning {
u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
u8 switch_trim;
u8 vco_band;
u8 hfdiv;
u8 vco_multi;
u8 presc;
u8 wbdmux;
u16 tuner_enable;
u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
u8 switch_trim;
u8 vco_band;
u8 hfdiv;
u8 vco_multi;
u8 presc;
u8 wbdmux;
u16 tuner_enable;
};
struct dib0070_lna_match {
u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
u8 lna_band;
u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
u8 lna_band;
};
static const struct dib0070_tuning dib0070s_tuning_table[] = {
{570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */
{700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800},
{863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800},
{1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */
{1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},
{2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},
{0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */
{ 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
{ 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
{ 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
{ 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
{ 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
{ 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
{ 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
};
static const struct dib0070_tuning dib0070_tuning_table[] = {
{115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */
{179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */
{189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000},
{250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000},
{569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */
{699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800},
{863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800},
{0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */
{ 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
{ 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
{ 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
{ 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
{ 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
{ 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
{ 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
{ 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
};
static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
{180000, 0}, /* VHF */
{188000, 1},
{196400, 2},
{250000, 3},
{550000, 0}, /* UHF */
{590000, 1},
{666000, 3},
{864000, 5},
{1500000, 0}, /* LBAND or everything higher than UHF */
{1600000, 1},
{2000000, 3},
{0xffffffff, 7},
{ 180000, 0 }, /* VHF */
{ 188000, 1 },
{ 196400, 2 },
{ 250000, 3 },
{ 550000, 0 }, /* UHF */
{ 590000, 1 },
{ 666000, 3 },
{ 864000, 5 },
{ 1500000, 0 }, /* LBAND or everything higher than UHF */
{ 1600000, 1 },
{ 2000000, 3 },
{ 0xffffffff, 7 },
};
static const struct dib0070_lna_match dib0070_lna[] = {
{180000, 0}, /* VHF */
{188000, 1},
{196400, 2},
{250000, 3},
{550000, 2}, /* UHF */
{650000, 3},
{750000, 5},
{850000, 6},
{864000, 7},
{1500000, 0}, /* LBAND or everything higher than UHF */
{1600000, 1},
{2000000, 3},
{0xffffffff, 7},
{ 180000, 0 }, /* VHF */
{ 188000, 1 },
{ 196400, 2 },
{ 250000, 3 },
{ 550000, 2 }, /* UHF */
{ 650000, 3 },
{ 750000, 5 },
{ 850000, 6 },
{ 864000, 7 },
{ 1500000, 0 }, /* LBAND or everything higher than UHF */
{ 1600000, 1 },
{ 2000000, 3 },
{ 0xffffffff, 7 },
};
#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
#define LPF 100
static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
{
struct dib0070_state *state = fe->tuner_priv;
struct dib0070_state *state = fe->tuner_priv;
const struct dib0070_tuning *tune;
const struct dib0070_lna_match *lna_match;
const struct dib0070_tuning *tune;
const struct dib0070_lna_match *lna_match;
enum frontend_tune_state *tune_state = &state->tune_state;
int ret = 10; /* 1ms is the default delay most of the time */
enum frontend_tune_state *tune_state = &state->tune_state;
int ret = 10; /* 1ms is the default delay most of the time */
u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
#ifdef CONFIG_SYS_ISDBT
if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
|| (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
@ -328,172 +315,180 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
freq += 850;
#endif
if (state->current_rf != freq) {
switch (state->revision) {
case DIB0070S_P1A:
tune = dib0070s_tuning_table;
lna_match = dib0070_lna;
break;
default:
tune = dib0070_tuning_table;
if (state->cfg->flip_chip)
lna_match = dib0070_lna_flip_chip;
else
lna_match = dib0070_lna;
break;
}
while (freq > tune->max_freq) /* find the right one */
tune++;
while (freq > lna_match->max_freq) /* find the right one */
lna_match++;
state->current_tune_table_index = tune;
state->lna_match = lna_match;
}
if (*tune_state == CT_TUNER_START) {
dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
if (state->current_rf != freq) {
u8 REFDIV;
u32 FBDiv, Rest, FREF, VCOF_kHz;
u8 Den;
state->current_rf = freq;
state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
dib0070_write_reg(state, 0x17, 0x30);
VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
switch (band) {
case BAND_VHF:
REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
break;
case BAND_FM:
REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
break;
default:
REFDIV = (u8) (state->cfg->clock_khz / 10000);
break;
}
FREF = state->cfg->clock_khz / REFDIV;
switch (state->revision) {
case DIB0070S_P1A:
tune = dib0070s_tuning_table;
lna_match = dib0070_lna;
FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
break;
case DIB0070_P1G:
case DIB0070_P1F:
default:
tune = dib0070_tuning_table;
if (state->cfg->flip_chip)
lna_match = dib0070_lna_flip_chip;
else
lna_match = dib0070_lna;
FBDiv = (freq / (FREF / 2));
Rest = 2 * freq - FBDiv * FREF;
break;
}
while (freq > tune->max_freq) /* find the right one */
tune++;
while (freq > lna_match->max_freq) /* find the right one */
lna_match++;
state->current_tune_table_index = tune;
state->lna_match = lna_match;
}
if (Rest < LPF)
Rest = 0;
else if (Rest < 2 * LPF)
Rest = 2 * LPF;
else if (Rest > (FREF - LPF)) {
Rest = 0;
FBDiv += 1;
} else if (Rest > (FREF - 2 * LPF))
Rest = FREF - 2 * LPF;
Rest = (Rest * 6528) / (FREF / 10);
if (*tune_state == CT_TUNER_START) {
dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
if (state->current_rf != freq) {
u8 REFDIV;
u32 FBDiv, Rest, FREF, VCOF_kHz;
u8 Den;
state->current_rf = freq;
state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
dib0070_write_reg(state, 0x17, 0x30);
VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
switch (band) {
case BAND_VHF:
REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
break;
case BAND_FM:
REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
break;
default:
REFDIV = (u8) (state->cfg->clock_khz / 10000);
break;
}
FREF = state->cfg->clock_khz / REFDIV;
switch (state->revision) {
case DIB0070S_P1A:
FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
break;
case DIB0070_P1G:
case DIB0070_P1F:
default:
FBDiv = (freq / (FREF / 2));
Rest = 2 * freq - FBDiv * FREF;
break;
}
if (Rest < LPF)
Rest = 0;
else if (Rest < 2 * LPF)
Rest = 2 * LPF;
else if (Rest > (FREF - LPF)) {
Rest = 0;
FBDiv += 1;
} else if (Rest > (FREF - 2 * LPF))
Rest = FREF - 2 * LPF;
Rest = (Rest * 6528) / (FREF / 10);
Den = 1;
if (Rest > 0) {
state->lo4 |= (1 << 14) | (1 << 12);
Den = 255;
}
dib0070_write_reg(state, 0x11, (u16) FBDiv);
dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
dib0070_write_reg(state, 0x13, (u16) Rest);
if (state->revision == DIB0070S_P1A) {
if (band == BAND_SBAND) {
dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
dib0070_write_reg(state, 0x1d, 0xFFFF);
} else
dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
}
dib0070_write_reg(state, 0x20,
0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
*tune_state = CT_TUNER_STEP_0;
} else { /* we are already tuned to this frequency - the configuration is correct */
ret = 50; /* wakeup time */
*tune_state = CT_TUNER_STEP_5;
Den = 1;
if (Rest > 0) {
state->lo4 |= (1 << 14) | (1 << 12);
Den = 255;
}
} else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
ret = dib0070_captrim(state, tune_state);
} else if (*tune_state == CT_TUNER_STEP_4) {
const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
if (tmp != NULL) {
while (freq / 1000 > tmp->freq) /* find the right one */
tmp++;
dib0070_write_reg(state, 0x0f,
(0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state->
current_tune_table_index->
wbdmux << 0));
state->wbd_gain_current = tmp->wbd_gain_val;
} else {
dib0070_write_reg(state, 0x11, (u16)FBDiv);
dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
dib0070_write_reg(state, 0x13, (u16) Rest);
if (state->revision == DIB0070S_P1A) {
if (band == BAND_SBAND) {
dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
dib0070_write_reg(state, 0x1d, 0xFFFF);
} else
dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
}
dib0070_write_reg(state, 0x20,
0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
*tune_state = CT_TUNER_STEP_0;
} else { /* we are already tuned to this frequency - the configuration is correct */
ret = 50; /* wakeup time */
*tune_state = CT_TUNER_STEP_5;
}
} else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
ret = dib0070_captrim(state, tune_state);
} else if (*tune_state == CT_TUNER_STEP_4) {
const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
if (tmp != NULL) {
while (freq/1000 > tmp->freq) /* find the right one */
tmp++;
dib0070_write_reg(state, 0x0f,
(0 << 15) | (1 << 14) | (3 << 12)
| (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
| (state->current_tune_table_index->wbdmux << 0));
state->wbd_gain_current = tmp->wbd_gain_val;
} else {
dib0070_write_reg(state, 0x0f,
(0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
wbdmux << 0));
state->wbd_gain_current = 6;
}
state->wbd_gain_current = 6;
}
dib0070_write_reg(state, 0x06, 0x3fff);
dib0070_write_reg(state, 0x06, 0x3fff);
dib0070_write_reg(state, 0x07,
(state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
dib0070_write_reg(state, 0x0d, 0x0d80);
dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
dib0070_write_reg(state, 0x0d, 0x0d80);
dib0070_write_reg(state, 0x18, 0x07ff);
dib0070_write_reg(state, 0x17, 0x0033);
*tune_state = CT_TUNER_STEP_5;
} else if (*tune_state == CT_TUNER_STEP_5) {
dib0070_set_bandwidth(fe, ch);
*tune_state = CT_TUNER_STOP;
} else {
ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
}
return ret;
dib0070_write_reg(state, 0x18, 0x07ff);
dib0070_write_reg(state, 0x17, 0x0033);
*tune_state = CT_TUNER_STEP_5;
} else if (*tune_state == CT_TUNER_STEP_5) {
dib0070_set_bandwidth(fe, ch);
*tune_state = CT_TUNER_STOP;
} else {
ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
}
return ret;
}
static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
struct dib0070_state *state = fe->tuner_priv;
uint32_t ret;
struct dib0070_state *state = fe->tuner_priv;
uint32_t ret;
state->tune_state = CT_TUNER_START;
state->tune_state = CT_TUNER_START;
do {
ret = dib0070_tune_digital(fe, p);
if (ret != FE_CALLBACK_TIME_NEVER)
msleep(ret / 10);
else
break;
} while (state->tune_state != CT_TUNER_STOP);
do {
ret = dib0070_tune_digital(fe, p);
if (ret != FE_CALLBACK_TIME_NEVER)
msleep(ret/10);
else
break;
} while (state->tune_state != CT_TUNER_STOP);
return 0;
return 0;
}
static int dib0070_wakeup(struct dvb_frontend *fe)
@ -512,92 +507,113 @@ static int dib0070_sleep(struct dvb_frontend *fe)
return 0;
}
static const u16 dib0070_p1f_defaults[] = {
u8 dib0070_get_rf_output(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
}
EXPORT_SYMBOL(dib0070_get_rf_output);
int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
{
struct dib0070_state *state = fe->tuner_priv;
u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
if (no > 3)
no = 3;
if (no < 1)
no = 1;
return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
}
EXPORT_SYMBOL(dib0070_set_rf_output);
static const u16 dib0070_p1f_defaults[] =
{
7, 0x02,
0x0008,
0x0000,
0x0000,
0x0000,
0x0000,
0x0002,
0x0100,
0x0008,
0x0000,
0x0000,
0x0000,
0x0000,
0x0002,
0x0100,
3, 0x0d,
0x0d80,
0x0001,
0x0000,
0x0d80,
0x0001,
0x0000,
4, 0x11,
0x0000,
0x0103,
0x0000,
0x0000,
0x0000,
0x0103,
0x0000,
0x0000,
3, 0x16,
0x0004 | 0x0040,
0x0030,
0x07ff,
0x0004 | 0x0040,
0x0030,
0x07ff,
6, 0x1b,
0x4112,
0xff00,
0xc07f,
0x0000,
0x0180,
0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
0x4112,
0xff00,
0xc07f,
0x0000,
0x0180,
0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
0,
};
static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
{
u16 tuner_en = dib0070_read_reg(state, 0x20);
u16 offset;
u16 tuner_en = dib0070_read_reg(state, 0x20);
u16 offset;
dib0070_write_reg(state, 0x18, 0x07ff);
dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
msleep(9);
offset = dib0070_read_reg(state, 0x19);
dib0070_write_reg(state, 0x20, tuner_en);
return offset;
dib0070_write_reg(state, 0x18, 0x07ff);
dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
msleep(9);
offset = dib0070_read_reg(state, 0x19);
dib0070_write_reg(state, 0x20, tuner_en);
return offset;
}
static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
{
u8 gain;
for (gain = 6; gain < 8; gain++) {
state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]);
}
u8 gain;
for (gain = 6; gain < 8; gain++) {
state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
}
}
u16 dib0070_wbd_offset(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
u32 freq = fe->dtv_property_cache.frequency / 1000;
struct dib0070_state *state = fe->tuner_priv;
const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
u32 freq = fe->dtv_property_cache.frequency/1000;
if (tmp != NULL) {
while (freq / 1000 > tmp->freq) /* find the right one */
tmp++;
state->wbd_gain_current = tmp->wbd_gain_val;
if (tmp != NULL) {
while (freq/1000 > tmp->freq) /* find the right one */
tmp++;
state->wbd_gain_current = tmp->wbd_gain_val;
} else
state->wbd_gain_current = 6;
state->wbd_gain_current = 6;
return state->wbd_offset_3_3[state->wbd_gain_current - 6];
return state->wbd_offset_3_3[state->wbd_gain_current - 6];
}
EXPORT_SYMBOL(dib0070_wbd_offset);
#define pgm_read_word(w) (*w)
static int dib0070_reset(struct dvb_frontend *fe)
{
struct dib0070_state *state = fe->tuner_priv;
struct dib0070_state *state = fe->tuner_priv;
u16 l, r, *n;
HARD_RESET(state);
#ifndef FORCE_SBAND_TUNER
if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
@ -605,7 +621,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
#else
#warning forcing SBAND
#endif
state->revision = DIB0070S_P1A;
state->revision = DIB0070S_P1A;
/* P1F or not */
dprintk("Revision: %x", state->revision);
@ -620,7 +636,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
while (l) {
r = pgm_read_word(n++);
do {
dib0070_write_reg(state, (u8) r, pgm_read_word(n++));
dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
r++;
} while (--l);
l = pgm_read_word(n++);
@ -633,6 +649,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
else
r = 2;
r |= state->cfg->osc_buffer_state << 3;
dib0070_write_reg(state, 0x10, r);
@ -643,16 +660,24 @@ static int dib0070_reset(struct dvb_frontend *fe)
dib0070_write_reg(state, 0x02, r | (1 << 5));
}
if (state->revision == DIB0070S_P1A)
dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
else
if (state->revision == DIB0070S_P1A)
dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
else
dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
dib0070_wbd_offset_calibration(state);
dib0070_wbd_offset_calibration(state);
return 0;
return 0;
}
static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct dib0070_state *state = fe->tuner_priv;
*frequency = 1000 * state->current_rf;
return 0;
}
static int dib0070_release(struct dvb_frontend *fe)
@ -664,18 +689,18 @@ static int dib0070_release(struct dvb_frontend *fe)
static const struct dvb_tuner_ops dib0070_ops = {
.info = {
.name = "DiBcom DiB0070",
.frequency_min = 45000000,
.frequency_max = 860000000,
.frequency_step = 1000,
},
.release = dib0070_release,
.name = "DiBcom DiB0070",
.frequency_min = 45000000,
.frequency_max = 860000000,
.frequency_step = 1000,
},
.release = dib0070_release,
.init = dib0070_wakeup,
.sleep = dib0070_sleep,
.set_params = dib0070_tune,
.init = dib0070_wakeup,
.sleep = dib0070_sleep,
.set_params = dib0070_tune,
// .get_frequency = dib0070_get_frequency,
.get_frequency = dib0070_get_frequency,
// .get_bandwidth = dib0070_get_bandwidth
};
@ -687,7 +712,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
state->cfg = cfg;
state->i2c = i2c;
state->fe = fe;
state->fe = fe;
fe->tuner_priv = state;
if (dib0070_reset(fe) != 0)
@ -699,12 +724,11 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
fe->tuner_priv = state;
return fe;
free_mem:
free_mem:
kfree(state);
fe->tuner_priv = NULL;
return NULL;
}
EXPORT_SYMBOL(dib0070_attach);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");

View file

@ -52,6 +52,8 @@ struct dib0070_config {
extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
extern u16 dib0070_wbd_offset(struct dvb_frontend *);
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
extern u8 dib0070_get_rf_output(struct dvb_frontend *fe);
extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no);
#else
static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
{
@ -62,7 +64,7 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struc
static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
return 0;
}
static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,108 @@
/*
* Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
*
* Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*/
#ifndef DIB0090_H
#define DIB0090_H
struct dvb_frontend;
struct i2c_adapter;
#define DEFAULT_DIB0090_I2C_ADDRESS 0x60
struct dib0090_io_config {
u32 clock_khz;
u8 pll_bypass:1;
u8 pll_range:1;
u8 pll_prediv:6;
u8 pll_loopdiv:6;
u8 adc_clock_ratio; /* valid is 8, 7 ,6 */
u16 pll_int_loop_filt;
};
struct dib0090_config {
struct dib0090_io_config io;
int (*reset) (struct dvb_frontend *, int);
int (*sleep) (struct dvb_frontend *, int);
/* offset in kHz */
int freq_offset_khz_uhf;
int freq_offset_khz_vhf;
int (*get_adc_power) (struct dvb_frontend *);
u8 clkouttobamse:1; /* activate or deactivate clock output */
u8 analog_output;
u8 i2c_address;
/* add drives and other things if necessary */
u16 wbd_vhf_offset;
u16 wbd_cband_offset;
u8 use_pwm_agc;
u8 clkoutdrive;
};
#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
extern int dib0090_gain_control(struct dvb_frontend *fe);
extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
#else
static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return 0;
}
static inline int dib0090_gain_control(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return CT_DONE;
}
static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
#endif
#endif

View file

@ -28,18 +28,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
enum frontend_tune_state {
CT_AGC_START = 20,
CT_AGC_STEP_0,
CT_AGC_STEP_1,
CT_AGC_STEP_2,
CT_AGC_STEP_3,
CT_AGC_STEP_4,
CT_AGC_STOP,
CT_DEMOD_START = 30,
};
#define FE_STATUS_TUNE_FAILED 0
struct i2c_device {
@ -133,104 +121,104 @@ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
return dib8000_i2c_write16(&state->i2c, reg, val);
}
const int16_t coeff_2k_sb_1seg_dqpsk[8] = {
static const int16_t coeff_2k_sb_1seg_dqpsk[8] = {
(769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
(920 << 5) | 0x09
};
const int16_t coeff_2k_sb_1seg[8] = {
static const int16_t coeff_2k_sb_1seg[8] = {
(692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
};
const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
static const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
(832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
(-931 << 5) | 0x0f
};
const int16_t coeff_2k_sb_3seg_0dqpsk[8] = {
static const int16_t coeff_2k_sb_3seg_0dqpsk[8] = {
(622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
(982 << 5) | 0x0c
};
const int16_t coeff_2k_sb_3seg_1dqpsk[8] = {
static const int16_t coeff_2k_sb_3seg_1dqpsk[8] = {
(699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
(-720 << 5) | 0x0d
};
const int16_t coeff_2k_sb_3seg[8] = {
static const int16_t coeff_2k_sb_3seg[8] = {
(664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
(-610 << 5) | 0x0a
};
const int16_t coeff_4k_sb_1seg_dqpsk[8] = {
static const int16_t coeff_4k_sb_1seg_dqpsk[8] = {
(-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
(-922 << 5) | 0x0d
};
const int16_t coeff_4k_sb_1seg[8] = {
static const int16_t coeff_4k_sb_1seg[8] = {
(638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
(-655 << 5) | 0x0a
};
const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
static const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
(-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
(-958 << 5) | 0x13
};
const int16_t coeff_4k_sb_3seg_0dqpsk[8] = {
static const int16_t coeff_4k_sb_3seg_0dqpsk[8] = {
(-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
(-568 << 5) | 0x0f
};
const int16_t coeff_4k_sb_3seg_1dqpsk[8] = {
static const int16_t coeff_4k_sb_3seg_1dqpsk[8] = {
(-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
(-848 << 5) | 0x13
};
const int16_t coeff_4k_sb_3seg[8] = {
static const int16_t coeff_4k_sb_3seg[8] = {
(612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
(-869 << 5) | 0x13
};
const int16_t coeff_8k_sb_1seg_dqpsk[8] = {
static const int16_t coeff_8k_sb_1seg_dqpsk[8] = {
(-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
(-598 << 5) | 0x10
};
const int16_t coeff_8k_sb_1seg[8] = {
static const int16_t coeff_8k_sb_1seg[8] = {
(673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
(585 << 5) | 0x0f
};
const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
static const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
(863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
(0 << 5) | 0x14
};
const int16_t coeff_8k_sb_3seg_0dqpsk[8] = {
static const int16_t coeff_8k_sb_3seg_0dqpsk[8] = {
(-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
(-877 << 5) | 0x15
};
const int16_t coeff_8k_sb_3seg_1dqpsk[8] = {
static const int16_t coeff_8k_sb_3seg_1dqpsk[8] = {
(-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
(-921 << 5) | 0x14
};
const int16_t coeff_8k_sb_3seg[8] = {
static const int16_t coeff_8k_sb_3seg[8] = {
(514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
(690 << 5) | 0x14
};
const int16_t ana_fe_coeff_3seg[24] = {
static const int16_t ana_fe_coeff_3seg[24] = {
81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
};
const int16_t ana_fe_coeff_1seg[24] = {
static const int16_t ana_fe_coeff_1seg[24] = {
249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
};
const int16_t ana_fe_coeff_13seg[24] = {
static const int16_t ana_fe_coeff_13seg[24] = {
396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
};
@ -852,6 +840,14 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
return 0;
}
void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
dib8000_set_adc_state(state, DIBX000_ADC_ON);
dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
}
EXPORT_SYMBOL(dib8000_pwm_agc_reset);
static int dib8000_agc_soft_split(struct dib8000_state *state)
{
u16 agc, split_offset;
@ -939,6 +935,32 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
}
static const int32_t lut_1000ln_mant[] =
{
908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
};
int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode)
{
struct dib8000_state *state = fe->demodulator_priv;
uint32_t ix = 0, tmp_val = 0, exp = 0, mant = 0;
int32_t val;
val = dib8000_read32(state, 384);
/* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */
if (mode) {
tmp_val = val;
while (tmp_val >>= 1)
exp++;
mant = (val * 1000 / (1<<exp));
ix = (uint8_t)((mant-1000)/100); /* index of the LUT */
val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */
val = (val*256)/1000;
}
return val;
}
EXPORT_SYMBOL(dib8000_get_adc_power);
static void dib8000_update_timf(struct dib8000_state *state)
{
u32 timf = state->timf = dib8000_read32(state, 435);
@ -1401,10 +1423,9 @@ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosear
}
break;
}
}
if (state->fe.dtv_property_cache.isdbt_sb_mode == 1)
for (i = 0; i < 8; i++)
dib8000_write_word(state, 343 + i, ncoeff[i]);
}
// P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5
dib8000_write_word(state, 351,
@ -1854,6 +1875,24 @@ static int dib8000_sleep(struct dvb_frontend *fe)
}
}
enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
return state->tune_state;
}
EXPORT_SYMBOL(dib8000_get_tune_state);
int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
struct dib8000_state *state = fe->demodulator_priv;
state->tune_state = tune_state;
return 0;
}
EXPORT_SYMBOL(dib8000_set_tune_state);
static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
{
struct dib8000_state *state = fe->demodulator_priv;
@ -2043,29 +2082,31 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
*stat = 0;
if ((lock >> 14) & 1) // AGC
if ((lock >> 13) & 1)
*stat |= FE_HAS_SIGNAL;
if ((lock >> 8) & 1) // Equal
if ((lock >> 8) & 1) /* Equal */
*stat |= FE_HAS_CARRIER;
if ((lock >> 3) & 1) // TMCC_SYNC
if (((lock >> 1) & 0xf) == 0xf) /* TMCC_SYNC */
*stat |= FE_HAS_SYNC;
if ((lock >> 5) & 7) // FEC MPEG
if (((lock >> 12) & 1) && ((lock >> 5) & 7)) /* FEC MPEG */
*stat |= FE_HAS_LOCK;
lock = dib8000_read_word(state, 554); // Viterbi Layer A
if (lock & 0x01)
*stat |= FE_HAS_VITERBI;
if ((lock >> 12) & 1) {
lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
if (lock & 0x01)
*stat |= FE_HAS_VITERBI;
lock = dib8000_read_word(state, 555); // Viterbi Layer B
if (lock & 0x01)
*stat |= FE_HAS_VITERBI;
lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
if (lock & 0x01)
*stat |= FE_HAS_VITERBI;
lock = dib8000_read_word(state, 556); // Viterbi Layer C
if (lock & 0x01)
*stat |= FE_HAS_VITERBI;
lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
if (lock & 0x01)
*stat |= FE_HAS_VITERBI;
}
return 0;
}

View file

@ -46,6 +46,10 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
#else
static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
{
@ -59,35 +63,53 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe
return NULL;
}
int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return CT_SHUTDOWN,
}
static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
}
#endif
#endif

View file

@ -6,7 +6,7 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
{
@ -25,7 +25,7 @@ static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
enum dibx000_i2c_interface intf)
{
if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
dprintk("selecting interface: %d\n", intf);
dprintk("selecting interface: %d", intf);
mst->selected_interface = intf;
return dibx000_write_word(mst, mst->base_reg + 4, intf);
}
@ -171,9 +171,18 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
{
i2c_del_adapter(&mst->gated_tuner_i2c_adap);
}
EXPORT_SYMBOL(dibx000_exit_i2c_master);
u32 systime()
{
struct timespec t;
t = current_kernel_time();
return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
}
EXPORT_SYMBOL(systime);
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
MODULE_LICENSE("GPL");

View file

@ -36,13 +36,17 @@ extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master
extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
extern u32 systime(void);
#define BAND_LBAND 0x01
#define BAND_UHF 0x02
#define BAND_VHF 0x04
#define BAND_SBAND 0x08
#define BAND_FM 0x10
#define BAND_FM 0x10
#define BAND_CBAND 0x20
#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
#define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \
(freq_kHz) <= 115000 ? BAND_FM : \
(freq_kHz) <= 250000 ? BAND_VHF : \
(freq_kHz) <= 863000 ? BAND_UHF : \
(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
@ -149,4 +153,67 @@ enum dibx000_adc_states {
#define OUTMODE_MPEG2_FIFO 5
#define OUTMODE_ANALOG_ADC 6
enum frontend_tune_state {
CT_TUNER_START = 10,
CT_TUNER_STEP_0,
CT_TUNER_STEP_1,
CT_TUNER_STEP_2,
CT_TUNER_STEP_3,
CT_TUNER_STEP_4,
CT_TUNER_STEP_5,
CT_TUNER_STEP_6,
CT_TUNER_STEP_7,
CT_TUNER_STOP,
CT_AGC_START = 20,
CT_AGC_STEP_0,
CT_AGC_STEP_1,
CT_AGC_STEP_2,
CT_AGC_STEP_3,
CT_AGC_STEP_4,
CT_AGC_STOP,
CT_DEMOD_START = 30,
CT_DEMOD_STEP_1,
CT_DEMOD_STEP_2,
CT_DEMOD_STEP_3,
CT_DEMOD_STEP_4,
CT_DEMOD_STEP_5,
CT_DEMOD_STEP_6,
CT_DEMOD_STEP_7,
CT_DEMOD_STEP_8,
CT_DEMOD_STEP_9,
CT_DEMOD_STEP_10,
CT_DEMOD_SEARCH_NEXT = 41,
CT_DEMOD_STEP_LOCKED,
CT_DEMOD_STOP,
CT_DONE = 100,
CT_SHUTDOWN,
};
struct dvb_frontend_parametersContext {
#define CHANNEL_STATUS_PARAMETERS_UNKNOWN 0x01
#define CHANNEL_STATUS_PARAMETERS_SET 0x02
u8 status;
u32 tune_time_estimation[2];
s32 tps_available;
u16 tps[9];
};
#define FE_STATUS_TUNE_FAILED 0
#define FE_STATUS_TUNE_TIMED_OUT -1
#define FE_STATUS_TUNE_TIME_TOO_SHORT -2
#define FE_STATUS_TUNE_PENDING -3
#define FE_STATUS_STD_SUCCESS -4
#define FE_STATUS_FFT_SUCCESS -5
#define FE_STATUS_DEMOD_SUCCESS -6
#define FE_STATUS_LOCKED -7
#define FE_STATUS_DATA_LOCKED -8
#define FE_CALLBACK_TIME_NEVER 0xffffffff
#define ABS(x) ((x < 0) ? (-x) : (x))
#endif

View file

@ -199,7 +199,7 @@ static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
val = freq;
if (freq != 0) {
val *= (u64)1 << 32;
val <<= 32;
if (if_clk != 0)
do_div(val, if_clk);
v32 = val & 0xFFFFFFFF;
@ -246,7 +246,7 @@ static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
val = v32;
val *= priv->config->if_clk_freq;
val /= (u64)1 << 32;
val >>= 32;
dprintk("AFC = %u kHz\n", (u32)val);
return 0;
}

View file

@ -1,7 +1,7 @@
/*
* lnbp21.c - driver for lnb supply and control ic lnbp21
*
* Copyright (C) 2006 Oliver Endriss
* Copyright (C) 2006, 2009 Oliver Endriss <o.endriss@gmx.de>
* Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
*
* This program is free software; you can redistribute it and/or
@ -91,6 +91,31 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static int lnbp21_set_tone(struct dvb_frontend *fe,
fe_sec_tone_mode_t tone)
{
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
struct i2c_msg msg = { .addr = lnbp21->i2c_addr, .flags = 0,
.buf = &lnbp21->config,
.len = sizeof(lnbp21->config) };
switch (tone) {
case SEC_TONE_OFF:
lnbp21->config &= ~LNBP21_TEN;
break;
case SEC_TONE_ON:
lnbp21->config |= LNBP21_TEN;
break;
default:
return -EINVAL;
};
lnbp21->config |= lnbp21->override_or;
lnbp21->config &= lnbp21->override_and;
return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static void lnbp21_release(struct dvb_frontend *fe)
{
/* LNBP power off */
@ -133,6 +158,7 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
/* override frontend ops */
fe->ops.set_voltage = lnbp21_set_voltage;
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
fe->ops.set_tone = lnbp21_set_tone;
printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
return fe;

View file

@ -1451,6 +1451,8 @@ static int stv0900_status(struct stv0900_internal *intp,
{
enum fe_stv0900_search_state demod_state;
int locked = FALSE;
u8 tsbitrate0_val, tsbitrate1_val;
s32 bitrate;
demod_state = stv0900_get_bits(intp, HEADER_MODE);
switch (demod_state) {
@ -1473,6 +1475,17 @@ static int stv0900_status(struct stv0900_internal *intp,
dprintk("%s: locked = %d\n", __func__, locked);
if (stvdebug) {
/* Print TS bitrate */
tsbitrate0_val = stv0900_read_reg(intp, TSBITRATE0);
tsbitrate1_val = stv0900_read_reg(intp, TSBITRATE1);
/* Formula Bit rate = Mclk * px_tsfifo_bitrate / 16384 */
bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
* (tsbitrate1_val << 8 | tsbitrate0_val);
bitrate /= 16384;
dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
};
return locked;
}

View file

@ -3597,7 +3597,8 @@ static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma
reg = STV090x_READ_DEMOD(state, DISTXCTL);
STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2);
STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD,
(state->config->diseqc_envelope_mode) ? 4 : 2);
STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
goto err;
@ -3649,10 +3650,10 @@ static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t
reg = STV090x_READ_DEMOD(state, DISTXCTL);
if (burst == SEC_MINI_A) {
mode = 3;
mode = (state->config->diseqc_envelope_mode) ? 5 : 3;
value = 0x00;
} else {
mode = 2;
mode = (state->config->diseqc_envelope_mode) ? 4 : 2;
value = 0xFF;
}

View file

@ -75,6 +75,8 @@ struct stv090x_config {
enum stv090x_i2crpt repeater_level;
bool diseqc_envelope_mode;
int (*tuner_init) (struct dvb_frontend *fe);
int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);

View file

@ -662,7 +662,7 @@ adapter_error:
return rc;
}
int smsdvb_module_init(void)
static int __init smsdvb_module_init(void)
{
int rc;
@ -676,7 +676,7 @@ int smsdvb_module_init(void)
return rc;
}
void smsdvb_module_exit(void)
static void __exit smsdvb_module_exit(void)
{
smscore_unregister_hotplug(smsdvb_hotplug);

View file

@ -48,7 +48,7 @@
#define SMSSDIO_INT 0x04
#define SMSSDIO_BLOCK_SIZE 128
static const struct sdio_device_id smssdio_ids[] = {
static const struct sdio_device_id smssdio_ids[] __devinitconst = {
{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
.driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
@ -222,7 +222,7 @@ static void smssdio_interrupt(struct sdio_func *func)
smscore_onresponse(smsdev->coredev, cb);
}
static int smssdio_probe(struct sdio_func *func,
static int __devinit smssdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
int ret;
@ -338,7 +338,7 @@ static struct sdio_driver smssdio_driver = {
/* Module functions */
/*******************************************************************/
int smssdio_module_init(void)
static int __init smssdio_module_init(void)
{
int ret = 0;
@ -350,7 +350,7 @@ int smssdio_module_init(void)
return ret;
}
void smssdio_module_exit(void)
static void __exit smssdio_module_exit(void)
{
sdio_unregister_driver(&smssdio_driver);
}

View file

@ -390,7 +390,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
return rc;
}
static int smsusb_probe(struct usb_interface *intf,
static int __devinit smsusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
@ -484,7 +484,7 @@ static int smsusb_resume(struct usb_interface *intf)
return 0;
}
struct usb_device_id smsusb_id_table[] = {
static const struct usb_device_id smsusb_id_table[] __devinitconst = {
{ USB_DEVICE(0x187f, 0x0010),
.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
{ USB_DEVICE(0x187f, 0x0100),
@ -533,8 +533,18 @@ struct usb_device_id smsusb_id_table[] = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xb910),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xb980),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xb990),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc000),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc010),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc080),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc090),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ } /* Terminating entry */
};
@ -550,7 +560,7 @@ static struct usb_driver smsusb_driver = {
.resume = smsusb_resume,
};
int smsusb_module_init(void)
static int __init smsusb_module_init(void)
{
int rc = usb_register(&smsusb_driver);
if (rc)
@ -561,7 +571,7 @@ int smsusb_module_init(void)
return rc;
}
void smsusb_module_exit(void)
static void __exit smsusb_module_exit(void)
{
/* Regular USB Cleanup */
usb_deregister(&smsusb_driver);

View file

@ -190,12 +190,13 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
struct saa7146_dev *saa = budget_ci->budget.dev;
struct input_dev *input_dev = budget_ci->ir.dev;
int error;
struct ir_scancode_table *ir_codes;
budget_ci->ir.dev = input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
error = -ENOMEM;
goto out1;
return -ENOMEM;
}
snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
@ -217,6 +218,11 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
}
input_dev->dev.parent = &saa->pci->dev;
if (rc5_device < 0)
budget_ci->ir.rc5_device = IR_DEVICE_ANY;
else
budget_ci->ir.rc5_device = rc5_device;
/* Select keymap and address */
switch (budget_ci->budget.dev->pci->subsystem_device) {
case 0x100c:
@ -224,53 +230,34 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
case 0x1011:
case 0x1012:
/* The hauppauge keymap is a superset of these remotes */
error = ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, &ir_codes_hauppauge_new_table);
if (error < 0)
goto out2;
ir_codes = &ir_codes_hauppauge_new_table;
if (rc5_device < 0)
budget_ci->ir.rc5_device = 0x1f;
else
budget_ci->ir.rc5_device = rc5_device;
break;
case 0x1010:
case 0x1017:
case 0x101a:
/* for the Technotrend 1500 bundled remote */
error = ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, &ir_codes_tt_1500_table);
if (error < 0)
goto out2;
if (rc5_device < 0)
budget_ci->ir.rc5_device = IR_DEVICE_ANY;
else
budget_ci->ir.rc5_device = rc5_device;
ir_codes = &ir_codes_tt_1500_table;
break;
default:
/* unknown remote */
error = ir_input_init(input_dev, &budget_ci->ir.state,
IR_TYPE_RC5, &ir_codes_budget_ci_old_table);
if (error < 0)
goto out2;
if (rc5_device < 0)
budget_ci->ir.rc5_device = IR_DEVICE_ANY;
else
budget_ci->ir.rc5_device = rc5_device;
ir_codes = &ir_codes_budget_ci_old_table;
break;
}
ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5);
/* initialise the key-up timeout handler */
init_timer(&budget_ci->ir.timer_keyup);
budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
budget_ci->ir.last_raw = 0xffff; /* An impossible value */
error = input_register_device(input_dev);
error = ir_input_register(input_dev, ir_codes);
if (error) {
printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
goto out2;
return error;
}
/* note: these must be after input_register_device */
@ -284,12 +271,6 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
return 0;
out2:
ir_input_free(input_dev);
input_free_device(input_dev);
out1:
return error;
}
static void msp430_ir_deinit(struct budget_ci *budget_ci)
@ -304,8 +285,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
del_timer_sync(&dev->timer);
ir_input_nokey(dev, &budget_ci->ir.state);
ir_input_free(dev);
input_unregister_device(dev);
ir_input_unregister(dev);
}
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)

View file

@ -215,13 +215,10 @@ config RADIO_MIROPCM20
module will be called radio-miropcm20.
config RADIO_SF16FMI
tristate "SF16FMI Radio"
tristate "SF16-FMI/SF16-FMP Radio"
depends on ISA && VIDEO_V4L2
---help---
Choose Y here if you have one of these FM radio cards. If you
compile the driver into the kernel and your card is not PnP one, you
have to add "sf16fm=<io>" to the kernel command line (I/O address is
0x284 or 0x384).
Choose Y here if you have one of these FM radio cards.
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on

View file

@ -268,6 +268,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct rtrack *rt = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
rt_setfreq(rt, f->frequency);
return 0;
}
@ -277,6 +279,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct rtrack *rt = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->curfreq;
return 0;

View file

@ -254,6 +254,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct aztech *az = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
az_setfreq(az, f->frequency);
return 0;
}
@ -263,6 +265,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct aztech *az = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = az->curfreq;
return 0;

View file

@ -240,6 +240,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct gemtek_pci *card = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency < GEMTEK_PCI_RANGE_LOW ||
f->frequency > GEMTEK_PCI_RANGE_HIGH)
return -EINVAL;
@ -253,6 +255,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct gemtek_pci *card = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = card->current_frequency;
return 0;

View file

@ -200,6 +200,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct maestro *dev = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
return -EINVAL;
mutex_lock(&dev->lock);
@ -213,6 +215,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct maestro *dev = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
mutex_lock(&dev->lock);
f->frequency = BITS2FREQ(radio_bits_get(dev));

View file

@ -262,6 +262,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct maxiradio *dev = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
f->frequency / 16000,
@ -285,6 +287,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct maxiradio *dev = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = dev->freq;

View file

@ -374,6 +374,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct amradio_device *radio = file->private_data;
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
return amradio_setfreq(radio, f->frequency);
}
@ -383,6 +385,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct amradio_device *radio = file->private_data;
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = radio->curfreq;

View file

@ -167,6 +167,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct rtrack2 *rt = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
rt_setfreq(rt, f->frequency);
return 0;
}
@ -176,6 +178,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct rtrack2 *rt = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = rt->curfreq;
return 0;

View file

@ -1,4 +1,4 @@
/* SF16FMI radio driver for Linux radio support
/* SF16-FMI and SF16-FMP radio driver for Linux radio support
* heavily based on rtrack driver...
* (c) 1997 M. Kirkwood
* (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
@ -11,7 +11,7 @@
*
* Frequency control is done digitally -- ie out(port,encodefreq(95.8));
* No volume control - only mute/unmute - you have to use line volume
* control on SB-part of SF16FMI
* control on SB-part of SF16-FMI/SF16-FMP
*
* Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
*/
@ -30,14 +30,14 @@
#include <media/v4l2-ioctl.h>
MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
MODULE_DESCRIPTION("A driver for the SF16MI radio.");
MODULE_DESCRIPTION("A driver for the SF16-FMI and SF16-FMP radio.");
MODULE_LICENSE("GPL");
static int io = -1;
static int radio_nr = -1;
module_param(io, int, 0);
MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)");
MODULE_PARM_DESC(io, "I/O address of the SF16-FMI or SF16-FMP card (0x284 or 0x384)");
module_param(radio_nr, int, 0);
#define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
@ -47,13 +47,14 @@ struct fmi
struct v4l2_device v4l2_dev;
struct video_device vdev;
int io;
int curvol; /* 1 or 0 */
bool mute;
unsigned long curfreq; /* freq in kHz */
struct mutex lock;
};
static struct fmi fmi_card;
static struct pnp_dev *dev;
bool pnp_attached;
/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
/* It is only useful to give freq in interval of 800 (=0.05Mhz),
@ -105,7 +106,7 @@ static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq)
outbits(8, 0xC0, fmi->io);
msleep(143); /* was schedule_timeout(HZ/7) */
mutex_unlock(&fmi->lock);
if (fmi->curvol)
if (!fmi->mute)
fmi_unmute(fmi);
return 0;
}
@ -116,7 +117,7 @@ static inline int fmi_getsigstr(struct fmi *fmi)
int res;
mutex_lock(&fmi->lock);
val = fmi->curvol ? 0x08 : 0x00; /* unmute/mute */
val = fmi->mute ? 0x00 : 0x08; /* mute/unmute */
outb(val, fmi->io);
outb(val | 0x10, fmi->io);
msleep(143); /* was schedule_timeout(HZ/7) */
@ -168,6 +169,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct fmi *fmi = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency < RSF16_MINFREQ ||
f->frequency > RSF16_MAXFREQ)
return -EINVAL;
@ -182,6 +185,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct fmi *fmi = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = fmi->curfreq;
return 0;
@ -204,7 +209,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
ctrl->value = fmi->curvol;
ctrl->value = fmi->mute;
return 0;
}
return -EINVAL;
@ -221,7 +226,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
fmi_mute(fmi);
else
fmi_unmute(fmi);
fmi->curvol = ctrl->value;
fmi->mute = ctrl->value;
return 0;
}
return -EINVAL;
@ -316,26 +321,54 @@ static int __init fmi_init(void)
{
struct fmi *fmi = &fmi_card;
struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
int res;
int res, i;
int probe_ports[] = { 0, 0x284, 0x384 };
if (io < 0) {
for (i = 0; i < ARRAY_SIZE(probe_ports); i++) {
io = probe_ports[i];
if (io == 0) {
io = isapnp_fmi_probe();
if (io < 0)
continue;
pnp_attached = 1;
}
if (!request_region(io, 2, "radio-sf16fmi")) {
if (pnp_attached)
pnp_device_detach(dev);
io = -1;
continue;
}
if (pnp_attached ||
((inb(io) & 0xf9) == 0xf9 && (inb(io) & 0x4) == 0))
break;
release_region(io, 2);
io = -1;
}
} else {
if (!request_region(io, 2, "radio-sf16fmi")) {
printk(KERN_ERR "radio-sf16fmi: port %#x already in use\n", io);
return -EBUSY;
}
if (inb(io) == 0xff) {
printk(KERN_ERR "radio-sf16fmi: card not present at %#x\n", io);
release_region(io, 2);
return -ENODEV;
}
}
if (io < 0) {
printk(KERN_ERR "radio-sf16fmi: no cards found\n");
return -ENODEV;
}
if (io < 0)
io = isapnp_fmi_probe();
strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
fmi->io = io;
if (fmi->io < 0) {
v4l2_err(v4l2_dev, "No PnP card found.\n");
return fmi->io;
}
if (!request_region(io, 2, "radio-sf16fmi")) {
v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io);
pnp_device_detach(dev);
return -EBUSY;
}
res = v4l2_device_register(NULL, v4l2_dev);
if (res < 0) {
release_region(fmi->io, 2);
pnp_device_detach(dev);
if (pnp_attached)
pnp_device_detach(dev);
v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
return res;
}
@ -352,7 +385,8 @@ static int __init fmi_init(void)
if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
v4l2_device_unregister(v4l2_dev);
release_region(fmi->io, 2);
pnp_device_detach(dev);
if (pnp_attached)
pnp_device_detach(dev);
return -EINVAL;
}
@ -369,7 +403,7 @@ static void __exit fmi_exit(void)
video_unregister_device(&fmi->vdev);
v4l2_device_unregister(&fmi->v4l2_dev);
release_region(fmi->io, 2);
if (dev)
if (dev && pnp_attached)
pnp_device_detach(dev);
}

View file

@ -251,6 +251,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct fmr2 *fmr2 = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency < RSF16_MINFREQ ||
f->frequency > RSF16_MAXFREQ)
return -EINVAL;
@ -272,6 +274,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct fmr2 *fmr2 = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = fmr2->curfreq;
return 0;

View file

@ -314,7 +314,7 @@ static int vidioc_g_tuner(struct file *file, void *priv,
if (v->index > 0)
return -EINVAL;
memset(v, 0, sizeof(v));
memset(v, 0, sizeof(*v));
strcpy(v->name, "FM");
v->type = V4L2_TUNER_RADIO;
tea5764_i2c_read(radio);
@ -349,7 +349,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct tea5764_device *radio = video_drvdata(file);
if (f->tuner != 0)
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (f->frequency == 0) {
/* We special case this as a power down control. */
@ -370,8 +370,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
struct tea5764_device *radio = video_drvdata(file);
struct tea5764_regs *r = &radio->regs;
if (f->tuner != 0)
return -EINVAL;
tea5764_i2c_read(radio);
memset(f, 0, sizeof(f));
memset(f, 0, sizeof(*f));
f->type = V4L2_TUNER_RADIO;
if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
f->frequency = (tea5764_get_freq(radio) * 2) / 125;
@ -458,12 +460,8 @@ static int vidioc_s_audio(struct file *file, void *priv,
static int tea5764_open(struct file *file)
{
/* Currently we support only one device */
int minor = video_devdata(file)->minor;
struct tea5764_device *radio = video_drvdata(file);
if (radio->videodev->minor != minor)
return -ENODEV;
mutex_lock(&radio->mutex);
/* Only exclusive access */
if (radio->users) {

View file

@ -240,6 +240,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct terratec *tt = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
tt_setfreq(tt, f->frequency);
return 0;
}
@ -249,6 +251,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct terratec *tt = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = tt->curfreq;
return 0;

View file

@ -239,6 +239,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct trust *tr = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
tr_setfreq(tr, f->frequency);
return 0;
}
@ -248,6 +250,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct trust *tr = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = tr->curfreq;
return 0;

View file

@ -207,6 +207,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct typhoon *dev = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = dev->curfreq;
return 0;
@ -217,6 +219,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct typhoon *dev = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
dev->curfreq = f->frequency;
typhoon_setfreq(dev, dev->curfreq);
return 0;

View file

@ -266,6 +266,8 @@ static int vidioc_s_frequency(struct file *file, void *priv,
{
struct zoltrix *zol = video_drvdata(file);
if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
return -EINVAL;
if (zol_setfreq(zol, f->frequency) != 0)
return -EINVAL;
return 0;
@ -276,6 +278,8 @@ static int vidioc_g_frequency(struct file *file, void *priv,
{
struct zoltrix *zol = video_drvdata(file);
if (f->tuner != 0)
return -EINVAL;
f->type = V4L2_TUNER_RADIO;
f->frequency = zol->curfreq;
return 0;

View file

@ -425,6 +425,104 @@ int si470x_rds_on(struct si470x_device *radio)
/**************************************************************************
* File Operations Interface
**************************************************************************/
/*
* si470x_fops_read - read RDS data
*/
static ssize_t si470x_fops_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
unsigned int block_count = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
si470x_rds_on(radio);
/* block if no new data available */
while (radio->wr_index == radio->rd_index) {
if (file->f_flags & O_NONBLOCK) {
retval = -EWOULDBLOCK;
goto done;
}
if (wait_event_interruptible(radio->read_queue,
radio->wr_index != radio->rd_index) < 0) {
retval = -EINTR;
goto done;
}
}
/* calculate block count from byte count */
count /= 3;
/* copy RDS block out of internal buffer and to user buffer */
mutex_lock(&radio->lock);
while (block_count < count) {
if (radio->rd_index == radio->wr_index)
break;
/* always transfer rds complete blocks */
if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
/* retval = -EFAULT; */
break;
/* increment and wrap read pointer */
radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0;
/* increment counters */
block_count++;
buf += 3;
retval += 3;
}
mutex_unlock(&radio->lock);
done:
return retval;
}
/*
* si470x_fops_poll - poll RDS data
*/
static unsigned int si470x_fops_poll(struct file *file,
struct poll_table_struct *pts)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
si470x_rds_on(radio);
poll_wait(file, &radio->read_queue, pts);
if (radio->rd_index != radio->wr_index)
retval = POLLIN | POLLRDNORM;
return retval;
}
/*
* si470x_fops - file operations interface
*/
static const struct v4l2_file_operations si470x_fops = {
.owner = THIS_MODULE,
.read = si470x_fops_read,
.poll = si470x_fops_poll,
.ioctl = video_ioctl2,
.open = si470x_fops_open,
.release = si470x_fops_release,
};
/**************************************************************************
* Video4Linux Interface
**************************************************************************/

View file

@ -22,22 +22,17 @@
*/
/*
* ToDo:
* - RDS support
*/
/* driver definitions */
#define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0)
#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 1)
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
#define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
#define DRIVER_VERSION "1.0.0"
#define DRIVER_VERSION "1.0.1"
/* kernel includes */
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include "radio-si470x.h"
@ -62,6 +57,20 @@ static int radio_nr = -1;
module_param(radio_nr, int, 0444);
MODULE_PARM_DESC(radio_nr, "Radio Nr");
/* RDS buffer blocks */
static unsigned int rds_buf = 100;
module_param(rds_buf, uint, 0444);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
/* RDS maximum block errors */
static unsigned short max_rds_errors = 1;
/* 0 means 0 errors requiring correction */
/* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */
/* 2 means 3-5 errors requiring correction */
/* 3 means 6+ errors or errors in checkword, correction not possible */
module_param(max_rds_errors, ushort, 0644);
MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
/**************************************************************************
@ -173,7 +182,7 @@ int si470x_disconnect_check(struct si470x_device *radio)
/*
* si470x_fops_open - file open
*/
static int si470x_fops_open(struct file *file)
int si470x_fops_open(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
@ -181,12 +190,21 @@ static int si470x_fops_open(struct file *file)
mutex_lock(&radio->lock);
radio->users++;
if (radio->users == 1)
if (radio->users == 1) {
/* start radio */
retval = si470x_start(radio);
if (retval < 0)
goto done;
/* enable RDS interrupt */
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
radio->registers[SYSCONFIG1] |= 0x1 << 2;
retval = si470x_set_register(radio, SYSCONFIG1);
}
done:
mutex_unlock(&radio->lock);
return retval;
}
@ -194,7 +212,7 @@ static int si470x_fops_open(struct file *file)
/*
* si470x_fops_release - file release
*/
static int si470x_fops_release(struct file *file)
int si470x_fops_release(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
@ -215,17 +233,6 @@ static int si470x_fops_release(struct file *file)
}
/*
* si470x_fops - file operations interface
*/
const struct v4l2_file_operations si470x_fops = {
.owner = THIS_MODULE,
.ioctl = video_ioctl2,
.open = si470x_fops_open,
.release = si470x_fops_release,
};
/**************************************************************************
* Video4Linux Interface
@ -252,6 +259,105 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
* I2C Interface
**************************************************************************/
/*
* si470x_i2c_interrupt_work - rds processing function
*/
static void si470x_i2c_interrupt_work(struct work_struct *work)
{
struct si470x_device *radio = container_of(work,
struct si470x_device, radio_work);
unsigned char regnr;
unsigned char blocknum;
unsigned short bler; /* rds block errors */
unsigned short rds;
unsigned char tmpbuf[3];
int retval = 0;
/* safety checks */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
return;
/* Update RDS registers */
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) {
retval = si470x_get_register(radio, STATUSRSSI + regnr);
if (retval < 0)
return;
}
/* get rds blocks */
if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
/* No RDS group ready, better luck next time */
return;
for (blocknum = 0; blocknum < 4; blocknum++) {
switch (blocknum) {
default:
bler = (radio->registers[STATUSRSSI] &
STATUSRSSI_BLERA) >> 9;
rds = radio->registers[RDSA];
break;
case 1:
bler = (radio->registers[READCHAN] &
READCHAN_BLERB) >> 14;
rds = radio->registers[RDSB];
break;
case 2:
bler = (radio->registers[READCHAN] &
READCHAN_BLERC) >> 12;
rds = radio->registers[RDSC];
break;
case 3:
bler = (radio->registers[READCHAN] &
READCHAN_BLERD) >> 10;
rds = radio->registers[RDSD];
break;
};
/* Fill the V4L2 RDS buffer */
put_unaligned_le16(rds, &tmpbuf);
tmpbuf[2] = blocknum; /* offset name */
tmpbuf[2] |= blocknum << 3; /* received offset */
if (bler > max_rds_errors)
tmpbuf[2] |= 0x80; /* uncorrectable errors */
else if (bler > 0)
tmpbuf[2] |= 0x40; /* corrected error(s) */
/* copy RDS block to internal buffer */
memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
radio->wr_index += 3;
/* wrap write pointer */
if (radio->wr_index >= radio->buf_size)
radio->wr_index = 0;
/* check for overflow */
if (radio->wr_index == radio->rd_index) {
/* increment and wrap read pointer */
radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0;
}
}
if (radio->wr_index != radio->rd_index)
wake_up_interruptible(&radio->read_queue);
}
/*
* si470x_i2c_interrupt - interrupt handler
*/
static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
{
struct si470x_device *radio = dev_id;
if (!work_pending(&radio->radio_work))
schedule_work(&radio->radio_work);
return IRQ_HANDLED;
}
/*
* si470x_i2c_probe - probe for the device
*/
@ -268,6 +374,8 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
retval = -ENOMEM;
goto err_initial;
}
INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work);
radio->users = 0;
radio->client = client;
mutex_init(&radio->lock);
@ -319,6 +427,26 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
/* set initial frequency */
si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
/* rds buffer allocation */
radio->buf_size = rds_buf * 3;
radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
if (!radio->buffer) {
retval = -EIO;
goto err_video;
}
/* rds buffer configuration */
radio->wr_index = 0;
radio->rd_index = 0;
init_waitqueue_head(&radio->read_queue);
retval = request_irq(client->irq, si470x_i2c_interrupt,
IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
if (retval) {
dev_err(&client->dev, "Failed to register interrupt\n");
goto err_rds;
}
/* register video device */
retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
radio_nr);
@ -330,6 +458,9 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
return 0;
err_all:
free_irq(client->irq, radio);
err_rds:
kfree(radio->buffer);
err_video:
video_device_release(radio->videodev);
err_radio:
@ -346,6 +477,8 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
{
struct si470x_device *radio = i2c_get_clientdata(client);
free_irq(client->irq, radio);
cancel_work_sync(&radio->radio_work);
video_unregister_device(radio->videodev);
kfree(radio);
i2c_set_clientdata(client, NULL);
@ -354,6 +487,44 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
}
#ifdef CONFIG_PM
/*
* si470x_i2c_suspend - suspend the device
*/
static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
{
struct si470x_device *radio = i2c_get_clientdata(client);
/* power down */
radio->registers[POWERCFG] |= POWERCFG_DISABLE;
if (si470x_set_register(radio, POWERCFG) < 0)
return -EIO;
return 0;
}
/*
* si470x_i2c_resume - resume the device
*/
static int si470x_i2c_resume(struct i2c_client *client)
{
struct si470x_device *radio = i2c_get_clientdata(client);
/* power up : need 110ms */
radio->registers[POWERCFG] |= POWERCFG_ENABLE;
if (si470x_set_register(radio, POWERCFG) < 0)
return -EIO;
msleep(110);
return 0;
}
#else
#define si470x_i2c_suspend NULL
#define si470x_i2c_resume NULL
#endif
/*
* si470x_i2c_driver - i2c driver interface
*/
@ -364,6 +535,8 @@ static struct i2c_driver si470x_i2c_driver = {
},
.probe = si470x_i2c_probe,
.remove = __devexit_p(si470x_i2c_remove),
.suspend = si470x_i2c_suspend,
.resume = si470x_i2c_resume,
.id_table = si470x_i2c_id,
};

View file

@ -508,90 +508,10 @@ resubmit:
* File Operations Interface
**************************************************************************/
/*
* si470x_fops_read - read RDS data
*/
static ssize_t si470x_fops_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
unsigned int block_count = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
si470x_rds_on(radio);
/* block if no new data available */
while (radio->wr_index == radio->rd_index) {
if (file->f_flags & O_NONBLOCK) {
retval = -EWOULDBLOCK;
goto done;
}
if (wait_event_interruptible(radio->read_queue,
radio->wr_index != radio->rd_index) < 0) {
retval = -EINTR;
goto done;
}
}
/* calculate block count from byte count */
count /= 3;
/* copy RDS block out of internal buffer and to user buffer */
mutex_lock(&radio->lock);
while (block_count < count) {
if (radio->rd_index == radio->wr_index)
break;
/* always transfer rds complete blocks */
if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
/* retval = -EFAULT; */
break;
/* increment and wrap read pointer */
radio->rd_index += 3;
if (radio->rd_index >= radio->buf_size)
radio->rd_index = 0;
/* increment counters */
block_count++;
buf += 3;
retval += 3;
}
mutex_unlock(&radio->lock);
done:
return retval;
}
/*
* si470x_fops_poll - poll RDS data
*/
static unsigned int si470x_fops_poll(struct file *file,
struct poll_table_struct *pts)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
/* switch on rds reception */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
si470x_rds_on(radio);
poll_wait(file, &radio->read_queue, pts);
if (radio->rd_index != radio->wr_index)
retval = POLLIN | POLLRDNORM;
return retval;
}
/*
* si470x_fops_open - file open
*/
static int si470x_fops_open(struct file *file)
int si470x_fops_open(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval;
@ -645,7 +565,7 @@ done:
/*
* si470x_fops_release - file release
*/
static int si470x_fops_release(struct file *file)
int si470x_fops_release(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
@ -688,19 +608,6 @@ done:
}
/*
* si470x_fops - file operations interface
*/
const struct v4l2_file_operations si470x_fops = {
.owner = THIS_MODULE,
.read = si470x_fops_read,
.poll = si470x_fops_poll,
.ioctl = video_ioctl2,
.open = si470x_fops_open,
.release = si470x_fops_release,
};
/**************************************************************************
* Video4Linux Interface

View file

@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/input.h>
@ -181,6 +182,7 @@ struct si470x_device {
#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
struct i2c_client *client;
struct work_struct radio_work;
#endif
};
@ -212,7 +214,6 @@ struct si470x_device {
/**************************************************************************
* Common Functions
**************************************************************************/
extern const struct v4l2_file_operations si470x_fops;
extern struct video_device si470x_viddev_template;
int si470x_get_register(struct si470x_device *radio, int regnr);
int si470x_set_register(struct si470x_device *radio, int regnr);
@ -221,5 +222,7 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq);
int si470x_start(struct si470x_device *radio);
int si470x_stop(struct si470x_device *radio);
int si470x_rds_on(struct si470x_device *radio);
int si470x_fops_open(struct file *file);
int si470x_fops_release(struct file *file);
int si470x_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *capability);

View file

@ -37,10 +37,6 @@ config VIDEO_BTCX
depends on PCI
tristate
config VIDEO_IR
tristate
depends on INPUT
config VIDEO_TVEEPROM
tristate
depends on I2C
@ -840,6 +836,12 @@ config SOC_CAMERA_MT9T031
help
This driver supports MT9T031 cameras from Micron.
config SOC_CAMERA_MT9T112
tristate "mt9t112 support"
depends on SOC_CAMERA && I2C
help
This driver supports MT9T112 cameras from Aptina.
config SOC_CAMERA_MT9V022
tristate "mt9v022 support"
depends on SOC_CAMERA && I2C

View file

@ -75,6 +75,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o
obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o
obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o
@ -149,7 +150,7 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o
obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o
obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
# soc-camera host drivers have to be linked after camera drivers
obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o

View file

@ -767,7 +767,6 @@ static struct video_device ar_template = {
.name = "Colour AR VGA",
.fops = &ar_fops,
.release = ar_release,
.minor = -1,
};
#define ALIGN4(x) ((((int)(x)) & 0x3) == 0)
@ -860,8 +859,8 @@ static int __init ar_init(void)
goto out_dev;
}
printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
ar->vdev->num, M32R_IRQ_INT3, freq);
printk("%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq);
return 0;

View file

@ -40,7 +40,6 @@
#include "au0828.h"
#include "au0828-reg.h"
static LIST_HEAD(au0828_devlist);
static DEFINE_MUTEX(au0828_sysfs_lock);
#define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
@ -693,10 +692,8 @@ void au0828_analog_unregister(struct au0828_dev *dev)
dprintk(1, "au0828_release_resources called\n");
mutex_lock(&au0828_sysfs_lock);
if (dev->vdev) {
list_del(&dev->au0828list);
if (dev->vdev)
video_unregister_device(dev->vdev);
}
if (dev->vbi_dev)
video_unregister_device(dev->vbi_dev);
@ -737,29 +734,15 @@ static void res_free(struct au0828_fh *fh)
static int au0828_v4l2_open(struct file *filp)
{
int minor = video_devdata(filp)->minor;
int ret = 0;
struct au0828_dev *h, *dev = NULL;
struct au0828_dev *dev = video_drvdata(filp);
struct au0828_fh *fh;
int type = 0;
struct list_head *list;
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
list_for_each(list, &au0828_devlist) {
h = list_entry(list, struct au0828_dev, au0828list);
if (h->vdev->minor == minor) {
dev = h;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
}
#ifdef VBI_IS_WORKING
if (h->vbi_dev->minor == minor) {
dev = h;
type = V4L2_BUF_TYPE_VBI_CAPTURE;
}
if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER)
type = V4L2_BUF_TYPE_VBI_CAPTURE;
#endif
}
if (NULL == dev)
return -ENODEV;
fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
if (NULL == fh) {
@ -1587,7 +1570,6 @@ static const struct video_device au0828_video_template = {
.fops = &au0828_v4l_fops,
.release = video_device_release,
.ioctl_ops = &video_ioctl_ops,
.minor = -1,
.tvnorms = V4L2_STD_NTSC_M,
.current_norm = V4L2_STD_NTSC_M,
};
@ -1676,25 +1658,23 @@ int au0828_analog_register(struct au0828_dev *dev,
strcpy(dev->vbi_dev->name, "au0828a vbi");
#endif
list_add_tail(&dev->au0828list, &au0828_devlist);
/* Register the v4l2 device */
video_set_drvdata(dev->vdev, dev);
retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
if (retval != 0) {
dprintk(1, "unable to register video device (error = %d).\n",
retval);
list_del(&dev->au0828list);
video_device_release(dev->vdev);
return -ENODEV;
}
#ifdef VBI_IS_WORKING
/* Register the vbi device */
video_set_drvdata(dev->vbi_dev, dev);
retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
if (retval != 0) {
dprintk(1, "unable to register vbi device (error = %d).\n",
retval);
list_del(&dev->au0828list);
video_device_release(dev->vbi_dev);
video_device_release(dev->vdev);
return -ENODEV;

View file

@ -192,7 +192,6 @@ struct au0828_dev {
struct au0828_dvb dvb;
/* Analog */
struct list_head au0828list;
struct v4l2_device v4l2_dev;
int users;
unsigned int stream_on:1; /* Locks streams */

View file

@ -3206,24 +3206,24 @@ err:
static int bttv_open(struct file *file)
{
int minor = video_devdata(file)->minor;
struct video_device *vdev = video_devdata(file);
struct bttv *btv = video_drvdata(file);
struct bttv_fh *fh;
enum v4l2_buf_type type = 0;
dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
lock_kernel();
if (btv->video_dev->minor == minor) {
if (vdev->vfl_type == VFL_TYPE_GRABBER) {
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
} else if (btv->vbi_dev->minor == minor) {
} else if (vdev->vfl_type == VFL_TYPE_VBI) {
type = V4L2_BUF_TYPE_VBI_CAPTURE;
} else {
WARN_ON(1);
unlock_kernel();
return -ENODEV;
}
lock_kernel();
dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
btv->c.nr,v4l2_type_names[type]);
@ -3397,7 +3397,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
static struct video_device bttv_video_template = {
.fops = &bttv_fops,
.minor = -1,
.ioctl_ops = &bttv_ioctl_ops,
.tvnorms = BTTV_NORMS,
.current_norm = V4L2_STD_PAL,
@ -3408,18 +3407,13 @@ static struct video_device bttv_video_template = {
static int radio_open(struct file *file)
{
int minor = video_devdata(file)->minor;
struct video_device *vdev = video_devdata(file);
struct bttv *btv = video_drvdata(file);
struct bttv_fh *fh;
dprintk("bttv: open minor=%d\n",minor);
dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
lock_kernel();
WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor);
if (!btv->radio_dev || btv->radio_dev->minor != minor) {
unlock_kernel();
return -ENODEV;
}
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
@ -3640,7 +3634,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
static struct video_device radio_template = {
.fops = &radio_fops,
.minor = -1,
.ioctl_ops = &radio_ioctl_ops,
};
@ -4208,21 +4201,21 @@ static struct video_device *vdev_init(struct bttv *btv,
static void bttv_unregister_video(struct bttv *btv)
{
if (btv->video_dev) {
if (-1 != btv->video_dev->minor)
if (video_is_registered(btv->video_dev))
video_unregister_device(btv->video_dev);
else
video_device_release(btv->video_dev);
btv->video_dev = NULL;
}
if (btv->vbi_dev) {
if (-1 != btv->vbi_dev->minor)
if (video_is_registered(btv->vbi_dev))
video_unregister_device(btv->vbi_dev);
else
video_device_release(btv->vbi_dev);
btv->vbi_dev = NULL;
}
if (btv->radio_dev) {
if (-1 != btv->radio_dev->minor)
if (video_is_registered(btv->radio_dev))
video_unregister_device(btv->radio_dev);
else
video_device_release(btv->radio_dev);
@ -4244,8 +4237,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
video_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device video%d\n",
btv->c.nr, btv->video_dev->num);
printk(KERN_INFO "bttv%d: registered device %s\n",
btv->c.nr, video_device_node_name(btv->video_dev));
if (device_create_file(&btv->video_dev->dev,
&dev_attr_card)<0) {
printk(KERN_ERR "bttv%d: device_create_file 'card' "
@ -4261,8 +4254,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
vbi_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device vbi%d\n",
btv->c.nr, btv->vbi_dev->num);
printk(KERN_INFO "bttv%d: registered device %s\n",
btv->c.nr, video_device_node_name(btv->vbi_dev));
if (!btv->has_radio)
return 0;
@ -4273,8 +4266,8 @@ static int __devinit bttv_register_video(struct bttv *btv)
if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
radio_nr[btv->c.nr]) < 0)
goto err;
printk(KERN_INFO "bttv%d: registered device radio%d\n",
btv->c.nr, btv->radio_dev->num);
printk(KERN_INFO "bttv%d: registered device %s\n",
btv->c.nr, video_device_node_name(btv->radio_dev));
/* all done */
return 0;

View file

@ -40,7 +40,7 @@ static int i2c_debug;
static int i2c_hw;
static int i2c_scan;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_hw,"configure i2c debug level");
MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
module_param(i2c_hw, int, 0444);
MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
"instead of software bitbang");
@ -400,7 +400,7 @@ int __devinit init_bttv_i2c(struct bttv *btv)
That's why we probe 0x1a (~0x34) first. CB
*/
const unsigned short addr_list[] = {
0x1a, 0x18, 0x4b, 0x64, 0x30,
0x1a, 0x18, 0x4b, 0x64, 0x30, 0x71,
I2C_CLIENT_END
};

View file

@ -368,7 +368,7 @@ int bttv_input_init(struct bttv *btv)
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
pci_name(btv->c.pci));
err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
err = ir_input_init(input_dev, &ir->ir, ir_type);
if (err < 0)
goto err_out_free;
@ -389,7 +389,7 @@ int bttv_input_init(struct bttv *btv)
bttv_ir_start(btv, ir);
/* all done */
err = input_register_device(btv->remote->dev);
err = ir_input_register(btv->remote->dev, ir_codes);
if (err)
goto err_out_stop;
@ -403,8 +403,6 @@ int bttv_input_init(struct bttv *btv)
bttv_ir_stop(btv);
btv->remote = NULL;
err_out_free:
ir_input_free(input_dev);
input_free_device(input_dev);
kfree(ir);
return err;
}
@ -415,8 +413,7 @@ void bttv_input_fini(struct bttv *btv)
return;
bttv_ir_stop(btv);
ir_input_free(btv->remote->dev);
input_unregister_device(btv->remote->dev);
ir_input_unregister(btv->remote->dev);
kfree(btv->remote);
btv->remote = NULL;
}

View file

@ -809,8 +809,8 @@ static int init_cqcam(struct parport *port)
return -ENODEV;
}
printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
qcam->vdev.num, qcam->pport->name);
printk(KERN_INFO "%s: Colour QuickCam found on %s\n",
video_device_node_name(&qcam->vdev), qcam->pport->name);
qcams[num_cams++] = qcam;

View file

@ -1723,7 +1723,6 @@ static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
static struct video_device cafe_v4l_template = {
.name = "cafe",
.minor = -1, /* Get one dynamically */
.tvnorms = V4L2_STD_NTSC_M,
.current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */

View file

@ -32,6 +32,7 @@
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
@ -244,72 +245,67 @@ static void rvfree(void *mem, unsigned long size)
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *cpia_proc_root=NULL;
static int cpia_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
static int cpia_proc_show(struct seq_file *m, void *v)
{
char *out = page;
int len, tmp;
struct cam_data *cam = data;
struct cam_data *cam = m->private;
int tmp;
char tmpstr[29];
/* IMPORTANT: This output MUST be kept under PAGE_SIZE
* or we need to get more sophisticated. */
out += sprintf(out, "read-only\n-----------------------\n");
out += sprintf(out, "V4L Driver version: %d.%d.%d\n",
seq_printf(m, "read-only\n-----------------------\n");
seq_printf(m, "V4L Driver version: %d.%d.%d\n",
CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
out += sprintf(out, "CPIA Version: %d.%02d (%d.%d)\n",
seq_printf(m, "CPIA Version: %d.%02d (%d.%d)\n",
cam->params.version.firmwareVersion,
cam->params.version.firmwareRevision,
cam->params.version.vcVersion,
cam->params.version.vcRevision);
out += sprintf(out, "CPIA PnP-ID: %04x:%04x:%04x\n",
seq_printf(m, "CPIA PnP-ID: %04x:%04x:%04x\n",
cam->params.pnpID.vendor, cam->params.pnpID.product,
cam->params.pnpID.deviceRevision);
out += sprintf(out, "VP-Version: %d.%d %04x\n",
seq_printf(m, "VP-Version: %d.%d %04x\n",
cam->params.vpVersion.vpVersion,
cam->params.vpVersion.vpRevision,
cam->params.vpVersion.cameraHeadID);
out += sprintf(out, "system_state: %#04x\n",
seq_printf(m, "system_state: %#04x\n",
cam->params.status.systemState);
out += sprintf(out, "grab_state: %#04x\n",
seq_printf(m, "grab_state: %#04x\n",
cam->params.status.grabState);
out += sprintf(out, "stream_state: %#04x\n",
seq_printf(m, "stream_state: %#04x\n",
cam->params.status.streamState);
out += sprintf(out, "fatal_error: %#04x\n",
seq_printf(m, "fatal_error: %#04x\n",
cam->params.status.fatalError);
out += sprintf(out, "cmd_error: %#04x\n",
seq_printf(m, "cmd_error: %#04x\n",
cam->params.status.cmdError);
out += sprintf(out, "debug_flags: %#04x\n",
seq_printf(m, "debug_flags: %#04x\n",
cam->params.status.debugFlags);
out += sprintf(out, "vp_status: %#04x\n",
seq_printf(m, "vp_status: %#04x\n",
cam->params.status.vpStatus);
out += sprintf(out, "error_code: %#04x\n",
seq_printf(m, "error_code: %#04x\n",
cam->params.status.errorCode);
/* QX3 specific entries */
if (cam->params.qx3.qx3_detected) {
out += sprintf(out, "button: %4d\n",
seq_printf(m, "button: %4d\n",
cam->params.qx3.button);
out += sprintf(out, "cradled: %4d\n",
seq_printf(m, "cradled: %4d\n",
cam->params.qx3.cradled);
}
out += sprintf(out, "video_size: %s\n",
seq_printf(m, "video_size: %s\n",
cam->params.format.videoSize == VIDEOSIZE_CIF ?
"CIF " : "QCIF");
out += sprintf(out, "roi: (%3d, %3d) to (%3d, %3d)\n",
seq_printf(m, "roi: (%3d, %3d) to (%3d, %3d)\n",
cam->params.roi.colStart*8,
cam->params.roi.rowStart*4,
cam->params.roi.colEnd*8,
cam->params.roi.rowEnd*4);
out += sprintf(out, "actual_fps: %3d\n", cam->fps);
out += sprintf(out, "transfer_rate: %4dkB/s\n",
seq_printf(m, "actual_fps: %3d\n", cam->fps);
seq_printf(m, "transfer_rate: %4dkB/s\n",
cam->transfer_rate);
out += sprintf(out, "\nread-write\n");
out += sprintf(out, "----------------------- current min"
seq_printf(m, "\nread-write\n");
seq_printf(m, "----------------------- current min"
" max default comment\n");
out += sprintf(out, "brightness: %8d %8d %8d %8d\n",
seq_printf(m, "brightness: %8d %8d %8d %8d\n",
cam->params.colourParams.brightness, 0, 100, 50);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
@ -318,26 +314,26 @@ static int cpia_read_proc(char *page, char **start, off_t off,
else
tmp = 96;
out += sprintf(out, "contrast: %8d %8d %8d %8d"
seq_printf(m, "contrast: %8d %8d %8d %8d"
" steps of 8\n",
cam->params.colourParams.contrast, 0, tmp, 48);
out += sprintf(out, "saturation: %8d %8d %8d %8d\n",
seq_printf(m, "saturation: %8d %8d %8d %8d\n",
cam->params.colourParams.saturation, 0, 100, 50);
tmp = (25000+5000*cam->params.sensorFps.baserate)/
(1<<cam->params.sensorFps.divisor);
out += sprintf(out, "sensor_fps: %4d.%03d %8d %8d %8d\n",
seq_printf(m, "sensor_fps: %4d.%03d %8d %8d %8d\n",
tmp/1000, tmp%1000, 3, 30, 15);
out += sprintf(out, "stream_start_line: %8d %8d %8d %8d\n",
seq_printf(m, "stream_start_line: %8d %8d %8d %8d\n",
2*cam->params.streamStartLine, 0,
cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
out += sprintf(out, "sub_sample: %8s %8s %8s %8s\n",
seq_printf(m, "sub_sample: %8s %8s %8s %8s\n",
cam->params.format.subSample == SUBSAMPLE_420 ?
"420" : "422", "420", "422", "422");
out += sprintf(out, "yuv_order: %8s %8s %8s %8s\n",
seq_printf(m, "yuv_order: %8s %8s %8s %8s\n",
cam->params.format.yuvOrder == YUVORDER_YUYV ?
"YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV");
out += sprintf(out, "ecp_timing: %8s %8s %8s %8s\n",
seq_printf(m, "ecp_timing: %8s %8s %8s %8s\n",
cam->params.ecpTiming ? "slow" : "normal", "slow",
"normal", "normal");
@ -346,13 +342,13 @@ static int cpia_read_proc(char *page, char **start, off_t off,
} else {
sprintf(tmpstr, "manual");
}
out += sprintf(out, "color_balance_mode: %8s %8s %8s"
seq_printf(m, "color_balance_mode: %8s %8s %8s"
" %8s\n", tmpstr, "manual", "auto", "auto");
out += sprintf(out, "red_gain: %8d %8d %8d %8d\n",
seq_printf(m, "red_gain: %8d %8d %8d %8d\n",
cam->params.colourBalance.redGain, 0, 212, 32);
out += sprintf(out, "green_gain: %8d %8d %8d %8d\n",
seq_printf(m, "green_gain: %8d %8d %8d %8d\n",
cam->params.colourBalance.greenGain, 0, 212, 6);
out += sprintf(out, "blue_gain: %8d %8d %8d %8d\n",
seq_printf(m, "blue_gain: %8d %8d %8d %8d\n",
cam->params.colourBalance.blueGain, 0, 212, 92);
if (cam->params.version.firmwareVersion == 1 &&
@ -363,10 +359,10 @@ static int cpia_read_proc(char *page, char **start, off_t off,
sprintf(tmpstr, "%8d %8d %8d", 1, 8, 2);
if (cam->params.exposure.gainMode == 0)
out += sprintf(out, "max_gain: unknown %28s"
seq_printf(m, "max_gain: unknown %28s"
" powers of 2\n", tmpstr);
else
out += sprintf(out, "max_gain: %8d %28s"
seq_printf(m, "max_gain: %8d %28s"
" 1,2,4 or 8 \n",
1<<(cam->params.exposure.gainMode-1), tmpstr);
@ -382,12 +378,12 @@ static int cpia_read_proc(char *page, char **start, off_t off,
sprintf(tmpstr, "unknown");
break;
}
out += sprintf(out, "exposure_mode: %8s %8s %8s"
seq_printf(m, "exposure_mode: %8s %8s %8s"
" %8s\n", tmpstr, "manual", "auto", "auto");
out += sprintf(out, "centre_weight: %8s %8s %8s %8s\n",
seq_printf(m, "centre_weight: %8s %8s %8s %8s\n",
(2-cam->params.exposure.centreWeight) ? "on" : "off",
"off", "on", "on");
out += sprintf(out, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
seq_printf(m, "gain: %8d %8d max_gain %8d 1,2,4,8 possible\n",
1<<cam->params.exposure.gain, 1, 1);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
@ -396,7 +392,7 @@ static int cpia_read_proc(char *page, char **start, off_t off,
else
tmp = 510;
out += sprintf(out, "fine_exp: %8d %8d %8d %8d\n",
seq_printf(m, "fine_exp: %8d %8d %8d %8d\n",
cam->params.exposure.fineExp*2, 0, tmp, 0);
if (cam->params.version.firmwareVersion == 1 &&
cam->params.version.firmwareRevision == 2)
@ -405,127 +401,122 @@ static int cpia_read_proc(char *page, char **start, off_t off,
else
tmp = MAX_EXP;
out += sprintf(out, "coarse_exp: %8d %8d %8d"
seq_printf(m, "coarse_exp: %8d %8d %8d"
" %8d\n", cam->params.exposure.coarseExpLo+
256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
out += sprintf(out, "red_comp: %8d %8d %8d %8d\n",
seq_printf(m, "red_comp: %8d %8d %8d %8d\n",
cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
out += sprintf(out, "green1_comp: %8d %8d %8d %8d\n",
seq_printf(m, "green1_comp: %8d %8d %8d %8d\n",
cam->params.exposure.green1Comp, COMP_GREEN1, 255,
COMP_GREEN1);
out += sprintf(out, "green2_comp: %8d %8d %8d %8d\n",
seq_printf(m, "green2_comp: %8d %8d %8d %8d\n",
cam->params.exposure.green2Comp, COMP_GREEN2, 255,
COMP_GREEN2);
out += sprintf(out, "blue_comp: %8d %8d %8d %8d\n",
seq_printf(m, "blue_comp: %8d %8d %8d %8d\n",
cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
out += sprintf(out, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
seq_printf(m, "apcor_gain1: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain1, 0, 0xff, 0x1c);
out += sprintf(out, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
seq_printf(m, "apcor_gain2: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain2, 0, 0xff, 0x1a);
out += sprintf(out, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
seq_printf(m, "apcor_gain4: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain4, 0, 0xff, 0x2d);
out += sprintf(out, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
seq_printf(m, "apcor_gain8: %#8x %#8x %#8x %#8x\n",
cam->params.apcor.gain8, 0, 0xff, 0x2a);
out += sprintf(out, "vl_offset_gain1: %8d %8d %8d %8d\n",
seq_printf(m, "vl_offset_gain1: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain1, 0, 255, 24);
out += sprintf(out, "vl_offset_gain2: %8d %8d %8d %8d\n",
seq_printf(m, "vl_offset_gain2: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain2, 0, 255, 28);
out += sprintf(out, "vl_offset_gain4: %8d %8d %8d %8d\n",
seq_printf(m, "vl_offset_gain4: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain4, 0, 255, 30);
out += sprintf(out, "vl_offset_gain8: %8d %8d %8d %8d\n",
seq_printf(m, "vl_offset_gain8: %8d %8d %8d %8d\n",
cam->params.vlOffset.gain8, 0, 255, 30);
out += sprintf(out, "flicker_control: %8s %8s %8s %8s\n",
seq_printf(m, "flicker_control: %8s %8s %8s %8s\n",
cam->params.flickerControl.flickerMode ? "on" : "off",
"off", "on", "off");
out += sprintf(out, "mains_frequency: %8d %8d %8d %8d"
seq_printf(m, "mains_frequency: %8d %8d %8d %8d"
" only 50/60\n",
cam->mainsFreq ? 60 : 50, 50, 60, 50);
if(cam->params.flickerControl.allowableOverExposure < 0)
out += sprintf(out, "allowable_overexposure: %4dauto auto %8d auto\n",
seq_printf(m, "allowable_overexposure: %4dauto auto %8d auto\n",
-cam->params.flickerControl.allowableOverExposure,
255);
else
out += sprintf(out, "allowable_overexposure: %8d auto %8d auto\n",
seq_printf(m, "allowable_overexposure: %8d auto %8d auto\n",
cam->params.flickerControl.allowableOverExposure,
255);
out += sprintf(out, "compression_mode: ");
seq_printf(m, "compression_mode: ");
switch(cam->params.compression.mode) {
case CPIA_COMPRESSION_NONE:
out += sprintf(out, "%8s", "none");
seq_printf(m, "%8s", "none");
break;
case CPIA_COMPRESSION_AUTO:
out += sprintf(out, "%8s", "auto");
seq_printf(m, "%8s", "auto");
break;
case CPIA_COMPRESSION_MANUAL:
out += sprintf(out, "%8s", "manual");
seq_printf(m, "%8s", "manual");
break;
default:
out += sprintf(out, "%8s", "unknown");
seq_printf(m, "%8s", "unknown");
break;
}
out += sprintf(out, " none,auto,manual auto\n");
out += sprintf(out, "decimation_enable: %8s %8s %8s %8s\n",
seq_printf(m, " none,auto,manual auto\n");
seq_printf(m, "decimation_enable: %8s %8s %8s %8s\n",
cam->params.compression.decimation ==
DECIMATION_ENAB ? "on":"off", "off", "on",
"off");
out += sprintf(out, "compression_target: %9s %9s %9s %9s\n",
seq_printf(m, "compression_target: %9s %9s %9s %9s\n",
cam->params.compressionTarget.frTargeting ==
CPIA_COMPRESSION_TARGET_FRAMERATE ?
"framerate":"quality",
"framerate", "quality", "quality");
out += sprintf(out, "target_framerate: %8d %8d %8d %8d\n",
seq_printf(m, "target_framerate: %8d %8d %8d %8d\n",
cam->params.compressionTarget.targetFR, 1, 30, 15);
out += sprintf(out, "target_quality: %8d %8d %8d %8d\n",
seq_printf(m, "target_quality: %8d %8d %8d %8d\n",
cam->params.compressionTarget.targetQ, 1, 64, 5);
out += sprintf(out, "y_threshold: %8d %8d %8d %8d\n",
seq_printf(m, "y_threshold: %8d %8d %8d %8d\n",
cam->params.yuvThreshold.yThreshold, 0, 31, 6);
out += sprintf(out, "uv_threshold: %8d %8d %8d %8d\n",
seq_printf(m, "uv_threshold: %8d %8d %8d %8d\n",
cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
out += sprintf(out, "hysteresis: %8d %8d %8d %8d\n",
seq_printf(m, "hysteresis: %8d %8d %8d %8d\n",
cam->params.compressionParams.hysteresis, 0, 255, 3);
out += sprintf(out, "threshold_max: %8d %8d %8d %8d\n",
seq_printf(m, "threshold_max: %8d %8d %8d %8d\n",
cam->params.compressionParams.threshMax, 0, 255, 11);
out += sprintf(out, "small_step: %8d %8d %8d %8d\n",
seq_printf(m, "small_step: %8d %8d %8d %8d\n",
cam->params.compressionParams.smallStep, 0, 255, 1);
out += sprintf(out, "large_step: %8d %8d %8d %8d\n",
seq_printf(m, "large_step: %8d %8d %8d %8d\n",
cam->params.compressionParams.largeStep, 0, 255, 3);
out += sprintf(out, "decimation_hysteresis: %8d %8d %8d %8d\n",
seq_printf(m, "decimation_hysteresis: %8d %8d %8d %8d\n",
cam->params.compressionParams.decimationHysteresis,
0, 255, 2);
out += sprintf(out, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
seq_printf(m, "fr_diff_step_thresh: %8d %8d %8d %8d\n",
cam->params.compressionParams.frDiffStepThresh,
0, 255, 5);
out += sprintf(out, "q_diff_step_thresh: %8d %8d %8d %8d\n",
seq_printf(m, "q_diff_step_thresh: %8d %8d %8d %8d\n",
cam->params.compressionParams.qDiffStepThresh,
0, 255, 3);
out += sprintf(out, "decimation_thresh_mod: %8d %8d %8d %8d\n",
seq_printf(m, "decimation_thresh_mod: %8d %8d %8d %8d\n",
cam->params.compressionParams.decimationThreshMod,
0, 255, 2);
/* QX3 specific entries */
if (cam->params.qx3.qx3_detected) {
out += sprintf(out, "toplight: %8s %8s %8s %8s\n",
seq_printf(m, "toplight: %8s %8s %8s %8s\n",
cam->params.qx3.toplight ? "on" : "off",
"off", "on", "off");
out += sprintf(out, "bottomlight: %8s %8s %8s %8s\n",
seq_printf(m, "bottomlight: %8s %8s %8s %8s\n",
cam->params.qx3.bottomlight ? "on" : "off",
"off", "on", "off");
}
len = out - page;
len -= off;
if (len < count) {
*eof = 1;
if (len <= 0) return 0;
} else
len = count;
*start = page + off;
return len;
return 0;
}
static int cpia_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, cpia_proc_show, PDE(inode)->data);
}
static int match(char *checkstr, char **buffer, unsigned long *count,
static int match(char *checkstr, char **buffer, size_t *count,
int *find_colon, int *err)
{
int ret, colon_found = 1;
@ -551,7 +542,7 @@ static int match(char *checkstr, char **buffer, unsigned long *count,
return ret;
}
static unsigned long int value(char **buffer, unsigned long *count, int *err)
static unsigned long int value(char **buffer, size_t *count, int *err)
{
char *p;
unsigned long int ret;
@ -565,10 +556,10 @@ static unsigned long int value(char **buffer, unsigned long *count, int *err)
return ret;
}
static int cpia_write_proc(struct file *file, const char __user *buf,
unsigned long count, void *data)
static ssize_t cpia_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
struct cam_data *cam = data;
struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data;
struct cam_params new_params;
char *page, *buffer;
int retval, find_colon;
@ -582,7 +573,7 @@ static int cpia_write_proc(struct file *file, const char __user *buf,
* from the comx driver
*/
if (count > PAGE_SIZE) {
printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE);
printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE);
return -ENOSPC;
}
@ -1340,23 +1331,28 @@ out:
return retval;
}
static const struct file_operations cpia_proc_fops = {
.owner = THIS_MODULE,
.open = cpia_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.write = cpia_proc_write,
};
static void create_proc_cpia_cam(struct cam_data *cam)
{
char name[5 + 1 + 10 + 1];
struct proc_dir_entry *ent;
if (!cpia_proc_root || !cam)
return;
snprintf(name, sizeof(name), "video%d", cam->vdev.num);
ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
ent = proc_create_data(video_device_node_name(&cam->vdev),
S_IRUGO|S_IWUSR, cpia_proc_root,
&cpia_proc_fops, cam);
if (!ent)
return;
ent->data = cam;
ent->read_proc = cpia_read_proc;
ent->write_proc = cpia_write_proc;
/*
size of the proc entry is 3736 bytes for the standard webcam;
the extra features of the QX3 microscope add 189 bytes.
@ -1368,13 +1364,10 @@ static void create_proc_cpia_cam(struct cam_data *cam)
static void destroy_proc_cpia_cam(struct cam_data *cam)
{
char name[5 + 1 + 10 + 1];
if (!cam || !cam->proc_entry)
return;
snprintf(name, sizeof(name), "video%d", cam->vdev.num);
remove_proc_entry(name, cpia_proc_root);
remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root);
cam->proc_entry = NULL;
}
@ -3999,7 +3992,7 @@ void cpia_unregister_camera(struct cam_data *cam)
}
#ifdef CONFIG_PROC_FS
DBG("destroying /proc/cpia/video%d\n", cam->vdev.num);
DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev));
destroy_proc_cpia_cam(cam);
#endif
if (!cam->open_count) {

View file

@ -38,17 +38,12 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/videodev.h>
#include <linux/stringify.h>
#include <media/v4l2-ioctl.h>
#include "cpia2.h"
#include "cpia2dev.h"
//#define _CPIA2_DEBUG_
#define MAKE_STRING_1(x) #x
#define MAKE_STRING(x) MAKE_STRING_1(x)
static int video_nr = -1;
module_param(video_nr, int, 0);
MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)");
@ -60,26 +55,26 @@ MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)
static int num_buffers = 3;
module_param(num_buffers, int, 0);
MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-"
MAKE_STRING(VIDEO_MAX_FRAME) ", default 3)");
__stringify(VIDEO_MAX_FRAME) ", default 3)");
static int alternate = DEFAULT_ALT;
module_param(alternate, int, 0);
MODULE_PARM_DESC(alternate, "USB Alternate (" MAKE_STRING(USBIF_ISO_1) "-"
MAKE_STRING(USBIF_ISO_6) ", default "
MAKE_STRING(DEFAULT_ALT) ")");
MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-"
__stringify(USBIF_ISO_6) ", default "
__stringify(DEFAULT_ALT) ")");
static int flicker_freq = 60;
module_param(flicker_freq, int, 0);
MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" MAKE_STRING(50) "or"
MAKE_STRING(60) ", default "
MAKE_STRING(60) ")");
MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" __stringify(50) "or"
__stringify(60) ", default "
__stringify(60) ")");
static int flicker_mode = NEVER_FLICKER;
module_param(flicker_mode, int, 0);
MODULE_PARM_DESC(flicker_mode,
"Flicker supression (" MAKE_STRING(NEVER_FLICKER) "or"
MAKE_STRING(ANTI_FLICKER_ON) ", default "
MAKE_STRING(NEVER_FLICKER) ")");
"Flicker supression (" __stringify(NEVER_FLICKER) "or"
__stringify(ANTI_FLICKER_ON) ", default "
__stringify(NEVER_FLICKER) ")");
MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
@ -1926,7 +1921,6 @@ static const struct v4l2_file_operations fops_template = {
static struct video_device cpia2_template = {
/* I could not find any place for the old .initialize initializer?? */
.name= "CPiA2 Camera",
.minor= -1,
.fops= &fops_template,
.release= video_device_release,
};
@ -1967,9 +1961,9 @@ void cpia2_unregister_camera(struct camera_data *cam)
if (!cam->open_count) {
video_unregister_device(cam->vdev);
} else {
LOG("/dev/video%d removed while open, "
"deferring video_unregister_device\n",
cam->vdev->num);
LOG("%s removed while open, deferring "
"video_unregister_device\n",
video_device_node_name(cam->vdev));
}
}

View file

@ -758,8 +758,8 @@ int cx18_v4l2_open(struct file *filp)
mutex_lock(&cx->serialize_lock);
if (cx18_init_on_first_open(cx)) {
CX18_ERR("Failed to initialize on minor %d\n",
video_dev->minor);
CX18_ERR("Failed to initialize on %s\n",
video_device_node_name(video_dev));
mutex_unlock(&cx->serialize_lock);
return -ENXIO;
}

View file

@ -219,6 +219,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
{
struct cx18_stream *s = &cx->streams[type];
int vfl_type = cx18_stream_info[type].vfl_type;
const char *name;
int num, ret;
/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
@ -258,31 +259,30 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
s->video_dev = NULL;
return ret;
}
num = s->video_dev->num;
name = video_device_node_name(s->video_dev);
switch (vfl_type) {
case VFL_TYPE_GRABBER:
CX18_INFO("Registered device video%d for %s "
"(%d x %d.%02d kB)\n",
num, s->name, cx->stream_buffers[type],
CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
name, s->name, cx->stream_buffers[type],
cx->stream_buf_size[type] / 1024,
(cx->stream_buf_size[type] * 100 / 1024) % 100);
break;
case VFL_TYPE_RADIO:
CX18_INFO("Registered device radio%d for %s\n",
num, s->name);
CX18_INFO("Registered device %s for %s\n", name, s->name);
break;
case VFL_TYPE_VBI:
if (cx->stream_buffers[type])
CX18_INFO("Registered device vbi%d for %s "
CX18_INFO("Registered device %s for %s "
"(%d x %d bytes)\n",
num, s->name, cx->stream_buffers[type],
name, s->name, cx->stream_buffers[type],
cx->stream_buf_size[type]);
else
CX18_INFO("Registered device vbi%d for %s\n",
num, s->name);
CX18_INFO("Registered device %s for %s\n",
name, s->name);
break;
}

View file

@ -68,19 +68,19 @@ struct cx231xx_board cx231xx_boards[] = {
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_3_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = 0,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = 0,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
(CX231XX_VIN_1_2 << 8) |
CX25840_SVIDEO_ON,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = 0,
.gpio = NULL,
}
},
},
@ -107,19 +107,19 @@ struct cx231xx_board cx231xx_boards[] = {
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_3_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = 0,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = 0,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
(CX231XX_VIN_1_2 << 8) |
CX25840_SVIDEO_ON,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = 0,
.gpio = NULL,
}
},
},
@ -147,19 +147,19 @@ struct cx231xx_board cx231xx_boards[] = {
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_3_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = 0,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = 0,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
(CX231XX_VIN_1_2 << 8) |
CX25840_SVIDEO_ON,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = 0,
.gpio = NULL,
}
},
},
@ -856,8 +856,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
if (dev->users) {
cx231xx_warn
("device /dev/video%d is open! Deregistration and memory "
"deallocation are deferred on close.\n", dev->vdev->num);
("device %s is open! Deregistration and memory "
"deallocation are deferred on close.\n",
video_device_node_name(dev->vdev));
dev->state |= DEV_MISCONFIGURED;
cx231xx_uninit_isoc(dev);

View file

@ -66,32 +66,6 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
static LIST_HEAD(cx231xx_devlist);
static DEFINE_MUTEX(cx231xx_devlist_mutex);
struct cx231xx *cx231xx_get_device(int minor,
enum v4l2_buf_type *fh_type, int *has_radio)
{
struct cx231xx *h, *dev = NULL;
*fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
*has_radio = 0;
mutex_lock(&cx231xx_devlist_mutex);
list_for_each_entry(h, &cx231xx_devlist, devlist) {
if (h->vdev->minor == minor)
dev = h;
if (h->vbi_dev->minor == minor) {
dev = h;
*fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
}
if (h->radio_dev && h->radio_dev->minor == minor) {
dev = h;
*has_radio = 1;
}
}
mutex_unlock(&cx231xx_devlist_mutex);
return dev;
}
/*
* cx231xx_realease_resources()
* unregisters the v4l2,i2c and usb devices

View file

@ -197,8 +197,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
strlcat(ir->phys, "/input0", sizeof(ir->phys));
err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER,
dev->board.ir_codes);
err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER);
if (err < 0)
goto err_out_free;
@ -217,7 +216,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
cx231xx_ir_start(ir);
/* all done */
err = input_register_device(ir->input);
err = ir_input_register(ir->input, dev->board.ir_codes);
if (err)
goto err_out_stop;
@ -226,8 +225,6 @@ err_out_stop:
cx231xx_ir_stop(ir);
dev->ir = NULL;
err_out_free:
ir_input_free(input_dev);
input_free_device(input_dev);
kfree(ir);
return err;
}
@ -241,8 +238,7 @@ int cx231xx_ir_fini(struct cx231xx *dev)
return 0;
cx231xx_ir_stop(ir);
ir_input_free(ir->input);
input_unregister_device(ir->input);
ir_input_unregister(ir->input);
kfree(ir);
/* done */

View file

@ -1916,20 +1916,29 @@ static int radio_queryctrl(struct file *file, void *priv,
*/
static int cx231xx_v4l2_open(struct file *filp)
{
int minor = video_devdata(filp)->minor;
int errCode = 0, radio = 0;
struct cx231xx *dev = NULL;
struct video_device *vdev = video_devdata(filp);
struct cx231xx *dev = video_drvdata(filp);
struct cx231xx_fh *fh;
enum v4l2_buf_type fh_type = 0;
dev = cx231xx_get_device(minor, &fh_type, &radio);
if (NULL == dev)
return -ENODEV;
switch (vdev->vfl_type) {
case VFL_TYPE_GRABBER:
fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
break;
case VFL_TYPE_VBI:
fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
break;
case VFL_TYPE_RADIO:
radio = 1;
break;
}
mutex_lock(&dev->lock);
cx231xx_videodbg("open minor=%d type=%s users=%d\n",
minor, v4l2_type_names[fh_type], dev->users);
cx231xx_videodbg("open dev=%s type=%s users=%d\n",
video_device_node_name(vdev), v4l2_type_names[fh_type],
dev->users);
#if 0
errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
@ -2020,25 +2029,25 @@ void cx231xx_release_analog_resources(struct cx231xx *dev)
/*FIXME: I2C IR should be disconnected */
if (dev->radio_dev) {
if (-1 != dev->radio_dev->minor)
if (video_is_registered(dev->radio_dev))
video_unregister_device(dev->radio_dev);
else
video_device_release(dev->radio_dev);
dev->radio_dev = NULL;
}
if (dev->vbi_dev) {
cx231xx_info("V4L2 device /dev/vbi%d deregistered\n",
dev->vbi_dev->num);
if (-1 != dev->vbi_dev->minor)
cx231xx_info("V4L2 device %s deregistered\n",
video_device_node_name(dev->vbi_dev));
if (video_is_registered(dev->vbi_dev))
video_unregister_device(dev->vbi_dev);
else
video_device_release(dev->vbi_dev);
dev->vbi_dev = NULL;
}
if (dev->vdev) {
cx231xx_info("V4L2 device /dev/video%d deregistered\n",
dev->vdev->num);
if (-1 != dev->vdev->minor)
cx231xx_info("V4L2 device %s deregistered\n",
video_device_node_name(dev->vdev));
if (video_is_registered(dev->vdev))
video_unregister_device(dev->vdev);
else
video_device_release(dev->vdev);
@ -2268,7 +2277,6 @@ static const struct video_device cx231xx_video_template = {
.fops = &cx231xx_v4l_fops,
.release = video_device_release,
.ioctl_ops = &video_ioctl_ops,
.minor = -1,
.tvnorms = V4L2_STD_ALL,
.current_norm = V4L2_STD_PAL,
};
@ -2303,7 +2311,6 @@ static struct video_device cx231xx_radio_template = {
.name = "cx231xx-radio",
.fops = &radio_fops,
.ioctl_ops = &radio_ioctl_ops,
.minor = -1,
};
/******************************** usb interface ******************************/
@ -2319,13 +2326,13 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
return NULL;
*vfd = *template;
vfd->minor = -1;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->release = video_device_release;
vfd->debug = video_debug;
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
video_set_drvdata(vfd, dev);
return vfd;
}
@ -2374,8 +2381,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
return ret;
}
cx231xx_info("%s/0: registered device video%d [v4l2]\n",
dev->name, dev->vdev->num);
cx231xx_info("%s/0: registered device %s [v4l2]\n",
dev->name, video_device_node_name(dev->vdev));
/* Initialize VBI template */
memcpy(&cx231xx_vbi_template, &cx231xx_video_template,
@ -2393,8 +2400,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
return ret;
}
cx231xx_info("%s/0: registered device vbi%d\n",
dev->name, dev->vbi_dev->num);
cx231xx_info("%s/0: registered device %s\n",
dev->name, video_device_node_name(dev->vbi_dev));
if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
@ -2409,12 +2416,13 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
cx231xx_errdev("can't register radio device\n");
return ret;
}
cx231xx_info("Registered radio device as /dev/radio%d\n",
dev->radio_dev->num);
cx231xx_info("Registered radio device as %s\n",
video_device_node_name(dev->radio_dev));
}
cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
dev->vdev->num, dev->vbi_dev->num);
cx231xx_info("V4L2 device registered as %s and %s\n",
video_device_node_name(dev->vdev),
video_device_node_name(dev->vbi_dev));
return 0;
}

View file

@ -689,8 +689,6 @@ void cx231xx_release_analog_resources(struct cx231xx *dev);
int cx231xx_register_analog_devices(struct cx231xx *dev);
void cx231xx_remove_from_devlist(struct cx231xx *dev);
void cx231xx_add_into_devlist(struct cx231xx *dev);
struct cx231xx *cx231xx_get_device(int minor,
enum v4l2_buf_type *fh_type, int *has_radio);
void cx231xx_init_extension(struct cx231xx *dev);
void cx231xx_close_extension(struct cx231xx *dev);

View file

@ -53,6 +53,8 @@
#define NETUP_CI_CTL 0x04
#define NETUP_CI_RD 1
#define NETUP_IRQ_DETAM 0x1
#define NETUP_IRQ_IRQAM 0x4
static unsigned int ci_dbg;
module_param(ci_dbg, int, 0644);
@ -73,6 +75,9 @@ struct netup_ci_state {
int status;
struct work_struct work;
void *priv;
u8 current_irq_mode;
int current_ci_flag;
unsigned long next_status_checked_time;
};
@ -169,24 +174,26 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
if (0 != slot)
return -EINVAL;
ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &store, 1);
if (ret != 0)
return ret;
if (state->current_ci_flag != flag) {
ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &store, 1);
if (ret != 0)
return ret;
store &= ~0x0c;
store |= flag;
store &= ~0x0c;
store |= flag;
ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &store, 1);
if (ret != 0)
return ret;
ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &store, 1);
if (ret != 0)
return ret;
};
state->current_ci_flag = flag;
mutex_lock(&dev->gpio_lock);
/* write addr */
cx_write(MC417_OEN, NETUP_EN_ALL);
msleep(2);
cx_write(MC417_RWD, NETUP_CTRL_OFF |
NETUP_ADLO | (0xff & addr));
cx_clear(MC417_RWD, NETUP_ADLO);
@ -196,7 +203,6 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
if (read) { /* data in */
cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
msleep(2);
} else /* data out */
cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
@ -213,8 +219,8 @@ int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
if (mem < 0)
return -EREMOTEIO;
ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
(read) ? "read" : "write", addr,
ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
(read) ? "read" : "write", state->ci_i2c_addr, addr,
(flag == NETUP_CI_CTL) ? "ctl" : "mem",
(read) ? mem : data);
@ -283,14 +289,39 @@ int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
return 0;
}
int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
{
struct netup_ci_state *state = en50221->data;
int ret;
if (irq_mode == state->current_irq_mode)
return 0;
ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
__func__, state->ci_i2c_addr, irq_mode);
ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
0x1b, &irq_mode, 1);
if (ret != 0)
return ret;
state->current_irq_mode = irq_mode;
return 0;
}
int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
{
struct netup_ci_state *state = en50221->data;
u8 buf = 0x60;
u8 buf;
if (0 != slot)
return -EINVAL;
netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &buf, 1);
buf |= 0x60;
return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &buf, 1);
}
@ -303,21 +334,35 @@ static void netup_read_ci_status(struct work_struct *work)
u8 buf[33];
int ret;
ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &buf[0], 33);
/* CAM module IRQ processing. fast operation */
dvb_ca_en50221_frda_irq(&state->ca, 0);
if (ret != 0)
return;
/* CAM module INSERT/REMOVE processing. slow operation because of i2c
* transfers */
if (time_after(jiffies, state->next_status_checked_time)
|| !state->status) {
ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &buf[0], 33);
ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, "
"TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0],
buf[32]);
state->next_status_checked_time = jiffies
+ msecs_to_jiffies(1000);
if (buf[0] & 1)
state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
DVB_CA_EN50221_POLL_CAM_READY;
else
state->status = 0;
if (ret != 0)
return;
ci_dbg_print("%s: Slot Status Addr=[0x%04x], "
"Reg=[0x%02x], data=%02x, "
"TS config = %02x\n", __func__,
state->ci_i2c_addr, 0, buf[0],
buf[0]);
if (buf[0] & 1)
state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
DVB_CA_EN50221_POLL_CAM_READY;
else
state->status = 0;
};
}
/* CI irq handler */
@ -347,6 +392,9 @@ int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open
if (0 != slot)
return -EINVAL;
netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | NETUP_IRQ_IRQAM)
: NETUP_IRQ_DETAM);
return state->status;
}
@ -381,8 +429,8 @@ int netup_ci_init(struct cx23885_tsport *port)
0x01, /* power on (use it like store place) */
0x00, /* RFU */
0x00, /* int status read only */
0x01, /* all int unmasked */
0x04, /* int config */
NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
0x05, /* EXTINT=active-high, INT=push-pull */
0x00, /* USCG1 */
0x04, /* ack active low */
0x00, /* LOCK = 0 */
@ -422,6 +470,7 @@ int netup_ci_init(struct cx23885_tsport *port)
state->ca.poll_slot_status = netup_poll_ci_slot_status;
state->ca.data = state;
state->priv = port;
state->current_irq_mode = NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM;
ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
0, &cimax_init[0], 34);

View file

@ -1568,28 +1568,11 @@ static int vidioc_queryctrl(struct file *file, void *priv,
static int mpeg_open(struct file *file)
{
int minor = video_devdata(file)->minor;
struct cx23885_dev *h, *dev = NULL;
struct list_head *list;
struct cx23885_dev *dev = video_drvdata(file);
struct cx23885_fh *fh;
dprintk(2, "%s()\n", __func__);
lock_kernel();
list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist);
if (h->v4l_device &&
h->v4l_device->minor == minor) {
dev = h;
break;
}
}
if (dev == NULL) {
unlock_kernel();
return -ENODEV;
}
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh), GFP_KERNEL);
if (NULL == fh) {
@ -1597,6 +1580,8 @@ static int mpeg_open(struct file *file)
return -ENOMEM;
}
lock_kernel();
file->private_data = fh;
fh->dev = dev;
@ -1736,7 +1721,6 @@ static struct video_device cx23885_mpeg_template = {
.name = "cx23885",
.fops = &mpeg_fops,
.ioctl_ops = &mpeg_ioctl_ops,
.minor = -1,
.tvnorms = CX23885_NORMS,
.current_norm = V4L2_STD_NTSC_M,
};
@ -1746,7 +1730,7 @@ void cx23885_417_unregister(struct cx23885_dev *dev)
dprintk(1, "%s()\n", __func__);
if (dev->v4l_device) {
if (-1 != dev->v4l_device->minor)
if (video_is_registered(dev->v4l_device))
video_unregister_device(dev->v4l_device);
else
video_device_release(dev->v4l_device);
@ -1803,6 +1787,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
/* Allocate and initialize V4L video device */
dev->v4l_device = cx23885_video_dev_alloc(tsport,
dev->pci, &cx23885_mpeg_template, "mpeg");
video_set_drvdata(dev->v4l_device, dev);
err = video_register_device(dev->v4l_device,
VFL_TYPE_GRABBER, -1);
if (err < 0) {
@ -1810,8 +1795,8 @@ int cx23885_417_register(struct cx23885_dev *dev)
return err;
}
printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
dev->name, dev->v4l_device->num);
printk(KERN_INFO "%s: registered device %s [mpeg]\n",
dev->name, video_device_node_name(dev->v4l_device));
return 0;
}

Some files were not shown because too many files have changed in this diff Show more