[media] dvbdev: Add RF connector if needed

Several pure digital TV devices have a frontend with the tuner
integrated on it. Add the RF connector when dvb_create_media_graph()
is called on such devices.

Tested with siano and dvb_usb_mxl111sf drivers.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
Mauro Carvalho Chehab 2015-12-29 11:52:23 -02:00
parent 0820eb5c55
commit 0230d60e46
7 changed files with 70 additions and 9 deletions

View File

@ -1184,7 +1184,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
if (smsdvb_debugfs_create(client) < 0)
pr_info("failed to create debugfs node\n");
rc = dvb_create_media_graph(&client->adapter);
rc = dvb_create_media_graph(&client->adapter, true);
if (rc < 0) {
pr_err("dvb_create_media_graph failed %d\n", rc);
goto client_error;

View File

@ -213,6 +213,13 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
media_devnode_remove(dvbdev->intf_devnode);
dvbdev->intf_devnode = NULL;
}
if (dvbdev->adapter->conn) {
media_device_unregister_entity(dvbdev->adapter->conn);
dvbdev->adapter->conn = NULL;
kfree(dvbdev->adapter->conn_pads);
dvbdev->adapter->conn_pads = NULL;
}
#endif
}
@ -559,16 +566,18 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
return 0;
}
int dvb_create_media_graph(struct dvb_adapter *adap)
int dvb_create_media_graph(struct dvb_adapter *adap,
bool create_rf_connector)
{
struct media_device *mdev = adap->mdev;
struct media_entity *entity, *tuner = NULL, *demod = NULL;
struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn;
struct media_entity *demux = NULL, *ca = NULL;
struct media_link *link;
struct media_interface *intf;
unsigned demux_pad = 0;
unsigned dvr_pad = 0;
int ret;
static const char *connector_name = "Television";
if (!mdev)
return 0;
@ -590,6 +599,42 @@ int dvb_create_media_graph(struct dvb_adapter *adap)
}
}
if (create_rf_connector) {
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn)
return -ENOMEM;
adap->conn = conn;
adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads),
GFP_KERNEL);
if (!adap->conn_pads)
return -ENOMEM;
conn->flags = MEDIA_ENT_FL_CONNECTOR;
conn->function = MEDIA_ENT_F_CONN_RF;
conn->name = connector_name;
adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(conn, 1, adap->conn_pads);
if (ret)
return ret;
ret = media_device_register_entity(mdev, conn);
if (ret)
return ret;
if (!tuner)
ret = media_create_pad_link(conn, 0,
demod, 0,
MEDIA_LNK_FL_ENABLED);
else
ret = media_create_pad_link(conn, 0,
tuner, TUNER_PAD_RF_INPUT,
MEDIA_LNK_FL_ENABLED);
if (ret)
return ret;
}
if (tuner && demod) {
ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT,
demod, 0, MEDIA_LNK_FL_ENABLED);

View File

@ -75,6 +75,9 @@ struct dvb_frontend;
* used.
* @mdev: pointer to struct media_device, used when the media
* controller is used.
* @conn: RF connector. Used only if the device has no separate
* tuner.
* @conn_pads: pointer to struct media_pad associated with @conn;
*/
struct dvb_adapter {
int num;
@ -94,6 +97,8 @@ struct dvb_adapter {
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
struct media_device *mdev;
struct media_entity *conn;
struct media_pad *conn_pads;
#endif
};
@ -214,7 +219,16 @@ int dvb_register_device(struct dvb_adapter *adap,
void dvb_unregister_device(struct dvb_device *dvbdev);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
__must_check int dvb_create_media_graph(struct dvb_adapter *adap);
/**
* dvb_create_media_graph - Creates media graph for the Digital TV part of the
* device.
*
* @adap: pointer to struct dvb_adapter
* @create_rf_connector: if true, it creates the RF connector too
*/
__must_check int dvb_create_media_graph(struct dvb_adapter *adap,
bool create_rf_connector);
static inline void dvb_register_media_controller(struct dvb_adapter *adap,
struct media_device *mdev)
{
@ -222,7 +236,9 @@ static inline void dvb_register_media_controller(struct dvb_adapter *adap,
}
#else
static inline int dvb_create_media_graph(struct dvb_adapter *adap)
static inline
int dvb_create_media_graph(struct dvb_adapter *adap,
bool create_rf_connector)
{
return 0;
};

View File

@ -486,7 +486,7 @@ static int dvb_register(struct au0828_dev *dev)
dvb->start_count = 0;
dvb->stop_count = 0;
result = dvb_create_media_graph(&dvb->adapter);
result = dvb_create_media_graph(&dvb->adapter, false);
if (result < 0)
goto fail_create_graph;

View File

@ -551,7 +551,7 @@ static int register_dvb(struct cx231xx_dvb *dvb,
/* register network adapter */
dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
result = dvb_create_media_graph(&dvb->adapter);
result = dvb_create_media_graph(&dvb->adapter, false);
if (result < 0)
goto fail_create_graph;

View File

@ -706,7 +706,7 @@ static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
}
}
ret = dvb_create_media_graph(&adap->dvb_adap);
ret = dvb_create_media_graph(&adap->dvb_adap, true);
if (ret < 0)
goto err_dvb_unregister_frontend;

View File

@ -330,7 +330,7 @@ int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
if (ret)
return ret;
ret = dvb_create_media_graph(&adap->dvb_adap);
ret = dvb_create_media_graph(&adap->dvb_adap, true);
if (ret)
return ret;