mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (362 commits) V4L-DVB: cx88-dvb: remove extra attribution for core V4L/DVB: v4l: soc_camera: fix bound checking of mbus_fmt[] index V4L/DVB: Add support for SMT7020 to cx88 V4L/DVB: radio-si470x: Use UTF-8 encoding on a comment V4L/DVB: MAINTAINERS: Telegent tlg2300 section fix V4L/DVB: gspca_stv06xx: Add support for camera button V4L/DVB: gspca_ov519: add support for the button on ov511 based cams V4L/DVB: gspca_ov519: Add support for the button on ov518 based cams V4L/DVB: gspca_ov519: add support for the button on ov519 based cams V4L/DVB: gspca_main: Fix a compile error when CONFIG_INPUT is not set V4L/DVB: gspca_main: some input error handling fixes V4L/DVB: gspca_main: Allow use of input device creation code for non int. inputs V4L/DVB: gspca_pac7302: much improved exposure control V4L/DVB: gspca_sonixb: Make sonixb driver handle pas106 and pas202 cameras V4L/DVB: gspca_sonixb: pas106: fixup bright ctrl and add gain and exposure ctrls V4L/DVB: Documentation: gspca.txt: update known mr97310a cams V4L/DVB: gspca_mr97310a: add support for the Sakar 1638x CyberPix V4L/DVB: gscpa_sonixb: limit ov7630 max framerate at 640x480 V4L/DVB: gspca_sonixb: pas202: fixup brightness ctrl and add gain and exposure ctrls V4L/DVB: gscpa_sonixb: Differentiate between sensors with a coarse and fine expo ctrl ...
This commit is contained in:
commit
2b8c70b217
293 changed files with 27854 additions and 4780 deletions
|
|
@ -1,5 +1,5 @@
|
|||
ir-common-objs := ir-functions.o ir-keymaps.o
|
||||
ir-core-objs := ir-keytable.o
|
||||
ir-core-objs := ir-keytable.o ir-sysfs.o
|
||||
|
||||
obj-$(CONFIG_IR_CORE) += ir-core.o
|
||||
obj-$(CONFIG_VIDEO_IR) += ir-common.o
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
|
|||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
|
||||
int ir_type)
|
||||
const u64 ir_type)
|
||||
{
|
||||
ir->ir_type = ir_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -3393,3 +3393,102 @@ struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table);
|
||||
|
||||
|
||||
/* Leadtek Winfast TV USB II Deluxe remote
|
||||
Magnus Alm <magnus.alm@gmail.com>
|
||||
*/
|
||||
static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = {
|
||||
{ 0x62, KEY_0},
|
||||
{ 0x75, KEY_1},
|
||||
{ 0x76, KEY_2},
|
||||
{ 0x77, KEY_3},
|
||||
{ 0x79, KEY_4},
|
||||
{ 0x7a, KEY_5},
|
||||
{ 0x7b, KEY_6},
|
||||
{ 0x7d, KEY_7},
|
||||
{ 0x7e, KEY_8},
|
||||
{ 0x7f, KEY_9},
|
||||
|
||||
{ 0x38, KEY_CAMERA}, /* SNAPSHOT */
|
||||
{ 0x37, KEY_RECORD}, /* RECORD */
|
||||
{ 0x35, KEY_TIME}, /* TIMESHIFT */
|
||||
|
||||
{ 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */
|
||||
{ 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */
|
||||
{ 0x64, KEY_MUTE}, /* MUTE */
|
||||
|
||||
{ 0x21, KEY_CHANNEL}, /* SURF */
|
||||
{ 0x7c, KEY_CHANNELUP}, /* CHANNELUP */
|
||||
{ 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */
|
||||
{ 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */
|
||||
|
||||
{ 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */
|
||||
|
||||
{ 0x70, KEY_POWER2}, /* TV ON/OFF */
|
||||
|
||||
{ 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */
|
||||
{ 0x3a, KEY_NEW}, /* PIP */
|
||||
{ 0x73, KEY_ZOOM}, /* FULLSECREEN */
|
||||
|
||||
{ 0x66, KEY_INFO}, /* OSD (DISPLAY) */
|
||||
|
||||
{ 0x31, KEY_DOT}, /* '.' */
|
||||
{ 0x63, KEY_ENTER}, /* ENTER */
|
||||
|
||||
};
|
||||
struct ir_scancode_table ir_codes_winfast_usbii_deluxe_table = {
|
||||
.scan = ir_codes_winfast_usbii_deluxe,
|
||||
.size = ARRAY_SIZE(ir_codes_winfast_usbii_deluxe),
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ir_codes_winfast_usbii_deluxe_table);
|
||||
|
||||
/* Kworld 315U
|
||||
*/
|
||||
static struct ir_scancode ir_codes_kworld_315u[] = {
|
||||
{ 0x6143, KEY_POWER },
|
||||
{ 0x6101, KEY_TUNER }, /* source */
|
||||
{ 0x610b, KEY_ZOOM },
|
||||
{ 0x6103, KEY_POWER2 }, /* shutdown */
|
||||
|
||||
{ 0x6104, KEY_1 },
|
||||
{ 0x6108, KEY_2 },
|
||||
{ 0x6102, KEY_3 },
|
||||
{ 0x6109, KEY_CHANNELUP },
|
||||
|
||||
{ 0x610f, KEY_4 },
|
||||
{ 0x6105, KEY_5 },
|
||||
{ 0x6106, KEY_6 },
|
||||
{ 0x6107, KEY_CHANNELDOWN },
|
||||
|
||||
{ 0x610c, KEY_7 },
|
||||
{ 0x610d, KEY_8 },
|
||||
{ 0x610a, KEY_9 },
|
||||
{ 0x610e, KEY_VOLUMEUP },
|
||||
|
||||
{ 0x6110, KEY_LAST },
|
||||
{ 0x6111, KEY_0 },
|
||||
{ 0x6112, KEY_ENTER },
|
||||
{ 0x6113, KEY_VOLUMEDOWN },
|
||||
|
||||
{ 0x6114, KEY_RECORD },
|
||||
{ 0x6115, KEY_STOP },
|
||||
{ 0x6116, KEY_PLAY },
|
||||
{ 0x6117, KEY_MUTE },
|
||||
|
||||
{ 0x6118, KEY_UP },
|
||||
{ 0x6119, KEY_DOWN },
|
||||
{ 0x611a, KEY_LEFT },
|
||||
{ 0x611b, KEY_RIGHT },
|
||||
|
||||
{ 0x611c, KEY_RED },
|
||||
{ 0x611d, KEY_GREEN },
|
||||
{ 0x611e, KEY_YELLOW },
|
||||
{ 0x611f, KEY_BLUE },
|
||||
};
|
||||
|
||||
struct ir_scancode_table ir_codes_kworld_315u_table = {
|
||||
.scan = ir_codes_kworld_315u,
|
||||
.size = ARRAY_SIZE(ir_codes_kworld_315u),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ir_codes_kworld_315u_table);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ exit:
|
|||
* In order to reduce the quantity of table resizes, it has a minimum
|
||||
* table size of IR_TAB_MIN_SIZE.
|
||||
*/
|
||||
int ir_roundup_tablesize(int n_elems)
|
||||
static int ir_roundup_tablesize(int n_elems)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
|
|
@ -81,7 +81,6 @@ int ir_roundup_tablesize(int n_elems)
|
|||
|
||||
return n_elems;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_roundup_tablesize);
|
||||
|
||||
/**
|
||||
* ir_copy_table() - copies a keytable, discarding the unused entries
|
||||
|
|
@ -89,9 +88,11 @@ EXPORT_SYMBOL_GPL(ir_roundup_tablesize);
|
|||
* @origin: origin table
|
||||
*
|
||||
* Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
|
||||
* Also copies table size and table protocol.
|
||||
* NOTE: It shouldn't copy the lock field
|
||||
*/
|
||||
|
||||
int ir_copy_table(struct ir_scancode_table *destin,
|
||||
static int ir_copy_table(struct ir_scancode_table *destin,
|
||||
const struct ir_scancode_table *origin)
|
||||
{
|
||||
int i, j = 0;
|
||||
|
|
@ -105,12 +106,12 @@ int ir_copy_table(struct ir_scancode_table *destin,
|
|||
j++;
|
||||
}
|
||||
destin->size = j;
|
||||
destin->ir_type = origin->ir_type;
|
||||
|
||||
IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_copy_table);
|
||||
|
||||
/**
|
||||
* ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
|
||||
|
|
@ -184,18 +185,14 @@ static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem)
|
|||
int newsize = rc_tab->size - 1;
|
||||
int resize = ir_is_resize_needed(rc_tab, newsize);
|
||||
struct ir_scancode *oldkeymap = rc_tab->scan;
|
||||
struct ir_scancode *newkeymap;
|
||||
struct ir_scancode *newkeymap = NULL;
|
||||
|
||||
if (resize) {
|
||||
if (resize)
|
||||
newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
|
||||
sizeof(*newkeymap), GFP_ATOMIC);
|
||||
|
||||
/* There's no memory for resize. Keep the old table */
|
||||
if (!newkeymap)
|
||||
resize = 0;
|
||||
}
|
||||
|
||||
if (!resize) {
|
||||
/* There's no memory for resize. Keep the old table */
|
||||
if (!resize || !newkeymap) {
|
||||
newkeymap = oldkeymap;
|
||||
|
||||
/* We'll modify the live table. Lock it */
|
||||
|
|
@ -399,12 +396,14 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
|
|||
* @input_dev: the struct input_dev descriptor of the device
|
||||
* @rc_tab: the struct ir_scancode_table table of scancode/keymap
|
||||
*
|
||||
* This routine is used to initialize the input infrastructure to work with
|
||||
* an IR.
|
||||
* It should be called before registering the IR device.
|
||||
* This routine is used to initialize the input infrastructure
|
||||
* to work with an IR.
|
||||
* It will register the input/evdev interface for the device and
|
||||
* register the syfs code for IR class
|
||||
*/
|
||||
int ir_input_register(struct input_dev *input_dev,
|
||||
struct ir_scancode_table *rc_tab)
|
||||
const struct ir_scancode_table *rc_tab,
|
||||
const struct ir_dev_props *props)
|
||||
{
|
||||
struct ir_input_dev *ir_dev;
|
||||
struct ir_scancode *keymap = rc_tab->scan;
|
||||
|
|
@ -417,19 +416,22 @@ int ir_input_register(struct input_dev *input_dev,
|
|||
if (!ir_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&rc_tab->lock);
|
||||
spin_lock_init(&ir_dev->rc_tab.lock);
|
||||
|
||||
ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size);
|
||||
ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size *
|
||||
sizeof(struct ir_scancode), GFP_KERNEL);
|
||||
if (!ir_dev->rc_tab.scan)
|
||||
if (!ir_dev->rc_tab.scan) {
|
||||
kfree(ir_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
|
||||
ir_dev->rc_tab.size,
|
||||
ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan));
|
||||
|
||||
ir_copy_table(&ir_dev->rc_tab, rc_tab);
|
||||
ir_dev->props = props;
|
||||
|
||||
/* set the bits for the keys */
|
||||
IR_dprintk(1, "key map size: %d\n", rc_tab->size);
|
||||
|
|
@ -447,16 +449,31 @@ int ir_input_register(struct input_dev *input_dev,
|
|||
input_set_drvdata(input_dev, ir_dev);
|
||||
|
||||
rc = input_register_device(input_dev);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
rc = ir_register_class(input_dev);
|
||||
if (rc < 0) {
|
||||
kfree(rc_tab->scan);
|
||||
kfree(ir_dev);
|
||||
input_set_drvdata(input_dev, NULL);
|
||||
input_unregister_device(input_dev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree(rc_tab->scan);
|
||||
kfree(ir_dev);
|
||||
input_set_drvdata(input_dev, NULL);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_input_register);
|
||||
|
||||
/**
|
||||
* ir_input_unregister() - unregisters IR and frees resources
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
||||
* This routine is used to free memory and de-register interfaces.
|
||||
*/
|
||||
void ir_input_unregister(struct input_dev *dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
|
||||
|
|
@ -472,6 +489,8 @@ void ir_input_unregister(struct input_dev *dev)
|
|||
kfree(rc_tab->scan);
|
||||
rc_tab->scan = NULL;
|
||||
|
||||
ir_unregister_class(dev);
|
||||
|
||||
kfree(ir_dev);
|
||||
input_unregister_device(dev);
|
||||
}
|
||||
|
|
|
|||
211
drivers/media/IR/ir-sysfs.c
Normal file
211
drivers/media/IR/ir-sysfs.c
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/* ir-register.c - handle IR scancode->keycode tables
|
||||
*
|
||||
* Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/device.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#define IRRCV_NUM_DEVICES 256
|
||||
|
||||
/* bit array to represent IR sysfs device number */
|
||||
static unsigned long ir_core_dev_number;
|
||||
|
||||
/* class for /sys/class/irrcv */
|
||||
static struct class *ir_input_class;
|
||||
|
||||
/**
|
||||
* show_protocol() - shows the current IR protocol
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the output buffer
|
||||
*
|
||||
* This routine is a callback routine for input read the IR protocol type.
|
||||
* it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol.
|
||||
* It returns the protocol name, as understood by the driver.
|
||||
*/
|
||||
static ssize_t show_protocol(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
char *s;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 ir_type = ir_dev->rc_tab.ir_type;
|
||||
|
||||
IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type);
|
||||
|
||||
/* FIXME: doesn't support multiple protocols at the same time */
|
||||
if (ir_type == IR_TYPE_UNKNOWN)
|
||||
s = "Unknown";
|
||||
else if (ir_type == IR_TYPE_RC5)
|
||||
s = "RC-5";
|
||||
else if (ir_type == IR_TYPE_PD)
|
||||
s = "Pulse/distance";
|
||||
else if (ir_type == IR_TYPE_NEC)
|
||||
s = "NEC";
|
||||
else
|
||||
s = "Other";
|
||||
|
||||
return sprintf(buf, "%s\n", s);
|
||||
}
|
||||
|
||||
/**
|
||||
* store_protocol() - shows the current IR protocol
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the input buffer
|
||||
* @len: length of the input buffer
|
||||
*
|
||||
* This routine is a callback routine for changing the IR protocol type.
|
||||
* it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol.
|
||||
* It changes the IR the protocol name, if the IR type is recognized
|
||||
* by the driver.
|
||||
* If an unknown protocol name is used, returns -EINVAL.
|
||||
*/
|
||||
static ssize_t store_protocol(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *data,
|
||||
size_t len)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 ir_type = IR_TYPE_UNKNOWN;
|
||||
int rc = -EINVAL;
|
||||
unsigned long flags;
|
||||
char *buf;
|
||||
|
||||
buf = strsep((char **) &data, "\n");
|
||||
|
||||
if (!strcasecmp(buf, "rc-5"))
|
||||
ir_type = IR_TYPE_RC5;
|
||||
else if (!strcasecmp(buf, "pd"))
|
||||
ir_type = IR_TYPE_PD;
|
||||
else if (!strcasecmp(buf, "nec"))
|
||||
ir_type = IR_TYPE_NEC;
|
||||
|
||||
if (ir_type == IR_TYPE_UNKNOWN) {
|
||||
IR_dprintk(1, "Error setting protocol to %lld\n",
|
||||
(long long)ir_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->change_protocol)
|
||||
rc = ir_dev->props->change_protocol(ir_dev->props->priv,
|
||||
ir_type);
|
||||
|
||||
if (rc < 0) {
|
||||
IR_dprintk(1, "Error setting protocol to %lld\n",
|
||||
(long long)ir_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
|
||||
ir_dev->rc_tab.ir_type = ir_type;
|
||||
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
|
||||
|
||||
IR_dprintk(1, "Current protocol is %lld\n",
|
||||
(long long)ir_type);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Static device attribute struct with the sysfs attributes for IR's
|
||||
*/
|
||||
static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR,
|
||||
show_protocol, store_protocol);
|
||||
|
||||
static struct attribute *ir_dev_attrs[] = {
|
||||
&dev_attr_current_protocol.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv?
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
*
|
||||
* This routine is used to register the syfs code for IR class
|
||||
*/
|
||||
int ir_register_class(struct input_dev *input_dev)
|
||||
{
|
||||
int rc;
|
||||
struct kobject *kobj;
|
||||
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
int devno = find_first_zero_bit(&ir_core_dev_number,
|
||||
IRRCV_NUM_DEVICES);
|
||||
|
||||
if (unlikely(devno < 0))
|
||||
return devno;
|
||||
|
||||
ir_dev->attr.attrs = ir_dev_attrs;
|
||||
ir_dev->class_dev = device_create(ir_input_class, NULL,
|
||||
input_dev->dev.devt, ir_dev,
|
||||
"irrcv%d", devno);
|
||||
kobj = &ir_dev->class_dev->kobj;
|
||||
|
||||
printk(KERN_WARNING "Creating IR device %s\n", kobject_name(kobj));
|
||||
rc = sysfs_create_group(kobj, &ir_dev->attr);
|
||||
if (unlikely(rc < 0)) {
|
||||
device_destroy(ir_input_class, input_dev->dev.devt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ir_dev->devno = devno;
|
||||
set_bit(devno, &ir_core_dev_number);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_unregister_class() - removes the sysfs for sysfs for
|
||||
* /sys/class/irrcv/irrcv?
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
*
|
||||
* This routine is used to unregister the syfs code for IR class
|
||||
*/
|
||||
void ir_unregister_class(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct kobject *kobj;
|
||||
|
||||
clear_bit(ir_dev->devno, &ir_core_dev_number);
|
||||
|
||||
kobj = &ir_dev->class_dev->kobj;
|
||||
|
||||
sysfs_remove_group(kobj, &ir_dev->attr);
|
||||
device_destroy(ir_input_class, input_dev->dev.devt);
|
||||
|
||||
kfree(ir_dev->attr.name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init/exit code for the module. Basically, creates/removes /sys/class/irrcv
|
||||
*/
|
||||
|
||||
static int __init ir_core_init(void)
|
||||
{
|
||||
ir_input_class = class_create(THIS_MODULE, "irrcv");
|
||||
if (IS_ERR(ir_input_class)) {
|
||||
printk(KERN_ERR "ir_core: unable to register irrcv class\n");
|
||||
return PTR_ERR(ir_input_class);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ir_core_exit(void)
|
||||
{
|
||||
class_destroy(ir_input_class);
|
||||
}
|
||||
|
||||
module_init(ir_core_init);
|
||||
module_exit(ir_core_exit);
|
||||
|
|
@ -423,14 +423,15 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
|
|||
}
|
||||
}
|
||||
|
||||
int saa7146_vv_devinit(struct saa7146_dev *dev)
|
||||
{
|
||||
return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(saa7146_vv_devinit);
|
||||
|
||||
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
|
||||
{
|
||||
struct saa7146_vv *vv;
|
||||
int err;
|
||||
|
||||
err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
|
||||
if (vv == NULL) {
|
||||
|
|
|
|||
|
|
@ -1337,6 +1337,22 @@ static struct tuner_params tuner_philips_cu1216l_params[] = {
|
|||
},
|
||||
};
|
||||
|
||||
/* ---------------------- TUNER_SONY_BTF_PXN01Z ------------------------ */
|
||||
|
||||
static struct tuner_range tuner_sony_btf_pxn01z_ranges[] = {
|
||||
{ 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
|
||||
{ 16 * 367.25 /*MHz*/, 0x8e, 0x02, },
|
||||
{ 16 * 999.99 , 0x8e, 0x04, },
|
||||
};
|
||||
|
||||
static struct tuner_params tuner_sony_btf_pxn01z_params[] = {
|
||||
{
|
||||
.type = TUNER_PARAM_TYPE_NTSC,
|
||||
.ranges = tuner_sony_btf_pxn01z_ranges,
|
||||
.count = ARRAY_SIZE(tuner_sony_btf_pxn01z_ranges),
|
||||
},
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
struct tunertype tuners[] = {
|
||||
|
|
@ -1805,6 +1821,11 @@ struct tunertype tuners[] = {
|
|||
.name = "NXP TDA18271",
|
||||
/* see tda18271-fe.c for details */
|
||||
},
|
||||
[TUNER_SONY_BTF_PXN01Z] = {
|
||||
.name = "Sony BTF-Pxn01Z",
|
||||
.params = tuner_sony_btf_pxn01z_params,
|
||||
.count = ARRAY_SIZE(tuner_sony_btf_pxn01z_params),
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(tuners);
|
||||
|
||||
|
|
|
|||
|
|
@ -917,30 +917,68 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
|
|||
* that xc2028 will be in a safe state.
|
||||
* Maybe this might also be needed for DTV.
|
||||
*/
|
||||
if (new_mode == T_ANALOG_TV)
|
||||
if (new_mode == T_ANALOG_TV) {
|
||||
rc = send_seq(priv, {0x00, 0x00});
|
||||
|
||||
/*
|
||||
* Digital modes require an offset to adjust to the
|
||||
* proper frequency.
|
||||
* Analog modes require offset = 0
|
||||
*/
|
||||
if (new_mode == T_DIGITAL_TV) {
|
||||
/* Sets the offset according with firmware */
|
||||
/* Analog modes require offset = 0 */
|
||||
} else {
|
||||
/*
|
||||
* Digital modes require an offset to adjust to the
|
||||
* proper frequency. The offset depends on what
|
||||
* firmware version is used.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Adjust to the center frequency. This is calculated by the
|
||||
* formula: offset = 1.25MHz - BW/2
|
||||
* For DTV 7/8, the firmware uses BW = 8000, so it needs a
|
||||
* further adjustment to get the frequency center on VHF
|
||||
*/
|
||||
if (priv->cur_fw.type & DTV6)
|
||||
offset = 1750000;
|
||||
else if (priv->cur_fw.type & DTV7)
|
||||
offset = 2250000;
|
||||
else /* DTV8 or DTV78 */
|
||||
offset = 2750000;
|
||||
|
||||
/*
|
||||
* We must adjust the offset by 500kHz when
|
||||
* tuning a 7MHz VHF channel with DTV78 firmware
|
||||
* (used in Australia, Italy and Germany)
|
||||
*/
|
||||
if ((priv->cur_fw.type & DTV78) && freq < 470000000)
|
||||
offset -= 500000;
|
||||
|
||||
/*
|
||||
* xc3028 additional "magic"
|
||||
* Depending on the firmware version, it needs some adjustments
|
||||
* to properly centralize the frequency. This seems to be
|
||||
* needed to compensate the SCODE table adjustments made by
|
||||
* newer firmwares
|
||||
*/
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* The proper adjustment would be to do it at s-code table.
|
||||
* However, this didn't work, as reported by
|
||||
* Robert Lowery <rglowery@exemail.com.au>
|
||||
*/
|
||||
|
||||
if (priv->cur_fw.type & DTV7)
|
||||
offset += 500000;
|
||||
|
||||
#else
|
||||
/*
|
||||
* Still need tests for XC3028L (firmware 3.2 or upper)
|
||||
* So, for now, let's just comment the per-firmware
|
||||
* version of this change. Reports with xc3028l working
|
||||
* with and without the lines bellow are welcome
|
||||
*/
|
||||
|
||||
if (priv->firm_version < 0x0302) {
|
||||
if (priv->cur_fw.type & DTV7)
|
||||
offset += 500000;
|
||||
} else {
|
||||
if (priv->cur_fw.type & DTV7)
|
||||
offset -= 300000;
|
||||
else if (type != ATSC) /* DVB @6MHz, DTV 8 and DTV 7/8 */
|
||||
offset += 200000;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
div = (freq - offset + DIV / 2) / DIV;
|
||||
|
|
@ -1097,17 +1135,24 @@ static int xc2028_set_params(struct dvb_frontend *fe,
|
|||
|
||||
/* All S-code tables need a 200kHz shift */
|
||||
if (priv->ctrl.demod) {
|
||||
demod = priv->ctrl.demod + 200;
|
||||
demod = priv->ctrl.demod;
|
||||
|
||||
/*
|
||||
* Newer firmwares require a 200 kHz offset only for ATSC
|
||||
*/
|
||||
if (type == ATSC || priv->firm_version < 0x0302)
|
||||
demod += 200;
|
||||
/*
|
||||
* The DTV7 S-code table needs a 700 kHz shift.
|
||||
* Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this
|
||||
*
|
||||
* DTV7 is only used in Australia. Germany or Italy may also
|
||||
* use this firmware after initialization, but a tune to a UHF
|
||||
* channel should then cause DTV78 to be used.
|
||||
*
|
||||
* Unfortunately, on real-field tests, the s-code offset
|
||||
* didn't work as expected, as reported by
|
||||
* Robert Lowery <rglowery@exemail.com.au>
|
||||
*/
|
||||
if (type & DTV7)
|
||||
demod += 500;
|
||||
}
|
||||
|
||||
return generic_set_freq(fe, p->frequency,
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ comment "Supported Mantis Adapters"
|
|||
depends on DVB_CORE && PCI && I2C
|
||||
source "drivers/media/dvb/mantis/Kconfig"
|
||||
|
||||
comment "Supported nGene Adapters"
|
||||
depends on DVB_CORE && PCI && I2C
|
||||
source "drivers/media/dvb/ngene/Kconfig"
|
||||
|
||||
comment "Supported DVB Frontends"
|
||||
depends on DVB_CORE
|
||||
source "drivers/media/dvb/frontends/Kconfig"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ obj-y := dvb-core/ \
|
|||
siano/ \
|
||||
dm1105/ \
|
||||
pt1/ \
|
||||
mantis/
|
||||
mantis/ \
|
||||
ngene/
|
||||
|
||||
obj-$(CONFIG_DVB_FIREDTV) += firewire/
|
||||
|
|
|
|||
|
|
@ -576,43 +576,30 @@ static struct pci_driver bt878_pci_driver = {
|
|||
.remove = __devexit_p(bt878_remove),
|
||||
};
|
||||
|
||||
static int bt878_pci_driver_registered;
|
||||
|
||||
/*******************************/
|
||||
/* Module management functions */
|
||||
/*******************************/
|
||||
|
||||
static int bt878_init_module(void)
|
||||
static int __init bt878_init_module(void)
|
||||
{
|
||||
bt878_num = 0;
|
||||
bt878_pci_driver_registered = 0;
|
||||
|
||||
printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n",
|
||||
(BT878_VERSION_CODE >> 16) & 0xff,
|
||||
(BT878_VERSION_CODE >> 8) & 0xff,
|
||||
BT878_VERSION_CODE & 0xff);
|
||||
/*
|
||||
bt878_check_chipset();
|
||||
*/
|
||||
/* later we register inside of bt878_find_audio_dma()
|
||||
* because we may want to ignore certain cards */
|
||||
bt878_pci_driver_registered = 1;
|
||||
|
||||
return pci_register_driver(&bt878_pci_driver);
|
||||
}
|
||||
|
||||
static void bt878_cleanup_module(void)
|
||||
static void __exit bt878_cleanup_module(void)
|
||||
{
|
||||
if (bt878_pci_driver_registered) {
|
||||
bt878_pci_driver_registered = 0;
|
||||
pci_unregister_driver(&bt878_pci_driver);
|
||||
}
|
||||
return;
|
||||
pci_unregister_driver(&bt878_pci_driver);
|
||||
}
|
||||
|
||||
module_init(bt878_init_module);
|
||||
module_exit(bt878_cleanup_module);
|
||||
|
||||
//MODULE_AUTHOR("XXX");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1352,8 +1352,7 @@ static int dst_get_tuna(struct dst_state *state)
|
|||
return retval;
|
||||
}
|
||||
if ((state->type_flags & DST_TYPE_HAS_VLF) &&
|
||||
!(state->dst_type == DST_TYPE_IS_CABLE) &&
|
||||
!(state->dst_type == DST_TYPE_IS_ATSC)) {
|
||||
!(state->dst_type == DST_TYPE_IS_ATSC)) {
|
||||
|
||||
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
|
||||
dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
|
||||
|
|
@ -1820,8 +1819,13 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
|
|||
.frequency_max = 858000000,
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 45000000,
|
||||
/* . symbol_rate_tolerance = ???,*/
|
||||
.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO
|
||||
.caps = FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QAM_AUTO |
|
||||
FE_CAN_QAM_16 |
|
||||
FE_CAN_QAM_32 |
|
||||
FE_CAN_QAM_64 |
|
||||
FE_CAN_QAM_128 |
|
||||
FE_CAN_QAM_256
|
||||
},
|
||||
|
||||
.release = dst_release,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ config DVB_DM1105
|
|||
select DVB_STB6000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_CX24116 if !DVB_FE_CUSTOMISE
|
||||
select DVB_SI21XX if !DVB_FE_CUSTOMISE
|
||||
select DVB_DS3000 if !DVB_FE_CUSTOMISE
|
||||
select VIDEO_IR
|
||||
help
|
||||
Support for cards based on the SDMC DM1105 PCI chip like
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "si21xx.h"
|
||||
#include "cx24116.h"
|
||||
#include "z0194a.h"
|
||||
#include "ds3000.h"
|
||||
|
||||
#define UNSET (-1U)
|
||||
|
||||
|
|
@ -269,7 +270,7 @@ struct infrared {
|
|||
u32 ir_command;
|
||||
};
|
||||
|
||||
struct dm1105dvb {
|
||||
struct dm1105_dev {
|
||||
/* pci */
|
||||
struct pci_dev *pdev;
|
||||
u8 __iomem *io_mem;
|
||||
|
|
@ -308,31 +309,47 @@ struct dm1105dvb {
|
|||
spinlock_t lock;
|
||||
};
|
||||
|
||||
#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
|
||||
#define dm_io_mem(reg) ((unsigned long)(&dev->io_mem[reg]))
|
||||
|
||||
#define dm_readb(reg) inb(dm_io_mem(reg))
|
||||
#define dm_writeb(reg, value) outb((value), (dm_io_mem(reg)))
|
||||
|
||||
#define dm_readw(reg) inw(dm_io_mem(reg))
|
||||
#define dm_writew(reg, value) outw((value), (dm_io_mem(reg)))
|
||||
|
||||
#define dm_readl(reg) inl(dm_io_mem(reg))
|
||||
#define dm_writel(reg, value) outl((value), (dm_io_mem(reg)))
|
||||
|
||||
#define dm_andorl(reg, mask, value) \
|
||||
outl((inl(dm_io_mem(reg)) & ~(mask)) |\
|
||||
((value) & (mask)), (dm_io_mem(reg)))
|
||||
|
||||
#define dm_setl(reg, bit) dm_andorl((reg), (bit), (bit))
|
||||
#define dm_clearl(reg, bit) dm_andorl((reg), (bit), 0)
|
||||
|
||||
static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb ;
|
||||
struct dm1105_dev *dev ;
|
||||
|
||||
int addr, rc, i, j, k, len, byte, data;
|
||||
u8 status;
|
||||
|
||||
dm1105dvb = i2c_adap->algo_data;
|
||||
dev = i2c_adap->algo_data;
|
||||
for (i = 0; i < num; i++) {
|
||||
outb(0x00, dm_io_mem(DM1105_I2CCTR));
|
||||
dm_writeb(DM1105_I2CCTR, 0x00);
|
||||
if (msgs[i].flags & I2C_M_RD) {
|
||||
/* read bytes */
|
||||
addr = msgs[i].addr << 1;
|
||||
addr |= 1;
|
||||
outb(addr, dm_io_mem(DM1105_I2CDAT));
|
||||
dm_writeb(DM1105_I2CDAT, addr);
|
||||
for (byte = 0; byte < msgs[i].len; byte++)
|
||||
outb(0, dm_io_mem(DM1105_I2CDAT + byte + 1));
|
||||
dm_writeb(DM1105_I2CDAT + byte + 1, 0);
|
||||
|
||||
outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
|
||||
dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
|
||||
for (j = 0; j < 55; j++) {
|
||||
mdelay(10);
|
||||
status = inb(dm_io_mem(DM1105_I2CSTS));
|
||||
status = dm_readb(DM1105_I2CSTS);
|
||||
if ((status & 0xc0) == 0x40)
|
||||
break;
|
||||
}
|
||||
|
|
@ -340,56 +357,54 @@ static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
|
|||
return -1;
|
||||
|
||||
for (byte = 0; byte < msgs[i].len; byte++) {
|
||||
rc = inb(dm_io_mem(DM1105_I2CDAT + byte + 1));
|
||||
rc = dm_readb(DM1105_I2CDAT + byte + 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
msgs[i].buf[byte] = rc;
|
||||
}
|
||||
} else {
|
||||
if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
|
||||
/* prepaired for cx24116 firmware */
|
||||
/* Write in small blocks */
|
||||
len = msgs[i].len - 1;
|
||||
k = 1;
|
||||
do {
|
||||
outb(msgs[i].addr << 1, dm_io_mem(DM1105_I2CDAT));
|
||||
outb(0xf7, dm_io_mem(DM1105_I2CDAT + 1));
|
||||
for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
|
||||
data = msgs[i].buf[k+byte];
|
||||
outb(data, dm_io_mem(DM1105_I2CDAT + byte + 2));
|
||||
}
|
||||
outb(0x82 + (len > 48 ? 48 : len), dm_io_mem(DM1105_I2CCTR));
|
||||
for (j = 0; j < 25; j++) {
|
||||
mdelay(10);
|
||||
status = inb(dm_io_mem(DM1105_I2CSTS));
|
||||
if ((status & 0xc0) == 0x40)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= 25)
|
||||
return -1;
|
||||
|
||||
k += 48;
|
||||
len -= 48;
|
||||
} while (len > 0);
|
||||
} else {
|
||||
/* write bytes */
|
||||
outb(msgs[i].addr<<1, dm_io_mem(DM1105_I2CDAT));
|
||||
for (byte = 0; byte < msgs[i].len; byte++) {
|
||||
data = msgs[i].buf[byte];
|
||||
outb(data, dm_io_mem(DM1105_I2CDAT + byte + 1));
|
||||
} else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
|
||||
/* prepaired for cx24116 firmware */
|
||||
/* Write in small blocks */
|
||||
len = msgs[i].len - 1;
|
||||
k = 1;
|
||||
do {
|
||||
dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
|
||||
dm_writeb(DM1105_I2CDAT + 1, 0xf7);
|
||||
for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
|
||||
data = msgs[i].buf[k + byte];
|
||||
dm_writeb(DM1105_I2CDAT + byte + 2, data);
|
||||
}
|
||||
outb(0x81 + msgs[i].len, dm_io_mem(DM1105_I2CCTR));
|
||||
dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len));
|
||||
for (j = 0; j < 25; j++) {
|
||||
mdelay(10);
|
||||
status = inb(dm_io_mem(DM1105_I2CSTS));
|
||||
status = dm_readb(DM1105_I2CSTS);
|
||||
if ((status & 0xc0) == 0x40)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= 25)
|
||||
return -1;
|
||||
|
||||
k += 48;
|
||||
len -= 48;
|
||||
} while (len > 0);
|
||||
} else {
|
||||
/* write bytes */
|
||||
dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
|
||||
for (byte = 0; byte < msgs[i].len; byte++) {
|
||||
data = msgs[i].buf[byte];
|
||||
dm_writeb(DM1105_I2CDAT + byte + 1, data);
|
||||
}
|
||||
dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
|
||||
for (j = 0; j < 25; j++) {
|
||||
mdelay(10);
|
||||
status = dm_readb(DM1105_I2CSTS);
|
||||
if ((status & 0xc0) == 0x40)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= 25)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
|
|
@ -407,22 +422,22 @@ static struct i2c_algorithm dm1105_algo = {
|
|||
.functionality = functionality,
|
||||
};
|
||||
|
||||
static inline struct dm1105dvb *feed_to_dm1105dvb(struct dvb_demux_feed *feed)
|
||||
static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed)
|
||||
{
|
||||
return container_of(feed->demux, struct dm1105dvb, demux);
|
||||
return container_of(feed->demux, struct dm1105_dev, demux);
|
||||
}
|
||||
|
||||
static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe)
|
||||
static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe)
|
||||
{
|
||||
return container_of(fe->dvb, struct dm1105dvb, dvb_adapter);
|
||||
return container_of(fe->dvb, struct dm1105_dev, dvb_adapter);
|
||||
}
|
||||
|
||||
static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe);
|
||||
struct dm1105_dev *dev = frontend_to_dm1105_dev(fe);
|
||||
u32 lnb_mask, lnb_13v, lnb_18v, lnb_off;
|
||||
|
||||
switch (dm1105dvb->boardnr) {
|
||||
switch (dev->boardnr) {
|
||||
case DM1105_BOARD_AXESS_DM05:
|
||||
lnb_mask = DM05_LNB_MASK;
|
||||
lnb_off = DM05_LNB_OFF;
|
||||
|
|
@ -438,62 +453,67 @@ static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volta
|
|||
lnb_18v = DM1105_LNB_18V;
|
||||
}
|
||||
|
||||
outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR));
|
||||
dm_writel(DM1105_GPIOCTR, lnb_mask);
|
||||
if (voltage == SEC_VOLTAGE_18)
|
||||
outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL));
|
||||
dm_writel(DM1105_GPIOVAL, lnb_18v);
|
||||
else if (voltage == SEC_VOLTAGE_13)
|
||||
outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL));
|
||||
dm_writel(DM1105_GPIOVAL, lnb_13v);
|
||||
else
|
||||
outl(lnb_off, dm_io_mem(DM1105_GPIOVAL));
|
||||
dm_writel(DM1105_GPIOVAL, lnb_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dm1105dvb_set_dma_addr(struct dm1105dvb *dm1105dvb)
|
||||
static void dm1105_set_dma_addr(struct dm1105_dev *dev)
|
||||
{
|
||||
outl(cpu_to_le32(dm1105dvb->dma_addr), dm_io_mem(DM1105_STADR));
|
||||
dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr));
|
||||
}
|
||||
|
||||
static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
|
||||
static int __devinit dm1105_dma_map(struct dm1105_dev *dev)
|
||||
{
|
||||
dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
|
||||
dev->ts_buf = pci_alloc_consistent(dev->pdev,
|
||||
6 * DM1105_DMA_BYTES,
|
||||
&dev->dma_addr);
|
||||
|
||||
return !dm1105dvb->ts_buf;
|
||||
return !dev->ts_buf;
|
||||
}
|
||||
|
||||
static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)
|
||||
static void dm1105_dma_unmap(struct dm1105_dev *dev)
|
||||
{
|
||||
pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr);
|
||||
pci_free_consistent(dev->pdev,
|
||||
6 * DM1105_DMA_BYTES,
|
||||
dev->ts_buf,
|
||||
dev->dma_addr);
|
||||
}
|
||||
|
||||
static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb)
|
||||
static void dm1105_enable_irqs(struct dm1105_dev *dev)
|
||||
{
|
||||
outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK));
|
||||
outb(1, dm_io_mem(DM1105_CR));
|
||||
dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK);
|
||||
dm_writeb(DM1105_CR, 1);
|
||||
}
|
||||
|
||||
static void dm1105dvb_disable_irqs(struct dm1105dvb *dm1105dvb)
|
||||
static void dm1105_disable_irqs(struct dm1105_dev *dev)
|
||||
{
|
||||
outb(INTMAK_IRM, dm_io_mem(DM1105_INTMAK));
|
||||
outb(0, dm_io_mem(DM1105_CR));
|
||||
dm_writeb(DM1105_INTMAK, INTMAK_IRM);
|
||||
dm_writeb(DM1105_CR, 0);
|
||||
}
|
||||
|
||||
static int dm1105dvb_start_feed(struct dvb_demux_feed *f)
|
||||
static int dm1105_start_feed(struct dvb_demux_feed *f)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
|
||||
struct dm1105_dev *dev = feed_to_dm1105_dev(f);
|
||||
|
||||
if (dm1105dvb->full_ts_users++ == 0)
|
||||
dm1105dvb_enable_irqs(dm1105dvb);
|
||||
if (dev->full_ts_users++ == 0)
|
||||
dm1105_enable_irqs(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
|
||||
static int dm1105_stop_feed(struct dvb_demux_feed *f)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb = feed_to_dm1105dvb(f);
|
||||
struct dm1105_dev *dev = feed_to_dm1105_dev(f);
|
||||
|
||||
if (--dm1105dvb->full_ts_users == 0)
|
||||
dm1105dvb_disable_irqs(dm1105dvb);
|
||||
if (--dev->full_ts_users == 0)
|
||||
dm1105_disable_irqs(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -517,68 +537,64 @@ static void dm1105_emit_key(struct work_struct *work)
|
|||
/* work handler */
|
||||
static void dm1105_dmx_buffer(struct work_struct *work)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb =
|
||||
container_of(work, struct dm1105dvb, work);
|
||||
struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work);
|
||||
unsigned int nbpackets;
|
||||
u32 oldwrp = dm1105dvb->wrp;
|
||||
u32 nextwrp = dm1105dvb->nextwrp;
|
||||
u32 oldwrp = dev->wrp;
|
||||
u32 nextwrp = dev->nextwrp;
|
||||
|
||||
if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
|
||||
(dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
|
||||
(dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
|
||||
dm1105dvb->PacketErrorCount++;
|
||||
if (!((dev->ts_buf[oldwrp] == 0x47) &&
|
||||
(dev->ts_buf[oldwrp + 188] == 0x47) &&
|
||||
(dev->ts_buf[oldwrp + 188 * 2] == 0x47))) {
|
||||
dev->PacketErrorCount++;
|
||||
/* bad packet found */
|
||||
if ((dm1105dvb->PacketErrorCount >= 2) &&
|
||||
(dm1105dvb->dmarst == 0)) {
|
||||
outb(1, dm_io_mem(DM1105_RST));
|
||||
dm1105dvb->wrp = 0;
|
||||
dm1105dvb->PacketErrorCount = 0;
|
||||
dm1105dvb->dmarst = 0;
|
||||
if ((dev->PacketErrorCount >= 2) &&
|
||||
(dev->dmarst == 0)) {
|
||||
dm_writeb(DM1105_RST, 1);
|
||||
dev->wrp = 0;
|
||||
dev->PacketErrorCount = 0;
|
||||
dev->dmarst = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextwrp < oldwrp) {
|
||||
memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
|
||||
dm1105dvb->ts_buf, nextwrp);
|
||||
nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
|
||||
memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp);
|
||||
nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188;
|
||||
} else
|
||||
nbpackets = (nextwrp - oldwrp) / 188;
|
||||
|
||||
dm1105dvb->wrp = nextwrp;
|
||||
dvb_dmx_swfilter_packets(&dm1105dvb->demux,
|
||||
&dm1105dvb->ts_buf[oldwrp], nbpackets);
|
||||
dev->wrp = nextwrp;
|
||||
dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets);
|
||||
}
|
||||
|
||||
static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
|
||||
static irqreturn_t dm1105_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb = dev_id;
|
||||
struct dm1105_dev *dev = dev_id;
|
||||
|
||||
/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
|
||||
unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
|
||||
outb(intsts, dm_io_mem(DM1105_INTSTS));
|
||||
unsigned int intsts = dm_readb(DM1105_INTSTS);
|
||||
dm_writeb(DM1105_INTSTS, intsts);
|
||||
|
||||
switch (intsts) {
|
||||
case INTSTS_TSIRQ:
|
||||
case (INTSTS_TSIRQ | INTSTS_IR):
|
||||
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
|
||||
inl(dm_io_mem(DM1105_STADR));
|
||||
queue_work(dm1105dvb->wq, &dm1105dvb->work);
|
||||
dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR);
|
||||
queue_work(dev->wq, &dev->work);
|
||||
break;
|
||||
case INTSTS_IR:
|
||||
dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
|
||||
schedule_work(&dm1105dvb->ir.work);
|
||||
dev->ir.ir_command = dm_readl(DM1105_IRCODE);
|
||||
schedule_work(&dev->ir.work);
|
||||
break;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
|
||||
int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
struct ir_scancode_table *ir_codes = &ir_codes_dm1105_nec_table;
|
||||
int ir_type = IR_TYPE_OTHER;
|
||||
u64 ir_type = IR_TYPE_OTHER;
|
||||
int err = -ENOMEM;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
|
|
@ -611,51 +627,51 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
|
|||
|
||||
INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
|
||||
|
||||
err = ir_input_register(input_dev, ir_codes);
|
||||
err = ir_input_register(input_dev, ir_codes, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
|
||||
void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
|
||||
{
|
||||
ir_input_unregister(dm1105->ir.input_dev);
|
||||
}
|
||||
|
||||
static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)
|
||||
static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
|
||||
{
|
||||
dm1105dvb_disable_irqs(dm1105dvb);
|
||||
dm1105_disable_irqs(dev);
|
||||
|
||||
outb(0, dm_io_mem(DM1105_HOST_CTR));
|
||||
dm_writeb(DM1105_HOST_CTR, 0);
|
||||
|
||||
/*DATALEN 188,*/
|
||||
outb(188, dm_io_mem(DM1105_DTALENTH));
|
||||
dm_writeb(DM1105_DTALENTH, 188);
|
||||
/*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
|
||||
outw(0xc10a, dm_io_mem(DM1105_TSCTR));
|
||||
dm_writew(DM1105_TSCTR, 0xc10a);
|
||||
|
||||
/* map DMA and set address */
|
||||
dm1105dvb_dma_map(dm1105dvb);
|
||||
dm1105dvb_set_dma_addr(dm1105dvb);
|
||||
dm1105_dma_map(dev);
|
||||
dm1105_set_dma_addr(dev);
|
||||
/* big buffer */
|
||||
outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN));
|
||||
outb(47, dm_io_mem(DM1105_INTCNT));
|
||||
dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES);
|
||||
dm_writeb(DM1105_INTCNT, 47);
|
||||
|
||||
/* IR NEC mode enable */
|
||||
outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR));
|
||||
outb(0, dm_io_mem(DM1105_IRMODE));
|
||||
outw(0, dm_io_mem(DM1105_SYSTEMCODE));
|
||||
dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK));
|
||||
dm_writeb(DM1105_IRMODE, 0);
|
||||
dm_writew(DM1105_SYSTEMCODE, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb)
|
||||
static void dm1105_hw_exit(struct dm1105_dev *dev)
|
||||
{
|
||||
dm1105dvb_disable_irqs(dm1105dvb);
|
||||
dm1105_disable_irqs(dev);
|
||||
|
||||
/* IR disable */
|
||||
outb(0, dm_io_mem(DM1105_IRCTR));
|
||||
outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK));
|
||||
dm_writeb(DM1105_IRCTR, 0);
|
||||
dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK);
|
||||
|
||||
dm1105dvb_dma_unmap(dm1105dvb);
|
||||
dm1105_dma_unmap(dev);
|
||||
}
|
||||
|
||||
static struct stv0299_config sharp_z0194a_config = {
|
||||
|
|
@ -685,70 +701,79 @@ static struct cx24116_config serit_sp2633_config = {
|
|||
.demod_address = 0x55,
|
||||
};
|
||||
|
||||
static int __devinit frontend_init(struct dm1105dvb *dm1105dvb)
|
||||
static struct ds3000_config dvbworld_ds3000_config = {
|
||||
.demod_address = 0x68,
|
||||
};
|
||||
|
||||
static int __devinit frontend_init(struct dm1105_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (dm1105dvb->boardnr) {
|
||||
switch (dev->boardnr) {
|
||||
case DM1105_BOARD_DVBWORLD_2004:
|
||||
dm1105dvb->fe = dvb_attach(
|
||||
dev->fe = dvb_attach(
|
||||
cx24116_attach, &serit_sp2633_config,
|
||||
&dm1105dvb->i2c_adap);
|
||||
if (dm1105dvb->fe)
|
||||
dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage;
|
||||
&dev->i2c_adap);
|
||||
if (dev->fe) {
|
||||
dev->fe->ops.set_voltage = dm1105_set_voltage;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->fe = dvb_attach(
|
||||
ds3000_attach, &dvbworld_ds3000_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->fe)
|
||||
dev->fe->ops.set_voltage = dm1105_set_voltage;
|
||||
|
||||
break;
|
||||
case DM1105_BOARD_DVBWORLD_2002:
|
||||
case DM1105_BOARD_AXESS_DM05:
|
||||
default:
|
||||
dm1105dvb->fe = dvb_attach(
|
||||
dev->fe = dvb_attach(
|
||||
stv0299_attach, &sharp_z0194a_config,
|
||||
&dm1105dvb->i2c_adap);
|
||||
if (dm1105dvb->fe) {
|
||||
dm1105dvb->fe->ops.set_voltage =
|
||||
dm1105dvb_set_voltage;
|
||||
dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60,
|
||||
&dm1105dvb->i2c_adap, DVB_PLL_OPERA1);
|
||||
&dev->i2c_adap);
|
||||
if (dev->fe) {
|
||||
dev->fe->ops.set_voltage = dm1105_set_voltage;
|
||||
dvb_attach(dvb_pll_attach, dev->fe, 0x60,
|
||||
&dev->i2c_adap, DVB_PLL_OPERA1);
|
||||
break;
|
||||
}
|
||||
|
||||
dm1105dvb->fe = dvb_attach(
|
||||
dev->fe = dvb_attach(
|
||||
stv0288_attach, &earda_config,
|
||||
&dm1105dvb->i2c_adap);
|
||||
if (dm1105dvb->fe) {
|
||||
dm1105dvb->fe->ops.set_voltage =
|
||||
dm1105dvb_set_voltage;
|
||||
dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61,
|
||||
&dm1105dvb->i2c_adap);
|
||||
&dev->i2c_adap);
|
||||
if (dev->fe) {
|
||||
dev->fe->ops.set_voltage = dm1105_set_voltage;
|
||||
dvb_attach(stb6000_attach, dev->fe, 0x61,
|
||||
&dev->i2c_adap);
|
||||
break;
|
||||
}
|
||||
|
||||
dm1105dvb->fe = dvb_attach(
|
||||
dev->fe = dvb_attach(
|
||||
si21xx_attach, &serit_config,
|
||||
&dm1105dvb->i2c_adap);
|
||||
if (dm1105dvb->fe)
|
||||
dm1105dvb->fe->ops.set_voltage =
|
||||
dm1105dvb_set_voltage;
|
||||
&dev->i2c_adap);
|
||||
if (dev->fe)
|
||||
dev->fe->ops.set_voltage = dm1105_set_voltage;
|
||||
|
||||
}
|
||||
|
||||
if (!dm1105dvb->fe) {
|
||||
dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n");
|
||||
if (!dev->fe) {
|
||||
dev_err(&dev->pdev->dev, "could not attach frontend\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe);
|
||||
ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe);
|
||||
if (ret < 0) {
|
||||
if (dm1105dvb->fe->ops.release)
|
||||
dm1105dvb->fe->ops.release(dm1105dvb->fe);
|
||||
dm1105dvb->fe = NULL;
|
||||
if (dev->fe->ops.release)
|
||||
dev->fe->ops.release(dev->fe);
|
||||
dev->fe = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
|
||||
static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
|
||||
{
|
||||
static u8 command[1] = { 0x28 };
|
||||
|
||||
|
|
@ -766,47 +791,47 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac)
|
|||
},
|
||||
};
|
||||
|
||||
dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2);
|
||||
dev_info(&dm1105dvb->pdev->dev, "MAC %pM\n", mac);
|
||||
dm1105_i2c_xfer(&dev->i2c_adap, msg , 2);
|
||||
dev_info(&dev->pdev->dev, "MAC %pM\n", mac);
|
||||
}
|
||||
|
||||
static int __devinit dm1105_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb;
|
||||
struct dm1105_dev *dev;
|
||||
struct dvb_adapter *dvb_adapter;
|
||||
struct dvb_demux *dvbdemux;
|
||||
struct dmx_demux *dmx;
|
||||
int ret = -ENOMEM;
|
||||
int i;
|
||||
|
||||
dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
|
||||
if (!dm1105dvb)
|
||||
dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* board config */
|
||||
dm1105dvb->nr = dm1105_devcount;
|
||||
dm1105dvb->boardnr = UNSET;
|
||||
if (card[dm1105dvb->nr] < ARRAY_SIZE(dm1105_boards))
|
||||
dm1105dvb->boardnr = card[dm1105dvb->nr];
|
||||
for (i = 0; UNSET == dm1105dvb->boardnr &&
|
||||
dev->nr = dm1105_devcount;
|
||||
dev->boardnr = UNSET;
|
||||
if (card[dev->nr] < ARRAY_SIZE(dm1105_boards))
|
||||
dev->boardnr = card[dev->nr];
|
||||
for (i = 0; UNSET == dev->boardnr &&
|
||||
i < ARRAY_SIZE(dm1105_subids); i++)
|
||||
if (pdev->subsystem_vendor ==
|
||||
dm1105_subids[i].subvendor &&
|
||||
pdev->subsystem_device ==
|
||||
dm1105_subids[i].subdevice)
|
||||
dm1105dvb->boardnr = dm1105_subids[i].card;
|
||||
dev->boardnr = dm1105_subids[i].card;
|
||||
|
||||
if (UNSET == dm1105dvb->boardnr) {
|
||||
dm1105dvb->boardnr = DM1105_BOARD_UNKNOWN;
|
||||
if (UNSET == dev->boardnr) {
|
||||
dev->boardnr = DM1105_BOARD_UNKNOWN;
|
||||
dm1105_card_list(pdev);
|
||||
}
|
||||
|
||||
dm1105_devcount++;
|
||||
dm1105dvb->pdev = pdev;
|
||||
dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
|
||||
dm1105dvb->PacketErrorCount = 0;
|
||||
dm1105dvb->dmarst = 0;
|
||||
dev->pdev = pdev;
|
||||
dev->buffer_size = 5 * DM1105_DMA_BYTES;
|
||||
dev->PacketErrorCount = 0;
|
||||
dev->dmarst = 0;
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret < 0)
|
||||
|
|
@ -822,47 +847,47 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||
if (ret < 0)
|
||||
goto err_pci_disable_device;
|
||||
|
||||
dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
|
||||
if (!dm1105dvb->io_mem) {
|
||||
dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
|
||||
if (!dev->io_mem) {
|
||||
ret = -EIO;
|
||||
goto err_pci_release_regions;
|
||||
}
|
||||
|
||||
spin_lock_init(&dm1105dvb->lock);
|
||||
pci_set_drvdata(pdev, dm1105dvb);
|
||||
spin_lock_init(&dev->lock);
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
ret = dm1105dvb_hw_init(dm1105dvb);
|
||||
ret = dm1105_hw_init(dev);
|
||||
if (ret < 0)
|
||||
goto err_pci_iounmap;
|
||||
|
||||
/* i2c */
|
||||
i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
|
||||
strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME);
|
||||
dm1105dvb->i2c_adap.owner = THIS_MODULE;
|
||||
dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
dm1105dvb->i2c_adap.dev.parent = &pdev->dev;
|
||||
dm1105dvb->i2c_adap.algo = &dm1105_algo;
|
||||
dm1105dvb->i2c_adap.algo_data = dm1105dvb;
|
||||
ret = i2c_add_adapter(&dm1105dvb->i2c_adap);
|
||||
i2c_set_adapdata(&dev->i2c_adap, dev);
|
||||
strcpy(dev->i2c_adap.name, DRIVER_NAME);
|
||||
dev->i2c_adap.owner = THIS_MODULE;
|
||||
dev->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
dev->i2c_adap.dev.parent = &pdev->dev;
|
||||
dev->i2c_adap.algo = &dm1105_algo;
|
||||
dev->i2c_adap.algo_data = dev;
|
||||
ret = i2c_add_adapter(&dev->i2c_adap);
|
||||
|
||||
if (ret < 0)
|
||||
goto err_dm1105dvb_hw_exit;
|
||||
goto err_dm1105_hw_exit;
|
||||
|
||||
/* dvb */
|
||||
ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME,
|
||||
ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME,
|
||||
THIS_MODULE, &pdev->dev, adapter_nr);
|
||||
if (ret < 0)
|
||||
goto err_i2c_del_adapter;
|
||||
|
||||
dvb_adapter = &dm1105dvb->dvb_adapter;
|
||||
dvb_adapter = &dev->dvb_adapter;
|
||||
|
||||
dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac);
|
||||
dm1105_read_mac(dev, dvb_adapter->proposed_mac);
|
||||
|
||||
dvbdemux = &dm1105dvb->demux;
|
||||
dvbdemux = &dev->demux;
|
||||
dvbdemux->filternum = 256;
|
||||
dvbdemux->feednum = 256;
|
||||
dvbdemux->start_feed = dm1105dvb_start_feed;
|
||||
dvbdemux->stop_feed = dm1105dvb_stop_feed;
|
||||
dvbdemux->start_feed = dm1105_start_feed;
|
||||
dvbdemux->stop_feed = dm1105_stop_feed;
|
||||
dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
|
||||
DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
|
||||
ret = dvb_dmx_init(dvbdemux);
|
||||
|
|
@ -870,113 +895,113 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
|
|||
goto err_dvb_unregister_adapter;
|
||||
|
||||
dmx = &dvbdemux->dmx;
|
||||
dm1105dvb->dmxdev.filternum = 256;
|
||||
dm1105dvb->dmxdev.demux = dmx;
|
||||
dm1105dvb->dmxdev.capabilities = 0;
|
||||
dev->dmxdev.filternum = 256;
|
||||
dev->dmxdev.demux = dmx;
|
||||
dev->dmxdev.capabilities = 0;
|
||||
|
||||
ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter);
|
||||
ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter);
|
||||
if (ret < 0)
|
||||
goto err_dvb_dmx_release;
|
||||
|
||||
dm1105dvb->hw_frontend.source = DMX_FRONTEND_0;
|
||||
dev->hw_frontend.source = DMX_FRONTEND_0;
|
||||
|
||||
ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend);
|
||||
ret = dmx->add_frontend(dmx, &dev->hw_frontend);
|
||||
if (ret < 0)
|
||||
goto err_dvb_dmxdev_release;
|
||||
|
||||
dm1105dvb->mem_frontend.source = DMX_MEMORY_FE;
|
||||
dev->mem_frontend.source = DMX_MEMORY_FE;
|
||||
|
||||
ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend);
|
||||
ret = dmx->add_frontend(dmx, &dev->mem_frontend);
|
||||
if (ret < 0)
|
||||
goto err_remove_hw_frontend;
|
||||
|
||||
ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend);
|
||||
ret = dmx->connect_frontend(dmx, &dev->hw_frontend);
|
||||
if (ret < 0)
|
||||
goto err_remove_mem_frontend;
|
||||
|
||||
ret = frontend_init(dm1105dvb);
|
||||
ret = frontend_init(dev);
|
||||
if (ret < 0)
|
||||
goto err_disconnect_frontend;
|
||||
|
||||
dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
|
||||
dm1105_ir_init(dm1105dvb);
|
||||
dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
|
||||
dm1105_ir_init(dev);
|
||||
|
||||
INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
|
||||
sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
|
||||
dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn);
|
||||
if (!dm1105dvb->wq)
|
||||
INIT_WORK(&dev->work, dm1105_dmx_buffer);
|
||||
sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
|
||||
dev->wq = create_singlethread_workqueue(dev->wqn);
|
||||
if (!dev->wq)
|
||||
goto err_dvb_net;
|
||||
|
||||
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
|
||||
DRIVER_NAME, dm1105dvb);
|
||||
ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED,
|
||||
DRIVER_NAME, dev);
|
||||
if (ret < 0)
|
||||
goto err_workqueue;
|
||||
|
||||
return 0;
|
||||
|
||||
err_workqueue:
|
||||
destroy_workqueue(dm1105dvb->wq);
|
||||
destroy_workqueue(dev->wq);
|
||||
err_dvb_net:
|
||||
dvb_net_release(&dm1105dvb->dvbnet);
|
||||
dvb_net_release(&dev->dvbnet);
|
||||
err_disconnect_frontend:
|
||||
dmx->disconnect_frontend(dmx);
|
||||
err_remove_mem_frontend:
|
||||
dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
|
||||
dmx->remove_frontend(dmx, &dev->mem_frontend);
|
||||
err_remove_hw_frontend:
|
||||
dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
|
||||
dmx->remove_frontend(dmx, &dev->hw_frontend);
|
||||
err_dvb_dmxdev_release:
|
||||
dvb_dmxdev_release(&dm1105dvb->dmxdev);
|
||||
dvb_dmxdev_release(&dev->dmxdev);
|
||||
err_dvb_dmx_release:
|
||||
dvb_dmx_release(dvbdemux);
|
||||
err_dvb_unregister_adapter:
|
||||
dvb_unregister_adapter(dvb_adapter);
|
||||
err_i2c_del_adapter:
|
||||
i2c_del_adapter(&dm1105dvb->i2c_adap);
|
||||
err_dm1105dvb_hw_exit:
|
||||
dm1105dvb_hw_exit(dm1105dvb);
|
||||
i2c_del_adapter(&dev->i2c_adap);
|
||||
err_dm1105_hw_exit:
|
||||
dm1105_hw_exit(dev);
|
||||
err_pci_iounmap:
|
||||
pci_iounmap(pdev, dm1105dvb->io_mem);
|
||||
pci_iounmap(pdev, dev->io_mem);
|
||||
err_pci_release_regions:
|
||||
pci_release_regions(pdev);
|
||||
err_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
err_kfree:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(dm1105dvb);
|
||||
kfree(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit dm1105_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev);
|
||||
struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter;
|
||||
struct dvb_demux *dvbdemux = &dm1105dvb->demux;
|
||||
struct dm1105_dev *dev = pci_get_drvdata(pdev);
|
||||
struct dvb_adapter *dvb_adapter = &dev->dvb_adapter;
|
||||
struct dvb_demux *dvbdemux = &dev->demux;
|
||||
struct dmx_demux *dmx = &dvbdemux->dmx;
|
||||
|
||||
dm1105_ir_exit(dm1105dvb);
|
||||
dm1105_ir_exit(dev);
|
||||
dmx->close(dmx);
|
||||
dvb_net_release(&dm1105dvb->dvbnet);
|
||||
if (dm1105dvb->fe)
|
||||
dvb_unregister_frontend(dm1105dvb->fe);
|
||||
dvb_net_release(&dev->dvbnet);
|
||||
if (dev->fe)
|
||||
dvb_unregister_frontend(dev->fe);
|
||||
|
||||
dmx->disconnect_frontend(dmx);
|
||||
dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);
|
||||
dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);
|
||||
dvb_dmxdev_release(&dm1105dvb->dmxdev);
|
||||
dmx->remove_frontend(dmx, &dev->mem_frontend);
|
||||
dmx->remove_frontend(dmx, &dev->hw_frontend);
|
||||
dvb_dmxdev_release(&dev->dmxdev);
|
||||
dvb_dmx_release(dvbdemux);
|
||||
dvb_unregister_adapter(dvb_adapter);
|
||||
if (&dm1105dvb->i2c_adap)
|
||||
i2c_del_adapter(&dm1105dvb->i2c_adap);
|
||||
if (&dev->i2c_adap)
|
||||
i2c_del_adapter(&dev->i2c_adap);
|
||||
|
||||
dm1105dvb_hw_exit(dm1105dvb);
|
||||
dm1105_hw_exit(dev);
|
||||
synchronize_irq(pdev->irq);
|
||||
free_irq(pdev->irq, dm1105dvb);
|
||||
pci_iounmap(pdev, dm1105dvb->io_mem);
|
||||
free_irq(pdev->irq, dev);
|
||||
pci_iounmap(pdev, dev->io_mem);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
dm1105_devcount--;
|
||||
kfree(dm1105dvb);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
static struct pci_device_id dm1105_id_table[] __devinitdata = {
|
||||
|
|
|
|||
|
|
@ -1199,8 +1199,6 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
|||
{
|
||||
int r = 0;
|
||||
|
||||
dtv_property_dump(tvp);
|
||||
|
||||
/* Allow the frontend to validate incoming properties */
|
||||
if (fe->ops.get_property)
|
||||
r = fe->ops.get_property(fe, tvp);
|
||||
|
|
@ -1323,6 +1321,8 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
|||
r = -1;
|
||||
}
|
||||
|
||||
dtv_property_dump(tvp);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1488,7 +1488,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
dprintk ("%s\n", __func__);
|
||||
dprintk("%s (%d)\n", __func__, _IOC_NR(cmd));
|
||||
|
||||
if (fepriv->exit)
|
||||
return -ENODEV;
|
||||
|
|
@ -1536,8 +1536,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
|
|||
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = (struct dtv_property *) kmalloc(tvps->num *
|
||||
sizeof(struct dtv_property), GFP_KERNEL);
|
||||
tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
|
||||
if (!tvp) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
|
@ -1569,8 +1568,7 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
|
|||
if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = (struct dtv_property *) kmalloc(tvps->num *
|
||||
sizeof(struct dtv_property), GFP_KERNEL);
|
||||
tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
|
||||
if (!tvp) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
|
|||
rbuf->pread = rbuf->pwrite;
|
||||
rbuf->error = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_ringbuffer_flush);
|
||||
|
||||
void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -336,3 +336,11 @@ config DVB_USB_EC168
|
|||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
|
||||
|
||||
config DVB_USB_AZ6027
|
||||
tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
|
||||
depends on DVB_USB
|
||||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the AZ6027 device
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
|
|||
dvb-usb-ec168-objs = ec168.o
|
||||
obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o
|
||||
|
||||
dvb-usb-az6027-objs = az6027.o
|
||||
obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
# due to tuner-xc3028
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/hash.h>
|
||||
|
||||
#include "af9015.h"
|
||||
#include "af9013.h"
|
||||
#include "mt2060.h"
|
||||
|
|
@ -553,26 +555,45 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* dump eeprom */
|
||||
static int af9015_eeprom_dump(struct dvb_usb_device *d)
|
||||
/* hash (and dump) eeprom */
|
||||
static int af9015_eeprom_hash(struct usb_device *udev)
|
||||
{
|
||||
u8 reg, val;
|
||||
static const unsigned int eeprom_size = 256;
|
||||
unsigned int reg;
|
||||
int ret;
|
||||
u8 val, *eeprom;
|
||||
struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
|
||||
|
||||
for (reg = 0; ; reg++) {
|
||||
if (reg % 16 == 0) {
|
||||
if (reg)
|
||||
deb_info(KERN_CONT "\n");
|
||||
deb_info(KERN_DEBUG "%02x:", reg);
|
||||
}
|
||||
if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0)
|
||||
deb_info(KERN_CONT " %02x", val);
|
||||
else
|
||||
deb_info(KERN_CONT " --");
|
||||
if (reg == 0xff)
|
||||
break;
|
||||
eeprom = kmalloc(eeprom_size, GFP_KERNEL);
|
||||
if (eeprom == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (reg = 0; reg < eeprom_size; reg++) {
|
||||
req.addr = reg;
|
||||
ret = af9015_rw_udev(udev, &req);
|
||||
if (ret)
|
||||
goto free;
|
||||
eeprom[reg] = val;
|
||||
}
|
||||
deb_info(KERN_CONT "\n");
|
||||
return 0;
|
||||
|
||||
if (dvb_usb_af9015_debug & 0x01)
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom,
|
||||
eeprom_size);
|
||||
|
||||
BUG_ON(eeprom_size % 4);
|
||||
|
||||
af9015_config.eeprom_sum = 0;
|
||||
for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) {
|
||||
af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32;
|
||||
af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]);
|
||||
}
|
||||
|
||||
deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum);
|
||||
|
||||
ret = 0;
|
||||
free:
|
||||
kfree(eeprom);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int af9015_download_ir_table(struct dvb_usb_device *d)
|
||||
|
|
@ -711,12 +732,132 @@ error:
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct af9015_setup {
|
||||
unsigned int id;
|
||||
struct dvb_usb_rc_key *rc_key_map;
|
||||
unsigned int rc_key_map_size;
|
||||
u8 *ir_table;
|
||||
unsigned int ir_table_size;
|
||||
};
|
||||
|
||||
static const struct af9015_setup *af9015_setup_match(unsigned int id,
|
||||
const struct af9015_setup *table)
|
||||
{
|
||||
for (; table->rc_key_map; table++)
|
||||
if (table->id == id)
|
||||
return table;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct af9015_setup af9015_setup_modparam[] = {
|
||||
{ AF9015_REMOTE_A_LINK_DTU_M,
|
||||
af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
|
||||
af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
|
||||
{ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
|
||||
af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
|
||||
af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
|
||||
{ AF9015_REMOTE_MYGICTV_U718,
|
||||
af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
|
||||
af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
|
||||
{ AF9015_REMOTE_DIGITTRADE_DVB_T,
|
||||
af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade),
|
||||
af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) },
|
||||
{ AF9015_REMOTE_AVERMEDIA_KS,
|
||||
af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
|
||||
af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) },
|
||||
{ }
|
||||
};
|
||||
|
||||
/* don't add new entries here anymore, use hashes instead */
|
||||
static const struct af9015_setup af9015_setup_usbids[] = {
|
||||
{ USB_VID_LEADTEK,
|
||||
af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek),
|
||||
af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) },
|
||||
{ USB_VID_VISIONPLUS,
|
||||
af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
|
||||
af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) },
|
||||
{ USB_VID_KWORLD_2, /* TODO: use correct rc keys */
|
||||
af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
|
||||
af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) },
|
||||
{ USB_VID_AVERMEDIA,
|
||||
af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
|
||||
af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) },
|
||||
{ USB_VID_MSI_2,
|
||||
af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii),
|
||||
af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct af9015_setup af9015_setup_hashes[] = {
|
||||
{ 0xb8feb708,
|
||||
af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
|
||||
af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
|
||||
{ 0xa3703d00,
|
||||
af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
|
||||
af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
|
||||
{ 0x9b7dc64e,
|
||||
af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
|
||||
af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static void af9015_set_remote_config(struct usb_device *udev,
|
||||
struct dvb_usb_device_properties *props)
|
||||
{
|
||||
const struct af9015_setup *table = NULL;
|
||||
|
||||
if (dvb_usb_af9015_remote) {
|
||||
/* load remote defined as module param */
|
||||
table = af9015_setup_match(dvb_usb_af9015_remote,
|
||||
af9015_setup_modparam);
|
||||
} else {
|
||||
u16 vendor = le16_to_cpu(udev->descriptor.idVendor);
|
||||
|
||||
table = af9015_setup_match(af9015_config.eeprom_sum,
|
||||
af9015_setup_hashes);
|
||||
|
||||
if (!table && vendor == USB_VID_AFATECH) {
|
||||
/* Check USB manufacturer and product strings and try
|
||||
to determine correct remote in case of chip vendor
|
||||
reference IDs are used.
|
||||
DO NOT ADD ANYTHING NEW HERE. Use hashes instead.
|
||||
*/
|
||||
char manufacturer[10];
|
||||
memset(manufacturer, 0, sizeof(manufacturer));
|
||||
usb_string(udev, udev->descriptor.iManufacturer,
|
||||
manufacturer, sizeof(manufacturer));
|
||||
if (!strcmp("MSI", manufacturer)) {
|
||||
/* iManufacturer 1 MSI
|
||||
iProduct 2 MSI K-VOX */
|
||||
table = af9015_setup_match(
|
||||
AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
|
||||
af9015_setup_modparam);
|
||||
} else if (udev->descriptor.idProduct ==
|
||||
cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
|
||||
table = &(const struct af9015_setup){ 0,
|
||||
af9015_rc_keys_trekstor,
|
||||
ARRAY_SIZE(af9015_rc_keys_trekstor),
|
||||
af9015_ir_table_trekstor,
|
||||
ARRAY_SIZE(af9015_ir_table_trekstor)
|
||||
};
|
||||
}
|
||||
} else if (!table)
|
||||
table = af9015_setup_match(vendor, af9015_setup_usbids);
|
||||
}
|
||||
|
||||
if (table) {
|
||||
props->rc_key_map = table->rc_key_map;
|
||||
props->rc_key_map_size = table->rc_key_map_size;
|
||||
af9015_config.ir_table = table->ir_table;
|
||||
af9015_config.ir_table_size = table->ir_table_size;
|
||||
}
|
||||
}
|
||||
|
||||
static int af9015_read_config(struct usb_device *udev)
|
||||
{
|
||||
int ret;
|
||||
u8 val, i, offset = 0;
|
||||
struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
|
||||
char manufacturer[10];
|
||||
|
||||
/* IR remote controller */
|
||||
req.addr = AF9015_EEPROM_IR_MODE;
|
||||
|
|
@ -728,158 +869,18 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
}
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = af9015_eeprom_hash(udev);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
deb_info("%s: IR mode:%d\n", __func__, val);
|
||||
for (i = 0; i < af9015_properties_count; i++) {
|
||||
if (val == AF9015_IR_MODE_DISABLED) {
|
||||
af9015_properties[i].rc_key_map = NULL;
|
||||
af9015_properties[i].rc_key_map_size = 0;
|
||||
} else if (dvb_usb_af9015_remote) {
|
||||
/* load remote defined as module param */
|
||||
switch (dvb_usb_af9015_remote) {
|
||||
case AF9015_REMOTE_A_LINK_DTU_M:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_a_link;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_a_link);
|
||||
af9015_config.ir_table = af9015_ir_table_a_link;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_a_link);
|
||||
break;
|
||||
case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_msi;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_msi);
|
||||
af9015_config.ir_table = af9015_ir_table_msi;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_msi);
|
||||
break;
|
||||
case AF9015_REMOTE_MYGICTV_U718:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_mygictv;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_mygictv);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_mygictv;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_mygictv);
|
||||
break;
|
||||
case AF9015_REMOTE_DIGITTRADE_DVB_T:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_digittrade;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_digittrade);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_digittrade;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_digittrade);
|
||||
break;
|
||||
case AF9015_REMOTE_AVERMEDIA_KS:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_avermedia;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_avermedia);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_avermedia_ks;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_avermedia_ks);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (le16_to_cpu(udev->descriptor.idVendor)) {
|
||||
case USB_VID_LEADTEK:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_leadtek;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_leadtek);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_leadtek;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_leadtek);
|
||||
break;
|
||||
case USB_VID_VISIONPLUS:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_twinhan;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_twinhan);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_twinhan;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_twinhan);
|
||||
break;
|
||||
case USB_VID_KWORLD_2:
|
||||
/* TODO: use correct rc keys */
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_twinhan;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_twinhan);
|
||||
af9015_config.ir_table = af9015_ir_table_kworld;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_kworld);
|
||||
break;
|
||||
/* Check USB manufacturer and product strings and try
|
||||
to determine correct remote in case of chip vendor
|
||||
reference IDs are used. */
|
||||
case USB_VID_AFATECH:
|
||||
memset(manufacturer, 0, sizeof(manufacturer));
|
||||
usb_string(udev, udev->descriptor.iManufacturer,
|
||||
manufacturer, sizeof(manufacturer));
|
||||
if (!strcmp("Geniatech", manufacturer)) {
|
||||
/* iManufacturer 1 Geniatech
|
||||
iProduct 2 AF9015 */
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_mygictv;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_mygictv);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_mygictv;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_mygictv);
|
||||
} else if (!strcmp("MSI", manufacturer)) {
|
||||
/* iManufacturer 1 MSI
|
||||
iProduct 2 MSI K-VOX */
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_msi;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_msi);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_msi;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_msi);
|
||||
} else if (udev->descriptor.idProduct ==
|
||||
cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_trekstor;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_trekstor);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_trekstor;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_trekstor);
|
||||
}
|
||||
break;
|
||||
case USB_VID_AVERMEDIA:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_avermedia;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_avermedia);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_avermedia;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_avermedia);
|
||||
break;
|
||||
case USB_VID_MSI_2:
|
||||
af9015_properties[i].rc_key_map =
|
||||
af9015_rc_keys_msi_digivox_iii;
|
||||
af9015_properties[i].rc_key_map_size =
|
||||
ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii);
|
||||
af9015_config.ir_table =
|
||||
af9015_ir_table_msi_digivox_iii;
|
||||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_msi_digivox_iii);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
af9015_set_remote_config(udev, &af9015_properties[i]);
|
||||
}
|
||||
|
||||
/* TS mode - one or two receivers */
|
||||
|
|
@ -1001,6 +1002,9 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
|
||||
af9015_af9013_config[i].rf_spec_inv = 1;
|
||||
break;
|
||||
case AF9013_TUNER_TDA18218:
|
||||
warn("tuner NXP TDA18218 not supported yet");
|
||||
return -ENODEV;
|
||||
default:
|
||||
warn("tuner id:%d not supported, please report!", val);
|
||||
return -ENODEV;
|
||||
|
|
@ -1125,11 +1129,6 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
deb_info("%s: init I2C\n", __func__);
|
||||
ret = af9015_i2c_init(adap->dev);
|
||||
|
||||
/* dump eeprom (debug) */
|
||||
ret = af9015_eeprom_dump(adap->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* select I2C adapter */
|
||||
i2c_adap = &state->i2c_adap;
|
||||
|
|
@ -1295,6 +1294,8 @@ static struct usb_device_id af9015_usb_table[] = {
|
|||
/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
|
||||
{USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
|
||||
{0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
|
||||
|
|
@ -1381,7 +1382,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
},
|
||||
{
|
||||
.name = "DigitalNow TinyTwin DVB-T Receiver",
|
||||
.cold_ids = {&af9015_usb_table[5], NULL},
|
||||
.cold_ids = {&af9015_usb_table[5],
|
||||
&af9015_usb_table[28], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
{
|
||||
|
|
@ -1566,7 +1568,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
.num_device_descs = 6, /* max 9 */
|
||||
.num_device_descs = 7, /* max 9 */
|
||||
.devices = {
|
||||
{
|
||||
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
|
||||
|
|
@ -1600,6 +1602,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.cold_ids = {&af9015_usb_table[27], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
{
|
||||
.name = "Leadtek WinFast DTV2000DS",
|
||||
.cold_ids = {&af9015_usb_table[29], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ struct af9015_config {
|
|||
u16 mt2060_if1[2];
|
||||
u16 firmware_size;
|
||||
u16 firmware_checksum;
|
||||
u32 eeprom_sum;
|
||||
u8 *ir_table;
|
||||
u16 ir_table_size;
|
||||
};
|
||||
|
|
|
|||
1151
drivers/media/dvb/dvb-usb/az6027.c
Normal file
1151
drivers/media/dvb/dvb-usb/az6027.c
Normal file
File diff suppressed because it is too large
Load diff
14
drivers/media/dvb/dvb-usb/az6027.h
Normal file
14
drivers/media/dvb/dvb-usb/az6027.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef _DVB_USB_VP6027_H_
|
||||
#define _DVB_USB_VP6027_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "az6027"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
|
||||
extern int dvb_usb_az6027_debug;
|
||||
#define deb_info(args...) dprintk(dvb_usb_az6027_debug, 0x01, args)
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_az6027_debug, 0x02, args)
|
||||
#define deb_rc(args...) dprintk(dvb_usb_az6027_debug, 0x04, args)
|
||||
#define deb_fe(args...) dprintk(dvb_usb_az6027_debug, 0x08, args)
|
||||
|
||||
#endif
|
||||
|
|
@ -1184,6 +1184,9 @@ static struct atbm8830_config mygica_d689_atbm8830_cfg = {
|
|||
.osc_clk_freq = 30400, /* in kHz */
|
||||
.if_freq = 0, /* zero IF */
|
||||
.zif_swap_iq = 1,
|
||||
.agc_min = 0x2E,
|
||||
.agc_max = 0x90,
|
||||
.agc_hold_loop = 0,
|
||||
};
|
||||
|
||||
static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ struct dib0700_state {
|
|||
u16 mt2060_if1[2];
|
||||
u8 rc_toggle;
|
||||
u8 rc_counter;
|
||||
u8 rc_func_version;
|
||||
u8 is_dib7000pc;
|
||||
u8 fw_use_new_i2c_api;
|
||||
u8 disable_streaming_master_mode;
|
||||
|
|
|
|||
|
|
@ -471,14 +471,209 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
return dib0700_ctrl_wr(adap->dev, b, 4);
|
||||
}
|
||||
|
||||
/* Number of keypresses to ignore before start repeating */
|
||||
#define RC_REPEAT_DELAY_V1_20 10
|
||||
|
||||
/* This is the structure of the RC response packet starting in firmware 1.20 */
|
||||
struct dib0700_rc_response {
|
||||
u8 report_id;
|
||||
u8 data_state;
|
||||
u16 system;
|
||||
u8 data;
|
||||
u8 not_data;
|
||||
};
|
||||
#define RC_MSG_SIZE_V1_20 6
|
||||
|
||||
static void dib0700_rc_urb_completion(struct urb *purb)
|
||||
{
|
||||
struct dvb_usb_device *d = purb->context;
|
||||
struct dvb_usb_rc_key *keymap;
|
||||
struct dib0700_state *st;
|
||||
struct dib0700_rc_response poll_reply;
|
||||
u8 *buf;
|
||||
int found = 0;
|
||||
u32 event;
|
||||
int state;
|
||||
int i;
|
||||
|
||||
deb_info("%s()\n", __func__);
|
||||
if (d == NULL)
|
||||
return;
|
||||
|
||||
if (d->rc_input_dev == NULL) {
|
||||
/* This will occur if disable_rc_polling=1 */
|
||||
usb_free_urb(purb);
|
||||
return;
|
||||
}
|
||||
|
||||
keymap = d->props.rc_key_map;
|
||||
st = d->priv;
|
||||
buf = (u8 *)purb->transfer_buffer;
|
||||
|
||||
if (purb->status < 0) {
|
||||
deb_info("discontinuing polling\n");
|
||||
usb_free_urb(purb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (purb->actual_length != RC_MSG_SIZE_V1_20) {
|
||||
deb_info("malformed rc msg size=%d\n", purb->actual_length);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
/* Set initial results in case we exit the function early */
|
||||
event = 0;
|
||||
state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0],
|
||||
buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length);
|
||||
|
||||
switch (dvb_usb_dib0700_ir_proto) {
|
||||
case 0:
|
||||
/* NEC Protocol */
|
||||
poll_reply.report_id = 0;
|
||||
poll_reply.data_state = 1;
|
||||
poll_reply.system = buf[2];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
|
||||
&& (poll_reply.not_data == 0xff)) {
|
||||
poll_reply.data_state = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* RC5 Protocol */
|
||||
poll_reply.report_id = buf[0];
|
||||
poll_reply.data_state = buf[1];
|
||||
poll_reply.system = (buf[2] << 8) | buf[3];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
break;
|
||||
}
|
||||
|
||||
if ((poll_reply.data + poll_reply.not_data) != 0xff) {
|
||||
/* Key failed integrity check */
|
||||
err("key failed integrity check: %04x %02x %02x",
|
||||
poll_reply.system,
|
||||
poll_reply.data, poll_reply.not_data);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n",
|
||||
poll_reply.report_id, poll_reply.data_state,
|
||||
poll_reply.system, poll_reply.data, poll_reply.not_data);
|
||||
|
||||
/* Find the key in the map */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
|
||||
rc5_data(&keymap[i]) == poll_reply.data) {
|
||||
event = keymap[i].event;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
err("Unknown remote controller key: %04x %02x %02x",
|
||||
poll_reply.system, poll_reply.data, poll_reply.not_data);
|
||||
d->last_event = 0;
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
if (poll_reply.data_state == 1) {
|
||||
/* New key hit */
|
||||
st->rc_counter = 0;
|
||||
event = keymap[i].event;
|
||||
state = REMOTE_KEY_PRESSED;
|
||||
d->last_event = keymap[i].event;
|
||||
} else if (poll_reply.data_state == 2) {
|
||||
/* Key repeated */
|
||||
st->rc_counter++;
|
||||
|
||||
/* prevents unwanted double hits */
|
||||
if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
|
||||
event = d->last_event;
|
||||
state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY_V1_20;
|
||||
}
|
||||
} else {
|
||||
err("Unknown data state [%d]", poll_reply.data_state);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case REMOTE_NO_KEY_PRESSED:
|
||||
break;
|
||||
case REMOTE_KEY_PRESSED:
|
||||
deb_info("key pressed\n");
|
||||
d->last_event = event;
|
||||
case REMOTE_KEY_REPEAT:
|
||||
deb_info("key repeated\n");
|
||||
input_event(d->rc_input_dev, EV_KEY, event, 1);
|
||||
input_sync(d->rc_input_dev);
|
||||
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||
input_sync(d->rc_input_dev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
resubmit:
|
||||
/* Clean the buffer before we requeue */
|
||||
memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20);
|
||||
|
||||
/* Requeue URB */
|
||||
usb_submit_urb(purb, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
int dib0700_rc_setup(struct dvb_usb_device *d)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
|
||||
int i = dib0700_ctrl_wr(d, rc_setup, 3);
|
||||
struct urb *purb;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (d->props.rc_key_map == NULL)
|
||||
return 0;
|
||||
|
||||
/* Set the IR mode */
|
||||
i = dib0700_ctrl_wr(d, rc_setup, 3);
|
||||
if (i<0) {
|
||||
err("ir protocol setup failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (st->fw_version < 0x10200)
|
||||
return 0;
|
||||
|
||||
/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
|
||||
purb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (purb == NULL) {
|
||||
err("rc usb alloc urb failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
|
||||
if (purb->transfer_buffer == NULL) {
|
||||
err("rc kzalloc failed\n");
|
||||
usb_free_urb(purb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
purb->status = -EINPROGRESS;
|
||||
usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1),
|
||||
purb->transfer_buffer, RC_MSG_SIZE_V1_20,
|
||||
dib0700_rc_urb_completion, d);
|
||||
|
||||
ret = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (ret != 0) {
|
||||
err("rc submit urb failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -472,20 +472,25 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
|
|||
|
||||
/* Number of keypresses to ignore before start repeating */
|
||||
#define RC_REPEAT_DELAY 6
|
||||
#define RC_REPEAT_DELAY_V1_20 10
|
||||
|
||||
|
||||
|
||||
/* Used by firmware versions < 1.20 (deprecated) */
|
||||
static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
u8 key[4];
|
||||
int i;
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct dib0700_state *st = d->priv;
|
||||
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
if (st->fw_version >= 0x10200) {
|
||||
/* For 1.20 firmware , We need to keep the RC polling
|
||||
callback so we can reuse the input device setup in
|
||||
dvb-usb-remote.c. However, the actual work is being done
|
||||
in the bulk URB completion handler. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
i=dib0700_ctrl_rd(d,rc_request,2,key,4);
|
||||
if (i<=0) {
|
||||
err("RC Query Failed");
|
||||
|
|
@ -557,149 +562,6 @@ static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* This is the structure of the RC response packet starting in firmware 1.20 */
|
||||
struct dib0700_rc_response {
|
||||
u8 report_id;
|
||||
u8 data_state;
|
||||
u16 system;
|
||||
u8 data;
|
||||
u8 not_data;
|
||||
};
|
||||
|
||||
/* This supports the new IR response format for firmware v1.20 */
|
||||
static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct dib0700_state *st = d->priv;
|
||||
struct dib0700_rc_response poll_reply;
|
||||
u8 buf[6];
|
||||
int i;
|
||||
int status;
|
||||
int actlen;
|
||||
int found = 0;
|
||||
|
||||
/* Set initial results in case we exit the function early */
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
/* Firmware v1.20 provides RC data via bulk endpoint 1 */
|
||||
status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf,
|
||||
sizeof(buf), &actlen, 50);
|
||||
if (status < 0) {
|
||||
/* No data available (meaning no key press) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
switch (dvb_usb_dib0700_ir_proto) {
|
||||
case 0:
|
||||
poll_reply.report_id = 0;
|
||||
poll_reply.data_state = 1;
|
||||
poll_reply.system = buf[2];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
|
||||
&& (poll_reply.not_data == 0xff)) {
|
||||
poll_reply.data_state = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (actlen != sizeof(buf)) {
|
||||
/* We didn't get back the 6 byte message we expected */
|
||||
err("Unexpected RC response size [%d]", actlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
poll_reply.report_id = buf[0];
|
||||
poll_reply.data_state = buf[1];
|
||||
poll_reply.system = (buf[2] << 8) | buf[3];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((poll_reply.data + poll_reply.not_data) != 0xff) {
|
||||
/* Key failed integrity check */
|
||||
err("key failed integrity check: %04x %02x %02x",
|
||||
poll_reply.system,
|
||||
poll_reply.data, poll_reply.not_data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Find the key in the map */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
|
||||
rc5_data(&keymap[i]) == poll_reply.data) {
|
||||
*event = keymap[i].event;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
err("Unknown remote controller key: %04x %02x %02x",
|
||||
poll_reply.system,
|
||||
poll_reply.data, poll_reply.not_data);
|
||||
d->last_event = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (poll_reply.data_state == 1) {
|
||||
/* New key hit */
|
||||
st->rc_counter = 0;
|
||||
*event = keymap[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
d->last_event = keymap[i].event;
|
||||
} else if (poll_reply.data_state == 2) {
|
||||
/* Key repeated */
|
||||
st->rc_counter++;
|
||||
|
||||
/* prevents unwanted double hits */
|
||||
if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
|
||||
*event = d->last_event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY_V1_20;
|
||||
}
|
||||
} else {
|
||||
err("Unknown data state [%d]", poll_reply.data_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
|
||||
/* Because some people may have improperly named firmware files,
|
||||
let's figure out whether to use the new firmware call or the legacy
|
||||
call based on the firmware version embedded in the file */
|
||||
if (st->rc_func_version == 0) {
|
||||
u32 hwver, romver, ramver, fwtype;
|
||||
int ret = dib0700_get_version(d, &hwver, &romver, &ramver,
|
||||
&fwtype);
|
||||
if (ret < 0) {
|
||||
err("Could not determine version info");
|
||||
return -1;
|
||||
}
|
||||
if (ramver < 0x10200)
|
||||
st->rc_func_version = 1;
|
||||
else
|
||||
st->rc_func_version = 2;
|
||||
}
|
||||
|
||||
if (st->rc_func_version == 2)
|
||||
return dib0700_rc_query_v1_20(d, event, state);
|
||||
else
|
||||
return dib0700_rc_query_legacy(d, event, state);
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key dib0700_rc_keys[] = {
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x0700, KEY_MUTE },
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@
|
|||
#define USB_VID_HUMAX_COEX 0x10b9
|
||||
#define USB_VID_774 0x7a69
|
||||
#define USB_VID_EVOLUTEPC 0x1e59
|
||||
#define USB_VID_AZUREWAVE 0x13d3
|
||||
#define USB_VID_TECHNISAT 0x14f7
|
||||
|
||||
/* Product IDs */
|
||||
#define USB_PID_ADSTECH_USB2_COLD 0xa333
|
||||
|
|
@ -138,6 +140,7 @@
|
|||
#define USB_PID_TWINHAN_VP7021_COLD 0x3207
|
||||
#define USB_PID_TWINHAN_VP7021_WARM 0x3208
|
||||
#define USB_PID_TINYTWIN 0x3226
|
||||
#define USB_PID_TINYTWIN_2 0xe402
|
||||
#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
|
||||
#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
|
||||
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
|
||||
|
|
@ -209,6 +212,7 @@
|
|||
#define USB_PID_PINNACLE_PCTV71E 0x022b
|
||||
#define USB_PID_PINNACLE_PCTV72E 0x0236
|
||||
#define USB_PID_PINNACLE_PCTV73E 0x0237
|
||||
#define USB_PID_PINNACLE_PCTV310E 0x3211
|
||||
#define USB_PID_PINNACLE_PCTV801E 0x023a
|
||||
#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
|
||||
#define USB_PID_PINNACLE_PCTV73A 0x0243
|
||||
|
|
@ -248,6 +252,7 @@
|
|||
#define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361
|
||||
#define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6
|
||||
#define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7
|
||||
#define USB_PID_WINFAST_DTV2000DS 0x6a04
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
|
||||
|
|
@ -290,5 +295,7 @@
|
|||
#define USB_PID_FRIIO_WHITE 0x0001
|
||||
#define USB_PID_TVWAY_PLUS 0x0002
|
||||
#define USB_PID_SVEON_STV20 0xe39d
|
||||
|
||||
#define USB_PID_AZUREWAVE_AZ6027 0x3275
|
||||
#define USB_PID_TERRATEC_DVBS2CI 0x3275
|
||||
#define USB_PID_TECHNISAT_USB2_HDCI 0x0002
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ int dvb_usb_device_init(struct usb_interface *intf,
|
|||
d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
|
||||
if (d == NULL) {
|
||||
err("no memory for 'struct dvb_usb_device'");
|
||||
return ret;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
d->udev = udev;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
case REMOTE_KEY_REPEAT:
|
||||
deb_rc("key repeated\n");
|
||||
input_event(d->rc_input_dev, EV_KEY, event, 1);
|
||||
input_sync(d->rc_input_dev);
|
||||
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||
input_sync(d->rc_input_dev);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* DVB USB framework compliant Linux driver for the
|
||||
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
|
||||
* TeVii S600, S630, S650 Cards
|
||||
* TeVii S600, S630, S650,
|
||||
* Prof 1100, 7500 Cards
|
||||
* Copyright (C) 2008,2009 Igor M. Liplianin (liplianin@me.by)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
|
@ -469,11 +470,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
struct usb_device *udev;
|
||||
int ret = 0;
|
||||
int len, i, j;
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
udev = d->udev;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
|
|
@ -488,8 +491,13 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
}
|
||||
case (DW2102_VOLTAGE_CTRL): {
|
||||
u8 obuf[2];
|
||||
|
||||
obuf[0] = 1;
|
||||
obuf[1] = msg[j].buf[1];/* off-on */
|
||||
ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
|
||||
obuf, 2, DW210X_WRITE_MSG);
|
||||
obuf[0] = 3;
|
||||
obuf[1] = msg[j].buf[0];
|
||||
obuf[1] = msg[j].buf[0];/* 13v-18v */
|
||||
ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
|
||||
obuf, 2, DW210X_WRITE_MSG);
|
||||
break;
|
||||
|
|
@ -527,6 +535,17 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
i += 16;
|
||||
len -= 16;
|
||||
} while (len > 0);
|
||||
} else if ((udev->descriptor.idProduct == 0x7500)
|
||||
&& (j < (num - 1))) {
|
||||
/* write register addr before read */
|
||||
u8 obuf[msg[j].len + 2];
|
||||
obuf[0] = msg[j + 1].len;
|
||||
obuf[1] = (msg[j].addr << 1);
|
||||
memcpy(obuf + 2, msg[j].buf, msg[j].len);
|
||||
ret = dw210x_op_rw(d->udev, 0x92, 0, 0,
|
||||
obuf, msg[j].len + 2,
|
||||
DW210X_WRITE_MSG);
|
||||
break;
|
||||
} else {
|
||||
/* write registers */
|
||||
u8 obuf[msg[j].len + 2];
|
||||
|
|
@ -651,18 +670,25 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
|||
|
||||
static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
static u8 command_13v[1] = {0x00};
|
||||
static u8 command_18v[1] = {0x01};
|
||||
struct i2c_msg msg[] = {
|
||||
{.addr = DW2102_VOLTAGE_CTRL, .flags = 0,
|
||||
.buf = command_13v, .len = 1},
|
||||
static u8 command_13v[] = {0x00, 0x01};
|
||||
static u8 command_18v[] = {0x01, 0x01};
|
||||
static u8 command_off[] = {0x00, 0x00};
|
||||
struct i2c_msg msg = {
|
||||
.addr = DW2102_VOLTAGE_CTRL,
|
||||
.flags = 0,
|
||||
.buf = command_off,
|
||||
.len = 2,
|
||||
};
|
||||
|
||||
struct dvb_usb_adapter *udev_adap =
|
||||
(struct dvb_usb_adapter *)(fe->dvb->priv);
|
||||
if (voltage == SEC_VOLTAGE_18)
|
||||
msg[0].buf = command_18v;
|
||||
i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
|
||||
msg.buf = command_18v;
|
||||
else if (voltage == SEC_VOLTAGE_13)
|
||||
msg.buf = command_13v;
|
||||
|
||||
i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -735,6 +761,18 @@ static struct stv6110_config dw2104_stv6110_config = {
|
|||
.clk_div = 1,
|
||||
};
|
||||
|
||||
static struct stv0900_config prof_7500_stv0900_config = {
|
||||
.demod_address = 0x6a,
|
||||
.demod_mode = 0,
|
||||
.xtal = 27000000,
|
||||
.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
|
||||
.diseqc_mode = 2,/* 2/3 PWM */
|
||||
.tun1_maddress = 0,/* 0x60 */
|
||||
.tun1_adc = 0,/* 2 Vpp */
|
||||
.path1_mode = 3,
|
||||
.tun1_type = 3,
|
||||
};
|
||||
|
||||
static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
|
|
@ -882,6 +920,19 @@ static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
|
||||
&d->dev->i2c_adap, 0);
|
||||
if (d->fe == NULL)
|
||||
return -EIO;
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
|
||||
info("Attached STV0900+STB6100A!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
|
||||
|
|
@ -1073,6 +1124,7 @@ static struct usb_device_id dw2102_table[] = {
|
|||
{USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
|
||||
{USB_DEVICE(0x3011, USB_PID_PROF_1100)},
|
||||
{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
|
||||
{USB_DEVICE(0x3034, 0x7500)},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
@ -1387,9 +1439,30 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
}
|
||||
};
|
||||
|
||||
struct dvb_usb_device_properties *p7500;
|
||||
static struct dvb_usb_device_description d7500 = {
|
||||
"Prof 7500 USB DVB-S2",
|
||||
{&dw2102_table[9], NULL},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static int dw2102_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
|
||||
p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p7500)
|
||||
return -ENOMEM;
|
||||
/* copy default structure */
|
||||
memcpy(p7500, &s6x0_properties,
|
||||
sizeof(struct dvb_usb_device_properties));
|
||||
/* fill only different fields */
|
||||
p7500->firmware = "dvb-usb-p7500.fw";
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc_key_map = tbs_rc_keys;
|
||||
p7500->rc_key_map_size = ARRAY_SIZE(tbs_rc_keys);
|
||||
p7500->adapter->frontend_attach = prof_7500_frontend_attach;
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &dw2104_properties,
|
||||
|
|
@ -1397,6 +1470,8 @@ static int dw2102_probe(struct usb_interface *intf,
|
|||
0 == dvb_usb_device_init(intf, &dw3101_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, &s6x0_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
0 == dvb_usb_device_init(intf, p7500,
|
||||
THIS_MODULE, NULL, adapter_nr))
|
||||
return 0;
|
||||
|
||||
|
|
@ -1431,6 +1506,6 @@ MODULE_AUTHOR("Igor M. Liplianin (c) [email protected]");
|
|||
MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
|
||||
" DVB-C 3101 USB2.0,"
|
||||
" TeVii S600, S630, S650, S660 USB2.0,"
|
||||
" Prof 1100 USB2.0 devices");
|
||||
" Prof 1100, 7500 USB2.0 devices");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ static u8 init_code[][2] = {
|
|||
{0x76, 0x0C},
|
||||
};
|
||||
|
||||
const static int init_code_len = sizeof(init_code) / sizeof(u8[2]);
|
||||
static const int init_code_len = sizeof(init_code) / sizeof(u8[2]);
|
||||
|
||||
static int jdvbt90502_init(struct dvb_frontend *fe)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
#include "qt1010.h"
|
||||
#include "tda1004x.h"
|
||||
#include "tda827x.h"
|
||||
|
||||
#include <media/tuner.h>
|
||||
#include "tuner-simple.h"
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/* debug */
|
||||
|
|
@ -158,11 +161,14 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
|
||||
case 0x93:
|
||||
case 0x92:
|
||||
case 0x83: /* pinnacle PCTV310e */
|
||||
case 0x82:
|
||||
m->rep_count = 0;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
goto unlock;
|
||||
|
||||
case 0x91:
|
||||
case 0x81: /* pinnacle PCTV310e */
|
||||
/* prevent immediate auto-repeat */
|
||||
if (++m->rep_count > 2)
|
||||
*state = REMOTE_KEY_REPEAT;
|
||||
|
|
@ -546,6 +552,14 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(simple_tuner_attach, adap->fe,
|
||||
&adap->dev->i2c_adap, 0x61,
|
||||
TUNER_PHILIPS_FMD1216ME_MK3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* device-specific initialization */
|
||||
static struct m920x_inits megasky_rc_init [] = {
|
||||
{ M9206_RC_INIT2, 0xa8 },
|
||||
|
|
@ -562,6 +576,18 @@ static struct m920x_inits tvwalkertwin_rc_init [] = {
|
|||
{ } /* terminating entry */
|
||||
};
|
||||
|
||||
static struct m920x_inits pinnacle310e_init[] = {
|
||||
/* without these the tuner don't work */
|
||||
{ 0xff20, 0x9b },
|
||||
{ 0xff22, 0x70 },
|
||||
|
||||
/* rc settings */
|
||||
{ 0xff50, 0x80 },
|
||||
{ M9206_RC_INIT1, 0x00 },
|
||||
{ M9206_RC_INIT2, 0xff },
|
||||
{ } /* terminating entry */
|
||||
};
|
||||
|
||||
/* ir keymaps */
|
||||
static struct dvb_usb_rc_key megasky_rc_keys [] = {
|
||||
{ 0x0012, KEY_POWER },
|
||||
|
|
@ -602,11 +628,68 @@ static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = {
|
|||
{ 0x001e, KEY_VOLUMEUP },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key pinnacle310e_rc_keys[] = {
|
||||
{ 0x16, KEY_POWER },
|
||||
{ 0x17, KEY_FAVORITES },
|
||||
{ 0x0f, KEY_TEXT },
|
||||
{ 0x48, KEY_MEDIA }, /* preview */
|
||||
{ 0x1c, KEY_EPG },
|
||||
{ 0x04, KEY_LIST }, /* record list */
|
||||
{ 0x03, KEY_1 },
|
||||
{ 0x01, KEY_2 },
|
||||
{ 0x06, KEY_3 },
|
||||
{ 0x09, KEY_4 },
|
||||
{ 0x1d, KEY_5 },
|
||||
{ 0x1f, KEY_6 },
|
||||
{ 0x0d, KEY_7 },
|
||||
{ 0x19, KEY_8 },
|
||||
{ 0x1b, KEY_9 },
|
||||
{ 0x15, KEY_0 },
|
||||
{ 0x0c, KEY_CANCEL },
|
||||
{ 0x4a, KEY_CLEAR },
|
||||
{ 0x13, KEY_BACK },
|
||||
{ 0x00, KEY_TAB },
|
||||
{ 0x4b, KEY_UP },
|
||||
{ 0x4e, KEY_LEFT },
|
||||
{ 0x52, KEY_RIGHT },
|
||||
{ 0x51, KEY_DOWN },
|
||||
{ 0x4f, KEY_ENTER }, /* could also be KEY_OK */
|
||||
{ 0x1e, KEY_VOLUMEUP },
|
||||
{ 0x0a, KEY_VOLUMEDOWN },
|
||||
{ 0x05, KEY_CHANNELUP },
|
||||
{ 0x02, KEY_CHANNELDOWN },
|
||||
{ 0x11, KEY_RECORD },
|
||||
{ 0x14, KEY_PLAY },
|
||||
{ 0x4c, KEY_PAUSE },
|
||||
{ 0x1a, KEY_STOP },
|
||||
{ 0x40, KEY_REWIND },
|
||||
{ 0x12, KEY_FASTFORWARD },
|
||||
{ 0x41, KEY_PREVIOUSSONG }, /* Replay */
|
||||
{ 0x42, KEY_NEXTSONG }, /* Skip */
|
||||
{ 0x54, KEY_CAMERA }, /* Capture */
|
||||
/* { 0x50, KEY_SAP }, */ /* Sap */
|
||||
{ 0x47, KEY_CYCLEWINDOWS }, /* Pip */
|
||||
{ 0x4d, KEY_SCREEN }, /* FullScreen */
|
||||
{ 0x08, KEY_SUBTITLE },
|
||||
{ 0x0e, KEY_MUTE },
|
||||
/* { 0x49, KEY_LR }, */ /* L/R */
|
||||
{ 0x07, KEY_SLEEP }, /* Hibernate */
|
||||
{ 0x08, KEY_MEDIA }, /* A/V */
|
||||
{ 0x0e, KEY_MENU }, /* Recall */
|
||||
{ 0x45, KEY_ZOOMIN },
|
||||
{ 0x46, KEY_ZOOMOUT },
|
||||
{ 0x18, KEY_TV }, /* Red */
|
||||
{ 0x53, KEY_VCR }, /* Green */
|
||||
{ 0x5e, KEY_SAT }, /* Yellow */
|
||||
{ 0x5f, KEY_PLAYER }, /* Blue */
|
||||
};
|
||||
|
||||
/* DVB USB Driver stuff */
|
||||
static struct dvb_usb_device_properties megasky_properties;
|
||||
static struct dvb_usb_device_properties digivox_mini_ii_properties;
|
||||
static struct dvb_usb_device_properties tvwalkertwin_properties;
|
||||
static struct dvb_usb_device_properties dposh_properties;
|
||||
static struct dvb_usb_device_properties pinnacle_pctv310e_properties;
|
||||
|
||||
static int m920x_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
|
|
@ -652,6 +735,13 @@ static int m920x_probe(struct usb_interface *intf,
|
|||
goto found;
|
||||
}
|
||||
|
||||
ret = dvb_usb_device_init(intf, &pinnacle_pctv310e_properties,
|
||||
THIS_MODULE, &d, adapter_nr);
|
||||
if (ret == 0) {
|
||||
rc_init_seq = pinnacle310e_init;
|
||||
goto found;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
/* Another interface on a multi-tuner device */
|
||||
|
|
@ -682,6 +772,7 @@ static struct usb_device_id m920x_table [] = {
|
|||
USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) },
|
||||
{ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, m920x_table);
|
||||
|
|
@ -895,6 +986,56 @@ static struct dvb_usb_device_properties dposh_properties = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.download_firmware = NULL,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = pinnacle310e_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(pinnacle310e_rc_keys),
|
||||
.rc_query = m920x_rc_query,
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
.pid_filter_count = 8,
|
||||
.pid_filter = m920x_pid_filter,
|
||||
.pid_filter_ctrl = m920x_pid_filter_ctrl,
|
||||
|
||||
.frontend_attach = m920x_mt352_frontend_attach,
|
||||
.tuner_attach = m920x_fmd1216me_tuner_attach,
|
||||
|
||||
.stream = {
|
||||
.type = USB_ISOC,
|
||||
.count = 5,
|
||||
.endpoint = 0x84,
|
||||
.u = {
|
||||
.isoc = {
|
||||
.framesperurb = 128,
|
||||
.framesize = 564,
|
||||
.interval = 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
} },
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Pinnacle PCTV 310e",
|
||||
{ &m920x_table[6], NULL },
|
||||
{ NULL },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static struct usb_driver m920x_driver = {
|
||||
.name = "dvb_usb_m920x",
|
||||
.probe = m920x_probe,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#define M9206_FW 0x30
|
||||
|
||||
#define M9206_MAX_FILTERS 8
|
||||
#define M9206_MAX_ADAPTERS 2
|
||||
#define M9206_MAX_ADAPTERS 4
|
||||
|
||||
/*
|
||||
sequences found in logs:
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||
(msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0),
|
||||
msg[i].buf,
|
||||
msg[i].len
|
||||
)!= msg[i].len)) {
|
||||
)) != msg[i].len) {
|
||||
break;
|
||||
}
|
||||
if (dvb_usb_opera1_debug & 0x10)
|
||||
|
|
|
|||
|
|
@ -90,13 +90,14 @@ static inline struct node_entry *node_of(struct firedtv *fdtv)
|
|||
return container_of(fdtv->device, struct unit_directory, device)->ne;
|
||||
}
|
||||
|
||||
static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
|
||||
static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
|
||||
{
|
||||
quadlet_t *d = data;
|
||||
int ret;
|
||||
|
||||
ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP,
|
||||
(__force quadlet_t *)&data[1], (__force quadlet_t)data[0]);
|
||||
data[0] = data[1];
|
||||
ret = hpsb_node_lock(node_of(fdtv), addr,
|
||||
EXTCODE_COMPARE_SWAP, &d[1], d[0]);
|
||||
d[0] = d[1];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -192,9 +193,13 @@ static int node_probe(struct device *dev)
|
|||
int kv_len, err;
|
||||
void *kv_str;
|
||||
|
||||
kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
|
||||
kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
|
||||
|
||||
if (ud->model_name_kv) {
|
||||
kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4;
|
||||
kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
|
||||
} else {
|
||||
kv_len = 0;
|
||||
kv_str = NULL;
|
||||
}
|
||||
fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
|
||||
if (!fdtv)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@
|
|||
#define EN50221_TAG_CA_INFO 0x9f8031
|
||||
|
||||
struct avc_command_frame {
|
||||
int length;
|
||||
u8 ctype;
|
||||
u8 subunit;
|
||||
u8 opcode;
|
||||
|
|
@ -82,13 +81,27 @@ struct avc_command_frame {
|
|||
};
|
||||
|
||||
struct avc_response_frame {
|
||||
int length;
|
||||
u8 response;
|
||||
u8 subunit;
|
||||
u8 opcode;
|
||||
u8 operand[509];
|
||||
};
|
||||
|
||||
#define LAST_OPERAND (509 - 1)
|
||||
|
||||
static inline void clear_operands(struct avc_command_frame *c, int from, int to)
|
||||
{
|
||||
memset(&c->operand[from], 0, to - from + 1);
|
||||
}
|
||||
|
||||
static void pad_operands(struct avc_command_frame *c, int from)
|
||||
{
|
||||
int to = ALIGN(from, 4);
|
||||
|
||||
if (from <= to && to <= LAST_OPERAND)
|
||||
clear_operands(c, from, to);
|
||||
}
|
||||
|
||||
#define AVC_DEBUG_READ_DESCRIPTOR 0x0001
|
||||
#define AVC_DEBUG_DSIT 0x0002
|
||||
#define AVC_DEBUG_DSD 0x0004
|
||||
|
|
@ -202,78 +215,65 @@ static void debug_pmt(char *msg, int length)
|
|||
16, 1, msg, length, false);
|
||||
}
|
||||
|
||||
static int __avc_write(struct firedtv *fdtv,
|
||||
const struct avc_command_frame *c, struct avc_response_frame *r)
|
||||
static int avc_write(struct firedtv *fdtv)
|
||||
{
|
||||
int err, retry;
|
||||
|
||||
if (r)
|
||||
fdtv->avc_reply_received = false;
|
||||
fdtv->avc_reply_received = false;
|
||||
|
||||
for (retry = 0; retry < 6; retry++) {
|
||||
if (unlikely(avc_debug))
|
||||
debug_fcp(&c->ctype, c->length);
|
||||
debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
|
||||
|
||||
err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
|
||||
(void *)&c->ctype, c->length);
|
||||
fdtv->avc_data, fdtv->avc_data_length);
|
||||
if (err) {
|
||||
fdtv->avc_reply_received = true;
|
||||
dev_err(fdtv->device, "FCP command write failed\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!r)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* AV/C specs say that answers should be sent within 150 ms.
|
||||
* Time out after 200 ms.
|
||||
*/
|
||||
if (wait_event_timeout(fdtv->avc_wait,
|
||||
fdtv->avc_reply_received,
|
||||
msecs_to_jiffies(200)) != 0) {
|
||||
r->length = fdtv->response_length;
|
||||
memcpy(&r->response, fdtv->response, r->length);
|
||||
|
||||
msecs_to_jiffies(200)) != 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dev_err(fdtv->device, "FCP response timed out\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int avc_write(struct firedtv *fdtv,
|
||||
const struct avc_command_frame *c, struct avc_response_frame *r)
|
||||
static bool is_register_rc(struct avc_response_frame *r)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&fdtv->avc_mutex))
|
||||
return -EINTR;
|
||||
|
||||
ret = __avc_write(fdtv, c, r);
|
||||
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
return ret;
|
||||
return r->opcode == AVC_OPCODE_VENDOR &&
|
||||
r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
|
||||
r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
|
||||
r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
|
||||
r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
|
||||
}
|
||||
|
||||
int avc_recv(struct firedtv *fdtv, void *data, size_t length)
|
||||
{
|
||||
struct avc_response_frame *r =
|
||||
data - offsetof(struct avc_response_frame, response);
|
||||
struct avc_response_frame *r = data;
|
||||
|
||||
if (unlikely(avc_debug))
|
||||
debug_fcp(data, length);
|
||||
|
||||
if (length >= 8 &&
|
||||
r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
|
||||
r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
|
||||
r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
|
||||
r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
|
||||
if (r->response == AVC_RESPONSE_CHANGED) {
|
||||
fdtv_handle_rc(fdtv,
|
||||
r->operand[4] << 8 | r->operand[5]);
|
||||
if (length >= 8 && is_register_rc(r)) {
|
||||
switch (r->response) {
|
||||
case AVC_RESPONSE_CHANGED:
|
||||
fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
|
||||
schedule_work(&fdtv->remote_ctrl_work);
|
||||
} else if (r->response != AVC_RESPONSE_INTERIM) {
|
||||
break;
|
||||
case AVC_RESPONSE_INTERIM:
|
||||
if (is_register_rc((void *)fdtv->avc_data))
|
||||
goto wake;
|
||||
break;
|
||||
default:
|
||||
dev_info(fdtv->device,
|
||||
"remote control result = %d\n", r->response);
|
||||
}
|
||||
|
|
@ -285,9 +285,9 @@ int avc_recv(struct firedtv *fdtv, void *data, size_t length)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(fdtv->response, data, length);
|
||||
fdtv->response_length = length;
|
||||
|
||||
memcpy(fdtv->avc_data, data, length);
|
||||
fdtv->avc_data_length = length;
|
||||
wake:
|
||||
fdtv->avc_reply_received = true;
|
||||
wake_up(&fdtv->avc_wait);
|
||||
|
||||
|
|
@ -318,10 +318,11 @@ static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
|
|||
* tuning command for setting the relative LNB frequency
|
||||
* (not supported by the AVC standard)
|
||||
*/
|
||||
static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params,
|
||||
struct avc_command_frame *c)
|
||||
static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
|
||||
c->opcode = AVC_OPCODE_VENDOR;
|
||||
|
||||
c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
|
||||
|
|
@ -370,16 +371,18 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
|
|||
c->operand[13] = 0x1;
|
||||
c->operand[14] = 0xff;
|
||||
c->operand[15] = 0xff;
|
||||
c->length = 20;
|
||||
|
||||
return 16;
|
||||
} else {
|
||||
c->length = 16;
|
||||
return 13;
|
||||
}
|
||||
}
|
||||
|
||||
static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params,
|
||||
struct avc_command_frame *c)
|
||||
static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
|
||||
c->opcode = AVC_OPCODE_DSD;
|
||||
|
||||
c->operand[0] = 0; /* source plug */
|
||||
|
|
@ -440,15 +443,14 @@ static void avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
|
|||
c->operand[20] = 0x00;
|
||||
c->operand[21] = 0x00;
|
||||
|
||||
/* Add PIDs to filter */
|
||||
c->length = ALIGN(22 + add_pid_filter(fdtv, &c->operand[22]) + 3, 4);
|
||||
return 22 + add_pid_filter(fdtv, &c->operand[22]);
|
||||
}
|
||||
|
||||
static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params,
|
||||
struct avc_command_frame *c)
|
||||
static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct dvb_ofdm_parameters *ofdm = ¶ms->u.ofdm;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
|
||||
c->opcode = AVC_OPCODE_DSD;
|
||||
|
||||
|
|
@ -543,55 +545,58 @@ static void avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
|
|||
c->operand[15] = 0x00; /* network_ID[0] */
|
||||
c->operand[16] = 0x00; /* network_ID[1] */
|
||||
|
||||
/* Add PIDs to filter */
|
||||
c->length = ALIGN(17 + add_pid_filter(fdtv, &c->operand[17]) + 3, 4);
|
||||
return 17 + add_pid_filter(fdtv, &c->operand[17]);
|
||||
}
|
||||
|
||||
int avc_tuner_dsd(struct firedtv *fdtv,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int pos, ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
||||
switch (fdtv->type) {
|
||||
case FIREDTV_DVB_S:
|
||||
case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
|
||||
case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(fdtv, params, c); break;
|
||||
case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(fdtv, params, c); break;
|
||||
case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, params); break;
|
||||
case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, params); break;
|
||||
case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, params); break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
pad_operands(c, pos);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
|
||||
msleep(500);
|
||||
fdtv->avc_data_length = ALIGN(3 + pos, 4);
|
||||
ret = avc_write(fdtv);
|
||||
#if 0
|
||||
/* FIXME: */
|
||||
/* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
|
||||
/*
|
||||
* FIXME:
|
||||
* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
|
||||
* Check for AVC_RESPONSE_ACCEPTED here instead?
|
||||
*/
|
||||
if (status)
|
||||
*status = r->operand[2];
|
||||
#endif
|
||||
return 0;
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
if (ret == 0)
|
||||
msleep(500);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
|
||||
int pos, k;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int ret, pos, k;
|
||||
|
||||
if (pidc > 16 && pidc != 0xff)
|
||||
return -EINVAL;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -614,24 +619,27 @@ int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
|
|||
c->operand[pos++] = 0x00; /* tableID */
|
||||
c->operand[pos++] = 0x00; /* filter_length */
|
||||
}
|
||||
pad_operands(c, pos);
|
||||
|
||||
c->length = ALIGN(3 + pos, 4);
|
||||
fdtv->avc_data_length = ALIGN(3 + pos, 4);
|
||||
ret = avc_write(fdtv);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
/* FIXME: check response code? */
|
||||
|
||||
msleep(50);
|
||||
return 0;
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
if (ret == 0)
|
||||
msleep(50);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_tuner_get_ts(struct firedtv *fdtv)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
|
||||
int sl;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int ret, sl;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -646,26 +654,33 @@ int avc_tuner_get_ts(struct firedtv *fdtv)
|
|||
c->operand[4] = 0x00; /* antenna number */
|
||||
c->operand[5] = 0x0; /* system_specific_search_flags */
|
||||
c->operand[6] = sl; /* system_specific_multiplex selection_length */
|
||||
c->operand[7] = 0x00; /* valid_flags [0] */
|
||||
c->operand[8] = 0x00; /* valid_flags [1] */
|
||||
c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
|
||||
/*
|
||||
* operand[7]: valid_flags[0]
|
||||
* operand[8]: valid_flags[1]
|
||||
* operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
|
||||
*/
|
||||
clear_operands(c, 7, 24);
|
||||
|
||||
c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
|
||||
fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
|
||||
ret = avc_write(fdtv);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
/* FIXME: check response code? */
|
||||
|
||||
msleep(250);
|
||||
return 0;
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
if (ret == 0)
|
||||
msleep(250);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_identify_subunit(struct firedtv *fdtv)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -678,31 +693,34 @@ int avc_identify_subunit(struct firedtv *fdtv)
|
|||
c->operand[4] = 0x08; /* length lowbyte */
|
||||
c->operand[5] = 0x00; /* offset highbyte */
|
||||
c->operand[6] = 0x0d; /* offset lowbyte */
|
||||
clear_operands(c, 7, 8); /* padding */
|
||||
|
||||
c->length = 12;
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if ((r->response != AVC_RESPONSE_STABLE &&
|
||||
r->response != AVC_RESPONSE_ACCEPTED) ||
|
||||
(r->operand[3] << 8) + r->operand[4] != 8) {
|
||||
dev_err(fdtv->device, "cannot read subunit identifier\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define SIZEOF_ANTENNA_INPUT_INFO 22
|
||||
|
||||
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
int length;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int length, ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -710,27 +728,30 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
|
|||
|
||||
c->operand[0] = DESCRIPTOR_TUNER_STATUS;
|
||||
c->operand[1] = 0xff; /* read_result_status */
|
||||
c->operand[2] = 0x00; /* reserved */
|
||||
c->operand[3] = 0; /* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
|
||||
c->operand[4] = 0; /* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
|
||||
c->operand[5] = 0x00;
|
||||
c->operand[6] = 0x00;
|
||||
/*
|
||||
* operand[2]: reserved
|
||||
* operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
|
||||
* operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
|
||||
*/
|
||||
clear_operands(c, 2, 31);
|
||||
|
||||
c->length = 12;
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (r->response != AVC_RESPONSE_STABLE &&
|
||||
r->response != AVC_RESPONSE_ACCEPTED) {
|
||||
dev_err(fdtv->device, "cannot read tuner status\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = r->operand[9];
|
||||
if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
|
||||
dev_err(fdtv->device, "got invalid tuner status\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
stat->active_system = r->operand[10];
|
||||
|
|
@ -766,20 +787,21 @@ int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
|
|||
stat->ca_dvb_flag = r->operand[31] >> 3 & 1;
|
||||
stat->ca_error_flag = r->operand[31] >> 2 & 1;
|
||||
stat->ca_initialization_status = r->operand[31] >> 1 & 1;
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
|
||||
char conttone, char nrdiseq,
|
||||
struct dvb_diseqc_master_cmd *diseqcmd)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
int i, j, k;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int pos, j, k, ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -789,41 +811,41 @@ int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
|
|||
c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
|
||||
c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
|
||||
c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
|
||||
|
||||
c->operand[4] = voltage;
|
||||
c->operand[5] = nrdiseq;
|
||||
|
||||
i = 6;
|
||||
|
||||
pos = 6;
|
||||
for (j = 0; j < nrdiseq; j++) {
|
||||
c->operand[i++] = diseqcmd[j].msg_len;
|
||||
c->operand[pos++] = diseqcmd[j].msg_len;
|
||||
|
||||
for (k = 0; k < diseqcmd[j].msg_len; k++)
|
||||
c->operand[i++] = diseqcmd[j].msg[k];
|
||||
c->operand[pos++] = diseqcmd[j].msg[k];
|
||||
}
|
||||
c->operand[pos++] = burst;
|
||||
c->operand[pos++] = conttone;
|
||||
pad_operands(c, pos);
|
||||
|
||||
c->operand[i++] = burst;
|
||||
c->operand[i++] = conttone;
|
||||
|
||||
c->length = ALIGN(3 + i, 4);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = ALIGN(3 + pos, 4);
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (r->response != AVC_RESPONSE_ACCEPTED) {
|
||||
dev_err(fdtv->device, "LNB control failed\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_register_remote_control(struct firedtv *fdtv)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_NOTIFY;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
|
||||
|
|
@ -833,10 +855,16 @@ int avc_register_remote_control(struct firedtv *fdtv)
|
|||
c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
|
||||
c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
|
||||
c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
|
||||
c->operand[4] = 0; /* padding */
|
||||
|
||||
c->length = 8;
|
||||
fdtv->avc_data_length = 8;
|
||||
ret = avc_write(fdtv);
|
||||
|
||||
return avc_write(fdtv, c, NULL);
|
||||
/* FIXME: check response code? */
|
||||
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void avc_remote_ctrl_work(struct work_struct *work)
|
||||
|
|
@ -851,11 +879,10 @@ void avc_remote_ctrl_work(struct work_struct *work)
|
|||
#if 0 /* FIXME: unused */
|
||||
int avc_tuner_host2ca(struct firedtv *fdtv)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -867,15 +894,16 @@ int avc_tuner_host2ca(struct firedtv *fdtv)
|
|||
c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
|
||||
c->operand[4] = 0; /* slot */
|
||||
c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
|
||||
c->operand[6] = 0; /* more/last */
|
||||
c->operand[7] = 0; /* length */
|
||||
clear_operands(c, 6, 8);
|
||||
|
||||
c->length = 12;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
/* FIXME: check response code? */
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -906,12 +934,11 @@ static int get_ca_object_length(struct avc_response_frame *r)
|
|||
|
||||
int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
int pos;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int pos, ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_STATUS;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -923,11 +950,12 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
|
|||
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
|
||||
c->operand[4] = 0; /* slot */
|
||||
c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
|
||||
clear_operands(c, 6, LAST_OPERAND);
|
||||
|
||||
c->length = 12;
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* FIXME: check response code and validate response data */
|
||||
|
||||
|
|
@ -939,18 +967,19 @@ int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
|
|||
app_info[4] = 0x01;
|
||||
memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
|
||||
*len = app_info[3] + 4;
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
int pos;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int pos, ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_STATUS;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -962,11 +991,14 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
|
|||
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
|
||||
c->operand[4] = 0; /* slot */
|
||||
c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
|
||||
clear_operands(c, 6, LAST_OPERAND);
|
||||
|
||||
c->length = 12;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
/* FIXME: check response code and validate response data */
|
||||
|
||||
pos = get_ca_object_pos(r);
|
||||
app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
|
||||
|
|
@ -976,17 +1008,18 @@ int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
|
|||
app_info[4] = r->operand[pos + 0];
|
||||
app_info[5] = r->operand[pos + 1];
|
||||
*len = app_info[3] + 4;
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_ca_reset(struct firedtv *fdtv)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -1002,19 +1035,20 @@ int avc_ca_reset(struct firedtv *fdtv)
|
|||
c->operand[7] = 1; /* length */
|
||||
c->operand[8] = 0; /* force hardware reset */
|
||||
|
||||
c->length = 12;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
/* FIXME: check response code? */
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int list_management;
|
||||
int program_info_length;
|
||||
int pmt_cmd_id;
|
||||
|
|
@ -1022,11 +1056,12 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
|||
int write_pos;
|
||||
int es_info_length;
|
||||
int crc32_csum;
|
||||
int ret;
|
||||
|
||||
if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
|
||||
debug_pmt(msg, length);
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_CONTROL;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -1058,7 +1093,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
|||
|
||||
c->operand[12] = 0x02; /* Table id=2 */
|
||||
c->operand[13] = 0x80; /* Section syntax + length */
|
||||
/* c->operand[14] = XXXprogram_info_length + 12; */
|
||||
|
||||
c->operand[15] = msg[1]; /* Program number */
|
||||
c->operand[16] = msg[2];
|
||||
c->operand[17] = 0x01; /* Version number=0 + current/next=1 */
|
||||
|
|
@ -1106,12 +1141,7 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
|||
write_pos += es_info_length;
|
||||
}
|
||||
}
|
||||
|
||||
/* CRC */
|
||||
c->operand[write_pos++] = 0x00;
|
||||
c->operand[write_pos++] = 0x00;
|
||||
c->operand[write_pos++] = 0x00;
|
||||
c->operand[write_pos++] = 0x00;
|
||||
write_pos += 4; /* CRC */
|
||||
|
||||
c->operand[7] = 0x82;
|
||||
c->operand[8] = (write_pos - 10) >> 8;
|
||||
|
|
@ -1123,28 +1153,31 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
|
|||
c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
|
||||
c->operand[write_pos - 2] = (crc32_csum >> 8) & 0xff;
|
||||
c->operand[write_pos - 1] = (crc32_csum >> 0) & 0xff;
|
||||
pad_operands(c, write_pos);
|
||||
|
||||
c->length = ALIGN(3 + write_pos, 4);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (r->response != AVC_RESPONSE_ACCEPTED) {
|
||||
dev_err(fdtv->device,
|
||||
"CA PMT failed with response 0x%x\n", r->response);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_STATUS;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -1156,28 +1189,28 @@ int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
|
|||
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
|
||||
c->operand[4] = 0; /* slot */
|
||||
c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
|
||||
c->operand[6] = 0; /* more/last */
|
||||
c->operand[7] = 0; /* length */
|
||||
clear_operands(c, 6, LAST_OPERAND);
|
||||
|
||||
c->length = 12;
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* FIXME: check response code and validate response data */
|
||||
|
||||
*interval = r->operand[get_ca_object_pos(r)];
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_ca_enter_menu(struct firedtv *fdtv)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_STATUS;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -1189,24 +1222,25 @@ int avc_ca_enter_menu(struct firedtv *fdtv)
|
|||
c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
|
||||
c->operand[4] = 0; /* slot */
|
||||
c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
|
||||
c->operand[6] = 0; /* more/last */
|
||||
c->operand[7] = 0; /* length */
|
||||
clear_operands(c, 6, 8);
|
||||
|
||||
c->length = 12;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
/* FIXME: check response code? */
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
|
||||
{
|
||||
char buffer[sizeof(struct avc_command_frame)];
|
||||
struct avc_command_frame *c = (void *)buffer;
|
||||
struct avc_response_frame *r = (void *)buffer;
|
||||
struct avc_command_frame *c = (void *)fdtv->avc_data;
|
||||
struct avc_response_frame *r = (void *)fdtv->avc_data;
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof(*c));
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
c->ctype = AVC_CTYPE_STATUS;
|
||||
c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
|
||||
|
|
@ -1218,20 +1252,21 @@ int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
|
|||
c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
|
||||
c->operand[4] = 0; /* slot */
|
||||
c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
|
||||
c->operand[6] = 0; /* more/last */
|
||||
c->operand[7] = 0; /* length */
|
||||
clear_operands(c, 6, LAST_OPERAND);
|
||||
|
||||
c->length = 12;
|
||||
|
||||
if (avc_write(fdtv, c, r) < 0)
|
||||
return -EIO;
|
||||
fdtv->avc_data_length = 12;
|
||||
ret = avc_write(fdtv);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* FIXME: check response code and validate response data */
|
||||
|
||||
*len = get_ca_object_length(r);
|
||||
memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
|
||||
out:
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL
|
||||
|
|
@ -1240,14 +1275,14 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&fdtv->avc_mutex))
|
||||
return -EINTR;
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
ret = fdtv->backend->read(fdtv, addr, data);
|
||||
if (ret < 0)
|
||||
dev_err(fdtv->device, "CMP: read I/O error\n");
|
||||
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1255,14 +1290,19 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&fdtv->avc_mutex))
|
||||
return -EINTR;
|
||||
mutex_lock(&fdtv->avc_mutex);
|
||||
|
||||
ret = fdtv->backend->lock(fdtv, addr, data);
|
||||
/* data[] is stack-allocated and should not be DMA-mapped. */
|
||||
memcpy(fdtv->avc_data, data, 8);
|
||||
|
||||
ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
|
||||
if (ret < 0)
|
||||
dev_err(fdtv->device, "CMP: lock I/O error\n");
|
||||
else
|
||||
memcpy(data, fdtv->avc_data, 8);
|
||||
|
||||
mutex_unlock(&fdtv->avc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,6 @@ struct firedtv *fdtv_alloc(struct device *dev,
|
|||
|
||||
mutex_init(&fdtv->avc_mutex);
|
||||
init_waitqueue_head(&fdtv->avc_wait);
|
||||
fdtv->avc_reply_received = true;
|
||||
mutex_init(&fdtv->demux_mutex);
|
||||
INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
|
|||
return rcode != RCODE_COMPLETE ? -EIO : 0;
|
||||
}
|
||||
|
||||
static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
|
||||
static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
|
||||
{
|
||||
return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ struct input_dev;
|
|||
struct firedtv;
|
||||
|
||||
struct firedtv_backend {
|
||||
int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]);
|
||||
int (*lock)(struct firedtv *fdtv, u64 addr, void *data);
|
||||
int (*read)(struct firedtv *fdtv, u64 addr, void *data);
|
||||
int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
|
||||
int (*start_iso)(struct firedtv *fdtv);
|
||||
|
|
@ -114,8 +114,8 @@ struct firedtv {
|
|||
unsigned long channel_active;
|
||||
u16 channel_pid[16];
|
||||
|
||||
size_t response_length;
|
||||
u8 response[512];
|
||||
int avc_data_length;
|
||||
u8 avc_data[512];
|
||||
};
|
||||
|
||||
/* firedtv-1394.c */
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ enum af9013_tuner {
|
|||
AF9013_TUNER_MT2060_2 = 147, /* Microtune */
|
||||
AF9013_TUNER_TDA18271 = 156, /* NXP */
|
||||
AF9013_TUNER_QT1010A = 162, /* Quantek */
|
||||
AF9013_TUNER_TDA18218 = 179, /* NXP */
|
||||
};
|
||||
|
||||
/* AF9013/5 GPIOs (mostly guessed)
|
||||
|
|
|
|||
|
|
@ -170,6 +170,19 @@ static int is_locked(struct atbm_state *priv, u8 *locked)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_agc_config(struct atbm_state *priv,
|
||||
u8 min, u8 max, u8 hold_loop)
|
||||
{
|
||||
/* no effect if both min and max are zero */
|
||||
if (!min && !max)
|
||||
return 0;
|
||||
|
||||
atbm8830_write_reg(priv, REG_AGC_MIN, min);
|
||||
atbm8830_write_reg(priv, REG_AGC_MAX, max);
|
||||
atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_static_channel_mode(struct atbm_state *priv)
|
||||
{
|
||||
|
|
@ -227,6 +240,9 @@ static int atbm8830_init(struct dvb_frontend *fe)
|
|||
/*Set IF frequency*/
|
||||
set_if_freq(priv, cfg->if_freq);
|
||||
|
||||
/*Set AGC Config*/
|
||||
set_agc_config(priv, cfg->agc_min, cfg->agc_max,
|
||||
cfg->agc_hold_loop);
|
||||
|
||||
/*Set static channel mode*/
|
||||
set_static_channel_mode(priv);
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ static int dib0090_sleep(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
|
||||
void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
|
||||
{
|
||||
struct dib0090_state *state = fe->tuner_priv;
|
||||
if (fast)
|
||||
|
|
|
|||
|
|
@ -1999,6 +1999,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
|
|||
struct dib8000_state *state = fe->demodulator_priv;
|
||||
int time, ret;
|
||||
|
||||
fe->dtv_property_cache.delivery_system = SYS_ISDBT;
|
||||
|
||||
dib8000_set_output_mode(state, OUTMODE_HIGH_Z);
|
||||
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
|
|||
EXPORT_SYMBOL(dibx000_exit_i2c_master);
|
||||
|
||||
|
||||
u32 systime()
|
||||
u32 systime(void)
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
|
|
|
|||
|
|
@ -158,7 +158,8 @@ static struct dvb_frontend *lnbx2x_attach(struct dvb_frontend *fe,
|
|||
/* override frontend ops */
|
||||
fe->ops.set_voltage = lnbp21_set_voltage;
|
||||
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
|
||||
fe->ops.set_tone = lnbp21_set_tone;
|
||||
if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/
|
||||
fe->ops.set_tone = lnbp21_set_tone;
|
||||
printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
|
||||
|
||||
return fe;
|
||||
|
|
|
|||
|
|
@ -97,8 +97,6 @@
|
|||
#define LNB_SUPPLY_CTRL_REG_4 0xce
|
||||
#define LNB_SUPPLY_STATUS_REG 0xcf
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#define FAIL -1
|
||||
#define PASS 0
|
||||
|
||||
|
|
@ -718,7 +716,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
|
|||
int fine_tune_freq;
|
||||
unsigned char sample_rate = 0;
|
||||
/* boolean */
|
||||
unsigned int inband_interferer_ind;
|
||||
bool inband_interferer_ind;
|
||||
|
||||
/* INTERMEDIATE VALUES */
|
||||
int icoarse_tune_freq; /* MHz */
|
||||
|
|
@ -728,15 +726,8 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
|
|||
unsigned int x1;
|
||||
unsigned int x2;
|
||||
int i;
|
||||
unsigned int inband_interferer_div2[ALLOWABLE_FS_COUNT] = {
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE
|
||||
};
|
||||
unsigned int inband_interferer_div4[ALLOWABLE_FS_COUNT] = {
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||
FALSE, FALSE, FALSE, FALSE, FALSE
|
||||
};
|
||||
|
||||
bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
|
||||
bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
|
||||
int status;
|
||||
|
||||
/* allowable sample rates for ADC in MHz */
|
||||
|
|
@ -762,7 +753,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
|
|||
}
|
||||
|
||||
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
|
||||
inband_interferer_div2[i] = inband_interferer_div4[i] = FALSE;
|
||||
inband_interferer_div2[i] = inband_interferer_div4[i] = false;
|
||||
|
||||
if_limit_high = -700000;
|
||||
if_limit_low = -100000;
|
||||
|
|
@ -798,7 +789,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
if (((band_low < x1) && (x1 < band_high)) ||
|
||||
((band_low < x2) && (x2 < band_high)))
|
||||
inband_interferer_div4[i] = TRUE;
|
||||
inband_interferer_div4[i] = true;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -811,25 +802,28 @@ static int si21xx_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
if (((band_low < x1) && (x1 < band_high)) ||
|
||||
((band_low < x2) && (x2 < band_high)))
|
||||
inband_interferer_div2[i] = TRUE;
|
||||
inband_interferer_div2[i] = true;
|
||||
}
|
||||
|
||||
inband_interferer_ind = TRUE;
|
||||
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
|
||||
inband_interferer_ind &= inband_interferer_div2[i] |
|
||||
inband_interferer_div4[i];
|
||||
inband_interferer_ind = true;
|
||||
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
|
||||
if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
|
||||
inband_interferer_ind = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inband_interferer_ind) {
|
||||
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
|
||||
if (inband_interferer_div2[i] == FALSE) {
|
||||
if (!inband_interferer_div2[i]) {
|
||||
sample_rate = (u8) afs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
|
||||
if ((inband_interferer_div2[i] |
|
||||
inband_interferer_div4[i]) == FALSE) {
|
||||
if ((inband_interferer_div2[i] ||
|
||||
!inband_interferer_div4[i])) {
|
||||
sample_rate = (u8) afs[i];
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ struct stv0900_config {
|
|||
u8 tun2_maddress;
|
||||
u8 tun1_adc;/* 1 for stv6110, 2 for stb6100 */
|
||||
u8 tun2_adc;
|
||||
u8 tun1_type;/* for now 3 for stb6100 auto, else - software */
|
||||
u8 tun2_type;
|
||||
/* Set device param to start dma */
|
||||
int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg)
|
|||
return buf;
|
||||
}
|
||||
|
||||
void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
|
||||
static void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
|
||||
{
|
||||
u8 position = 0, i = 0;
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label)
|
|||
return val;
|
||||
}
|
||||
|
||||
enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
|
||||
static enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
|
|||
return STV0900_NO_ERROR;
|
||||
}
|
||||
|
||||
u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
|
||||
static u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
|
||||
{
|
||||
u32 mclk = 90000000, div = 0, ad_div = 0;
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
|
|||
return mclk;
|
||||
}
|
||||
|
||||
enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
|
||||
static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
|
||||
{
|
||||
u32 m_div, clk_sel;
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
|
|||
return STV0900_NO_ERROR;
|
||||
}
|
||||
|
||||
u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr,
|
||||
static u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr,
|
||||
enum fe_stv0900_demod_num demod)
|
||||
{
|
||||
u32 lsb, msb, hsb, err_val;
|
||||
|
|
@ -567,6 +567,46 @@ void stv0900_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
|
|||
}
|
||||
}
|
||||
|
||||
u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod)
|
||||
{
|
||||
u32 freq, round;
|
||||
/* Formulat :
|
||||
Tuner_Frequency(MHz) = Regs / 64
|
||||
Tuner_granularity(MHz) = Regs / 2048
|
||||
real_Tuner_Frequency = Tuner_Frequency(MHz) - Tuner_granularity(MHz)
|
||||
*/
|
||||
freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) +
|
||||
(stv0900_get_bits(intp, TUN_RFFREQ1) << 2) +
|
||||
stv0900_get_bits(intp, TUN_RFFREQ0);
|
||||
|
||||
freq = (freq * 1000) / 64;
|
||||
|
||||
round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) +
|
||||
stv0900_get_bits(intp, TUN_RFRESTE0);
|
||||
|
||||
round = (round * 1000) / 2048;
|
||||
|
||||
return freq + round;
|
||||
}
|
||||
|
||||
void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
|
||||
u32 Bandwidth, int demod)
|
||||
{
|
||||
u32 tunerFrequency;
|
||||
/* Formulat:
|
||||
Tuner_frequency_reg= Frequency(MHz)*64
|
||||
*/
|
||||
tunerFrequency = (Frequency * 64) / 1000;
|
||||
|
||||
stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10));
|
||||
stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff);
|
||||
stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03));
|
||||
/* Low Pass Filter = BW /2 (MHz)*/
|
||||
stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000);
|
||||
/* Tuner Write trig */
|
||||
stv0900_write_reg(intp, TNRLD, 1);
|
||||
}
|
||||
|
||||
static s32 stv0900_get_rf_level(struct stv0900_internal *intp,
|
||||
const struct stv0900_table *lookup,
|
||||
enum fe_stv0900_demod_num demod)
|
||||
|
|
@ -1329,7 +1369,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
|||
enum fe_stv0900_error error = STV0900_NO_ERROR;
|
||||
enum fe_stv0900_error demodError = STV0900_NO_ERROR;
|
||||
struct stv0900_internal *intp = NULL;
|
||||
|
||||
int selosci, i;
|
||||
|
||||
struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
|
||||
|
|
@ -1345,7 +1384,14 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
|||
} else {
|
||||
state->internal = kmalloc(sizeof(struct stv0900_internal),
|
||||
GFP_KERNEL);
|
||||
if (state->internal == NULL)
|
||||
return STV0900_INVALID_HANDLE;
|
||||
temp_int = append_internal(state->internal);
|
||||
if (temp_int == NULL) {
|
||||
kfree(state->internal);
|
||||
state->internal = NULL;
|
||||
return STV0900_INVALID_HANDLE;
|
||||
}
|
||||
state->internal->dmds_used = 1;
|
||||
state->internal->i2c_adap = state->i2c_adap;
|
||||
state->internal->i2c_addr = state->config->demod_address;
|
||||
|
|
@ -1371,11 +1417,6 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
|||
return error;
|
||||
}
|
||||
|
||||
if (state->internal == NULL) {
|
||||
error = STV0900_INVALID_HANDLE;
|
||||
return error;
|
||||
}
|
||||
|
||||
intp = state->internal;
|
||||
|
||||
intp->demod_mode = p_init->demod_mode;
|
||||
|
|
@ -1404,6 +1445,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
|||
stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0);
|
||||
}
|
||||
|
||||
intp->tuner_type[0] = p_init->tuner1_type;
|
||||
intp->tuner_type[1] = p_init->tuner2_type;
|
||||
/* tuner init */
|
||||
switch (p_init->tuner1_type) {
|
||||
case 3: /*FE_AUTO_STB6100:*/
|
||||
stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c);
|
||||
stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86);
|
||||
stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18);
|
||||
stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */
|
||||
stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05);
|
||||
stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17);
|
||||
stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f);
|
||||
stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0);
|
||||
stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3);
|
||||
break;
|
||||
/* case FE_SW_TUNER: */
|
||||
default:
|
||||
stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6);
|
||||
break;
|
||||
}
|
||||
|
||||
stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
|
||||
switch (p_init->tuner1_adc) {
|
||||
case 1:
|
||||
|
|
@ -1413,6 +1475,27 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
|||
break;
|
||||
}
|
||||
|
||||
stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */
|
||||
|
||||
/* tuner init */
|
||||
switch (p_init->tuner2_type) {
|
||||
case 3: /*FE_AUTO_STB6100:*/
|
||||
stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c);
|
||||
stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86);
|
||||
stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18);
|
||||
stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */
|
||||
stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05);
|
||||
stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17);
|
||||
stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f);
|
||||
stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0);
|
||||
stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3);
|
||||
break;
|
||||
/* case FE_SW_TUNER: */
|
||||
default:
|
||||
stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6);
|
||||
break;
|
||||
}
|
||||
|
||||
stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress);
|
||||
switch (p_init->tuner2_adc) {
|
||||
case 1:
|
||||
|
|
@ -1422,6 +1505,8 @@ static enum fe_stv0900_error stv0900_init_internal(struct dvb_frontend *fe,
|
|||
break;
|
||||
}
|
||||
|
||||
stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */
|
||||
|
||||
stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv);
|
||||
stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv);
|
||||
stv0900_set_mclk(intp, 135000000);
|
||||
|
|
@ -1824,10 +1909,12 @@ struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
|
|||
init_params.tun1_maddress = config->tun1_maddress;
|
||||
init_params.tun1_iq_inv = STV0900_IQ_NORMAL;
|
||||
init_params.tuner1_adc = config->tun1_adc;
|
||||
init_params.tuner1_type = config->tun1_type;
|
||||
init_params.path2_ts_clock = config->path2_mode;
|
||||
init_params.ts_config = config->ts_config_regs;
|
||||
init_params.tun2_maddress = config->tun2_maddress;
|
||||
init_params.tuner2_adc = config->tun2_adc;
|
||||
init_params.tuner2_type = config->tun2_type;
|
||||
init_params.tun2_iq_inv = STV0900_IQ_SWAPPED;
|
||||
|
||||
err_stv0900 = stv0900_init_internal(&state->frontend,
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ struct stv0900_init_params{
|
|||
|
||||
u8 tun1_maddress;
|
||||
int tuner1_adc;
|
||||
int tuner1_type;
|
||||
|
||||
/* IQ from the tuner1 to the demod */
|
||||
enum stv0900_iq_inversion tun1_iq_inv;
|
||||
|
|
@ -254,6 +255,7 @@ struct stv0900_init_params{
|
|||
|
||||
u8 tun2_maddress;
|
||||
int tuner2_adc;
|
||||
int tuner2_type;
|
||||
|
||||
/* IQ from the tuner2 to the demod */
|
||||
enum stv0900_iq_inversion tun2_iq_inv;
|
||||
|
|
@ -309,6 +311,8 @@ struct stv0900_internal{
|
|||
s32 bw[2];
|
||||
s32 symbol_rate[2];
|
||||
s32 srch_range[2];
|
||||
/* for software/auto tuner */
|
||||
int tuner_type[2];
|
||||
|
||||
/* algorithm for search Blind, Cold or Warm*/
|
||||
enum fe_stv0900_search_algo srch_algo[2];
|
||||
|
|
@ -394,4 +398,11 @@ extern enum
|
|||
fe_stv0900_tracking_standard stv0900_get_standard(struct dvb_frontend *fe,
|
||||
enum fe_stv0900_demod_num demod);
|
||||
|
||||
extern u32
|
||||
stv0900_get_freq_auto(struct stv0900_internal *intp, int demod);
|
||||
|
||||
extern void
|
||||
stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
|
||||
u32 Bandwidth, int demod);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3174,17 +3174,21 @@ extern s32 shiftx(s32 x, int demod, s32 shift);
|
|||
#define R0900_P1_TNRRF1 0xf4e9
|
||||
#define TNRRF1 REGx(R0900_P1_TNRRF1)
|
||||
#define F0900_P1_TUN_RFFREQ2 0xf4e900ff
|
||||
#define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2)
|
||||
|
||||
/*P1_TNRRF0*/
|
||||
#define R0900_P1_TNRRF0 0xf4ea
|
||||
#define TNRRF0 REGx(R0900_P1_TNRRF0)
|
||||
#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff
|
||||
#define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1)
|
||||
|
||||
/*P1_TNRBW*/
|
||||
#define R0900_P1_TNRBW 0xf4eb
|
||||
#define TNRBW REGx(R0900_P1_TNRBW)
|
||||
#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0
|
||||
#define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0)
|
||||
#define F0900_P1_TUN_BW 0xf4eb003f
|
||||
#define TUN_BW FLDx(F0900_P1_TUN_BW)
|
||||
|
||||
/*P1_TNRADJ*/
|
||||
#define R0900_P1_TNRADJ 0xf4ec
|
||||
|
|
@ -3234,11 +3238,13 @@ extern s32 shiftx(s32 x, int demod, s32 shift);
|
|||
#define F0900_P1_TUN_I2CLOCKED 0xf4f60010
|
||||
#define F0900_P1_TUN_PROGDONE 0xf4f6000c
|
||||
#define F0900_P1_TUN_RFRESTE1 0xf4f60003
|
||||
#define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1)
|
||||
|
||||
/*P1_TNRRESTE*/
|
||||
#define R0900_P1_TNRRESTE 0xf4f7
|
||||
#define TNRRESTE REGx(R0900_P1_TNRRESTE)
|
||||
#define F0900_P1_TUN_RFRESTE0 0xf4f700ff
|
||||
#define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0)
|
||||
|
||||
/*P1_SMAPCOEF7*/
|
||||
#define R0900_P1_SMAPCOEF7 0xf500
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ static int stv0900_search_carr_sw_loop(struct stv0900_internal *intp,
|
|||
return lock;
|
||||
}
|
||||
|
||||
int stv0900_sw_algo(struct stv0900_internal *intp,
|
||||
static int stv0900_sw_algo(struct stv0900_internal *intp,
|
||||
enum fe_stv0900_demod_num demod)
|
||||
{
|
||||
int lock = FALSE,
|
||||
|
|
@ -606,7 +606,12 @@ static int stv0900_get_demod_cold_lock(struct dvb_frontend *fe,
|
|||
tuner_freq -= (current_step * currier_step);
|
||||
|
||||
if (intp->chip_id <= 0x20) {
|
||||
stv0900_set_tuner(fe, tuner_freq, intp->bw[d]);
|
||||
if (intp->tuner_type[d] == 3)
|
||||
stv0900_set_tuner_auto(intp, tuner_freq,
|
||||
intp->bw[d], demod);
|
||||
else
|
||||
stv0900_set_tuner(fe, tuner_freq, intp->bw[d]);
|
||||
|
||||
stv0900_write_reg(intp, DMDISTATE, 0x1c);
|
||||
stv0900_write_reg(intp, CFRINIT1, 0);
|
||||
stv0900_write_reg(intp, CFRINIT0, 0);
|
||||
|
|
@ -790,7 +795,7 @@ static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp,
|
|||
return prate;
|
||||
}
|
||||
|
||||
void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp,
|
||||
static void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp,
|
||||
enum fe_stv0900_demod_num demod,
|
||||
u32 srate)
|
||||
{
|
||||
|
|
@ -976,8 +981,16 @@ static void stv0900_track_optimization(struct dvb_frontend *fe)
|
|||
intp->rolloff) + 10000000;
|
||||
|
||||
if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) {
|
||||
if (intp->srch_algo[demod] != STV0900_WARM_START)
|
||||
stv0900_set_bandwidth(fe, intp->bw[demod]);
|
||||
if (intp->srch_algo[demod] != STV0900_WARM_START) {
|
||||
if (intp->tuner_type[demod] == 3)
|
||||
stv0900_set_tuner_auto(intp,
|
||||
intp->freq[demod],
|
||||
intp->bw[demod],
|
||||
demod);
|
||||
else
|
||||
stv0900_set_bandwidth(fe,
|
||||
intp->bw[demod]);
|
||||
}
|
||||
}
|
||||
|
||||
if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) ||
|
||||
|
|
@ -1202,7 +1215,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
|
|||
}
|
||||
|
||||
result->standard = stv0900_get_standard(fe, d);
|
||||
result->frequency = stv0900_get_tuner_freq(fe);
|
||||
if (intp->tuner_type[demod] == 3)
|
||||
result->frequency = stv0900_get_freq_auto(intp, d);
|
||||
else
|
||||
result->frequency = stv0900_get_tuner_freq(fe);
|
||||
|
||||
offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000;
|
||||
result->frequency += offsetFreq;
|
||||
result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d);
|
||||
|
|
@ -1213,6 +1230,9 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
|
|||
result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01;
|
||||
result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1;
|
||||
result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS);
|
||||
|
||||
dprintk("%s: modcode=0x%x \n", __func__, result->modcode);
|
||||
|
||||
switch (result->standard) {
|
||||
case STV0900_DVBS2_STANDARD:
|
||||
result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD);
|
||||
|
|
@ -1239,7 +1259,11 @@ fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
|
|||
if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) ||
|
||||
(intp->symbol_rate[d] < 10000000)) {
|
||||
offsetFreq = result->frequency - intp->freq[d];
|
||||
intp->freq[d] = stv0900_get_tuner_freq(fe);
|
||||
if (intp->tuner_type[demod] == 3)
|
||||
intp->freq[d] = stv0900_get_freq_auto(intp, d);
|
||||
else
|
||||
intp->freq[d] = stv0900_get_tuner_freq(fe);
|
||||
|
||||
if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500))
|
||||
range = STV0900_RANGEOK;
|
||||
else if (ABS(offsetFreq) <=
|
||||
|
|
@ -1481,7 +1505,12 @@ static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe)
|
|||
else
|
||||
tuner_freq -= (current_step * currier_step);
|
||||
|
||||
stv0900_set_tuner(fe, tuner_freq, intp->bw[demod]);
|
||||
if (intp->tuner_type[demod] == 3)
|
||||
stv0900_set_tuner_auto(intp, tuner_freq,
|
||||
intp->bw[demod], demod);
|
||||
else
|
||||
stv0900_set_tuner(fe, tuner_freq,
|
||||
intp->bw[demod]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1608,7 +1637,8 @@ static int stv0900_blind_search_algo(struct dvb_frontend *fe)
|
|||
|
||||
agc2_int = stv0900_blind_check_agc2_min_level(intp, demod);
|
||||
|
||||
if (agc2_int > STV0900_BLIND_SEARCH_AGC2_TH)
|
||||
dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th);
|
||||
if (agc2_int > agc2_th)
|
||||
return FALSE;
|
||||
|
||||
if (intp->chip_id == 0x10)
|
||||
|
|
@ -1875,7 +1905,11 @@ enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe)
|
|||
|
||||
}
|
||||
|
||||
stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]);
|
||||
if (intp->tuner_type[demod] == 3)
|
||||
stv0900_set_tuner_auto(intp, intp->freq[demod],
|
||||
intp->bw[demod], demod);
|
||||
else
|
||||
stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]);
|
||||
|
||||
agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1),
|
||||
stv0900_get_bits(intp, AGCIQ_VALUE0));
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -60,6 +60,11 @@ enum stv090x_i2crpt {
|
|||
STV090x_RPTLEVEL_2 = 7,
|
||||
};
|
||||
|
||||
enum stv090x_adc_range {
|
||||
STV090x_ADC_2Vpp = 0,
|
||||
STV090x_ADC_1Vpp = 1
|
||||
};
|
||||
|
||||
struct stv090x_config {
|
||||
enum stv090x_device device;
|
||||
enum stv090x_mode demod_mode;
|
||||
|
|
@ -68,13 +73,17 @@ struct stv090x_config {
|
|||
u32 xtal; /* default: 8000000 */
|
||||
u8 address; /* default: 0x68 */
|
||||
|
||||
u32 ref_clk; /* default: 16000000 FIXME to tuner config */
|
||||
|
||||
u8 ts1_mode;
|
||||
u8 ts2_mode;
|
||||
u32 ts1_clk;
|
||||
u32 ts2_clk;
|
||||
|
||||
enum stv090x_i2crpt repeater_level;
|
||||
|
||||
u8 tuner_bbgain; /* default: 10db */
|
||||
enum stv090x_adc_range adc1_range; /* default: 2Vpp */
|
||||
enum stv090x_adc_range adc2_range; /* default: 2Vpp */
|
||||
|
||||
bool diseqc_envelope_mode;
|
||||
|
||||
int (*tuner_init) (struct dvb_frontend *fe);
|
||||
|
|
|
|||
|
|
@ -230,11 +230,23 @@ struct stv090x_tab {
|
|||
s32 read;
|
||||
};
|
||||
|
||||
struct stv090x_internal {
|
||||
struct i2c_adapter *i2c_adap;
|
||||
u8 i2c_addr;
|
||||
|
||||
struct mutex demod_lock; /* Lock access to shared register */
|
||||
struct mutex tuner_lock; /* Lock access to tuners */
|
||||
s32 mclk; /* Masterclock Divider factor */
|
||||
u32 dev_ver;
|
||||
|
||||
int num_used;
|
||||
};
|
||||
|
||||
struct stv090x_state {
|
||||
enum stv090x_device device;
|
||||
enum stv090x_demodulator demod;
|
||||
enum stv090x_mode demod_mode;
|
||||
u32 dev_ver;
|
||||
struct stv090x_internal *internal;
|
||||
|
||||
struct i2c_adapter *i2c;
|
||||
const struct stv090x_config *config;
|
||||
|
|
@ -256,11 +268,8 @@ struct stv090x_state {
|
|||
u32 frequency;
|
||||
u32 srate;
|
||||
|
||||
s32 mclk; /* Masterclock Divider factor */
|
||||
s32 tuner_bw;
|
||||
|
||||
u32 tuner_refclk;
|
||||
|
||||
s32 search_range;
|
||||
|
||||
s32 DemodTimeout;
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ static unsigned int verbose;
|
|||
module_param(verbose, int, 0644);
|
||||
MODULE_PARM_DESC(verbose, "Set Verbosity level");
|
||||
|
||||
static u8 stv6110x_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
|
||||
|
||||
static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -58,12 +56,23 @@ static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
|
||||
static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len)
|
||||
{
|
||||
int ret;
|
||||
const struct stv6110x_config *config = stv6110x->config;
|
||||
u8 buf[] = { reg, data };
|
||||
struct i2c_msg msg = { .addr = config->addr, .flags = 0, . buf = buf, .len = 2 };
|
||||
u8 buf[len + 1];
|
||||
struct i2c_msg msg = {
|
||||
.addr = config->addr,
|
||||
.flags = 0,
|
||||
.buf = buf,
|
||||
.len = len + 1
|
||||
};
|
||||
|
||||
if (start + len > 8)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = start;
|
||||
memcpy(&buf[1], data, len);
|
||||
|
||||
ret = i2c_transfer(stv6110x->i2c, &msg, 1);
|
||||
if (ret != 1) {
|
||||
|
|
@ -74,18 +83,21 @@ static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
|
||||
{
|
||||
return stv6110x_write_regs(stv6110x, reg, &data, 1);
|
||||
}
|
||||
|
||||
static int stv6110x_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
int ret;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stv6110x_regs); i++) {
|
||||
ret = stv6110x_write_reg(stv6110x, i, stv6110x_regs[i]);
|
||||
if (ret < 0) {
|
||||
dprintk(FE_ERROR, 1, "Initialization failed");
|
||||
return -1;
|
||||
}
|
||||
ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
|
||||
ARRAY_SIZE(stv6110x->regs));
|
||||
if (ret < 0) {
|
||||
dprintk(FE_ERROR, 1, "Initialization failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -98,23 +110,23 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
|
|||
s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000;
|
||||
u8 i;
|
||||
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
|
||||
|
||||
if (frequency <= 1023000) {
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
|
||||
pVal = 40;
|
||||
} else if (frequency <= 1300000) {
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
|
||||
pVal = 40;
|
||||
} else if (frequency <= 2046000) {
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
|
||||
pVal = 20;
|
||||
} else {
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
|
||||
pVal = 20;
|
||||
}
|
||||
|
||||
|
|
@ -130,21 +142,21 @@ static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
|
|||
divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
|
||||
divider = (divider + 5) / 10;
|
||||
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
|
||||
|
||||
/* VCO Auto calibration */
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
|
||||
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x_regs[STV6110x_TNG1]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x_regs[STV6110x_TNG0]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
|
||||
|
||||
for (i = 0; i < TRIALS; i++) {
|
||||
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
|
||||
if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x_regs[STV6110x_STAT1]))
|
||||
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
|
||||
if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1]))
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
|
|
@ -156,14 +168,14 @@ static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
|||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
|
||||
stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x_regs[STV6110x_TNG1]);
|
||||
stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x_regs[STV6110x_TNG0]);
|
||||
stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]);
|
||||
stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]);
|
||||
|
||||
*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x_regs[STV6110x_TNG1]),
|
||||
STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x_regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
|
||||
*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]),
|
||||
STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
|
||||
|
||||
*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x_regs[STV6110x_TNG1]) +
|
||||
STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x_regs[STV6110x_TNG1])));
|
||||
*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) +
|
||||
STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1])));
|
||||
|
||||
*frequency >>= 2;
|
||||
|
||||
|
|
@ -179,27 +191,27 @@ static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
|
|||
halfbw = bandwidth >> 1;
|
||||
|
||||
if (halfbw > 36000000)
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
|
||||
else if (halfbw < 5000000)
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
|
||||
else
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
|
||||
|
||||
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
|
||||
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x_regs[STV6110x_STAT1]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
|
||||
|
||||
for (i = 0; i < TRIALS; i++) {
|
||||
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
|
||||
if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x_regs[STV6110x_STAT1]))
|
||||
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
|
||||
if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1]))
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x_regs[STV6110x_CTRL3]);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -208,8 +220,8 @@ static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
|||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
|
||||
stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x_regs[STV6110x_CTRL3]);
|
||||
*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x_regs[STV6110x_CTRL3]) + 5) * 2000000;
|
||||
stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]);
|
||||
*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -222,20 +234,20 @@ static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
|
|||
switch (refclock) {
|
||||
default:
|
||||
case 1:
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
|
||||
break;
|
||||
case 2:
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
|
||||
break;
|
||||
case 4:
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
|
||||
break;
|
||||
case 8:
|
||||
case 0:
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
|
||||
break;
|
||||
}
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -244,8 +256,8 @@ static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
|
|||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
|
||||
stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x_regs[STV6110x_CTRL2]);
|
||||
*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x_regs[STV6110x_CTRL2]);
|
||||
stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]);
|
||||
*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -254,8 +266,8 @@ static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
|
|||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x_regs[STV6110x_CTRL2]);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
|
||||
stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -267,19 +279,19 @@ static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
|
|||
|
||||
switch (mode) {
|
||||
case TUNER_SLEEP:
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 0);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 0);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0);
|
||||
break;
|
||||
|
||||
case TUNER_WAKE:
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_SYN, 1);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_RX, 1);
|
||||
STV6110x_SETFIELD(stv6110x_regs[STV6110x_CTRL1], CTRL1_LPT, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1);
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x_regs[STV6110x_CTRL1]);
|
||||
ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
|
||||
if (ret < 0) {
|
||||
dprintk(FE_ERROR, 1, "I/O Error");
|
||||
return -EIO;
|
||||
|
|
@ -297,9 +309,9 @@ static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
|
|||
{
|
||||
struct stv6110x_state *stv6110x = fe->tuner_priv;
|
||||
|
||||
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x_regs[STV6110x_STAT1]);
|
||||
stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
|
||||
|
||||
if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x_regs[STV6110x_STAT1]))
|
||||
if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1]))
|
||||
*status = TUNER_PHASELOCKED;
|
||||
else
|
||||
*status = 0;
|
||||
|
|
@ -349,6 +361,8 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
|||
struct i2c_adapter *i2c)
|
||||
{
|
||||
struct stv6110x_state *stv6110x;
|
||||
u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
|
||||
int ret;
|
||||
|
||||
stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
|
||||
if (stv6110x == NULL)
|
||||
|
|
@ -357,6 +371,44 @@ struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
|
|||
stv6110x->i2c = i2c;
|
||||
stv6110x->config = config;
|
||||
stv6110x->devctl = &stv6110x_ctl;
|
||||
memcpy(stv6110x->regs, default_regs, 8);
|
||||
|
||||
/* setup divider */
|
||||
switch (stv6110x->config->clk_div) {
|
||||
default:
|
||||
case 1:
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
|
||||
break;
|
||||
case 2:
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
|
||||
break;
|
||||
case 4:
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
|
||||
break;
|
||||
case 8:
|
||||
case 0:
|
||||
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl) {
|
||||
ret = fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
|
||||
ARRAY_SIZE(stv6110x->regs));
|
||||
if (ret < 0) {
|
||||
dprintk(FE_ERROR, 1, "Initialization failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl) {
|
||||
ret = fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
fe->tuner_priv = stv6110x;
|
||||
fe->ops.tuner_ops = stv6110x_ops;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
struct stv6110x_config {
|
||||
u8 addr;
|
||||
u32 refclk;
|
||||
u8 clk_div; /* divisor value for the output clock */
|
||||
};
|
||||
|
||||
enum tuner_mode {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@
|
|||
struct stv6110x_state {
|
||||
struct i2c_adapter *i2c;
|
||||
const struct stv6110x_config *config;
|
||||
u8 regs[8];
|
||||
|
||||
struct stv6110x_devctl *devctl;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ static int tda665x_set_state(struct dvb_frontend *fe,
|
|||
frequency += config->ref_divider >> 1;
|
||||
frequency /= config->ref_divider;
|
||||
|
||||
buf[0] = (u8) (frequency & 0x7f00) >> 8;
|
||||
buf[0] = (u8) ((frequency & 0x7f00) >> 8);
|
||||
buf[1] = (u8) (frequency & 0x00ff) >> 0;
|
||||
buf[2] = 0x80 | 0x40 | 0x02;
|
||||
buf[3] = 0x00;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ static int tda8261_read(struct tda8261_state *state, u8 *buf)
|
|||
{
|
||||
const struct tda8261_config *config = state->config;
|
||||
int err = 0;
|
||||
struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 2 };
|
||||
struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD,.buf = buf, .len = 1 };
|
||||
|
||||
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
|
||||
printk("%s: read error, err=%d\n", __func__, err);
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ static int zl10036_init_regs(struct zl10036_state *state)
|
|||
state->bf = 0xff;
|
||||
|
||||
if (!state->config->rf_loop_enable)
|
||||
zl10036_init_tab[1][2] |= 0x01;
|
||||
zl10036_init_tab[1][0] |= 0x01;
|
||||
|
||||
deb_info("%s\n", __func__);
|
||||
|
||||
|
|
|
|||
|
|
@ -287,7 +287,6 @@ struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
|
|||
break;
|
||||
default:
|
||||
dprintk("Chip ID=%x does not match a known type\n", state->id);
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@
|
|||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ int mantis_input_init(struct mantis_pci *mantis)
|
|||
rc->id.version = 1;
|
||||
rc->dev = mantis->pdev->dev;
|
||||
|
||||
err = ir_input_register(rc, &ir_mantis);
|
||||
err = ir_input_register(rc, &ir_mantis, NULL);
|
||||
if (err) {
|
||||
dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
|
||||
input_free_device(rc);
|
||||
|
|
|
|||
|
|
@ -41,11 +41,6 @@
|
|||
#include "dvb_frontend.h"
|
||||
#include "dvb_net.h"
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "mantis_common.h"
|
||||
#include "mantis_reg.h"
|
||||
#include "mantis_pci.h"
|
||||
|
|
|
|||
9
drivers/media/dvb/ngene/Kconfig
Normal file
9
drivers/media/dvb/ngene/Kconfig
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
config DVB_NGENE
|
||||
tristate "Micronas nGene support"
|
||||
depends on DVB_CORE && PCI && I2C
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV6110x if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV090x if !DVB_FE_CUSTOMISE
|
||||
---help---
|
||||
Support for Micronas PCI express cards with nGene bridge.
|
||||
|
||||
11
drivers/media/dvb/ngene/Makefile
Normal file
11
drivers/media/dvb/ngene/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Makefile for the nGene device driver
|
||||
#
|
||||
|
||||
ngene-objs := ngene-core.o
|
||||
|
||||
obj-$(CONFIG_DVB_NGENE) += ngene.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
|
||||
|
||||
2024
drivers/media/dvb/ngene/ngene-core.c
Normal file
2024
drivers/media/dvb/ngene/ngene-core.c
Normal file
File diff suppressed because it is too large
Load diff
859
drivers/media/dvb/ngene/ngene.h
Normal file
859
drivers/media/dvb/ngene/ngene.h
Normal file
|
|
@ -0,0 +1,859 @@
|
|||
/*
|
||||
* ngene.h: nGene PCIe bridge driver
|
||||
*
|
||||
* Copyright (C) 2005-2007 Micronas
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 only, as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#ifndef _NGENE_H_
|
||||
#define _NGENE_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/dma.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
#include "dvbdev.h"
|
||||
#include "dvb_demux.h"
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_ringbuffer.h"
|
||||
|
||||
#define NGENE_VID 0x18c3
|
||||
#define NGENE_PID 0x0720
|
||||
|
||||
#ifndef VIDEO_CAP_VC1
|
||||
#define VIDEO_CAP_AVC 128
|
||||
#define VIDEO_CAP_H264 128
|
||||
#define VIDEO_CAP_VC1 256
|
||||
#define VIDEO_CAP_WMV9 256
|
||||
#define VIDEO_CAP_MPEG4 512
|
||||
#endif
|
||||
|
||||
enum STREAM {
|
||||
STREAM_VIDEOIN1 = 0, /* ITU656 or TS Input */
|
||||
STREAM_VIDEOIN2,
|
||||
STREAM_AUDIOIN1, /* I2S or SPI Input */
|
||||
STREAM_AUDIOIN2,
|
||||
STREAM_AUDIOOUT,
|
||||
MAX_STREAM
|
||||
};
|
||||
|
||||
enum SMODE_BITS {
|
||||
SMODE_AUDIO_SPDIF = 0x20,
|
||||
SMODE_AVSYNC = 0x10,
|
||||
SMODE_TRANSPORT_STREAM = 0x08,
|
||||
SMODE_AUDIO_CAPTURE = 0x04,
|
||||
SMODE_VBI_CAPTURE = 0x02,
|
||||
SMODE_VIDEO_CAPTURE = 0x01
|
||||
};
|
||||
|
||||
enum STREAM_FLAG_BITS {
|
||||
SFLAG_CHROMA_FORMAT_2COMP = 0x01, /* Chroma Format : 2's complement */
|
||||
SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */
|
||||
SFLAG_ORDER_LUMA_CHROMA = 0x02, /* Byte order: Y,Cb,Y,Cr */
|
||||
SFLAG_ORDER_CHROMA_LUMA = 0x00, /* Byte order: Cb,Y,Cr,Y */
|
||||
SFLAG_COLORBAR = 0x04, /* Select colorbar */
|
||||
};
|
||||
|
||||
#define PROGRAM_ROM 0x0000
|
||||
#define PROGRAM_SRAM 0x1000
|
||||
#define PERIPHERALS0 0x8000
|
||||
#define PERIPHERALS1 0x9000
|
||||
#define SHARED_BUFFER 0xC000
|
||||
|
||||
#define HOST_TO_NGENE (SHARED_BUFFER+0x0000)
|
||||
#define NGENE_TO_HOST (SHARED_BUFFER+0x0100)
|
||||
#define NGENE_COMMAND (SHARED_BUFFER+0x0200)
|
||||
#define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204)
|
||||
#define NGENE_STATUS (SHARED_BUFFER+0x0208)
|
||||
#define NGENE_STATUS_HI (SHARED_BUFFER+0x020C)
|
||||
#define NGENE_EVENT (SHARED_BUFFER+0x0210)
|
||||
#define NGENE_EVENT_HI (SHARED_BUFFER+0x0214)
|
||||
#define VARIABLES (SHARED_BUFFER+0x0210)
|
||||
|
||||
#define NGENE_INT_COUNTS (SHARED_BUFFER+0x0260)
|
||||
#define NGENE_INT_ENABLE (SHARED_BUFFER+0x0264)
|
||||
#define NGENE_VBI_LINE_COUNT (SHARED_BUFFER+0x0268)
|
||||
|
||||
#define BUFFER_GP_XMIT (SHARED_BUFFER+0x0800)
|
||||
#define BUFFER_GP_RECV (SHARED_BUFFER+0x0900)
|
||||
#define EEPROM_AREA (SHARED_BUFFER+0x0A00)
|
||||
|
||||
#define SG_V_IN_1 (SHARED_BUFFER+0x0A80)
|
||||
#define SG_VBI_1 (SHARED_BUFFER+0x0B00)
|
||||
#define SG_A_IN_1 (SHARED_BUFFER+0x0B80)
|
||||
#define SG_V_IN_2 (SHARED_BUFFER+0x0C00)
|
||||
#define SG_VBI_2 (SHARED_BUFFER+0x0C80)
|
||||
#define SG_A_IN_2 (SHARED_BUFFER+0x0D00)
|
||||
#define SG_V_OUT (SHARED_BUFFER+0x0D80)
|
||||
#define SG_A_OUT2 (SHARED_BUFFER+0x0E00)
|
||||
|
||||
#define DATA_A_IN_1 (SHARED_BUFFER+0x0E80)
|
||||
#define DATA_A_IN_2 (SHARED_BUFFER+0x0F00)
|
||||
#define DATA_A_OUT (SHARED_BUFFER+0x0F80)
|
||||
#define DATA_V_IN_1 (SHARED_BUFFER+0x1000)
|
||||
#define DATA_V_IN_2 (SHARED_BUFFER+0x2000)
|
||||
#define DATA_V_OUT (SHARED_BUFFER+0x3000)
|
||||
|
||||
#define DATA_FIFO_AREA (SHARED_BUFFER+0x1000)
|
||||
|
||||
#define TIMESTAMPS 0xA000
|
||||
#define SCRATCHPAD 0xA080
|
||||
#define FORCE_INT 0xA088
|
||||
#define FORCE_NMI 0xA090
|
||||
#define INT_STATUS 0xA0A0
|
||||
|
||||
#define DEV_VER 0x9004
|
||||
|
||||
#define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF)
|
||||
|
||||
struct SG_ADDR {
|
||||
u64 start;
|
||||
u64 curr;
|
||||
u16 curr_ptr;
|
||||
u16 elements;
|
||||
u32 pad[3];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct SHARED_MEMORY {
|
||||
/* C000 */
|
||||
u32 HostToNgene[64];
|
||||
|
||||
/* C100 */
|
||||
u32 NgeneToHost[64];
|
||||
|
||||
/* C200 */
|
||||
u64 NgeneCommand;
|
||||
u64 NgeneStatus;
|
||||
u64 NgeneEvent;
|
||||
|
||||
/* C210 */
|
||||
u8 pad1[0xc260 - 0xc218];
|
||||
|
||||
/* C260 */
|
||||
u32 IntCounts;
|
||||
u32 IntEnable;
|
||||
|
||||
/* C268 */
|
||||
u8 pad2[0xd000 - 0xc268];
|
||||
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct BUFFER_STREAM_RESULTS {
|
||||
u32 Clock; /* Stream time in 100ns units */
|
||||
u16 RemainingLines; /* Remaining lines in this field.
|
||||
0 for complete field */
|
||||
u8 FieldCount; /* Video field number */
|
||||
u8 Flags; /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow,
|
||||
Bit 0 = FieldID */
|
||||
u16 BlockCount; /* Audio block count (unused) */
|
||||
u8 Reserved[2];
|
||||
u32 DTOUpdate;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct HW_SCATTER_GATHER_ELEMENT {
|
||||
u64 Address;
|
||||
u32 Length;
|
||||
u32 Reserved;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct BUFFER_HEADER {
|
||||
u64 Next;
|
||||
struct BUFFER_STREAM_RESULTS SR;
|
||||
|
||||
u32 Number_of_entries_1;
|
||||
u32 Reserved5;
|
||||
u64 Address_of_first_entry_1;
|
||||
|
||||
u32 Number_of_entries_2;
|
||||
u32 Reserved7;
|
||||
u64 Address_of_first_entry_2;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct EVENT_BUFFER {
|
||||
u32 TimeStamp;
|
||||
u8 GPIOStatus;
|
||||
u8 UARTStatus;
|
||||
u8 RXCharacter;
|
||||
u8 EventStatus;
|
||||
u32 Reserved[2];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/* Firmware commands. */
|
||||
|
||||
enum OPCODES {
|
||||
CMD_NOP = 0,
|
||||
CMD_FWLOAD_PREPARE = 0x01,
|
||||
CMD_FWLOAD_FINISH = 0x02,
|
||||
CMD_I2C_READ = 0x03,
|
||||
CMD_I2C_WRITE = 0x04,
|
||||
|
||||
CMD_I2C_WRITE_NOSTOP = 0x05,
|
||||
CMD_I2C_CONTINUE_WRITE = 0x06,
|
||||
CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07,
|
||||
|
||||
CMD_DEBUG_OUTPUT = 0x09,
|
||||
|
||||
CMD_CONTROL = 0x10,
|
||||
CMD_CONFIGURE_BUFFER = 0x11,
|
||||
CMD_CONFIGURE_FREE_BUFFER = 0x12,
|
||||
|
||||
CMD_SPI_READ = 0x13,
|
||||
CMD_SPI_WRITE = 0x14,
|
||||
|
||||
CMD_MEM_READ = 0x20,
|
||||
CMD_MEM_WRITE = 0x21,
|
||||
CMD_SFR_READ = 0x22,
|
||||
CMD_SFR_WRITE = 0x23,
|
||||
CMD_IRAM_READ = 0x24,
|
||||
CMD_IRAM_WRITE = 0x25,
|
||||
CMD_SET_GPIO_PIN = 0x26,
|
||||
CMD_SET_GPIO_INT = 0x27,
|
||||
CMD_CONFIGURE_UART = 0x28,
|
||||
CMD_WRITE_UART = 0x29,
|
||||
MAX_CMD
|
||||
};
|
||||
|
||||
enum RESPONSES {
|
||||
OK = 0,
|
||||
ERROR = 1
|
||||
};
|
||||
|
||||
struct FW_HEADER {
|
||||
u8 Opcode;
|
||||
u8 Length;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_I2C_WRITE {
|
||||
struct FW_HEADER hdr;
|
||||
u8 Device;
|
||||
u8 Data[250];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_I2C_CONTINUE_WRITE {
|
||||
struct FW_HEADER hdr;
|
||||
u8 Data[250];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_I2C_READ {
|
||||
struct FW_HEADER hdr;
|
||||
u8 Device;
|
||||
u8 Data[252]; /* followed by two bytes of read data count */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SPI_WRITE {
|
||||
struct FW_HEADER hdr;
|
||||
u8 ModeSelect;
|
||||
u8 Data[250];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SPI_READ {
|
||||
struct FW_HEADER hdr;
|
||||
u8 ModeSelect;
|
||||
u8 Data[252]; /* followed by two bytes of read data count */
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_FWLOAD_PREPARE {
|
||||
struct FW_HEADER hdr;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_FWLOAD_FINISH {
|
||||
struct FW_HEADER hdr;
|
||||
u16 Address; /* address of final block */
|
||||
u16 Length;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
/*
|
||||
* Meaning of FW_STREAM_CONTROL::Mode bits:
|
||||
* Bit 7: Loopback PEXin to PEXout using TVOut channel
|
||||
* Bit 6: AVLOOP
|
||||
* Bit 5: Audio select; 0=I2S, 1=SPDIF
|
||||
* Bit 4: AVSYNC
|
||||
* Bit 3: Enable transport stream
|
||||
* Bit 2: Enable audio capture
|
||||
* Bit 1: Enable ITU-Video VBI capture
|
||||
* Bit 0: Enable ITU-Video capture
|
||||
*
|
||||
* Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL)
|
||||
* Bit 7: continuous capture
|
||||
* Bit 6: capture one field
|
||||
* Bit 5: capture one frame
|
||||
* Bit 4: unused
|
||||
* Bit 3: starting field; 0=odd, 1=even
|
||||
* Bit 2: sample size; 0=8-bit, 1=10-bit
|
||||
* Bit 1: data format; 0=UYVY, 1=YUY2
|
||||
* Bit 0: resets buffer pointers
|
||||
*/
|
||||
|
||||
enum FSC_MODE_BITS {
|
||||
SMODE_LOOPBACK = 0x80,
|
||||
SMODE_AVLOOP = 0x40,
|
||||
_SMODE_AUDIO_SPDIF = 0x20,
|
||||
_SMODE_AVSYNC = 0x10,
|
||||
_SMODE_TRANSPORT_STREAM = 0x08,
|
||||
_SMODE_AUDIO_CAPTURE = 0x04,
|
||||
_SMODE_VBI_CAPTURE = 0x02,
|
||||
_SMODE_VIDEO_CAPTURE = 0x01
|
||||
};
|
||||
|
||||
|
||||
/* Meaning of FW_STREAM_CONTROL::Stream bits:
|
||||
* Bit 3: Audio sample count: 0 = relative, 1 = absolute
|
||||
* Bit 2: color bar select; 1=color bars, 0=CV3 decoder
|
||||
* Bits 1-0: stream select, UVI1, UVI2, TVOUT
|
||||
*/
|
||||
|
||||
struct FW_STREAM_CONTROL {
|
||||
struct FW_HEADER hdr;
|
||||
u8 Stream; /* Stream number (UVI1, UVI2, TVOUT) */
|
||||
u8 Control; /* Value written to UVI1_CTL */
|
||||
u8 Mode; /* Controls clock source */
|
||||
u8 SetupDataLen; /* Length of setup data, MSB=1 write
|
||||
backwards */
|
||||
u16 CaptureBlockCount; /* Blocks (a 256 Bytes) to capture per buffer
|
||||
for TS and Audio */
|
||||
u64 Buffer_Address; /* Address of first buffer header */
|
||||
u16 BytesPerVideoLine;
|
||||
u16 MaxLinesPerField;
|
||||
u16 MinLinesPerField;
|
||||
u16 Reserved_1;
|
||||
u16 BytesPerVBILine;
|
||||
u16 MaxVBILinesPerField;
|
||||
u16 MinVBILinesPerField;
|
||||
u16 SetupDataAddr; /* ngene relative address of setup data */
|
||||
u8 SetupData[32]; /* setup data */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define AUDIO_BLOCK_SIZE 256
|
||||
#define TS_BLOCK_SIZE 256
|
||||
|
||||
struct FW_MEM_READ {
|
||||
struct FW_HEADER hdr;
|
||||
u16 address;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_MEM_WRITE {
|
||||
struct FW_HEADER hdr;
|
||||
u16 address;
|
||||
u8 data;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SFR_IRAM_READ {
|
||||
struct FW_HEADER hdr;
|
||||
u8 address;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SFR_IRAM_WRITE {
|
||||
struct FW_HEADER hdr;
|
||||
u8 address;
|
||||
u8 data;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SET_GPIO_PIN {
|
||||
struct FW_HEADER hdr;
|
||||
u8 select;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SET_GPIO_INT {
|
||||
struct FW_HEADER hdr;
|
||||
u8 select;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_SET_DEBUGMODE {
|
||||
struct FW_HEADER hdr;
|
||||
u8 debug_flags;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_CONFIGURE_BUFFERS {
|
||||
struct FW_HEADER hdr;
|
||||
u8 config;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum _BUFFER_CONFIGS {
|
||||
/* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2 (standard usage) */
|
||||
BUFFER_CONFIG_4422 = 0,
|
||||
/* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2 (4x TS input usage) */
|
||||
BUFFER_CONFIG_3333 = 1,
|
||||
/* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut (HDTV decoder usage) */
|
||||
BUFFER_CONFIG_8022 = 2,
|
||||
BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */
|
||||
};
|
||||
|
||||
struct FW_CONFIGURE_FREE_BUFFERS {
|
||||
struct FW_HEADER hdr;
|
||||
u8 UVI1_BufferLength;
|
||||
u8 UVI2_BufferLength;
|
||||
u8 TVO_BufferLength;
|
||||
u8 AUD1_BufferLength;
|
||||
u8 AUD2_BufferLength;
|
||||
u8 TVA_BufferLength;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct FW_CONFIGURE_UART {
|
||||
struct FW_HEADER hdr;
|
||||
u8 UartControl;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
enum _UART_CONFIG {
|
||||
_UART_BAUDRATE_19200 = 0,
|
||||
_UART_BAUDRATE_9600 = 1,
|
||||
_UART_BAUDRATE_4800 = 2,
|
||||
_UART_BAUDRATE_2400 = 3,
|
||||
_UART_RX_ENABLE = 0x40,
|
||||
_UART_TX_ENABLE = 0x80,
|
||||
};
|
||||
|
||||
struct FW_WRITE_UART {
|
||||
struct FW_HEADER hdr;
|
||||
u8 Data[252];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
|
||||
struct ngene_command {
|
||||
u32 in_len;
|
||||
u32 out_len;
|
||||
union {
|
||||
u32 raw[64];
|
||||
u8 raw8[256];
|
||||
struct FW_HEADER hdr;
|
||||
struct FW_I2C_WRITE I2CWrite;
|
||||
struct FW_I2C_CONTINUE_WRITE I2CContinueWrite;
|
||||
struct FW_I2C_READ I2CRead;
|
||||
struct FW_STREAM_CONTROL StreamControl;
|
||||
struct FW_FWLOAD_PREPARE FWLoadPrepare;
|
||||
struct FW_FWLOAD_FINISH FWLoadFinish;
|
||||
struct FW_MEM_READ MemoryRead;
|
||||
struct FW_MEM_WRITE MemoryWrite;
|
||||
struct FW_SFR_IRAM_READ SfrIramRead;
|
||||
struct FW_SFR_IRAM_WRITE SfrIramWrite;
|
||||
struct FW_SPI_WRITE SPIWrite;
|
||||
struct FW_SPI_READ SPIRead;
|
||||
struct FW_SET_GPIO_PIN SetGpioPin;
|
||||
struct FW_SET_GPIO_INT SetGpioInt;
|
||||
struct FW_SET_DEBUGMODE SetDebugMode;
|
||||
struct FW_CONFIGURE_BUFFERS ConfigureBuffers;
|
||||
struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers;
|
||||
struct FW_CONFIGURE_UART ConfigureUart;
|
||||
struct FW_WRITE_UART WriteUart;
|
||||
} cmd;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#define NGENE_INTERFACE_VERSION 0x103
|
||||
#define MAX_VIDEO_BUFFER_SIZE (417792) /* 288*1440 rounded up to next page */
|
||||
#define MAX_AUDIO_BUFFER_SIZE (8192) /* Gives room for about 23msec@48KHz */
|
||||
#define MAX_VBI_BUFFER_SIZE (28672) /* 1144*18 rounded up to next page */
|
||||
#define MAX_TS_BUFFER_SIZE (98304) /* 512*188 rounded up to next page */
|
||||
#define MAX_HDTV_BUFFER_SIZE (2080768) /* 541*1920*2 rounded up to next page
|
||||
Max: (1920x1080i60) */
|
||||
|
||||
#define OVERFLOW_BUFFER_SIZE (8192)
|
||||
|
||||
#define RING_SIZE_VIDEO 4
|
||||
#define RING_SIZE_AUDIO 8
|
||||
#define RING_SIZE_TS 8
|
||||
|
||||
#define NUM_SCATTER_GATHER_ENTRIES 8
|
||||
|
||||
#define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \
|
||||
RING_SIZE_VIDEO * 2) + \
|
||||
(MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \
|
||||
(MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \
|
||||
(RING_SIZE_VIDEO * PAGE_SIZE * 2) + \
|
||||
(RING_SIZE_AUDIO * PAGE_SIZE * 2) + \
|
||||
(RING_SIZE_TS * PAGE_SIZE * 4) + \
|
||||
8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE)
|
||||
|
||||
#define EVENT_QUEUE_SIZE 16
|
||||
|
||||
/* Gathers the current state of a single channel. */
|
||||
|
||||
struct SBufferHeader {
|
||||
struct BUFFER_HEADER ngeneBuffer; /* Physical descriptor */
|
||||
struct SBufferHeader *Next;
|
||||
void *Buffer1;
|
||||
struct HW_SCATTER_GATHER_ELEMENT *scList1;
|
||||
void *Buffer2;
|
||||
struct HW_SCATTER_GATHER_ELEMENT *scList2;
|
||||
};
|
||||
|
||||
/* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */
|
||||
#define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63)
|
||||
|
||||
enum HWSTATE {
|
||||
HWSTATE_STOP,
|
||||
HWSTATE_STARTUP,
|
||||
HWSTATE_RUN,
|
||||
HWSTATE_PAUSE,
|
||||
};
|
||||
|
||||
enum KSSTATE {
|
||||
KSSTATE_STOP,
|
||||
KSSTATE_ACQUIRE,
|
||||
KSSTATE_PAUSE,
|
||||
KSSTATE_RUN,
|
||||
};
|
||||
|
||||
struct SRingBufferDescriptor {
|
||||
struct SBufferHeader *Head; /* Points to first buffer in ring buffer
|
||||
structure*/
|
||||
u64 PAHead; /* Physical address of first buffer */
|
||||
u32 MemSize; /* Memory size of allocated ring buffers
|
||||
(needed for freeing) */
|
||||
u32 NumBuffers; /* Number of buffers in the ring */
|
||||
u32 Buffer1Length; /* Allocated length of Buffer 1 */
|
||||
u32 Buffer2Length; /* Allocated length of Buffer 2 */
|
||||
void *SCListMem; /* Memory to hold scatter gather lists for this
|
||||
ring */
|
||||
u64 PASCListMem; /* Physical address .. */
|
||||
u32 SCListMemSize; /* Size of this memory */
|
||||
};
|
||||
|
||||
enum STREAMMODEFLAGS {
|
||||
StreamMode_NONE = 0, /* Stream not used */
|
||||
StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */
|
||||
StreamMode_TSIN = 2, /* Transport stream input (all) */
|
||||
StreamMode_HDTV = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60
|
||||
(only stream 0) */
|
||||
StreamMode_TSOUT = 8, /* Transport stream output (only stream 3) */
|
||||
};
|
||||
|
||||
|
||||
enum BufferExchangeFlags {
|
||||
BEF_EVEN_FIELD = 0x00000001,
|
||||
BEF_CONTINUATION = 0x00000002,
|
||||
BEF_MORE_DATA = 0x00000004,
|
||||
BEF_OVERFLOW = 0x00000008,
|
||||
DF_SWAP32 = 0x00010000,
|
||||
};
|
||||
|
||||
typedef void *(IBufferExchange)(void *, void *, u32, u32, u32);
|
||||
|
||||
struct MICI_STREAMINFO {
|
||||
IBufferExchange *pExchange;
|
||||
IBufferExchange *pExchangeVBI; /* Secondary (VBI, ancillary) */
|
||||
u8 Stream;
|
||||
u8 Flags;
|
||||
u8 Mode;
|
||||
u8 Reserved;
|
||||
u16 nLinesVideo;
|
||||
u16 nBytesPerLineVideo;
|
||||
u16 nLinesVBI;
|
||||
u16 nBytesPerLineVBI;
|
||||
u32 CaptureLength; /* Used for audio and transport stream */
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/* STRUCTS ******************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
/* sound hardware definition */
|
||||
#define MIXER_ADDR_TVTUNER 0
|
||||
#define MIXER_ADDR_LAST 0
|
||||
|
||||
struct ngene_channel;
|
||||
|
||||
/*struct sound chip*/
|
||||
|
||||
struct mychip {
|
||||
struct ngene_channel *chan;
|
||||
struct snd_card *card;
|
||||
struct pci_dev *pci;
|
||||
struct snd_pcm_substream *substream;
|
||||
struct snd_pcm *pcm;
|
||||
unsigned long port;
|
||||
int irq;
|
||||
spinlock_t mixer_lock;
|
||||
spinlock_t lock;
|
||||
int mixer_volume[MIXER_ADDR_LAST + 1][2];
|
||||
int capture_source[MIXER_ADDR_LAST + 1][2];
|
||||
};
|
||||
|
||||
#ifdef NGENE_V4L
|
||||
struct ngene_overlay {
|
||||
int tvnorm;
|
||||
struct v4l2_rect w;
|
||||
enum v4l2_field field;
|
||||
struct v4l2_clip *clips;
|
||||
int nclips;
|
||||
int setup_ok;
|
||||
};
|
||||
|
||||
struct ngene_tvnorm {
|
||||
int v4l2_id;
|
||||
char *name;
|
||||
u16 swidth, sheight; /* scaled standard width, height */
|
||||
int tuner_norm;
|
||||
int soundstd;
|
||||
};
|
||||
|
||||
struct ngene_vopen {
|
||||
struct ngene_channel *ch;
|
||||
enum v4l2_priority prio;
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
struct videobuf_queue vbuf_q;
|
||||
struct videobuf_queue vbi;
|
||||
int fourcc;
|
||||
int picxcount;
|
||||
int resources;
|
||||
enum v4l2_buf_type type;
|
||||
const struct ngene_format *fmt;
|
||||
|
||||
const struct ngene_format *ovfmt;
|
||||
struct ngene_overlay ov;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ngene_channel {
|
||||
struct device device;
|
||||
struct i2c_adapter i2c_adapter;
|
||||
|
||||
struct ngene *dev;
|
||||
int number;
|
||||
int type;
|
||||
int mode;
|
||||
|
||||
struct dvb_frontend *fe;
|
||||
struct dmxdev dmxdev;
|
||||
struct dvb_demux demux;
|
||||
struct dmx_frontend hw_frontend;
|
||||
struct dmx_frontend mem_frontend;
|
||||
int users;
|
||||
struct video_device *v4l_dev;
|
||||
struct tasklet_struct demux_tasklet;
|
||||
|
||||
struct SBufferHeader *nextBuffer;
|
||||
enum KSSTATE State;
|
||||
enum HWSTATE HWState;
|
||||
u8 Stream;
|
||||
u8 Flags;
|
||||
u8 Mode;
|
||||
IBufferExchange *pBufferExchange;
|
||||
IBufferExchange *pBufferExchange2;
|
||||
|
||||
spinlock_t state_lock;
|
||||
u16 nLines;
|
||||
u16 nBytesPerLine;
|
||||
u16 nVBILines;
|
||||
u16 nBytesPerVBILine;
|
||||
u16 itumode;
|
||||
u32 Capture1Length;
|
||||
u32 Capture2Length;
|
||||
struct SRingBufferDescriptor RingBuffer;
|
||||
struct SRingBufferDescriptor TSRingBuffer;
|
||||
struct SRingBufferDescriptor TSIdleBuffer;
|
||||
|
||||
u32 DataFormatFlags;
|
||||
|
||||
int AudioDTOUpdated;
|
||||
u32 AudioDTOValue;
|
||||
|
||||
int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t);
|
||||
u8 lnbh;
|
||||
|
||||
/* stuff from analog driver */
|
||||
|
||||
int minor;
|
||||
struct mychip *mychip;
|
||||
struct snd_card *soundcard;
|
||||
u8 *evenbuffer;
|
||||
u8 dma_on;
|
||||
int soundstreamon;
|
||||
int audiomute;
|
||||
int soundbuffisallocated;
|
||||
int sndbuffflag;
|
||||
int tun_rdy;
|
||||
int dec_rdy;
|
||||
int tun_dec_rdy;
|
||||
int lastbufferflag;
|
||||
|
||||
struct ngene_tvnorm *tvnorms;
|
||||
int tvnorm_num;
|
||||
int tvnorm;
|
||||
|
||||
#ifdef NGENE_V4L
|
||||
int videousers;
|
||||
struct v4l2_prio_state prio;
|
||||
struct ngene_vopen init;
|
||||
int resources;
|
||||
struct v4l2_framebuffer fbuf;
|
||||
struct ngene_buffer *screen; /* overlay */
|
||||
struct list_head capture; /* video capture queue */
|
||||
spinlock_t s_lock;
|
||||
struct semaphore reslock;
|
||||
#endif
|
||||
|
||||
int running;
|
||||
};
|
||||
|
||||
struct ngene;
|
||||
|
||||
typedef void (rx_cb_t)(struct ngene *, u32, u8);
|
||||
typedef void (tx_cb_t)(struct ngene *, u32);
|
||||
|
||||
struct ngene {
|
||||
int nr;
|
||||
struct pci_dev *pci_dev;
|
||||
unsigned char *iomem;
|
||||
|
||||
/*struct i2c_adapter i2c_adapter;*/
|
||||
|
||||
u32 device_version;
|
||||
u32 fw_interface_version;
|
||||
u32 icounts;
|
||||
|
||||
u8 *CmdDoneByte;
|
||||
int BootFirmware;
|
||||
void *OverflowBuffer;
|
||||
dma_addr_t PAOverflowBuffer;
|
||||
void *FWInterfaceBuffer;
|
||||
dma_addr_t PAFWInterfaceBuffer;
|
||||
u8 *ngenetohost;
|
||||
u8 *hosttongene;
|
||||
|
||||
struct EVENT_BUFFER EventQueue[EVENT_QUEUE_SIZE];
|
||||
int EventQueueOverflowCount;
|
||||
int EventQueueOverflowFlag;
|
||||
struct tasklet_struct event_tasklet;
|
||||
struct EVENT_BUFFER *EventBuffer;
|
||||
int EventQueueWriteIndex;
|
||||
int EventQueueReadIndex;
|
||||
|
||||
wait_queue_head_t cmd_wq;
|
||||
int cmd_done;
|
||||
struct semaphore cmd_mutex;
|
||||
struct semaphore stream_mutex;
|
||||
struct semaphore pll_mutex;
|
||||
struct semaphore i2c_switch_mutex;
|
||||
int i2c_current_channel;
|
||||
int i2c_current_bus;
|
||||
spinlock_t cmd_lock;
|
||||
|
||||
struct dvb_adapter adapter[MAX_STREAM];
|
||||
struct ngene_channel channel[MAX_STREAM];
|
||||
|
||||
struct ngene_info *card_info;
|
||||
|
||||
tx_cb_t *TxEventNotify;
|
||||
rx_cb_t *RxEventNotify;
|
||||
int tx_busy;
|
||||
wait_queue_head_t tx_wq;
|
||||
wait_queue_head_t rx_wq;
|
||||
#define UART_RBUF_LEN 4096
|
||||
u8 uart_rbuf[UART_RBUF_LEN];
|
||||
int uart_rp, uart_wp;
|
||||
|
||||
u8 *tsout_buf;
|
||||
#define TSOUT_BUF_SIZE (512*188*8)
|
||||
struct dvb_ringbuffer tsout_rbuf;
|
||||
|
||||
u8 *ain_buf;
|
||||
#define AIN_BUF_SIZE (128*1024)
|
||||
struct dvb_ringbuffer ain_rbuf;
|
||||
|
||||
|
||||
u8 *vin_buf;
|
||||
#define VIN_BUF_SIZE (4*1920*1080)
|
||||
struct dvb_ringbuffer vin_rbuf;
|
||||
|
||||
unsigned long exp_val;
|
||||
int prev_cmd;
|
||||
};
|
||||
|
||||
struct ngene_info {
|
||||
int type;
|
||||
#define NGENE_APP 0
|
||||
#define NGENE_TERRATEC 1
|
||||
#define NGENE_SIDEWINDER 2
|
||||
#define NGENE_RACER 3
|
||||
#define NGENE_VIPER 4
|
||||
#define NGENE_PYTHON 5
|
||||
#define NGENE_VBOX_V1 6
|
||||
#define NGENE_VBOX_V2 7
|
||||
|
||||
int fw_version;
|
||||
char *name;
|
||||
|
||||
int io_type[MAX_STREAM];
|
||||
#define NGENE_IO_NONE 0
|
||||
#define NGENE_IO_TV 1
|
||||
#define NGENE_IO_HDTV 2
|
||||
#define NGENE_IO_TSIN 4
|
||||
#define NGENE_IO_TSOUT 8
|
||||
#define NGENE_IO_AIN 16
|
||||
|
||||
void *fe_config[4];
|
||||
void *tuner_config[4];
|
||||
|
||||
int (*demod_attach[4])(struct ngene_channel *);
|
||||
int (*tuner_attach[4])(struct ngene_channel *);
|
||||
|
||||
u8 avf[4];
|
||||
u8 msp[4];
|
||||
u8 demoda[4];
|
||||
u8 lnb[4];
|
||||
int i2c_access;
|
||||
u8 ntsc;
|
||||
u8 tsf[4];
|
||||
u8 i2s[4];
|
||||
|
||||
int (*gate_ctrl)(struct dvb_frontend *, int);
|
||||
int (*switch_ctrl)(struct ngene_channel *, int, int);
|
||||
};
|
||||
|
||||
#ifdef NGENE_V4L
|
||||
struct ngene_format{
|
||||
char *name;
|
||||
int fourcc; /* video4linux 2 */
|
||||
int btformat; /* BT848_COLOR_FMT_* */
|
||||
int format;
|
||||
int btswap; /* BT848_COLOR_CTL_* */
|
||||
int depth; /* bit/pixel */
|
||||
int flags;
|
||||
int hshift, vshift; /* for planar modes */
|
||||
int palette;
|
||||
};
|
||||
|
||||
#define RESOURCE_OVERLAY 1
|
||||
#define RESOURCE_VIDEO 2
|
||||
#define RESOURCE_VBI 4
|
||||
|
||||
struct ngene_buffer {
|
||||
/* common v4l buffer stuff -- must be first */
|
||||
struct videobuf_buffer vb;
|
||||
|
||||
/* ngene specific */
|
||||
const struct ngene_format *fmt;
|
||||
int tvnorm;
|
||||
int btformat;
|
||||
int btswap;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* LocalWords: Endif
|
||||
*/
|
||||
|
|
@ -62,6 +62,7 @@ static struct sms_board sms_boards[] = {
|
|||
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
|
||||
.name = "Hauppauge WinTV MiniStick",
|
||||
.type = SMS_NOVA_B0,
|
||||
.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
|
||||
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
|
||||
.board_cfg.leds_power = 26,
|
||||
.board_cfg.led0 = 27,
|
||||
|
|
|
|||
|
|
@ -1459,8 +1459,10 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
|
|||
if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
|
||||
pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
|
||||
if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
|
||||
&groupCfg) != 0)
|
||||
return -EINVAL;
|
||||
&groupCfg) != 0) {
|
||||
rc = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
|
||||
pMsg->msgData[1] = TranslatedPinNum;
|
||||
pMsg->msgData[2] = GroupNum;
|
||||
|
|
@ -1490,6 +1492,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
|
|||
else
|
||||
sms_err("smscore_gpio_configure error");
|
||||
}
|
||||
free:
|
||||
kfree(buffer);
|
||||
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -212,6 +212,8 @@ struct smscore_device_t {
|
|||
#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_RES 616
|
||||
#define MSG_SMS_GET_STATISTICS_REQ 615
|
||||
#define MSG_SMS_HO_PER_SLICES_IND 630
|
||||
#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651
|
||||
#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652
|
||||
|
|
@ -339,7 +341,7 @@ struct SmsFirmware_ST {
|
|||
|
||||
/* Statistics information returned as response for
|
||||
* SmsHostApiGetStatistics_Req */
|
||||
struct SMSHOSTLIB_STATISTICS_S {
|
||||
struct SMSHOSTLIB_STATISTICS_ST {
|
||||
u32 Reserved; /* Reserved */
|
||||
|
||||
/* Common parameters */
|
||||
|
|
@ -424,6 +426,79 @@ struct SMSHOSTLIB_STATISTICS_S {
|
|||
u32 ReservedFields[10]; /* Reserved */
|
||||
};
|
||||
|
||||
struct SmsMsgStatisticsInfo_ST {
|
||||
u32 RequestResult;
|
||||
|
||||
struct SMSHOSTLIB_STATISTICS_ST Stat;
|
||||
|
||||
/* Split the calc of the SNR in DAB */
|
||||
u32 Signal; /* dB */
|
||||
u32 Noise; /* dB */
|
||||
|
||||
};
|
||||
|
||||
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 PID_STATISTICS_DATA_S {
|
||||
struct PID_BURST_S {
|
||||
u32 size;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,118 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
|
||||
struct SMSHOSTLIB_STATISTICS_ST *p)
|
||||
{
|
||||
if (sms_dbg & 2) {
|
||||
printk(KERN_DEBUG "Reserved = %d", p->Reserved);
|
||||
printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
|
||||
printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
|
||||
printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
|
||||
printk(KERN_DEBUG "SNR = %d", p->SNR);
|
||||
printk(KERN_DEBUG "BER = %d", p->BER);
|
||||
printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
|
||||
printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
|
||||
printk(KERN_DEBUG "MFER = %d", p->MFER);
|
||||
printk(KERN_DEBUG "RSSI = %d", p->RSSI);
|
||||
printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
|
||||
printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
|
||||
printk(KERN_DEBUG "Frequency = %d", p->Frequency);
|
||||
printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
|
||||
printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
|
||||
printk(KERN_DEBUG "ModemState = %d", p->ModemState);
|
||||
printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
|
||||
printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
|
||||
printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
|
||||
printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
|
||||
printk(KERN_DEBUG "Constellation = %d", p->Constellation);
|
||||
printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
|
||||
printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
|
||||
printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
|
||||
printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
|
||||
printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
|
||||
printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
|
||||
printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
|
||||
printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
|
||||
printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
|
||||
printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
|
||||
printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
|
||||
printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
|
||||
printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
|
||||
printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
|
||||
printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
|
||||
printk(KERN_DEBUG "PreBER = %d", p->PreBER);
|
||||
printk(KERN_DEBUG "CellId = %d", p->CellId);
|
||||
printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
|
||||
printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
|
||||
printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
|
||||
}
|
||||
|
||||
pReceptionData->IsDemodLocked = p->IsDemodLocked;
|
||||
|
||||
pReceptionData->SNR = p->SNR;
|
||||
pReceptionData->BER = p->BER;
|
||||
pReceptionData->BERErrorCount = p->BERErrorCount;
|
||||
pReceptionData->InBandPwr = p->InBandPwr;
|
||||
pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
|
||||
};
|
||||
|
||||
|
||||
static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
|
||||
struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sms_dbg & 2) {
|
||||
printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
|
||||
printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
|
||||
printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
|
||||
printk(KERN_DEBUG "SNR = %d", p->SNR);
|
||||
printk(KERN_DEBUG "RSSI = %d", p->RSSI);
|
||||
printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
|
||||
printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
|
||||
printk(KERN_DEBUG "Frequency = %d", p->Frequency);
|
||||
printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
|
||||
printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
|
||||
printk(KERN_DEBUG "ModemState = %d", p->ModemState);
|
||||
printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
|
||||
printk(KERN_DEBUG "SystemType = %d", p->SystemType);
|
||||
printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
|
||||
printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
|
||||
printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
|
||||
printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
|
||||
printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
|
||||
printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
|
||||
printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
|
||||
printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
|
||||
printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
|
||||
printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
|
||||
printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
|
||||
printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
|
||||
printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
|
||||
printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
|
||||
}
|
||||
}
|
||||
|
||||
pReceptionData->IsDemodLocked = p->IsDemodLocked;
|
||||
|
||||
pReceptionData->SNR = p->SNR;
|
||||
pReceptionData->InBandPwr = p->InBandPwr;
|
||||
|
||||
pReceptionData->ErrorTSPackets = 0;
|
||||
pReceptionData->BER = 0;
|
||||
pReceptionData->BERErrorCount = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
pReceptionData->BER += p->LayerInfo[i].BER;
|
||||
pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
|
||||
pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
|
||||
}
|
||||
}
|
||||
|
||||
static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
|
||||
{
|
||||
struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
|
||||
|
|
@ -134,6 +246,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
|
|||
break;
|
||||
|
||||
case MSG_SMS_RF_TUNE_RES:
|
||||
case MSG_SMS_ISDBT_TUNE_RES:
|
||||
complete(&client->tune_done);
|
||||
break;
|
||||
|
||||
|
|
@ -217,6 +330,40 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
|
|||
is_status_update = true;
|
||||
break;
|
||||
}
|
||||
case MSG_SMS_GET_STATISTICS_RES: {
|
||||
union {
|
||||
struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
|
||||
struct SmsMsgStatisticsInfo_ST dvb;
|
||||
} *p = (void *) (phdr + 1);
|
||||
struct RECEPTION_STATISTICS_S *pReceptionData =
|
||||
&client->sms_stat_dvb.ReceptionData;
|
||||
|
||||
sms_info("MSG_SMS_GET_STATISTICS_RES");
|
||||
|
||||
is_status_update = true;
|
||||
|
||||
switch (smscore_get_device_mode(client->coredev)) {
|
||||
case DEVICE_MODE_ISDBT:
|
||||
case DEVICE_MODE_ISDBT_BDA:
|
||||
smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
|
||||
break;
|
||||
default:
|
||||
smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
|
||||
}
|
||||
if (!pReceptionData->IsDemodLocked) {
|
||||
pReceptionData->SNR = 0;
|
||||
pReceptionData->BER = 0;
|
||||
pReceptionData->BERErrorCount = 0;
|
||||
pReceptionData->InBandPwr = 0;
|
||||
pReceptionData->ErrorTSPackets = 0;
|
||||
}
|
||||
|
||||
complete(&client->tune_done);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sms_info("Unhandled message %d", phdr->msgType);
|
||||
|
||||
}
|
||||
smscore_putbuffer(client->coredev, cb);
|
||||
|
||||
|
|
@ -233,10 +380,10 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
|
|||
DVB3_EVENT_UNC_ERR);
|
||||
|
||||
} else {
|
||||
/*client->fe_status =
|
||||
(phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ?
|
||||
0 : FE_HAS_SIGNAL;*/
|
||||
client->fe_status = 0;
|
||||
if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
|
||||
client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
else
|
||||
client->fe_status = 0;
|
||||
sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
|
||||
}
|
||||
}
|
||||
|
|
@ -325,6 +472,20 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
|
|||
0 : -ETIME;
|
||||
}
|
||||
|
||||
static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
|
||||
{
|
||||
int rc;
|
||||
struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
|
||||
DVBT_BDA_CONTROL_MSG_ID,
|
||||
HIF_TASK,
|
||||
sizeof(struct SmsMsgHdr_ST), 0 };
|
||||
|
||||
rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
|
||||
&client->tune_done);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int led_feedback(struct smsdvb_client_t *client)
|
||||
{
|
||||
if (client->fe_status & FE_HAS_LOCK)
|
||||
|
|
@ -337,33 +498,43 @@ static inline int led_feedback(struct smsdvb_client_t *client)
|
|||
|
||||
static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
|
||||
{
|
||||
int rc;
|
||||
struct smsdvb_client_t *client;
|
||||
client = container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
rc = smsdvb_send_statistics_request(client);
|
||||
|
||||
*stat = client->fe_status;
|
||||
|
||||
led_feedback(client);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
int rc;
|
||||
struct smsdvb_client_t *client;
|
||||
client = container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
rc = smsdvb_send_statistics_request(client);
|
||||
|
||||
*ber = client->sms_stat_dvb.ReceptionData.BER;
|
||||
|
||||
led_feedback(client);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
{
|
||||
int rc;
|
||||
|
||||
struct smsdvb_client_t *client;
|
||||
client = container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
rc = smsdvb_send_statistics_request(client);
|
||||
|
||||
if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
|
||||
*strength = 0;
|
||||
else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
|
||||
|
|
@ -375,31 +546,37 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
|||
|
||||
led_feedback(client);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
{
|
||||
int rc;
|
||||
struct smsdvb_client_t *client;
|
||||
client = container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
rc = smsdvb_send_statistics_request(client);
|
||||
|
||||
*snr = client->sms_stat_dvb.ReceptionData.SNR;
|
||||
|
||||
led_feedback(client);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||
{
|
||||
int rc;
|
||||
struct smsdvb_client_t *client;
|
||||
client = container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
rc = smsdvb_send_statistics_request(client);
|
||||
|
||||
*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
|
||||
|
||||
led_feedback(client);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
|
||||
|
|
@ -413,9 +590,10 @@ static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int smsdvb_set_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *fep)
|
||||
static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct smsdvb_client_t *client =
|
||||
container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
|
|
@ -429,24 +607,33 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
|
|||
client->fe_status = FE_HAS_SIGNAL;
|
||||
client->event_fe_state = -1;
|
||||
client->event_unc_state = -1;
|
||||
fe->dtv_property_cache.delivery_system = SYS_DVBT;
|
||||
|
||||
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[0] = c->frequency;
|
||||
Msg.Data[2] = 12000000;
|
||||
|
||||
sms_debug("freq %d band %d",
|
||||
fep->frequency, fep->u.ofdm.bandwidth);
|
||||
sms_info("%s: freq %d band %d", __func__, c->frequency,
|
||||
c->bandwidth_hz);
|
||||
|
||||
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;
|
||||
case BANDWIDTH_AUTO: return -EOPNOTSUPP;
|
||||
default: return -EINVAL;
|
||||
switch (c->bandwidth_hz / 1000000) {
|
||||
case 8:
|
||||
Msg.Data[1] = BW_8_MHZ;
|
||||
break;
|
||||
case 7:
|
||||
Msg.Data[1] = BW_7_MHZ;
|
||||
break;
|
||||
case 6:
|
||||
Msg.Data[1] = BW_6_MHZ;
|
||||
break;
|
||||
case 0:
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Disable LNA, if any. An error is returned if no LNA is present */
|
||||
ret = sms_board_lna_control(client->coredev, 0);
|
||||
|
|
@ -470,6 +657,90 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
|
|||
&client->tune_done);
|
||||
}
|
||||
|
||||
static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
struct smsdvb_client_t *client =
|
||||
container_of(fe, struct smsdvb_client_t, frontend);
|
||||
|
||||
struct {
|
||||
struct SmsMsgHdr_ST Msg;
|
||||
u32 Data[4];
|
||||
} Msg;
|
||||
|
||||
fe->dtv_property_cache.delivery_system = SYS_ISDBT;
|
||||
|
||||
Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
|
||||
Msg.Msg.msgDstId = HIF_TASK;
|
||||
Msg.Msg.msgFlags = 0;
|
||||
Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ;
|
||||
Msg.Msg.msgLength = sizeof(Msg);
|
||||
|
||||
if (c->isdbt_sb_segment_idx == -1)
|
||||
c->isdbt_sb_segment_idx = 0;
|
||||
|
||||
switch (c->isdbt_sb_segment_count) {
|
||||
case 3:
|
||||
Msg.Data[1] = BW_ISDBT_3SEG;
|
||||
break;
|
||||
case 1:
|
||||
Msg.Data[1] = BW_ISDBT_1SEG;
|
||||
break;
|
||||
case 0: /* AUTO */
|
||||
switch (c->bandwidth_hz / 1000000) {
|
||||
case 8:
|
||||
case 7:
|
||||
c->isdbt_sb_segment_count = 3;
|
||||
Msg.Data[1] = BW_ISDBT_3SEG;
|
||||
break;
|
||||
case 6:
|
||||
c->isdbt_sb_segment_count = 1;
|
||||
Msg.Data[1] = BW_ISDBT_1SEG;
|
||||
break;
|
||||
default: /* Assumes 6 MHZ bw */
|
||||
c->isdbt_sb_segment_count = 1;
|
||||
c->bandwidth_hz = 6000;
|
||||
Msg.Data[1] = BW_ISDBT_1SEG;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
Msg.Data[0] = c->frequency;
|
||||
Msg.Data[2] = 12000000;
|
||||
Msg.Data[3] = c->isdbt_sb_segment_idx;
|
||||
|
||||
sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
|
||||
c->frequency, c->isdbt_sb_segment_count,
|
||||
c->isdbt_sb_segment_idx);
|
||||
|
||||
return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
|
||||
&client->tune_done);
|
||||
}
|
||||
|
||||
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 smscore_device_t *coredev = client->coredev;
|
||||
|
||||
switch (smscore_get_device_mode(coredev)) {
|
||||
case DEVICE_MODE_DVBT:
|
||||
case DEVICE_MODE_DVBT_BDA:
|
||||
return smsdvb_dvbt_set_frontend(fe, fep);
|
||||
case DEVICE_MODE_ISDBT:
|
||||
case DEVICE_MODE_ISDBT_BDA:
|
||||
return smsdvb_isdbt_set_frontend(fe, fep);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int smsdvb_get_frontend(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
|
|
@ -557,13 +828,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
|
|||
/* device removal handled by onremove callback */
|
||||
if (!arrival)
|
||||
return 0;
|
||||
|
||||
if (smscore_get_device_mode(coredev) != DEVICE_MODE_DVBT_BDA) {
|
||||
sms_err("SMS Device mode is not set for "
|
||||
"DVB operation.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
|
||||
if (!client) {
|
||||
sms_err("kmalloc() failed");
|
||||
|
|
|
|||
|
|
@ -85,9 +85,9 @@ static struct keyboard_layout_map_t keyboard_layout_maps[] = {
|
|||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
u32 ir_pos;
|
||||
u32 ir_word;
|
||||
u32 ir_toggle;
|
||||
static u32 ir_pos;
|
||||
static u32 ir_word;
|
||||
static u32 ir_toggle;
|
||||
|
||||
#define RC5_PUSH_BIT(dst, bit, pos) \
|
||||
{ dst <<= 1; dst |= bit; pos++; }
|
||||
|
|
|
|||
|
|
@ -268,8 +268,8 @@ int av7110_check_ir_config(struct av7110 *av7110, int force)
|
|||
|
||||
|
||||
/* /proc/av7110_ir interface */
|
||||
static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
char *page;
|
||||
u32 ir_config;
|
||||
|
|
@ -309,6 +309,10 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
|
|||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations av7110_ir_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = av7110_ir_proc_write,
|
||||
};
|
||||
|
||||
/* interrupt handler */
|
||||
static void ir_handler(struct av7110 *av7110, u32 ircom)
|
||||
|
|
@ -368,11 +372,9 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
|
|||
input_dev->timer.data = (unsigned long) &av7110->ir;
|
||||
|
||||
if (av_cnt == 1) {
|
||||
e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
|
||||
if (e) {
|
||||
e->write_proc = av7110_ir_write_proc;
|
||||
e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops);
|
||||
if (e)
|
||||
e->size = 4 + 256 * sizeof(u16);
|
||||
}
|
||||
}
|
||||
|
||||
tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir);
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
|
|||
budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
|
||||
budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
|
||||
budget_ci->ir.last_raw = 0xffff; /* An impossible value */
|
||||
error = ir_input_register(input_dev, ir_codes);
|
||||
error = ir_input_register(input_dev, ir_codes, NULL);
|
||||
if (error) {
|
||||
printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
|
||||
return error;
|
||||
|
|
|
|||
|
|
@ -433,9 +433,8 @@ static struct stv090x_config tt1600_stv090x_config = {
|
|||
.demod_mode = STV090x_SINGLE,
|
||||
.clk_mode = STV090x_CLK_EXT,
|
||||
|
||||
.xtal = 27000000,
|
||||
.xtal = 13500000,
|
||||
.address = 0x68,
|
||||
.ref_clk = 27000000,
|
||||
|
||||
.ts1_mode = STV090x_TSMODE_DVBCI,
|
||||
.ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS,
|
||||
|
|
@ -457,6 +456,7 @@ static struct stv090x_config tt1600_stv090x_config = {
|
|||
static struct stv6110x_config tt1600_stv6110x_config = {
|
||||
.addr = 0x60,
|
||||
.refclk = 27000000,
|
||||
.clk_div = 2,
|
||||
};
|
||||
|
||||
static struct isl6423_config tt1600_isl6423_config = {
|
||||
|
|
|
|||
|
|
@ -417,6 +417,18 @@ config RADIO_TEA5764_XTAL
|
|||
Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
|
||||
here if TEA5764 reference frequency is connected in FREQIN.
|
||||
|
||||
config RADIO_SAA7706H
|
||||
tristate "SAA7706H Car Radio DSP"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
---help---
|
||||
Say Y here if you want to use the SAA7706H Car radio Digital
|
||||
Signal Processor, found for instance on the Russellville development
|
||||
board. On the russellville the device is connected to internal
|
||||
timberdale I2C bus.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called SAA7706H.
|
||||
|
||||
config RADIO_TEF6862
|
||||
tristate "TEF6862 Car Radio Enhanced Selectivity Tuner"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
|
|
@ -429,4 +441,15 @@ config RADIO_TEF6862
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called TEF6862.
|
||||
|
||||
config RADIO_TIMBERDALE
|
||||
tristate "Enable the Timberdale radio driver"
|
||||
depends on MFD_TIMBERDALE && VIDEO_V4L2
|
||||
depends on I2C # for RADIO_SAA7706H
|
||||
select RADIO_TEF6862
|
||||
select RADIO_SAA7706H
|
||||
---help---
|
||||
This is a kind of umbrella driver for the Radio Tuner and DSP
|
||||
found behind the Timberdale FPGA on the Russellville board.
|
||||
Enabling this driver will automatically select the DSP and tuner.
|
||||
|
||||
endif # RADIO_ADAPTERS
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ obj-$(CONFIG_USB_DSBR) += dsbr100.o
|
|||
obj-$(CONFIG_RADIO_SI470X) += si470x/
|
||||
obj-$(CONFIG_USB_MR800) += radio-mr800.o
|
||||
obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
|
||||
obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
|
||||
obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
|
||||
obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
|
||||
|
||||
EXTRA_CFLAGS += -Isound
|
||||
|
|
|
|||
244
drivers/media/radio/radio-timb.c
Normal file
244
drivers/media/radio/radio-timb.c
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* radio-timb.c Timberdale FPGA Radio driver
|
||||
* Copyright (c) 2009 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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/version.h>
|
||||
#include <linux/io.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <media/timb_radio.h>
|
||||
|
||||
#define DRIVER_NAME "timb-radio"
|
||||
|
||||
struct timbradio {
|
||||
struct timb_radio_platform_data pdata;
|
||||
struct v4l2_subdev *sd_tuner;
|
||||
struct v4l2_subdev *sd_dsp;
|
||||
struct video_device video_dev;
|
||||
struct v4l2_device v4l2_dev;
|
||||
};
|
||||
|
||||
|
||||
static int timbradio_vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *v)
|
||||
{
|
||||
strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver));
|
||||
strlcpy(v->card, "Timberdale Radio", sizeof(v->card));
|
||||
snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME);
|
||||
v->version = KERNEL_VERSION(0, 0, 1);
|
||||
v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_g_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_tuner, tuner, g_tuner, v);
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_s_tuner(struct file *file, void *priv,
|
||||
struct v4l2_tuner *v)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v);
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_g_input(struct file *filp, void *priv,
|
||||
unsigned int *i)
|
||||
{
|
||||
*i = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_s_input(struct file *filp, void *priv,
|
||||
unsigned int i)
|
||||
{
|
||||
return i ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_g_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
{
|
||||
a->index = 0;
|
||||
strlcpy(a->name, "Radio", sizeof(a->name));
|
||||
a->capability = V4L2_AUDCAP_STEREO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_s_audio(struct file *file, void *priv,
|
||||
struct v4l2_audio *a)
|
||||
{
|
||||
return a->index ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_s_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_tuner, tuner, s_frequency, f);
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_g_frequency(struct file *file, void *priv,
|
||||
struct v4l2_frequency *f)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f);
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_queryctrl(struct file *file, void *priv,
|
||||
struct v4l2_queryctrl *qc)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc);
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_g_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl);
|
||||
}
|
||||
|
||||
static int timbradio_vidioc_s_ctrl(struct file *file, void *priv,
|
||||
struct v4l2_control *ctrl)
|
||||
{
|
||||
struct timbradio *tr = video_drvdata(file);
|
||||
return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl);
|
||||
}
|
||||
|
||||
static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
|
||||
.vidioc_querycap = timbradio_vidioc_querycap,
|
||||
.vidioc_g_tuner = timbradio_vidioc_g_tuner,
|
||||
.vidioc_s_tuner = timbradio_vidioc_s_tuner,
|
||||
.vidioc_g_frequency = timbradio_vidioc_g_frequency,
|
||||
.vidioc_s_frequency = timbradio_vidioc_s_frequency,
|
||||
.vidioc_g_input = timbradio_vidioc_g_input,
|
||||
.vidioc_s_input = timbradio_vidioc_s_input,
|
||||
.vidioc_g_audio = timbradio_vidioc_g_audio,
|
||||
.vidioc_s_audio = timbradio_vidioc_s_audio,
|
||||
.vidioc_queryctrl = timbradio_vidioc_queryctrl,
|
||||
.vidioc_g_ctrl = timbradio_vidioc_g_ctrl,
|
||||
.vidioc_s_ctrl = timbradio_vidioc_s_ctrl
|
||||
};
|
||||
|
||||
static const struct v4l2_file_operations timbradio_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = video_ioctl2,
|
||||
};
|
||||
|
||||
static int __devinit timbradio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct timbradio *tr;
|
||||
int err;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "Platform data missing\n");
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
tr = kzalloc(sizeof(*tr), GFP_KERNEL);
|
||||
if (!tr) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
tr->pdata = *pdata;
|
||||
|
||||
strlcpy(tr->video_dev.name, "Timberdale Radio",
|
||||
sizeof(tr->video_dev.name));
|
||||
tr->video_dev.fops = &timbradio_fops;
|
||||
tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
|
||||
tr->video_dev.release = video_device_release_empty;
|
||||
tr->video_dev.minor = -1;
|
||||
|
||||
strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
|
||||
err = v4l2_device_register(NULL, &tr->v4l2_dev);
|
||||
if (err)
|
||||
goto err_v4l2_dev;
|
||||
|
||||
tr->video_dev.v4l2_dev = &tr->v4l2_dev;
|
||||
|
||||
err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Error reg video\n");
|
||||
goto err_video_req;
|
||||
}
|
||||
|
||||
video_set_drvdata(&tr->video_dev, tr);
|
||||
|
||||
platform_set_drvdata(pdev, tr);
|
||||
return 0;
|
||||
|
||||
err_video_req:
|
||||
video_device_release_empty(&tr->video_dev);
|
||||
v4l2_device_unregister(&tr->v4l2_dev);
|
||||
err_v4l2_dev:
|
||||
kfree(tr);
|
||||
err:
|
||||
dev_err(&pdev->dev, "Failed to register: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit timbradio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct timbradio *tr = platform_get_drvdata(pdev);
|
||||
|
||||
video_unregister_device(&tr->video_dev);
|
||||
video_device_release_empty(&tr->video_dev);
|
||||
|
||||
v4l2_device_unregister(&tr->v4l2_dev);
|
||||
|
||||
kfree(tr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver timbradio_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = timbradio_probe,
|
||||
.remove = timbradio_remove,
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int __init timbradio_init(void)
|
||||
{
|
||||
return platform_driver_register(&timbradio_platform_driver);
|
||||
}
|
||||
|
||||
static void __exit timbradio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&timbradio_platform_driver);
|
||||
}
|
||||
|
||||
module_init(timbradio_init);
|
||||
module_exit(timbradio_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Timberdale Radio driver");
|
||||
MODULE_AUTHOR("Mocean Laboratories <[email protected]>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:"DRIVER_NAME);
|
||||
451
drivers/media/radio/saa7706h.c
Normal file
451
drivers/media/radio/saa7706h.c
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
/*
|
||||
* saa7706.c Philips SAA7706H Car Radio DSP driver
|
||||
* Copyright (c) 2009 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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 <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-chip-ident.h>
|
||||
|
||||
#define DRIVER_NAME "saa7706h"
|
||||
|
||||
/* the I2C memory map looks like this
|
||||
|
||||
$1C00 - $FFFF Not Used
|
||||
$2200 - $3FFF Reserved YRAM (DSP2) space
|
||||
$2000 - $21FF YRAM (DSP2)
|
||||
$1FF0 - $1FFF Hardware Registers
|
||||
$1280 - $1FEF Reserved XRAM (DSP2) space
|
||||
$1000 - $127F XRAM (DSP2)
|
||||
$0FFF DSP CONTROL
|
||||
$0A00 - $0FFE Reserved
|
||||
$0980 - $09FF Reserved YRAM (DSP1) space
|
||||
$0800 - $097F YRAM (DSP1)
|
||||
$0200 - $07FF Not Used
|
||||
$0180 - $01FF Reserved XRAM (DSP1) space
|
||||
$0000 - $017F XRAM (DSP1)
|
||||
*/
|
||||
|
||||
#define SAA7706H_REG_CTRL 0x0fff
|
||||
#define SAA7706H_CTRL_BYP_PLL 0x0001
|
||||
#define SAA7706H_CTRL_PLL_DIV_MASK 0x003e
|
||||
#define SAA7706H_CTRL_PLL3_62975MHZ 0x003e
|
||||
#define SAA7706H_CTRL_DSP_TURBO 0x0040
|
||||
#define SAA7706H_CTRL_PC_RESET_DSP1 0x0080
|
||||
#define SAA7706H_CTRL_PC_RESET_DSP2 0x0100
|
||||
#define SAA7706H_CTRL_DSP1_ROM_EN_MASK 0x0600
|
||||
#define SAA7706H_CTRL_DSP1_FUNC_PROM 0x0000
|
||||
#define SAA7706H_CTRL_DSP2_ROM_EN_MASK 0x1800
|
||||
#define SAA7706H_CTRL_DSP2_FUNC_PROM 0x0000
|
||||
#define SAA7706H_CTRL_DIG_SIL_INTERPOL 0x8000
|
||||
|
||||
#define SAA7706H_REG_EVALUATION 0x1ff0
|
||||
#define SAA7706H_EVAL_DISABLE_CHARGE_PUMP 0x000001
|
||||
#define SAA7706H_EVAL_DCS_CLOCK 0x000002
|
||||
#define SAA7706H_EVAL_GNDRC1_ENABLE 0x000004
|
||||
#define SAA7706H_EVAL_GNDRC2_ENABLE 0x000008
|
||||
|
||||
#define SAA7706H_REG_CL_GEN1 0x1ff3
|
||||
#define SAA7706H_CL_GEN1_MIN_LOOPGAIN_MASK 0x00000f
|
||||
#define SAA7706H_CL_GEN1_LOOPGAIN_MASK 0x0000f0
|
||||
#define SAA7706H_CL_GEN1_COARSE_RATION 0xffff00
|
||||
|
||||
#define SAA7706H_REG_CL_GEN2 0x1ff4
|
||||
#define SAA7706H_CL_GEN2_WSEDGE_FALLING 0x000001
|
||||
#define SAA7706H_CL_GEN2_STOP_VCO 0x000002
|
||||
#define SAA7706H_CL_GEN2_FRERUN 0x000004
|
||||
#define SAA7706H_CL_GEN2_ADAPTIVE 0x000008
|
||||
#define SAA7706H_CL_GEN2_FINE_RATIO_MASK 0x0ffff0
|
||||
|
||||
#define SAA7706H_REG_CL_GEN4 0x1ff6
|
||||
#define SAA7706H_CL_GEN4_BYPASS_PLL1 0x001000
|
||||
#define SAA7706H_CL_GEN4_PLL1_DIV_MASK 0x03e000
|
||||
#define SAA7706H_CL_GEN4_DSP1_TURBO 0x040000
|
||||
|
||||
#define SAA7706H_REG_SEL 0x1ff7
|
||||
#define SAA7706H_SEL_DSP2_SRCA_MASK 0x000007
|
||||
#define SAA7706H_SEL_DSP2_FMTA_MASK 0x000031
|
||||
#define SAA7706H_SEL_DSP2_SRCB_MASK 0x0001c0
|
||||
#define SAA7706H_SEL_DSP2_FMTB_MASK 0x000e00
|
||||
#define SAA7706H_SEL_DSP1_SRC_MASK 0x003000
|
||||
#define SAA7706H_SEL_DSP1_FMT_MASK 0x01c003
|
||||
#define SAA7706H_SEL_SPDIF2 0x020000
|
||||
#define SAA7706H_SEL_HOST_IO_FMT_MASK 0x1c0000
|
||||
#define SAA7706H_SEL_EN_HOST_IO 0x200000
|
||||
|
||||
#define SAA7706H_REG_IAC 0x1ff8
|
||||
#define SAA7706H_REG_CLK_SET 0x1ff9
|
||||
#define SAA7706H_REG_CLK_COEFF 0x1ffa
|
||||
#define SAA7706H_REG_INPUT_SENS 0x1ffb
|
||||
#define SAA7706H_INPUT_SENS_RDS_VOL_MASK 0x0003f
|
||||
#define SAA7706H_INPUT_SENS_FM_VOL_MASK 0x00fc0
|
||||
#define SAA7706H_INPUT_SENS_FM_MPX 0x01000
|
||||
#define SAA7706H_INPUT_SENS_OFF_FILTER_A_EN 0x02000
|
||||
#define SAA7706H_INPUT_SENS_OFF_FILTER_B_EN 0x04000
|
||||
#define SAA7706H_REG_PHONE_NAV_AUDIO 0x1ffc
|
||||
#define SAA7706H_REG_IO_CONF_DSP2 0x1ffd
|
||||
#define SAA7706H_REG_STATUS_DSP2 0x1ffe
|
||||
#define SAA7706H_REG_PC_DSP2 0x1fff
|
||||
|
||||
#define SAA7706H_DSP1_MOD0 0x0800
|
||||
#define SAA7706H_DSP1_ROM_VER 0x097f
|
||||
#define SAA7706H_DSP2_MPTR0 0x1000
|
||||
|
||||
#define SAA7706H_DSP1_MODPNTR 0x0000
|
||||
|
||||
#define SAA7706H_DSP2_XMEM_CONTLLCW 0x113e
|
||||
#define SAA7706H_DSP2_XMEM_BUSAMP 0x114a
|
||||
#define SAA7706H_DSP2_XMEM_FDACPNTR 0x11f9
|
||||
#define SAA7706H_DSP2_XMEM_IIS1PNTR 0x11fb
|
||||
|
||||
#define SAA7706H_DSP2_YMEM_PVGA 0x212a
|
||||
#define SAA7706H_DSP2_YMEM_PVAT1 0x212b
|
||||
#define SAA7706H_DSP2_YMEM_PVAT 0x212c
|
||||
#define SAA7706H_DSP2_YMEM_ROM_VER 0x21ff
|
||||
|
||||
#define SUPPORTED_DSP1_ROM_VER 0x667
|
||||
|
||||
struct saa7706h_state {
|
||||
struct v4l2_subdev sd;
|
||||
unsigned muted;
|
||||
};
|
||||
|
||||
static inline struct saa7706h_state *to_state(struct v4l2_subdev *sd)
|
||||
{
|
||||
return container_of(sd, struct saa7706h_state, sd);
|
||||
}
|
||||
|
||||
static int saa7706h_i2c_send(struct i2c_client *client, const u8 *data, int len)
|
||||
{
|
||||
int err = i2c_master_send(client, data, len);
|
||||
if (err == len)
|
||||
return 0;
|
||||
return err > 0 ? -EIO : err;
|
||||
}
|
||||
|
||||
static int saa7706h_i2c_transfer(struct i2c_client *client,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
int err = i2c_transfer(client->adapter, msgs, num);
|
||||
if (err == num)
|
||||
return 0;
|
||||
return err > 0 ? -EIO : err;
|
||||
}
|
||||
|
||||
static int saa7706h_set_reg24(struct v4l2_subdev *sd, u16 reg, u32 val)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
u8 buf[5];
|
||||
int pos = 0;
|
||||
|
||||
buf[pos++] = reg >> 8;
|
||||
buf[pos++] = reg;
|
||||
buf[pos++] = val >> 16;
|
||||
buf[pos++] = val >> 8;
|
||||
buf[pos++] = val;
|
||||
|
||||
return saa7706h_i2c_send(client, buf, pos);
|
||||
}
|
||||
|
||||
static int saa7706h_set_reg24_err(struct v4l2_subdev *sd, u16 reg, u32 val,
|
||||
int *err)
|
||||
{
|
||||
return *err ? *err : saa7706h_set_reg24(sd, reg, val);
|
||||
}
|
||||
|
||||
static int saa7706h_set_reg16(struct v4l2_subdev *sd, u16 reg, u16 val)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
u8 buf[4];
|
||||
int pos = 0;
|
||||
|
||||
buf[pos++] = reg >> 8;
|
||||
buf[pos++] = reg;
|
||||
buf[pos++] = val >> 8;
|
||||
buf[pos++] = val;
|
||||
|
||||
return saa7706h_i2c_send(client, buf, pos);
|
||||
}
|
||||
|
||||
static int saa7706h_set_reg16_err(struct v4l2_subdev *sd, u16 reg, u16 val,
|
||||
int *err)
|
||||
{
|
||||
return *err ? *err : saa7706h_set_reg16(sd, reg, val);
|
||||
}
|
||||
|
||||
static int saa7706h_get_reg16(struct v4l2_subdev *sd, u16 reg)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
u8 buf[2];
|
||||
int err;
|
||||
u8 regaddr[] = {reg >> 8, reg};
|
||||
struct i2c_msg msg[] = { {client->addr, 0, sizeof(regaddr), regaddr},
|
||||
{client->addr, I2C_M_RD, sizeof(buf), buf} };
|
||||
|
||||
err = saa7706h_i2c_transfer(client, msg, ARRAY_SIZE(msg));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return buf[0] << 8 | buf[1];
|
||||
}
|
||||
|
||||
static int saa7706h_unmute(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct saa7706h_state *state = to_state(sd);
|
||||
int err = 0;
|
||||
|
||||
err = saa7706h_set_reg16_err(sd, SAA7706H_REG_CTRL,
|
||||
SAA7706H_CTRL_PLL3_62975MHZ | SAA7706H_CTRL_PC_RESET_DSP1 |
|
||||
SAA7706H_CTRL_PC_RESET_DSP2, &err);
|
||||
|
||||
/* newer versions of the chip requires a small sleep after reset */
|
||||
msleep(1);
|
||||
|
||||
err = saa7706h_set_reg16_err(sd, SAA7706H_REG_CTRL,
|
||||
SAA7706H_CTRL_PLL3_62975MHZ, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_EVALUATION, 0, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN1, 0x040022, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN2,
|
||||
SAA7706H_CL_GEN2_WSEDGE_FALLING, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CL_GEN4, 0x024080, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_SEL, 0x200080, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_IAC, 0xf4caed, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CLK_SET, 0x124334, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_CLK_COEFF, 0x004a1a,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_INPUT_SENS, 0x0071c7,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_PHONE_NAV_AUDIO,
|
||||
0x0e22ff, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_IO_CONF_DSP2, 0x001ff8,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_STATUS_DSP2, 0x080003,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_REG_PC_DSP2, 0x000004, &err);
|
||||
|
||||
err = saa7706h_set_reg16_err(sd, SAA7706H_DSP1_MOD0, 0x0c6c, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_MPTR0, 0x000b4b, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP1_MODPNTR, 0x000600, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP1_MODPNTR, 0x0000c0, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x000819,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x00085a,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_BUSAMP, 0x7fffff,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_FDACPNTR, 0x2000cb,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_IIS1PNTR, 0x2000cb,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVGA, 0x0f80, &err);
|
||||
|
||||
err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVAT1, 0x0800,
|
||||
&err);
|
||||
|
||||
err = saa7706h_set_reg16_err(sd, SAA7706H_DSP2_YMEM_PVAT, 0x0800, &err);
|
||||
|
||||
err = saa7706h_set_reg24_err(sd, SAA7706H_DSP2_XMEM_CONTLLCW, 0x000905,
|
||||
&err);
|
||||
if (!err)
|
||||
state->muted = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int saa7706h_mute(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct saa7706h_state *state = to_state(sd);
|
||||
int err;
|
||||
|
||||
err = saa7706h_set_reg16(sd, SAA7706H_REG_CTRL,
|
||||
SAA7706H_CTRL_PLL3_62975MHZ | SAA7706H_CTRL_PC_RESET_DSP1 |
|
||||
SAA7706H_CTRL_PC_RESET_DSP2);
|
||||
if (!err)
|
||||
state->muted = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int saa7706h_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
|
||||
{
|
||||
switch (qc->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int saa7706h_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
|
||||
{
|
||||
struct saa7706h_state *state = to_state(sd);
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
ctrl->value = state->muted;
|
||||
return 0;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
|
||||
{
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_AUDIO_MUTE:
|
||||
if (ctrl->value)
|
||||
return saa7706h_mute(sd);
|
||||
return saa7706h_unmute(sd);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int saa7706h_g_chip_ident(struct v4l2_subdev *sd,
|
||||
struct v4l2_dbg_chip_ident *chip)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7706H, 0);
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_core_ops saa7706h_core_ops = {
|
||||
.g_chip_ident = saa7706h_g_chip_ident,
|
||||
.queryctrl = saa7706h_queryctrl,
|
||||
.g_ctrl = saa7706h_g_ctrl,
|
||||
.s_ctrl = saa7706h_s_ctrl,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops saa7706h_ops = {
|
||||
.core = &saa7706h_core_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* Generic i2c probe
|
||||
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
|
||||
*/
|
||||
|
||||
static int __devinit saa7706h_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct saa7706h_state *state;
|
||||
struct v4l2_subdev *sd;
|
||||
int err;
|
||||
|
||||
/* Check if the adapter supports the needed features */
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -EIO;
|
||||
|
||||
v4l_info(client, "chip found @ 0x%02x (%s)\n",
|
||||
client->addr << 1, client->adapter->name);
|
||||
|
||||
state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
return -ENOMEM;
|
||||
sd = &state->sd;
|
||||
v4l2_i2c_subdev_init(sd, client, &saa7706h_ops);
|
||||
|
||||
/* check the rom versions */
|
||||
err = saa7706h_get_reg16(sd, SAA7706H_DSP1_ROM_VER);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
if (err != SUPPORTED_DSP1_ROM_VER)
|
||||
v4l2_warn(sd, "Unknown DSP1 ROM code version: 0x%x\n", err);
|
||||
|
||||
state->muted = 1;
|
||||
|
||||
/* startup in a muted state */
|
||||
err = saa7706h_mute(sd);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
kfree(to_state(sd));
|
||||
|
||||
printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit saa7706h_remove(struct i2c_client *client)
|
||||
{
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
|
||||
saa7706h_mute(sd);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
kfree(to_state(sd));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id saa7706h_id[] = {
|
||||
{DRIVER_NAME, 0},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, saa7706h_id);
|
||||
|
||||
static struct i2c_driver saa7706h_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = DRIVER_NAME,
|
||||
},
|
||||
.probe = saa7706h_probe,
|
||||
.remove = saa7706h_remove,
|
||||
.id_table = saa7706h_id,
|
||||
};
|
||||
|
||||
static __init int saa7706h_init(void)
|
||||
{
|
||||
return i2c_add_driver(&saa7706h_driver);
|
||||
}
|
||||
|
||||
static __exit void saa7706h_exit(void)
|
||||
{
|
||||
i2c_del_driver(&saa7706h_driver);
|
||||
}
|
||||
|
||||
module_init(saa7706h_init);
|
||||
module_exit(saa7706h_exit);
|
||||
|
||||
MODULE_DESCRIPTION("SAA7706H Car Radio DSP driver");
|
||||
MODULE_AUTHOR("Mocean Laboratories");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -724,7 +724,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
|
|||
tuner->audmode = V4L2_TUNER_MODE_MONO;
|
||||
|
||||
/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
|
||||
/* measured in units of db쨉V in 1 db increments (max at ~75 db쨉V) */
|
||||
/* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
|
||||
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
|
||||
/* the ideal factor is 0xffff/75 = 873,8 */
|
||||
tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
|
||||
|
|
|
|||
|
|
@ -590,8 +590,9 @@ int si470x_fops_release(struct file *file)
|
|||
video_unregister_device(radio->videodev);
|
||||
kfree(radio->int_in_buffer);
|
||||
kfree(radio->buffer);
|
||||
mutex_unlock(&radio->disconnect_lock);
|
||||
kfree(radio);
|
||||
goto unlock;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* cancel read processes */
|
||||
|
|
@ -601,7 +602,6 @@ int si470x_fops_release(struct file *file)
|
|||
retval = si470x_stop(radio);
|
||||
usb_autopm_put_interface(radio->intf);
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&radio->disconnect_lock);
|
||||
done:
|
||||
return retval;
|
||||
|
|
@ -842,9 +842,11 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
|
|||
kfree(radio->int_in_buffer);
|
||||
video_unregister_device(radio->videodev);
|
||||
kfree(radio->buffer);
|
||||
mutex_unlock(&radio->disconnect_lock);
|
||||
kfree(radio);
|
||||
} else {
|
||||
mutex_unlock(&radio->disconnect_lock);
|
||||
}
|
||||
mutex_unlock(&radio->disconnect_lock);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -388,6 +388,15 @@ config VIDEO_TVP5150
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called tvp5150.
|
||||
|
||||
config VIDEO_TVP7002
|
||||
tristate "Texas Instruments TVP7002 video decoder"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
---help---
|
||||
Support for the Texas Instruments TVP7002 video decoder.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called tvp7002.
|
||||
|
||||
config VIDEO_VPX3220
|
||||
tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
|
|
@ -548,7 +557,6 @@ config VIDEO_VPSS_SYSTEM
|
|||
depends on ARCH_DAVINCI
|
||||
help
|
||||
Support for vpss system module for video driver
|
||||
default y
|
||||
|
||||
config VIDEO_VPFE_CAPTURE
|
||||
tristate "VPFE Video Capture Driver"
|
||||
|
|
@ -592,6 +600,19 @@ config VIDEO_DM355_CCDC
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
|
||||
config VIDEO_ISIF
|
||||
tristate "ISIF HW module"
|
||||
depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables ISIF hw module. This is the hardware module for
|
||||
configuring ISIF in VPFE to capture Raw Bayer RGB data from
|
||||
a image sensor or YUV data from a YUV source.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
|
||||
source "drivers/media/video/bt8xx/Kconfig"
|
||||
|
||||
config VIDEO_PMS
|
||||
|
|
@ -638,9 +659,14 @@ config VIDEO_W9966
|
|||
information.
|
||||
|
||||
config VIDEO_CPIA
|
||||
tristate "CPiA Video For Linux"
|
||||
tristate "CPiA Video For Linux (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca cpia1 module
|
||||
instead. Note that you need atleast version 0.6.4 of libv4l for
|
||||
the cpia1 gspca module.
|
||||
|
||||
This is the video4linux driver for cameras based on Vision's CPiA
|
||||
(Colour Processor Interface ASIC), such as the Creative Labs Video
|
||||
Blaster Webcam II. If you have one of these cameras, say Y here
|
||||
|
|
@ -944,6 +970,8 @@ source "drivers/media/video/hdpvr/Kconfig"
|
|||
|
||||
source "drivers/media/video/em28xx/Kconfig"
|
||||
|
||||
source "drivers/media/video/tlg2300/Kconfig"
|
||||
|
||||
source "drivers/media/video/cx231xx/Kconfig"
|
||||
|
||||
source "drivers/media/video/usbvision/Kconfig"
|
||||
|
|
@ -955,6 +983,7 @@ source "drivers/media/video/et61x251/Kconfig"
|
|||
config VIDEO_OVCAMCHIP
|
||||
tristate "OmniVision Camera Chip support (DEPRECATED)"
|
||||
depends on I2C && VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the ov511 / ov518 support of the gspca module
|
||||
|
|
@ -971,6 +1000,7 @@ config VIDEO_OVCAMCHIP
|
|||
config USB_W9968CF
|
||||
tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the w9968cf support of the gspca module
|
||||
|
|
@ -992,6 +1022,7 @@ config USB_W9968CF
|
|||
config USB_OV511
|
||||
tristate "USB OV511 Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the ov511 / ov518 support of the gspca module
|
||||
|
|
@ -1020,6 +1051,7 @@ source "drivers/media/video/sn9c102/Kconfig"
|
|||
config USB_STV680
|
||||
tristate "USB STV680 (Pencam) Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca stv0680 module
|
||||
instead. Note that for the gspca stv0680 module you need
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
|
|||
obj-$(CONFIG_VIDEO_VINO) += indycam.o
|
||||
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
|
||||
obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
|
||||
obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
|
||||
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
|
||||
obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
|
||||
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
|
||||
|
|
@ -99,6 +100,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o
|
|||
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
|
||||
obj-$(CONFIG_VIDEO_CX88) += cx88/
|
||||
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
|
||||
obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
|
||||
obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
|
||||
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
|
||||
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
|
|||
v4l2_err(sd, "no notify found!\n");
|
||||
|
||||
if (std & V4L2_STD_NTSC) {
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0);
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
|
||||
bt819_setbit(decoder, 0x01, 0, 1);
|
||||
bt819_setbit(decoder, 0x01, 1, 0);
|
||||
bt819_setbit(decoder, 0x01, 5, 0);
|
||||
|
|
@ -263,7 +263,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
|
|||
/* bt819_setbit(decoder, 0x1a, 5, 1); */
|
||||
timing = &timing_data[1];
|
||||
} else if (std & V4L2_STD_PAL) {
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0);
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
|
||||
bt819_setbit(decoder, 0x01, 0, 1);
|
||||
bt819_setbit(decoder, 0x01, 1, 1);
|
||||
bt819_setbit(decoder, 0x01, 5, 1);
|
||||
|
|
@ -288,7 +288,7 @@ static int bt819_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
|
|||
bt819_write(decoder, 0x08, (timing->hscale >> 8) & 0xff);
|
||||
bt819_write(decoder, 0x09, timing->hscale & 0xff);
|
||||
decoder->norm = std;
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0);
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -306,7 +306,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd,
|
|||
v4l2_err(sd, "no notify found!\n");
|
||||
|
||||
if (decoder->input != input) {
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, 0);
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
|
||||
decoder->input = input;
|
||||
/* select mode */
|
||||
if (decoder->input == 0) {
|
||||
|
|
@ -316,7 +316,7 @@ static int bt819_s_routing(struct v4l2_subdev *sd,
|
|||
bt819_setbit(decoder, 0x0b, 6, 1);
|
||||
bt819_setbit(decoder, 0x1a, 1, 0);
|
||||
}
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, 0);
|
||||
v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
|
|||
static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
|
||||
static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
|
||||
static int debug_latency;
|
||||
static int disable_ir;
|
||||
|
||||
static unsigned int fdsr;
|
||||
|
||||
|
|
@ -107,6 +108,7 @@ module_param(bttv_gpio, int, 0644);
|
|||
module_param(bttv_debug, int, 0644);
|
||||
module_param(irq_debug, int, 0644);
|
||||
module_param(debug_latency, int, 0644);
|
||||
module_param(disable_ir, int, 0444);
|
||||
|
||||
module_param(fdsr, int, 0444);
|
||||
module_param(gbuffers, int, 0444);
|
||||
|
|
@ -139,6 +141,7 @@ MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
|
|||
MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
|
||||
MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
|
||||
MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
|
||||
MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
|
||||
MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
|
||||
MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
|
||||
MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
|
||||
|
|
@ -4461,8 +4464,10 @@ static int __devinit bttv_probe(struct pci_dev *dev,
|
|||
request_modules(btv);
|
||||
}
|
||||
|
||||
init_bttv_i2c_ir(btv);
|
||||
bttv_input_init(btv);
|
||||
if (!disable_ir) {
|
||||
init_bttv_i2c_ir(btv);
|
||||
bttv_input_init(btv);
|
||||
}
|
||||
|
||||
/* everything is fine */
|
||||
bttv_num++;
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ int bttv_input_init(struct bttv *btv)
|
|||
struct card_ir *ir;
|
||||
struct ir_scancode_table *ir_codes = NULL;
|
||||
struct input_dev *input_dev;
|
||||
int ir_type = IR_TYPE_OTHER;
|
||||
u64 ir_type = IR_TYPE_OTHER;
|
||||
int err = -ENOMEM;
|
||||
|
||||
if (!btv->has_remote)
|
||||
|
|
@ -389,7 +389,7 @@ int bttv_input_init(struct bttv *btv)
|
|||
bttv_ir_start(btv, ir);
|
||||
|
||||
/* all done */
|
||||
err = ir_input_register(btv->remote->dev, ir_codes);
|
||||
err = ir_input_register(btv->remote->dev, ir_codes, NULL);
|
||||
if (err)
|
||||
goto err_out_stop;
|
||||
|
||||
|
|
|
|||
|
|
@ -1907,7 +1907,6 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
|||
goto out_free;
|
||||
|
||||
mutex_init(&cam->s_mutex);
|
||||
mutex_lock(&cam->s_mutex);
|
||||
spin_lock_init(&cam->dev_lock);
|
||||
cam->state = S_NOTREADY;
|
||||
cafe_set_config_needed(cam, 1);
|
||||
|
|
@ -1947,7 +1946,6 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
|||
* because the sensor could attach in this call chain, leading to
|
||||
* unsightly deadlocks.
|
||||
*/
|
||||
mutex_unlock(&cam->s_mutex); /* attach can deadlock */
|
||||
ret = cafe_smbus_setup(cam);
|
||||
if (ret)
|
||||
goto out_freeirq;
|
||||
|
|
@ -1973,7 +1971,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
|||
cam->vdev.v4l2_dev = &cam->v4l2_dev;
|
||||
ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
|
||||
if (ret)
|
||||
goto out_smbus;
|
||||
goto out_unlock;
|
||||
video_set_drvdata(&cam->vdev, cam);
|
||||
|
||||
/*
|
||||
|
|
@ -1988,6 +1986,8 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
|||
mutex_unlock(&cam->s_mutex);
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&cam->s_mutex);
|
||||
out_smbus:
|
||||
cafe_smbus_shutdown(cam);
|
||||
out_freeirq:
|
||||
|
|
|
|||
|
|
@ -3737,9 +3737,6 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
if (size > FRAME_NUM*CPIA_MAX_FRAME_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cam || !cam->ops)
|
||||
return -ENODEV;
|
||||
|
||||
/* make this _really_ smp-safe */
|
||||
if (mutex_lock_interruptible(&cam->busy_lock))
|
||||
return -EINTR;
|
||||
|
|
|
|||
|
|
@ -19,3 +19,14 @@ config VIDEO_CX18
|
|||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cx18.
|
||||
|
||||
config VIDEO_CX18_ALSA
|
||||
tristate "Conexant 23418 DMA audio support"
|
||||
depends on VIDEO_CX18 && SND && EXPERIMENTAL
|
||||
select SND_PCM
|
||||
---help---
|
||||
This is a video4linux driver for direct (DMA) audio on
|
||||
Conexant 23418 based TV cards using ALSA.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cx18-alsa.
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ cx18-objs := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.
|
|||
cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
|
||||
cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
|
||||
cx18-dvb.o cx18-io.o
|
||||
cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CX18) += cx18.o
|
||||
obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
|
||||
|
|
|
|||
293
drivers/media/video/cx18/cx18-alsa-main.c
Normal file
293
drivers/media/video/cx18/cx18-alsa-main.c
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* ALSA interface to cx18 PCM capture streams
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.net>
|
||||
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
|
||||
*
|
||||
* Portions of this work were sponsored by ONELAN Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/initval.h>
|
||||
|
||||
#include "cx18-driver.h"
|
||||
#include "cx18-version.h"
|
||||
#include "cx18-alsa.h"
|
||||
#include "cx18-alsa-mixer.h"
|
||||
#include "cx18-alsa-pcm.h"
|
||||
|
||||
int cx18_alsa_debug;
|
||||
|
||||
#define CX18_DEBUG_ALSA_INFO(fmt, arg...) \
|
||||
do { \
|
||||
if (cx18_alsa_debug & 2) \
|
||||
printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \
|
||||
} while (0);
|
||||
|
||||
module_param_named(debug, cx18_alsa_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,
|
||||
"Debug level (bitmask). Default: 0\n"
|
||||
"\t\t\t 1/0x0001: warning\n"
|
||||
"\t\t\t 2/0x0002: info\n");
|
||||
|
||||
MODULE_AUTHOR("Andy Walls");
|
||||
MODULE_DESCRIPTION("CX23418 ALSA Interface");
|
||||
MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
MODULE_VERSION(CX18_VERSION);
|
||||
|
||||
static inline
|
||||
struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev)
|
||||
{
|
||||
return to_cx18(v4l2_dev)->alsa;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev)
|
||||
{
|
||||
return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev);
|
||||
}
|
||||
|
||||
static void snd_cx18_card_free(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
if (cxsc == NULL)
|
||||
return;
|
||||
|
||||
if (cxsc->v4l2_dev != NULL)
|
||||
to_cx18(cxsc->v4l2_dev)->alsa = NULL;
|
||||
|
||||
/* FIXME - take any other stopping actions needed */
|
||||
|
||||
kfree(cxsc);
|
||||
}
|
||||
|
||||
static void snd_cx18_card_private_free(struct snd_card *sc)
|
||||
{
|
||||
if (sc == NULL)
|
||||
return;
|
||||
snd_cx18_card_free(sc->private_data);
|
||||
sc->private_data = NULL;
|
||||
sc->private_free = NULL;
|
||||
}
|
||||
|
||||
static int snd_cx18_card_create(struct v4l2_device *v4l2_dev,
|
||||
struct snd_card *sc,
|
||||
struct snd_cx18_card **cxsc)
|
||||
{
|
||||
*cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL);
|
||||
if (*cxsc == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
(*cxsc)->v4l2_dev = v4l2_dev;
|
||||
(*cxsc)->sc = sc;
|
||||
|
||||
sc->private_data = *cxsc;
|
||||
sc->private_free = snd_cx18_card_private_free;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
|
||||
struct snd_card *sc = cxsc->sc;
|
||||
|
||||
/* sc->driver is used by alsa-lib's configurator: simple, unique */
|
||||
strlcpy(sc->driver, "CX23418", sizeof(sc->driver));
|
||||
|
||||
/* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */
|
||||
snprintf(sc->shortname, sizeof(sc->shortname), "CX18-%d",
|
||||
cx->instance);
|
||||
|
||||
/* sc->longname is read from /proc/asound/cards */
|
||||
snprintf(sc->longname, sizeof(sc->longname),
|
||||
"CX23418 #%d %s TV/FM Radio/Line-In Capture",
|
||||
cx->instance, cx->card_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_init(struct v4l2_device *v4l2_dev)
|
||||
{
|
||||
struct cx18 *cx = to_cx18(v4l2_dev);
|
||||
struct snd_card *sc = NULL;
|
||||
struct snd_cx18_card *cxsc;
|
||||
int ret;
|
||||
|
||||
/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
|
||||
|
||||
/* (1) Check and increment the device index */
|
||||
/* This is a no-op for us. We'll use the cx->instance */
|
||||
|
||||
/* (2) Create a card instance */
|
||||
ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
|
||||
SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
|
||||
THIS_MODULE, 0, &sc);
|
||||
if (ret) {
|
||||
CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
|
||||
__func__, ret);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
/* (3) Create a main component */
|
||||
ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc);
|
||||
if (ret) {
|
||||
CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n",
|
||||
__func__, ret);
|
||||
goto err_exit_free;
|
||||
}
|
||||
|
||||
/* (4) Set the driver ID and name strings */
|
||||
snd_cx18_card_set_names(cxsc);
|
||||
|
||||
|
||||
ret = snd_cx18_pcm_create(cxsc);
|
||||
if (ret) {
|
||||
CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
|
||||
__func__, ret);
|
||||
goto err_exit_free;
|
||||
}
|
||||
/* FIXME - proc files */
|
||||
|
||||
/* (7) Set the driver data and return 0 */
|
||||
/* We do this out of normal order for PCI drivers to avoid races */
|
||||
cx->alsa = cxsc;
|
||||
|
||||
/* (6) Register the card instance */
|
||||
ret = snd_card_register(sc);
|
||||
if (ret) {
|
||||
cx->alsa = NULL;
|
||||
CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
|
||||
__func__, ret);
|
||||
goto err_exit_free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit_free:
|
||||
if (sc != NULL)
|
||||
snd_card_free(sc);
|
||||
err_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cx18_alsa_load(struct cx18 *cx)
|
||||
{
|
||||
struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
|
||||
struct cx18_stream *s;
|
||||
|
||||
if (v4l2_dev == NULL) {
|
||||
printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cx = to_cx18(v4l2_dev);
|
||||
if (cx == NULL) {
|
||||
printk(KERN_ERR "cx18-alsa cx is NULL\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
|
||||
if (s->video_dev == NULL) {
|
||||
CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
|
||||
"skipping\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cx->alsa != NULL) {
|
||||
CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snd_cx18_init(v4l2_dev)) {
|
||||
CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n",
|
||||
__func__);
|
||||
} else {
|
||||
CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance "
|
||||
"\n", __func__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init cx18_alsa_init(void)
|
||||
{
|
||||
printk(KERN_INFO "cx18-alsa: module loading...\n");
|
||||
cx18_ext_init = &cx18_alsa_load;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
|
||||
|
||||
/* FIXME - pointer checks & shutdown cxsc */
|
||||
|
||||
snd_card_free(cxsc->sc);
|
||||
cx->alsa = NULL;
|
||||
}
|
||||
|
||||
static int __exit cx18_alsa_exit_callback(struct device *dev, void *data)
|
||||
{
|
||||
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
|
||||
struct snd_cx18_card *cxsc;
|
||||
|
||||
if (v4l2_dev == NULL) {
|
||||
printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cxsc = to_snd_cx18_card(v4l2_dev);
|
||||
if (cxsc == NULL) {
|
||||
CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
snd_cx18_exit(cxsc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit cx18_alsa_exit(void)
|
||||
{
|
||||
struct device_driver *drv;
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "cx18-alsa: module unloading...\n");
|
||||
|
||||
drv = driver_find("cx18", &pci_bus_type);
|
||||
ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
|
||||
put_driver(drv);
|
||||
|
||||
cx18_ext_init = NULL;
|
||||
printk(KERN_INFO "cx18-alsa: module unload complete\n");
|
||||
}
|
||||
|
||||
module_init(cx18_alsa_init);
|
||||
module_exit(cx18_alsa_exit);
|
||||
175
drivers/media/video/cx18/cx18-alsa-mixer.c
Normal file
175
drivers/media/video/cx18/cx18-alsa-mixer.c
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* ALSA mixer controls for the
|
||||
* ALSA interface to cx18 PCM capture streams
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "cx18-alsa.h"
|
||||
#include "cx18-driver.h"
|
||||
|
||||
/*
|
||||
* Note the cx18-av-core volume scale is funny, due to the alignment of the
|
||||
* scale with another chip's range:
|
||||
*
|
||||
* v4l2_control value /512 indicated dB actual dB reg 0x8d4
|
||||
* 0x0000 - 0x01ff 0 -119 -96 228
|
||||
* 0x0200 - 0x02ff 1 -118 -96 228
|
||||
* ...
|
||||
* 0x2c00 - 0x2dff 22 -97 -96 228
|
||||
* 0x2e00 - 0x2fff 23 -96 -96 228
|
||||
* 0x3000 - 0x31ff 24 -95 -95 226
|
||||
* ...
|
||||
* 0xee00 - 0xefff 119 0 0 36
|
||||
* ...
|
||||
* 0xfe00 - 0xffff 127 +8 +8 20
|
||||
*/
|
||||
static inline int dB_to_cx18_av_vol(int dB)
|
||||
{
|
||||
if (dB < -96)
|
||||
dB = -96;
|
||||
else if (dB > 8)
|
||||
dB = 8;
|
||||
return (dB + 119) << 9;
|
||||
}
|
||||
|
||||
static inline int cx18_av_vol_to_dB(int v)
|
||||
{
|
||||
if (v < (23 << 9))
|
||||
v = (23 << 9);
|
||||
else if (v > (127 << 9))
|
||||
v = (127 << 9);
|
||||
return (v >> 9) - 119;
|
||||
}
|
||||
|
||||
static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->count = 1;
|
||||
/* We're already translating values, just keep this control in dB */
|
||||
uinfo->value.integer.min = -96;
|
||||
uinfo->value.integer.max = 8;
|
||||
uinfo->value.integer.step = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *uctl)
|
||||
{
|
||||
struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
|
||||
struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
|
||||
struct v4l2_control vctrl;
|
||||
int ret;
|
||||
|
||||
vctrl.id = V4L2_CID_AUDIO_VOLUME;
|
||||
vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
|
||||
|
||||
snd_cx18_lock(cxsc);
|
||||
ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
|
||||
snd_cx18_unlock(cxsc);
|
||||
|
||||
if (!ret)
|
||||
uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl,
|
||||
struct snd_ctl_elem_value *uctl)
|
||||
{
|
||||
struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
|
||||
struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
|
||||
struct v4l2_control vctrl;
|
||||
int ret;
|
||||
|
||||
vctrl.id = V4L2_CID_AUDIO_VOLUME;
|
||||
vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
|
||||
|
||||
snd_cx18_lock(cxsc);
|
||||
|
||||
/* Fetch current state */
|
||||
ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
|
||||
|
||||
if (ret ||
|
||||
(cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
|
||||
|
||||
/* Set, if needed */
|
||||
vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
|
||||
ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl);
|
||||
if (!ret)
|
||||
ret = 1; /* Indicate control was changed w/o error */
|
||||
}
|
||||
snd_cx18_unlock(cxsc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* This is a bit of overkill, the slider is already in dB internally */
|
||||
static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0);
|
||||
|
||||
static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
|
||||
.name = "Analog TV Capture Volume",
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
|
||||
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
|
||||
.info = snd_cx18_mixer_tv_volume_info,
|
||||
.get = snd_cx18_mixer_tv_volume_get,
|
||||
.put = snd_cx18_mixer_tv_volume_put,
|
||||
.tlv.p = snd_cx18_mixer_tv_vol_db_scale
|
||||
};
|
||||
|
||||
/* FIXME - add mute switch and balance, bass, treble sliders:
|
||||
V4L2_CID_AUDIO_MUTE
|
||||
|
||||
V4L2_CID_AUDIO_BALANCE
|
||||
|
||||
V4L2_CID_AUDIO_BASS
|
||||
V4L2_CID_AUDIO_TREBLE
|
||||
*/
|
||||
|
||||
/* FIXME - add stereo, lang1, lang2, mono menu */
|
||||
/* FIXME - add CS5345 I2S volume for HVR-1600 */
|
||||
|
||||
int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
|
||||
struct snd_card *sc = cxsc->sc;
|
||||
int ret;
|
||||
|
||||
strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername));
|
||||
|
||||
ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc));
|
||||
if (ret) {
|
||||
CX18_ALSA_WARN("%s: failed to add %s control, err %d\n",
|
||||
__func__, snd_cx18_mixer_tv_vol.name, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
23
drivers/media/video/cx18/cx18-alsa-mixer.h
Normal file
23
drivers/media/video/cx18/cx18-alsa-mixer.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* ALSA mixer controls for the
|
||||
* ALSA interface to cx18 PCM capture streams
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc);
|
||||
354
drivers/media/video/cx18/cx18-alsa-pcm.c
Normal file
354
drivers/media/video/cx18/cx18-alsa-pcm.c
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* ALSA PCM device for the
|
||||
* ALSA interface to cx18 PCM capture streams
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.net>
|
||||
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
|
||||
*
|
||||
* Portions of this work were sponsored by ONELAN Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#include "cx18-driver.h"
|
||||
#include "cx18-queue.h"
|
||||
#include "cx18-streams.h"
|
||||
#include "cx18-fileops.h"
|
||||
#include "cx18-alsa.h"
|
||||
|
||||
static unsigned int pcm_debug;
|
||||
module_param(pcm_debug, int, 0644);
|
||||
MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
|
||||
|
||||
#define dprintk(fmt, arg...) do { \
|
||||
if (pcm_debug) \
|
||||
printk(KERN_INFO "cx18-alsa-pcm %s: " fmt, \
|
||||
__func__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
static struct snd_pcm_hardware snd_cx18_hw_capture = {
|
||||
.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
|
||||
SNDRV_PCM_INFO_MMAP |
|
||||
SNDRV_PCM_INFO_INTERLEAVED |
|
||||
SNDRV_PCM_INFO_MMAP_VALID,
|
||||
|
||||
.formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
|
||||
.rates = SNDRV_PCM_RATE_48000,
|
||||
|
||||
.rate_min = 48000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 2,
|
||||
.buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */
|
||||
.period_bytes_min = 64, /* 12544/2, */
|
||||
.period_bytes_max = 12544,
|
||||
.periods_min = 2,
|
||||
.periods_max = 98, /* 12544, */
|
||||
};
|
||||
|
||||
void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data,
|
||||
size_t num_bytes)
|
||||
{
|
||||
struct snd_pcm_substream *substream;
|
||||
struct snd_pcm_runtime *runtime;
|
||||
unsigned int oldptr;
|
||||
unsigned int stride;
|
||||
int period_elapsed = 0;
|
||||
int length;
|
||||
|
||||
dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc,
|
||||
pcm_data, num_bytes);
|
||||
|
||||
substream = cxsc->capture_pcm_substream;
|
||||
if (substream == NULL) {
|
||||
dprintk("substream was NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
runtime = substream->runtime;
|
||||
if (runtime == NULL) {
|
||||
dprintk("runtime was NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
stride = runtime->frame_bits >> 3;
|
||||
if (stride == 0) {
|
||||
dprintk("stride is zero\n");
|
||||
return;
|
||||
}
|
||||
|
||||
length = num_bytes / stride;
|
||||
if (length == 0) {
|
||||
dprintk("%s: length was zero\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (runtime->dma_area == NULL) {
|
||||
dprintk("dma area was NULL - ignoring\n");
|
||||
return;
|
||||
}
|
||||
|
||||
oldptr = cxsc->hwptr_done_capture;
|
||||
if (oldptr + length >= runtime->buffer_size) {
|
||||
unsigned int cnt =
|
||||
runtime->buffer_size - oldptr;
|
||||
memcpy(runtime->dma_area + oldptr * stride, pcm_data,
|
||||
cnt * stride);
|
||||
memcpy(runtime->dma_area, pcm_data + cnt * stride,
|
||||
length * stride - cnt * stride);
|
||||
} else {
|
||||
memcpy(runtime->dma_area + oldptr * stride, pcm_data,
|
||||
length * stride);
|
||||
}
|
||||
snd_pcm_stream_lock(substream);
|
||||
|
||||
cxsc->hwptr_done_capture += length;
|
||||
if (cxsc->hwptr_done_capture >=
|
||||
runtime->buffer_size)
|
||||
cxsc->hwptr_done_capture -=
|
||||
runtime->buffer_size;
|
||||
|
||||
cxsc->capture_transfer_done += length;
|
||||
if (cxsc->capture_transfer_done >=
|
||||
runtime->period_size) {
|
||||
cxsc->capture_transfer_done -=
|
||||
runtime->period_size;
|
||||
period_elapsed = 1;
|
||||
}
|
||||
|
||||
snd_pcm_stream_unlock(substream);
|
||||
|
||||
if (period_elapsed)
|
||||
snd_pcm_period_elapsed(substream);
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
|
||||
struct cx18 *cx = to_cx18(v4l2_dev);
|
||||
struct cx18_stream *s;
|
||||
struct cx18_open_id item;
|
||||
int ret;
|
||||
|
||||
/* Instruct the cx18 to start sending packets */
|
||||
snd_cx18_lock(cxsc);
|
||||
s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
|
||||
|
||||
item.cx = cx;
|
||||
item.type = s->type;
|
||||
item.open_id = cx->open_id++;
|
||||
|
||||
/* See if the stream is available */
|
||||
if (cx18_claim_stream(&item, item.type)) {
|
||||
/* No, it's already in use */
|
||||
snd_cx18_unlock(cxsc);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
|
||||
test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
|
||||
/* We're already streaming. No additional action required */
|
||||
snd_cx18_unlock(cxsc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
runtime->hw = snd_cx18_hw_capture;
|
||||
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
cxsc->capture_pcm_substream = substream;
|
||||
runtime->private_data = cx;
|
||||
|
||||
cx->pcm_announce_callback = cx18_alsa_announce_pcm_data;
|
||||
|
||||
/* Not currently streaming, so start it up */
|
||||
set_bit(CX18_F_S_STREAMING, &s->s_flags);
|
||||
ret = cx18_start_v4l2_encode_stream(s);
|
||||
snd_cx18_unlock(cxsc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
|
||||
struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
|
||||
struct cx18 *cx = to_cx18(v4l2_dev);
|
||||
struct cx18_stream *s;
|
||||
int ret;
|
||||
|
||||
/* Instruct the cx18 to stop sending packets */
|
||||
snd_cx18_lock(cxsc);
|
||||
s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
|
||||
ret = cx18_stop_v4l2_encode_stream(s, 0);
|
||||
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
|
||||
|
||||
cx18_release_stream(s);
|
||||
|
||||
cx->pcm_announce_callback = NULL;
|
||||
snd_cx18_unlock(cxsc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
|
||||
unsigned int cmd, void *arg)
|
||||
{
|
||||
return snd_pcm_lib_ioctl(substream, cmd, arg);
|
||||
}
|
||||
|
||||
|
||||
static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
|
||||
size_t size)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = subs->runtime;
|
||||
|
||||
dprintk("Allocating vbuffer\n");
|
||||
if (runtime->dma_area) {
|
||||
if (runtime->dma_bytes > size)
|
||||
return 0;
|
||||
|
||||
vfree(runtime->dma_area);
|
||||
}
|
||||
runtime->dma_area = vmalloc(size);
|
||||
if (!runtime->dma_area)
|
||||
return -ENOMEM;
|
||||
|
||||
runtime->dma_bytes = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dprintk("%s called\n", __func__);
|
||||
|
||||
ret = snd_pcm_alloc_vmalloc_buffer(substream,
|
||||
params_buffer_bytes(params));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cxsc->slock, flags);
|
||||
if (substream->runtime->dma_area) {
|
||||
dprintk("freeing pcm capture region\n");
|
||||
vfree(substream->runtime->dma_area);
|
||||
substream->runtime->dma_area = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&cxsc->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
|
||||
|
||||
cxsc->hwptr_done_capture = 0;
|
||||
cxsc->capture_transfer_done = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
unsigned long flags;
|
||||
snd_pcm_uframes_t hwptr_done;
|
||||
struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
|
||||
|
||||
spin_lock_irqsave(&cxsc->slock, flags);
|
||||
hwptr_done = cxsc->hwptr_done_capture;
|
||||
spin_unlock_irqrestore(&cxsc->slock, flags);
|
||||
|
||||
return hwptr_done;
|
||||
}
|
||||
|
||||
static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
|
||||
unsigned long offset)
|
||||
{
|
||||
void *pageptr = subs->runtime->dma_area + offset;
|
||||
|
||||
return vmalloc_to_page(pageptr);
|
||||
}
|
||||
|
||||
static struct snd_pcm_ops snd_cx18_pcm_capture_ops = {
|
||||
.open = snd_cx18_pcm_capture_open,
|
||||
.close = snd_cx18_pcm_capture_close,
|
||||
.ioctl = snd_cx18_pcm_ioctl,
|
||||
.hw_params = snd_cx18_pcm_hw_params,
|
||||
.hw_free = snd_cx18_pcm_hw_free,
|
||||
.prepare = snd_cx18_pcm_prepare,
|
||||
.trigger = snd_cx18_pcm_trigger,
|
||||
.pointer = snd_cx18_pcm_pointer,
|
||||
.page = snd_pcm_get_vmalloc_page,
|
||||
};
|
||||
|
||||
int snd_cx18_pcm_create(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
struct snd_pcm *sp;
|
||||
struct snd_card *sc = cxsc->sc;
|
||||
struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
|
||||
struct cx18 *cx = to_cx18(v4l2_dev);
|
||||
int ret;
|
||||
|
||||
ret = snd_pcm_new(sc, "CX23418 PCM",
|
||||
0, /* PCM device 0, the only one for this card */
|
||||
0, /* 0 playback substreams */
|
||||
1, /* 1 capture substream */
|
||||
&sp);
|
||||
if (ret) {
|
||||
CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
|
||||
__func__, ret);
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
spin_lock_init(&cxsc->slock);
|
||||
|
||||
snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
|
||||
&snd_cx18_pcm_capture_ops);
|
||||
sp->info_flags = 0;
|
||||
sp->private_data = cxsc;
|
||||
strlcpy(sp->name, cx->card_name, sizeof(sp->name));
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
return ret;
|
||||
}
|
||||
27
drivers/media/video/cx18/cx18-alsa-pcm.h
Normal file
27
drivers/media/video/cx18/cx18-alsa-pcm.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* ALSA PCM device for the
|
||||
* ALSA interface to cx18 PCM capture streams
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc);
|
||||
|
||||
/* Used by cx18-mailbox to announce the PCM data to the module */
|
||||
void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data,
|
||||
size_t num_bytes);
|
||||
75
drivers/media/video/cx18/cx18-alsa.h
Normal file
75
drivers/media/video/cx18/cx18-alsa.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* ALSA interface to cx18 PCM capture streams
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
|
||||
struct snd_card;
|
||||
|
||||
struct snd_cx18_card {
|
||||
struct v4l2_device *v4l2_dev;
|
||||
struct snd_card *sc;
|
||||
unsigned int capture_transfer_done;
|
||||
unsigned int hwptr_done_capture;
|
||||
struct snd_pcm_substream *capture_pcm_substream;
|
||||
spinlock_t slock;
|
||||
};
|
||||
|
||||
extern int cx18_alsa_debug;
|
||||
|
||||
/*
|
||||
* File operations that manipulate the encoder or video or audio subdevices
|
||||
* need to be serialized. Use the same lock we use for v4l2 file ops.
|
||||
*/
|
||||
static inline void snd_cx18_lock(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
|
||||
mutex_lock(&cx->serialize_lock);
|
||||
}
|
||||
|
||||
static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
|
||||
{
|
||||
struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
|
||||
mutex_unlock(&cx->serialize_lock);
|
||||
}
|
||||
|
||||
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
|
||||
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
|
||||
#define CX18_ALSA_DBGFLG_INFO (1 << 1)
|
||||
|
||||
#define CX18_ALSA_DEBUG(x, type, fmt, args...) \
|
||||
do { \
|
||||
if ((x) & cx18_alsa_debug) \
|
||||
printk(KERN_INFO "%s-alsa: " type ": " fmt, \
|
||||
v4l2_dev->name , ## args); \
|
||||
} while (0)
|
||||
|
||||
#define CX18_ALSA_DEBUG_WARN(fmt, args...) \
|
||||
CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_WARN, "warning", fmt , ## args)
|
||||
|
||||
#define CX18_ALSA_DEBUG_INFO(fmt, args...) \
|
||||
CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_INFO, "info", fmt , ## args)
|
||||
|
||||
#define CX18_ALSA_ERR(fmt, args...) \
|
||||
printk(KERN_ERR "%s-alsa: " fmt, v4l2_dev->name , ## args)
|
||||
|
||||
#define CX18_ALSA_WARN(fmt, args...) \
|
||||
printk(KERN_WARNING "%s-alsa: " fmt, v4l2_dev->name , ## args)
|
||||
|
||||
#define CX18_ALSA_INFO(fmt, args...) \
|
||||
printk(KERN_INFO "%s-alsa: " fmt, v4l2_dev->name , ## args)
|
||||
|
|
@ -393,7 +393,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = {
|
|||
.gpio_init.direction = 0x7,
|
||||
.gpio_audio_input = { .mask = 0x7,
|
||||
.tuner = 0x6, .linein = 0x2, .radio = 0x2 },
|
||||
.xceive_pin = 15,
|
||||
.xceive_pin = 1,
|
||||
.pci_list = cx18_pci_leadtek_pvr2100,
|
||||
.i2c = &cx18_i2c_std,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@
|
|||
setting this to 1 you ensure that radio0 is now also radio1. */
|
||||
int cx18_first_minor;
|
||||
|
||||
/* Callback for registering extensions */
|
||||
int (*cx18_ext_init)(struct cx18 *);
|
||||
EXPORT_SYMBOL(cx18_ext_init);
|
||||
|
||||
/* add your revision and whatnot here */
|
||||
static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
|
||||
{PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
|
||||
|
|
@ -91,7 +95,7 @@ static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE;
|
|||
|
||||
static int enc_ts_bufs = -1;
|
||||
static int enc_mpg_bufs = -1;
|
||||
static int enc_idx_bufs = -1;
|
||||
static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM;
|
||||
static int enc_yuv_bufs = -1;
|
||||
static int enc_vbi_bufs = -1;
|
||||
static int enc_pcm_bufs = -1;
|
||||
|
|
@ -196,14 +200,17 @@ MODULE_PARM_DESC(enc_mpg_bufs,
|
|||
"Number of encoder MPG buffers\n"
|
||||
"\t\t\tDefault is computed from other enc_mpg_* parameters");
|
||||
MODULE_PARM_DESC(enc_idx_buffers,
|
||||
"Encoder IDX buffer memory (MB). (enc_idx_bufs can override)\n"
|
||||
"\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFFERS));
|
||||
"(Deprecated) Encoder IDX buffer memory (MB)\n"
|
||||
"\t\t\tIgnored, except 0 disables IDX buffer allocations\n"
|
||||
"\t\t\tDefault: 1 [Enabled]");
|
||||
MODULE_PARM_DESC(enc_idx_bufsize,
|
||||
"Size of an encoder IDX buffer (kB)\n"
|
||||
"\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_IDX_BUFSIZE));
|
||||
"\t\t\tAllowed values are multiples of 1.5 kB rounded up\n"
|
||||
"\t\t\t(multiples of size required for 64 index entries)\n"
|
||||
"\t\t\tDefault: 2");
|
||||
MODULE_PARM_DESC(enc_idx_bufs,
|
||||
"Number of encoder IDX buffers\n"
|
||||
"\t\t\tDefault is computed from other enc_idx_* parameters");
|
||||
"\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM));
|
||||
MODULE_PARM_DESC(enc_yuv_buffers,
|
||||
"Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n"
|
||||
"\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
|
||||
|
|
@ -231,7 +238,8 @@ MODULE_PARM_DESC(enc_pcm_bufs,
|
|||
"Number of encoder PCM buffers\n"
|
||||
"\t\t\tDefault is computed from other enc_pcm_* parameters");
|
||||
|
||||
MODULE_PARM_DESC(cx18_first_minor, "Set device node number assigned to first card");
|
||||
MODULE_PARM_DESC(cx18_first_minor,
|
||||
"Set device node number assigned to first card");
|
||||
|
||||
MODULE_AUTHOR("Hans Verkuil");
|
||||
MODULE_DESCRIPTION("CX23418 driver");
|
||||
|
|
@ -240,6 +248,28 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
MODULE_VERSION(CX18_VERSION);
|
||||
|
||||
#if defined(CONFIG_MODULES) && defined(MODULE)
|
||||
static void request_module_async(struct work_struct *work)
|
||||
{
|
||||
struct cx18 *dev = container_of(work, struct cx18, request_module_wk);
|
||||
|
||||
/* Make sure cx18-alsa module is loaded */
|
||||
request_module("cx18-alsa");
|
||||
|
||||
/* Initialize cx18-alsa for this instance of the cx18 device */
|
||||
if (cx18_ext_init != NULL)
|
||||
cx18_ext_init(dev);
|
||||
}
|
||||
|
||||
static void request_modules(struct cx18 *dev)
|
||||
{
|
||||
INIT_WORK(&dev->request_module_wk, request_module_async);
|
||||
schedule_work(&dev->request_module_wk);
|
||||
}
|
||||
#else
|
||||
#define request_modules(dev)
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
/* Generic utility functions */
|
||||
int cx18_msleep_timeout(unsigned int msecs, int intr)
|
||||
{
|
||||
|
|
@ -501,7 +531,12 @@ static void cx18_process_options(struct cx18 *cx)
|
|||
/*
|
||||
* YUV is a special case where the stream_buf_size needs to be
|
||||
* an integral multiple of 33.75 kB (storage for 32 screens
|
||||
* lines to maintain alignment in case of lost buffers
|
||||
* lines to maintain alignment in case of lost buffers).
|
||||
*
|
||||
* IDX is a special case where the stream_buf_size should be
|
||||
* an integral multiple of 1.5 kB (storage for 64 index entries
|
||||
* to maintain alignment in case of lost buffers).
|
||||
*
|
||||
*/
|
||||
if (i == CX18_ENC_STREAM_TYPE_YUV) {
|
||||
cx->stream_buf_size[i] *= 1024;
|
||||
|
|
@ -511,15 +546,24 @@ static void cx18_process_options(struct cx18 *cx)
|
|||
if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE)
|
||||
cx->stream_buf_size[i] =
|
||||
CX18_UNIT_ENC_YUV_BUFSIZE;
|
||||
} else if (i == CX18_ENC_STREAM_TYPE_IDX) {
|
||||
cx->stream_buf_size[i] *= 1024;
|
||||
cx->stream_buf_size[i] -=
|
||||
(cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE);
|
||||
|
||||
if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE)
|
||||
cx->stream_buf_size[i] =
|
||||
CX18_UNIT_ENC_IDX_BUFSIZE;
|
||||
}
|
||||
/*
|
||||
* YUV is a special case where the stream_buf_size is
|
||||
* YUV and IDX are special cases where the stream_buf_size is
|
||||
* now in bytes.
|
||||
* VBI is a special case where the stream_buf_size is fixed
|
||||
* and already in bytes
|
||||
*/
|
||||
if (i == CX18_ENC_STREAM_TYPE_VBI ||
|
||||
i == CX18_ENC_STREAM_TYPE_YUV) {
|
||||
i == CX18_ENC_STREAM_TYPE_YUV ||
|
||||
i == CX18_ENC_STREAM_TYPE_IDX) {
|
||||
if (cx->stream_buffers[i] < 0) {
|
||||
cx->stream_buffers[i] =
|
||||
cx->options.megabytes[i] * 1024 * 1024
|
||||
|
|
@ -1032,6 +1076,10 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
|
|||
}
|
||||
|
||||
CX18_INFO("Initialized card: %s\n", cx->card_name);
|
||||
|
||||
/* Load cx18 submodules (cx18-alsa) */
|
||||
request_modules(cx);
|
||||
|
||||
return 0;
|
||||
|
||||
free_streams:
|
||||
|
|
@ -1220,6 +1268,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
|
|||
kfree(cx);
|
||||
}
|
||||
|
||||
|
||||
/* define a pci_driver for card detection */
|
||||
static struct pci_driver cx18_pci_driver = {
|
||||
.name = "cx18",
|
||||
|
|
@ -1230,7 +1279,8 @@ static struct pci_driver cx18_pci_driver = {
|
|||
|
||||
static int __init module_start(void)
|
||||
{
|
||||
printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION);
|
||||
printk(KERN_INFO "cx18: Start initialization, version %s\n",
|
||||
CX18_VERSION);
|
||||
|
||||
/* Validate parameters */
|
||||
if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
|
||||
|
|
|
|||
|
|
@ -126,10 +126,22 @@
|
|||
#define CX18_625_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32)
|
||||
#define CX18_525_LINE_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32)
|
||||
|
||||
/* IDX buffer size should be a multiple of the index entry size from the chip */
|
||||
struct cx18_enc_idx_entry {
|
||||
__le32 length;
|
||||
__le32 offset_low;
|
||||
__le32 offset_high;
|
||||
__le32 flags;
|
||||
__le32 pts_low;
|
||||
__le32 pts_high;
|
||||
} __attribute__ ((packed));
|
||||
#define CX18_UNIT_ENC_IDX_BUFSIZE \
|
||||
(sizeof(struct cx18_enc_idx_entry) * V4L2_ENC_IDX_ENTRIES)
|
||||
|
||||
/* DMA buffer, default size in kB allocated */
|
||||
#define CX18_DEFAULT_ENC_TS_BUFSIZE 32
|
||||
#define CX18_DEFAULT_ENC_MPG_BUFSIZE 32
|
||||
#define CX18_DEFAULT_ENC_IDX_BUFSIZE 32
|
||||
#define CX18_DEFAULT_ENC_IDX_BUFSIZE (CX18_UNIT_ENC_IDX_BUFSIZE * 1 / 1024 + 1)
|
||||
#define CX18_DEFAULT_ENC_YUV_BUFSIZE (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1)
|
||||
#define CX18_DEFAULT_ENC_PCM_BUFSIZE 4
|
||||
|
||||
|
|
@ -234,16 +246,8 @@
|
|||
#define CX18_WARN_DEV(dev, fmt, args...) v4l2_warn(dev, fmt , ## args)
|
||||
#define CX18_INFO_DEV(dev, fmt, args...) v4l2_info(dev, fmt , ## args)
|
||||
|
||||
/* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
|
||||
#define MPEG_FRAME_TYPE_IFRAME 1
|
||||
#define MPEG_FRAME_TYPE_IFRAME_PFRAME 3
|
||||
#define MPEG_FRAME_TYPE_ALL 7
|
||||
|
||||
#define CX18_MAX_PGM_INDEX (400)
|
||||
|
||||
extern int cx18_debug;
|
||||
|
||||
|
||||
struct cx18_options {
|
||||
int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
|
||||
int cardtype; /* force card type on load */
|
||||
|
|
@ -276,6 +280,18 @@ struct cx18_options {
|
|||
#define CX18_SLICED_TYPE_WSS_625 (5)
|
||||
#define CX18_SLICED_TYPE_VPS (7)
|
||||
|
||||
/**
|
||||
* list_entry_is_past_end - check if a previous loop cursor is off list end
|
||||
* @pos: the type * previously used as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Check if the entry's list_head is the head of the list, thus it's not a
|
||||
* real entry but was the loop cursor that walked past the end
|
||||
*/
|
||||
#define list_entry_is_past_end(pos, head, member) \
|
||||
(&pos->member == (head))
|
||||
|
||||
struct cx18_buffer {
|
||||
struct list_head list;
|
||||
dma_addr_t dma_handle;
|
||||
|
|
@ -558,6 +574,10 @@ struct cx18 {
|
|||
int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */
|
||||
int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
|
||||
struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */
|
||||
struct snd_cx18_card *alsa; /* ALSA interface for PCM capture stream */
|
||||
void (*pcm_announce_callback)(struct snd_cx18_card *card, u8 *pcm_data,
|
||||
size_t num_bytes);
|
||||
|
||||
unsigned long i_flags; /* global cx18 flags */
|
||||
atomic_t ana_capturing; /* count number of active analog capture streams */
|
||||
atomic_t tot_capturing; /* total count number of active capture streams */
|
||||
|
|
@ -575,12 +595,6 @@ struct cx18 {
|
|||
|
||||
struct vbi_info vbi;
|
||||
|
||||
u32 pgm_info_offset;
|
||||
u32 pgm_info_num;
|
||||
u32 pgm_info_write_idx;
|
||||
u32 pgm_info_read_idx;
|
||||
struct v4l2_enc_idx_entry pgm_info[CX18_MAX_PGM_INDEX];
|
||||
|
||||
u64 mpg_data_received;
|
||||
u64 vbi_data_inserted;
|
||||
|
||||
|
|
@ -623,6 +637,9 @@ struct cx18 {
|
|||
u32 active_input;
|
||||
v4l2_std_id std;
|
||||
v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
|
||||
|
||||
/* Used for cx18-alsa module loading */
|
||||
struct work_struct request_module_wk;
|
||||
};
|
||||
|
||||
static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
|
||||
|
|
@ -630,6 +647,9 @@ static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
|
|||
return container_of(v4l2_dev, struct cx18, v4l2_dev);
|
||||
}
|
||||
|
||||
/* cx18 extensions to be loaded */
|
||||
extern int (*cx18_ext_init)(struct cx18 *);
|
||||
|
||||
/* Globals */
|
||||
extern int cx18_first_minor;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue