summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/Documentation/video4linux/CARDLIST.saa71341
-rw-r--r--linux/drivers/media/dvb/Kconfig1
-rw-r--r--linux/drivers/media/dvb/Makefile2
-rw-r--r--linux/drivers/media/dvb/frontends/drx397xD.c8
-rw-r--r--linux/drivers/media/dvb/siano/Kconfig26
-rw-r--r--linux/drivers/media/dvb/siano/Makefile8
-rw-r--r--linux/drivers/media/dvb/siano/sms-cards.c102
-rw-r--r--linux/drivers/media/dvb/siano/sms-cards.h45
-rw-r--r--linux/drivers/media/dvb/siano/smscoreapi.c1312
-rw-r--r--linux/drivers/media/dvb/siano/smscoreapi.h603
-rw-r--r--linux/drivers/media/dvb/siano/smsdvb.c458
-rw-r--r--linux/drivers/media/dvb/siano/smsusb.c463
-rw-r--r--linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c18
-rw-r--r--linux/drivers/media/video/bt819.c2
-rw-r--r--linux/drivers/media/video/cx18/cx18-av-firmware.c2
-rw-r--r--linux/drivers/media/video/gspca/gspca.c6
-rw-r--r--linux/drivers/media/video/ivtv/ivtvfb.c7
-rw-r--r--linux/drivers/media/video/ov7670.c16
-rw-r--r--linux/drivers/media/video/ovcamchip/ovcamchip_core.c1
-rw-r--r--linux/drivers/media/video/s2255drv.c61
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-cards.c25
-rw-r--r--linux/drivers/media/video/saa7134/saa7134-dvb.c10
-rw-r--r--linux/drivers/media/video/saa7134/saa7134.h1
-rw-r--r--linux/drivers/media/video/tvaudio.c13
-rw-r--r--linux/drivers/media/video/uvc/uvc_driver.c18
-rw-r--r--linux/drivers/media/video/uvc/uvc_v4l2.c2
-rw-r--r--linux/drivers/media/video/videobuf-dma-sg.c6
-rw-r--r--linux/drivers/media/video/zoran_card.c11
-rw-r--r--linux/include/linux/i2c-id.h8
29 files changed, 3134 insertions, 102 deletions
diff --git a/linux/Documentation/video4linux/CARDLIST.saa7134 b/linux/Documentation/video4linux/CARDLIST.saa7134
index f58192276..171905e87 100644
--- a/linux/Documentation/video4linux/CARDLIST.saa7134
+++ b/linux/Documentation/video4linux/CARDLIST.saa7134
@@ -143,3 +143,4 @@
142 -> Beholder BeholdTV H6 [5ace:6290]
143 -> Beholder BeholdTV M63 [5ace:6191]
144 -> Beholder BeholdTV M6 Extra [5ace:6193]
+145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636]
diff --git a/linux/drivers/media/dvb/Kconfig b/linux/drivers/media/dvb/Kconfig
index 7b21b49f1..8bc1445bd 100644
--- a/linux/drivers/media/dvb/Kconfig
+++ b/linux/drivers/media/dvb/Kconfig
@@ -21,6 +21,7 @@ source "drivers/media/dvb/dvb-usb/Kconfig"
source "drivers/media/dvb/ttusb-budget/Kconfig"
source "drivers/media/dvb/ttusb-dec/Kconfig"
source "drivers/media/dvb/cinergyT2/Kconfig"
+source "drivers/media/dvb/siano/Kconfig"
comment "Supported FlexCopII (B2C2) Adapters"
depends on DVB_CORE && (PCI || USB) && I2C
diff --git a/linux/drivers/media/dvb/Makefile b/linux/drivers/media/dvb/Makefile
index a7ad0841e..d6ba4d195 100644
--- a/linux/drivers/media/dvb/Makefile
+++ b/linux/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/
+obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/
diff --git a/linux/drivers/media/dvb/frontends/drx397xD.c b/linux/drivers/media/dvb/frontends/drx397xD.c
index 327fff4b8..52a9a6553 100644
--- a/linux/drivers/media/dvb/frontends/drx397xD.c
+++ b/linux/drivers/media/dvb/frontends/drx397xD.c
@@ -74,7 +74,7 @@ static struct {
const struct firmware *file;
rwlock_t lock;
int refcnt;
- u8 *data[ARRAY_SIZE(blob_name)];
+ const u8 *data[ARRAY_SIZE(blob_name)];
} fw[] = {
#define _FW_ENTRY(a, b) { \
.name = a, \
@@ -110,7 +110,7 @@ static void drx_release_fw(struct drx397xD_state *s)
static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
{
- u8 *data;
+ const u8 *data;
size_t size, len;
int i = 0, j, rc = -EINVAL;
@@ -194,7 +194,7 @@ static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
{
struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
- u8 *data;
+ const u8 *data;
int len, rc = 0, i = 0;
if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
@@ -215,7 +215,7 @@ static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
case 0: /* bytecode */
len = data[i++];
msg.len = len;
- msg.buf = &data[i];
+ msg.buf = (__u8 *) &data[i];
if (i2c_transfer(s->i2c, &msg, 1) != 1) {
rc = -EIO;
goto exit_rc;
diff --git a/linux/drivers/media/dvb/siano/Kconfig b/linux/drivers/media/dvb/siano/Kconfig
new file mode 100644
index 000000000..dd863f261
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/Kconfig
@@ -0,0 +1,26 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config DVB_SIANO_SMS1XXX
+ tristate "Siano SMS1XXX USB dongle support"
+ depends on DVB_CORE && USB
+ ---help---
+ Choose Y here if you have a USB dongle with a SMS1XXX chipset.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sms1xxx.
+
+config DVB_SIANO_SMS1XXX_SMS_IDS
+ bool "Enable support for Siano Mobile Silicon default USB IDs"
+ depends on DVB_SIANO_SMS1XXX
+ default y
+ ---help---
+ Choose Y here if you have a USB dongle with a SMS1XXX chipset
+ that uses Siano Mobile Silicon's default usb vid:pid.
+
+ Choose N here if you would prefer to use Siano's external driver.
+
+ Further documentation on this driver can be found on the WWW at
+ <http://www.siano-ms.com/>.
+
diff --git a/linux/drivers/media/dvb/siano/Makefile b/linux/drivers/media/dvb/siano/Makefile
new file mode 100644
index 000000000..ee0737af9
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/Makefile
@@ -0,0 +1,8 @@
+sms1xxx-objs := smscoreapi.o smsusb.o smsdvb.o sms-cards.o
+
+obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/linux/drivers/media/dvb/siano/sms-cards.c b/linux/drivers/media/dvb/siano/sms-cards.c
new file mode 100644
index 000000000..e7a8ac0c4
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/sms-cards.c
@@ -0,0 +1,102 @@
+/*
+ * Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "sms-cards.h"
+
+struct usb_device_id smsusb_id_table[] = {
+#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
+ { USB_DEVICE(0x187f, 0x0010),
+ .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+ { USB_DEVICE(0x187f, 0x0100),
+ .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+ { USB_DEVICE(0x187f, 0x0200),
+ .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
+ { USB_DEVICE(0x187f, 0x0201),
+ .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
+ { USB_DEVICE(0x187f, 0x0300),
+ .driver_info = SMS1XXX_BOARD_SIANO_VEGA },
+#endif
+ { USB_DEVICE(0x2040, 0x1700),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
+ { USB_DEVICE(0x2040, 0x1800),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
+ { USB_DEVICE(0x2040, 0x1801),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
+ { USB_DEVICE(0x2040, 0x5500),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5580),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0x5590),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, smsusb_id_table);
+
+static struct sms_board sms_boards[] = {
+ [SMS_BOARD_UNKNOWN] = {
+ .name = "Unknown board",
+ },
+ [SMS1XXX_BOARD_SIANO_STELLAR] = {
+ .name = "Siano Stellar Digital Receiver",
+ .type = SMS_STELLAR,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_SIANO_NOVA_A] = {
+ .name = "Siano Nova A Digital Receiver",
+ .type = SMS_NOVA_A0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_SIANO_NOVA_B] = {
+ .name = "Siano Nova B Digital Receiver",
+ .type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_SIANO_VEGA] = {
+ .name = "Siano Vega Digital Receiver",
+ .type = SMS_VEGA,
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
+ .name = "Hauppauge Catamount",
+ .type = SMS_STELLAR,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
+ .name = "Hauppauge Okemo-A",
+ .type = SMS_NOVA_A0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
+ .name = "Hauppauge Okemo-B",
+ .type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+ },
+ [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
+ .name = "Hauppauge WinTV-Nova-T-MiniStick",
+ .type = SMS_NOVA_B0,
+ .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
+ },
+};
+
+struct sms_board *sms_get_board(int id)
+{
+ BUG_ON(id >= ARRAY_SIZE(sms_boards));
+
+ return &sms_boards[id];
+}
+
diff --git a/linux/drivers/media/dvb/siano/sms-cards.h b/linux/drivers/media/dvb/siano/sms-cards.h
new file mode 100644
index 000000000..83b39bc20
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/sms-cards.h
@@ -0,0 +1,45 @@
+/*
+ * Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SMS_CARDS_H__
+#define __SMS_CARDS_H__
+
+#include <linux/usb.h>
+#include "smscoreapi.h"
+
+#define SMS_BOARD_UNKNOWN 0
+#define SMS1XXX_BOARD_SIANO_STELLAR 1
+#define SMS1XXX_BOARD_SIANO_NOVA_A 2
+#define SMS1XXX_BOARD_SIANO_NOVA_B 3
+#define SMS1XXX_BOARD_SIANO_VEGA 4
+#define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
+#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
+
+struct sms_board {
+ enum sms_device_type_st type;
+ char *name, *fw[DEVICE_MODE_MAX];
+};
+
+struct sms_board *sms_get_board(int id);
+
+extern struct usb_device_id smsusb_id_table[];
+
+#endif /* __SMS_CARDS_H__ */
diff --git a/linux/drivers/media/dvb/siano/smscoreapi.c b/linux/drivers/media/dvb/siano/smscoreapi.c
new file mode 100644
index 000000000..549332b53
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/smscoreapi.c
@@ -0,0 +1,1312 @@
+/*
+ * Siano core API module
+ *
+ * This file contains implementation for the interface to sms core component
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include <linux/firmware.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+int sms_debug;
+module_param_named(debug, sms_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
+struct smscore_device_notifyee_t {
+ struct list_head entry;
+ hotplug_t hotplug;
+};
+
+struct smscore_idlist_t {
+ struct list_head entry;
+ int id;
+ int data_type;
+};
+
+struct smscore_client_t {
+ struct list_head entry;
+ struct smscore_device_t *coredev;
+ void *context;
+ struct list_head idlist;
+ onresponse_t onresponse_handler;
+ onremove_t onremove_handler;
+};
+
+struct smscore_device_t {
+ struct list_head entry;
+
+ struct list_head clients;
+ struct list_head subclients;
+ spinlock_t clientslock;
+
+ struct list_head buffers;
+ spinlock_t bufferslock;
+ int num_buffers;
+
+ void *common_buffer;
+ int common_buffer_size;
+ dma_addr_t common_buffer_phys;
+
+ void *context;
+ struct device *device;
+
+ char devpath[32];
+ unsigned long device_flags;
+
+ setmode_t setmode_handler;
+ detectmode_t detectmode_handler;
+ sendrequest_t sendrequest_handler;
+ preload_t preload_handler;
+ postload_t postload_handler;
+
+ int mode, modes_supported;
+
+ struct completion version_ex_done, data_download_done, trigger_done;
+ struct completion init_device_done, reload_start_done, resume_done;
+
+ int board_id;
+};
+
+void smscore_set_board_id(struct smscore_device_t *core, int id)
+{
+ core->board_id = id;
+}
+
+int smscore_get_board_id(struct smscore_device_t *core)
+{
+ return core->board_id;
+}
+
+struct smscore_registry_entry_t {
+ struct list_head entry;
+ char devpath[32];
+ int mode;
+ enum sms_device_type_st type;
+};
+
+struct list_head g_smscore_notifyees;
+struct list_head g_smscore_devices;
+struct mutex g_smscore_deviceslock;
+
+struct list_head g_smscore_registry;
+struct mutex g_smscore_registrylock;
+
+static int default_mode = 4;
+
+module_param(default_mode, int, 0644);
+MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
+
+static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
+{
+ struct smscore_registry_entry_t *entry;
+ struct list_head *next;
+
+ kmutex_lock(&g_smscore_registrylock);
+ for (next = g_smscore_registry.next;
+ next != &g_smscore_registry;
+ next = next->next) {
+ entry = (struct smscore_registry_entry_t *) next;
+ if (!strcmp(entry->devpath, devpath)) {
+ kmutex_unlock(&g_smscore_registrylock);
+ return entry;
+ }
+ }
+ entry = (struct smscore_registry_entry_t *)
+ kmalloc(sizeof(struct smscore_registry_entry_t),
+ GFP_KERNEL);
+ if (entry) {
+ entry->mode = default_mode;
+ strcpy(entry->devpath, devpath);
+ list_add(&entry->entry, &g_smscore_registry);
+ } else
+ sms_err("failed to create smscore_registry.");
+ kmutex_unlock(&g_smscore_registrylock);
+ return entry;
+}
+
+int smscore_registry_getmode(char *devpath)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ return entry->mode;
+ else
+ sms_err("No registry found.");
+
+ return default_mode;
+}
+
+static enum sms_device_type_st smscore_registry_gettype(char *devpath)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ return entry->type;
+ else
+ sms_err("No registry found.");
+
+ return -1;
+}
+
+void smscore_registry_setmode(char *devpath, int mode)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ entry->mode = mode;
+ else
+ sms_err("No registry found.");
+}
+
+static void smscore_registry_settype(char *devpath,
+ enum sms_device_type_st type)
+{
+ struct smscore_registry_entry_t *entry;
+
+ entry = smscore_find_registry(devpath);
+ if (entry)
+ entry->type = type;
+ else
+ sms_err("No registry found.");
+}
+
+
+static void list_add_locked(struct list_head *new, struct list_head *head,
+ spinlock_t *lock)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(lock, flags);
+
+ list_add(new, head);
+
+ spin_unlock_irqrestore(lock, flags);
+}
+
+/**
+ * register a client callback that called when device plugged in/unplugged
+ * NOTE: if devices exist callback is called immediately for each device
+ *
+ * @param hotplug callback
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_hotplug(hotplug_t hotplug)
+{
+ struct smscore_device_notifyee_t *notifyee;
+ struct list_head *next, *first;
+ int rc = 0;
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
+ GFP_KERNEL);
+ if (notifyee) {
+ /* now notify callback about existing devices */
+ first = &g_smscore_devices;
+ for (next = first->next;
+ next != first && !rc;
+ next = next->next) {
+ struct smscore_device_t *coredev =
+ (struct smscore_device_t *) next;
+ rc = hotplug(coredev, coredev->device, 1);
+ }
+
+ if (rc >= 0) {
+ notifyee->hotplug = hotplug;
+ list_add(&notifyee->entry, &g_smscore_notifyees);
+ } else
+ kfree(notifyee);
+ } else
+ rc = -ENOMEM;
+
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ return rc;
+}
+
+/**
+ * unregister a client callback that called when device plugged in/unplugged
+ *
+ * @param hotplug callback
+ *
+ */
+void smscore_unregister_hotplug(hotplug_t hotplug)
+{
+ struct list_head *next, *first;
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ first = &g_smscore_notifyees;
+
+ for (next = first->next; next != first;) {
+ struct smscore_device_notifyee_t *notifyee =
+ (struct smscore_device_notifyee_t *) next;
+ next = next->next;
+
+ if (notifyee->hotplug == hotplug) {
+ list_del(&notifyee->entry);
+ kfree(notifyee);
+ }
+ }
+
+ kmutex_unlock(&g_smscore_deviceslock);
+}
+
+static void smscore_notify_clients(struct smscore_device_t *coredev)
+{
+ struct smscore_client_t *client;
+
+ /* the client must call smscore_unregister_client from remove handler */
+ while (!list_empty(&coredev->clients)) {
+ client = (struct smscore_client_t *) coredev->clients.next;
+ client->onremove_handler(client->context);
+ }
+}
+
+static int smscore_notify_callbacks(struct smscore_device_t *coredev,
+ struct device *device, int arrival)
+{
+ struct list_head *next, *first;
+ int rc = 0;
+
+ /* note: must be called under g_deviceslock */
+
+ first = &g_smscore_notifyees;
+
+ for (next = first->next; next != first; next = next->next) {
+ rc = ((struct smscore_device_notifyee_t *) next)->
+ hotplug(coredev, device, arrival);
+ if (rc < 0)
+ break;
+ }
+
+ return rc;
+}
+
+static struct
+smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
+ dma_addr_t common_buffer_phys)
+{
+ struct smscore_buffer_t *cb =
+ kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+ if (!cb) {
+ sms_info("kmalloc(...) failed");
+ return NULL;
+ }
+
+ cb->p = buffer;
+ cb->offset_in_common = buffer - (u8 *) common_buffer;
+ cb->phys = common_buffer_phys + cb->offset_in_common;
+
+ return cb;
+}
+
+/**
+ * creates coredev object for a device, prepares buffers,
+ * creates buffer mappings, notifies registered hotplugs about new device.
+ *
+ * @param params device pointer to struct with device specific parameters
+ * and handlers
+ * @param coredev pointer to a value that receives created coredev object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_device(struct smsdevice_params_t *params,
+ struct smscore_device_t **coredev)
+{
+ struct smscore_device_t *dev;
+ u8 *buffer;
+
+ dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
+ if (!dev) {
+ sms_info("kzalloc(...) failed");
+ return -ENOMEM;
+ }
+
+ /* init list entry so it could be safe in smscore_unregister_device */
+ INIT_LIST_HEAD(&dev->entry);
+
+ /* init queues */
+ INIT_LIST_HEAD(&dev->clients);
+ INIT_LIST_HEAD(&dev->buffers);
+
+ /* init locks */
+ spin_lock_init(&dev->clientslock);
+ spin_lock_init(&dev->bufferslock);
+
+ /* init completion events */
+ init_completion(&dev->version_ex_done);
+ init_completion(&dev->data_download_done);
+ init_completion(&dev->trigger_done);
+ init_completion(&dev->init_device_done);
+ init_completion(&dev->reload_start_done);
+ init_completion(&dev->resume_done);
+
+ /* alloc common buffer */
+ dev->common_buffer_size = params->buffer_size * params->num_buffers;
+ dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
+ &dev->common_buffer_phys,
+ GFP_KERNEL | GFP_DMA);
+ if (!dev->common_buffer) {
+ smscore_unregister_device(dev);
+ return -ENOMEM;
+ }
+
+ /* prepare dma buffers */
+ for (buffer = dev->common_buffer;
+ dev->num_buffers < params->num_buffers;
+ dev->num_buffers++, buffer += params->buffer_size) {
+ struct smscore_buffer_t *cb =
+ smscore_createbuffer(buffer, dev->common_buffer,
+ dev->common_buffer_phys);
+ if (!cb) {
+ smscore_unregister_device(dev);
+ return -ENOMEM;
+ }
+
+ smscore_putbuffer(dev, cb);
+ }
+
+ sms_info("allocated %d buffers", dev->num_buffers);
+
+ dev->mode = DEVICE_MODE_NONE;
+ dev->context = params->context;
+ dev->device = params->device;
+ dev->setmode_handler = params->setmode_handler;
+ dev->detectmode_handler = params->detectmode_handler;
+ dev->sendrequest_handler = params->sendrequest_handler;
+ dev->preload_handler = params->preload_handler;
+ dev->postload_handler = params->postload_handler;
+
+ dev->device_flags = params->flags;
+ strcpy(dev->devpath, params->devpath);
+
+ smscore_registry_settype(dev->devpath, params->device_type);
+
+ /* add device to devices list */
+ kmutex_lock(&g_smscore_deviceslock);
+ list_add(&dev->entry, &g_smscore_devices);
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ *coredev = dev;
+
+ sms_info("device %p created", dev);
+
+ return 0;
+}
+
+/**
+ * sets initial device mode and notifies client hotplugs that device is ready
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_start_device(struct smscore_device_t *coredev)
+{
+ int rc = smscore_set_device_mode(
+ coredev, smscore_registry_getmode(coredev->devpath));
+ if (rc < 0) {
+ sms_info("set device mode faile , rc %d", rc);
+ return rc;
+ }
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ rc = smscore_notify_callbacks(coredev, coredev->device, 1);
+
+ sms_info("device %p started, rc %d", coredev, rc);
+
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ return rc;
+}
+
+static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
+ void *buffer, size_t size,
+ struct completion *completion)
+{
+ int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+ if (rc < 0) {
+ sms_info("sendrequest returned error %d", rc);
+ return rc;
+ }
+
+ return wait_for_completion_timeout(completion,
+ msecs_to_jiffies(10000)) ?
+ 0 : -ETIME;
+}
+
+static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
+ void *buffer, size_t size)
+{
+ struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
+ struct SmsMsgHdr_ST *msg;
+ u32 mem_address = firmware->StartAddress;
+ u8 *payload = firmware->Payload;
+ int rc = 0;
+
+ sms_info("loading FW to addr 0x%x size %d",
+ mem_address, firmware->Length);
+ if (coredev->preload_handler) {
+ rc = coredev->preload_handler(coredev->context);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* PAGE_SIZE buffer shall be enough and dma aligned */
+ msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+ if (!msg)
+ return -ENOMEM;
+
+ if (coredev->mode != DEVICE_MODE_NONE) {
+ sms_debug("sending reload command.");
+ SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
+ sizeof(struct SmsMsgHdr_ST));
+ rc = smscore_sendrequest_and_wait(coredev, msg,
+ msg->msgLength,
+ &coredev->reload_start_done);
+ mem_address = *(u32 *) &payload[20];
+ }
+
+ while (size && rc >= 0) {
+ struct SmsDataDownload_ST *DataMsg =
+ (struct SmsDataDownload_ST *) msg;
+ int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
+
+ SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
+ (u16)(sizeof(struct SmsMsgHdr_ST) +
+ sizeof(u32) + payload_size));
+
+ DataMsg->MemAddr = mem_address;
+ memcpy(DataMsg->Payload, payload, payload_size);
+
+ if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
+ (coredev->mode == DEVICE_MODE_NONE))
+ rc = coredev->sendrequest_handler(
+ coredev->context, DataMsg,
+ DataMsg->xMsgHeader.msgLength);
+ else
+ rc = smscore_sendrequest_and_wait(
+ coredev, DataMsg,
+ DataMsg->xMsgHeader.msgLength,
+ &coredev->data_download_done);
+
+ payload += payload_size;
+ size -= payload_size;
+ mem_address += payload_size;
+ }
+
+ if (rc >= 0) {
+ if (coredev->mode == DEVICE_MODE_NONE) {
+ struct SmsMsgData_ST *TriggerMsg =
+ (struct SmsMsgData_ST *) msg;
+
+ SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+ sizeof(struct SmsMsgHdr_ST) +
+ sizeof(u32) * 5);
+
+ TriggerMsg->msgData[0] = firmware->StartAddress;
+ /* Entry point */
+ TriggerMsg->msgData[1] = 5; /* Priority */
+ TriggerMsg->msgData[2] = 0x200; /* Stack size */
+ TriggerMsg->msgData[3] = 0; /* Parameter */
+ TriggerMsg->msgData[4] = 4; /* Task ID */
+
+ if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
+ rc = coredev->sendrequest_handler(
+ coredev->context, TriggerMsg,
+ TriggerMsg->xMsgHeader.msgLength);
+ msleep(100);
+ } else
+ rc = smscore_sendrequest_and_wait(
+ coredev, TriggerMsg,
+ TriggerMsg->xMsgHeader.msgLength,
+ &coredev->trigger_done);
+ } else {
+ SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
+ sizeof(struct SmsMsgHdr_ST));
+
+ rc = coredev->sendrequest_handler(coredev->context,
+ msg, msg->msgLength);
+ }
+ msleep(500);
+ }
+
+ sms_debug("rc=%d, postload=%p ", rc,
+ coredev->postload_handler);
+
+ kfree(msg);
+
+ return ((rc >= 0) && coredev->postload_handler) ?
+ coredev->postload_handler(coredev->context) :
+ rc;
+}
+
+/**
+ * loads specified firmware into a buffer and calls device loadfirmware_handler
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param filename null-terminated string specifies firmware file name
+ * @param loadfirmware_handler device handler that loads firmware
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
+ char *filename,
+ loadfirmware_t loadfirmware_handler)
+{
+ int rc = -ENOENT;
+ const struct firmware *fw;
+ u8 *fw_buffer;
+
+ if (loadfirmware_handler == NULL && !(coredev->device_flags &
+ SMS_DEVICE_FAMILY2))
+ return -EINVAL;
+
+ rc = request_firmware(&fw, filename, coredev->device);
+ if (rc < 0) {
+ sms_info("failed to open \"%s\"", filename);
+ return rc;
+ }
+ sms_info("read FW %s, size=%zd", filename, fw->size);
+ fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+ GFP_KERNEL | GFP_DMA);
+ if (fw_buffer) {
+ memcpy(fw_buffer, fw->data, fw->size);
+
+ rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
+ smscore_load_firmware_family2(coredev,
+ fw_buffer,
+ fw->size) :
+ loadfirmware_handler(coredev->context,
+ fw_buffer, fw->size);
+
+ kfree(fw_buffer);
+ } else {
+ sms_info("failed to allocate firmware buffer");
+ rc = -ENOMEM;
+ }
+
+ release_firmware(fw);
+
+ return rc;
+}
+
+/**
+ * notifies all clients registered with the device, notifies hotplugs,
+ * frees all buffers and coredev object
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+void smscore_unregister_device(struct smscore_device_t *coredev)
+{
+ struct smscore_buffer_t *cb;
+ int num_buffers = 0;
+ int retry = 0;
+
+ kmutex_lock(&g_smscore_deviceslock);
+
+ smscore_notify_clients(coredev);
+ smscore_notify_callbacks(coredev, NULL, 0);
+
+ /* at this point all buffers should be back
+ * onresponse must no longer be called */
+
+ while (1) {
+ while ((cb = smscore_getbuffer(coredev))) {
+ kfree(cb);
+ num_buffers++;
+ }
+ if (num_buffers == coredev->num_buffers)
+ break;
+ if (++retry > 10) {
+ sms_info("exiting although "
+ "not all buffers released.");
+ break;
+ }
+
+ sms_info("waiting for %d buffer(s)",
+ coredev->num_buffers - num_buffers);
+ msleep(100);
+ }
+
+ sms_info("freed %d buffers", num_buffers);
+
+ if (coredev->common_buffer)
+ dma_free_coherent(NULL, coredev->common_buffer_size,
+ coredev->common_buffer,
+ coredev->common_buffer_phys);
+
+ list_del(&coredev->entry);
+ kfree(coredev);
+
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ sms_info("device %p destroyed", coredev);
+}
+
+static int smscore_detect_mode(struct smscore_device_t *coredev)
+{
+ void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
+ GFP_KERNEL | GFP_DMA);
+ struct SmsMsgHdr_ST *msg =
+ (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
+ int rc;
+
+ if (!buffer)
+ return -ENOMEM;
+
+ SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
+ sizeof(struct SmsMsgHdr_ST));
+
+ rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
+ &coredev->version_ex_done);
+ if (rc == -ETIME) {
+ sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
+
+ if (wait_for_completion_timeout(&coredev->resume_done,
+ msecs_to_jiffies(5000))) {
+ rc = smscore_sendrequest_and_wait(
+ coredev, msg, msg->msgLength,
+ &coredev->version_ex_done);
+ if (rc < 0)
+ sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
+ "second try, rc %d", rc);
+ } else
+ rc = -ETIME;
+ }
+
+ kfree(buffer);
+
+ return rc;
+}
+
+static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
+ /*Stellar NOVA A0 Nova B0 VEGA*/
+ /*DVBT*/
+ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+ /*DVBH*/
+ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+ /*TDMB*/
+ {"none", "tdmb_nova_12mhz.inp", "none", "none"},
+ /*DABIP*/
+ {"none", "none", "none", "none"},
+ /*BDA*/
+ {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+ /*ISDBT*/
+ {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},
+ /*ISDBTBDA*/
+ {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+ /*CMMB*/
+ {"none", "none", "none", "cmmb_vega_12mhz.inp"}
+};
+
+static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
+ int mode, enum sms_device_type_st type)
+{
+ char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
+ return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+}
+
+/**
+ * calls device handler to change mode of operation
+ * NOTE: stellar/usb may disconnect when changing mode
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
+{
+ void *buffer;
+ int rc = 0;
+ enum sms_device_type_st type;
+
+ sms_debug("set device mode to %d", mode);
+ if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
+ if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
+ sms_err("invalid mode specified %d", mode);
+ return -EINVAL;
+ }
+
+ smscore_registry_setmode(coredev->devpath, mode);
+
+ if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
+ rc = smscore_detect_mode(coredev);
+ if (rc < 0) {
+ sms_err("mode detect failed %d", rc);
+ return rc;
+ }
+ }
+
+ if (coredev->mode == mode) {
+ sms_info("device mode %d already set", mode);
+ return 0;
+ }
+
+ if (!(coredev->modes_supported & (1 << mode))) {
+ char *fw_filename;
+
+ type = smscore_registry_gettype(coredev->devpath);
+ fw_filename = sms_get_fw_name(coredev, mode, type);
+
+ rc = smscore_load_firmware_from_file(coredev,
+ fw_filename, NULL);
+ if (rc < 0) {
+ sms_warn("error %d loading firmware: %s, "
+ "trying again with default firmware",
+ rc, fw_filename);
+
+ /* try again with the default firmware */
+ fw_filename = smscore_fw_lkup[mode][type];
+ rc = smscore_load_firmware_from_file(coredev,
+ fw_filename, NULL);
+
+ if (rc < 0) {
+ sms_warn("error %d loading "
+ "firmware: %s", rc,
+ fw_filename);
+ return rc;
+ }
+ }
+ sms_log("firmware download success: %s", fw_filename);
+ } else
+ sms_info("mode %d supported by running "
+ "firmware", mode);
+
+ buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
+ SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+ if (buffer) {
+ struct SmsMsgData_ST *msg =
+ (struct SmsMsgData_ST *)
+ SMS_ALIGN_ADDRESS(buffer);
+
+ SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
+ sizeof(struct SmsMsgData_ST));
+ msg->msgData[0] = mode;
+
+ rc = smscore_sendrequest_and_wait(
+ coredev, msg, msg->xMsgHeader.msgLength,
+ &coredev->init_device_done);
+
+ kfree(buffer);
+ } else {
+ sms_err("Could not allocate buffer for "
+ "init device message.");
+ rc = -ENOMEM;
+ }
+ } else {
+ if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+ sms_err("invalid mode specified %d", mode);
+ return -EINVAL;
+ }
+
+ smscore_registry_setmode(coredev->devpath, mode);
+
+ if (coredev->detectmode_handler)
+ coredev->detectmode_handler(coredev->context,
+ &coredev->mode);
+
+ if (coredev->mode != mode && coredev->setmode_handler)
+ rc = coredev->setmode_handler(coredev->context, mode);
+ }
+
+ if (rc >= 0) {
+ coredev->mode = mode;
+ coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
+ }
+
+ if (rc != 0)
+ sms_err("return error code %d.", rc);
+ return rc;
+}
+
+/**
+ * calls device handler to get current mode of operation
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return current mode
+ */
+int smscore_get_device_mode(struct smscore_device_t *coredev)
+{
+ return coredev->mode;
+}
+
+/**
+ * find client by response id & type within the clients list.
+ * return client handle or NULL.
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param data_type client data type (SMS_DONT_CARE for all types)
+ * @param id client id (SMS_DONT_CARE for all id)
+ *
+ */
+static struct
+smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
+ int data_type, int id)
+{
+ struct smscore_client_t *client = NULL;
+ struct list_head *next, *first;
+ unsigned long flags;
+ struct list_head *firstid, *nextid;
+
+
+ spin_lock_irqsave(&coredev->clientslock, flags);
+ first = &coredev->clients;
+ for (next = first->next;
+ (next != first) && !client;
+ next = next->next) {
+ firstid = &((struct smscore_client_t *)next)->idlist;
+ for (nextid = firstid->next;
+ nextid != firstid;
+ nextid = nextid->next) {
+ if ((((struct smscore_idlist_t *)nextid)->id == id) &&
+ (((struct smscore_idlist_t *)nextid)->data_type == data_type ||
+ (((struct smscore_idlist_t *)nextid)->data_type == 0))) {
+ client = (struct smscore_client_t *) next;
+ break;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&coredev->clientslock, flags);
+ return client;
+}
+
+/**
+ * find client by response id/type, call clients onresponse handler
+ * return buffer to pool on error
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param cb pointer to response buffer descriptor
+ *
+ */
+void smscore_onresponse(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb)
+{
+ struct SmsMsgHdr_ST *phdr =
+ (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
+ struct smscore_client_t *client =
+ smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+ int rc = -EBUSY;
+
+#if 1
+ static unsigned long last_sample_time; /* = 0; */
+ static int data_total; /* = 0; */
+ unsigned long time_now = jiffies_to_msecs(jiffies);
+
+ if (!last_sample_time)
+ last_sample_time = time_now;
+
+ if (time_now - last_sample_time > 10000) {
+ sms_debug("\ndata rate %d bytes/secs",
+ (int)((data_total * 1000) /
+ (time_now - last_sample_time)));
+
+ last_sample_time = time_now;
+ data_total = 0;
+ }
+
+ data_total += cb->size;
+#endif
+ /* If no client registered for type & id,
+ * check for control client where type is not registered */
+#if 0
+ if (!client)
+ client = smscore_find_client(coredev, 0, phdr->msgDstId);
+#endif
+ if (client)
+ rc = client->onresponse_handler(client->context, cb);
+
+ if (rc < 0) {
+ switch (phdr->msgType) {
+ case MSG_SMS_GET_VERSION_EX_RES:
+ {
+ struct SmsVersionRes_ST *ver =
+ (struct SmsVersionRes_ST *) phdr;
+ sms_debug("MSG_SMS_GET_VERSION_EX_RES "
+ "id %d prots 0x%x ver %d.%d",
+ ver->FirmwareId, ver->SupportedProtocols,
+ ver->RomVersionMajor, ver->RomVersionMinor);
+
+ coredev->mode = ver->FirmwareId == 255 ?
+ DEVICE_MODE_NONE : ver->FirmwareId;
+ coredev->modes_supported = ver->SupportedProtocols;
+
+ complete(&coredev->version_ex_done);
+ break;
+ }
+ case MSG_SMS_INIT_DEVICE_RES:
+ sms_debug("MSG_SMS_INIT_DEVICE_RES");
+ complete(&coredev->init_device_done);
+ break;
+ case MSG_SW_RELOAD_START_RES:
+ sms_debug("MSG_SW_RELOAD_START_RES");
+ complete(&coredev->reload_start_done);
+ break;
+ case MSG_SMS_DATA_DOWNLOAD_RES:
+ complete(&coredev->data_download_done);
+ break;
+ case MSG_SW_RELOAD_EXEC_RES:
+ sms_debug("MSG_SW_RELOAD_EXEC_RES");
+ break;
+ case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
+ sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
+ complete(&coredev->trigger_done);
+ break;
+ case MSG_SMS_SLEEP_RESUME_COMP_IND:
+ complete(&coredev->resume_done);
+ break;
+ default:
+#if 0
+ sms_info("no client (%p) or error (%d), "
+ "type:%d dstid:%d", client, rc,
+ phdr->msgType, phdr->msgDstId);
+#endif
+ break;
+ }
+ smscore_putbuffer(coredev, cb);
+ }
+}
+
+/**
+ * return pointer to next free buffer descriptor from core pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ *
+ * @return pointer to descriptor on success, NULL on error.
+ */
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+ struct smscore_buffer_t *cb = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&coredev->bufferslock, flags);
+
+ if (!list_empty(&coredev->buffers)) {
+ cb = (struct smscore_buffer_t *) coredev->buffers.next;
+ list_del(&cb->entry);
+ }
+
+ spin_unlock_irqrestore(&coredev->bufferslock, flags);
+
+ return cb;
+}
+
+/**
+ * return buffer descriptor to a pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ * smscore_register_device
+ * @param cb pointer buffer descriptor
+ *
+ */
+void smscore_putbuffer(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb)
+{
+ list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
+}
+
+static int smscore_validate_client(struct smscore_device_t *coredev,
+ struct smscore_client_t *client,
+ int data_type, int id)
+{
+ struct smscore_idlist_t *listentry;
+ struct smscore_client_t *registered_client;
+
+ if (!client) {
+ sms_err("bad parameter.");
+ return -EFAULT;
+ }
+ registered_client = smscore_find_client(coredev, data_type, id);
+ if (registered_client == client)
+ return 0;
+
+ if (registered_client) {
+ sms_err("The msg ID already registered to another client.");
+ return -EEXIST;
+ }
+ listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
+ if (!listentry) {
+ sms_err("Can't allocate memory for client id.");
+ return -ENOMEM;
+ }
+ listentry->id = id;
+ listentry->data_type = data_type;
+ list_add_locked(&listentry->entry, &client->idlist,
+ &coredev->clientslock);
+ return 0;
+}
+
+/**
+ * creates smsclient object, check that id is taken by another client
+ *
+ * @param coredev pointer to a coredev object from clients hotplug
+ * @param initial_id all messages with this id would be sent to this client
+ * @param data_type all messages of this type would be sent to this client
+ * @param onresponse_handler client handler that is called to
+ * process incoming messages
+ * @param onremove_handler client handler that is called when device is removed
+ * @param context client-specific context
+ * @param client pointer to a value that receives created smsclient object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_client(struct smscore_device_t *coredev,
+ struct smsclient_params_t *params,
+ struct smscore_client_t **client)
+{
+ struct smscore_client_t *newclient;
+ /* check that no other channel with same parameters exists */
+ if (smscore_find_client(coredev, params->data_type,
+ params->initial_id)) {
+ sms_err("Client already exist.");
+ return -EEXIST;
+ }
+
+ newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
+ if (!newclient) {
+ sms_err("Failed to allocate memory for client.");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&newclient->idlist);
+ newclient->coredev = coredev;
+ newclient->onresponse_handler = params->onresponse_handler;
+ newclient->onremove_handler = params->onremove_handler;
+ newclient->context = params->context;
+ list_add_locked(&newclient->entry, &coredev->clients,
+ &coredev->clientslock);
+ smscore_validate_client(coredev, newclient, params->data_type,
+ params->initial_id);
+ *client = newclient;
+ sms_debug("%p %d %d", params->context, params->data_type,
+ params->initial_id);
+
+ return 0;
+}
+
+/**
+ * frees smsclient object and all subclients associated with it
+ *
+ * @param client pointer to smsclient object returned by
+ * smscore_register_client
+ *
+ */
+void smscore_unregister_client(struct smscore_client_t *client)
+{
+ struct smscore_device_t *coredev = client->coredev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&coredev->clientslock, flags);
+
+
+ while (!list_empty(&client->idlist)) {
+ struct smscore_idlist_t *identry =
+ (struct smscore_idlist_t *) client->idlist.next;
+ list_del(&identry->entry);
+ kfree(identry);
+ }
+
+ sms_info("%p", client->context);
+
+ list_del(&client->entry);
+ kfree(client);
+
+ spin_unlock_irqrestore(&coredev->clientslock, flags);
+}
+
+/**
+ * verifies that source id is not taken by another client,
+ * calls device handler to send requests to the device
+ *
+ * @param client pointer to smsclient object returned by
+ * smscore_register_client
+ * @param buffer pointer to a request buffer
+ * @param size size (in bytes) of request buffer
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smsclient_sendrequest(struct smscore_client_t *client,
+ void *buffer, size_t size)
+{
+ struct smscore_device_t *coredev;
+ struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
+ int rc;
+
+ if (client == NULL) {
+ sms_err("Got NULL client");
+ return -EINVAL;
+ }
+
+ coredev = client->coredev;
+
+ /* check that no other channel with same id exists */
+ if (coredev == NULL) {
+ sms_err("Got NULL coredev");
+ return -EINVAL;
+ }
+
+ rc = smscore_validate_client(client->coredev, client, 0,
+ phdr->msgSrcId);
+ if (rc < 0)
+ return rc;
+
+ return coredev->sendrequest_handler(coredev->context, buffer, size);
+}
+
+#if 0
+/**
+ * return the size of large (common) buffer
+ *
+ * @param coredev pointer to a coredev object from clients hotplug
+ *
+ * @return size (in bytes) of the buffer
+ */
+int smscore_get_common_buffer_size(struct smscore_device_t *coredev)
+{
+ return coredev->common_buffer_size;
+}
+
+/**
+ * maps common buffer (if supported by platform)
+ *
+ * @param coredev pointer to a coredev object from clients hotplug
+ * @param vma pointer to vma struct from mmap handler
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_map_common_buffer(struct smscore_device_t *coredev,
+ struct vm_area_struct *vma)
+{
+ unsigned long end = vma->vm_end,
+ start = vma->vm_start,
+ size = PAGE_ALIGN(coredev->common_buffer_size);
+
+ if (!(vma->vm_flags & (VM_READ | VM_SHARED)) ||
+ (vma->vm_flags & VM_WRITE)) {
+ sms_err("invalid vm flags");
+ return -EINVAL;
+ }
+
+ if ((end - start) != size) {
+ sms_err("invalid size %d expected %d",
+ (int)(end - start), (int) size);
+ return -EINVAL;
+ }
+
+ if (remap_pfn_range(vma, start,
+ coredev->common_buffer_phys >> PAGE_SHIFT,
+ size, pgprot_noncached(vma->vm_page_prot))) {
+ sms_err("remap_page_range failed");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+#endif
+
+int smscore_module_init(void)
+{
+ int rc = 0;
+
+ INIT_LIST_HEAD(&g_smscore_notifyees);
+ INIT_LIST_HEAD(&g_smscore_devices);
+ kmutex_init(&g_smscore_deviceslock);
+
+ INIT_LIST_HEAD(&g_smscore_registry);
+ kmutex_init(&g_smscore_registrylock);
+
+ /* USB Register */
+ rc = smsusb_register();
+
+ /* DVB Register */
+ rc = smsdvb_register();
+
+ sms_debug("rc %d", rc);
+
+ return rc;
+}
+
+void smscore_module_exit(void)
+{
+
+ kmutex_lock(&g_smscore_deviceslock);
+ while (!list_empty(&g_smscore_notifyees)) {
+ struct smscore_device_notifyee_t *notifyee =
+ (struct smscore_device_notifyee_t *)
+ g_smscore_notifyees.next;
+
+ list_del(&notifyee->entry);
+ kfree(notifyee);
+ }
+ kmutex_unlock(&g_smscore_deviceslock);
+
+ kmutex_lock(&g_smscore_registrylock);
+ while (!list_empty(&g_smscore_registry)) {
+ struct smscore_registry_entry_t *entry =
+ (struct smscore_registry_entry_t *)
+ g_smscore_registry.next;
+
+ list_del(&entry->entry);
+ kfree(entry);
+ }
+ kmutex_unlock(&g_smscore_registrylock);
+
+ /* DVB UnRegister */
+ smsdvb_unregister();
+
+ /* Unregister USB */
+ smsusb_unregister();
+
+ sms_debug("");
+}
+
+module_init(smscore_module_init);
+module_exit(smscore_module_exit);
+
+MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
+MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/siano/smscoreapi.h b/linux/drivers/media/dvb/siano/smscoreapi.h
new file mode 100644
index 000000000..d49bd5012
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/smscoreapi.h
@@ -0,0 +1,603 @@
+/*
+ * Driver for the Siano SMS1xxx USB dongle
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __smscoreapi_h__
+#define __smscoreapi_h__
+
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <asm/page.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include <linux/mutex.h>
+
+#define kmutex_init(_p_) mutex_init(_p_)
+#define kmutex_lock(_p_) mutex_lock(_p_)
+#define kmutex_trylock(_p_) mutex_trylock(_p_)
+#define kmutex_unlock(_p_) mutex_unlock(_p_)
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define SMS_ALLOC_ALIGNMENT 128
+#define SMS_DMA_ALIGNMENT 16
+#define SMS_ALIGN_ADDRESS(addr) \
+ ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
+
+#define SMS_DEVICE_FAMILY2 1
+#define SMS_ROM_NO_RESPONSE 2
+#define SMS_DEVICE_NOT_READY 0x8000000
+
+enum sms_device_type_st {
+ SMS_STELLAR = 0,
+ SMS_NOVA_A0,
+ SMS_NOVA_B0,
+ SMS_VEGA,
+ SMS_NUM_OF_DEVICE_TYPES
+};
+
+struct smscore_device_t;
+struct smscore_client_t;
+struct smscore_buffer_t;
+
+typedef int (*hotplug_t)(struct smscore_device_t *coredev,
+ struct device *device, int arrival);
+
+typedef int (*setmode_t)(void *context, int mode);
+typedef void (*detectmode_t)(void *context, int *mode);
+typedef int (*sendrequest_t)(void *context, void *buffer, size_t size);
+typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size);
+typedef int (*preload_t)(void *context);
+typedef int (*postload_t)(void *context);
+
+typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb);
+typedef void (*onremove_t)(void *context);
+
+struct smscore_buffer_t {
+ /* public members, once passed to clients can be changed freely */
+ struct list_head entry;
+ int size;
+ int offset;
+
+ /* private members, read-only for clients */
+ void *p;
+ dma_addr_t phys;
+ unsigned long offset_in_common;
+};
+
+struct smsdevice_params_t {
+ struct device *device;
+
+ int buffer_size;
+ int num_buffers;
+
+ char devpath[32];
+ unsigned long flags;
+
+ setmode_t setmode_handler;
+ detectmode_t detectmode_handler;
+ sendrequest_t sendrequest_handler;
+ preload_t preload_handler;
+ postload_t postload_handler;
+
+ void *context;
+ enum sms_device_type_st device_type;
+};
+
+struct smsclient_params_t {
+ int initial_id;
+ int data_type;
+ onresponse_t onresponse_handler;
+ onremove_t onremove_handler;
+
+ void *context;
+};
+
+/* GPIO definitions for antenna frequency domain control (SMS8021) */
+#define SMS_ANTENNA_GPIO_0 1
+#define SMS_ANTENNA_GPIO_1 0
+
+#define BW_8_MHZ 0
+#define BW_7_MHZ 1
+#define BW_6_MHZ 2
+#define BW_5_MHZ 3
+#define BW_ISDBT_1SEG 4
+#define BW_ISDBT_3SEG 5
+
+#define MSG_HDR_FLAG_SPLIT_MSG 4
+
+#define MAX_GPIO_PIN_NUMBER 31
+
+#define HIF_TASK 11
+#define SMS_HOST_LIB 150
+#define DVBT_BDA_CONTROL_MSG_ID 201
+
+#define SMS_MAX_PAYLOAD_SIZE 240
+#define SMS_TUNE_TIMEOUT 500
+
+#define MSG_SMS_GPIO_CONFIG_REQ 507
+#define MSG_SMS_GPIO_CONFIG_RES 508
+#define MSG_SMS_GPIO_SET_LEVEL_REQ 509
+#define MSG_SMS_GPIO_SET_LEVEL_RES 510
+#define MSG_SMS_GPIO_GET_LEVEL_REQ 511
+#define MSG_SMS_GPIO_GET_LEVEL_RES 512
+#define MSG_SMS_RF_TUNE_REQ 561
+#define MSG_SMS_RF_TUNE_RES 562
+#define MSG_SMS_INIT_DEVICE_REQ 578
+#define MSG_SMS_INIT_DEVICE_RES 579
+#define MSG_SMS_ADD_PID_FILTER_REQ 601
+#define MSG_SMS_ADD_PID_FILTER_RES 602
+#define MSG_SMS_REMOVE_PID_FILTER_REQ 603
+#define MSG_SMS_REMOVE_PID_FILTER_RES 604
+#define MSG_SMS_DAB_CHANNEL 607
+#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608
+#define MSG_SMS_GET_PID_FILTER_LIST_RES 609
+#define MSG_SMS_GET_STATISTICS_REQ 615
+#define MSG_SMS_GET_STATISTICS_RES 616
+#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651
+#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652
+#define MSG_SMS_GET_STATISTICS_EX_REQ 653
+#define MSG_SMS_GET_STATISTICS_EX_RES 654
+#define MSG_SMS_SLEEP_RESUME_COMP_IND 655
+#define MSG_SMS_DATA_DOWNLOAD_REQ 660
+#define MSG_SMS_DATA_DOWNLOAD_RES 661
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES 665
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ 666
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES 667
+#define MSG_SMS_GET_VERSION_EX_REQ 668
+#define MSG_SMS_GET_VERSION_EX_RES 669
+#define MSG_SMS_SET_CLOCK_OUTPUT_REQ 670
+#define MSG_SMS_I2C_SET_FREQ_REQ 685
+#define MSG_SMS_GENERIC_I2C_REQ 687
+#define MSG_SMS_GENERIC_I2C_RES 688
+#define MSG_SMS_DVBT_BDA_DATA 693
+#define MSG_SW_RELOAD_REQ 697
+#define MSG_SMS_DATA_MSG 699
+#define MSG_SW_RELOAD_START_REQ 702
+#define MSG_SW_RELOAD_START_RES 703
+#define MSG_SW_RELOAD_EXEC_REQ 704
+#define MSG_SW_RELOAD_EXEC_RES 705
+#define MSG_SMS_SPI_INT_LINE_SET_REQ 710
+#define MSG_SMS_ISDBT_TUNE_REQ 776
+#define MSG_SMS_ISDBT_TUNE_RES 777
+
+#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
+ (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
+ (ptr)->msgLength = len; (ptr)->msgFlags = 0; \
+} while (0)
+#define SMS_INIT_MSG(ptr, type, len) \
+ SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
+
+enum SMS_DEVICE_MODE {
+ DEVICE_MODE_NONE = -1,
+ DEVICE_MODE_DVBT = 0,
+ DEVICE_MODE_DVBH,
+ DEVICE_MODE_DAB_TDMB,
+ DEVICE_MODE_DAB_TDMB_DABIP,
+ DEVICE_MODE_DVBT_BDA,
+ DEVICE_MODE_ISDBT,
+ DEVICE_MODE_ISDBT_BDA,
+ DEVICE_MODE_CMMB,
+ DEVICE_MODE_RAW_TUNER,
+ DEVICE_MODE_MAX,
+};
+
+struct SmsMsgHdr_ST {
+ u16 msgType;
+ u8 msgSrcId;
+ u8 msgDstId;
+ u16 msgLength; /* Length of entire message, including header */
+ u16 msgFlags;
+};
+
+struct SmsMsgData_ST {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 msgData[1];
+};
+
+struct SmsDataDownload_ST {
+ struct SmsMsgHdr_ST xMsgHeader;
+ u32 MemAddr;
+ u8 Payload[SMS_MAX_PAYLOAD_SIZE];
+};
+
+struct SmsVersionRes_ST {
+ struct SmsMsgHdr_ST xMsgHeader;
+
+ u16 ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
+ u8 Step; /* 0 - Step A */
+ u8 MetalFix; /* 0 - Metal 0 */
+
+ u8 FirmwareId; /* 0xFF � ROM, otherwise the
+ * value indicated by
+ * SMSHOSTLIB_DEVICE_MODES_E */
+ u8 SupportedProtocols; /* Bitwise OR combination of
+ * supported protocols */
+
+ u8 VersionMajor;
+ u8 VersionMinor;
+ u8 VersionPatch;
+ u8 VersionFieldPatch;
+
+ u8 RomVersionMajor;
+ u8 RomVersionMinor;
+ u8 RomVersionPatch;
+ u8 RomVersionFieldPatch;
+
+ u8 TextLabel[34];
+};
+
+struct SmsFirmware_ST {
+ u32 CheckSum;
+ u32 Length;
+ u32 StartAddress;
+ u8 Payload[1];
+};
+
+struct SMSHOSTLIB_STATISTICS_ST {
+ u32 Reserved; /* Reserved */
+
+ /* Common parameters */
+ u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+ u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+ u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+ /* Reception quality */
+ s32 SNR; /* dB */
+ u32 BER; /* Post Viterbi BER [1E-5] */
+ u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */
+ u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A,
+ * valid only for DVB-T/H */
+ u32 MFER; /* DVB-H frame error rate in percentage,
+ * 0xFFFFFFFF indicate N/A, valid only for DVB-H */
+ s32 RSSI; /* dBm */
+ s32 InBandPwr; /* In band power in dBM */
+ s32 CarrierOffset; /* Carrier Offset in bin/1024 */
+
+ /* Transmission parameters, valid only for DVB-T/H */
+ u32 Frequency; /* Frequency in Hz */
+ u32 Bandwidth; /* Bandwidth in MHz */
+ u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
+ * for DVB-T/H FFT mode carriers in Kilos */
+ u32 ModemState; /* from SMS_DvbModemState_ET */
+ u32 GuardInterval; /* Guard Interval, 1 divided by value */
+ u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */
+ u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */
+ u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */
+ u32 Constellation; /* Constellation from SMS_Constellation_ET */
+
+ /* Burst parameters, valid only for DVB-H */
+ u32 BurstSize; /* Current burst size in bytes */
+ u32 BurstDuration; /* Current burst duration in mSec */
+ u32 BurstCycleTime; /* Current burst cycle time in mSec */
+ u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec,
+ * as calculated by demodulator */
+ u32 NumOfRows; /* Number of rows in MPE table */
+ u32 NumOfPaddCols; /* Number of padding columns in MPE table */
+ u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */
+ /* Burst parameters */
+ u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+ u32 TotalTSPackets; /* Total number of transport-stream packets */
+ u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include
+ * errors after MPE RS decoding */
+ u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors
+ * after MPE RS decoding */
+ u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected
+ * by MPE RS decoding */
+
+ /* Common params */
+ u32 BERErrorCount; /* Number of errornous SYNC bits. */
+ u32 BERBitCount; /* Total number of SYNC bits. */
+
+ /* Interface information */
+ u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+
+ /* DAB/T-DMB */
+ u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+
+ /* DVB-H TPS parameters */
+ u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero;
+ * if set to 0xFFFFFFFF cell_id not yet recovered */
+
+};
+
+struct SmsMsgStatisticsInfo_ST {
+ u32 RequestResult;
+
+ struct SMSHOSTLIB_STATISTICS_ST Stat;
+
+ /* Split the calc of the SNR in DAB */
+ u32 Signal; /* dB */
+ u32 Noise; /* dB */
+
+};
+
+#if 0
+struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST {
+ /* Per-layer information */
+ u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+ * 255 means layer does not exist */
+ u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET,
+ * 255 means layer does not exist */
+ u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
+ u32 BERErrorCount; /* Post Viterbi Error Bits Count */
+ u32 BERBitCount; /* Post Viterbi Total Bits Count */
+ u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
+ u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
+ u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+ u32 TotalTSPackets; /* Total number of transport-stream packets */
+ u32 TILdepthI; /* Time interleaver depth I parameter,
+ * 255 means layer does not exist */
+ u32 NumberOfSegments; /* Number of segments in layer A,
+ * 255 means layer does not exist */
+ u32 TMCCErrors; /* TMCC errors */
+};
+
+struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
+ u32 StatisticsType; /* Enumerator identifying the type of the
+ * structure. Values are the same as
+ * SMSHOSTLIB_DEVICE_MODES_E
+ *
+ * This field MUST always be first in any
+ * statistics structure */
+
+ u32 FullSize; /* Total size of the structure returned by the modem.
+ * If the size requested by the host is smaller than
+ * FullSize, the struct will be truncated */
+
+ /* Common parameters */
+ u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+ u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+ u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+ /* Reception quality */
+ s32 SNR; /* dB */
+ s32 RSSI; /* dBm */
+ s32 InBandPwr; /* In band power in dBM */
+ s32 CarrierOffset; /* Carrier Offset in Hz */
+
+ /* Transmission parameters */
+ u32 Frequency; /* Frequency in Hz */
+ u32 Bandwidth; /* Bandwidth in MHz */
+ u32 TransmissionMode; /* ISDB-T transmission mode */
+ u32 ModemState; /* 0 - Acquisition, 1 - Locked */
+ u32 GuardInterval; /* Guard Interval, 1 divided by value */
+ u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+ u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
+ u32 NumOfLayers; /* Number of ISDB-T layers in the network */
+
+ /* Per-layer information */
+ /* Layers A, B and C */
+ struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3];
+ /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */
+
+ /* Interface information */
+ u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+
+};
+
+struct SMSHOSTLIB_STATISTICS_DVB_ST {
+ u32 StatisticsType; /* Enumerator identifying the type of the
+ * structure. Values are the same as
+ * SMSHOSTLIB_DEVICE_MODES_E
+ * This field MUST always first in any
+ * statistics structure */
+
+ u32 FullSize; /* Total size of the structure returned by the modem.
+ * If the size requested by the host is smaller than
+ * FullSize, the struct will be truncated */
+ /* Common parameters */
+ u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+ u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+ u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+ /* Reception quality */
+ s32 SNR; /* dB */
+ u32 BER; /* Post Viterbi BER [1E-5] */
+ u32 BERErrorCount; /* Number of errornous SYNC bits. */
+ u32 BERBitCount; /* Total number of SYNC bits. */
+ u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A */
+ u32 MFER; /* DVB-H frame error rate in percentage,
+ * 0xFFFFFFFF indicate N/A, valid only for DVB-H */
+ s32 RSSI; /* dBm */
+ s32 InBandPwr; /* In band power in dBM */
+ s32 CarrierOffset; /* Carrier Offset in bin/1024 */
+
+ /* Transmission parameters */
+ u32 Frequency; /* Frequency in Hz */
+ u32 Bandwidth; /* Bandwidth in MHz */
+ u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+ u32 TransmissionMode; /* FFT mode carriers in Kilos */
+ u32 GuardInterval; /* Guard Interval, 1 divided by value */
+ u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
+ u32 LPCodeRate; /* Low Priority Code Rate from
+ * SMSHOSTLIB_CODE_RATE_ET */
+ u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */
+ u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET */
+
+ /* Burst parameters, valid only for DVB-H */
+ u32 BurstSize; /* Current burst size in bytes */
+ u32 BurstDuration; /* Current burst duration in mSec */
+ u32 BurstCycleTime; /* Current burst cycle time in mSec */
+ u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec,
+ * as calculated by demodulator */
+ u32 NumOfRows; /* Number of rows in MPE table */
+ u32 NumOfPaddCols; /* Number of padding columns in MPE table */
+ u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */
+
+ u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+ u32 TotalTSPackets; /* Total number of transport-stream packets */
+
+ u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include
+ * errors after MPE RS decoding */
+ u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include
+ * errors after MPE RS decoding */
+ u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were
+ * corrected by MPE RS decoding */
+
+ u32 NumMPEReceived; /* DVB-H, Num MPE section received */
+
+ /* DVB-H TPS parameters */
+ u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero;
+ * if set to 0xFFFFFFFF cell_id not yet recovered */
+ u32 DvbhSrvIndHP; /* DVB-H service indication info,
+ * bit 1 - Time Slicing indicator,
+ * bit 0 - MPE-FEC indicator */
+ u32 DvbhSrvIndLP; /* DVB-H service indication info,
+ * bit 1 - Time Slicing indicator,
+ * bit 0 - MPE-FEC indicator */
+
+ /* Interface information */
+ u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+
+};
+
+struct SMSHOSTLIB_GPIO_CONFIG_ST {
+ u8 Direction; /* GPIO direction: Input - 0, Output - 1 */
+ u8 PullUpDown; /* PullUp/PullDown: None - 0,
+ * PullDown - 1, PullUp - 2, Keeper - 3 */
+ u8 InputCharacteristics; /* Input Characteristics: Normal - 0,
+ * Schmitt trigger - 1 */
+ u8 OutputSlewRate; /* Output Slew Rate:
+ * Fast slew rate - 0, Slow slew rate - 1 */
+ u8 OutputDriving; /* Output driving capability:
+ * 4mA - 0, 8mA - 1, 12mA - 2, 16mA - 3 */
+};
+
+struct SMSHOSTLIB_I2C_REQ_ST {
+ u32 DeviceAddress; /* I2c device address */
+ u32 WriteCount; /* number of bytes to write */
+ u32 ReadCount; /* number of bytes to read */
+ u8 Data[1];
+};
+
+struct SMSHOSTLIB_I2C_RES_ST {
+ u32 Status; /* non-zero value in case of failure */
+ u32 ReadCount; /* number of bytes read */
+ u8 Data[1];
+};
+#endif
+
+struct smsdvb_client_t {
+ struct list_head entry;
+
+ struct smscore_device_t *coredev;
+ struct smscore_client_t *smsclient;
+
+ struct dvb_adapter adapter;
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dvb_frontend frontend;
+
+ fe_status_t fe_status;
+ int fe_ber, fe_snr, fe_signal_strength;
+
+ struct completion tune_done, stat_done;
+
+ /* todo: save freq/band instead whole struct */
+ struct dvb_frontend_parameters fe_params;
+
+};
+
+extern void smscore_registry_setmode(char *devpath, int mode);
+extern int smscore_registry_getmode(char *devpath);
+
+extern int smscore_register_hotplug(hotplug_t hotplug);
+extern void smscore_unregister_hotplug(hotplug_t hotplug);
+
+extern int smscore_register_device(struct smsdevice_params_t *params,
+ struct smscore_device_t **coredev);
+extern void smscore_unregister_device(struct smscore_device_t *coredev);
+
+extern int smscore_start_device(struct smscore_device_t *coredev);
+extern int smscore_load_firmware(struct smscore_device_t *coredev,
+ char *filename,
+ loadfirmware_t loadfirmware_handler);
+
+extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode);
+extern int smscore_get_device_mode(struct smscore_device_t *coredev);
+
+extern int smscore_register_client(struct smscore_device_t *coredev,
+ struct smsclient_params_t *params,
+ struct smscore_client_t **client);
+extern void smscore_unregister_client(struct smscore_client_t *client);
+
+extern int smsclient_sendrequest(struct smscore_client_t *client,
+ void *buffer, size_t size);
+extern void smscore_onresponse(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb);
+
+#if 0
+extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev);
+extern int smscore_map_common_buffer(struct smscore_device_t *coredev,
+ struct vm_area_struct *vma);
+#endif
+
+extern
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
+extern void smscore_putbuffer(struct smscore_device_t *coredev,
+ struct smscore_buffer_t *cb);
+
+void smscore_set_board_id(struct smscore_device_t *core, int id);
+int smscore_get_board_id(struct smscore_device_t *core);
+
+/* smsdvb.c */
+int smsdvb_register(void);
+void smsdvb_unregister(void);
+
+/* smsusb.c */
+int smsusb_register(void);
+void smsusb_unregister(void);
+
+/* ------------------------------------------------------------------------ */
+
+extern int sms_debug;
+
+#define DBG_INFO 1
+#define DBG_ADV 2
+
+#define sms_printk(kern, fmt, arg...) \
+ printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define dprintk(kern, lvl, fmt, arg...) do {\
+ if (sms_debug & lvl) \
+ sms_printk(kern, fmt, ##arg); } while (0)
+
+#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
+#define sms_err(fmt, arg...) \
+ sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
+#define sms_warn(fmt, arg...) sms_printk(KERN_WARNING, fmt, ##arg)
+#define sms_info(fmt, arg...) \
+ dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
+#define sms_debug(fmt, arg...) \
+ dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
+
+
+#endif /* __smscoreapi_h__ */
diff --git a/linux/drivers/media/dvb/siano/smsdvb.c b/linux/drivers/media/dvb/siano/smsdvb.c
new file mode 100644
index 000000000..2da99f19e
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/smsdvb.c
@@ -0,0 +1,458 @@
+/*
+ * Driver for the Siano SMS1xxx USB dongle
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct list_head g_smsdvb_clients;
+struct mutex g_smsdvb_clientslock;
+
+static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
+{
+ struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
+ struct SmsMsgHdr_ST *phdr =
+ (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset);
+
+ switch (phdr->msgType) {
+ case MSG_SMS_DVBT_BDA_DATA:
+ dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
+ cb->size - sizeof(struct SmsMsgHdr_ST));
+ break;
+
+ case MSG_SMS_RF_TUNE_RES:
+ complete(&client->tune_done);
+ break;
+
+ case MSG_SMS_GET_STATISTICS_RES:
+ {
+ struct SmsMsgStatisticsInfo_ST *p =
+ (struct SmsMsgStatisticsInfo_ST *)(phdr + 1);
+
+ if (p->Stat.IsDemodLocked) {
+ client->fe_status = FE_HAS_SIGNAL |
+ FE_HAS_CARRIER |
+ FE_HAS_VITERBI |
+ FE_HAS_SYNC |
+ FE_HAS_LOCK;
+
+ client->fe_snr = p->Stat.SNR;
+ client->fe_ber = p->Stat.BER;
+
+ if (p->Stat.InBandPwr < -95)
+ client->fe_signal_strength = 0;
+ else if (p->Stat.InBandPwr > -29)
+ client->fe_signal_strength = 100;
+ else
+ client->fe_signal_strength =
+ (p->Stat.InBandPwr + 95) * 3 / 2;
+ } else {
+ client->fe_status = 0;
+ client->fe_snr =
+ client->fe_ber =
+ client->fe_signal_strength = 0;
+ }
+
+ complete(&client->stat_done);
+ break;
+ } }
+
+ smscore_putbuffer(client->coredev, cb);
+
+ return 0;
+}
+
+static void smsdvb_unregister_client(struct smsdvb_client_t *client)
+{
+ /* must be called under clientslock */
+
+ list_del(&client->entry);
+
+ smscore_unregister_client(client->smsclient);
+ dvb_unregister_frontend(&client->frontend);
+ dvb_dmxdev_release(&client->dmxdev);
+ dvb_dmx_release(&client->demux);
+ dvb_unregister_adapter(&client->adapter);
+ kfree(client);
+}
+
+static void smsdvb_onremove(void *context)
+{
+ kmutex_lock(&g_smsdvb_clientslock);
+
+ smsdvb_unregister_client((struct smsdvb_client_t *) context);
+
+ kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+static int smsdvb_start_feed(struct dvb_demux_feed *feed)
+{
+ struct smsdvb_client_t *client =
+ container_of(feed->demux, struct smsdvb_client_t, demux);
+ struct SmsMsgData_ST PidMsg;
+
+ sms_debug("add pid %d(%x)",
+ feed->pid, feed->pid);
+
+ PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+ PidMsg.xMsgHeader.msgFlags = 0;
+ PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
+ PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+ PidMsg.msgData[0] = feed->pid;
+
+ return smsclient_sendrequest(client->smsclient,
+ &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct smsdvb_client_t *client =
+ container_of(feed->demux, struct smsdvb_client_t, demux);
+ struct SmsMsgData_ST PidMsg;
+
+ sms_debug("remove pid %d(%x)",
+ feed->pid, feed->pid);
+
+ PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+ PidMsg.xMsgHeader.msgFlags = 0;
+ PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
+ PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+ PidMsg.msgData[0] = feed->pid;
+
+ return smsclient_sendrequest(client->smsclient,
+ &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
+ void *buffer, size_t size,
+ struct completion *completion)
+{
+ int rc = smsclient_sendrequest(client->smsclient, buffer, size);
+ if (rc < 0)
+ return rc;
+
+ return wait_for_completion_timeout(completion,
+ msecs_to_jiffies(2000)) ?
+ 0 : -ETIME;
+}
+
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+ struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
+ DVBT_BDA_CONTROL_MSG_ID,
+ HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 };
+ return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->stat_done);
+}
+
+static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *stat = client->fe_status;
+
+ return rc;
+}
+
+static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *ber = client->fe_ber;
+
+ return rc;
+}
+
+static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *strength = client->fe_signal_strength;
+
+ return rc;
+}
+
+static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ int rc = smsdvb_send_statistics_request(client);
+
+ if (!rc)
+ *snr = client->fe_snr;
+
+ return rc;
+}
+
+static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ sms_debug("");
+
+ tune->min_delay_ms = 400;
+ tune->step_size = 250000;
+ tune->max_drift = 0;
+ return 0;
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+
+ struct {
+ struct SmsMsgHdr_ST Msg;
+ u32 Data[3];
+ } Msg;
+
+ Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+ Msg.Msg.msgDstId = HIF_TASK;
+ Msg.Msg.msgFlags = 0;
+ Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
+ Msg.Msg.msgLength = sizeof(Msg);
+ Msg.Data[0] = fep->frequency;
+ Msg.Data[2] = 12000000;
+
+ sms_debug("freq %d band %d",
+ fep->frequency, fep->u.ofdm.bandwidth);
+
+ switch (fep->u.ofdm.bandwidth) {
+ case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
+ case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
+ case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
+#if 0
+ case BANDWIDTH_5_MHZ: Msg.Data[1] = BW_5_MHZ; break;
+#endif
+ case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+ default: return -EINVAL;
+ }
+
+ return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+ &client->tune_done);
+}
+
+static int smsdvb_get_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+
+ sms_debug("");
+
+ /* todo: */
+ memcpy(fep, &client->fe_params,
+ sizeof(struct dvb_frontend_parameters));
+ return 0;
+}
+
+static void smsdvb_release(struct dvb_frontend *fe)
+{
+ /* do nothing */
+}
+
+static struct dvb_frontend_ops smsdvb_fe_ops = {
+ .info = {
+ .name = "Siano Mobile Digital SMS1xxx",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
+ .frequency_stepsize = 250000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+ FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = smsdvb_release,
+
+ .set_frontend = smsdvb_set_frontend,
+ .get_frontend = smsdvb_get_frontend,
+ .get_tune_settings = smsdvb_get_tune_settings,
+
+ .read_status = smsdvb_read_status,
+ .read_ber = smsdvb_read_ber,
+ .read_signal_strength = smsdvb_read_signal_strength,
+ .read_snr = smsdvb_read_snr,
+};
+
+static int smsdvb_hotplug(struct smscore_device_t *coredev,
+ struct device *device, int arrival)
+{
+ struct smsclient_params_t params;
+ struct smsdvb_client_t *client;
+ int rc;
+
+ /* device removal handled by onremove callback */
+ if (!arrival)
+ return 0;
+
+ if (smscore_get_device_mode(coredev) != 4) {
+#if 1 /* new siano drop (1.2.17) does this -- yuck */
+ sms_err("SMS Device mode is not set for "
+ "DVB operation.");
+ return 0;
+#else
+ rc = smscore_set_device_mode(coredev, 4);
+ if (rc < 0)
+ return rc;
+#endif
+ }
+
+ client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
+ if (!client) {
+ sms_err("kmalloc() failed");
+ return -ENOMEM;
+ }
+
+ /* register dvb adapter */
+ rc = dvb_register_adapter(&client->adapter,
+ sms_get_board(
+ smscore_get_board_id(coredev))->name,
+ THIS_MODULE, device, adapter_nr);
+ if (rc < 0) {
+ sms_err("dvb_register_adapter() failed %d", rc);
+ goto adapter_error;
+ }
+
+ /* init dvb demux */
+ client->demux.dmx.capabilities = DMX_TS_FILTERING;
+ client->demux.filternum = 32; /* todo: nova ??? */
+ client->demux.feednum = 32;
+ client->demux.start_feed = smsdvb_start_feed;
+ client->demux.stop_feed = smsdvb_stop_feed;
+
+ rc = dvb_dmx_init(&client->demux);
+ if (rc < 0) {
+ sms_err("dvb_dmx_init failed %d", rc);
+ goto dvbdmx_error;
+ }
+
+ /* init dmxdev */
+ client->dmxdev.filternum = 32;
+ client->dmxdev.demux = &client->demux.dmx;
+ client->dmxdev.capabilities = 0;
+
+ rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
+ if (rc < 0) {
+ sms_err("dvb_dmxdev_init failed %d", rc);
+ goto dmxdev_error;
+ }
+
+ /* init and register frontend */
+ memcpy(&client->frontend.ops, &smsdvb_fe_ops,
+ sizeof(struct dvb_frontend_ops));
+
+ rc = dvb_register_frontend(&client->adapter, &client->frontend);
+ if (rc < 0) {
+ sms_err("frontend registration failed %d", rc);
+ goto frontend_error;
+ }
+
+ params.initial_id = 1;
+ params.data_type = MSG_SMS_DVBT_BDA_DATA;
+ params.onresponse_handler = smsdvb_onresponse;
+ params.onremove_handler = smsdvb_onremove;
+ params.context = client;
+
+ rc = smscore_register_client(coredev, &params, &client->smsclient);
+ if (rc < 0) {
+ sms_err("smscore_register_client() failed %d", rc);
+ goto client_error;
+ }
+
+ client->coredev = coredev;
+
+ init_completion(&client->tune_done);
+ init_completion(&client->stat_done);
+
+ kmutex_lock(&g_smsdvb_clientslock);
+
+ list_add(&client->entry, &g_smsdvb_clients);
+
+ kmutex_unlock(&g_smsdvb_clientslock);
+
+ sms_info("success");
+
+ return 0;
+
+client_error:
+ dvb_unregister_frontend(&client->frontend);
+
+frontend_error:
+ dvb_dmxdev_release(&client->dmxdev);
+
+dmxdev_error:
+ dvb_dmx_release(&client->demux);
+
+dvbdmx_error:
+ dvb_unregister_adapter(&client->adapter);
+
+adapter_error:
+ kfree(client);
+ return rc;
+}
+
+int smsdvb_register(void)
+{
+ int rc;
+
+ INIT_LIST_HEAD(&g_smsdvb_clients);
+ kmutex_init(&g_smsdvb_clientslock);
+
+ rc = smscore_register_hotplug(smsdvb_hotplug);
+
+ sms_debug("");
+
+ return rc;
+}
+
+void smsdvb_unregister(void)
+{
+ smscore_unregister_hotplug(smsdvb_hotplug);
+
+ kmutex_lock(&g_smsdvb_clientslock);
+
+ while (!list_empty(&g_smsdvb_clients))
+ smsdvb_unregister_client(
+ (struct smsdvb_client_t *) g_smsdvb_clients.next);
+
+ kmutex_unlock(&g_smsdvb_clientslock);
+}
diff --git a/linux/drivers/media/dvb/siano/smsusb.c b/linux/drivers/media/dvb/siano/smsusb.c
new file mode 100644
index 000000000..079deb2a1
--- /dev/null
+++ b/linux/drivers/media/dvb/siano/smsusb.c
@@ -0,0 +1,463 @@
+/*
+ * Driver for the Siano SMS1xxx USB dongle
+ *
+ * author: Anatoly Greenblat
+ *
+ * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation;
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+#define USB1_BUFFER_SIZE 0x1000
+#define USB2_BUFFER_SIZE 0x4000
+
+#define MAX_BUFFERS 50
+#define MAX_URBS 10
+
+struct smsusb_device_t;
+
+struct smsusb_urb_t {
+ struct smscore_buffer_t *cb;
+ struct smsusb_device_t *dev;
+
+ struct urb urb;
+};
+
+struct smsusb_device_t {
+ struct usb_device *udev;
+ struct smscore_device_t *coredev;
+
+ struct smsusb_urb_t surbs[MAX_URBS];
+
+ int response_alignment;
+ int buffer_size;
+};
+
+static int smsusb_submit_urb(struct smsusb_device_t *dev,
+ struct smsusb_urb_t *surb);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
+static void smsusb_onresponse(struct urb *urb)
+#else
+static void smsusb_onresponse(struct urb *urb, struct pt_regs *regs)
+#endif
+{
+ struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
+ struct smsusb_device_t *dev = surb->dev;
+
+ if (urb->status < 0) {
+ sms_err("error, urb status %d, %d bytes",
+ urb->status, urb->actual_length);
+ return;
+ }
+
+ if (urb->actual_length > 0) {
+ struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p;
+
+ if (urb->actual_length >= phdr->msgLength) {
+ surb->cb->size = phdr->msgLength;
+
+ if (dev->response_alignment &&
+ (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) {
+
+ surb->cb->offset =
+ dev->response_alignment +
+ ((phdr->msgFlags >> 8) & 3);
+
+ /* sanity check */
+ if (((int) phdr->msgLength +
+ surb->cb->offset) > urb->actual_length) {
+ sms_err("invalid response "
+ "msglen %d offset %d "
+ "size %d",
+ phdr->msgLength,
+ surb->cb->offset,
+ urb->actual_length);
+ goto exit_and_resubmit;
+ }
+
+ /* move buffer pointer and
+ * copy header to its new location */
+ memcpy((char *) phdr + surb->cb->offset,
+ phdr, sizeof(struct SmsMsgHdr_ST));
+ } else
+ surb->cb->offset = 0;
+
+ smscore_onresponse(dev->coredev, surb->cb);
+ surb->cb = NULL;
+ } else {
+ sms_err("invalid response "
+ "msglen %d actual %d",
+ phdr->msgLength, urb->actual_length);
+ }
+ }
+
+exit_and_resubmit:
+ smsusb_submit_urb(dev, surb);
+}
+
+static int smsusb_submit_urb(struct smsusb_device_t *dev,
+ struct smsusb_urb_t *surb)
+{
+ if (!surb->cb) {
+ surb->cb = smscore_getbuffer(dev->coredev);
+ if (!surb->cb) {
+ sms_err("smscore_getbuffer(...) returned NULL");
+ return -ENOMEM;
+ }
+ }
+
+ usb_fill_bulk_urb(
+ &surb->urb,
+ dev->udev,
+ usb_rcvbulkpipe(dev->udev, 0x81),
+ surb->cb->p,
+ dev->buffer_size,
+ smsusb_onresponse,
+ surb
+ );
+ surb->urb.transfer_dma = surb->cb->phys;
+ surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ return usb_submit_urb(&surb->urb, GFP_ATOMIC);
+}
+
+static void smsusb_stop_streaming(struct smsusb_device_t *dev)
+{
+ int i;
+
+ for (i = 0; i < MAX_URBS; i++) {
+ usb_kill_urb(&dev->surbs[i].urb);
+
+ if (dev->surbs[i].cb) {
+ smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
+ dev->surbs[i].cb = NULL;
+ }
+ }
+}
+
+static int smsusb_start_streaming(struct smsusb_device_t *dev)
+{
+ int i, rc;
+
+ for (i = 0; i < MAX_URBS; i++) {
+ rc = smsusb_submit_urb(dev, &dev->surbs[i]);
+ if (rc < 0) {
+ sms_err("smsusb_submit_urb(...) failed");
+ smsusb_stop_streaming(dev);
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static int smsusb_sendrequest(void *context, void *buffer, size_t size)
+{
+ struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
+ int dummy;
+
+ return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+ buffer, size, &dummy, 1000);
+}
+
+static char *smsusb1_fw_lkup[] = {
+ "dvbt_stellar_usb.inp",
+ "dvbh_stellar_usb.inp",
+ "tdmb_stellar_usb.inp",
+ "none",
+ "dvbt_bda_stellar_usb.inp",
+};
+
+static inline char *sms_get_fw_name(int mode, int board_id)
+{
+ char **fw = sms_get_board(board_id)->fw;
+ return (fw && fw[mode]) ? fw[mode] : smsusb1_fw_lkup[mode];
+}
+
+static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
+{
+ const struct firmware *fw;
+ u8 *fw_buffer;
+ int rc, dummy;
+ char *fw_filename;
+
+ if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
+ sms_err("invalid firmware id specified %d", id);
+ return -EINVAL;
+ }
+
+ fw_filename = sms_get_fw_name(id, board_id);
+
+ rc = request_firmware(&fw, fw_filename, &udev->dev);
+ if (rc < 0) {
+ sms_warn("failed to open \"%s\" mode %d, "
+ "trying again with default firmware", fw_filename, id);
+
+ fw_filename = smsusb1_fw_lkup[id];
+ rc = request_firmware(&fw, fw_filename, &udev->dev);
+ if (rc < 0) {
+ sms_warn("failed to open \"%s\" mode %d",
+ fw_filename, id);
+
+ return rc;
+ }
+ }
+
+ fw_buffer = kmalloc(fw->size, GFP_KERNEL);
+ if (fw_buffer) {
+ memcpy(fw_buffer, fw->data, fw->size);
+
+ rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
+ fw_buffer, fw->size, &dummy, 1000);
+
+ sms_info("sent %zd(%d) bytes, rc %d", fw->size, dummy, rc);
+
+ kfree(fw_buffer);
+ } else {
+ sms_err("failed to allocate firmware buffer");
+ rc = -ENOMEM;
+ }
+ sms_info("read FW %s, size=%zd", fw_filename, fw->size);
+
+ release_firmware(fw);
+
+ return rc;
+}
+
+static void smsusb1_detectmode(void *context, int *mode)
+{
+ char *product_string =
+ ((struct smsusb_device_t *) context)->udev->product;
+
+ *mode = DEVICE_MODE_NONE;
+
+ if (!product_string) {
+ product_string = "none";
+ sms_err("product string not found");
+ } else if (strstr(product_string, "DVBH"))
+ *mode = 1;
+ else if (strstr(product_string, "BDA"))
+ *mode = 4;
+ else if (strstr(product_string, "DVBT"))
+ *mode = 0;
+ else if (strstr(product_string, "TDMB"))
+ *mode = 2;
+
+ sms_info("%d \"%s\"", *mode, product_string);
+}
+
+static int smsusb1_setmode(void *context, int mode)
+{
+ struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
+ sizeof(struct SmsMsgHdr_ST), 0 };
+
+ if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+ sms_err("invalid firmware id specified %d", mode);
+ return -EINVAL;
+ }
+
+ return smsusb_sendrequest(context, &Msg, sizeof(Msg));
+}
+
+static void smsusb_term_device(struct usb_interface *intf)
+{
+ struct smsusb_device_t *dev =
+ (struct smsusb_device_t *) usb_get_intfdata(intf);
+
+ if (dev) {
+ smsusb_stop_streaming(dev);
+
+ /* unregister from smscore */
+ if (dev->coredev)
+ smscore_unregister_device(dev->coredev);
+
+ kfree(dev);
+
+ sms_info("device %p destroyed", dev);
+ }
+
+ usb_set_intfdata(intf, NULL);
+}
+
+static int smsusb_init_device(struct usb_interface *intf, int board_id)
+{
+ struct smsdevice_params_t params;
+ struct smsusb_device_t *dev;
+ int i, rc;
+
+ /* create device object */
+ dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
+ if (!dev) {
+ sms_err("kzalloc(sizeof(struct smsusb_device_t) failed");
+ return -ENOMEM;
+ }
+
+ memset(&params, 0, sizeof(params));
+ usb_set_intfdata(intf, dev);
+ dev->udev = interface_to_usbdev(intf);
+
+ params.device_type = sms_get_board(board_id)->type;
+
+ switch (params.device_type) {
+ case SMS_STELLAR:
+ dev->buffer_size = USB1_BUFFER_SIZE;
+
+ params.setmode_handler = smsusb1_setmode;
+ params.detectmode_handler = smsusb1_detectmode;
+ break;
+ default:
+ sms_err("Unspecified sms device type!");
+ /* fall-thru */
+ case SMS_NOVA_A0:
+ case SMS_NOVA_B0:
+ case SMS_VEGA:
+ dev->buffer_size = USB2_BUFFER_SIZE;
+ dev->response_alignment =
+ dev->udev->ep_in[1]->desc.wMaxPacketSize -
+ sizeof(struct SmsMsgHdr_ST);
+
+ params.flags |= SMS_DEVICE_FAMILY2;
+ break;
+ }
+
+ params.device = &dev->udev->dev;
+ params.buffer_size = dev->buffer_size;
+ params.num_buffers = MAX_BUFFERS;
+ params.sendrequest_handler = smsusb_sendrequest;
+ params.context = dev;
+ snprintf(params.devpath, sizeof(params.devpath),
+ "usb\\%d-%s", dev->udev->bus->busnum, dev->udev->devpath);
+
+ /* register in smscore */
+ rc = smscore_register_device(&params, &dev->coredev);
+ if (rc < 0) {
+ sms_err("smscore_register_device(...) failed, rc %d", rc);
+ smsusb_term_device(intf);
+ return rc;
+ }
+
+ smscore_set_board_id(dev->coredev, board_id);
+
+ /* initialize urbs */
+ for (i = 0; i < MAX_URBS; i++) {
+ dev->surbs[i].dev = dev;
+ usb_init_urb(&dev->surbs[i].urb);
+ }
+
+ sms_info("smsusb_start_streaming(...).");
+ rc = smsusb_start_streaming(dev);
+ if (rc < 0) {
+ sms_err("smsusb_start_streaming(...) failed");
+ smsusb_term_device(intf);
+ return rc;
+ }
+
+ rc = smscore_start_device(dev->coredev);
+ if (rc < 0) {
+ sms_err("smscore_start_device(...) failed");
+ smsusb_term_device(intf);
+ return rc;
+ }
+
+ sms_info("device %p created", dev);
+
+ return rc;
+}
+
+static int smsusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ char devpath[32];
+ int i, rc;
+
+ rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
+ rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
+
+ if (intf->num_altsetting > 0) {
+ rc = usb_set_interface(
+ udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
+ if (rc < 0) {
+ sms_err("usb_set_interface failed, rc %d", rc);
+ return rc;
+ }
+ }
+
+ sms_info("smsusb_probe %d",
+ intf->cur_altsetting->desc.bInterfaceNumber);
+ for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
+ sms_info("endpoint %d %02x %02x %d", i,
+ intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
+ intf->cur_altsetting->endpoint[i].desc.bmAttributes,
+ intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
+
+ if ((udev->actconfig->desc.bNumInterfaces == 2) &&
+ (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
+ sms_err("rom interface 0 is not used");
+ return -ENODEV;
+ }
+
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
+ snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
+ udev->bus->busnum, udev->devpath);
+ sms_info("stellar device was found.");
+ return smsusb1_load_firmware(
+ udev, smscore_registry_getmode(devpath),
+ id->driver_info);
+ }
+
+ rc = smsusb_init_device(intf, id->driver_info);
+ sms_info("rc %d", rc);
+ return rc;
+}
+
+static void smsusb_disconnect(struct usb_interface *intf)
+{
+ smsusb_term_device(intf);
+}
+
+static struct usb_driver smsusb_driver = {
+ .name = "sms1xxx",
+ .probe = smsusb_probe,
+ .disconnect = smsusb_disconnect,
+ .id_table = smsusb_id_table,
+};
+
+int smsusb_register(void)
+{
+ int rc = usb_register(&smsusb_driver);
+ if (rc)
+ sms_err("usb_register failed. Error number %d", rc);
+
+ sms_debug("");
+
+ return rc;
+}
+
+void smsusb_unregister(void)
+{
+ sms_debug("");
+ /* Regular USB Cleanup */
+ usb_deregister(&smsusb_driver);
+}
+
diff --git a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 8786d3d6f..133648277 100644
--- a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/wait.h>
+#include <linux/fs.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/delay.h>
@@ -988,22 +989,9 @@ static int stc_open(struct inode *inode, struct file *file)
}
static ssize_t stc_read(struct file *file, char *buf, size_t count,
- loff_t * offset)
+ loff_t *offset)
{
- int tc = count;
-
- if ((tc + *offset) > 8192)
- tc = 8192 - *offset;
-
- if (tc < 0)
- return 0;
-
- if (copy_to_user(buf, stc_firmware + *offset, tc))
- return -EFAULT;
-
- *offset += tc;
-
- return tc;
+ return simple_read_from_buffer(buf, count, offset, stc_firmware, 8192);
}
static int stc_release(struct inode *inode, struct file *file)
diff --git a/linux/drivers/media/video/bt819.c b/linux/drivers/media/video/bt819.c
index 402bccaf7..90be239cc 100644
--- a/linux/drivers/media/video/bt819.c
+++ b/linux/drivers/media/video/bt819.c
@@ -517,7 +517,7 @@ bt819_detect_client (struct i2c_adapter *adapter,
dprintk(1,
KERN_INFO
- "saa7111.c: detecting bt819 client on address 0x%x\n",
+ "bt819: detecting bt819 client on address 0x%x\n",
address << 1);
/* Check if the adapter supports the needed features */
diff --git a/linux/drivers/media/video/cx18/cx18-av-firmware.c b/linux/drivers/media/video/cx18/cx18-av-firmware.c
index 6fa3b01a1..834b92482 100644
--- a/linux/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/linux/drivers/media/video/cx18/cx18-av-firmware.c
@@ -30,7 +30,7 @@ int cx18_av_loadfw(struct cx18 *cx)
const struct firmware *fw = NULL;
u32 size;
u32 v;
- u8 *ptr;
+ const u8 *ptr;
int i;
int retries = 0;
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index eb7abbaa8..cb07f2b2e 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -219,7 +219,7 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
if (len > 0) {
if (frame->data_end - frame->data + len
> frame->v4l2_buf.length) {
- PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
+ PDEBUG(D_ERR|D_PACK, "frame overflow %zd > %d",
frame->data_end - frame->data + len,
frame->v4l2_buf.length);
packet_type = DISCARD_PACKET;
@@ -1567,7 +1567,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
struct timeval timestamp;
int n, ret, ret2;
- PDEBUG(D_FRAM, "read (%d)", count);
+ PDEBUG(D_FRAM, "read (%zd)", count);
if (!gspca_dev->present)
return -ENODEV;
switch (gspca_dev->memory) {
@@ -1618,7 +1618,7 @@ static ssize_t dev_read(struct file *file, char __user *data,
ret = copy_to_user(data, frame->data, count);
if (ret != 0) {
PDEBUG(D_ERR|D_STREAM,
- "read cp to user lack %d / %d", ret, count);
+ "read cp to user lack %d / %zd", ret, count);
ret = -EFAULT;
goto out;
}
diff --git a/linux/drivers/media/video/ivtv/ivtvfb.c b/linux/drivers/media/video/ivtv/ivtvfb.c
index 14f93341f..bdfda48e5 100644
--- a/linux/drivers/media/video/ivtv/ivtvfb.c
+++ b/linux/drivers/media/video/ivtv/ivtvfb.c
@@ -417,10 +417,11 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
if (!err) {
/* If transfer size > threshold and both src/dst
addresses are aligned, use DMA */
- if (count >= 4096 && ((u32)buf & 3) == ((u32)dst & 3)) {
+ if (count >= 4096 &&
+ ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
/* Odd address = can't DMA. Align */
- if ((u32)dst & 3) {
- lead = 4 - ((u32)dst & 3);
+ if ((unsigned long)dst & 3) {
+ lead = 4 - ((unsigned long)dst & 3);
memcpy(dst, buf, lead);
buf += lead;
dst += lead;
diff --git a/linux/drivers/media/video/ov7670.c b/linux/drivers/media/video/ov7670.c
index fb8c607fc..dcf7678a8 100644
--- a/linux/drivers/media/video/ov7670.c
+++ b/linux/drivers/media/video/ov7670.c
@@ -407,8 +407,10 @@ static int ov7670_read(struct i2c_client *c, unsigned char reg,
int ret;
ret = i2c_smbus_read_byte_data(c, reg);
- if (ret >= 0)
+ if (ret >= 0) {
*value = (unsigned char) ret;
+ ret = 0;
+ }
return ret;
}
@@ -702,17 +704,17 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
for (index = 0; index < N_OV7670_FMTS; index++)
if (ov7670_formats[index].pixelformat == pix->pixelformat)
break;
- if (index >= N_OV7670_FMTS)
- return -EINVAL;
+ if (index >= N_OV7670_FMTS) {
+ /* default to first format */
+ index = 0;
+ pix->pixelformat = ov7670_formats[0].pixelformat;
+ }
if (ret_fmt != NULL)
*ret_fmt = ov7670_formats + index;
/*
* Fields: the OV devices claim to be progressive.
*/
- if (pix->field == V4L2_FIELD_ANY)
- pix->field = V4L2_FIELD_NONE;
- else if (pix->field != V4L2_FIELD_NONE)
- return -EINVAL;
+ pix->field = V4L2_FIELD_NONE;
/*
* Round requested image size down to the nearest
* we support, but not below the smallest.
diff --git a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c
index 8063e33f1..065c24541 100644
--- a/linux/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/linux/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -297,7 +297,6 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
switch (adap->id) {
case I2C_HW_SMBUS_OV511:
case I2C_HW_SMBUS_OV518:
- case I2C_HW_SMBUS_OVFX2:
case I2C_HW_SMBUS_W9968CF:
PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
break;
diff --git a/linux/drivers/media/video/s2255drv.c b/linux/drivers/media/video/s2255drv.c
index aca8c3d90..6eb396ffc 100644
--- a/linux/drivers/media/video/s2255drv.c
+++ b/linux/drivers/media/video/s2255drv.c
@@ -68,17 +68,17 @@
/* maximum time for DSP to start responding after last FW word loaded(ms) */
#define S2255_DSP_BOOTTIME 400
/* maximum time to wait for firmware to load (ms) */
-#define S2255_LOAD_TIMEOUT (5000+S2255_DSP_BOOTTIME)
+#define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME)
#define S2255_DEF_BUFS 16
#define MAX_CHANNELS 4
#define FRAME_MARKER 0x2255DA4AL
-#define MAX_PIPE_USBBLOCK (40*1024)
-#define DEFAULT_PIPE_USBBLOCK (16*1024)
+#define MAX_PIPE_USBBLOCK (40 * 1024)
+#define DEFAULT_PIPE_USBBLOCK (16 * 1024)
#define MAX_CHANNELS 4
#define MAX_PIPE_BUFFERS 1
#define SYS_FRAMES 4
/* maximum size is PAL full size plus room for the marker header(s) */
-#define SYS_FRAMES_MAXSIZE (720*288*2*2 + 4096)
+#define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096)
#define DEF_USB_BLOCK (4096)
#define LINE_SZ_4CIFS_NTSC 640
#define LINE_SZ_2CIFS_NTSC 640
@@ -169,7 +169,7 @@ struct s2255_bufferi {
#define DEF_MODEI_NTSC_CONT {FORMAT_NTSC, DEF_SCALE, DEF_COLOR, \
DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
- DEF_HUE, 0, DEF_USB_BLOCK, 0 }
+ DEF_HUE, 0, DEF_USB_BLOCK, 0}
struct s2255_dmaqueue {
struct list_head active;
@@ -276,6 +276,10 @@ struct s2255_fh {
struct s2255_mode mode;
};
+/*
+ * TODO: fixme S2255_MAX_USERS. Do not limit open driver handles.
+ * Limit V4L to one stream at a time.
+ */
#define S2255_MAX_USERS 1
#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */
@@ -294,7 +298,7 @@ struct s2255_fh {
#define PREFIX_SIZE 512
/* Channels on box are in reverse order */
-static unsigned long G_chnmap[MAX_CHANNELS] = { 3, 2, 1, 0 };
+static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0};
static LIST_HEAD(s2255_devlist);
@@ -330,11 +334,11 @@ static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
/* start video number */
static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
-module_param(debug, int, 0);
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level(0-100) default 0");
-module_param(vid_limit, int, 0);
+module_param(vid_limit, int, 0644);
MODULE_PARM_DESC(vid_limit, "video memory limit(Mb)");
-module_param(video_nr, int, 0);
+module_param(video_nr, int, 0644);
MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)");
/* USB device table */
@@ -438,7 +442,10 @@ static int norm_minh(struct video_device *vdev)
}
-/* converts 2255 planar format to yuyv or uyvy */
+/*
+ * TODO: fixme: move YUV reordering to hardware
+ * converts 2255 planar format to yuyv or uyvy
+ */
static void planar422p_to_yuv_packed(const unsigned char *in,
unsigned char *out,
int width, int height,
@@ -503,7 +510,7 @@ static void s2255_fwchunk_complete(struct urb *urb)
struct usb_device *udev = urb->dev;
int len;
dprintk(100, "udev %p urb %p", udev, urb);
-
+ /* TODO: fixme. reflect change in status */
if (urb->status) {
dev_err(&udev->dev, "URB failed with status %d", urb->status);
return;
@@ -683,7 +690,7 @@ static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
if (0 == *count)
*count = S2255_DEF_BUFS;
- while (*size * *count > vid_limit * 1024 * 1024)
+ while (*size * (*count) > vid_limit * 1024 * 1024)
(*count)--;
return 0;
@@ -790,7 +797,7 @@ static int res_get(struct s2255_dev *dev, struct s2255_fh *fh)
static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh)
{
- return (dev->resources[fh->channel]);
+ return dev->resources[fh->channel];
}
static void res_free(struct s2255_dev *dev, struct s2255_fh *fh)
@@ -807,7 +814,8 @@ static int vidioc_querycap(struct file *file, void *priv,
struct s2255_dev *dev = fh->dev;
strlcpy(cap->driver, "s2255", sizeof(cap->driver));
strlcpy(cap->card, "s2255", sizeof(cap->card));
- strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
+ strlcpy(cap->bus_info, dev_name(&dev->udev->dev),
+ sizeof(cap->bus_info));
cap->version = S2255_VERSION;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
return 0;
@@ -840,8 +848,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = fh->fmt->fourcc;
f->fmt.pix.bytesperline = f->fmt.pix.width * (fh->fmt->depth >> 3);
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-
- return (0);
+ return 0;
}
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
@@ -962,7 +969,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
ret = vidioc_try_fmt_vid_cap(file, fh, f);
if (ret < 0)
- return (ret);
+ return ret;
fmt = format_by_fourcc(f->fmt.pix.pixelformat);
@@ -1337,7 +1344,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
inp->type = V4L2_INPUT_TYPE_CAMERA;
inp->std = S2255_NORMS;
strlcpy(inp->name, "Camera", sizeof(inp->name));
- return (0);
+ return 0;
}
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
@@ -1361,7 +1368,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
if (qc->id && qc->id == s2255_qctrl[i].id) {
memcpy(qc, &(s2255_qctrl[i]), sizeof(*qc));
- return (0);
+ return 0;
}
dprintk(4, "query_ctrl -EINVAL %d\n", qc->id);
@@ -1376,7 +1383,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
if (ctrl->id == s2255_qctrl[i].id) {
ctrl->value = qctl_regs[i];
- return (0);
+ return 0;
}
dprintk(4, "g_ctrl -EINVAL\n");
@@ -1396,7 +1403,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
if (ctrl->id == s2255_qctrl[i].id) {
if (ctrl->value < s2255_qctrl[i].minimum ||
ctrl->value > s2255_qctrl[i].maximum)
- return (-ERANGE);
+ return -ERANGE;
qctl_regs[i] = ctrl->value;
/* update the mode to the corresponding value */
@@ -1572,6 +1579,11 @@ static void s2255_destroy(struct kref *kref)
usb_free_urb(dev->fw_data->fw_urb);
dev->fw_data->fw_urb = NULL;
}
+ /*
+ * TODO: fixme(above, below): potentially leaving timers alive.
+ * do not ignore timeout below if
+ * it occurs.
+ */
/* make sure we aren't waiting for the DSP */
if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_LOADED_DSPWAIT) {
@@ -1583,15 +1595,12 @@ static void s2255_destroy(struct kref *kref)
}
if (dev->fw_data) {
+ if (dev->fw_data->fw)
+ release_firmware(dev->fw_data->fw);
kfree(dev->fw_data->pfw_data);
kfree(dev->fw_data);
}
- if (dev->fw_data->fw) {
- release_firmware(dev->fw_data->fw);
- dev->fw_data->fw = NULL;
- }
-
usb_put_dev(dev->udev);
dprintk(1, "%s", __func__);
kfree(dev);
diff --git a/linux/drivers/media/video/saa7134/saa7134-cards.c b/linux/drivers/media/video/saa7134/saa7134-cards.c
index f772e9da9..a2a4ca6f8 100644
--- a/linux/drivers/media/video/saa7134/saa7134-cards.c
+++ b/linux/drivers/media/video/saa7134/saa7134-cards.c
@@ -1287,6 +1287,22 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 8,
}},
},
+ [SAA7134_BOARD_AVERMEDIA_M103] = {
+ /* Massimo Piccioni <dafastidio@libero.it> */
+ .name = "AVerMedia MiniPCI DVB-T Hybrid M103",
+ .audio_clock = 0x187de7,
+ .tuner_type = TUNER_XC2028,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ } },
+ },
[SAA7134_BOARD_NOVAC_PRIMETV7133] = {
/* toshii@netbsd.org */
.name = "Noval Prime TV 7133",
@@ -5416,6 +5432,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x6290,
.driver_data = SAA7134_BOARD_BEHOLD_H6,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xf636,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_M103,
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5517,6 +5539,7 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev,
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
switch (dev->board) {
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+ case SAA7134_BOARD_AVERMEDIA_M103:
saa7134_set_gpio(dev, 23, 0);
msleep(10);
saa7134_set_gpio(dev, 23, 1);
@@ -5750,6 +5773,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
msleep(10);
break;
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+ case SAA7134_BOARD_AVERMEDIA_M103:
saa7134_set_gpio(dev, 23, 0);
msleep(10);
saa7134_set_gpio(dev, 23, 1);
@@ -5877,6 +5901,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_AVERMEDIA_A16D:
case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+ case SAA7134_BOARD_AVERMEDIA_M103:
ctl.demod = XC3028_FE_ZARLINK456;
break;
default:
diff --git a/linux/drivers/media/video/saa7134/saa7134-dvb.c b/linux/drivers/media/video/saa7134/saa7134-dvb.c
index 3cadbad1d..ef8baf5fe 100644
--- a/linux/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/linux/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1263,6 +1263,7 @@ static int dvb_init(struct saa7134_dev *dev)
&avermedia_xc3028_mt352_dev,
&dev->i2c_adap);
attach_xc3028 = 1;
+ break;
#if 0
/*FIXME: What frontend does Videomate T750 use? */
case SAA7134_BOARD_VIDEOMATE_T750:
@@ -1294,6 +1295,15 @@ static int dvb_init(struct saa7134_dev *dev)
fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
}
break;
+ case SAA7134_BOARD_AVERMEDIA_M103:
+ saa7134_set_gpio(dev, 25, 0);
+ msleep(10);
+ saa7134_set_gpio(dev, 25, 1);
+ dev->dvb.frontend = dvb_attach(mt352_attach,
+ &avermedia_xc3028_mt352_dev,
+ &dev->i2c_adap);
+ attach_xc3028 = 1;
+ break;
default:
wprintk("Huh? unknown DVB card?\n");
break;
diff --git a/linux/drivers/media/video/saa7134/saa7134.h b/linux/drivers/media/video/saa7134/saa7134.h
index 6afbc0c57..4a9bebb2d 100644
--- a/linux/drivers/media/video/saa7134/saa7134.h
+++ b/linux/drivers/media/video/saa7134/saa7134.h
@@ -267,6 +267,7 @@ struct saa7134_format {
#define SAA7134_BOARD_BEHOLD_H6 142
#define SAA7134_BOARD_BEHOLD_M63 143
#define SAA7134_BOARD_BEHOLD_M6_EXTRA 144
+#define SAA7134_BOARD_AVERMEDIA_M103 145
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
diff --git a/linux/drivers/media/video/tvaudio.c b/linux/drivers/media/video/tvaudio.c
index 84e2c43b7..53ece95db 100644
--- a/linux/drivers/media/video/tvaudio.c
+++ b/linux/drivers/media/video/tvaudio.c
@@ -72,7 +72,6 @@ typedef struct AUDIOCMD {
/* chip description */
struct CHIPDESC {
char *name; /* chip name */
- int id; /* ID */
int addr_lo, addr_hi; /* i2c address range */
int registers; /* # of registers */
@@ -1264,7 +1263,6 @@ module_param(ta8874z, int, 0444);
static struct CHIPDESC chiplist[] = {
{
.name = "tda9840",
- .id = I2C_DRIVERID_TDA9840,
.insmodopt = &tda9840,
.addr_lo = I2C_ADDR_TDA9840 >> 1,
.addr_hi = I2C_ADDR_TDA9840 >> 1,
@@ -1280,7 +1278,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda9873h",
- .id = I2C_DRIVERID_TDA9873,
.checkit = tda9873_checkit,
.insmodopt = &tda9873,
.addr_lo = I2C_ADDR_TDA985x_L >> 1,
@@ -1301,7 +1298,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda9874h/a",
- .id = I2C_DRIVERID_TDA9874,
.checkit = tda9874a_checkit,
.initialize = tda9874a_initialize,
.insmodopt = &tda9874a,
@@ -1314,7 +1310,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda9850",
- .id = I2C_DRIVERID_TDA9850,
.insmodopt = &tda9850,
.addr_lo = I2C_ADDR_TDA985x_L >> 1,
.addr_hi = I2C_ADDR_TDA985x_H >> 1,
@@ -1327,7 +1322,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda9855",
- .id = I2C_DRIVERID_TDA9855,
.insmodopt = &tda9855,
.addr_lo = I2C_ADDR_TDA985x_L >> 1,
.addr_hi = I2C_ADDR_TDA985x_H >> 1,
@@ -1352,7 +1346,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tea6300",
- .id = I2C_DRIVERID_TEA6300,
.insmodopt = &tea6300,
.addr_lo = I2C_ADDR_TEA6300 >> 1,
.addr_hi = I2C_ADDR_TEA6300 >> 1,
@@ -1373,7 +1366,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tea6320",
- .id = I2C_DRIVERID_TEA6300,
.initialize = tea6320_initialize,
.insmodopt = &tea6320,
.addr_lo = I2C_ADDR_TEA6300 >> 1,
@@ -1395,7 +1387,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tea6420",
- .id = I2C_DRIVERID_TEA6420,
.insmodopt = &tea6420,
.addr_lo = I2C_ADDR_TEA6420 >> 1,
.addr_hi = I2C_ADDR_TEA6420 >> 1,
@@ -1408,7 +1399,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "tda8425",
- .id = I2C_DRIVERID_TDA8425,
.insmodopt = &tda8425,
.addr_lo = I2C_ADDR_TDA8425 >> 1,
.addr_hi = I2C_ADDR_TDA8425 >> 1,
@@ -1432,7 +1422,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "pic16c54 (PV951)",
- .id = I2C_DRIVERID_PIC16C54_PV9,
.insmodopt = &pic16c54,
.addr_lo = I2C_ADDR_PIC16C54 >> 1,
.addr_hi = I2C_ADDR_PIC16C54>> 1,
@@ -1448,8 +1437,6 @@ static struct CHIPDESC chiplist[] = {
},
{
.name = "ta8874z",
- .id = -1,
- /*.id = I2C_DRIVERID_TA8874Z, */
.checkit = ta8874z_checkit,
.insmodopt = &ta8874z,
.addr_lo = I2C_ADDR_TDA9840 >> 1,
diff --git a/linux/drivers/media/video/uvc/uvc_driver.c b/linux/drivers/media/video/uvc/uvc_driver.c
index 2c0b16960..f2b2983fe 100644
--- a/linux/drivers/media/video/uvc/uvc_driver.c
+++ b/linux/drivers/media/video/uvc/uvc_driver.c
@@ -1633,13 +1633,16 @@ static void uvc_disconnect(struct usb_interface *intf)
* reference to the uvc_device instance after uvc_v4l2_open() received
* the pointer to the device (video_devdata) but before it got the
* chance to increase the reference count (kref_get).
+ *
+ * Note that the reference can't be released with the lock held,
+ * otherwise a AB-BA deadlock can occur with videodev_lock that
+ * videodev acquires in videodev_open() and video_unregister_device().
*/
mutex_lock(&uvc_driver.open_mutex);
-
dev->state |= UVC_DEV_DISCONNECTED;
- kref_put(&dev->kref, uvc_delete);
-
mutex_unlock(&uvc_driver.open_mutex);
+
+ kref_put(&dev->kref, uvc_delete);
}
static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
@@ -1826,6 +1829,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID },
+ /* Asus F9SG */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x174f,
+ .idProduct = 0x8a31,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* Syntek (Asus U3S) */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/linux/drivers/media/video/uvc/uvc_v4l2.c b/linux/drivers/media/video/uvc/uvc_v4l2.c
index 0456bbdcd..b5a11eb8f 100644
--- a/linux/drivers/media/video/uvc/uvc_v4l2.c
+++ b/linux/drivers/media/video/uvc/uvc_v4l2.c
@@ -1032,7 +1032,7 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
{
struct video_device *vdev = video_devdata(file);
struct uvc_video_device *video = video_get_drvdata(vdev);
- struct uvc_buffer *buffer;
+ struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
unsigned long addr, start, size;
unsigned int i;
diff --git a/linux/drivers/media/video/videobuf-dma-sg.c b/linux/drivers/media/video/videobuf-dma-sg.c
index 39ae44bda..21194d6fe 100644
--- a/linux/drivers/media/video/videobuf-dma-sg.c
+++ b/linux/drivers/media/video/videobuf-dma-sg.c
@@ -81,17 +81,15 @@ struct scatterlist*
videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
{
struct scatterlist *sglist;
- int i = 0;
+ int i;
if (NULL == pages[0])
return NULL;
- sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
+ sglist = kmalloc(nr_pages * sizeof(*sglist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
sg_init_table(sglist, nr_pages);
- if (NULL == pages[0])
- goto nopage;
if (PageHighMem(pages[0]))
/* DMA to highmem pages might not work */
goto highmem;
diff --git a/linux/drivers/media/video/zoran_card.c b/linux/drivers/media/video/zoran_card.c
index 56d8edecc..cc45ae5cd 100644
--- a/linux/drivers/media/video/zoran_card.c
+++ b/linux/drivers/media/video/zoran_card.c
@@ -359,14 +359,6 @@ i2cid_to_modulename (u16 i2c_id)
case I2C_DRIVERID_VPX3220:
name = "vpx3220";
break;
-/* case I2C_DRIVERID_VPX3224:
- name = "vpx3224";
- break;
- case I2C_DRIVERID_MSE3000:
- name = "mse3000";
- break;*/
- default:
- break;
}
return name;
@@ -387,8 +379,6 @@ codecid_to_modulename (u16 codecid)
case CODEC_TYPE_ZR36016:
name = "zr36016";
break;
- default:
- break;
}
return name;
@@ -429,7 +419,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
.type = DC10_old,
.name = "DC10(old)",
.i2c_decoder = I2C_DRIVERID_VPX3220,
- /*.i2c_encoder = I2C_DRIVERID_MSE3000,*/
.video_codec = CODEC_TYPE_ZR36050,
.video_vfe = CODEC_TYPE_ZR36016,
diff --git a/linux/include/linux/i2c-id.h b/linux/include/linux/i2c-id.h
index 580acc939..3db09bc06 100644
--- a/linux/include/linux/i2c-id.h
+++ b/linux/include/linux/i2c-id.h
@@ -33,15 +33,11 @@
#define I2C_DRIVERID_MSP3400 1
#define I2C_DRIVERID_TUNER 2
-#define I2C_DRIVERID_TDA8425 4 /* stereo sound processor */
#define I2C_DRIVERID_TEA6420 5 /* audio matrix switch */
#define I2C_DRIVERID_TEA6415C 6 /* video matrix switch */
#define I2C_DRIVERID_TDA9840 7 /* stereo sound processor */
#define I2C_DRIVERID_SAA7111A 8 /* video input processor */
#define I2C_DRIVERID_SAA7185B 13 /* video encoder */
-#define I2C_DRIVERID_TEA6300 18 /* audio mixer */
-#define I2C_DRIVERID_TDA9850 20 /* audio mixer */
-#define I2C_DRIVERID_TDA9855 21 /* audio mixer */
#define I2C_DRIVERID_SAA7110 22 /* video decoder */
#define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */
#define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */
@@ -50,9 +46,7 @@
#define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */
#define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */
#define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */
-#define I2C_DRIVERID_TDA9873 31 /* TV sound decoder chip */
#define I2C_DRIVERID_TDA9875 32 /* TV sound decoder chip */
-#define I2C_DRIVERID_PIC16C54_PV9 33 /* Audio mux/ir receiver */
#define I2C_DRIVERID_BT819 40 /* video decoder */
#define I2C_DRIVERID_BT856 41 /* video encoder */
#define I2C_DRIVERID_VPX3220 42 /* video decoder+vbi/vtxt */
@@ -63,7 +57,6 @@
#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
#define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */
#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */
-#define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */
#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */
#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */
#define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */
@@ -161,7 +154,6 @@
#define I2C_HW_SMBUS_W9968CF 0x04000d
#define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */
#define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */
-#define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */
#define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */
#define I2C_HW_SMBUS_ALI1563 0x040013