Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 38237
b: refs/heads/master
c: b7f5491
h: refs/heads/master
i:
  38235: 097c220
v: v3
  • Loading branch information
Patrick Boettcher authored and Mauro Carvalho Chehab committed Oct 3, 2006
1 parent 879be74 commit efef99c
Show file tree
Hide file tree
Showing 5 changed files with 527 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 136cafbf4a024b52ba0a10627217f03cea9ff9f8
refs/heads/master: b7f54910ce018f93a74211136be46c09cefd80e2
47 changes: 47 additions & 0 deletions trunk/drivers/media/dvb/dvb-usb/dib0700.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
*
* 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.
*
* Copyright (C) 2005-6 DiBcom, SA
*/
#ifndef _DIB0700_H_
#define _DIB0700_H_

#define DVB_USB_LOG_PREFIX "dib0700"
#include "dvb-usb.h"

#include "dib07x0.h"

extern int dvb_usb_dib0700_debug;
#define deb_info(args...) dprintk(dvb_usb_dib0700_debug,0x01,args)
#define deb_fw(args...) dprintk(dvb_usb_dib0700_debug,0x02,args)
#define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args)
#define deb_data(args...) dprintk(dvb_usb_dib0700_debug,0x08,args)

#define REQUEST_I2C_READ 0x2
#define REQUEST_I2C_WRITE 0x3
#define REQUEST_POLL_RC 0x4
#define REQUEST_JUMPRAM 0x8
#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( " " )

struct dib0700_state {
u8 channel_state;
u8 mt2060_if1[2];
};

extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
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;

extern int dib0700_device_count;
extern struct dvb_usb_device_properties dib0700_devices[];
extern struct usb_device_id dib0700_usb_id_table[];

#endif
264 changes: 264 additions & 0 deletions trunk/drivers/media/dvb/dvb-usb/dib0700_core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
*
* 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.
*
* Copyright (C) 2005-6 DiBcom, SA
*/
#include "dib0700.h"

/* debug */
int dvb_usb_dib0700_debug;
module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);

/* expecting rx buffer: request data[0] data[1] ... data[2] */
static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
{
int status;

deb_data(">>> ");
debug_dump(tx,txlen,deb_data);

status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0),
tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen,
USB_CTRL_GET_TIMEOUT);

if (status != txlen)
err("ep 0 write error (status = %d, len: %d)",status,txlen);

return status < 0 ? status : 0;
}

/* expecting tx buffer: request data[0] ... data[n] (n <= 4) */
static int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
{
u16 index, value;
int status;

if (txlen < 2) {
err("tx buffer length is smaller than 2. Makes no sense.");
return -EINVAL;
}
if (txlen > 4) {
err("tx buffer length is larger than 4. Not supported.");
return -EINVAL;
}

deb_data(">>> ");
debug_dump(tx,txlen,deb_data);

value = ((txlen - 2) << 8) | tx[1];
index = 0;
if (txlen > 2)
index |= (tx[2] << 8);
if (txlen > 3)
index |= tx[3];

/* think about swapping here */
value = le16_to_cpu(value);
index = le16_to_cpu(index);

status = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), tx[0],
USB_TYPE_VENDOR | USB_DIR_IN, value, index, rx, rxlen,
USB_CTRL_GET_TIMEOUT);

if (status < 0)
err("ep 0 read error (status = %d)",status);

deb_data("<<< ");
debug_dump(rx,rxlen,deb_data);

return status; /* length in case of success */
}

int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
{
u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
return dib0700_ctrl_wr(d,buf,3);
}

/*
* I2C master xfer function
*/
static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i,len;
u8 buf[255];

if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;

for (i = 0; i < num; i++) {
/* fill in the address */
buf[1] = (msg[i].addr << 1);
/* fill the buffer */
memcpy(&buf[2], msg[i].buf, msg[i].len);

/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
buf[0] = REQUEST_I2C_READ;
buf[1] |= 1;

/* special thing in the current firmware: when length is zero the read-failed */
if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0)
break;

msg[i+1].len = len;

i++;
} else {
buf[0] = REQUEST_I2C_WRITE;
if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0)
break;
}
}

mutex_unlock(&d->i2c_mutex);
return i;
}

static u32 dib0700_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}

struct i2c_algorithm dib0700_i2c_algo = {
.master_xfer = dib0700_i2c_xfer,
.functionality = dib0700_i2c_func,
};

static int dib0700_jumpram(struct usb_device *udev, u32 address)
{
int ret, actlen;
u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0,
(address >> 24) & 0xff,
(address >> 16) & 0xff,
(address >> 8) & 0xff,
address & 0xff };

if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
deb_fw("jumpram to 0x%x failed\n",address);
return ret;
}
if (actlen != 8) {
deb_fw("jumpram to 0x%x failed\n",address);
return -EIO;
}
return 0;
}

int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
{
struct hexline hx;
int pos = 0, ret, act_len;

u8 buf[260];

while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
deb_fwdata("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr, hx.len, hx.chk);

buf[0] = hx.len;
buf[1] = hx.addr >> 8;
buf[2] = hx.addr & 0xff;
buf[3] = hx.type;
memcpy(&buf[4],hx.data,hx.len);
buf[4+hx.len] = hx.chk;

ret = usb_bulk_msg(udev,
usb_sndbulkpipe(udev, 0x01),
buf,
hx.len + 5,
&act_len,
1000);

if (ret < 0) {
err("firmware download failed at %d with %d",pos,ret);
return ret;
}
}

if (ret == 0) {
/* start the firmware */
if ((ret = dib0700_jumpram(udev,0x70000000)) == 0)
info("firmware started successfully.");
} else
ret = -EIO;

return ret;
}

int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
struct dib0700_state *st = adap->dev->priv;
u8 b[4];

b[0] = REQUEST_ENABLE_VIDEO;
b[1] = 0x00;
b[2] = (0x01 << 4); /* Master mode */
b[3] = 0x00;

deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);

if (onoff)
st->channel_state |= 1 << adap->id;
else
st->channel_state &= ~(1 << adap->id);

b[2] |= st->channel_state;

if (st->channel_state) /* if at least one channel is active */
b[1] = (0x01 << 4) | 0x00;

deb_info("data for streaming: %x %x\n",b[1],b[2]);

return dib0700_ctrl_wr(adap->dev, b, 4);
}

static int dib0700_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int i;

for (i = 0; i < dib0700_device_count; i++)
if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, NULL) == 0)
return 0;

return -ENODEV;
}

static struct usb_driver dib0700_driver = {
.name = "dvb_usb_dib0700",
.probe = dib0700_probe,
.disconnect = dvb_usb_device_exit,
.id_table = dib0700_usb_id_table,
};

/* module stuff */
static int __init dib0700_module_init(void)
{
int result;
info("loaded with support for %d different device-types", dib0700_device_count);
if ((result = usb_register(&dib0700_driver))) {
err("usb_register failed. Error number %d",result);
return result;
}

return 0;
}

static void __exit dib0700_module_exit(void)
{
/* deregister this driver from the USB subsystem */
usb_deregister(&dib0700_driver);
}

module_init (dib0700_module_init);
module_exit (dib0700_module_exit);

MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
Loading

0 comments on commit efef99c

Please sign in to comment.