summaryrefslogtreecommitdiff
path: root/drivers/media/dvb-core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb-core')
-rw-r--r--drivers/media/dvb-core/dmxdev.c4
-rw-r--r--drivers/media/dvb-core/dvb_ca_en50221.c2
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c2
-rw-r--r--drivers/media/dvb-core/dvb_net.c2
-rw-r--r--drivers/media/dvb-core/dvbdev.c146
-rw-r--r--drivers/media/dvb-core/dvbdev.h9
6 files changed, 139 insertions, 26 deletions
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index ea9abde902e9..a168cbe1c998 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -1244,9 +1244,9 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
}
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
- DVB_DEVICE_DEMUX);
+ DVB_DEVICE_DEMUX, dmxdev->filternum);
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
- dmxdev, DVB_DEVICE_DVR);
+ dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c
index fb66184dc9b6..f82cd1ff4f3a 100644
--- a/drivers/media/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb-core/dvb_ca_en50221.c
@@ -1695,7 +1695,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
pubca->private = ca;
/* register the DVB device */
- ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
+ ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA, 0);
if (ret)
goto free_slot_info;
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 42ab6aaeed7d..40080645341e 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2759,7 +2759,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
fe->dvb->num, fe->id, fe->ops.info.name);
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
- fe, DVB_DEVICE_FRONTEND);
+ fe, DVB_DEVICE_FRONTEND, 0);
/*
* Initialize the cache to the proper values according with the
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index ce4332e80a91..ce6a711b42d4 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -1502,6 +1502,6 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
dvbnet->state[i] = 0;
return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
- dvbnet, DVB_DEVICE_NET);
+ dvbnet, DVB_DEVICE_NET, 0);
}
EXPORT_SYMBOL(dvb_net_init);
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index dadcf1655070..6babc688801b 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -180,18 +180,86 @@ skip:
return -ENFILE;
}
+static void dvb_create_tsout_entity(struct dvb_device *dvbdev,
+ const char *name, int npads)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+ int i, ret = 0;
+
+ dvbdev->tsout_pads = kcalloc(npads, sizeof(*dvbdev->tsout_pads),
+ GFP_KERNEL);
+ if (!dvbdev->tsout_pads)
+ return;
+ dvbdev->tsout_entity = kcalloc(npads, sizeof(*dvbdev->tsout_entity),
+ GFP_KERNEL);
+ if (!dvbdev->tsout_entity) {
+ kfree(dvbdev->tsout_pads);
+ dvbdev->tsout_pads = NULL;
+ return;
+ }
+ for (i = 0; i < npads; i++) {
+ struct media_pad *pads = &dvbdev->tsout_pads[i];
+ struct media_entity *entity = &dvbdev->tsout_entity[i];
+
+ entity->name = kasprintf(GFP_KERNEL, "%s #%d", name, i);
+ if (!entity->name) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ entity->type = MEDIA_ENT_T_DVB_TSOUT;
+ pads->flags = MEDIA_PAD_FL_SINK;
+
+ ret = media_entity_init(entity, 1, pads);
+ if (ret < 0)
+ break;
+
+ ret = media_device_register_entity(dvbdev->adapter->mdev,
+ entity);
+ if (ret < 0)
+ break;
+ }
+
+ if (!ret) {
+ dvbdev->tsout_num_entities = npads;
+ return;
+ }
+
+ for (i--; i >= 0; i--) {
+ media_device_unregister_entity(&dvbdev->tsout_entity[i]);
+ kfree(dvbdev->tsout_entity[i].name);
+ }
+
+ printk(KERN_ERR
+ "%s: media_device_register_entity failed for %s\n",
+ __func__, name);
+
+ kfree(dvbdev->tsout_entity);
+ kfree(dvbdev->tsout_pads);
+ dvbdev->tsout_entity = NULL;
+ dvbdev->tsout_pads = NULL;
+#endif
+}
+
+#define DEMUX_TSOUT "demux-tsout"
+#define DVR_TSOUT "dvr-tsout"
+
static void dvb_create_media_entity(struct dvb_device *dvbdev,
- int type, int minor)
+ int type, int demux_sink_pads)
{
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
- int ret = 0, npads;
+ int i, ret = 0, npads;
switch (type) {
case DVB_DEVICE_FRONTEND:
npads = 2;
break;
+ case DVB_DEVICE_DVR:
+ dvb_create_tsout_entity(dvbdev, DVR_TSOUT, demux_sink_pads);
+ return;
case DVB_DEVICE_DEMUX:
- npads = 2;
+ npads = 1 + demux_sink_pads;
+ dvb_create_tsout_entity(dvbdev, DEMUX_TSOUT, demux_sink_pads);
break;
case DVB_DEVICE_CA:
npads = 2;
@@ -215,8 +283,6 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
if (!dvbdev->entity)
return;
- dvbdev->entity->info.dev.major = DVB_MAJOR;
- dvbdev->entity->info.dev.minor = minor;
dvbdev->entity->name = dvbdev->name;
if (npads) {
@@ -237,7 +303,8 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
case DVB_DEVICE_DEMUX:
dvbdev->entity->type = MEDIA_ENT_T_DVB_DEMUX;
dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
- dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+ for (i = 1; i < npads; i++)
+ dvbdev->pads[i].flags = MEDIA_PAD_FL_SOURCE;
break;
case DVB_DEVICE_CA:
dvbdev->entity->type = MEDIA_ENT_T_DVB_CA;
@@ -259,8 +326,16 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
printk(KERN_ERR
"%s: media_device_register_entity failed for %s\n",
__func__, dvbdev->entity->name);
+
+ media_device_unregister_entity(dvbdev->entity);
+ for (i = 0; i < dvbdev->tsout_num_entities; i++) {
+ media_device_unregister_entity(&dvbdev->tsout_entity[i]);
+ kfree(dvbdev->tsout_entity[i].name);
+ }
kfree(dvbdev->pads);
kfree(dvbdev->entity);
+ kfree(dvbdev->tsout_pads);
+ kfree(dvbdev->tsout_entity);
dvbdev->entity = NULL;
return;
}
@@ -271,7 +346,8 @@ static void dvb_create_media_entity(struct dvb_device *dvbdev,
}
static void dvb_register_media_device(struct dvb_device *dvbdev,
- int type, int minor)
+ int type, int minor,
+ unsigned demux_sink_pads)
{
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
u32 intf_type;
@@ -279,7 +355,7 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
if (!dvbdev->adapter->mdev)
return;
- dvb_create_media_entity(dvbdev, type, minor);
+ dvb_create_media_entity(dvbdev, type, demux_sink_pads);
switch (type) {
case DVB_DEVICE_FRONTEND:
@@ -323,7 +399,8 @@ static void dvb_register_media_device(struct dvb_device *dvbdev,
}
int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
- const struct dvb_device *template, void *priv, int type)
+ const struct dvb_device *template, void *priv, int type,
+ int demux_sink_pads)
{
struct dvb_device *dvbdev;
struct file_operations *dvbdevfops;
@@ -402,7 +479,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, minor, minor);
- dvb_register_media_device(dvbdev, type, minor);
+ dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
return 0;
}
@@ -422,9 +499,18 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
if (dvbdev->entity) {
+ int i;
+
media_device_unregister_entity(dvbdev->entity);
+ for (i = 0; i < dvbdev->tsout_num_entities; i++) {
+ media_device_unregister_entity(&dvbdev->tsout_entity[i]);
+ kfree(dvbdev->tsout_entity[i].name);
+ }
+
kfree(dvbdev->entity);
kfree(dvbdev->pads);
+ kfree(dvbdev->tsout_entity);
+ kfree(dvbdev->tsout_pads);
}
#endif
@@ -440,8 +526,10 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
{
struct media_device *mdev = adap->mdev;
struct media_entity *entity, *tuner = NULL, *demod = NULL;
- struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
+ struct media_entity *demux = NULL, *ca = NULL;
struct media_interface *intf;
+ unsigned demux_pad = 0;
+ unsigned dvr_pad = 0;
if (!mdev)
return;
@@ -457,9 +545,6 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
case MEDIA_ENT_T_DVB_DEMUX:
demux = entity;
break;
- case MEDIA_ENT_T_DVB_TSOUT:
- dvr = entity;
- break;
case MEDIA_ENT_T_DVB_CA:
ca = entity;
break;
@@ -471,21 +556,46 @@ void dvb_create_media_graph(struct dvb_adapter *adap)
if (demod && demux)
media_create_pad_link(demod, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
-
- if (demux && dvr)
- media_create_pad_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
-
if (demux && ca)
media_create_pad_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
+ /* Create demux links for each ringbuffer/pad */
+ if (demux) {
+ media_device_for_each_entity(entity, mdev) {
+ if (entity->type == MEDIA_ENT_T_DVB_TSOUT) {
+ if (!strncmp(entity->name, DVR_TSOUT,
+ strlen(DVR_TSOUT)))
+ media_create_pad_link(demux,
+ ++dvr_pad,
+ entity, 0, 0);
+ if (!strncmp(entity->name, DEMUX_TSOUT,
+ strlen(DEMUX_TSOUT)))
+ media_create_pad_link(demux,
+ ++demux_pad,
+ entity, 0, 0);
+ }
+ }
+ }
+
/* Create indirect interface links for FE->tuner, DVR->demux and CA->ca */
list_for_each_entry(intf, &mdev->interfaces, list) {
if (intf->type == MEDIA_INTF_T_DVB_CA && ca)
media_create_intf_link(ca, intf, 0);
if (intf->type == MEDIA_INTF_T_DVB_FE && tuner)
media_create_intf_link(tuner, intf, 0);
+
if (intf->type == MEDIA_INTF_T_DVB_DVR && demux)
media_create_intf_link(demux, intf, 0);
+
+ media_device_for_each_entity(entity, mdev) {
+ if (entity->type == MEDIA_ENT_T_DVB_TSOUT) {
+ if (!strcmp(entity->name, DVR_TSOUT))
+ media_create_intf_link(entity, intf, 0);
+ if (!strcmp(entity->name, DEMUX_TSOUT))
+ media_create_intf_link(entity, intf, 0);
+ break;
+ }
+ }
}
}
EXPORT_SYMBOL_GPL(dvb_create_media_graph);
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 8398c8fb02b0..7af8adbb589b 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -148,9 +148,11 @@ struct dvb_device {
const char *name;
/* Allocated and filled inside dvbdev.c */
- struct media_entity *entity;
struct media_intf_devnode *intf_devnode;
- struct media_pad *pads;
+
+ unsigned tsout_num_entities;
+ struct media_entity *entity, *tsout_entity;
+ struct media_pad *pads, *tsout_pads;
#endif
void *priv;
@@ -193,7 +195,8 @@ int dvb_register_device(struct dvb_adapter *adap,
struct dvb_device **pdvbdev,
const struct dvb_device *template,
void *priv,
- int type);
+ int type,
+ int demux_sink_pads);
/**
* dvb_unregister_device - Unregisters a DVB device