From patchwork Wed Jul 25 16:38:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Todor Tomov X-Patchwork-Id: 10544373 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9EB917FD for ; Wed, 25 Jul 2018 16:40:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A44FC2A75E for ; Wed, 25 Jul 2018 16:40:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9610A2A765; Wed, 25 Jul 2018 16:40:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E81562A75E for ; Wed, 25 Jul 2018 16:39:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731339AbeGYRwT (ORCPT ); Wed, 25 Jul 2018 13:52:19 -0400 Received: from ns.mm-sol.com ([37.157.136.199]:35606 "EHLO extserv.mm-sol.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730033AbeGYRva (ORCPT ); Wed, 25 Jul 2018 13:51:30 -0400 Received: from mms-0439.qualcomm.mm-sol.com (unknown [37.157.136.206]) by extserv.mm-sol.com (Postfix) with ESMTPSA id 95DDDCD6C; Wed, 25 Jul 2018 19:38:54 +0300 (EEST) From: Todor Tomov To: mchehab@kernel.org, sakari.ailus@linux.intel.com, hans.verkuil@cisco.com, laurent.pinchart+renesas@ideasonboard.com, linux-media@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Todor Tomov Subject: [PATCH v4 26/34] media: camss: Format configuration per hardware version Date: Wed, 25 Jul 2018 19:38:35 +0300 Message-Id: <1532536723-19062-27-git-send-email-todor.tomov@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1532536723-19062-1-git-send-email-todor.tomov@linaro.org> References: <1532536723-19062-1-git-send-email-todor.tomov@linaro.org> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP As the 8x16 and 8x96 support different formats, separate the arrays which contain the supported formats. For the VFE also add separate arrays for RDI and PIX subdevices. Signed-off-by: Todor Tomov --- drivers/media/platform/qcom/camss/camss-csid.c | 196 +++++++++++++++++++---- drivers/media/platform/qcom/camss/camss-csid.h | 2 + drivers/media/platform/qcom/camss/camss-csiphy.c | 145 ++++++++--------- drivers/media/platform/qcom/camss/camss-csiphy.h | 2 + drivers/media/platform/qcom/camss/camss-ispif.c | 43 ++++- drivers/media/platform/qcom/camss/camss-ispif.h | 2 + drivers/media/platform/qcom/camss/camss-vfe.c | 189 ++++++++++++---------- drivers/media/platform/qcom/camss/camss-vfe.h | 2 + drivers/media/platform/qcom/camss/camss-video.c | 97 ++++++++++- 9 files changed, 467 insertions(+), 211 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index 915835e..db960da 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -62,7 +62,7 @@ #define CSID_RESET_TIMEOUT_MS 500 -struct csid_fmts { +struct csid_format { u32 code; u8 data_type; u8 decode_format; @@ -70,7 +70,7 @@ struct csid_fmts { u8 spp; /* bus samples per pixel */ }; -static const struct csid_fmts csid_input_fmts[] = { +static const struct csid_format csid_formats_8x16[] = { { MEDIA_BUS_FMT_UYVY8_2X8, DATA_TYPE_YUV422_8BIT, @@ -185,17 +185,135 @@ static const struct csid_fmts csid_input_fmts[] = { } }; -static const struct csid_fmts *csid_get_fmt_entry(u32 code) +static const struct csid_format csid_formats_8x96[] = { + { + MEDIA_BUS_FMT_UYVY8_2X8, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_VYUY8_2X8, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YUYV8_2X8, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YVYU8_2X8, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_SBGGR8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + } +}; + +static const struct csid_format *csid_get_fmt_entry( + const struct csid_format *formats, + unsigned int nformat, + u32 code) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(csid_input_fmts); i++) - if (code == csid_input_fmts[i].code) - return &csid_input_fmts[i]; + for (i = 0; i < nformat; i++) + if (code == formats[i].code) + return &formats[i]; WARN(1, "Unknown format\n"); - return &csid_input_fmts[0]; + return &formats[0]; } /* @@ -242,10 +360,13 @@ static int csid_set_clock_rates(struct csid_device *csid) !strcmp(clock->name, "csi1") || !strcmp(clock->name, "csi2") || !strcmp(clock->name, "csi3")) { - u8 bpp = csid_get_fmt_entry( - csid->fmt[MSM_CSIPHY_PAD_SINK].code)->bpp; + const struct csid_format *f = csid_get_fmt_entry( + csid->formats, + csid->nformats, + csid->fmt[MSM_CSIPHY_PAD_SINK].code); u8 num_lanes = csid->phy.lane_cnt; - u64 min_rate = pixel_clock * bpp / (2 * num_lanes * 4); + u64 min_rate = pixel_clock * f->bpp / + (2 * num_lanes * 4); long rate; camss_add_clock_margin(&min_rate); @@ -408,9 +529,10 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) /* Config Test Generator */ struct v4l2_mbus_framefmt *f = &csid->fmt[MSM_CSID_PAD_SRC]; - u8 bpp = csid_get_fmt_entry(f->code)->bpp; - u8 spp = csid_get_fmt_entry(f->code)->spp; - u32 num_bytes_per_line = f->width * bpp * spp / 8; + const struct csid_format *format = csid_get_fmt_entry( + csid->formats, csid->nformats, f->code); + u32 num_bytes_per_line = + f->width * format->bpp * format->spp / 8; u32 num_lines = f->height; /* 31:24 V blank, 23:13 H blank, 3:2 num of active DT */ @@ -426,8 +548,7 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_0(ver, 0)); - dt = csid_get_fmt_entry( - csid->fmt[MSM_CSID_PAD_SRC].code)->data_type; + dt = format->data_type; /* 5:0 data type */ val = dt; @@ -439,9 +560,12 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) writel_relaxed(val, csid->base + CAMSS_CSID_TG_DT_n_CGG_2(ver, 0)); - df = csid_get_fmt_entry( - csid->fmt[MSM_CSID_PAD_SRC].code)->decode_format; + df = format->decode_format; } else { + struct v4l2_mbus_framefmt *f = + &csid->fmt[MSM_CSID_PAD_SINK]; + const struct csid_format *format = csid_get_fmt_entry( + csid->formats, csid->nformats, f->code); struct csid_phy_config *phy = &csid->phy; val = phy->lane_cnt - 1; @@ -456,10 +580,8 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) writel_relaxed(val, csid->base + CAMSS_CSID_CORE_CTRL_1); - dt = csid_get_fmt_entry( - csid->fmt[MSM_CSID_PAD_SINK].code)->data_type; - df = csid_get_fmt_entry( - csid->fmt[MSM_CSID_PAD_SINK].code)->decode_format; + dt = format->data_type; + df = format->decode_format; } /* Config LUT */ @@ -534,12 +656,12 @@ static void csid_try_format(struct csid_device *csid, case MSM_CSID_PAD_SINK: /* Set format on sink pad */ - for (i = 0; i < ARRAY_SIZE(csid_input_fmts); i++) - if (fmt->code == csid_input_fmts[i].code) + for (i = 0; i < csid->nformats; i++) + if (fmt->code == csid->formats[i].code) break; /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(csid_input_fmts)) + if (i >= csid->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -563,12 +685,12 @@ static void csid_try_format(struct csid_device *csid, /* Test generator is enabled, set format on source*/ /* pad to allow test generator usage */ - for (i = 0; i < ARRAY_SIZE(csid_input_fmts); i++) - if (csid_input_fmts[i].code == fmt->code) + for (i = 0; i < csid->nformats; i++) + if (csid->formats[i].code == fmt->code) break; /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(csid_input_fmts)) + if (i >= csid->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -597,10 +719,10 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format; if (code->pad == MSM_CSID_PAD_SINK) { - if (code->index >= ARRAY_SIZE(csid_input_fmts)) + if (code->index >= csid->nformats) return -EINVAL; - code->code = csid_input_fmts[code->index].code; + code->code = csid->formats[code->index].code; } else { if (csid->testgen_mode->cur.val == 0) { if (code->index > 0) @@ -611,10 +733,10 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, code->code = format->code; } else { - if (code->index >= ARRAY_SIZE(csid_input_fmts)) + if (code->index >= csid->nformats) return -EINVAL; - code->code = csid_input_fmts[code->index].code; + code->code = csid->formats[code->index].code; } } @@ -834,6 +956,18 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, csid->camss = camss; csid->id = id; + if (camss->version == CAMSS_8x16) { + csid->formats = csid_formats_8x16; + csid->nformats = + ARRAY_SIZE(csid_formats_8x16); + } else if (camss->version == CAMSS_8x96) { + csid->formats = csid_formats_8x96; + csid->nformats = + ARRAY_SIZE(csid_formats_8x96); + } else { + return -EINVAL; + } + /* Memory */ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res->reg[0]); diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index ed605fd..1824b37 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -58,6 +58,8 @@ struct csid_device { struct v4l2_mbus_framefmt fmt[MSM_CSID_PADS_NUM]; struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *testgen_mode; + const struct csid_format *formats; + unsigned int nformats; }; struct resources; diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 7da7051..3cdab59 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -23,93 +23,69 @@ #define MSM_CSIPHY_NAME "msm_csiphy" -static const struct { +struct csiphy_format { u32 code; u8 bpp; -} csiphy_formats[] = { - { - MEDIA_BUS_FMT_UYVY8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_VYUY8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_YUYV8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_YVYU8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_SBGGR8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SGBRG8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SGRBG8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SRGGB8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SBGGR10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SGBRG10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SGRBG10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SRGGB10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SBGGR12_1X12, - 12, - }, - { - MEDIA_BUS_FMT_SGBRG12_1X12, - 12, - }, - { - MEDIA_BUS_FMT_SGRBG12_1X12, - 12, - }, - { - MEDIA_BUS_FMT_SRGGB12_1X12, - 12, - } +}; + +static const struct csiphy_format csiphy_formats_8x16[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, + { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, + { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, + { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, +}; + +static const struct csiphy_format csiphy_formats_8x96[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, + { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, + { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, + { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, }; /* * csiphy_get_bpp - map media bus format to bits per pixel + * @formats: supported media bus formats array + * @nformats: size of @formats array * @code: media bus format code * * Return number of bits per pixel */ -static u8 csiphy_get_bpp(u32 code) +static u8 csiphy_get_bpp(const struct csiphy_format *formats, + unsigned int nformats, u32 code) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(csiphy_formats); i++) - if (code == csiphy_formats[i].code) - return csiphy_formats[i].bpp; + for (i = 0; i < nformats; i++) + if (code == formats[i].code) + return formats[i].bpp; WARN(1, "Unknown format\n"); - return csiphy_formats[0].bpp; + return formats[0].bpp; } /* @@ -133,7 +109,8 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) if (!strcmp(clock->name, "csiphy0_timer") || !strcmp(clock->name, "csiphy1_timer") || !strcmp(clock->name, "csiphy2_timer")) { - u8 bpp = csiphy_get_bpp( + u8 bpp = csiphy_get_bpp(csiphy->formats, + csiphy->nformats, csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data; u64 min_rate = pixel_clock * bpp / (2 * num_lanes * 4); @@ -256,7 +233,8 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) struct csiphy_config *cfg = &csiphy->cfg; u32 pixel_clock; u8 lane_mask = csiphy_get_lane_mask(&cfg->csi2->lane_cfg); - u8 bpp = csiphy_get_bpp(csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); + u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats, + csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); u8 val; int ret; @@ -361,12 +339,12 @@ static void csiphy_try_format(struct csiphy_device *csiphy, case MSM_CSIPHY_PAD_SINK: /* Set format on sink pad */ - for (i = 0; i < ARRAY_SIZE(csiphy_formats); i++) - if (fmt->code == csiphy_formats[i].code) + for (i = 0; i < csiphy->nformats; i++) + if (fmt->code == csiphy->formats[i].code) break; /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(csiphy_formats)) + if (i >= csiphy->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -402,10 +380,10 @@ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format; if (code->pad == MSM_CSIPHY_PAD_SINK) { - if (code->index >= ARRAY_SIZE(csiphy_formats)) + if (code->index >= csiphy->nformats) return -EINVAL; - code->code = csiphy_formats[code->index].code; + code->code = csiphy->formats[code->index].code; } else { if (code->index > 0) return -EINVAL; @@ -563,12 +541,17 @@ int msm_csiphy_subdev_init(struct camss *camss, csiphy->id = id; csiphy->cfg.combo_mode = 0; - if (camss->version == CAMSS_8x16) + if (camss->version == CAMSS_8x16) { csiphy->ops = &csiphy_ops_2ph_1_0; - else if (camss->version == CAMSS_8x96) + csiphy->formats = csiphy_formats_8x16; + csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x16); + } else if (camss->version == CAMSS_8x96) { csiphy->ops = &csiphy_ops_3ph_1_0; - else + csiphy->formats = csiphy_formats_8x96; + csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x96); + } else { return -EINVAL; + } /* Memory */ diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 5debe46..376f865a 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -71,6 +71,8 @@ struct csiphy_device { struct csiphy_config cfg; struct v4l2_mbus_framefmt fmt[MSM_CSIPHY_PADS_NUM]; const struct csiphy_hw_ops *ops; + const struct csiphy_format *formats; + unsigned int nformats; }; struct resources; diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c index ae80732..146d5d2 100644 --- a/drivers/media/platform/qcom/camss/camss-ispif.c +++ b/drivers/media/platform/qcom/camss/camss-ispif.c @@ -96,7 +96,26 @@ enum ispif_intf_cmd { CMD_ALL_NO_CHANGE = 0xffffffff, }; -static const u32 ispif_formats[] = { +static const u32 ispif_formats_8x16[] = { + MEDIA_BUS_FMT_UYVY8_2X8, + MEDIA_BUS_FMT_VYUY8_2X8, + MEDIA_BUS_FMT_YUYV8_2X8, + MEDIA_BUS_FMT_YVYU8_2X8, + MEDIA_BUS_FMT_SBGGR8_1X8, + MEDIA_BUS_FMT_SGBRG8_1X8, + MEDIA_BUS_FMT_SGRBG8_1X8, + MEDIA_BUS_FMT_SRGGB8_1X8, + MEDIA_BUS_FMT_SBGGR10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, + MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_SBGGR12_1X12, + MEDIA_BUS_FMT_SGBRG12_1X12, + MEDIA_BUS_FMT_SGRBG12_1X12, + MEDIA_BUS_FMT_SRGGB12_1X12, +}; + +static const u32 ispif_formats_8x96[] = { MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_VYUY8_2X8, MEDIA_BUS_FMT_YUYV8_2X8, @@ -780,12 +799,12 @@ static void ispif_try_format(struct ispif_line *line, case MSM_ISPIF_PAD_SINK: /* Set format on sink pad */ - for (i = 0; i < ARRAY_SIZE(ispif_formats); i++) - if (fmt->code == ispif_formats[i]) + for (i = 0; i < line->nformats; i++) + if (fmt->code == line->formats[i]) break; /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(ispif_formats)) + if (i >= line->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -823,10 +842,10 @@ static int ispif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format; if (code->pad == MSM_ISPIF_PAD_SINK) { - if (code->index >= ARRAY_SIZE(ispif_formats)) + if (code->index >= line->nformats) return -EINVAL; - code->code = ispif_formats[code->index]; + code->code = line->formats[code->index]; } else { if (code->index > 0) return -EINVAL; @@ -993,6 +1012,18 @@ int msm_ispif_subdev_init(struct ispif_device *ispif, for (i = 0; i < ispif->line_num; i++) { ispif->line[i].ispif = ispif; ispif->line[i].id = i; + + if (to_camss(ispif)->version == CAMSS_8x16) { + ispif->line[i].formats = ispif_formats_8x16; + ispif->line[i].nformats = + ARRAY_SIZE(ispif_formats_8x16); + } else if (to_camss(ispif)->version == CAMSS_8x96) { + ispif->line[i].formats = ispif_formats_8x96; + ispif->line[i].nformats = + ARRAY_SIZE(ispif_formats_8x96); + } else { + return -EINVAL; + } } /* Memory */ diff --git a/drivers/media/platform/qcom/camss/camss-ispif.h b/drivers/media/platform/qcom/camss/camss-ispif.h index 9cd51dc..1a5ba24 100644 --- a/drivers/media/platform/qcom/camss/camss-ispif.h +++ b/drivers/media/platform/qcom/camss/camss-ispif.h @@ -43,6 +43,8 @@ struct ispif_line { struct v4l2_subdev subdev; struct media_pad pads[MSM_ISPIF_PADS_NUM]; struct v4l2_mbus_framefmt fmt[MSM_ISPIF_PADS_NUM]; + const u32 *formats; + unsigned int nformats; }; struct ispif_device { diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index e6f66cf..c27097c 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -45,93 +45,83 @@ #define SCALER_RATIO_MAX 16 -static const struct { +struct vfe_format { u32 code; u8 bpp; -} vfe_formats[] = { - { - MEDIA_BUS_FMT_UYVY8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_VYUY8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_YUYV8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_YVYU8_2X8, - 8, - }, - { - MEDIA_BUS_FMT_SBGGR8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SGBRG8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SGRBG8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SRGGB8_1X8, - 8, - }, - { - MEDIA_BUS_FMT_SBGGR10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SGBRG10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SGRBG10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SRGGB10_1X10, - 10, - }, - { - MEDIA_BUS_FMT_SBGGR12_1X12, - 12, - }, - { - MEDIA_BUS_FMT_SGBRG12_1X12, - 12, - }, - { - MEDIA_BUS_FMT_SGRBG12_1X12, - 12, - }, - { - MEDIA_BUS_FMT_SRGGB12_1X12, - 12, - } +}; + +static const struct vfe_format formats_rdi_8x16[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, + { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, + { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, + { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, +}; + +static const struct vfe_format formats_pix_8x16[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, + { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, + { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, + { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, +}; + +static const struct vfe_format formats_rdi_8x96[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, + { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, + { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, + { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, +}; + +static const struct vfe_format formats_pix_8x96[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, 8 }, + { MEDIA_BUS_FMT_VYUY8_2X8, 8 }, + { MEDIA_BUS_FMT_YUYV8_2X8, 8 }, + { MEDIA_BUS_FMT_YVYU8_2X8, 8 }, }; /* * vfe_get_bpp - map media bus format to bits per pixel + * @formats: supported media bus formats array + * @nformats: size of @formats array * @code: media bus format code * * Return number of bits per pixel */ -static u8 vfe_get_bpp(u32 code) +static u8 vfe_get_bpp(const struct vfe_format *formats, + unsigned int nformats, u32 code) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(vfe_formats); i++) - if (code == vfe_formats[i].code) - return vfe_formats[i].bpp; + for (i = 0; i < nformats; i++) + if (code == formats[i].code) + return formats[i].bpp; WARN(1, "Unknown format\n"); - return vfe_formats[0].bpp; + return formats[0].bpp; } /* @@ -978,8 +968,11 @@ static int vfe_set_clock_rates(struct vfe_device *vfe) if (j == VFE_LINE_PIX) { tmp = pixel_clock[j]; } else { - bpp = vfe_get_bpp(vfe->line[j]. - fmt[MSM_VFE_PAD_SINK].code); + struct vfe_line *l = &vfe->line[j]; + + bpp = vfe_get_bpp(l->formats, + l->nformats, + l->fmt[MSM_VFE_PAD_SINK].code); tmp = pixel_clock[j] * bpp / 64; } @@ -1057,8 +1050,11 @@ static int vfe_check_clock_rates(struct vfe_device *vfe) if (j == VFE_LINE_PIX) { tmp = pixel_clock[j]; } else { - bpp = vfe_get_bpp(vfe->line[j]. - fmt[MSM_VFE_PAD_SINK].code); + struct vfe_line *l = &vfe->line[j]; + + bpp = vfe_get_bpp(l->formats, + l->nformats, + l->fmt[MSM_VFE_PAD_SINK].code); tmp = pixel_clock[j] * bpp / 64; } @@ -1374,12 +1370,12 @@ static void vfe_try_format(struct vfe_line *line, case MSM_VFE_PAD_SINK: /* Set format on sink pad */ - for (i = 0; i < ARRAY_SIZE(vfe_formats); i++) - if (fmt->code == vfe_formats[i].code) + for (i = 0; i < line->nformats; i++) + if (fmt->code == line->formats[i].code) break; /* If not found, use UYVY as default */ - if (i >= ARRAY_SIZE(vfe_formats)) + if (i >= line->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -1539,10 +1535,10 @@ static int vfe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format; if (code->pad == MSM_VFE_PAD_SINK) { - if (code->index >= ARRAY_SIZE(vfe_formats)) + if (code->index >= line->nformats) return -EINVAL; - code->code = vfe_formats[code->index].code; + code->code = line->formats[code->index].code; } else { if (code->index > 0) return -EINVAL; @@ -1943,12 +1939,33 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, vfe->reg_update = 0; for (i = VFE_LINE_RDI0; i <= VFE_LINE_PIX; i++) { - vfe->line[i].video_out.type = - V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - vfe->line[i].video_out.camss = camss; - vfe->line[i].id = i; - init_completion(&vfe->line[i].output.sof); - init_completion(&vfe->line[i].output.reg_update); + struct vfe_line *l = &vfe->line[i]; + + l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + l->video_out.camss = camss; + l->id = i; + init_completion(&l->output.sof); + init_completion(&l->output.reg_update); + + if (camss->version == CAMSS_8x16) { + if (i == VFE_LINE_PIX) { + l->formats = formats_pix_8x16; + l->nformats = ARRAY_SIZE(formats_pix_8x16); + } else { + l->formats = formats_rdi_8x16; + l->nformats = ARRAY_SIZE(formats_rdi_8x16); + } + } else if (camss->version == CAMSS_8x96) { + if (i == VFE_LINE_PIX) { + l->formats = formats_pix_8x96; + l->nformats = ARRAY_SIZE(formats_pix_8x96); + } else { + l->formats = formats_rdi_8x96; + l->nformats = ARRAY_SIZE(formats_rdi_8x96); + } + } else { + return -EINVAL; + } } init_completion(&vfe->reset_complete); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index eaebe83..71f6c97 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -71,6 +71,8 @@ struct vfe_line { struct v4l2_rect crop; struct camss_video video_out; struct vfe_output output; + const struct vfe_format *formats; + unsigned int nformats; }; struct vfe_device; diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 16e74b2..ba7d0c4 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -41,7 +41,7 @@ struct camss_format_info { unsigned int bpp[3]; }; -static const struct camss_format_info formats_rdi[] = { +static const struct camss_format_info formats_rdi_8x16[] = { { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1, { { 1, 1 } }, { { 1, 1 } }, { 16 } }, { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1, @@ -76,7 +76,77 @@ static const struct camss_format_info formats_rdi[] = { { { 1, 1 } }, { { 1, 1 } }, { 12 } }, }; -static const struct camss_format_info formats_pix[] = { +static const struct camss_format_info formats_rdi_8x96[] = { + { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1, + { { 1, 1 } }, { { 1, 1 } }, { 16 } }, + { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1, + { { 1, 1 } }, { { 1, 1 } }, { 16 } }, + { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1, + { { 1, 1 } }, { { 1, 1 } }, { 16 } }, + { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1, + { { 1, 1 } }, { { 1, 1 } }, { 16 } }, + { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1, + { { 1, 1 } }, { { 1, 1 } }, { 8 } }, + { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1, + { { 1, 1 } }, { { 1, 1 } }, { 8 } }, + { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1, + { { 1, 1 } }, { { 1, 1 } }, { 8 } }, + { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1, + { { 1, 1 } }, { { 1, 1 } }, { 8 } }, + { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 10 } }, + { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, + { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1, + { { 1, 1 } }, { { 1, 1 } }, { 12 } }, +}; + +static const struct camss_format_info formats_pix_8x16[] = { + { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1, + { { 1, 1 } }, { { 2, 3 } }, { 8 } }, + { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV16, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV16, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV16, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV16, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_NV61, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_NV61, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_NV61, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, + { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1, + { { 1, 1 } }, { { 1, 2 } }, { 8 } }, +}; + +static const struct camss_format_info formats_pix_8x96[] = { { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1, { { 1, 1 } }, { { 2, 3 } }, { 8 } }, { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1, @@ -790,11 +860,24 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, mutex_init(&video->lock); - video->formats = formats_rdi; - video->nformats = ARRAY_SIZE(formats_rdi); - if (is_pix) { - video->formats = formats_pix; - video->nformats = ARRAY_SIZE(formats_pix); + if (video->camss->version == CAMSS_8x16) { + if (is_pix) { + video->formats = formats_pix_8x16; + video->nformats = ARRAY_SIZE(formats_pix_8x16); + } else { + video->formats = formats_rdi_8x16; + video->nformats = ARRAY_SIZE(formats_rdi_8x16); + } + } else if (video->camss->version == CAMSS_8x96) { + if (is_pix) { + video->formats = formats_pix_8x96; + video->nformats = ARRAY_SIZE(formats_pix_8x96); + } else { + video->formats = formats_rdi_8x96; + video->nformats = ARRAY_SIZE(formats_rdi_8x96); + } + } else { + goto error_video_register; } ret = msm_video_init_format(video);