// SPDX-License-Identifier: GPL-2.0+ // // em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB // video capture devices // // Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> // Markus Rechberger <mrechberger@gmail.com> // Mauro Carvalho Chehab <mchehab@kernel.org> // Sascha Sommer <saschasommer@freenet.de> // Copyright (C) 2012 Frank Schäfer <fschaefer.oss@googlemail.com> // // Some parts based on SN9C10x PC Camera Controllers GPL driver made // by Luca Risolia <luca.risolia@studio.unibo.it>
fmt = v4l2->format->reg; if (!dev->is_em25xx)
fmt |= 0x20; /* * NOTE: it's not clear if this is really needed ! * The datasheets say bit 5 is a reserved bit and devices seem to work * fine without it. But the Windows driver sets it for em2710/50+em28xx * devices and we've always been setting it, too. * * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set, * it's likely used for an additional (compressed ?) format there.
*/
ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt); if (ret < 0) return ret;
ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, v4l2->vinmode); if (ret < 0) return ret;
buf[0] = v;
buf[1] = v >> 8;
em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2); /* * it seems that both H and V scalers must be active * to work correctly
*/
mode = (h || v) ? 0x30 : 0x00;
} return em28xx_write_reg(dev, EM28XX_R26_COMPR, mode);
}
/* FIXME: this only function read values from dev */ staticint em28xx_resolution_set(struct em28xx *dev)
{ struct em28xx_v4l2 *v4l2 = dev->v4l2; int width = norm_maxw(dev); int height = norm_maxh(dev);
/* * If we don't set the start position to 2 in VBI mode, we end up * with line 20/21 being YUYV encoded instead of being in 8-bit * greyscale. The core of the issue is that line 21 (and line 23 for * PAL WSS) are inside of active video region, and as a result they * get the pixelformatting associated with that area. So by cropping * it out, we end up with the same format as the rest of the VBI * region
*/ if (em28xx_vbi_supported(dev) == 1)
em28xx_capture_area_set(dev, 0, 2, width, height); else
em28xx_capture_area_set(dev, 0, 0, width, height);
/* Set USB alternate setting for analog video */ staticint em28xx_set_alternate(struct em28xx *dev)
{ struct em28xx_v4l2 *v4l2 = dev->v4l2; struct usb_device *udev = interface_to_usbdev(dev->intf); int err; int i; unsignedint min_pkt_size = v4l2->width * 2 + 4;
/* * NOTE: for isoc transfers, only alt settings > 0 are allowed * bulk transfers seem to work only with alt=0 !
*/
dev->alt = 0; if (alt > 0 && alt < dev->num_alt) {
em28xx_videodbg("alternate forced to %d\n", dev->alt);
dev->alt = alt; goto set_alt;
} if (dev->analog_xfer_bulk) goto set_alt;
/* * When image size is bigger than a certain value, * the frame size should be increased, otherwise, only * green screen will be received.
*/ if (v4l2->width * 2 * v4l2->height > 720 * 240 * 2)
min_pkt_size *= 2;
for (i = 0; i < dev->num_alt; i++) { /* stop when the selected alt setting offers enough bandwidth */ if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
dev->alt = i; break; /* * otherwise make sure that we end up with the maximum * bandwidth because the min_pkt_size equation might be wrong. *
*/
} elseif (dev->alt_max_pkt_size_isoc[i] >
dev->alt_max_pkt_size_isoc[dev->alt])
dev->alt = i;
}
set_alt: /* * NOTE: for bulk transfers, we need to call usb_set_interface() * even if the previous settings were the same. Otherwise streaming * fails with all urbs having status = -EOVERFLOW !
*/ if (dev->analog_xfer_bulk) {
dev->max_pkt_size = 512; /* USB 2.0 spec */
dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
} else { /* isoc */
em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
min_pkt_size, dev->alt);
dev->max_pkt_size =
dev->alt_max_pkt_size_isoc[dev->alt];
dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
}
em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
dev->alt, dev->max_pkt_size);
err = usb_set_interface(udev, dev->ifnum, dev->alt); if (err < 0) {
dev_err(&dev->intf->dev, "cannot change alternate number to %d (error=%i)\n",
dev->alt, err); return err;
} return 0;
}
/* * DMA and thread functions
*/
/* * Finish the current buffer
*/ staticinlinevoid finish_buffer(struct em28xx *dev, struct em28xx_buffer *buf)
{
em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
/* * Copy picture data from USB buffer to video buffer
*/ staticvoid em28xx_copy_video(struct em28xx *dev, struct em28xx_buffer *buf, unsignedchar *usb_buf, unsignedlong len)
{ struct em28xx_v4l2 *v4l2 = dev->v4l2; void *fieldstart, *startwrite, *startread; int linesdone, currlinedone, offset, lencopy, remain; int bytesperline = v4l2->width << 1;
if (buf->pos + len > buf->length)
len = buf->length - buf->pos;
startread = usb_buf;
remain = len;
if (v4l2->progressive || buf->top_field)
fieldstart = buf->vb_buf; else/* interlaced mode, even nr. of lines */
fieldstart = buf->vb_buf + bytesperline;
/* * Copy VBI data from USB buffer to video buffer
*/ staticvoid em28xx_copy_vbi(struct em28xx *dev, struct em28xx_buffer *buf, unsignedchar *usb_buf, unsignedlong len)
{ unsignedint offset;
if (buf->pos + len > buf->length)
len = buf->length - buf->pos;
offset = buf->pos; /* Make sure the bottom field populates the second half of the frame */ if (buf->top_field == 0)
offset += dev->v4l2->vbi_width * dev->v4l2->vbi_height;
staticinlinevoid print_err_status(struct em28xx *dev, int packet, int status)
{ char *errmsg = "Unknown";
switch (status) { case -ENOENT:
errmsg = "unlinked synchronously"; break; case -ECONNRESET:
errmsg = "unlinked asynchronously"; break; case -ENOSR:
errmsg = "Buffer error (overrun)"; break; case -EPIPE:
errmsg = "Stalled (device not responding)"; break; case -EOVERFLOW:
errmsg = "Babble (bad cable?)"; break; case -EPROTO:
errmsg = "Bit-stuff error (bad cable?)"; break; case -EILSEQ:
errmsg = "CRC/Timeout (could be anything)"; break; case -ETIME:
errmsg = "Device does not respond"; break;
} if (packet < 0) {
em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
} else {
em28xx_isocdbg("URB packet %d, status %d [%s].\n",
packet, status, errmsg);
}
}
/* * get the next available buffer from dma queue
*/ staticinlinestruct em28xx_buffer *get_next_buf(struct em28xx *dev, struct em28xx_dmaqueue *dma_q)
{ struct em28xx_buffer *buf;
if (list_empty(&dma_q->active)) {
em28xx_isocdbg("No active queue to serve\n"); return NULL;
}
/* Get the next buffer */
buf = list_entry(dma_q->active.next, struct em28xx_buffer, list); /* Cleans up buffer - Useful for testing for frame/URB loss */
list_del(&buf->list);
buf->pos = 0;
buf->vb_buf = buf->mem;
return buf;
}
/* * Finish the current buffer if completed and prepare for the next field
*/ staticstruct em28xx_buffer *
finish_field_prepare_next(struct em28xx *dev, struct em28xx_buffer *buf, struct em28xx_dmaqueue *dma_q)
{ struct em28xx_v4l2 *v4l2 = dev->v4l2;
if (v4l2->progressive || v4l2->top_field) { /* Brand new frame */ if (buf)
finish_buffer(dev, buf);
buf = get_next_buf(dev, dma_q);
} if (buf) {
buf->top_field = v4l2->top_field;
buf->pos = 0;
}
return buf;
}
/* * Process data packet according to the em2710/em2750/em28xx frame data format
*/ staticinlinevoid process_frame_data_em28xx(struct em28xx *dev, unsignedchar *data_pkt, unsignedint data_len)
{ struct em28xx_v4l2 *v4l2 = dev->v4l2; struct em28xx_buffer *buf = dev->usb_ctl.vid_buf; struct em28xx_buffer *vbi_buf = dev->usb_ctl.vbi_buf; struct em28xx_dmaqueue *dma_q = &dev->vidq; struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
/* * capture type 0 = vbi start * capture type 1 = vbi in progress * capture type 2 = video start * capture type 3 = video in progress
*/ if (data_len >= 4) { /* * NOTE: Headers are always 4 bytes and * never split across packets
*/ if (data_pkt[0] == 0x88 && data_pkt[1] == 0x88 &&
data_pkt[2] == 0x88 && data_pkt[3] == 0x88) { /* Continuation */
data_pkt += 4;
data_len -= 4;
} elseif (data_pkt[0] == 0x33 && data_pkt[1] == 0x95) { /* Field start (VBI mode) */
v4l2->capture_type = 0;
v4l2->vbi_read = 0;
em28xx_isocdbg("VBI START HEADER !!!\n");
v4l2->top_field = !(data_pkt[2] & 1);
data_pkt += 4;
data_len -= 4;
} elseif (data_pkt[0] == 0x22 && data_pkt[1] == 0x5a) { /* Field start (VBI disabled) */
v4l2->capture_type = 2;
em28xx_isocdbg("VIDEO START HEADER !!!\n");
v4l2->top_field = !(data_pkt[2] & 1);
data_pkt += 4;
data_len -= 4;
}
} /* * NOTE: With bulk transfers, intermediate data packets * have no continuation header
*/
/* * Process data packet according to the em25xx/em276x/7x/8x frame data format
*/ staticinlinevoid process_frame_data_em25xx(struct em28xx *dev, unsignedchar *data_pkt, unsignedint data_len)
{ struct em28xx_buffer *buf = dev->usb_ctl.vid_buf; struct em28xx_dmaqueue *dmaq = &dev->vidq; struct em28xx_v4l2 *v4l2 = dev->v4l2; bool frame_end = false;
/* Check for header */ /* * NOTE: at least with bulk transfers, only the first packet * has a header and has always set the FRAME_END bit
*/ if (data_len >= 2) { /* em25xx header is only 2 bytes long */ if ((data_pkt[0] == EM25XX_FRMDATAHDR_BYTE1) &&
((data_pkt[1] & ~EM25XX_FRMDATAHDR_BYTE2_MASK) == 0x00)) {
v4l2->top_field = !(data_pkt[1] &
EM25XX_FRMDATAHDR_BYTE2_FRAME_ID);
frame_end = data_pkt[1] &
EM25XX_FRMDATAHDR_BYTE2_FRAME_END;
data_pkt += 2;
data_len -= 2;
}
/* Finish field and prepare next (BULK only) */ if (dev->analog_xfer_bulk && frame_end) {
buf = finish_field_prepare_next(dev, buf, dmaq);
dev->usb_ctl.vid_buf = buf;
} /* * NOTE: in ISOC mode when a new frame starts and buf==NULL, * we COULD already prepare a buffer here to avoid skipping the * first frame.
*/
}
/* Copy data */ if (buf && data_len > 0)
em28xx_copy_video(dev, buf, data_pkt, data_len);
/* Finish frame (ISOC only) => avoids lag of 1 frame */ if (!dev->analog_xfer_bulk && frame_end) {
buf = finish_field_prepare_next(dev, buf, dmaq);
dev->usb_ctl.vid_buf = buf;
}
/* * NOTES: * * 1) Tested with USB bulk transfers only ! * The wording in the datasheet suggests that isoc might work different. * The current code assumes that with isoc transfers each packet has a * header like with the other em28xx devices. * * 2) Support for interlaced mode is pure theory. It has not been * tested and it is unknown if these devices actually support it.
*/
}
/* Processes and copies the URB data content (video and VBI data) */ staticinlineint em28xx_urb_data_copy(struct em28xx *dev, struct urb *urb)
{ int xfer_bulk, num_packets, i; unsignedchar *usb_data_pkt; unsignedint usb_data_len;
if (!dev) return 0;
if (dev->disconnected) return 0;
if (urb->status < 0)
print_err_status(dev, -1, urb->status);
/* * This will find the tuner that is connected into the decoder. * Technically, this is not 100% correct, as the device may be * using an analog input instead of the tuner. However, as we can't * do DVB streaming while the DMA engine is being used for V4L2, * this should be enough for the actual needs.
*/
list_for_each_entry(link, &v4l2->decoder->links, list) { if (link->sink->entity == v4l2->decoder) {
found_link = link; if (link->flags & MEDIA_LNK_FL_ENABLED)
active_links++; break;
}
}
/* Initialize Video, VBI and Radio pads */
v4l2->video_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad); if (ret < 0)
dev_err(&dev->intf->dev, "failed to initialize video media entity!\n");
if (em28xx_vbi_supported(dev)) {
v4l2->vbi_pad.flags = MEDIA_PAD_FL_SINK;
ret = media_entity_pads_init(&v4l2->vbi_dev.entity, 1,
&v4l2->vbi_pad); if (ret < 0)
dev_err(&dev->intf->dev, "failed to initialize vbi media entity!\n");
}
/* Webcams don't have input connectors */ if (dev->is_webcam) return;
/* Create entities for each input connector */ for (i = 0; i < MAX_EM28XX_INPUT; i++) { struct media_entity *ent = &dev->input_ent[i];
if (vb2_plane_size(vb, 0) < size) {
em28xx_videodbg("%s data will not fit into plane (%lu < %lu)\n",
__func__, vb2_plane_size(vb, 0), size); return -EINVAL;
}
vb2_set_plane_payload(vb, 0, size);
/* * djh: it's not clear whether this code is still needed. I'm * leaving it in here for now entirely out of concern for * backward compatibility (the old code did it)
*/
/* Ask tuner to go to analog or radio mode */
memset(&f, 0, sizeof(f));
f.frequency = v4l2->frequency;
owner = (struct v4l2_fh *)vq->owner; if (owner && owner->vdev->vfl_type == VFL_TYPE_RADIO)
f.type = V4L2_TUNER_RADIO; else
f.type = V4L2_TUNER_ANALOG_TV;
v4l2_device_call_all(&v4l2->v4l2_dev,
0, tuner, s_frequency, &f);
/* Enable video stream at TV decoder */
v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1);
}
/* * In the case of non-AC97 volume controls, we still need * to do some setups at em28xx, in order to mute/unmute * and to adjust audio volume. However, the value ranges * should be checked by the corresponding V4L subdriver.
*/ switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE:
dev->mute = ctrl->val;
em28xx_audio_analog_set(dev); break; case V4L2_CID_AUDIO_VOLUME:
dev->volume = ctrl->val;
em28xx_audio_analog_set(dev); break;
}
}
switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE:
dev->mute = ctrl->val;
ret = em28xx_audio_analog_set(dev); break; case V4L2_CID_AUDIO_VOLUME:
dev->volume = ctrl->val;
ret = em28xx_audio_analog_set(dev); break; case V4L2_CID_CONTRAST:
ret = em28xx_write_reg(dev, EM28XX_R20_YGAIN, ctrl->val); break; case V4L2_CID_BRIGHTNESS:
ret = em28xx_write_reg(dev, EM28XX_R21_YOFFSET, ctrl->val); break; case V4L2_CID_SATURATION:
ret = em28xx_write_reg(dev, EM28XX_R22_UVGAIN, ctrl->val); break; case V4L2_CID_BLUE_BALANCE:
ret = em28xx_write_reg(dev, EM28XX_R23_UOFFSET, ctrl->val); break; case V4L2_CID_RED_BALANCE:
ret = em28xx_write_reg(dev, EM28XX_R24_VOFFSET, ctrl->val); break; case V4L2_CID_SHARPNESS:
ret = em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, ctrl->val); break;
}
fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) {
fmt = &format[0];
em28xx_videodbg("Fourcc format (%08x) invalid. Using default (%08x).\n",
f->fmt.pix.pixelformat, fmt->fourcc);
}
if (dev->board.is_em2800) { /* the em2800 can only scale down to 50% */
height = height > (3 * maxh / 4) ? maxh : maxh / 2;
width = width > (3 * maxw / 4) ? maxw : maxw / 2; /* * MaxPacketSize for em2800 is too small to capture at full * resolution use half of maxw as the scaler can only scale * to 50%
*/ if (width == maxw && height == maxh)
width /= 2;
} else { /* * width must even because of the YUYV format * height must be even because of interlacing
*/
v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
1, 0);
} /* Avoid division by zero at size_to_scale */ if (width < 1)
width = 1; if (height < 1)
height = 1;
/* * With msp3400, almost all mappings use the default (amux = 0). * The only one may use a different value is WinTV USB2, where it * can also be SCART1 input. * As it is very doubtful that we would see new boards with msp3400, * let's just reuse the existing switch.
*/ if (dev->has_msp34xx && idx != EM28XX_AMUX_UNUSED)
idx = EM28XX_AMUX_LINE_IN;
switch (idx) { case EM28XX_AMUX_VIDEO:
strscpy(a->name, "Television", sizeof(a->name)); break; case EM28XX_AMUX_LINE_IN:
strscpy(a->name, "Line In", sizeof(a->name)); break; case EM28XX_AMUX_VIDEO2:
strscpy(a->name, "Television alt", sizeof(a->name)); break; case EM28XX_AMUX_PHONE:
strscpy(a->name, "Phone", sizeof(a->name)); break; case EM28XX_AMUX_MIC:
strscpy(a->name, "Mic", sizeof(a->name)); break; case EM28XX_AMUX_CD:
strscpy(a->name, "CD", sizeof(a->name)); break; case EM28XX_AMUX_AUX:
strscpy(a->name, "Aux", sizeof(a->name)); break; case EM28XX_AMUX_PCM_OUT:
strscpy(a->name, "PCM", sizeof(a->name)); break; case EM28XX_AMUX_UNUSED: default: return -EINVAL;
}
a->index = index;
a->capability = V4L2_AUDCAP_STEREO;
em28xx_videodbg("%s: audio input index %d is '%s'\n",
s, a->index, a->name);
/* * FIXME: This is wrong, as different inputs at em28xx_cards * may have different audio outputs. So, the right thing * to do is to implement VIDIOC_G_AUDOUT/VIDIOC_S_AUDOUT. * With the current board definitions, this would work fine, * as, currently, all boards fit.
*/ for (i = 0; i < MAX_EM28XX_INPUT; i++) if (idx == dev->amux_map[i]) break; if (i == MAX_EM28XX_INPUT) return -EINVAL;
dev->ctl_aoutput = INPUT(i)->aout;
if (!dev->ctl_aoutput)
dev->ctl_aoutput = EM28XX_AOUT_MASTER;
em28xx_videodbg("%s: set audio input to %d\n", __func__,
dev->ctl_ainput);
/* * em28xx_v4l2_fini() * unregisters the v4l2,i2c and usb devices * called when the device gets disconnected or at module unload
*/ staticint em28xx_v4l2_fini(struct em28xx *dev)
{ struct em28xx_v4l2 *v4l2 = dev->v4l2;
if (dev->is_audio_only) { /* Shouldn't initialize IR for this interface */ return 0;
}
if (!dev->has_video) { /* This device does not support the v4l2 extension */ return 0;
}
if (!v4l2) return 0;
dev_info(&dev->intf->dev, "Closing video extension\n");
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.