Commit d855497e authored by Mike Isely's avatar Mike Isely Committed by Mauro Carvalho Chehab

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: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent eb99adde
$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
......
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.
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
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
/*
* $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: ***
*/
/*
* $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: ***
*/
This diff is collapsed.
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
/*
* $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: ***
*/
This diff is collapsed.
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
/*
*
* $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: ***
*/
This diff is collapsed.
/*
*
* $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_ENCODER_H
#define __PVRUSB2_ENCODER_H
struct pvr2_hdw;
int pvr2_encoder_configure(struct pvr2_hdw *);
int pvr2_encoder_start(struct pvr2_hdw *);
int pvr2_encoder_stop(struct pvr2_hdw *);
#endif /* __PVRUSB2_ENCODER_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: ***
*/
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
*
* $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-i2c-core.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-debug.h"
#include "pvrusb2-i2c-cmd-v4l2.h"
#include "pvrusb2-audio.h"
#include "pvrusb2-tuner.h"
#include "pvrusb2-demod.h"
#include "pvrusb2-video-v4l.h"
#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
#include "pvrusb2-cx2584x-v4l.h"
#include "pvrusb2-wm8775.h"
#endif
#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
#define OP_STANDARD 0
#define OP_BCSH 1
#define OP_VOLUME 2
#define OP_FREQ 3
#define OP_AUDIORATE 4
#define OP_SIZE 5
#define OP_LOG 6
static const struct pvr2_i2c_op * const ops[] = {
[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
[OP_SIZE] = &pvr2_i2c_op_v4l2_size,
[OP_LOG] = &pvr2_i2c_op_v4l2_log,
};
void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
{
int id;
id = cp->client->driver->id;
cp->ctl_mask = ((1 << OP_STANDARD) |
(1 << OP_BCSH) |
(1 << OP_VOLUME) |
(1 << OP_FREQ) |
(1 << OP_SIZE) |
(1 << OP_LOG));
if (id == I2C_DRIVERID_MSP3400) {
if (pvr2_i2c_msp3400_setup(hdw,cp)) {
return;
}
}
if (id == I2C_DRIVERID_TUNER) {
if (pvr2_i2c_tuner_setup(hdw,cp)) {
return;
}
}
#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
if (id == I2C_DRIVERID_CX25840) {
if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
return;
}
}
if (id == I2C_DRIVERID_WM8775) {
if (pvr2_i2c_wm8775_setup(hdw,cp)) {
return;
}
}
#endif
if (id == I2C_DRIVERID_SAA711X) {
if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
return;
}
}
if (id == I2C_DRIVERID_TDA9887) {
if (pvr2_i2c_demod_setup(hdw,cp)) {
return;
}
}
}
const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
{
if (idx >= sizeof(ops)/sizeof(ops[0])) return 0;
return ops[idx];
}
/*
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: ***
*/
/*
*
* $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-i2c-cmd-v4l2.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-debug.h"
#include <linux/videodev2.h>
static void set_standard(struct pvr2_hdw *hdw)
{
v4l2_std_id vs;
vs = hdw->std_mask_cur;
pvr2_trace(PVR2_TRACE_CHIPS,
"i2c v4l2 set_standard(0x%llx)",(__u64)vs);
pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
}
static int check_standard(struct pvr2_hdw *hdw)
{
return hdw->std_dirty != 0;
}
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = {
.check = check_standard,
.update = set_standard,
.name = "v4l2_standard",
};
static void set_bcsh(struct pvr2_hdw *hdw)
{
struct v4l2_control ctrl;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh"
" b=%d c=%d s=%d h=%d",
hdw->brightness_val,hdw->contrast_val,
hdw->saturation_val,hdw->hue_val);
memset(&ctrl,0,sizeof(ctrl));
ctrl.id = V4L2_CID_BRIGHTNESS;
ctrl.value = hdw->brightness_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_CONTRAST;
ctrl.value = hdw->contrast_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_SATURATION;
ctrl.value = hdw->saturation_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_HUE;
ctrl.value = hdw->hue_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
}
static int check_bcsh(struct pvr2_hdw *hdw)
{
return (hdw->brightness_dirty ||
hdw->contrast_dirty ||
hdw->saturation_dirty ||
hdw->hue_dirty);
}
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = {
.check = check_bcsh,
.update = set_bcsh,
.name = "v4l2_bcsh",
};
static void set_volume(struct pvr2_hdw *hdw)
{
struct v4l2_control ctrl;
pvr2_trace(PVR2_TRACE_CHIPS,
"i2c v4l2 set_volume"
"(vol=%d bal=%d bas=%d treb=%d mute=%d)",
hdw->volume_val,
hdw->balance_val,
hdw->bass_val,
hdw->treble_val,
hdw->mute_val);
memset(&ctrl,0,sizeof(ctrl));
ctrl.id = V4L2_CID_AUDIO_MUTE;
ctrl.value = hdw->mute_val ? 1 : 0;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_VOLUME;
ctrl.value = hdw->volume_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_BALANCE;
ctrl.value = hdw->balance_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_BASS;
ctrl.value = hdw->bass_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
ctrl.id = V4L2_CID_AUDIO_TREBLE;
ctrl.value = hdw->treble_val;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
}
static int check_volume(struct pvr2_hdw *hdw)
{
return (hdw->volume_dirty ||
hdw->balance_dirty ||
hdw->bass_dirty ||
hdw->treble_dirty ||
hdw->mute_dirty);
}
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = {
.check = check_volume,
.update = set_volume,
.name = "v4l2_volume",
};
static void set_frequency(struct pvr2_hdw *hdw)
{
unsigned long fv;
struct v4l2_frequency freq;
fv = hdw->freqVal;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
memset(&freq,0,sizeof(freq));
freq.frequency = fv / 62500;
freq.tuner = 0;
freq.type = V4L2_TUNER_ANALOG_TV;
pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
}
static int check_frequency(struct pvr2_hdw *hdw)
{
return hdw->freqDirty != 0;
}
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = {
.check = check_frequency,
.update = set_frequency,
.name = "v4l2_freq",
};
static void set_size(struct pvr2_hdw *hdw)
{
struct v4l2_format fmt;
memset(&fmt,0,sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = hdw->res_hor_val;
fmt.fmt.pix.height = hdw->res_ver_val;
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)",
fmt.fmt.pix.width,fmt.fmt.pix.height);
pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt);
}
static int check_size(struct pvr2_hdw *hdw)
{
return (hdw->res_hor_dirty || hdw->res_ver_dirty);
}
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
.check = check_size,
.update = set_size,
.name = "v4l2_size",
};
static void do_log(struct pvr2_hdw *hdw)
{
pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,0);
}
static int check_log(struct pvr2_hdw *hdw)
{
return hdw->log_requested != 0;
}
const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = {
.check = check_log,
.update = do_log,
.name = "v4l2_log",
};
void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
{
pvr2_i2c_client_cmd(cp,
(fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),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: ***
*/
/*
*
* $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_CMD_V4L2_H
#define __PVRUSB2_CMD_V4L2_H
#include "pvrusb2-i2c-core.h"
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
#endif /* __PVRUSB2_CMD_V4L2_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: ***
*/
This diff is collapsed.
/*
*
* $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_I2C_CORE_H
#define __PVRUSB2_I2C_CORE_H
#include <linux/list.h>
#include <linux/i2c.h>
struct pvr2_hdw;
struct pvr2_i2c_client;
struct pvr2_i2c_handler;
struct pvr2_i2c_handler_functions;
struct pvr2_i2c_op;
struct pvr2_i2c_op_functions;
struct pvr2_i2c_client {
struct i2c_client *client;
struct pvr2_i2c_handler *handler;
struct list_head list;
int detected_flag;
int recv_enable;
unsigned long pend_mask;
unsigned long ctl_mask;
};
struct pvr2_i2c_handler {
void *func_data;
const struct pvr2_i2c_handler_functions *func_table;
};
struct pvr2_i2c_handler_functions {
void (*detach)(void *);
int (*check)(void *);
void (*update)(void *);
unsigned int (*describe)(void *,char *,unsigned int);
};
struct pvr2_i2c_op {
int (*check)(struct pvr2_hdw *);
void (*update)(struct pvr2_hdw *);
const char *name;
};
void pvr2_i2c_core_init(struct pvr2_hdw *);
void pvr2_i2c_core_done(struct pvr2_hdw *);
int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg);
int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg);
int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
void pvr2_i2c_core_sync(struct pvr2_hdw *);
unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
#define PVR2_I2C_DETAIL_DEBUG 0x0001
#define PVR2_I2C_DETAIL_HANDLER 0x0002
#define PVR2_I2C_DETAIL_CTLMASK 0x0004
#define PVR2_I2C_DETAIL_ALL (\
PVR2_I2C_DETAIL_DEBUG |\
PVR2_I2C_DETAIL_HANDLER |\
PVR2_I2C_DETAIL_CTLMASK)
unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *,
unsigned int detail_mask,
char *buf,unsigned int maxlen);
void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
#endif /* __PVRUSB2_I2C_CORE_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: ***
*/
This diff is collapsed.
/*
*
* $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_IO_H
#define __PVRUSB2_IO_H
#include <linux/usb.h>
#include <linux/list.h>
typedef void (*pvr2_stream_callback)(void *);
enum pvr2_buffer_state {
pvr2_buffer_state_none = 0, // Not on any list
pvr2_buffer_state_idle = 1, // Buffer is ready to be used again
pvr2_buffer_state_queued = 2, // Buffer has been queued for filling
pvr2_buffer_state_ready = 3, // Buffer has data available
};
struct pvr2_stream;
struct pvr2_buffer;
const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
/* Initialize / tear down stream structure */
struct pvr2_stream *pvr2_stream_create(void);
void pvr2_stream_destroy(struct pvr2_stream *);
void pvr2_stream_setup(struct pvr2_stream *,
struct usb_device *dev,int endpoint,
unsigned int tolerance);
void pvr2_stream_set_callback(struct pvr2_stream *,
pvr2_stream_callback func,
void *data);
/* Query / set the nominal buffer count */
int pvr2_stream_get_buffer_count(struct pvr2_stream *);
int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
/* Get a pointer to a buffer that is either idle, ready, or is specified
named. */
struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *);
struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *);
struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
/* Find out how many buffers are idle or ready */
int pvr2_stream_get_idle_count(struct pvr2_stream *);
int pvr2_stream_get_ready_count(struct pvr2_stream *);
/* Kill all pending operations */
void pvr2_stream_flush(struct pvr2_stream *);
/* Kill all pending buffers and throw away any ready buffers as well */
void pvr2_stream_kill(struct pvr2_stream *);
/* Set up the actual storage for a buffer */
int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt);
/* Find out size of data in the given ready buffer */
unsigned int pvr2_buffer_get_count(struct pvr2_buffer *);
/* Retrieve completion code for given ready buffer */
int pvr2_buffer_get_status(struct pvr2_buffer *);
/* Retrieve state of given buffer */
enum pvr2_buffer_state pvr2_buffer_get_state(struct pvr2_buffer *);
/* Retrieve ID of given buffer */
int pvr2_buffer_get_id(struct pvr2_buffer *);
/* Start reading into given buffer (kill it if needed) */
int pvr2_buffer_queue(struct pvr2_buffer *);
/* Move buffer back to idle pool (kill it if needed) */
int pvr2_buffer_idle(struct pvr2_buffer *);
#endif /* __PVRUSB2_IO_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: ***
*/
This diff is collapsed.
/*
*
* $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_IOREAD_H
#define __PVRUSB2_IOREAD_H
#include "pvrusb2-io.h"
struct pvr2_ioread;
struct pvr2_ioread *pvr2_ioread_create(void);
void pvr2_ioread_destroy(struct pvr2_ioread *);
int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *);
struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *);
void pvr2_ioread_set_sync_key(struct pvr2_ioread *,
const char *sync_key_ptr,
unsigned int sync_key_len);
int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl);
int pvr2_ioread_get_enabled(struct pvr2_ioread *);
int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt);
int pvr2_ioread_avail(struct pvr2_ioread *);
#endif /* __PVRUSB2_IOREAD_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: ***
*/
/*
*
* $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 <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/smp_lock.h>
#include <linux/usb.h>
#include <linux/videodev2.h>
#include "pvrusb2-hdw.h"
#include "pvrusb2-context.h"
#include "pvrusb2-debug.h"
#include "pvrusb2-v4l2.h"
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
#include "pvrusb2-sysfs.h"
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>"
#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner"
#define DRIVER_VERSION "V4L in-tree version"
#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \
PVR2_TRACE_INFO| \
PVR2_TRACE_TOLERANCE| \
PVR2_TRACE_TRAP| \
PVR2_TRACE_FIRMWARE| \
PVR2_TRACE_EEPROM | \
PVR2_TRACE_INIT | \
PVR2_TRACE_I2C | \
PVR2_TRACE_CHIPS | \
PVR2_TRACE_START_STOP | \
PVR2_TRACE_CTL | \
PVR2_TRACE_DEBUGIFC | \
0)
int pvrusb2_debug = DEFAULT_DEBUG_MASK;
module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "Debug trace mask");
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
static struct pvr2_sysfs_class *class_ptr = 0;
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
static void pvr_setup_attach(struct pvr2_context *pvr)
{
/* Create association with v4l layer */
pvr2_v4l2_create(pvr);
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_create(pvr,class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
}
static int pvr_probe(struct usb_interface *intf,
const struct usb_device_id *devid)
{
struct pvr2_context *pvr;
/* Create underlying hardware interface */
pvr = pvr2_context_create(intf,devid,pvr_setup_attach);
if (!pvr) {
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
"Failed to create hdw handler");
return -ENOMEM;
}
pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr);
usb_set_intfdata(intf, pvr);
return 0;
}
/*
* pvr_disconnect()
*
*/
static void pvr_disconnect(struct usb_interface *intf)
{
struct pvr2_context *pvr = usb_get_intfdata(intf);
pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr);
usb_set_intfdata (intf, NULL);
pvr2_context_disconnect(pvr);
pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr);
}
static struct usb_driver pvr_driver = {
name: "pvrusb2",
id_table: pvr2_device_table,
probe: pvr_probe,
disconnect: pvr_disconnect
};
/*
* pvr_init() / pvr_exit()
*
* This code is run to initialize/exit the driver.
*
*/
static int __init pvr_init(void)
{
int ret;
pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
class_ptr = pvr2_sysfs_class_create();
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
ret = usb_register(&pvr_driver);
if (ret == 0)
info(DRIVER_DESC " : " DRIVER_VERSION);
if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
pvrusb2_debug,pvrusb2_debug);
return ret;
}
static void __exit pvr_exit(void)
{
pvr2_trace(PVR2_TRACE_INIT,"pvr_exit");
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_class_destroy(class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
usb_deregister(&pvr_driver);
}
module_init(pvr_init);
module_exit(pvr_exit);
/* Mike Isely <mcisely@pobox.com> 11-Mar-2006: See pvrusb2-hdw.c for
MODULE_DEVICE_TABLE(). We have to declare that attribute there
because that's where the device table actually is now and it seems
that certain gcc configurations get angry if MODULE_DEVICE_TABLE()
is used on what ends up being an external symbol. */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
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: ***
*/
This diff is collapsed.
/*
*
* $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_STD_H
#define __PVRUSB2_STD_H
#include <linux/videodev2.h>
// Convert string describing one or more video standards into a mask of V4L
// standard bits. Return true if conversion succeeds otherwise return
// false. String is expected to be of the form: C1-x/y;C2-a/b where C1 and
// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are
// modulation schemes (e.g. "M", "B", "G", etc).
int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
unsigned int bufSize);
// Convert any arbitrary set of video standard bits into an unambiguous
// readable string. Return value is the number of bytes consumed in the
// buffer. The formatted string is of a form that can be parsed by our
// sibling std_std_to_id() function.
unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
v4l2_std_id id);
// Create an array of suitable v4l2_standard structures given a bit mask of
// video standards to support. The array is allocated from the heap, and
// the number of elements is returned in the first argument.
struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
v4l2_std_id id);
// Return mask of which video standard bits are valid
v4l2_std_id pvr2_std_get_usable(void);
#endif /* __PVRUSB2_STD_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: ***
*/
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment