You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
V4L/DVB (4228a): pvrusb2 to kernel 2.6.18
Implement V4L2 driver for the Hauppauge PVR USB2 TV tuner. The Hauppauge PVR USB2 is a USB connected TV tuner with an embedded cx23416 hardware MPEG2 encoder. There are two major variants of this device; this driver handles both. Any V4L2 application which understands MPEG2 video stream data should be able to work with this device. Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
eb99adde31
commit
d855497edb
212
Documentation/video4linux/README.pvrusb2
Normal file
212
Documentation/video4linux/README.pvrusb2
Normal file
@@ -0,0 +1,212 @@
|
||||
|
||||
$Id$
|
||||
Mike Isely <isely@pobox.com>
|
||||
|
||||
pvrusb2 driver
|
||||
|
||||
Background:
|
||||
|
||||
This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which
|
||||
is a USB 2.0 hosted TV Tuner. This driver is a work in progress.
|
||||
Its history started with the reverse-engineering effort by Björn
|
||||
Danielsson <pvrusb2@dax.nu> whose web page can be found here:
|
||||
|
||||
http://pvrusb2.dax.nu/
|
||||
|
||||
From there Aurelien Alleaume <slts@free.fr> began an effort to
|
||||
create a video4linux compatible driver. I began with Aurelien's
|
||||
last known snapshot and evolved the driver to the state it is in
|
||||
here.
|
||||
|
||||
More information on this driver can be found at:
|
||||
|
||||
http://www.isely.net/pvrusb2.html
|
||||
|
||||
|
||||
This driver has a strong separation of layers. They are very
|
||||
roughly:
|
||||
|
||||
1a. Low level wire-protocol implementation with the device.
|
||||
|
||||
1b. I2C adaptor implementation and corresponding I2C client drivers
|
||||
implemented elsewhere in V4L.
|
||||
|
||||
1c. High level hardware driver implementation which coordinates all
|
||||
activities that ensure correct operation of the device.
|
||||
|
||||
2. A "context" layer which manages instancing of driver, setup,
|
||||
tear-down, arbitration, and interaction with high level
|
||||
interfaces appropriately as devices are hotplugged in the
|
||||
system.
|
||||
|
||||
3. High level interfaces which glue the driver to various published
|
||||
Linux APIs (V4L, sysfs, maybe DVB in the future).
|
||||
|
||||
The most important shearing layer is between the top 2 layers. A
|
||||
lot of work went into the driver to ensure that any kind of
|
||||
conceivable API can be laid on top of the core driver. (Yes, the
|
||||
driver internally leverages V4L to do its work but that really has
|
||||
nothing to do with the API published by the driver to the outside
|
||||
world.) The architecture allows for different APIs to
|
||||
simultaneously access the driver. I have a strong sense of fairness
|
||||
about APIs and also feel that it is a good design principle to keep
|
||||
implementation and interface isolated from each other. Thus while
|
||||
right now the V4L high level interface is the most complete, the
|
||||
sysfs high level interface will work equally well for similar
|
||||
functions, and there's no reason I see right now why it shouldn't be
|
||||
possible to produce a DVB high level interface that can sit right
|
||||
alongside V4L.
|
||||
|
||||
NOTE: Complete documentation on the pvrusb2 driver is contained in
|
||||
the html files within the doc directory; these are exactly the same
|
||||
as what is on the web site at the time. Browse those files
|
||||
(especially the FAQ) before asking questions.
|
||||
|
||||
|
||||
Building
|
||||
|
||||
To build these modules essentially amounts to just running "Make",
|
||||
but you need the kernel source tree nearby and you will likely also
|
||||
want to set a few controlling environment variables first in order
|
||||
to link things up with that source tree. Please see the Makefile
|
||||
here for comments that explain how to do that.
|
||||
|
||||
|
||||
Source file list / functional overview:
|
||||
|
||||
(Note: The term "module" used below generally refers to loosely
|
||||
defined functional units within the pvrusb2 driver and bears no
|
||||
relation to the Linux kernel's concept of a loadable module.)
|
||||
|
||||
pvrusb2-audio.[ch] - This is glue logic that resides between this
|
||||
driver and the msp3400.ko I2C client driver (which is found
|
||||
elsewhere in V4L).
|
||||
|
||||
pvrusb2-context.[ch] - This module implements the context for an
|
||||
instance of the driver. Everything else eventually ties back to
|
||||
or is otherwise instanced within the data structures implemented
|
||||
here. Hotplugging is ultimately coordinated here. All high level
|
||||
interfaces tie into the driver through this module. This module
|
||||
helps arbitrate each interface's access to the actual driver core,
|
||||
and is designed to allow concurrent access through multiple
|
||||
instances of multiple interfaces (thus you can for example change
|
||||
the tuner's frequency through sysfs while simultaneously streaming
|
||||
video through V4L out to an instance of mplayer).
|
||||
|
||||
pvrusb2-debug.h - This header defines a printk() wrapper and a mask
|
||||
of debugging bit definitions for the various kinds of debug
|
||||
messages that can be enabled within the driver.
|
||||
|
||||
pvrusb2-debugifc.[ch] - This module implements a crude command line
|
||||
oriented debug interface into the driver. Aside from being part
|
||||
of the process for implementing manual firmware extraction (see
|
||||
the pvrusb2 web site mentioned earlier), probably I'm the only one
|
||||
who has ever used this. It is mainly a debugging aid.
|
||||
|
||||
pvrusb2-eeprom.[ch] - This is glue logic that resides between this
|
||||
driver the tveeprom.ko module, which is itself implemented
|
||||
elsewhere in V4L.
|
||||
|
||||
pvrusb2-encoder.[ch] - This module implements all protocol needed to
|
||||
interact with the Conexant mpeg2 encoder chip within the pvrusb2
|
||||
device. It is a crude echo of corresponding logic in ivtv,
|
||||
however the design goals (strict isolation) and physical layer
|
||||
(proxy through USB instead of PCI) are enough different that this
|
||||
implementation had to be completely different.
|
||||
|
||||
pvrusb2-hdw-internal.h - This header defines the core data structure
|
||||
in the driver used to track ALL internal state related to control
|
||||
of the hardware. Nobody outside of the core hardware-handling
|
||||
modules should have any business using this header. All external
|
||||
access to the driver should be through one of the high level
|
||||
interfaces (e.g. V4L, sysfs, etc), and in fact even those high
|
||||
level interfaces are restricted to the API defined in
|
||||
pvrusb2-hdw.h and NOT this header.
|
||||
|
||||
pvrusb2-hdw.h - This header defines the full internal API for
|
||||
controlling the hardware. High level interfaces (e.g. V4L, sysfs)
|
||||
will work through here.
|
||||
|
||||
pvrusb2-hdw.c - This module implements all the various bits of logic
|
||||
that handle overall control of a specific pvrusb2 device.
|
||||
(Policy, instantiation, and arbitration of pvrusb2 devices fall
|
||||
within the jurisdiction of pvrusb-context not here).
|
||||
|
||||
pvrusb2-i2c-chips-*.c - These modules implement the glue logic to
|
||||
tie together and configure various I2C modules as they attach to
|
||||
the I2C bus. There are two versions of this file. The "v4l2"
|
||||
version is intended to be used in-tree alongside V4L, where we
|
||||
implement just the logic that makes sense for a pure V4L
|
||||
environment. The "all" version is intended for use outside of
|
||||
V4L, where we might encounter other possibly "challenging" modules
|
||||
from ivtv or older kernel snapshots (or even the support modules
|
||||
in the standalone snapshot).
|
||||
|
||||
pvrusb2-i2c-cmd-v4l1.[ch] - This module implements generic V4L1
|
||||
compatible commands to the I2C modules. It is here where state
|
||||
changes inside the pvrusb2 driver are translated into V4L1
|
||||
commands that are in turn send to the various I2C modules.
|
||||
|
||||
pvrusb2-i2c-cmd-v4l2.[ch] - This module implements generic V4L2
|
||||
compatible commands to the I2C modules. It is here where state
|
||||
changes inside the pvrusb2 driver are translated into V4L2
|
||||
commands that are in turn send to the various I2C modules.
|
||||
|
||||
pvrusb2-i2c-core.[ch] - This module provides an implementation of a
|
||||
kernel-friendly I2C adaptor driver, through which other external
|
||||
I2C client drivers (e.g. msp3400, tuner, lirc) may connect and
|
||||
operate corresponding chips within the the pvrusb2 device. It is
|
||||
through here that other V4L modules can reach into this driver to
|
||||
operate specific pieces (and those modules are in turn driven by
|
||||
glue logic which is coordinated by pvrusb2-hdw, doled out by
|
||||
pvrusb2-context, and then ultimately made available to users
|
||||
through one of the high level interfaces).
|
||||
|
||||
pvrusb2-io.[ch] - This module implements a very low level ring of
|
||||
transfer buffers, required in order to stream data from the
|
||||
device. This module is *very* low level. It only operates the
|
||||
buffers and makes no attempt to define any policy or mechanism for
|
||||
how such buffers might be used.
|
||||
|
||||
pvrusb2-ioread.[ch] - This module layers on top of pvrusb2-io.[ch]
|
||||
to provide a streaming API usable by a read() system call style of
|
||||
I/O. Right now this is the only layer on top of pvrusb2-io.[ch],
|
||||
however the underlying architecture here was intended to allow for
|
||||
other styles of I/O to be implemented with additonal modules, like
|
||||
mmap()'ed buffers or something even more exotic.
|
||||
|
||||
pvrusb2-main.c - This is the top level of the driver. Module level
|
||||
and USB core entry points are here. This is our "main".
|
||||
|
||||
pvrusb2-sysfs.[ch] - This is the high level interface which ties the
|
||||
pvrusb2 driver into sysfs. Through this interface you can do
|
||||
everything with the driver except actually stream data.
|
||||
|
||||
pvrusb2-tuner.[ch] - This is glue logic that resides between this
|
||||
driver and the tuner.ko I2C client driver (which is found
|
||||
elsewhere in V4L).
|
||||
|
||||
pvrusb2-util.h - This header defines some common macros used
|
||||
throughout the driver. These macros are not really specific to
|
||||
the driver, but they had to go somewhere.
|
||||
|
||||
pvrusb2-v4l2.[ch] - This is the high level interface which ties the
|
||||
pvrusb2 driver into video4linux. It is through here that V4L
|
||||
applications can open and operate the driver in the usual V4L
|
||||
ways. Note that **ALL** V4L functionality is published only
|
||||
through here and nowhere else.
|
||||
|
||||
pvrusb2-video-*.[ch] - This is glue logic that resides between this
|
||||
driver and the saa711x.ko I2C client driver (which is found
|
||||
elsewhere in V4L). Note that saa711x.ko used to be known as
|
||||
saa7115.ko in ivtv. There are two versions of this; one is
|
||||
selected depending on the particular saa711[5x].ko that is found.
|
||||
|
||||
pvrusb2.h - This header contains compile time tunable parameters
|
||||
(and at the moment the driver has very little that needs to be
|
||||
tuned).
|
||||
|
||||
|
||||
-Mike Isely
|
||||
isely@pobox.com
|
||||
|
||||
@@ -445,6 +445,8 @@ endmenu # encoder / decoder chips
|
||||
menu "V4L USB devices"
|
||||
depends on USB && VIDEO_DEV
|
||||
|
||||
source "drivers/media/video/pvrusb2/Kconfig"
|
||||
|
||||
source "drivers/media/video/em28xx/Kconfig"
|
||||
|
||||
config USB_DSBR
|
||||
|
||||
@@ -47,6 +47,7 @@ obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/
|
||||
obj-$(CONFIG_VIDEO_CX88) += cx88/
|
||||
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
|
||||
obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o
|
||||
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
|
||||
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
|
||||
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
|
||||
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
|
||||
|
||||
62
drivers/media/video/pvrusb2/Kconfig
Normal file
62
drivers/media/video/pvrusb2/Kconfig
Normal file
@@ -0,0 +1,62 @@
|
||||
config VIDEO_PVRUSB2
|
||||
tristate "Hauppauge WinTV-PVR USB2 support"
|
||||
depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
|
||||
select FW_LOADER
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_TVEEPROM
|
||||
select VIDEO_CX2341X
|
||||
select VIDEO_SAA711X
|
||||
select VIDEO_MSP3400
|
||||
---help---
|
||||
This is a video4linux driver for Conexant 23416 based
|
||||
usb2 personal video recorder devices.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called pvrusb2
|
||||
|
||||
config VIDEO_PVRUSB2_24XXX
|
||||
bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series"
|
||||
depends on VIDEO_PVRUSB2 && EXPERIMENTAL
|
||||
select VIDEO_CX25840
|
||||
select VIDEO_WM8775
|
||||
---help---
|
||||
This option enables inclusion of additional logic to operate
|
||||
newer WinTV-PVR USB2 devices whose model number is of the
|
||||
form "24xxx" (leading prefix of "24" followed by 3 digits).
|
||||
To see if you may need this option, examine the white
|
||||
sticker on the underside of your device. Enabling this
|
||||
option will not harm support for older devices, however it
|
||||
is a separate option because of the experimental nature of
|
||||
this new feature.
|
||||
|
||||
If you are in doubt, say N.
|
||||
|
||||
Note: This feature is _very_ experimental. You have been
|
||||
warned.
|
||||
|
||||
config VIDEO_PVRUSB2_SYSFS
|
||||
bool "pvrusb2 sysfs support (EXPERIMENTAL)"
|
||||
default y
|
||||
depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
|
||||
---help---
|
||||
This option enables the operation of a sysfs based
|
||||
interface for query and control of the pvrusb2 driver.
|
||||
|
||||
This is not generally needed for v4l applications,
|
||||
although certain applications are optimized to take
|
||||
advantage of this feature.
|
||||
|
||||
If you are in doubt, say Y.
|
||||
|
||||
Note: This feature is experimental and subject to change.
|
||||
|
||||
config VIDEO_PVRUSB2_DEBUGIFC
|
||||
bool "pvrusb2 debug interface"
|
||||
depends on VIDEO_PVRUSB2_SYSFS
|
||||
---help---
|
||||
This option enables the inclusion of a debug interface
|
||||
in the pvrusb2 driver, hosted through sysfs.
|
||||
|
||||
You do not need to select this option unless you plan
|
||||
on debugging the driver or performing a manual firmware
|
||||
extraction.
|
||||
18
drivers/media/video/pvrusb2/Makefile
Normal file
18
drivers/media/video/pvrusb2/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
|
||||
obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
|
||||
|
||||
obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \
|
||||
pvrusb2-cx2584x-v4l.o \
|
||||
pvrusb2-wm8775.o
|
||||
|
||||
pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
|
||||
pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
|
||||
pvrusb2-encoder.o pvrusb2-video-v4l.o \
|
||||
pvrusb2-eeprom.o pvrusb2-tuner.o pvrusb2-demod.o \
|
||||
pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
|
||||
pvrusb2-ctrl.o pvrusb2-std.o \
|
||||
pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
|
||||
$(obj-pvrusb2-24xxx-y) \
|
||||
$(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
|
||||
|
||||
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
|
||||
204
drivers/media/video/pvrusb2/pvrusb2-audio.c
Normal file
204
drivers/media/video/pvrusb2/pvrusb2-audio.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pvrusb2-audio.h"
|
||||
#include "pvrusb2-hdw-internal.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/msp3400.h>
|
||||
#include <media/v4l2-common.h>
|
||||
|
||||
struct pvr2_msp3400_handler {
|
||||
struct pvr2_hdw *hdw;
|
||||
struct pvr2_i2c_client *client;
|
||||
struct pvr2_i2c_handler i2c_handler;
|
||||
struct pvr2_audio_stat astat;
|
||||
unsigned long stale_mask;
|
||||
};
|
||||
|
||||
|
||||
/* This function selects the correct audio input source */
|
||||
static void set_stereo(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
struct v4l2_routing route;
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
|
||||
|
||||
if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
|
||||
struct v4l2_tuner vt;
|
||||
memset(&vt,0,sizeof(vt));
|
||||
vt.audmode = hdw->audiomode_val;
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
|
||||
}
|
||||
|
||||
route.input = MSP_INPUT_DEFAULT;
|
||||
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
|
||||
switch (hdw->input_val) {
|
||||
case PVR2_CVAL_INPUT_TV:
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_RADIO:
|
||||
/* Assume that msp34xx also handle FM decoding, in which case
|
||||
we're still using the tuner. */
|
||||
/* HV: actually it is more likely to be the SCART2 input if
|
||||
the ivtv experience is any indication. */
|
||||
route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_SVIDEO:
|
||||
case PVR2_CVAL_INPUT_COMPOSITE:
|
||||
/* SCART 1 input */
|
||||
route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
|
||||
MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
|
||||
break;
|
||||
}
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
|
||||
}
|
||||
|
||||
|
||||
static int check_stereo(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
return (hdw->input_dirty ||
|
||||
hdw->audiomode_dirty);
|
||||
}
|
||||
|
||||
|
||||
struct pvr2_msp3400_ops {
|
||||
void (*update)(struct pvr2_msp3400_handler *);
|
||||
int (*check)(struct pvr2_msp3400_handler *);
|
||||
};
|
||||
|
||||
|
||||
static const struct pvr2_msp3400_ops msp3400_ops[] = {
|
||||
{ .update = set_stereo, .check = check_stereo},
|
||||
};
|
||||
|
||||
|
||||
static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
unsigned long msk;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
|
||||
idx++) {
|
||||
msk = 1 << idx;
|
||||
if (ctxt->stale_mask & msk) continue;
|
||||
if (msp3400_ops[idx].check(ctxt)) {
|
||||
ctxt->stale_mask |= msk;
|
||||
}
|
||||
}
|
||||
return ctxt->stale_mask != 0;
|
||||
}
|
||||
|
||||
|
||||
static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
unsigned long msk;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
|
||||
idx++) {
|
||||
msk = 1 << idx;
|
||||
if (!(ctxt->stale_mask & msk)) continue;
|
||||
ctxt->stale_mask &= ~msk;
|
||||
msp3400_ops[idx].update(ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This reads back the current signal type */
|
||||
static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
struct v4l2_tuner vt;
|
||||
int stat;
|
||||
|
||||
memset(&vt,0,sizeof(vt));
|
||||
stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
|
||||
if (stat < 0) return stat;
|
||||
|
||||
ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0;
|
||||
ctxt->hdw->flag_bilingual =
|
||||
(vt.audmode & V4L2_TUNER_MODE_LANG2) != 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
|
||||
{
|
||||
ctxt->client->handler = 0;
|
||||
ctxt->hdw->audio_stat = 0;
|
||||
kfree(ctxt);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
|
||||
char *buf,unsigned int cnt)
|
||||
{
|
||||
return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2");
|
||||
}
|
||||
|
||||
|
||||
const static struct pvr2_i2c_handler_functions msp3400_funcs = {
|
||||
.detach = (void (*)(void *))pvr2_msp3400_detach,
|
||||
.check = (int (*)(void *))msp3400_check,
|
||||
.update = (void (*)(void *))msp3400_update,
|
||||
.describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe,
|
||||
};
|
||||
|
||||
|
||||
int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
|
||||
{
|
||||
struct pvr2_msp3400_handler *ctxt;
|
||||
if (hdw->audio_stat) return 0;
|
||||
if (cp->handler) return 0;
|
||||
|
||||
ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
|
||||
if (!ctxt) return 0;
|
||||
memset(ctxt,0,sizeof(*ctxt));
|
||||
|
||||
ctxt->i2c_handler.func_data = ctxt;
|
||||
ctxt->i2c_handler.func_table = &msp3400_funcs;
|
||||
ctxt->client = cp;
|
||||
ctxt->hdw = hdw;
|
||||
ctxt->astat.ctxt = ctxt;
|
||||
ctxt->astat.status = (int (*)(void *))get_audio_status;
|
||||
ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach;
|
||||
ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
|
||||
sizeof(msp3400_ops[0]))) - 1;
|
||||
cp->handler = &ctxt->i2c_handler;
|
||||
hdw->audio_stat = &ctxt->astat;
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
|
||||
cp->client->addr);
|
||||
return !0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
40
drivers/media/video/pvrusb2/pvrusb2-audio.h
Normal file
40
drivers/media/video/pvrusb2/pvrusb2-audio.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PVRUSB2_AUDIO_H
|
||||
#define __PVRUSB2_AUDIO_H
|
||||
|
||||
#include "pvrusb2-i2c-core.h"
|
||||
|
||||
int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
|
||||
|
||||
#endif /* __PVRUSB2_AUDIO_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
230
drivers/media/video/pvrusb2/pvrusb2-context.c
Normal file
230
drivers/media/video/pvrusb2/pvrusb2-context.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pvrusb2-context.h"
|
||||
#include "pvrusb2-io.h"
|
||||
#include "pvrusb2-ioread.h"
|
||||
#include "pvrusb2-hdw.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
|
||||
static void pvr2_context_destroy(struct pvr2_context *mp)
|
||||
{
|
||||
if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
|
||||
pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
|
||||
flush_workqueue(mp->workqueue);
|
||||
destroy_workqueue(mp->workqueue);
|
||||
kfree(mp);
|
||||
}
|
||||
|
||||
|
||||
static void pvr2_context_trigger_poll(struct pvr2_context *mp)
|
||||
{
|
||||
queue_work(mp->workqueue,&mp->workpoll);
|
||||
}
|
||||
|
||||
|
||||
static void pvr2_context_poll(struct pvr2_context *mp)
|
||||
{
|
||||
pvr2_context_enter(mp); do {
|
||||
pvr2_hdw_poll(mp->hdw);
|
||||
} while (0); pvr2_context_exit(mp);
|
||||
}
|
||||
|
||||
|
||||
static void pvr2_context_setup(struct pvr2_context *mp)
|
||||
{
|
||||
pvr2_context_enter(mp); do {
|
||||
if (!pvr2_hdw_dev_ok(mp->hdw)) break;
|
||||
pvr2_hdw_setup(mp->hdw);
|
||||
pvr2_hdw_setup_poll_trigger(
|
||||
mp->hdw,
|
||||
(void (*)(void *))pvr2_context_trigger_poll,
|
||||
mp);
|
||||
if (!pvr2_hdw_dev_ok(mp->hdw)) break;
|
||||
if (!pvr2_hdw_init_ok(mp->hdw)) break;
|
||||
mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
|
||||
if (mp->setup_func) {
|
||||
mp->setup_func(mp);
|
||||
}
|
||||
} while (0); pvr2_context_exit(mp);
|
||||
}
|
||||
|
||||
|
||||
struct pvr2_context *pvr2_context_create(
|
||||
struct usb_interface *intf,
|
||||
const struct usb_device_id *devid,
|
||||
void (*setup_func)(struct pvr2_context *))
|
||||
{
|
||||
struct pvr2_context *mp = 0;
|
||||
mp = kmalloc(sizeof(*mp),GFP_KERNEL);
|
||||
if (!mp) goto done;
|
||||
memset(mp,0,sizeof(*mp));
|
||||
pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
|
||||
mp->setup_func = setup_func;
|
||||
mutex_init(&mp->mutex);
|
||||
mp->hdw = pvr2_hdw_create(intf,devid);
|
||||
if (!mp->hdw) {
|
||||
pvr2_context_destroy(mp);
|
||||
mp = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
mp->workqueue = create_singlethread_workqueue("pvrusb2");
|
||||
INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp);
|
||||
INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp);
|
||||
queue_work(mp->workqueue,&mp->workinit);
|
||||
done:
|
||||
return mp;
|
||||
}
|
||||
|
||||
|
||||
void pvr2_context_enter(struct pvr2_context *mp)
|
||||
{
|
||||
mutex_lock(&mp->mutex);
|
||||
pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
|
||||
}
|
||||
|
||||
|
||||
void pvr2_context_exit(struct pvr2_context *mp)
|
||||
{
|
||||
int destroy_flag = 0;
|
||||
if (!(mp->mc_first || !mp->disconnect_flag)) {
|
||||
destroy_flag = !0;
|
||||
}
|
||||
pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
|
||||
mutex_unlock(&mp->mutex);
|
||||
if (destroy_flag) pvr2_context_destroy(mp);
|
||||
}
|
||||
|
||||
|
||||
static void pvr2_context_run_checks(struct pvr2_context *mp)
|
||||
{
|
||||
struct pvr2_channel *ch1,*ch2;
|
||||
for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
|
||||
ch2 = ch1->mc_next;
|
||||
if (ch1->check_func) {
|
||||
ch1->check_func(ch1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pvr2_context_disconnect(struct pvr2_context *mp)
|
||||
{
|
||||
pvr2_context_enter(mp); do {
|
||||
pvr2_hdw_disconnect(mp->hdw);
|
||||
mp->disconnect_flag = !0;
|
||||
pvr2_context_run_checks(mp);
|
||||
} while (0); pvr2_context_exit(mp);
|
||||
}
|
||||
|
||||
|
||||
void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
|
||||
{
|
||||
cp->hdw = mp->hdw;
|
||||
cp->mc_head = mp;
|
||||
cp->mc_next = 0;
|
||||
cp->mc_prev = mp->mc_last;
|
||||
if (mp->mc_last) {
|
||||
mp->mc_last->mc_next = cp;
|
||||
} else {
|
||||
mp->mc_first = cp;
|
||||
}
|
||||
mp->mc_last = cp;
|
||||
}
|
||||
|
||||
|
||||
static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
|
||||
{
|
||||
if (!cp->stream) return;
|
||||
pvr2_stream_kill(cp->stream->stream);
|
||||
cp->stream->user = 0;
|
||||
cp->stream = 0;
|
||||
}
|
||||
|
||||
|
||||
void pvr2_channel_done(struct pvr2_channel *cp)
|
||||
{
|
||||
struct pvr2_context *mp = cp->mc_head;
|
||||
pvr2_channel_disclaim_stream(cp);
|
||||
if (cp->mc_next) {
|
||||
cp->mc_next->mc_prev = cp->mc_prev;
|
||||
} else {
|
||||
mp->mc_last = cp->mc_prev;
|
||||
}
|
||||
if (cp->mc_prev) {
|
||||
cp->mc_prev->mc_next = cp->mc_next;
|
||||
} else {
|
||||
mp->mc_first = cp->mc_next;
|
||||
}
|
||||
cp->hdw = 0;
|
||||
}
|
||||
|
||||
|
||||
int pvr2_channel_claim_stream(struct pvr2_channel *cp,
|
||||
struct pvr2_context_stream *sp)
|
||||
{
|
||||
int code = 0;
|
||||
pvr2_context_enter(cp->mc_head); do {
|
||||
if (sp == cp->stream) break;
|
||||
if (sp->user) {
|
||||
code = -EBUSY;
|
||||
break;
|
||||
}
|
||||
pvr2_channel_disclaim_stream(cp);
|
||||
if (!sp) break;
|
||||
sp->user = cp;
|
||||
cp->stream = sp;
|
||||
} while (0); pvr2_context_exit(cp->mc_head);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
// This is the marker for the real beginning of a legitimate mpeg2 stream.
|
||||
static char stream_sync_key[] = {
|
||||
0x00, 0x00, 0x01, 0xba,
|
||||
};
|
||||
|
||||
struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
|
||||
struct pvr2_context_stream *sp)
|
||||
{
|
||||
struct pvr2_ioread *cp;
|
||||
cp = pvr2_ioread_create();
|
||||
if (!cp) return 0;
|
||||
pvr2_ioread_setup(cp,sp->stream);
|
||||
pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 75 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
92
drivers/media/video/pvrusb2/pvrusb2-context.h
Normal file
92
drivers/media/video/pvrusb2/pvrusb2-context.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __PVRUSB2_BASE_H
|
||||
#define __PVRUSB2_BASE_H
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
struct pvr2_hdw; /* hardware interface - defined elsewhere */
|
||||
struct pvr2_stream; /* stream interface - defined elsewhere */
|
||||
|
||||
struct pvr2_context; /* All central state */
|
||||
struct pvr2_channel; /* One I/O pathway to a user */
|
||||
struct pvr2_context_stream; /* Wrapper for a stream */
|
||||
struct pvr2_crit_reg; /* Critical region pointer */
|
||||
struct pvr2_ioread; /* Low level stream structure */
|
||||
|
||||
struct pvr2_context_stream {
|
||||
struct pvr2_channel *user;
|
||||
struct pvr2_stream *stream;
|
||||
};
|
||||
|
||||
struct pvr2_context {
|
||||
struct pvr2_channel *mc_first;
|
||||
struct pvr2_channel *mc_last;
|
||||
struct pvr2_hdw *hdw;
|
||||
struct pvr2_context_stream video_stream;
|
||||
struct mutex mutex;
|
||||
int disconnect_flag;
|
||||
|
||||
/* Called after pvr2_context initialization is complete */
|
||||
void (*setup_func)(struct pvr2_context *);
|
||||
|
||||
/* Work queue overhead for out-of-line processing */
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct workinit;
|
||||
struct work_struct workpoll;
|
||||
};
|
||||
|
||||
struct pvr2_channel {
|
||||
struct pvr2_context *mc_head;
|
||||
struct pvr2_channel *mc_next;
|
||||
struct pvr2_channel *mc_prev;
|
||||
struct pvr2_context_stream *stream;
|
||||
struct pvr2_hdw *hdw;
|
||||
void (*check_func)(struct pvr2_channel *);
|
||||
};
|
||||
|
||||
void pvr2_context_enter(struct pvr2_context *);
|
||||
void pvr2_context_exit(struct pvr2_context *);
|
||||
|
||||
struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
|
||||
const struct usb_device_id *devid,
|
||||
void (*setup_func)(struct pvr2_context *));
|
||||
void pvr2_context_disconnect(struct pvr2_context *);
|
||||
|
||||
void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
|
||||
void pvr2_channel_done(struct pvr2_channel *);
|
||||
int pvr2_channel_claim_stream(struct pvr2_channel *,
|
||||
struct pvr2_context_stream *);
|
||||
struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
|
||||
struct pvr2_context_stream *);
|
||||
|
||||
|
||||
#endif /* __PVRUSB2_CONTEXT_H */
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 75 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
544
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
Normal file
544
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
Normal file
File diff suppressed because it is too large
Load Diff
115
drivers/media/video/pvrusb2/pvrusb2-ctrl.h
Normal file
115
drivers/media/video/pvrusb2/pvrusb2-ctrl.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __PVRUSB2_CTRL_H
|
||||
#define __PVRUSB2_CTRL_H
|
||||
|
||||
struct pvr2_ctrl;
|
||||
|
||||
enum pvr2_ctl_type {
|
||||
pvr2_ctl_int = 0,
|
||||
pvr2_ctl_enum = 1,
|
||||
pvr2_ctl_bitmask = 2,
|
||||
};
|
||||
|
||||
|
||||
/* Set the given control. */
|
||||
int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
|
||||
|
||||
/* Set/clear specific bits of the given control. */
|
||||
int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val);
|
||||
|
||||
/* Get the current value of the given control. */
|
||||
int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr);
|
||||
|
||||
/* Retrieve control's type */
|
||||
enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve control's maximum value (int type) */
|
||||
int pvr2_ctrl_get_max(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve control's minimum value (int type) */
|
||||
int pvr2_ctrl_get_min(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve control's default value (any type) */
|
||||
int pvr2_ctrl_get_def(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve control's enumeration count (enum only) */
|
||||
int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve control's valid mask bits (bit mask only) */
|
||||
int pvr2_ctrl_get_mask(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve the control's name */
|
||||
const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve the control's desc */
|
||||
const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
|
||||
|
||||
/* Retrieve a control enumeration or bit mask value */
|
||||
int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int,
|
||||
unsigned int *);
|
||||
|
||||
/* Return true if control is writable */
|
||||
int pvr2_ctrl_is_writable(struct pvr2_ctrl *);
|
||||
|
||||
/* Return true if control has custom symbolic representation */
|
||||
int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *);
|
||||
|
||||
/* Convert a given mask/val to a custom symbolic value */
|
||||
int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *,
|
||||
int mask,int val,
|
||||
char *buf,unsigned int maxlen,
|
||||
unsigned int *len);
|
||||
|
||||
/* Convert a symbolic value to a mask/value pair */
|
||||
int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *,
|
||||
const char *buf,unsigned int len,
|
||||
int *maskptr,int *valptr);
|
||||
|
||||
/* Convert a given mask/val to a symbolic value */
|
||||
int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *,
|
||||
int mask,int val,
|
||||
char *buf,unsigned int maxlen,
|
||||
unsigned int *len);
|
||||
|
||||
/* Convert a symbolic value to a mask/value pair */
|
||||
int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *,
|
||||
const char *buf,unsigned int len,
|
||||
int *maskptr,int *valptr);
|
||||
|
||||
/* Convert a given mask/val to a symbolic value - must already be
|
||||
inside of critical region. */
|
||||
int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
|
||||
int mask,int val,
|
||||
char *buf,unsigned int maxlen,
|
||||
unsigned int *len);
|
||||
|
||||
#endif /* __PVRUSB2_CTRL_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 75 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
276
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
Normal file
276
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This source file is specifically designed to interface with the
|
||||
cx2584x, in kernels 2.6.16 or newer.
|
||||
|
||||
*/
|
||||
|
||||
#include "pvrusb2-cx2584x-v4l.h"
|
||||
#include "pvrusb2-video-v4l.h"
|
||||
#include "pvrusb2-i2c-cmd-v4l2.h"
|
||||
|
||||
|
||||
#include "pvrusb2-hdw-internal.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
#include <media/cx25840.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct pvr2_v4l_cx2584x {
|
||||
struct pvr2_i2c_handler handler;
|
||||
struct pvr2_decoder_ctrl ctrl;
|
||||
struct pvr2_i2c_client *client;
|
||||
struct pvr2_hdw *hdw;
|
||||
unsigned long stale_mask;
|
||||
};
|
||||
|
||||
|
||||
static void set_input(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
struct v4l2_routing route;
|
||||
enum cx25840_video_input vid_input;
|
||||
enum cx25840_audio_input aud_input;
|
||||
|
||||
memset(&route,0,sizeof(route));
|
||||
|
||||
switch(hdw->input_val) {
|
||||
case PVR2_CVAL_INPUT_TV:
|
||||
vid_input = CX25840_COMPOSITE7;
|
||||
aud_input = CX25840_AUDIO8;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_COMPOSITE:
|
||||
vid_input = CX25840_COMPOSITE3;
|
||||
aud_input = CX25840_AUDIO_SERIAL;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_SVIDEO:
|
||||
vid_input = CX25840_SVIDEO1;
|
||||
aud_input = CX25840_AUDIO_SERIAL;
|
||||
break;
|
||||
case PVR2_CVAL_INPUT_RADIO:
|
||||
default:
|
||||
// Just set it to be composite input for now...
|
||||
vid_input = CX25840_COMPOSITE3;
|
||||
aud_input = CX25840_AUDIO_SERIAL;
|
||||
break;
|
||||
}
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
|
||||
vid_input,aud_input);
|
||||
route.input = (u32)vid_input;
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
|
||||
route.input = (u32)aud_input;
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
|
||||
}
|
||||
|
||||
|
||||
static int check_input(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
return hdw->input_dirty != 0;
|
||||
}
|
||||
|
||||
|
||||
static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
u32 val;
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
|
||||
hdw->srate_val);
|
||||
switch (hdw->srate_val) {
|
||||
default:
|
||||
case PVR2_CVAL_SRATE_48:
|
||||
val = 48000;
|
||||
break;
|
||||
case PVR2_CVAL_SRATE_44_1:
|
||||
val = 44100;
|
||||
break;
|
||||
}
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
|
||||
}
|
||||
|
||||
|
||||
static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
return hdw->srate_dirty != 0;
|
||||
}
|
||||
|
||||
|
||||
struct pvr2_v4l_cx2584x_ops {
|
||||
void (*update)(struct pvr2_v4l_cx2584x *);
|
||||
int (*check)(struct pvr2_v4l_cx2584x *);
|
||||
};
|
||||
|
||||
|
||||
static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
|
||||
{ .update = set_input, .check = check_input},
|
||||
{ .update = set_audio, .check = check_audio},
|
||||
};
|
||||
|
||||
|
||||
static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
ctxt->client->handler = 0;
|
||||
ctxt->hdw->decoder_ctrl = 0;
|
||||
kfree(ctxt);
|
||||
}
|
||||
|
||||
|
||||
static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
unsigned long msk;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
|
||||
idx++) {
|
||||
msk = 1 << idx;
|
||||
if (ctxt->stale_mask & msk) continue;
|
||||
if (decoder_ops[idx].check(ctxt)) {
|
||||
ctxt->stale_mask |= msk;
|
||||
}
|
||||
}
|
||||
return ctxt->stale_mask != 0;
|
||||
}
|
||||
|
||||
|
||||
static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
unsigned long msk;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
|
||||
idx++) {
|
||||
msk = 1 << idx;
|
||||
if (!(ctxt->stale_mask & msk)) continue;
|
||||
ctxt->stale_mask &= ~msk;
|
||||
decoder_ops[idx].update(ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl)
|
||||
{
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl);
|
||||
pvr2_v4l2_cmd_stream(ctxt->client,fl);
|
||||
}
|
||||
|
||||
|
||||
static int decoder_detect(struct pvr2_i2c_client *cp)
|
||||
{
|
||||
int ret;
|
||||
/* Attempt to query the decoder - let's see if it will answer */
|
||||
struct v4l2_queryctrl qc;
|
||||
|
||||
memset(&qc,0,sizeof(qc));
|
||||
|
||||
qc.id = V4L2_CID_BRIGHTNESS;
|
||||
|
||||
ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc);
|
||||
return ret == 0; /* Return true if it answered */
|
||||
}
|
||||
|
||||
|
||||
static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
struct v4l2_tuner vt;
|
||||
int ret;
|
||||
|
||||
memset(&vt,0,sizeof(vt));
|
||||
ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
|
||||
if (ret < 0) return -EINVAL;
|
||||
return vt.signal ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
|
||||
char *buf,unsigned int cnt)
|
||||
{
|
||||
return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l");
|
||||
}
|
||||
|
||||
|
||||
static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
|
||||
{
|
||||
int ret;
|
||||
ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,0);
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
|
||||
}
|
||||
|
||||
|
||||
const static struct pvr2_i2c_handler_functions hfuncs = {
|
||||
.detach = (void (*)(void *))decoder_detach,
|
||||
.check = (int (*)(void *))decoder_check,
|
||||
.update = (void (*)(void *))decoder_update,
|
||||
.describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
|
||||
};
|
||||
|
||||
|
||||
int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
|
||||
struct pvr2_i2c_client *cp)
|
||||
{
|
||||
struct pvr2_v4l_cx2584x *ctxt;
|
||||
|
||||
if (hdw->decoder_ctrl) return 0;
|
||||
if (cp->handler) return 0;
|
||||
if (!decoder_detect(cp)) return 0;
|
||||
|
||||
ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
|
||||
if (!ctxt) return 0;
|
||||
memset(ctxt,0,sizeof(*ctxt));
|
||||
|
||||
ctxt->handler.func_data = ctxt;
|
||||
ctxt->handler.func_table = &hfuncs;
|
||||
ctxt->ctrl.ctxt = ctxt;
|
||||
ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
|
||||
ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
|
||||
ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
|
||||
ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
|
||||
ctxt->client = cp;
|
||||
ctxt->hdw = hdw;
|
||||
ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
|
||||
sizeof(decoder_ops[0]))) - 1;
|
||||
hdw->decoder_ctrl = &ctxt->ctrl;
|
||||
cp->handler = &ctxt->handler;
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
|
||||
cp->client->addr);
|
||||
return !0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
53
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
Normal file
53
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PVRUSB2_CX2584X_V4L_H
|
||||
#define __PVRUSB2_CX2584X_V4L_H
|
||||
|
||||
/*
|
||||
|
||||
This module connects the pvrusb2 driver to the I2C chip level
|
||||
driver which handles combined device audio & video processing.
|
||||
This interface is used internally by the driver; higher level code
|
||||
should only interact through the interface provided by
|
||||
pvrusb2-hdw.h.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "pvrusb2-i2c-core.h"
|
||||
|
||||
int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
|
||||
|
||||
|
||||
#endif /* __PVRUSB2_CX2584X_V4L_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
67
drivers/media/video/pvrusb2/pvrusb2-debug.h
Normal file
67
drivers/media/video/pvrusb2/pvrusb2-debug.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __PVRUSB2_DEBUG_H
|
||||
#define __PVRUSB2_DEBUG_H
|
||||
|
||||
extern int pvrusb2_debug;
|
||||
|
||||
#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0)
|
||||
|
||||
/* These are listed in *rough* order of decreasing usefulness and
|
||||
increasing noise level. */
|
||||
#define PVR2_TRACE_INFO (1 << 0) // Normal messages
|
||||
#define PVR2_TRACE_ERROR_LEGS (1 << 1) // error messages
|
||||
#define PVR2_TRACE_TOLERANCE (1 << 2) // track tolerance-affected errors
|
||||
#define PVR2_TRACE_TRAP (1 << 3) // Trap & report misbehavior from app
|
||||
#define PVR2_TRACE_INIT (1 << 4) // misc initialization steps
|
||||
#define PVR2_TRACE_START_STOP (1 << 5) // Streaming start / stop
|
||||
#define PVR2_TRACE_CTL (1 << 6) // commit of control changes
|
||||
#define PVR2_TRACE_DEBUG (1 << 7) // Temporary debug code
|
||||
#define PVR2_TRACE_EEPROM (1 << 8) // eeprom parsing / report
|
||||
#define PVR2_TRACE_STRUCT (1 << 9) // internal struct creation
|
||||
#define PVR2_TRACE_OPEN_CLOSE (1 << 10) // application open / close
|
||||
#define PVR2_TRACE_CREG (1 << 11) // Main critical region entry / exit
|
||||
#define PVR2_TRACE_SYSFS (1 << 12) // Sysfs driven I/O
|
||||
#define PVR2_TRACE_FIRMWARE (1 << 13) // firmware upload actions
|
||||
#define PVR2_TRACE_CHIPS (1 << 14) // chip broadcast operation
|
||||
#define PVR2_TRACE_I2C (1 << 15) // I2C related stuff
|
||||
#define PVR2_TRACE_I2C_CMD (1 << 16) // Software commands to I2C modules
|
||||
#define PVR2_TRACE_I2C_CORE (1 << 17) // I2C core debugging
|
||||
#define PVR2_TRACE_I2C_TRAF (1 << 18) // I2C traffic through the adapter
|
||||
#define PVR2_TRACE_V4LIOCTL (1 << 19) // v4l ioctl details
|
||||
#define PVR2_TRACE_ENCODER (1 << 20) // mpeg2 encoder operation
|
||||
#define PVR2_TRACE_BUF_POOL (1 << 21) // Track buffer pool management
|
||||
#define PVR2_TRACE_BUF_FLOW (1 << 22) // Track buffer flow in system
|
||||
#define PVR2_TRACE_DATA_FLOW (1 << 23) // Track data flow
|
||||
#define PVR2_TRACE_DEBUGIFC (1 << 24) // Debug interface actions
|
||||
#define PVR2_TRACE_GPIO (1 << 25) // GPIO state bit changes
|
||||
|
||||
|
||||
#endif /* __PVRUSB2_HDW_INTERNAL_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 75 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
478
drivers/media/video/pvrusb2/pvrusb2-debugifc.c
Normal file
478
drivers/media/video/pvrusb2/pvrusb2-debugifc.c
Normal file
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include "pvrusb2-debugifc.h"
|
||||
#include "pvrusb2-hdw.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
#include "pvrusb2-i2c-core.h"
|
||||
|
||||
struct debugifc_mask_item {
|
||||
const char *name;
|
||||
unsigned long msk;
|
||||
};
|
||||
|
||||
static struct debugifc_mask_item mask_items[] = {
|
||||
{"ENC_FIRMWARE",(1<<PVR2_SUBSYS_B_ENC_FIRMWARE)},
|
||||
{"ENC_CFG",(1<<PVR2_SUBSYS_B_ENC_CFG)},
|
||||
{"DIG_RUN",(1<<PVR2_SUBSYS_B_DIGITIZER_RUN)},
|
||||
{"USB_RUN",(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)},
|
||||
{"ENC_RUN",(1<<PVR2_SUBSYS_B_ENC_RUN)},
|
||||
};
|
||||
|
||||
|
||||
static unsigned int debugifc_count_whitespace(const char *buf,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int scnt;
|
||||
char ch;
|
||||
|
||||
for (scnt = 0; scnt < count; scnt++) {
|
||||
ch = buf[scnt];
|
||||
if (ch == ' ') continue;
|
||||
if (ch == '\t') continue;
|
||||
if (ch == '\n') continue;
|
||||
break;
|
||||
}
|
||||
return scnt;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int debugifc_count_nonwhitespace(const char *buf,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int scnt;
|
||||
char ch;
|
||||
|
||||
for (scnt = 0; scnt < count; scnt++) {
|
||||
ch = buf[scnt];
|
||||
if (ch == ' ') break;
|
||||
if (ch == '\t') break;
|
||||
if (ch == '\n') break;
|
||||
}
|
||||
return scnt;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
|
||||
const char **wstrPtr,
|
||||
unsigned int *wlenPtr)
|
||||
{
|
||||
const char *wptr;
|
||||
unsigned int consume_cnt = 0;
|
||||
unsigned int wlen;
|
||||
unsigned int scnt;
|
||||
|
||||
wptr = 0;
|
||||
wlen = 0;
|
||||
scnt = debugifc_count_whitespace(buf,count);
|
||||
consume_cnt += scnt; count -= scnt; buf += scnt;
|
||||
if (!count) goto done;
|
||||
|
||||
scnt = debugifc_count_nonwhitespace(buf,count);
|
||||
if (!scnt) goto done;
|
||||
wptr = buf;
|
||||
wlen = scnt;
|
||||
consume_cnt += scnt; count -= scnt; buf += scnt;
|
||||
|
||||
done:
|
||||
*wstrPtr = wptr;
|
||||
*wlenPtr = wlen;
|
||||
return consume_cnt;
|
||||
}
|
||||
|
||||
|
||||
static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
|
||||
u32 *num_ptr)
|
||||
{
|
||||
u32 result = 0;
|
||||
u32 val;
|
||||
int ch;
|
||||
int radix = 10;
|
||||
if ((count >= 2) && (buf[0] == '0') &&
|
||||
((buf[1] == 'x') || (buf[1] == 'X'))) {
|
||||
radix = 16;
|
||||
count -= 2;
|
||||
buf += 2;
|
||||
} else if ((count >= 1) && (buf[0] == '0')) {
|
||||
radix = 8;
|
||||
}
|
||||
|
||||
while (count--) {
|
||||
ch = *buf++;
|
||||
if ((ch >= '0') && (ch <= '9')) {
|
||||
val = ch - '0';
|
||||
} else if ((ch >= 'a') && (ch <= 'f')) {
|
||||
val = ch - 'a' + 10;
|
||||
} else if ((ch >= 'A') && (ch <= 'F')) {
|
||||
val = ch - 'A' + 10;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (val >= radix) return -EINVAL;
|
||||
result *= radix;
|
||||
result += val;
|
||||
}
|
||||
*num_ptr = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int debugifc_match_keyword(const char *buf,unsigned int count,
|
||||
const char *keyword)
|
||||
{
|
||||
unsigned int kl;
|
||||
if (!keyword) return 0;
|
||||
kl = strlen(keyword);
|
||||
if (kl != count) return 0;
|
||||
return !memcmp(buf,keyword,kl);
|
||||
}
|
||||
|
||||
|
||||
static unsigned long debugifc_find_mask(const char *buf,unsigned int count)
|
||||
{
|
||||
struct debugifc_mask_item *mip;
|
||||
unsigned int idx;
|
||||
for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
|
||||
mip = mask_items + idx;
|
||||
if (debugifc_match_keyword(buf,count,mip->name)) {
|
||||
return mip->msk;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int debugifc_print_mask(char *buf,unsigned int sz,
|
||||
unsigned long msk,unsigned long val)
|
||||
{
|
||||
struct debugifc_mask_item *mip;
|
||||
unsigned int idx;
|
||||
int bcnt = 0;
|
||||
int ccnt;
|
||||
for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
|
||||
mip = mask_items + idx;
|
||||
if (!(mip->msk & msk)) continue;
|
||||
ccnt = scnprintf(buf,sz,"%s%c%s",
|
||||
(bcnt ? " " : ""),
|
||||
((mip->msk & val) ? '+' : '-'),
|
||||
mip->name);
|
||||
sz -= ccnt;
|
||||
buf += ccnt;
|
||||
bcnt += ccnt;
|
||||
}
|
||||
return bcnt;
|
||||
}
|
||||
|
||||
static unsigned int debugifc_parse_subsys_mask(const char *buf,
|
||||
unsigned int count,
|
||||
unsigned long *mskPtr,
|
||||
unsigned long *valPtr)
|
||||
{
|
||||
const char *wptr;
|
||||
unsigned int consume_cnt = 0;
|
||||
unsigned int scnt;
|
||||
unsigned int wlen;
|
||||
int mode;
|
||||
unsigned long m1,msk,val;
|
||||
|
||||
msk = 0;
|
||||
val = 0;
|
||||
|
||||
while (count) {
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (!scnt) break;
|
||||
consume_cnt += scnt; count -= scnt; buf += scnt;
|
||||
if (!wptr) break;
|
||||
|
||||
mode = 0;
|
||||
if (wlen) switch (wptr[0]) {
|
||||
case '+':
|
||||
wptr++;
|
||||
wlen--;
|
||||
break;
|
||||
case '-':
|
||||
mode = 1;
|
||||
wptr++;
|
||||
wlen--;
|
||||
break;
|
||||
}
|
||||
if (!wlen) continue;
|
||||
m1 = debugifc_find_mask(wptr,wlen);
|
||||
if (!m1) break;
|
||||
msk |= m1;
|
||||
if (!mode) val |= m1;
|
||||
}
|
||||
*mskPtr = msk;
|
||||
*valPtr = val;
|
||||
return consume_cnt;
|
||||
}
|
||||
|
||||
|
||||
int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
|
||||
{
|
||||
int bcnt = 0;
|
||||
int ccnt;
|
||||
struct pvr2_hdw_debug_info dbg;
|
||||
|
||||
pvr2_hdw_get_debug_info(hdw,&dbg);
|
||||
|
||||
ccnt = scnprintf(buf,acnt,"big lock %s; ctl lock %s",
|
||||
(dbg.big_lock_held ? "held" : "free"),
|
||||
(dbg.ctl_lock_held ? "held" : "free"));
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
if (dbg.ctl_lock_held) {
|
||||
ccnt = scnprintf(buf,acnt,"; cmd_state=%d cmd_code=%d"
|
||||
" cmd_wlen=%d cmd_rlen=%d"
|
||||
" wpend=%d rpend=%d tmout=%d rstatus=%d"
|
||||
" wstatus=%d",
|
||||
dbg.cmd_debug_state,dbg.cmd_code,
|
||||
dbg.cmd_debug_write_len,
|
||||
dbg.cmd_debug_read_len,
|
||||
dbg.cmd_debug_write_pend,
|
||||
dbg.cmd_debug_read_pend,
|
||||
dbg.cmd_debug_timeout,
|
||||
dbg.cmd_debug_rstatus,
|
||||
dbg.cmd_debug_wstatus);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
}
|
||||
ccnt = scnprintf(buf,acnt,"\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(
|
||||
buf,acnt,"driver flags: %s %s %s\n",
|
||||
(dbg.flag_init_ok ? "initialized" : "uninitialized"),
|
||||
(dbg.flag_ok ? "ok" : "fail"),
|
||||
(dbg.flag_disconnected ? "disconnected" : "connected"));
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: ");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = debugifc_print_mask(buf,acnt,dbg.subsys_flags,dbg.subsys_flags);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: ");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = debugifc_print_mask(buf,acnt,~dbg.subsys_flags,dbg.subsys_flags);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = pvr2_i2c_report(hdw,buf,acnt);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
return bcnt;
|
||||
}
|
||||
|
||||
|
||||
int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
|
||||
char *buf,unsigned int acnt)
|
||||
{
|
||||
int bcnt = 0;
|
||||
int ccnt;
|
||||
unsigned long msk;
|
||||
int ret;
|
||||
u32 gpio_dir,gpio_in,gpio_out;
|
||||
|
||||
ret = pvr2_hdw_is_hsm(hdw);
|
||||
ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
|
||||
(ret < 0 ? "FAIL" : (ret ? "high" : "full")));
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
gpio_dir = 0; gpio_in = 0; gpio_out = 0;
|
||||
pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
|
||||
pvr2_hdw_gpio_get_out(hdw,&gpio_out);
|
||||
pvr2_hdw_gpio_get_in(hdw,&gpio_in);
|
||||
ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
|
||||
gpio_dir,gpio_in,gpio_out);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
|
||||
pvr2_hdw_get_streaming(hdw) ? "on" : "off");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
msk = pvr2_hdw_subsys_get(hdw);
|
||||
ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: ");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = debugifc_print_mask(buf,acnt,msk,msk);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: ");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = debugifc_print_mask(buf,acnt,~msk,msk);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
msk = pvr2_hdw_subsys_stream_get(hdw);
|
||||
ccnt = scnprintf(buf,acnt,"Subsystems stopped on stream shutdown: ");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = debugifc_print_mask(buf,acnt,msk,msk);
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
ccnt = scnprintf(buf,acnt,"\n");
|
||||
bcnt += ccnt; acnt -= ccnt; buf += ccnt;
|
||||
|
||||
return bcnt;
|
||||
}
|
||||
|
||||
|
||||
int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
|
||||
unsigned int count)
|
||||
{
|
||||
const char *wptr;
|
||||
unsigned int wlen;
|
||||
unsigned int scnt;
|
||||
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (!scnt) return 0;
|
||||
count -= scnt; buf += scnt;
|
||||
if (!wptr) return 0;
|
||||
|
||||
pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
|
||||
if (debugifc_match_keyword(wptr,wlen,"reset")) {
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (!scnt) return -EINVAL;
|
||||
count -= scnt; buf += scnt;
|
||||
if (!wptr) return -EINVAL;
|
||||
if (debugifc_match_keyword(wptr,wlen,"cpu")) {
|
||||
pvr2_hdw_cpureset_assert(hdw,!0);
|
||||
pvr2_hdw_cpureset_assert(hdw,0);
|
||||
return 0;
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"bus")) {
|
||||
pvr2_hdw_device_reset(hdw);
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"soft")) {
|
||||
return pvr2_hdw_cmd_powerup(hdw);
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"deep")) {
|
||||
return pvr2_hdw_cmd_deep_reset(hdw);
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
|
||||
return pvr2_upload_firmware2(hdw);
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
|
||||
return pvr2_hdw_cmd_decoder_reset(hdw);
|
||||
}
|
||||
return -EINVAL;
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"subsys_flags")) {
|
||||
unsigned long msk = 0;
|
||||
unsigned long val = 0;
|
||||
if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) {
|
||||
pvr2_trace(PVR2_TRACE_DEBUGIFC,
|
||||
"debugifc parse error on subsys mask");
|
||||
return -EINVAL;
|
||||
}
|
||||
pvr2_hdw_subsys_bit_chg(hdw,msk,val);
|
||||
return 0;
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"stream_flags")) {
|
||||
unsigned long msk = 0;
|
||||
unsigned long val = 0;
|
||||
if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) {
|
||||
pvr2_trace(PVR2_TRACE_DEBUGIFC,
|
||||
"debugifc parse error on stream mask");
|
||||
return -EINVAL;
|
||||
}
|
||||
pvr2_hdw_subsys_stream_bit_chg(hdw,msk,val);
|
||||
return 0;
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (!scnt) return -EINVAL;
|
||||
count -= scnt; buf += scnt;
|
||||
if (!wptr) return -EINVAL;
|
||||
if (debugifc_match_keyword(wptr,wlen,"fetch")) {
|
||||
pvr2_hdw_cpufw_set_enabled(hdw,!0);
|
||||
return 0;
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"done")) {
|
||||
pvr2_hdw_cpufw_set_enabled(hdw,0);
|
||||
return 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
|
||||
int dir_fl = 0;
|
||||
int ret;
|
||||
u32 msk,val;
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (!scnt) return -EINVAL;
|
||||
count -= scnt; buf += scnt;
|
||||
if (!wptr) return -EINVAL;
|
||||
if (debugifc_match_keyword(wptr,wlen,"dir")) {
|
||||
dir_fl = !0;
|
||||
} else if (!debugifc_match_keyword(wptr,wlen,"out")) {
|
||||
return -EINVAL;
|
||||
}
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (!scnt) return -EINVAL;
|
||||
count -= scnt; buf += scnt;
|
||||
if (!wptr) return -EINVAL;
|
||||
ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
|
||||
if (ret) return ret;
|
||||
scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
|
||||
if (wptr) {
|
||||
ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
|
||||
if (ret) return ret;
|
||||
} else {
|
||||
val = msk;
|
||||
msk = 0xffffffff;
|
||||
}
|
||||
if (dir_fl) {
|
||||
ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
|
||||
} else {
|
||||
ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
pvr2_trace(PVR2_TRACE_DEBUGIFC,
|
||||
"debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
|
||||
unsigned int count)
|
||||
{
|
||||
unsigned int bcnt = 0;
|
||||
int ret;
|
||||
|
||||
while (count) {
|
||||
for (bcnt = 0; bcnt < count; bcnt++) {
|
||||
if (buf[bcnt] == '\n') break;
|
||||
}
|
||||
|
||||
ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
|
||||
if (ret < 0) return ret;
|
||||
if (bcnt < count) bcnt++;
|
||||
buf += bcnt;
|
||||
count -= bcnt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 75 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
53
drivers/media/video/pvrusb2/pvrusb2-debugifc.h
Normal file
53
drivers/media/video/pvrusb2/pvrusb2-debugifc.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __PVRUSB2_DEBUGIFC_H
|
||||
#define __PVRUSB2_DEBUGIFC_H
|
||||
|
||||
struct pvr2_hdw;
|
||||
|
||||
/* Non-intrusively print some useful debugging info from inside the
|
||||
driver. This should work even if the driver appears to be
|
||||
wedged. */
|
||||
int pvr2_debugifc_print_info(struct pvr2_hdw *,
|
||||
char *buf_ptr,unsigned int buf_size);
|
||||
|
||||
/* Print general status of driver. This will also trigger a probe of
|
||||
the USB link. Unlike print_info(), this one synchronizes with the
|
||||
driver so the information should be self-consistent (but it will
|
||||
hang if the driver is wedged). */
|
||||
int pvr2_debugifc_print_status(struct pvr2_hdw *,
|
||||
char *buf_ptr,unsigned int buf_size);
|
||||
|
||||
/* Parse a string command into a driver action. */
|
||||
int pvr2_debugifc_docmd(struct pvr2_hdw *,
|
||||
const char *buf_ptr,unsigned int buf_size);
|
||||
|
||||
#endif /* __PVRUSB2_DEBUGIFC_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 75 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
126
drivers/media/video/pvrusb2/pvrusb2-demod.c
Normal file
126
drivers/media/video/pvrusb2/pvrusb2-demod.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pvrusb2.h"
|
||||
#include "pvrusb2-util.h"
|
||||
#include "pvrusb2-demod.h"
|
||||
#include "pvrusb2-hdw-internal.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/tuner.h>
|
||||
#include <media/v4l2-common.h>
|
||||
|
||||
|
||||
struct pvr2_demod_handler {
|
||||
struct pvr2_hdw *hdw;
|
||||
struct pvr2_i2c_client *client;
|
||||
struct pvr2_i2c_handler i2c_handler;
|
||||
int type_update_fl;
|
||||
};
|
||||
|
||||
|
||||
static void set_config(struct pvr2_demod_handler *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
int cfg = 0;
|
||||
|
||||
switch (hdw->tuner_type) {
|
||||
case TUNER_PHILIPS_FM1216ME_MK3:
|
||||
case TUNER_PHILIPS_FM1236_MK3:
|
||||
cfg = TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c demod set_config(0x%x)",cfg);
|
||||
pvr2_i2c_client_cmd(ctxt->client,TDA9887_SET_CONFIG,&cfg);
|
||||
ctxt->type_update_fl = 0;
|
||||
}
|
||||
|
||||
|
||||
static int demod_check(struct pvr2_demod_handler *ctxt)
|
||||
{
|
||||
struct pvr2_hdw *hdw = ctxt->hdw;
|
||||
if (hdw->tuner_updated) ctxt->type_update_fl = !0;
|
||||
return ctxt->type_update_fl != 0;
|
||||
}
|
||||
|
||||
|
||||
static void demod_update(struct pvr2_demod_handler *ctxt)
|
||||
{
|
||||
if (ctxt->type_update_fl) set_config(ctxt);
|
||||
}
|
||||
|
||||
|
||||
static void demod_detach(struct pvr2_demod_handler *ctxt)
|
||||
{
|
||||
ctxt->client->handler = 0;
|
||||
kfree(ctxt);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int demod_describe(struct pvr2_demod_handler *ctxt,char *buf,unsigned int cnt)
|
||||
{
|
||||
return scnprintf(buf,cnt,"handler: pvrusb2-demod");
|
||||
}
|
||||
|
||||
|
||||
const static struct pvr2_i2c_handler_functions tuner_funcs = {
|
||||
.detach = (void (*)(void *))demod_detach,
|
||||
.check = (int (*)(void *))demod_check,
|
||||
.update = (void (*)(void *))demod_update,
|
||||
.describe = (unsigned int (*)(void *,char *,unsigned int))demod_describe,
|
||||
};
|
||||
|
||||
|
||||
int pvr2_i2c_demod_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
|
||||
{
|
||||
struct pvr2_demod_handler *ctxt;
|
||||
if (cp->handler) return 0;
|
||||
|
||||
ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
|
||||
if (!ctxt) return 0;
|
||||
memset(ctxt,0,sizeof(*ctxt));
|
||||
|
||||
ctxt->i2c_handler.func_data = ctxt;
|
||||
ctxt->i2c_handler.func_table = &tuner_funcs;
|
||||
ctxt->type_update_fl = !0;
|
||||
ctxt->client = cp;
|
||||
ctxt->hdw = hdw;
|
||||
cp->handler = &ctxt->i2c_handler;
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tda9887 V4L2 handler set up",
|
||||
cp->client->addr);
|
||||
return !0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
38
drivers/media/video/pvrusb2/pvrusb2-demod.h
Normal file
38
drivers/media/video/pvrusb2/pvrusb2-demod.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __PVRUSB2_DEMOD_H
|
||||
#define __PVRUSB2_DEMOD_H
|
||||
|
||||
#include "pvrusb2-i2c-core.h"
|
||||
|
||||
int pvr2_i2c_demod_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
|
||||
|
||||
#endif /* __PVRUSB2_DEMOD_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
164
drivers/media/video/pvrusb2/pvrusb2-eeprom.c
Normal file
164
drivers/media/video/pvrusb2/pvrusb2-eeprom.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pvrusb2-eeprom.h"
|
||||
#include "pvrusb2-hdw-internal.h"
|
||||
#include "pvrusb2-debug.h"
|
||||
|
||||
#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Read and analyze data in the eeprom. Use tveeprom to figure out
|
||||
the packet structure, since this is another Hauppauge device and
|
||||
internally it has a family resemblence to ivtv-type devices
|
||||
|
||||
*/
|
||||
|
||||
#include <media/tveeprom.h>
|
||||
|
||||
/* We seem to only be interested in the last 128 bytes of the EEPROM */
|
||||
#define EEPROM_SIZE 128
|
||||
|
||||
/* Grab EEPROM contents, needed for direct method. */
|
||||
static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
|
||||
{
|
||||
struct i2c_msg msg[2];
|
||||
u8 *eeprom;
|
||||
u8 iadd[2];
|
||||
u8 addr;
|
||||
u16 eepromSize;
|
||||
unsigned int offs;
|
||||
int ret;
|
||||
int mode16 = 0;
|
||||
unsigned pcnt,tcnt;
|
||||
eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
|
||||
if (!eeprom) {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"Failed to allocate memory"
|
||||
" required to read eeprom");
|
||||
return 0;
|
||||
}
|
||||
|
||||
trace_eeprom("Value for eeprom addr from controller was 0x%x",
|
||||
hdw->eeprom_addr);
|
||||
addr = hdw->eeprom_addr;
|
||||
/* Seems that if the high bit is set, then the *real* eeprom
|
||||
address is shifted right now bit position (noticed this in
|
||||
newer PVR USB2 hardware) */
|
||||
if (addr & 0x80) addr >>= 1;
|
||||
|
||||
/* FX2 documentation states that a 16bit-addressed eeprom is
|
||||
expected if the I2C address is an odd number (yeah, this is
|
||||
strange but it's what they do) */
|
||||
mode16 = (addr & 1);
|
||||
eepromSize = (mode16 ? 4096 : 256);
|
||||
trace_eeprom("Examining %d byte eeprom at location 0x%x"
|
||||
" using %d bit addressing",eepromSize,addr,
|
||||
mode16 ? 16 : 8);
|
||||
|
||||
msg[0].addr = addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = mode16 ? 2 : 1;
|
||||
msg[0].buf = iadd;
|
||||
msg[1].addr = addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
|
||||
/* We have to do the actual eeprom data fetch ourselves, because
|
||||
(1) we're only fetching part of the eeprom, and (2) if we were
|
||||
getting the whole thing our I2C driver can't grab it in one
|
||||
pass - which is what tveeprom is otherwise going to attempt */
|
||||
memset(eeprom,0,EEPROM_SIZE);
|
||||
for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
|
||||
pcnt = 16;
|
||||
if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
|
||||
offs = tcnt + (eepromSize - EEPROM_SIZE);
|
||||
if (mode16) {
|
||||
iadd[0] = offs >> 8;
|
||||
iadd[1] = offs;
|
||||
} else {
|
||||
iadd[0] = offs;
|
||||
}
|
||||
msg[1].len = pcnt;
|
||||
msg[1].buf = eeprom+tcnt;
|
||||
if ((ret = i2c_transfer(
|
||||
&hdw->i2c_adap,
|
||||
msg,sizeof(msg)/sizeof(msg[0]))) != 2) {
|
||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||
"eeprom fetch set offs err=%d",ret);
|
||||
kfree(eeprom);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return eeprom;
|
||||
}
|
||||
|
||||
|
||||
/* Directly call eeprom analysis function within tveeprom. */
|
||||
int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
|
||||
{
|
||||
u8 *eeprom;
|
||||
struct tveeprom tvdata;
|
||||
|
||||
memset(&tvdata,0,sizeof(tvdata));
|
||||
|
||||
eeprom = pvr2_eeprom_fetch(hdw);
|
||||
if (!eeprom) return -EINVAL;
|
||||
|
||||
{
|
||||
struct i2c_client fake_client;
|
||||
/* Newer version expects a useless client interface */
|
||||
fake_client.addr = hdw->eeprom_addr;
|
||||
fake_client.adapter = &hdw->i2c_adap;
|
||||
tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
|
||||
}
|
||||
|
||||
trace_eeprom("eeprom assumed v4l tveeprom module");
|
||||
trace_eeprom("eeprom direct call results:");
|
||||
trace_eeprom("has_radio=%d",tvdata.has_radio);
|
||||
trace_eeprom("tuner_type=%d",tvdata.tuner_type);
|
||||
trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats);
|
||||
trace_eeprom("audio_processor=%d",tvdata.audio_processor);
|
||||
trace_eeprom("model=%d",tvdata.model);
|
||||
trace_eeprom("revision=%d",tvdata.revision);
|
||||
trace_eeprom("serial_number=%d",tvdata.serial_number);
|
||||
trace_eeprom("rev_str=%s",tvdata.rev_str);
|
||||
hdw->tuner_type = tvdata.tuner_type;
|
||||
hdw->serial_number = tvdata.serial_number;
|
||||
hdw->std_mask_eeprom = tvdata.tuner_formats;
|
||||
|
||||
kfree(eeprom);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
40
drivers/media/video/pvrusb2/pvrusb2-eeprom.h
Normal file
40
drivers/media/video/pvrusb2/pvrusb2-eeprom.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2005 Mike Isely <isely@pobox.com>
|
||||
* Copyright (C) 2004 Aurelien Alleaume <slts@free.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; either 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PVRUSB2_EEPROM_H
|
||||
#define __PVRUSB2_EEPROM_H
|
||||
|
||||
struct pvr2_hdw;
|
||||
|
||||
int pvr2_eeprom_analyze(struct pvr2_hdw *);
|
||||
|
||||
#endif /* __PVRUSB2_EEPROM_H */
|
||||
|
||||
/*
|
||||
Stuff for Emacs to see, in order to encourage consistent editing style:
|
||||
*** Local Variables: ***
|
||||
*** mode: c ***
|
||||
*** fill-column: 70 ***
|
||||
*** tab-width: 8 ***
|
||||
*** c-basic-offset: 8 ***
|
||||
*** End: ***
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user