Commit b1b81f1d authored by Steven Toth's avatar Steven Toth Committed by Mauro Carvalho Chehab

V4L/DVB (7725): cx23885: Add generic cx23417 hardware encoder support

cx23885: Add generic cx23417 hardware encoder support.
Signed-off-by: default avatarSteven Toth <stoth@hauppauge.com>
Signed-off-by: default avatarMichael Krufky <mkrufky@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent e57b1c80
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 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
......
This diff is collapsed.
...@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = { ...@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = {
static int cx23885_risc_decode(u32 risc) static int cx23885_risc_decode(u32 risc)
{ {
static char *instr[16] = { static char *instr[16] = {
[ RISC_SYNC >> 28 ] = "sync", [RISC_SYNC >> 28] = "sync",
[ RISC_WRITE >> 28 ] = "write", [RISC_WRITE >> 28] = "write",
[ RISC_WRITEC >> 28 ] = "writec", [RISC_WRITEC >> 28] = "writec",
[ RISC_READ >> 28 ] = "read", [RISC_READ >> 28] = "read",
[ RISC_READC >> 28 ] = "readc", [RISC_READC >> 28] = "readc",
[ RISC_JUMP >> 28 ] = "jump", [RISC_JUMP >> 28] = "jump",
[ RISC_SKIP >> 28 ] = "skip", [RISC_SKIP >> 28] = "skip",
[ RISC_WRITERM >> 28 ] = "writerm", [RISC_WRITERM >> 28] = "writerm",
[ RISC_WRITECM >> 28 ] = "writecm", [RISC_WRITECM >> 28] = "writecm",
[ RISC_WRITECR >> 28 ] = "writecr", [RISC_WRITECR >> 28] = "writecr",
}; };
static int incr[16] = { static int incr[16] = {
[ RISC_WRITE >> 28 ] = 3, [RISC_WRITE >> 28] = 3,
[ RISC_JUMP >> 28 ] = 3, [RISC_JUMP >> 28] = 3,
[ RISC_SKIP >> 28 ] = 1, [RISC_SKIP >> 28] = 1,
[ RISC_SYNC >> 28 ] = 1, [RISC_SYNC >> 28] = 1,
[ RISC_WRITERM >> 28 ] = 3, [RISC_WRITERM >> 28] = 3,
[ RISC_WRITECM >> 28 ] = 3, [RISC_WRITECM >> 28] = 3,
[ RISC_WRITECR >> 28 ] = 4, [RISC_WRITECR >> 28] = 4,
}; };
static char *bits[] = { static char *bits[] = {
"12", "13", "14", "resync", "12", "13", "14", "resync",
...@@ -518,6 +518,8 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p ...@@ -518,6 +518,8 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p
/* Transport bus init dma queue - Common settings */ /* Transport bus init dma queue - Common settings */
port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */ port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */
port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */ 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); spin_lock_init(&port->slock);
port->dev = dev; port->dev = dev;
...@@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) ...@@ -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].reg_wdata = I2C3_WDATA;
dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ 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); 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); cx23885_init_tsport(dev, &dev->ts2, 2);
if (get_resources(dev) < 0) { if (get_resources(dev) < 0) {
...@@ -760,11 +764,26 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) ...@@ -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", printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
__func__); __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_boards[dev->board].portc == CX23885_MPEG_DVB) {
if (cx23885_dvb_register(&dev->ts2) < 0) { 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__); __func__);
} }
} }
...@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) ...@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev)
if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
cx23885_video_unregister(dev); 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); 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); 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[2]);
cx23885_i2c_unregister(&dev->i2c_bus[1]); cx23885_i2c_unregister(&dev->i2c_bus[1]);
cx23885_i2c_unregister(&dev->i2c_bus[0]); cx23885_i2c_unregister(&dev->i2c_bus[0]);
...@@ -1043,9 +1068,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, ...@@ -1043,9 +1068,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
if(port->reg_src_sel) if(port->reg_src_sel)
cx_write(port->reg_src_sel, port->src_sel_val); 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_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); cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
udelay(100); udelay(100);
...@@ -1239,6 +1264,16 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason, ...@@ -1239,6 +1264,16 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
spin_unlock_irqrestore(&port->slock, flags); 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) static void cx23885_timeout(unsigned long data)
{ {
...@@ -1254,13 +1289,74 @@ static void cx23885_timeout(unsigned long data) ...@@ -1254,13 +1289,74 @@ static void cx23885_timeout(unsigned long data)
do_cancel_buffers(port, "timeout", 1); 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) static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
{ {
struct cx23885_dev *dev = port->dev; struct cx23885_dev *dev = port->dev;
int handled = 0; int handled = 0;
u32 count; u32 count;
if ( (status & VID_BC_MSK_OPC_ERR) || if ((status & VID_BC_MSK_OPC_ERR) ||
(status & VID_BC_MSK_BAD_PKT) || (status & VID_BC_MSK_BAD_PKT) ||
(status & VID_BC_MSK_SYNC) || (status & VID_BC_MSK_SYNC) ||
(status & VID_BC_MSK_OF)) (status & VID_BC_MSK_OF))
...@@ -1277,7 +1373,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) ...@@ -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); printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
cx_clear(port->reg_dma_ctl, port->dma_ctl_val); 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) { } else if (status & VID_BC_MSK_RISCI1) {
...@@ -1378,11 +1475,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) ...@@ -1378,11 +1475,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
if (ts1_status) { if (ts1_status) {
if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
handled += cx23885_irq_ts(ts1, ts1_status); 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 (ts2_status) {
if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
handled += cx23885_irq_ts(ts2, ts2_status); 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) if (vida_status)
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "btcx-risc.h" #include "btcx-risc.h"
#include "cx23885-reg.h" #include "cx23885-reg.h"
#include "media/cx2341x.h"
#include <linux/version.h> #include <linux/version.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -157,6 +158,7 @@ typedef enum { ...@@ -157,6 +158,7 @@ typedef enum {
CX23885_MPEG_UNDEFINED = 0, CX23885_MPEG_UNDEFINED = 0,
CX23885_MPEG_DVB, CX23885_MPEG_DVB,
CX23885_ANALOG_VIDEO, CX23885_ANALOG_VIDEO,
CX23885_MPEG_ENCODER,
} port_t; } port_t;
struct cx23885_board { struct cx23885_board {
...@@ -255,6 +257,8 @@ struct cx23885_tsport { ...@@ -255,6 +257,8 @@ struct cx23885_tsport {
u32 gen_ctrl_val; u32 gen_ctrl_val;
u32 ts_clk_en_val; u32 ts_clk_en_val;
u32 src_sel_val; u32 src_sel_val;
u32 vld_misc_val;
u32 hw_sop_ctrl_val;
}; };
struct cx23885_dev { struct cx23885_dev {
...@@ -315,6 +319,14 @@ struct cx23885_dev { ...@@ -315,6 +319,14 @@ struct cx23885_dev {
struct cx23885_dmaqueue vidq; struct cx23885_dmaqueue vidq;
struct cx23885_dmaqueue vbiq; struct cx23885_dmaqueue vbiq;
spinlock_t slock; 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; extern struct list_head cx23885_devlist;
...@@ -435,6 +447,17 @@ extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); ...@@ -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, extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd,
void *arg); 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 */ /* tv norms */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment