From patchwork Thu Jun 12 17:06:22 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Zabel X-Patchwork-Id: 4343911 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 142839F440 for ; Thu, 12 Jun 2014 17:07:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D7E6320351 for ; Thu, 12 Jun 2014 17:07:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9BF5220340 for ; Thu, 12 Jun 2014 17:07:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756169AbaFLRHn (ORCPT ); Thu, 12 Jun 2014 13:07:43 -0400 Received: from metis.ext.pengutronix.de ([92.198.50.35]:33022 "EHLO metis.ext.pengutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756171AbaFLRGp (ORCPT ); Thu, 12 Jun 2014 13:06:45 -0400 Received: from dude.hi.pengutronix.de ([10.1.0.7] helo=dude.pengutronix.de) by metis.ext.pengutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1Wv8SZ-0000jm-9J; Thu, 12 Jun 2014 19:06:43 +0200 From: Philipp Zabel To: linux-media@vger.kernel.org Cc: Steve Longerbeam , Sascha Hauer , Lucas Stach , Philipp Zabel Subject: [RFC PATCH 08/26] [media] imx-ipu: add ipu media common code Date: Thu, 12 Jun 2014 19:06:22 +0200 Message-Id: <1402592800-2925-9-git-send-email-p.zabel@pengutronix.de> X-Mailer: git-send-email 2.0.0.rc2 In-Reply-To: <1402592800-2925-1-git-send-email-p.zabel@pengutronix.de> References: <1402592800-2925-1-git-send-email-p.zabel@pengutronix.de> X-SA-Exim-Connect-IP: 10.1.0.7 X-SA-Exim-Mail-From: p.zabel@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-media@vger.kernel.org Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Sascha Hauer Add video4linux API routines common to IPU scaler, overlay, and deinterlacer drivers. Signed-off-by: Sascha Hauer Signed-off-by: Lucas Stach Signed-off-by: Philipp Zabel --- drivers/media/platform/Kconfig | 2 + drivers/media/platform/Makefile | 1 + drivers/media/platform/imx/Kconfig | 2 + drivers/media/platform/imx/Makefile | 1 + drivers/media/platform/imx/imx-ipu.c | 313 +++++++++++++++++++++++++++++++++++ drivers/media/platform/imx/imx-ipu.h | 35 ++++ 6 files changed, 354 insertions(+) create mode 100644 drivers/media/platform/imx/Kconfig create mode 100644 drivers/media/platform/imx/Makefile create mode 100644 drivers/media/platform/imx/imx-ipu.c create mode 100644 drivers/media/platform/imx/imx-ipu.h diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 20f1655..8e9c26c 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -29,6 +29,8 @@ config VIDEO_VIA_CAMERA source "drivers/media/platform/davinci/Kconfig" +source "drivers/media/platform/imx/Kconfig" + source "drivers/media/platform/omap/Kconfig" source "drivers/media/platform/blackfin/Kconfig" diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index e5269da..ba114c0 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera/ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ obj-y += davinci/ +obj-y += imx/ obj-$(CONFIG_ARCH_OMAP) += omap/ diff --git a/drivers/media/platform/imx/Kconfig b/drivers/media/platform/imx/Kconfig new file mode 100644 index 0000000..a90c973 --- /dev/null +++ b/drivers/media/platform/imx/Kconfig @@ -0,0 +1,2 @@ +config VIDEO_IMX_IPU_COMMON + tristate diff --git a/drivers/media/platform/imx/Makefile b/drivers/media/platform/imx/Makefile new file mode 100644 index 0000000..5de119c --- /dev/null +++ b/drivers/media/platform/imx/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_IMX_IPU_COMMON) += imx-ipu.o diff --git a/drivers/media/platform/imx/imx-ipu.c b/drivers/media/platform/imx/imx-ipu.c new file mode 100644 index 0000000..c1b8637 --- /dev/null +++ b/drivers/media/platform/imx/imx-ipu.c @@ -0,0 +1,313 @@ +/* + * i.MX IPUv3 common v4l2 support + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include + +#include "imx-ipu.h" + +static struct ipu_fmt ipu_fmt_yuv[] = { + { + .fourcc = V4L2_PIX_FMT_YUV420, + .name = "YUV 4:2:0 planar, YCbCr", + .bytes_per_pixel = 1, + }, { + .fourcc = V4L2_PIX_FMT_YVU420, + .name = "YUV 4:2:0 planar, YCrCb", + .bytes_per_pixel = 1, + }, { + .fourcc = V4L2_PIX_FMT_YUV422P, + .name = "YUV 4:2:2 planar, YCbCr", + .bytes_per_pixel = 1, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .name = "YUV 4:2:0 partial interleaved, YCbCr", + .bytes_per_pixel = 1, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .name = "4:2:2, packed, UYVY", + .bytes_per_pixel = 2, + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .name = "4:2:2, packed, YUYV", + .bytes_per_pixel = 2, + }, +}; + +static struct ipu_fmt ipu_fmt_rgb[] = { + { + .fourcc = V4L2_PIX_FMT_RGB32, + .name = "RGB888", + .bytes_per_pixel = 4, + }, { + .fourcc = V4L2_PIX_FMT_RGB24, + .name = "RGB24", + .bytes_per_pixel = 3, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, + .name = "BGR24", + .bytes_per_pixel = 3, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bytes_per_pixel = 2, + }, + { + .fourcc = V4L2_PIX_FMT_BGR32, + .name = "BGR888", + .bytes_per_pixel = 4, + }, +}; + +struct ipu_fmt *ipu_find_fmt_yuv(unsigned int pixelformat) +{ + struct ipu_fmt *fmt; + int i; + + for (i = 0; i < ARRAY_SIZE(ipu_fmt_yuv); i++) { + fmt = &ipu_fmt_yuv[i]; + if (fmt->fourcc == pixelformat) + return fmt; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(ipu_find_fmt_yuv); + +struct ipu_fmt *ipu_find_fmt_rgb(unsigned int pixelformat) +{ + struct ipu_fmt *fmt; + int i; + + for (i = 0; i < ARRAY_SIZE(ipu_fmt_rgb); i++) { + fmt = &ipu_fmt_rgb[i]; + if (fmt->fourcc == pixelformat) + return fmt; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(ipu_find_fmt_rgb); + +static struct ipu_fmt *ipu_find_fmt(unsigned long pixelformat) +{ + struct ipu_fmt *fmt; + + fmt = ipu_find_fmt_yuv(pixelformat); + if (fmt) + return fmt; + fmt = ipu_find_fmt_rgb(pixelformat); + + return fmt; +} +EXPORT_SYMBOL_GPL(ipu_find_fmt); + +int ipu_try_fmt(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct ipu_fmt *fmt; + + v4l_bound_align_image(&f->fmt.pix.width, 8, 4096, 2, + &f->fmt.pix.height, 2, 4096, 1, 0); + + f->fmt.pix.field = V4L2_FIELD_NONE; + + fmt = ipu_find_fmt(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + + f->fmt.pix.bytesperline = f->fmt.pix.width * fmt->bytes_per_pixel; + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; + if (fmt->fourcc == V4L2_PIX_FMT_YUV420 || + fmt->fourcc == V4L2_PIX_FMT_YVU420 || + fmt->fourcc == V4L2_PIX_FMT_NV12) + f->fmt.pix.sizeimage = f->fmt.pix.sizeimage * 3 / 2; + else if (fmt->fourcc == V4L2_PIX_FMT_YUV422P) + f->fmt.pix.sizeimage *= 2; + + f->fmt.pix.priv = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_try_fmt); + +int ipu_try_fmt_rgb(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct ipu_fmt *fmt; + + fmt = ipu_find_fmt_rgb(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + + return ipu_try_fmt(file, fh, f); +} +EXPORT_SYMBOL_GPL(ipu_try_fmt_rgb); + +int ipu_try_fmt_yuv(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct ipu_fmt *fmt; + + fmt = ipu_find_fmt_yuv(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + + return ipu_try_fmt(file, fh, f); +} +EXPORT_SYMBOL_GPL(ipu_try_fmt_yuv); + +int ipu_enum_fmt_rgb(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + struct ipu_fmt *fmt; + + if (f->index >= ARRAY_SIZE(ipu_fmt_rgb)) + return -EINVAL; + + fmt = &ipu_fmt_rgb[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_enum_fmt_rgb); + +int ipu_enum_fmt_yuv(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + struct ipu_fmt *fmt; + + if (f->index >= ARRAY_SIZE(ipu_fmt_yuv)) + return -EINVAL; + + fmt = &ipu_fmt_yuv[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_enum_fmt_yuv); + +int ipu_enum_fmt(struct file *file, void *fh, + struct v4l2_fmtdesc *f) +{ + struct ipu_fmt *fmt; + int index = f->index; + + if (index >= ARRAY_SIZE(ipu_fmt_yuv)) { + index -= ARRAY_SIZE(ipu_fmt_yuv); + if (index >= ARRAY_SIZE(ipu_fmt_rgb)) + return -EINVAL; + fmt = &ipu_fmt_rgb[index]; + } else { + fmt = &ipu_fmt_yuv[index]; + } + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_enum_fmt); + +int ipu_s_fmt(struct file *file, void *fh, + struct v4l2_format *f, struct v4l2_pix_format *pix) +{ + int ret; + + ret = ipu_try_fmt(file, fh, f); + if (ret) + return ret; + + pix->width = f->fmt.pix.width; + pix->height = f->fmt.pix.height; + pix->pixelformat = f->fmt.pix.pixelformat; + pix->bytesperline = f->fmt.pix.bytesperline; + pix->sizeimage = f->fmt.pix.sizeimage; + pix->colorspace = f->fmt.pix.colorspace; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_s_fmt); + +int ipu_s_fmt_rgb(struct file *file, void *fh, + struct v4l2_format *f, struct v4l2_pix_format *pix) +{ + struct ipu_fmt *fmt; + + fmt = ipu_find_fmt_rgb(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + + return ipu_s_fmt(file, fh, f, pix); +} +EXPORT_SYMBOL_GPL(ipu_s_fmt_rgb); + +int ipu_s_fmt_yuv(struct file *file, void *fh, + struct v4l2_format *f, struct v4l2_pix_format *pix) +{ + struct ipu_fmt *fmt; + + fmt = ipu_find_fmt_yuv(f->fmt.pix.pixelformat); + if (!fmt) + return -EINVAL; + + return ipu_s_fmt(file, fh, f, pix); +} +EXPORT_SYMBOL_GPL(ipu_s_fmt_yuv); + +int ipu_g_fmt(struct v4l2_format *f, struct v4l2_pix_format *pix) +{ + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = pix->pixelformat; + f->fmt.pix.bytesperline = pix->bytesperline; + f->fmt.pix.width = pix->width; + f->fmt.pix.height = pix->height; + f->fmt.pix.sizeimage = pix->sizeimage; + f->fmt.pix.colorspace = pix->colorspace; + f->fmt.pix.priv = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_g_fmt); + +int ipu_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct ipu_fmt *fmt; + + if (fsize->index != 0) + return -EINVAL; + + fmt = ipu_find_fmt(fsize->pixel_format); + if (!fmt) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + fsize->stepwise.min_width = 1; + fsize->stepwise.min_height = 1; + fsize->stepwise.max_width = 4096; + fsize->stepwise.max_height = 4096; + fsize->stepwise.step_width = fsize->stepwise.step_height = 1; + + return 0; +} +EXPORT_SYMBOL_GPL(ipu_enum_framesizes); + +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/imx/imx-ipu.h b/drivers/media/platform/imx/imx-ipu.h new file mode 100644 index 0000000..51c0982 --- /dev/null +++ b/drivers/media/platform/imx/imx-ipu.h @@ -0,0 +1,35 @@ +#ifndef __MEDIA_IMX_IPU_H +#define __MEDIA_IMX_IPU_H +#include + +struct ipu_fmt { + u32 fourcc; + const char *name; + int bytes_per_pixel; +}; + +int ipu_enum_fmt(struct file *file, void *fh, + struct v4l2_fmtdesc *f); +int ipu_enum_fmt_rgb(struct file *file, void *fh, + struct v4l2_fmtdesc *f); +int ipu_enum_fmt_yuv(struct file *file, void *fh, + struct v4l2_fmtdesc *f); +struct ipu_fmt *ipu_find_fmt_rgb(unsigned int pixelformat); +struct ipu_fmt *ipu_find_fmt_yuv(unsigned int pixelformat); +int ipu_try_fmt(struct file *file, void *fh, + struct v4l2_format *f); +int ipu_try_fmt_rgb(struct file *file, void *fh, + struct v4l2_format *f); +int ipu_try_fmt_yuv(struct file *file, void *fh, + struct v4l2_format *f); +int ipu_s_fmt(struct file *file, void *fh, + struct v4l2_format *f, struct v4l2_pix_format *pix); +int ipu_s_fmt_rgb(struct file *file, void *fh, + struct v4l2_format *f, struct v4l2_pix_format *pix); +int ipu_s_fmt_yuv(struct file *file, void *fh, + struct v4l2_format *f, struct v4l2_pix_format *pix); +int ipu_g_fmt(struct v4l2_format *f, struct v4l2_pix_format *pix); +int ipu_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize); + +#endif /* __MEDIA_IMX_IPU_H */