From patchwork Thu Dec 2 17:29:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lane Brooks X-Patchwork-Id: 375341 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oB2HTpiQ018818 for ; Thu, 2 Dec 2010 17:29:52 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757228Ab0LBR3u (ORCPT ); Thu, 2 Dec 2010 12:29:50 -0500 Received: from mail-fx0-f46.google.com ([209.85.161.46]:61748 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752830Ab0LBR3t (ORCPT ); Thu, 2 Dec 2010 12:29:49 -0500 Received: by fxm20 with SMTP id 20so1359307fxm.19 for ; Thu, 02 Dec 2010 09:29:48 -0800 (PST) Received: by 10.223.85.197 with SMTP id p5mr869988fal.65.1291310988072; Thu, 02 Dec 2010 09:29:48 -0800 (PST) Received: from dome.lane.brooks.nu (c-24-10-162-244.hsd1.ut.comcast.net [24.10.162.244]) by mx.google.com with ESMTPS id a25sm287800fak.20.2010.12.02.09.29.45 (version=SSLv3 cipher=RC4-MD5); Thu, 02 Dec 2010 09:29:46 -0800 (PST) Message-ID: <4CF7D785.9050606@brooks.nu> Date: Thu, 02 Dec 2010 10:29:41 -0700 From: Lane Brooks User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.12) Gecko/20101027 Fedora/3.1.6-1.fc13 Thunderbird/3.1.6 MIME-Version: 1.0 To: "laurent.pinchart@ideasonboard.com" , "linux-media@vger.kernel.org" Subject: ispvideo patch Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 02 Dec 2010 17:29:52 +0000 (UTC) diff --git a/drivers/media/video/isp/ispvideo.c b/drivers/media/video/isp/ispvideo.c index 1edfafa..0e37062 100644 --- a/drivers/media/video/isp/ispvideo.c +++ b/drivers/media/video/isp/ispvideo.c @@ -988,6 +988,69 @@ isp_video_s_input(struct file *file, void *fh, unsigned int input) return input == 0 ? 0 : -EINVAL; } +static int +isp_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) +{ + struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video *video = video_drvdata(file); + + if (f->index > 0 || f->type != video->type) + return -EINVAL; + + mutex_lock(&video->mutex); + f->flags = 0; + f->pixelformat = vfh->format.fmt.pix.pixelformat; + mutex_unlock(&video->mutex); + return 0; +} + +static int +isp_video_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *f) +{ + int ret = 0; + struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video *video = video_drvdata(file); + + if (f->index > 0) + return -EINVAL; + + mutex_lock(&video->mutex); + if (f->pixel_format == vfh->format.fmt.pix.pixelformat) { + f->type = V4L2_FRMSIZE_TYPE_DISCRETE; + f->discrete.width = vfh->format.fmt.pix.width; + f->discrete.height = vfh->format.fmt.pix.height; + } else { + ret = -EINVAL; + } + mutex_unlock(&video->mutex); + return 0; +} + +static int +isp_video_enum_ivals(struct file *file, void *fh, struct v4l2_frmivalenum *f) +{ + int ret = 0; + struct isp_video_fh *vfh = to_isp_video_fh(fh); + struct isp_video *video = video_drvdata(file); + + if (f->index > 0) + return -EINVAL; + + mutex_lock(&video->mutex); + if (f->pixel_format == vfh->format.fmt.pix.pixelformat && + f->width == vfh->format.fmt.pix.width && + f->height == vfh->format.fmt.pix.height) { + f->type = V4L2_FRMIVAL_TYPE_DISCRETE; + f->discrete.numerator = vfh->timeperframe.numerator; + f->discrete.denominator = vfh->timeperframe.denominator; + } else { + ret = -EINVAL; + } + mutex_unlock(&video->mutex); + return ret; +} + static const struct v4l2_ioctl_ops isp_video_ioctl_ops = { .vidioc_querycap = isp_video_querycap, .vidioc_g_fmt_vid_cap = isp_video_get_format, @@ -1010,16 +1073,57 @@ static const struct v4l2_ioctl_ops isp_video_ioctl_ops = { .vidioc_enum_input = isp_video_enum_input, .vidioc_g_input = isp_video_g_input, .vidioc_s_input = isp_video_s_input, + .vidioc_enum_fmt_vid_cap = isp_video_enum_format, + .vidioc_enum_frameintervals = isp_video_enum_ivals, + .vidioc_enum_framesizes = isp_video_enum_framesizes, }; /* ----------------------------------------------------------------------------- * V4L2 file operations */ +static int __find_timeperframe(struct media_entity_pad *pad, + struct v4l2_subdev *subdev, + struct v4l2_subdev_frame_interval *fi, + int depth) { + int err; + unsigned int i; + if (depth > 16) /* max depth. if this depth reached, bail the search. */ + return -EINVAL; + + err = v4l2_subdev_call(subdev, video, g_frame_interval, fi); + if (err < 0) { + /* Trace backwards through the pipeline to find a subdev + with the frame interval set. */ + struct media_entity_pad *_pad; + struct v4l2_subdev *_subdev; + for (i = 0; i < pad->entity->num_pads; ++i) { + _pad = pad->entity->pads + i; + if (i == pad->index || + _pad->type != MEDIA_PAD_TYPE_INPUT) + continue; + _pad = media_entity_remote_pad(_pad); + if (!_pad || + _pad->entity->type != MEDIA_ENTITY_TYPE_SUBDEV) + continue; + _subdev = media_entity_to_v4l2_subdev(_pad->entity); + err = __find_timeperframe(_pad, _subdev, fi, depth+1); + if (err < 0) + continue; + else + return err; + } + return -EINVAL; /* search failed to find any frame intervals */ + } else { + return err; + } +} + static int isp_video_open(struct file *file) { struct isp_video *video = video_drvdata(file); struct isp_video_fh *handle; + struct media_entity_pad *pad; int ret = 0; handle = kzalloc(sizeof(*handle), GFP_KERNEL); @@ -1042,6 +1146,29 @@ static int isp_video_open(struct file *file) handle->format.type = video->type; handle->timeperframe.denominator = 1; + /* If a subdev is linked to this dev, then initialize the + format to match the subdev. */ + pad = media_entity_remote_pad(&video->pad); + if (pad && pad->entity->type == MEDIA_ENTITY_TYPE_SUBDEV) { + struct v4l2_subdev *subdev; + struct v4l2_mbus_framefmt fmt_source; + struct v4l2_subdev_frame_interval fi; + int err; + subdev = media_entity_to_v4l2_subdev(pad->entity); + err = v4l2_subdev_call(subdev, pad, get_fmt, NULL, pad->index, + &fmt_source, V4L2_SUBDEV_FORMAT_ACTIVE); + if (err >= 0) { + isp_video_mbus_to_pix(video, &fmt_source, + &(handle->format.fmt.pix)); + handle->format.fmt.pix.width = fmt_source.width; + handle->format.fmt.pix.height = fmt_source.height; + } + + err = __find_timeperframe(pad, subdev, &fi, 0); + if (err >= 0) + handle->timeperframe = fi.interval; + } + handle->video = video; file->private_data = &handle->vfh;