Commit 04910bdc authored by Michael Krufky's avatar Michael Krufky Committed by Mauro Carvalho Chehab

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: default avatarMichael Krufky <mkrufky@linuxtv.org>
Signed-off-by: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent e7f677f3
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 \ ...@@ -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
...@@ -23,6 +23,7 @@ ...@@ -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 { ...@@ -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
......
/*
* 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;
}
#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__ */
...@@ -41,6 +41,7 @@ ...@@ -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 { ...@@ -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 */
......
...@@ -60,6 +60,10 @@ static void pvr_setup_attach(struct pvr2_context *pvr) ...@@ -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) ...@@ -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);
......
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