From: Gabriele Dini Ciacci <dark.schneider@iol.it>
To: linux-media@vger.kernel.org
Cc: Patrick Boettcher <patrick.boettcher@desy.de>
Subject: [PATCH] Drivers for Pinnacle pctv200e and pctv60e
Date: Sun, 29 Mar 2009 15:56:08 +0200 [thread overview]
Message-ID: <20090329155608.396d2257@gdc1> (raw)
[-- Attachment #1: Type: text/plain, Size: 1276 bytes --]
Hello,
This is a stub patch to make the subjects card work.
I am using the driver on a pctv60e and it is very stable, I use it
daily. It should work for pctv200e but not owning the device I cannot
test it.
The code need to be cleaned, as I am not an experienced kernel coder.
The code in mt352.c contains an hard-coded address for the device, while
Pinnalce devices with that tuner uses a different address. Currently
the address is "hijacked" to be the correct one. This is a hack, and i
think that mt352.c should be changed to support multiple addresses,
selected via params, duplicate code or something.
Remote support is missing, cause it was not working out of the box. I
do not use it and so developing it for myself only was not very useful,
if someone wants it or is interested I can have a look.
The patch is generally messy, I need help there. I do not know if I
have to change all the functions to take as parameter an adapter_nr or
change the caller to continue to pass them a struct dvb_usb_device
obtained with i2c_get_adapdata(adapter_nr).
Here is the patch, as an attachment, thanks meanwhile.
Best Regards,
Gabriele Dini Ciacci
Signed-off-by: Gabriele Dini Ciacci <gab@diniciacci.org>
-----------
http://linux-wildo.sf.net
http://www.diniciacci.org
[-- Attachment #2: pctv200e.patch --]
[-- Type: text/x-patch, Size: 23634 bytes --]
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/Kconfig my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Kconfig
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/Kconfig 2009-01-06 00:16:39.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Kconfig 2009-01-06 15:22:31.000000000 +0100
@@ -299,3 +299,9 @@ config DVB_USB_AF9015
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
+
+config DVB_USB_PCTV200E
+ tristate "Pinnacle PCTV200e and PCTV60e support"
+ depends on DVB_USB && EXPERIMENTAL
+ help
+ Say Y here to support for PCTV200e or PCTV60e
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/Makefile my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Makefile
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/Makefile 2009-01-06 00:16:39.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/Makefile 2009-01-06 00:20:40.000000000 +0100
@@ -54,6 +54,8 @@ obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb
dvb-usb-opera-objs = opera1.o
obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
+dvb-usb-pctv200e-objs = pctv200e.o
+obj-$(CONFIG_DVB_USB_PCTV200E) += dvb-usb-pctv200e.o
dvb-usb-af9005-objs = af9005.o af9005-fe.o
obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2009-01-06 00:16:39.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h 2009-01-06 00:31:01.000000000 +0100
@@ -174,6 +174,7 @@
#define USB_PID_PINNACLE_PCTV73E 0x0237
#define USB_PID_PINNACLE_PCTV801E 0x023a
#define USB_PID_PINNACLE_PCTV801E_SE 0x023b
+#define USB_PID_PCTV_60E 0x0216
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
#define USB_PID_PCTV_450E 0x0222
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.c my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.c
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.c 1970-01-01 01:00:00.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.c 2009-01-06 15:30:32.000000000 +0100
@@ -0,0 +1,644 @@
+/*
+ * DVB USB compliant linux driver for Pinnacle PCTV 200e DVB-T reciever
+ *
+ * Copyright (C) 2008 Gabriele Dini Ciacci <gab@diniciacci.org>
+ * 2007 Jakob Steidl (jakob.steidl@gmail.com)
+ * based on Patrick Boettcher's driver for the Nebula Electronics uDigiTV
+ *
+ *
+ * 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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+// mt352 registers
+#define CLOCK_CTL 0x89
+#define RESET 0x50
+#define ACQ_CTL 0x53
+#define TRL_NOMINAL_RATE_1 0x54
+#define INPUT_FREQ_1 0x56
+#define UNKNOWN_3 0x5e
+#define AGC_TARGET 0x67
+#define CAPT_RANGE 0x75
+#define SNR_SELECT_1 0x79
+#define UNKNOWN_1 0x7B
+#define SCAN_CTL 0x88
+#define MCLK_RATIO 0x8B
+#define GPP_CTL 0x8C
+#define ADC_CTL_1 0x8E
+#define UNKNOWN_2 0x98
+
+#include "pctv200e.h"
+
+#include "dvb-usb.h"
+#include "mt352.h"
+#include "mt2060.h"
+#include "mt2060_priv.h"
+
+
+
+/* debug */
+// To enable the debug set a value 1 for dvb_usb_pctv200e_debug
+int dvb_usb_pctv200e_debug=0;
+static int ctrl_msg_last_device=0;
+static int ctrl_msg_last_operation=0;
+
+static struct mt352_config pctv200e_mt352_config;
+static struct mt2060_config pctv200e_mt2060_config;
+
+module_param_named(debug,dvb_usb_pctv200e_debug, int, 0644);
+MODULE_PARM_DESC( debug, "Set debug level (1=info,xfer=2,rc=4 (RC is the codeword for ALL ;) (|-able))." DVB_USB_DEBUG_STATUS );
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* I2C */
+/*
+01 c0 02 03 80
+ - request type (read: 0x01, write: 0x02)
+ - addr to be read or written (0xc0 ... tuner)
+ - number of of bits that follow
+ - just data
+ - data (optional, if number data >1)
+*/
+
+static int pctv200e_ctrl_msg(struct dvb_usb_device *d,
+ u8 addr, u8 rw, u8 reg, u8 *wbuf, int wlen, u8 *rbuf,int rlen)
+{
+ // atm, u8 rw is being ignored, it should be clear from the
+ int wo = (rbuf == NULL || rlen == 0); /* then its a write-only*/
+ int counter;
+ u8 sndbuf[5],rcvbuf[64] = { 0 };
+// u8 sndbuf[8],rcvbuf[5]; /* actually we don't know the max. answer lenght //yet..
+
+ if (wlen>64) {
+ warn ("pctv200e_ctrl_msg: failed, command too long!");
+ return 0;
+ }
+
+ memset(sndbuf,0,5); memset(rcvbuf,0,64);
+
+ if (ctrl_msg_last_device == 0) {
+
+// The very first time we send the following sequence "0x15 0x80" and then "0x16 0x00"
+ sndbuf[0] = 0x15;
+ sndbuf[1] = 0x80;
+ dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+ warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+
+ sndbuf[0] = 0x16;
+ sndbuf[1] = 0x00;
+ dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+ warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+ warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+ }
+ }
+
+ // Now start to check the last operation and send the intermedium sequence
+ // If the command is sent to the tuner mt2060
+ // first we sent the sequence "0x16 0x01", and below after the command
+ // then we send the sequence "0x16 0x00".
+ // This is not needed when the command goes to the demod mt352
+
+ if (addr == pctv200e_mt2060_config.i2c_address ) {
+
+ sndbuf[0] = 0x16;
+ sndbuf[1] = 0x01;
+ dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+ warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+ }
+
+ }
+
+ sndbuf[1] = addr;
+
+ ctrl_msg_last_device = addr;
+ // We store who which address was access (DEMOD or TUNER)
+// memcpy(&sndbuf[5],wbuf,wlen);
+
+ if (wo) {
+ ctrl_msg_last_operation = 0x01;
+ sndbuf[0] = 0x01;
+ sndbuf[2] = 0x02;
+ sndbuf[3] = reg;
+
+ // We convert multiple writes into single writes
+ for (counter=0; counter < wlen; counter++) {
+ sndbuf[4] = wbuf[counter];
+
+ // For Pinnacle cards it should be send 0xf4 for ACQ_CTL as mentioned
+ // in mt352.c. At this moment the mt352.c send by default 0x50,
+ // so we intercept and change the value here.
+ // This way we don't need to change mt352.c
+
+ if ((addr == 0x3e) & (sndbuf[3] == ACQ_CTL) & (sndbuf[4] == 0x50)) {
+ if (dvb_usb_pctv200e_debug)
+ warn("crtl_msg(): Changed ACQ_CTL value to 0xf4!!!");
+ sndbuf[4] = 0xf4;
+ }
+
+// memcpy(&sndbuf[3],wbuf,wlen);
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() wlen: %d, rlen: %d,WRITE: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+ }
+
+ dvb_usb_generic_rw(d,sndbuf,5,rcvbuf,64,4);
+
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+ }
+
+ if (rcvbuf[0] != 0x1) {
+ warn("crtl_msg() WRITE ERROR: returned byte [0] not 0x1");
+// return -EIO;
+ }
+
+ if (rcvbuf[1] != 0x0) {
+ warn("crtl_msg() WRITE ERROR: returned error!");
+// return -EIO;
+ }
+ // it is write_regs, so we increment the register value
+ sndbuf[3] = sndbuf[3]+1;
+ }
+
+ } else {
+ ctrl_msg_last_operation = 0x02;
+ sndbuf[0] = 0x02;
+ sndbuf[2] = 0x01;
+ sndbuf[3] = 0x01;
+ sndbuf[4] = reg;
+
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+ }
+
+ dvb_usb_generic_rw(d,sndbuf,5,rcvbuf,64,4);
+
+ if (rlen > 0) {
+ memcpy(rbuf,&rcvbuf[2],rlen);
+ }
+
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+ }
+ }
+
+ if (addr == pctv200e_mt2060_config.i2c_address ) {
+
+ sndbuf[0] = 0x16;
+ sndbuf[1] = 0x00;
+ dvb_usb_generic_rw(d,sndbuf,2,rcvbuf,64,4);
+
+ if (dvb_usb_pctv200e_debug) {
+ warn("crtl_msg() wlen: %d, rlen: %d, READ: %x %x %x %x %x",wlen,rlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+ warn("crtl_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+ }
+
+ }
+
+ return 0;
+}
+
+static int pctv200e_cmd_msg(struct dvb_usb_device *d, u8 *wbuf, int wlen)
+{
+ u8 sndbuf[64] = { 0 };
+ u8 rcvbuf[64] = { 0 };
+// u8 sndbuf[8],rcvbuf[5]; /* actually we don't know the max. answer lenght //yet.. */
+ if (wlen>64) {
+ warn ("pctv200e_cmd_msg: failed, command too long!");
+ return 0;
+ }
+ memset(sndbuf,0,64); memset(rcvbuf,0,64);
+ memcpy(sndbuf,wbuf,wlen);
+
+ if (dvb_usb_pctv200e_debug)
+ warn("cmd_msg() wlen: %d, WRITE: %x %x %x %x %x",wlen,sndbuf[0],sndbuf[1],sndbuf[2],sndbuf[3],sndbuf[4]);
+
+ dvb_usb_generic_rw(d,sndbuf,wlen,rcvbuf,64,4);
+
+ if (rcvbuf[1] != 0x00) {
+ warn("crtl_msg() WRITE ERROR: returned error!");
+ }
+
+ if (dvb_usb_pctv200e_debug)
+ warn("cmd_msg() RECEIVED: %x %x %x %x %x %x %x %x %x %x %x %x %x",rcvbuf[0],rcvbuf[1],rcvbuf[2],rcvbuf[3],rcvbuf[4],rcvbuf[5],rcvbuf[6],rcvbuf[7],rcvbuf[8],rcvbuf[9],rcvbuf[10],rcvbuf[11],rcvbuf[12]);
+
+ return 0;
+}
+
+
+static int pctv200e_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int i;
+
+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+ return -EAGAIN;
+
+ if (num > 2)
+ warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+ for (i = 0; i < num; i++) {
+ /* write/read request */
+ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+ if (pctv200e_ctrl_msg(d, msg[i].addr,USB_READ, msg[i].buf[0], NULL, 0, msg[i+1].buf,msg[i+1].len) < 0)
+ break;
+ i++;
+ } else
+ if (pctv200e_ctrl_msg(d,msg[i].addr,USB_WRITE, msg[i].buf[0],&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
+ break;
+ }
+
+ mutex_unlock(&d->i2c_mutex);
+ if (dvb_usb_pctv200e_debug)
+ warn("pctv200e_i2c_xfer() called.");
+ return i;
+}
+
+static u32 pctv200e_i2c_func(struct i2c_adapter *adapter)
+{
+ warn ("pctv200e_i2c_func: entering, done nothing");
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm pctv200e_i2c_algo = {
+ .master_xfer = pctv200e_i2c_xfer,
+ .functionality = pctv200e_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int pctv200e_identify_state (struct usb_device *udev, struct
+ dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+ return 0;
+}
+// probably this needs to be changed.
+static int pctv200e_mt352_demod_init(struct dvb_frontend *fe)
+{
+// We implement the RESET sequence for the demod mt352
+ static u8 clock_config [] = { CLOCK_CTL, 0xbd, 0x28 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 reset_stop [] = { RESET, 0x00 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x1c };
+// static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x30 };
+
+ static u8 input_freq[] = { INPUT_FREQ_1, 0x31, 0xb5 };
+ static u8 clock_ratio[] = { MCLK_RATIO, 0x00 };
+ static u8 scan_ctl[] = { SCAN_CTL, 0x0d };
+ static u8 unknown_1[] = { UNKNOWN_1, 0x04 };
+
+ static u8 acq_ctl[] = { ACQ_CTL, 0xf4 };
+
+ static u8 trl_nominal_rate[] = { TRL_NOMINAL_RATE_1, 0x73, 0x1c };
+
+ static u8 unknown_2[] = { UNKNOWN_2, 0x00, 0x00, 0x80, 0x20, 0x80, 0x80, 0x55, 0x62, 0x00 };
+
+ static u8 unknown_3[] = { UNKNOWN_3, 0x01 };
+
+// static u8 snr_select_1[] = { SNR_SELECT_1, 0x20, 0x00 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(1000);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, reset_stop, sizeof(reset_stop));
+
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+ mt352_write(fe, input_freq, sizeof(input_freq));
+ mt352_write(fe, clock_ratio, sizeof(clock_ratio));
+ mt352_write(fe, scan_ctl, sizeof(scan_ctl));
+
+ mt352_write(fe, unknown_1, sizeof(unknown_1));
+
+ mt352_write(fe, acq_ctl, sizeof(acq_ctl));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, trl_nominal_rate, sizeof(trl_nominal_rate));
+
+ mt352_write(fe, unknown_2, sizeof(unknown_2));
+ mt352_write(fe, unknown_3, sizeof(unknown_3));
+
+// mt352_write(fe, snr_select_1, sizeof(snr_select_1));
+// mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+
+ warn ("PCTV200e initialized mt352");
+ return 0;
+}
+
+static struct mt352_config pctv200e_mt352_config = {
+ .demod_address = 0x3e,
+ .demod_init = pctv200e_mt352_demod_init,
+ .no_tuner = 1,
+ .adc_clock = 20333,
+ .if2 = 56468,
+};
+
+static struct mt2060_config pctv200e_mt2060_config = {
+ .i2c_address = 0xc0,
+ .clock_out = 1,
+};
+
+/*
+static int pctv200e_mt2060_tuner_set_params(struct v4l_dvb_tuner_ops *ops, struct dvb_int_frontend_parameters *fep)
+{
+ warn ("pctv200e_mt2060_tuner_set_params: setting parameters!");
+
+ ops->set_params (ops,fep);
+
+ // ret = fe->ops.tuner_ops.set_params(fe, fep);
+
+ return 0;
+}
+*/
+
+static u16 if1 = 1220; // this is probably wrong, but we need some value to compile this shite
+
+
+// source (for the tuner attach: dibusb-common.c)
+static int pctv200e_frontend_attach(struct dvb_usb_adapter *adap)
+{
+ warn(" trying to attach a frontend.");
+ static u8 cmd_buf3[] = { 0x10, 0xED};
+ static u8 cmd_buf4[] = { 0x11, 0x41};
+ static u8 cmd_buf5[] = { 0x12, 0x01};
+ // Sending "0x18 0x01" turns the antenna power on
+ // Sending "0x18 0x00" turns the antenna power off
+ static u8 cmd_buf6[] = { 0x18, 0x01};
+
+ if ((adap->fe = dvb_attach(mt352_attach, &pctv200e_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+ // adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ warn(" attaching and initializing mt352frontend attached.");
+// pctv200e_cmd_msg(adap->dev, cmd_buf1, sizeof(cmd_buf1));
+ pctv200e_mt352_demod_init (adap->fe);
+ // Send, maybe is start command?
+// pctv200e_cmd_msg(adap->dev, cmd_buf1, sizeof(cmd_buf1));
+// pctv200e_cmd_msg(adap->dev, cmd_buf2, sizeof(cmd_buf2));
+ pctv200e_cmd_msg(adap->dev, cmd_buf3, sizeof(cmd_buf3));
+ pctv200e_cmd_msg(adap->dev, cmd_buf4, sizeof(cmd_buf4));
+ pctv200e_cmd_msg(adap->dev, cmd_buf5, sizeof(cmd_buf5));
+ pctv200e_cmd_msg(adap->dev, cmd_buf6, sizeof(cmd_buf6));
+// pctv200e_cmd_msg(adap->dev, cmd_buf1, sizeof(cmd_buf1));
+
+ warn(" frontend attached.");
+ return 0;
+ }
+ warn(" frontend attach FAILED.");
+ return -EIO;
+}
+
+static int pctv200e_tuner_attach(struct dvb_usb_adapter *adap)
+{
+
+ warn(" trying to attach a tuner.");
+ // adap->fe->ops.tuner_ops.fe = adap->fe;
+
+// if ((adap->fe = dvb_attach(mt2060_attach, &adap->fe->ops.tuner_ops,
+// if ((dvb_attach(mt2060_attach, &adap->fe->ops.tuner_ops,
+ if ((dvb_attach(mt2060_attach, adap->fe,
+ &adap->dev->i2c_adap, &pctv200e_mt2060_config, if1)) != NULL) {
+ // adap->fe->ops.tuner_ops.fe = adap->fe;
+// adap->fe->ops.tuner_ops.set_params = pctv200e_mt2060_tuner_set_params;
+// adap->pll_addr = 0xc0;
+ // adap->pll_desc = &dvb_pll_tded4;
+ warn("tuner mt2060 attached.");
+ // if (!dvb_attach(dvb_pll_attach, adap->fe, 0xc0, NULL, DVB_PLL_TDED4)) return -ENODEV;
+ // warn("pll tuner attached.");
+ return 0;
+ }
+
+ warn("frontend_attach failed (mt2060)");
+
+ return -EIO;
+}
+
+// currently not aim of my mission
+#if 0
+
+static struct dvb_usb_rc_key pctv200e_rc_keys[] = {
+ { 0x5f, 0x55, KEY_0 },
+ { 0x6f, 0x55, KEY_1 },
+ { 0x9f, 0x55, KEY_2 },
+ { 0xaf, 0x55, KEY_3 },
+ { 0x5f, 0x56, KEY_4 },
+ { 0x6f, 0x56, KEY_5 },
+ { 0x9f, 0x56, KEY_6 },
+ { 0xaf, 0x56, KEY_7 },
+ { 0x5f, 0x59, KEY_8 },
+ { 0x6f, 0x59, KEY_9 },
+ { 0x9f, 0x59, KEY_TV },
+ { 0xaf, 0x59, KEY_AUX },
+ { 0x5f, 0x5a, KEY_DVD },
+ { 0x6f, 0x5a, KEY_POWER },
+ { 0x9f, 0x5a, KEY_MHP }, /* labelled 'Picture' */
+ { 0xaf, 0x5a, KEY_AUDIO },
+ { 0x5f, 0x65, KEY_INFO },
+ { 0x6f, 0x65, KEY_F13 }, /* 16:9 */
+ { 0x9f, 0x65, KEY_F14 }, /* 14:9 */
+ { 0xaf, 0x65, KEY_EPG },
+ { 0x5f, 0x66, KEY_EXIT },
+ { 0x6f, 0x66, KEY_MENU },
+ { 0x9f, 0x66, KEY_UP },
+ { 0xaf, 0x66, KEY_DOWN },
+ { 0x5f, 0x69, KEY_LEFT },
+ { 0x6f, 0x69, KEY_RIGHT },
+ { 0x9f, 0x69, KEY_ENTER },
+ { 0xaf, 0x69, KEY_CHANNELUP },
+ { 0x5f, 0x6a, KEY_CHANNELDOWN },
+ { 0x6f, 0x6a, KEY_VOLUMEUP },
+ { 0x9f, 0x6a, KEY_VOLUMEDOWN },
+ { 0xaf, 0x6a, KEY_RED },
+ { 0x5f, 0x95, KEY_GREEN },
+ { 0x6f, 0x95, KEY_YELLOW },
+ { 0x9f, 0x95, KEY_BLUE },
+ { 0xaf, 0x95, KEY_SUBTITLE },
+ { 0x5f, 0x96, KEY_F15 }, /* AD */
+ { 0x6f, 0x96, KEY_TEXT },
+ { 0x9f, 0x96, KEY_MUTE },
+ { 0xaf, 0x96, KEY_REWIND },
+ { 0x5f, 0x99, KEY_STOP },
+ { 0x6f, 0x99, KEY_PLAY },
+ { 0x9f, 0x99, KEY_FASTFORWARD },
+ { 0xaf, 0x99, KEY_F16 }, /* chapter */
+ { 0x5f, 0x9a, KEY_PAUSE },
+ { 0x6f, 0x9a, KEY_PLAY },
+ { 0x9f, 0x9a, KEY_RECORD },
+ { 0xaf, 0x9a, KEY_F17 }, /* picture in picture */
+ { 0x5f, 0xa5, KEY_KPPLUS }, /* zoom in */
+ { 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */
+ { 0x9f, 0xa5, KEY_F18 }, /* capture */
+ { 0xaf, 0xa5, KEY_F19 }, /* web */
+ { 0x5f, 0xa6, KEY_EMAIL },
+ { 0x6f, 0xa6, KEY_PHONE },
+ { 0x9f, 0xa6, KEY_PC },
+};
+
+static int pctv200e_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ int i;
+ u8 key[5];
+ u8 b[4] = { 0 };
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ pctv200e_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
+
+ /* Tell the device we've read the remote. Not sure how necessary
+ this is, but the Nebula SDK does it. */
+ pctv200e_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+
+ /* if something is inside the buffer, simulate key press */
+ if (key[1] != 0)
+ {
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (d->props.rc_key_map[i].custom == key[1] &&
+ d->props.rc_key_map[i].data == key[2]) {
+ *event = d->props.rc_key_map[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ return 0;
+ }
+ }
+ }
+
+ if (key[0] != 0)
+ warn("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+ return 0;
+}
+#endif
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties pctv200e_properties;
+
+static int pctv200e_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+// Scheduled for removal [GDC]
+// struct dvb_usb_device *d;
+// cause we removed &d from next one.
+ int ret;
+ if ((ret = dvb_usb_device_init(intf, &pctv200e_properties,
+ THIS_MODULE, NULL, adapter_nr)) == 0) {
+#if 0
+ u8 b[4] = { 0 };
+// Do not know if we use this here, or change all the functions to take
+// an adapter_nr as parameter.
+ struct dvb_usb_device *d = i2c_get_adapdata(adapter_nr);
+ /* do we need that?? */
+ if (d != NULL) { /* do that only when the firmware is loaded */
+ b[0] = 1;
+ pctv200e_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+
+ b[0] = 0;
+ pctv200e_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+ }
+#endif
+ }
+ warn("usb_device_init sucessfull.");
+ return ret;
+}
+
+
+static struct usb_device_id pctv200e_table [] = {
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_200E) },
+ { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_60E) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, pctv200e_table);
+
+// change me
+static struct dvb_usb_device_properties pctv200e_properties = {
+ .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING | DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = CYPRESS_FX2,
+ //.firmware = "dvb-usb-digitv-02.fw", // no!
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .frontend_attach = pctv200e_frontend_attach,
+ .tuner_attach = pctv200e_tuner_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ }
+ },
+ .identify_state = pctv200e_identify_state,
+
+ /*.rc_interval = 1000,
+ .rc_key_map = pctv200e_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(pctv200e_rc_keys),
+ .rc_query = pctv200e_rc_query,*/
+
+ .i2c_algo = &pctv200e_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ .num_device_descs = 2,
+ .devices = {
+ { "Pinnacle PCTV 200e DVB-T",
+ { &pctv200e_table[0], NULL },
+ { NULL },
+ },
+ { "Pinnacle PCTV 60e DVB-T",
+ { &pctv200e_table[1], NULL },
+ { NULL },
+ },
+ { NULL },
+ }
+};
+
+static struct usb_driver pctv200e_driver = {
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)
+ .owner = THIS_MODULE,
+#endif
+ .name = "dvb_usb_pctv200e",
+ .probe = pctv200e_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = pctv200e_table,
+};
+
+/* module stuff */
+static int __init pctv200e_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&pctv200e_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+ warn("usb_register successfull.");
+
+ return 0;
+}
+
+static void __exit pctv200e_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ warn("usb_DEregister started.");
+ usb_deregister(&pctv200e_driver);
+ warn("usb_DEregister successfull.");
+}
+
+module_init (pctv200e_module_init);
+module_exit (pctv200e_module_exit);
+
+MODULE_AUTHOR("Jakob Steidl <jakob.steidl@gmail.com>, Gabriele Dini Ciacci <gabriele@diniciacci.org>");
+MODULE_DESCRIPTION("Driver for Pinnacle PCTV 200e and 60e DVB-T USB2.0");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff -uprN v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.h my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.h
--- v4l-dvd/linux/drivers/media/dvb/dvb-usb/pctv200e.h 1970-01-01 01:00:00.000000000 +0100
+++ my_v4l-dvb/linux/drivers/media/dvb/dvb-usb/pctv200e.h 2008-01-02 02:09:34.000000000 +0100
@@ -0,0 +1,35 @@
+#ifndef _DVB_USB_PCTV200E_H_
+#define _DVB_USB_PCTV200E_H_
+
+#define DVB_USB_LOG_PREFIX "pctv200e"
+#include "dvb-usb.h"
+
+extern int dvb_usb_pctv200e_debug;
+#define deb_rc(args...) dprintk(dvb_usb_pctv200e_debug,0x01,args)
+
+/*
+#define USB_READ_EEPROM 1
+
+#define USB_READ_COFDM 2
+#define USB_WRITE_COFDM 5
+
+#define USB_WRITE_TUNER 6
+
+#define USB_READ_REMOTE 3
+#define USB_WRITE_REMOTE 7
+#define USB_WRITE_REMOTE_TYPE 8
+
+#define USB_DEV_INIT 9
+*/
+
+
+#define USB_READ 1
+#define USB_WRITE 2
+
+#define TUNER_ADDR 0xc0
+#define DEMUX_ADDR 0x3e
+
+
+
+
+#endif
next reply other threads:[~2009-03-29 14:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-29 13:56 Gabriele Dini Ciacci [this message]
2009-03-31 10:56 ` [PATCH] Drivers for Pinnacle pctv200e and pctv60e Mauro Carvalho Chehab
2009-03-31 19:20 ` Gabriele Dini Ciacci
2009-03-31 20:59 ` Devin Heitmueller
2009-03-31 21:35 ` Gabriele Dini Ciacci
2009-03-31 21:51 ` Devin Heitmueller
2009-03-31 22:47 ` Gabriele Dini Ciacci
2009-04-01 7:34 ` Patrick Boettcher
2009-04-01 15:27 ` Patrick Boettcher
2009-04-01 18:28 ` Gabriele Dini Ciacci
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090329155608.396d2257@gdc1 \
--to=dark.schneider@iol.it \
--cc=linux-media@vger.kernel.org \
--cc=patrick.boettcher@desy.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.