Path: blob/master/drivers/media/video/ivtv/ivtv-ioctl.c
17778 views
/*1ioctl system call2Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com>3Copyright (C) 2005-2007 Hans Verkuil <[email protected]>45This program is free software; you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation; either version 2 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program; if not, write to the Free Software17Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920#include "ivtv-driver.h"21#include "ivtv-version.h"22#include "ivtv-mailbox.h"23#include "ivtv-i2c.h"24#include "ivtv-queue.h"25#include "ivtv-fileops.h"26#include "ivtv-vbi.h"27#include "ivtv-routing.h"28#include "ivtv-streams.h"29#include "ivtv-yuv.h"30#include "ivtv-ioctl.h"31#include "ivtv-gpio.h"32#include "ivtv-controls.h"33#include "ivtv-cards.h"34#include <media/saa7127.h>35#include <media/tveeprom.h>36#include <media/v4l2-chip-ident.h>37#include <media/v4l2-event.h>38#include <linux/dvb/audio.h>3940u16 ivtv_service2vbi(int type)41{42switch (type) {43case V4L2_SLICED_TELETEXT_B:44return IVTV_SLICED_TYPE_TELETEXT_B;45case V4L2_SLICED_CAPTION_525:46return IVTV_SLICED_TYPE_CAPTION_525;47case V4L2_SLICED_WSS_625:48return IVTV_SLICED_TYPE_WSS_625;49case V4L2_SLICED_VPS:50return IVTV_SLICED_TYPE_VPS;51default:52return 0;53}54}5556static int valid_service_line(int field, int line, int is_pal)57{58return (is_pal && line >= 6 && (line != 23 || field == 0)) ||59(!is_pal && line >= 10 && line < 22);60}6162static u16 select_service_from_set(int field, int line, u16 set, int is_pal)63{64u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);65int i;6667set = set & valid_set;68if (set == 0 || !valid_service_line(field, line, is_pal)) {69return 0;70}71if (!is_pal) {72if (line == 21 && (set & V4L2_SLICED_CAPTION_525))73return V4L2_SLICED_CAPTION_525;74}75else {76if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))77return V4L2_SLICED_VPS;78if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))79return V4L2_SLICED_WSS_625;80if (line == 23)81return 0;82}83for (i = 0; i < 32; i++) {84if ((1 << i) & set)85return 1 << i;86}87return 0;88}8990void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)91{92u16 set = fmt->service_set;93int f, l;9495fmt->service_set = 0;96for (f = 0; f < 2; f++) {97for (l = 0; l < 24; l++) {98fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);99}100}101}102103static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)104{105int f, l;106107for (f = 0; f < 2; f++) {108for (l = 0; l < 24; l++) {109fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);110}111}112}113114u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)115{116int f, l;117u16 set = 0;118119for (f = 0; f < 2; f++) {120for (l = 0; l < 24; l++) {121set |= fmt->service_lines[f][l];122}123}124return set;125}126127void ivtv_set_osd_alpha(struct ivtv *itv)128{129ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,130itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);131ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);132}133134int ivtv_set_speed(struct ivtv *itv, int speed)135{136u32 data[CX2341X_MBOX_MAX_DATA];137struct ivtv_stream *s;138int single_step = (speed == 1 || speed == -1);139DEFINE_WAIT(wait);140141if (speed == 0) speed = 1000;142143/* No change? */144if (speed == itv->speed && !single_step)145return 0;146147s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];148149if (single_step && (speed < 0) == (itv->speed < 0)) {150/* Single step video and no need to change direction */151ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);152itv->speed = speed;153return 0;154}155if (single_step)156/* Need to change direction */157speed = speed < 0 ? -1000 : 1000;158159data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;160data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;161data[1] = (speed < 0);162data[2] = speed < 0 ? 3 : 7;163data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);164data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;165data[5] = 0;166data[6] = 0;167168if (speed == 1500 || speed == -1500) data[0] |= 1;169else if (speed == 2000 || speed == -2000) data[0] |= 2;170else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);171else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);172173/* If not decoding, just change speed setting */174if (atomic_read(&itv->decoding) > 0) {175int got_sig = 0;176177/* Stop all DMA and decoding activity */178ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);179180/* Wait for any DMA to finish */181prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);182while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {183got_sig = signal_pending(current);184if (got_sig)185break;186got_sig = 0;187schedule();188}189finish_wait(&itv->dma_waitq, &wait);190if (got_sig)191return -EINTR;192193/* Change Speed safely */194ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);195IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",196data[0], data[1], data[2], data[3], data[4], data[5], data[6]);197}198if (single_step) {199speed = (speed < 0) ? -1 : 1;200ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);201}202itv->speed = speed;203return 0;204}205206static int ivtv_validate_speed(int cur_speed, int new_speed)207{208int fact = new_speed < 0 ? -1 : 1;209int s;210211if (cur_speed == 0)212cur_speed = 1000;213if (new_speed < 0)214new_speed = -new_speed;215if (cur_speed < 0)216cur_speed = -cur_speed;217218if (cur_speed <= new_speed) {219if (new_speed > 1500)220return fact * 2000;221if (new_speed > 1000)222return fact * 1500;223}224else {225if (new_speed >= 2000)226return fact * 2000;227if (new_speed >= 1500)228return fact * 1500;229if (new_speed >= 1000)230return fact * 1000;231}232if (new_speed == 0)233return 1000;234if (new_speed == 1 || new_speed == 1000)235return fact * new_speed;236237s = new_speed;238new_speed = 1000 / new_speed;239if (1000 / cur_speed == new_speed)240new_speed += (cur_speed < s) ? -1 : 1;241if (new_speed > 60) return 1000 / (fact * 60);242return 1000 / (fact * new_speed);243}244245static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,246struct video_command *vc, int try)247{248struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];249250if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))251return -EINVAL;252253switch (vc->cmd) {254case VIDEO_CMD_PLAY: {255vc->flags = 0;256vc->play.speed = ivtv_validate_speed(itv->speed, vc->play.speed);257if (vc->play.speed < 0)258vc->play.format = VIDEO_PLAY_FMT_GOP;259if (try) break;260261if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)262return -EBUSY;263if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {264/* forces ivtv_set_speed to be called */265itv->speed = 0;266}267return ivtv_start_decoding(id, vc->play.speed);268}269270case VIDEO_CMD_STOP:271vc->flags &= VIDEO_CMD_STOP_IMMEDIATELY|VIDEO_CMD_STOP_TO_BLACK;272if (vc->flags & VIDEO_CMD_STOP_IMMEDIATELY)273vc->stop.pts = 0;274if (try) break;275if (atomic_read(&itv->decoding) == 0)276return 0;277if (itv->output_mode != OUT_MPG)278return -EBUSY;279280itv->output_mode = OUT_NONE;281return ivtv_stop_v4l2_decode_stream(s, vc->flags, vc->stop.pts);282283case VIDEO_CMD_FREEZE:284vc->flags &= VIDEO_CMD_FREEZE_TO_BLACK;285if (try) break;286if (itv->output_mode != OUT_MPG)287return -EBUSY;288if (atomic_read(&itv->decoding) > 0) {289ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,290(vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0);291set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);292}293break;294295case VIDEO_CMD_CONTINUE:296vc->flags = 0;297if (try) break;298if (itv->output_mode != OUT_MPG)299return -EBUSY;300if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {301int speed = itv->speed;302itv->speed = 0;303return ivtv_start_decoding(id, speed);304}305break;306307default:308return -EINVAL;309}310return 0;311}312313static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)314{315struct ivtv *itv = fh2id(fh)->itv;316struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;317318vbifmt->reserved[0] = 0;319vbifmt->reserved[1] = 0;320if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))321return -EINVAL;322vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;323if (itv->is_60hz) {324vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;325vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;326} else {327vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;328vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;329}330vbifmt->service_set = ivtv_get_service_set(vbifmt);331return 0;332}333334static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)335{336struct ivtv_open_id *id = fh2id(fh);337struct ivtv *itv = id->itv;338struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;339340pixfmt->width = itv->cxhdl.width;341pixfmt->height = itv->cxhdl.height;342pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;343pixfmt->field = V4L2_FIELD_INTERLACED;344pixfmt->priv = 0;345if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {346pixfmt->pixelformat = V4L2_PIX_FMT_HM12;347/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */348pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;349pixfmt->bytesperline = 720;350} else {351pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;352pixfmt->sizeimage = 128 * 1024;353pixfmt->bytesperline = 0;354}355return 0;356}357358static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)359{360struct ivtv *itv = fh2id(fh)->itv;361struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;362363vbifmt->sampling_rate = 27000000;364vbifmt->offset = 248;365vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;366vbifmt->sample_format = V4L2_PIX_FMT_GREY;367vbifmt->start[0] = itv->vbi.start[0];368vbifmt->start[1] = itv->vbi.start[1];369vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;370vbifmt->flags = 0;371vbifmt->reserved[0] = 0;372vbifmt->reserved[1] = 0;373return 0;374}375376static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)377{378struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;379struct ivtv_open_id *id = fh2id(fh);380struct ivtv *itv = id->itv;381382vbifmt->reserved[0] = 0;383vbifmt->reserved[1] = 0;384vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;385386if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {387vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :388V4L2_SLICED_VBI_525;389ivtv_expand_service_set(vbifmt, itv->is_50hz);390return 0;391}392393v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);394vbifmt->service_set = ivtv_get_service_set(vbifmt);395return 0;396}397398static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)399{400struct ivtv_open_id *id = fh2id(fh);401struct ivtv *itv = id->itv;402struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;403404if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))405return -EINVAL;406pixfmt->width = itv->main_rect.width;407pixfmt->height = itv->main_rect.height;408pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;409pixfmt->field = V4L2_FIELD_INTERLACED;410pixfmt->priv = 0;411if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {412switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {413case IVTV_YUV_MODE_INTERLACED:414pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?415V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;416break;417case IVTV_YUV_MODE_PROGRESSIVE:418pixfmt->field = V4L2_FIELD_NONE;419break;420default:421pixfmt->field = V4L2_FIELD_ANY;422break;423}424pixfmt->pixelformat = V4L2_PIX_FMT_HM12;425pixfmt->bytesperline = 720;426pixfmt->width = itv->yuv_info.v4l2_src_w;427pixfmt->height = itv->yuv_info.v4l2_src_h;428/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */429pixfmt->sizeimage =4301080 * ((pixfmt->height + 31) & ~31);431} else {432pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;433pixfmt->sizeimage = 128 * 1024;434pixfmt->bytesperline = 0;435}436return 0;437}438439static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)440{441struct ivtv *itv = fh2id(fh)->itv;442struct v4l2_window *winfmt = &fmt->fmt.win;443444if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))445return -EINVAL;446winfmt->chromakey = itv->osd_chroma_key;447winfmt->global_alpha = itv->osd_global_alpha;448winfmt->field = V4L2_FIELD_INTERLACED;449winfmt->clips = NULL;450winfmt->clipcount = 0;451winfmt->bitmap = NULL;452winfmt->w.top = winfmt->w.left = 0;453winfmt->w.width = itv->osd_rect.width;454winfmt->w.height = itv->osd_rect.height;455return 0;456}457458static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)459{460return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);461}462463static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)464{465struct ivtv_open_id *id = fh2id(fh);466struct ivtv *itv = id->itv;467int w = fmt->fmt.pix.width;468int h = fmt->fmt.pix.height;469int min_h = 2;470471w = min(w, 720);472w = max(w, 2);473if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {474/* YUV height must be a multiple of 32 */475h &= ~0x1f;476min_h = 32;477}478h = min(h, itv->is_50hz ? 576 : 480);479h = max(h, min_h);480ivtv_g_fmt_vid_cap(file, fh, fmt);481fmt->fmt.pix.width = w;482fmt->fmt.pix.height = h;483return 0;484}485486static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)487{488return ivtv_g_fmt_vbi_cap(file, fh, fmt);489}490491static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)492{493struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;494struct ivtv_open_id *id = fh2id(fh);495struct ivtv *itv = id->itv;496497if (id->type == IVTV_DEC_STREAM_TYPE_VBI)498return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);499500/* set sliced VBI capture format */501vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;502vbifmt->reserved[0] = 0;503vbifmt->reserved[1] = 0;504505if (vbifmt->service_set)506ivtv_expand_service_set(vbifmt, itv->is_50hz);507check_service_set(vbifmt, itv->is_50hz);508vbifmt->service_set = ivtv_get_service_set(vbifmt);509return 0;510}511512static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)513{514struct ivtv_open_id *id = fh2id(fh);515s32 w = fmt->fmt.pix.width;516s32 h = fmt->fmt.pix.height;517int field = fmt->fmt.pix.field;518int ret = ivtv_g_fmt_vid_out(file, fh, fmt);519520w = min(w, 720);521w = max(w, 2);522/* Why can the height be 576 even when the output is NTSC?523524Internally the buffers of the PVR350 are always set to 720x576. The525decoded video frame will always be placed in the top left corner of526this buffer. For any video which is not 720x576, the buffer will527then be cropped to remove the unused right and lower areas, with528the remaining image being scaled by the hardware to fit the display529area. The video can be scaled both up and down, so a 720x480 video530can be displayed full-screen on PAL and a 720x576 video can be531displayed without cropping on NTSC.532533Note that the scaling only occurs on the video stream, the osd534resolution is locked to the broadcast standard and not scaled.535536Thanks to Ian Armstrong for this explanation. */537h = min(h, 576);538h = max(h, 2);539if (id->type == IVTV_DEC_STREAM_TYPE_YUV)540fmt->fmt.pix.field = field;541fmt->fmt.pix.width = w;542fmt->fmt.pix.height = h;543return ret;544}545546static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)547{548struct ivtv *itv = fh2id(fh)->itv;549u32 chromakey = fmt->fmt.win.chromakey;550u8 global_alpha = fmt->fmt.win.global_alpha;551552if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))553return -EINVAL;554ivtv_g_fmt_vid_out_overlay(file, fh, fmt);555fmt->fmt.win.chromakey = chromakey;556fmt->fmt.win.global_alpha = global_alpha;557return 0;558}559560static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)561{562return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);563}564565static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)566{567struct ivtv_open_id *id = fh2id(fh);568struct ivtv *itv = id->itv;569struct v4l2_mbus_framefmt mbus_fmt;570int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);571int w = fmt->fmt.pix.width;572int h = fmt->fmt.pix.height;573574if (ret)575return ret;576577if (itv->cxhdl.width == w && itv->cxhdl.height == h)578return 0;579580if (atomic_read(&itv->capturing) > 0)581return -EBUSY;582583itv->cxhdl.width = w;584itv->cxhdl.height = h;585if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)586fmt->fmt.pix.width /= 2;587mbus_fmt.width = fmt->fmt.pix.width;588mbus_fmt.height = h;589mbus_fmt.code = V4L2_MBUS_FMT_FIXED;590v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);591return ivtv_g_fmt_vid_cap(file, fh, fmt);592}593594static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)595{596struct ivtv *itv = fh2id(fh)->itv;597598if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)599return -EBUSY;600itv->vbi.sliced_in->service_set = 0;601itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;602v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);603return ivtv_g_fmt_vbi_cap(file, fh, fmt);604}605606static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)607{608struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;609struct ivtv_open_id *id = fh2id(fh);610struct ivtv *itv = id->itv;611int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);612613if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)614return ret;615616check_service_set(vbifmt, itv->is_50hz);617if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)618return -EBUSY;619itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;620v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);621memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));622return 0;623}624625static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)626{627struct ivtv_open_id *id = fh2id(fh);628struct ivtv *itv = id->itv;629struct yuv_playback_info *yi = &itv->yuv_info;630int ret = ivtv_try_fmt_vid_out(file, fh, fmt);631632if (ret)633return ret;634635if (id->type != IVTV_DEC_STREAM_TYPE_YUV)636return 0;637638/* Return now if we already have some frame data */639if (yi->stream_size)640return -EBUSY;641642yi->v4l2_src_w = fmt->fmt.pix.width;643yi->v4l2_src_h = fmt->fmt.pix.height;644645switch (fmt->fmt.pix.field) {646case V4L2_FIELD_NONE:647yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;648break;649case V4L2_FIELD_ANY:650yi->lace_mode = IVTV_YUV_MODE_AUTO;651break;652case V4L2_FIELD_INTERLACED_BT:653yi->lace_mode =654IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;655break;656case V4L2_FIELD_INTERLACED_TB:657default:658yi->lace_mode = IVTV_YUV_MODE_INTERLACED;659break;660}661yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;662663if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))664itv->dma_data_req_size =6651080 * ((yi->v4l2_src_h + 31) & ~31);666667return 0;668}669670static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)671{672struct ivtv *itv = fh2id(fh)->itv;673int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);674675if (ret == 0) {676itv->osd_chroma_key = fmt->fmt.win.chromakey;677itv->osd_global_alpha = fmt->fmt.win.global_alpha;678ivtv_set_osd_alpha(itv);679}680return ret;681}682683static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)684{685struct ivtv *itv = fh2id(fh)->itv;686687chip->ident = V4L2_IDENT_NONE;688chip->revision = 0;689if (chip->match.type == V4L2_CHIP_MATCH_HOST) {690if (v4l2_chip_match_host(&chip->match))691chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;692return 0;693}694if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&695chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)696return -EINVAL;697/* TODO: is this correct? */698return ivtv_call_all_err(itv, core, g_chip_ident, chip);699}700701#ifdef CONFIG_VIDEO_ADV_DEBUG702static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)703{704struct v4l2_dbg_register *regs = arg;705volatile u8 __iomem *reg_start;706707if (!capable(CAP_SYS_ADMIN))708return -EPERM;709if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)710reg_start = itv->reg_mem - IVTV_REG_OFFSET;711else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&712regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)713reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;714else if (regs->reg < IVTV_ENCODER_SIZE)715reg_start = itv->enc_mem;716else717return -EINVAL;718719regs->size = 4;720if (cmd == VIDIOC_DBG_G_REGISTER)721regs->val = readl(regs->reg + reg_start);722else723writel(regs->val, regs->reg + reg_start);724return 0;725}726727static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)728{729struct ivtv *itv = fh2id(fh)->itv;730731if (v4l2_chip_match_host(®->match))732return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);733/* TODO: subdev errors should not be ignored, this should become a734subdev helper function. */735ivtv_call_all(itv, core, g_register, reg);736return 0;737}738739static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)740{741struct ivtv *itv = fh2id(fh)->itv;742743if (v4l2_chip_match_host(®->match))744return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);745/* TODO: subdev errors should not be ignored, this should become a746subdev helper function. */747ivtv_call_all(itv, core, s_register, reg);748return 0;749}750#endif751752static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)753{754struct ivtv *itv = fh2id(fh)->itv;755756strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));757strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));758snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));759vcap->version = IVTV_DRIVER_VERSION; /* version */760vcap->capabilities = itv->v4l2_cap; /* capabilities */761return 0;762}763764static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)765{766struct ivtv *itv = fh2id(fh)->itv;767768return ivtv_get_audio_input(itv, vin->index, vin);769}770771static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)772{773struct ivtv *itv = fh2id(fh)->itv;774775vin->index = itv->audio_input;776return ivtv_get_audio_input(itv, vin->index, vin);777}778779static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)780{781struct ivtv *itv = fh2id(fh)->itv;782783if (vout->index >= itv->nof_audio_inputs)784return -EINVAL;785786itv->audio_input = vout->index;787ivtv_audio_set_io(itv);788789return 0;790}791792static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)793{794struct ivtv *itv = fh2id(fh)->itv;795796/* set it to defaults from our table */797return ivtv_get_audio_output(itv, vin->index, vin);798}799800static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)801{802struct ivtv *itv = fh2id(fh)->itv;803804vin->index = 0;805return ivtv_get_audio_output(itv, vin->index, vin);806}807808static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)809{810struct ivtv *itv = fh2id(fh)->itv;811812return ivtv_get_audio_output(itv, vout->index, vout);813}814815static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)816{817struct ivtv *itv = fh2id(fh)->itv;818819/* set it to defaults from our table */820return ivtv_get_input(itv, vin->index, vin);821}822823static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)824{825struct ivtv *itv = fh2id(fh)->itv;826827return ivtv_get_output(itv, vout->index, vout);828}829830static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)831{832struct ivtv_open_id *id = fh2id(fh);833struct ivtv *itv = id->itv;834struct yuv_playback_info *yi = &itv->yuv_info;835int streamtype;836837streamtype = id->type;838839if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)840return -EINVAL;841cropcap->bounds.top = cropcap->bounds.left = 0;842cropcap->bounds.width = 720;843if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {844cropcap->bounds.height = itv->is_50hz ? 576 : 480;845cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;846cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;847} else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {848if (yi->track_osd) {849cropcap->bounds.width = yi->osd_full_w;850cropcap->bounds.height = yi->osd_full_h;851} else {852cropcap->bounds.width = 720;853cropcap->bounds.height =854itv->is_out_50hz ? 576 : 480;855}856cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;857cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;858} else {859cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;860cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;861cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;862}863cropcap->defrect = cropcap->bounds;864return 0;865}866867static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)868{869struct ivtv_open_id *id = fh2id(fh);870struct ivtv *itv = id->itv;871struct yuv_playback_info *yi = &itv->yuv_info;872int streamtype;873874streamtype = id->type;875876if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&877(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {878if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {879yi->main_rect = crop->c;880return 0;881} else {882if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,883crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {884itv->main_rect = crop->c;885return 0;886}887}888return -EINVAL;889}890return -EINVAL;891}892893static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)894{895struct ivtv_open_id *id = fh2id(fh);896struct ivtv *itv = id->itv;897struct yuv_playback_info *yi = &itv->yuv_info;898int streamtype;899900streamtype = id->type;901902if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&903(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {904if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)905crop->c = yi->main_rect;906else907crop->c = itv->main_rect;908return 0;909}910return -EINVAL;911}912913static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)914{915static struct v4l2_fmtdesc formats[] = {916{ 0, 0, 0,917"HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,918{ 0, 0, 0, 0 }919},920{ 1, 0, V4L2_FMT_FLAG_COMPRESSED,921"MPEG", V4L2_PIX_FMT_MPEG,922{ 0, 0, 0, 0 }923}924};925enum v4l2_buf_type type = fmt->type;926927if (fmt->index > 1)928return -EINVAL;929930*fmt = formats[fmt->index];931fmt->type = type;932return 0;933}934935static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)936{937struct ivtv *itv = fh2id(fh)->itv;938939static struct v4l2_fmtdesc formats[] = {940{ 0, 0, 0,941"HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,942{ 0, 0, 0, 0 }943},944{ 1, 0, V4L2_FMT_FLAG_COMPRESSED,945"MPEG", V4L2_PIX_FMT_MPEG,946{ 0, 0, 0, 0 }947}948};949enum v4l2_buf_type type = fmt->type;950951if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))952return -EINVAL;953954if (fmt->index > 1)955return -EINVAL;956957*fmt = formats[fmt->index];958fmt->type = type;959960return 0;961}962963static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)964{965struct ivtv *itv = fh2id(fh)->itv;966967*i = itv->active_input;968969return 0;970}971972int ivtv_s_input(struct file *file, void *fh, unsigned int inp)973{974struct ivtv *itv = fh2id(fh)->itv;975976if (inp < 0 || inp >= itv->nof_inputs)977return -EINVAL;978979if (inp == itv->active_input) {980IVTV_DEBUG_INFO("Input unchanged\n");981return 0;982}983984if (atomic_read(&itv->capturing) > 0) {985return -EBUSY;986}987988IVTV_DEBUG_INFO("Changing input from %d to %d\n",989itv->active_input, inp);990991itv->active_input = inp;992/* Set the audio input to whatever is appropriate for the993input type. */994itv->audio_input = itv->card->video_inputs[inp].audio_index;995996/* prevent others from messing with the streams until997we're finished changing inputs. */998ivtv_mute(itv);999ivtv_video_set_io(itv);1000ivtv_audio_set_io(itv);1001ivtv_unmute(itv);10021003return 0;1004}10051006static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)1007{1008struct ivtv *itv = fh2id(fh)->itv;10091010if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))1011return -EINVAL;10121013*i = itv->active_output;10141015return 0;1016}10171018static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)1019{1020struct ivtv *itv = fh2id(fh)->itv;10211022if (outp >= itv->card->nof_outputs)1023return -EINVAL;10241025if (outp == itv->active_output) {1026IVTV_DEBUG_INFO("Output unchanged\n");1027return 0;1028}1029IVTV_DEBUG_INFO("Changing output from %d to %d\n",1030itv->active_output, outp);10311032itv->active_output = outp;1033ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,1034SAA7127_INPUT_TYPE_NORMAL,1035itv->card->video_outputs[outp].video_output, 0);10361037return 0;1038}10391040static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)1041{1042struct ivtv *itv = fh2id(fh)->itv;10431044if (vf->tuner != 0)1045return -EINVAL;10461047ivtv_call_all(itv, tuner, g_frequency, vf);1048return 0;1049}10501051int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)1052{1053struct ivtv *itv = fh2id(fh)->itv;10541055if (vf->tuner != 0)1056return -EINVAL;10571058ivtv_mute(itv);1059IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);1060ivtv_call_all(itv, tuner, s_frequency, vf);1061ivtv_unmute(itv);1062return 0;1063}10641065static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)1066{1067struct ivtv *itv = fh2id(fh)->itv;10681069*std = itv->std;1070return 0;1071}10721073void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)1074{1075itv->std = *std;1076itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;1077itv->is_50hz = !itv->is_60hz;1078cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);1079itv->cxhdl.width = 720;1080itv->cxhdl.height = itv->is_50hz ? 576 : 480;1081itv->vbi.count = itv->is_50hz ? 18 : 12;1082itv->vbi.start[0] = itv->is_50hz ? 6 : 10;1083itv->vbi.start[1] = itv->is_50hz ? 318 : 273;10841085if (itv->hw_flags & IVTV_HW_CX25840)1086itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;10871088/* Tuner */1089ivtv_call_all(itv, core, s_std, itv->std);1090}10911092void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)1093{1094struct yuv_playback_info *yi = &itv->yuv_info;1095DEFINE_WAIT(wait);1096int f;10971098/* set display standard */1099itv->std_out = *std;1100itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;1101itv->is_out_50hz = !itv->is_out_60hz;1102ivtv_call_all(itv, video, s_std_output, itv->std_out);11031104/*1105* The next firmware call is time sensitive. Time it to1106* avoid risk of a hard lock, by trying to ensure the call1107* happens within the first 100 lines of the top field.1108* Make 4 attempts to sync to the decoder before giving up.1109*/1110for (f = 0; f < 4; f++) {1111prepare_to_wait(&itv->vsync_waitq, &wait,1112TASK_UNINTERRUPTIBLE);1113if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)1114break;1115schedule_timeout(msecs_to_jiffies(25));1116}1117finish_wait(&itv->vsync_waitq, &wait);11181119if (f == 4)1120IVTV_WARN("Mode change failed to sync to decoder\n");11211122ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);1123itv->main_rect.left = 0;1124itv->main_rect.top = 0;1125itv->main_rect.width = 720;1126itv->main_rect.height = itv->is_out_50hz ? 576 : 480;1127ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,1128720, itv->main_rect.height, 0, 0);1129yi->main_rect = itv->main_rect;1130if (!itv->osd_info) {1131yi->osd_full_w = 720;1132yi->osd_full_h = itv->is_out_50hz ? 576 : 480;1133}1134}11351136int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)1137{1138struct ivtv *itv = fh2id(fh)->itv;11391140if ((*std & V4L2_STD_ALL) == 0)1141return -EINVAL;11421143if (*std == itv->std)1144return 0;11451146if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||1147atomic_read(&itv->capturing) > 0 ||1148atomic_read(&itv->decoding) > 0) {1149/* Switching standard would mess with already running1150streams, prevent that by returning EBUSY. */1151return -EBUSY;1152}11531154IVTV_DEBUG_INFO("Switching standard to %llx.\n",1155(unsigned long long)itv->std);11561157ivtv_s_std_enc(itv, std);1158if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)1159ivtv_s_std_dec(itv, std);11601161return 0;1162}11631164static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)1165{1166struct ivtv_open_id *id = fh2id(fh);1167struct ivtv *itv = id->itv;11681169if (vt->index != 0)1170return -EINVAL;11711172ivtv_call_all(itv, tuner, s_tuner, vt);11731174return 0;1175}11761177static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)1178{1179struct ivtv *itv = fh2id(fh)->itv;11801181if (vt->index != 0)1182return -EINVAL;11831184ivtv_call_all(itv, tuner, g_tuner, vt);11851186if (vt->type == V4L2_TUNER_RADIO)1187strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));1188else1189strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));1190return 0;1191}11921193static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)1194{1195struct ivtv *itv = fh2id(fh)->itv;1196int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;1197int f, l;11981199if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {1200for (f = 0; f < 2; f++) {1201for (l = 0; l < 24; l++) {1202if (valid_service_line(f, l, itv->is_50hz))1203cap->service_lines[f][l] = set;1204}1205}1206return 0;1207}1208if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {1209if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))1210return -EINVAL;1211if (itv->is_60hz) {1212cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;1213cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;1214} else {1215cap->service_lines[0][23] = V4L2_SLICED_WSS_625;1216cap->service_lines[0][16] = V4L2_SLICED_VPS;1217}1218return 0;1219}1220return -EINVAL;1221}12221223static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)1224{1225struct ivtv *itv = fh2id(fh)->itv;1226struct v4l2_enc_idx_entry *e = idx->entry;1227int entries;1228int i;12291230entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %1231IVTV_MAX_PGM_INDEX;1232if (entries > V4L2_ENC_IDX_ENTRIES)1233entries = V4L2_ENC_IDX_ENTRIES;1234idx->entries = 0;1235for (i = 0; i < entries; i++) {1236*e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];1237if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {1238idx->entries++;1239e++;1240}1241}1242itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;1243return 0;1244}12451246static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)1247{1248struct ivtv_open_id *id = fh2id(fh);1249struct ivtv *itv = id->itv;125012511252switch (enc->cmd) {1253case V4L2_ENC_CMD_START:1254IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");1255enc->flags = 0;1256return ivtv_start_capture(id);12571258case V4L2_ENC_CMD_STOP:1259IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");1260enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;1261ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);1262return 0;12631264case V4L2_ENC_CMD_PAUSE:1265IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");1266enc->flags = 0;12671268if (!atomic_read(&itv->capturing))1269return -EPERM;1270if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))1271return 0;12721273ivtv_mute(itv);1274ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);1275break;12761277case V4L2_ENC_CMD_RESUME:1278IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");1279enc->flags = 0;12801281if (!atomic_read(&itv->capturing))1282return -EPERM;12831284if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))1285return 0;12861287ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);1288ivtv_unmute(itv);1289break;1290default:1291IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);1292return -EINVAL;1293}12941295return 0;1296}12971298static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)1299{1300struct ivtv *itv = fh2id(fh)->itv;13011302switch (enc->cmd) {1303case V4L2_ENC_CMD_START:1304IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");1305enc->flags = 0;1306return 0;13071308case V4L2_ENC_CMD_STOP:1309IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");1310enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;1311return 0;13121313case V4L2_ENC_CMD_PAUSE:1314IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");1315enc->flags = 0;1316return 0;13171318case V4L2_ENC_CMD_RESUME:1319IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");1320enc->flags = 0;1321return 0;1322default:1323IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);1324return -EINVAL;1325}1326}13271328static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)1329{1330struct ivtv *itv = fh2id(fh)->itv;1331u32 data[CX2341X_MBOX_MAX_DATA];1332struct yuv_playback_info *yi = &itv->yuv_info;13331334int pixfmt;1335static u32 pixel_format[16] = {1336V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */1337V4L2_PIX_FMT_RGB565,1338V4L2_PIX_FMT_RGB555,1339V4L2_PIX_FMT_RGB444,1340V4L2_PIX_FMT_RGB32,13410,13420,13430,1344V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */1345V4L2_PIX_FMT_YUV565,1346V4L2_PIX_FMT_YUV555,1347V4L2_PIX_FMT_YUV444,1348V4L2_PIX_FMT_YUV32,13490,13500,13510,1352};13531354if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))1355return -EINVAL;1356if (!itv->osd_video_pbase)1357return -EINVAL;13581359fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |1360V4L2_FBUF_CAP_GLOBAL_ALPHA;13611362ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);1363data[0] |= (read_reg(0x2a00) >> 7) & 0x40;1364pixfmt = (data[0] >> 3) & 0xf;13651366fb->fmt.pixelformat = pixel_format[pixfmt];1367fb->fmt.width = itv->osd_rect.width;1368fb->fmt.height = itv->osd_rect.height;1369fb->fmt.field = V4L2_FIELD_INTERLACED;1370fb->fmt.bytesperline = fb->fmt.width;1371fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;1372fb->fmt.field = V4L2_FIELD_INTERLACED;1373fb->fmt.priv = 0;1374if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)1375fb->fmt.bytesperline *= 2;1376if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||1377fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)1378fb->fmt.bytesperline *= 2;1379fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;1380fb->base = (void *)itv->osd_video_pbase;1381fb->flags = 0;13821383if (itv->osd_chroma_key_state)1384fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;13851386if (itv->osd_global_alpha_state)1387fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;13881389if (yi->track_osd)1390fb->flags |= V4L2_FBUF_FLAG_OVERLAY;13911392pixfmt &= 7;13931394/* no local alpha for RGB565 or unknown formats */1395if (pixfmt == 1 || pixfmt > 4)1396return 0;13971398/* 16-bit formats have inverted local alpha */1399if (pixfmt == 2 || pixfmt == 3)1400fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;1401else1402fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;14031404if (itv->osd_local_alpha_state) {1405/* 16-bit formats have inverted local alpha */1406if (pixfmt == 2 || pixfmt == 3)1407fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;1408else1409fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;1410}14111412return 0;1413}14141415static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)1416{1417struct ivtv_open_id *id = fh2id(fh);1418struct ivtv *itv = id->itv;1419struct yuv_playback_info *yi = &itv->yuv_info;14201421if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))1422return -EINVAL;1423if (!itv->osd_video_pbase)1424return -EINVAL;14251426itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;1427itv->osd_local_alpha_state =1428(fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;1429itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;1430ivtv_set_osd_alpha(itv);1431yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;1432return ivtv_g_fbuf(file, fh, fb);1433}14341435static int ivtv_overlay(struct file *file, void *fh, unsigned int on)1436{1437struct ivtv_open_id *id = fh2id(fh);1438struct ivtv *itv = id->itv;14391440if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))1441return -EINVAL;14421443ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);14441445return 0;1446}14471448static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub)1449{1450switch (sub->type) {1451case V4L2_EVENT_VSYNC:1452case V4L2_EVENT_EOS:1453break;1454default:1455return -EINVAL;1456}1457return v4l2_event_subscribe(fh, sub);1458}14591460static int ivtv_log_status(struct file *file, void *fh)1461{1462struct ivtv *itv = fh2id(fh)->itv;1463u32 data[CX2341X_MBOX_MAX_DATA];14641465int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;1466struct v4l2_input vidin;1467struct v4l2_audio audin;1468int i;14691470IVTV_INFO("================= START STATUS CARD #%d =================\n",1471itv->instance);1472IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);1473if (itv->hw_flags & IVTV_HW_TVEEPROM) {1474struct tveeprom tv;14751476ivtv_read_eeprom(itv, &tv);1477}1478ivtv_call_all(itv, core, log_status);1479ivtv_get_input(itv, itv->active_input, &vidin);1480ivtv_get_audio_input(itv, itv->audio_input, &audin);1481IVTV_INFO("Video Input: %s\n", vidin.name);1482IVTV_INFO("Audio Input: %s%s\n", audin.name,1483(itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");1484if (has_output) {1485struct v4l2_output vidout;1486struct v4l2_audioout audout;1487int mode = itv->output_mode;1488static const char * const output_modes[5] = {1489"None",1490"MPEG Streaming",1491"YUV Streaming",1492"YUV Frames",1493"Passthrough",1494};1495static const char * const audio_modes[5] = {1496"Stereo",1497"Left",1498"Right",1499"Mono",1500"Swapped"1501};1502static const char * const alpha_mode[4] = {1503"None",1504"Global",1505"Local",1506"Global and Local"1507};1508static const char * const pixel_format[16] = {1509"ARGB Indexed",1510"RGB 5:6:5",1511"ARGB 1:5:5:5",1512"ARGB 1:4:4:4",1513"ARGB 8:8:8:8",1514"5",1515"6",1516"7",1517"AYUV Indexed",1518"YUV 5:6:5",1519"AYUV 1:5:5:5",1520"AYUV 1:4:4:4",1521"AYUV 8:8:8:8",1522"13",1523"14",1524"15",1525};15261527ivtv_get_output(itv, itv->active_output, &vidout);1528ivtv_get_audio_output(itv, 0, &audout);1529IVTV_INFO("Video Output: %s\n", vidout.name);1530IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,1531audio_modes[itv->audio_stereo_mode],1532audio_modes[itv->audio_bilingual_mode]);1533if (mode < 0 || mode > OUT_PASSTHROUGH)1534mode = OUT_NONE;1535IVTV_INFO("Output Mode: %s\n", output_modes[mode]);1536ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);1537data[0] |= (read_reg(0x2a00) >> 7) & 0x40;1538IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",1539data[0] & 1 ? "On" : "Off",1540alpha_mode[(data[0] >> 1) & 0x3],1541pixel_format[(data[0] >> 3) & 0xf]);1542}1543IVTV_INFO("Tuner: %s\n",1544test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");1545v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);1546IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);1547for (i = 0; i < IVTV_MAX_STREAMS; i++) {1548struct ivtv_stream *s = &itv->streams[i];15491550if (s->vdev == NULL || s->buffers == 0)1551continue;1552IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,1553(s->buffers - s->q_free.buffers) * 100 / s->buffers,1554(s->buffers * s->buf_size) / 1024, s->buffers);1555}15561557IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",1558(long long)itv->mpg_data_received,1559(long long)itv->vbi_data_inserted);1560IVTV_INFO("================== END STATUS CARD #%d ==================\n",1561itv->instance);15621563return 0;1564}15651566static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)1567{1568struct ivtv_open_id *id = fh2id(filp->private_data);1569struct ivtv *itv = id->itv;1570int nonblocking = filp->f_flags & O_NONBLOCK;1571struct ivtv_stream *s = &itv->streams[id->type];1572unsigned long iarg = (unsigned long)arg;15731574switch (cmd) {1575case IVTV_IOC_DMA_FRAME: {1576struct ivtv_dma_frame *args = arg;15771578IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");1579if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))1580return -EINVAL;1581if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)1582return -EINVAL;1583if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)1584return 0;1585if (ivtv_start_decoding(id, id->type)) {1586return -EBUSY;1587}1588if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {1589ivtv_release_stream(s);1590return -EBUSY;1591}1592/* Mark that this file handle started the UDMA_YUV mode */1593id->yuv_frames = 1;1594if (args->y_source == NULL)1595return 0;1596return ivtv_yuv_prep_frame(itv, args);1597}15981599case VIDEO_GET_PTS: {1600u32 data[CX2341X_MBOX_MAX_DATA];1601u64 *pts = arg;16021603IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");1604if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {1605*pts = s->dma_pts;1606break;1607}1608if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))1609return -EINVAL;16101611if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {1612*pts = (u64) ((u64)itv->last_dec_timing[2] << 32) |1613(u64)itv->last_dec_timing[1];1614break;1615}1616*pts = 0;1617if (atomic_read(&itv->decoding)) {1618if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {1619IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");1620return -EIO;1621}1622memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));1623set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);1624*pts = (u64) ((u64) data[2] << 32) | (u64) data[1];1625/*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/1626}1627break;1628}16291630case VIDEO_GET_FRAME_COUNT: {1631u32 data[CX2341X_MBOX_MAX_DATA];1632u64 *frame = arg;16331634IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");1635if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {1636*frame = 0;1637break;1638}1639if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))1640return -EINVAL;16411642if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {1643*frame = itv->last_dec_timing[0];1644break;1645}1646*frame = 0;1647if (atomic_read(&itv->decoding)) {1648if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {1649IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");1650return -EIO;1651}1652memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));1653set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);1654*frame = data[0];1655}1656break;1657}16581659case VIDEO_PLAY: {1660struct video_command vc;16611662IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");1663memset(&vc, 0, sizeof(vc));1664vc.cmd = VIDEO_CMD_PLAY;1665return ivtv_video_command(itv, id, &vc, 0);1666}16671668case VIDEO_STOP: {1669struct video_command vc;16701671IVTV_DEBUG_IOCTL("VIDEO_STOP\n");1672memset(&vc, 0, sizeof(vc));1673vc.cmd = VIDEO_CMD_STOP;1674vc.flags = VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY;1675return ivtv_video_command(itv, id, &vc, 0);1676}16771678case VIDEO_FREEZE: {1679struct video_command vc;16801681IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");1682memset(&vc, 0, sizeof(vc));1683vc.cmd = VIDEO_CMD_FREEZE;1684return ivtv_video_command(itv, id, &vc, 0);1685}16861687case VIDEO_CONTINUE: {1688struct video_command vc;16891690IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");1691memset(&vc, 0, sizeof(vc));1692vc.cmd = VIDEO_CMD_CONTINUE;1693return ivtv_video_command(itv, id, &vc, 0);1694}16951696case VIDEO_COMMAND:1697case VIDEO_TRY_COMMAND: {1698struct video_command *vc = arg;1699int try = (cmd == VIDEO_TRY_COMMAND);17001701if (try)1702IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", vc->cmd);1703else1704IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", vc->cmd);1705return ivtv_video_command(itv, id, vc, try);1706}17071708case VIDEO_GET_EVENT: {1709struct video_event *ev = arg;1710DEFINE_WAIT(wait);17111712IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");1713if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))1714return -EINVAL;1715memset(ev, 0, sizeof(*ev));1716set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);17171718while (1) {1719if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))1720ev->type = VIDEO_EVENT_DECODER_STOPPED;1721else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {1722ev->type = VIDEO_EVENT_VSYNC;1723ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?1724VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;1725if (itv->output_mode == OUT_UDMA_YUV &&1726(itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==1727IVTV_YUV_MODE_PROGRESSIVE) {1728ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;1729}1730}1731if (ev->type)1732return 0;1733if (nonblocking)1734return -EAGAIN;1735/* Wait for event. Note that serialize_lock is locked,1736so to allow other processes to access the driver while1737we are waiting unlock first and later lock again. */1738mutex_unlock(&itv->serialize_lock);1739prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);1740if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&1741!test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))1742schedule();1743finish_wait(&itv->event_waitq, &wait);1744mutex_lock(&itv->serialize_lock);1745if (signal_pending(current)) {1746/* return if a signal was received */1747IVTV_DEBUG_INFO("User stopped wait for event\n");1748return -EINTR;1749}1750}1751break;1752}17531754case VIDEO_SELECT_SOURCE:1755IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");1756if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))1757return -EINVAL;1758return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);17591760case AUDIO_SET_MUTE:1761IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");1762itv->speed_mute_audio = iarg;1763return 0;17641765case AUDIO_CHANNEL_SELECT:1766IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");1767if (iarg > AUDIO_STEREO_SWAPPED)1768return -EINVAL;1769itv->audio_stereo_mode = iarg;1770ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);1771return 0;17721773case AUDIO_BILINGUAL_CHANNEL_SELECT:1774IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");1775if (iarg > AUDIO_STEREO_SWAPPED)1776return -EINVAL;1777itv->audio_bilingual_mode = iarg;1778ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);1779return 0;17801781default:1782return -EINVAL;1783}1784return 0;1785}17861787static long ivtv_default(struct file *file, void *fh, bool valid_prio,1788int cmd, void *arg)1789{1790struct ivtv *itv = fh2id(fh)->itv;17911792if (!valid_prio) {1793switch (cmd) {1794case VIDEO_PLAY:1795case VIDEO_STOP:1796case VIDEO_FREEZE:1797case VIDEO_CONTINUE:1798case VIDEO_COMMAND:1799case VIDEO_SELECT_SOURCE:1800case AUDIO_SET_MUTE:1801case AUDIO_CHANNEL_SELECT:1802case AUDIO_BILINGUAL_CHANNEL_SELECT:1803return -EBUSY;1804}1805}18061807switch (cmd) {1808case VIDIOC_INT_RESET: {1809u32 val = *(u32 *)arg;18101811if ((val == 0 && itv->options.newi2c) || (val & 0x01))1812ivtv_reset_ir_gpio(itv);1813if (val & 0x02)1814v4l2_subdev_call(itv->sd_video, core, reset, 0);1815break;1816}18171818case IVTV_IOC_DMA_FRAME:1819case VIDEO_GET_PTS:1820case VIDEO_GET_FRAME_COUNT:1821case VIDEO_GET_EVENT:1822case VIDEO_PLAY:1823case VIDEO_STOP:1824case VIDEO_FREEZE:1825case VIDEO_CONTINUE:1826case VIDEO_COMMAND:1827case VIDEO_TRY_COMMAND:1828case VIDEO_SELECT_SOURCE:1829case AUDIO_SET_MUTE:1830case AUDIO_CHANNEL_SELECT:1831case AUDIO_BILINGUAL_CHANNEL_SELECT:1832return ivtv_decoder_ioctls(file, cmd, (void *)arg);18331834default:1835return -EINVAL;1836}1837return 0;1838}18391840static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,1841unsigned int cmd, unsigned long arg)1842{1843struct video_device *vfd = video_devdata(filp);1844long ret;18451846if (ivtv_debug & IVTV_DBGFLG_IOCTL)1847vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;1848ret = video_ioctl2(filp, cmd, arg);1849vfd->debug = 0;1850return ret;1851}18521853long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)1854{1855struct ivtv_open_id *id = fh2id(filp->private_data);1856struct ivtv *itv = id->itv;1857long res;18581859/* DQEVENT can block, so this should not run with the serialize lock */1860if (cmd == VIDIOC_DQEVENT)1861return ivtv_serialized_ioctl(itv, filp, cmd, arg);1862mutex_lock(&itv->serialize_lock);1863res = ivtv_serialized_ioctl(itv, filp, cmd, arg);1864mutex_unlock(&itv->serialize_lock);1865return res;1866}18671868static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {1869.vidioc_querycap = ivtv_querycap,1870.vidioc_s_audio = ivtv_s_audio,1871.vidioc_g_audio = ivtv_g_audio,1872.vidioc_enumaudio = ivtv_enumaudio,1873.vidioc_s_audout = ivtv_s_audout,1874.vidioc_g_audout = ivtv_g_audout,1875.vidioc_enum_input = ivtv_enum_input,1876.vidioc_enum_output = ivtv_enum_output,1877.vidioc_enumaudout = ivtv_enumaudout,1878.vidioc_cropcap = ivtv_cropcap,1879.vidioc_s_crop = ivtv_s_crop,1880.vidioc_g_crop = ivtv_g_crop,1881.vidioc_g_input = ivtv_g_input,1882.vidioc_s_input = ivtv_s_input,1883.vidioc_g_output = ivtv_g_output,1884.vidioc_s_output = ivtv_s_output,1885.vidioc_g_frequency = ivtv_g_frequency,1886.vidioc_s_frequency = ivtv_s_frequency,1887.vidioc_s_tuner = ivtv_s_tuner,1888.vidioc_g_tuner = ivtv_g_tuner,1889.vidioc_g_enc_index = ivtv_g_enc_index,1890.vidioc_g_fbuf = ivtv_g_fbuf,1891.vidioc_s_fbuf = ivtv_s_fbuf,1892.vidioc_g_std = ivtv_g_std,1893.vidioc_s_std = ivtv_s_std,1894.vidioc_overlay = ivtv_overlay,1895.vidioc_log_status = ivtv_log_status,1896.vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap,1897.vidioc_encoder_cmd = ivtv_encoder_cmd,1898.vidioc_try_encoder_cmd = ivtv_try_encoder_cmd,1899.vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out,1900.vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap,1901.vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap,1902.vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap,1903.vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out,1904.vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay,1905.vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out,1906.vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap,1907.vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap,1908.vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap,1909.vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out,1910.vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay,1911.vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out,1912.vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap,1913.vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap,1914.vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap,1915.vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out,1916.vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay,1917.vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out,1918.vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap,1919.vidioc_g_chip_ident = ivtv_g_chip_ident,1920#ifdef CONFIG_VIDEO_ADV_DEBUG1921.vidioc_g_register = ivtv_g_register,1922.vidioc_s_register = ivtv_s_register,1923#endif1924.vidioc_default = ivtv_default,1925.vidioc_subscribe_event = ivtv_subscribe_event,1926.vidioc_unsubscribe_event = v4l2_event_unsubscribe,1927};19281929void ivtv_set_funcs(struct video_device *vdev)1930{1931vdev->ioctl_ops = &ivtv_ioctl_ops;1932}193319341935