diff options
Diffstat (limited to 'drivers/media/dvb/ngene/ngene-core.c')
-rw-r--r-- | drivers/media/dvb/ngene/ngene-core.c | 80 |
1 files changed, 55 insertions, 25 deletions
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c index c8b4dfa0ab5f..4caeb163a666 100644 --- a/drivers/media/dvb/ngene/ngene-core.c +++ b/drivers/media/dvb/ngene/ngene-core.c | |||
@@ -53,8 +53,6 @@ MODULE_PARM_DESC(debug, "Print debugging information."); | |||
53 | 53 | ||
54 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 54 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
55 | 55 | ||
56 | #define COMMAND_TIMEOUT_WORKAROUND | ||
57 | |||
58 | #define dprintk if (debug) printk | 56 | #define dprintk if (debug) printk |
59 | 57 | ||
60 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) | 58 | #define ngwriteb(dat, adr) writeb((dat), (char *)(dev->iomem + (adr))) |
@@ -147,24 +145,24 @@ static void demux_tasklet(unsigned long data) | |||
147 | } else { | 145 | } else { |
148 | if (chan->HWState == HWSTATE_RUN) { | 146 | if (chan->HWState == HWSTATE_RUN) { |
149 | u32 Flags = 0; | 147 | u32 Flags = 0; |
148 | IBufferExchange *exch1 = chan->pBufferExchange; | ||
149 | IBufferExchange *exch2 = chan->pBufferExchange2; | ||
150 | if (Cur->ngeneBuffer.SR.Flags & 0x01) | 150 | if (Cur->ngeneBuffer.SR.Flags & 0x01) |
151 | Flags |= BEF_EVEN_FIELD; | 151 | Flags |= BEF_EVEN_FIELD; |
152 | if (Cur->ngeneBuffer.SR.Flags & 0x20) | 152 | if (Cur->ngeneBuffer.SR.Flags & 0x20) |
153 | Flags |= BEF_OVERFLOW; | 153 | Flags |= BEF_OVERFLOW; |
154 | if (chan->pBufferExchange) | 154 | spin_unlock_irq(&chan->state_lock); |
155 | chan->pBufferExchange(chan, | 155 | if (exch1) |
156 | Cur->Buffer1, | 156 | exch1(chan, Cur->Buffer1, |
157 | chan-> | 157 | chan->Capture1Length, |
158 | Capture1Length, | 158 | Cur->ngeneBuffer.SR.Clock, |
159 | Cur->ngeneBuffer. | 159 | Flags); |
160 | SR.Clock, Flags); | 160 | if (exch2) |
161 | if (chan->pBufferExchange2) | 161 | exch2(chan, Cur->Buffer2, |
162 | chan->pBufferExchange2(chan, | 162 | chan->Capture2Length, |
163 | Cur->Buffer2, | 163 | Cur->ngeneBuffer.SR.Clock, |
164 | chan-> | 164 | Flags); |
165 | Capture2Length, | 165 | spin_lock_irq(&chan->state_lock); |
166 | Cur->ngeneBuffer. | ||
167 | SR.Clock, Flags); | ||
168 | } else if (chan->HWState != HWSTATE_STOP) | 166 | } else if (chan->HWState != HWSTATE_STOP) |
169 | chan->HWState = HWSTATE_RUN; | 167 | chan->HWState = HWSTATE_RUN; |
170 | } | 168 | } |
@@ -572,11 +570,7 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream, | |||
572 | u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); | 570 | u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); |
573 | u16 BsSDO = 0x9B00; | 571 | u16 BsSDO = 0x9B00; |
574 | 572 | ||
575 | /* down(&dev->stream_mutex); */ | 573 | down(&dev->stream_mutex); |
576 | while (down_trylock(&dev->stream_mutex)) { | ||
577 | printk(KERN_INFO DEVICE_NAME ": SC locked\n"); | ||
578 | msleep(1); | ||
579 | } | ||
580 | memset(&com, 0, sizeof(com)); | 574 | memset(&com, 0, sizeof(com)); |
581 | com.cmd.hdr.Opcode = CMD_CONTROL; | 575 | com.cmd.hdr.Opcode = CMD_CONTROL; |
582 | com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; | 576 | com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; |
@@ -1252,14 +1246,17 @@ static int ngene_load_firm(struct ngene *dev) | |||
1252 | version = 15; | 1246 | version = 15; |
1253 | size = 23466; | 1247 | size = 23466; |
1254 | fw_name = "ngene_15.fw"; | 1248 | fw_name = "ngene_15.fw"; |
1249 | dev->cmd_timeout_workaround = true; | ||
1255 | break; | 1250 | break; |
1256 | case 16: | 1251 | case 16: |
1257 | size = 23498; | 1252 | size = 23498; |
1258 | fw_name = "ngene_16.fw"; | 1253 | fw_name = "ngene_16.fw"; |
1254 | dev->cmd_timeout_workaround = true; | ||
1259 | break; | 1255 | break; |
1260 | case 17: | 1256 | case 17: |
1261 | size = 24446; | 1257 | size = 24446; |
1262 | fw_name = "ngene_17.fw"; | 1258 | fw_name = "ngene_17.fw"; |
1259 | dev->cmd_timeout_workaround = true; | ||
1263 | break; | 1260 | break; |
1264 | } | 1261 | } |
1265 | 1262 | ||
@@ -1299,11 +1296,16 @@ static void ngene_stop(struct ngene *dev) | |||
1299 | ngwritel(0, NGENE_EVENT); | 1296 | ngwritel(0, NGENE_EVENT); |
1300 | ngwritel(0, NGENE_EVENT_HI); | 1297 | ngwritel(0, NGENE_EVENT_HI); |
1301 | free_irq(dev->pci_dev->irq, dev); | 1298 | free_irq(dev->pci_dev->irq, dev); |
1299 | #ifdef CONFIG_PCI_MSI | ||
1300 | if (dev->msi_enabled) | ||
1301 | pci_disable_msi(dev->pci_dev); | ||
1302 | #endif | ||
1302 | } | 1303 | } |
1303 | 1304 | ||
1304 | static int ngene_start(struct ngene *dev) | 1305 | static int ngene_start(struct ngene *dev) |
1305 | { | 1306 | { |
1306 | int stat; | 1307 | int stat; |
1308 | unsigned long flags; | ||
1307 | int i; | 1309 | int i; |
1308 | 1310 | ||
1309 | pci_set_master(dev->pci_dev); | 1311 | pci_set_master(dev->pci_dev); |
@@ -1333,6 +1335,28 @@ static int ngene_start(struct ngene *dev) | |||
1333 | if (stat < 0) | 1335 | if (stat < 0) |
1334 | goto fail; | 1336 | goto fail; |
1335 | 1337 | ||
1338 | #ifdef CONFIG_PCI_MSI | ||
1339 | /* enable MSI if kernel and card support it */ | ||
1340 | if (pci_msi_enabled() && dev->card_info->msi_supported) { | ||
1341 | ngwritel(0, NGENE_INT_ENABLE); | ||
1342 | free_irq(dev->pci_dev->irq, dev); | ||
1343 | stat = pci_enable_msi(dev->pci_dev); | ||
1344 | if (stat) { | ||
1345 | printk(KERN_INFO DEVICE_NAME | ||
1346 | ": MSI not available\n"); | ||
1347 | flags = IRQF_SHARED; | ||
1348 | } else { | ||
1349 | flags = 0; | ||
1350 | dev->msi_enabled = true; | ||
1351 | } | ||
1352 | stat = request_irq(dev->pci_dev->irq, irq_handler, | ||
1353 | flags, "nGene", dev); | ||
1354 | if (stat < 0) | ||
1355 | goto fail2; | ||
1356 | ngwritel(1, NGENE_INT_ENABLE); | ||
1357 | } | ||
1358 | #endif | ||
1359 | |||
1336 | stat = ngene_i2c_init(dev, 0); | 1360 | stat = ngene_i2c_init(dev, 0); |
1337 | if (stat < 0) | 1361 | if (stat < 0) |
1338 | goto fail; | 1362 | goto fail; |
@@ -1358,10 +1382,18 @@ static int ngene_start(struct ngene *dev) | |||
1358 | bconf = BUFFER_CONFIG_3333; | 1382 | bconf = BUFFER_CONFIG_3333; |
1359 | stat = ngene_command_config_buf(dev, bconf); | 1383 | stat = ngene_command_config_buf(dev, bconf); |
1360 | } | 1384 | } |
1361 | return stat; | 1385 | if (!stat) |
1386 | return stat; | ||
1387 | |||
1388 | /* otherwise error: fall through */ | ||
1362 | fail: | 1389 | fail: |
1363 | ngwritel(0, NGENE_INT_ENABLE); | 1390 | ngwritel(0, NGENE_INT_ENABLE); |
1364 | free_irq(dev->pci_dev->irq, dev); | 1391 | free_irq(dev->pci_dev->irq, dev); |
1392 | #ifdef CONFIG_PCI_MSI | ||
1393 | fail2: | ||
1394 | if (dev->msi_enabled) | ||
1395 | pci_disable_msi(dev->pci_dev); | ||
1396 | #endif | ||
1365 | return stat; | 1397 | return stat; |
1366 | } | 1398 | } |
1367 | 1399 | ||
@@ -1379,10 +1411,8 @@ static void release_channel(struct ngene_channel *chan) | |||
1379 | struct ngene_info *ni = dev->card_info; | 1411 | struct ngene_info *ni = dev->card_info; |
1380 | int io = ni->io_type[chan->number]; | 1412 | int io = ni->io_type[chan->number]; |
1381 | 1413 | ||
1382 | #ifdef COMMAND_TIMEOUT_WORKAROUND | 1414 | if (chan->dev->cmd_timeout_workaround && chan->running) |
1383 | if (chan->running) | ||
1384 | set_transfer(chan, 0); | 1415 | set_transfer(chan, 0); |
1385 | #endif | ||
1386 | 1416 | ||
1387 | tasklet_kill(&chan->demux_tasklet); | 1417 | tasklet_kill(&chan->demux_tasklet); |
1388 | 1418 | ||