From patchwork Wed Mar 18 10:22:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Zabel X-Patchwork-Id: 6037881 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 0B9CB9F399 for ; Wed, 18 Mar 2015 10:23:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C8790204FF for ; Wed, 18 Mar 2015 10:23:07 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id ED9EA20503 for ; Wed, 18 Mar 2015 10:23:05 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 5EBF9720BF; Wed, 18 Mar 2015 03:23:04 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [92.198.50.35]) by gabe.freedesktop.org (Postfix) with ESMTP id 0F4BD6E7F5 for ; Wed, 18 Mar 2015 03:23:01 -0700 (PDT) Received: from dude.hi.4.pengutronix.de ([10.1.0.7] helo=dude.pengutronix.de.) by metis.ext.pengutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1YYB7s-0006KQ-65; Wed, 18 Mar 2015 11:23:00 +0100 From: Philipp Zabel To: linux-media@vger.kernel.org Subject: [PATCH v2 4/5] [media] imx-ipu: Add ipu media common code Date: Wed, 18 Mar 2015 11:22:52 +0100 Message-Id: <1426674173-17088-5-git-send-email-p.zabel@pengutronix.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1426674173-17088-1-git-send-email-p.zabel@pengutronix.de> References: <1426674173-17088-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: dri-devel@lists.freedesktop.org Cc: Mauro Carvalho Chehab , dri-devel@lists.freedesktop.org, Hans Verkuil , kernel@pengutronix.de, Steve Longerbeam , Jean-Michel Hautbois X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 drivers for units that accept or provide video data via the i.MX IPU IDMAC channels, such as scaler or 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 d9b872b..650a9a6 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 3ec1547..2e35581 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera/ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ +obj-y += imx/ obj-y += omap/ obj-$(CONFIG_VIDEO_AM437X_VPFE) += am437x/ 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 */