diff options
Diffstat (limited to 'linux/drivers/media/dvb')
69 files changed, 2709 insertions, 328 deletions
diff --git a/linux/drivers/media/dvb/b2c2/flexcop-pci.c b/linux/drivers/media/dvb/b2c2/flexcop-pci.c index eb2e6432c..e6362f304 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c @@ -122,7 +122,11 @@ static void flexcop_pci_irq_check_work(void *data) /* When PID filtering is turned on, we use the timer IRQ, because small amounts * of data need to be passed to the user space instantly as well. When PID * filtering is turned off, we use the page-change-IRQ */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t flexcop_pci_isr(int irq, void *dev_id) +#endif { struct flexcop_pci *fc_pci = dev_id; struct flexcop_device *fc = fc_pci->fc_dev; diff --git a/linux/drivers/media/dvb/b2c2/flexcop-usb.c b/linux/drivers/media/dvb/b2c2/flexcop-usb.c index 8a3ae27f8..8d16d6e72 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-usb.c @@ -328,7 +328,11 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, in fc_usb->tmp_buffer_length = l; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs) +#else +static void flexcop_usb_urb_complete(struct urb *urb) +#endif { struct flexcop_usb *fc_usb = urb->context; int i; diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c index 755822ee6..c63314b9f 100644 --- a/linux/drivers/media/dvb/bt8xx/bt878.c +++ b/linux/drivers/media/dvb/bt8xx/bt878.c @@ -266,7 +266,11 @@ EXPORT_SYMBOL(bt878_stop); /* Interrupt service routine */ /*****************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static irqreturn_t bt878_irq(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t bt878_irq(int irq, void *dev_id) +#endif { u32 stat, astat, mask; int count; diff --git a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c index 5964b27f9..90672efea 100644 --- a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -255,7 +255,11 @@ static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep) cinergyt2->sleeping = sleep; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs); +#else +static void cinergyt2_stream_irq (struct urb *urb); +#endif static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb) { @@ -275,7 +279,11 @@ static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb return err; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs) +#else +static void cinergyt2_stream_irq (struct urb *urb) +#endif { struct cinergyt2 *cinergyt2 = urb->context; diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 67cefdd23..dfd53d5e7 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -26,7 +26,7 @@ config DVB_USB_A800 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" depends on DVB_USB select DVB_DIB3000MB - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. @@ -69,9 +69,10 @@ config DVB_USB_DIBUSB_MC config DVB_USB_DIB0700 tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" depends on DVB_USB + select DVB_DIB7000P select DVB_DIB7000M select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -88,7 +89,7 @@ config DVB_USB_UMT_010 tristate "HanfTek UMT-010 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -154,7 +155,7 @@ config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. diff --git a/linux/drivers/media/dvb/dvb-usb/a800.c b/linux/drivers/media/dvb/dvb-usb/a800.c index 45543c5a2..16df0a3f9 100644 --- a/linux/drivers/media/dvb/dvb-usb/a800.c +++ b/linux/drivers/media/dvb/dvb-usb/a800.c @@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), }, diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index 1e96afbe2..ecc764c85 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -14,7 +14,7 @@ * TODO: Use the cx25840-driver for the analogue part * * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) - * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net) + * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au) * * This program is free software; you can redistribute it and/or modify it @@ -396,7 +396,7 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap) return 0; } -static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap) +static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap) { adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params; return 0; @@ -529,20 +529,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_cx22702_frontend_attach, - .tuner_attach = cxusb_fmd1216me_tuner_attach, - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_cx22702_frontend_attach, + .tuner_attach = cxusb_fmd1216me_tuner_attach, + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -575,21 +575,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_lgdt3303_frontend_attach, - .tuner_attach = cxusb_lgdt3303_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 5, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_lgdt3303_frontend_attach, + .tuner_attach = cxusb_lgh064f_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -627,20 +627,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_dee1601_frontend_attach, - .tuner_attach = cxusb_dee1601_tuner_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_dee1601_frontend_attach, + .tuner_attach = cxusb_dee1601_tuner_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, @@ -686,21 +686,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { .num_adapters = 2, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mt352_frontend_attach, - .tuner_attach = cxusb_lgz201_tuner_attach, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_lgz201_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, .power_ctrl = cxusb_bluebird_power_ctrl, @@ -736,21 +736,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = cxusb_streaming_ctrl, - .frontend_attach = cxusb_mt352_frontend_attach, - .tuner_attach = cxusb_dtt7579_tuner_attach, + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mt352_frontend_attach, + .tuner_attach = cxusb_dtt7579_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 5, - .endpoint = 0x04, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 5, + .endpoint = 0x04, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, }, }, .power_ctrl = cxusb_bluebird_power_ctrl, @@ -805,7 +805,7 @@ module_init (cxusb_module_init); module_exit (cxusb_module_exit); MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); -MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>"); +MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); MODULE_VERSION("1.0-alpha"); diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700.h b/linux/drivers/media/dvb/dvb-usb/dib0700.h index ac84347f9..cda3adea2 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700.h +++ b/linux/drivers/media/dvb/dvb-usb/dib0700.h @@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug; #define REQUEST_I2C_WRITE 0x3 #define REQUEST_POLL_RC 0x4 #define REQUEST_JUMPRAM 0x8 +#define REQUEST_SET_CLOCK 0xB #define REQUEST_SET_GPIO 0xC #define REQUEST_ENABLE_VIDEO 0xF // 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog) // 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1) // 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " ) +#define REQUEST_GET_VERSION 0x15 struct dib0700_state { u8 channel_state; u16 mt2060_if1[2]; + + u8 is_dib7000pc; }; extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); +extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw); extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff); extern struct i2c_algorithm dib0700_i2c_algo; diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c index 47339cfe7..4b95a01ea 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = { int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, struct dvb_usb_device_description **desc, int *cold) { - u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C - *cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0), - buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3; + u8 b[16]; + s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0), + REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); + + deb_info("FW GET_VERSION length: %d\n",ret); + + *cold = ret <= 0; deb_info("cold: %d\n", *cold); return 0; } +static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, + u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, + u16 pll_loopdiv, u16 free_div, u16 dsuScaler) +{ + u8 b[10]; + b[0] = REQUEST_SET_CLOCK; + b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4); + b[2] = (pll_prediv >> 8) & 0xff; // MSB + b[3] = pll_prediv & 0xff; // LSB + b[4] = (pll_loopdiv >> 8) & 0xff; // MSB + b[5] = pll_loopdiv & 0xff; // LSB + b[6] = (free_div >> 8) & 0xff; // MSB + b[7] = free_div & 0xff; // LSB + b[8] = (dsuScaler >> 8) & 0xff; // MSB + b[9] = dsuScaler & 0xff; // LSB + + return dib0700_ctrl_wr(d, b, 10); +} + +int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) +{ + switch (clk_MHz) { + case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; + default: return -EINVAL; + } + return 0; +} + static int dib0700_jumpram(struct usb_device *udev, u32 address) { int ret, actlen; @@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw /* start the firmware */ if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { info("firmware started successfully."); - msleep(100); + msleep(500); } } else ret = -EIO; diff --git a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c index b4e339df7..1b1598d08 100644 --- a/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/linux/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -10,6 +10,7 @@ #include "dib3000mc.h" #include "dib7000m.h" +#include "dib7000p.h" #include "mt2060.h" static int force_lna_activation; @@ -96,37 +97,186 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) } /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ -/* -static struct mt2060_config stk7000p_mt2060_config = { - 0x60 +static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = { + BAND_UHF | BAND_VHF, // band_caps + + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup + + 712, // inv_gain + 41, // time_stabiliz + + 0, // alpha_level + 118, // thlock + + 0, // wbd_inv + 4095, // wbd_ref + 0, // wbd_sel + 0, // wbd_alpha + + 42598, // agc1_max + 17694, // agc1_min + 45875, // agc2_max + 2621, // agc2_min + 0, // agc1_pt1 + 76, // agc1_pt2 + 139, // agc1_pt3 + 52, // agc1_slope1 + 59, // agc1_slope2 + 107, // agc2_pt1 + 172, // agc2_pt2 + 57, // agc2_slope1 + 70, // agc2_slope2 + + 21, // alpha_mant + 25, // alpha_exp + 28, // beta_mant + 48, // beta_exp + + 1, // perform_agc_softsplit + { 0, // split_min + 107, // split_max + 51800, // global_split_min + 24700 // global_split_max + }, +}; + +static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = { + BAND_UHF | BAND_VHF, + + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup + + 712, // inv_gain + 41, // time_stabiliz + + 0, // alpha_level + 118, // thlock + + 0, // wbd_inv + 4095, // wbd_ref + 0, // wbd_sel + 0, // wbd_alpha + + 42598, // agc1_max + 16384, // agc1_min + 42598, // agc2_max + 0, // agc2_min + + 0, // agc1_pt1 + 137, // agc1_pt2 + 255, // agc1_pt3 + + 0, // agc1_slope1 + 255, // agc1_slope2 + + 0, // agc2_pt1 + 0, // agc2_pt2 + + 0, // agc2_slope1 + 41, // agc2_slope2 + + 15, // alpha_mant + 25, // alpha_exp + + 28, // beta_mant + 48, // beta_exp + + 0, // perform_agc_softsplit +}; + +static struct dibx000_bandwidth_config stk7700p_pll_config = { + 60000, 30000, // internal, sampling + 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass + 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo + (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k + 60258167, // ifreq + 20452225, // timf +}; + +static struct dib7000m_config stk7700p_dib7000m_config = { + .dvbt_mode = 1, + .output_mpeg2_in_188_bytes = 1, + .quartz_direct = 1, + + .agc_config_count = 1, + .agc = &stk7700p_7000m_mt2060_agc_config, + .bw = &stk7700p_pll_config, + + .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, +}; + +static struct dib7000p_config stk7700p_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + + .agc = &stk7700p_7000p_mt2060_agc_config, + .bw = &stk7700p_pll_config, + + .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, }; -*/ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) { + struct dib0700_state *st = adap->dev->priv; /* unless there is no real power management in DVB - we leave the device on GPIO6 */ - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); - dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); - dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); + + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50); + + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); + dib0700_ctrl_clock(adap->dev, 72, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100); + + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + st->mt2060_if1[0] = 1220; + + if (dib7000pc_detection(&adap->dev->i2c_adap)) { + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); + st->is_dib7000pc = 1; + } else + adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); -// adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18); - return 0; + return adap->fe == NULL ? -ENODEV : 0; } +static struct mt2060_config stk7700p_mt2060_config = { + 0x60 +}; + static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) { -// tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1); -// return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1); - return 0; + struct dib0700_state *st = adap->dev->priv; + struct i2c_adapter *tun_i2c; + + if (st->is_dib7000pc) + tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + else + tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); + + return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config, + st->mt2060_if1[0]) == NULL ? -ENODEV : 0; } struct usb_device_id dib0700_usb_id_table[] = { { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, + { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, + { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, + { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) }, + { USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -168,20 +318,28 @@ struct dvb_usb_device_properties dib0700_devices[] = { }, }, - .num_device_descs = 3, + .num_device_descs = 5, .devices = { { "DiBcom STK7700P reference design", - { &dib0700_usb_id_table[0], NULL }, + { &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] }, { NULL }, }, { "Hauppauge Nova-T Stick", - { &dib0700_usb_id_table[3], NULL }, + { &dib0700_usb_id_table[4], NULL }, { NULL }, }, { "AVerMedia AVerTV DVB-T Volar", - { &dib0700_usb_id_table[4], NULL }, + { &dib0700_usb_id_table[5], NULL }, + { NULL }, + }, + { "Compro Videomate U500", + { &dib0700_usb_id_table[6], NULL }, { NULL }, }, + { "Uniwill STK7700P based (Hama and others)", + { &dib0700_usb_id_table[7], NULL }, + { NULL }, + } } }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, @@ -203,7 +361,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .num_device_descs = 1, .devices = { { "Hauppauge Nova-T 500 Dual DVB-T", - { &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL }, + { &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL }, { NULL }, }, } diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c index fd3a9902f..5143e426d 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -169,7 +169,7 @@ EXPORT_SYMBOL(dibusb_read_eeprom_byte); // Config Adjacent channels Perf -cal22 static struct dibx000_agc_config dib3000p_mt2060_agc_config = { .band_caps = BAND_VHF | BAND_UHF, - .setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0), + .setup = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0), .agc1_max = 48497, .agc1_min = 23593, @@ -196,10 +196,14 @@ static struct dib3000mc_config stk3000p_dib3000p_config = { .ln_adc_level = 0x1cc7, .output_mpeg2_in_188_bytes = 1, + + .agc_command1 = 1, + .agc_command2 = 1, }; static struct dibx000_agc_config dib3000p_panasonic_agc_config = { - .setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0), + .band_caps = BAND_VHF | BAND_UHF, + .setup = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0), .agc1_max = 56361, .agc1_min = 22282, @@ -226,6 +230,9 @@ static struct dib3000mc_config mod3000p_dib3000p_config = { .ln_adc_level = 0x1cc7, .output_mpeg2_in_188_bytes = 1, + + .agc_command1 = 1, + .agc_command2 = 1, }; int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap) diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c index 9e6bdcbae..5a8745056 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, + .streaming_ctrl = dibusb_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, @@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, .pid_filter_count = 16, - .streaming_ctrl = dibusb_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, + .streaming_ctrl = dibusb_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), }, }, @@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_thomson_tuner_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_thomson_tuner_attach, + + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, @@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 16, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mb_frontend_attach, - .tuner_attach = dibusb_tuner_probe_and_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mb_frontend_attach, + .tuner_attach = dibusb_tuner_probe_and_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c index b65e76693..8fa2b6908 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = { { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb.h b/linux/drivers/media/dvb/dvb-usb/dibusb.h index 5153fb943..b60781032 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb.h +++ b/linux/drivers/media/dvb/dvb-usb/dibusb.h @@ -99,7 +99,9 @@ struct dibusb_state { struct dib_fe_xfer_ops ops; int mt2060_present; +}; +struct dibusb_device_state { /* for RC5 remote control */ int old_toggle; int last_repeat_count; diff --git a/linux/drivers/media/dvb/dvb-usb/digitv.c b/linux/drivers/media/dvb/dvb-usb/digitv.c index c4cc08bde..15686a626 100644 --- a/linux/drivers/media/dvb/dvb-usb/digitv.c +++ b/linux/drivers/media/dvb/dvb-usb/digitv.c @@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = { .num_adapters = 1, .adapter = { { - .frontend_attach = digitv_frontend_attach, - .tuner_attach = digitv_tuner_attach, + .frontend_attach = digitv_frontend_attach, + .tuner_attach = digitv_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .identify_state = digitv_identify_state, diff --git a/linux/drivers/media/dvb/dvb-usb/dtt200u.c b/linux/drivers/media/dvb/dvb-usb/dtt200u.c index f12ce5007..61a496109 100644 --- a/linux/drivers/media/dvb/dvb-usb/dtt200u.c +++ b/linux/drivers/media/dvb/dvb-usb/dtt200u.c @@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING, .pid_filter_count = 15, - .streaming_ctrl = dtt200u_streaming_ctrl, - .pid_filter = dtt200u_pid_filter, - .frontend_attach = dtt200u_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = dtt200u_streaming_ctrl, + .pid_filter = dtt200u_pid_filter, + .frontend_attach = dtt200u_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .power_ctrl = dtt200u_power_ctrl, diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 4d6b06953..58e1a449b 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -32,6 +32,7 @@ #define USB_VID_PINNACLE 0x2304 #define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_TWINHAN 0x1822 +#define USB_VID_UNIWILL 0x1584 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 #define USB_VID_WIDEVIEW 0x14aa @@ -46,6 +47,7 @@ #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d +#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 @@ -53,7 +55,9 @@ #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 #define USB_PID_DIBCOM_STK7700P 0x1e14 +#define USB_PID_DIBCOM_STK7700P_PC 0x1e78 #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 +#define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de @@ -97,7 +101,7 @@ #define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941 #define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950 #define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050 -#define USB_PID_AVERMEDIA_VOLAR 0x1234 +#define USB_PID_AVERMEDIA_VOLAR 0xa807 #define USB_PID_NEBULA_DIGITV 0x0201 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 @@ -110,8 +114,8 @@ #define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58 #define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59 -#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 -#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 +#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54 +#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55 #define USB_PID_MEDION_MD95700 0x0932 #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f @@ -128,4 +132,5 @@ #define USB_PID_GENPIX_8PSK_COLD 0x0200 #define USB_PID_GENPIX_8PSK_WARM 0x0201 + #endif diff --git a/linux/drivers/media/dvb/dvb-usb/gp8psk.c b/linux/drivers/media/dvb/dvb-usb/gp8psk.c index e2d906985..6295e30c3 100644 --- a/linux/drivers/media/dvb/dvb-usb/gp8psk.c +++ b/linux/drivers/media/dvb/dvb-usb/gp8psk.c @@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = gp8psk_streaming_ctrl, - .frontend_attach = gp8psk_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .streaming_ctrl = gp8psk_streaming_ctrl, + .frontend_attach = gp8psk_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x82, - .u = { - .bulk = { - .buffersize = 8192, - } - } - }, + .count = 7, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, } }, .power_ctrl = gp8psk_power_ctrl, diff --git a/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c index 7b91f6b4a..8bd6d88ce 100644 --- a/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c +++ b/linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c @@ -75,7 +75,7 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; u16 raw; int i; - struct dibusb_state *st = d->priv; + struct dibusb_device_state *st = d->priv; dvb_usb_generic_rw(d,cmd,2,key,5,0); @@ -163,27 +163,28 @@ static struct dvb_usb_device_properties nova_t_properties = { .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, .pid_filter_count = 32, - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .pid_filter = dibusb_pid_filter, - .pid_filter_ctrl = dibusb_pid_filter_ctrl, - .frontend_attach = dibusb_dib3000mc_frontend_attach, - .tuner_attach = dibusb_dib3000mc_tuner_attach, - - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_BULK, - .count = 7, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .pid_filter = dibusb_pid_filter, + .pid_filter_ctrl = dibusb_pid_filter_ctrl, + .frontend_attach = dibusb_dib3000mc_frontend_attach, + .tuner_attach = dibusb_dib3000mc_tuner_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 7, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } }, + .size_of_priv = sizeof(struct dibusb_device_state), .power_ctrl = dibusb2_0_power_ctrl, .read_mac_address = nova_t_read_mac_address, diff --git a/linux/drivers/media/dvb/dvb-usb/umt-010.c b/linux/drivers/media/dvb/dvb-usb/umt-010.c index ba0c4ab3f..3f840a94c 100644 --- a/linux/drivers/media/dvb/dvb-usb/umt-010.c +++ b/linux/drivers/media/dvb/dvb-usb/umt-010.c @@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = { .num_adapters = 1, .adapter = { { - .streaming_ctrl = dibusb2_0_streaming_ctrl, - .frontend_attach = umt_mt352_frontend_attach, - .tuner_attach = umt_tuner_attach, + .streaming_ctrl = dibusb2_0_streaming_ctrl, + .frontend_attach = umt_mt352_frontend_attach, + .tuner_attach = umt_tuner_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 20, - .endpoint = 0x06, - .u = { - .bulk = { - .buffersize = 512, - } - } - }, + .count = 20, + .endpoint = 0x06, + .u = { + .bulk = { + .buffersize = 512, + } + } + }, .size_of_priv = sizeof(struct dibusb_state), } diff --git a/linux/drivers/media/dvb/dvb-usb/usb-urb.c b/linux/drivers/media/dvb/dvb-usb/usb-urb.c index 572b2d9aa..2ed0a214b 100644 --- a/linux/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/linux/drivers/media/dvb/dvb-usb/usb-urb.c @@ -11,7 +11,11 @@ #include "dvb-usb-common.h" /* URB stuff for streaming */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void usb_urb_complete(struct urb *urb, struct pt_regs *ptregs) +#else +static void usb_urb_complete(struct urb *urb) +#endif { struct usb_data_stream *stream = urb->context; int ptype = usb_pipetype(urb->pipe); diff --git a/linux/drivers/media/dvb/dvb-usb/vp702x.c b/linux/drivers/media/dvb/dvb-usb/vp702x.c index 77cb25271..b203810ba 100644 --- a/linux/drivers/media/dvb/dvb-usb/vp702x.c +++ b/linux/drivers/media/dvb/dvb-usb/vp702x.c @@ -307,22 +307,22 @@ static struct dvb_usb_device_properties vp702x_properties = { .caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS, .streaming_ctrl = vp702x_streaming_ctrl, - .frontend_attach = vp702x_frontend_attach, + .frontend_attach = vp702x_frontend_attach, - /* parameter for the MPEG2-data transfer */ + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, .count = 10, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, .size_of_priv = sizeof(struct vp702x_state), } - }, + }, .read_mac_address = vp702x_read_mac_addr, .rc_key_map = vp702x_rc_keys, diff --git a/linux/drivers/media/dvb/dvb-usb/vp7045.c b/linux/drivers/media/dvb/dvb-usb/vp7045.c index 02c6776d2..0ddeb3fce 100644 --- a/linux/drivers/media/dvb/dvb-usb/vp7045.c +++ b/linux/drivers/media/dvb/dvb-usb/vp7045.c @@ -125,7 +125,33 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = { { 0x00, 0x00, KEY_TAB }, /* Tab */ { 0x00, 0x48, KEY_INFO }, /* Preview */ { 0x00, 0x04, KEY_LIST }, /* RecordList */ - { 0x00, 0x0f, KEY_TEXT } /* Teletext */ + { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ + { 0x00, 0x41, KEY_PREVIOUSSONG }, + { 0x00, 0x42, KEY_NEXTSONG }, + { 0x00, 0x4b, KEY_UP }, + { 0x00, 0x51, KEY_DOWN }, + { 0x00, 0x4e, KEY_LEFT }, + { 0x00, 0x52, KEY_RIGHT }, + { 0x00, 0x4f, KEY_ENTER }, + { 0x00, 0x13, KEY_CANCEL }, + { 0x00, 0x4a, KEY_CLEAR }, + { 0x00, 0x54, KEY_PRINT }, /* Capture */ + { 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */ + { 0x00, 0x08, KEY_VIDEO }, /* A/V */ + { 0x00, 0x07, KEY_SLEEP }, /* Hibernate */ + { 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */ + { 0x00, 0x18, KEY_RED}, + { 0x00, 0x53, KEY_GREEN}, + { 0x00, 0x5e, KEY_YELLOW}, + { 0x00, 0x5f, KEY_BLUE} +#if 0 + /* not sure which linux key codes to use for the following buttons: */ + { 0x00, 0x46, ???}, /* Zoom- */ + { 0x00, 0x0e, ???}, /* Recall */ + { 0x00, 0x49, ???}, /* L/R */ + { 0x00, 0x47, ???}, /* PIP */ + { 0x00, 0x50, ???}, /* SAP */ +#endif }; static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state) @@ -217,18 +243,18 @@ static struct dvb_usb_device_properties vp7045_properties = { .num_adapters = 1, .adapter = { { - .frontend_attach = vp7045_frontend_attach, - /* parameter for the MPEG2-data transfer */ + .frontend_attach = vp7045_frontend_attach, + /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_BULK, - .count = 7, - .endpoint = 0x02, - .u = { - .bulk = { - .buffersize = 4096, - } - } - }, + .count = 7, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 4096, + } + } + }, } }, .power_ctrl = vp7045_power_ctrl, diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index ee14a7641..7279e587e 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -180,6 +180,14 @@ config DVB_DIB7000M A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. +config DVB_DIB7000P + tristate "DiBcom 7000PC" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-T tuner module. Designed for mobile usage. Say Y when you want + to support this frontend. + comment "DVB-C (cable) frontends" depends on DVB_CORE @@ -284,6 +292,8 @@ config DVB_TDA826X config DVB_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" + depends on I2C + default m if DVB_FE_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 244e87417..593152ecf 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_DVB_L64781) += l64781.o obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o +obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o diff --git a/linux/drivers/media/dvb/frontends/at76c651.h b/linux/drivers/media/dvb/frontends/at76c651.h index 32b26e368..334d7a075 100644 --- a/linux/drivers/media/dvb/frontends/at76c651.h +++ b/linux/drivers/media/dvb/frontends/at76c651.h @@ -37,7 +37,7 @@ struct at76c651_config u8 demod_address; }; -#if defined(CONFIG_DVB_AT76C651) || defined(CONFIG_DVB_AT76C651_MODULE) +#if defined(CONFIG_DVB_AT76C651) || (defined(CONFIG_DVB_AT76C651_MODULE) && defined(MODULE)) extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/bcm3510.h b/linux/drivers/media/dvb/frontends/bcm3510.h index 6dfa839a7..7e4f95e17 100644 --- a/linux/drivers/media/dvb/frontends/bcm3510.h +++ b/linux/drivers/media/dvb/frontends/bcm3510.h @@ -34,7 +34,7 @@ struct bcm3510_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE) +#if defined(CONFIG_DVB_BCM3510) || (defined(CONFIG_DVB_BCM3510_MODULE) && defined(MODULE)) extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/cx22700.h b/linux/drivers/media/dvb/frontends/cx22700.h index 10286cc29..7ac33690c 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.h +++ b/linux/drivers/media/dvb/frontends/cx22700.h @@ -31,7 +31,7 @@ struct cx22700_config u8 demod_address; }; -#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE) +#if defined(CONFIG_DVB_CX22700) || (defined(CONFIG_DVB_CX22700_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/cx22702.h b/linux/drivers/media/dvb/frontends/cx22702.h index bc217ddf0..9cd64da6e 100644 --- a/linux/drivers/media/dvb/frontends/cx22702.h +++ b/linux/drivers/media/dvb/frontends/cx22702.h @@ -41,7 +41,7 @@ struct cx22702_config u8 output_mode; }; -#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE) +#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/cx24110.h b/linux/drivers/media/dvb/frontends/cx24110.h index c9d5ae250..0ca3af4db 100644 --- a/linux/drivers/media/dvb/frontends/cx24110.h +++ b/linux/drivers/media/dvb/frontends/cx24110.h @@ -41,7 +41,7 @@ static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) { return r; } -#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE) +#if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/cx24123.h b/linux/drivers/media/dvb/frontends/cx24123.h index 57a1dae1d..84f9e4f5c 100644 --- a/linux/drivers/media/dvb/frontends/cx24123.h +++ b/linux/drivers/media/dvb/frontends/cx24123.h @@ -35,7 +35,7 @@ struct cx24123_config int lnb_polarity; }; -#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE) +#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/dib3000.h b/linux/drivers/media/dvb/frontends/dib3000.h index 0caac3f0f..a6d3854a6 100644 --- a/linux/drivers/media/dvb/frontends/dib3000.h +++ b/linux/drivers/media/dvb/frontends/dib3000.h @@ -41,7 +41,7 @@ struct dib_fe_xfer_ops int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl); }; -#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE) +#if defined(CONFIG_DVB_DIB3000MB) || (defined(CONFIG_DVB_DIB3000MB_MODULE) && defined(MODULE)) extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops); #else diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.c b/linux/drivers/media/dvb/frontends/dib3000mc.c index 555f7d43d..399204103 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc.c +++ b/linux/drivers/media/dvb/frontends/dib3000mc.c @@ -369,7 +369,7 @@ static int dib3000mc_init(struct dvb_frontend *demod) /* agc */ dib3000mc_write_word(state, 36, state->cfg->max_time); - dib3000mc_write_word(state, 37, agc->setup); + dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0)); dib3000mc_write_word(state, 38, state->cfg->pwm3_value); dib3000mc_write_word(state, 39, state->cfg->ln_adc_level); @@ -544,16 +544,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000 #endif /* a channel for autosearch */ - reg = 0; - if (chan->nfft == -1 && chan->guard == -1) reg = 7; - if (chan->nfft == -1 && chan->guard != -1) reg = 2; - if (chan->nfft != -1 && chan->guard == -1) reg = 3; - fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; fchan.vit_hrch = 0; fchan.vit_select_hp = 1; - dib3000mc_set_channel_cfg(state, &fchan, reg); + dib3000mc_set_channel_cfg(state, &fchan, 7); reg = dib3000mc_read_word(state, 0); dib3000mc_write_word(state, 0, reg | (1 << 8)); diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.h b/linux/drivers/media/dvb/frontends/dib3000mc.h index b198cd5b1..72d475760 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc.h +++ b/linux/drivers/media/dvb/frontends/dib3000mc.h @@ -28,6 +28,9 @@ struct dib3000mc_config { u16 max_time; u16 ln_adc_level; + u8 agc_command1 :1; + u8 agc_command2 :1; + u8 mobile_mode; u8 output_mpeg2_in_188_bytes; @@ -36,7 +39,7 @@ struct dib3000mc_config { #define DEFAULT_DIB3000MC_I2C_ADDRESS 16 #define DEFAULT_DIB3000P_I2C_ADDRESS 24 -#if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE) +#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg); #else static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg) diff --git a/linux/drivers/media/dvb/frontends/dib7000m.c b/linux/drivers/media/dvb/frontends/dib7000m.c index c9a57678f..88e741e78 100644 --- a/linux/drivers/media/dvb/frontends/dib7000m.c +++ b/linux/drivers/media/dvb/frontends/dib7000m.c @@ -19,7 +19,7 @@ static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); -#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0) +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) struct dib7000m_state { struct dvb_frontend demod; @@ -38,11 +38,21 @@ struct dib7000m_state { u8 current_band; fe_bandwidth_t current_bandwidth; struct dibx000_agc_config *current_agc; - u32 timf[9]; + u32 timf; u16 revision; }; +enum dib7000m_power_mode { + DIB7000M_POWER_ALL = 0, + + DIB7000M_POWER_NO, + DIB7000M_POWER_INTERF_ANALOG_AGC, + DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, + DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, + DIB7000M_POWER_INTERFACE_ONLY, +}; + static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) { u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; @@ -58,7 +68,6 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) return (rb[0] << 8) | rb[1]; } -/* static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) { u8 b[4] = { @@ -70,7 +79,865 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) }; return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; } -*/ +static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) +{ + int ret = 0; + u16 outreg, fifo_threshold, smo_mode, + sram = 0x0005; /* by default SRAM output is disabled */ + + outreg = 0; + fifo_threshold = 1792; + smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); + + dprintk("-I- Setting output mode for demod %p to %d\n", + &state->demod, mode); + + switch (mode) { + case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock + outreg = (1 << 10); /* 0x0400 */ + break; + case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock + outreg = (1 << 10) | (1 << 6); /* 0x0440 */ + break; + case OUTMODE_MPEG2_SERIAL: // STBs with serial input + outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ + break; + case OUTMODE_DIVERSITY: + if (state->cfg.hostbus_diversity) + outreg = (1 << 10) | (4 << 6); /* 0x0500 */ + else + sram |= 0x0c00; + break; + case OUTMODE_MPEG2_FIFO: // e.g. USB feeding + smo_mode |= (3 << 1); + fifo_threshold = 512; + outreg = (1 << 10) | (5 << 6); + break; + case OUTMODE_HIGH_Z: // disable + outreg = 0; + break; + default: + dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); + break; + } + + if (state->cfg.output_mpeg2_in_188_bytes) + smo_mode |= (1 << 5) ; + + ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); + ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ + ret |= dib7000m_write_word(state, 1795, outreg); + ret |= dib7000m_write_word(state, 1805, sram); + + return ret; +} + +static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) +{ + /* by default everything is going to be powered off */ + u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; + + /* now, depending on the requested mode, we power on */ + switch (mode) { + /* power up everything in the demod */ + case DIB7000M_POWER_ALL: + reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; + break; + + /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ + case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ + reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); + break; + + case DIB7000M_POWER_INTERF_ANALOG_AGC: + reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); + reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); + reg_906 &= ~((1 << 0)); + break; + + case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: + reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; + break; + + case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: + reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; + break; + case DIB7000M_POWER_NO: + break; + } + + /* always power down unused parts */ + if (!state->cfg.mobile_mode) + reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); + + /* P_sdio_select_clk = 0 on MC */ + if (state->revision != 0x4000) + reg_906 <<= 1; + + dib7000m_write_word(state, 903, reg_903); + dib7000m_write_word(state, 904, reg_904); + dib7000m_write_word(state, 905, reg_905); + dib7000m_write_word(state, 906, reg_906); + + return 0; +} + +static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) +{ + int ret = 0; + u16 reg_913 = dib7000m_read_word(state, 913), + reg_914 = dib7000m_read_word(state, 914); + + switch (no) { + case DIBX000_SLOW_ADC_ON: + reg_914 |= (1 << 1) | (1 << 0); + ret |= dib7000m_write_word(state, 914, reg_914); + reg_914 &= ~(1 << 1); + break; + + case DIBX000_SLOW_ADC_OFF: + reg_914 |= (1 << 1) | (1 << 0); + break; + + case DIBX000_ADC_ON: + if (state->revision == 0x4000) { // workaround for PA/MA + // power-up ADC + dib7000m_write_word(state, 913, 0); + dib7000m_write_word(state, 914, reg_914 & 0x3); + // power-down bandgag + dib7000m_write_word(state, 913, (1 << 15)); + dib7000m_write_word(state, 914, reg_914 & 0x3); + } + + reg_913 &= 0x0fff; + reg_914 &= 0x0003; + break; + + case DIBX000_ADC_OFF: // leave the VBG voltage on + reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); + reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); + break; + + case DIBX000_VBG_ENABLE: + reg_913 &= ~(1 << 15); + break; + + case DIBX000_VBG_DISABLE: + reg_913 |= (1 << 15); + break; + + default: + break; + } + +// dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); + + ret |= dib7000m_write_word(state, 913, reg_913); + ret |= dib7000m_write_word(state, 914, reg_914); + + return ret; +} + +static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) +{ + struct dib7000m_state *state = demod->demodulator_priv; + u32 timf; + + // store the current bandwidth for later use + state->current_bandwidth = bw_idx; + + if (state->timf == 0) { + dprintk("-D- Using default timf\n"); + timf = state->cfg.bw->timf; + } else { + dprintk("-D- Using updated timf\n"); + timf = state->timf; + } + + timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; + + dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); + dib7000m_write_word(state, 24, (timf ) & 0xffff); + + return 0; +} + +static int dib7000m_sad_calib(struct dib7000m_state *state) +{ +#if 0 + REAL ref,x; +/* external */ + dib7000m_write_word(state, 928, (1 << 14) | (3 << 12) | (524 << 0)); + dib7000m_write_word(state, 929, (1 << 1) | (0 << 0)); + dib7000m_write_word(state, 930, 4096); + msleep(1); + + ref = dib7000m_read_word(state, 934); + x = 0.625/3.3 * (4096.0/ref); + + dprintk("-D- ref: %g = %g (%x) \n", ref, x, (INT) (x * 8192.0) / 2); + + dib7000m_write_word(state, 930, (INT) (x * 8192.0) / 2); + + dib7000m_write_word(state, 928, (0 << 14) | (1 << 12) | (524 << 0)); + + msleep(1); + + ref = dib7000m_read_word(state, 932); + dprintk("-D- wbd voltage: %g = %g\n", ref, ref/4096.0 * 3.3); + msleep(1); + ref = dib7000m_read_word(state, 932); + dprintk("-D- wbd voltage: %g = %g\n", ref, ref/4096.0 * 3.3); + msleep(1); + ref = dib7000m_read_word(state, 932); + dprintk("-D- wbd voltage: %g = %g\n", ref, ref/4096.0 * 3.3); + msleep(1); + ref = dib7000m_read_word(state, 932); + dprintk("-D- wbd voltage: %g = %g\n", ref, ref/4096.0 * 3.3); + msleep(1); + ref = dib7000m_read_word(state, 932); + dprintk("-D- wbd voltage: %g = %g\n", ref, ref/4096.0 * 3.3); +#else + +/* internal */ +// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth + dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); + dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 + + /* do the calibration */ + dib7000m_write_word(state, 929, (1 << 0)); + dib7000m_write_word(state, 929, (0 << 0)); + + msleep(1); +#endif + + return 0; +} + +static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) +{ + dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); + dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); + dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); + dib7000m_write_word(state, 22, bw->ifreq & 0xffff); + + dib7000m_write_word(state, 928, bw->sad_cfg); +} + +static void dib7000m_reset_pll(struct dib7000m_state *state) +{ + const struct dibx000_bandwidth_config *bw = state->cfg.bw; + u16 reg_907,reg_910; + + /* default */ + reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | + (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | + (bw->enable_refdiv << 1) | (0 << 0); + reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; + + // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) + // this is only working only for 30 MHz crystals + if (!state->cfg.quartz_direct) { + reg_910 |= (1 << 5); // forcing the predivider to 1 + + // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) + if(state->cfg.input_clk_is_div_2) + reg_907 |= (16 << 9); + else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary + reg_907 |= (8 << 9); + } else { + reg_907 |= (bw->pll_ratio & 0x3f) << 9; + reg_910 |= (bw->pll_prediv << 5); + } + + dib7000m_write_word(state, 910, reg_910); // pll cfg + dib7000m_write_word(state, 907, reg_907); // clk cfg0 + dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 + + dib7000m_reset_pll_common(state, bw); +} + +static void dib7000mc_reset_pll(struct dib7000m_state *state) +{ + const struct dibx000_bandwidth_config *bw = state->cfg.bw; + + // clk_cfg0 + dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); + + // clk_cfg1 + //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | + dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | + (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | + (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); + + // smpl_cfg + dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); + + dib7000m_reset_pll_common(state, bw); +} + +static int dib7000m_reset_gpio(struct dib7000m_state *st) +{ + /* reset the GPIOs */ + dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", + st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); + + dib7000m_write_word(st, 773, st->cfg.gpio_dir); + dib7000m_write_word(st, 774, st->cfg.gpio_val); + + /* TODO 782 is P_gpio_od */ + + dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); + + dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); + return 0; +} + +static int dib7000m_demod_reset(struct dib7000m_state *state) +{ + dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); + + /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ + dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); + + /* restart all parts */ + dib7000m_write_word(state, 898, 0xffff); + dib7000m_write_word(state, 899, 0xffff); + dib7000m_write_word(state, 900, 0xff0f); + dib7000m_write_word(state, 901, 0xfffc); + + dib7000m_write_word(state, 898, 0); + dib7000m_write_word(state, 899, 0); + dib7000m_write_word(state, 900, 0); + dib7000m_write_word(state, 901, 0); + + if (state->revision == 0x4000) + dib7000m_reset_pll(state); + else + dib7000mc_reset_pll(state); + + if (dib7000m_reset_gpio(state) != 0) + dprintk("-E- GPIO reset was not successful.\n"); + + if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) + dprintk("-E- OUTPUT_MODE could not be resetted.\n"); + + /* unforce divstr regardless whether i2c enumeration was done or not */ + dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); + + dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); + + dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); + dib7000m_sad_calib(state); + dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); + + dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); + + return 0; +} + +static void dib7000m_restart_agc(struct dib7000m_state *state) +{ + // P_restart_iqc & P_restart_agc + dib7000m_write_word(state, 898, 0x0c00); + dib7000m_write_word(state, 898, 0x0000); +} + +static int dib7000m_agc_soft_split(struct dib7000m_state *state) +{ + u16 agc,split_offset; + + if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) + return 0; + + // n_agc_global + agc = dib7000m_read_word(state, 390); + + if (agc > state->current_agc->split.min_thres) + split_offset = state->current_agc->split.min; + else if (agc < state->current_agc->split.max_thres) + split_offset = state->current_agc->split.max; + else + split_offset = state->current_agc->split.max * + (agc - state->current_agc->split.min_thres) / + (state->current_agc->split.max_thres - state->current_agc->split.min_thres); + + dprintk("AGC split_offset: %d\n",split_offset); + + // P_agc_force_split and P_agc_split_offset + return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); +} + +static int dib7000m_update_lna(struct dib7000m_state *state) +{ + int i; + u16 dyn_gain; + + // when there is no LNA to program return immediatly + if (state->cfg.update_lna == NULL) + return 0; + + msleep(60); + for (i = 0; i < 20; i++) { + // read dyn_gain here (because it is demod-dependent and not tuner) + dyn_gain = dib7000m_read_word(state, 390); + + dprintk("agc global: %d\n", dyn_gain); + + if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed + dib7000m_restart_agc(state); + msleep(60); + } else + break; + } + return 0; +} + +static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) +{ + struct dibx000_agc_config *agc = NULL; + int i; + if (state->current_band == band) + return; + state->current_band = band; + + for (i = 0; i < state->cfg.agc_config_count; i++) + if (state->cfg.agc[i].band_caps & band) { + agc = &state->cfg.agc[i]; + break; + } + + if (agc == NULL) { + dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); + return; + } + + state->current_agc = agc; + + /* AGC */ + dib7000m_write_word(state, 72 , agc->setup); + dib7000m_write_word(state, 73 , agc->inv_gain); + dib7000m_write_word(state, 74 , agc->time_stabiliz); + dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); + + // Demod AGC loop configuration + dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); + dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); + + dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", + state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); + + /* AGC continued */ + if (state->wbd_ref != 0) + dib7000m_write_word(state, 102, state->wbd_ref); + else // use default + dib7000m_write_word(state, 102, agc->wbd_ref); + + dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); + dib7000m_write_word(state, 104, agc->agc1_max); + dib7000m_write_word(state, 105, agc->agc1_min); + dib7000m_write_word(state, 106, agc->agc2_max); + dib7000m_write_word(state, 107, agc->agc2_min); + dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); + dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); + dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); + dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); + + if (state->revision > 0x4000) { // settings for the MC + dib7000m_write_word(state, 71, agc->agc1_pt3); +// dprintk("-D- 929: %x %d %d\n", +// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); + dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); + } else { + // wrong default values + u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; + for (i = 0; i < 9; i++) + dib7000m_write_word(state, 88 + i, b[i]); + } +} + +static void dib7000m_update_timf_freq(struct dib7000m_state *state) +{ + u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); + state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); + dib7000m_write_word(state, 23, (u16) (timf >> 16)); + dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); + dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); +} + +static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) +{ + u16 value, est[4]; + + dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); + + /* nfft, guard, qam, alpha */ + dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); + dib7000m_write_word(state, 5, (seq << 4)); + + /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ + value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); + if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) + value |= (ch->vit_code_rate_hp << 1); + else + value |= (ch->vit_code_rate_lp << 1); + dib7000m_write_word(state, 267 + state->reg_offs, value); + + /* offset loop parameters */ + + /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ + dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); + + /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ + dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); + + /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ + dib7000m_write_word(state, 32, (0 << 4) | 0x3); + + /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ + dib7000m_write_word(state, 33, (0 << 4) | 0x5); + + /* P_dvsy_sync_wait */ + switch (ch->nfft) { + case 1: value = 256; break; + case 2: value = 128; break; + case 0: + default: value = 64; break; + } + value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin + value <<= 4; + + /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ + /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ + if (ch->intlv_native || state->revision > 0x4000) + value |= (1 << 2) | (2 << 0); + else + value |= 0; + dib7000m_write_word(state, 266 + state->reg_offs, value); + + /* channel estimation fine configuration */ + switch (ch->nqam) { + case 2: + est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ + est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ + break; + case 1: + est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ + est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ + break; + default: + est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ + est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ + est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ + break; + } + for (value = 0; value < 4; value++) + dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); + + // set power-up level: interf+analog+AGC + dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); + dib7000m_set_adc_state(state, DIBX000_ADC_ON); + + msleep(7); + + //AGC initialization + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 1); + + dib7000m_restart_agc(state); + + // wait AGC rough lock time + msleep(5); + + dib7000m_update_lna(state); + dib7000m_agc_soft_split(state); + + // wait AGC accurate lock time + msleep(7); + + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 0); + + // set power-up level: autosearch + dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); +} + +static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000m_state *state = demod->demodulator_priv; + struct dibx000_ofdm_channel auto_ch; + int ret = 0; + u32 value; + + INIT_OFDM_CHANNEL(&auto_ch); + auto_ch.RF_kHz = ch->RF_kHz; + auto_ch.Bw = ch->Bw; + auto_ch.nqam = 2; + auto_ch.guard = 0; + auto_ch.nfft = 1; + auto_ch.vit_alpha = 1; + auto_ch.vit_select_hp = 1; + auto_ch.vit_code_rate_hp = 2; + auto_ch.vit_code_rate_lp = 3; + auto_ch.vit_hrch = 0; + auto_ch.intlv_native = 1; + + dib7000m_set_channel(state, &auto_ch, 7); + + // always use the setting for 8MHz here lock_time for 7,6 MHz are longer + value = 30 * state->cfg.bw->internal; + ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time + ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time + value = 100 * state->cfg.bw->internal; + ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time + ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time + value = 500 * state->cfg.bw->internal; + ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time + ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time + + // start search + value = dib7000m_read_word(state, 0); + ret |= dib7000m_write_word(state, 0, value | (1 << 9)); + + /* clear n_irq_pending */ + if (state->revision == 0x4000) + dib7000m_write_word(state, 1793, 0); + else + dib7000m_read_word(state, 537); + + ret |= dib7000m_write_word(state, 0, (u16) value); + + return ret; +} + +static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) +{ + u16 irq_pending = dib7000m_read_word(state, reg); + + if (irq_pending & 0x1) { // failed + dprintk("#\n"); + return 1; + } + + if (irq_pending & 0x2) { // succeeded + dprintk("!\n"); + return 2; + } + return 0; // still pending +} + +static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) +{ + struct dib7000m_state *state = demod->demodulator_priv; + if (state->revision == 0x4000) + return dib7000m_autosearch_irq(state, 1793); + else + return dib7000m_autosearch_irq(state, 537); +} + +static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000m_state *state = demod->demodulator_priv; + int ret = 0; + u16 value; + + // we are already tuned - just resuming from suspend + if (ch != NULL) + dib7000m_set_channel(state, ch, 0); + else + return -EINVAL; + + // restart demod + ret |= dib7000m_write_word(state, 898, 0x4000); + ret |= dib7000m_write_word(state, 898, 0x0000); + msleep(45); + + ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); + /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ + ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); + + // never achieved a lock with that bandwidth so far - wait for timfreq to update + if (state->timf == 0) + msleep(200); + + //dump_reg(state); + /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ + value = (6 << 8) | 0x80; + switch (ch->nfft) { + case 0: value |= (7 << 12); break; + case 1: value |= (9 << 12); break; + case 2: value |= (8 << 12); break; + } + ret |= dib7000m_write_word(state, 26, value); + + /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ + value = (0 << 4); + switch (ch->nfft) { + case 0: value |= 0x6; break; + case 1: value |= 0x8; break; + case 2: value |= 0x7; break; + } + ret |= dib7000m_write_word(state, 32, value); + + /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ + value = (0 << 4); + switch (ch->nfft) { + case 0: value |= 0x6; break; + case 1: value |= 0x8; break; + case 2: value |= 0x7; break; + } + ret |= dib7000m_write_word(state, 33, value); + + // we achieved a lock - it's time to update the osc freq + if ((dib7000m_read_word(state, 535) >> 6) & 0x1) + dib7000m_update_timf_freq(state); + + return ret; +} + +static int dib7000m_init(struct dvb_frontend *demod) +{ + struct dib7000m_state *state = demod->demodulator_priv; + int ret = 0; + u8 o = state->reg_offs; + + dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); + + if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) + dprintk("-E- could not start Slow ADC\n"); + + if (state->cfg.dvbt_mode) + dib7000m_write_word(state, 1796, 0x0); // select DVB-T output + + if (state->cfg.mobile_mode) + ret |= dib7000m_write_word(state, 261 + o, 2); + else + ret |= dib7000m_write_word(state, 224 + o, 1); + + ret |= dib7000m_write_word(state, 173 + o, 0); + ret |= dib7000m_write_word(state, 174 + o, 0); + ret |= dib7000m_write_word(state, 175 + o, 0); + ret |= dib7000m_write_word(state, 176 + o, 0); + ret |= dib7000m_write_word(state, 177 + o, 0); + ret |= dib7000m_write_word(state, 178 + o, 0); + ret |= dib7000m_write_word(state, 179 + o, 0); + ret |= dib7000m_write_word(state, 180 + o, 0); + + // P_corm_thres Lock algorithms configuration + ret |= dib7000m_write_word(state, 26, 0x6680); + + // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on + ret |= dib7000m_write_word(state, 170 + o, 0x0410); + // P_fft_nb_to_cut + ret |= dib7000m_write_word(state, 182 + o, 8192); + // P_pha3_thres + ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); + // P_cti_use_cpe, P_cti_use_prog + ret |= dib7000m_write_word(state, 196 + o, 0); + // P_cspu_regul, P_cspu_win_cut + ret |= dib7000m_write_word(state, 205 + o, 0x200f); + // P_adp_regul_cnt + ret |= dib7000m_write_word(state, 214 + o, 0x023d); + // P_adp_noise_cnt + ret |= dib7000m_write_word(state, 215 + o, 0x00a4); + // P_adp_regul_ext + ret |= dib7000m_write_word(state, 216 + o, 0x00a4); + // P_adp_noise_ext + ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); + // P_adp_fil + ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); + + // P_2d_byp_ti_num + ret |= dib7000m_write_word(state, 226 + o, 0); + + // P_fec_* + ret |= dib7000m_write_word(state, 281 + o, 0x0010); + // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard + ret |= dib7000m_write_word(state, 294 + o,0x0062); + + // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... + if(state->cfg.tuner_is_baseband) + ret |= dib7000m_write_word(state, 36, 0x0755); + else + ret |= dib7000m_write_word(state, 36, 0x1f55); + + // auto search configuration + ret |= dib7000m_write_word(state, 2, 0x0004); + ret |= dib7000m_write_word(state, 3, 0x1000); + ret |= dib7000m_write_word(state, 4, 0x0814); + ret |= dib7000m_write_word(state, 6, 0x001b); + ret |= dib7000m_write_word(state, 7, 0x7740); + ret |= dib7000m_write_word(state, 8, 0x005b); + ret |= dib7000m_write_word(state, 9, 0x8d80); + ret |= dib7000m_write_word(state, 10, 0x01c9); + ret |= dib7000m_write_word(state, 11, 0xc380); + ret |= dib7000m_write_word(state, 12, 0x0000); + ret |= dib7000m_write_word(state, 13, 0x0080); + ret |= dib7000m_write_word(state, 14, 0x0000); + ret |= dib7000m_write_word(state, 15, 0x0090); + ret |= dib7000m_write_word(state, 16, 0x0001); + ret |= dib7000m_write_word(state, 17, 0xd4c0); + ret |= dib7000m_write_word(state, 263 + o,0x0001); + + // P_divclksel=3 P_divbitsel=1 + if (state->revision == 0x4000) + dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); + else + dib7000m_write_word(state, 909, (3 << 4) | 1); + + // Tuner IO bank: max drive (14mA) + ret |= dib7000m_write_word(state, 912 ,0x2c8a); + + ret |= dib7000m_write_word(state, 1817, 1); + + return ret; +} + +static int dib7000m_sleep(struct dvb_frontend *demod) +{ + struct dib7000m_state *st = demod->demodulator_priv; + dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); + return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | + dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | + dib7000m_set_adc_state(st, DIBX000_ADC_OFF); +} + +static int dib7000m_identify(struct dib7000m_state *state) +{ + u16 value; + if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { + dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); + return -EREMOTEIO; + } + + state->revision = dib7000m_read_word(state, 897); + if (state->revision != 0x4000 && + state->revision != 0x4001 && + state->revision != 0x4002) { + dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); + return -EREMOTEIO; + } + + /* protect this driver to be used with 7000PC */ + if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { + dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); + return -EREMOTEIO; + } + + switch (state->revision) { + case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; + case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; + case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; + } + + return 0; +} + static int dib7000m_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) @@ -82,7 +949,7 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe, fep->u.ofdm.bandwidth = state->current_bandwidth; - switch ((tps >> 8) & 0x2) { + switch ((tps >> 8) & 0x3) { case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ @@ -133,13 +1000,48 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe, static int dib7000m_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) { - return 0; + struct dib7000m_state *state = fe->demodulator_priv; + struct dibx000_ofdm_channel ch; + + INIT_OFDM_CHANNEL(&ch); + FEP2DIB(fep,&ch); + + state->current_bandwidth = fep->u.ofdm.bandwidth; + dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); + + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, fep); + + if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || + fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || + fep->u.ofdm.constellation == QAM_AUTO || + fep->u.ofdm.code_rate_HP == FEC_AUTO) { + int i = 800, found; + + dib7000m_autosearch_start(fe, &ch); + do { + msleep(1); + found = dib7000m_autosearch_is_irq(fe); + } while (found == 0 && i--); + + dprintk("autosearch returns: %d\n",found); + if (found == 0 || found == 1) + return 0; // no channel found + + dib7000m_get_frontend(fe, fep); + FEP2DIB(fep, &ch); + } + + /* make this a config parameter */ + dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); + + return dib7000m_tune(fe, &ch); } static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) { struct dib7000m_state *state = fe->demodulator_priv; - u16 lock = dib7000m_read_word(state, 509); + u16 lock = dib7000m_read_word(state, 535); *stat = 0; @@ -191,18 +1093,100 @@ static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fro return 0; } -static int dib7000m_init(struct dvb_frontend *fe) +static void dib7000m_release(struct dvb_frontend *demod) { - return 0; + struct dib7000m_state *st = demod->demodulator_priv; + dibx000_exit_i2c_master(&st->i2c_master); + kfree(st); +} + +struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) +{ + struct dib7000m_state *st = demod->demodulator_priv; + return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); } +EXPORT_SYMBOL(dib7000m_get_i2c_master); -static int dib7000m_sleep(struct dvb_frontend *fe) +int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) { + struct dib7000m_state st = { .i2c_adap = i2c }; + int k = 0; + u8 new_addr = 0; + + for (k = no_of_demods-1; k >= 0; k--) { + st.cfg = cfg[k]; + + /* designated i2c address */ + new_addr = (0x40 + k) << 1; + st.i2c_addr = new_addr; + if (dib7000m_identify(&st) != 0) { + st.i2c_addr = default_addr; + if (dib7000m_identify(&st) != 0) { + dprintk("DiB7000M #%d: not identified\n", k); + return -EIO; + } + } + + /* start diversity to pull_down div_str - just for i2c-enumeration */ + dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); + + dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output + + /* set new i2c address and force divstart */ + dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); + + dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); + } + + for (k = 0; k < no_of_demods; k++) { + st.cfg = cfg[k]; + st.i2c_addr = (0x40 + k) << 1; + + // unforce divstr + dib7000m_write_word(&st,1794, st.i2c_addr << 2); + + /* deactivate div - it was just for i2c-enumeration */ + dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); + } + return 0; } +EXPORT_SYMBOL(dib7000m_i2c_enumeration); -static void dib7000m_release(struct dvb_frontend *fe) -{ } +static struct dvb_frontend_ops dib7000m_ops; +struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) +{ + struct dvb_frontend *demod; + struct dib7000m_state *st; + st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); + if (st == NULL) + return NULL; + + memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); + st->i2c_adap = i2c_adap; + st->i2c_addr = i2c_addr; + + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); + + if (dib7000m_identify(st) != 0) + goto error; + + if (st->revision == 0x4000) + dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); + else + dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); + + dib7000m_demod_reset(st); + + return demod; + +error: + kfree(st); + return NULL; +} +EXPORT_SYMBOL(dib7000m_attach); static struct dvb_frontend_ops dib7000m_ops = { .info = { diff --git a/linux/drivers/media/dvb/frontends/dib7000m.h b/linux/drivers/media/dvb/frontends/dib7000m.h index 45990e3a5..597e9cc2d 100644 --- a/linux/drivers/media/dvb/frontends/dib7000m.h +++ b/linux/drivers/media/dvb/frontends/dib7000m.h @@ -32,12 +32,13 @@ struct dib7000m_config { u8 quartz_direct; u8 input_clk_is_div_2; + + int (*agc_control) (struct dvb_frontend *, u8 before); }; #define DEFAULT_DIB7000M_I2C_ADDRESS 18 -extern int dib7000m_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr , u8 do_i2c_enum, struct dib7000m_config[], struct dvb_frontend*[]); - +extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); /* TODO diff --git a/linux/drivers/media/dvb/frontends/dib7000p.c b/linux/drivers/media/dvb/frontends/dib7000p.c new file mode 100644 index 000000000..02ccd2f79 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/dib7000p.c @@ -0,0 +1,1044 @@ +/* + * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC). + * + * Copyright (C) 2005-6 DiBcom (http://www.dibcom.fr/) + * + * 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. + */ +#include <linux/kernel.h> +#include <linux/i2c.h> + +#include "dvb_frontend.h" + +#include "dib7000p.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); + +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P:"); printk(args); } } while (0) + +struct dib7000p_state { + struct dvb_frontend demod; + struct dib7000p_config cfg; + + u8 i2c_addr; + struct i2c_adapter *i2c_adap; + + struct dibx000_i2c_master i2c_master; + + u16 wbd_ref; + + u8 current_band; + fe_bandwidth_t current_bandwidth; + struct dibx000_agc_config *current_agc; + u32 timf; + + u16 gpio_dir; + u16 gpio_val; +}; + +enum dib7000p_power_mode { + DIB7000P_POWER_ALL = 0, + DIB7000P_POWER_INTERFACE_ONLY, +}; + +static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg) +{ + u8 wb[2] = { reg >> 8, reg & 0xff }; + u8 rb[2]; + struct i2c_msg msg[2] = { + { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + }; + + if (i2c_transfer(state->i2c_adap, msg, 2) != 2) + dprintk("i2c read error on %d\n",reg); + + return (rb[0] << 8) | rb[1]; +} + +static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val) +{ + u8 b[4] = { + (reg >> 8) & 0xff, reg & 0xff, + (val >> 8) & 0xff, val & 0xff, + }; + struct i2c_msg msg = { + .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 + }; + return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; +} +static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode) +{ + int ret = 0; + u16 outreg, fifo_threshold, smo_mode; + + outreg = 0; + fifo_threshold = 1792; + smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1); + + dprintk("-I- Setting output mode for demod %p to %d\n", + &state->demod, mode); + + switch (mode) { + case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock + outreg = (1 << 10); /* 0x0400 */ + break; + case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock + outreg = (1 << 10) | (1 << 6); /* 0x0440 */ + break; + case OUTMODE_MPEG2_SERIAL: // STBs with serial input + outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */ + break; + case OUTMODE_DIVERSITY: + if (state->cfg.hostbus_diversity) + outreg = (1 << 10) | (4 << 6); /* 0x0500 */ + else + outreg = (1 << 11); + break; + case OUTMODE_MPEG2_FIFO: // e.g. USB feeding + smo_mode |= (3 << 1); + fifo_threshold = 512; + outreg = (1 << 10) | (5 << 6); + break; + case OUTMODE_HIGH_Z: // disable + outreg = 0; + break; + default: + dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); + break; + } + + if (state->cfg.output_mpeg2_in_188_bytes) + smo_mode |= (1 << 5) ; + + ret |= dib7000p_write_word(state, 235, smo_mode); + ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */ + ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */ + + return ret; +} + +static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode) +{ + /* by default everything is powered off */ + u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, + reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff); + + /* now, depending on the requested mode, we power on */ + switch (mode) { + /* power up everything in the demod */ + case DIB7000P_POWER_ALL: + reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff; + break; + /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ + case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */ + reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10)); + break; +/* TODO following stuff is just converted from the dib7000-driver - check when is used what */ +#if 0 + case DIB7000_POWER_LEVEL_INTERF_ANALOG_AGC: + /* dem, cfg, iqc, sad, agc */ + reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9)); + /* sdio, i2c, gpio */ + reg_1280 &= ~((1 << 13) | (1 << 12) | (1 << 10)); + break; + case DIB7000_POWER_LEVEL_DOWN_COR4_DINTLV_ICIRM_EQUAL_CFROD: + reg_774 = 0; + /* power down: cor4 dintlv equal */ + reg_775 = (1 << 15) | (1 << 6) | (1 << 5); + reg_776 = 0; + reg_899 = 0; + reg_1280 &= 0x01ff; + break; + case DIB7000_POWER_LEVEL_DOWN_COR4_CRY_ESRAM_MOUT_NUD: + reg_774 = 0; + /* power down: cor4 */ + reg_775 = (1 << 15); + /* nud */ + reg_776 = (1 << 0); + reg_899 = 0; + reg_1280 &= 0x01ff; + break; +#endif + } + + dib7000p_write_word(state, 774, reg_774); + dib7000p_write_word(state, 775, reg_775); + dib7000p_write_word(state, 776, reg_776); + dib7000p_write_word(state, 899, reg_899); + dib7000p_write_word(state, 1280, reg_1280); + + return 0; +} + +static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no) +{ + u16 reg_908 = dib7000p_read_word(state, 908), + reg_909 = dib7000p_read_word(state, 909); + + switch (no) { + case DIBX000_SLOW_ADC_ON: + reg_909 |= (1 << 1) | (1 << 0); + dib7000p_write_word(state, 909, reg_909); + reg_909 &= ~(1 << 1); + break; + + case DIBX000_SLOW_ADC_OFF: + reg_909 |= (1 << 1) | (1 << 0); + break; + + case DIBX000_ADC_ON: + reg_908 &= 0x0fff; + reg_909 &= 0x0003; + break; + + case DIBX000_ADC_OFF: // leave the VBG voltage on + reg_908 |= (1 << 14) | (1 << 13) | (1 << 12); + reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); + break; + + case DIBX000_VBG_ENABLE: + reg_908 &= ~(1 << 15); + break; + + case DIBX000_VBG_DISABLE: + reg_908 |= (1 << 15); + break; + + default: + break; + } + +// dprintk("908: %x, 909: %x\n", reg_908, reg_909); + + dib7000p_write_word(state, 908, reg_908); + dib7000p_write_word(state, 909, reg_909); +} + +static int dib7000p_set_bandwidth(struct dvb_frontend *demod, u8 BW_Idx) +{ + struct dib7000p_state *state = demod->demodulator_priv; + u32 timf; + + // store the current bandwidth for later use + state->current_bandwidth = BW_Idx; + + if (state->timf == 0) { + dprintk("-D- Using default timf\n"); + timf = state->cfg.bw->timf; + } else { + dprintk("-D- Using updated timf\n"); + timf = state->timf; + } + + timf = timf * (BW_INDEX_TO_KHZ(BW_Idx) / 100) / 80; + + dprintk("timf: %d\n",timf); + + dib7000p_write_word(state, 23, (timf >> 16) & 0xffff); + dib7000p_write_word(state, 24, (timf ) & 0xffff); + + return 0; +} + +static int dib7000p_sad_calib(struct dib7000p_state *state) +{ +/* internal */ +// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth + dib7000p_write_word(state, 73, (0 << 1) | (0 << 0)); + dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096 + + /* do the calibration */ + dib7000p_write_word(state, 73, (1 << 0)); + dib7000p_write_word(state, 73, (0 << 0)); + + msleep(1); + + return 0; +} + +static void dib7000p_reset_pll(struct dib7000p_state *state) +{ + struct dibx000_bandwidth_config *bw = &state->cfg.bw[0]; + + dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset); + dib7000p_write_word(state, 900, ((bw->pll_ratio & 0x3f) << 9) | (bw->pll_bypass << 15) | (bw->modulo << 7) | (bw->ADClkSrc << 6) | + (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0)); + + dib7000p_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); + dib7000p_write_word(state, 19, (bw->internal*1000 ) & 0xffff); + dib7000p_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); + dib7000p_write_word(state, 22, (bw->ifreq ) & 0xffff); + + dib7000p_write_word(state, 72, bw->sad_cfg); +} + +static int dib7000p_reset_gpio(struct dib7000p_state *st) +{ + /* reset the GPIOs */ + dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos); + + dib7000p_write_word(st, 1029, st->gpio_dir); + dib7000p_write_word(st, 1030, st->gpio_val); + + /* TODO 1031 is P_gpio_od */ + + dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos); + + dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div); + return 0; +} + +static int dib7000p_demod_reset(struct dib7000p_state *state) +{ + dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); + + dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE); + + /* restart all parts */ + dib7000p_write_word(state, 770, 0xffff); + dib7000p_write_word(state, 771, 0xffff); + dib7000p_write_word(state, 772, 0x001f); + dib7000p_write_word(state, 898, 0x0003); + /* except i2c, sdio, gpio - control interfaces */ + dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) ); + + dib7000p_write_word(state, 770, 0); + dib7000p_write_word(state, 771, 0); + dib7000p_write_word(state, 772, 0); + dib7000p_write_word(state, 898, 0); + dib7000p_write_word(state, 1280, 0); + + /* default */ + dib7000p_reset_pll(state); + + if (dib7000p_reset_gpio(state) != 0) + dprintk("-E- GPIO reset was not successful.\n"); + + if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0) + dprintk("-E- OUTPUT_MODE could not be resetted.\n"); + + /* unforce divstr regardless whether i2c enumeration was done or not */ + dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) ); + + dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); + + return 0; +} + +static void dib7000p_restart_agc(struct dib7000p_state *state) +{ + // P_restart_iqc & P_restart_agc + dib7000p_write_word(state, 770, 0x0c00); + dib7000p_write_word(state, 770, 0x0000); +} + +static void dib7000p_update_lna(struct dib7000p_state *state) +{ + int i; + u16 dyn_gain; + + // when there is no LNA to program return immediatly + if (state->cfg.update_lna == NULL) + return; + + for (i = 0; i < 5; i++) { + // read dyn_gain here (because it is demod-dependent and not tuner) + dyn_gain = dib7000p_read_word(state, 394); + + if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed + dib7000p_restart_agc(state); + msleep(5); + } else + break; + } +} + +static void dib7000p_pll_clk_cfg(struct dib7000p_state *state) +{ + u16 tmp = 0; + tmp = dib7000p_read_word(state, 903); + dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll + tmp = dib7000p_read_word(state, 900); + dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock +} + +static void dib7000p_update_timf_freq(struct dib7000p_state *state) +{ + u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428); + state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); + dib7000p_write_word(state, 23, (u16) (timf >> 16)); + dib7000p_write_word(state, 24, (u16) (timf & 0xffff)); + dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); +} + +static void dib7000p_set_channel(struct dib7000p_state *state, struct dibx000_ofdm_channel *ch, u8 seq) +{ + u16 tmp, est[4]; // reg_26, reg_32, reg_33, reg_187, reg_188, reg_189, reg_190, reg_207, reg_208; + + /* nfft, guard, qam, alpha */ + dib7000p_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); + dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */ + + /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ + tmp = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); + if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) + tmp |= (ch->vit_code_rate_hp << 1); + else + tmp |= (ch->vit_code_rate_lp << 1); + dib7000p_write_word(state, 208, tmp); + + /* P_dvsy_sync_wait */ + switch (ch->nfft) { + case 1: tmp = 256; break; + case 2: tmp = 128; break; + case 0: + default: tmp = 64; break; + } + tmp *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin + tmp <<= 4; + + /* deactive the possibility of diversity reception if extended interleave */ + /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ + if (ch->intlv_native || ch->nfft == 1) + tmp |= (1 << 2) | (2 << 0); + dib7000p_write_word(state, 207, tmp); + + dib7000p_write_word(state, 26, 0x6680); // timf(6xxx) + dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073 + dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3) + dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5) + + /* channel estimation fine configuration */ + switch (ch->nqam) { + case 2: + est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ + est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ + break; + case 1: + est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ + est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ + est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ + est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ + break; + default: + est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ + est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ + est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ + est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ + break; + } + for (tmp = 0; tmp < 4; tmp++) + dib7000p_write_word(state, 187 + tmp, est[tmp]); + + // set power-up level: interf+analog+AGC + dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); + dib7000p_set_adc_state(state, DIBX000_ADC_ON); + dib7000p_pll_clk_cfg(state); + msleep(7); + + // AGC initialization + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 1); + + dib7000p_restart_agc(state); + + // wait AGC rough lock time + msleep(5); + + dib7000p_update_lna(state); + + // wait AGC accurate lock time + msleep(7); + if (state->cfg.agc_control) + state->cfg.agc_control(&state->demod, 0); +} + +static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000p_state *state = demod->demodulator_priv; + struct dibx000_ofdm_channel auto_ch; + u32 value; + + INIT_OFDM_CHANNEL(&auto_ch); + auto_ch.RF_kHz = ch->RF_kHz; + auto_ch.Bw = ch->Bw; + auto_ch.nqam = 2; + auto_ch.guard = 0; + auto_ch.nfft = 1; + auto_ch.vit_alpha = 1; + auto_ch.vit_select_hp = 1; + auto_ch.vit_code_rate_hp = 2; + auto_ch.vit_code_rate_lp = 3; + auto_ch.vit_hrch = 0; + auto_ch.intlv_native = 1; + + dib7000p_set_channel(state, &auto_ch, 7); + + // always use the setting for 8MHz here lock_time for 7,6 MHz are longer + value = 30 * state->cfg.bw->internal; + dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time + dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time + value = 100 * state->cfg.bw->internal; + dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time + dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time + value = 500 * state->cfg.bw->internal; + dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time + dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time + + value = dib7000p_read_word(state, 0); + dib7000p_write_word(state, 0, (1 << 9) | value); + dib7000p_read_word(state, 1284); + dib7000p_write_word(state, 0, (u16) value); + + return 0; +} + +static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod) +{ + struct dib7000p_state *state = demod->demodulator_priv; + u16 irq_pending = dib7000p_read_word(state, 1284); + + if (irq_pending & 0x1) // failed + return 1; + + if (irq_pending & 0x2) // succeeded + return 2; + + return 0; // still pending +} + +static int dib7000p_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) +{ + struct dib7000p_state *state = demod->demodulator_priv; + u16 tmp = 0; + + if (ch != NULL) + dib7000p_set_channel(state, ch, 0); + else + return -EINVAL; + + // restart demod + dib7000p_write_word(state, 770, 0x4000); + dib7000p_write_word(state, 770, 0x0000); + msleep(45); + + /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ + dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); + + // never achieved a lock with that bandwidth so far - wait for osc-freq to update + if (state->timf == 0) + msleep(200); + + /* offset loop parameters */ + + /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ + tmp = (6 << 8) | 0x80; + switch (ch->nfft) { + case 0: tmp |= (7 << 12); break; + case 1: tmp |= (9 << 12); break; + case 2: tmp |= (8 << 12); break; + } + dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */ + + /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ + tmp = (0 << 4); + switch (ch->nfft) { + case 0: tmp |= 0x6; break; + case 1: tmp |= 0x8; break; + case 2: tmp |= 0x7; break; + } + dib7000p_write_word(state, 32, tmp); + + /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ + tmp = (0 << 4); + switch (ch->nfft) { + case 0: tmp |= 0x6; break; + case 1: tmp |= 0x8; break; + case 2: tmp |= 0x7; break; + } + dib7000p_write_word(state, 33, tmp); + + tmp = dib7000p_read_word(state,509); + if (!((tmp >> 6) & 0x1)) { + /* restart the fec */ + tmp = dib7000p_read_word(state,771); + dib7000p_write_word(state, 771, tmp | (1 << 1)); + dib7000p_write_word(state, 771, tmp); + msleep(10); + tmp = dib7000p_read_word(state,509); + } + + // we achieved a lock - it's time to update the osc freq + if ((tmp >> 6) & 0x1) + dib7000p_update_timf_freq(state); + + return 0; +} + +static int dib7000p_init(struct dvb_frontend *demod) +{ + struct dibx000_agc_config *agc; + struct dib7000p_state *state = demod->demodulator_priv; + int ret = 0; + + // Demodulator default configuration + agc = state->cfg.agc; + + dib7000p_set_power_mode(state, DIB7000P_POWER_ALL); + dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON); + + /* AGC */ + ret |= dib7000p_write_word(state, 75 , agc->setup ); + ret |= dib7000p_write_word(state, 76 , agc->inv_gain ); + ret |= dib7000p_write_word(state, 77 , agc->time_stabiliz ); + ret |= dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock); + + // Demod AGC loop configuration + ret |= dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp); + ret |= dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp); + + /* AGC continued */ + dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", + state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); + + if (state->wbd_ref != 0) + ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref); + else + ret |= dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref); + + ret |= dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); + + ret |= dib7000p_write_word(state, 107, agc->agc1_max); + ret |= dib7000p_write_word(state, 108, agc->agc1_min); + ret |= dib7000p_write_word(state, 109, agc->agc2_max); + ret |= dib7000p_write_word(state, 110, agc->agc2_min); + ret |= dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); + ret |= dib7000p_write_word(state, 112, agc->agc1_pt3); + ret |= dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); + ret |= dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); + ret |= dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); + + /* disable power smoothing */ + ret |= dib7000p_write_word(state, 145, 0); + ret |= dib7000p_write_word(state, 146, 0); + ret |= dib7000p_write_word(state, 147, 0); + ret |= dib7000p_write_word(state, 148, 0); + ret |= dib7000p_write_word(state, 149, 0); + ret |= dib7000p_write_word(state, 150, 0); + ret |= dib7000p_write_word(state, 151, 0); + ret |= dib7000p_write_word(state, 152, 0); + + // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26 + ret |= dib7000p_write_word(state, 26 ,0x6680); + + // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16 + ret |= dib7000p_write_word(state, 142,0x0410); + // P_fft_freq_dir=1, P_fft_nb_to_cut=0 + ret |= dib7000p_write_word(state, 154,1 << 13); + // P_pha3_thres, default 0x3000 + ret |= dib7000p_write_word(state, 168,0x0ccd); + // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010 + //ret |= dib7000p_write_word(state, 169,0x0010); + // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005 + ret |= dib7000p_write_word(state, 183,0x200f); + // P_adp_regul_cnt=573, default: 410 + ret |= dib7000p_write_word(state, 187,0x023d); + // P_adp_noise_cnt= + ret |= dib7000p_write_word(state, 188,0x00a4); + // P_adp_regul_ext + ret |= dib7000p_write_word(state, 189,0x00a4); + // P_adp_noise_ext + ret |= dib7000p_write_word(state, 190,0x7ff0); + // P_adp_fil + ret |= dib7000p_write_word(state, 191,0x3ccc); + + ret |= dib7000p_write_word(state, 222,0x0010); + // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard + ret |= dib7000p_write_word(state, 235,0x0062); + + // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ... + if(state->cfg.tuner_is_baseband) + ret |= dib7000p_write_word(state, 36,0x0755); + else + ret |= dib7000p_write_word(state, 36,0x1f55); + + // auto search configuration + ret |= dib7000p_write_word(state, 2 ,0x0004); + ret |= dib7000p_write_word(state, 3 ,0x1000); + + /* Equal Lock */ + ret |= dib7000p_write_word(state, 4 ,0x0814); + + ret |= dib7000p_write_word(state, 6 ,0x001b); + ret |= dib7000p_write_word(state, 7 ,0x7740); + ret |= dib7000p_write_word(state, 8 ,0x005b); + ret |= dib7000p_write_word(state, 9 ,0x8d80); + ret |= dib7000p_write_word(state, 10 ,0x01c9); + ret |= dib7000p_write_word(state, 11 ,0xc380); + ret |= dib7000p_write_word(state, 12 ,0x0000); + ret |= dib7000p_write_word(state, 13 ,0x0080); + ret |= dib7000p_write_word(state, 14 ,0x0000); + ret |= dib7000p_write_word(state, 15 ,0x0090); + ret |= dib7000p_write_word(state, 16 ,0x0001); + ret |= dib7000p_write_word(state, 17 ,0xd4c0); + + // P_clk_cfg1 + ret |= dib7000p_write_word(state, 901, 0x0006); + + // P_divclksel=3 P_divbitsel=1 + ret |= dib7000p_write_word(state, 902, (3 << 10) | (1 << 6)); + + // Tuner IO bank: max drive (14mA) + divout pads max drive + ret |= dib7000p_write_word(state, 905, 0x2c8e); + + ret |= dib7000p_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); + dib7000p_sad_calib(state); + + return ret; +} + +static int dib7000p_sleep(struct dvb_frontend *demod) +{ + struct dib7000p_state *state = demod->demodulator_priv; + return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY); +} + +static int dib7000p_identify(struct dib7000p_state *st) +{ + u16 value; + dprintk("-I- DiB7000PC: checking demod on I2C address: %d (%x)\n", + st->i2c_addr, st->i2c_addr); + + if ((value = dib7000p_read_word(st, 768)) != 0x01b3) { + dprintk("-E- DiB7000PC: wrong Vendor ID (read=0x%x)\n",value); + return -EREMOTEIO; + } + + if ((value = dib7000p_read_word(st, 769)) != 0x4000) { + dprintk("-E- DiB7000PC: wrong Device ID (%x)\n",value); + return -EREMOTEIO; + } + + return 0; +} + + +static int dib7000p_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 tps = dib7000p_read_word(state,463); + + fep->inversion = INVERSION_AUTO; + + fep->u.ofdm.bandwidth = state->current_bandwidth; + + switch ((tps >> 8) & 0x3) { + case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; + case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; + /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */ + } + + switch (tps & 0x3) { + case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; + case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; + case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; + case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; + } + + switch ((tps >> 14) & 0x3) { + case 0: fep->u.ofdm.constellation = QPSK; break; + case 1: fep->u.ofdm.constellation = QAM_16; break; + case 2: + default: fep->u.ofdm.constellation = QAM_64; break; + } + + /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ + /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */ + + fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; + switch ((tps >> 5) & 0x7) { + case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; + + } + + switch ((tps >> 2) & 0x7) { + case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; + } + + /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */ + + return 0; +} + +static int dib7000p_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct dib7000p_state *state = fe->demodulator_priv; + struct dibx000_ofdm_channel ch; + + INIT_OFDM_CHANNEL(&ch); + FEP2DIB(fep,&ch); + + state->current_bandwidth = fep->u.ofdm.bandwidth; + dib7000p_set_bandwidth(fe, fep->u.ofdm.bandwidth); + + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe, fep); + + if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || + fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || + fep->u.ofdm.constellation == QAM_AUTO || + fep->u.ofdm.code_rate_HP == FEC_AUTO) { + int i = 800, found; + + dib7000p_autosearch_start(fe, &ch); + do { + msleep(1); + found = dib7000p_autosearch_is_irq(fe); + } while (found == 0 && i--); + + dprintk("autosearch returns: %d\n",found); + if (found == 0 || found == 1) + return 0; // no channel found + + dib7000p_get_frontend(fe, fep); + FEP2DIB(fep, &ch); + } + + /* make this a config parameter */ + dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO); + + return dib7000p_tune(fe, &ch); +} + +static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 lock = dib7000p_read_word(state, 509); + + *stat = 0; + + if (lock & 0x8000) + *stat |= FE_HAS_SIGNAL; + if (lock & 0x3000) + *stat |= FE_HAS_CARRIER; + if (lock & 0x0100) + *stat |= FE_HAS_VITERBI; + if (lock & 0x0010) + *stat |= FE_HAS_SYNC; + if (lock & 0x0008) + *stat |= FE_HAS_LOCK; + + return 0; +} + +static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + struct dib7000p_state *state = fe->demodulator_priv; + *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501); + return 0; +} + +static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) +{ + struct dib7000p_state *state = fe->demodulator_priv; + *unc = dib7000p_read_word(state, 506); + return 0; +} + +static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct dib7000p_state *state = fe->demodulator_priv; + u16 val = dib7000p_read_word(state, 394); + *strength = 65535 - val; + return 0; +} + +static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr) +{ + *snr = 0x0000; + return 0; +} + +static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 1000; + return 0; +} + +static void dib7000p_release(struct dvb_frontend *demod) +{ + struct dib7000p_state *st = demod->demodulator_priv; + dibx000_exit_i2c_master(&st->i2c_master); + kfree(st); +} + +int dib7000pc_detection(struct i2c_adapter *i2c_adap) +{ + u8 tx[2], rx[2]; + struct i2c_msg msg[2] = { + { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 }, + { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 }, + }; + + tx[0] = 0x03; + tx[1] = 0x00; + + if (i2c_transfer(i2c_adap, msg, 2) == 2) + if (rx[0] == 0x01 && rx[1] == 0xb3) { + dprintk("-D- DiB7000PC detected\n"); + return 1; + } + + msg[0].addr = msg[1].addr = 0x40; + + if (i2c_transfer(i2c_adap, msg, 2) == 2) + if (rx[0] == 0x01 && rx[1] == 0xb3) { + dprintk("-D- DiB7000PC detected\n"); + return 1; + } + + dprintk("-D- DiB7000PC not detected\n"); + return 0; +} +EXPORT_SYMBOL(dib7000pc_detection); + +struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) +{ + struct dib7000p_state *st = demod->demodulator_priv; + return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); +} +EXPORT_SYMBOL(dib7000p_get_i2c_master); + +int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]) +{ + struct dib7000p_state st = { .i2c_adap = i2c }; + int k = 0; + u8 new_addr = 0; + + for (k = no_of_demods-1; k >= 0; k--) { + st.cfg = cfg[k]; + + /* designated i2c address */ + new_addr = (0x40 + k) << 1; + st.i2c_addr = new_addr; + if (dib7000p_identify(&st) != 0) { + st.i2c_addr = default_addr; + if (dib7000p_identify(&st) != 0) { + dprintk("DiB7000P #%d: not identified\n", k); + return -EIO; + } + } + + /* start diversity to pull_down div_str - just for i2c-enumeration */ + dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY); + + /* set new i2c address and force divstart */ + dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2); + + dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); + } + + for (k = 0; k < no_of_demods; k++) { + st.cfg = cfg[k]; + st.i2c_addr = (0x40 + k) << 1; + + // unforce divstr + dib7000p_write_word(&st, 1285, st.i2c_addr << 2); + + /* deactivate div - it was just for i2c-enumeration */ + dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z); + } + + return 0; +} +EXPORT_SYMBOL(dib7000p_i2c_enumeration); + +static struct dvb_frontend_ops dib7000p_ops; +struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg) +{ + struct dvb_frontend *demod; + struct dib7000p_state *st; + st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL); + if (st == NULL) + return NULL; + + memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config)); + st->i2c_adap = i2c_adap; + st->i2c_addr = i2c_addr; + st->gpio_val = cfg->gpio_val; + st->gpio_dir = cfg->gpio_dir; + + demod = &st->demod; + demod->demodulator_priv = st; + memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops)); + + if (dib7000p_identify(st) != 0) + goto error; + + dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); + + dib7000p_demod_reset(st); + + return demod; + +error: + kfree(st); + return NULL; +} +EXPORT_SYMBOL(dib7000p_attach); + +static struct dvb_frontend_ops dib7000p_ops = { + .info = { + .name = "DiBcom 7000PC", + .type = FE_OFDM, + .frequency_min = 44250000, + .frequency_max = 867250000, + .frequency_stepsize = 62500, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = dib7000p_release, + + .init = dib7000p_init, + .sleep = dib7000p_sleep, + + .set_frontend = dib7000p_set_frontend, + .get_tune_settings = dib7000p_fe_get_tune_settings, + .get_frontend = dib7000p_get_frontend, + + .read_status = dib7000p_read_status, + .read_ber = dib7000p_read_ber, + .read_signal_strength = dib7000p_read_signal_strength, + .read_snr = dib7000p_read_snr, + .read_ucblocks = dib7000p_read_unc_blocks, +}; + +MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); +MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/dib7000p.h b/linux/drivers/media/dvb/frontends/dib7000p.h new file mode 100644 index 000000000..79465cf1a --- /dev/null +++ b/linux/drivers/media/dvb/frontends/dib7000p.h @@ -0,0 +1,46 @@ +#ifndef DIB7000P_H +#define DIB7000P_H + +#include "dibx000_common.h" + +struct dib7000p_config { + u8 output_mpeg2_in_188_bytes; + u8 hostbus_diversity; + u8 tuner_is_baseband; + int (*update_lna) (struct dvb_frontend *, u16 agc_global); + + struct dibx000_agc_config *agc; + struct dibx000_bandwidth_config *bw; + +#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff + u16 gpio_dir; +#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000 + u16 gpio_val; +#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12) +#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 ) +#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 ) +#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf) +#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff + u16 gpio_pwm_pos; + + u16 pwm_freq_div; + + u8 quartz_direct; + + int (*agc_control) (struct dvb_frontend *, u8 before); +}; + +#define DEFAULT_DIB7000P_I2C_ADDRESS 18 + +extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg); +extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); +extern int dib7000pc_detection(struct i2c_adapter *i2c_adap); + +/* TODO +extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); +extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod); +extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff); +extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod); +*/ + +#endif diff --git a/linux/drivers/media/dvb/frontends/dibx000_common.c b/linux/drivers/media/dvb/frontends/dibx000_common.c index 1f6dc06a3..bdc6d7a7d 100644 --- a/linux/drivers/media/dvb/frontends/dibx000_common.c +++ b/linux/drivers/media/dvb/frontends/dibx000_common.c @@ -85,7 +85,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c struct i2c_msg m[2 + num]; u8 tx_open[4], tx_close[4]; - memset(m,0, sizeof(struct i2c_msg) * (2 + num)); + memset(m,0, sizeof(struct i2c_msg) * (2 + num)), dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); diff --git a/linux/drivers/media/dvb/frontends/dibx000_common.h b/linux/drivers/media/dvb/frontends/dibx000_common.h index bb0c65f8a..a1df60436 100644 --- a/linux/drivers/media/dvb/frontends/dibx000_common.h +++ b/linux/drivers/media/dvb/frontends/dibx000_common.h @@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); #define BAND_LBAND 0x01 #define BAND_UHF 0x02 #define BAND_VHF 0x04 +#define BAND_SBAND 0x08 +#define BAND_FM 0x10 + +#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ + (freq_kHz) <= 250000 ? BAND_VHF : \ + (freq_kHz) <= 863000 ? BAND_UHF : \ + (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) struct dibx000_agc_config { /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ @@ -129,6 +136,7 @@ enum dibx000_adc_states { /* I hope I can get rid of the following kludge in the near future */ struct dibx000_ofdm_channel { + u32 RF_kHz; u8 Bw; s16 nfft; s16 guard; @@ -138,9 +146,11 @@ struct dibx000_ofdm_channel { s16 vit_alpha; s16 vit_code_rate_hp; s16 vit_code_rate_lp; + u8 intlv_native; }; #define FEP2DIB(fep,ch) \ + (ch)->RF_kHz = (fep)->frequency / 1000; \ (ch)->Bw = (fep)->u.ofdm.bandwidth; \ (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ @@ -149,7 +159,8 @@ struct dibx000_ofdm_channel { (ch)->vit_select_hp = 1; \ (ch)->vit_alpha = 1; \ (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ - (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; + (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ + (ch)->intlv_native = 1; #define INIT_OFDM_CHANNEL(ch) do {\ (ch)->Bw = 0; \ diff --git a/linux/drivers/media/dvb/frontends/isl6421.h b/linux/drivers/media/dvb/frontends/isl6421.h index 1916e3eb2..ea7f78a7d 100644 --- a/linux/drivers/media/dvb/frontends/isl6421.h +++ b/linux/drivers/media/dvb/frontends/isl6421.h @@ -39,7 +39,7 @@ #define ISL6421_ISEL1 0x20 #define ISL6421_DCL 0x40 -#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE) +#if defined(CONFIG_DVB_ISL6421) || (defined(CONFIG_DVB_ISL6421_MODULE) && defined(MODULE)) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, u8 override_set, u8 override_clear); diff --git a/linux/drivers/media/dvb/frontends/l64781.h b/linux/drivers/media/dvb/frontends/l64781.h index 21ba4a230..cd15f76ff 100644 --- a/linux/drivers/media/dvb/frontends/l64781.h +++ b/linux/drivers/media/dvb/frontends/l64781.h @@ -31,7 +31,7 @@ struct l64781_config u8 demod_address; }; -#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE) +#if defined(CONFIG_DVB_L64781) || (defined(CONFIG_DVB_L64781_MODULE) && defined(MODULE)) extern struct dvb_frontend* l64781_attach(const struct l64781_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.h b/linux/drivers/media/dvb/frontends/lgdt330x.h index 3f96b4855..995059004 100644 --- a/linux/drivers/media/dvb/frontends/lgdt330x.h +++ b/linux/drivers/media/dvb/frontends/lgdt330x.h @@ -52,7 +52,7 @@ struct lgdt330x_config int clock_polarity_flip; }; -#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE) +#if defined(CONFIG_DVB_LGDT330X) || (defined(CONFIG_DVB_LGDT330X_MODULE) && defined(MODULE)) extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/lnbp21.h b/linux/drivers/media/dvb/frontends/lnbp21.h index 1fe1dd179..68906acf7 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.h +++ b/linux/drivers/media/dvb/frontends/lnbp21.h @@ -39,7 +39,7 @@ #include <linux/dvb/frontend.h> -#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE) +#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) && defined(MODULE)) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); #else diff --git a/linux/drivers/media/dvb/frontends/mt2060.h b/linux/drivers/media/dvb/frontends/mt2060.h index 34a37c2b5..0a86eab3a 100644 --- a/linux/drivers/media/dvb/frontends/mt2060.h +++ b/linux/drivers/media/dvb/frontends/mt2060.h @@ -30,6 +30,14 @@ struct mt2060_config { u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */ }; +#if defined(CONFIG_DVB_TUNER_MT2060) || (defined(CONFIG_DVB_TUNER_MT2060_MODULE) && defined(MODULE)) extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1); +#else +static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TUNER_MT2060 #endif diff --git a/linux/drivers/media/dvb/frontends/mt312.h b/linux/drivers/media/dvb/frontends/mt312.h index 7112fb4d5..cf9a1505a 100644 --- a/linux/drivers/media/dvb/frontends/mt312.h +++ b/linux/drivers/media/dvb/frontends/mt312.h @@ -34,7 +34,7 @@ struct mt312_config u8 demod_address; }; -#if defined(CONFIG_DVB_MT312) || defined(CONFIG_DVB_MT312_MODULE) +#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE)) struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/mt352.h b/linux/drivers/media/dvb/frontends/mt352.h index 0035c2e2d..e9964081f 100644 --- a/linux/drivers/media/dvb/frontends/mt352.h +++ b/linux/drivers/media/dvb/frontends/mt352.h @@ -51,7 +51,7 @@ struct mt352_config int (*demod_init)(struct dvb_frontend* fe); }; -#if defined(CONFIG_DVB_MT352) || defined(CONFIG_DVB_MT352_MODULE) +#if defined(CONFIG_DVB_MT352) || (defined(CONFIG_DVB_MT352_MODULE) && defined(MODULE)) extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/nxt200x.h b/linux/drivers/media/dvb/frontends/nxt200x.h index 2eb220e98..28bc5591b 100644 --- a/linux/drivers/media/dvb/frontends/nxt200x.h +++ b/linux/drivers/media/dvb/frontends/nxt200x.h @@ -45,7 +45,7 @@ struct nxt200x_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; -#if defined(CONFIG_DVB_NXT200X) || defined(CONFIG_DVB_NXT200X_MODULE) +#if defined(CONFIG_DVB_NXT200X) || (defined(CONFIG_DVB_NXT200X_MODULE) && defined(MODULE)) extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/nxt6000.h b/linux/drivers/media/dvb/frontends/nxt6000.h index 9397393a6..13d225183 100644 --- a/linux/drivers/media/dvb/frontends/nxt6000.h +++ b/linux/drivers/media/dvb/frontends/nxt6000.h @@ -33,7 +33,7 @@ struct nxt6000_config u8 clock_inversion:1; }; -#if defined(CONFIG_DVB_NXT6000) || defined(CONFIG_DVB_NXT6000_MODULE) +#if defined(CONFIG_DVB_NXT6000) || (defined(CONFIG_DVB_NXT6000_MODULE) && defined(MODULE)) extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/or51132.h b/linux/drivers/media/dvb/frontends/or51132.h index 9718be4fb..add24f0a7 100644 --- a/linux/drivers/media/dvb/frontends/or51132.h +++ b/linux/drivers/media/dvb/frontends/or51132.h @@ -34,7 +34,7 @@ struct or51132_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; -#if defined(CONFIG_DVB_OR51132) || defined(CONFIG_DVB_OR51132_MODULE) +#if defined(CONFIG_DVB_OR51132) || (defined(CONFIG_DVB_OR51132_MODULE) && defined(MODULE)) extern struct dvb_frontend* or51132_attach(const struct or51132_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/or51211.h b/linux/drivers/media/dvb/frontends/or51211.h index 10a5419f9..8aad8402d 100644 --- a/linux/drivers/media/dvb/frontends/or51211.h +++ b/linux/drivers/media/dvb/frontends/or51211.h @@ -37,7 +37,7 @@ struct or51211_config void (*sleep)(struct dvb_frontend * fe); }; -#if defined(CONFIG_DVB_OR51211) || defined(CONFIG_DVB_OR51211_MODULE) +#if defined(CONFIG_DVB_OR51211) || (defined(CONFIG_DVB_OR51211_MODULE) && defined(MODULE)) extern struct dvb_frontend* or51211_attach(const struct or51211_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/s5h1420.h b/linux/drivers/media/dvb/frontends/s5h1420.h index efc54d7f3..1555870f7 100644 --- a/linux/drivers/media/dvb/frontends/s5h1420.h +++ b/linux/drivers/media/dvb/frontends/s5h1420.h @@ -34,7 +34,7 @@ struct s5h1420_config u8 invert:1; }; -#if defined(CONFIG_DVB_S5H1420) || defined(CONFIG_DVB_S5H1420_MODULE) +#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE)) extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/sp8870.h b/linux/drivers/media/dvb/frontends/sp8870.h index 4cf27d3b1..909cefe71 100644 --- a/linux/drivers/media/dvb/frontends/sp8870.h +++ b/linux/drivers/media/dvb/frontends/sp8870.h @@ -35,7 +35,7 @@ struct sp8870_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE) +#if defined(CONFIG_DVB_SP8870) || (defined(CONFIG_DVB_SP8870_MODULE) && defined(MODULE)) extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/sp887x.h b/linux/drivers/media/dvb/frontends/sp887x.h index cab7ea644..7ee78d7d9 100644 --- a/linux/drivers/media/dvb/frontends/sp887x.h +++ b/linux/drivers/media/dvb/frontends/sp887x.h @@ -17,7 +17,7 @@ struct sp887x_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_SP887X) || defined(CONFIG_DVB_SP887X_MODULE) +#if defined(CONFIG_DVB_SP887X) || (defined(CONFIG_DVB_SP887X_MODULE) && defined(MODULE)) extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/stv0297.h b/linux/drivers/media/dvb/frontends/stv0297.h index 760b80db4..69f4515df 100644 --- a/linux/drivers/media/dvb/frontends/stv0297.h +++ b/linux/drivers/media/dvb/frontends/stv0297.h @@ -42,7 +42,7 @@ struct stv0297_config u8 stop_during_read:1; }; -#if defined(CONFIG_DVB_STV0297) || defined(CONFIG_DVB_STV0297_MODULE) +#if defined(CONFIG_DVB_STV0297) || (defined(CONFIG_DVB_STV0297_MODULE) && defined(MODULE)) extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/stv0299.h b/linux/drivers/media/dvb/frontends/stv0299.h index 7ef252070..33df94959 100644 --- a/linux/drivers/media/dvb/frontends/stv0299.h +++ b/linux/drivers/media/dvb/frontends/stv0299.h @@ -89,7 +89,7 @@ struct stv0299_config int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); }; -#if defined(CONFIG_DVB_STV0299) || defined(CONFIG_DVB_STV0299_MODULE) +#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE)) extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/tda10021.h b/linux/drivers/media/dvb/frontends/tda10021.h index d68ae20c8..e3da78010 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.h +++ b/linux/drivers/media/dvb/frontends/tda10021.h @@ -32,7 +32,7 @@ struct tda10021_config u8 demod_address; }; -#if defined(CONFIG_DVB_TDA10021) || defined(CONFIG_DVB_TDA10021_MODULE) +#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, struct i2c_adapter* i2c, u8 pwm); #else diff --git a/linux/drivers/media/dvb/frontends/tda1004x.h b/linux/drivers/media/dvb/frontends/tda1004x.h index e28fca057..605ad2dfc 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.h +++ b/linux/drivers/media/dvb/frontends/tda1004x.h @@ -71,7 +71,7 @@ struct tda1004x_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_TDA1004X) || defined(CONFIG_DVB_TDA1004X_MODULE) +#if defined(CONFIG_DVB_TDA1004X) || (defined(CONFIG_DVB_TDA1004X_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c); diff --git a/linux/drivers/media/dvb/frontends/tda10086.h b/linux/drivers/media/dvb/frontends/tda10086.h index 18457adee..ed584a8f4 100644 --- a/linux/drivers/media/dvb/frontends/tda10086.h +++ b/linux/drivers/media/dvb/frontends/tda10086.h @@ -35,7 +35,7 @@ struct tda10086_config u8 invert; }; -#if defined(CONFIG_DVB_TDA10086) || defined(CONFIG_DVB_TDA10086_MODULE) +#if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/tda8083.h b/linux/drivers/media/dvb/frontends/tda8083.h index aae15bdce..2d3307999 100644 --- a/linux/drivers/media/dvb/frontends/tda8083.h +++ b/linux/drivers/media/dvb/frontends/tda8083.h @@ -35,7 +35,7 @@ struct tda8083_config u8 demod_address; }; -#if defined(CONFIG_DVB_TDA8083) || defined(CONFIG_DVB_TDA8083_MODULE) +#if defined(CONFIG_DVB_TDA8083) || (defined(CONFIG_DVB_TDA8083_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/tda80xx.h b/linux/drivers/media/dvb/frontends/tda80xx.h index ce472b3fb..8bdaa3117 100644 --- a/linux/drivers/media/dvb/frontends/tda80xx.h +++ b/linux/drivers/media/dvb/frontends/tda80xx.h @@ -41,7 +41,7 @@ struct tda80xx_config u8 volt18setting; }; -#if defined(CONFIG_DVB_TDA80XX) || defined(CONFIG_DVB_TDA80XX_MODULE) +#if defined(CONFIG_DVB_TDA80XX) || (defined(CONFIG_DVB_TDA80XX_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/tda826x.h b/linux/drivers/media/dvb/frontends/tda826x.h index 83998c001..ad9981195 100644 --- a/linux/drivers/media/dvb/frontends/tda826x.h +++ b/linux/drivers/media/dvb/frontends/tda826x.h @@ -35,7 +35,7 @@ * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector. * @return FE pointer on success, NULL on failure. */ -#if defined(CONFIG_DVB_TDA826X) || defined(CONFIG_DVB_TDA826X_MODULE) +#if defined(CONFIG_DVB_TDA826X) || (defined(CONFIG_DVB_TDA826X_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough); diff --git a/linux/drivers/media/dvb/frontends/tua6100.h b/linux/drivers/media/dvb/frontends/tua6100.h index 8f98033ff..03a665e7d 100644 --- a/linux/drivers/media/dvb/frontends/tua6100.h +++ b/linux/drivers/media/dvb/frontends/tua6100.h @@ -34,7 +34,7 @@ #include <linux/i2c.h> #include "dvb_frontend.h" -#if defined(CONFIG_DVB_TUA6100) || defined(CONFIG_DVB_TUA6100_MODULE) +#if defined(CONFIG_DVB_TUA6100) || (defined(CONFIG_DVB_TUA6100_MODULE) && defined(MODULE)) extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c); #else static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c) diff --git a/linux/drivers/media/dvb/frontends/ves1820.h b/linux/drivers/media/dvb/frontends/ves1820.h index f0c9dded3..e4a2a3240 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.h +++ b/linux/drivers/media/dvb/frontends/ves1820.h @@ -41,7 +41,7 @@ struct ves1820_config u8 selagc:1; }; -#if defined(CONFIG_DVB_VES1820) || defined(CONFIG_DVB_VES1820_MODULE) +#if defined(CONFIG_DVB_VES1820) || (defined(CONFIG_DVB_VES1820_MODULE) && defined(MODULE)) extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, struct i2c_adapter* i2c, u8 pwm); #else diff --git a/linux/drivers/media/dvb/frontends/ves1x93.h b/linux/drivers/media/dvb/frontends/ves1x93.h index 395fed39b..d507f8966 100644 --- a/linux/drivers/media/dvb/frontends/ves1x93.h +++ b/linux/drivers/media/dvb/frontends/ves1x93.h @@ -40,7 +40,7 @@ struct ves1x93_config u8 invert_pwm:1; }; -#if defined(CONFIG_DVB_VES1X93) || defined(CONFIG_DVB_VES1X93_MODULE) +#if defined(CONFIG_DVB_VES1X93) || (defined(CONFIG_DVB_VES1X93_MODULE) && defined(MODULE)) extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, struct i2c_adapter* i2c); #else diff --git a/linux/drivers/media/dvb/frontends/zl10353.h b/linux/drivers/media/dvb/frontends/zl10353.h index 79a947215..0bc010973 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.h +++ b/linux/drivers/media/dvb/frontends/zl10353.h @@ -36,7 +36,7 @@ struct zl10353_config int parallel_ts; }; -#if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE) +#if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, struct i2c_adapter *i2c); #else diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index 2310b2bfe..3de55e0cc 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -306,7 +306,11 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets) TS_DMA_BYTES, PCI_DMA_FROMDEVICE); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static irqreturn_t pluto_irq(int irq, void *dev_id, struct pt_regs *regs) +#else +static irqreturn_t pluto_irq(int irq, void *dev_id) +#endif { struct pluto *pluto = dev_id; u32 tscr; diff --git a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index af3391314..239a48bcb 100644 --- a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -740,7 +740,11 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs) +#else +static void ttusb_iso_irq(struct urb *urb) +#endif { struct ttusb *ttusb = urb->context; diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 36dd35db4..f2d18a5fb 100644 --- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -214,7 +214,11 @@ static u16 rc_keys[] = { static void ttusb_dec_set_model(struct ttusb_dec *dec, enum ttusb_dec_model model); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs) +#else +static void ttusb_dec_handle_irq( struct urb *urb) +#endif { struct ttusb_dec * dec = urb->context; char *buffer = dec->irq_buffer; @@ -766,7 +770,11 @@ static void ttusb_dec_process_urb_frame_list(unsigned long data) } } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs) +#else +static void ttusb_dec_process_urb(struct urb *urb) +#endif { struct ttusb_dec *dec = urb->context; |