diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-04-08 10:35:30 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-08 10:35:30 +0200 |
commit | 5ea472a77f8e4811ceee3f44a9deda6ad6e8b789 (patch) | |
tree | a9ec5019e2b666a19874fc344ffb0dd5da6bce94 /drivers/media/dvb | |
parent | 6c009ecef8cca28c7c09eb16d0802e37915a76e1 (diff) | |
parent | 577c9c456f0e1371cbade38eaf91ae8e8a308555 (diff) |
Merge commit 'v2.6.30-rc1' into perfcounters/core
Conflicts:
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
include/linux/init_task.h
Merge reason: the conflicts are non-trivial: PowerPC placement
of sys_perf_counter_open has to be mixed with the
new preadv/pwrite syscalls.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/dm1105/dm1105.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/Kconfig | 4 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9015.c | 63 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9015.h | 75 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/ce6230.c | 8 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 4 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-avc.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/au8522_decoder.c | 12 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.c | 816 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.h | 90 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx_priv.h | 70 | ||||
-rw-r--r-- | drivers/media/dvb/pluto2/pluto2.c | 2 |
14 files changed, 1121 insertions, 35 deletions
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 5b20cf5a29f..971a8b18f6d 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -662,7 +662,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, if (ret < 0) goto err_kfree; - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret < 0) goto err_pci_disable_device; diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 6103caad164..60955a70d88 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -294,7 +294,7 @@ config DVB_USB_DTV5100 config DVB_USB_AF9015 tristate "Afatech AF9015 DVB-T USB2.0 support" - depends on DVB_USB && EXPERIMENTAL + depends on DVB_USB select DVB_AF9013 select DVB_PLL if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE @@ -309,6 +309,6 @@ config DVB_USB_CE6230 tristate "Intel CE6230 DVB-T USB2.0 support" depends on DVB_USB && EXPERIMENTAL select DVB_ZL10353 - select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index f0ba8b07b84..53bfc8e42fb 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -782,17 +782,14 @@ static int af9015_read_config(struct usb_device *udev) ARRAY_SIZE(af9015_ir_table_leadtek); break; case USB_VID_VISIONPLUS: - if (udev->descriptor.idProduct == - cpu_to_le16(USB_PID_AZUREWAVE_AD_TU700)) { - 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); - } + 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 */ @@ -833,6 +830,16 @@ static int af9015_read_config(struct usb_device *udev) 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: @@ -981,6 +988,21 @@ error: if (ret) err("eeprom read failed:%d", ret); + /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM + content :-( Override some wrong values here. */ + if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA && + le16_to_cpu(udev->descriptor.idProduct) == USB_PID_AVERMEDIA_A850) { + deb_info("%s: AverMedia A850: overriding config\n", __func__); + /* disable dual mode */ + af9015_config.dual_mode = 0; + /* disable 2nd adapter */ + for (i = 0; i < af9015_properties_count; i++) + af9015_properties[i].num_adapters = 1; + + /* set correct IF */ + af9015_af9013_config[0].tuner_if = 4570; + } + return ret; } @@ -1237,6 +1259,9 @@ static struct usb_device_id af9015_usb_table[] = { /* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)}, + {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)}, + {USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)}, + {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)}, {0}, }; MODULE_DEVICE_TABLE(usb, af9015_usb_table); @@ -1401,7 +1426,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .i2c_algo = &af9015_i2c_algo, - .num_device_descs = 7, + .num_device_descs = 9, .devices = { { .name = "Xtensions XD-380", @@ -1437,7 +1462,19 @@ static struct dvb_usb_device_properties af9015_properties[] = { .name = "KWorld USB DVB-T TV Stick II " \ "(VS-DVB-T 395U)", .cold_ids = {&af9015_usb_table[16], - &af9015_usb_table[17], NULL}, + &af9015_usb_table[17], + &af9015_usb_table[18], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "TrekStor DVB-T USB Stick", + .cold_ids = {&af9015_usb_table[19], NULL}, + .warm_ids = {NULL}, + }, + { + .name = "AverMedia AVerTV Volar Black HD " \ + "(A850)", + .cold_ids = {&af9015_usb_table[20], NULL}, .warm_ids = {NULL}, }, } diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 00e25714662..8d81a17c116 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -64,14 +64,6 @@ #define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1) -#define AF9015_GPIO_ON (1 << 0) -#define AF9015_GPIO_EN (1 << 1) -#define AF9015_GPIO_O (1 << 2) -#define AF9015_GPIO_I (1 << 3) - -#define AF9015_GPIO_TUNER_ON (AF9015_GPIO_ON|AF9015_GPIO_EN) -#define AF9015_GPIO_TUNER_OFF (AF9015_GPIO_ON|AF9015_GPIO_EN|AF9015_GPIO_O) - struct req_t { u8 cmd; /* [0] */ /* seq */ /* [1] */ @@ -120,11 +112,11 @@ struct af9015_config { enum af9015_remote { AF9015_REMOTE_NONE = 0, - AF9015_REMOTE_A_LINK_DTU_M, +/* 1 */ AF9015_REMOTE_A_LINK_DTU_M, AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, AF9015_REMOTE_MYGICTV_U718, AF9015_REMOTE_DIGITTRADE_DVB_T, - AF9015_REMOTE_AVERMEDIA_KS, +/* 5 */ AF9015_REMOTE_AVERMEDIA_KS, }; /* Leadtek WinFast DTV Dongle Gold */ @@ -691,4 +683,67 @@ static u8 af9015_ir_table_digittrade[] = { 0x00, 0xff, 0x1d, 0xe2, 0x40, 0x00, 0x00, }; +/* TREKSTOR DVB-T USB Stick */ +static struct dvb_usb_rc_key af9015_rc_keys_trekstor[] = { + { 0x07, 0x04, KEY_AGAIN }, /* Home */ + { 0x07, 0x05, KEY_MUTE }, /* Mute */ + { 0x07, 0x06, KEY_UP }, /* Up */ + { 0x07, 0x07, KEY_DOWN }, /* Down */ + { 0x07, 0x09, KEY_RIGHT }, /* Right */ + { 0x07, 0x0a, KEY_ENTER }, /* OK */ + { 0x07, 0x0b, KEY_FASTFORWARD }, /* Fast forward */ + { 0x07, 0x0c, KEY_REWIND }, /* Rewind */ + { 0x07, 0x0d, KEY_PLAY }, /* Play/Pause */ + { 0x07, 0x0e, KEY_VOLUMEUP }, /* Volume + */ + { 0x07, 0x0f, KEY_VOLUMEDOWN }, /* Volume - */ + { 0x07, 0x10, KEY_RECORD }, /* Record */ + { 0x07, 0x11, KEY_STOP }, /* Stop */ + { 0x07, 0x12, KEY_ZOOM }, /* TV */ + { 0x07, 0x13, KEY_EPG }, /* Info/EPG */ + { 0x07, 0x14, KEY_CHANNELDOWN }, /* Channel - */ + { 0x07, 0x15, KEY_CHANNELUP }, /* Channel + */ + { 0x07, 0x1e, KEY_1 }, + { 0x07, 0x1f, KEY_2 }, + { 0x07, 0x20, KEY_3 }, + { 0x07, 0x21, KEY_4 }, + { 0x07, 0x22, KEY_5 }, + { 0x07, 0x23, KEY_6 }, + { 0x07, 0x24, KEY_7 }, + { 0x07, 0x25, KEY_8 }, + { 0x07, 0x26, KEY_9 }, + { 0x07, 0x08, KEY_LEFT }, /* LEFT */ + { 0x07, 0x27, KEY_0 }, +}; + +static u8 af9015_ir_table_trekstor[] = { + 0x00, 0xff, 0x86, 0x79, 0x04, 0x07, 0x00, + 0x00, 0xff, 0x85, 0x7a, 0x05, 0x07, 0x00, + 0x00, 0xff, 0x87, 0x78, 0x06, 0x07, 0x00, + 0x00, 0xff, 0x8c, 0x73, 0x07, 0x07, 0x00, + 0x00, 0xff, 0x89, 0x76, 0x09, 0x07, 0x00, + 0x00, 0xff, 0x88, 0x77, 0x0a, 0x07, 0x00, + 0x00, 0xff, 0x8a, 0x75, 0x0b, 0x07, 0x00, + 0x00, 0xff, 0x9e, 0x61, 0x0c, 0x07, 0x00, + 0x00, 0xff, 0x8d, 0x72, 0x0d, 0x07, 0x00, + 0x00, 0xff, 0x8b, 0x74, 0x0e, 0x07, 0x00, + 0x00, 0xff, 0x9b, 0x64, 0x0f, 0x07, 0x00, + 0x00, 0xff, 0x9d, 0x62, 0x10, 0x07, 0x00, + 0x00, 0xff, 0x8e, 0x71, 0x11, 0x07, 0x00, + 0x00, 0xff, 0x9c, 0x63, 0x12, 0x07, 0x00, + 0x00, 0xff, 0x8f, 0x70, 0x13, 0x07, 0x00, + 0x00, 0xff, 0x93, 0x6c, 0x14, 0x07, 0x00, + 0x00, 0xff, 0x97, 0x68, 0x15, 0x07, 0x00, + 0x00, 0xff, 0x92, 0x6d, 0x1e, 0x07, 0x00, + 0x00, 0xff, 0x96, 0x69, 0x1f, 0x07, 0x00, + 0x00, 0xff, 0x9a, 0x65, 0x20, 0x07, 0x00, + 0x00, 0xff, 0x91, 0x6e, 0x21, 0x07, 0x00, + 0x00, 0xff, 0x95, 0x6a, 0x22, 0x07, 0x00, + 0x00, 0xff, 0x99, 0x66, 0x23, 0x07, 0x00, + 0x00, 0xff, 0x90, 0x6f, 0x24, 0x07, 0x00, + 0x00, 0xff, 0x94, 0x6b, 0x25, 0x07, 0x00, + 0x00, 0xff, 0x98, 0x67, 0x26, 0x07, 0x00, + 0x00, 0xff, 0x9f, 0x60, 0x08, 0x07, 0x00, + 0x00, 0xff, 0x84, 0x7b, 0x27, 0x07, 0x00, +}; + #endif diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c index 5862820f109..52badc00e67 100644 --- a/drivers/media/dvb/dvb-usb/ce6230.c +++ b/drivers/media/dvb/dvb-usb/ce6230.c @@ -250,6 +250,7 @@ static int ce6230_probe(struct usb_interface *intf, static struct usb_device_id ce6230_table[] = { { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) }, + { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ce6230_table); @@ -284,13 +285,18 @@ static struct dvb_usb_device_properties ce6230_properties = { .i2c_algo = &ce6230_i2c_algo, - .num_device_descs = 1, + .num_device_descs = 2, .devices = { { .name = "Intel CE9500 reference design", .cold_ids = {NULL}, .warm_ids = {&ce6230_table[0], NULL}, }, + { + .name = "AVerMedia A310 USB 2.0 DVB-T tuner", + .cold_ids = {NULL}, + .warm_ids = {&ce6230_table[1], NULL}, + }, } }; diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index dc7ea21cd13..f506c74119f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -65,6 +65,7 @@ #define USB_PID_AFATECH_AF9005 0x9020 #define USB_PID_AFATECH_AF9015_9015 0x9015 #define USB_PID_AFATECH_AF9015_9016 0x9016 +#define USB_PID_TREKSTOR_DVBT 0x901b #define USB_VID_ALINK_DTU 0xf170 #define USB_PID_ANSONIC_DVBT_USB 0x6000 #define USB_PID_ANYSEE 0x861f @@ -102,6 +103,7 @@ #define USB_PID_KWORLD_399U 0xe399 #define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U_2 0xe39b +#define USB_PID_KWORLD_395U_3 0xe395 #define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df @@ -167,6 +169,8 @@ #define USB_PID_AVERMEDIA_VOLAR_X 0xa815 #define USB_PID_AVERMEDIA_VOLAR_X_2 0x8150 #define USB_PID_AVERMEDIA_A309 0xa309 +#define USB_PID_AVERMEDIA_A310 0xa310 +#define USB_PID_AVERMEDIA_A850 0x850a #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index 12f7730184a..32526f103b5 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -151,7 +151,7 @@ static void debug_fcp(const u8 *data, int length) subunit_type = data[1] >> 3; subunit_id = data[1] & 7; op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; - printk(KERN_INFO "%ssu=%x.%x l=%zu: %-8s - %s\n", + printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", prefix, subunit_type, subunit_id, length, debug_fcp_ctype(data[0]), debug_fcp_opcode(op, data, length)); diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a486a7f81fa..23e4cffeba3 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -513,6 +513,13 @@ config DVB_LGS8GL5 help A DMB-TH tuner module. Say Y when you want to support this frontend. +config DVB_LGS8GXX + tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DMB-TH tuner module. Say Y when you want to support this frontend. + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 65a336aa1db..bc2b00abd10 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o +obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o obj-$(CONFIG_DVB_AF9013) += af9013.o obj-$(CONFIG_DVB_CX24116) += cx24116.o diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index d63e1527dc8..9e9a75576a1 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -652,7 +652,7 @@ static int au8522_reset(struct v4l2_subdev *sd, u32 val) } static int au8522_s_video_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct au8522_state *state = to_state(sd); @@ -663,11 +663,11 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, closed), and then came back to analog mode */ au8522_writereg(state, 0x106, 1); - if (route->input == AU8522_COMPOSITE_CH1) { + if (input == AU8522_COMPOSITE_CH1) { au8522_setup_cvbs_mode(state); - } else if (route->input == AU8522_SVIDEO_CH13) { + } else if (input == AU8522_SVIDEO_CH13) { au8522_setup_svideo_mode(state); - } else if (route->input == AU8522_COMPOSITE_CH4_SIF) { + } else if (input == AU8522_COMPOSITE_CH4_SIF) { au8522_setup_cvbs_tuner_mode(state); } else { printk(KERN_ERR "au8522 mode not currently supported\n"); @@ -677,10 +677,10 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd, } static int au8522_s_audio_routing(struct v4l2_subdev *sd, - const struct v4l2_routing *route) + u32 input, u32 output, u32 config) { struct au8522_state *state = to_state(sd); - set_audio_input(state, route->input); + set_audio_input(state, input); return 0; } diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c new file mode 100644 index 00000000000..f9785dfe735 --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gxx.c @@ -0,0 +1,816 @@ +/* + * Support for Legend Silicon DMB-TH demodulator + * LGS8913, LGS8GL5 + * experimental support LGS8G42, LGS8G52 + * + * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> + * Copyright (C) 2008 Sirius International (Hong Kong) Limited + * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <asm/div64.h> + +#include "dvb_frontend.h" + +#include "lgs8gxx.h" +#include "lgs8gxx_priv.h" + +#define dprintk(args...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "lgs8gxx: " args); \ + } while (0) + +static int debug; +static int fake_signal_str; + +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); + +module_param(fake_signal_str, int, 0644); +MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." +"Signal strength calculation is slow.(default:off)."); + +/* LGS8GXX internal helper functions */ + +static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) +{ + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; + + msg.addr = priv->config->demod_address; + if (reg >= 0xC0) + msg.addr += 0x02; + + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + __func__, reg, data); + + ret = i2c_transfer(priv->i2c, &msg, 1); + + if (ret != 1) + dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", + __func__, reg, data, ret); + + return (ret != 1) ? -1 : 0; +} + +static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) +{ + int ret; + u8 dev_addr; + + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = { + { .flags = 0, .buf = b0, .len = 1 }, + { .flags = I2C_M_RD, .buf = b1, .len = 1 }, + }; + + dev_addr = priv->config->demod_address; + if (reg >= 0xC0) + dev_addr += 0x02; + msg[1].addr = msg[0].addr = dev_addr; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret != 2) { + dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", + __func__, reg, ret); + return -1; + } + + *p_data = b1[0]; + if (debug >= 2) + printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", + __func__, reg, b1[0]); + return 0; +} + +static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv) +{ + lgs8gxx_write_reg(priv, 0x02, 0x00); + msleep(1); + lgs8gxx_write_reg(priv, 0x02, 0x01); + msleep(100); + + return 0; +} + +static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) +{ + const struct lgs8gxx_config *config = priv->config; + u8 if_conf; + + if_conf = 0x10; /* AGC output on; */ + + if_conf |= + ((config->ext_adc) ? 0x80 : 0x00) | + ((config->if_neg_center) ? 0x04 : 0x00) | + ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ + ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | + ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); + + if (config->ext_adc && + (config->prod == LGS8GXX_PROD_LGS8G52)) { + lgs8gxx_write_reg(priv, 0xBA, 0x40); + } + + lgs8gxx_write_reg(priv, 0x07, if_conf); + + return 0; +} + +static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) +{ + u64 val; + u32 v32; + u32 if_clk; + + if_clk = priv->config->if_clk_freq; + + val = freq; + if (freq != 0) { + val *= (u64)1 << 32; + if (if_clk != 0) + do_div(val, if_clk); + v32 = val & 0xFFFFFFFF; + dprintk("Set IF Freq to %dkHz\n", freq); + } else { + v32 = 0; + dprintk("Set IF Freq to baseband\n"); + } + dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); + + lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); + lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); + lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); + lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); + + return 0; +} + +static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) +{ + u8 t; + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC6, 0x01); + + lgs8gxx_read_reg(priv, 0x7E, &t); + lgs8gxx_write_reg(priv, 0x7E, t | 0x01); + + /* clear FEC self reset */ + lgs8gxx_read_reg(priv, 0xC5, &t); + lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + /* FEC auto detect */ + lgs8gxx_write_reg(priv, 0xC1, 0x03); + + lgs8gxx_read_reg(priv, 0x7C, &t); + t = (t & 0x8C) | 0x03; + lgs8gxx_write_reg(priv, 0x7C, t); + } + + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + /* BER test mode */ + lgs8gxx_read_reg(priv, 0xC3, &t); + t = (t & 0xEF) | 0x10; + lgs8gxx_write_reg(priv, 0xC3, t); + } + + if (priv->config->prod == LGS8GXX_PROD_LGS8G52) + lgs8gxx_write_reg(priv, 0xD9, 0x40); + + return 0; +} + +static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv) +{ + int ret = 0; + u8 t; + + /* turn off auto-detect; manual settings */ + lgs8gxx_write_reg(priv, 0x7E, 0); + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC1, 0); + + ret = lgs8gxx_read_reg(priv, 0xC5, &t); + t = (t & 0xE0) | 0x06; + lgs8gxx_write_reg(priv, 0xC5, t); + + lgs8gxx_soft_reset(priv); + + return 0; +} + +static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked) +{ + int ret = 0; + u8 t; + + ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (ret != 0) + return ret; + + *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; + return 0; +} + +static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv, + u8 *finished) +{ + int ret = 0; + u8 t; + + ret = lgs8gxx_read_reg(priv, 0xA4, &t); + if (ret != 0) + return ret; + + *finished = ((t & 0x3) == 0x1) ? 1 : 0; + + return 0; +} + +static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) +{ + int err; + u8 ad_fini = 0; + + if (gi == GI_945) + dprintk("try GI 945\n"); + else if (gi == GI_595) + dprintk("try GI 595\n"); + else if (gi == GI_420) + dprintk("try GI 420\n"); + lgs8gxx_write_reg(priv, 0x04, gi); + lgs8gxx_soft_reset(priv); + msleep(50); + err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); + if (err != 0) + return err; + if (ad_fini) { + err = lgs8gxx_is_locked(priv, locked); + if (err != 0) + return err; + } + + return 0; +} + +static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, + u8 *detected_param, u8 *gi) +{ + int i, j; + int err = 0; + u8 locked = 0, tmp_gi; + + dprintk("%s\n", __func__); + + lgs8gxx_set_mode_auto(priv); + /* Guard Interval */ + lgs8gxx_write_reg(priv, 0x03, 00); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + tmp_gi = GI_945; + err = lgs8gxx_autolock_gi(priv, GI_945, &locked); + if (err) + goto out; + if (locked) + goto locked; + } + for (j = 0; j < 2; j++) { + tmp_gi = GI_420; + err = lgs8gxx_autolock_gi(priv, GI_420, &locked); + if (err) + goto out; + if (locked) + goto locked; + } + tmp_gi = GI_595; + err = lgs8gxx_autolock_gi(priv, GI_595, &locked); + if (err) + goto out; + if (locked) + goto locked; + } + +locked: + if ((err == 0) && (locked == 1)) { + u8 t; + + lgs8gxx_read_reg(priv, 0xA2, &t); + *detected_param = t; + + if (tmp_gi == GI_945) + dprintk("GI 945 locked\n"); + else if (tmp_gi == GI_595) + dprintk("GI 595 locked\n"); + else if (tmp_gi == GI_420) + dprintk("GI 420 locked\n"); + *gi = tmp_gi; + } + if (!locked) + err = -1; + +out: + return err; +} + +static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv) +{ + s8 err; + u8 gi = 0x2; + u8 detected_param = 0; + + err = lgs8gxx_auto_detect(priv, &detected_param, &gi); + + if (err != 0) { + dprintk("lgs8gxx_auto_detect failed\n"); + } + + /* Apply detected parameters */ + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + u8 inter_leave_len = detected_param & TIM_MASK ; + inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; + detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; + detected_param |= inter_leave_len; + } + lgs8gxx_write_reg(priv, 0x7D, detected_param); + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + lgs8gxx_write_reg(priv, 0xC0, detected_param); + /* lgs8gxx_soft_reset(priv); */ + + /* Enter manual mode */ + lgs8gxx_set_mode_manual(priv); + + switch (gi) { + case GI_945: + priv->curr_gi = 945; break; + case GI_595: + priv->curr_gi = 595; break; + case GI_420: + priv->curr_gi = 420; break; + default: + priv->curr_gi = 945; break; + } +} + +static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, + u8 serial, u8 clk_pol, u8 clk_gated) +{ + int ret = 0; + u8 t; + + ret = lgs8gxx_read_reg(priv, 0xC2, &t); + if (ret != 0) + return ret; + + t &= 0xF8; + t |= serial ? TS_SERIAL : TS_PARALLEL; + t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; + t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; + + ret = lgs8gxx_write_reg(priv, 0xC2, t); + if (ret != 0) + return ret; + + return 0; +} + + +/* LGS8913 demod frontend functions */ + +static int lgs8913_init(struct lgs8gxx_state *priv) +{ + u8 t; + + /* LGS8913 specific */ + lgs8gxx_write_reg(priv, 0xc1, 0x3); + + lgs8gxx_read_reg(priv, 0x7c, &t); + lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3); + + /* LGS8913 specific */ + lgs8gxx_read_reg(priv, 0xc3, &t); + lgs8gxx_write_reg(priv, 0xc3, t&0x10); + + + return 0; +} + +static int lgs8gxx_init(struct dvb_frontend *fe) +{ + struct lgs8gxx_state *priv = + (struct lgs8gxx_state *)fe->demodulator_priv; + const struct lgs8gxx_config *config = priv->config; + u8 data = 0; + s8 err; + dprintk("%s\n", __func__); + + lgs8gxx_read_reg(priv, 0, &data); + dprintk("reg 0 = 0x%02X\n", data); + + /* Setup MPEG output format */ + err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, + config->ts_clk_pol, + config->ts_clk_gated); + if (err != 0) + return -EIO; + + if (config->prod == LGS8GXX_PROD_LGS8913) + lgs8913_init(priv); + lgs8gxx_set_if_freq(priv, priv->config->if_freq); + if (config->prod != LGS8GXX_PROD_LGS8913) + lgs8gxx_set_ad_mode(priv); + + return 0; +} + +static void lgs8gxx_release(struct dvb_frontend *fe) +{ + struct lgs8gxx_state *state = fe->demodulator_priv; + dprintk("%s\n", __func__); + + kfree(state); +} + + +static int lgs8gxx_write(struct dvb_frontend *fe, u8 *buf, int len) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + if (len != 2) + return -EINVAL; + + return lgs8gxx_write_reg(priv, buf[0], buf[1]); +} + +static int lgs8gxx_set_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fe_params) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + dprintk("%s\n", __func__); + + /* set frequency */ + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fe_params); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } + + /* start auto lock */ + lgs8gxx_auto_lock(priv); + + msleep(10); + + return 0; +} + +static int lgs8gxx_get_fe(struct dvb_frontend *fe, + struct dvb_frontend_parameters *fe_params) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + u8 t; + + dprintk("%s\n", __func__); + + /* TODO: get real readings from device */ + /* inversion status */ + fe_params->inversion = INVERSION_OFF; + + /* bandwidth */ + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + + + lgs8gxx_read_reg(priv, 0x7D, &t); + fe_params->u.ofdm.code_rate_HP = FEC_AUTO; + fe_params->u.ofdm.code_rate_LP = FEC_AUTO; + + /* constellation */ + switch (t & SC_MASK) { + case SC_QAM64: + fe_params->u.ofdm.constellation = QAM_64; + break; + case SC_QAM32: + fe_params->u.ofdm.constellation = QAM_32; + break; + case SC_QAM16: + fe_params->u.ofdm.constellation = QAM_16; + break; + case SC_QAM4: + case SC_QAM4NR: + fe_params->u.ofdm.constellation = QPSK; + break; + default: + fe_params->u.ofdm.constellation = QAM_64; + } + + /* transmission mode */ + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + + /* guard interval */ + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + + /* hierarchy */ + fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; + + return 0; +} + +static +int lgs8gxx_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + /* FIXME: copy from tda1004x.c */ + fesettings->min_delay_ms = 800; + fesettings->step_size = 0; + fesettings->max_drift = 0; + return 0; +} + +static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + s8 ret; + u8 t; + + dprintk("%s\n", __func__); + + ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (ret != 0) + return -EIO; + + dprintk("Reg 0x4B: 0x%02X\n", t); + + *fe_status = 0; + if (priv->config->prod == LGS8GXX_PROD_LGS8913) { + if ((t & 0x40) == 0x40) + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; + if ((t & 0x80) == 0x80) + *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | + FE_HAS_LOCK; + } else { + if ((t & 0x80) == 0x80) + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + } + + /* success */ + dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); + return 0; +} + +static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal) +{ + u16 v; + u8 agc_lvl[2], cat; + + dprintk("%s()\n", __func__); + lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]); + lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]); + + v = agc_lvl[0]; + v <<= 8; + v |= agc_lvl[1]; + + dprintk("agc_lvl: 0x%04X\n", v); + + if (v < 0x100) + cat = 0; + else if (v < 0x190) + cat = 5; + else if (v < 0x2A8) + cat = 4; + else if (v < 0x381) + cat = 3; + else if (v < 0x400) + cat = 2; + else if (v == 0x400) + cat = 1; + else + cat = 0; + + *signal = cat; + + return 0; +} + +static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) +{ + u8 t; s8 ret; + s16 max_strength = 0; + u8 str; + u16 i, gi = priv->curr_gi; + + dprintk("%s\n", __func__); + + ret = lgs8gxx_read_reg(priv, 0x4B, &t); + if (ret != 0) + return -EIO; + + if (fake_signal_str) { + if ((t & 0xC0) == 0xC0) { + dprintk("Fake signal strength as 50\n"); + *signal = 0x32; + } else + *signal = 0; + return 0; + } + + dprintk("gi = %d\n", gi); + for (i = 0; i < gi; i++) { + + if ((i & 0xFF) == 0) + lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8)); + lgs8gxx_write_reg(priv, 0x83, i & 0xFF); + + lgs8gxx_read_reg(priv, 0x94, &str); + if (max_strength < str) + max_strength = str; + } + + *signal = max_strength; + dprintk("%s: signal=0x%02X\n", __func__, *signal); + + lgs8gxx_read_reg(priv, 0x95, &t); + dprintk("%s: AVG Noise=0x%02X\n", __func__, t); + + return 0; +} + +static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + if (priv->config->prod == LGS8GXX_PROD_LGS8913) + return lgs8913_read_signal_strength(priv, signal); + else + return lgs8gxx_read_signal_agc(priv, signal); +} + +static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + u8 t; + *snr = 0; + + lgs8gxx_read_reg(priv, 0x95, &t); + dprintk("AVG Noise=0x%02X\n", t); + *snr = 256 - t; + *snr <<= 8; + dprintk("snr=0x%x\n", *snr); + + return 0; +} + +static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + *ucblocks = 0; + dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks); + return 0; +} + +static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + u8 r0, r1, r2, r3; + u32 total_cnt, err_cnt; + + dprintk("%s\n", __func__); + + lgs8gxx_write_reg(priv, 0xc6, 0x01); + lgs8gxx_write_reg(priv, 0xc6, 0x41); + lgs8gxx_write_reg(priv, 0xc6, 0x01); + + msleep(200); + + lgs8gxx_write_reg(priv, 0xc6, 0x81); + lgs8gxx_read_reg(priv, 0xd0, &r0); + lgs8gxx_read_reg(priv, 0xd1, &r1); + lgs8gxx_read_reg(priv, 0xd2, &r2); + lgs8gxx_read_reg(priv, 0xd3, &r3); + total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); + lgs8gxx_read_reg(priv, 0xd4, &r0); + lgs8gxx_read_reg(priv, 0xd5, &r1); + lgs8gxx_read_reg(priv, 0xd6, &r2); + lgs8gxx_read_reg(priv, 0xd7, &r3); + err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); + dprintk("error=%d total=%d\n", err_cnt, total_cnt); + + if (total_cnt == 0) + *ber = 0; + else + *ber = err_cnt * 100 / total_cnt; + + dprintk("%s: ber=0x%x\n", __func__, *ber); + return 0; +} + +static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct lgs8gxx_state *priv = fe->demodulator_priv; + + if (priv->config->tuner_address == 0) + return 0; + if (enable) { + u8 v = 0x80 | priv->config->tuner_address; + return lgs8gxx_write_reg(priv, 0x01, v); + } + return lgs8gxx_write_reg(priv, 0x01, 0); +} + +static struct dvb_frontend_ops lgs8gxx_ops = { + .info = { + .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH", + .type = FE_OFDM, + .frequency_min = 474000000, + .frequency_max = 858000000, + .frequency_stepsize = 10000, + .caps = + FE_CAN_FEC_AUTO | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO + }, + + .release = lgs8gxx_release, + + .init = lgs8gxx_init, + .write = lgs8gxx_write, + .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, + + .set_frontend = lgs8gxx_set_fe, + .get_frontend = lgs8gxx_get_fe, + .get_tune_settings = lgs8gxx_get_tune_settings, + + .read_status = lgs8gxx_read_status, + .read_ber = lgs8gxx_read_ber, + .read_signal_strength = lgs8gxx_read_signal_strength, + .read_snr = lgs8gxx_read_snr, + .read_ucblocks = lgs8gxx_read_ucblocks, +}; + +struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, + struct i2c_adapter *i2c) +{ + struct lgs8gxx_state *priv = NULL; + u8 data = 0; + + dprintk("%s()\n", __func__); + + if (config == NULL || i2c == NULL) + return NULL; + + priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL); + if (priv == NULL) + goto error_out; + + priv->config = config; + priv->i2c = i2c; + + /* check if the demod is there */ + if (lgs8gxx_read_reg(priv, 0, &data) != 0) { + dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n", + __func__, priv->config->demod_address); + goto error_out; + } + + lgs8gxx_read_reg(priv, 1, &data); + + memcpy(&priv->frontend.ops, &lgs8gxx_ops, + sizeof(struct dvb_frontend_ops)); + priv->frontend.demodulator_priv = priv; + + return &priv->frontend; + +error_out: + dprintk("%s() error_out\n", __func__); + kfree(priv); + return NULL; + +} +EXPORT_SYMBOL(lgs8gxx_attach); + +MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver"); +MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/lgs8gxx.h b/drivers/media/dvb/frontends/lgs8gxx.h new file mode 100644 index 00000000000..321d366a830 --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gxx.h @@ -0,0 +1,90 @@ +/* + * Support for Legend Silicon DMB-TH demodulator + * LGS8913, LGS8GL5 + * experimental support LGS8G42, LGS8G52 + * + * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> + * Copyright (C) 2008 Sirius International (Hong Kong) Limited + * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __LGS8GXX_H__ +#define __LGS8GXX_H__ + +#include <linux/dvb/frontend.h> +#include <linux/i2c.h> + +#define LGS8GXX_PROD_LGS8913 0 +#define LGS8GXX_PROD_LGS8GL5 1 +#define LGS8GXX_PROD_LGS8G42 3 +#define LGS8GXX_PROD_LGS8G52 4 +#define LGS8GXX_PROD_LGS8G54 5 + +struct lgs8gxx_config { + + /* product type */ + u8 prod; + + /* the demodulator's i2c address */ + u8 demod_address; + + /* parallel or serial transport stream */ + u8 serial_ts; + + /* transport stream polarity*/ + u8 ts_clk_pol; + + /* transport stream clock gated by ts_valid */ + u8 ts_clk_gated; + + /* A/D Clock frequency */ + u32 if_clk_freq; /* in kHz */ + + /* IF frequency */ + u32 if_freq; /* in kHz */ + + /*Use External ADC*/ + u8 ext_adc; + + /*External ADC output two's complement*/ + u8 adc_signed; + + /*Sample IF data at falling edge of IF_CLK*/ + u8 if_neg_edge; + + /*IF use Negative center frequency*/ + u8 if_neg_center; + + /* slave address and configuration of the tuner */ + u8 tuner_address; +}; + +#if defined(CONFIG_DVB_LGS8GXX) || \ + (defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE)) +extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, + struct i2c_adapter *i2c); +#else +static inline +struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, + struct i2c_adapter *i2c) { + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_LGS8GXX */ + +#endif /* __LGS8GXX_H__ */ diff --git a/drivers/media/dvb/frontends/lgs8gxx_priv.h b/drivers/media/dvb/frontends/lgs8gxx_priv.h new file mode 100644 index 00000000000..9776d30686d --- /dev/null +++ b/drivers/media/dvb/frontends/lgs8gxx_priv.h @@ -0,0 +1,70 @@ +/* + * Support for Legend Silicon DMB-TH demodulator + * LGS8913, LGS8GL5 + * experimental support LGS8G42, LGS8G52 + * + * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> + * Copyright (C) 2008 Sirius International (Hong Kong) Limited + * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef LGS8913_PRIV_H +#define LGS8913_PRIV_H + +struct lgs8gxx_state { + struct i2c_adapter *i2c; + /* configuration settings */ + const struct lgs8gxx_config *config; + struct dvb_frontend frontend; + u16 curr_gi; /* current guard interval */ +}; + +#define SC_MASK 0x1C /* Sub-Carrier Modulation Mask */ +#define SC_QAM64 0x10 /* 64QAM modulation */ +#define SC_QAM32 0x0C /* 32QAM modulation */ +#define SC_QAM16 0x08 /* 16QAM modulation */ +#define SC_QAM4NR 0x04 /* 4QAM modulation */ +#define SC_QAM4 0x00 /* 4QAM modulation */ + +#define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ +#define LGS_FEC_0_4 0x00 /* FEC Rate 0.4 */ +#define LGS_FEC_0_6 0x01 /* FEC Rate 0.6 */ +#define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ + +#define TIM_MASK 0x20 /* Time Interleave Length Mask */ +#define TIM_LONG 0x00 /* Time Interleave Length = 720 */ +#define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ + +#define CF_MASK 0x80 /* Control Frame Mask */ +#define CF_EN 0x80 /* Control Frame On */ + +#define GI_MASK 0x03 /* Guard Interval Mask */ +#define GI_420 0x00 /* 1/9 Guard Interval */ +#define GI_595 0x01 /* */ +#define GI_945 0x02 /* 1/4 Guard Interval */ + + +#define TS_PARALLEL 0x00 /* Parallel TS Output a.k.a. SPI */ +#define TS_SERIAL 0x01 /* Serial TS Output a.k.a. SSI */ +#define TS_CLK_NORMAL 0x00 /* MPEG Clock Normal */ +#define TS_CLK_INVERTED 0x02 /* MPEG Clock Inverted */ +#define TS_CLK_GATED 0x00 /* MPEG clock gated */ +#define TS_CLK_FREERUN 0x04 /* MPEG clock free running*/ + + +#endif diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c index ee89623be85..598eaf8acc6 100644 --- a/drivers/media/dvb/pluto2/pluto2.c +++ b/drivers/media/dvb/pluto2/pluto2.c @@ -616,7 +616,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, /* enable interrupts */ pci_write_config_dword(pdev, 0x6c, 0x8000); - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret < 0) goto err_pci_disable_device; |