diff options
Diffstat (limited to 'drivers/media')
73 files changed, 3863 insertions, 816 deletions
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 6098b626811f..47fee05eaefb 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c | |||
@@ -576,6 +576,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) | |||
576 | vv->vflip = c->value; | 576 | vv->vflip = c->value; |
577 | break; | 577 | break; |
578 | default: { | 578 | default: { |
579 | mutex_unlock(&dev->lock); | ||
579 | return -EINVAL; | 580 | return -EINVAL; |
580 | } | 581 | } |
581 | } | 582 | } |
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c index 64379f2bf237..3ec28945c26f 100644 --- a/drivers/media/common/tuners/mxl5007t.c +++ b/drivers/media/common/tuners/mxl5007t.c | |||
@@ -657,7 +657,7 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status) | |||
657 | { | 657 | { |
658 | struct mxl5007t_state *state = fe->tuner_priv; | 658 | struct mxl5007t_state *state = fe->tuner_priv; |
659 | int rf_locked, ref_locked; | 659 | int rf_locked, ref_locked; |
660 | s32 rf_input_level; | 660 | s32 rf_input_level = 0; |
661 | int ret; | 661 | int ret; |
662 | 662 | ||
663 | if (fe->ops.i2c_gate_ctrl) | 663 | if (fe->ops.i2c_gate_ctrl) |
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c index de7adaf5fa5b..78412c9c424a 100644 --- a/drivers/media/common/tuners/tuner-simple.c +++ b/drivers/media/common/tuners/tuner-simple.c | |||
@@ -318,7 +318,6 @@ static int simple_std_setup(struct dvb_frontend *fe, | |||
318 | u8 *config, u8 *cb) | 318 | u8 *config, u8 *cb) |
319 | { | 319 | { |
320 | struct tuner_simple_priv *priv = fe->tuner_priv; | 320 | struct tuner_simple_priv *priv = fe->tuner_priv; |
321 | u8 tuneraddr; | ||
322 | int rc; | 321 | int rc; |
323 | 322 | ||
324 | /* tv norm specific stuff for multi-norm tuners */ | 323 | /* tv norm specific stuff for multi-norm tuners */ |
@@ -387,6 +386,7 @@ static int simple_std_setup(struct dvb_frontend *fe, | |||
387 | 386 | ||
388 | case TUNER_PHILIPS_TUV1236D: | 387 | case TUNER_PHILIPS_TUV1236D: |
389 | { | 388 | { |
389 | struct tuner_i2c_props i2c = priv->i2c_props; | ||
390 | /* 0x40 -> ATSC antenna input 1 */ | 390 | /* 0x40 -> ATSC antenna input 1 */ |
391 | /* 0x48 -> ATSC antenna input 2 */ | 391 | /* 0x48 -> ATSC antenna input 2 */ |
392 | /* 0x00 -> NTSC antenna input 1 */ | 392 | /* 0x00 -> NTSC antenna input 1 */ |
@@ -398,17 +398,15 @@ static int simple_std_setup(struct dvb_frontend *fe, | |||
398 | buffer[1] = 0x04; | 398 | buffer[1] = 0x04; |
399 | } | 399 | } |
400 | /* set to the correct mode (analog or digital) */ | 400 | /* set to the correct mode (analog or digital) */ |
401 | tuneraddr = priv->i2c_props.addr; | 401 | i2c.addr = 0x0a; |
402 | priv->i2c_props.addr = 0x0a; | 402 | rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2); |
403 | rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2); | ||
404 | if (2 != rc) | 403 | if (2 != rc) |
405 | tuner_warn("i2c i/o error: rc == %d " | 404 | tuner_warn("i2c i/o error: rc == %d " |
406 | "(should be 2)\n", rc); | 405 | "(should be 2)\n", rc); |
407 | rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2); | 406 | rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2); |
408 | if (2 != rc) | 407 | if (2 != rc) |
409 | tuner_warn("i2c i/o error: rc == %d " | 408 | tuner_warn("i2c i/o error: rc == %d " |
410 | "(should be 2)\n", rc); | 409 | "(should be 2)\n", rc); |
411 | priv->i2c_props.addr = tuneraddr; | ||
412 | break; | 410 | break; |
413 | } | 411 | } |
414 | } | 412 | } |
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 40ebde53b3ce..b0198691892a 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig | |||
@@ -51,6 +51,10 @@ comment "Supported SDMC DM1105 Adapters" | |||
51 | depends on DVB_CORE && PCI && I2C | 51 | depends on DVB_CORE && PCI && I2C |
52 | source "drivers/media/dvb/dm1105/Kconfig" | 52 | source "drivers/media/dvb/dm1105/Kconfig" |
53 | 53 | ||
54 | comment "Supported FireWire (IEEE 1394) Adapters" | ||
55 | depends on DVB_CORE && IEEE1394 | ||
56 | source "drivers/media/dvb/firewire/Kconfig" | ||
57 | |||
54 | comment "Supported DVB Frontends" | 58 | comment "Supported DVB Frontends" |
55 | depends on DVB_CORE | 59 | depends on DVB_CORE |
56 | source "drivers/media/dvb/frontends/Kconfig" | 60 | source "drivers/media/dvb/frontends/Kconfig" |
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index f91e9eb15e52..6092a5bb5a7d 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile | |||
@@ -3,3 +3,5 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ | 5 | obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ |
6 | |||
7 | obj-$(CONFIG_DVB_FIREDTV) += firewire/ | ||
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c index b386cc66c6b3..451974ba32f3 100644 --- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c +++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c | |||
@@ -192,6 +192,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d | |||
192 | 192 | ||
193 | return 0; | 193 | return 0; |
194 | } | 194 | } |
195 | EXPORT_SYMBOL(flexcop_pid_feed_control); | ||
195 | 196 | ||
196 | void flexcop_hw_filter_init(struct flexcop_device *fc) | 197 | void flexcop_hw_filter_init(struct flexcop_device *fc) |
197 | { | 198 | { |
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c index 5b30dfc7846b..76e37fd96bb6 100644 --- a/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/drivers/media/dvb/b2c2/flexcop-pci.c | |||
@@ -13,9 +13,9 @@ static int enable_pid_filtering = 1; | |||
13 | module_param(enable_pid_filtering, int, 0444); | 13 | module_param(enable_pid_filtering, int, 0444); |
14 | MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); | 14 | MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); |
15 | 15 | ||
16 | static int irq_chk_intv; | 16 | static int irq_chk_intv = 100; |
17 | module_param(irq_chk_intv, int, 0644); | 17 | module_param(irq_chk_intv, int, 0644); |
18 | MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging)."); | 18 | MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog."); |
19 | 19 | ||
20 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG | 20 | #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG |
21 | #define dprintk(level,args...) \ | 21 | #define dprintk(level,args...) \ |
@@ -34,7 +34,9 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently jus | |||
34 | 34 | ||
35 | static int debug; | 35 | static int debug; |
36 | module_param(debug, int, 0644); | 36 | module_param(debug, int, 0644); |
37 | MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS); | 37 | MODULE_PARM_DESC(debug, |
38 | "set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))." | ||
39 | DEBSTATUS); | ||
38 | 40 | ||
39 | #define DRIVER_VERSION "0.1" | 41 | #define DRIVER_VERSION "0.1" |
40 | #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" | 42 | #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" |
@@ -58,6 +60,8 @@ struct flexcop_pci { | |||
58 | int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ | 60 | int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ |
59 | u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ | 61 | u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ |
60 | int count; | 62 | int count; |
63 | int count_prev; | ||
64 | int stream_problem; | ||
61 | 65 | ||
62 | spinlock_t irq_lock; | 66 | spinlock_t irq_lock; |
63 | 67 | ||
@@ -103,18 +107,32 @@ static void flexcop_pci_irq_check_work(struct work_struct *work) | |||
103 | container_of(work, struct flexcop_pci, irq_check_work.work); | 107 | container_of(work, struct flexcop_pci, irq_check_work.work); |
104 | struct flexcop_device *fc = fc_pci->fc_dev; | 108 | struct flexcop_device *fc = fc_pci->fc_dev; |
105 | 109 | ||
106 | flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); | 110 | if (fc->feedcount) { |
107 | 111 | ||
108 | flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4); | 112 | if (fc_pci->count == fc_pci->count_prev) { |
109 | 113 | deb_chk("no IRQ since the last check\n"); | |
110 | if (v.sram_dest_reg_714.net_ovflow_error) | 114 | if (fc_pci->stream_problem++ == 3) { |
111 | deb_chk("sram net_ovflow_error\n"); | 115 | struct dvb_demux_feed *feed; |
112 | if (v.sram_dest_reg_714.media_ovflow_error) | 116 | |
113 | deb_chk("sram media_ovflow_error\n"); | 117 | spin_lock_irq(&fc->demux.lock); |
114 | if (v.sram_dest_reg_714.cai_ovflow_error) | 118 | list_for_each_entry(feed, &fc->demux.feed_list, |
115 | deb_chk("sram cai_ovflow_error\n"); | 119 | list_head) { |
116 | if (v.sram_dest_reg_714.cai_ovflow_error) | 120 | flexcop_pid_feed_control(fc, feed, 0); |
117 | deb_chk("sram cai_ovflow_error\n"); | 121 | } |
122 | |||
123 | list_for_each_entry(feed, &fc->demux.feed_list, | ||
124 | list_head) { | ||
125 | flexcop_pid_feed_control(fc, feed, 1); | ||
126 | } | ||
127 | spin_unlock_irq(&fc->demux.lock); | ||
128 | |||
129 | fc_pci->stream_problem = 0; | ||
130 | } | ||
131 | } else { | ||
132 | fc_pci->stream_problem = 0; | ||
133 | fc_pci->count_prev = fc_pci->count; | ||
134 | } | ||
135 | } | ||
118 | 136 | ||
119 | schedule_delayed_work(&fc_pci->irq_check_work, | 137 | schedule_delayed_work(&fc_pci->irq_check_work, |
120 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | 138 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); |
@@ -216,16 +234,12 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff) | |||
216 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); | 234 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,1); |
217 | deb_irq("IRQ enabled\n"); | 235 | deb_irq("IRQ enabled\n"); |
218 | 236 | ||
237 | fc_pci->count_prev = fc_pci->count; | ||
238 | |||
219 | // fc_pci->active_dma1_addr = 0; | 239 | // fc_pci->active_dma1_addr = 0; |
220 | // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); | 240 | // flexcop_dma_control_size_irq(fc,FC_DMA_1,1); |
221 | 241 | ||
222 | if (irq_chk_intv > 0) | ||
223 | schedule_delayed_work(&fc_pci->irq_check_work, | ||
224 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | ||
225 | } else { | 242 | } else { |
226 | if (irq_chk_intv > 0) | ||
227 | cancel_delayed_work(&fc_pci->irq_check_work); | ||
228 | |||
229 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); | 243 | flexcop_dma_control_timer_irq(fc,FC_DMA_1,0); |
230 | deb_irq("IRQ disabled\n"); | 244 | deb_irq("IRQ disabled\n"); |
231 | 245 | ||
@@ -299,8 +313,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) | |||
299 | IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) | 313 | IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) |
300 | goto err_pci_iounmap; | 314 | goto err_pci_iounmap; |
301 | 315 | ||
302 | |||
303 | |||
304 | fc_pci->init_state |= FC_PCI_INIT; | 316 | fc_pci->init_state |= FC_PCI_INIT; |
305 | return ret; | 317 | return ret; |
306 | 318 | ||
@@ -375,6 +387,10 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
375 | 387 | ||
376 | INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); | 388 | INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); |
377 | 389 | ||
390 | if (irq_chk_intv > 0) | ||
391 | schedule_delayed_work(&fc_pci->irq_check_work, | ||
392 | msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); | ||
393 | |||
378 | return ret; | 394 | return ret; |
379 | 395 | ||
380 | err_fc_exit: | 396 | err_fc_exit: |
@@ -393,6 +409,9 @@ static void flexcop_pci_remove(struct pci_dev *pdev) | |||
393 | { | 409 | { |
394 | struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); | 410 | struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); |
395 | 411 | ||
412 | if (irq_chk_intv > 0) | ||
413 | cancel_delayed_work(&fc_pci->irq_check_work); | ||
414 | |||
396 | flexcop_pci_dma_exit(fc_pci); | 415 | flexcop_pci_dma_exit(fc_pci); |
397 | flexcop_device_exit(fc_pci->fc_dev); | 416 | flexcop_device_exit(fc_pci->fc_dev); |
398 | flexcop_pci_exit(fc_pci); | 417 | flexcop_pci_exit(fc_pci); |
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c index 676413a915b4..91068952b502 100644 --- a/drivers/media/dvb/b2c2/flexcop.c +++ b/drivers/media/dvb/b2c2/flexcop.c | |||
@@ -212,8 +212,7 @@ void flexcop_reset_block_300(struct flexcop_device *fc) | |||
212 | v210.sw_reset_210.Block_reset_enable = 0xb2; | 212 | v210.sw_reset_210.Block_reset_enable = 0xb2; |
213 | 213 | ||
214 | fc->write_ibi_reg(fc,sw_reset_210,v210); | 214 | fc->write_ibi_reg(fc,sw_reset_210,v210); |
215 | msleep(1); | 215 | udelay(1000); |
216 | |||
217 | fc->write_ibi_reg(fc,ctrl_208,v208_save); | 216 | fc->write_ibi_reg(fc,ctrl_208,v208_save); |
218 | } | 217 | } |
219 | 218 | ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c index 0c733c66a441..069d847ba887 100644 --- a/drivers/media/dvb/dvb-core/dmxdev.c +++ b/drivers/media/dvb/dvb-core/dmxdev.c | |||
@@ -364,16 +364,15 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | |||
364 | enum dmx_success success) | 364 | enum dmx_success success) |
365 | { | 365 | { |
366 | struct dmxdev_filter *dmxdevfilter = filter->priv; | 366 | struct dmxdev_filter *dmxdevfilter = filter->priv; |
367 | unsigned long flags; | ||
368 | int ret; | 367 | int ret; |
369 | 368 | ||
370 | if (dmxdevfilter->buffer.error) { | 369 | if (dmxdevfilter->buffer.error) { |
371 | wake_up(&dmxdevfilter->buffer.queue); | 370 | wake_up(&dmxdevfilter->buffer.queue); |
372 | return 0; | 371 | return 0; |
373 | } | 372 | } |
374 | spin_lock_irqsave(&dmxdevfilter->dev->lock, flags); | 373 | spin_lock(&dmxdevfilter->dev->lock); |
375 | if (dmxdevfilter->state != DMXDEV_STATE_GO) { | 374 | if (dmxdevfilter->state != DMXDEV_STATE_GO) { |
376 | spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); | 375 | spin_unlock(&dmxdevfilter->dev->lock); |
377 | return 0; | 376 | return 0; |
378 | } | 377 | } |
379 | del_timer(&dmxdevfilter->timer); | 378 | del_timer(&dmxdevfilter->timer); |
@@ -392,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, | |||
392 | } | 391 | } |
393 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) | 392 | if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) |
394 | dmxdevfilter->state = DMXDEV_STATE_DONE; | 393 | dmxdevfilter->state = DMXDEV_STATE_DONE; |
395 | spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); | 394 | spin_unlock(&dmxdevfilter->dev->lock); |
396 | wake_up(&dmxdevfilter->buffer.queue); | 395 | wake_up(&dmxdevfilter->buffer.queue); |
397 | return 0; | 396 | return 0; |
398 | } | 397 | } |
@@ -404,12 +403,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
404 | { | 403 | { |
405 | struct dmxdev_filter *dmxdevfilter = feed->priv; | 404 | struct dmxdev_filter *dmxdevfilter = feed->priv; |
406 | struct dvb_ringbuffer *buffer; | 405 | struct dvb_ringbuffer *buffer; |
407 | unsigned long flags; | ||
408 | int ret; | 406 | int ret; |
409 | 407 | ||
410 | spin_lock_irqsave(&dmxdevfilter->dev->lock, flags); | 408 | spin_lock(&dmxdevfilter->dev->lock); |
411 | if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { | 409 | if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { |
412 | spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); | 410 | spin_unlock(&dmxdevfilter->dev->lock); |
413 | return 0; | 411 | return 0; |
414 | } | 412 | } |
415 | 413 | ||
@@ -419,7 +417,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
419 | else | 417 | else |
420 | buffer = &dmxdevfilter->dev->dvr_buffer; | 418 | buffer = &dmxdevfilter->dev->dvr_buffer; |
421 | if (buffer->error) { | 419 | if (buffer->error) { |
422 | spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); | 420 | spin_unlock(&dmxdevfilter->dev->lock); |
423 | wake_up(&buffer->queue); | 421 | wake_up(&buffer->queue); |
424 | return 0; | 422 | return 0; |
425 | } | 423 | } |
@@ -430,7 +428,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, | |||
430 | dvb_ringbuffer_flush(buffer); | 428 | dvb_ringbuffer_flush(buffer); |
431 | buffer->error = ret; | 429 | buffer->error = ret; |
432 | } | 430 | } |
433 | spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); | 431 | spin_unlock(&dmxdevfilter->dev->lock); |
434 | wake_up(&buffer->queue); | 432 | wake_up(&buffer->queue); |
435 | return 0; | 433 | return 0; |
436 | } | 434 | } |
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 98ee16773ff2..7e3aeaa7370f 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c | |||
@@ -93,6 +93,9 @@ struct dvb_ca_slot { | |||
93 | /* current state of the CAM */ | 93 | /* current state of the CAM */ |
94 | int slot_state; | 94 | int slot_state; |
95 | 95 | ||
96 | /* mutex used for serializing access to one CI slot */ | ||
97 | struct mutex slot_lock; | ||
98 | |||
96 | /* Number of CAMCHANGES that have occurred since last processing */ | 99 | /* Number of CAMCHANGES that have occurred since last processing */ |
97 | atomic_t camchange_count; | 100 | atomic_t camchange_count; |
98 | 101 | ||
@@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b | |||
711 | dprintk("%s\n", __func__); | 714 | dprintk("%s\n", __func__); |
712 | 715 | ||
713 | 716 | ||
714 | // sanity check | 717 | /* sanity check */ |
715 | if (bytes_write > ca->slot_info[slot].link_buf_size) | 718 | if (bytes_write > ca->slot_info[slot].link_buf_size) |
716 | return -EINVAL; | 719 | return -EINVAL; |
717 | 720 | ||
718 | /* check if interface is actually waiting for us to read from it, or if a read is in progress */ | 721 | /* it is possible we are dealing with a single buffer implementation, |
722 | thus if there is data available for read or if there is even a read | ||
723 | already in progress, we do nothing but awake the kernel thread to | ||
724 | process the data if necessary. */ | ||
719 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) | 725 | if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) |
720 | goto exitnowrite; | 726 | goto exitnowrite; |
721 | if (status & (STATUSREG_DA | STATUSREG_RE)) { | 727 | if (status & (STATUSREG_DA | STATUSREG_RE)) { |
728 | if (status & STATUSREG_DA) | ||
729 | dvb_ca_en50221_thread_wakeup(ca); | ||
730 | |||
722 | status = -EAGAIN; | 731 | status = -EAGAIN; |
723 | goto exitnowrite; | 732 | goto exitnowrite; |
724 | } | 733 | } |
@@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data) | |||
987 | /* go through all the slots processing them */ | 996 | /* go through all the slots processing them */ |
988 | for (slot = 0; slot < ca->slot_count; slot++) { | 997 | for (slot = 0; slot < ca->slot_count; slot++) { |
989 | 998 | ||
999 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1000 | |||
990 | // check the cam status + deal with CAMCHANGEs | 1001 | // check the cam status + deal with CAMCHANGEs |
991 | while (dvb_ca_en50221_check_camstatus(ca, slot)) { | 1002 | while (dvb_ca_en50221_check_camstatus(ca, slot)) { |
992 | /* clear down an old CI slot if necessary */ | 1003 | /* clear down an old CI slot if necessary */ |
@@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data) | |||
1122 | 1133 | ||
1123 | case DVB_CA_SLOTSTATE_RUNNING: | 1134 | case DVB_CA_SLOTSTATE_RUNNING: |
1124 | if (!ca->open) | 1135 | if (!ca->open) |
1125 | continue; | 1136 | break; |
1126 | 1137 | ||
1127 | // poll slots for data | 1138 | // poll slots for data |
1128 | pktcount = 0; | 1139 | pktcount = 0; |
@@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data) | |||
1146 | } | 1157 | } |
1147 | break; | 1158 | break; |
1148 | } | 1159 | } |
1160 | |||
1161 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1149 | } | 1162 | } |
1150 | } | 1163 | } |
1151 | 1164 | ||
@@ -1181,6 +1194,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, | |||
1181 | switch (cmd) { | 1194 | switch (cmd) { |
1182 | case CA_RESET: | 1195 | case CA_RESET: |
1183 | for (slot = 0; slot < ca->slot_count; slot++) { | 1196 | for (slot = 0; slot < ca->slot_count; slot++) { |
1197 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1184 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { | 1198 | if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) { |
1185 | dvb_ca_en50221_slot_shutdown(ca, slot); | 1199 | dvb_ca_en50221_slot_shutdown(ca, slot); |
1186 | if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) | 1200 | if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) |
@@ -1188,6 +1202,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, | |||
1188 | slot, | 1202 | slot, |
1189 | DVB_CA_EN50221_CAMCHANGE_INSERTED); | 1203 | DVB_CA_EN50221_CAMCHANGE_INSERTED); |
1190 | } | 1204 | } |
1205 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1191 | } | 1206 | } |
1192 | ca->next_read_slot = 0; | 1207 | ca->next_read_slot = 0; |
1193 | dvb_ca_en50221_thread_wakeup(ca); | 1208 | dvb_ca_en50221_thread_wakeup(ca); |
@@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, | |||
1308 | goto exit; | 1323 | goto exit; |
1309 | } | 1324 | } |
1310 | 1325 | ||
1326 | mutex_lock(&ca->slot_info[slot].slot_lock); | ||
1311 | status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); | 1327 | status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2); |
1328 | mutex_unlock(&ca->slot_info[slot].slot_lock); | ||
1312 | if (status == (fraglen + 2)) { | 1329 | if (status == (fraglen + 2)) { |
1313 | written = 1; | 1330 | written = 1; |
1314 | break; | 1331 | break; |
@@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, | |||
1664 | ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; | 1681 | ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE; |
1665 | atomic_set(&ca->slot_info[i].camchange_count, 0); | 1682 | atomic_set(&ca->slot_info[i].camchange_count, 0); |
1666 | ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; | 1683 | ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED; |
1684 | mutex_init(&ca->slot_info[i].slot_lock); | ||
1667 | } | 1685 | } |
1668 | 1686 | ||
1669 | if (signal_pending(current)) { | 1687 | if (signal_pending(current)) { |
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h index 8467e63ddc0d..7df2e141187a 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h | |||
@@ -45,8 +45,10 @@ struct dvb_ca_en50221 { | |||
45 | /* the module owning this structure */ | 45 | /* the module owning this structure */ |
46 | struct module* owner; | 46 | struct module* owner; |
47 | 47 | ||
48 | /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as | 48 | /* NOTE: the read_*, write_* and poll_slot_status functions will be |
49 | * they may be called from several threads at once */ | 49 | * called for different slots concurrently and need to use locks where |
50 | * and if appropriate. There will be no concurrent access to one slot. | ||
51 | */ | ||
50 | 52 | ||
51 | /* functions for accessing attribute memory on the CAM */ | 53 | /* functions for accessing attribute memory on the CAM */ |
52 | int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); | 54 | int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address); |
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index a2c1fd5d2f67..e2eca0b1fe7c 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c | |||
@@ -399,9 +399,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf) | |||
399 | void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, | 399 | void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, |
400 | size_t count) | 400 | size_t count) |
401 | { | 401 | { |
402 | unsigned long flags; | 402 | spin_lock(&demux->lock); |
403 | |||
404 | spin_lock_irqsave(&demux->lock, flags); | ||
405 | 403 | ||
406 | while (count--) { | 404 | while (count--) { |
407 | if (buf[0] == 0x47) | 405 | if (buf[0] == 0x47) |
@@ -409,17 +407,16 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, | |||
409 | buf += 188; | 407 | buf += 188; |
410 | } | 408 | } |
411 | 409 | ||
412 | spin_unlock_irqrestore(&demux->lock, flags); | 410 | spin_unlock(&demux->lock); |
413 | } | 411 | } |
414 | 412 | ||
415 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); | 413 | EXPORT_SYMBOL(dvb_dmx_swfilter_packets); |
416 | 414 | ||
417 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | 415 | void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) |
418 | { | 416 | { |
419 | unsigned long flags; | ||
420 | int p = 0, i, j; | 417 | int p = 0, i, j; |
421 | 418 | ||
422 | spin_lock_irqsave(&demux->lock, flags); | 419 | spin_lock(&demux->lock); |
423 | 420 | ||
424 | if (demux->tsbufp) { | 421 | if (demux->tsbufp) { |
425 | i = demux->tsbufp; | 422 | i = demux->tsbufp; |
@@ -452,18 +449,17 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) | |||
452 | } | 449 | } |
453 | 450 | ||
454 | bailout: | 451 | bailout: |
455 | spin_unlock_irqrestore(&demux->lock, flags); | 452 | spin_unlock(&demux->lock); |
456 | } | 453 | } |
457 | 454 | ||
458 | EXPORT_SYMBOL(dvb_dmx_swfilter); | 455 | EXPORT_SYMBOL(dvb_dmx_swfilter); |
459 | 456 | ||
460 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | 457 | void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) |
461 | { | 458 | { |
462 | unsigned long flags; | ||
463 | int p = 0, i, j; | 459 | int p = 0, i, j; |
464 | u8 tmppack[188]; | 460 | u8 tmppack[188]; |
465 | 461 | ||
466 | spin_lock_irqsave(&demux->lock, flags); | 462 | spin_lock(&demux->lock); |
467 | 463 | ||
468 | if (demux->tsbufp) { | 464 | if (demux->tsbufp) { |
469 | i = demux->tsbufp; | 465 | i = demux->tsbufp; |
@@ -504,7 +500,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) | |||
504 | } | 500 | } |
505 | 501 | ||
506 | bailout: | 502 | bailout: |
507 | spin_unlock_irqrestore(&demux->lock, flags); | 503 | spin_unlock(&demux->lock); |
508 | } | 504 | } |
509 | 505 | ||
510 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); | 506 | EXPORT_SYMBOL(dvb_dmx_swfilter_204); |
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c index b1a9c4cdec93..199ece0d4883 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c | |||
@@ -220,7 +220,7 @@ static int af9005_get_post_vit_ber(struct dvb_frontend *fe, | |||
220 | u16 * abort_count) | 220 | u16 * abort_count) |
221 | { | 221 | { |
222 | u32 loc_cw_count = 0, loc_err_count; | 222 | u32 loc_cw_count = 0, loc_err_count; |
223 | u16 loc_abort_count; | 223 | u16 loc_abort_count = 0; |
224 | int ret; | 224 | int ret; |
225 | 225 | ||
226 | ret = | 226 | ret = |
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index e1e9aa5c6b84..6a97a40d3dfb 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c | |||
@@ -694,7 +694,12 @@ static int af9015_read_config(struct usb_device *udev) | |||
694 | 694 | ||
695 | /* IR remote controller */ | 695 | /* IR remote controller */ |
696 | req.addr = AF9015_EEPROM_IR_MODE; | 696 | req.addr = AF9015_EEPROM_IR_MODE; |
697 | ret = af9015_rw_udev(udev, &req); | 697 | /* first message will timeout often due to possible hw bug */ |
698 | for (i = 0; i < 4; i++) { | ||
699 | ret = af9015_rw_udev(udev, &req); | ||
700 | if (!ret) | ||
701 | break; | ||
702 | } | ||
698 | if (ret) | 703 | if (ret) |
699 | goto error; | 704 | goto error; |
700 | deb_info("%s: IR mode:%d\n", __func__, val); | 705 | deb_info("%s: IR mode:%d\n", __func__, val); |
@@ -835,18 +840,19 @@ static int af9015_read_config(struct usb_device *udev) | |||
835 | if (!dvb_usb_af9015_dual_mode) | 840 | if (!dvb_usb_af9015_dual_mode) |
836 | af9015_config.dual_mode = 0; | 841 | af9015_config.dual_mode = 0; |
837 | 842 | ||
838 | /* set buffer size according to USB port speed */ | 843 | /* Set adapter0 buffer size according to USB port speed, adapter1 buffer |
844 | size can be static because it is enabled only USB2.0 */ | ||
839 | for (i = 0; i < af9015_properties_count; i++) { | 845 | for (i = 0; i < af9015_properties_count; i++) { |
840 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ | 846 | /* USB1.1 set smaller buffersize and disable 2nd adapter */ |
841 | if (udev->speed == USB_SPEED_FULL) { | 847 | if (udev->speed == USB_SPEED_FULL) { |
842 | af9015_properties[i].adapter->stream.u.bulk.buffersize = | 848 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize |
843 | TS_USB11_MAX_PACKET_SIZE; | 849 | = TS_USB11_MAX_PACKET_SIZE; |
844 | /* disable 2nd adapter because we don't have | 850 | /* disable 2nd adapter because we don't have |
845 | PID-filters */ | 851 | PID-filters */ |
846 | af9015_config.dual_mode = 0; | 852 | af9015_config.dual_mode = 0; |
847 | } else { | 853 | } else { |
848 | af9015_properties[i].adapter->stream.u.bulk.buffersize = | 854 | af9015_properties[i].adapter[0].stream.u.bulk.buffersize |
849 | TS_USB20_MAX_PACKET_SIZE; | 855 | = TS_USB20_MAX_PACKET_SIZE; |
850 | } | 856 | } |
851 | } | 857 | } |
852 | 858 | ||
@@ -1254,6 +1260,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1254 | .type = USB_BULK, | 1260 | .type = USB_BULK, |
1255 | .count = 6, | 1261 | .count = 6, |
1256 | .endpoint = 0x85, | 1262 | .endpoint = 0x85, |
1263 | .u = { | ||
1264 | .bulk = { | ||
1265 | .buffersize = | ||
1266 | TS_USB20_MAX_PACKET_SIZE, | ||
1267 | } | ||
1268 | } | ||
1257 | }, | 1269 | }, |
1258 | } | 1270 | } |
1259 | }, | 1271 | }, |
@@ -1353,6 +1365,12 @@ static struct dvb_usb_device_properties af9015_properties[] = { | |||
1353 | .type = USB_BULK, | 1365 | .type = USB_BULK, |
1354 | .count = 6, | 1366 | .count = 6, |
1355 | .endpoint = 0x85, | 1367 | .endpoint = 0x85, |
1368 | .u = { | ||
1369 | .bulk = { | ||
1370 | .buffersize = | ||
1371 | TS_USB20_MAX_PACKET_SIZE, | ||
1372 | } | ||
1373 | } | ||
1356 | }, | 1374 | }, |
1357 | } | 1375 | } |
1358 | }, | 1376 | }, |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 391732788911..635d30a55078 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -1393,6 +1393,9 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
1393 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, | 1393 | { USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) }, |
1394 | /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, | 1394 | /* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) }, |
1395 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, | 1395 | { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) }, |
1396 | { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) }, | ||
1397 | { USB_DEVICE(USB_VID_TERRATEC, | ||
1398 | USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, | ||
1396 | { 0 } /* Terminating entry */ | 1399 | { 0 } /* Terminating entry */ |
1397 | }; | 1400 | }; |
1398 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 1401 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -1537,7 +1540,8 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1537 | { "DiBcom STK7700D reference design", | 1540 | { "DiBcom STK7700D reference design", |
1538 | { &dib0700_usb_id_table[14], NULL }, | 1541 | { &dib0700_usb_id_table[14], NULL }, |
1539 | { NULL }, | 1542 | { NULL }, |
1540 | } | 1543 | }, |
1544 | |||
1541 | }, | 1545 | }, |
1542 | 1546 | ||
1543 | .rc_interval = DEFAULT_RC_INTERVAL, | 1547 | .rc_interval = DEFAULT_RC_INTERVAL, |
@@ -1557,7 +1561,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1557 | }, | 1561 | }, |
1558 | }, | 1562 | }, |
1559 | 1563 | ||
1560 | .num_device_descs = 2, | 1564 | .num_device_descs = 3, |
1561 | .devices = { | 1565 | .devices = { |
1562 | { "ASUS My Cinema U3000 Mini DVBT Tuner", | 1566 | { "ASUS My Cinema U3000 Mini DVBT Tuner", |
1563 | { &dib0700_usb_id_table[23], NULL }, | 1567 | { &dib0700_usb_id_table[23], NULL }, |
@@ -1566,6 +1570,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1566 | { "Yuan EC372S", | 1570 | { "Yuan EC372S", |
1567 | { &dib0700_usb_id_table[31], NULL }, | 1571 | { &dib0700_usb_id_table[31], NULL }, |
1568 | { NULL }, | 1572 | { NULL }, |
1573 | }, | ||
1574 | { "Terratec Cinergy T Express", | ||
1575 | { &dib0700_usb_id_table[42], NULL }, | ||
1576 | { NULL }, | ||
1569 | } | 1577 | } |
1570 | }, | 1578 | }, |
1571 | 1579 | ||
@@ -1653,7 +1661,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1653 | } | 1661 | } |
1654 | }, | 1662 | }, |
1655 | 1663 | ||
1656 | .num_device_descs = 4, | 1664 | .num_device_descs = 5, |
1657 | .devices = { | 1665 | .devices = { |
1658 | { "DiBcom STK7070PD reference design", | 1666 | { "DiBcom STK7070PD reference design", |
1659 | { &dib0700_usb_id_table[17], NULL }, | 1667 | { &dib0700_usb_id_table[17], NULL }, |
@@ -1670,6 +1678,10 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
1670 | { "Hauppauge Nova-TD-500 (84xxx)", | 1678 | { "Hauppauge Nova-TD-500 (84xxx)", |
1671 | { &dib0700_usb_id_table[36], NULL }, | 1679 | { &dib0700_usb_id_table[36], NULL }, |
1672 | { NULL }, | 1680 | { NULL }, |
1681 | }, | ||
1682 | { "Terratec Cinergy DT USB XS Diversity", | ||
1683 | { &dib0700_usb_id_table[43], NULL }, | ||
1684 | { NULL }, | ||
1673 | } | 1685 | } |
1674 | } | 1686 | } |
1675 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, | 1687 | }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index a4fca3fca5ee..0db0c06ee6f2 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -162,8 +162,10 @@ | |||
162 | #define USB_PID_AVERMEDIA_A309 0xa309 | 162 | #define USB_PID_AVERMEDIA_A309 0xa309 |
163 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 | 163 | #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 |
164 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a | 164 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a |
165 | #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 | ||
165 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 | 166 | #define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 |
166 | #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 | 167 | #define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060 |
168 | #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 | ||
167 | #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 | 169 | #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 |
168 | #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e | 170 | #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e |
169 | #define USB_PID_PINNACLE_PCTV2000E 0x022c | 171 | #define USB_PID_PINNACLE_PCTV2000E 0x022c |
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig new file mode 100644 index 000000000000..69028253e984 --- /dev/null +++ b/drivers/media/dvb/firewire/Kconfig | |||
@@ -0,0 +1,22 @@ | |||
1 | config DVB_FIREDTV | ||
2 | tristate "FireDTV and FloppyDTV" | ||
3 | depends on DVB_CORE && IEEE1394 | ||
4 | help | ||
5 | Support for DVB receivers from Digital Everywhere | ||
6 | which are connected via IEEE 1394 (FireWire). | ||
7 | |||
8 | These devices don't have an MPEG decoder built in, | ||
9 | so you need an external software decoder to watch TV. | ||
10 | |||
11 | To compile this driver as a module, say M here: | ||
12 | the module will be called firedtv. | ||
13 | |||
14 | if DVB_FIREDTV | ||
15 | |||
16 | config DVB_FIREDTV_IEEE1394 | ||
17 | def_bool IEEE1394 | ||
18 | |||
19 | config DVB_FIREDTV_INPUT | ||
20 | def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m) | ||
21 | |||
22 | endif # DVB_FIREDTV | ||
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile new file mode 100644 index 000000000000..2034695ba194 --- /dev/null +++ b/drivers/media/dvb/firewire/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | obj-$(CONFIG_DVB_FIREDTV) += firedtv.o | ||
2 | |||
3 | firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o | ||
4 | firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o | ||
5 | firedtv-$(CONFIG_DVB_FIREDTV_INPUT) += firedtv-rc.o | ||
6 | |||
7 | ccflags-y += -Idrivers/media/dvb/dvb-core | ||
8 | ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394 | ||
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c new file mode 100644 index 000000000000..4e207658c5d9 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-1394.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com> | ||
6 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/types.h> | ||
20 | |||
21 | #include <dma.h> | ||
22 | #include <csr1212.h> | ||
23 | #include <highlevel.h> | ||
24 | #include <hosts.h> | ||
25 | #include <ieee1394.h> | ||
26 | #include <iso.h> | ||
27 | #include <nodemgr.h> | ||
28 | |||
29 | #include "firedtv.h" | ||
30 | |||
31 | static LIST_HEAD(node_list); | ||
32 | static DEFINE_SPINLOCK(node_list_lock); | ||
33 | |||
34 | #define FIREWIRE_HEADER_SIZE 4 | ||
35 | #define CIP_HEADER_SIZE 8 | ||
36 | |||
37 | static void rawiso_activity_cb(struct hpsb_iso *iso) | ||
38 | { | ||
39 | struct firedtv *f, *fdtv = NULL; | ||
40 | unsigned int i, num, packet; | ||
41 | unsigned char *buf; | ||
42 | unsigned long flags; | ||
43 | int count; | ||
44 | |||
45 | spin_lock_irqsave(&node_list_lock, flags); | ||
46 | list_for_each_entry(f, &node_list, list) | ||
47 | if (f->backend_data == iso) { | ||
48 | fdtv = f; | ||
49 | break; | ||
50 | } | ||
51 | spin_unlock_irqrestore(&node_list_lock, flags); | ||
52 | |||
53 | packet = iso->first_packet; | ||
54 | num = hpsb_iso_n_ready(iso); | ||
55 | |||
56 | if (!fdtv) { | ||
57 | dev_err(fdtv->device, "received at unknown iso channel\n"); | ||
58 | goto out; | ||
59 | } | ||
60 | |||
61 | for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) { | ||
62 | buf = dma_region_i(&iso->data_buf, unsigned char, | ||
63 | iso->infos[packet].offset + CIP_HEADER_SIZE); | ||
64 | count = (iso->infos[packet].len - CIP_HEADER_SIZE) / | ||
65 | (188 + FIREWIRE_HEADER_SIZE); | ||
66 | |||
67 | /* ignore empty packet */ | ||
68 | if (iso->infos[packet].len <= CIP_HEADER_SIZE) | ||
69 | continue; | ||
70 | |||
71 | while (count--) { | ||
72 | if (buf[FIREWIRE_HEADER_SIZE] == 0x47) | ||
73 | dvb_dmx_swfilter_packets(&fdtv->demux, | ||
74 | &buf[FIREWIRE_HEADER_SIZE], 1); | ||
75 | else | ||
76 | dev_err(fdtv->device, | ||
77 | "skipping invalid packet\n"); | ||
78 | buf += 188 + FIREWIRE_HEADER_SIZE; | ||
79 | } | ||
80 | } | ||
81 | out: | ||
82 | hpsb_iso_recv_release_packets(iso, num); | ||
83 | } | ||
84 | |||
85 | static inline struct node_entry *node_of(struct firedtv *fdtv) | ||
86 | { | ||
87 | return container_of(fdtv->device, struct unit_directory, device)->ne; | ||
88 | } | ||
89 | |||
90 | static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg) | ||
91 | { | ||
92 | return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data, | ||
93 | (__force quadlet_t)arg); | ||
94 | } | ||
95 | |||
96 | static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len) | ||
97 | { | ||
98 | return hpsb_node_read(node_of(fdtv), addr, data, len); | ||
99 | } | ||
100 | |||
101 | static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len) | ||
102 | { | ||
103 | return hpsb_node_write(node_of(fdtv), addr, data, len); | ||
104 | } | ||
105 | |||
106 | #define FDTV_ISO_BUFFER_PACKETS 256 | ||
107 | #define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200) | ||
108 | |||
109 | static int start_iso(struct firedtv *fdtv) | ||
110 | { | ||
111 | struct hpsb_iso *iso_handle; | ||
112 | int ret; | ||
113 | |||
114 | iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host, | ||
115 | FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS, | ||
116 | fdtv->isochannel, HPSB_ISO_DMA_DEFAULT, | ||
117 | -1, /* stat.config.irq_interval */ | ||
118 | rawiso_activity_cb); | ||
119 | if (iso_handle == NULL) { | ||
120 | dev_err(fdtv->device, "cannot initialize iso receive\n"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | fdtv->backend_data = iso_handle; | ||
124 | |||
125 | ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0); | ||
126 | if (ret != 0) { | ||
127 | dev_err(fdtv->device, "cannot start iso receive\n"); | ||
128 | hpsb_iso_shutdown(iso_handle); | ||
129 | fdtv->backend_data = NULL; | ||
130 | } | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static void stop_iso(struct firedtv *fdtv) | ||
135 | { | ||
136 | struct hpsb_iso *iso_handle = fdtv->backend_data; | ||
137 | |||
138 | if (iso_handle != NULL) { | ||
139 | hpsb_iso_stop(iso_handle); | ||
140 | hpsb_iso_shutdown(iso_handle); | ||
141 | } | ||
142 | fdtv->backend_data = NULL; | ||
143 | } | ||
144 | |||
145 | static const struct firedtv_backend fdtv_1394_backend = { | ||
146 | .lock = node_lock, | ||
147 | .read = node_read, | ||
148 | .write = node_write, | ||
149 | .start_iso = start_iso, | ||
150 | .stop_iso = stop_iso, | ||
151 | }; | ||
152 | |||
153 | static void fcp_request(struct hpsb_host *host, int nodeid, int direction, | ||
154 | int cts, u8 *data, size_t length) | ||
155 | { | ||
156 | struct firedtv *f, *fdtv = NULL; | ||
157 | unsigned long flags; | ||
158 | int su; | ||
159 | |||
160 | if (length == 0 || (data[0] & 0xf0) != 0) | ||
161 | return; | ||
162 | |||
163 | su = data[1] & 0x7; | ||
164 | |||
165 | spin_lock_irqsave(&node_list_lock, flags); | ||
166 | list_for_each_entry(f, &node_list, list) | ||
167 | if (node_of(f)->host == host && | ||
168 | node_of(f)->nodeid == nodeid && | ||
169 | (f->subunit == su || (f->subunit == 0 && su == 0x7))) { | ||
170 | fdtv = f; | ||
171 | break; | ||
172 | } | ||
173 | spin_unlock_irqrestore(&node_list_lock, flags); | ||
174 | |||
175 | if (fdtv) | ||
176 | avc_recv(fdtv, data, length); | ||
177 | } | ||
178 | |||
179 | static int node_probe(struct device *dev) | ||
180 | { | ||
181 | struct unit_directory *ud = | ||
182 | container_of(dev, struct unit_directory, device); | ||
183 | struct firedtv *fdtv; | ||
184 | int kv_len, err; | ||
185 | void *kv_str; | ||
186 | |||
187 | kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); | ||
188 | kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); | ||
189 | |||
190 | fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); | ||
191 | if (!fdtv) | ||
192 | return -ENOMEM; | ||
193 | |||
194 | /* | ||
195 | * Work around a bug in udev's path_id script: Use the fw-host's dev | ||
196 | * instead of the unit directory's dev as parent of the input device. | ||
197 | */ | ||
198 | err = fdtv_register_rc(fdtv, dev->parent->parent); | ||
199 | if (err) | ||
200 | goto fail_free; | ||
201 | |||
202 | spin_lock_irq(&node_list_lock); | ||
203 | list_add_tail(&fdtv->list, &node_list); | ||
204 | spin_unlock_irq(&node_list_lock); | ||
205 | |||
206 | err = avc_identify_subunit(fdtv); | ||
207 | if (err) | ||
208 | goto fail; | ||
209 | |||
210 | err = fdtv_dvb_register(fdtv); | ||
211 | if (err) | ||
212 | goto fail; | ||
213 | |||
214 | avc_register_remote_control(fdtv); | ||
215 | return 0; | ||
216 | fail: | ||
217 | spin_lock_irq(&node_list_lock); | ||
218 | list_del(&fdtv->list); | ||
219 | spin_unlock_irq(&node_list_lock); | ||
220 | fdtv_unregister_rc(fdtv); | ||
221 | fail_free: | ||
222 | kfree(fdtv); | ||
223 | return err; | ||
224 | } | ||
225 | |||
226 | static int node_remove(struct device *dev) | ||
227 | { | ||
228 | struct firedtv *fdtv = dev->driver_data; | ||
229 | |||
230 | fdtv_dvb_unregister(fdtv); | ||
231 | |||
232 | spin_lock_irq(&node_list_lock); | ||
233 | list_del(&fdtv->list); | ||
234 | spin_unlock_irq(&node_list_lock); | ||
235 | |||
236 | cancel_work_sync(&fdtv->remote_ctrl_work); | ||
237 | fdtv_unregister_rc(fdtv); | ||
238 | |||
239 | kfree(fdtv); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int node_update(struct unit_directory *ud) | ||
244 | { | ||
245 | struct firedtv *fdtv = ud->device.driver_data; | ||
246 | |||
247 | if (fdtv->isochannel >= 0) | ||
248 | cmp_establish_pp_connection(fdtv, fdtv->subunit, | ||
249 | fdtv->isochannel); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static struct hpsb_protocol_driver fdtv_driver = { | ||
254 | .name = "firedtv", | ||
255 | .update = node_update, | ||
256 | .driver = { | ||
257 | .probe = node_probe, | ||
258 | .remove = node_remove, | ||
259 | }, | ||
260 | }; | ||
261 | |||
262 | static struct hpsb_highlevel fdtv_highlevel = { | ||
263 | .name = "firedtv", | ||
264 | .fcp_request = fcp_request, | ||
265 | }; | ||
266 | |||
267 | int __init fdtv_1394_init(struct ieee1394_device_id id_table[]) | ||
268 | { | ||
269 | int ret; | ||
270 | |||
271 | hpsb_register_highlevel(&fdtv_highlevel); | ||
272 | fdtv_driver.id_table = id_table; | ||
273 | ret = hpsb_register_protocol(&fdtv_driver); | ||
274 | if (ret) { | ||
275 | printk(KERN_ERR "firedtv: failed to register protocol\n"); | ||
276 | hpsb_unregister_highlevel(&fdtv_highlevel); | ||
277 | } | ||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | void __exit fdtv_1394_exit(void) | ||
282 | { | ||
283 | hpsb_unregister_protocol(&fdtv_driver); | ||
284 | hpsb_unregister_highlevel(&fdtv_highlevel); | ||
285 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c new file mode 100644 index 000000000000..b55d9ccaf33e --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-avc.c | |||
@@ -0,0 +1,1315 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Ben Backx <ben@bbackx.com> | ||
6 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of | ||
11 | * the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/bug.h> | ||
15 | #include <linux/crc32.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/jiffies.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/mutex.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/stringify.h> | ||
24 | #include <linux/wait.h> | ||
25 | #include <linux/workqueue.h> | ||
26 | |||
27 | #include "firedtv.h" | ||
28 | |||
29 | #define FCP_COMMAND_REGISTER 0xfffff0000b00ULL | ||
30 | |||
31 | #define AVC_CTYPE_CONTROL 0x0 | ||
32 | #define AVC_CTYPE_STATUS 0x1 | ||
33 | #define AVC_CTYPE_NOTIFY 0x3 | ||
34 | |||
35 | #define AVC_RESPONSE_ACCEPTED 0x9 | ||
36 | #define AVC_RESPONSE_STABLE 0xc | ||
37 | #define AVC_RESPONSE_CHANGED 0xd | ||
38 | #define AVC_RESPONSE_INTERIM 0xf | ||
39 | |||
40 | #define AVC_SUBUNIT_TYPE_TUNER (0x05 << 3) | ||
41 | #define AVC_SUBUNIT_TYPE_UNIT (0x1f << 3) | ||
42 | |||
43 | #define AVC_OPCODE_VENDOR 0x00 | ||
44 | #define AVC_OPCODE_READ_DESCRIPTOR 0x09 | ||
45 | #define AVC_OPCODE_DSIT 0xc8 | ||
46 | #define AVC_OPCODE_DSD 0xcb | ||
47 | |||
48 | #define DESCRIPTOR_TUNER_STATUS 0x80 | ||
49 | #define DESCRIPTOR_SUBUNIT_IDENTIFIER 0x00 | ||
50 | |||
51 | #define SFE_VENDOR_DE_COMPANYID_0 0x00 /* OUI of Digital Everywhere */ | ||
52 | #define SFE_VENDOR_DE_COMPANYID_1 0x12 | ||
53 | #define SFE_VENDOR_DE_COMPANYID_2 0x87 | ||
54 | |||
55 | #define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a | ||
56 | #define SFE_VENDOR_OPCODE_LNB_CONTROL 0x52 | ||
57 | #define SFE_VENDOR_OPCODE_TUNE_QPSK 0x58 /* for DVB-S */ | ||
58 | |||
59 | #define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION 0x00 | ||
60 | #define SFE_VENDOR_OPCODE_HOST2CA 0x56 | ||
61 | #define SFE_VENDOR_OPCODE_CA2HOST 0x57 | ||
62 | #define SFE_VENDOR_OPCODE_CISTATUS 0x59 | ||
63 | #define SFE_VENDOR_OPCODE_TUNE_QPSK2 0x60 /* for DVB-S2 */ | ||
64 | |||
65 | #define SFE_VENDOR_TAG_CA_RESET 0x00 | ||
66 | #define SFE_VENDOR_TAG_CA_APPLICATION_INFO 0x01 | ||
67 | #define SFE_VENDOR_TAG_CA_PMT 0x02 | ||
68 | #define SFE_VENDOR_TAG_CA_DATE_TIME 0x04 | ||
69 | #define SFE_VENDOR_TAG_CA_MMI 0x05 | ||
70 | #define SFE_VENDOR_TAG_CA_ENTER_MENU 0x07 | ||
71 | |||
72 | #define EN50221_LIST_MANAGEMENT_ONLY 0x03 | ||
73 | #define EN50221_TAG_APP_INFO 0x9f8021 | ||
74 | #define EN50221_TAG_CA_INFO 0x9f8031 | ||
75 | |||
76 | struct avc_command_frame { | ||
77 | int length; | ||
78 | u8 ctype; | ||
79 | u8 subunit; | ||
80 | u8 opcode; | ||
81 | u8 operand[509]; | ||
82 | }; | ||
83 | |||
84 | struct avc_response_frame { | ||
85 | int length; | ||
86 | u8 response; | ||
87 | u8 subunit; | ||
88 | u8 opcode; | ||
89 | u8 operand[509]; | ||
90 | }; | ||
91 | |||
92 | #define AVC_DEBUG_FCP_SUBACTIONS 1 | ||
93 | #define AVC_DEBUG_FCP_PAYLOADS 2 | ||
94 | |||
95 | static int avc_debug; | ||
96 | module_param_named(debug, avc_debug, int, 0644); | ||
97 | MODULE_PARM_DESC(debug, "Verbose logging (default = 0" | ||
98 | ", FCP subactions = " __stringify(AVC_DEBUG_FCP_SUBACTIONS) | ||
99 | ", FCP payloads = " __stringify(AVC_DEBUG_FCP_PAYLOADS) | ||
100 | ", or all = -1)"); | ||
101 | |||
102 | static const char *debug_fcp_ctype(unsigned int ctype) | ||
103 | { | ||
104 | static const char *ctypes[] = { | ||
105 | [0x0] = "CONTROL", [0x1] = "STATUS", | ||
106 | [0x2] = "SPECIFIC INQUIRY", [0x3] = "NOTIFY", | ||
107 | [0x4] = "GENERAL INQUIRY", [0x8] = "NOT IMPLEMENTED", | ||
108 | [0x9] = "ACCEPTED", [0xa] = "REJECTED", | ||
109 | [0xb] = "IN TRANSITION", [0xc] = "IMPLEMENTED/STABLE", | ||
110 | [0xd] = "CHANGED", [0xf] = "INTERIM", | ||
111 | }; | ||
112 | const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL; | ||
113 | |||
114 | return ret ? ret : "?"; | ||
115 | } | ||
116 | |||
117 | static const char *debug_fcp_opcode(unsigned int opcode, | ||
118 | const u8 *data, size_t length) | ||
119 | { | ||
120 | switch (opcode) { | ||
121 | case AVC_OPCODE_VENDOR: break; | ||
122 | case AVC_OPCODE_READ_DESCRIPTOR: return "ReadDescriptor"; | ||
123 | case AVC_OPCODE_DSIT: return "DirectSelectInfo.Type"; | ||
124 | case AVC_OPCODE_DSD: return "DirectSelectData"; | ||
125 | default: return "?"; | ||
126 | } | ||
127 | |||
128 | if (length < 7 || | ||
129 | data[3] != SFE_VENDOR_DE_COMPANYID_0 || | ||
130 | data[4] != SFE_VENDOR_DE_COMPANYID_1 || | ||
131 | data[5] != SFE_VENDOR_DE_COMPANYID_2) | ||
132 | return "Vendor"; | ||
133 | |||
134 | switch (data[6]) { | ||
135 | case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC"; | ||
136 | case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl"; | ||
137 | case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK"; | ||
138 | case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA"; | ||
139 | case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host"; | ||
140 | } | ||
141 | return "Vendor"; | ||
142 | } | ||
143 | |||
144 | static void debug_fcp(const u8 *data, size_t length) | ||
145 | { | ||
146 | unsigned int subunit_type, subunit_id, op; | ||
147 | const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> "; | ||
148 | |||
149 | if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) { | ||
150 | subunit_type = data[1] >> 3; | ||
151 | subunit_id = data[1] & 7; | ||
152 | op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; | ||
153 | printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", | ||
154 | prefix, subunit_type, subunit_id, length, | ||
155 | debug_fcp_ctype(data[0]), | ||
156 | debug_fcp_opcode(op, data, length)); | ||
157 | } | ||
158 | |||
159 | if (avc_debug & AVC_DEBUG_FCP_PAYLOADS) | ||
160 | print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1, | ||
161 | data, length, false); | ||
162 | } | ||
163 | |||
164 | static int __avc_write(struct firedtv *fdtv, | ||
165 | const struct avc_command_frame *c, struct avc_response_frame *r) | ||
166 | { | ||
167 | int err, retry; | ||
168 | |||
169 | if (r) | ||
170 | fdtv->avc_reply_received = false; | ||
171 | |||
172 | for (retry = 0; retry < 6; retry++) { | ||
173 | if (unlikely(avc_debug)) | ||
174 | debug_fcp(&c->ctype, c->length); | ||
175 | |||
176 | err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER, | ||
177 | (void *)&c->ctype, c->length); | ||
178 | if (err) { | ||
179 | fdtv->avc_reply_received = true; | ||
180 | dev_err(fdtv->device, "FCP command write failed\n"); | ||
181 | return err; | ||
182 | } | ||
183 | |||
184 | if (!r) | ||
185 | return 0; | ||
186 | |||
187 | /* | ||
188 | * AV/C specs say that answers should be sent within 150 ms. | ||
189 | * Time out after 200 ms. | ||
190 | */ | ||
191 | if (wait_event_timeout(fdtv->avc_wait, | ||
192 | fdtv->avc_reply_received, | ||
193 | msecs_to_jiffies(200)) != 0) { | ||
194 | r->length = fdtv->response_length; | ||
195 | memcpy(&r->response, fdtv->response, r->length); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | } | ||
200 | dev_err(fdtv->device, "FCP response timed out\n"); | ||
201 | return -ETIMEDOUT; | ||
202 | } | ||
203 | |||
204 | static int avc_write(struct firedtv *fdtv, | ||
205 | const struct avc_command_frame *c, struct avc_response_frame *r) | ||
206 | { | ||
207 | int ret; | ||
208 | |||
209 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
210 | return -EINTR; | ||
211 | |||
212 | ret = __avc_write(fdtv, c, r); | ||
213 | |||
214 | mutex_unlock(&fdtv->avc_mutex); | ||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | int avc_recv(struct firedtv *fdtv, void *data, size_t length) | ||
219 | { | ||
220 | struct avc_response_frame *r = | ||
221 | data - offsetof(struct avc_response_frame, response); | ||
222 | |||
223 | if (unlikely(avc_debug)) | ||
224 | debug_fcp(data, length); | ||
225 | |||
226 | if (length >= 8 && | ||
227 | r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 && | ||
228 | r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 && | ||
229 | r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && | ||
230 | r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) { | ||
231 | if (r->response == AVC_RESPONSE_CHANGED) { | ||
232 | fdtv_handle_rc(fdtv, | ||
233 | r->operand[4] << 8 | r->operand[5]); | ||
234 | schedule_work(&fdtv->remote_ctrl_work); | ||
235 | } else if (r->response != AVC_RESPONSE_INTERIM) { | ||
236 | dev_info(fdtv->device, | ||
237 | "remote control result = %d\n", r->response); | ||
238 | } | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | if (fdtv->avc_reply_received) { | ||
243 | dev_err(fdtv->device, "out-of-order AVC response, ignored\n"); | ||
244 | return -EIO; | ||
245 | } | ||
246 | |||
247 | memcpy(fdtv->response, data, length); | ||
248 | fdtv->response_length = length; | ||
249 | |||
250 | fdtv->avc_reply_received = true; | ||
251 | wake_up(&fdtv->avc_wait); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * tuning command for setting the relative LNB frequency | ||
258 | * (not supported by the AVC standard) | ||
259 | */ | ||
260 | static void avc_tuner_tuneqpsk(struct firedtv *fdtv, | ||
261 | struct dvb_frontend_parameters *params, | ||
262 | struct avc_command_frame *c) | ||
263 | { | ||
264 | c->opcode = AVC_OPCODE_VENDOR; | ||
265 | |||
266 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
267 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
268 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
269 | c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; | ||
270 | |||
271 | c->operand[4] = (params->frequency >> 24) & 0xff; | ||
272 | c->operand[5] = (params->frequency >> 16) & 0xff; | ||
273 | c->operand[6] = (params->frequency >> 8) & 0xff; | ||
274 | c->operand[7] = params->frequency & 0xff; | ||
275 | |||
276 | c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff; | ||
277 | c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff; | ||
278 | |||
279 | switch (params->u.qpsk.fec_inner) { | ||
280 | case FEC_1_2: c->operand[10] = 0x1; break; | ||
281 | case FEC_2_3: c->operand[10] = 0x2; break; | ||
282 | case FEC_3_4: c->operand[10] = 0x3; break; | ||
283 | case FEC_5_6: c->operand[10] = 0x4; break; | ||
284 | case FEC_7_8: c->operand[10] = 0x5; break; | ||
285 | case FEC_4_5: | ||
286 | case FEC_8_9: | ||
287 | case FEC_AUTO: | ||
288 | default: c->operand[10] = 0x0; | ||
289 | } | ||
290 | |||
291 | if (fdtv->voltage == 0xff) | ||
292 | c->operand[11] = 0xff; | ||
293 | else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */ | ||
294 | c->operand[11] = 0; | ||
295 | else | ||
296 | c->operand[11] = 1; | ||
297 | |||
298 | if (fdtv->tone == 0xff) | ||
299 | c->operand[12] = 0xff; | ||
300 | else if (fdtv->tone == SEC_TONE_ON) /* band */ | ||
301 | c->operand[12] = 1; | ||
302 | else | ||
303 | c->operand[12] = 0; | ||
304 | |||
305 | if (fdtv->type == FIREDTV_DVB_S2) { | ||
306 | c->operand[13] = 0x1; | ||
307 | c->operand[14] = 0xff; | ||
308 | c->operand[15] = 0xff; | ||
309 | c->length = 20; | ||
310 | } else { | ||
311 | c->length = 16; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, | ||
316 | struct avc_command_frame *c) | ||
317 | { | ||
318 | c->opcode = AVC_OPCODE_DSD; | ||
319 | |||
320 | c->operand[0] = 0; /* source plug */ | ||
321 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
322 | c->operand[2] = 0x20; /* system id = DVB */ | ||
323 | c->operand[3] = 0x00; /* antenna number */ | ||
324 | c->operand[4] = 0x11; /* system_specific_multiplex selection_length */ | ||
325 | |||
326 | /* multiplex_valid_flags, high byte */ | ||
327 | c->operand[5] = 0 << 7 /* reserved */ | ||
328 | | 0 << 6 /* Polarisation */ | ||
329 | | 0 << 5 /* Orbital_Pos */ | ||
330 | | 1 << 4 /* Frequency */ | ||
331 | | 1 << 3 /* Symbol_Rate */ | ||
332 | | 0 << 2 /* FEC_outer */ | ||
333 | | (params->u.qam.fec_inner != FEC_AUTO ? 1 << 1 : 0) | ||
334 | | (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0); | ||
335 | |||
336 | /* multiplex_valid_flags, low byte */ | ||
337 | c->operand[6] = 0 << 7 /* NetworkID */ | ||
338 | | 0 << 0 /* reserved */ ; | ||
339 | |||
340 | c->operand[7] = 0x00; | ||
341 | c->operand[8] = 0x00; | ||
342 | c->operand[9] = 0x00; | ||
343 | c->operand[10] = 0x00; | ||
344 | |||
345 | c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6); | ||
346 | c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff; | ||
347 | c->operand[13] = (params->frequency / 4000) & 0xff; | ||
348 | c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff; | ||
349 | c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff; | ||
350 | c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0; | ||
351 | c->operand[17] = 0x00; | ||
352 | |||
353 | switch (params->u.qpsk.fec_inner) { | ||
354 | case FEC_1_2: c->operand[18] = 0x1; break; | ||
355 | case FEC_2_3: c->operand[18] = 0x2; break; | ||
356 | case FEC_3_4: c->operand[18] = 0x3; break; | ||
357 | case FEC_5_6: c->operand[18] = 0x4; break; | ||
358 | case FEC_7_8: c->operand[18] = 0x5; break; | ||
359 | case FEC_8_9: c->operand[18] = 0x6; break; | ||
360 | case FEC_4_5: c->operand[18] = 0x8; break; | ||
361 | case FEC_AUTO: | ||
362 | default: c->operand[18] = 0x0; | ||
363 | } | ||
364 | |||
365 | switch (params->u.qam.modulation) { | ||
366 | case QAM_16: c->operand[19] = 0x08; break; | ||
367 | case QAM_32: c->operand[19] = 0x10; break; | ||
368 | case QAM_64: c->operand[19] = 0x18; break; | ||
369 | case QAM_128: c->operand[19] = 0x20; break; | ||
370 | case QAM_256: c->operand[19] = 0x28; break; | ||
371 | case QAM_AUTO: | ||
372 | default: c->operand[19] = 0x00; | ||
373 | } | ||
374 | |||
375 | c->operand[20] = 0x00; | ||
376 | c->operand[21] = 0x00; | ||
377 | /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ | ||
378 | c->operand[22] = 0x00; | ||
379 | |||
380 | c->length = 28; | ||
381 | } | ||
382 | |||
383 | static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, | ||
384 | struct avc_command_frame *c) | ||
385 | { | ||
386 | struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm; | ||
387 | |||
388 | c->opcode = AVC_OPCODE_DSD; | ||
389 | |||
390 | c->operand[0] = 0; /* source plug */ | ||
391 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
392 | c->operand[2] = 0x20; /* system id = DVB */ | ||
393 | c->operand[3] = 0x00; /* antenna number */ | ||
394 | c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */ | ||
395 | |||
396 | /* multiplex_valid_flags, high byte */ | ||
397 | c->operand[5] = | ||
398 | 0 << 7 /* reserved */ | ||
399 | | 1 << 6 /* CenterFrequency */ | ||
400 | | (ofdm->bandwidth != BANDWIDTH_AUTO ? 1 << 5 : 0) | ||
401 | | (ofdm->constellation != QAM_AUTO ? 1 << 4 : 0) | ||
402 | | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0) | ||
403 | | (ofdm->code_rate_HP != FEC_AUTO ? 1 << 2 : 0) | ||
404 | | (ofdm->code_rate_LP != FEC_AUTO ? 1 << 1 : 0) | ||
405 | | (ofdm->guard_interval != GUARD_INTERVAL_AUTO ? 1 << 0 : 0); | ||
406 | |||
407 | /* multiplex_valid_flags, low byte */ | ||
408 | c->operand[6] = | ||
409 | 0 << 7 /* NetworkID */ | ||
410 | | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0) | ||
411 | | 0 << 5 /* OtherFrequencyFlag */ | ||
412 | | 0 << 0 /* reserved */ ; | ||
413 | |||
414 | c->operand[7] = 0x0; | ||
415 | c->operand[8] = (params->frequency / 10) >> 24; | ||
416 | c->operand[9] = ((params->frequency / 10) >> 16) & 0xff; | ||
417 | c->operand[10] = ((params->frequency / 10) >> 8) & 0xff; | ||
418 | c->operand[11] = (params->frequency / 10) & 0xff; | ||
419 | |||
420 | switch (ofdm->bandwidth) { | ||
421 | case BANDWIDTH_7_MHZ: c->operand[12] = 0x20; break; | ||
422 | case BANDWIDTH_8_MHZ: | ||
423 | case BANDWIDTH_6_MHZ: /* not defined by AVC spec */ | ||
424 | case BANDWIDTH_AUTO: | ||
425 | default: c->operand[12] = 0x00; | ||
426 | } | ||
427 | |||
428 | switch (ofdm->constellation) { | ||
429 | case QAM_16: c->operand[13] = 1 << 6; break; | ||
430 | case QAM_64: c->operand[13] = 2 << 6; break; | ||
431 | case QPSK: | ||
432 | default: c->operand[13] = 0x00; | ||
433 | } | ||
434 | |||
435 | switch (ofdm->hierarchy_information) { | ||
436 | case HIERARCHY_1: c->operand[13] |= 1 << 3; break; | ||
437 | case HIERARCHY_2: c->operand[13] |= 2 << 3; break; | ||
438 | case HIERARCHY_4: c->operand[13] |= 3 << 3; break; | ||
439 | case HIERARCHY_AUTO: | ||
440 | case HIERARCHY_NONE: | ||
441 | default: break; | ||
442 | } | ||
443 | |||
444 | switch (ofdm->code_rate_HP) { | ||
445 | case FEC_2_3: c->operand[13] |= 1; break; | ||
446 | case FEC_3_4: c->operand[13] |= 2; break; | ||
447 | case FEC_5_6: c->operand[13] |= 3; break; | ||
448 | case FEC_7_8: c->operand[13] |= 4; break; | ||
449 | case FEC_1_2: | ||
450 | default: break; | ||
451 | } | ||
452 | |||
453 | switch (ofdm->code_rate_LP) { | ||
454 | case FEC_2_3: c->operand[14] = 1 << 5; break; | ||
455 | case FEC_3_4: c->operand[14] = 2 << 5; break; | ||
456 | case FEC_5_6: c->operand[14] = 3 << 5; break; | ||
457 | case FEC_7_8: c->operand[14] = 4 << 5; break; | ||
458 | case FEC_1_2: | ||
459 | default: c->operand[14] = 0x00; break; | ||
460 | } | ||
461 | |||
462 | switch (ofdm->guard_interval) { | ||
463 | case GUARD_INTERVAL_1_16: c->operand[14] |= 1 << 3; break; | ||
464 | case GUARD_INTERVAL_1_8: c->operand[14] |= 2 << 3; break; | ||
465 | case GUARD_INTERVAL_1_4: c->operand[14] |= 3 << 3; break; | ||
466 | case GUARD_INTERVAL_1_32: | ||
467 | case GUARD_INTERVAL_AUTO: | ||
468 | default: break; | ||
469 | } | ||
470 | |||
471 | switch (ofdm->transmission_mode) { | ||
472 | case TRANSMISSION_MODE_8K: c->operand[14] |= 1 << 1; break; | ||
473 | case TRANSMISSION_MODE_2K: | ||
474 | case TRANSMISSION_MODE_AUTO: | ||
475 | default: break; | ||
476 | } | ||
477 | |||
478 | c->operand[15] = 0x00; /* network_ID[0] */ | ||
479 | c->operand[16] = 0x00; /* network_ID[1] */ | ||
480 | /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ | ||
481 | c->operand[17] = 0x00; | ||
482 | |||
483 | c->length = 24; | ||
484 | } | ||
485 | |||
486 | int avc_tuner_dsd(struct firedtv *fdtv, | ||
487 | struct dvb_frontend_parameters *params) | ||
488 | { | ||
489 | char buffer[sizeof(struct avc_command_frame)]; | ||
490 | struct avc_command_frame *c = (void *)buffer; | ||
491 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
492 | |||
493 | memset(c, 0, sizeof(*c)); | ||
494 | |||
495 | c->ctype = AVC_CTYPE_CONTROL; | ||
496 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
497 | |||
498 | switch (fdtv->type) { | ||
499 | case FIREDTV_DVB_S: | ||
500 | case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break; | ||
501 | case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break; | ||
502 | case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break; | ||
503 | default: | ||
504 | BUG(); | ||
505 | } | ||
506 | |||
507 | if (avc_write(fdtv, c, r) < 0) | ||
508 | return -EIO; | ||
509 | |||
510 | msleep(500); | ||
511 | #if 0 | ||
512 | /* FIXME: */ | ||
513 | /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ | ||
514 | if (status) | ||
515 | *status = r->operand[2]; | ||
516 | #endif | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]) | ||
521 | { | ||
522 | char buffer[sizeof(struct avc_command_frame)]; | ||
523 | struct avc_command_frame *c = (void *)buffer; | ||
524 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
525 | int pos, k; | ||
526 | |||
527 | if (pidc > 16 && pidc != 0xff) | ||
528 | return -EINVAL; | ||
529 | |||
530 | memset(c, 0, sizeof(*c)); | ||
531 | |||
532 | c->ctype = AVC_CTYPE_CONTROL; | ||
533 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
534 | c->opcode = AVC_OPCODE_DSD; | ||
535 | |||
536 | c->operand[0] = 0; /* source plug */ | ||
537 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
538 | c->operand[2] = 0x20; /* system id = DVB */ | ||
539 | c->operand[3] = 0x00; /* antenna number */ | ||
540 | c->operand[4] = 0x00; /* system_specific_multiplex selection_length */ | ||
541 | c->operand[5] = pidc; /* Nr_of_dsd_sel_specs */ | ||
542 | |||
543 | pos = 6; | ||
544 | if (pidc != 0xff) | ||
545 | for (k = 0; k < pidc; k++) { | ||
546 | c->operand[pos++] = 0x13; /* flowfunction relay */ | ||
547 | c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */ | ||
548 | c->operand[pos++] = (pid[k] >> 8) & 0x1f; | ||
549 | c->operand[pos++] = pid[k] & 0xff; | ||
550 | c->operand[pos++] = 0x00; /* tableID */ | ||
551 | c->operand[pos++] = 0x00; /* filter_length */ | ||
552 | } | ||
553 | |||
554 | c->length = ALIGN(3 + pos, 4); | ||
555 | |||
556 | if (avc_write(fdtv, c, r) < 0) | ||
557 | return -EIO; | ||
558 | |||
559 | msleep(50); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | int avc_tuner_get_ts(struct firedtv *fdtv) | ||
564 | { | ||
565 | char buffer[sizeof(struct avc_command_frame)]; | ||
566 | struct avc_command_frame *c = (void *)buffer; | ||
567 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
568 | int sl; | ||
569 | |||
570 | memset(c, 0, sizeof(*c)); | ||
571 | |||
572 | c->ctype = AVC_CTYPE_CONTROL; | ||
573 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
574 | c->opcode = AVC_OPCODE_DSIT; | ||
575 | |||
576 | sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11; | ||
577 | |||
578 | c->operand[0] = 0; /* source plug */ | ||
579 | c->operand[1] = 0xd2; /* subfunction replace */ | ||
580 | c->operand[2] = 0xff; /* status */ | ||
581 | c->operand[3] = 0x20; /* system id = DVB */ | ||
582 | c->operand[4] = 0x00; /* antenna number */ | ||
583 | c->operand[5] = 0x0; /* system_specific_search_flags */ | ||
584 | c->operand[6] = sl; /* system_specific_multiplex selection_length */ | ||
585 | c->operand[7] = 0x00; /* valid_flags [0] */ | ||
586 | c->operand[8] = 0x00; /* valid_flags [1] */ | ||
587 | c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */ | ||
588 | |||
589 | c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28; | ||
590 | |||
591 | if (avc_write(fdtv, c, r) < 0) | ||
592 | return -EIO; | ||
593 | |||
594 | msleep(250); | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | int avc_identify_subunit(struct firedtv *fdtv) | ||
599 | { | ||
600 | char buffer[sizeof(struct avc_command_frame)]; | ||
601 | struct avc_command_frame *c = (void *)buffer; | ||
602 | struct avc_response_frame *r = (void *)buffer; | ||
603 | |||
604 | memset(c, 0, sizeof(*c)); | ||
605 | |||
606 | c->ctype = AVC_CTYPE_CONTROL; | ||
607 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
608 | c->opcode = AVC_OPCODE_READ_DESCRIPTOR; | ||
609 | |||
610 | c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER; | ||
611 | c->operand[1] = 0xff; | ||
612 | c->operand[2] = 0x00; | ||
613 | c->operand[3] = 0x00; /* length highbyte */ | ||
614 | c->operand[4] = 0x08; /* length lowbyte */ | ||
615 | c->operand[5] = 0x00; /* offset highbyte */ | ||
616 | c->operand[6] = 0x0d; /* offset lowbyte */ | ||
617 | |||
618 | c->length = 12; | ||
619 | |||
620 | if (avc_write(fdtv, c, r) < 0) | ||
621 | return -EIO; | ||
622 | |||
623 | if ((r->response != AVC_RESPONSE_STABLE && | ||
624 | r->response != AVC_RESPONSE_ACCEPTED) || | ||
625 | (r->operand[3] << 8) + r->operand[4] != 8) { | ||
626 | dev_err(fdtv->device, "cannot read subunit identifier\n"); | ||
627 | return -EINVAL; | ||
628 | } | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | #define SIZEOF_ANTENNA_INPUT_INFO 22 | ||
633 | |||
634 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat) | ||
635 | { | ||
636 | char buffer[sizeof(struct avc_command_frame)]; | ||
637 | struct avc_command_frame *c = (void *)buffer; | ||
638 | struct avc_response_frame *r = (void *)buffer; | ||
639 | int length; | ||
640 | |||
641 | memset(c, 0, sizeof(*c)); | ||
642 | |||
643 | c->ctype = AVC_CTYPE_CONTROL; | ||
644 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
645 | c->opcode = AVC_OPCODE_READ_DESCRIPTOR; | ||
646 | |||
647 | c->operand[0] = DESCRIPTOR_TUNER_STATUS; | ||
648 | c->operand[1] = 0xff; /* read_result_status */ | ||
649 | c->operand[2] = 0x00; /* reserved */ | ||
650 | c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */ | ||
651 | c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */ | ||
652 | c->operand[5] = 0x00; | ||
653 | c->operand[6] = 0x00; | ||
654 | |||
655 | c->length = 12; | ||
656 | |||
657 | if (avc_write(fdtv, c, r) < 0) | ||
658 | return -EIO; | ||
659 | |||
660 | if (r->response != AVC_RESPONSE_STABLE && | ||
661 | r->response != AVC_RESPONSE_ACCEPTED) { | ||
662 | dev_err(fdtv->device, "cannot read tuner status\n"); | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | |||
666 | length = r->operand[9]; | ||
667 | if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) { | ||
668 | dev_err(fdtv->device, "got invalid tuner status\n"); | ||
669 | return -EINVAL; | ||
670 | } | ||
671 | |||
672 | stat->active_system = r->operand[10]; | ||
673 | stat->searching = r->operand[11] >> 7 & 1; | ||
674 | stat->moving = r->operand[11] >> 6 & 1; | ||
675 | stat->no_rf = r->operand[11] >> 5 & 1; | ||
676 | stat->input = r->operand[12] >> 7 & 1; | ||
677 | stat->selected_antenna = r->operand[12] & 0x7f; | ||
678 | stat->ber = r->operand[13] << 24 | | ||
679 | r->operand[14] << 16 | | ||
680 | r->operand[15] << 8 | | ||
681 | r->operand[16]; | ||
682 | stat->signal_strength = r->operand[17]; | ||
683 | stat->raster_frequency = r->operand[18] >> 6 & 2; | ||
684 | stat->rf_frequency = (r->operand[18] & 0x3f) << 16 | | ||
685 | r->operand[19] << 8 | | ||
686 | r->operand[20]; | ||
687 | stat->man_dep_info_length = r->operand[21]; | ||
688 | stat->front_end_error = r->operand[22] >> 4 & 1; | ||
689 | stat->antenna_error = r->operand[22] >> 3 & 1; | ||
690 | stat->front_end_power_status = r->operand[22] >> 1 & 1; | ||
691 | stat->power_supply = r->operand[22] & 1; | ||
692 | stat->carrier_noise_ratio = r->operand[23] << 8 | | ||
693 | r->operand[24]; | ||
694 | stat->power_supply_voltage = r->operand[27]; | ||
695 | stat->antenna_voltage = r->operand[28]; | ||
696 | stat->firewire_bus_voltage = r->operand[29]; | ||
697 | stat->ca_mmi = r->operand[30] & 1; | ||
698 | stat->ca_pmt_reply = r->operand[31] >> 7 & 1; | ||
699 | stat->ca_date_time_request = r->operand[31] >> 6 & 1; | ||
700 | stat->ca_application_info = r->operand[31] >> 5 & 1; | ||
701 | stat->ca_module_present_status = r->operand[31] >> 4 & 1; | ||
702 | stat->ca_dvb_flag = r->operand[31] >> 3 & 1; | ||
703 | stat->ca_error_flag = r->operand[31] >> 2 & 1; | ||
704 | stat->ca_initialization_status = r->operand[31] >> 1 & 1; | ||
705 | |||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | ||
710 | char conttone, char nrdiseq, | ||
711 | struct dvb_diseqc_master_cmd *diseqcmd) | ||
712 | { | ||
713 | char buffer[sizeof(struct avc_command_frame)]; | ||
714 | struct avc_command_frame *c = (void *)buffer; | ||
715 | struct avc_response_frame *r = (void *)buffer; | ||
716 | int i, j, k; | ||
717 | |||
718 | memset(c, 0, sizeof(*c)); | ||
719 | |||
720 | c->ctype = AVC_CTYPE_CONTROL; | ||
721 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
722 | c->opcode = AVC_OPCODE_VENDOR; | ||
723 | |||
724 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
725 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
726 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
727 | c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL; | ||
728 | |||
729 | c->operand[4] = voltage; | ||
730 | c->operand[5] = nrdiseq; | ||
731 | |||
732 | i = 6; | ||
733 | |||
734 | for (j = 0; j < nrdiseq; j++) { | ||
735 | c->operand[i++] = diseqcmd[j].msg_len; | ||
736 | |||
737 | for (k = 0; k < diseqcmd[j].msg_len; k++) | ||
738 | c->operand[i++] = diseqcmd[j].msg[k]; | ||
739 | } | ||
740 | |||
741 | c->operand[i++] = burst; | ||
742 | c->operand[i++] = conttone; | ||
743 | |||
744 | c->length = ALIGN(3 + i, 4); | ||
745 | |||
746 | if (avc_write(fdtv, c, r) < 0) | ||
747 | return -EIO; | ||
748 | |||
749 | if (r->response != AVC_RESPONSE_ACCEPTED) { | ||
750 | dev_err(fdtv->device, "LNB control failed\n"); | ||
751 | return -EINVAL; | ||
752 | } | ||
753 | |||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | int avc_register_remote_control(struct firedtv *fdtv) | ||
758 | { | ||
759 | char buffer[sizeof(struct avc_command_frame)]; | ||
760 | struct avc_command_frame *c = (void *)buffer; | ||
761 | |||
762 | memset(c, 0, sizeof(*c)); | ||
763 | |||
764 | c->ctype = AVC_CTYPE_NOTIFY; | ||
765 | c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7; | ||
766 | c->opcode = AVC_OPCODE_VENDOR; | ||
767 | |||
768 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
769 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
770 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
771 | c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL; | ||
772 | |||
773 | c->length = 8; | ||
774 | |||
775 | return avc_write(fdtv, c, NULL); | ||
776 | } | ||
777 | |||
778 | void avc_remote_ctrl_work(struct work_struct *work) | ||
779 | { | ||
780 | struct firedtv *fdtv = | ||
781 | container_of(work, struct firedtv, remote_ctrl_work); | ||
782 | |||
783 | /* Should it be rescheduled in failure cases? */ | ||
784 | avc_register_remote_control(fdtv); | ||
785 | } | ||
786 | |||
787 | #if 0 /* FIXME: unused */ | ||
788 | int avc_tuner_host2ca(struct firedtv *fdtv) | ||
789 | { | ||
790 | char buffer[sizeof(struct avc_command_frame)]; | ||
791 | struct avc_command_frame *c = (void *)buffer; | ||
792 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
793 | |||
794 | memset(c, 0, sizeof(*c)); | ||
795 | |||
796 | c->ctype = AVC_CTYPE_CONTROL; | ||
797 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
798 | c->opcode = AVC_OPCODE_VENDOR; | ||
799 | |||
800 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
801 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
802 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
803 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
804 | c->operand[4] = 0; /* slot */ | ||
805 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | ||
806 | c->operand[6] = 0; /* more/last */ | ||
807 | c->operand[7] = 0; /* length */ | ||
808 | |||
809 | c->length = 12; | ||
810 | |||
811 | if (avc_write(fdtv, c, r) < 0) | ||
812 | return -EIO; | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | #endif | ||
817 | |||
818 | static int get_ca_object_pos(struct avc_response_frame *r) | ||
819 | { | ||
820 | int length = 1; | ||
821 | |||
822 | /* Check length of length field */ | ||
823 | if (r->operand[7] & 0x80) | ||
824 | length = (r->operand[7] & 0x7f) + 1; | ||
825 | return length + 7; | ||
826 | } | ||
827 | |||
828 | static int get_ca_object_length(struct avc_response_frame *r) | ||
829 | { | ||
830 | #if 0 /* FIXME: unused */ | ||
831 | int size = 0; | ||
832 | int i; | ||
833 | |||
834 | if (r->operand[7] & 0x80) | ||
835 | for (i = 0; i < (r->operand[7] & 0x7f); i++) { | ||
836 | size <<= 8; | ||
837 | size += r->operand[8 + i]; | ||
838 | } | ||
839 | #endif | ||
840 | return r->operand[7]; | ||
841 | } | ||
842 | |||
843 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | ||
844 | { | ||
845 | char buffer[sizeof(struct avc_command_frame)]; | ||
846 | struct avc_command_frame *c = (void *)buffer; | ||
847 | struct avc_response_frame *r = (void *)buffer; | ||
848 | int pos; | ||
849 | |||
850 | memset(c, 0, sizeof(*c)); | ||
851 | |||
852 | c->ctype = AVC_CTYPE_STATUS; | ||
853 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
854 | c->opcode = AVC_OPCODE_VENDOR; | ||
855 | |||
856 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
857 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
858 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
859 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
860 | c->operand[4] = 0; /* slot */ | ||
861 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | ||
862 | |||
863 | c->length = 12; | ||
864 | |||
865 | if (avc_write(fdtv, c, r) < 0) | ||
866 | return -EIO; | ||
867 | |||
868 | /* FIXME: check response code and validate response data */ | ||
869 | |||
870 | pos = get_ca_object_pos(r); | ||
871 | app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff; | ||
872 | app_info[1] = (EN50221_TAG_APP_INFO >> 8) & 0xff; | ||
873 | app_info[2] = (EN50221_TAG_APP_INFO >> 0) & 0xff; | ||
874 | app_info[3] = 6 + r->operand[pos + 4]; | ||
875 | app_info[4] = 0x01; | ||
876 | memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]); | ||
877 | *len = app_info[3] + 4; | ||
878 | |||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len) | ||
883 | { | ||
884 | char buffer[sizeof(struct avc_command_frame)]; | ||
885 | struct avc_command_frame *c = (void *)buffer; | ||
886 | struct avc_response_frame *r = (void *)buffer; | ||
887 | int pos; | ||
888 | |||
889 | memset(c, 0, sizeof(*c)); | ||
890 | |||
891 | c->ctype = AVC_CTYPE_STATUS; | ||
892 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
893 | c->opcode = AVC_OPCODE_VENDOR; | ||
894 | |||
895 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
896 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
897 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
898 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
899 | c->operand[4] = 0; /* slot */ | ||
900 | c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */ | ||
901 | |||
902 | c->length = 12; | ||
903 | |||
904 | if (avc_write(fdtv, c, r) < 0) | ||
905 | return -EIO; | ||
906 | |||
907 | pos = get_ca_object_pos(r); | ||
908 | app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff; | ||
909 | app_info[1] = (EN50221_TAG_CA_INFO >> 8) & 0xff; | ||
910 | app_info[2] = (EN50221_TAG_CA_INFO >> 0) & 0xff; | ||
911 | app_info[3] = 2; | ||
912 | app_info[4] = r->operand[pos + 0]; | ||
913 | app_info[5] = r->operand[pos + 1]; | ||
914 | *len = app_info[3] + 4; | ||
915 | |||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | int avc_ca_reset(struct firedtv *fdtv) | ||
920 | { | ||
921 | char buffer[sizeof(struct avc_command_frame)]; | ||
922 | struct avc_command_frame *c = (void *)buffer; | ||
923 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
924 | |||
925 | memset(c, 0, sizeof(*c)); | ||
926 | |||
927 | c->ctype = AVC_CTYPE_CONTROL; | ||
928 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
929 | c->opcode = AVC_OPCODE_VENDOR; | ||
930 | |||
931 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
932 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
933 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
934 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
935 | c->operand[4] = 0; /* slot */ | ||
936 | c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */ | ||
937 | c->operand[6] = 0; /* more/last */ | ||
938 | c->operand[7] = 1; /* length */ | ||
939 | c->operand[8] = 0; /* force hardware reset */ | ||
940 | |||
941 | c->length = 12; | ||
942 | |||
943 | if (avc_write(fdtv, c, r) < 0) | ||
944 | return -EIO; | ||
945 | |||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) | ||
950 | { | ||
951 | char buffer[sizeof(struct avc_command_frame)]; | ||
952 | struct avc_command_frame *c = (void *)buffer; | ||
953 | struct avc_response_frame *r = (void *)buffer; | ||
954 | int list_management; | ||
955 | int program_info_length; | ||
956 | int pmt_cmd_id; | ||
957 | int read_pos; | ||
958 | int write_pos; | ||
959 | int es_info_length; | ||
960 | int crc32_csum; | ||
961 | |||
962 | memset(c, 0, sizeof(*c)); | ||
963 | |||
964 | c->ctype = AVC_CTYPE_CONTROL; | ||
965 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
966 | c->opcode = AVC_OPCODE_VENDOR; | ||
967 | |||
968 | if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) { | ||
969 | dev_info(fdtv->device, "forcing list_management to ONLY\n"); | ||
970 | msg[0] = EN50221_LIST_MANAGEMENT_ONLY; | ||
971 | } | ||
972 | /* We take the cmd_id from the programme level only! */ | ||
973 | list_management = msg[0]; | ||
974 | program_info_length = ((msg[4] & 0x0f) << 8) + msg[5]; | ||
975 | if (program_info_length > 0) | ||
976 | program_info_length--; /* Remove pmt_cmd_id */ | ||
977 | pmt_cmd_id = msg[6]; | ||
978 | |||
979 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
980 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
981 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
982 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
983 | c->operand[4] = 0; /* slot */ | ||
984 | c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */ | ||
985 | c->operand[6] = 0; /* more/last */ | ||
986 | /* c->operand[7] = XXXprogram_info_length + 17; */ /* length */ | ||
987 | c->operand[8] = list_management; | ||
988 | c->operand[9] = 0x01; /* pmt_cmd=OK_descramble */ | ||
989 | |||
990 | /* TS program map table */ | ||
991 | |||
992 | c->operand[10] = 0x02; /* Table id=2 */ | ||
993 | c->operand[11] = 0x80; /* Section syntax + length */ | ||
994 | /* c->operand[12] = XXXprogram_info_length + 12; */ | ||
995 | c->operand[13] = msg[1]; /* Program number */ | ||
996 | c->operand[14] = msg[2]; | ||
997 | c->operand[15] = 0x01; /* Version number=0 + current/next=1 */ | ||
998 | c->operand[16] = 0x00; /* Section number=0 */ | ||
999 | c->operand[17] = 0x00; /* Last section number=0 */ | ||
1000 | c->operand[18] = 0x1f; /* PCR_PID=1FFF */ | ||
1001 | c->operand[19] = 0xff; | ||
1002 | c->operand[20] = (program_info_length >> 8); /* Program info length */ | ||
1003 | c->operand[21] = (program_info_length & 0xff); | ||
1004 | |||
1005 | /* CA descriptors at programme level */ | ||
1006 | read_pos = 6; | ||
1007 | write_pos = 22; | ||
1008 | if (program_info_length > 0) { | ||
1009 | pmt_cmd_id = msg[read_pos++]; | ||
1010 | if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||
1011 | dev_err(fdtv->device, | ||
1012 | "invalid pmt_cmd_id %d\n", pmt_cmd_id); | ||
1013 | |||
1014 | memcpy(&c->operand[write_pos], &msg[read_pos], | ||
1015 | program_info_length); | ||
1016 | read_pos += program_info_length; | ||
1017 | write_pos += program_info_length; | ||
1018 | } | ||
1019 | while (read_pos < length) { | ||
1020 | c->operand[write_pos++] = msg[read_pos++]; | ||
1021 | c->operand[write_pos++] = msg[read_pos++]; | ||
1022 | c->operand[write_pos++] = msg[read_pos++]; | ||
1023 | es_info_length = | ||
1024 | ((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1]; | ||
1025 | read_pos += 2; | ||
1026 | if (es_info_length > 0) | ||
1027 | es_info_length--; /* Remove pmt_cmd_id */ | ||
1028 | c->operand[write_pos++] = es_info_length >> 8; | ||
1029 | c->operand[write_pos++] = es_info_length & 0xff; | ||
1030 | if (es_info_length > 0) { | ||
1031 | pmt_cmd_id = msg[read_pos++]; | ||
1032 | if (pmt_cmd_id != 1 && pmt_cmd_id != 4) | ||
1033 | dev_err(fdtv->device, "invalid pmt_cmd_id %d " | ||
1034 | "at stream level\n", pmt_cmd_id); | ||
1035 | |||
1036 | memcpy(&c->operand[write_pos], &msg[read_pos], | ||
1037 | es_info_length); | ||
1038 | read_pos += es_info_length; | ||
1039 | write_pos += es_info_length; | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | /* CRC */ | ||
1044 | c->operand[write_pos++] = 0x00; | ||
1045 | c->operand[write_pos++] = 0x00; | ||
1046 | c->operand[write_pos++] = 0x00; | ||
1047 | c->operand[write_pos++] = 0x00; | ||
1048 | |||
1049 | c->operand[7] = write_pos - 8; | ||
1050 | c->operand[12] = write_pos - 13; | ||
1051 | |||
1052 | crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1); | ||
1053 | c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff; | ||
1054 | c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff; | ||
1055 | c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff; | ||
1056 | c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff; | ||
1057 | |||
1058 | c->length = ALIGN(3 + write_pos, 4); | ||
1059 | |||
1060 | if (avc_write(fdtv, c, r) < 0) | ||
1061 | return -EIO; | ||
1062 | |||
1063 | if (r->response != AVC_RESPONSE_ACCEPTED) { | ||
1064 | dev_err(fdtv->device, | ||
1065 | "CA PMT failed with response 0x%x\n", r->response); | ||
1066 | return -EFAULT; | ||
1067 | } | ||
1068 | |||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval) | ||
1073 | { | ||
1074 | char buffer[sizeof(struct avc_command_frame)]; | ||
1075 | struct avc_command_frame *c = (void *)buffer; | ||
1076 | struct avc_response_frame *r = (void *)buffer; | ||
1077 | |||
1078 | memset(c, 0, sizeof(*c)); | ||
1079 | |||
1080 | c->ctype = AVC_CTYPE_STATUS; | ||
1081 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
1082 | c->opcode = AVC_OPCODE_VENDOR; | ||
1083 | |||
1084 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
1085 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
1086 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
1087 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
1088 | c->operand[4] = 0; /* slot */ | ||
1089 | c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */ | ||
1090 | c->operand[6] = 0; /* more/last */ | ||
1091 | c->operand[7] = 0; /* length */ | ||
1092 | |||
1093 | c->length = 12; | ||
1094 | |||
1095 | if (avc_write(fdtv, c, r) < 0) | ||
1096 | return -EIO; | ||
1097 | |||
1098 | /* FIXME: check response code and validate response data */ | ||
1099 | |||
1100 | *interval = r->operand[get_ca_object_pos(r)]; | ||
1101 | |||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | int avc_ca_enter_menu(struct firedtv *fdtv) | ||
1106 | { | ||
1107 | char buffer[sizeof(struct avc_command_frame)]; | ||
1108 | struct avc_command_frame *c = (void *)buffer; | ||
1109 | struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */ | ||
1110 | |||
1111 | memset(c, 0, sizeof(*c)); | ||
1112 | |||
1113 | c->ctype = AVC_CTYPE_STATUS; | ||
1114 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
1115 | c->opcode = AVC_OPCODE_VENDOR; | ||
1116 | |||
1117 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
1118 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
1119 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
1120 | c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA; | ||
1121 | c->operand[4] = 0; /* slot */ | ||
1122 | c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU; | ||
1123 | c->operand[6] = 0; /* more/last */ | ||
1124 | c->operand[7] = 0; /* length */ | ||
1125 | |||
1126 | c->length = 12; | ||
1127 | |||
1128 | if (avc_write(fdtv, c, r) < 0) | ||
1129 | return -EIO; | ||
1130 | |||
1131 | return 0; | ||
1132 | } | ||
1133 | |||
1134 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len) | ||
1135 | { | ||
1136 | char buffer[sizeof(struct avc_command_frame)]; | ||
1137 | struct avc_command_frame *c = (void *)buffer; | ||
1138 | struct avc_response_frame *r = (void *)buffer; | ||
1139 | |||
1140 | memset(c, 0, sizeof(*c)); | ||
1141 | |||
1142 | c->ctype = AVC_CTYPE_STATUS; | ||
1143 | c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit; | ||
1144 | c->opcode = AVC_OPCODE_VENDOR; | ||
1145 | |||
1146 | c->operand[0] = SFE_VENDOR_DE_COMPANYID_0; | ||
1147 | c->operand[1] = SFE_VENDOR_DE_COMPANYID_1; | ||
1148 | c->operand[2] = SFE_VENDOR_DE_COMPANYID_2; | ||
1149 | c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST; | ||
1150 | c->operand[4] = 0; /* slot */ | ||
1151 | c->operand[5] = SFE_VENDOR_TAG_CA_MMI; | ||
1152 | c->operand[6] = 0; /* more/last */ | ||
1153 | c->operand[7] = 0; /* length */ | ||
1154 | |||
1155 | c->length = 12; | ||
1156 | |||
1157 | if (avc_write(fdtv, c, r) < 0) | ||
1158 | return -EIO; | ||
1159 | |||
1160 | /* FIXME: check response code and validate response data */ | ||
1161 | |||
1162 | *len = get_ca_object_length(r); | ||
1163 | memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len); | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | #define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL | ||
1169 | |||
1170 | static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len) | ||
1171 | { | ||
1172 | int ret; | ||
1173 | |||
1174 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
1175 | return -EINTR; | ||
1176 | |||
1177 | ret = fdtv->backend->read(fdtv, addr, buf, len); | ||
1178 | if (ret < 0) | ||
1179 | dev_err(fdtv->device, "CMP: read I/O error\n"); | ||
1180 | |||
1181 | mutex_unlock(&fdtv->avc_mutex); | ||
1182 | return ret; | ||
1183 | } | ||
1184 | |||
1185 | static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg) | ||
1186 | { | ||
1187 | int ret; | ||
1188 | |||
1189 | if (mutex_lock_interruptible(&fdtv->avc_mutex)) | ||
1190 | return -EINTR; | ||
1191 | |||
1192 | ret = fdtv->backend->lock(fdtv, addr, data, arg); | ||
1193 | if (ret < 0) | ||
1194 | dev_err(fdtv->device, "CMP: lock I/O error\n"); | ||
1195 | |||
1196 | mutex_unlock(&fdtv->avc_mutex); | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift) | ||
1201 | { | ||
1202 | return (be32_to_cpu(opcr) >> shift) & mask; | ||
1203 | } | ||
1204 | |||
1205 | static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift) | ||
1206 | { | ||
1207 | *opcr &= ~cpu_to_be32(mask << shift); | ||
1208 | *opcr |= cpu_to_be32((value & mask) << shift); | ||
1209 | } | ||
1210 | |||
1211 | #define get_opcr_online(v) get_opcr((v), 0x1, 31) | ||
1212 | #define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24) | ||
1213 | #define get_opcr_channel(v) get_opcr((v), 0x3f, 16) | ||
1214 | |||
1215 | #define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24) | ||
1216 | #define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16) | ||
1217 | #define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14) | ||
1218 | #define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10) | ||
1219 | |||
1220 | int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel) | ||
1221 | { | ||
1222 | __be32 old_opcr, opcr; | ||
1223 | u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); | ||
1224 | int attempts = 0; | ||
1225 | int ret; | ||
1226 | |||
1227 | ret = cmp_read(fdtv, &opcr, opcr_address, 4); | ||
1228 | if (ret < 0) | ||
1229 | return ret; | ||
1230 | |||
1231 | repeat: | ||
1232 | if (!get_opcr_online(opcr)) { | ||
1233 | dev_err(fdtv->device, "CMP: output offline\n"); | ||
1234 | return -EBUSY; | ||
1235 | } | ||
1236 | |||
1237 | old_opcr = opcr; | ||
1238 | |||
1239 | if (get_opcr_p2p_connections(opcr)) { | ||
1240 | if (get_opcr_channel(opcr) != channel) { | ||
1241 | dev_err(fdtv->device, "CMP: cannot change channel\n"); | ||
1242 | return -EBUSY; | ||
1243 | } | ||
1244 | dev_info(fdtv->device, "CMP: overlaying connection\n"); | ||
1245 | |||
1246 | /* We don't allocate isochronous resources. */ | ||
1247 | } else { | ||
1248 | set_opcr_channel(&opcr, channel); | ||
1249 | set_opcr_data_rate(&opcr, 2); /* S400 */ | ||
1250 | |||
1251 | /* FIXME: this is for the worst case - optimize */ | ||
1252 | set_opcr_overhead_id(&opcr, 0); | ||
1253 | |||
1254 | /* | ||
1255 | * FIXME: allocate isochronous channel and bandwidth at IRM | ||
1256 | * fdtv->backend->alloc_resources(fdtv, channels_mask, bw); | ||
1257 | */ | ||
1258 | } | ||
1259 | |||
1260 | set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1); | ||
1261 | |||
1262 | ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr); | ||
1263 | if (ret < 0) | ||
1264 | return ret; | ||
1265 | |||
1266 | if (old_opcr != opcr) { | ||
1267 | /* | ||
1268 | * FIXME: if old_opcr.P2P_Connections > 0, | ||
1269 | * deallocate isochronous channel and bandwidth at IRM | ||
1270 | * if (...) | ||
1271 | * fdtv->backend->dealloc_resources(fdtv, channel, bw); | ||
1272 | */ | ||
1273 | |||
1274 | if (++attempts < 6) /* arbitrary limit */ | ||
1275 | goto repeat; | ||
1276 | return -EBUSY; | ||
1277 | } | ||
1278 | |||
1279 | return 0; | ||
1280 | } | ||
1281 | |||
1282 | void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel) | ||
1283 | { | ||
1284 | __be32 old_opcr, opcr; | ||
1285 | u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); | ||
1286 | int attempts = 0; | ||
1287 | |||
1288 | if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0) | ||
1289 | return; | ||
1290 | |||
1291 | repeat: | ||
1292 | if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) || | ||
1293 | get_opcr_channel(opcr) != channel) { | ||
1294 | dev_err(fdtv->device, "CMP: no connection to break\n"); | ||
1295 | return; | ||
1296 | } | ||
1297 | |||
1298 | old_opcr = opcr; | ||
1299 | set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1); | ||
1300 | |||
1301 | if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0) | ||
1302 | return; | ||
1303 | |||
1304 | if (old_opcr != opcr) { | ||
1305 | /* | ||
1306 | * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last | ||
1307 | * owner, deallocate isochronous channel and bandwidth at IRM | ||
1308 | * if (...) | ||
1309 | * fdtv->backend->dealloc_resources(fdtv, channel, bw); | ||
1310 | */ | ||
1311 | |||
1312 | if (++attempts < 6) /* arbitrary limit */ | ||
1313 | goto repeat; | ||
1314 | } | ||
1315 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c new file mode 100644 index 000000000000..eeb80d0ea3ff --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-ci.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/dvb/ca.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include <dvbdev.h> | ||
19 | |||
20 | #include "firedtv.h" | ||
21 | |||
22 | #define EN50221_TAG_APP_INFO_ENQUIRY 0x9f8020 | ||
23 | #define EN50221_TAG_CA_INFO_ENQUIRY 0x9f8030 | ||
24 | #define EN50221_TAG_CA_PMT 0x9f8032 | ||
25 | #define EN50221_TAG_ENTER_MENU 0x9f8022 | ||
26 | |||
27 | static int fdtv_ca_ready(struct firedtv_tuner_status *stat) | ||
28 | { | ||
29 | return stat->ca_initialization_status == 1 && | ||
30 | stat->ca_error_flag == 0 && | ||
31 | stat->ca_dvb_flag == 1 && | ||
32 | stat->ca_module_present_status == 1; | ||
33 | } | ||
34 | |||
35 | static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat) | ||
36 | { | ||
37 | int flags = 0; | ||
38 | |||
39 | if (stat->ca_module_present_status == 1) | ||
40 | flags |= CA_CI_MODULE_PRESENT; | ||
41 | if (stat->ca_initialization_status == 1 && | ||
42 | stat->ca_error_flag == 0 && | ||
43 | stat->ca_dvb_flag == 1) | ||
44 | flags |= CA_CI_MODULE_READY; | ||
45 | return flags; | ||
46 | } | ||
47 | |||
48 | static int fdtv_ca_reset(struct firedtv *fdtv) | ||
49 | { | ||
50 | return avc_ca_reset(fdtv) ? -EFAULT : 0; | ||
51 | } | ||
52 | |||
53 | static int fdtv_ca_get_caps(void *arg) | ||
54 | { | ||
55 | struct ca_caps *cap = arg; | ||
56 | |||
57 | cap->slot_num = 1; | ||
58 | cap->slot_type = CA_CI; | ||
59 | cap->descr_num = 1; | ||
60 | cap->descr_type = CA_ECD; | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg) | ||
65 | { | ||
66 | struct firedtv_tuner_status stat; | ||
67 | struct ca_slot_info *slot = arg; | ||
68 | |||
69 | if (avc_tuner_status(fdtv, &stat)) | ||
70 | return -EFAULT; | ||
71 | |||
72 | if (slot->num != 0) | ||
73 | return -EFAULT; | ||
74 | |||
75 | slot->type = CA_CI; | ||
76 | slot->flags = fdtv_get_ca_flags(&stat); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg) | ||
81 | { | ||
82 | struct ca_msg *reply = arg; | ||
83 | |||
84 | return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
85 | } | ||
86 | |||
87 | static int fdtv_ca_info(struct firedtv *fdtv, void *arg) | ||
88 | { | ||
89 | struct ca_msg *reply = arg; | ||
90 | |||
91 | return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
92 | } | ||
93 | |||
94 | static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg) | ||
95 | { | ||
96 | struct ca_msg *reply = arg; | ||
97 | |||
98 | return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0; | ||
99 | } | ||
100 | |||
101 | static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg) | ||
102 | { | ||
103 | struct firedtv_tuner_status stat; | ||
104 | int err; | ||
105 | |||
106 | switch (fdtv->ca_last_command) { | ||
107 | case EN50221_TAG_APP_INFO_ENQUIRY: | ||
108 | err = fdtv_ca_app_info(fdtv, arg); | ||
109 | break; | ||
110 | case EN50221_TAG_CA_INFO_ENQUIRY: | ||
111 | err = fdtv_ca_info(fdtv, arg); | ||
112 | break; | ||
113 | default: | ||
114 | if (avc_tuner_status(fdtv, &stat)) | ||
115 | err = -EFAULT; | ||
116 | else if (stat.ca_mmi == 1) | ||
117 | err = fdtv_ca_get_mmi(fdtv, arg); | ||
118 | else { | ||
119 | dev_info(fdtv->device, "unhandled CA message 0x%08x\n", | ||
120 | fdtv->ca_last_command); | ||
121 | err = -EFAULT; | ||
122 | } | ||
123 | } | ||
124 | fdtv->ca_last_command = 0; | ||
125 | return err; | ||
126 | } | ||
127 | |||
128 | static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) | ||
129 | { | ||
130 | struct ca_msg *msg = arg; | ||
131 | int data_pos; | ||
132 | int data_length; | ||
133 | int i; | ||
134 | |||
135 | data_pos = 4; | ||
136 | if (msg->msg[3] & 0x80) { | ||
137 | data_length = 0; | ||
138 | for (i = 0; i < (msg->msg[3] & 0x7f); i++) | ||
139 | data_length = (data_length << 8) + msg->msg[data_pos++]; | ||
140 | } else { | ||
141 | data_length = msg->msg[3]; | ||
142 | } | ||
143 | |||
144 | return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0; | ||
145 | } | ||
146 | |||
147 | static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg) | ||
148 | { | ||
149 | struct ca_msg *msg = arg; | ||
150 | int err; | ||
151 | |||
152 | /* Do we need a semaphore for this? */ | ||
153 | fdtv->ca_last_command = | ||
154 | (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2]; | ||
155 | switch (fdtv->ca_last_command) { | ||
156 | case EN50221_TAG_CA_PMT: | ||
157 | err = fdtv_ca_pmt(fdtv, arg); | ||
158 | break; | ||
159 | case EN50221_TAG_APP_INFO_ENQUIRY: | ||
160 | /* handled in ca_get_msg */ | ||
161 | err = 0; | ||
162 | break; | ||
163 | case EN50221_TAG_CA_INFO_ENQUIRY: | ||
164 | /* handled in ca_get_msg */ | ||
165 | err = 0; | ||
166 | break; | ||
167 | case EN50221_TAG_ENTER_MENU: | ||
168 | err = avc_ca_enter_menu(fdtv); | ||
169 | break; | ||
170 | default: | ||
171 | dev_err(fdtv->device, "unhandled CA message 0x%08x\n", | ||
172 | fdtv->ca_last_command); | ||
173 | err = -EFAULT; | ||
174 | } | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | static int fdtv_ca_ioctl(struct inode *inode, struct file *file, | ||
179 | unsigned int cmd, void *arg) | ||
180 | { | ||
181 | struct dvb_device *dvbdev = file->private_data; | ||
182 | struct firedtv *fdtv = dvbdev->priv; | ||
183 | struct firedtv_tuner_status stat; | ||
184 | int err; | ||
185 | |||
186 | switch (cmd) { | ||
187 | case CA_RESET: | ||
188 | err = fdtv_ca_reset(fdtv); | ||
189 | break; | ||
190 | case CA_GET_CAP: | ||
191 | err = fdtv_ca_get_caps(arg); | ||
192 | break; | ||
193 | case CA_GET_SLOT_INFO: | ||
194 | err = fdtv_ca_get_slot_info(fdtv, arg); | ||
195 | break; | ||
196 | case CA_GET_MSG: | ||
197 | err = fdtv_ca_get_msg(fdtv, arg); | ||
198 | break; | ||
199 | case CA_SEND_MSG: | ||
200 | err = fdtv_ca_send_msg(fdtv, arg); | ||
201 | break; | ||
202 | default: | ||
203 | dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd); | ||
204 | err = -EOPNOTSUPP; | ||
205 | } | ||
206 | |||
207 | /* FIXME Is this necessary? */ | ||
208 | avc_tuner_status(fdtv, &stat); | ||
209 | |||
210 | return err; | ||
211 | } | ||
212 | |||
213 | static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait) | ||
214 | { | ||
215 | return POLLIN; | ||
216 | } | ||
217 | |||
218 | static struct file_operations fdtv_ca_fops = { | ||
219 | .owner = THIS_MODULE, | ||
220 | .ioctl = dvb_generic_ioctl, | ||
221 | .open = dvb_generic_open, | ||
222 | .release = dvb_generic_release, | ||
223 | .poll = fdtv_ca_io_poll, | ||
224 | }; | ||
225 | |||
226 | static struct dvb_device fdtv_ca = { | ||
227 | .users = 1, | ||
228 | .readers = 1, | ||
229 | .writers = 1, | ||
230 | .fops = &fdtv_ca_fops, | ||
231 | .kernel_ioctl = fdtv_ca_ioctl, | ||
232 | }; | ||
233 | |||
234 | int fdtv_ca_register(struct firedtv *fdtv) | ||
235 | { | ||
236 | struct firedtv_tuner_status stat; | ||
237 | int err; | ||
238 | |||
239 | if (avc_tuner_status(fdtv, &stat)) | ||
240 | return -EINVAL; | ||
241 | |||
242 | if (!fdtv_ca_ready(&stat)) | ||
243 | return -EFAULT; | ||
244 | |||
245 | err = dvb_register_device(&fdtv->adapter, &fdtv->cadev, | ||
246 | &fdtv_ca, fdtv, DVB_DEVICE_CA); | ||
247 | |||
248 | if (stat.ca_application_info == 0) | ||
249 | dev_err(fdtv->device, "CaApplicationInfo is not set\n"); | ||
250 | if (stat.ca_date_time_request == 1) | ||
251 | avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval); | ||
252 | |||
253 | return err; | ||
254 | } | ||
255 | |||
256 | void fdtv_ca_release(struct firedtv *fdtv) | ||
257 | { | ||
258 | if (fdtv->cadev) | ||
259 | dvb_unregister_device(fdtv->cadev); | ||
260 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c new file mode 100644 index 000000000000..9d308dd32a5c --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-dvb.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/bitops.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mod_devicetable.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/wait.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #include <dmxdev.h> | ||
27 | #include <dvb_demux.h> | ||
28 | #include <dvbdev.h> | ||
29 | #include <dvb_frontend.h> | ||
30 | |||
31 | #include "firedtv.h" | ||
32 | |||
33 | static int alloc_channel(struct firedtv *fdtv) | ||
34 | { | ||
35 | int i; | ||
36 | |||
37 | for (i = 0; i < 16; i++) | ||
38 | if (!__test_and_set_bit(i, &fdtv->channel_active)) | ||
39 | break; | ||
40 | return i; | ||
41 | } | ||
42 | |||
43 | static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[]) | ||
44 | { | ||
45 | int i, n; | ||
46 | |||
47 | for (i = 0, n = 0; i < 16; i++) | ||
48 | if (test_bit(i, &fdtv->channel_active)) | ||
49 | pid[n++] = fdtv->channel_pid[i]; | ||
50 | *pidc = n; | ||
51 | } | ||
52 | |||
53 | static inline void dealloc_channel(struct firedtv *fdtv, int i) | ||
54 | { | ||
55 | __clear_bit(i, &fdtv->channel_active); | ||
56 | } | ||
57 | |||
58 | int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
59 | { | ||
60 | struct firedtv *fdtv = dvbdmxfeed->demux->priv; | ||
61 | int pidc, c, ret; | ||
62 | u16 pids[16]; | ||
63 | |||
64 | switch (dvbdmxfeed->type) { | ||
65 | case DMX_TYPE_TS: | ||
66 | case DMX_TYPE_SEC: | ||
67 | break; | ||
68 | default: | ||
69 | dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n", | ||
70 | dvbdmxfeed->type); | ||
71 | return -EINVAL; | ||
72 | } | ||
73 | |||
74 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
75 | return -EINTR; | ||
76 | |||
77 | if (dvbdmxfeed->type == DMX_TYPE_TS) { | ||
78 | switch (dvbdmxfeed->pes_type) { | ||
79 | case DMX_TS_PES_VIDEO: | ||
80 | case DMX_TS_PES_AUDIO: | ||
81 | case DMX_TS_PES_TELETEXT: | ||
82 | case DMX_TS_PES_PCR: | ||
83 | case DMX_TS_PES_OTHER: | ||
84 | c = alloc_channel(fdtv); | ||
85 | break; | ||
86 | default: | ||
87 | dev_err(fdtv->device, | ||
88 | "can't start dmx feed: invalid pes type %u\n", | ||
89 | dvbdmxfeed->pes_type); | ||
90 | ret = -EINVAL; | ||
91 | goto out; | ||
92 | } | ||
93 | } else { | ||
94 | c = alloc_channel(fdtv); | ||
95 | } | ||
96 | |||
97 | if (c > 15) { | ||
98 | dev_err(fdtv->device, "can't start dmx feed: busy\n"); | ||
99 | ret = -EBUSY; | ||
100 | goto out; | ||
101 | } | ||
102 | |||
103 | dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c; | ||
104 | fdtv->channel_pid[c] = dvbdmxfeed->pid; | ||
105 | collect_channels(fdtv, &pidc, pids); | ||
106 | |||
107 | if (dvbdmxfeed->pid == 8192) { | ||
108 | ret = avc_tuner_get_ts(fdtv); | ||
109 | if (ret) { | ||
110 | dealloc_channel(fdtv, c); | ||
111 | dev_err(fdtv->device, "can't get TS\n"); | ||
112 | goto out; | ||
113 | } | ||
114 | } else { | ||
115 | ret = avc_tuner_set_pids(fdtv, pidc, pids); | ||
116 | if (ret) { | ||
117 | dealloc_channel(fdtv, c); | ||
118 | dev_err(fdtv->device, "can't set PIDs\n"); | ||
119 | goto out; | ||
120 | } | ||
121 | } | ||
122 | out: | ||
123 | mutex_unlock(&fdtv->demux_mutex); | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
129 | { | ||
130 | struct dvb_demux *demux = dvbdmxfeed->demux; | ||
131 | struct firedtv *fdtv = demux->priv; | ||
132 | int pidc, c, ret; | ||
133 | u16 pids[16]; | ||
134 | |||
135 | if (dvbdmxfeed->type == DMX_TYPE_TS && | ||
136 | !((dvbdmxfeed->ts_type & TS_PACKET) && | ||
137 | (demux->dmx.frontend->source != DMX_MEMORY_FE))) { | ||
138 | |||
139 | if (dvbdmxfeed->ts_type & TS_DECODER) { | ||
140 | if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER || | ||
141 | !demux->pesfilter[dvbdmxfeed->pes_type]) | ||
142 | return -EINVAL; | ||
143 | |||
144 | demux->pids[dvbdmxfeed->pes_type] |= 0x8000; | ||
145 | demux->pesfilter[dvbdmxfeed->pes_type] = NULL; | ||
146 | } | ||
147 | |||
148 | if (!(dvbdmxfeed->ts_type & TS_DECODER && | ||
149 | dvbdmxfeed->pes_type < DMX_TS_PES_OTHER)) | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | if (mutex_lock_interruptible(&fdtv->demux_mutex)) | ||
154 | return -EINTR; | ||
155 | |||
156 | c = (unsigned long)dvbdmxfeed->priv; | ||
157 | dealloc_channel(fdtv, c); | ||
158 | collect_channels(fdtv, &pidc, pids); | ||
159 | |||
160 | ret = avc_tuner_set_pids(fdtv, pidc, pids); | ||
161 | |||
162 | mutex_unlock(&fdtv->demux_mutex); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
168 | |||
169 | int fdtv_dvb_register(struct firedtv *fdtv) | ||
170 | { | ||
171 | int err; | ||
172 | |||
173 | err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type], | ||
174 | THIS_MODULE, fdtv->device, adapter_nr); | ||
175 | if (err < 0) | ||
176 | goto fail_log; | ||
177 | |||
178 | /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/ | ||
179 | fdtv->demux.dmx.capabilities = 0; | ||
180 | |||
181 | fdtv->demux.priv = fdtv; | ||
182 | fdtv->demux.filternum = 16; | ||
183 | fdtv->demux.feednum = 16; | ||
184 | fdtv->demux.start_feed = fdtv_start_feed; | ||
185 | fdtv->demux.stop_feed = fdtv_stop_feed; | ||
186 | fdtv->demux.write_to_decoder = NULL; | ||
187 | |||
188 | err = dvb_dmx_init(&fdtv->demux); | ||
189 | if (err) | ||
190 | goto fail_unreg_adapter; | ||
191 | |||
192 | fdtv->dmxdev.filternum = 16; | ||
193 | fdtv->dmxdev.demux = &fdtv->demux.dmx; | ||
194 | fdtv->dmxdev.capabilities = 0; | ||
195 | |||
196 | err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter); | ||
197 | if (err) | ||
198 | goto fail_dmx_release; | ||
199 | |||
200 | fdtv->frontend.source = DMX_FRONTEND_0; | ||
201 | |||
202 | err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend); | ||
203 | if (err) | ||
204 | goto fail_dmxdev_release; | ||
205 | |||
206 | err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx, | ||
207 | &fdtv->frontend); | ||
208 | if (err) | ||
209 | goto fail_rem_frontend; | ||
210 | |||
211 | dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx); | ||
212 | |||
213 | fdtv_frontend_init(fdtv); | ||
214 | err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe); | ||
215 | if (err) | ||
216 | goto fail_net_release; | ||
217 | |||
218 | err = fdtv_ca_register(fdtv); | ||
219 | if (err) | ||
220 | dev_info(fdtv->device, | ||
221 | "Conditional Access Module not enabled\n"); | ||
222 | return 0; | ||
223 | |||
224 | fail_net_release: | ||
225 | dvb_net_release(&fdtv->dvbnet); | ||
226 | fdtv->demux.dmx.close(&fdtv->demux.dmx); | ||
227 | fail_rem_frontend: | ||
228 | fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend); | ||
229 | fail_dmxdev_release: | ||
230 | dvb_dmxdev_release(&fdtv->dmxdev); | ||
231 | fail_dmx_release: | ||
232 | dvb_dmx_release(&fdtv->demux); | ||
233 | fail_unreg_adapter: | ||
234 | dvb_unregister_adapter(&fdtv->adapter); | ||
235 | fail_log: | ||
236 | dev_err(fdtv->device, "DVB initialization failed\n"); | ||
237 | return err; | ||
238 | } | ||
239 | |||
240 | void fdtv_dvb_unregister(struct firedtv *fdtv) | ||
241 | { | ||
242 | fdtv_ca_release(fdtv); | ||
243 | dvb_unregister_frontend(&fdtv->fe); | ||
244 | dvb_net_release(&fdtv->dvbnet); | ||
245 | fdtv->demux.dmx.close(&fdtv->demux.dmx); | ||
246 | fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend); | ||
247 | dvb_dmxdev_release(&fdtv->dmxdev); | ||
248 | dvb_dmx_release(&fdtv->demux); | ||
249 | dvb_unregister_adapter(&fdtv->adapter); | ||
250 | } | ||
251 | |||
252 | const char *fdtv_model_names[] = { | ||
253 | [FIREDTV_UNKNOWN] = "unknown type", | ||
254 | [FIREDTV_DVB_S] = "FireDTV S/CI", | ||
255 | [FIREDTV_DVB_C] = "FireDTV C/CI", | ||
256 | [FIREDTV_DVB_T] = "FireDTV T/CI", | ||
257 | [FIREDTV_DVB_S2] = "FireDTV S2 ", | ||
258 | }; | ||
259 | |||
260 | struct firedtv *fdtv_alloc(struct device *dev, | ||
261 | const struct firedtv_backend *backend, | ||
262 | const char *name, size_t name_len) | ||
263 | { | ||
264 | struct firedtv *fdtv; | ||
265 | int i; | ||
266 | |||
267 | fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL); | ||
268 | if (!fdtv) | ||
269 | return NULL; | ||
270 | |||
271 | dev->driver_data = fdtv; | ||
272 | fdtv->device = dev; | ||
273 | fdtv->isochannel = -1; | ||
274 | fdtv->voltage = 0xff; | ||
275 | fdtv->tone = 0xff; | ||
276 | fdtv->backend = backend; | ||
277 | |||
278 | mutex_init(&fdtv->avc_mutex); | ||
279 | init_waitqueue_head(&fdtv->avc_wait); | ||
280 | fdtv->avc_reply_received = true; | ||
281 | mutex_init(&fdtv->demux_mutex); | ||
282 | INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); | ||
283 | |||
284 | for (i = ARRAY_SIZE(fdtv_model_names); --i; ) | ||
285 | if (strlen(fdtv_model_names[i]) <= name_len && | ||
286 | strncmp(name, fdtv_model_names[i], name_len) == 0) | ||
287 | break; | ||
288 | fdtv->type = i; | ||
289 | |||
290 | return fdtv; | ||
291 | } | ||
292 | |||
293 | #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \ | ||
294 | IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION) | ||
295 | |||
296 | #define DIGITAL_EVERYWHERE_OUI 0x001287 | ||
297 | #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d | ||
298 | #define AVC_SW_VERSION_ENTRY 0x010001 | ||
299 | |||
300 | static struct ieee1394_device_id fdtv_id_table[] = { | ||
301 | { | ||
302 | /* FloppyDTV S/CI and FloppyDTV S2 */ | ||
303 | .match_flags = MATCH_FLAGS, | ||
304 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
305 | .model_id = 0x000024, | ||
306 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
307 | .version = AVC_SW_VERSION_ENTRY, | ||
308 | }, { | ||
309 | /* FloppyDTV T/CI */ | ||
310 | .match_flags = MATCH_FLAGS, | ||
311 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
312 | .model_id = 0x000025, | ||
313 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
314 | .version = AVC_SW_VERSION_ENTRY, | ||
315 | }, { | ||
316 | /* FloppyDTV C/CI */ | ||
317 | .match_flags = MATCH_FLAGS, | ||
318 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
319 | .model_id = 0x000026, | ||
320 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
321 | .version = AVC_SW_VERSION_ENTRY, | ||
322 | }, { | ||
323 | /* FireDTV S/CI and FloppyDTV S2 */ | ||
324 | .match_flags = MATCH_FLAGS, | ||
325 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
326 | .model_id = 0x000034, | ||
327 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
328 | .version = AVC_SW_VERSION_ENTRY, | ||
329 | }, { | ||
330 | /* FireDTV T/CI */ | ||
331 | .match_flags = MATCH_FLAGS, | ||
332 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
333 | .model_id = 0x000035, | ||
334 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
335 | .version = AVC_SW_VERSION_ENTRY, | ||
336 | }, { | ||
337 | /* FireDTV C/CI */ | ||
338 | .match_flags = MATCH_FLAGS, | ||
339 | .vendor_id = DIGITAL_EVERYWHERE_OUI, | ||
340 | .model_id = 0x000036, | ||
341 | .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, | ||
342 | .version = AVC_SW_VERSION_ENTRY, | ||
343 | }, {} | ||
344 | }; | ||
345 | MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); | ||
346 | |||
347 | static int __init fdtv_init(void) | ||
348 | { | ||
349 | return fdtv_1394_init(fdtv_id_table); | ||
350 | } | ||
351 | |||
352 | static void __exit fdtv_exit(void) | ||
353 | { | ||
354 | fdtv_1394_exit(); | ||
355 | } | ||
356 | |||
357 | module_init(fdtv_init); | ||
358 | module_exit(fdtv_exit); | ||
359 | |||
360 | MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>"); | ||
361 | MODULE_AUTHOR("Ben Backx <ben@bbackx.com>"); | ||
362 | MODULE_DESCRIPTION("FireDTV DVB Driver"); | ||
363 | MODULE_LICENSE("GPL"); | ||
364 | MODULE_SUPPORTED_DEVICE("FireDTV DVB"); | ||
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c new file mode 100644 index 000000000000..7ba43630a25d --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-fe.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/types.h> | ||
18 | |||
19 | #include <dvb_frontend.h> | ||
20 | |||
21 | #include "firedtv.h" | ||
22 | |||
23 | static int fdtv_dvb_init(struct dvb_frontend *fe) | ||
24 | { | ||
25 | struct firedtv *fdtv = fe->sec_priv; | ||
26 | int err; | ||
27 | |||
28 | /* FIXME - allocate free channel at IRM */ | ||
29 | fdtv->isochannel = fdtv->adapter.num; | ||
30 | |||
31 | err = cmp_establish_pp_connection(fdtv, fdtv->subunit, | ||
32 | fdtv->isochannel); | ||
33 | if (err) { | ||
34 | dev_err(fdtv->device, | ||
35 | "could not establish point to point connection\n"); | ||
36 | return err; | ||
37 | } | ||
38 | |||
39 | return fdtv->backend->start_iso(fdtv); | ||
40 | } | ||
41 | |||
42 | static int fdtv_sleep(struct dvb_frontend *fe) | ||
43 | { | ||
44 | struct firedtv *fdtv = fe->sec_priv; | ||
45 | |||
46 | fdtv->backend->stop_iso(fdtv); | ||
47 | cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel); | ||
48 | fdtv->isochannel = -1; | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | #define LNBCONTROL_DONTCARE 0xff | ||
53 | |||
54 | static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe, | ||
55 | struct dvb_diseqc_master_cmd *cmd) | ||
56 | { | ||
57 | struct firedtv *fdtv = fe->sec_priv; | ||
58 | |||
59 | return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, | ||
60 | LNBCONTROL_DONTCARE, 1, cmd); | ||
61 | } | ||
62 | |||
63 | static int fdtv_diseqc_send_burst(struct dvb_frontend *fe, | ||
64 | fe_sec_mini_cmd_t minicmd) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) | ||
70 | { | ||
71 | struct firedtv *fdtv = fe->sec_priv; | ||
72 | |||
73 | fdtv->tone = tone; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int fdtv_set_voltage(struct dvb_frontend *fe, | ||
78 | fe_sec_voltage_t voltage) | ||
79 | { | ||
80 | struct firedtv *fdtv = fe->sec_priv; | ||
81 | |||
82 | fdtv->voltage = voltage; | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status) | ||
87 | { | ||
88 | struct firedtv *fdtv = fe->sec_priv; | ||
89 | struct firedtv_tuner_status stat; | ||
90 | |||
91 | if (avc_tuner_status(fdtv, &stat)) | ||
92 | return -EINVAL; | ||
93 | |||
94 | if (stat.no_rf) | ||
95 | *status = 0; | ||
96 | else | ||
97 | *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | | ||
98 | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
103 | { | ||
104 | struct firedtv *fdtv = fe->sec_priv; | ||
105 | struct firedtv_tuner_status stat; | ||
106 | |||
107 | if (avc_tuner_status(fdtv, &stat)) | ||
108 | return -EINVAL; | ||
109 | |||
110 | *ber = stat.ber; | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
115 | { | ||
116 | struct firedtv *fdtv = fe->sec_priv; | ||
117 | struct firedtv_tuner_status stat; | ||
118 | |||
119 | if (avc_tuner_status(fdtv, &stat)) | ||
120 | return -EINVAL; | ||
121 | |||
122 | *strength = stat.signal_strength << 8; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
127 | { | ||
128 | struct firedtv *fdtv = fe->sec_priv; | ||
129 | struct firedtv_tuner_status stat; | ||
130 | |||
131 | if (avc_tuner_status(fdtv, &stat)) | ||
132 | return -EINVAL; | ||
133 | |||
134 | /* C/N[dB] = -10 * log10(snr / 65535) */ | ||
135 | *snr = stat.carrier_noise_ratio * 257; | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
140 | { | ||
141 | return -EOPNOTSUPP; | ||
142 | } | ||
143 | |||
144 | #define ACCEPTED 0x9 | ||
145 | |||
146 | static int fdtv_set_frontend(struct dvb_frontend *fe, | ||
147 | struct dvb_frontend_parameters *params) | ||
148 | { | ||
149 | struct firedtv *fdtv = fe->sec_priv; | ||
150 | |||
151 | /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */ | ||
152 | if (avc_tuner_dsd(fdtv, params) != ACCEPTED) | ||
153 | return -EINVAL; | ||
154 | else | ||
155 | return 0; /* not sure of this... */ | ||
156 | } | ||
157 | |||
158 | static int fdtv_get_frontend(struct dvb_frontend *fe, | ||
159 | struct dvb_frontend_parameters *params) | ||
160 | { | ||
161 | return -EOPNOTSUPP; | ||
162 | } | ||
163 | |||
164 | void fdtv_frontend_init(struct firedtv *fdtv) | ||
165 | { | ||
166 | struct dvb_frontend_ops *ops = &fdtv->fe.ops; | ||
167 | struct dvb_frontend_info *fi = &ops->info; | ||
168 | |||
169 | ops->init = fdtv_dvb_init; | ||
170 | ops->sleep = fdtv_sleep; | ||
171 | |||
172 | ops->set_frontend = fdtv_set_frontend; | ||
173 | ops->get_frontend = fdtv_get_frontend; | ||
174 | |||
175 | ops->read_status = fdtv_read_status; | ||
176 | ops->read_ber = fdtv_read_ber; | ||
177 | ops->read_signal_strength = fdtv_read_signal_strength; | ||
178 | ops->read_snr = fdtv_read_snr; | ||
179 | ops->read_ucblocks = fdtv_read_uncorrected_blocks; | ||
180 | |||
181 | ops->diseqc_send_master_cmd = fdtv_diseqc_send_master_cmd; | ||
182 | ops->diseqc_send_burst = fdtv_diseqc_send_burst; | ||
183 | ops->set_tone = fdtv_set_tone; | ||
184 | ops->set_voltage = fdtv_set_voltage; | ||
185 | |||
186 | switch (fdtv->type) { | ||
187 | case FIREDTV_DVB_S: | ||
188 | case FIREDTV_DVB_S2: | ||
189 | fi->type = FE_QPSK; | ||
190 | |||
191 | fi->frequency_min = 950000; | ||
192 | fi->frequency_max = 2150000; | ||
193 | fi->frequency_stepsize = 125; | ||
194 | fi->symbol_rate_min = 1000000; | ||
195 | fi->symbol_rate_max = 40000000; | ||
196 | |||
197 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
198 | FE_CAN_FEC_1_2 | | ||
199 | FE_CAN_FEC_2_3 | | ||
200 | FE_CAN_FEC_3_4 | | ||
201 | FE_CAN_FEC_5_6 | | ||
202 | FE_CAN_FEC_7_8 | | ||
203 | FE_CAN_FEC_AUTO | | ||
204 | FE_CAN_QPSK; | ||
205 | break; | ||
206 | |||
207 | case FIREDTV_DVB_C: | ||
208 | fi->type = FE_QAM; | ||
209 | |||
210 | fi->frequency_min = 47000000; | ||
211 | fi->frequency_max = 866000000; | ||
212 | fi->frequency_stepsize = 62500; | ||
213 | fi->symbol_rate_min = 870000; | ||
214 | fi->symbol_rate_max = 6900000; | ||
215 | |||
216 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
217 | FE_CAN_QAM_16 | | ||
218 | FE_CAN_QAM_32 | | ||
219 | FE_CAN_QAM_64 | | ||
220 | FE_CAN_QAM_128 | | ||
221 | FE_CAN_QAM_256 | | ||
222 | FE_CAN_QAM_AUTO; | ||
223 | break; | ||
224 | |||
225 | case FIREDTV_DVB_T: | ||
226 | fi->type = FE_OFDM; | ||
227 | |||
228 | fi->frequency_min = 49000000; | ||
229 | fi->frequency_max = 861000000; | ||
230 | fi->frequency_stepsize = 62500; | ||
231 | |||
232 | fi->caps = FE_CAN_INVERSION_AUTO | | ||
233 | FE_CAN_FEC_2_3 | | ||
234 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
235 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
236 | FE_CAN_HIERARCHY_AUTO; | ||
237 | break; | ||
238 | |||
239 | default: | ||
240 | dev_err(fdtv->device, "no frontend for model type %d\n", | ||
241 | fdtv->type); | ||
242 | } | ||
243 | strcpy(fi->name, fdtv_model_names[fdtv->type]); | ||
244 | |||
245 | fdtv->fe.dvb = &fdtv->adapter; | ||
246 | fdtv->fe.sec_priv = fdtv; | ||
247 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c new file mode 100644 index 000000000000..46a6324d7b73 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv-rc.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/bitops.h> | ||
13 | #include <linux/input.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #include "firedtv.h" | ||
19 | |||
20 | /* fixed table with older keycodes, geared towards MythTV */ | ||
21 | const static u16 oldtable[] = { | ||
22 | |||
23 | /* code from device: 0x4501...0x451f */ | ||
24 | |||
25 | KEY_ESC, | ||
26 | KEY_F9, | ||
27 | KEY_1, | ||
28 | KEY_2, | ||
29 | KEY_3, | ||
30 | KEY_4, | ||
31 | KEY_5, | ||
32 | KEY_6, | ||
33 | KEY_7, | ||
34 | KEY_8, | ||
35 | KEY_9, | ||
36 | KEY_I, | ||
37 | KEY_0, | ||
38 | KEY_ENTER, | ||
39 | KEY_RED, | ||
40 | KEY_UP, | ||
41 | KEY_GREEN, | ||
42 | KEY_F10, | ||
43 | KEY_SPACE, | ||
44 | KEY_F11, | ||
45 | KEY_YELLOW, | ||
46 | KEY_DOWN, | ||
47 | KEY_BLUE, | ||
48 | KEY_Z, | ||
49 | KEY_P, | ||
50 | KEY_PAGEDOWN, | ||
51 | KEY_LEFT, | ||
52 | KEY_W, | ||
53 | KEY_RIGHT, | ||
54 | KEY_P, | ||
55 | KEY_M, | ||
56 | |||
57 | /* code from device: 0x4540...0x4542 */ | ||
58 | |||
59 | KEY_R, | ||
60 | KEY_V, | ||
61 | KEY_C, | ||
62 | }; | ||
63 | |||
64 | /* user-modifiable table for a remote as sold in 2008 */ | ||
65 | const static u16 keytable[] = { | ||
66 | |||
67 | /* code from device: 0x0300...0x031f */ | ||
68 | |||
69 | [0x00] = KEY_POWER, | ||
70 | [0x01] = KEY_SLEEP, | ||
71 | [0x02] = KEY_STOP, | ||
72 | [0x03] = KEY_OK, | ||
73 | [0x04] = KEY_RIGHT, | ||
74 | [0x05] = KEY_1, | ||
75 | [0x06] = KEY_2, | ||
76 | [0x07] = KEY_3, | ||
77 | [0x08] = KEY_LEFT, | ||
78 | [0x09] = KEY_4, | ||
79 | [0x0a] = KEY_5, | ||
80 | [0x0b] = KEY_6, | ||
81 | [0x0c] = KEY_UP, | ||
82 | [0x0d] = KEY_7, | ||
83 | [0x0e] = KEY_8, | ||
84 | [0x0f] = KEY_9, | ||
85 | [0x10] = KEY_DOWN, | ||
86 | [0x11] = KEY_TITLE, /* "OSD" - fixme */ | ||
87 | [0x12] = KEY_0, | ||
88 | [0x13] = KEY_F20, /* "16:9" - fixme */ | ||
89 | [0x14] = KEY_SCREEN, /* "FULL" - fixme */ | ||
90 | [0x15] = KEY_MUTE, | ||
91 | [0x16] = KEY_SUBTITLE, | ||
92 | [0x17] = KEY_RECORD, | ||
93 | [0x18] = KEY_TEXT, | ||
94 | [0x19] = KEY_AUDIO, | ||
95 | [0x1a] = KEY_RED, | ||
96 | [0x1b] = KEY_PREVIOUS, | ||
97 | [0x1c] = KEY_REWIND, | ||
98 | [0x1d] = KEY_PLAYPAUSE, | ||
99 | [0x1e] = KEY_NEXT, | ||
100 | [0x1f] = KEY_VOLUMEUP, | ||
101 | |||
102 | /* code from device: 0x0340...0x0354 */ | ||
103 | |||
104 | [0x20] = KEY_CHANNELUP, | ||
105 | [0x21] = KEY_F21, /* "4:3" - fixme */ | ||
106 | [0x22] = KEY_TV, | ||
107 | [0x23] = KEY_DVD, | ||
108 | [0x24] = KEY_VCR, | ||
109 | [0x25] = KEY_AUX, | ||
110 | [0x26] = KEY_GREEN, | ||
111 | [0x27] = KEY_YELLOW, | ||
112 | [0x28] = KEY_BLUE, | ||
113 | [0x29] = KEY_CHANNEL, /* "CH.LIST" */ | ||
114 | [0x2a] = KEY_VENDOR, /* "CI" - fixme */ | ||
115 | [0x2b] = KEY_VOLUMEDOWN, | ||
116 | [0x2c] = KEY_CHANNELDOWN, | ||
117 | [0x2d] = KEY_LAST, | ||
118 | [0x2e] = KEY_INFO, | ||
119 | [0x2f] = KEY_FORWARD, | ||
120 | [0x30] = KEY_LIST, | ||
121 | [0x31] = KEY_FAVORITES, | ||
122 | [0x32] = KEY_MENU, | ||
123 | [0x33] = KEY_EPG, | ||
124 | [0x34] = KEY_EXIT, | ||
125 | }; | ||
126 | |||
127 | int fdtv_register_rc(struct firedtv *fdtv, struct device *dev) | ||
128 | { | ||
129 | struct input_dev *idev; | ||
130 | int i, err; | ||
131 | |||
132 | idev = input_allocate_device(); | ||
133 | if (!idev) | ||
134 | return -ENOMEM; | ||
135 | |||
136 | fdtv->remote_ctrl_dev = idev; | ||
137 | idev->name = "FireDTV remote control"; | ||
138 | idev->dev.parent = dev; | ||
139 | idev->evbit[0] = BIT_MASK(EV_KEY); | ||
140 | idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL); | ||
141 | if (!idev->keycode) { | ||
142 | err = -ENOMEM; | ||
143 | goto fail; | ||
144 | } | ||
145 | idev->keycodesize = sizeof(keytable[0]); | ||
146 | idev->keycodemax = ARRAY_SIZE(keytable); | ||
147 | |||
148 | for (i = 0; i < ARRAY_SIZE(keytable); i++) | ||
149 | set_bit(keytable[i], idev->keybit); | ||
150 | |||
151 | err = input_register_device(idev); | ||
152 | if (err) | ||
153 | goto fail_free_keymap; | ||
154 | |||
155 | return 0; | ||
156 | |||
157 | fail_free_keymap: | ||
158 | kfree(idev->keycode); | ||
159 | fail: | ||
160 | input_free_device(idev); | ||
161 | return err; | ||
162 | } | ||
163 | |||
164 | void fdtv_unregister_rc(struct firedtv *fdtv) | ||
165 | { | ||
166 | kfree(fdtv->remote_ctrl_dev->keycode); | ||
167 | input_unregister_device(fdtv->remote_ctrl_dev); | ||
168 | } | ||
169 | |||
170 | void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) | ||
171 | { | ||
172 | u16 *keycode = fdtv->remote_ctrl_dev->keycode; | ||
173 | |||
174 | if (code >= 0x0300 && code <= 0x031f) | ||
175 | code = keycode[code - 0x0300]; | ||
176 | else if (code >= 0x0340 && code <= 0x0354) | ||
177 | code = keycode[code - 0x0320]; | ||
178 | else if (code >= 0x4501 && code <= 0x451f) | ||
179 | code = oldtable[code - 0x4501]; | ||
180 | else if (code >= 0x4540 && code <= 0x4542) | ||
181 | code = oldtable[code - 0x4521]; | ||
182 | else { | ||
183 | printk(KERN_DEBUG "firedtv: invalid key code 0x%04x " | ||
184 | "from remote control\n", code); | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | input_report_key(fdtv->remote_ctrl_dev, code, 1); | ||
189 | input_report_key(fdtv->remote_ctrl_dev, code, 0); | ||
190 | } | ||
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h new file mode 100644 index 000000000000..d48530b81e61 --- /dev/null +++ b/drivers/media/dvb/firewire/firedtv.h | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * FireDTV driver (formerly known as FireSAT) | ||
3 | * | ||
4 | * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com> | ||
5 | * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef _FIREDTV_H | ||
14 | #define _FIREDTV_H | ||
15 | |||
16 | #include <linux/dvb/dmx.h> | ||
17 | #include <linux/dvb/frontend.h> | ||
18 | #include <linux/list.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/spinlock_types.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | |||
25 | #include <demux.h> | ||
26 | #include <dmxdev.h> | ||
27 | #include <dvb_demux.h> | ||
28 | #include <dvb_frontend.h> | ||
29 | #include <dvb_net.h> | ||
30 | #include <dvbdev.h> | ||
31 | |||
32 | struct firedtv_tuner_status { | ||
33 | unsigned active_system:8; | ||
34 | unsigned searching:1; | ||
35 | unsigned moving:1; | ||
36 | unsigned no_rf:1; | ||
37 | unsigned input:1; | ||
38 | unsigned selected_antenna:7; | ||
39 | unsigned ber:32; | ||
40 | unsigned signal_strength:8; | ||
41 | unsigned raster_frequency:2; | ||
42 | unsigned rf_frequency:22; | ||
43 | unsigned man_dep_info_length:8; | ||
44 | unsigned front_end_error:1; | ||
45 | unsigned antenna_error:1; | ||
46 | unsigned front_end_power_status:1; | ||
47 | unsigned power_supply:1; | ||
48 | unsigned carrier_noise_ratio:16; | ||
49 | unsigned power_supply_voltage:8; | ||
50 | unsigned antenna_voltage:8; | ||
51 | unsigned firewire_bus_voltage:8; | ||
52 | unsigned ca_mmi:1; | ||
53 | unsigned ca_pmt_reply:1; | ||
54 | unsigned ca_date_time_request:1; | ||
55 | unsigned ca_application_info:1; | ||
56 | unsigned ca_module_present_status:1; | ||
57 | unsigned ca_dvb_flag:1; | ||
58 | unsigned ca_error_flag:1; | ||
59 | unsigned ca_initialization_status:1; | ||
60 | }; | ||
61 | |||
62 | enum model_type { | ||
63 | FIREDTV_UNKNOWN = 0, | ||
64 | FIREDTV_DVB_S = 1, | ||
65 | FIREDTV_DVB_C = 2, | ||
66 | FIREDTV_DVB_T = 3, | ||
67 | FIREDTV_DVB_S2 = 4, | ||
68 | }; | ||
69 | |||
70 | struct device; | ||
71 | struct input_dev; | ||
72 | struct firedtv; | ||
73 | |||
74 | struct firedtv_backend { | ||
75 | int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg); | ||
76 | int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len); | ||
77 | int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len); | ||
78 | int (*start_iso)(struct firedtv *fdtv); | ||
79 | void (*stop_iso)(struct firedtv *fdtv); | ||
80 | }; | ||
81 | |||
82 | struct firedtv { | ||
83 | struct device *device; | ||
84 | struct list_head list; | ||
85 | |||
86 | struct dvb_adapter adapter; | ||
87 | struct dmxdev dmxdev; | ||
88 | struct dvb_demux demux; | ||
89 | struct dmx_frontend frontend; | ||
90 | struct dvb_net dvbnet; | ||
91 | struct dvb_frontend fe; | ||
92 | |||
93 | struct dvb_device *cadev; | ||
94 | int ca_last_command; | ||
95 | int ca_time_interval; | ||
96 | |||
97 | struct mutex avc_mutex; | ||
98 | wait_queue_head_t avc_wait; | ||
99 | bool avc_reply_received; | ||
100 | struct work_struct remote_ctrl_work; | ||
101 | struct input_dev *remote_ctrl_dev; | ||
102 | |||
103 | enum model_type type; | ||
104 | char subunit; | ||
105 | char isochannel; | ||
106 | fe_sec_voltage_t voltage; | ||
107 | fe_sec_tone_mode_t tone; | ||
108 | |||
109 | const struct firedtv_backend *backend; | ||
110 | void *backend_data; | ||
111 | |||
112 | struct mutex demux_mutex; | ||
113 | unsigned long channel_active; | ||
114 | u16 channel_pid[16]; | ||
115 | |||
116 | size_t response_length; | ||
117 | u8 response[512]; | ||
118 | }; | ||
119 | |||
120 | /* firedtv-1394.c */ | ||
121 | #ifdef CONFIG_DVB_FIREDTV_IEEE1394 | ||
122 | int fdtv_1394_init(struct ieee1394_device_id id_table[]); | ||
123 | void fdtv_1394_exit(void); | ||
124 | #else | ||
125 | static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; } | ||
126 | static inline void fdtv_1394_exit(void) {} | ||
127 | #endif | ||
128 | |||
129 | /* firedtv-avc.c */ | ||
130 | int avc_recv(struct firedtv *fdtv, void *data, size_t length); | ||
131 | int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat); | ||
132 | struct dvb_frontend_parameters; | ||
133 | int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params); | ||
134 | int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]); | ||
135 | int avc_tuner_get_ts(struct firedtv *fdtv); | ||
136 | int avc_identify_subunit(struct firedtv *fdtv); | ||
137 | struct dvb_diseqc_master_cmd; | ||
138 | int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst, | ||
139 | char conttone, char nrdiseq, | ||
140 | struct dvb_diseqc_master_cmd *diseqcmd); | ||
141 | void avc_remote_ctrl_work(struct work_struct *work); | ||
142 | int avc_register_remote_control(struct firedtv *fdtv); | ||
143 | int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len); | ||
144 | int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len); | ||
145 | int avc_ca_reset(struct firedtv *fdtv); | ||
146 | int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length); | ||
147 | int avc_ca_get_time_date(struct firedtv *fdtv, int *interval); | ||
148 | int avc_ca_enter_menu(struct firedtv *fdtv); | ||
149 | int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len); | ||
150 | int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel); | ||
151 | void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel); | ||
152 | |||
153 | /* firedtv-ci.c */ | ||
154 | int fdtv_ca_register(struct firedtv *fdtv); | ||
155 | void fdtv_ca_release(struct firedtv *fdtv); | ||
156 | |||
157 | /* firedtv-dvb.c */ | ||
158 | int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
159 | int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed); | ||
160 | int fdtv_dvb_register(struct firedtv *fdtv); | ||
161 | void fdtv_dvb_unregister(struct firedtv *fdtv); | ||
162 | struct firedtv *fdtv_alloc(struct device *dev, | ||
163 | const struct firedtv_backend *backend, | ||
164 | const char *name, size_t name_len); | ||
165 | extern const char *fdtv_model_names[]; | ||
166 | |||
167 | /* firedtv-fe.c */ | ||
168 | void fdtv_frontend_init(struct firedtv *fdtv); | ||
169 | |||
170 | /* firedtv-rc.c */ | ||
171 | #ifdef CONFIG_DVB_FIREDTV_INPUT | ||
172 | int fdtv_register_rc(struct firedtv *fdtv, struct device *dev); | ||
173 | void fdtv_unregister_rc(struct firedtv *fdtv); | ||
174 | void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code); | ||
175 | #else | ||
176 | static inline int fdtv_register_rc(struct firedtv *fdtv, | ||
177 | struct device *dev) { return 0; } | ||
178 | static inline void fdtv_unregister_rc(struct firedtv *fdtv) {} | ||
179 | static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {} | ||
180 | #endif | ||
181 | |||
182 | #endif /* _FIREDTV_H */ | ||
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c index ec4e08dbc699..1e81e713df63 100644 --- a/drivers/media/dvb/frontends/drx397xD.c +++ b/drivers/media/dvb/frontends/drx397xD.c | |||
@@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s, | |||
646 | u32 edi = 0, ebx = 0, ebp = 0, edx = 0; | 646 | u32 edi = 0, ebx = 0, ebp = 0, edx = 0; |
647 | u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0; | 647 | u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0; |
648 | 648 | ||
649 | int rc, df_tuner; | 649 | int rc, df_tuner = 0; |
650 | int a, b, c, d; | 650 | int a, b, c, d; |
651 | pr_debug("%s %d\n", __func__, s->config.d60); | 651 | pr_debug("%s %d\n", __func__, s->config.d60); |
652 | 652 | ||
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c index cf4d8936bb83..3e08d985d6e5 100644 --- a/drivers/media/dvb/frontends/s5h1409.c +++ b/drivers/media/dvb/frontends/s5h1409.c | |||
@@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, | |||
545 | 545 | ||
546 | s5h1409_enable_modulation(fe, p->u.vsb.modulation); | 546 | s5h1409_enable_modulation(fe, p->u.vsb.modulation); |
547 | 547 | ||
548 | /* Allow the demod to settle */ | ||
549 | msleep(100); | ||
550 | |||
551 | if (fe->ops.tuner_ops.set_params) { | 548 | if (fe->ops.tuner_ops.set_params) { |
552 | if (fe->ops.i2c_gate_ctrl) | 549 | if (fe->ops.i2c_gate_ctrl) |
553 | fe->ops.i2c_gate_ctrl(fe, 1); | 550 | fe->ops.i2c_gate_ctrl(fe, 1); |
@@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe, | |||
562 | s5h1409_set_qam_interleave_mode(fe); | 559 | s5h1409_set_qam_interleave_mode(fe); |
563 | } | 560 | } |
564 | 561 | ||
562 | /* Issue a reset to the demod so it knows to resync against the | ||
563 | newly tuned frequency */ | ||
564 | s5h1409_softreset(fe); | ||
565 | |||
565 | return 0; | 566 | return 0; |
566 | } | 567 | } |
567 | 568 | ||
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index 83dc7e12d5f0..a67d1775a43c 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c | |||
@@ -31,6 +31,8 @@ inline u32 stb0899_do_div(u64 n, u32 d) | |||
31 | return n; | 31 | return n; |
32 | } | 32 | } |
33 | 33 | ||
34 | #if 0 | ||
35 | /* These functions are currently unused */ | ||
34 | /* | 36 | /* |
35 | * stb0899_calc_srate | 37 | * stb0899_calc_srate |
36 | * Compute symbol rate | 38 | * Compute symbol rate |
@@ -63,6 +65,7 @@ static u32 stb0899_get_srate(struct stb0899_state *state) | |||
63 | 65 | ||
64 | return stb0899_calc_srate(internal->master_clk, sfr); | 66 | return stb0899_calc_srate(internal->master_clk, sfr); |
65 | } | 67 | } |
68 | #endif | ||
66 | 69 | ||
67 | /* | 70 | /* |
68 | * stb0899_set_srate | 71 | * stb0899_set_srate |
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 1638e1d9f538..83e9e7750c8c 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
@@ -470,6 +470,7 @@ static void frontend_init(struct budget *budget) | |||
470 | budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); | 470 | budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); |
471 | if (budget->dvb_frontend) { | 471 | if (budget->dvb_frontend) { |
472 | budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; | 472 | budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; |
473 | budget->dvb_frontend->tuner_priv = NULL; | ||
473 | break; | 474 | break; |
474 | } | 475 | } |
475 | break; | 476 | break; |
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 0aa96df80fc2..d91e0638448f 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
@@ -1384,7 +1384,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) | |||
1384 | static int ttusb_dec_init_stb(struct ttusb_dec *dec) | 1384 | static int ttusb_dec_init_stb(struct ttusb_dec *dec) |
1385 | { | 1385 | { |
1386 | int result; | 1386 | int result; |
1387 | unsigned int mode, model, version; | 1387 | unsigned int mode = 0, model = 0, version = 0; |
1388 | 1388 | ||
1389 | dprintk("%s\n", __func__); | 1389 | dprintk("%s\n", __func__); |
1390 | 1390 | ||
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0747dc8862b0..fdfc7bf86b9e 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -194,10 +194,10 @@ static int amradio_start(struct amradio_device *radio) | |||
194 | return retval; | 194 | return retval; |
195 | } | 195 | } |
196 | 196 | ||
197 | mutex_unlock(&radio->lock); | ||
198 | |||
199 | radio->muted = 0; | 197 | radio->muted = 0; |
200 | 198 | ||
199 | mutex_unlock(&radio->lock); | ||
200 | |||
201 | return retval; | 201 | return retval; |
202 | } | 202 | } |
203 | 203 | ||
@@ -230,10 +230,10 @@ static int amradio_stop(struct amradio_device *radio) | |||
230 | return retval; | 230 | return retval; |
231 | } | 231 | } |
232 | 232 | ||
233 | mutex_unlock(&radio->lock); | ||
234 | |||
235 | radio->muted = 1; | 233 | radio->muted = 1; |
236 | 234 | ||
235 | mutex_unlock(&radio->lock); | ||
236 | |||
237 | return retval; | 237 | return retval; |
238 | } | 238 | } |
239 | 239 | ||
@@ -284,10 +284,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq) | |||
284 | return retval; | 284 | return retval; |
285 | } | 285 | } |
286 | 286 | ||
287 | mutex_unlock(&radio->lock); | ||
288 | |||
289 | radio->stereo = 0; | 287 | radio->stereo = 0; |
290 | 288 | ||
289 | mutex_unlock(&radio->lock); | ||
290 | |||
291 | return retval; | 291 | return retval; |
292 | } | 292 | } |
293 | 293 | ||
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 67cbce82cb91..4dfed6aa2dbc 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c | |||
@@ -98,11 +98,16 @@ | |||
98 | * - blacklisted KWorld radio in hid-core.c and hid-ids.h | 98 | * - blacklisted KWorld radio in hid-core.c and hid-ids.h |
99 | * 2008-12-03 Mark Lord <mlord@pobox.com> | 99 | * 2008-12-03 Mark Lord <mlord@pobox.com> |
100 | * - add support for DealExtreme USB Radio | 100 | * - add support for DealExtreme USB Radio |
101 | * 2009-01-31 Bob Ross <pigiron@gmx.com> | ||
102 | * - correction of stereo detection/setting | ||
103 | * - correction of signal strength indicator scaling | ||
104 | * 2009-01-31 Rick Bronson <rick@efn.org> | ||
105 | * Tobias Lorenz <tobias.lorenz@gmx.net> | ||
106 | * - add LED status output | ||
101 | * | 107 | * |
102 | * ToDo: | 108 | * ToDo: |
103 | * - add firmware download/update support | 109 | * - add firmware download/update support |
104 | * - RDS support: interrupt mode, instead of polling | 110 | * - RDS support: interrupt mode, instead of polling |
105 | * - add LED status output (check if that's not already done in firmware) | ||
106 | */ | 111 | */ |
107 | 112 | ||
108 | 113 | ||
@@ -882,6 +887,30 @@ static int si470x_rds_on(struct si470x_device *radio) | |||
882 | 887 | ||
883 | 888 | ||
884 | /************************************************************************** | 889 | /************************************************************************** |
890 | * General Driver Functions - LED_REPORT | ||
891 | **************************************************************************/ | ||
892 | |||
893 | /* | ||
894 | * si470x_set_led_state - sets the led state | ||
895 | */ | ||
896 | static int si470x_set_led_state(struct si470x_device *radio, | ||
897 | unsigned char led_state) | ||
898 | { | ||
899 | unsigned char buf[LED_REPORT_SIZE]; | ||
900 | int retval; | ||
901 | |||
902 | buf[0] = LED_REPORT; | ||
903 | buf[1] = LED_COMMAND; | ||
904 | buf[2] = led_state; | ||
905 | |||
906 | retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); | ||
907 | |||
908 | return (retval < 0) ? -EINVAL : 0; | ||
909 | } | ||
910 | |||
911 | |||
912 | |||
913 | /************************************************************************** | ||
885 | * RDS Driver Functions | 914 | * RDS Driver Functions |
886 | **************************************************************************/ | 915 | **************************************************************************/ |
887 | 916 | ||
@@ -1385,20 +1414,22 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, | |||
1385 | }; | 1414 | }; |
1386 | 1415 | ||
1387 | /* stereo indicator == stereo (instead of mono) */ | 1416 | /* stereo indicator == stereo (instead of mono) */ |
1388 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1) | 1417 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) |
1389 | tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
1390 | else | ||
1391 | tuner->rxsubchans = V4L2_TUNER_SUB_MONO; | 1418 | tuner->rxsubchans = V4L2_TUNER_SUB_MONO; |
1419 | else | ||
1420 | tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
1392 | 1421 | ||
1393 | /* mono/stereo selector */ | 1422 | /* mono/stereo selector */ |
1394 | if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1) | 1423 | if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0) |
1395 | tuner->audmode = V4L2_TUNER_MODE_MONO; | ||
1396 | else | ||
1397 | tuner->audmode = V4L2_TUNER_MODE_STEREO; | 1424 | tuner->audmode = V4L2_TUNER_MODE_STEREO; |
1425 | else | ||
1426 | tuner->audmode = V4L2_TUNER_MODE_MONO; | ||
1398 | 1427 | ||
1399 | /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ | 1428 | /* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */ |
1400 | tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI) | 1429 | /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */ |
1401 | * 0x0101; | 1430 | tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); |
1431 | /* the ideal factor is 0xffff/75 = 873,8 */ | ||
1432 | tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); | ||
1402 | 1433 | ||
1403 | /* automatic frequency control: -1: freq to low, 1 freq to high */ | 1434 | /* automatic frequency control: -1: freq to low, 1 freq to high */ |
1404 | /* AFCRL does only indicate that freq. differs, not if too low/high */ | 1435 | /* AFCRL does only indicate that freq. differs, not if too low/high */ |
@@ -1632,6 +1663,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, | |||
1632 | /* set initial frequency */ | 1663 | /* set initial frequency */ |
1633 | si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ | 1664 | si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ |
1634 | 1665 | ||
1666 | /* set led to connect state */ | ||
1667 | si470x_set_led_state(radio, BLINK_GREEN_LED); | ||
1668 | |||
1635 | /* rds buffer allocation */ | 1669 | /* rds buffer allocation */ |
1636 | radio->buf_size = rds_buf * 3; | 1670 | radio->buf_size = rds_buf * 3; |
1637 | radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); | 1671 | radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); |
@@ -1715,6 +1749,9 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) | |||
1715 | cancel_delayed_work_sync(&radio->work); | 1749 | cancel_delayed_work_sync(&radio->work); |
1716 | usb_set_intfdata(intf, NULL); | 1750 | usb_set_intfdata(intf, NULL); |
1717 | if (radio->users == 0) { | 1751 | if (radio->users == 0) { |
1752 | /* set led to disconnect state */ | ||
1753 | si470x_set_led_state(radio, BLINK_ORANGE_LED); | ||
1754 | |||
1718 | video_unregister_device(radio->videodev); | 1755 | video_unregister_device(radio->videodev); |
1719 | kfree(radio->buffer); | 1756 | kfree(radio->buffer); |
1720 | kfree(radio); | 1757 | kfree(radio); |
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 14bebf8a116f..87e91072627a 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c | |||
@@ -18,7 +18,6 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | 20 | ||
21 | #include <linux/version.h> | ||
22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
23 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
24 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 8f1db57bd1dd..bfe25841dbf4 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -1586,7 +1586,8 @@ static int mpeg_open(struct file *file) | |||
1586 | lock_kernel(); | 1586 | lock_kernel(); |
1587 | list_for_each(list, &cx23885_devlist) { | 1587 | list_for_each(list, &cx23885_devlist) { |
1588 | h = list_entry(list, struct cx23885_dev, devlist); | 1588 | h = list_entry(list, struct cx23885_dev, devlist); |
1589 | if (h->v4l_device->minor == minor) { | 1589 | if (h->v4l_device && |
1590 | h->v4l_device->minor == minor) { | ||
1590 | dev = h; | 1591 | dev = h; |
1591 | break; | 1592 | break; |
1592 | } | 1593 | } |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 2d81c4d04340..eaa11893bfe9 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -730,12 +730,13 @@ static int video_open(struct file *file) | |||
730 | lock_kernel(); | 730 | lock_kernel(); |
731 | list_for_each(list, &cx23885_devlist) { | 731 | list_for_each(list, &cx23885_devlist) { |
732 | h = list_entry(list, struct cx23885_dev, devlist); | 732 | h = list_entry(list, struct cx23885_dev, devlist); |
733 | if (h->video_dev->minor == minor) { | 733 | if (h->video_dev && |
734 | h->video_dev->minor == minor) { | ||
734 | dev = h; | 735 | dev = h; |
735 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 736 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
736 | } | 737 | } |
737 | if (h->vbi_dev && | 738 | if (h->vbi_dev && |
738 | h->vbi_dev->minor == minor) { | 739 | h->vbi_dev->minor == minor) { |
739 | dev = h; | 740 | dev = h; |
740 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | 741 | type = V4L2_BUF_TYPE_VBI_CAPTURE; |
741 | } | 742 | } |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 88f2fd32bfe3..25eb3bec9e5d 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -1382,6 +1382,14 @@ static int cx25840_log_status(struct v4l2_subdev *sd) | |||
1382 | 1382 | ||
1383 | static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) | 1383 | static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg) |
1384 | { | 1384 | { |
1385 | /* ignore this command */ | ||
1386 | if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG) | ||
1387 | return 0; | ||
1388 | |||
1389 | /* Old-style drivers rely on initialization on first use, so | ||
1390 | call the init whenever a command is issued to this driver. | ||
1391 | New-style drivers using v4l2_subdev should call init explicitly. */ | ||
1392 | cx25840_init(i2c_get_clientdata(client), 0); | ||
1385 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); | 1393 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); |
1386 | } | 1394 | } |
1387 | 1395 | ||
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 613dfea4ff3e..aef5297534af 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -614,34 +614,41 @@ static struct stv0288_config tevii_tuner_earda_config = { | |||
614 | .set_ts_params = cx24116_set_ts_param, | 614 | .set_ts_params = cx24116_set_ts_param, |
615 | }; | 615 | }; |
616 | 616 | ||
617 | static int dvb_register(struct cx8802_dev *dev) | 617 | static int cx8802_alloc_frontends(struct cx8802_dev *dev) |
618 | { | 618 | { |
619 | struct cx88_core *core = dev->core; | 619 | struct cx88_core *core = dev->core; |
620 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; | 620 | struct videobuf_dvb_frontend *fe = NULL; |
621 | int mfe_shared = 0; /* bus not shared by default */ | ||
622 | int i; | 621 | int i; |
623 | 622 | ||
624 | if (0 != core->i2c_rc) { | ||
625 | printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); | ||
626 | goto frontend_detach; | ||
627 | } | ||
628 | |||
629 | if (!core->board.num_frontends) | ||
630 | return -EINVAL; | ||
631 | |||
632 | mutex_init(&dev->frontends.lock); | 623 | mutex_init(&dev->frontends.lock); |
633 | INIT_LIST_HEAD(&dev->frontends.felist); | 624 | INIT_LIST_HEAD(&dev->frontends.felist); |
634 | 625 | ||
626 | if (!core->board.num_frontends) | ||
627 | return -ENODEV; | ||
628 | |||
635 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, | 629 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, |
636 | core->board.num_frontends); | 630 | core->board.num_frontends); |
637 | for (i = 1; i <= core->board.num_frontends; i++) { | 631 | for (i = 1; i <= core->board.num_frontends; i++) { |
638 | fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, i); | 632 | fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); |
639 | if (!fe0) { | 633 | if (!fe) { |
640 | printk(KERN_ERR "%s() failed to alloc\n", __func__); | 634 | printk(KERN_ERR "%s() failed to alloc\n", __func__); |
641 | videobuf_dvb_dealloc_frontends(&dev->frontends); | 635 | videobuf_dvb_dealloc_frontends(&dev->frontends); |
642 | goto frontend_detach; | 636 | return -ENOMEM; |
643 | } | 637 | } |
644 | } | 638 | } |
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static int dvb_register(struct cx8802_dev *dev) | ||
643 | { | ||
644 | struct cx88_core *core = dev->core; | ||
645 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; | ||
646 | int mfe_shared = 0; /* bus not shared by default */ | ||
647 | |||
648 | if (0 != core->i2c_rc) { | ||
649 | printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); | ||
650 | goto frontend_detach; | ||
651 | } | ||
645 | 652 | ||
646 | /* Get the first frontend */ | 653 | /* Get the first frontend */ |
647 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | 654 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); |
@@ -1243,6 +1250,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
1243 | struct cx88_core *core = drv->core; | 1250 | struct cx88_core *core = drv->core; |
1244 | struct cx8802_dev *dev = drv->core->dvbdev; | 1251 | struct cx8802_dev *dev = drv->core->dvbdev; |
1245 | int err; | 1252 | int err; |
1253 | struct videobuf_dvb_frontend *fe; | ||
1254 | int i; | ||
1246 | 1255 | ||
1247 | dprintk( 1, "%s\n", __func__); | 1256 | dprintk( 1, "%s\n", __func__); |
1248 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", | 1257 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
@@ -1258,39 +1267,34 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
1258 | /* If vp3054 isn't enabled, a stub will just return 0 */ | 1267 | /* If vp3054 isn't enabled, a stub will just return 0 */ |
1259 | err = vp3054_i2c_probe(dev); | 1268 | err = vp3054_i2c_probe(dev); |
1260 | if (0 != err) | 1269 | if (0 != err) |
1261 | goto fail_probe; | 1270 | goto fail_core; |
1262 | 1271 | ||
1263 | /* dvb stuff */ | 1272 | /* dvb stuff */ |
1264 | printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); | 1273 | printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); |
1265 | dev->ts_gen_cntrl = 0x0c; | 1274 | dev->ts_gen_cntrl = 0x0c; |
1266 | 1275 | ||
1276 | err = cx8802_alloc_frontends(dev); | ||
1277 | if (err) | ||
1278 | goto fail_core; | ||
1279 | |||
1267 | err = -ENODEV; | 1280 | err = -ENODEV; |
1268 | if (core->board.num_frontends) { | 1281 | for (i = 1; i <= core->board.num_frontends; i++) { |
1269 | struct videobuf_dvb_frontend *fe; | 1282 | fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); |
1270 | int i; | 1283 | if (fe == NULL) { |
1271 | 1284 | printk(KERN_ERR "%s() failed to get frontend(%d)\n", | |
1272 | for (i = 1; i <= core->board.num_frontends; i++) { | ||
1273 | fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); | ||
1274 | if (fe == NULL) { | ||
1275 | printk(KERN_ERR "%s() failed to get frontend(%d)\n", | ||
1276 | __func__, i); | 1285 | __func__, i); |
1277 | goto fail_probe; | 1286 | goto fail_probe; |
1278 | } | 1287 | } |
1279 | videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, | 1288 | videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, |
1280 | &dev->pci->dev, &dev->slock, | 1289 | &dev->pci->dev, &dev->slock, |
1281 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1290 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
1282 | V4L2_FIELD_TOP, | 1291 | V4L2_FIELD_TOP, |
1283 | sizeof(struct cx88_buffer), | 1292 | sizeof(struct cx88_buffer), |
1284 | dev); | 1293 | dev); |
1285 | /* init struct videobuf_dvb */ | 1294 | /* init struct videobuf_dvb */ |
1286 | fe->dvb.name = dev->core->name; | 1295 | fe->dvb.name = dev->core->name; |
1287 | } | ||
1288 | } else { | ||
1289 | /* no frontends allocated */ | ||
1290 | printk(KERN_ERR "%s/2 .num_frontends should be non-zero\n", | ||
1291 | core->name); | ||
1292 | goto fail_core; | ||
1293 | } | 1296 | } |
1297 | |||
1294 | err = dvb_register(dev); | 1298 | err = dvb_register(dev); |
1295 | if (err) | 1299 | if (err) |
1296 | /* frontends/adapter de-allocated in dvb_register */ | 1300 | /* frontends/adapter de-allocated in dvb_register */ |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 60a8b3187f14..6025fdd23344 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -336,8 +336,8 @@ struct cx88_core { | |||
336 | /* config info -- dvb */ | 336 | /* config info -- dvb */ |
337 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) | 337 | #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) |
338 | int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); | 338 | int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); |
339 | void (*gate_ctrl)(struct cx88_core *core, int open); | ||
340 | #endif | 339 | #endif |
340 | void (*gate_ctrl)(struct cx88_core *core, int open); | ||
341 | 341 | ||
342 | /* state info */ | 342 | /* state info */ |
343 | struct task_struct *kthread; | 343 | struct task_struct *kthread; |
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 94378ccb7505..2ac738fa6a07 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -62,9 +62,15 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) | |||
62 | 62 | ||
63 | dprintk("Stopping isoc\n"); | 63 | dprintk("Stopping isoc\n"); |
64 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | 64 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { |
65 | usb_unlink_urb(dev->adev.urb[i]); | 65 | if (!irqs_disabled()) |
66 | usb_kill_urb(dev->adev.urb[i]); | ||
67 | else | ||
68 | usb_unlink_urb(dev->adev.urb[i]); | ||
66 | usb_free_urb(dev->adev.urb[i]); | 69 | usb_free_urb(dev->adev.urb[i]); |
67 | dev->adev.urb[i] = NULL; | 70 | dev->adev.urb[i] = NULL; |
71 | |||
72 | kfree(dev->adev.transfer_buffer[i]); | ||
73 | dev->adev.transfer_buffer[i] = NULL; | ||
68 | } | 74 | } |
69 | 75 | ||
70 | return 0; | 76 | return 0; |
@@ -389,11 +395,15 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream, | |||
389 | static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream | 395 | static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream |
390 | *substream) | 396 | *substream) |
391 | { | 397 | { |
392 | struct em28xx *dev; | 398 | unsigned long flags; |
393 | 399 | ||
400 | struct em28xx *dev; | ||
394 | snd_pcm_uframes_t hwptr_done; | 401 | snd_pcm_uframes_t hwptr_done; |
402 | |||
395 | dev = snd_pcm_substream_chip(substream); | 403 | dev = snd_pcm_substream_chip(substream); |
404 | spin_lock_irqsave(&dev->adev.slock, flags); | ||
396 | hwptr_done = dev->adev.hwptr_done_capture; | 405 | hwptr_done = dev->adev.hwptr_done_capture; |
406 | spin_unlock_irqrestore(&dev->adev.slock, flags); | ||
397 | 407 | ||
398 | return hwptr_done; | 408 | return hwptr_done; |
399 | } | 409 | } |
@@ -453,6 +463,8 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
453 | pcm->info_flags = 0; | 463 | pcm->info_flags = 0; |
454 | pcm->private_data = dev; | 464 | pcm->private_data = dev; |
455 | strcpy(pcm->name, "Empia 28xx Capture"); | 465 | strcpy(pcm->name, "Empia 28xx Capture"); |
466 | |||
467 | snd_card_set_dev(card, &dev->udev->dev); | ||
456 | strcpy(card->driver, "Empia Em28xx Audio"); | 468 | strcpy(card->driver, "Empia Em28xx Audio"); |
457 | strcpy(card->shortname, "Em28xx Audio"); | 469 | strcpy(card->shortname, "Em28xx Audio"); |
458 | strcpy(card->longname, "Empia Em28xx Audio"); | 470 | strcpy(card->longname, "Empia Em28xx Audio"); |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ef9bf008a924..3b3ca3f46d52 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -102,6 +102,18 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { | |||
102 | /* Board - EM2870 Kworld 355u | 102 | /* Board - EM2870 Kworld 355u |
103 | Analog - No input analog */ | 103 | Analog - No input analog */ |
104 | 104 | ||
105 | static struct em28xx_reg_seq kworld_330u_analog[] = { | ||
106 | {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, | ||
107 | {EM2880_R04_GPO, 0x00, 0xff, 10}, | ||
108 | { -1, -1, -1, -1}, | ||
109 | }; | ||
110 | |||
111 | static struct em28xx_reg_seq kworld_330u_digital[] = { | ||
112 | {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, | ||
113 | {EM2880_R04_GPO, 0x08, 0xff, 10}, | ||
114 | { -1, -1, -1, -1}, | ||
115 | }; | ||
116 | |||
105 | /* Callback for the most boards */ | 117 | /* Callback for the most boards */ |
106 | static struct em28xx_reg_seq default_tuner_gpio[] = { | 118 | static struct em28xx_reg_seq default_tuner_gpio[] = { |
107 | {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, | 119 | {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, |
@@ -1177,29 +1189,33 @@ struct em28xx_board em28xx_boards[] = { | |||
1177 | .gpio = hauppauge_wintv_hvr_900_analog, | 1189 | .gpio = hauppauge_wintv_hvr_900_analog, |
1178 | } }, | 1190 | } }, |
1179 | }, | 1191 | }, |
1180 | [EM2883_BOARD_KWORLD_HYBRID_A316] = { | 1192 | [EM2883_BOARD_KWORLD_HYBRID_330U] = { |
1181 | .name = "Kworld PlusTV HD Hybrid 330", | 1193 | .name = "Kworld PlusTV HD Hybrid 330", |
1182 | .tuner_type = TUNER_XC2028, | 1194 | .tuner_type = TUNER_XC2028, |
1183 | .tuner_gpio = default_tuner_gpio, | 1195 | .tuner_gpio = default_tuner_gpio, |
1184 | .decoder = EM28XX_TVP5150, | 1196 | .decoder = EM28XX_TVP5150, |
1185 | .mts_firmware = 1, | 1197 | .mts_firmware = 1, |
1186 | .has_dvb = 1, | 1198 | .has_dvb = 1, |
1187 | .dvb_gpio = default_digital, | 1199 | .dvb_gpio = kworld_330u_digital, |
1200 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, | ||
1201 | .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID, | ||
1188 | .input = { { | 1202 | .input = { { |
1189 | .type = EM28XX_VMUX_TELEVISION, | 1203 | .type = EM28XX_VMUX_TELEVISION, |
1190 | .vmux = TVP5150_COMPOSITE0, | 1204 | .vmux = TVP5150_COMPOSITE0, |
1191 | .amux = EM28XX_AMUX_VIDEO, | 1205 | .amux = EM28XX_AMUX_VIDEO, |
1192 | .gpio = default_analog, | 1206 | .gpio = kworld_330u_analog, |
1207 | .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, | ||
1193 | }, { | 1208 | }, { |
1194 | .type = EM28XX_VMUX_COMPOSITE1, | 1209 | .type = EM28XX_VMUX_COMPOSITE1, |
1195 | .vmux = TVP5150_COMPOSITE1, | 1210 | .vmux = TVP5150_COMPOSITE1, |
1196 | .amux = EM28XX_AMUX_LINE_IN, | 1211 | .amux = EM28XX_AMUX_LINE_IN, |
1197 | .gpio = hauppauge_wintv_hvr_900_analog, | 1212 | .gpio = kworld_330u_analog, |
1213 | .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, | ||
1198 | }, { | 1214 | }, { |
1199 | .type = EM28XX_VMUX_SVIDEO, | 1215 | .type = EM28XX_VMUX_SVIDEO, |
1200 | .vmux = TVP5150_SVIDEO, | 1216 | .vmux = TVP5150_SVIDEO, |
1201 | .amux = EM28XX_AMUX_LINE_IN, | 1217 | .amux = EM28XX_AMUX_LINE_IN, |
1202 | .gpio = hauppauge_wintv_hvr_900_analog, | 1218 | .gpio = kworld_330u_analog, |
1203 | } }, | 1219 | } }, |
1204 | }, | 1220 | }, |
1205 | [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { | 1221 | [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = { |
@@ -1249,7 +1265,7 @@ struct usb_device_id em28xx_id_table [] = { | |||
1249 | { USB_DEVICE(0xeb1a, 0xe310), | 1265 | { USB_DEVICE(0xeb1a, 0xe310), |
1250 | .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD }, | 1266 | .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD }, |
1251 | { USB_DEVICE(0xeb1a, 0xa316), | 1267 | { USB_DEVICE(0xeb1a, 0xa316), |
1252 | .driver_info = EM2883_BOARD_KWORLD_HYBRID_A316 }, | 1268 | .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U }, |
1253 | { USB_DEVICE(0xeb1a, 0xe320), | 1269 | { USB_DEVICE(0xeb1a, 0xe320), |
1254 | .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II }, | 1270 | .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II }, |
1255 | { USB_DEVICE(0xeb1a, 0xe323), | 1271 | { USB_DEVICE(0xeb1a, 0xe323), |
@@ -1526,6 +1542,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
1526 | /* FIXME: Better to specify the needed IF */ | 1542 | /* FIXME: Better to specify the needed IF */ |
1527 | ctl->demod = XC3028_FE_DEFAULT; | 1543 | ctl->demod = XC3028_FE_DEFAULT; |
1528 | break; | 1544 | break; |
1545 | case EM2883_BOARD_KWORLD_HYBRID_330U: | ||
1546 | ctl->demod = XC3028_FE_CHINA; | ||
1547 | ctl->fname = XC2028_DEFAULT_FIRMWARE; | ||
1548 | break; | ||
1529 | default: | 1549 | default: |
1530 | ctl->demod = XC3028_FE_OREN538; | 1550 | ctl->demod = XC3028_FE_OREN538; |
1531 | } | 1551 | } |
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index eb5fb05fab22..94fb1b639a2e 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -438,6 +438,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) | |||
438 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { | 438 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { |
439 | int vol; | 439 | int vol; |
440 | 440 | ||
441 | em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200); | ||
442 | em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031); | ||
443 | em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80); | ||
444 | |||
441 | /* LSB: left channel - both channels with the same level */ | 445 | /* LSB: left channel - both channels with the same level */ |
442 | vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); | 446 | vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); |
443 | 447 | ||
@@ -454,6 +458,15 @@ int em28xx_audio_analog_set(struct em28xx *dev) | |||
454 | em28xx_warn("couldn't setup AC97 register %d\n", | 458 | em28xx_warn("couldn't setup AC97 register %d\n", |
455 | outputs[i].reg); | 459 | outputs[i].reg); |
456 | } | 460 | } |
461 | |||
462 | if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) { | ||
463 | int sel = ac97_return_record_select(dev->ctl_aoutput); | ||
464 | |||
465 | /* Use the same input for both left and right channels */ | ||
466 | sel |= (sel << 8); | ||
467 | |||
468 | em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel); | ||
469 | } | ||
457 | } | 470 | } |
458 | 471 | ||
459 | return ret; | 472 | return ret; |
@@ -847,8 +860,11 @@ void em28xx_uninit_isoc(struct em28xx *dev) | |||
847 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | 860 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { |
848 | urb = dev->isoc_ctl.urb[i]; | 861 | urb = dev->isoc_ctl.urb[i]; |
849 | if (urb) { | 862 | if (urb) { |
850 | usb_kill_urb(urb); | 863 | if (!irqs_disabled()) |
851 | usb_unlink_urb(urb); | 864 | usb_kill_urb(urb); |
865 | else | ||
866 | usb_unlink_urb(urb); | ||
867 | |||
852 | if (dev->isoc_ctl.transfer_buffer[i]) { | 868 | if (dev->isoc_ctl.transfer_buffer[i]) { |
853 | usb_buffer_free(dev->udev, | 869 | usb_buffer_free(dev->udev, |
854 | urb->transfer_buffer_length, | 870 | urb->transfer_buffer_length, |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index d38cb21834d9..9ad8527b3fda 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -28,6 +28,7 @@ | |||
28 | 28 | ||
29 | #include "lgdt330x.h" | 29 | #include "lgdt330x.h" |
30 | #include "zl10353.h" | 30 | #include "zl10353.h" |
31 | #include "s5h1409.h" | ||
31 | #ifdef EM28XX_DRX397XD_SUPPORT | 32 | #ifdef EM28XX_DRX397XD_SUPPORT |
32 | #include "drx397xD.h" | 33 | #include "drx397xD.h" |
33 | #endif | 34 | #endif |
@@ -232,6 +233,15 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = { | |||
232 | .if2 = 45600, | 233 | .if2 = 45600, |
233 | }; | 234 | }; |
234 | 235 | ||
236 | static struct s5h1409_config em28xx_s5h1409_with_xc3028 = { | ||
237 | .demod_address = 0x32 >> 1, | ||
238 | .output_mode = S5H1409_PARALLEL_OUTPUT, | ||
239 | .gpio = S5H1409_GPIO_OFF, | ||
240 | .inversion = S5H1409_INVERSION_OFF, | ||
241 | .status_mode = S5H1409_DEMODLOCKING, | ||
242 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | ||
243 | }; | ||
244 | |||
235 | #ifdef EM28XX_DRX397XD_SUPPORT | 245 | #ifdef EM28XX_DRX397XD_SUPPORT |
236 | /* [TODO] djh - not sure yet what the device config needs to contain */ | 246 | /* [TODO] djh - not sure yet what the device config needs to contain */ |
237 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { | 247 | static struct drx397xD_config em28xx_drx397xD_with_xc3028 = { |
@@ -412,7 +422,6 @@ static int dvb_init(struct em28xx *dev) | |||
412 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: | 422 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850: |
413 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: | 423 | case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: |
414 | case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: | 424 | case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: |
415 | case EM2883_BOARD_KWORLD_HYBRID_A316: | ||
416 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: | 425 | case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: |
417 | dvb->frontend = dvb_attach(lgdt330x_attach, | 426 | dvb->frontend = dvb_attach(lgdt330x_attach, |
418 | &em2880_lgdt3303_dev, | 427 | &em2880_lgdt3303_dev, |
@@ -433,6 +442,15 @@ static int dvb_init(struct em28xx *dev) | |||
433 | goto out_free; | 442 | goto out_free; |
434 | } | 443 | } |
435 | break; | 444 | break; |
445 | case EM2883_BOARD_KWORLD_HYBRID_330U: | ||
446 | dvb->frontend = dvb_attach(s5h1409_attach, | ||
447 | &em28xx_s5h1409_with_xc3028, | ||
448 | &dev->i2c_adap); | ||
449 | if (attach_xc3028(0x61, dev) < 0) { | ||
450 | result = -EINVAL; | ||
451 | goto out_free; | ||
452 | } | ||
453 | break; | ||
436 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: | 454 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: |
437 | #ifdef EM28XX_DRX397XD_SUPPORT | 455 | #ifdef EM28XX_DRX397XD_SUPPORT |
438 | /* We don't have the config structure properly populated, so | 456 | /* We don't have the config structure properly populated, so |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 416b691c33c1..8e61b2ca9167 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -886,10 +886,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
886 | if (0 == INPUT(i)->type) | 886 | if (0 == INPUT(i)->type) |
887 | return -EINVAL; | 887 | return -EINVAL; |
888 | 888 | ||
889 | mutex_lock(&dev->lock); | 889 | dev->ctl_input = i; |
890 | |||
891 | video_mux(dev, i); | ||
892 | 890 | ||
891 | mutex_lock(&dev->lock); | ||
892 | video_mux(dev, dev->ctl_input); | ||
893 | mutex_unlock(&dev->lock); | 893 | mutex_unlock(&dev->lock); |
894 | return 0; | 894 | return 0; |
895 | } | 895 | } |
@@ -939,6 +939,12 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) | |||
939 | struct em28xx_fh *fh = priv; | 939 | struct em28xx_fh *fh = priv; |
940 | struct em28xx *dev = fh->dev; | 940 | struct em28xx *dev = fh->dev; |
941 | 941 | ||
942 | |||
943 | if (a->index >= MAX_EM28XX_INPUT) | ||
944 | return -EINVAL; | ||
945 | if (0 == INPUT(a->index)->type) | ||
946 | return -EINVAL; | ||
947 | |||
942 | mutex_lock(&dev->lock); | 948 | mutex_lock(&dev->lock); |
943 | 949 | ||
944 | dev->ctl_ainput = INPUT(a->index)->amux; | 950 | dev->ctl_ainput = INPUT(a->index)->amux; |
@@ -1950,6 +1956,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
1950 | 1956 | ||
1951 | int em28xx_register_analog_devices(struct em28xx *dev) | 1957 | int em28xx_register_analog_devices(struct em28xx *dev) |
1952 | { | 1958 | { |
1959 | u8 val; | ||
1953 | int ret; | 1960 | int ret; |
1954 | 1961 | ||
1955 | printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", | 1962 | printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n", |
@@ -1957,34 +1964,34 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
1957 | (EM28XX_VERSION_CODE >> 16) & 0xff, | 1964 | (EM28XX_VERSION_CODE >> 16) & 0xff, |
1958 | (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); | 1965 | (EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff); |
1959 | 1966 | ||
1967 | /* set default norm */ | ||
1968 | dev->norm = em28xx_video_template.current_norm; | ||
1969 | dev->width = norm_maxw(dev); | ||
1970 | dev->height = norm_maxh(dev); | ||
1971 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | ||
1972 | dev->hscale = 0; | ||
1973 | dev->vscale = 0; | ||
1974 | dev->ctl_input = 0; | ||
1975 | |||
1960 | /* Analog specific initialization */ | 1976 | /* Analog specific initialization */ |
1961 | dev->format = &format[0]; | 1977 | dev->format = &format[0]; |
1962 | video_mux(dev, 0); | 1978 | video_mux(dev, dev->ctl_input); |
1979 | |||
1980 | /* Audio defaults */ | ||
1981 | dev->mute = 1; | ||
1982 | dev->volume = 0x1f; | ||
1963 | 1983 | ||
1964 | /* enable vbi capturing */ | 1984 | /* enable vbi capturing */ |
1965 | 1985 | ||
1966 | /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ | 1986 | /* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */ |
1967 | /* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */ | 1987 | val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK); |
1988 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val)); | ||
1968 | em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); | 1989 | em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51); |
1969 | 1990 | ||
1970 | dev->mute = 1; /* maybe not the right place... */ | ||
1971 | dev->volume = 0x1f; | ||
1972 | |||
1973 | em28xx_set_outfmt(dev); | 1991 | em28xx_set_outfmt(dev); |
1974 | em28xx_colorlevels_set_default(dev); | 1992 | em28xx_colorlevels_set_default(dev); |
1975 | em28xx_compression_disable(dev); | 1993 | em28xx_compression_disable(dev); |
1976 | 1994 | ||
1977 | /* set default norm */ | ||
1978 | dev->norm = em28xx_video_template.current_norm; | ||
1979 | dev->width = norm_maxw(dev); | ||
1980 | dev->height = norm_maxh(dev); | ||
1981 | dev->interlaced = EM28XX_INTERLACED_DEFAULT; | ||
1982 | dev->hscale = 0; | ||
1983 | dev->vscale = 0; | ||
1984 | |||
1985 | /* FIXME: This is a very bad hack! Not all devices have TV on input 2 */ | ||
1986 | dev->ctl_input = 2; | ||
1987 | |||
1988 | /* allocate and fill video video_device struct */ | 1995 | /* allocate and fill video video_device struct */ |
1989 | dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); | 1996 | dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); |
1990 | if (!dev->vdev) { | 1997 | if (!dev->vdev) { |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 6c6b94aa05b2..dd2cd36fb1bb 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -94,7 +94,7 @@ | |||
94 | #define EM2882_BOARD_KWORLD_VS_DVBT 54 | 94 | #define EM2882_BOARD_KWORLD_VS_DVBT 54 |
95 | #define EM2882_BOARD_TERRATEC_HYBRID_XS 55 | 95 | #define EM2882_BOARD_TERRATEC_HYBRID_XS 55 |
96 | #define EM2882_BOARD_PINNACLE_HYBRID_PRO 56 | 96 | #define EM2882_BOARD_PINNACLE_HYBRID_PRO 56 |
97 | #define EM2883_BOARD_KWORLD_HYBRID_A316 57 | 97 | #define EM2883_BOARD_KWORLD_HYBRID_330U 57 |
98 | #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 | 98 | #define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58 |
99 | #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 | 99 | #define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60 |
100 | #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 | 100 | #define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61 |
@@ -300,13 +300,32 @@ enum em28xx_amux { | |||
300 | }; | 300 | }; |
301 | 301 | ||
302 | enum em28xx_aout { | 302 | enum em28xx_aout { |
303 | /* AC97 outputs */ | ||
303 | EM28XX_AOUT_MASTER = 1 << 0, | 304 | EM28XX_AOUT_MASTER = 1 << 0, |
304 | EM28XX_AOUT_LINE = 1 << 1, | 305 | EM28XX_AOUT_LINE = 1 << 1, |
305 | EM28XX_AOUT_MONO = 1 << 2, | 306 | EM28XX_AOUT_MONO = 1 << 2, |
306 | EM28XX_AOUT_LFE = 1 << 3, | 307 | EM28XX_AOUT_LFE = 1 << 3, |
307 | EM28XX_AOUT_SURR = 1 << 4, | 308 | EM28XX_AOUT_SURR = 1 << 4, |
309 | |||
310 | /* PCM IN Mixer - used by AC97_RECORD_SELECT register */ | ||
311 | EM28XX_AOUT_PCM_IN = 1 << 7, | ||
312 | |||
313 | /* Bits 10-8 are used to indicate the PCM IN record select */ | ||
314 | EM28XX_AOUT_PCM_MIC_PCM = 0 << 8, | ||
315 | EM28XX_AOUT_PCM_CD = 1 << 8, | ||
316 | EM28XX_AOUT_PCM_VIDEO = 2 << 8, | ||
317 | EM28XX_AOUT_PCM_AUX = 3 << 8, | ||
318 | EM28XX_AOUT_PCM_LINE = 4 << 8, | ||
319 | EM28XX_AOUT_PCM_STEREO = 5 << 8, | ||
320 | EM28XX_AOUT_PCM_MONO = 6 << 8, | ||
321 | EM28XX_AOUT_PCM_PHONE = 7 << 8, | ||
308 | }; | 322 | }; |
309 | 323 | ||
324 | static inline int ac97_return_record_select(int a_out) | ||
325 | { | ||
326 | return (a_out & 0x700) >> 8; | ||
327 | } | ||
328 | |||
310 | struct em28xx_reg_seq { | 329 | struct em28xx_reg_seq { |
311 | int reg; | 330 | int reg; |
312 | unsigned char val, mask; | 331 | unsigned char val, mask; |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 5e36b9a4ae3e..65e4901f4db7 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -422,8 +422,10 @@ static void destroy_urbs(struct gspca_dev *gspca_dev) | |||
422 | if (urb == NULL) | 422 | if (urb == NULL) |
423 | break; | 423 | break; |
424 | 424 | ||
425 | BUG_ON(!gspca_dev->dev); | ||
425 | gspca_dev->urb[i] = NULL; | 426 | gspca_dev->urb[i] = NULL; |
426 | usb_kill_urb(urb); | 427 | if (!gspca_dev->present) |
428 | usb_kill_urb(urb); | ||
427 | if (urb->transfer_buffer != NULL) | 429 | if (urb->transfer_buffer != NULL) |
428 | usb_buffer_free(gspca_dev->dev, | 430 | usb_buffer_free(gspca_dev->dev, |
429 | urb->transfer_buffer_length, | 431 | urb->transfer_buffer_length, |
@@ -1949,9 +1951,12 @@ void gspca_disconnect(struct usb_interface *intf) | |||
1949 | { | 1951 | { |
1950 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); | 1952 | struct gspca_dev *gspca_dev = usb_get_intfdata(intf); |
1951 | 1953 | ||
1954 | mutex_lock(&gspca_dev->usb_lock); | ||
1952 | gspca_dev->present = 0; | 1955 | gspca_dev->present = 0; |
1953 | gspca_dev->streaming = 0; | 1956 | mutex_unlock(&gspca_dev->usb_lock); |
1954 | 1957 | ||
1958 | destroy_urbs(gspca_dev); | ||
1959 | gspca_dev->dev = NULL; | ||
1955 | usb_set_intfdata(intf, NULL); | 1960 | usb_set_intfdata(intf, NULL); |
1956 | 1961 | ||
1957 | /* release the device */ | 1962 | /* release the device */ |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e8e5921cdc34..c46c990987f9 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -949,8 +949,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
949 | itv->instance = atomic_inc_return(&ivtv_instance) - 1; | 949 | itv->instance = atomic_inc_return(&ivtv_instance) - 1; |
950 | 950 | ||
951 | retval = v4l2_device_register(&dev->dev, &itv->device); | 951 | retval = v4l2_device_register(&dev->dev, &itv->device); |
952 | if (retval) | 952 | if (retval) { |
953 | kfree(itv); | ||
953 | return retval; | 954 | return retval; |
955 | } | ||
954 | /* "ivtv + PCI ID" is a bit of a mouthful, so use | 956 | /* "ivtv + PCI ID" is a bit of a mouthful, so use |
955 | "ivtv + instance" instead. */ | 957 | "ivtv + instance" instead. */ |
956 | snprintf(itv->device.name, sizeof(itv->device.name), | 958 | snprintf(itv->device.name, sizeof(itv->device.name), |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index f6b3ef6e691b..c13bd2aa0bea 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo | |||
393 | return 0; | 393 | return 0; |
394 | } | 394 | } |
395 | 395 | ||
396 | v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt); | 396 | v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt); |
397 | vbifmt->service_set = ivtv_get_service_set(vbifmt); | 397 | vbifmt->service_set = ivtv_get_service_set(vbifmt); |
398 | return 0; | 398 | return 0; |
399 | } | 399 | } |
@@ -1748,6 +1748,18 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg) | |||
1748 | break; | 1748 | break; |
1749 | } | 1749 | } |
1750 | 1750 | ||
1751 | case IVTV_IOC_DMA_FRAME: | ||
1752 | case VIDEO_GET_PTS: | ||
1753 | case VIDEO_GET_FRAME_COUNT: | ||
1754 | case VIDEO_GET_EVENT: | ||
1755 | case VIDEO_PLAY: | ||
1756 | case VIDEO_STOP: | ||
1757 | case VIDEO_FREEZE: | ||
1758 | case VIDEO_CONTINUE: | ||
1759 | case VIDEO_COMMAND: | ||
1760 | case VIDEO_TRY_COMMAND: | ||
1761 | return ivtv_decoder_ioctls(file, cmd, (void *)arg); | ||
1762 | |||
1751 | default: | 1763 | default: |
1752 | return -EINVAL; | 1764 | return -EINVAL; |
1753 | } | 1765 | } |
@@ -1790,18 +1802,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp, | |||
1790 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); | 1802 | ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); |
1791 | return 0; | 1803 | return 0; |
1792 | 1804 | ||
1793 | case IVTV_IOC_DMA_FRAME: | ||
1794 | case VIDEO_GET_PTS: | ||
1795 | case VIDEO_GET_FRAME_COUNT: | ||
1796 | case VIDEO_GET_EVENT: | ||
1797 | case VIDEO_PLAY: | ||
1798 | case VIDEO_STOP: | ||
1799 | case VIDEO_FREEZE: | ||
1800 | case VIDEO_CONTINUE: | ||
1801 | case VIDEO_COMMAND: | ||
1802 | case VIDEO_TRY_COMMAND: | ||
1803 | return ivtv_decoder_ioctls(filp, cmd, (void *)arg); | ||
1804 | |||
1805 | default: | 1805 | default: |
1806 | break; | 1806 | break; |
1807 | } | 1807 | } |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 39fbc970f43d..0d810189dd87 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/poll.h> | 62 | #include <linux/poll.h> |
63 | #include <linux/slab.h> | 63 | #include <linux/slab.h> |
64 | #include <linux/vmalloc.h> | 64 | #include <linux/vmalloc.h> |
65 | #include <linux/version.h> | ||
66 | #include <asm/io.h> | 65 | #include <asm/io.h> |
67 | 66 | ||
68 | #include "pwc.h" | 67 | #include "pwc.h" |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index a1d6008efcbb..07c334f25aae 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -1155,23 +1155,23 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1155 | { | 1155 | { |
1156 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1156 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
1157 | struct pxa_camera_dev *pcdev = ici->priv; | 1157 | struct pxa_camera_dev *pcdev = ici->priv; |
1158 | const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL; | 1158 | const struct soc_camera_data_format *cam_fmt = NULL; |
1159 | const struct soc_camera_format_xlate *xlate; | 1159 | const struct soc_camera_format_xlate *xlate = NULL; |
1160 | struct soc_camera_sense sense = { | 1160 | struct soc_camera_sense sense = { |
1161 | .master_clock = pcdev->mclk, | 1161 | .master_clock = pcdev->mclk, |
1162 | .pixel_clock_max = pcdev->ciclk / 4, | 1162 | .pixel_clock_max = pcdev->ciclk / 4, |
1163 | }; | 1163 | }; |
1164 | int ret, buswidth; | 1164 | int ret; |
1165 | 1165 | ||
1166 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 1166 | if (pixfmt) { |
1167 | if (!xlate) { | 1167 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
1168 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); | 1168 | if (!xlate) { |
1169 | return -EINVAL; | 1169 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); |
1170 | } | 1170 | return -EINVAL; |
1171 | } | ||
1171 | 1172 | ||
1172 | buswidth = xlate->buswidth; | 1173 | cam_fmt = xlate->cam_fmt; |
1173 | host_fmt = xlate->host_fmt; | 1174 | } |
1174 | cam_fmt = xlate->cam_fmt; | ||
1175 | 1175 | ||
1176 | /* If PCLK is used to latch data from the sensor, check sense */ | 1176 | /* If PCLK is used to latch data from the sensor, check sense */ |
1177 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) | 1177 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
@@ -1201,8 +1201,8 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd, | |||
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | if (pixfmt && !ret) { | 1203 | if (pixfmt && !ret) { |
1204 | icd->buswidth = buswidth; | 1204 | icd->buswidth = xlate->buswidth; |
1205 | icd->current_fmt = host_fmt; | 1205 | icd->current_fmt = xlate->host_fmt; |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | return ret; | 1208 | return ret; |
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index d6848f7a503b..05221d47dd4c 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -149,7 +149,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = { | |||
149 | { SAA7127_REG_COPYGEN_0, 0x77 }, | 149 | { SAA7127_REG_COPYGEN_0, 0x77 }, |
150 | { SAA7127_REG_COPYGEN_1, 0x41 }, | 150 | { SAA7127_REG_COPYGEN_1, 0x41 }, |
151 | { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ | 151 | { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */ |
152 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e }, | 152 | { SAA7127_REG_OUTPUT_PORT_CONTROL, 0xbf }, |
153 | { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, | 153 | { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 }, |
154 | { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, | 154 | { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 }, |
155 | { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ | 155 | { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */ |
@@ -488,12 +488,18 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) | |||
488 | break; | 488 | break; |
489 | 489 | ||
490 | case SAA7127_OUTPUT_TYPE_COMPOSITE: | 490 | case SAA7127_OUTPUT_TYPE_COMPOSITE: |
491 | state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ | 491 | if (state->ident == V4L2_IDENT_SAA7129) |
492 | state->reg_2d = 0x20; /* CVBS only */ | ||
493 | else | ||
494 | state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ | ||
492 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | 495 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ |
493 | break; | 496 | break; |
494 | 497 | ||
495 | case SAA7127_OUTPUT_TYPE_SVIDEO: | 498 | case SAA7127_OUTPUT_TYPE_SVIDEO: |
496 | state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */ | 499 | if (state->ident == V4L2_IDENT_SAA7129) |
500 | state->reg_2d = 0x18; /* Y + C */ | ||
501 | else | ||
502 | state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */ | ||
497 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | 503 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ |
498 | break; | 504 | break; |
499 | 505 | ||
@@ -508,7 +514,10 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) | |||
508 | break; | 514 | break; |
509 | 515 | ||
510 | case SAA7127_OUTPUT_TYPE_BOTH: | 516 | case SAA7127_OUTPUT_TYPE_BOTH: |
511 | state->reg_2d = 0xbf; | 517 | if (state->ident == V4L2_IDENT_SAA7129) |
518 | state->reg_2d = 0x38; | ||
519 | else | ||
520 | state->reg_2d = 0xbf; | ||
512 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ | 521 | state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */ |
513 | break; | 522 | break; |
514 | 523 | ||
@@ -731,24 +740,6 @@ static int saa7127_probe(struct i2c_client *client, | |||
731 | return -ENODEV; | 740 | return -ENODEV; |
732 | } | 741 | } |
733 | 742 | ||
734 | /* Configure Encoder */ | ||
735 | |||
736 | v4l2_dbg(1, debug, sd, "Configuring encoder\n"); | ||
737 | saa7127_write_inittab(sd, saa7127_init_config_common); | ||
738 | saa7127_set_std(sd, V4L2_STD_NTSC); | ||
739 | saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH); | ||
740 | saa7127_set_vps(sd, &vbi); | ||
741 | saa7127_set_wss(sd, &vbi); | ||
742 | saa7127_set_cc(sd, &vbi); | ||
743 | saa7127_set_xds(sd, &vbi); | ||
744 | if (test_image == 1) | ||
745 | /* The Encoder has an internal Colorbar generator */ | ||
746 | /* This can be used for debugging */ | ||
747 | saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE); | ||
748 | else | ||
749 | saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); | ||
750 | saa7127_set_video_enable(sd, 1); | ||
751 | |||
752 | if (id->driver_data) { /* Chip type is already known */ | 743 | if (id->driver_data) { /* Chip type is already known */ |
753 | state->ident = id->driver_data; | 744 | state->ident = id->driver_data; |
754 | } else { /* Needs detection */ | 745 | } else { /* Needs detection */ |
@@ -770,6 +761,23 @@ static int saa7127_probe(struct i2c_client *client, | |||
770 | 761 | ||
771 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | 762 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, |
772 | client->addr << 1, client->adapter->name); | 763 | client->addr << 1, client->adapter->name); |
764 | |||
765 | v4l2_dbg(1, debug, sd, "Configuring encoder\n"); | ||
766 | saa7127_write_inittab(sd, saa7127_init_config_common); | ||
767 | saa7127_set_std(sd, V4L2_STD_NTSC); | ||
768 | saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH); | ||
769 | saa7127_set_vps(sd, &vbi); | ||
770 | saa7127_set_wss(sd, &vbi); | ||
771 | saa7127_set_cc(sd, &vbi); | ||
772 | saa7127_set_xds(sd, &vbi); | ||
773 | if (test_image == 1) | ||
774 | /* The Encoder has an internal Colorbar generator */ | ||
775 | /* This can be used for debugging */ | ||
776 | saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE); | ||
777 | else | ||
778 | saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); | ||
779 | saa7127_set_video_enable(sd, 1); | ||
780 | |||
773 | if (state->ident == V4L2_IDENT_SAA7129) | 781 | if (state->ident == V4L2_IDENT_SAA7129) |
774 | saa7127_write_inittab(sd, saa7129_init_config_extra); | 782 | saa7127_write_inittab(sd, saa7129_init_config_extra); |
775 | return 0; | 783 | return 0; |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 26194a0ce927..c750d3dd57d2 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -1089,7 +1089,11 @@ static int saa7134_alsa_init(void) | |||
1089 | 1089 | ||
1090 | list_for_each(list,&saa7134_devlist) { | 1090 | list_for_each(list,&saa7134_devlist) { |
1091 | dev = list_entry(list, struct saa7134_dev, devlist); | 1091 | dev = list_entry(list, struct saa7134_dev, devlist); |
1092 | alsa_device_init(dev); | 1092 | if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130) |
1093 | printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n", | ||
1094 | dev->name, saa7134_boards[dev->board].name); | ||
1095 | else | ||
1096 | alsa_device_init(dev); | ||
1093 | } | 1097 | } |
1094 | 1098 | ||
1095 | if (dev == NULL) | 1099 | if (dev == NULL) |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index dfbe08a9ad9b..99221d726edb 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -660,6 +660,10 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) | |||
660 | 660 | ||
661 | saa_writel(SAA7134_IRQ1, 0); | 661 | saa_writel(SAA7134_IRQ1, 0); |
662 | saa_writel(SAA7134_IRQ2, 0); | 662 | saa_writel(SAA7134_IRQ2, 0); |
663 | |||
664 | /* Clear any stale IRQ reports */ | ||
665 | saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT)); | ||
666 | |||
663 | mutex_init(&dev->lock); | 667 | mutex_init(&dev->lock); |
664 | spin_lock_init(&dev->slock); | 668 | spin_lock_init(&dev->slock); |
665 | 669 | ||
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index 454ad1dd7507..88c5e942f751 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c | |||
@@ -30,7 +30,6 @@ | |||
30 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 30 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/version.h> | ||
34 | #include <linux/module.h> | 33 | #include <linux/module.h> |
35 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
36 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 9a2586b07a05..ddcb81d0b81a 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -603,21 +603,18 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
603 | const struct soc_camera_format_xlate *xlate; | 603 | const struct soc_camera_format_xlate *xlate; |
604 | int ret; | 604 | int ret; |
605 | 605 | ||
606 | if (!pixfmt) | ||
607 | return icd->ops->set_fmt(icd, pixfmt, rect); | ||
608 | |||
606 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); | 609 | xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); |
607 | if (!xlate) { | 610 | if (!xlate) { |
608 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); | 611 | dev_warn(&ici->dev, "Format %x not found\n", pixfmt); |
609 | return -EINVAL; | 612 | return -EINVAL; |
610 | } | 613 | } |
611 | 614 | ||
612 | switch (pixfmt) { | 615 | ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); |
613 | case 0: /* Only geometry change */ | ||
614 | ret = icd->ops->set_fmt(icd, pixfmt, rect); | ||
615 | break; | ||
616 | default: | ||
617 | ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect); | ||
618 | } | ||
619 | 616 | ||
620 | if (pixfmt && !ret) { | 617 | if (!ret) { |
621 | icd->buswidth = xlate->buswidth; | 618 | icd->buswidth = xlate->buswidth; |
622 | icd->current_fmt = xlate->host_fmt; | 619 | icd->current_fmt = xlate->host_fmt; |
623 | pcdev->camera_fmt = xlate->cam_fmt; | 620 | pcdev->camera_fmt = xlate->cam_fmt; |
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 56f0c0eb500f..00c6cbe06ab0 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c | |||
@@ -242,7 +242,7 @@ static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
242 | static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 242 | static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) |
243 | { | 243 | { |
244 | struct tda9875 *t = to_state(sd); | 244 | struct tda9875 *t = to_state(sd); |
245 | int chvol=0, volume, balance, left, right; | 245 | int chvol = 0, volume = 0, balance = 0, left, right; |
246 | 246 | ||
247 | switch (ctrl->id) { | 247 | switch (ctrl->id) { |
248 | case V4L2_CID_AUDIO_VOLUME: | 248 | case V4L2_CID_AUDIO_VOLUME: |
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 3b0b84c2e451..78277abb733b 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -427,6 +427,9 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, | |||
427 | const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; | 427 | const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; |
428 | 428 | ||
429 | memset(tvee, 0, sizeof(*tvee)); | 429 | memset(tvee, 0, sizeof(*tvee)); |
430 | tvee->tuner_type = TUNER_ABSENT; | ||
431 | tvee->tuner2_type = TUNER_ABSENT; | ||
432 | |||
430 | done = len = beenhere = 0; | 433 | done = len = beenhere = 0; |
431 | 434 | ||
432 | /* Different eeprom start offsets for em28xx, cx2388x and cx23418 */ | 435 | /* Different eeprom start offsets for em28xx, cx2388x and cx23418 */ |
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c index ac9aa40d09f6..8e23aa53c29a 100644 --- a/drivers/media/video/tvp514x.c +++ b/drivers/media/video/tvp514x.c | |||
@@ -1401,7 +1401,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1401 | 1401 | ||
1402 | decoder->pdata = client->dev.platform_data; | 1402 | decoder->pdata = client->dev.platform_data; |
1403 | if (!decoder->pdata) { | 1403 | if (!decoder->pdata) { |
1404 | v4l_err(client, "No platform data\n!!"); | 1404 | v4l_err(client, "No platform data!!\n"); |
1405 | return -ENODEV; | 1405 | return -ENODEV; |
1406 | } | 1406 | } |
1407 | /* | 1407 | /* |
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 4f16effb530f..f4522bb08916 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c | |||
@@ -21,7 +21,6 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | 23 | ||
24 | #include <linux/version.h> | ||
25 | #include <linux/module.h> | 24 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 4b712f69d1b7..a5fb74bf2407 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * 02110-1301, USA. | 21 | * 02110-1301, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/version.h> | ||
25 | #include <linux/module.h> | 24 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 9907b9aff2b9..6b66ae4f430f 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -157,7 +157,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | |||
157 | struct i2c_msg *pmsg; | 157 | struct i2c_msg *pmsg; |
158 | struct usb_usbvision *usbvision; | 158 | struct usb_usbvision *usbvision; |
159 | int i, ret; | 159 | int i, ret; |
160 | unsigned char addr; | 160 | unsigned char addr = 0; |
161 | 161 | ||
162 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); | 162 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap); |
163 | 163 | ||
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 2208165aa6f0..d2576f6391c0 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_ctrl.c -- USB Video Class driver - Controls | 2 | * uvc_ctrl.c -- USB Video Class driver - Controls |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2008 | 4 | * Copyright (C) 2005-2009 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/version.h> | ||
16 | #include <linux/list.h> | 15 | #include <linux/list.h> |
17 | #include <linux/module.h> | 16 | #include <linux/module.h> |
18 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
@@ -29,7 +28,7 @@ | |||
29 | #define UVC_CTRL_DATA_BACKUP 1 | 28 | #define UVC_CTRL_DATA_BACKUP 1 |
30 | 29 | ||
31 | /* ------------------------------------------------------------------------ | 30 | /* ------------------------------------------------------------------------ |
32 | * Control, formats, ... | 31 | * Controls |
33 | */ | 32 | */ |
34 | 33 | ||
35 | static struct uvc_control_info uvc_ctrls[] = { | 34 | static struct uvc_control_info uvc_ctrls[] = { |
@@ -635,7 +634,7 @@ static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping, | |||
635 | mask = (1 << bits) - 1; | 634 | mask = (1 << bits) - 1; |
636 | } | 635 | } |
637 | 636 | ||
638 | /* Sign-extend the value if needed */ | 637 | /* Sign-extend the value if needed. */ |
639 | if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) | 638 | if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) |
640 | value |= -(value & (1 << (mapping->size - 1))); | 639 | value |= -(value & (1 << (mapping->size - 1))); |
641 | 640 | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 89d8bd10a852..b12873265cc5 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_driver.c -- USB Video Class driver | 2 | * uvc_driver.c -- USB Video Class driver |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2008 | 4 | * Copyright (C) 2005-2009 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -24,7 +24,6 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/version.h> | ||
28 | #include <linux/list.h> | 27 | #include <linux/list.h> |
29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
30 | #include <linux/usb.h> | 29 | #include <linux/usb.h> |
@@ -49,7 +48,7 @@ static unsigned int uvc_quirks_param; | |||
49 | unsigned int uvc_trace_param; | 48 | unsigned int uvc_trace_param; |
50 | 49 | ||
51 | /* ------------------------------------------------------------------------ | 50 | /* ------------------------------------------------------------------------ |
52 | * Control, formats, ... | 51 | * Video formats |
53 | */ | 52 | */ |
54 | 53 | ||
55 | static struct uvc_format_desc uvc_fmts[] = { | 54 | static struct uvc_format_desc uvc_fmts[] = { |
@@ -474,7 +473,7 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
474 | 473 | ||
475 | /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize | 474 | /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize |
476 | * completely. Observed behaviours range from setting the | 475 | * completely. Observed behaviours range from setting the |
477 | * value to 1.1x the actual frame size of hardwiring the | 476 | * value to 1.1x the actual frame size to hardwiring the |
478 | * 16 low bits to 0. This results in a higher than necessary | 477 | * 16 low bits to 0. This results in a higher than necessary |
479 | * memory usage as well as a wrong image size information. For | 478 | * memory usage as well as a wrong image size information. For |
480 | * uncompressed formats this can be fixed by computing the | 479 | * uncompressed formats this can be fixed by computing the |
@@ -487,7 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev, | |||
487 | /* Some bogus devices report dwMinFrameInterval equal to | 486 | /* Some bogus devices report dwMinFrameInterval equal to |
488 | * dwMaxFrameInterval and have dwFrameIntervalStep set to | 487 | * dwMaxFrameInterval and have dwFrameIntervalStep set to |
489 | * zero. Setting all null intervals to 1 fixes the problem and | 488 | * zero. Setting all null intervals to 1 fixes the problem and |
490 | * some other divisions by zero which could happen. | 489 | * some other divisions by zero that could happen. |
491 | */ | 490 | */ |
492 | for (i = 0; i < n; ++i) { | 491 | for (i = 0; i < n; ++i) { |
493 | interval = get_unaligned_le32(&buffer[26+4*i]); | 492 | interval = get_unaligned_le32(&buffer[26+4*i]); |
@@ -1200,13 +1199,13 @@ static void uvc_unregister_video(struct uvc_device *dev) | |||
1200 | * Scan the UVC descriptors to locate a chain starting at an Output Terminal | 1199 | * Scan the UVC descriptors to locate a chain starting at an Output Terminal |
1201 | * and containing the following units: | 1200 | * and containing the following units: |
1202 | * | 1201 | * |
1203 | * - a USB Streaming Output Terminal | 1202 | * - one Output Terminal (USB Streaming or Display) |
1204 | * - zero or one Processing Unit | 1203 | * - zero or one Processing Unit |
1205 | * - zero, one or mode single-input Selector Units | 1204 | * - zero, one or mode single-input Selector Units |
1206 | * - zero or one multiple-input Selector Units, provided all inputs are | 1205 | * - zero or one multiple-input Selector Units, provided all inputs are |
1207 | * connected to input terminals | 1206 | * connected to input terminals |
1208 | * - zero, one or mode single-input Extension Units | 1207 | * - zero, one or mode single-input Extension Units |
1209 | * - one Camera Input Terminal, or one or more External terminals. | 1208 | * - one or more Input Terminals (Camera, External or USB Streaming) |
1210 | * | 1209 | * |
1211 | * A side forward scan is made on each detected entity to check for additional | 1210 | * A side forward scan is made on each detected entity to check for additional |
1212 | * extension units. | 1211 | * extension units. |
@@ -1531,10 +1530,6 @@ static int uvc_register_video(struct uvc_device *dev) | |||
1531 | 1530 | ||
1532 | /* Set the driver data before calling video_register_device, otherwise | 1531 | /* Set the driver data before calling video_register_device, otherwise |
1533 | * uvc_v4l2_open might race us. | 1532 | * uvc_v4l2_open might race us. |
1534 | * | ||
1535 | * FIXME: usb_set_intfdata hasn't been called so far. Is that a | ||
1536 | * problem ? Does any function which could be called here get | ||
1537 | * a pointer to the usb_interface ? | ||
1538 | */ | 1533 | */ |
1539 | dev->video.vdev = vdev; | 1534 | dev->video.vdev = vdev; |
1540 | video_set_drvdata(vdev, &dev->video); | 1535 | video_set_drvdata(vdev, &dev->video); |
@@ -1569,7 +1564,7 @@ void uvc_delete(struct kref *kref) | |||
1569 | struct uvc_device *dev = container_of(kref, struct uvc_device, kref); | 1564 | struct uvc_device *dev = container_of(kref, struct uvc_device, kref); |
1570 | struct list_head *p, *n; | 1565 | struct list_head *p, *n; |
1571 | 1566 | ||
1572 | /* Unregister the video device */ | 1567 | /* Unregister the video device. */ |
1573 | uvc_unregister_video(dev); | 1568 | uvc_unregister_video(dev); |
1574 | usb_put_intf(dev->intf); | 1569 | usb_put_intf(dev->intf); |
1575 | usb_put_dev(dev->udev); | 1570 | usb_put_dev(dev->udev); |
@@ -1612,7 +1607,7 @@ static int uvc_probe(struct usb_interface *intf, | |||
1612 | uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", | 1607 | uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", |
1613 | udev->devpath); | 1608 | udev->devpath); |
1614 | 1609 | ||
1615 | /* Allocate memory for the device and initialize it */ | 1610 | /* Allocate memory for the device and initialize it. */ |
1616 | if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) | 1611 | if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) |
1617 | return -ENOMEM; | 1612 | return -ENOMEM; |
1618 | 1613 | ||
@@ -1633,14 +1628,14 @@ static int uvc_probe(struct usb_interface *intf, | |||
1633 | le16_to_cpu(udev->descriptor.idVendor), | 1628 | le16_to_cpu(udev->descriptor.idVendor), |
1634 | le16_to_cpu(udev->descriptor.idProduct)); | 1629 | le16_to_cpu(udev->descriptor.idProduct)); |
1635 | 1630 | ||
1636 | /* Parse the Video Class control descriptor */ | 1631 | /* Parse the Video Class control descriptor. */ |
1637 | if (uvc_parse_control(dev) < 0) { | 1632 | if (uvc_parse_control(dev) < 0) { |
1638 | uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " | 1633 | uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " |
1639 | "descriptors.\n"); | 1634 | "descriptors.\n"); |
1640 | goto error; | 1635 | goto error; |
1641 | } | 1636 | } |
1642 | 1637 | ||
1643 | uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n", | 1638 | uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n", |
1644 | dev->uvc_version >> 8, dev->uvc_version & 0xff, | 1639 | dev->uvc_version >> 8, dev->uvc_version & 0xff, |
1645 | udev->product ? udev->product : "<unnamed>", | 1640 | udev->product ? udev->product : "<unnamed>", |
1646 | le16_to_cpu(udev->descriptor.idVendor), | 1641 | le16_to_cpu(udev->descriptor.idVendor), |
@@ -1653,18 +1648,18 @@ static int uvc_probe(struct usb_interface *intf, | |||
1653 | "linux-uvc-devel mailing list.\n"); | 1648 | "linux-uvc-devel mailing list.\n"); |
1654 | } | 1649 | } |
1655 | 1650 | ||
1656 | /* Initialize controls */ | 1651 | /* Initialize controls. */ |
1657 | if (uvc_ctrl_init_device(dev) < 0) | 1652 | if (uvc_ctrl_init_device(dev) < 0) |
1658 | goto error; | 1653 | goto error; |
1659 | 1654 | ||
1660 | /* Register the video devices */ | 1655 | /* Register the video devices. */ |
1661 | if (uvc_register_video(dev) < 0) | 1656 | if (uvc_register_video(dev) < 0) |
1662 | goto error; | 1657 | goto error; |
1663 | 1658 | ||
1664 | /* Save our data pointer in the interface data */ | 1659 | /* Save our data pointer in the interface data. */ |
1665 | usb_set_intfdata(intf, dev); | 1660 | usb_set_intfdata(intf, dev); |
1666 | 1661 | ||
1667 | /* Initialize the interrupt URB */ | 1662 | /* Initialize the interrupt URB. */ |
1668 | if ((ret = uvc_status_init(dev)) < 0) { | 1663 | if ((ret = uvc_status_init(dev)) < 0) { |
1669 | uvc_printk(KERN_INFO, "Unable to initialize the status " | 1664 | uvc_printk(KERN_INFO, "Unable to initialize the status " |
1670 | "endpoint (%d), status interrupt will not be " | 1665 | "endpoint (%d), status interrupt will not be " |
@@ -1839,24 +1834,24 @@ static struct usb_device_id uvc_ids[] = { | |||
1839 | .bInterfaceSubClass = 1, | 1834 | .bInterfaceSubClass = 1, |
1840 | .bInterfaceProtocol = 0 }, | 1835 | .bInterfaceProtocol = 0 }, |
1841 | /* Apple Built-In iSight */ | 1836 | /* Apple Built-In iSight */ |
1842 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1837 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1843 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1838 | | USB_DEVICE_ID_MATCH_INT_INFO, |
1844 | .idVendor = 0x05ac, | 1839 | .idVendor = 0x05ac, |
1845 | .idProduct = 0x8501, | 1840 | .idProduct = 0x8501, |
1846 | .bInterfaceClass = USB_CLASS_VIDEO, | 1841 | .bInterfaceClass = USB_CLASS_VIDEO, |
1847 | .bInterfaceSubClass = 1, | 1842 | .bInterfaceSubClass = 1, |
1848 | .bInterfaceProtocol = 0, | 1843 | .bInterfaceProtocol = 0, |
1849 | .driver_info = UVC_QUIRK_PROBE_MINMAX | 1844 | .driver_info = UVC_QUIRK_PROBE_MINMAX |
1850 | | UVC_QUIRK_BUILTIN_ISIGHT }, | 1845 | | UVC_QUIRK_BUILTIN_ISIGHT }, |
1851 | /* Genesys Logic USB 2.0 PC Camera */ | 1846 | /* Genesys Logic USB 2.0 PC Camera */ |
1852 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1847 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1853 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1848 | | USB_DEVICE_ID_MATCH_INT_INFO, |
1854 | .idVendor = 0x05e3, | 1849 | .idVendor = 0x05e3, |
1855 | .idProduct = 0x0505, | 1850 | .idProduct = 0x0505, |
1856 | .bInterfaceClass = USB_CLASS_VIDEO, | 1851 | .bInterfaceClass = USB_CLASS_VIDEO, |
1857 | .bInterfaceSubClass = 1, | 1852 | .bInterfaceSubClass = 1, |
1858 | .bInterfaceProtocol = 0, | 1853 | .bInterfaceProtocol = 0, |
1859 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | 1854 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, |
1860 | /* MT6227 */ | 1855 | /* MT6227 */ |
1861 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 1856 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
1862 | | USB_DEVICE_ID_MATCH_INT_INFO, | 1857 | | USB_DEVICE_ID_MATCH_INT_INFO, |
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c index 37bdefdbead5..436f462685a0 100644 --- a/drivers/media/video/uvc/uvc_isight.c +++ b/drivers/media/video/uvc/uvc_isight.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2006-2007 | 4 | * Copyright (C) 2006-2007 |
5 | * Ivan N. Zlatev <contact@i-nz.net> | 5 | * Ivan N. Zlatev <contact@i-nz.net> |
6 | * Copyright (C) 2008-2009 | ||
7 | * Laurent Pinchart <laurent.pinchart@skynet.be> | ||
6 | * | 8 | * |
7 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 42546342e97d..0155752e4a5a 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_queue.c -- USB Video Class driver - Buffers management | 2 | * uvc_queue.c -- USB Video Class driver - Buffers management |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2008 | 4 | * Copyright (C) 2005-2009 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/version.h> | ||
16 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
17 | #include <linux/list.h> | 16 | #include <linux/list.h> |
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
@@ -37,22 +36,22 @@ | |||
37 | * to user space will return -EBUSY. | 36 | * to user space will return -EBUSY. |
38 | * | 37 | * |
39 | * Video buffers are managed using two queues. However, unlike most USB video | 38 | * Video buffers are managed using two queues. However, unlike most USB video |
40 | * drivers which use an in queue and an out queue, we use a main queue which | 39 | * drivers that use an in queue and an out queue, we use a main queue to hold |
41 | * holds all queued buffers (both 'empty' and 'done' buffers), and an irq | 40 | * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to |
42 | * queue which holds empty buffers. This design (copied from video-buf) | 41 | * hold empty buffers. This design (copied from video-buf) minimizes locking |
43 | * minimizes locking in interrupt, as only one queue is shared between | 42 | * in interrupt, as only one queue is shared between interrupt and user |
44 | * interrupt and user contexts. | 43 | * contexts. |
45 | * | 44 | * |
46 | * Use cases | 45 | * Use cases |
47 | * --------- | 46 | * --------- |
48 | * | 47 | * |
49 | * Unless stated otherwise, all operations which modify the irq buffers queue | 48 | * Unless stated otherwise, all operations that modify the irq buffers queue |
50 | * are protected by the irq spinlock. | 49 | * are protected by the irq spinlock. |
51 | * | 50 | * |
52 | * 1. The user queues the buffers, starts streaming and dequeues a buffer. | 51 | * 1. The user queues the buffers, starts streaming and dequeues a buffer. |
53 | * | 52 | * |
54 | * The buffers are added to the main and irq queues. Both operations are | 53 | * The buffers are added to the main and irq queues. Both operations are |
55 | * protected by the queue lock, and the latert is protected by the irq | 54 | * protected by the queue lock, and the later is protected by the irq |
56 | * spinlock as well. | 55 | * spinlock as well. |
57 | * | 56 | * |
58 | * The completion handler fetches a buffer from the irq queue and fills it | 57 | * The completion handler fetches a buffer from the irq queue and fills it |
@@ -60,7 +59,7 @@ | |||
60 | * returns immediately. | 59 | * returns immediately. |
61 | * | 60 | * |
62 | * When the buffer is full, the completion handler removes it from the irq | 61 | * When the buffer is full, the completion handler removes it from the irq |
63 | * queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue. | 62 | * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. |
64 | * At that point, any process waiting on the buffer will be woken up. If a | 63 | * At that point, any process waiting on the buffer will be woken up. If a |
65 | * process tries to dequeue a buffer after it has been marked ready, the | 64 | * process tries to dequeue a buffer after it has been marked ready, the |
66 | * dequeing will succeed immediately. | 65 | * dequeing will succeed immediately. |
@@ -91,8 +90,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) | |||
91 | /* | 90 | /* |
92 | * Allocate the video buffers. | 91 | * Allocate the video buffers. |
93 | * | 92 | * |
94 | * Pages are reserved to make sure they will not be swaped, as they will be | 93 | * Pages are reserved to make sure they will not be swapped, as they will be |
95 | * filled in URB completion handler. | 94 | * filled in the URB completion handler. |
96 | * | 95 | * |
97 | * Buffers will be individually mapped, so they must all be page aligned. | 96 | * Buffers will be individually mapped, so they must all be page aligned. |
98 | */ | 97 | */ |
@@ -210,8 +209,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue, | |||
210 | __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); | 209 | __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); |
211 | 210 | ||
212 | done: | 211 | done: |
213 | mutex_unlock(&queue->mutex); | 212 | mutex_unlock(&queue->mutex); |
214 | return ret; | 213 | return ret; |
215 | } | 214 | } |
216 | 215 | ||
217 | /* | 216 | /* |
@@ -236,7 +235,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, | |||
236 | } | 235 | } |
237 | 236 | ||
238 | mutex_lock(&queue->mutex); | 237 | mutex_lock(&queue->mutex); |
239 | if (v4l2_buf->index >= queue->count) { | 238 | if (v4l2_buf->index >= queue->count) { |
240 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); | 239 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); |
241 | ret = -EINVAL; | 240 | ret = -EINVAL; |
242 | goto done; | 241 | goto done; |
@@ -429,7 +428,7 @@ done: | |||
429 | * Cancel the video buffers queue. | 428 | * Cancel the video buffers queue. |
430 | * | 429 | * |
431 | * Cancelling the queue marks all buffers on the irq queue as erroneous, | 430 | * Cancelling the queue marks all buffers on the irq queue as erroneous, |
432 | * wakes them up and remove them from the queue. | 431 | * wakes them up and removes them from the queue. |
433 | * | 432 | * |
434 | * If the disconnect parameter is set, further calls to uvc_queue_buffer will | 433 | * If the disconnect parameter is set, further calls to uvc_queue_buffer will |
435 | * fail with -ENODEV. | 434 | * fail with -ENODEV. |
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c index 5d60b264d59a..c705f248da88 100644 --- a/drivers/media/video/uvc/uvc_status.c +++ b/drivers/media/video/uvc/uvc_status.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_status.c -- USB Video Class driver - Status endpoint | 2 | * uvc_status.c -- USB Video Class driver - Status endpoint |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 | 4 | * Copyright (C) 2007-2009 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/version.h> | ||
16 | #include <linux/input.h> | 15 | #include <linux/input.h> |
17 | #include <linux/usb.h> | 16 | #include <linux/usb.h> |
18 | #include <linux/usb/input.h> | 17 | #include <linux/usb/input.h> |
@@ -47,8 +46,8 @@ static int uvc_input_init(struct uvc_device *dev) | |||
47 | usb_to_input_id(udev, &input->id); | 46 | usb_to_input_id(udev, &input->id); |
48 | input->dev.parent = &dev->intf->dev; | 47 | input->dev.parent = &dev->intf->dev; |
49 | 48 | ||
50 | set_bit(EV_KEY, input->evbit); | 49 | __set_bit(EV_KEY, input->evbit); |
51 | set_bit(BTN_0, input->keybit); | 50 | __set_bit(KEY_CAMERA, input->keybit); |
52 | 51 | ||
53 | if ((ret = input_register_device(input)) < 0) | 52 | if ((ret = input_register_device(input)) < 0) |
54 | goto error; | 53 | goto error; |
@@ -71,8 +70,10 @@ static void uvc_input_cleanup(struct uvc_device *dev) | |||
71 | static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, | 70 | static void uvc_input_report_key(struct uvc_device *dev, unsigned int code, |
72 | int value) | 71 | int value) |
73 | { | 72 | { |
74 | if (dev->input) | 73 | if (dev->input) { |
75 | input_report_key(dev->input, code, value); | 74 | input_report_key(dev->input, code, value); |
75 | input_sync(dev->input); | ||
76 | } | ||
76 | } | 77 | } |
77 | 78 | ||
78 | #else | 79 | #else |
@@ -97,7 +98,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) | |||
97 | return; | 98 | return; |
98 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", | 99 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", |
99 | data[1], data[3] ? "pressed" : "released", len); | 100 | data[1], data[3] ? "pressed" : "released", len); |
100 | uvc_input_report_key(dev, BTN_0, data[3]); | 101 | uvc_input_report_key(dev, KEY_CAMERA, data[3]); |
101 | } else { | 102 | } else { |
102 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " | 103 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " |
103 | "len %d.\n", data[1], data[2], data[3], len); | 104 | "len %d.\n", data[1], data[2], data[3], len); |
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index fa150fff2c10..d681519d0c8a 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_v4l2.c -- USB Video Class driver - V4L2 API | 2 | * uvc_v4l2.c -- USB Video Class driver - V4L2 API |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2008 | 4 | * Copyright (C) 2005-2009 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -37,7 +37,7 @@ | |||
37 | * must be grouped (for instance the Red Balance, Blue Balance and Do White | 37 | * must be grouped (for instance the Red Balance, Blue Balance and Do White |
38 | * Balance V4L2 controls use the White Balance Component UVC control) or | 38 | * Balance V4L2 controls use the White Balance Component UVC control) or |
39 | * otherwise translated. The approach we take here is to use a translation | 39 | * otherwise translated. The approach we take here is to use a translation |
40 | * table for the controls which can be mapped directly, and handle the others | 40 | * table for the controls that can be mapped directly, and handle the others |
41 | * manually. | 41 | * manually. |
42 | */ | 42 | */ |
43 | static int uvc_v4l2_query_menu(struct uvc_video_device *video, | 43 | static int uvc_v4l2_query_menu(struct uvc_video_device *video, |
@@ -189,7 +189,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video, | |||
189 | probe->dwMaxVideoFrameSize = | 189 | probe->dwMaxVideoFrameSize = |
190 | video->streaming->ctrl.dwMaxVideoFrameSize; | 190 | video->streaming->ctrl.dwMaxVideoFrameSize; |
191 | 191 | ||
192 | /* Probe the device */ | 192 | /* Probe the device. */ |
193 | if ((ret = uvc_probe_video(video, probe)) < 0) | 193 | if ((ret = uvc_probe_video(video, probe)) < 0) |
194 | goto done; | 194 | goto done; |
195 | 195 | ||
@@ -354,11 +354,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, | |||
354 | * | 354 | * |
355 | * Each open instance of a UVC device can either be in a privileged or | 355 | * Each open instance of a UVC device can either be in a privileged or |
356 | * unprivileged state. Only a single instance can be in a privileged state at | 356 | * unprivileged state. Only a single instance can be in a privileged state at |
357 | * a given time. Trying to perform an operation which requires privileges will | 357 | * a given time. Trying to perform an operation that requires privileges will |
358 | * automatically acquire the required privileges if possible, or return -EBUSY | 358 | * automatically acquire the required privileges if possible, or return -EBUSY |
359 | * otherwise. Privileges are dismissed when closing the instance. | 359 | * otherwise. Privileges are dismissed when closing the instance. |
360 | * | 360 | * |
361 | * Operations which require privileges are: | 361 | * Operations that require privileges are: |
362 | * | 362 | * |
363 | * - VIDIOC_S_INPUT | 363 | * - VIDIOC_S_INPUT |
364 | * - VIDIOC_S_PARM | 364 | * - VIDIOC_S_PARM |
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index e7c31995527f..9bc4705be78d 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * uvc_video.c -- USB Video Class driver - Video handling | 2 | * uvc_video.c -- USB Video Class driver - Video handling |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2008 | 4 | * Copyright (C) 2005-2009 |
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/version.h> | ||
16 | #include <linux/list.h> | 15 | #include <linux/list.h> |
17 | #include <linux/module.h> | 16 | #include <linux/module.h> |
18 | #include <linux/usb.h> | 17 | #include <linux/usb.h> |
@@ -115,7 +114,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, | |||
115 | ctrl->wCompQuality = le16_to_cpup((__le16 *)data); | 114 | ctrl->wCompQuality = le16_to_cpup((__le16 *)data); |
116 | ret = 0; | 115 | ret = 0; |
117 | goto out; | 116 | goto out; |
118 | } else if (query == GET_DEF && probe == 1) { | 117 | } else if (query == GET_DEF && probe == 1 && ret != size) { |
119 | /* Many cameras don't support the GET_DEF request on their | 118 | /* Many cameras don't support the GET_DEF request on their |
120 | * video probe control. Warn once and return, the caller will | 119 | * video probe control. Warn once and return, the caller will |
121 | * fall back to GET_CUR. | 120 | * fall back to GET_CUR. |
@@ -160,7 +159,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, | |||
160 | } | 159 | } |
161 | 160 | ||
162 | /* Some broken devices return a null or wrong dwMaxVideoFrameSize. | 161 | /* Some broken devices return a null or wrong dwMaxVideoFrameSize. |
163 | * Try to get the value from the format and frame descriptor. | 162 | * Try to get the value from the format and frame descriptors. |
164 | */ | 163 | */ |
165 | uvc_fixup_buffer_size(video, ctrl); | 164 | uvc_fixup_buffer_size(video, ctrl); |
166 | ret = 0; | 165 | ret = 0; |
@@ -191,9 +190,6 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video, | |||
191 | *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); | 190 | *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); |
192 | *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); | 191 | *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); |
193 | *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); | 192 | *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); |
194 | /* Note: Some of the fields below are not required for IN devices (see | ||
195 | * UVC spec, 4.3.1.1), but we still copy them in case support for OUT | ||
196 | * devices is added in the future. */ | ||
197 | put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); | 193 | put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); |
198 | put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); | 194 | put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); |
199 | 195 | ||
@@ -400,7 +396,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video, | |||
400 | * | 396 | * |
401 | * Empty buffers (bytesused == 0) don't trigger end of frame detection | 397 | * Empty buffers (bytesused == 0) don't trigger end of frame detection |
402 | * as it doesn't make sense to return an empty buffer. This also | 398 | * as it doesn't make sense to return an empty buffer. This also |
403 | * avoids detecting and of frame conditions at FID toggling if the | 399 | * avoids detecting end of frame conditions at FID toggling if the |
404 | * previous payload had the EOF bit set. | 400 | * previous payload had the EOF bit set. |
405 | */ | 401 | */ |
406 | if (fid != video->last_fid && buf->buf.bytesused != 0) { | 402 | if (fid != video->last_fid && buf->buf.bytesused != 0) { |
@@ -453,6 +449,17 @@ static void uvc_video_decode_end(struct uvc_video_device *video, | |||
453 | } | 449 | } |
454 | } | 450 | } |
455 | 451 | ||
452 | /* Video payload encoding is handled by uvc_video_encode_header() and | ||
453 | * uvc_video_encode_data(). Only bulk transfers are currently supported. | ||
454 | * | ||
455 | * uvc_video_encode_header is called at the start of a payload. It adds header | ||
456 | * data to the transfer buffer and returns the header size. As the only known | ||
457 | * UVC output device transfers a whole frame in a single payload, the EOF bit | ||
458 | * is always set in the header. | ||
459 | * | ||
460 | * uvc_video_encode_data is called for every URB and copies the data from the | ||
461 | * video buffer to the transfer buffer. | ||
462 | */ | ||
456 | static int uvc_video_encode_header(struct uvc_video_device *video, | 463 | static int uvc_video_encode_header(struct uvc_video_device *video, |
457 | struct uvc_buffer *buf, __u8 *data, int len) | 464 | struct uvc_buffer *buf, __u8 *data, int len) |
458 | { | 465 | { |
@@ -953,7 +960,7 @@ int uvc_video_suspend(struct uvc_video_device *video) | |||
953 | } | 960 | } |
954 | 961 | ||
955 | /* | 962 | /* |
956 | * Reconfigure the video interface and restart streaming if it was enable | 963 | * Reconfigure the video interface and restart streaming if it was enabled |
957 | * before suspend. | 964 | * before suspend. |
958 | * | 965 | * |
959 | * If an error occurs, disable the video queue. This will wake all pending | 966 | * If an error occurs, disable the video queue. This will wake all pending |
@@ -985,8 +992,8 @@ int uvc_video_resume(struct uvc_video_device *video) | |||
985 | */ | 992 | */ |
986 | 993 | ||
987 | /* | 994 | /* |
988 | * Initialize the UVC video device by retrieving the default format and | 995 | * Initialize the UVC video device by switching to alternate setting 0 and |
989 | * committing it. | 996 | * retrieve the default format. |
990 | * | 997 | * |
991 | * Some cameras (namely the Fuji Finepix) set the format and frame | 998 | * Some cameras (namely the Fuji Finepix) set the format and frame |
992 | * indexes to zero. The UVC standard doesn't clearly make this a spec | 999 | * indexes to zero. The UVC standard doesn't clearly make this a spec |
@@ -1014,7 +1021,7 @@ int uvc_video_init(struct uvc_video_device *video) | |||
1014 | */ | 1021 | */ |
1015 | usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); | 1022 | usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); |
1016 | 1023 | ||
1017 | /* Some webcams don't suport GET_DEF request on the probe control. We | 1024 | /* Some webcams don't suport GET_DEF requests on the probe control. We |
1018 | * fall back to GET_CUR if GET_DEF fails. | 1025 | * fall back to GET_CUR if GET_DEF fails. |
1019 | */ | 1026 | */ |
1020 | if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && | 1027 | if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bcf4361dc1bc..027947ea9b6e 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -72,149 +72,149 @@ struct uvc_xu_control { | |||
72 | * UVC constants | 72 | * UVC constants |
73 | */ | 73 | */ |
74 | 74 | ||
75 | #define SC_UNDEFINED 0x00 | 75 | #define SC_UNDEFINED 0x00 |
76 | #define SC_VIDEOCONTROL 0x01 | 76 | #define SC_VIDEOCONTROL 0x01 |
77 | #define SC_VIDEOSTREAMING 0x02 | 77 | #define SC_VIDEOSTREAMING 0x02 |
78 | #define SC_VIDEO_INTERFACE_COLLECTION 0x03 | 78 | #define SC_VIDEO_INTERFACE_COLLECTION 0x03 |
79 | 79 | ||
80 | #define PC_PROTOCOL_UNDEFINED 0x00 | 80 | #define PC_PROTOCOL_UNDEFINED 0x00 |
81 | 81 | ||
82 | #define CS_UNDEFINED 0x20 | 82 | #define CS_UNDEFINED 0x20 |
83 | #define CS_DEVICE 0x21 | 83 | #define CS_DEVICE 0x21 |
84 | #define CS_CONFIGURATION 0x22 | 84 | #define CS_CONFIGURATION 0x22 |
85 | #define CS_STRING 0x23 | 85 | #define CS_STRING 0x23 |
86 | #define CS_INTERFACE 0x24 | 86 | #define CS_INTERFACE 0x24 |
87 | #define CS_ENDPOINT 0x25 | 87 | #define CS_ENDPOINT 0x25 |
88 | 88 | ||
89 | /* VideoControl class specific interface descriptor */ | 89 | /* VideoControl class specific interface descriptor */ |
90 | #define VC_DESCRIPTOR_UNDEFINED 0x00 | 90 | #define VC_DESCRIPTOR_UNDEFINED 0x00 |
91 | #define VC_HEADER 0x01 | 91 | #define VC_HEADER 0x01 |
92 | #define VC_INPUT_TERMINAL 0x02 | 92 | #define VC_INPUT_TERMINAL 0x02 |
93 | #define VC_OUTPUT_TERMINAL 0x03 | 93 | #define VC_OUTPUT_TERMINAL 0x03 |
94 | #define VC_SELECTOR_UNIT 0x04 | 94 | #define VC_SELECTOR_UNIT 0x04 |
95 | #define VC_PROCESSING_UNIT 0x05 | 95 | #define VC_PROCESSING_UNIT 0x05 |
96 | #define VC_EXTENSION_UNIT 0x06 | 96 | #define VC_EXTENSION_UNIT 0x06 |
97 | 97 | ||
98 | /* VideoStreaming class specific interface descriptor */ | 98 | /* VideoStreaming class specific interface descriptor */ |
99 | #define VS_UNDEFINED 0x00 | 99 | #define VS_UNDEFINED 0x00 |
100 | #define VS_INPUT_HEADER 0x01 | 100 | #define VS_INPUT_HEADER 0x01 |
101 | #define VS_OUTPUT_HEADER 0x02 | 101 | #define VS_OUTPUT_HEADER 0x02 |
102 | #define VS_STILL_IMAGE_FRAME 0x03 | 102 | #define VS_STILL_IMAGE_FRAME 0x03 |
103 | #define VS_FORMAT_UNCOMPRESSED 0x04 | 103 | #define VS_FORMAT_UNCOMPRESSED 0x04 |
104 | #define VS_FRAME_UNCOMPRESSED 0x05 | 104 | #define VS_FRAME_UNCOMPRESSED 0x05 |
105 | #define VS_FORMAT_MJPEG 0x06 | 105 | #define VS_FORMAT_MJPEG 0x06 |
106 | #define VS_FRAME_MJPEG 0x07 | 106 | #define VS_FRAME_MJPEG 0x07 |
107 | #define VS_FORMAT_MPEG2TS 0x0a | 107 | #define VS_FORMAT_MPEG2TS 0x0a |
108 | #define VS_FORMAT_DV 0x0c | 108 | #define VS_FORMAT_DV 0x0c |
109 | #define VS_COLORFORMAT 0x0d | 109 | #define VS_COLORFORMAT 0x0d |
110 | #define VS_FORMAT_FRAME_BASED 0x10 | 110 | #define VS_FORMAT_FRAME_BASED 0x10 |
111 | #define VS_FRAME_FRAME_BASED 0x11 | 111 | #define VS_FRAME_FRAME_BASED 0x11 |
112 | #define VS_FORMAT_STREAM_BASED 0x12 | 112 | #define VS_FORMAT_STREAM_BASED 0x12 |
113 | 113 | ||
114 | /* Endpoint type */ | 114 | /* Endpoint type */ |
115 | #define EP_UNDEFINED 0x00 | 115 | #define EP_UNDEFINED 0x00 |
116 | #define EP_GENERAL 0x01 | 116 | #define EP_GENERAL 0x01 |
117 | #define EP_ENDPOINT 0x02 | 117 | #define EP_ENDPOINT 0x02 |
118 | #define EP_INTERRUPT 0x03 | 118 | #define EP_INTERRUPT 0x03 |
119 | 119 | ||
120 | /* Request codes */ | 120 | /* Request codes */ |
121 | #define RC_UNDEFINED 0x00 | 121 | #define RC_UNDEFINED 0x00 |
122 | #define SET_CUR 0x01 | 122 | #define SET_CUR 0x01 |
123 | #define GET_CUR 0x81 | 123 | #define GET_CUR 0x81 |
124 | #define GET_MIN 0x82 | 124 | #define GET_MIN 0x82 |
125 | #define GET_MAX 0x83 | 125 | #define GET_MAX 0x83 |
126 | #define GET_RES 0x84 | 126 | #define GET_RES 0x84 |
127 | #define GET_LEN 0x85 | 127 | #define GET_LEN 0x85 |
128 | #define GET_INFO 0x86 | 128 | #define GET_INFO 0x86 |
129 | #define GET_DEF 0x87 | 129 | #define GET_DEF 0x87 |
130 | 130 | ||
131 | /* VideoControl interface controls */ | 131 | /* VideoControl interface controls */ |
132 | #define VC_CONTROL_UNDEFINED 0x00 | 132 | #define VC_CONTROL_UNDEFINED 0x00 |
133 | #define VC_VIDEO_POWER_MODE_CONTROL 0x01 | 133 | #define VC_VIDEO_POWER_MODE_CONTROL 0x01 |
134 | #define VC_REQUEST_ERROR_CODE_CONTROL 0x02 | 134 | #define VC_REQUEST_ERROR_CODE_CONTROL 0x02 |
135 | 135 | ||
136 | /* Terminal controls */ | 136 | /* Terminal controls */ |
137 | #define TE_CONTROL_UNDEFINED 0x00 | 137 | #define TE_CONTROL_UNDEFINED 0x00 |
138 | 138 | ||
139 | /* Selector Unit controls */ | 139 | /* Selector Unit controls */ |
140 | #define SU_CONTROL_UNDEFINED 0x00 | 140 | #define SU_CONTROL_UNDEFINED 0x00 |
141 | #define SU_INPUT_SELECT_CONTROL 0x01 | 141 | #define SU_INPUT_SELECT_CONTROL 0x01 |
142 | 142 | ||
143 | /* Camera Terminal controls */ | 143 | /* Camera Terminal controls */ |
144 | #define CT_CONTROL_UNDEFINED 0x00 | 144 | #define CT_CONTROL_UNDEFINED 0x00 |
145 | #define CT_SCANNING_MODE_CONTROL 0x01 | 145 | #define CT_SCANNING_MODE_CONTROL 0x01 |
146 | #define CT_AE_MODE_CONTROL 0x02 | 146 | #define CT_AE_MODE_CONTROL 0x02 |
147 | #define CT_AE_PRIORITY_CONTROL 0x03 | 147 | #define CT_AE_PRIORITY_CONTROL 0x03 |
148 | #define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 | 148 | #define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 |
149 | #define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 | 149 | #define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 |
150 | #define CT_FOCUS_ABSOLUTE_CONTROL 0x06 | 150 | #define CT_FOCUS_ABSOLUTE_CONTROL 0x06 |
151 | #define CT_FOCUS_RELATIVE_CONTROL 0x07 | 151 | #define CT_FOCUS_RELATIVE_CONTROL 0x07 |
152 | #define CT_FOCUS_AUTO_CONTROL 0x08 | 152 | #define CT_FOCUS_AUTO_CONTROL 0x08 |
153 | #define CT_IRIS_ABSOLUTE_CONTROL 0x09 | 153 | #define CT_IRIS_ABSOLUTE_CONTROL 0x09 |
154 | #define CT_IRIS_RELATIVE_CONTROL 0x0a | 154 | #define CT_IRIS_RELATIVE_CONTROL 0x0a |
155 | #define CT_ZOOM_ABSOLUTE_CONTROL 0x0b | 155 | #define CT_ZOOM_ABSOLUTE_CONTROL 0x0b |
156 | #define CT_ZOOM_RELATIVE_CONTROL 0x0c | 156 | #define CT_ZOOM_RELATIVE_CONTROL 0x0c |
157 | #define CT_PANTILT_ABSOLUTE_CONTROL 0x0d | 157 | #define CT_PANTILT_ABSOLUTE_CONTROL 0x0d |
158 | #define CT_PANTILT_RELATIVE_CONTROL 0x0e | 158 | #define CT_PANTILT_RELATIVE_CONTROL 0x0e |
159 | #define CT_ROLL_ABSOLUTE_CONTROL 0x0f | 159 | #define CT_ROLL_ABSOLUTE_CONTROL 0x0f |
160 | #define CT_ROLL_RELATIVE_CONTROL 0x10 | 160 | #define CT_ROLL_RELATIVE_CONTROL 0x10 |
161 | #define CT_PRIVACY_CONTROL 0x11 | 161 | #define CT_PRIVACY_CONTROL 0x11 |
162 | 162 | ||
163 | /* Processing Unit controls */ | 163 | /* Processing Unit controls */ |
164 | #define PU_CONTROL_UNDEFINED 0x00 | 164 | #define PU_CONTROL_UNDEFINED 0x00 |
165 | #define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 | 165 | #define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 |
166 | #define PU_BRIGHTNESS_CONTROL 0x02 | 166 | #define PU_BRIGHTNESS_CONTROL 0x02 |
167 | #define PU_CONTRAST_CONTROL 0x03 | 167 | #define PU_CONTRAST_CONTROL 0x03 |
168 | #define PU_GAIN_CONTROL 0x04 | 168 | #define PU_GAIN_CONTROL 0x04 |
169 | #define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 | 169 | #define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 |
170 | #define PU_HUE_CONTROL 0x06 | 170 | #define PU_HUE_CONTROL 0x06 |
171 | #define PU_SATURATION_CONTROL 0x07 | 171 | #define PU_SATURATION_CONTROL 0x07 |
172 | #define PU_SHARPNESS_CONTROL 0x08 | 172 | #define PU_SHARPNESS_CONTROL 0x08 |
173 | #define PU_GAMMA_CONTROL 0x09 | 173 | #define PU_GAMMA_CONTROL 0x09 |
174 | #define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a | 174 | #define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a |
175 | #define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b | 175 | #define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b |
176 | #define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c | 176 | #define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c |
177 | #define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d | 177 | #define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d |
178 | #define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e | 178 | #define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e |
179 | #define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f | 179 | #define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f |
180 | #define PU_HUE_AUTO_CONTROL 0x10 | 180 | #define PU_HUE_AUTO_CONTROL 0x10 |
181 | #define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 | 181 | #define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 |
182 | #define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 | 182 | #define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 |
183 | 183 | ||
184 | #define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 | 184 | #define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 |
185 | #define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 | 185 | #define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 |
186 | #define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 | 186 | #define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 |
187 | 187 | ||
188 | /* VideoStreaming interface controls */ | 188 | /* VideoStreaming interface controls */ |
189 | #define VS_CONTROL_UNDEFINED 0x00 | 189 | #define VS_CONTROL_UNDEFINED 0x00 |
190 | #define VS_PROBE_CONTROL 0x01 | 190 | #define VS_PROBE_CONTROL 0x01 |
191 | #define VS_COMMIT_CONTROL 0x02 | 191 | #define VS_COMMIT_CONTROL 0x02 |
192 | #define VS_STILL_PROBE_CONTROL 0x03 | 192 | #define VS_STILL_PROBE_CONTROL 0x03 |
193 | #define VS_STILL_COMMIT_CONTROL 0x04 | 193 | #define VS_STILL_COMMIT_CONTROL 0x04 |
194 | #define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 | 194 | #define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 |
195 | #define VS_STREAM_ERROR_CODE_CONTROL 0x06 | 195 | #define VS_STREAM_ERROR_CODE_CONTROL 0x06 |
196 | #define VS_GENERATE_KEY_FRAME_CONTROL 0x07 | 196 | #define VS_GENERATE_KEY_FRAME_CONTROL 0x07 |
197 | #define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 | 197 | #define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 |
198 | #define VS_SYNC_DELAY_CONTROL 0x09 | 198 | #define VS_SYNC_DELAY_CONTROL 0x09 |
199 | 199 | ||
200 | #define TT_VENDOR_SPECIFIC 0x0100 | 200 | #define TT_VENDOR_SPECIFIC 0x0100 |
201 | #define TT_STREAMING 0x0101 | 201 | #define TT_STREAMING 0x0101 |
202 | 202 | ||
203 | /* Input Terminal types */ | 203 | /* Input Terminal types */ |
204 | #define ITT_VENDOR_SPECIFIC 0x0200 | 204 | #define ITT_VENDOR_SPECIFIC 0x0200 |
205 | #define ITT_CAMERA 0x0201 | 205 | #define ITT_CAMERA 0x0201 |
206 | #define ITT_MEDIA_TRANSPORT_INPUT 0x0202 | 206 | #define ITT_MEDIA_TRANSPORT_INPUT 0x0202 |
207 | 207 | ||
208 | /* Output Terminal types */ | 208 | /* Output Terminal types */ |
209 | #define OTT_VENDOR_SPECIFIC 0x0300 | 209 | #define OTT_VENDOR_SPECIFIC 0x0300 |
210 | #define OTT_DISPLAY 0x0301 | 210 | #define OTT_DISPLAY 0x0301 |
211 | #define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 | 211 | #define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 |
212 | 212 | ||
213 | /* External Terminal types */ | 213 | /* External Terminal types */ |
214 | #define EXTERNAL_VENDOR_SPECIFIC 0x0400 | 214 | #define EXTERNAL_VENDOR_SPECIFIC 0x0400 |
215 | #define COMPOSITE_CONNECTOR 0x0401 | 215 | #define COMPOSITE_CONNECTOR 0x0401 |
216 | #define SVIDEO_CONNECTOR 0x0402 | 216 | #define SVIDEO_CONNECTOR 0x0402 |
217 | #define COMPONENT_CONNECTOR 0x0403 | 217 | #define COMPONENT_CONNECTOR 0x0403 |
218 | 218 | ||
219 | #define UVC_TERM_INPUT 0x0000 | 219 | #define UVC_TERM_INPUT 0x0000 |
220 | #define UVC_TERM_OUTPUT 0x8000 | 220 | #define UVC_TERM_OUTPUT 0x8000 |
@@ -541,11 +541,11 @@ struct uvc_streaming { | |||
541 | }; | 541 | }; |
542 | 542 | ||
543 | enum uvc_buffer_state { | 543 | enum uvc_buffer_state { |
544 | UVC_BUF_STATE_IDLE = 0, | 544 | UVC_BUF_STATE_IDLE = 0, |
545 | UVC_BUF_STATE_QUEUED = 1, | 545 | UVC_BUF_STATE_QUEUED = 1, |
546 | UVC_BUF_STATE_ACTIVE = 2, | 546 | UVC_BUF_STATE_ACTIVE = 2, |
547 | UVC_BUF_STATE_DONE = 3, | 547 | UVC_BUF_STATE_DONE = 3, |
548 | UVC_BUF_STATE_ERROR = 4, | 548 | UVC_BUF_STATE_ERROR = 4, |
549 | }; | 549 | }; |
550 | 550 | ||
551 | struct uvc_buffer { | 551 | struct uvc_buffer { |
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index fbe9cc0d433a..21208805ea9b 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c | |||
@@ -28,13 +28,13 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg) | |||
28 | { | 28 | { |
29 | switch (cmd) { | 29 | switch (cmd) { |
30 | case VIDIOC_QUERYCTRL: | 30 | case VIDIOC_QUERYCTRL: |
31 | return v4l2_subdev_call(sd, core, querymenu, arg); | 31 | return v4l2_subdev_call(sd, core, queryctrl, arg); |
32 | case VIDIOC_G_CTRL: | 32 | case VIDIOC_G_CTRL: |
33 | return v4l2_subdev_call(sd, core, g_ctrl, arg); | 33 | return v4l2_subdev_call(sd, core, g_ctrl, arg); |
34 | case VIDIOC_S_CTRL: | 34 | case VIDIOC_S_CTRL: |
35 | return v4l2_subdev_call(sd, core, s_ctrl, arg); | 35 | return v4l2_subdev_call(sd, core, s_ctrl, arg); |
36 | case VIDIOC_QUERYMENU: | 36 | case VIDIOC_QUERYMENU: |
37 | return v4l2_subdev_call(sd, core, queryctrl, arg); | 37 | return v4l2_subdev_call(sd, core, querymenu, arg); |
38 | case VIDIOC_LOG_STATUS: | 38 | case VIDIOC_LOG_STATUS: |
39 | return v4l2_subdev_call(sd, core, log_status); | 39 | return v4l2_subdev_call(sd, core, log_status); |
40 | case VIDIOC_DBG_G_CHIP_IDENT: | 40 | case VIDIOC_DBG_G_CHIP_IDENT: |
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index 46b7ad477ceb..e873a916250f 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h | |||
@@ -349,7 +349,6 @@ struct card_info { | |||
349 | u16 i2c_decoder, i2c_encoder; /* I2C types */ | 349 | u16 i2c_decoder, i2c_encoder; /* I2C types */ |
350 | u16 video_vfe, video_codec; /* videocodec types */ | 350 | u16 video_vfe, video_codec; /* videocodec types */ |
351 | u16 audio_chip; /* audio type */ | 351 | u16 audio_chip; /* audio type */ |
352 | u16 vendor_id, device_id; /* subsystem vendor/device ID */ | ||
353 | 352 | ||
354 | int inputs; /* number of video inputs */ | 353 | int inputs; /* number of video inputs */ |
355 | struct input { | 354 | struct input { |
@@ -401,7 +400,6 @@ struct zoran { | |||
401 | char name[32]; /* name of this device */ | 400 | char name[32]; /* name of this device */ |
402 | struct pci_dev *pci_dev; /* PCI device */ | 401 | struct pci_dev *pci_dev; /* PCI device */ |
403 | unsigned char revision; /* revision of zr36057 */ | 402 | unsigned char revision; /* revision of zr36057 */ |
404 | unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */ | ||
405 | unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */ | 403 | unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */ |
406 | 404 | ||
407 | spinlock_t spinlock; /* Spinlock */ | 405 | spinlock_t spinlock; /* Spinlock */ |
@@ -490,16 +488,10 @@ struct zoran { | |||
490 | wait_queue_head_t test_q; | 488 | wait_queue_head_t test_q; |
491 | }; | 489 | }; |
492 | 490 | ||
493 | /*The following should be done in more portable way. It depends on define | 491 | /* There was something called _ALPHA_BUZ that used the PCI address instead of |
494 | of _ALPHA_BUZ in the Makefile.*/ | 492 | * the kernel iomapped address for btread/btwrite. */ |
495 | |||
496 | #ifdef _ALPHA_BUZ | ||
497 | #define btwrite(dat,adr) writel((dat), zr->zr36057_adr+(adr)) | ||
498 | #define btread(adr) readl(zr->zr36057_adr+(adr)) | ||
499 | #else | ||
500 | #define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) | 493 | #define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) |
501 | #define btread(adr) readl(zr->zr36057_mem+(adr)) | 494 | #define btread(adr) readl(zr->zr36057_mem+(adr)) |
502 | #endif | ||
503 | 495 | ||
504 | #define btand(dat,adr) btwrite((dat) & btread(adr), adr) | 496 | #define btand(dat,adr) btwrite((dat) & btread(adr), adr) |
505 | #define btor(dat,adr) btwrite((dat) | btread(adr), adr) | 497 | #define btor(dat,adr) btwrite((dat) | btread(adr), adr) |
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c index 05f39195372e..5d2f090aa0f8 100644 --- a/drivers/media/video/zoran/zoran_card.c +++ b/drivers/media/video/zoran/zoran_card.c | |||
@@ -61,17 +61,17 @@ | |||
61 | 61 | ||
62 | extern const struct zoran_format zoran_formats[]; | 62 | extern const struct zoran_format zoran_formats[]; |
63 | 63 | ||
64 | static int card[BUZ_MAX] = { -1, -1, -1, -1 }; | 64 | static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; |
65 | module_param_array(card, int, NULL, 0444); | 65 | module_param_array(card, int, NULL, 0444); |
66 | MODULE_PARM_DESC(card, "The type of card"); | 66 | MODULE_PARM_DESC(card, "Card type"); |
67 | 67 | ||
68 | static int encoder[BUZ_MAX] = { -1, -1, -1, -1 }; | 68 | static int encoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; |
69 | module_param_array(encoder, int, NULL, 0444); | 69 | module_param_array(encoder, int, NULL, 0444); |
70 | MODULE_PARM_DESC(encoder, "i2c TV encoder"); | 70 | MODULE_PARM_DESC(encoder, "Video encoder chip"); |
71 | 71 | ||
72 | static int decoder[BUZ_MAX] = { -1, -1, -1, -1 }; | 72 | static int decoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; |
73 | module_param_array(decoder, int, NULL, 0444); | 73 | module_param_array(decoder, int, NULL, 0444); |
74 | MODULE_PARM_DESC(decoder, "i2c TV decoder"); | 74 | MODULE_PARM_DESC(decoder, "Video decoder chip"); |
75 | 75 | ||
76 | /* | 76 | /* |
77 | The video mem address of the video card. | 77 | The video mem address of the video card. |
@@ -104,9 +104,9 @@ module_param(default_norm, int, 0444); | |||
104 | MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); | 104 | MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); |
105 | 105 | ||
106 | /* /dev/videoN, -1 for autodetect */ | 106 | /* /dev/videoN, -1 for autodetect */ |
107 | static int video_nr[BUZ_MAX] = {-1, -1, -1, -1}; | 107 | static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; |
108 | module_param_array(video_nr, int, NULL, 0444); | 108 | module_param_array(video_nr, int, NULL, 0444); |
109 | MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); | 109 | MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); |
110 | 110 | ||
111 | /* | 111 | /* |
112 | Number and size of grab buffers for Video 4 Linux | 112 | Number and size of grab buffers for Video 4 Linux |
@@ -153,9 +153,21 @@ MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); | |||
153 | MODULE_AUTHOR("Serguei Miridonov"); | 153 | MODULE_AUTHOR("Serguei Miridonov"); |
154 | MODULE_LICENSE("GPL"); | 154 | MODULE_LICENSE("GPL"); |
155 | 155 | ||
156 | #define ZR_DEVICE(subven, subdev, data) { \ | ||
157 | .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \ | ||
158 | .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) } | ||
159 | |||
160 | static struct pci_device_id zr36067_pci_tbl[] = { | ||
161 | ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus), | ||
162 | ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus), | ||
163 | ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10), | ||
164 | ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ), | ||
165 | ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS), | ||
166 | {0} | ||
167 | }; | ||
168 | MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); | ||
156 | 169 | ||
157 | int zoran_num; /* number of Buzs in use */ | 170 | static unsigned int zoran_num; /* number of cards found */ |
158 | struct zoran *zoran[BUZ_MAX]; | ||
159 | 171 | ||
160 | /* videocodec bus functions ZR36060 */ | 172 | /* videocodec bus functions ZR36060 */ |
161 | static u32 | 173 | static u32 |
@@ -472,8 +484,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
472 | }, { | 484 | }, { |
473 | .type = DC10plus, | 485 | .type = DC10plus, |
474 | .name = "DC10plus", | 486 | .name = "DC10plus", |
475 | .vendor_id = PCI_VENDOR_ID_MIRO, | ||
476 | .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS, | ||
477 | .i2c_decoder = I2C_DRIVERID_SAA7110, | 487 | .i2c_decoder = I2C_DRIVERID_SAA7110, |
478 | .i2c_encoder = I2C_DRIVERID_ADV7175, | 488 | .i2c_encoder = I2C_DRIVERID_ADV7175, |
479 | .video_codec = CODEC_TYPE_ZR36060, | 489 | .video_codec = CODEC_TYPE_ZR36060, |
@@ -531,8 +541,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
531 | }, { | 541 | }, { |
532 | .type = DC30plus, | 542 | .type = DC30plus, |
533 | .name = "DC30plus", | 543 | .name = "DC30plus", |
534 | .vendor_id = PCI_VENDOR_ID_MIRO, | ||
535 | .device_id = PCI_DEVICE_ID_MIRO_DC30PLUS, | ||
536 | .i2c_decoder = I2C_DRIVERID_VPX3220, | 544 | .i2c_decoder = I2C_DRIVERID_VPX3220, |
537 | .i2c_encoder = I2C_DRIVERID_ADV7175, | 545 | .i2c_encoder = I2C_DRIVERID_ADV7175, |
538 | .video_codec = CODEC_TYPE_ZR36050, | 546 | .video_codec = CODEC_TYPE_ZR36050, |
@@ -589,8 +597,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
589 | }, { | 597 | }, { |
590 | .type = LML33R10, | 598 | .type = LML33R10, |
591 | .name = "LML33R10", | 599 | .name = "LML33R10", |
592 | .vendor_id = PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, | ||
593 | .device_id = PCI_DEVICE_ID_LML_33R10, | ||
594 | .i2c_decoder = I2C_DRIVERID_SAA7114, | 600 | .i2c_decoder = I2C_DRIVERID_SAA7114, |
595 | .i2c_encoder = I2C_DRIVERID_ADV7170, | 601 | .i2c_encoder = I2C_DRIVERID_ADV7170, |
596 | .video_codec = CODEC_TYPE_ZR36060, | 602 | .video_codec = CODEC_TYPE_ZR36060, |
@@ -618,8 +624,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
618 | }, { | 624 | }, { |
619 | .type = BUZ, | 625 | .type = BUZ, |
620 | .name = "Buz", | 626 | .name = "Buz", |
621 | .vendor_id = PCI_VENDOR_ID_IOMEGA, | ||
622 | .device_id = PCI_DEVICE_ID_IOMEGA_BUZ, | ||
623 | .i2c_decoder = I2C_DRIVERID_SAA7111A, | 627 | .i2c_decoder = I2C_DRIVERID_SAA7111A, |
624 | .i2c_encoder = I2C_DRIVERID_SAA7185B, | 628 | .i2c_encoder = I2C_DRIVERID_SAA7185B, |
625 | .video_codec = CODEC_TYPE_ZR36060, | 629 | .video_codec = CODEC_TYPE_ZR36060, |
@@ -649,8 +653,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = { | |||
649 | .name = "6-Eyes", | 653 | .name = "6-Eyes", |
650 | /* AverMedia chose not to brand the 6-Eyes. Thus it | 654 | /* AverMedia chose not to brand the 6-Eyes. Thus it |
651 | can't be autodetected, and requires card=x. */ | 655 | can't be autodetected, and requires card=x. */ |
652 | .vendor_id = -1, | ||
653 | .device_id = -1, | ||
654 | .i2c_decoder = I2C_DRIVERID_KS0127, | 656 | .i2c_decoder = I2C_DRIVERID_KS0127, |
655 | .i2c_encoder = I2C_DRIVERID_BT866, | 657 | .i2c_encoder = I2C_DRIVERID_BT866, |
656 | .video_codec = CODEC_TYPE_ZR36060, | 658 | .video_codec = CODEC_TYPE_ZR36060, |
@@ -1138,7 +1140,8 @@ zr36057_init (struct zoran *zr) | |||
1138 | strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); | 1140 | strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); |
1139 | err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); | 1141 | err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); |
1140 | if (err < 0) | 1142 | if (err < 0) |
1141 | goto exit_unregister; | 1143 | goto exit_free; |
1144 | video_set_drvdata(zr->video_dev, zr); | ||
1142 | 1145 | ||
1143 | zoran_init_hardware(zr); | 1146 | zoran_init_hardware(zr); |
1144 | if (zr36067_debug > 2) | 1147 | if (zr36067_debug > 2) |
@@ -1153,19 +1156,19 @@ zr36057_init (struct zoran *zr) | |||
1153 | zr->initialized = 1; | 1156 | zr->initialized = 1; |
1154 | return 0; | 1157 | return 0; |
1155 | 1158 | ||
1156 | exit_unregister: | ||
1157 | zoran_unregister_i2c(zr); | ||
1158 | exit_free: | 1159 | exit_free: |
1159 | kfree(zr->stat_com); | 1160 | kfree(zr->stat_com); |
1160 | kfree(zr->video_dev); | 1161 | kfree(zr->video_dev); |
1161 | return err; | 1162 | return err; |
1162 | } | 1163 | } |
1163 | 1164 | ||
1164 | static void | 1165 | static void __devexit zoran_remove(struct pci_dev *pdev) |
1165 | zoran_release (struct zoran *zr) | ||
1166 | { | 1166 | { |
1167 | struct zoran *zr = pci_get_drvdata(pdev); | ||
1168 | |||
1167 | if (!zr->initialized) | 1169 | if (!zr->initialized) |
1168 | goto exit_free; | 1170 | goto exit_free; |
1171 | |||
1169 | /* unregister videocodec bus */ | 1172 | /* unregister videocodec bus */ |
1170 | if (zr->codec) { | 1173 | if (zr->codec) { |
1171 | struct videocodec_master *master = zr->codec->master_data; | 1174 | struct videocodec_master *master = zr->codec->master_data; |
@@ -1194,6 +1197,7 @@ zoran_release (struct zoran *zr) | |||
1194 | pci_disable_device(zr->pci_dev); | 1197 | pci_disable_device(zr->pci_dev); |
1195 | video_unregister_device(zr->video_dev); | 1198 | video_unregister_device(zr->video_dev); |
1196 | exit_free: | 1199 | exit_free: |
1200 | pci_set_drvdata(pdev, NULL); | ||
1197 | kfree(zr); | 1201 | kfree(zr); |
1198 | } | 1202 | } |
1199 | 1203 | ||
@@ -1256,338 +1260,329 @@ zoran_setup_videocodec (struct zoran *zr, | |||
1256 | * Scan for a Buz card (actually for the PCI controller ZR36057), | 1260 | * Scan for a Buz card (actually for the PCI controller ZR36057), |
1257 | * request the irq and map the io memory | 1261 | * request the irq and map the io memory |
1258 | */ | 1262 | */ |
1259 | static int __devinit | 1263 | static int __devinit zoran_probe(struct pci_dev *pdev, |
1260 | find_zr36057 (void) | 1264 | const struct pci_device_id *ent) |
1261 | { | 1265 | { |
1262 | unsigned char latency, need_latency; | 1266 | unsigned char latency, need_latency; |
1263 | struct zoran *zr; | 1267 | struct zoran *zr; |
1264 | struct pci_dev *dev = NULL; | ||
1265 | int result; | 1268 | int result; |
1266 | struct videocodec_master *master_vfe = NULL; | 1269 | struct videocodec_master *master_vfe = NULL; |
1267 | struct videocodec_master *master_codec = NULL; | 1270 | struct videocodec_master *master_codec = NULL; |
1268 | int card_num; | 1271 | int card_num; |
1269 | char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name; | 1272 | char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name; |
1273 | unsigned int nr; | ||
1270 | 1274 | ||
1271 | zoran_num = 0; | ||
1272 | while (zoran_num < BUZ_MAX && | ||
1273 | (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) { | ||
1274 | card_num = card[zoran_num]; | ||
1275 | zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); | ||
1276 | if (!zr) { | ||
1277 | dprintk(1, | ||
1278 | KERN_ERR | ||
1279 | "%s: find_zr36057() - kzalloc failed\n", | ||
1280 | ZORAN_NAME); | ||
1281 | continue; | ||
1282 | } | ||
1283 | zr->pci_dev = dev; | ||
1284 | //zr->zr36057_mem = NULL; | ||
1285 | zr->id = zoran_num; | ||
1286 | snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); | ||
1287 | spin_lock_init(&zr->spinlock); | ||
1288 | mutex_init(&zr->resource_lock); | ||
1289 | if (pci_enable_device(dev)) | ||
1290 | goto zr_free_mem; | ||
1291 | zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0); | ||
1292 | pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, | ||
1293 | &zr->revision); | ||
1294 | if (zr->revision < 2) { | ||
1295 | dprintk(1, | ||
1296 | KERN_INFO | ||
1297 | "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n", | ||
1298 | ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq, | ||
1299 | zr->zr36057_adr); | ||
1300 | 1275 | ||
1301 | if (card_num == -1) { | 1276 | nr = zoran_num++; |
1302 | dprintk(1, | 1277 | if (nr >= BUZ_MAX) { |
1303 | KERN_ERR | 1278 | dprintk(1, |
1304 | "%s: find_zr36057() - no card specified, please use the card=X insmod option\n", | 1279 | KERN_ERR |
1305 | ZR_DEVNAME(zr)); | 1280 | "%s: driver limited to %d card(s) maximum\n", |
1306 | goto zr_free_mem; | 1281 | ZORAN_NAME, BUZ_MAX); |
1307 | } | 1282 | return -ENOENT; |
1308 | } else { | 1283 | } |
1309 | int i; | ||
1310 | unsigned short ss_vendor, ss_device; | ||
1311 | 1284 | ||
1312 | ss_vendor = zr->pci_dev->subsystem_vendor; | 1285 | zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); |
1313 | ss_device = zr->pci_dev->subsystem_device; | 1286 | if (!zr) { |
1287 | dprintk(1, | ||
1288 | KERN_ERR | ||
1289 | "%s: find_zr36057() - kzalloc failed\n", | ||
1290 | ZORAN_NAME); | ||
1291 | return -ENOMEM; | ||
1292 | } | ||
1293 | zr->pci_dev = pdev; | ||
1294 | zr->id = nr; | ||
1295 | snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); | ||
1296 | spin_lock_init(&zr->spinlock); | ||
1297 | mutex_init(&zr->resource_lock); | ||
1298 | if (pci_enable_device(pdev)) | ||
1299 | goto zr_free_mem; | ||
1300 | pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision); | ||
1301 | |||
1302 | dprintk(1, | ||
1303 | KERN_INFO | ||
1304 | "%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n", | ||
1305 | ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision, | ||
1306 | zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0)); | ||
1307 | if (zr->revision >= 2) { | ||
1308 | dprintk(1, | ||
1309 | KERN_INFO | ||
1310 | "%s: Subsystem vendor=0x%04x id=0x%04x\n", | ||
1311 | ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor, | ||
1312 | zr->pci_dev->subsystem_device); | ||
1313 | } | ||
1314 | |||
1315 | /* Use auto-detected card type? */ | ||
1316 | if (card[nr] == -1) { | ||
1317 | if (zr->revision < 2) { | ||
1314 | dprintk(1, | 1318 | dprintk(1, |
1315 | KERN_INFO | 1319 | KERN_ERR |
1316 | "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n", | 1320 | "%s: No card type specified, please use the card=X module parameter\n", |
1317 | ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq, | 1321 | ZR_DEVNAME(zr)); |
1318 | zr->zr36057_adr); | ||
1319 | dprintk(1, | 1322 | dprintk(1, |
1320 | KERN_INFO | ||
1321 | "%s: subsystem vendor=0x%04x id=0x%04x\n", | ||
1322 | ZR_DEVNAME(zr), ss_vendor, ss_device); | ||
1323 | if (card_num == -1) { | ||
1324 | dprintk(3, | ||
1325 | KERN_DEBUG | ||
1326 | "%s: find_zr36057() - trying to autodetect card type\n", | ||
1327 | ZR_DEVNAME(zr)); | ||
1328 | for (i=0;i<NUM_CARDS;i++) { | ||
1329 | if (ss_vendor == zoran_cards[i].vendor_id && | ||
1330 | ss_device == zoran_cards[i].device_id) { | ||
1331 | dprintk(3, | ||
1332 | KERN_DEBUG | ||
1333 | "%s: find_zr36057() - card %s detected\n", | ||
1334 | ZR_DEVNAME(zr), | ||
1335 | zoran_cards[i].name); | ||
1336 | card_num = i; | ||
1337 | break; | ||
1338 | } | ||
1339 | } | ||
1340 | if (i == NUM_CARDS) { | ||
1341 | dprintk(1, | ||
1342 | KERN_ERR | ||
1343 | "%s: find_zr36057() - unknown card\n", | ||
1344 | ZR_DEVNAME(zr)); | ||
1345 | goto zr_free_mem; | ||
1346 | } | ||
1347 | } | ||
1348 | } | ||
1349 | |||
1350 | if (card_num < 0 || card_num >= NUM_CARDS) { | ||
1351 | dprintk(2, | ||
1352 | KERN_ERR | 1323 | KERN_ERR |
1353 | "%s: find_zr36057() - invalid cardnum %d\n", | 1324 | "%s: It is not possible to auto-detect ZR36057 based cards\n", |
1354 | ZR_DEVNAME(zr), card_num); | 1325 | ZR_DEVNAME(zr)); |
1355 | goto zr_free_mem; | 1326 | goto zr_free_mem; |
1356 | } | 1327 | } |
1357 | 1328 | ||
1358 | /* even though we make this a non pointer and thus | 1329 | card_num = ent->driver_data; |
1359 | * theoretically allow for making changes to this struct | 1330 | if (card_num >= NUM_CARDS) { |
1360 | * on a per-individual card basis at runtime, this is | ||
1361 | * strongly discouraged. This structure is intended to | ||
1362 | * keep general card information, no settings or anything */ | ||
1363 | zr->card = zoran_cards[card_num]; | ||
1364 | snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), | ||
1365 | "%s[%u]", zr->card.name, zr->id); | ||
1366 | |||
1367 | zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000); | ||
1368 | if (!zr->zr36057_mem) { | ||
1369 | dprintk(1, | 1331 | dprintk(1, |
1370 | KERN_ERR | 1332 | KERN_ERR |
1371 | "%s: find_zr36057() - ioremap failed\n", | 1333 | "%s: Unknown card, try specifying card=X module parameter\n", |
1372 | ZR_DEVNAME(zr)); | 1334 | ZR_DEVNAME(zr)); |
1373 | goto zr_free_mem; | 1335 | goto zr_free_mem; |
1374 | } | 1336 | } |
1375 | 1337 | dprintk(3, | |
1376 | result = request_irq(zr->pci_dev->irq, | 1338 | KERN_DEBUG |
1377 | zoran_irq, | 1339 | "%s: %s() - card %s detected\n", |
1378 | IRQF_SHARED | IRQF_DISABLED, | 1340 | ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name); |
1379 | ZR_DEVNAME(zr), | 1341 | } else { |
1380 | (void *) zr); | 1342 | card_num = card[nr]; |
1381 | if (result < 0) { | 1343 | if (card_num >= NUM_CARDS || card_num < 0) { |
1382 | if (result == -EINVAL) { | 1344 | dprintk(1, |
1383 | dprintk(1, | 1345 | KERN_ERR |
1384 | KERN_ERR | 1346 | "%s: User specified card type %d out of range (0 .. %d)\n", |
1385 | "%s: find_zr36057() - bad irq number or handler\n", | 1347 | ZR_DEVNAME(zr), card_num, NUM_CARDS - 1); |
1386 | ZR_DEVNAME(zr)); | 1348 | goto zr_free_mem; |
1387 | } else if (result == -EBUSY) { | ||
1388 | dprintk(1, | ||
1389 | KERN_ERR | ||
1390 | "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", | ||
1391 | ZR_DEVNAME(zr), zr->pci_dev->irq); | ||
1392 | } else { | ||
1393 | dprintk(1, | ||
1394 | KERN_ERR | ||
1395 | "%s: find_zr36057() - can't assign irq, error code %d\n", | ||
1396 | ZR_DEVNAME(zr), result); | ||
1397 | } | ||
1398 | goto zr_unmap; | ||
1399 | } | ||
1400 | |||
1401 | /* set PCI latency timer */ | ||
1402 | pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, | ||
1403 | &latency); | ||
1404 | need_latency = zr->revision > 1 ? 32 : 48; | ||
1405 | if (latency != need_latency) { | ||
1406 | dprintk(2, | ||
1407 | KERN_INFO | ||
1408 | "%s: Changing PCI latency from %d to %d.\n", | ||
1409 | ZR_DEVNAME(zr), latency, need_latency); | ||
1410 | pci_write_config_byte(zr->pci_dev, | ||
1411 | PCI_LATENCY_TIMER, | ||
1412 | need_latency); | ||
1413 | } | 1349 | } |
1350 | } | ||
1414 | 1351 | ||
1415 | zr36057_restart(zr); | 1352 | /* even though we make this a non pointer and thus |
1416 | /* i2c */ | 1353 | * theoretically allow for making changes to this struct |
1417 | dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", | 1354 | * on a per-individual card basis at runtime, this is |
1418 | ZR_DEVNAME(zr)); | 1355 | * strongly discouraged. This structure is intended to |
1356 | * keep general card information, no settings or anything */ | ||
1357 | zr->card = zoran_cards[card_num]; | ||
1358 | snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), | ||
1359 | "%s[%u]", zr->card.name, zr->id); | ||
1360 | |||
1361 | zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0); | ||
1362 | if (!zr->zr36057_mem) { | ||
1363 | dprintk(1, | ||
1364 | KERN_ERR | ||
1365 | "%s: %s() - ioremap failed\n", | ||
1366 | ZR_DEVNAME(zr), __func__); | ||
1367 | goto zr_free_mem; | ||
1368 | } | ||
1419 | 1369 | ||
1420 | /* i2c decoder */ | 1370 | result = request_irq(zr->pci_dev->irq, zoran_irq, |
1421 | if (decoder[zr->id] != -1) { | 1371 | IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr); |
1422 | i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); | 1372 | if (result < 0) { |
1423 | zr->card.i2c_decoder = decoder[zr->id]; | 1373 | if (result == -EINVAL) { |
1424 | } else if (zr->card.i2c_decoder != 0) { | 1374 | dprintk(1, |
1425 | i2c_dec_name = | 1375 | KERN_ERR |
1426 | i2cid_to_modulename(zr->card.i2c_decoder); | 1376 | "%s: find_zr36057() - bad irq number or handler\n", |
1377 | ZR_DEVNAME(zr)); | ||
1378 | } else if (result == -EBUSY) { | ||
1379 | dprintk(1, | ||
1380 | KERN_ERR | ||
1381 | "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n", | ||
1382 | ZR_DEVNAME(zr), zr->pci_dev->irq); | ||
1427 | } else { | 1383 | } else { |
1428 | i2c_dec_name = NULL; | 1384 | dprintk(1, |
1385 | KERN_ERR | ||
1386 | "%s: find_zr36057() - can't assign irq, error code %d\n", | ||
1387 | ZR_DEVNAME(zr), result); | ||
1429 | } | 1388 | } |
1389 | goto zr_unmap; | ||
1390 | } | ||
1430 | 1391 | ||
1431 | if (i2c_dec_name) { | 1392 | /* set PCI latency timer */ |
1432 | if ((result = request_module(i2c_dec_name)) < 0) { | 1393 | pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, |
1433 | dprintk(1, | 1394 | &latency); |
1434 | KERN_ERR | 1395 | need_latency = zr->revision > 1 ? 32 : 48; |
1435 | "%s: failed to load module %s: %d\n", | 1396 | if (latency != need_latency) { |
1436 | ZR_DEVNAME(zr), i2c_dec_name, result); | 1397 | dprintk(2, |
1437 | } | 1398 | KERN_INFO |
1438 | } | 1399 | "%s: Changing PCI latency from %d to %d\n", |
1400 | ZR_DEVNAME(zr), latency, need_latency); | ||
1401 | pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, | ||
1402 | need_latency); | ||
1403 | } | ||
1439 | 1404 | ||
1440 | /* i2c encoder */ | 1405 | zr36057_restart(zr); |
1441 | if (encoder[zr->id] != -1) { | 1406 | /* i2c */ |
1442 | i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); | 1407 | dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", |
1443 | zr->card.i2c_encoder = encoder[zr->id]; | 1408 | ZR_DEVNAME(zr)); |
1444 | } else if (zr->card.i2c_encoder != 0) { | 1409 | |
1445 | i2c_enc_name = | 1410 | /* i2c decoder */ |
1446 | i2cid_to_modulename(zr->card.i2c_encoder); | 1411 | if (decoder[zr->id] != -1) { |
1447 | } else { | 1412 | i2c_dec_name = i2cid_to_modulename(decoder[zr->id]); |
1448 | i2c_enc_name = NULL; | 1413 | zr->card.i2c_decoder = decoder[zr->id]; |
1449 | } | 1414 | } else if (zr->card.i2c_decoder != 0) { |
1415 | i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder); | ||
1416 | } else { | ||
1417 | i2c_dec_name = NULL; | ||
1418 | } | ||
1450 | 1419 | ||
1451 | if (i2c_enc_name) { | 1420 | if (i2c_dec_name) { |
1452 | if ((result = request_module(i2c_enc_name)) < 0) { | 1421 | result = request_module(i2c_dec_name); |
1453 | dprintk(1, | 1422 | if (result < 0) { |
1454 | KERN_ERR | 1423 | dprintk(1, |
1455 | "%s: failed to load module %s: %d\n", | 1424 | KERN_ERR |
1456 | ZR_DEVNAME(zr), i2c_enc_name, result); | 1425 | "%s: failed to load module %s: %d\n", |
1457 | } | 1426 | ZR_DEVNAME(zr), i2c_dec_name, result); |
1458 | } | 1427 | } |
1428 | } | ||
1429 | |||
1430 | /* i2c encoder */ | ||
1431 | if (encoder[zr->id] != -1) { | ||
1432 | i2c_enc_name = i2cid_to_modulename(encoder[zr->id]); | ||
1433 | zr->card.i2c_encoder = encoder[zr->id]; | ||
1434 | } else if (zr->card.i2c_encoder != 0) { | ||
1435 | i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder); | ||
1436 | } else { | ||
1437 | i2c_enc_name = NULL; | ||
1438 | } | ||
1459 | 1439 | ||
1460 | if (zoran_register_i2c(zr) < 0) { | 1440 | if (i2c_enc_name) { |
1441 | result = request_module(i2c_enc_name); | ||
1442 | if (result < 0) { | ||
1461 | dprintk(1, | 1443 | dprintk(1, |
1462 | KERN_ERR | 1444 | KERN_ERR |
1463 | "%s: find_zr36057() - can't initialize i2c bus\n", | 1445 | "%s: failed to load module %s: %d\n", |
1464 | ZR_DEVNAME(zr)); | 1446 | ZR_DEVNAME(zr), i2c_enc_name, result); |
1465 | goto zr_free_irq; | ||
1466 | } | 1447 | } |
1448 | } | ||
1467 | 1449 | ||
1468 | dprintk(2, | 1450 | if (zoran_register_i2c(zr) < 0) { |
1469 | KERN_INFO "%s: Initializing videocodec bus...\n", | 1451 | dprintk(1, |
1452 | KERN_ERR | ||
1453 | "%s: find_zr36057() - can't initialize i2c bus\n", | ||
1470 | ZR_DEVNAME(zr)); | 1454 | ZR_DEVNAME(zr)); |
1455 | goto zr_free_irq; | ||
1456 | } | ||
1471 | 1457 | ||
1472 | if (zr->card.video_codec != 0 && | 1458 | dprintk(2, |
1473 | (codec_name = | 1459 | KERN_INFO "%s: Initializing videocodec bus...\n", |
1474 | codecid_to_modulename(zr->card.video_codec)) != NULL) { | 1460 | ZR_DEVNAME(zr)); |
1475 | if ((result = request_module(codec_name)) < 0) { | 1461 | |
1462 | if (zr->card.video_codec) { | ||
1463 | codec_name = codecid_to_modulename(zr->card.video_codec); | ||
1464 | if (codec_name) { | ||
1465 | result = request_module(codec_name); | ||
1466 | if (result) { | ||
1476 | dprintk(1, | 1467 | dprintk(1, |
1477 | KERN_ERR | 1468 | KERN_ERR |
1478 | "%s: failed to load modules %s: %d\n", | 1469 | "%s: failed to load modules %s: %d\n", |
1479 | ZR_DEVNAME(zr), codec_name, result); | 1470 | ZR_DEVNAME(zr), codec_name, result); |
1480 | } | 1471 | } |
1481 | } | 1472 | } |
1482 | if (zr->card.video_vfe != 0 && | 1473 | } |
1483 | (vfe_name = | 1474 | if (zr->card.video_vfe) { |
1484 | codecid_to_modulename(zr->card.video_vfe)) != NULL) { | 1475 | vfe_name = codecid_to_modulename(zr->card.video_vfe); |
1485 | if ((result = request_module(vfe_name)) < 0) { | 1476 | if (vfe_name) { |
1477 | result = request_module(vfe_name); | ||
1478 | if (result < 0) { | ||
1486 | dprintk(1, | 1479 | dprintk(1, |
1487 | KERN_ERR | 1480 | KERN_ERR |
1488 | "%s: failed to load modules %s: %d\n", | 1481 | "%s: failed to load modules %s: %d\n", |
1489 | ZR_DEVNAME(zr), vfe_name, result); | 1482 | ZR_DEVNAME(zr), vfe_name, result); |
1490 | } | 1483 | } |
1491 | } | 1484 | } |
1485 | } | ||
1492 | 1486 | ||
1493 | /* reset JPEG codec */ | 1487 | /* reset JPEG codec */ |
1494 | jpeg_codec_sleep(zr, 1); | 1488 | jpeg_codec_sleep(zr, 1); |
1495 | jpeg_codec_reset(zr); | 1489 | jpeg_codec_reset(zr); |
1496 | /* video bus enabled */ | 1490 | /* video bus enabled */ |
1497 | /* display codec revision */ | 1491 | /* display codec revision */ |
1498 | if (zr->card.video_codec != 0) { | 1492 | if (zr->card.video_codec != 0) { |
1499 | master_codec = zoran_setup_videocodec(zr, | 1493 | master_codec = zoran_setup_videocodec(zr, zr->card.video_codec); |
1500 | zr->card.video_codec); | 1494 | if (!master_codec) |
1501 | if (!master_codec) | 1495 | goto zr_unreg_i2c; |
1502 | goto zr_unreg_i2c; | 1496 | zr->codec = videocodec_attach(master_codec); |
1503 | zr->codec = videocodec_attach(master_codec); | 1497 | if (!zr->codec) { |
1504 | if (!zr->codec) { | 1498 | dprintk(1, |
1505 | dprintk(1, | 1499 | KERN_ERR |
1506 | KERN_ERR | 1500 | "%s: find_zr36057() - no codec found\n", |
1507 | "%s: find_zr36057() - no codec found\n", | 1501 | ZR_DEVNAME(zr)); |
1508 | ZR_DEVNAME(zr)); | 1502 | goto zr_free_codec; |
1509 | goto zr_free_codec; | ||
1510 | } | ||
1511 | if (zr->codec->type != zr->card.video_codec) { | ||
1512 | dprintk(1, | ||
1513 | KERN_ERR | ||
1514 | "%s: find_zr36057() - wrong codec\n", | ||
1515 | ZR_DEVNAME(zr)); | ||
1516 | goto zr_detach_codec; | ||
1517 | } | ||
1518 | } | 1503 | } |
1519 | if (zr->card.video_vfe != 0) { | 1504 | if (zr->codec->type != zr->card.video_codec) { |
1520 | master_vfe = zoran_setup_videocodec(zr, | 1505 | dprintk(1, |
1521 | zr->card.video_vfe); | 1506 | KERN_ERR |
1522 | if (!master_vfe) | 1507 | "%s: find_zr36057() - wrong codec\n", |
1523 | goto zr_detach_codec; | 1508 | ZR_DEVNAME(zr)); |
1524 | zr->vfe = videocodec_attach(master_vfe); | 1509 | goto zr_detach_codec; |
1525 | if (!zr->vfe) { | 1510 | } |
1526 | dprintk(1, | 1511 | } |
1527 | KERN_ERR | 1512 | if (zr->card.video_vfe != 0) { |
1528 | "%s: find_zr36057() - no VFE found\n", | 1513 | master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe); |
1529 | ZR_DEVNAME(zr)); | 1514 | if (!master_vfe) |
1530 | goto zr_free_vfe; | 1515 | goto zr_detach_codec; |
1531 | } | 1516 | zr->vfe = videocodec_attach(master_vfe); |
1532 | if (zr->vfe->type != zr->card.video_vfe) { | 1517 | if (!zr->vfe) { |
1533 | dprintk(1, | 1518 | dprintk(1, |
1534 | KERN_ERR | 1519 | KERN_ERR |
1535 | "%s: find_zr36057() = wrong VFE\n", | 1520 | "%s: find_zr36057() - no VFE found\n", |
1536 | ZR_DEVNAME(zr)); | 1521 | ZR_DEVNAME(zr)); |
1537 | goto zr_detach_vfe; | 1522 | goto zr_free_vfe; |
1538 | } | 1523 | } |
1524 | if (zr->vfe->type != zr->card.video_vfe) { | ||
1525 | dprintk(1, | ||
1526 | KERN_ERR | ||
1527 | "%s: find_zr36057() = wrong VFE\n", | ||
1528 | ZR_DEVNAME(zr)); | ||
1529 | goto zr_detach_vfe; | ||
1539 | } | 1530 | } |
1540 | /* Success so keep the pci_dev referenced */ | ||
1541 | pci_dev_get(zr->pci_dev); | ||
1542 | zoran[zoran_num++] = zr; | ||
1543 | continue; | ||
1544 | |||
1545 | // Init errors | ||
1546 | zr_detach_vfe: | ||
1547 | videocodec_detach(zr->vfe); | ||
1548 | zr_free_vfe: | ||
1549 | kfree(master_vfe); | ||
1550 | zr_detach_codec: | ||
1551 | videocodec_detach(zr->codec); | ||
1552 | zr_free_codec: | ||
1553 | kfree(master_codec); | ||
1554 | zr_unreg_i2c: | ||
1555 | zoran_unregister_i2c(zr); | ||
1556 | zr_free_irq: | ||
1557 | btwrite(0, ZR36057_SPGPPCR); | ||
1558 | free_irq(zr->pci_dev->irq, zr); | ||
1559 | zr_unmap: | ||
1560 | iounmap(zr->zr36057_mem); | ||
1561 | zr_free_mem: | ||
1562 | kfree(zr); | ||
1563 | continue; | ||
1564 | } | 1531 | } |
1565 | if (dev) /* Clean up ref count on early exit */ | ||
1566 | pci_dev_put(dev); | ||
1567 | 1532 | ||
1568 | if (zoran_num == 0) { | 1533 | /* take care of Natoma chipset and a revision 1 zr36057 */ |
1569 | dprintk(1, KERN_INFO "No known MJPEG cards found.\n"); | 1534 | if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { |
1535 | zr->jpg_buffers.need_contiguous = 1; | ||
1536 | dprintk(1, | ||
1537 | KERN_INFO | ||
1538 | "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", | ||
1539 | ZR_DEVNAME(zr)); | ||
1570 | } | 1540 | } |
1571 | return zoran_num; | 1541 | |
1542 | if (zr36057_init(zr) < 0) | ||
1543 | goto zr_detach_vfe; | ||
1544 | |||
1545 | zoran_proc_init(zr); | ||
1546 | |||
1547 | pci_set_drvdata(pdev, zr); | ||
1548 | |||
1549 | return 0; | ||
1550 | |||
1551 | zr_detach_vfe: | ||
1552 | videocodec_detach(zr->vfe); | ||
1553 | zr_free_vfe: | ||
1554 | kfree(master_vfe); | ||
1555 | zr_detach_codec: | ||
1556 | videocodec_detach(zr->codec); | ||
1557 | zr_free_codec: | ||
1558 | kfree(master_codec); | ||
1559 | zr_unreg_i2c: | ||
1560 | zoran_unregister_i2c(zr); | ||
1561 | zr_free_irq: | ||
1562 | btwrite(0, ZR36057_SPGPPCR); | ||
1563 | free_irq(zr->pci_dev->irq, zr); | ||
1564 | zr_unmap: | ||
1565 | iounmap(zr->zr36057_mem); | ||
1566 | zr_free_mem: | ||
1567 | kfree(zr); | ||
1568 | |||
1569 | return -ENODEV; | ||
1572 | } | 1570 | } |
1573 | 1571 | ||
1574 | static int __init | 1572 | static struct pci_driver zoran_driver = { |
1575 | init_dc10_cards (void) | 1573 | .name = "zr36067", |
1574 | .id_table = zr36067_pci_tbl, | ||
1575 | .probe = zoran_probe, | ||
1576 | .remove = zoran_remove, | ||
1577 | }; | ||
1578 | |||
1579 | static int __init zoran_init(void) | ||
1576 | { | 1580 | { |
1577 | int i; | 1581 | int res; |
1578 | 1582 | ||
1579 | memset(zoran, 0, sizeof(zoran)); | ||
1580 | printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n", | 1583 | printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n", |
1581 | MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION); | 1584 | MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION); |
1582 | 1585 | ||
1583 | /* Look for cards */ | ||
1584 | if (find_zr36057() < 0) { | ||
1585 | return -EIO; | ||
1586 | } | ||
1587 | if (zoran_num == 0) | ||
1588 | return -ENODEV; | ||
1589 | dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME, | ||
1590 | zoran_num); | ||
1591 | /* check the parameters we have been given, adjust if necessary */ | 1586 | /* check the parameters we have been given, adjust if necessary */ |
1592 | if (v4l_nbufs < 2) | 1587 | if (v4l_nbufs < 2) |
1593 | v4l_nbufs = 2; | 1588 | v4l_nbufs = 2; |
@@ -1629,37 +1624,22 @@ init_dc10_cards (void) | |||
1629 | ZORAN_NAME); | 1624 | ZORAN_NAME); |
1630 | } | 1625 | } |
1631 | 1626 | ||
1632 | /* take care of Natoma chipset and a revision 1 zr36057 */ | 1627 | res = pci_register_driver(&zoran_driver); |
1633 | for (i = 0; i < zoran_num; i++) { | 1628 | if (res) { |
1634 | struct zoran *zr = zoran[i]; | 1629 | dprintk(1, |
1635 | 1630 | KERN_ERR | |
1636 | if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { | 1631 | "%s: Unable to register ZR36057 driver\n", |
1637 | zr->jpg_buffers.need_contiguous = 1; | 1632 | ZORAN_NAME); |
1638 | dprintk(1, | 1633 | return res; |
1639 | KERN_INFO | ||
1640 | "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", | ||
1641 | ZR_DEVNAME(zr)); | ||
1642 | } | ||
1643 | |||
1644 | if (zr36057_init(zr) < 0) { | ||
1645 | for (i = 0; i < zoran_num; i++) | ||
1646 | zoran_release(zoran[i]); | ||
1647 | return -EIO; | ||
1648 | } | ||
1649 | zoran_proc_init(zr); | ||
1650 | } | 1634 | } |
1651 | 1635 | ||
1652 | return 0; | 1636 | return 0; |
1653 | } | 1637 | } |
1654 | 1638 | ||
1655 | static void __exit | 1639 | static void __exit zoran_exit(void) |
1656 | unload_dc10_cards (void) | ||
1657 | { | 1640 | { |
1658 | int i; | 1641 | pci_unregister_driver(&zoran_driver); |
1659 | |||
1660 | for (i = 0; i < zoran_num; i++) | ||
1661 | zoran_release(zoran[i]); | ||
1662 | } | 1642 | } |
1663 | 1643 | ||
1664 | module_init(init_dc10_cards); | 1644 | module_init(zoran_init); |
1665 | module_exit(unload_dc10_cards); | 1645 | module_exit(zoran_exit); |
diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h index e4dc9d29b404..4507bdc5e338 100644 --- a/drivers/media/video/zoran/zoran_card.h +++ b/drivers/media/video/zoran/zoran_card.h | |||
@@ -40,8 +40,6 @@ extern int zr36067_debug; | |||
40 | 40 | ||
41 | /* Anybody who uses more than four? */ | 41 | /* Anybody who uses more than four? */ |
42 | #define BUZ_MAX 4 | 42 | #define BUZ_MAX 4 |
43 | extern int zoran_num; | ||
44 | extern struct zoran *zoran[BUZ_MAX]; | ||
45 | 43 | ||
46 | extern struct video_device zoran_template; | 44 | extern struct video_device zoran_template; |
47 | 45 | ||
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index b58b9dda715c..120ef235e63d 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -1196,83 +1196,54 @@ zoran_close_end_session (struct file *file) | |||
1196 | * Open a zoran card. Right now the flags stuff is just playing | 1196 | * Open a zoran card. Right now the flags stuff is just playing |
1197 | */ | 1197 | */ |
1198 | 1198 | ||
1199 | static int | 1199 | static int zoran_open(struct file *file) |
1200 | zoran_open(struct file *file) | ||
1201 | { | 1200 | { |
1202 | unsigned int minor = video_devdata(file)->minor; | 1201 | struct zoran *zr = video_drvdata(file); |
1203 | struct zoran *zr = NULL; | ||
1204 | struct zoran_fh *fh; | 1202 | struct zoran_fh *fh; |
1205 | int i, res, first_open = 0, have_module_locks = 0; | 1203 | int res, first_open = 0; |
1206 | 1204 | ||
1207 | lock_kernel(); | 1205 | dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", |
1208 | /* find the device */ | 1206 | ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1); |
1209 | for (i = 0; i < zoran_num; i++) { | ||
1210 | if (zoran[i]->video_dev->minor == minor) { | ||
1211 | zr = zoran[i]; | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | 1207 | ||
1216 | if (!zr) { | 1208 | lock_kernel(); |
1217 | dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME); | ||
1218 | res = -ENODEV; | ||
1219 | goto open_unlock_and_return; | ||
1220 | } | ||
1221 | 1209 | ||
1222 | /* see fs/device.c - the kernel already locks during open(), | 1210 | /* see fs/device.c - the kernel already locks during open(), |
1223 | * so locking ourselves only causes deadlocks */ | 1211 | * so locking ourselves only causes deadlocks */ |
1224 | /*mutex_lock(&zr->resource_lock);*/ | 1212 | /*mutex_lock(&zr->resource_lock);*/ |
1225 | 1213 | ||
1214 | if (zr->user >= 2048) { | ||
1215 | dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", | ||
1216 | ZR_DEVNAME(zr), zr->user); | ||
1217 | res = -EBUSY; | ||
1218 | goto fail_unlock; | ||
1219 | } | ||
1220 | |||
1226 | if (!zr->decoder) { | 1221 | if (!zr->decoder) { |
1227 | dprintk(1, | 1222 | dprintk(1, |
1228 | KERN_ERR "%s: no TV decoder loaded for device!\n", | 1223 | KERN_ERR "%s: no TV decoder loaded for device!\n", |
1229 | ZR_DEVNAME(zr)); | 1224 | ZR_DEVNAME(zr)); |
1230 | res = -EIO; | 1225 | res = -EIO; |
1231 | goto open_unlock_and_return; | 1226 | goto fail_unlock; |
1232 | } | 1227 | } |
1233 | 1228 | ||
1234 | /* try to grab a module lock */ | ||
1235 | if (!try_module_get(THIS_MODULE)) { | ||
1236 | dprintk(1, | ||
1237 | KERN_ERR | ||
1238 | "%s: failed to acquire my own lock! PANIC!\n", | ||
1239 | ZR_DEVNAME(zr)); | ||
1240 | res = -ENODEV; | ||
1241 | goto open_unlock_and_return; | ||
1242 | } | ||
1243 | if (!try_module_get(zr->decoder->driver->driver.owner)) { | 1229 | if (!try_module_get(zr->decoder->driver->driver.owner)) { |
1244 | dprintk(1, | 1230 | dprintk(1, |
1245 | KERN_ERR | 1231 | KERN_ERR |
1246 | "%s: failed to grab ownership of i2c decoder\n", | 1232 | "%s: failed to grab ownership of video decoder\n", |
1247 | ZR_DEVNAME(zr)); | 1233 | ZR_DEVNAME(zr)); |
1248 | res = -EIO; | 1234 | res = -EIO; |
1249 | module_put(THIS_MODULE); | 1235 | goto fail_unlock; |
1250 | goto open_unlock_and_return; | ||
1251 | } | 1236 | } |
1252 | if (zr->encoder && | 1237 | if (zr->encoder && |
1253 | !try_module_get(zr->encoder->driver->driver.owner)) { | 1238 | !try_module_get(zr->encoder->driver->driver.owner)) { |
1254 | dprintk(1, | 1239 | dprintk(1, |
1255 | KERN_ERR | 1240 | KERN_ERR |
1256 | "%s: failed to grab ownership of i2c encoder\n", | 1241 | "%s: failed to grab ownership of video encoder\n", |
1257 | ZR_DEVNAME(zr)); | 1242 | ZR_DEVNAME(zr)); |
1258 | res = -EIO; | 1243 | res = -EIO; |
1259 | module_put(zr->decoder->driver->driver.owner); | 1244 | goto fail_decoder; |
1260 | module_put(THIS_MODULE); | ||
1261 | goto open_unlock_and_return; | ||
1262 | } | 1245 | } |
1263 | 1246 | ||
1264 | have_module_locks = 1; | ||
1265 | |||
1266 | if (zr->user >= 2048) { | ||
1267 | dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", | ||
1268 | ZR_DEVNAME(zr), zr->user); | ||
1269 | res = -EBUSY; | ||
1270 | goto open_unlock_and_return; | ||
1271 | } | ||
1272 | |||
1273 | dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n", | ||
1274 | ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user); | ||
1275 | |||
1276 | /* now, create the open()-specific file_ops struct */ | 1247 | /* now, create the open()-specific file_ops struct */ |
1277 | fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); | 1248 | fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); |
1278 | if (!fh) { | 1249 | if (!fh) { |
@@ -1281,7 +1252,7 @@ zoran_open(struct file *file) | |||
1281 | "%s: zoran_open() - allocation of zoran_fh failed\n", | 1252 | "%s: zoran_open() - allocation of zoran_fh failed\n", |
1282 | ZR_DEVNAME(zr)); | 1253 | ZR_DEVNAME(zr)); |
1283 | res = -ENOMEM; | 1254 | res = -ENOMEM; |
1284 | goto open_unlock_and_return; | 1255 | goto fail_encoder; |
1285 | } | 1256 | } |
1286 | /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows | 1257 | /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows |
1287 | * on norm-change! */ | 1258 | * on norm-change! */ |
@@ -1292,9 +1263,8 @@ zoran_open(struct file *file) | |||
1292 | KERN_ERR | 1263 | KERN_ERR |
1293 | "%s: zoran_open() - allocation of overlay_mask failed\n", | 1264 | "%s: zoran_open() - allocation of overlay_mask failed\n", |
1294 | ZR_DEVNAME(zr)); | 1265 | ZR_DEVNAME(zr)); |
1295 | kfree(fh); | ||
1296 | res = -ENOMEM; | 1266 | res = -ENOMEM; |
1297 | goto open_unlock_and_return; | 1267 | goto fail_fh; |
1298 | } | 1268 | } |
1299 | 1269 | ||
1300 | if (zr->user++ == 0) | 1270 | if (zr->user++ == 0) |
@@ -1319,22 +1289,19 @@ zoran_open(struct file *file) | |||
1319 | 1289 | ||
1320 | return 0; | 1290 | return 0; |
1321 | 1291 | ||
1322 | open_unlock_and_return: | 1292 | fail_fh: |
1323 | /* if we grabbed locks, release them accordingly */ | 1293 | kfree(fh); |
1324 | if (have_module_locks) { | 1294 | fail_encoder: |
1325 | module_put(zr->decoder->driver->driver.owner); | 1295 | if (zr->encoder) |
1326 | if (zr->encoder) { | 1296 | module_put(zr->encoder->driver->driver.owner); |
1327 | module_put(zr->encoder->driver->driver.owner); | 1297 | fail_decoder: |
1328 | } | 1298 | module_put(zr->decoder->driver->driver.owner); |
1329 | module_put(THIS_MODULE); | 1299 | fail_unlock: |
1330 | } | ||
1331 | |||
1332 | /* if there's no device found, we didn't obtain the lock either */ | ||
1333 | if (zr) { | ||
1334 | /*mutex_unlock(&zr->resource_lock);*/ | ||
1335 | } | ||
1336 | unlock_kernel(); | 1300 | unlock_kernel(); |
1337 | 1301 | ||
1302 | dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n", | ||
1303 | ZR_DEVNAME(zr), res, zr->user); | ||
1304 | |||
1338 | return res; | 1305 | return res; |
1339 | } | 1306 | } |
1340 | 1307 | ||
@@ -1344,8 +1311,8 @@ zoran_close(struct file *file) | |||
1344 | struct zoran_fh *fh = file->private_data; | 1311 | struct zoran_fh *fh = file->private_data; |
1345 | struct zoran *zr = fh->zr; | 1312 | struct zoran *zr = fh->zr; |
1346 | 1313 | ||
1347 | dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", | 1314 | dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n", |
1348 | ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user); | 1315 | ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1); |
1349 | 1316 | ||
1350 | /* kernel locks (fs/device.c), so don't do that ourselves | 1317 | /* kernel locks (fs/device.c), so don't do that ourselves |
1351 | * (prevents deadlocks) */ | 1318 | * (prevents deadlocks) */ |
@@ -1391,10 +1358,8 @@ zoran_close(struct file *file) | |||
1391 | 1358 | ||
1392 | /* release locks on the i2c modules */ | 1359 | /* release locks on the i2c modules */ |
1393 | module_put(zr->decoder->driver->driver.owner); | 1360 | module_put(zr->decoder->driver->driver.owner); |
1394 | if (zr->encoder) { | 1361 | if (zr->encoder) |
1395 | module_put(zr->encoder->driver->driver.owner); | 1362 | module_put(zr->encoder->driver->driver.owner); |
1396 | } | ||
1397 | module_put(THIS_MODULE); | ||
1398 | 1363 | ||
1399 | /*mutex_unlock(&zr->resource_lock);*/ | 1364 | /*mutex_unlock(&zr->resource_lock);*/ |
1400 | 1365 | ||