Path: blob/master/drivers/media/video/cx18/cx18-streams.c
17687 views
/*1* cx18 init/start/stop/exit stream functions2*3* Derived from ivtv-streams.c4*5* Copyright (C) 2007 Hans Verkuil <[email protected]>6* Copyright (C) 2008 Andy Walls <[email protected]>7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License as published by10* the Free Software Foundation; either version 2 of the License, or11* (at your option) any later version.12*13* This program is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*18* You should have received a copy of the GNU General Public License19* along with this program; if not, write to the Free Software20* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA21* 02111-1307 USA22*/2324#include "cx18-driver.h"25#include "cx18-io.h"26#include "cx18-fileops.h"27#include "cx18-mailbox.h"28#include "cx18-i2c.h"29#include "cx18-queue.h"30#include "cx18-ioctl.h"31#include "cx18-streams.h"32#include "cx18-cards.h"33#include "cx18-scb.h"34#include "cx18-dvb.h"3536#define CX18_DSP0_INTERRUPT_MASK 0xd0004C3738static struct v4l2_file_operations cx18_v4l2_enc_fops = {39.owner = THIS_MODULE,40.read = cx18_v4l2_read,41.open = cx18_v4l2_open,42/* FIXME change to video_ioctl2 if serialization lock can be removed */43.unlocked_ioctl = cx18_v4l2_ioctl,44.release = cx18_v4l2_close,45.poll = cx18_v4l2_enc_poll,46.mmap = cx18_v4l2_mmap,47};4849/* offset from 0 to register ts v4l2 minors on */50#define CX18_V4L2_ENC_TS_OFFSET 1651/* offset from 0 to register pcm v4l2 minors on */52#define CX18_V4L2_ENC_PCM_OFFSET 2453/* offset from 0 to register yuv v4l2 minors on */54#define CX18_V4L2_ENC_YUV_OFFSET 325556static struct {57const char *name;58int vfl_type;59int num_offset;60int dma;61enum v4l2_buf_type buf_type;62} cx18_stream_info[] = {63{ /* CX18_ENC_STREAM_TYPE_MPG */64"encoder MPEG",65VFL_TYPE_GRABBER, 0,66PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,67},68{ /* CX18_ENC_STREAM_TYPE_TS */69"TS",70VFL_TYPE_GRABBER, -1,71PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,72},73{ /* CX18_ENC_STREAM_TYPE_YUV */74"encoder YUV",75VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,76PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,77},78{ /* CX18_ENC_STREAM_TYPE_VBI */79"encoder VBI",80VFL_TYPE_VBI, 0,81PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,82},83{ /* CX18_ENC_STREAM_TYPE_PCM */84"encoder PCM audio",85VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,86PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,87},88{ /* CX18_ENC_STREAM_TYPE_IDX */89"encoder IDX",90VFL_TYPE_GRABBER, -1,91PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,92},93{ /* CX18_ENC_STREAM_TYPE_RAD */94"encoder radio",95VFL_TYPE_RADIO, 0,96PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,97},98};99100101void cx18_dma_free(struct videobuf_queue *q,102struct cx18_stream *s, struct cx18_videobuf_buffer *buf)103{104videobuf_waiton(q, &buf->vb, 0, 0);105videobuf_vmalloc_free(&buf->vb);106buf->vb.state = VIDEOBUF_NEEDS_INIT;107}108109static int cx18_prepare_buffer(struct videobuf_queue *q,110struct cx18_stream *s,111struct cx18_videobuf_buffer *buf,112u32 pixelformat,113unsigned int width, unsigned int height,114enum v4l2_field field)115{116struct cx18 *cx = s->cx;117int rc = 0;118119/* check settings */120buf->bytes_used = 0;121122if ((width < 48) || (height < 32))123return -EINVAL;124125buf->vb.size = (width * height * 2);126if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))127return -EINVAL;128129/* alloc + fill struct (if changed) */130if (buf->vb.width != width || buf->vb.height != height ||131buf->vb.field != field || s->pixelformat != pixelformat ||132buf->tvnorm != cx->std) {133134buf->vb.width = width;135buf->vb.height = height;136buf->vb.field = field;137buf->tvnorm = cx->std;138s->pixelformat = pixelformat;139140cx18_dma_free(q, s, buf);141}142143if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))144return -EINVAL;145146if (buf->vb.field == 0)147buf->vb.field = V4L2_FIELD_INTERLACED;148149if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {150buf->vb.width = width;151buf->vb.height = height;152buf->vb.field = field;153buf->tvnorm = cx->std;154s->pixelformat = pixelformat;155156rc = videobuf_iolock(q, &buf->vb, NULL);157if (rc != 0)158goto fail;159}160buf->vb.state = VIDEOBUF_PREPARED;161return 0;162163fail:164cx18_dma_free(q, s, buf);165return rc;166167}168169/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)1701440 is a single line of 4:2:2 YUV at 720 luma samples wide171*/172#define VB_MIN_BUFFERS 32173#define VB_MIN_BUFSIZE 4147200174175static int buffer_setup(struct videobuf_queue *q,176unsigned int *count, unsigned int *size)177{178struct cx18_stream *s = q->priv_data;179struct cx18 *cx = s->cx;180181*size = 2 * cx->cxhdl.width * cx->cxhdl.height;182if (*count == 0)183*count = VB_MIN_BUFFERS;184185while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)186(*count)--;187188q->field = V4L2_FIELD_INTERLACED;189q->last = V4L2_FIELD_INTERLACED;190191return 0;192}193194static int buffer_prepare(struct videobuf_queue *q,195struct videobuf_buffer *vb,196enum v4l2_field field)197{198struct cx18_videobuf_buffer *buf =199container_of(vb, struct cx18_videobuf_buffer, vb);200struct cx18_stream *s = q->priv_data;201struct cx18 *cx = s->cx;202203return cx18_prepare_buffer(q, s, buf, s->pixelformat,204cx->cxhdl.width, cx->cxhdl.height, field);205}206207static void buffer_release(struct videobuf_queue *q,208struct videobuf_buffer *vb)209{210struct cx18_videobuf_buffer *buf =211container_of(vb, struct cx18_videobuf_buffer, vb);212struct cx18_stream *s = q->priv_data;213214cx18_dma_free(q, s, buf);215}216217static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)218{219struct cx18_videobuf_buffer *buf =220container_of(vb, struct cx18_videobuf_buffer, vb);221struct cx18_stream *s = q->priv_data;222223buf->vb.state = VIDEOBUF_QUEUED;224225list_add_tail(&buf->vb.queue, &s->vb_capture);226}227228static struct videobuf_queue_ops cx18_videobuf_qops = {229.buf_setup = buffer_setup,230.buf_prepare = buffer_prepare,231.buf_queue = buffer_queue,232.buf_release = buffer_release,233};234235static void cx18_stream_init(struct cx18 *cx, int type)236{237struct cx18_stream *s = &cx->streams[type];238struct video_device *video_dev = s->video_dev;239240/* we need to keep video_dev, so restore it afterwards */241memset(s, 0, sizeof(*s));242s->video_dev = video_dev;243244/* initialize cx18_stream fields */245s->dvb = NULL;246s->cx = cx;247s->type = type;248s->name = cx18_stream_info[type].name;249s->handle = CX18_INVALID_TASK_HANDLE;250251s->dma = cx18_stream_info[type].dma;252s->buffers = cx->stream_buffers[type];253s->buf_size = cx->stream_buf_size[type];254INIT_LIST_HEAD(&s->buf_pool);255s->bufs_per_mdl = 1;256s->mdl_size = s->buf_size * s->bufs_per_mdl;257258init_waitqueue_head(&s->waitq);259s->id = -1;260spin_lock_init(&s->q_free.lock);261cx18_queue_init(&s->q_free);262spin_lock_init(&s->q_busy.lock);263cx18_queue_init(&s->q_busy);264spin_lock_init(&s->q_full.lock);265cx18_queue_init(&s->q_full);266spin_lock_init(&s->q_idle.lock);267cx18_queue_init(&s->q_idle);268269INIT_WORK(&s->out_work_order, cx18_out_work_handler);270271INIT_LIST_HEAD(&s->vb_capture);272s->vb_timeout.function = cx18_vb_timeout;273s->vb_timeout.data = (unsigned long)s;274init_timer(&s->vb_timeout);275spin_lock_init(&s->vb_lock);276if (type == CX18_ENC_STREAM_TYPE_YUV) {277spin_lock_init(&s->vbuf_q_lock);278279s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;280videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,281&cx->pci_dev->dev, &s->vbuf_q_lock,282V4L2_BUF_TYPE_VIDEO_CAPTURE,283V4L2_FIELD_INTERLACED,284sizeof(struct cx18_videobuf_buffer),285s, &cx->serialize_lock);286287/* Assume the previous pixel default */288s->pixelformat = V4L2_PIX_FMT_HM12;289}290}291292static int cx18_prep_dev(struct cx18 *cx, int type)293{294struct cx18_stream *s = &cx->streams[type];295u32 cap = cx->v4l2_cap;296int num_offset = cx18_stream_info[type].num_offset;297int num = cx->instance + cx18_first_minor + num_offset;298299/*300* These five fields are always initialized.301* For analog capture related streams, if video_dev == NULL then the302* stream is not in use.303* For the TS stream, if dvb == NULL then the stream is not in use.304* In those cases no other fields but these four can be used.305*/306s->video_dev = NULL;307s->dvb = NULL;308s->cx = cx;309s->type = type;310s->name = cx18_stream_info[type].name;311312/* Check whether the radio is supported */313if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))314return 0;315316/* Check whether VBI is supported */317if (type == CX18_ENC_STREAM_TYPE_VBI &&318!(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))319return 0;320321/* User explicitly selected 0 buffers for these streams, so don't322create them. */323if (cx18_stream_info[type].dma != PCI_DMA_NONE &&324cx->stream_buffers[type] == 0) {325CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);326return 0;327}328329cx18_stream_init(cx, type);330331/* Allocate the cx18_dvb struct only for the TS on cards with DTV */332if (type == CX18_ENC_STREAM_TYPE_TS) {333if (cx->card->hw_all & CX18_HW_DVB) {334s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);335if (s->dvb == NULL) {336CX18_ERR("Couldn't allocate cx18_dvb structure"337" for %s\n", s->name);338return -ENOMEM;339}340} else {341/* Don't need buffers for the TS, if there is no DVB */342s->buffers = 0;343}344}345346if (num_offset == -1)347return 0;348349/* allocate and initialize the v4l2 video device structure */350s->video_dev = video_device_alloc();351if (s->video_dev == NULL) {352CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",353s->name);354return -ENOMEM;355}356357snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",358cx->v4l2_dev.name, s->name);359360s->video_dev->num = num;361s->video_dev->v4l2_dev = &cx->v4l2_dev;362s->video_dev->fops = &cx18_v4l2_enc_fops;363s->video_dev->release = video_device_release;364s->video_dev->tvnorms = V4L2_STD_ALL;365set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);366cx18_set_funcs(s->video_dev);367return 0;368}369370/* Initialize v4l2 variables and register v4l2 devices */371int cx18_streams_setup(struct cx18 *cx)372{373int type, ret;374375/* Setup V4L2 Devices */376for (type = 0; type < CX18_MAX_STREAMS; type++) {377/* Prepare device */378ret = cx18_prep_dev(cx, type);379if (ret < 0)380break;381382/* Allocate Stream */383ret = cx18_stream_alloc(&cx->streams[type]);384if (ret < 0)385break;386}387if (type == CX18_MAX_STREAMS)388return 0;389390/* One or more streams could not be initialized. Clean 'em all up. */391cx18_streams_cleanup(cx, 0);392return ret;393}394395static int cx18_reg_dev(struct cx18 *cx, int type)396{397struct cx18_stream *s = &cx->streams[type];398int vfl_type = cx18_stream_info[type].vfl_type;399const char *name;400int num, ret;401402if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {403ret = cx18_dvb_register(s);404if (ret < 0) {405CX18_ERR("DVB failed to register\n");406return ret;407}408}409410if (s->video_dev == NULL)411return 0;412413num = s->video_dev->num;414/* card number + user defined offset + device offset */415if (type != CX18_ENC_STREAM_TYPE_MPG) {416struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];417418if (s_mpg->video_dev)419num = s_mpg->video_dev->num420+ cx18_stream_info[type].num_offset;421}422video_set_drvdata(s->video_dev, s);423424/* Register device. First try the desired minor, then any free one. */425ret = video_register_device_no_warn(s->video_dev, vfl_type, num);426if (ret < 0) {427CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",428s->name, num);429video_device_release(s->video_dev);430s->video_dev = NULL;431return ret;432}433434name = video_device_node_name(s->video_dev);435436switch (vfl_type) {437case VFL_TYPE_GRABBER:438CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",439name, s->name, cx->stream_buffers[type],440cx->stream_buf_size[type] / 1024,441(cx->stream_buf_size[type] * 100 / 1024) % 100);442break;443444case VFL_TYPE_RADIO:445CX18_INFO("Registered device %s for %s\n", name, s->name);446break;447448case VFL_TYPE_VBI:449if (cx->stream_buffers[type])450CX18_INFO("Registered device %s for %s "451"(%d x %d bytes)\n",452name, s->name, cx->stream_buffers[type],453cx->stream_buf_size[type]);454else455CX18_INFO("Registered device %s for %s\n",456name, s->name);457break;458}459460return 0;461}462463/* Register v4l2 devices */464int cx18_streams_register(struct cx18 *cx)465{466int type;467int err;468int ret = 0;469470/* Register V4L2 devices */471for (type = 0; type < CX18_MAX_STREAMS; type++) {472err = cx18_reg_dev(cx, type);473if (err && ret == 0)474ret = err;475}476477if (ret == 0)478return 0;479480/* One or more streams could not be initialized. Clean 'em all up. */481cx18_streams_cleanup(cx, 1);482return ret;483}484485/* Unregister v4l2 devices */486void cx18_streams_cleanup(struct cx18 *cx, int unregister)487{488struct video_device *vdev;489int type;490491/* Teardown all streams */492for (type = 0; type < CX18_MAX_STREAMS; type++) {493494/* The TS has a cx18_dvb structure, not a video_device */495if (type == CX18_ENC_STREAM_TYPE_TS) {496if (cx->streams[type].dvb != NULL) {497if (unregister)498cx18_dvb_unregister(&cx->streams[type]);499kfree(cx->streams[type].dvb);500cx->streams[type].dvb = NULL;501cx18_stream_free(&cx->streams[type]);502}503continue;504}505506/* No struct video_device, but can have buffers allocated */507if (type == CX18_ENC_STREAM_TYPE_IDX) {508/* If the module params didn't inhibit IDX ... */509if (cx->stream_buffers[type] != 0) {510cx->stream_buffers[type] = 0;511/*512* Before calling cx18_stream_free(),513* check if the IDX stream was actually set up.514* Needed, since the cx18_probe() error path515* exits through here as well as normal clean up516*/517if (cx->streams[type].buffers != 0)518cx18_stream_free(&cx->streams[type]);519}520continue;521}522523/* If struct video_device exists, can have buffers allocated */524vdev = cx->streams[type].video_dev;525526cx->streams[type].video_dev = NULL;527if (vdev == NULL)528continue;529530if (type == CX18_ENC_STREAM_TYPE_YUV)531videobuf_mmap_free(&cx->streams[type].vbuf_q);532533cx18_stream_free(&cx->streams[type]);534535/* Unregister or release device */536if (unregister)537video_unregister_device(vdev);538else539video_device_release(vdev);540}541}542543static void cx18_vbi_setup(struct cx18_stream *s)544{545struct cx18 *cx = s->cx;546int raw = cx18_raw_vbi(cx);547u32 data[CX2341X_MBOX_MAX_DATA];548int lines;549550if (cx->is_60hz) {551cx->vbi.count = 12;552cx->vbi.start[0] = 10;553cx->vbi.start[1] = 273;554} else { /* PAL/SECAM */555cx->vbi.count = 18;556cx->vbi.start[0] = 6;557cx->vbi.start[1] = 318;558}559560/* setup VBI registers */561if (raw)562v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi);563else564v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced);565566/*567* Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw568* VBI when the first analog capture channel starts, as once it starts569* (e.g. MPEG), we can't effect any change in the Encoder Raw VBI setup570* (i.e. for the VBI capture channels). We also send it for each571* analog capture channel anyway just to make sure we get the proper572* behavior573*/574if (raw) {575lines = cx->vbi.count * 2;576} else {577/*578* For 525/60 systems, according to the VIP 2 & BT.656 std:579* The EAV RP code's Field bit toggles on line 4, a few lines580* after the Vertcal Blank bit has already toggled.581* Tell the encoder to capture 21-4+1=18 lines per field,582* since we want lines 10 through 21.583*584* For 625/50 systems, according to the VIP 2 & BT.656 std:585* The EAV RP code's Field bit toggles on line 1, a few lines586* after the Vertcal Blank bit has already toggled.587* (We've actually set the digitizer so that the Field bit588* toggles on line 2.) Tell the encoder to capture 23-2+1=22589* lines per field, since we want lines 6 through 23.590*/591lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2;592}593594data[0] = s->handle;595/* Lines per field */596data[1] = (lines / 2) | ((lines / 2) << 16);597/* bytes per line */598data[2] = (raw ? vbi_active_samples599: (cx->is_60hz ? vbi_hblank_samples_60Hz600: vbi_hblank_samples_50Hz));601/* Every X number of frames a VBI interrupt arrives602(frames as in 25 or 30 fps) */603data[3] = 1;604/*605* Set the SAV/EAV RP codes to look for as start/stop points606* when in VIP-1.1 mode607*/608if (raw) {609/*610* Start codes for beginning of "active" line in vertical blank611* 0x20 ( VerticalBlank )612* 0x60 ( EvenField VerticalBlank )613*/614data[4] = 0x20602060;615/*616* End codes for end of "active" raw lines and regular lines617* 0x30 ( VerticalBlank HorizontalBlank)618* 0x70 ( EvenField VerticalBlank HorizontalBlank)619* 0x90 (Task HorizontalBlank)620* 0xd0 (Task EvenField HorizontalBlank)621*/622data[5] = 0x307090d0;623} else {624/*625* End codes for active video, we want data in the hblank region626* 0xb0 (Task 0 VerticalBlank HorizontalBlank)627* 0xf0 (Task EvenField VerticalBlank HorizontalBlank)628*629* Since the V bit is only allowed to toggle in the EAV RP code,630* just before the first active region line, these two631* are problematic:632* 0x90 (Task HorizontalBlank)633* 0xd0 (Task EvenField HorizontalBlank)634*635* We have set the digitzer such that we don't have to worry636* about these problem codes.637*/638data[4] = 0xB0F0B0F0;639/*640* Start codes for beginning of active line in vertical blank641* 0xa0 (Task VerticalBlank )642* 0xe0 (Task EvenField VerticalBlank )643*/644data[5] = 0xA0E0A0E0;645}646647CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",648data[0], data[1], data[2], data[3], data[4], data[5]);649650cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);651}652653void cx18_stream_rotate_idx_mdls(struct cx18 *cx)654{655struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];656struct cx18_mdl *mdl;657658if (!cx18_stream_enabled(s))659return;660661/* Return if the firmware is not running low on MDLs */662if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >=663CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN)664return;665666/* Return if there are no MDLs to rotate back to the firmware */667if (atomic_read(&s->q_full.depth) < 2)668return;669670/*671* Take the oldest IDX MDL still holding data, and discard its index672* entries by scheduling the MDL to go back to the firmware673*/674mdl = cx18_dequeue(s, &s->q_full);675if (mdl != NULL)676cx18_enqueue(s, mdl, &s->q_free);677}678679static680struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,681struct cx18_mdl *mdl)682{683struct cx18 *cx = s->cx;684struct cx18_queue *q;685686/* Don't give it to the firmware, if we're not running a capture */687if (s->handle == CX18_INVALID_TASK_HANDLE ||688test_bit(CX18_F_S_STOPPING, &s->s_flags) ||689!test_bit(CX18_F_S_STREAMING, &s->s_flags))690return cx18_enqueue(s, mdl, &s->q_free);691692q = cx18_enqueue(s, mdl, &s->q_busy);693if (q != &s->q_busy)694return q; /* The firmware has the max MDLs it can handle */695696cx18_mdl_sync_for_device(s, mdl);697cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,698(void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem,699s->bufs_per_mdl, mdl->id, s->mdl_size);700return q;701}702703static704void _cx18_stream_load_fw_queue(struct cx18_stream *s)705{706struct cx18_queue *q;707struct cx18_mdl *mdl;708709if (atomic_read(&s->q_free.depth) == 0 ||710atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM)711return;712713/* Move from q_free to q_busy notifying the firmware, until the limit */714do {715mdl = cx18_dequeue(s, &s->q_free);716if (mdl == NULL)717break;718q = _cx18_stream_put_mdl_fw(s, mdl);719} while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM720&& q == &s->q_busy);721}722723void cx18_out_work_handler(struct work_struct *work)724{725struct cx18_stream *s =726container_of(work, struct cx18_stream, out_work_order);727728_cx18_stream_load_fw_queue(s);729}730731static void cx18_stream_configure_mdls(struct cx18_stream *s)732{733cx18_unload_queues(s);734735switch (s->type) {736case CX18_ENC_STREAM_TYPE_YUV:737/*738* Height should be a multiple of 32 lines.739* Set the MDL size to the exact size needed for one frame.740* Use enough buffers per MDL to cover the MDL size741*/742if (s->pixelformat == V4L2_PIX_FMT_HM12)743s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;744else745s->mdl_size = 720 * s->cx->cxhdl.height * 2;746s->bufs_per_mdl = s->mdl_size / s->buf_size;747if (s->mdl_size % s->buf_size)748s->bufs_per_mdl++;749break;750case CX18_ENC_STREAM_TYPE_VBI:751s->bufs_per_mdl = 1;752if (cx18_raw_vbi(s->cx)) {753s->mdl_size = (s->cx->is_60hz ? 12 : 18)754* 2 * vbi_active_samples;755} else {756/*757* See comment in cx18_vbi_setup() below about the758* extra lines we capture in sliced VBI mode due to759* the lines on which EAV RP codes toggle.760*/761s->mdl_size = s->cx->is_60hz762? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz763: (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;764}765break;766default:767s->bufs_per_mdl = 1;768s->mdl_size = s->buf_size * s->bufs_per_mdl;769break;770}771772cx18_load_queues(s);773}774775int cx18_start_v4l2_encode_stream(struct cx18_stream *s)776{777u32 data[MAX_MB_ARGUMENTS];778struct cx18 *cx = s->cx;779int captype = 0;780struct cx18_stream *s_idx;781782if (!cx18_stream_enabled(s))783return -EINVAL;784785CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);786787switch (s->type) {788case CX18_ENC_STREAM_TYPE_MPG:789captype = CAPTURE_CHANNEL_TYPE_MPEG;790cx->mpg_data_received = cx->vbi_data_inserted = 0;791cx->dualwatch_jiffies = jiffies;792cx->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);793cx->search_pack_header = 0;794break;795796case CX18_ENC_STREAM_TYPE_IDX:797captype = CAPTURE_CHANNEL_TYPE_INDEX;798break;799case CX18_ENC_STREAM_TYPE_TS:800captype = CAPTURE_CHANNEL_TYPE_TS;801break;802case CX18_ENC_STREAM_TYPE_YUV:803captype = CAPTURE_CHANNEL_TYPE_YUV;804break;805case CX18_ENC_STREAM_TYPE_PCM:806captype = CAPTURE_CHANNEL_TYPE_PCM;807break;808case CX18_ENC_STREAM_TYPE_VBI:809#ifdef CX18_ENCODER_PARSES_SLICED810captype = cx18_raw_vbi(cx) ?811CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI;812#else813/*814* Currently we set things up so that Sliced VBI from the815* digitizer is handled as Raw VBI by the encoder816*/817captype = CAPTURE_CHANNEL_TYPE_VBI;818#endif819cx->vbi.frame = 0;820cx->vbi.inserted_frame = 0;821memset(cx->vbi.sliced_mpeg_size,8220, sizeof(cx->vbi.sliced_mpeg_size));823break;824default:825return -EINVAL;826}827828/* Clear Streamoff flags in case left from last capture */829clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);830831cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);832s->handle = data[0];833cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);834835/*836* For everything but CAPTURE_CHANNEL_TYPE_TS, play it safe and837* set up all the parameters, as it is not obvious which parameters the838* firmware shares across capture channel types and which it does not.839*840* Some of the cx18_vapi() calls below apply to only certain capture841* channel types. We're hoping there's no harm in calling most of them842* anyway, as long as the values are all consistent. Setting some843* shared parameters will have no effect once an analog capture channel844* has started streaming.845*/846if (captype != CAPTURE_CHANNEL_TYPE_TS) {847cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);848cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);849cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);850cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);851852/*853* Audio related reset according to854* Documentation/video4linux/cx2341x/fw-encoder-api.txt855*/856if (atomic_read(&cx->ana_capturing) == 0)857cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,858s->handle, 12);859860/*861* Number of lines for Field 1 & Field 2 according to862* Documentation/video4linux/cx2341x/fw-encoder-api.txt863* Field 1 is 312 for 625 line systems in BT.656864* Field 2 is 313 for 625 line systems in BT.656865*/866cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,867s->handle, 312, 313);868869if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)870cx18_vbi_setup(s);871872/*873* Select to receive I, P, and B frame index entries, if the874* index stream is enabled. Otherwise disable index entry875* generation.876*/877s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];878cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2,879s->handle, cx18_stream_enabled(s_idx) ? 7 : 0);880881/* Call out to the common CX2341x API setup for user controls */882cx->cxhdl.priv = s;883cx2341x_handler_setup(&cx->cxhdl);884885/*886* When starting a capture and we're set for radio,887* ensure the video is muted, despite the user control.888*/889if (!cx->cxhdl.video_mute &&890test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))891cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,892(v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);893894/* Enable the Video Format Converter for UYVY 4:2:2 support,895* rather than the default HM12 Macroblovk 4:2:0 support.896*/897if (captype == CAPTURE_CHANNEL_TYPE_YUV) {898if (s->pixelformat == V4L2_PIX_FMT_UYVY)899cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,900s->handle, 1);901else902/* If in doubt, default to HM12 */903cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,904s->handle, 0);905}906}907908if (atomic_read(&cx->tot_capturing) == 0) {909cx2341x_handler_set_busy(&cx->cxhdl, 1);910clear_bit(CX18_F_I_EOS, &cx->i_flags);911cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);912}913914cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,915(void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,916(void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);917918/* Init all the cpu_mdls for this stream */919cx18_stream_configure_mdls(s);920_cx18_stream_load_fw_queue(s);921922/* begin_capture */923if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {924CX18_DEBUG_WARN("Error starting capture!\n");925/* Ensure we're really not capturing before releasing MDLs */926set_bit(CX18_F_S_STOPPING, &s->s_flags);927if (s->type == CX18_ENC_STREAM_TYPE_MPG)928cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);929else930cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);931clear_bit(CX18_F_S_STREAMING, &s->s_flags);932/* FIXME - CX18_F_S_STREAMOFF as well? */933cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);934cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);935s->handle = CX18_INVALID_TASK_HANDLE;936clear_bit(CX18_F_S_STOPPING, &s->s_flags);937if (atomic_read(&cx->tot_capturing) == 0) {938set_bit(CX18_F_I_EOS, &cx->i_flags);939cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);940}941return -EINVAL;942}943944/* you're live! sit back and await interrupts :) */945if (captype != CAPTURE_CHANNEL_TYPE_TS)946atomic_inc(&cx->ana_capturing);947atomic_inc(&cx->tot_capturing);948return 0;949}950EXPORT_SYMBOL(cx18_start_v4l2_encode_stream);951952void cx18_stop_all_captures(struct cx18 *cx)953{954int i;955956for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {957struct cx18_stream *s = &cx->streams[i];958959if (!cx18_stream_enabled(s))960continue;961if (test_bit(CX18_F_S_STREAMING, &s->s_flags))962cx18_stop_v4l2_encode_stream(s, 0);963}964}965966int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)967{968struct cx18 *cx = s->cx;969unsigned long then;970971if (!cx18_stream_enabled(s))972return -EINVAL;973974/* This function assumes that you are allowed to stop the capture975and that we are actually capturing */976977CX18_DEBUG_INFO("Stop Capture\n");978979if (atomic_read(&cx->tot_capturing) == 0)980return 0;981982set_bit(CX18_F_S_STOPPING, &s->s_flags);983if (s->type == CX18_ENC_STREAM_TYPE_MPG)984cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);985else986cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);987988then = jiffies;989990if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {991CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");992}993994if (s->type != CX18_ENC_STREAM_TYPE_TS)995atomic_dec(&cx->ana_capturing);996atomic_dec(&cx->tot_capturing);997998/* Clear capture and no-read bits */999clear_bit(CX18_F_S_STREAMING, &s->s_flags);10001001/* Tell the CX23418 it can't use our buffers anymore */1002cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);10031004cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);1005s->handle = CX18_INVALID_TASK_HANDLE;1006clear_bit(CX18_F_S_STOPPING, &s->s_flags);10071008if (atomic_read(&cx->tot_capturing) > 0)1009return 0;10101011cx2341x_handler_set_busy(&cx->cxhdl, 0);1012cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);1013wake_up(&s->waitq);10141015return 0;1016}1017EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream);10181019u32 cx18_find_handle(struct cx18 *cx)1020{1021int i;10221023/* find first available handle to be used for global settings */1024for (i = 0; i < CX18_MAX_STREAMS; i++) {1025struct cx18_stream *s = &cx->streams[i];10261027if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE))1028return s->handle;1029}1030return CX18_INVALID_TASK_HANDLE;1031}10321033struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle)1034{1035int i;1036struct cx18_stream *s;10371038if (handle == CX18_INVALID_TASK_HANDLE)1039return NULL;10401041for (i = 0; i < CX18_MAX_STREAMS; i++) {1042s = &cx->streams[i];1043if (s->handle != handle)1044continue;1045if (cx18_stream_enabled(s))1046return s;1047}1048return NULL;1049}105010511052