mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
V4L/DVB (7725): cx23885: Add generic cx23417 hardware encoder support
cx23885: Add generic cx23417 hardware encoder support. Signed-off-by: Steven Toth <stoth@hauppauge.com> Signed-off-by: Michael Krufky <mkrufky@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
e57b1c8006
commit
b1b81f1db7
4 changed files with 1921 additions and 31 deletions
|
@ -1,4 +1,4 @@
|
|||
cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o
|
||||
cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
|
||||
|
||||
|
|
1764
drivers/media/video/cx23885/cx23885-417.c
Normal file
1764
drivers/media/video/cx23885/cx23885-417.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = {
|
|||
static int cx23885_risc_decode(u32 risc)
|
||||
{
|
||||
static char *instr[16] = {
|
||||
[ RISC_SYNC >> 28 ] = "sync",
|
||||
[ RISC_WRITE >> 28 ] = "write",
|
||||
[ RISC_WRITEC >> 28 ] = "writec",
|
||||
[ RISC_READ >> 28 ] = "read",
|
||||
[ RISC_READC >> 28 ] = "readc",
|
||||
[ RISC_JUMP >> 28 ] = "jump",
|
||||
[ RISC_SKIP >> 28 ] = "skip",
|
||||
[ RISC_WRITERM >> 28 ] = "writerm",
|
||||
[ RISC_WRITECM >> 28 ] = "writecm",
|
||||
[ RISC_WRITECR >> 28 ] = "writecr",
|
||||
[RISC_SYNC >> 28] = "sync",
|
||||
[RISC_WRITE >> 28] = "write",
|
||||
[RISC_WRITEC >> 28] = "writec",
|
||||
[RISC_READ >> 28] = "read",
|
||||
[RISC_READC >> 28] = "readc",
|
||||
[RISC_JUMP >> 28] = "jump",
|
||||
[RISC_SKIP >> 28] = "skip",
|
||||
[RISC_WRITERM >> 28] = "writerm",
|
||||
[RISC_WRITECM >> 28] = "writecm",
|
||||
[RISC_WRITECR >> 28] = "writecr",
|
||||
};
|
||||
static int incr[16] = {
|
||||
[ RISC_WRITE >> 28 ] = 3,
|
||||
[ RISC_JUMP >> 28 ] = 3,
|
||||
[ RISC_SKIP >> 28 ] = 1,
|
||||
[ RISC_SYNC >> 28 ] = 1,
|
||||
[ RISC_WRITERM >> 28 ] = 3,
|
||||
[ RISC_WRITECM >> 28 ] = 3,
|
||||
[ RISC_WRITECR >> 28 ] = 4,
|
||||
[RISC_WRITE >> 28] = 3,
|
||||
[RISC_JUMP >> 28] = 3,
|
||||
[RISC_SKIP >> 28] = 1,
|
||||
[RISC_SYNC >> 28] = 1,
|
||||
[RISC_WRITERM >> 28] = 3,
|
||||
[RISC_WRITECM >> 28] = 3,
|
||||
[RISC_WRITECR >> 28] = 4,
|
||||
};
|
||||
static char *bits[] = {
|
||||
"12", "13", "14", "resync",
|
||||
|
@ -518,6 +518,8 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
|
|||
/* Transport bus init dma queue - Common settings */
|
||||
port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */
|
||||
port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */
|
||||
port->vld_misc_val = 0x0;
|
||||
port->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4);
|
||||
|
||||
spin_lock_init(&port->slock);
|
||||
port->dev = dev;
|
||||
|
@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
|
|||
port->reg_ts_clk_en = VID_B_TS_CLK_EN;
|
||||
port->reg_src_sel = VID_B_SRC_SEL;
|
||||
port->reg_ts_int_msk = VID_B_INT_MSK;
|
||||
port->reg_ts_int_stat = VID_B_INT_STAT;
|
||||
port->reg_ts_int_stat = VID_B_INT_STAT;
|
||||
port->sram_chno = SRAM_CH03; /* VID_B */
|
||||
port->pci_irqmask = 0x02; /* VID_B bit1 */
|
||||
break;
|
||||
|
@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
|
|||
dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
|
||||
dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
|
||||
|
||||
if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
|
||||
if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
|
||||
(cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
|
||||
cx23885_init_tsport(dev, &dev->ts1, 1);
|
||||
|
||||
if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
|
||||
if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
|
||||
(cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
|
||||
cx23885_init_tsport(dev, &dev->ts2, 2);
|
||||
|
||||
if (get_resources(dev) < 0) {
|
||||
|
@ -760,11 +764,26 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
|
|||
printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
|
||||
__func__);
|
||||
}
|
||||
} else
|
||||
if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
|
||||
if (cx23885_417_register(dev) < 0) {
|
||||
printk(KERN_ERR
|
||||
"%s() Failed to register 417 on VID_B\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
|
||||
if (cx23885_dvb_register(&dev->ts2) < 0) {
|
||||
printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n",
|
||||
printk(KERN_ERR
|
||||
"%s() Failed to register dvb on VID_C\n",
|
||||
__func__);
|
||||
}
|
||||
} else
|
||||
if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
|
||||
if (cx23885_417_register(dev) < 0) {
|
||||
printk(KERN_ERR
|
||||
"%s() Failed to register 417 on VID_C\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
|
|||
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
|
||||
cx23885_video_unregister(dev);
|
||||
|
||||
if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
|
||||
if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
|
||||
cx23885_dvb_unregister(&dev->ts1);
|
||||
|
||||
if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
|
||||
if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
|
||||
cx23885_417_unregister(dev);
|
||||
|
||||
if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
|
||||
cx23885_dvb_unregister(&dev->ts2);
|
||||
|
||||
if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
|
||||
cx23885_417_unregister(dev);
|
||||
|
||||
cx23885_i2c_unregister(&dev->i2c_bus[2]);
|
||||
cx23885_i2c_unregister(&dev->i2c_bus[1]);
|
||||
cx23885_i2c_unregister(&dev->i2c_bus[0]);
|
||||
|
@ -1043,9 +1068,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
|
|||
if(port->reg_src_sel)
|
||||
cx_write(port->reg_src_sel, port->src_sel_val);
|
||||
|
||||
cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4);
|
||||
cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
|
||||
cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
|
||||
cx_write(port->reg_vld_misc, 0x00);
|
||||
cx_write(port->reg_vld_misc, port->vld_misc_val);
|
||||
cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
|
||||
udelay(100);
|
||||
|
||||
|
@ -1239,6 +1264,16 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
|
|||
spin_unlock_irqrestore(&port->slock, flags);
|
||||
}
|
||||
|
||||
void cx23885_cancel_buffers(struct cx23885_tsport *port)
|
||||
{
|
||||
struct cx23885_dev *dev = port->dev;
|
||||
struct cx23885_dmaqueue *q = &port->mpegq;
|
||||
|
||||
dprintk(1, "%s()\n", __FUNCTION__);
|
||||
del_timer_sync(&q->timeout);
|
||||
cx23885_stop_dma(port);
|
||||
do_cancel_buffers(port, "cancel", 0);
|
||||
}
|
||||
|
||||
static void cx23885_timeout(unsigned long data)
|
||||
{
|
||||
|
@ -1254,16 +1289,77 @@ static void cx23885_timeout(unsigned long data)
|
|||
do_cancel_buffers(port, "timeout", 1);
|
||||
}
|
||||
|
||||
int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
|
||||
{
|
||||
/* FIXME: port1 assumption here. */
|
||||
struct cx23885_tsport *port = &dev->ts1;
|
||||
int count = 0;
|
||||
int handled = 0;
|
||||
|
||||
if (status == 0)
|
||||
return handled;
|
||||
|
||||
count = cx_read(port->reg_gpcnt);
|
||||
dprintk(7, "status: 0x%08x mask: 0x%08x count: 0x%x\n",
|
||||
status, cx_read(port->reg_ts_int_msk), count);
|
||||
|
||||
if ((status & VID_B_MSK_BAD_PKT) ||
|
||||
(status & VID_B_MSK_OPC_ERR) ||
|
||||
(status & VID_B_MSK_VBI_OPC_ERR) ||
|
||||
(status & VID_B_MSK_SYNC) ||
|
||||
(status & VID_B_MSK_VBI_SYNC) ||
|
||||
(status & VID_B_MSK_OF) ||
|
||||
(status & VID_B_MSK_VBI_OF)) {
|
||||
printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
|
||||
"= 0x%x\n", dev->name, status);
|
||||
if (status & VID_B_MSK_BAD_PKT)
|
||||
dprintk(1, " VID_B_MSK_BAD_PKT\n");
|
||||
if (status & VID_B_MSK_OPC_ERR)
|
||||
dprintk(1, " VID_B_MSK_OPC_ERR\n");
|
||||
if (status & VID_B_MSK_VBI_OPC_ERR)
|
||||
dprintk(1, " VID_B_MSK_VBI_OPC_ERR\n");
|
||||
if (status & VID_B_MSK_SYNC)
|
||||
dprintk(1, " VID_B_MSK_SYNC\n");
|
||||
if (status & VID_B_MSK_VBI_SYNC)
|
||||
dprintk(1, " VID_B_MSK_VBI_SYNC\n");
|
||||
if (status & VID_B_MSK_OF)
|
||||
dprintk(1, " VID_B_MSK_OF\n");
|
||||
if (status & VID_B_MSK_VBI_OF)
|
||||
dprintk(1, " VID_B_MSK_VBI_OF\n");
|
||||
|
||||
cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
|
||||
cx23885_sram_channel_dump(dev,
|
||||
&dev->sram_channels[port->sram_chno]);
|
||||
cx23885_417_check_encoder(dev);
|
||||
} else if (status & VID_B_MSK_RISCI1) {
|
||||
dprintk(7, " VID_B_MSK_RISCI1\n");
|
||||
spin_lock(&port->slock);
|
||||
cx23885_wakeup(port, &port->mpegq, count);
|
||||
spin_unlock(&port->slock);
|
||||
} else if (status & VID_B_MSK_RISCI2) {
|
||||
dprintk(7, " VID_B_MSK_RISCI2\n");
|
||||
spin_lock(&port->slock);
|
||||
cx23885_restart_queue(port, &port->mpegq);
|
||||
spin_unlock(&port->slock);
|
||||
}
|
||||
if (status) {
|
||||
cx_write(port->reg_ts_int_stat, status);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
|
||||
{
|
||||
struct cx23885_dev *dev = port->dev;
|
||||
int handled = 0;
|
||||
u32 count;
|
||||
|
||||
if ( (status & VID_BC_MSK_OPC_ERR) ||
|
||||
(status & VID_BC_MSK_BAD_PKT) ||
|
||||
(status & VID_BC_MSK_SYNC) ||
|
||||
(status & VID_BC_MSK_OF))
|
||||
if ((status & VID_BC_MSK_OPC_ERR) ||
|
||||
(status & VID_BC_MSK_BAD_PKT) ||
|
||||
(status & VID_BC_MSK_SYNC) ||
|
||||
(status & VID_BC_MSK_OF))
|
||||
{
|
||||
if (status & VID_BC_MSK_OPC_ERR)
|
||||
dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR);
|
||||
|
@ -1277,7 +1373,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
|
|||
printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
|
||||
|
||||
cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
|
||||
cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]);
|
||||
cx23885_sram_channel_dump(dev,
|
||||
&dev->sram_channels[port->sram_chno]);
|
||||
|
||||
} else if (status & VID_BC_MSK_RISCI1) {
|
||||
|
||||
|
@ -1378,11 +1475,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
|
|||
if (ts1_status) {
|
||||
if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
|
||||
handled += cx23885_irq_ts(ts1, ts1_status);
|
||||
else
|
||||
if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
|
||||
handled += cx23885_irq_417(dev, ts1_status);
|
||||
}
|
||||
|
||||
if (ts2_status) {
|
||||
if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
|
||||
handled += cx23885_irq_ts(ts2, ts2_status);
|
||||
else
|
||||
if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
|
||||
handled += cx23885_irq_417(dev, ts2_status);
|
||||
}
|
||||
|
||||
if (vida_status)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "btcx-risc.h"
|
||||
#include "cx23885-reg.h"
|
||||
#include "media/cx2341x.h"
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -157,6 +158,7 @@ typedef enum {
|
|||
CX23885_MPEG_UNDEFINED = 0,
|
||||
CX23885_MPEG_DVB,
|
||||
CX23885_ANALOG_VIDEO,
|
||||
CX23885_MPEG_ENCODER,
|
||||
} port_t;
|
||||
|
||||
struct cx23885_board {
|
||||
|
@ -255,6 +257,8 @@ struct cx23885_tsport {
|
|||
u32 gen_ctrl_val;
|
||||
u32 ts_clk_en_val;
|
||||
u32 src_sel_val;
|
||||
u32 vld_misc_val;
|
||||
u32 hw_sop_ctrl_val;
|
||||
};
|
||||
|
||||
struct cx23885_dev {
|
||||
|
@ -315,6 +319,14 @@ struct cx23885_dev {
|
|||
struct cx23885_dmaqueue vidq;
|
||||
struct cx23885_dmaqueue vbiq;
|
||||
spinlock_t slock;
|
||||
|
||||
/* MPEG Encoder ONLY settings */
|
||||
u32 cx23417_mailbox;
|
||||
struct cx2341x_mpeg_params mpeg_params;
|
||||
struct video_device *v4l_device;
|
||||
atomic_t v4l_reader_count;
|
||||
struct cx23885_tvnorm encodernorm;
|
||||
|
||||
};
|
||||
|
||||
extern struct list_head cx23885_devlist;
|
||||
|
@ -435,6 +447,17 @@ extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
|
|||
extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
|
||||
void *arg);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* cx23885-417.c */
|
||||
extern int cx23885_417_register(struct cx23885_dev *dev);
|
||||
extern void cx23885_417_unregister(struct cx23885_dev *dev);
|
||||
extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
|
||||
extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
|
||||
extern void cx23885_mc417_init(struct cx23885_dev *dev);
|
||||
extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
|
||||
extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tv norms */
|
||||
|
||||
|
|
Loading…
Reference in a new issue