Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 124290
b: refs/heads/master
c: ee2d64f
h: refs/heads/master
v: v3
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Dec 30, 2008
1 parent e0d0b30 commit 08e7656
Show file tree
Hide file tree
Showing 17 changed files with 409 additions and 216 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ba38ee8ebe4a42ce2213802152b0b86a95dc109f
refs/heads/master: ee2d64f5ccc71b5c5191e92ea91a12b65f9ca060
8 changes: 7 additions & 1 deletion trunk/drivers/media/video/cx18/cx18-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ static void cx18_process_options(struct cx18 *cx)
*/
static int __devinit cx18_init_struct1(struct cx18 *cx)
{
int i;

cx->base_addr = pci_resource_start(cx->dev, 0);

mutex_init(&cx->serialize_lock);
Expand All @@ -451,7 +453,11 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)

spin_lock_init(&cx->lock);

INIT_WORK(&cx->work, cx18_work_handler);
for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
cx->epu_work_order[i].cx = cx;
cx->epu_work_order[i].str = cx->epu_debug_str;
INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler);
}

/* start counting open_id at 1 */
cx->open_id = 1;
Expand Down
19 changes: 15 additions & 4 deletions trunk/drivers/media/video/cx18/cx18-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,6 @@ struct cx18_options {
#define CX18_F_I_EOS 4 /* End of encoder stream */
#define CX18_F_I_RADIO_USER 5 /* radio tuner is selected */
#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */
#define CX18_F_I_HAVE_WORK 15 /* there is work to be done */
#define CX18_F_I_WORK_HANDLER_DVB 18 /* work to be done for DVB */
#define CX18_F_I_INITED 21 /* set after first open */
#define CX18_F_I_FAILED 22 /* set if first open failed */

Expand Down Expand Up @@ -247,6 +245,19 @@ struct cx18_dvb {
struct cx18; /* forward reference */
struct cx18_scb; /* forward reference */

#define CX18_MAX_MDL_ACKS 2
#define CX18_MAX_EPU_WORK_ORDERS 70 /* CPU_DE_RELEASE_MDL bursts 63 commands */

struct cx18_epu_work_order {
struct work_struct work;
atomic_t pending;
struct cx18 *cx;
int rpu;
struct cx18_mailbox mb;
struct cx18_mdl_ack mdl_ack[CX18_MAX_MDL_ACKS];
char *str;
};

#define CX18_INVALID_TASK_HANDLE 0xffffffff

struct cx18_stream {
Expand Down Expand Up @@ -388,7 +399,6 @@ struct cx18 {
struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/
struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/


struct cx18_av_state av_state;

/* codec settings */
Expand Down Expand Up @@ -441,7 +451,8 @@ struct cx18 {
/* when the current DMA is finished this queue is woken up */
wait_queue_head_t dma_waitq;

struct work_struct work;
struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS];
char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */

/* i2c */
struct i2c_adapter i2c_adap[2];
Expand Down
25 changes: 0 additions & 25 deletions trunk/drivers/media/video/cx18/cx18-dvb.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
#include "cx18-dvb.h"
#include "cx18-io.h"
#include "cx18-streams.h"
#include "cx18-queue.h"
#include "cx18-scb.h"
#include "cx18-cards.h"
#include "s5h1409.h"
#include "mxl5005s.h"
Expand Down Expand Up @@ -305,26 +303,3 @@ static int dvb_register(struct cx18_stream *stream)

return ret;
}

void cx18_dvb_work_handler(struct cx18 *cx)
{
struct cx18_buffer *buf;
struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_TS];

while ((buf = cx18_dequeue(s, &s->q_full)) != NULL) {
if (s->dvb.enabled)
dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
buf->bytesused);

cx18_buf_sync_for_device(s, buf);
cx18_enqueue(s, buf, &s->q_free);

if (s->handle == CX18_INVALID_TASK_HANDLE ||
!test_bit(CX18_F_S_STREAMING, &s->s_flags))
continue;

cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
(void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
1, buf->id, s->buf_size);
}
}
1 change: 0 additions & 1 deletion trunk/drivers/media/video/cx18/cx18-dvb.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,3 @@

int cx18_dvb_register(struct cx18_stream *stream);
void cx18_dvb_unregister(struct cx18_stream *stream);
void cx18_dvb_work_handler(struct cx18 *cx);
5 changes: 5 additions & 0 deletions trunk/drivers/media/video/cx18/cx18-firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
if (cx18_raw_readl(cx, dst) != *src) {
CX18_ERR("Mismatch at offset %x\n", i);
release_firmware(fw);
cx18_setup_page(cx, 0);
return -EIO;
}
dst++;
Expand All @@ -131,6 +132,7 @@ static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
size = fw->size;
release_firmware(fw);
cx18_setup_page(cx, SCB_OFFSET);
return size;
}

Expand All @@ -150,6 +152,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
if (request_firmware(&fw, fn, &cx->dev->dev)) {
CX18_ERR("unable to open firmware %s\n", fn);
CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
cx18_setup_page(cx, 0);
return -ENOMEM;
}

Expand Down Expand Up @@ -185,6 +188,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
CX18_ERR("Mismatch at offset %x\n",
offset + j);
release_firmware(fw);
cx18_setup_page(cx, 0);
return -EIO;
}
}
Expand All @@ -196,6 +200,7 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
fn, apu_version, fw->size);
size = fw->size;
release_firmware(fw);
cx18_setup_page(cx, 0);
return size;
}

Expand Down
35 changes: 0 additions & 35 deletions trunk/drivers/media/video/cx18/cx18-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,41 +166,6 @@ u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr)
return val;
}

void cx18_memcpy_fromio(struct cx18 *cx, void *to,
const void __iomem *from, unsigned int len)
{
const u8 __iomem *src = from;
u8 *dst = to;

/* Align reads on the CX23418's addresses */
if ((len > 0) && ((unsigned long) src & 1)) {
*dst = cx18_readb(cx, src);
len--;
dst++;
src++;
}
if ((len > 1) && ((unsigned long) src & 2)) {
*((u16 *)dst) = cx18_raw_readw(cx, src);
len -= 2;
dst += 2;
src += 2;
}
while (len > 3) {
*((u32 *)dst) = cx18_raw_readl(cx, src);
len -= 4;
dst += 4;
src += 4;
}
if (len > 1) {
*((u16 *)dst) = cx18_raw_readw(cx, src);
len -= 2;
dst += 2;
src += 2;
}
if (len > 0)
*dst = cx18_readb(cx, src);
}

void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
{
u8 __iomem *dst = addr;
Expand Down
7 changes: 6 additions & 1 deletion trunk/drivers/media/video/cx18/cx18-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,13 @@ static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr)
}


static inline
void cx18_memcpy_fromio(struct cx18 *cx, void *to,
const void __iomem *from, unsigned int len);
const void __iomem *from, unsigned int len)
{
memcpy_fromio(to, from, len);
}

void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);


Expand Down
133 changes: 15 additions & 118 deletions trunk/drivers/media/video/cx18/cx18-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,121 +21,9 @@

#include "cx18-driver.h"
#include "cx18-io.h"
#include "cx18-firmware.h"
#include "cx18-fileops.h"
#include "cx18-queue.h"
#include "cx18-irq.h"
#include "cx18-ioctl.h"
#include "cx18-mailbox.h"
#include "cx18-vbi.h"
#include "cx18-scb.h"
#include "cx18-dvb.h"

void cx18_work_handler(struct work_struct *work)
{
struct cx18 *cx = container_of(work, struct cx18, work);
if (test_and_clear_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags))
cx18_dvb_work_handler(cx);
}

static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb, int rpu)
{
u32 handle = mb->args[0];
struct cx18_stream *s = NULL;
struct cx18_buffer *buf;
u32 off;
int i;
int id;

for (i = 0; i < CX18_MAX_STREAMS; i++) {
s = &cx->streams[i];
if ((handle == s->handle) && (s->dvb.enabled))
break;
if (s->v4l2dev && handle == s->handle)
break;
}
if (i == CX18_MAX_STREAMS) {
CX18_WARN("Got DMA done notification for unknown/inactive"
" handle %d\n", handle);
mb->error = CXERR_NOT_OPEN;
mb->cmd = 0;
cx18_mb_ack(cx, mb, rpu);
return;
}

off = mb->args[1];
if (mb->args[2] != 1)
CX18_WARN("Ack struct = %d for %s\n",
mb->args[2], s->name);
id = cx18_read_enc(cx, off);
buf = cx18_queue_get_buf_irq(s, id, cx18_read_enc(cx, off + 4));
CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
if (buf) {
cx18_buf_sync_for_cpu(s, buf);
if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n",
buf->bytesused);

set_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags);
set_bit(CX18_F_I_HAVE_WORK, &cx->i_flags);
} else
set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
} else {
CX18_WARN("Could not find buf %d for stream %s\n",
cx18_read_enc(cx, off), s->name);
}
mb->error = 0;
mb->cmd = 0;
cx18_mb_ack(cx, mb, rpu);
wake_up(&cx->dma_waitq);
if (s->id != -1)
wake_up(&s->waitq);
}

static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb, int rpu)
{
char str[256] = { 0 };
char *p;

if (mb->args[1]) {
cx18_setup_page(cx, mb->args[1]);
cx18_memcpy_fromio(cx, str, cx->enc_mem + mb->args[1], 252);
str[252] = 0;
}
cx18_mb_ack(cx, mb, rpu);
CX18_DEBUG_INFO("%x %s\n", mb->args[0], str);
p = strchr(str, '.');
if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
CX18_INFO("FW version: %s\n", p - 1);
}

static void epu_cmd(struct cx18 *cx, u32 sw1)
{
struct cx18_mailbox mb;

if (sw1 & IRQ_CPU_TO_EPU) {
cx18_memcpy_fromio(cx, &mb, &cx->scb->cpu2epu_mb, sizeof(mb));
mb.error = 0;

switch (mb.cmd) {
case CX18_EPU_DMA_DONE:
epu_dma_done(cx, &mb, CPU);
break;
case CX18_EPU_DEBUG:
epu_debug(cx, &mb, CPU);
break;
default:
CX18_WARN("Unknown CPU_TO_EPU mailbox command %#08x\n",
mb.cmd);
break;
}
}

if (sw1 & IRQ_APU_TO_EPU) {
cx18_memcpy_fromio(cx, &mb, &cx->scb->apu2epu_mb, sizeof(mb));
CX18_WARN("Unknown APU_TO_EPU mailbox command %#08x\n", mb.cmd);
}
}

static void xpu_ack(struct cx18 *cx, u32 sw2)
{
Expand All @@ -145,6 +33,14 @@ static void xpu_ack(struct cx18 *cx, u32 sw2)
wake_up(&cx->mb_apu_waitq);
}

static void epu_cmd(struct cx18 *cx, u32 sw1)
{
if (sw1 & IRQ_CPU_TO_EPU)
cx18_api_epu_cmd_irq(cx, CPU);
if (sw1 & IRQ_APU_TO_EPU)
cx18_api_epu_cmd_irq(cx, APU);
}

irqreturn_t cx18_irq_handler(int irq, void *dev_id)
{
struct cx18 *cx = (struct cx18 *)dev_id;
Expand All @@ -170,6 +66,13 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
CX18_DEBUG_HI_IRQ("received interrupts "
"SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2);

/*
* SW1 responses have to happen first. The sending XPU times out the
* incoming mailboxes on us rather rapidly.
*/
if (sw1)
epu_cmd(cx, sw1);

/* To do: interrupt-based I2C handling
if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
}
Expand All @@ -178,11 +81,5 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id)
if (sw2)
xpu_ack(cx, sw2);

if (sw1)
epu_cmd(cx, sw1);

if (test_and_clear_bit(CX18_F_I_HAVE_WORK, &cx->i_flags))
schedule_work(&cx->work);

return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
}
2 changes: 0 additions & 2 deletions trunk/drivers/media/video/cx18/cx18-irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,3 @@
#define SW2_INT_ENABLE_PCI 0xc7315c

irqreturn_t cx18_irq_handler(int irq, void *dev_id);

void cx18_work_handler(struct work_struct *work);
Loading

0 comments on commit 08e7656

Please sign in to comment.