From patchwork Sat Nov 21 15:44:07 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Piero Terzulli X-Patchwork-Id: 61950 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nALFqfKc022617 for ; Sat, 21 Nov 2009 15:52:41 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754767AbZKUPwd (ORCPT ); Sat, 21 Nov 2009 10:52:33 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754609AbZKUPwd (ORCPT ); Sat, 21 Nov 2009 10:52:33 -0500 Received: from ey-out-2122.google.com ([74.125.78.25]:52139 "EHLO ey-out-2122.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754546AbZKUPwb (ORCPT ); Sat, 21 Nov 2009 10:52:31 -0500 Received: by ey-out-2122.google.com with SMTP id 4so674443eyf.19 for ; Sat, 21 Nov 2009 07:52:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :from:date:message-id:subject:to:content-type; bh=kVhZ4Z7WdmiRqu5GnbKAL7TiPFRA36iOU+1Trn5Jvak=; b=LMqz3oHmFG9ODLfsUSBGyfChYB7SdOj903f23QoVFQVJjGc/t8yArHpbDZEyLz0WQH +RfGKx8+ToBdKJ5HKG3q+LDSbrmn2HRQyJLrs083ueQMwTbyHn1QjrGqMzN6RpoVM7xc /b6VJUGVP4IcpCmvjdJLa9TgRbTsWFhYICSiQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; b=NppXKf2uzoetB6k7/6Inj+NmLJwbFWBJT5GGofKhcLG7MP9QWng3zHfr+T95mJJont kIr6jpTXwRBRnOKKWnj1p3i00AYjG3rwzTEeu3zYTp+lvK4pPpfYwMDN29Osw2iVijtU LFABX+Rp2Bc6t6jUWpV5TPgm46I90vg8Hx9n0= MIME-Version: 1.0 Received: by 10.213.100.167 with SMTP id y39mr1501755ebn.51.1258818267103; Sat, 21 Nov 2009 07:44:27 -0800 (PST) In-Reply-To: <492564760911151801k536539acw5550735ce97e5ca5@mail.gmail.com> References: <492564760911151801k536539acw5550735ce97e5ca5@mail.gmail.com> From: Piero Terzulli Date: Sat, 21 Nov 2009 16:44:07 +0100 Message-ID: <492564760911210744n212a0740j4714b5761d68ccb0@mail.gmail.com> Subject: Re: AverTV TwinStar support To: linux-media@vger.kernel.org Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org diff -ur v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.c v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.c --- v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.c 2009-10-01 21:13:56.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.c 2009-09-29 01:43:36.000000000 +0200 @@ -375,7 +375,6 @@ mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if); mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz); - set_reg_bits(state->tab_init, 0x04, 0x01, cfg->loop_thru_enable); set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3); set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp); @@ -480,15 +479,21 @@ static int mxl5007t_write_regs(struct mxl5007t_state *state, struct reg_pair_t *reg_pair) { - unsigned int i = 0; - int ret = 0; + struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0, + .buf = (u8 *)reg_pair, .len = 0 }; + int ret; + int i = 0; - while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) { - ret = mxl5007t_write_reg(state, - reg_pair[i].reg, reg_pair[i].val); + while (reg_pair[i].reg || reg_pair[i].val) { i++; + msg.len += 2; } - return ret; + ret = i2c_transfer(state->i2c_props.adap, &msg, 1); + if (ret != 1) { + mxl_err("failed!"); + return -EREMOTEIO; + } + return 0; } static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val) @@ -865,6 +870,18 @@ /* check return value of mxl5007t_get_chip_id */ if (mxl_fail(ret)) goto fail; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + ret = mxl5007t_write_reg(state, 0x04, state->config->loop_thru_enable); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + /* check return value of mxl5007t_get_chip_id */ + if (mxl_fail(ret)) + goto fail; break; default: /* existing tuner instance */ diff -ur v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.h v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.h --- v4l-dvb/linux/drivers/media/common/tuners/mxl5007t.h 2009-10-01 21:13:56.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/common/tuners/mxl5007t.h 2009-09-29 01:43:36.000000000 +0200 @@ -73,7 +73,7 @@ enum mxl5007t_xtal_freq xtal_freq_hz; enum mxl5007t_if_freq if_freq_hz; unsigned int invert_if:1; - unsigned int loop_thru_enable:1; + unsigned int loop_thru_enable:2; unsigned int clk_out_enable:1; }; diff -ur v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.c v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.c --- v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.c 2009-10-01 21:15:00.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.c 2009-09-29 01:43:28.000000000 +0200 @@ -25,6 +25,7 @@ #include "af9035.h" #include "af9033.h" #include "tua9001.h" +#include "mxl5007t.h" static int dvb_usb_af9035_debug; module_param_named(debug, dvb_usb_af9035_debug, int, 0644); @@ -40,9 +41,11 @@ static struct af9033_config af9035_af9033_config[] = { { .demod_address = 0, + .tuner_address = 0, .output_mode = AF9033_TS_MODE_USB, }, { .demod_address = 0, + .tuner_address = 0, .output_mode = AF9033_TS_MODE_SERIAL, } }; @@ -137,7 +140,7 @@ return ret; } -static int af9035_write_regs(struct dvb_usb_device *d, u8 mbox, u16 reg, +static int af9035_write_regs_bis(struct usb_device *d, u8 mbox, u16 reg, u8 *val, u8 len) { u8 wbuf[6+len]; @@ -150,51 +153,74 @@ wbuf[4] = reg >> 8; wbuf[5] = reg & 0xff; memcpy(&wbuf[6], val, len); - return af9035_rw_udev(d->udev, &req); + return af9035_rw_udev(d, &req); } -static int af9035_read_regs(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 *val, +static int af9035_write_regs(struct dvb_usb_device *d, u8 mbox, u16 reg, +u8 *val, u8 len) +{ + return af9035_write_regs_bis(d->udev, mbox, reg, val, len); +} + +static int af9035_read_regs_bis(struct usb_device *d, u8 mbox, u16 reg, u8 *val, u8 len) { u8 wbuf[] = {len, 2, 0, 0, reg >> 8, reg & 0xff}; struct af9035_req req = {CMD_REG_DEMOD_READ, mbox, sizeof(wbuf), wbuf, len, val}; - return af9035_rw_udev(d->udev, &req); + return af9035_rw_udev(d, &req); +} + +static int af9035_read_regs(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 *val, + u8 len) +{ + return af9035_read_regs_bis(d->udev, mbox, reg, val, len); +} + +static int af9035_write_reg_bis(struct usb_device *d, u8 mbox, u16 reg, u8 val) +{ + return af9035_write_regs_bis(d, mbox, reg, &val, 1); } static int af9035_write_reg(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 val) { - return af9035_write_regs(d, mbox, reg, &val, 1); + return af9035_write_regs_bis(d->udev, mbox, reg, &val, 1); } -static int af9035_read_reg(struct dvb_usb_device *d, u8 mbox, u16 reg, u8 *val) +static int af9035_read_reg_bis(struct usb_device *d, u8 mbox, u16 reg, u8 *val) { - return af9035_read_regs(d, mbox, reg, val, 1); + return af9035_read_regs_bis(d, mbox, reg, val, 1); } -static int af9035_write_reg_bits(struct dvb_usb_device *d, u8 mbox, u16 reg, +static int af9035_write_reg_bits_bis(struct usb_device *d, u8 mbox, u16 reg, u8 pos, u8 len, u8 val) { int ret; u8 tmp, mask; - ret = af9035_read_reg(d, mbox, reg, &tmp); + ret = af9035_read_reg_bis(d, mbox, reg, &tmp); if (ret) return ret; mask = regmask[len - 1] << pos; tmp = (tmp & ~mask) | ((val << pos) & mask); - return af9035_write_reg(d, mbox, reg, tmp); + return af9035_write_reg_bis(d, mbox, reg, tmp); +} + +static int af9035_write_reg_bits(struct dvb_usb_device *d, u8 mbox, u16 reg, + u8 pos, u8 len, u8 val) +{ + return af9035_write_reg_bits_bis(d->udev, mbox, reg, pos, len, val); } -static int af9035_read_reg_bits(struct dvb_usb_device *d, u8 mbox, u16 reg, +static int af9035_read_reg_bits_bis(struct usb_device *d, u8 mbox, u16 reg, u8 pos, u8 len, u8 *val) { int ret; u8 tmp; - ret = af9035_read_reg(d, mbox, reg, &tmp); + ret = af9035_read_reg_bis(d, mbox, reg, &tmp); if (ret) return ret; *val = (tmp >> pos) & regmask[len - 1]; @@ -221,21 +247,29 @@ af9035_af9033_config[0].demod_address || msg[i].addr == af9035_af9033_config[1].demod_address) { + if (af9035_af9033_config[1].demod_address && (msg[i].addr == af9035_af9033_config[1].demod_address)) + mbox += 0x10; ret = af9035_read_regs(d, mbox, reg, &msg[i+1].buf[0], msg[i+1].len); } else { /* FIXME */ u8 wbuf[5]; - u8 rbuf[2]; + u8 rbuf[BUF_SIZE]; struct af9035_req req = {CMD_REG_TUNER_READ, - LINK, sizeof(wbuf), wbuf, sizeof(rbuf), + LINK, sizeof(wbuf), wbuf, msg[i + 1].len, rbuf}; - wbuf[0] = 0x02; /* read len */ + if (af9035_af9033_config[1].tuner_address && + (msg[i].addr == af9035_af9033_config[1].tuner_address)) { + msg[i].addr = af9035_af9033_config[0].tuner_address; + req.mbox += 0x10; + } + wbuf[0] = msg[i + 1].len; /* read len */ wbuf[1] = msg[i].addr; /* tuner i2c addr */ wbuf[2] = 0x01; /* reg width */ wbuf[3] = 0x00; /* reg MSB */ wbuf[4] = msg[i].buf[0]; /* reg LSB */ ret = af9035_rw_udev(d->udev, &req); + memcpy (msg[i + 1].buf, rbuf, msg[i + 1].len); } i += 2; } else { @@ -243,19 +277,24 @@ af9035_af9033_config[0].demod_address || msg[i].addr == af9035_af9033_config[1].demod_address) { + if (af9035_af9033_config[1].demod_address && (msg[i].addr == af9035_af9033_config[1].demod_address)) + mbox += 0x10; ret = af9035_write_regs(d, mbox, reg, &msg[i].buf[3], msg[i].len-3); } else { - u8 wbuf[7]; + u8 wbuf[BUF_SIZE]; struct af9035_req req = {CMD_REG_TUNER_WRITE, - LINK, sizeof(wbuf), wbuf, 0, NULL}; - wbuf[0] = 0x02; /* write len */ + LINK, 4 + msg[i].len, wbuf, 0, NULL}; + if (af9035_af9033_config[1].tuner_address && + (msg[i].addr == af9035_af9033_config[1].tuner_address)) { + msg[i].addr = af9035_af9033_config[0].tuner_address; + req.mbox += 0x10; + } + wbuf[0] = msg[i].len - 1; /* write len */ wbuf[1] = msg[i].addr; /* tuner i2c addr */ wbuf[2] = 0x01; /* reg width */ wbuf[3] = 0x00; /* reg MSB */ - wbuf[4] = msg[i].buf[0]; /* reg LSB */ - wbuf[5] = msg[i].buf[1]; /* reg val MSB */ - wbuf[6] = msg[i].buf[2]; /* reg val LSB */ + memcpy (&wbuf[4], msg[i].buf, msg[i].len); ret = af9035_rw_udev(d->udev, &req); } i += 1; @@ -424,8 +463,9 @@ u8 wbuf[1]; u8 rbuf[4]; struct af9035_firmware_header fw_hdr; - struct af9035_req req = {0, LINK, 0, NULL, 0, NULL}; - struct af9035_req req_fw_dl = {CMD_FW_DOWNLOAD, LINK, 0, wbuf, 0, NULL}; + struct af9035_req req = {0, LINK, 0, NULL, 1, rbuf}; + struct af9035_req req_fw_dl = {CMD_FW_DOWNLOAD, LINK, 0, NULL, 0, NULL}; + struct af9035_req req_rom = {CMD_SCATTER_WRITE, LINK, 0, NULL, 1, rbuf}; struct af9035_req req_fw_ver = {CMD_QUERYINFO, LINK, 1, wbuf, 4, rbuf}; /* read firmware segment info from beginning of the firmware file */ @@ -485,6 +525,25 @@ err("firmware download failed:%d", ret); goto error; } + } else if (fw_hdr.segment[i].type == SEGMENT_ROM_COPY){ + packets = fw_hdr.segment[i].len / FW_PACKET_MAX_DATA; + remainder = fw_hdr.segment[i].len % FW_PACKET_MAX_DATA; + len = FW_PACKET_MAX_DATA; + for (j = 0; j <= packets; j++) { + if (j == packets) /* size of the last packet */ + len = remainder; + + req_rom.wlen = len; + req_rom.wbuf = fw_data_ptr; + ret = af9035_rw_udev(udev, &req_rom); + if (ret) { + err("firmware download failed at " \ + "segment:%d packet:%d err:%d", \ + i, j, ret); + goto error; + } + fw_data_ptr += len; + } } else { deb_info("%s: segment type:%d not implemented\n", __func__, fw_hdr.segment[i].type); @@ -556,7 +615,7 @@ af9035_config.dual_mode = 0; } else { af9035_properties[i].adapter[0].stream.u.bulk.buffersize - = TS_USB20_MAX_PACKET_SIZE; + = TS_USB20_FRAME_SIZE; } } @@ -635,6 +694,9 @@ case AF9033_TUNER_TUA9001: af9035_af9033_config[i].rf_spec_inv = 1; break; + case AF9033_TUNER_MXL5007t: + af9035_af9033_config[i].rf_spec_inv = 1; + break; default: warn("tuner ID:%d not supported, please report!", val); return -ENODEV; @@ -648,6 +710,48 @@ if (ret) err("eeprom read failed:%d", ret); + if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA && + le16_to_cpu(udev->descriptor.idProduct) == USB_PID_AVERMEDIA_A825) { + deb_info("%s: AverMedia A825: overriding config\n", __func__); + /* set correct IF */ + for (i = 0; i < af9035_properties[0].num_adapters; i++) { + af9035_af9033_config[i].if_freq = 4570000; + } + } + + return ret; +} + +static int af9035_aux_init(struct usb_device *d) +{ + int ret; + u8 tmp, i; + + /* get demod crystal and ADC freqs */ + ret = af9035_read_reg_bits_bis(d, LINK, + r_io_mux_pwron_clk_strap, io_mux_pwron_clk_strap_pos, + io_mux_pwron_clk_strap_len, &tmp); + if (ret) + goto error; + + for (i = 0; i < af9035_properties[0].num_adapters; i++) { + af9035_af9033_config[i].crystal_clock = + clock_table[tmp].crystal; + af9035_af9033_config[i].adc_clock = + clock_table[tmp].adc; + } + + /* write 2nd demod I2C address to device */ + ret = af9035_write_reg_bis(d, LINK, 0x417f, + af9035_af9033_config[1].demod_address); + if (ret) + goto error; + + /* enable / disable clock out for 2nd demod for power saving */ + ret = af9035_write_reg_bis(d, LINK, p_reg_top_clkoen, + af9035_config.dual_mode); + +error: return ret; } @@ -678,49 +782,37 @@ static int af9035_af9033_frontend_attach(struct dvb_usb_adapter *adap) { - int ret; - u8 tmp, i; - - if (adap->id == 0) { - /* get demod crystal and ADC freqs */ - ret = af9035_read_reg_bits(adap->dev, LINK, - r_io_mux_pwron_clk_strap, io_mux_pwron_clk_strap_pos, - io_mux_pwron_clk_strap_len, &tmp); - if (ret) - goto error; - - for (i = 0; i < af9035_properties[0].num_adapters; i++) { - af9035_af9033_config[i].crystal_clock = - clock_table[tmp].crystal; - af9035_af9033_config[i].adc_clock = - clock_table[tmp].adc; - } - - /* write 2nd demod I2C address to device */ - ret = af9035_write_reg(adap->dev, LINK, 0x417f, - af9035_af9033_config[1].demod_address); - if (ret) - goto error; - - /* enable / disable clock out for 2nd demod for power saving */ - ret = af9035_write_reg(adap->dev, LINK, p_reg_top_clkoen, - af9035_config.dual_mode); - if (ret) - goto error; - } - /* attach demodulator */ adap->fe = dvb_attach(af9033_attach, &af9035_af9033_config[adap->id], &adap->dev->i2c_adap); return adap->fe == NULL ? -ENODEV : 0; - -error: - return ret; } -static struct tua9001_config af9035_tua9001_config = { - .i2c_address = 0xc0, +static struct tua9001_config af9035_tua9001_config[] = { + { + .i2c_address = 0xc0, + } , { + .i2c_address = 0xc1, + } +}; + +static struct mxl5007t_config af9035_mxl5007t_config[] = { + { + .xtal_freq_hz = MxL_XTAL_24_MHZ, + .if_freq_hz = MxL_IF_4_57_MHZ, + .invert_if = 0, + .loop_thru_enable = 0, + .clk_out_enable = 0, + .clk_out_amp = MxL_CLKOUT_AMP_0_94V, + } , { + .xtal_freq_hz = MxL_XTAL_24_MHZ, + .if_freq_hz = MxL_IF_4_57_MHZ, + .invert_if = 0, + .loop_thru_enable = 3, + .clk_out_enable = 1, + .clk_out_amp = MxL_CLKOUT_AMP_0_94V, + } }; static int af9035_tuner_attach(struct dvb_usb_adapter *adap) @@ -730,34 +822,93 @@ switch (af9035_af9033_config[adap->id].tuner) { case AF9033_TUNER_TUA9001: - /* gpiot3 TUA9001 RESETN - gpiot2 TUA9001 RXEN */ - ret = af9035_write_reg_bits(adap->dev, LINK, - p_reg_top_gpiot2_en, reg_top_gpiot2_en_pos, - reg_top_gpiot2_en_len, 1); - ret = af9035_write_reg_bits(adap->dev, LINK, - p_reg_top_gpiot2_on, reg_top_gpiot2_on_pos, - reg_top_gpiot2_on_len, 1); - ret = af9035_write_reg_bits(adap->dev, LINK, - p_reg_top_gpiot3_en, reg_top_gpiot3_en_pos, - reg_top_gpiot3_en_len, 1); - ret = af9035_write_reg_bits(adap->dev, LINK, - p_reg_top_gpiot3_on, reg_top_gpiot3_on_pos, - reg_top_gpiot3_on_len, 1); - - /* reset tuner */ - ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o, - reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 0); - msleep(1); - ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o, - reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 1); - - /* activate tuner - TODO: do that like I2C gate control */ - ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot2_o, - reg_top_gpiot2_o_pos, reg_top_gpiot2_o_len, 1); + af9035_af9033_config[adap->id].tuner_address = af9035_tua9001_config[adap->id].i2c_address; + af9035_af9033_config[adap->id].tuner_address += adap->id; + if (adap->id == 0) { + /* gpiot3 TUA9001 RESETN + gpiot2 TUA9001 RXEN */ + ret = af9035_write_reg_bits(adap->dev, LINK, + p_reg_top_gpiot2_en, reg_top_gpiot2_en_pos, + reg_top_gpiot2_en_len, 1); + ret = af9035_write_reg_bits(adap->dev, LINK, + p_reg_top_gpiot2_on, reg_top_gpiot2_on_pos, + reg_top_gpiot2_on_len, 1); + ret = af9035_write_reg_bits(adap->dev, LINK, + p_reg_top_gpiot3_en, reg_top_gpiot3_en_pos, + reg_top_gpiot3_en_len, 1); + ret = af9035_write_reg_bits(adap->dev, LINK, + p_reg_top_gpiot3_on, reg_top_gpiot3_on_pos, + reg_top_gpiot3_on_len, 1); + + /* reset tuner */ + ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o, + reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 0); + msleep(1); + ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot3_o, + reg_top_gpiot3_o_pos, reg_top_gpiot3_o_len, 1); + + /* activate tuner - TODO: do that like I2C gate control */ + ret = af9035_write_reg_bits(adap->dev, LINK, p_reg_top_gpiot2_o, + reg_top_gpiot2_o_pos, reg_top_gpiot2_o_len, 1); + } ret = dvb_attach(tua9001_attach, adap->fe, &adap->dev->i2c_adap, - &af9035_tua9001_config) == NULL ? -ENODEV : 0; + &af9035_tua9001_config[adap->id]) == NULL ? -ENODEV : 0; + + break; + case AF9033_TUNER_MXL5007t: + af9035_af9033_config[adap->id].tuner_address = 0xc0; + af9035_af9033_config[adap->id].tuner_address += adap->id; + if (adap->id == 0) { + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh12_en, + 1); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh12_on, + 1); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh12_o, + 0); + + msleep(30); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh12_o, + 1); + + msleep(300); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh4_en, + 1); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh4_on, + 1); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh4_o, + 0); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh3_en, + 1); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh3_on, + 1); + + ret = af9035_write_reg(adap->dev, LINK, + p_reg_top_gpioh3_o, + 1); + } + + ret = dvb_attach(mxl5007t_attach, adap->fe, &adap->dev->i2c_adap, + af9035_af9033_config[adap->id].tuner_address, + &af9035_mxl5007t_config[adap->id]) == NULL ? -ENODEV : 0; + break; default: ret = -ENODEV; @@ -775,6 +926,7 @@ {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003)}, {USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035)}, /* 5 */{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)}, +/* 6 */{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A825)}, {0}, }; @@ -798,7 +950,7 @@ .tuner_attach = af9035_tuner_attach, .stream = { .type = USB_BULK, - .count = 6, + .count = 4, .endpoint = 0x84, }, }, @@ -808,12 +960,12 @@ .tuner_attach = af9035_tuner_attach, .stream = { .type = USB_BULK, - .count = 6, + .count = 4, .endpoint = 0x85, .u = { .bulk = { .buffersize = - TS_USB20_MAX_PACKET_SIZE, + TS_USB20_FRAME_SIZE, } } }, @@ -824,7 +976,7 @@ .i2c_algo = &af9035_i2c_algo, - .num_device_descs = 2, + .num_device_descs = 3, .devices = { { .name = "Afatech AF9035 DVB-T USB2.0 stick", @@ -840,6 +992,11 @@ .cold_ids = {&af9035_usb_table[5], NULL}, .warm_ids = {NULL}, }, + { + .name = "Avermedia TwinStar", + .cold_ids = {&af9035_usb_table[6], NULL}, + .warm_ids = {NULL}, + }, } }, }; @@ -862,6 +1019,10 @@ if (ret) return ret; + ret = af9035_aux_init(udev); + if (ret) + return ret; + for (i = 0; i < af9035_properties_count; i++) { ret = dvb_usb_device_init(intf, &af9035_properties[i], THIS_MODULE, &d, adapter_nr); diff -ur v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.h v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.h --- v4l-dvb/linux/drivers/media/dvb/dvb-usb/af9035.h 2009-10-01 21:15:00.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/af9035.h 2009-09-07 01:27:03.000000000 +0200 @@ -179,7 +179,7 @@ }; struct af9035_firmware_header { -#define SEGMENT_MAX_COUNT 6 +#define SEGMENT_MAX_COUNT 50 u8 segment_count; struct af9035_segment segment[SEGMENT_MAX_COUNT]; }; diff -ur v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h --- v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2009-10-01 21:15:00.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2009-09-29 01:59:52.000000000 +0200 @@ -187,6 +187,7 @@ #define USB_PID_AVERMEDIA_A310 0xa310 #define USB_PID_AVERMEDIA_A850 0x850a #define USB_PID_AVERMEDIA_A805 0xa805 +#define USB_PID_AVERMEDIA_A825 0x0825 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 diff -ur v4l-dvb/linux/drivers/media/dvb/frontends/af9033.c v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.c --- v4l-dvb/linux/drivers/media/dvb/frontends/af9033.c 2009-10-01 21:15:00.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.c 2009-09-29 01:43:28.000000000 +0200 @@ -891,8 +891,7 @@ goto error; /* set fpga latch */ - ret = af9033_write_reg_bits(state, OFDM, p_reg_dca_fpga_latch, - reg_dca_fpga_latch_pos, reg_dca_fpga_latch_len, 0); + ret = af9033_write_reg(state, OFDM, p_reg_dca_fpga_latch, 0); if (ret) goto error; @@ -925,6 +924,10 @@ len = ARRAY_SIZE(tuner_init_tua9001); init = tuner_init_tua9001; break; + case AF9033_TUNER_MXL5007t: + len = ARRAY_SIZE(tuner_init_mxl5007t); + init = tuner_init_mxl5007t; + break; default: len = 0; init = NULL; @@ -981,6 +984,12 @@ if (ret) goto error; + if (state->config.output_mode == AF9033_TS_MODE_SERIAL) { + ret = af9033_write_reg_bits(state, LINK, p_reg_top_hostb_mpeg_ser_mode, + reg_top_hostb_mpeg_ser_mode_pos, reg_top_hostb_mpeg_ser_mode_len, 1); + if (ret) + goto error; + } error: if (ret) deb_info("%s: failed:%d\n", __func__, ret); @@ -1115,11 +1124,11 @@ 1670 - 1680 MHz L-BAND band = 0x02 otherwise band = 0xff */ /* TODO: are both min/max ranges really required... */ - if ((state->frequency >= 174000) && (state->frequency <= 230000)) + if ((state->frequency >= 174000000) && (state->frequency <= 230000000)) tmp = 0x00; /* VHF */ - else if ((state->frequency >= 350000) && (state->frequency <= 900000)) + else if ((state->frequency >= 350000000) && (state->frequency <= 900000000)) tmp = 0x01; /* UHF */ - else if ((state->frequency >= 1670000) && (state->frequency <= 1680000)) + else if ((state->frequency >= 1670000000) && (state->frequency <= 1680000000)) tmp = 0x02; /* L-BAND */ else tmp = 0xff; diff -ur v4l-dvb/linux/drivers/media/dvb/frontends/af9033.h v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.h --- v4l-dvb/linux/drivers/media/dvb/frontends/af9033.h 2009-10-01 21:15:00.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033.h 2009-09-16 15:52:01.000000000 +0200 @@ -36,6 +36,7 @@ enum af9033_tuner { AF9033_TUNER_TUA9001 = 0x27, /* Infineon TUA 9001 */ AF9033_TUNER_FC0011 = 0x28, /* Fitipower FC0011 */ + AF9033_TUNER_MXL5007t = 0xa0, /* Maxlinear MXL5007t */ }; /* clock setting table: @@ -60,6 +61,8 @@ /* demodulator's I2C address */ u8 demod_address; + u8 tuner_address; + /* xtal clock Hz */ u32 crystal_clock; diff -ur v4l-dvb/linux/drivers/media/dvb/frontends/af9033_priv.h v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033_priv.h --- v4l-dvb/linux/drivers/media/dvb/frontends/af9033_priv.h 2009-10-01 21:15:00.000000000 +0200 +++ v4l-dvb.new/linux/drivers/media/dvb/frontends/af9033_priv.h 2009-09-06 23:55:51.000000000 +0200 @@ -305,5 +305,38 @@ {0xF1E6, 0x00}, }; +static struct regdesc tuner_init_mxl5007t[] = { + {0x0046, 0x1b}, + {0x0057, 0x01}, + {0x0058, 0x01}, + {0x005f, 0x00}, + {0x0060, 0x00}, + {0x0068, 0x96}, + {0x0071, 0x05}, + {0x0072, 0x02}, + {0x0074, 0x01}, + {0x0079, 0x01}, + {0x0093, 0x00}, + {0x0094, 0x00}, + {0x0095, 0x00}, + {0x0096, 0x00}, + {0x00b3, 0x01}, + {0x00c1, 0x01}, + {0x00c2, 0x00}, + {0xF007, 0x00}, + {0xF00C, 0x19}, + {0xF00D, 0x1a}, + {0xF012, 0xda}, + {0xF013, 0x00}, + {0xF014, 0x00}, + {0xF015, 0x02}, + {0xF01F, 0x82}, + {0xF020, 0x00}, + {0xF029, 0x82}, + {0xF02A, 0x00}, + {0xF077, 0x02}, + {0xF1E6, 0x00}, +}; + #endif /* AF9033_PRIV_H */