提交 754f9969 编写于 作者: A Andy Walls 提交者: Mauro Carvalho Chehab

[media] cx18: Only allocate a struct cx18_dvb for the DVB TS stream

The cx18_stream struct contained a struct cx18_dvb for
every stream object, most of which were for analog capture.
Now we only allocate the cx18_dvb object for the DTV TS stream.
Signed-off-by: NAndy Walls <awalls@md.metrocast.net>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 fa98447f
...@@ -325,7 +325,10 @@ struct cx18_queue { ...@@ -325,7 +325,10 @@ struct cx18_queue {
spinlock_t lock; spinlock_t lock;
}; };
struct cx18_stream; /* forward reference */
struct cx18_dvb { struct cx18_dvb {
struct cx18_stream *stream;
struct dmx_frontend hw_frontend; struct dmx_frontend hw_frontend;
struct dmx_frontend mem_frontend; struct dmx_frontend mem_frontend;
struct dmxdev dmxdev; struct dmxdev dmxdev;
...@@ -365,9 +368,10 @@ struct cx18_in_work_order { ...@@ -365,9 +368,10 @@ struct cx18_in_work_order {
#define CX18_INVALID_TASK_HANDLE 0xffffffff #define CX18_INVALID_TASK_HANDLE 0xffffffff
struct cx18_stream { struct cx18_stream {
/* These first four fields are always set, even if the stream /* These first five fields are always set, even if the stream
is not actually created. */ is not actually created. */
struct video_device *video_dev; /* NULL when stream not created */ struct video_device *video_dev; /* NULL when stream not created */
struct cx18_dvb *dvb; /* DVB / Digital Transport */
struct cx18 *cx; /* for ease of use */ struct cx18 *cx; /* for ease of use */
const char *name; /* name of the stream */ const char *name; /* name of the stream */
int type; /* stream type */ int type; /* stream type */
...@@ -397,9 +401,6 @@ struct cx18_stream { ...@@ -397,9 +401,6 @@ struct cx18_stream {
struct cx18_queue q_idle; /* idle - not in rotation */ struct cx18_queue q_idle; /* idle - not in rotation */
struct work_struct out_work_order; struct work_struct out_work_order;
/* DVB / Digital Transport */
struct cx18_dvb dvb;
}; };
struct cx18_open_id { struct cx18_open_id {
......
...@@ -137,7 +137,7 @@ static int yuan_mpc718_mt352_init(struct dvb_frontend *fe) ...@@ -137,7 +137,7 @@ static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
{ {
struct cx18_dvb *dvb = container_of(fe->dvb, struct cx18_dvb *dvb = container_of(fe->dvb,
struct cx18_dvb, dvb_adapter); struct cx18_dvb, dvb_adapter);
struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb); struct cx18_stream *stream = dvb->stream;
const struct firmware *fw = NULL; const struct firmware *fw = NULL;
int ret; int ret;
int i; int i;
...@@ -266,22 +266,22 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) ...@@ -266,22 +266,22 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend) if (!demux->dmx.frontend)
return -EINVAL; return -EINVAL;
mutex_lock(&stream->dvb.feedlock); mutex_lock(&stream->dvb->feedlock);
if (stream->dvb.feeding++ == 0) { if (stream->dvb->feeding++ == 0) {
CX18_DEBUG_INFO("Starting Transport DMA\n"); CX18_DEBUG_INFO("Starting Transport DMA\n");
mutex_lock(&cx->serialize_lock); mutex_lock(&cx->serialize_lock);
set_bit(CX18_F_S_STREAMING, &stream->s_flags); set_bit(CX18_F_S_STREAMING, &stream->s_flags);
ret = cx18_start_v4l2_encode_stream(stream); ret = cx18_start_v4l2_encode_stream(stream);
if (ret < 0) { if (ret < 0) {
CX18_DEBUG_INFO("Failed to start Transport DMA\n"); CX18_DEBUG_INFO("Failed to start Transport DMA\n");
stream->dvb.feeding--; stream->dvb->feeding--;
if (stream->dvb.feeding == 0) if (stream->dvb->feeding == 0)
clear_bit(CX18_F_S_STREAMING, &stream->s_flags); clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
} }
mutex_unlock(&cx->serialize_lock); mutex_unlock(&cx->serialize_lock);
} else } else
ret = 0; ret = 0;
mutex_unlock(&stream->dvb.feedlock); mutex_unlock(&stream->dvb->feedlock);
return ret; return ret;
} }
...@@ -299,15 +299,15 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) ...@@ -299,15 +299,15 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n", CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
feed->pid, feed->index); feed->pid, feed->index);
mutex_lock(&stream->dvb.feedlock); mutex_lock(&stream->dvb->feedlock);
if (--stream->dvb.feeding == 0) { if (--stream->dvb->feeding == 0) {
CX18_DEBUG_INFO("Stopping Transport DMA\n"); CX18_DEBUG_INFO("Stopping Transport DMA\n");
mutex_lock(&cx->serialize_lock); mutex_lock(&cx->serialize_lock);
ret = cx18_stop_v4l2_encode_stream(stream, 0); ret = cx18_stop_v4l2_encode_stream(stream, 0);
mutex_unlock(&cx->serialize_lock); mutex_unlock(&cx->serialize_lock);
} else } else
ret = 0; ret = 0;
mutex_unlock(&stream->dvb.feedlock); mutex_unlock(&stream->dvb->feedlock);
} }
return ret; return ret;
...@@ -316,7 +316,7 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) ...@@ -316,7 +316,7 @@ static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
int cx18_dvb_register(struct cx18_stream *stream) int cx18_dvb_register(struct cx18_stream *stream)
{ {
struct cx18 *cx = stream->cx; struct cx18 *cx = stream->cx;
struct cx18_dvb *dvb = &stream->dvb; struct cx18_dvb *dvb = stream->dvb;
struct dvb_adapter *dvb_adapter; struct dvb_adapter *dvb_adapter;
struct dvb_demux *dvbdemux; struct dvb_demux *dvbdemux;
struct dmx_demux *dmx; struct dmx_demux *dmx;
...@@ -325,6 +325,9 @@ int cx18_dvb_register(struct cx18_stream *stream) ...@@ -325,6 +325,9 @@ int cx18_dvb_register(struct cx18_stream *stream)
if (!dvb) if (!dvb)
return -EINVAL; return -EINVAL;
dvb->enabled = 0;
dvb->stream = stream;
ret = dvb_register_adapter(&dvb->dvb_adapter, ret = dvb_register_adapter(&dvb->dvb_adapter,
CX18_DRIVER_NAME, CX18_DRIVER_NAME,
THIS_MODULE, &cx->pci_dev->dev, adapter_nr); THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
...@@ -378,7 +381,7 @@ int cx18_dvb_register(struct cx18_stream *stream) ...@@ -378,7 +381,7 @@ int cx18_dvb_register(struct cx18_stream *stream)
CX18_INFO("DVB Frontend registered\n"); CX18_INFO("DVB Frontend registered\n");
CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n", CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
stream->dvb.dvb_adapter.num, stream->name, stream->dvb->dvb_adapter.num, stream->name,
stream->buffers, stream->buf_size/1024, stream->buffers, stream->buf_size/1024,
(stream->buf_size * 100 / 1024) % 100); (stream->buf_size * 100 / 1024) % 100);
...@@ -405,13 +408,16 @@ int cx18_dvb_register(struct cx18_stream *stream) ...@@ -405,13 +408,16 @@ int cx18_dvb_register(struct cx18_stream *stream)
void cx18_dvb_unregister(struct cx18_stream *stream) void cx18_dvb_unregister(struct cx18_stream *stream)
{ {
struct cx18 *cx = stream->cx; struct cx18 *cx = stream->cx;
struct cx18_dvb *dvb = &stream->dvb; struct cx18_dvb *dvb = stream->dvb;
struct dvb_adapter *dvb_adapter; struct dvb_adapter *dvb_adapter;
struct dvb_demux *dvbdemux; struct dvb_demux *dvbdemux;
struct dmx_demux *dmx; struct dmx_demux *dmx;
CX18_INFO("unregister DVB\n"); CX18_INFO("unregister DVB\n");
if (dvb == NULL || !dvb->enabled)
return;
dvb_adapter = &dvb->dvb_adapter; dvb_adapter = &dvb->dvb_adapter;
dvbdemux = &dvb->demux; dvbdemux = &dvb->demux;
dmx = &dvbdemux->dmx; dmx = &dvbdemux->dmx;
...@@ -432,7 +438,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream) ...@@ -432,7 +438,7 @@ void cx18_dvb_unregister(struct cx18_stream *stream)
*/ */
static int dvb_register(struct cx18_stream *stream) static int dvb_register(struct cx18_stream *stream)
{ {
struct cx18_dvb *dvb = &stream->dvb; struct cx18_dvb *dvb = stream->dvb;
struct cx18 *cx = stream->cx; struct cx18 *cx = stream->cx;
int ret = 0; int ret = 0;
......
...@@ -136,7 +136,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) ...@@ -136,7 +136,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
{ {
struct cx18_buffer *buf; struct cx18_buffer *buf;
if (!s->dvb.enabled || mdl->bytesused == 0) if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0)
return; return;
/* We ignore mdl and buf readpos accounting here - it doesn't matter */ /* We ignore mdl and buf readpos accounting here - it doesn't matter */
...@@ -146,7 +146,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) ...@@ -146,7 +146,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
buf = list_first_entry(&mdl->buf_list, struct cx18_buffer, buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
list); list);
if (buf->bytesused) if (buf->bytesused)
dvb_dmx_swfilter(&s->dvb.demux, dvb_dmx_swfilter(&s->dvb->demux,
buf->buf, buf->bytesused); buf->buf, buf->bytesused);
return; return;
} }
...@@ -154,7 +154,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl) ...@@ -154,7 +154,7 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
list_for_each_entry(buf, &mdl->buf_list, list) { list_for_each_entry(buf, &mdl->buf_list, list) {
if (buf->bytesused == 0) if (buf->bytesused == 0)
break; break;
dvb_dmx_swfilter(&s->dvb.demux, buf->buf, buf->bytesused); dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused);
} }
} }
......
...@@ -107,6 +107,7 @@ static void cx18_stream_init(struct cx18 *cx, int type) ...@@ -107,6 +107,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
s->video_dev = video_dev; s->video_dev = video_dev;
/* initialize cx18_stream fields */ /* initialize cx18_stream fields */
s->dvb = NULL;
s->cx = cx; s->cx = cx;
s->type = type; s->type = type;
s->name = cx18_stream_info[type].name; s->name = cx18_stream_info[type].name;
...@@ -140,10 +141,15 @@ static int cx18_prep_dev(struct cx18 *cx, int type) ...@@ -140,10 +141,15 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
int num_offset = cx18_stream_info[type].num_offset; int num_offset = cx18_stream_info[type].num_offset;
int num = cx->instance + cx18_first_minor + num_offset; int num = cx->instance + cx18_first_minor + num_offset;
/* These four fields are always initialized. If video_dev == NULL, then /*
this stream is not in use. In that case no other fields but these * These five fields are always initialized.
four can be used. */ * For analog capture related streams, if video_dev == NULL then the
* stream is not in use.
* For the TS stream, if dvb == NULL then the stream is not in use.
* In those cases no other fields but these four can be used.
*/
s->video_dev = NULL; s->video_dev = NULL;
s->dvb = NULL;
s->cx = cx; s->cx = cx;
s->type = type; s->type = type;
s->name = cx18_stream_info[type].name; s->name = cx18_stream_info[type].name;
...@@ -167,6 +173,21 @@ static int cx18_prep_dev(struct cx18 *cx, int type) ...@@ -167,6 +173,21 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
cx18_stream_init(cx, type); cx18_stream_init(cx, type);
/* Allocate the cx18_dvb struct only for the TS on cards with DTV */
if (type == CX18_ENC_STREAM_TYPE_TS) {
if (cx->card->hw_all & CX18_HW_DVB) {
s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
if (s->dvb == NULL) {
CX18_ERR("Couldn't allocate cx18_dvb structure"
" for %s\n", s->name);
return -ENOMEM;
}
} else {
/* Don't need buffers for the TS, if there is no DVB */
s->buffers = 0;
}
}
if (num_offset == -1) if (num_offset == -1)
return 0; return 0;
...@@ -222,13 +243,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type) ...@@ -222,13 +243,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
const char *name; const char *name;
int num, ret; int num, ret;
/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something? if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
* We need a VFL_TYPE_TS defined.
*/
if (strcmp("TS", s->name) == 0) {
/* just return if no DVB is supported */
if ((cx->card->hw_all & CX18_HW_DVB) == 0)
return 0;
ret = cx18_dvb_register(s); ret = cx18_dvb_register(s);
if (ret < 0) { if (ret < 0) {
CX18_ERR("DVB failed to register\n"); CX18_ERR("DVB failed to register\n");
...@@ -320,11 +335,13 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) ...@@ -320,11 +335,13 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
/* Teardown all streams */ /* Teardown all streams */
for (type = 0; type < CX18_MAX_STREAMS; type++) { for (type = 0; type < CX18_MAX_STREAMS; type++) {
/* No struct video_device, but can have buffers allocated */ /* The TS has a cx18_dvb structure, not a video_device */
if (type == CX18_ENC_STREAM_TYPE_TS) { if (type == CX18_ENC_STREAM_TYPE_TS) {
if (cx->streams[type].dvb.enabled) { if (cx->streams[type].dvb != NULL) {
cx18_dvb_unregister(&cx->streams[type]); if (unregister)
cx->streams[type].dvb.enabled = false; cx18_dvb_unregister(&cx->streams[type]);
kfree(cx->streams[type].dvb);
cx->streams[type].dvb = NULL;
cx18_stream_free(&cx->streams[type]); cx18_stream_free(&cx->streams[type]);
} }
continue; continue;
......
...@@ -33,7 +33,8 @@ void cx18_stream_rotate_idx_mdls(struct cx18 *cx); ...@@ -33,7 +33,8 @@ void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
static inline bool cx18_stream_enabled(struct cx18_stream *s) static inline bool cx18_stream_enabled(struct cx18_stream *s)
{ {
return s->video_dev || s->dvb.enabled || return s->video_dev ||
(s->dvb && s->dvb->enabled) ||
(s->type == CX18_ENC_STREAM_TYPE_IDX && (s->type == CX18_ENC_STREAM_TYPE_IDX &&
s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册