V4L/DVB (7679): pvrusb2: add DVB API framework

Add basic framework for the DVB API.  This is enough to control the
tuner & demod of the digital frontend, but the stream & buffer handling
is still missing.

Additional note from Mike Isely <isely@pobox.com> - also, since these
changes are still very experimental arrange for DVB changes to be
compiled in via new CONFIG_VIDEO_PVRUSB2_DVB option, for now.

Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Michael Krufky 2008-02-03 23:46:16 -03:00 committed by Mauro Carvalho Chehab
parent e7f677f336
commit 04910bdc5c
6 changed files with 232 additions and 0 deletions

View file

@ -1,5 +1,6 @@
obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
@ -9,6 +10,11 @@ pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
$(obj-pvrusb2-dvb-y) \
$(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
EXTRA_CFLAGS += -Idrivers/media/video
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends

View file

@ -23,6 +23,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include "pvrusb2-dvb.h"
/* /*
@ -65,6 +66,9 @@ struct pvr2_device_desc {
was initialized from internal ROM. */ was initialized from internal ROM. */
struct pvr2_string_table fx2_firmware; struct pvr2_string_table fx2_firmware;
/* callback functions to handle attachment of digital tuner & demod */
struct pvr2_dvb_props *dvb_props;
/* Initial standard bits to use for this device, if not zero. /* Initial standard bits to use for this device, if not zero.
Anything set here is also implied as an available standard. Anything set here is also implied as an available standard.
Note: This is ignored if overridden on the module load line via Note: This is ignored if overridden on the module load line via

View file

@ -0,0 +1,179 @@
/*
* pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
*
* Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
*
* 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 "dvbdev.h"
#include "pvrusb2-hdw-internal.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-dvb.h"
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
dvbdmxfeed->pid, dvbdmxfeed->type);
return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 1); */
}
static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
dvbdmxfeed->pid, dvbdmxfeed->type);
return 0; /* FIXME: pvr2_dvb_ctrl_feed(dvbdmxfeed, 0); */
}
static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
{
int ret;
ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
THIS_MODULE/*&hdw->usb_dev->owner*/,
&adap->pvr->hdw->usb_dev->dev,
adapter_nr);
if (ret < 0) {
err("dvb_register_adapter failed: error %d", ret);
goto err;
}
adap->dvb_adap.priv = adap;
adap->demux.dmx.capabilities = DMX_TS_FILTERING |
DMX_SECTION_FILTERING |
DMX_MEMORY_BASED_FILTERING;
adap->demux.priv = adap;
adap->demux.filternum = 256;
adap->demux.feednum = 256;
adap->demux.start_feed = pvr2_dvb_start_feed;
adap->demux.stop_feed = pvr2_dvb_stop_feed;
adap->demux.write_to_decoder = NULL;
ret = dvb_dmx_init(&adap->demux);
if (ret < 0) {
err("dvb_dmx_init failed: error %d", ret);
goto err_dmx;
}
adap->dmxdev.filternum = adap->demux.filternum;
adap->dmxdev.demux = &adap->demux.dmx;
adap->dmxdev.capabilities = 0;
ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
if (ret < 0) {
err("dvb_dmxdev_init failed: error %d", ret);
goto err_dmx_dev;
}
dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
adap->digital_up = 1;
return 0;
err_dmx_dev:
dvb_dmx_release(&adap->demux);
err_dmx:
dvb_unregister_adapter(&adap->dvb_adap);
err:
return ret;
}
static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
{
if (adap->digital_up) {
printk(KERN_DEBUG "unregistering DVB devices\n");
dvb_net_release(&adap->dvb_net);
adap->demux.dmx.close(&adap->demux.dmx);
dvb_dmxdev_release(&adap->dmxdev);
dvb_dmx_release(&adap->demux);
dvb_unregister_adapter(&adap->dvb_adap);
adap->digital_up = 0;
}
return 0;
}
static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
{
struct pvr2_dvb_props *dvb_props = adap->pvr->hdw->hdw_desc->dvb_props;
if (dvb_props == NULL) {
err("fe_props not defined!");
return -EINVAL;
}
if (dvb_props->frontend_attach == NULL) {
err("frontend_attach not defined!");
return -EINVAL;
}
if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
err("frontend registration failed!");
dvb_frontend_detach(adap->fe);
adap->fe = NULL;
return -ENODEV;
}
if (dvb_props->tuner_attach)
dvb_props->tuner_attach(adap);
if (adap->fe->ops.analog_ops.standby)
adap->fe->ops.analog_ops.standby(adap->fe);
} else {
err("no frontend was attached!");
return -ENODEV;
}
return 0;
}
static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
{
if (adap->fe != NULL) {
dvb_unregister_frontend(adap->fe);
dvb_frontend_detach(adap->fe);
}
return 0;
}
int pvr2_dvb_init(struct pvr2_context *pvr)
{
int ret = 0;
pvr->hdw->dvb.pvr = pvr;
ret = pvr2_dvb_adapter_init(&pvr->hdw->dvb);
if (ret < 0)
goto fail;
ret = pvr2_dvb_frontend_init(&pvr->hdw->dvb);
fail:
return ret;
}
int pvr2_dvb_exit(struct pvr2_context *pvr)
{
pvr2_dvb_frontend_exit(&pvr->hdw->dvb);
pvr2_dvb_adapter_exit(&pvr->hdw->dvb);
pvr->hdw->dvb.pvr = NULL;
return 0;
}

View file

@ -0,0 +1,33 @@
#ifndef __PVRUSB2_DVB_H__
#define __PVRUSB2_DVB_H__
#include "dvb_frontend.h"
#include "dvb_demux.h"
#include "dvb_net.h"
#include "dmxdev.h"
#include "pvrusb2-context.h"
struct pvr2_dvb_adapter {
struct pvr2_context *pvr;
struct dvb_adapter dvb_adap;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvb_net;
struct dvb_frontend *fe;
int feedcount;
int max_feed_count;
unsigned int digital_up:1;
};
struct pvr2_dvb_props {
int (*frontend_attach) (struct pvr2_dvb_adapter *);
int (*tuner_attach) (struct pvr2_dvb_adapter *);
};
int pvr2_dvb_init(struct pvr2_context *pvr);
int pvr2_dvb_exit(struct pvr2_context *pvr);
#endif /* __PVRUSB2_DVB_H__ */

View file

@ -41,6 +41,7 @@
#include "pvrusb2-io.h" #include "pvrusb2-io.h"
#include <media/cx2341x.h> #include <media/cx2341x.h>
#include "pvrusb2-devattr.h" #include "pvrusb2-devattr.h"
#include "pvrusb2-dvb.h"
/* Legal values for PVR2_CID_HSM */ /* Legal values for PVR2_CID_HSM */
#define PVR2_CVAL_HSM_FAIL 0 #define PVR2_CVAL_HSM_FAIL 0
@ -373,6 +374,8 @@ struct pvr2_hdw {
struct pvr2_ctrl *controls; struct pvr2_ctrl *controls;
unsigned int control_cnt; unsigned int control_cnt;
struct pvr2_dvb_adapter dvb;
}; };
/* This function gets the current frequency */ /* This function gets the current frequency */

View file

@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr)
{ {
/* Create association with v4l layer */ /* Create association with v4l layer */
pvr2_v4l2_create(pvr); pvr2_v4l2_create(pvr);
#ifdef CONFIG_VIDEO_PVRUSB2_DVB
/* Create association with dvb layer */
pvr2_dvb_init(pvr);
#endif
#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS #ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
pvr2_sysfs_create(pvr,class_ptr); pvr2_sysfs_create(pvr,class_ptr);
#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ #endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
@ -95,6 +99,9 @@ static void pvr_disconnect(struct usb_interface *intf)
pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr); pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr);
#ifdef CONFIG_VIDEO_PVRUSB2_DVB
pvr2_dvb_exit(pvr);
#endif
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
pvr2_context_disconnect(pvr); pvr2_context_disconnect(pvr);