/*
 * Decide whether desired output pixel code can be obtained with
 * the lane shifter by shifting the input pixel code.
 * @in: input pixelcode to shifter
 * @out: output pixelcode from shifter
 * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
 *
 * return true if the combination is possible
 * return false otherwise
 */
static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
                                   enum v4l2_mbus_pixelcode out,
                                   unsigned int additional_shift)
{
    const struct isp_format_info *in_info, *out_info;

    if (in == out)
        return true;

    in_info = omap3isp_video_format_info(in);
    out_info = omap3isp_video_format_info(out);

    if ((in_info->flavor == 0) || (out_info->flavor == 0))
        return false;

    if (in_info->flavor != out_info->flavor)
        return false;

    return in_info->bpp - out_info->bpp + additional_shift <= 6;
}
Exemple #2
0
static void
csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_pad_config *cfg,
                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                enum v4l2_subdev_format_whence which)
{
    u32 pixelcode;
    struct v4l2_mbus_framefmt *format;
    const struct isp_format_info *info;
    unsigned int i;

    switch (pad) {
    case CSI2_PAD_SINK:
        /* Clamp the width and height to valid range (1-8191). */
        for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
            if (fmt->code == csi2_input_fmts[i])
                break;
        }

        /* If not found, use SGRBG10 as default */
        if (i >= ARRAY_SIZE(csi2_input_fmts))
            fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;

        fmt->width = clamp_t(u32, fmt->width, 1, 8191);
        fmt->height = clamp_t(u32, fmt->height, 1, 8191);
        break;

    case CSI2_PAD_SOURCE:
        /* Source format same as sink format, except for DPCM
         * compression.
         */
        pixelcode = fmt->code;
        format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK, which);
        memcpy(fmt, format, sizeof(*fmt));

        /*
         * Only Allow DPCM decompression, and check that the
         * pattern is preserved
         */
        info = omap3isp_video_format_info(fmt->code);
        if (info->uncompressed == pixelcode)
            fmt->code = pixelcode;
        break;
    }

    /* RGB, non-interlaced */
    fmt->colorspace = V4L2_COLORSPACE_SRGB;
    fmt->field = V4L2_FIELD_NONE;
}
Exemple #3
0
/*
 * csi2_enum_mbus_code - Handle pixel format enumeration
 * @sd     : pointer to v4l2 subdev structure
 * @cfg: V4L2 subdev pad configuration
 * @code   : pointer to v4l2_subdev_mbus_code_enum structure
 * return -EINVAL or zero on success
 */
static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
                               struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
{
    struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
    struct v4l2_mbus_framefmt *format;
    const struct isp_format_info *info;

    if (code->pad == CSI2_PAD_SINK) {
        if (code->index >= ARRAY_SIZE(csi2_input_fmts))
            return -EINVAL;

        code->code = csi2_input_fmts[code->index];
    } else {
        format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK,
                                   V4L2_SUBDEV_FORMAT_TRY);
        switch (code->index) {
        case 0:
            /* Passthrough sink pad code */
            code->code = format->code;
            break;
        case 1:
            /* Uncompressed code */
            info = omap3isp_video_format_info(format->code);
            if (info->uncompressed == format->code)
                return -EINVAL;

            code->code = info->uncompressed;
            break;
        default:
            return -EINVAL;
        }
    }

    return 0;
}