diff options
author | Steven Toth <stoth@kernellabs.com> | 2010-07-31 13:44:53 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-10-21 05:54:34 -0400 |
commit | 7615e434aefd95181eae099c4f019e021b024eb6 (patch) | |
tree | 22901c7326d8edfe0b8ac1208cb289fcc55241ad /drivers/media/video/saa7164/saa7164-core.c | |
parent | add3f580a4342b8bca7e0fb4737fe9eeaefa4319 (diff) |
[media] saa7164: add various encoder message functions
Signed-off-by: Steven Toth <stoth@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7164/saa7164-core.c')
-rw-r--r-- | drivers/media/video/saa7164/saa7164-core.c | 167 |
1 files changed, 142 insertions, 25 deletions
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index 88c36bd2bd1d..b8e56d88743f 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c | |||
@@ -82,6 +82,69 @@ static void saa7164_buffer_deliver(struct saa7164_buffer *buf) | |||
82 | 82 | ||
83 | } | 83 | } |
84 | 84 | ||
85 | static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port) | ||
86 | { | ||
87 | struct saa7164_dev *dev = port->dev; | ||
88 | struct saa7164_buffer *buf; | ||
89 | struct saa7164_user_buffer *ubuf; | ||
90 | struct list_head *c, *n; | ||
91 | int wp, i = 0, rp; | ||
92 | |||
93 | /* Find the current write point from the hardware */ | ||
94 | wp = saa7164_readl(port->bufcounter); | ||
95 | if (wp > (port->hwcfg.buffercount - 1)) | ||
96 | BUG(); | ||
97 | |||
98 | /* Find the previous buffer to the current write point */ | ||
99 | if (wp == 0) | ||
100 | rp = 7; | ||
101 | else | ||
102 | rp = wp - 1; | ||
103 | |||
104 | /* Lookup the WP in the buffer list */ | ||
105 | /* TODO: turn this into a worker thread */ | ||
106 | list_for_each_safe(c, n, &port->dmaqueue.list) { | ||
107 | buf = list_entry(c, struct saa7164_buffer, list); | ||
108 | if (i++ > port->hwcfg.buffercount) | ||
109 | BUG(); | ||
110 | |||
111 | if (buf->idx == rp) { | ||
112 | /* Found the buffer, deal with it */ | ||
113 | dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n", | ||
114 | __func__, wp, rp); | ||
115 | |||
116 | /* */ | ||
117 | /* find a free user buffer and clone to it */ | ||
118 | if (!list_empty(&port->list_buf_free.list)) { | ||
119 | |||
120 | /* Pull the first buffer from the used list */ | ||
121 | ubuf = list_first_entry(&port->list_buf_free.list, | ||
122 | struct saa7164_user_buffer, list); | ||
123 | |||
124 | if (ubuf->actual_size == buf->actual_size) | ||
125 | memcpy(ubuf->data, buf->cpu, ubuf->actual_size); | ||
126 | |||
127 | /* Requeue the buffer on the free list */ | ||
128 | ubuf->pos = 0; | ||
129 | |||
130 | |||
131 | // mutex_lock(&port->dmaqueue_lock); | ||
132 | list_move_tail(&ubuf->list, &port->list_buf_used.list); | ||
133 | // mutex_unlock(&port->dmaqueue_lock); | ||
134 | |||
135 | /* Flag any userland waiters */ | ||
136 | wake_up_interruptible(&port->wait_read); | ||
137 | |||
138 | } else | ||
139 | printk(KERN_ERR "encirq no free buffers\n"); | ||
140 | |||
141 | break; | ||
142 | } | ||
143 | |||
144 | } | ||
145 | return 0; | ||
146 | } | ||
147 | |||
85 | static irqreturn_t saa7164_irq_ts(struct saa7164_port *port) | 148 | static irqreturn_t saa7164_irq_ts(struct saa7164_port *port) |
86 | { | 149 | { |
87 | struct saa7164_dev *dev = port->dev; | 150 | struct saa7164_dev *dev = port->dev; |
@@ -123,6 +186,11 @@ static irqreturn_t saa7164_irq_ts(struct saa7164_port *port) | |||
123 | static irqreturn_t saa7164_irq(int irq, void *dev_id) | 186 | static irqreturn_t saa7164_irq(int irq, void *dev_id) |
124 | { | 187 | { |
125 | struct saa7164_dev *dev = dev_id; | 188 | struct saa7164_dev *dev = dev_id; |
189 | struct saa7164_port *porta = &dev->ports[ SAA7164_PORT_TS1 ]; | ||
190 | struct saa7164_port *portb = &dev->ports[ SAA7164_PORT_TS2 ]; | ||
191 | struct saa7164_port *portc = &dev->ports[ SAA7164_PORT_ENC1 ]; | ||
192 | struct saa7164_port *portd = &dev->ports[ SAA7164_PORT_ENC2 ]; | ||
193 | |||
126 | u32 intid, intstat[INT_SIZE/4]; | 194 | u32 intid, intstat[INT_SIZE/4]; |
127 | int i, handled = 0, bit; | 195 | int i, handled = 0, bit; |
128 | 196 | ||
@@ -168,17 +236,25 @@ static irqreturn_t saa7164_irq(int irq, void *dev_id) | |||
168 | if (intid == dev->intfdesc.bInterruptId) { | 236 | if (intid == dev->intfdesc.bInterruptId) { |
169 | /* A response to an cmd/api call */ | 237 | /* A response to an cmd/api call */ |
170 | schedule_work(&dev->workcmd); | 238 | schedule_work(&dev->workcmd); |
171 | } else if (intid == | 239 | } else if (intid == porta->hwcfg.interruptid) { |
172 | dev->ts1.hwcfg.interruptid) { | ||
173 | 240 | ||
174 | /* Transport path 1 */ | 241 | /* Transport path 1 */ |
175 | saa7164_irq_ts(&dev->ts1); | 242 | saa7164_irq_ts(porta); |
176 | 243 | ||
177 | } else if (intid == | 244 | } else if (intid == portb->hwcfg.interruptid) { |
178 | dev->ts2.hwcfg.interruptid) { | ||
179 | 245 | ||
180 | /* Transport path 2 */ | 246 | /* Transport path 2 */ |
181 | saa7164_irq_ts(&dev->ts2); | 247 | saa7164_irq_ts(portb); |
248 | |||
249 | } else if (intid == portc->hwcfg.interruptid) { | ||
250 | |||
251 | /* Encoder path 1 */ | ||
252 | saa7164_irq_encoder(portc); | ||
253 | |||
254 | } else if (intid == portd->hwcfg.interruptid) { | ||
255 | |||
256 | /* Encoder path 1 */ | ||
257 | saa7164_irq_encoder(portd); | ||
182 | 258 | ||
183 | } else { | 259 | } else { |
184 | /* Find the function */ | 260 | /* Find the function */ |
@@ -402,6 +478,37 @@ static int get_resources(struct saa7164_dev *dev) | |||
402 | return -EBUSY; | 478 | return -EBUSY; |
403 | } | 479 | } |
404 | 480 | ||
481 | static int saa7164_port_init(struct saa7164_dev *dev, int portnr) | ||
482 | { | ||
483 | struct saa7164_port *port = 0; | ||
484 | |||
485 | if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS)) | ||
486 | BUG(); | ||
487 | |||
488 | port = &dev->ports[ portnr ]; | ||
489 | |||
490 | port->dev = dev; | ||
491 | port->nr = portnr; | ||
492 | |||
493 | if ((portnr == SAA7164_PORT_TS1) || (portnr == SAA7164_PORT_TS2)) | ||
494 | port->type = SAA7164_MPEG_DVB; | ||
495 | else | ||
496 | if ((portnr == SAA7164_PORT_ENC1) || (portnr == SAA7164_PORT_ENC2)) | ||
497 | port->type = SAA7164_MPEG_ENCODER; | ||
498 | else | ||
499 | BUG(); | ||
500 | |||
501 | /* Init all the critical resources */ | ||
502 | mutex_init(&port->dvb.lock); | ||
503 | INIT_LIST_HEAD(&port->dmaqueue.list); | ||
504 | mutex_init(&port->dmaqueue_lock); | ||
505 | |||
506 | INIT_LIST_HEAD(&port->list_buf_used.list); | ||
507 | INIT_LIST_HEAD(&port->list_buf_free.list); | ||
508 | init_waitqueue_head(&port->wait_read); | ||
509 | return 0; | ||
510 | } | ||
511 | |||
405 | static int saa7164_dev_setup(struct saa7164_dev *dev) | 512 | static int saa7164_dev_setup(struct saa7164_dev *dev) |
406 | { | 513 | { |
407 | int i; | 514 | int i; |
@@ -443,21 +550,11 @@ static int saa7164_dev_setup(struct saa7164_dev *dev) | |||
443 | dev->i2c_bus[2].dev = dev; | 550 | dev->i2c_bus[2].dev = dev; |
444 | dev->i2c_bus[2].nr = 2; | 551 | dev->i2c_bus[2].nr = 2; |
445 | 552 | ||
446 | /* Transport port A Defaults / setup */ | 553 | /* Transport + Encoder ports 1, 2, 3, 4 - Defaults / setup */ |
447 | dev->ts1.dev = dev; | 554 | saa7164_port_init(dev, SAA7164_PORT_TS1); |
448 | dev->ts1.nr = 0; | 555 | saa7164_port_init(dev, SAA7164_PORT_TS2); |
449 | dev->ts1.type = SAA7164_MPEG_UNDEFINED; | 556 | saa7164_port_init(dev, SAA7164_PORT_ENC1); |
450 | mutex_init(&dev->ts1.dvb.lock); | 557 | saa7164_port_init(dev, SAA7164_PORT_ENC2); |
451 | INIT_LIST_HEAD(&dev->ts1.dmaqueue.list); | ||
452 | mutex_init(&dev->ts1.dmaqueue_lock); | ||
453 | |||
454 | /* Transport port B Defaults / setup */ | ||
455 | dev->ts2.dev = dev; | ||
456 | dev->ts2.nr = 1; | ||
457 | dev->ts2.type = SAA7164_MPEG_UNDEFINED; | ||
458 | mutex_init(&dev->ts2.dvb.lock); | ||
459 | INIT_LIST_HEAD(&dev->ts2.dmaqueue.list); | ||
460 | mutex_init(&dev->ts2.dmaqueue_lock); | ||
461 | 558 | ||
462 | if (get_resources(dev) < 0) { | 559 | if (get_resources(dev) < 0) { |
463 | printk(KERN_ERR "CORE %s No more PCIe resources for " | 560 | printk(KERN_ERR "CORE %s No more PCIe resources for " |
@@ -631,7 +728,7 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev, | |||
631 | 728 | ||
632 | /* Begin to create the video sub-systems and register funcs */ | 729 | /* Begin to create the video sub-systems and register funcs */ |
633 | if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) { | 730 | if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) { |
634 | if (saa7164_dvb_register(&dev->ts1) < 0) { | 731 | if (saa7164_dvb_register(&dev->ports[ SAA7164_PORT_TS1 ]) < 0) { |
635 | printk(KERN_ERR "%s() Failed to register " | 732 | printk(KERN_ERR "%s() Failed to register " |
636 | "dvb adapters on porta\n", | 733 | "dvb adapters on porta\n", |
637 | __func__); | 734 | __func__); |
@@ -639,13 +736,27 @@ static int __devinit saa7164_initdev(struct pci_dev *pci_dev, | |||
639 | } | 736 | } |
640 | 737 | ||
641 | if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) { | 738 | if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) { |
642 | if (saa7164_dvb_register(&dev->ts2) < 0) { | 739 | if (saa7164_dvb_register(&dev->ports[ SAA7164_PORT_TS2 ]) < 0) { |
643 | printk(KERN_ERR"%s() Failed to register " | 740 | printk(KERN_ERR"%s() Failed to register " |
644 | "dvb adapters on portb\n", | 741 | "dvb adapters on portb\n", |
645 | __func__); | 742 | __func__); |
646 | } | 743 | } |
647 | } | 744 | } |
648 | 745 | ||
746 | if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) { | ||
747 | if (saa7164_encoder_register(&dev->ports[ SAA7164_PORT_ENC1 ]) < 0) { | ||
748 | printk(KERN_ERR"%s() Failed to register " | ||
749 | "mpeg encoder\n", __func__); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) { | ||
754 | if (saa7164_encoder_register(&dev->ports[ SAA7164_PORT_ENC2 ]) < 0) { | ||
755 | printk(KERN_ERR"%s() Failed to register " | ||
756 | "mpeg encoder\n", __func__); | ||
757 | } | ||
758 | } | ||
759 | |||
649 | } /* != BOARD_UNKNOWN */ | 760 | } /* != BOARD_UNKNOWN */ |
650 | else | 761 | else |
651 | printk(KERN_ERR "%s() Unsupported board detected, " | 762 | printk(KERN_ERR "%s() Unsupported board detected, " |
@@ -676,10 +787,16 @@ static void __devexit saa7164_finidev(struct pci_dev *pci_dev) | |||
676 | saa7164_shutdown(dev); | 787 | saa7164_shutdown(dev); |
677 | 788 | ||
678 | if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) | 789 | if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) |
679 | saa7164_dvb_unregister(&dev->ts1); | 790 | saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS1 ]); |
680 | 791 | ||
681 | if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) | 792 | if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) |
682 | saa7164_dvb_unregister(&dev->ts2); | 793 | saa7164_dvb_unregister(&dev->ports[ SAA7164_PORT_TS2 ]); |
794 | |||
795 | if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) | ||
796 | saa7164_encoder_unregister(&dev->ports[ SAA7164_PORT_ENC1 ]); | ||
797 | |||
798 | if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) | ||
799 | saa7164_encoder_unregister(&dev->ports[ SAA7164_PORT_ENC2 ]); | ||
683 | 800 | ||
684 | saa7164_i2c_unregister(&dev->i2c_bus[0]); | 801 | saa7164_i2c_unregister(&dev->i2c_bus[0]); |
685 | saa7164_i2c_unregister(&dev->i2c_bus[1]); | 802 | saa7164_i2c_unregister(&dev->i2c_bus[1]); |