summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c152
1 files changed, 114 insertions, 38 deletions
diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index b2df5535f..a75509993 100644
--- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -41,6 +41,7 @@
#include "dvb_net.h"
static int debug = 0;
+static int output_avpes = 0;
#define dprintk if (debug) printk
@@ -48,14 +49,15 @@ static int debug = 0;
#define COMMAND_PIPE 0x03
#define RESULT_PIPE 0x84
-#define STREAM_PIPE 0x88
+#define IN_PIPE 0x88
+#define OUT_PIPE 0x07
#define COMMAND_PACKET_SIZE 0x3c
#define ARM_PACKET_SIZE 0x1000
#define ISO_BUF_COUNT 0x04
#define FRAMES_PER_ISO_BUF 0x04
-#define ISO_FRAME_SIZE 0x0380
+#define ISO_FRAME_SIZE 0x03FF
#define MAX_AV_PES_LENGTH 6144
@@ -69,14 +71,22 @@ enum ttusb_dec_model {
};
enum ttusb_dec_packet_type {
- PACKET_AV_PES,
- PACKET_SECTION
+ TTUSB_DEC_PACKET_AV_PES,
+ TTUSB_DEC_PACKET_SECTION,
+ TTUSB_DEC_PACKET_EMPTY
+};
+
+enum ttusb_dec_interface {
+ TTUSB_DEC_INTERFACE_INITIAL,
+ TTUSB_DEC_INTERFACE_IN,
+ TTUSB_DEC_INTERFACE_OUT
};
struct ttusb_dec {
enum ttusb_dec_model model;
char *model_name;
char *firmware_name;
+ int can_playback;
/* DVB bits */
struct dvb_adapter *adapter;
@@ -92,13 +102,14 @@ struct ttusb_dec {
int hi_band;
/* USB bits */
- struct usb_device *udev;
- u8 trans_count;
- unsigned int command_pipe;
- unsigned int result_pipe;
- unsigned int stream_pipe;
- int interface;
- struct semaphore usb_sem;
+ struct usb_device *udev;
+ u8 trans_count;
+ unsigned int command_pipe;
+ unsigned int result_pipe;
+ unsigned int in_pipe;
+ unsigned int out_pipe;
+ enum ttusb_dec_interface interface;
+ struct semaphore usb_sem;
void *iso_buffer;
dma_addr_t iso_dma_handle;
@@ -111,6 +122,7 @@ struct ttusb_dec {
int packet_state;
int packet_length;
int packet_payload_length;
+ u16 next_packet_id;
int av_pes_stream_count;
int filter_stream_count;
@@ -336,6 +348,13 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec *dec, u8 *av_pes,
return;
}
+ if (output_avpes) {
+ dec->av_filter->feed->cb.ts(av_pes, length, 0, 0,
+ &dec->av_filter->feed->feed.ts,
+ DMX_OK);
+ return;
+ }
+
switch (av_pes[2]) {
case 0x01: { /* VideoStream */
@@ -439,6 +458,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
{
int i;
u16 csum = 0;
+ u16 packet_id;
if (dec->packet_length % 2) {
printk("%s: odd sized packet - discarding\n", __FUNCTION__);
@@ -453,18 +473,34 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
return;
}
+ packet_id = dec->packet[dec->packet_length - 4] << 8;
+ packet_id += dec->packet[dec->packet_length - 3];
+
+ if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
+ printk("%s: warning: lost packets between %u and %u\n",
+ __FUNCTION__, dec->next_packet_id - 1, packet_id);
+ }
+
+ if (packet_id == 0xffff)
+ dec->next_packet_id = 0x8000;
+ else
+ dec->next_packet_id = packet_id + 1;
+
switch (dec->packet_type) {
- case PACKET_AV_PES:
+ case TTUSB_DEC_PACKET_AV_PES:
if (dec->av_pes_stream_count)
ttusb_dec_process_av_pes(dec, dec->packet,
dec->packet_payload_length);
break;
- case PACKET_SECTION:
+ case TTUSB_DEC_PACKET_SECTION:
if (dec->filter_stream_count)
ttusb_dec_process_filter(dec, dec->packet,
dec->packet_payload_length);
break;
+
+ case TTUSB_DEC_PACKET_EMPTY:
+ break;
}
}
@@ -513,15 +549,25 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
case 4:
dec->packet[dec->packet_length++] = *b++;
- if (dec->packet_length == 3) {
+ if (dec->packet_length == 2) {
if (dec->packet[0] == 'A' &&
dec->packet[1] == 'V') {
- dec->packet_type = PACKET_AV_PES;
+ dec->packet_type =
+ TTUSB_DEC_PACKET_AV_PES;
dec->packet_state++;
} else if (dec->packet[0] == 'S') {
- dec->packet_type = PACKET_SECTION;
+ dec->packet_type =
+ TTUSB_DEC_PACKET_SECTION;
dec->packet_state++;
+ } else if (dec->packet[0] == 0x00) {
+ dec->packet_type =
+ TTUSB_DEC_PACKET_EMPTY;
+ dec->packet_payload_length = 2;
+ dec->packet_state = 7;
} else {
+ printk("%s: unknown packet type: "
+ "%02x%02x\n", __FUNCTION__,
+ dec->packet[0], dec->packet[1]);
dec->packet_state = 0;
}
}
@@ -532,13 +578,14 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
case 5:
dec->packet[dec->packet_length++] = *b++;
- if (dec->packet_type == PACKET_AV_PES &&
+ if (dec->packet_type == TTUSB_DEC_PACKET_AV_PES &&
dec->packet_length == 8) {
dec->packet_state++;
dec->packet_payload_length = 8 +
(dec->packet[6] << 8) +
dec->packet[7];
- } else if (dec->packet_type == PACKET_SECTION &&
+ } else if (dec->packet_type ==
+ TTUSB_DEC_PACKET_SECTION &&
dec->packet_length == 5) {
dec->packet_state++;
dec->packet_payload_length = 5 +
@@ -575,7 +622,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
dec->packet[dec->packet_length++] = *b++;
- if (dec->packet_type == PACKET_SECTION &&
+ if (dec->packet_type == TTUSB_DEC_PACKET_SECTION &&
dec->packet_payload_length % 2)
tail++;
@@ -690,7 +737,7 @@ static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
urb->dev = dec->udev;
urb->context = dec;
urb->complete = ttusb_dec_process_urb;
- urb->pipe = dec->stream_pipe;
+ urb->pipe = dec->in_pipe;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
urb->transfer_flags = URB_ISO_ASAP;
urb->interval = 1;
@@ -734,12 +781,30 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
* for a short period, so it's important not to call this function just before
* trying to talk to it.
*/
-static void ttusb_dec_set_streaming_interface(struct ttusb_dec *dec)
+static int ttusb_dec_set_interface(struct ttusb_dec *dec,
+ enum ttusb_dec_interface interface)
{
- if (!dec->interface) {
- usb_set_interface(dec->udev, 0, 8);
- dec->interface = 8;
+ int result = 0;
+
+ if (interface != dec->interface) {
+ switch (interface) {
+ case TTUSB_DEC_INTERFACE_INITIAL:
+ result = usb_set_interface(dec->udev, 0, 0);
+ break;
+ case TTUSB_DEC_INTERFACE_IN:
+ result = usb_set_interface(dec->udev, 0, 7);
+ break;
+ case TTUSB_DEC_INTERFACE_OUT:
+ result = usb_set_interface(dec->udev, 0, 1);
+ break;
+ }
+
+ if (result)
+ return result;
+
+ dec->interface = interface;
}
+ return 0;
}
static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
@@ -754,6 +819,10 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
if (!dec->iso_stream_count) {
ttusb_dec_setup_urbs(dec);
+ dec->packet_state = 0;
+ dec->v_pes_postbytes = 0;
+ dec->next_packet_id = 0;
+
for (i = 0; i < ISO_BUF_COUNT; i++) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if ((result = usb_submit_urb(dec->iso_urb[i],
@@ -773,9 +842,6 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
return result;
}
}
-
- dec->packet_state = 0;
- dec->v_pes_postbytes = 0;
}
dec->iso_stream_count++;
@@ -783,7 +849,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
up(&dec->iso_sem);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- ttusb_dec_set_streaming_interface(dec);
+ ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
#endif
return 0;
@@ -794,6 +860,7 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct ttusb_dec *dec = dvbdmx->priv;
u8 b0[] = { 0x05 };
+ int result = 0;
dprintk("%s\n", __FUNCTION__);
@@ -848,12 +915,12 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
}
- ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
+ result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
+ if (result)
+ return result;
dec->av_pes_stream_count++;
- ttusb_dec_start_iso_xfer(dec);
-
- return 0;
+ return ttusb_dec_start_iso_xfer(dec);
}
static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -903,9 +970,7 @@ static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
dvbdmxfeed->priv = finfo;
dec->filter_stream_count++;
- ttusb_dec_start_iso_xfer(dec);
-
- return 0;
+ return ttusb_dec_start_iso_xfer(dec);
}
return -EAGAIN;
@@ -1078,13 +1143,15 @@ static void ttusb_dec_init_usb(struct ttusb_dec *dec)
dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
- dec->stream_pipe = usb_rcvisocpipe(dec->udev, STREAM_PIPE);
+ dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE);
+ dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE);
ttusb_dec_alloc_iso_urbs(dec);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include "dsp_dec2000t.h"
+#include "dsp_dec2540t.h"
#include "dsp_dec3000s.h"
#endif
@@ -1121,11 +1188,15 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
#else
switch (dec->model) {
case TTUSB_DEC2000T:
- case TTUSB_DEC2540T:
firmware = &dsp_dec2000t[0];
firmware_size = sizeof(dsp_dec2000t);
break;
+ case TTUSB_DEC2540T:
+ firmware = &dsp_dec2540t[0];
+ firmware_size = sizeof(dsp_dec2540t);
+ break;
+
case TTUSB_DEC3000S:
firmware = &dsp_dec3000s[0];
firmware_size = sizeof(dsp_dec3000s);
@@ -1245,6 +1316,9 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
break;
}
+ if (version >= 0x01770000)
+ dec->can_playback = 1;
+
return 0;
}
}
@@ -1698,7 +1772,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
return (void *)dec;
#else
- ttusb_dec_set_streaming_interface(dec);
+ ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
return 0;
#endif
@@ -1801,3 +1875,5 @@ MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug level");
+MODULE_PARM(output_avpes, "i");
+MODULE_PARM_DESC(output_avpes, "Output AVPES from dvr device");