diff options
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r-- | linux/drivers/media/dvb/bt8xx/dst_ca.c | 7 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/ce6230.c | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/pluto2/pluto2.c | 7 | ||||
-rw-r--r-- | linux/drivers/media/dvb/siano/smssdio.c | 356 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/budget-ci.c | 6 |
5 files changed, 372 insertions, 6 deletions
diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c index 68aef6786..e71c269c1 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_ca.c +++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c @@ -648,8 +648,10 @@ free_mem_and_exit: return result; } -static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg) +static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg) { + lock_kernel(); + struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; struct dst_state* state = (struct dst_state*) dvbdev->priv; struct ca_slot_info *p_ca_slot_info; @@ -743,6 +745,7 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd kfree (p_ca_slot_info); kfree (p_ca_caps); + unlock_kernel(); return result; } @@ -780,7 +783,7 @@ static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t static const struct file_operations dst_ca_fops = { .owner = THIS_MODULE, - .ioctl = dst_ca_ioctl, + .unlocked_ioctl = dst_ca_ioctl, .open = dst_ca_open, .release = dst_ca_release, .read = dst_ca_read, diff --git a/linux/drivers/media/dvb/dvb-usb/ce6230.c b/linux/drivers/media/dvb/dvb-usb/ce6230.c index 2a959c4bd..1682af62f 100644 --- a/linux/drivers/media/dvb/dvb-usb/ce6230.c +++ b/linux/drivers/media/dvb/dvb-usb/ce6230.c @@ -104,7 +104,7 @@ static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], struct dvb_usb_device *d = i2c_get_adapdata(adap); int i = 0; struct req_t req; - int ret; + int ret = 0; memset(&req, 0, sizeof(&req)); if (num > 2) diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index 8522757a5..b27073216 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -116,6 +116,7 @@ struct pluto { /* irq */ unsigned int overflow; + unsigned int dead; /* dma */ dma_addr_t dma_addr; @@ -344,8 +345,10 @@ static irqreturn_t pluto_irq(int irq, void *dev_id) return IRQ_NONE; if (tscr == 0xffffffff) { - // FIXME: maybe recover somehow - dev_err(&pluto->pdev->dev, "card hung up :(\n"); + if (pluto->dead == 0) + dev_err(&pluto->pdev->dev, "card has hung or been ejected.\n"); + /* It's dead Jim */ + pluto->dead = 1; return IRQ_HANDLED; } diff --git a/linux/drivers/media/dvb/siano/smssdio.c b/linux/drivers/media/dvb/siano/smssdio.c new file mode 100644 index 000000000..31ba8c5af --- /dev/null +++ b/linux/drivers/media/dvb/siano/smssdio.c @@ -0,0 +1,356 @@ +/* + * smssdio.c - Siano 1xxx SDIO interface driver + * + * Copyright 2008 Pierre Ossman + * + * Based on code by Siano Mobile Silicon, Inc., + * Copyright (C) 2006-2008, Uri Shkolnik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * + * This hardware is a bit odd in that all transfers should be done + * to/from the SMSSDIO_DATA register, yet the "increase address" bit + * always needs to be set. + * + * Also, buffers from the card are always aligned to 128 byte + * boundaries. + */ + +/* + * General cleanup notes: + * + * - only typedefs should be name *_t + * + * - use ERR_PTR and friends for smscore_register_device() + * + * - smscore_getbuffer should zero fields + * + * Fix stop command + */ + +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <linux/delay.h> +#include <linux/mmc/card.h> +#include <linux/mmc/sdio_func.h> +#include <linux/mmc/sdio_ids.h> + +#include "smscoreapi.h" +#include "sms-cards.h" + +/* Registers */ + +#define SMSSDIO_DATA 0x00 +#define SMSSDIO_INT 0x04 + +static const struct sdio_device_id smssdio_ids[] = { + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), + .driver_data = SMS1XXX_BOARD_SIANO_STELLAR}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0), + .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0), + .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0), + .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, + {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE), + .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, + { /* end: all zeroes */ }, +}; + +MODULE_DEVICE_TABLE(sdio, smssdio_ids); + +struct smssdio_device { + struct sdio_func *func; + + struct smscore_device_t *coredev; + + struct smscore_buffer_t *split_cb; +}; + +/*******************************************************************/ +/* Siano core callbacks */ +/*******************************************************************/ + +static int smssdio_sendrequest(void *context, void *buffer, size_t size) +{ + int ret; + struct smssdio_device *smsdev; + + smsdev = context; + + sdio_claim_host(smsdev->func); + + while (size >= smsdev->func->cur_blksize) { + ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1); + if (ret) + goto out; + + buffer += smsdev->func->cur_blksize; + size -= smsdev->func->cur_blksize; + } + + if (size) { + ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, + buffer, size); + if (ret) + goto out; + } + +out: + sdio_release_host(smsdev->func); + + return ret; +} + +/*******************************************************************/ +/* SDIO callbacks */ +/*******************************************************************/ + +static void smssdio_interrupt(struct sdio_func *func) +{ + int ret, isr; + + struct smssdio_device *smsdev; + struct smscore_buffer_t *cb; + struct SmsMsgHdr_ST *hdr; + size_t size; + + smsdev = sdio_get_drvdata(func); + + /* + * The interrupt register has no defined meaning. It is just + * a way of turning of the level triggered interrupt. + */ + isr = sdio_readb(func, SMSSDIO_INT, &ret); + if (ret) { + dev_err(&smsdev->func->dev, + "Unable to read interrupt register!\n"); + return; + } + + if (smsdev->split_cb == NULL) { + cb = smscore_getbuffer(smsdev->coredev); + if (!cb) { + dev_err(&smsdev->func->dev, + "Unable to allocate data buffer!\n"); + return; + } + + ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); + if (ret) { + dev_err(&smsdev->func->dev, + "Error %d reading initial block!\n", ret); + return; + } + + hdr = cb->p; + + if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { + smsdev->split_cb = cb; + return; + } + + size = hdr->msgLength - smsdev->func->cur_blksize; + } else { + cb = smsdev->split_cb; + hdr = cb->p; + + size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); + + smsdev->split_cb = NULL; + } + + if (hdr->msgLength > smsdev->func->cur_blksize) { + void *buffer; + + size = ALIGN(size, 128); + buffer = cb->p + hdr->msgLength; + + BUG_ON(smsdev->func->cur_blksize != 128); + + /* + * First attempt to transfer all of it in one go... + */ + ret = sdio_read_blocks(smsdev->func, buffer, + SMSSDIO_DATA, size / 128); + if (ret && ret != -EINVAL) { + smscore_putbuffer(smsdev->coredev, cb); + dev_err(&smsdev->func->dev, + "Error %d reading data from card!\n", ret); + return; + } + + /* + * ..then fall back to one block at a time if that is + * not possible... + * + * (we have to do this manually because of the + * problem with the "increase address" bit) + */ + if (ret == -EINVAL) { + while (size) { + ret = sdio_read_blocks(smsdev->func, + buffer, SMSSDIO_DATA, 1); + if (ret) { + smscore_putbuffer(smsdev->coredev, cb); + dev_err(&smsdev->func->dev, + "Error %d reading " + "data from card!\n", ret); + return; + } + + buffer += smsdev->func->cur_blksize; + if (size > smsdev->func->cur_blksize) + size -= smsdev->func->cur_blksize; + else + size = 0; + } + } + } + + cb->size = hdr->msgLength; + cb->offset = 0; + + smscore_onresponse(smsdev->coredev, cb); +} + +static int smssdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + int ret; + + int board_id; + struct smssdio_device *smsdev; + struct smsdevice_params_t params; + + board_id = id->driver_data; + + smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL); + if (!smsdev) + return -ENOMEM; + + smsdev->func = func; + + memset(¶ms, 0, sizeof(struct smsdevice_params_t)); + + params.device = &func->dev; + params.buffer_size = 0x5000; /* ?? */ + params.num_buffers = 22; /* ?? */ + params.context = smsdev; + + snprintf(params.devpath, sizeof(params.devpath), + "sdio\\%s", sdio_func_id(func)); + + params.sendrequest_handler = smssdio_sendrequest; + + params.device_type = sms_get_board(board_id)->type; + + if (params.device_type != SMS_STELLAR) + params.flags |= SMS_DEVICE_FAMILY2; + else { + /* + * FIXME: Stellar needs special handling... + */ + ret = -ENODEV; + goto free; + } + + ret = smscore_register_device(¶ms, &smsdev->coredev); + if (ret < 0) + goto free; + + smscore_set_board_id(smsdev->coredev, board_id); + + sdio_claim_host(func); + + ret = sdio_enable_func(func); + if (ret) + goto release; + + ret = sdio_set_block_size(func, 128); + if (ret) + goto disable; + + ret = sdio_claim_irq(func, smssdio_interrupt); + if (ret) + goto disable; + + sdio_set_drvdata(func, smsdev); + + sdio_release_host(func); + + ret = smscore_start_device(smsdev->coredev); + if (ret < 0) + goto reclaim; + + return 0; + +reclaim: + sdio_claim_host(func); + sdio_release_irq(func); +disable: + sdio_disable_func(func); +release: + sdio_release_host(func); + smscore_unregister_device(smsdev->coredev); +free: + kfree(smsdev); + + return ret; +} + +static void smssdio_remove(struct sdio_func *func) +{ + struct smssdio_device *smsdev; + + smsdev = sdio_get_drvdata(func); + + /* FIXME: racy! */ + if (smsdev->split_cb) + smscore_putbuffer(smsdev->coredev, smsdev->split_cb); + + smscore_unregister_device(smsdev->coredev); + + sdio_claim_host(func); + sdio_release_irq(func); + sdio_disable_func(func); + sdio_release_host(func); + + kfree(smsdev); +} + +static struct sdio_driver smssdio_driver = { + .name = "smssdio", + .id_table = smssdio_ids, + .probe = smssdio_probe, + .remove = smssdio_remove, +}; + +/*******************************************************************/ +/* Module functions */ +/*******************************************************************/ + +int smssdio_register(void) +{ + int ret = 0; + + printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n"); + printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n"); + + ret = sdio_register_driver(&smssdio_driver); + + return ret; +} + +void smssdio_unregister(void) +{ + sdio_unregister_driver(&smssdio_driver); +} + +MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver"); +MODULE_AUTHOR("Pierre Ossman"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 99fcb55d5..1b564eb79 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -1084,6 +1084,10 @@ static struct tda10023_config tda10023_config = { .deltaf = 0xa511, }; +static struct tda827x_config tda827x_config = { + .config = 0, +}; + /* TT S2-3200 DVB-S (STB0899) Inittab */ static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = { @@ -1422,7 +1426,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */ budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48); if (budget_ci->budget.dvb_frontend) { - if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, NULL) == NULL) { + if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, &tda827x_config) == NULL) { printk(KERN_ERR "%s: No tda827x found!\n", __func__); dvb_frontend_detach(budget_ci->budget.dvb_frontend); budget_ci->budget.dvb_frontend = NULL; |