#define em28xx_regdbg(fmt, arg...) do { \ if (reg_debug) \
dev_printk(KERN_DEBUG, &dev->intf->dev, \ "reg: %s: " fmt, __func__, ## arg); \
} while (0)
/* FIXME: don't abuse core_debug */ #define em28xx_isocdbg(fmt, arg...) do { \ if (core_debug) \
dev_printk(KERN_DEBUG, &dev->intf->dev, \ "core: %s: " fmt, __func__, ## arg); \
} while (0)
/* * em28xx_read_reg_req() * reads data from the usb device specifying bRequest
*/ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, char *buf, int len)
{ int ret; struct usb_device *udev = interface_to_usbdev(dev->intf); int pipe = usb_rcvctrlpipe(udev, 0);
/* * em28xx_read_reg_req() * reads data from the usb device specifying bRequest
*/ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
{ int ret;
u8 val;
ret = em28xx_read_reg_req_len(dev, req, reg, &val, 1); if (ret < 0) return ret;
/* * em28xx_write_regs_req() * sends data to the usb device, specifying bRequest
*/ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len)
{ int ret; struct usb_device *udev = interface_to_usbdev(dev->intf); int pipe = usb_sndctrlpipe(udev, 0);
if (dev->disconnected) return -ENODEV;
if (len < 1 || len > URB_MAX_CTRL_SIZE) return -EINVAL;
if (dev->wait_after_write)
msleep(dev->wait_after_write);
return ret;
}
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
{ return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
}
EXPORT_SYMBOL_GPL(em28xx_write_regs);
/* Write a single register */ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val)
{ return em28xx_write_regs(dev, reg, &val, 1);
}
EXPORT_SYMBOL_GPL(em28xx_write_reg);
/* * em28xx_write_reg_bits() * sets only some bits (specified by bitmask) of a register, by first reading * the actual value
*/ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
u8 bitmask)
{ int oldval;
u8 newval;
oldval = em28xx_read_reg(dev, reg); if (oldval < 0) return oldval;
/* * em28xx_toggle_reg_bits() * toggles/inverts the bits (specified by bitmask) of a register
*/ int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask)
{ int oldval;
u8 newval;
oldval = em28xx_read_reg(dev, reg); if (oldval < 0) return oldval;
/* * em28xx_is_ac97_ready() * Checks if ac97 is ready
*/ staticint em28xx_is_ac97_ready(struct em28xx *dev)
{ unsignedlong timeout = jiffies + msecs_to_jiffies(EM28XX_AC97_XFER_TIMEOUT); int ret;
/* Wait up to 50 ms for AC97 command to complete */ while (time_is_after_jiffies(timeout)) {
ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY); if (ret < 0) return ret;
if (!(ret & 0x01)) return 0;
msleep(5);
}
dev_warn(&dev->intf->dev, "AC97 command still being executed: not handled properly!\n"); return -EBUSY;
}
/* * em28xx_read_ac97() * write a 16 bit value to the specified AC97 address (LSB first!)
*/ int em28xx_read_ac97(struct em28xx *dev, u8 reg)
{ int ret;
u8 addr = (reg & 0x7f) | 0x80;
__le16 val;
ret = em28xx_is_ac97_ready(dev); if (ret < 0) return ret;
ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); if (ret < 0) return ret;
ret = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R40_AC97LSB,
(u8 *)&val, sizeof(val));
if (ret < 0) return ret; return le16_to_cpu(val);
}
EXPORT_SYMBOL_GPL(em28xx_read_ac97);
/* * em28xx_write_ac97() * write a 16 bit value to the specified AC97 address (LSB first!)
*/ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val)
{ int ret;
u8 addr = reg & 0x7f;
__le16 value;
value = cpu_to_le16(val);
ret = em28xx_is_ac97_ready(dev); if (ret < 0) return ret;
ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *)&value, 2); if (ret < 0) return ret;
ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1); if (ret < 0) return ret;
/* * EM28XX_AMUX_VIDEO2 is a special case used to indicate that * em28xx should point to LINE IN, while AC97 should use VIDEO
*/ if (amux == EM28XX_AMUX_VIDEO2)
amux = EM28XX_AMUX_VIDEO;
/* Mute all entres but the one that were selected */ for (i = 0; i < ARRAY_SIZE(inputs); i++) { if (amux == inputs[i].mux)
ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808); else
ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000);
int em28xx_audio_analog_set(struct em28xx *dev)
{ int ret, i;
u8 xclk;
/* Set GPIOs here for boards without audio */ if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) return em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio);
/* * It is assumed that all devices use master volume for output. * It would be possible to use also line output.
*/ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { /* Mute all outputs */ for (i = 0; i < ARRAY_SIZE(outputs); i++) {
ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000); if (ret < 0)
dev_warn(&dev->intf->dev, "couldn't setup AC97 register %d\n",
outputs[i].reg);
}
}
xclk = dev->board.xclk & 0x7f; if (!dev->mute)
xclk |= EM28XX_XCLK_AUDIO_UNMUTE;
ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk); if (ret < 0) return ret;
usleep_range(10000, 11000);
/* Selects the proper audio input */
ret = em28xx_set_audio_source(dev);
/* Sets volume */ if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { int vol;
/* * Allocate URBs
*/ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk, int num_bufs, int max_pkt_size, int packet_multiplier)
{ struct em28xx_usb_bufs *usb_bufs; struct urb *urb; struct usb_device *udev = interface_to_usbdev(dev->intf); int i; int sb_size, pipe; int j, k;
em28xx_isocdbg("em28xx: called %s in mode %d\n", __func__, mode);
/* * Check mode and if we have an endpoint for the selected * transfer type, select buffer
*/ if (mode == EM28XX_DIGITAL_MODE) { if ((xfer_bulk && !dev->dvb_ep_bulk) ||
(!xfer_bulk && !dev->dvb_ep_isoc)) {
dev_err(&dev->intf->dev, "no endpoint for DVB mode and transfer type %d\n",
xfer_bulk > 0); return -EINVAL;
}
usb_bufs = &dev->usb_ctl.digital_bufs;
} elseif (mode == EM28XX_ANALOG_MODE) { if ((xfer_bulk && !dev->analog_ep_bulk) ||
(!xfer_bulk && !dev->analog_ep_isoc)) {
dev_err(&dev->intf->dev, "no endpoint for analog mode and transfer type %d\n",
xfer_bulk > 0); return -EINVAL;
}
usb_bufs = &dev->usb_ctl.analog_bufs;
} else {
dev_err(&dev->intf->dev, "invalid mode selected\n"); return -EINVAL;
}
/* De-allocates all pending stuff */
em28xx_uninit_usb_xfer(dev, mode);
usb_bufs->num_bufs = num_bufs;
usb_bufs->urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); if (!usb_bufs->urb) return -ENOMEM;
/* allocate urbs and transfer buffers */ for (i = 0; i < usb_bufs->num_bufs; i++) {
urb = usb_alloc_urb(usb_bufs->num_packets, GFP_KERNEL); if (!urb) {
em28xx_uninit_usb_xfer(dev, mode); return -ENOMEM;
}
usb_bufs->urb[i] = urb;
usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL); if (!usb_bufs->buf[i]) { for (i--; i >= 0; i--)
kfree(usb_bufs->buf[i]);
/* * Allocate URBs and start IRQ
*/ int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk, int num_bufs, int max_pkt_size, int packet_multiplier, int (*urb_data_copy)(struct em28xx *dev, struct urb *urb))
{ struct em28xx_dmaqueue *dma_q = &dev->vidq; struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq; struct em28xx_usb_bufs *usb_bufs; struct usb_device *udev = interface_to_usbdev(dev->intf); int i; int rc; int alloc;
em28xx_isocdbg("em28xx: called %s in mode %d\n", __func__, mode);
dev->usb_ctl.urb_data_copy = urb_data_copy;
if (mode == EM28XX_DIGITAL_MODE) {
usb_bufs = &dev->usb_ctl.digital_bufs; /* no need to free/alloc usb buffers in digital mode */
alloc = 0;
} else {
usb_bufs = &dev->usb_ctl.analog_bufs;
alloc = 1;
}
if (alloc) {
rc = em28xx_alloc_urbs(dev, mode, xfer_bulk, num_bufs,
max_pkt_size, packet_multiplier); if (rc) return rc;
}
if (xfer_bulk) {
rc = usb_clear_halt(udev, usb_bufs->urb[0]->pipe); if (rc < 0) {
dev_err(&dev->intf->dev, "failed to clear USB bulk endpoint stall/halt condition (error=%i)\n",
rc);
em28xx_uninit_usb_xfer(dev, mode); return rc;
}
}
/* submit urbs and enables IRQ */ for (i = 0; i < usb_bufs->num_bufs; i++) {
rc = usb_submit_urb(usb_bufs->urb[i], GFP_KERNEL); if (rc) {
dev_err(&dev->intf->dev, "submit of urb %i failed (error=%i)\n", i, rc);
em28xx_uninit_usb_xfer(dev, mode); return rc;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.