media: camss: Format configuration per hardware version
authorTodor Tomov <todor.tomov@linaro.org>
Wed, 25 Jul 2018 16:38:35 +0000 (12:38 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Thu, 2 Aug 2018 10:35:09 +0000 (06:35 -0400)
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 <todor.tomov@linaro.org>
Signed-off-by: Hans Verkuil <hansverk@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/qcom/camss/camss-csid.c
drivers/media/platform/qcom/camss/camss-csid.h
drivers/media/platform/qcom/camss/camss-csiphy.c
drivers/media/platform/qcom/camss/camss-csiphy.h
drivers/media/platform/qcom/camss/camss-ispif.c
drivers/media/platform/qcom/camss/camss-ispif.h
drivers/media/platform/qcom/camss/camss-vfe.c
drivers/media/platform/qcom/camss/camss-vfe.h
drivers/media/platform/qcom/camss/camss-video.c

index 915835ee32719fe935385d3066f1cafe5317a94f..db960da560c999a9a46bc69a4d29f79686ab4104 100644 (file)
@@ -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]);
index ed605fd3bb8759f82ee55c4e70427258644d7f29..1824b3745e1079d2ad346612ea7cff7033c33422 100644 (file)
@@ -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;
index 7da705147966097048ebc448e1e0ebf25347854a..3cdab59d24f9abf90787247c93edf4f125a993cb 100644 (file)
 
 #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 */
 
index 5debe46b6cf1a6edb09e1a6e3b2ccfd9c5579d20..376f865ad383b2ff3befafc77389d317b291c779 100644 (file)
@@ -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;
index ae80732746241fbe829c16ecd990b8557a09a96d..146d5d26b3c193843e447918537d1498d83abbc9 100644 (file)
@@ -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 */
index 9cd51dcb3ede393c0f7351a077d0984e72bd1418..1a5ba2425a429f01c5709f2baec8d87bd5a3c712 100644 (file)
@@ -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 {
index e6f66cfad86d43708719228401678359e281a6a9..c27097c440f2323ea692f21a44de5931e85dccd8 100644 (file)
 
 #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);
index eaebe833c143379de2f74bc9f23ca3cacf65a88e..71f6c97b266e9e0d508be2f1834a8be6fb096247 100644 (file)
@@ -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;
index 16e74b2448fe8e19e595ed0d7e3c58cd218569a9..ba7d0c45a8d9d178a96d0f0371b7ab49174569b8 100644 (file)
@@ -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);