[linux-dvb] [PATCH] DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)
Michael Krufky
mkrufky at linuxtv.org
Mon Aug 4 18:35:04 CEST 2008
On Mon, Aug 4, 2008 at 9:10 AM, Anton Blanchard <anton at samba.org> wrote:
> A number of people in Australia have bought the dual digital 4 only to
> find revision 2 contains a completely different chipset (DIBCOM DIB7070P).
>
> I took a look at one this weekend. It has two Cypress FX2's hooked up to
> two DIB7070P's; I guess they took the previous design and bolted on the
> DIBCOM chips. This means it shares a lot with the cxusb driver as well as
> the dib0700 driver.
Not really -- the only thing in common with the dib0700 driver is the
fact that there are dib7070 demod / tuner chips.
> After some reverse engineering I've come up with the patch below which
> works for me (DVB-T reception and remote control). Right now I've copied
> bits of the dib0700 driver, I wonder if we need to consolidate that code
> in a shared dib7070 driver.
Consolidating that code is a nice idea, however, it doesn't really pay
in this instance. The code that you're talking about is actually the
tuner & demod configuration, which is not the same for all devices.
In this case, it is more trouble than it is worth to attempt to share
this particular code. (it's a very small amount of code anyway, so no
big loss there)
If you have patches in the future that centralize common code in a
clean way, without breaking any other user of the dibcom drivers, then
it can be dealt with separately -- these is no reason why this code
can't be merged the way it is now.
> While I'm not downloading any firmware to the DIBCOM chips, I wonder if
> the dvb-usb-dib0700-1.10.fw firmware would be usable in this setup. I'm
> not even sure how Id go about downloading it yet (the Windows driver
> doesn't download any firmware).
No -- the dib0700 firmware is for the dib0700 chip. The FusionHDTV
Dual Digital 4 Rev 2 uses two cypress FX2's instead of any dib0700.
Please see some additional small comments inline, below:
> Index: v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
> ===================================================================
> --- v4l-dvb.orig/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2008-08-04 18:10:30.000000000 +1000
> +++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2008-08-04 18:10:46.000000000 +1000
> @@ -172,6 +172,7 @@
> #define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
> #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70
> #define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71
> +#define USB_PID_DVICO_BLUEBIRD_DUAL_5 0xdb98
Bluebird Dual 5 is a different device that is not related to the DUAL
4 rev2 -- please rename this to something more appropriate, like
"USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2"
> #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
> #define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
> #define USB_PID_MEDION_MD95700 0x0932
> Index: v4l-dvb/linux/drivers/media/dvb/dvb-usb/cxusb.c
> ===================================================================
> --- v4l-dvb.orig/linux/drivers/media/dvb/dvb-usb/cxusb.c 2008-08-04 18:10:30.000000000 +1000
> +++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/cxusb.c 2008-08-04 21:30:20.000000000 +1000
> @@ -36,6 +36,8 @@
> #include "tuner-xc2028.h"
> #include "tuner-simple.h"
> #include "mxl5005s.h"
> +#include "dib7000p.h"
> +#include "dib0070.h"
>
> /* debug */
> static int dvb_usb_cxusb_debug;
> @@ -725,6 +727,155 @@
> return 0;
> }
>
> +/* XXX Copied from dib0700, need to share the original */
> +/* DIB7070 generic */
> +static struct dibx000_agc_config dib7070_agc_config = {
> + BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
> + /* 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=5, P_agc_write=0 */
> + (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
> +
> + 600, // inv_gain
> + 10, // time_stabiliz
> +
> + 0, // alpha_level
> + 118, // thlock
> +
> + 0, // wbd_inv
> + 3530, // wbd_ref
> + 1, // wbd_sel
> + 5, // wbd_alpha
> +
> + 65535, // agc1_max
> + 0, // agc1_min
> +
> + 65535, // agc2_max
> + 0, // agc2_min
> +
> + 0, // agc1_pt1
> + 40, // agc1_pt2
> + 183, // agc1_pt3
> + 206, // agc1_slope1
> + 255, // agc1_slope2
> + 72, // agc2_pt1
> + 152, // agc2_pt2
> + 88, // agc2_slope1
> + 90, // agc2_slope2
> +
> + 17, // alpha_mant
> + 27, // alpha_exp
> + 23, // beta_mant
> + 51, // beta_exp
> +
> + 0, // perform_agc_softsplit
> +};
Please convert all // comments to /* comments */ according to kernel
codingstyle. Yes, I know you copied this code block, but it should be
cleaned up before merge.
> +
> +/* XXX Copied from dib0700, need to share the original */
^^^^^^^^^ this comment is not necessary.
> +static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
> + 60000, 15000, // internal, sampling
> + 1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
> + 0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
> + (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
> + (0 << 25) | 0, // ifreq = 0.000000 MHz
> + 20452225, // timf
> + 12000000, // xtal_hz
Again, please convert // comments to /* comments */
> +};
> +
> +static struct dib7000p_config cxusb_dualdig4_rev2_config = {
> + .output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
> + .output_mpeg2_in_188_bytes = 1,
> +
> + .agc_config_count = 1,
> + .agc = &dib7070_agc_config,
> + .bw = &dib7070_bw_config_12_mhz,
> + .tuner_is_baseband = 1,
> + .spur_protect = 1,
> +
> + .gpio_dir = 0xfcef,
> + .gpio_val = 0x0110,
> +
> + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
> +
> + .hostbus_diversity = 1,
> +};
> +
> +static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
> +{
> + if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
> + err("set interface failed");
> +
> + /* XXX Needed? */
> + cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
Yes, you need to set digital mode, otherwise the bluebird firmware
will be in an unknown state.
> +
> + cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
> +
> + dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
> + &cxusb_dualdig4_rev2_config);
> +
> + if ((adap->fe = dvb_attach(dib7000p_attach,
> + &adap->dev->i2c_adap, 0x80,
> + &cxusb_dualdig4_rev2_config)) == NULL)
> + return -EIO;
> +
> + return 0;
> +}
> +
> +static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
> +{
> + return dib7000p_set_gpio(fe, 8, 0, !onoff);
> +}
> +
> +static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
> +{
> + return 0;
> +}
> +
> +static struct dib0070_config dib7070p_dib0070_config = {
> + .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
> + .reset = dib7070_tuner_reset,
> + .sleep = dib7070_tuner_sleep,
> + .clock_khz = 12000,
> + /* .clock_pad_drive = 4 */
> +};
> +
> +struct dib0700_adapter_state {
> + int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
> +};
> +
> +/* XXX Copied from dib0700, need to share the original */
^^^^^^^^^ this comment is not necessary.
> +static int dib7070_set_param_override(struct dvb_frontend *fe,
> + struct dvb_frontend_parameters *fep)
> +{
> + struct dvb_usb_adapter *adap = fe->dvb->priv;
> + struct dib0700_adapter_state *state = adap->priv;
> +
> + u16 offset;
> + u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
> + switch (band) {
> + case BAND_VHF: offset = 950; break;
> + case BAND_UHF:
> + default: offset = 550; break;
> + }
> +
> + dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
> +
> + return state->set_param_save(fe, fep);
> +}
> +
> +static int cxusb_dualdig4_tuner_attach(struct dvb_usb_adapter *adap)
> +{
> + struct dib0700_adapter_state *st = adap->priv;
> + struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
> +
> + if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
> + &dib7070p_dib0070_config) == NULL)
> + return -ENODEV;
> +
> + st->set_param_save = adap->fe->ops.tuner_ops.set_params;
> + adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
> + return 0;
> +}
> +
> static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
> {
> if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
> @@ -825,6 +976,7 @@
> static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
> static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
> static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
> +static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties;
> static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
> static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
> static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
> @@ -844,6 +996,9 @@
> THIS_MODULE, NULL, adapter_nr) ||
> 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
> THIS_MODULE, NULL, adapter_nr) ||
> + 0 == dvb_usb_device_init(intf,
> + &cxusb_bluebird_dualdig4_rev2_properties,
> + THIS_MODULE, NULL, adapter_nr) ||
> 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
> THIS_MODULE, NULL, adapter_nr) ||
> 0 == dvb_usb_device_init(intf,
> @@ -875,6 +1030,7 @@
> { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
> { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
> { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
> + { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_5) },
> {} /* Terminating entry */
> };
> MODULE_DEVICE_TABLE (usb, cxusb_table);
> @@ -1180,6 +1336,54 @@
> }
> };
>
> +static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
> + .caps = DVB_USB_IS_AN_I2C_ADAPTER,
> +
> + .usb_ctrl = CYPRESS_FX2,
> +
> + .size_of_priv = sizeof(struct cxusb_state),
> +
> + .num_adapters = 1,
> + .adapter = {
> + {
> + .streaming_ctrl = cxusb_streaming_ctrl,
> + .frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
> + .tuner_attach = cxusb_dualdig4_tuner_attach,
> + .size_of_priv = sizeof(struct dib0700_adapter_state),
> + /* parameter for the MPEG2-data transfer */
> + .stream = {
> + .type = USB_BULK,
> + .count = 7,
> + .endpoint = 0x02,
> + .u = {
> + .bulk = {
> + .buffersize = 4096,
> + }
> + }
> + },
> + },
> + },
> +
> + .power_ctrl = cxusb_bluebird_power_ctrl,
> +
> + .i2c_algo = &cxusb_i2c_algo,
> +
> + .generic_bulk_ctrl_endpoint = 0x01,
> +
> + .rc_interval = 100,
> + .rc_key_map = dvico_mce_rc_keys,
> + .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
> + .rc_query = cxusb_rc_query,
> +
> + .num_device_descs = 1,
> + .devices = {
> + { "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)",
> + { NULL },
> + { &cxusb_table[17], NULL },
> + },
> + }
> +};
> +
> static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
> .caps = DVB_USB_IS_AN_I2C_ADAPTER,
>
> Index: v4l-dvb/linux/drivers/media/dvb/frontends/dib7000p.c
> ===================================================================
> --- v4l-dvb.orig/linux/drivers/media/dvb/frontends/dib7000p.c 2008-08-04 18:10:30.000000000 +1000
> +++ v4l-dvb/linux/drivers/media/dvb/frontends/dib7000p.c 2008-08-04 18:10:46.000000000 +1000
> @@ -1359,7 +1359,8 @@
> /* Ensure the output mode remains at the previous default if it's
> * not specifically set by the caller.
> */
> - if (st->cfg.output_mode != OUTMODE_MPEG2_SERIAL)
> + if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&
> + (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
> st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
There doesnt look to be anything wrong with this, but I don't know
very much about this -- why is this needed? Have you tested on other
devices that use dib7000p to confirm that it doesn't break anything?
>
> demod = &st->demod;
>
...and finally, after cleaning the patch up as per my comments
above.... Please also provide your developer sign-off, so that your
patch can be merged into the master repository.
Good work!
Regards,
Mike Krufky
More information about the linux-dvb
mailing list