MIPI CSI2 ioctl_g_ifparm ?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MIPI CSI2 ioctl_g_ifparm ?

1,438 Views
mustafabakircio
Contributor IV

Hello ;

I am writing imx290 mipi csi2 driver on imx6q (wandboard). I am facing with the mipi csi2 can not receive sensor clk " error. I modified the ov5640_mipi.c file according to the camera registers and settings. But I am only using mipi csi-2 interface with i2c (4 mipi data lanes , 1 mipi clock lane and i2c communication). According to the code something is look like wrong to me.

static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
{
    if (s == NULL) {
        pr_err("   ERROR!! no slave device set!\n");
        return -1;
    }

    memset(p, 0, sizeof(*p));
    p->u.bt656.clock_curr = imx290_data.mclk;
    pr_debug("   clock_curr=mclk=%d\n", imx290_data.mclk);
    pr_info("   clock_curr=mclk=%d\n", imx290_data.mclk);
    p->if_type = V4L2_IF_TYPE_BT656;
    p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
    p->u.bt656.clock_min = IMX290_XCLK_MIN;
    p->u.bt656.clock_max = IMX290_XCLK_MAX;
    p->u.bt656.bt_sync_correct = 1;  /* Indicate external vsync */

    return 0;
}

   Screenshot from 2017-10-12 01-12-34.png

This settings are done according to the parallel camera settings . Is there any setting modes according to the mipi csi2 interface codes or macros.

Thanks.

Best Regards

0 Kudos
4 Replies

834 Views
mustafabakircio
Contributor IV

Guys I could not find any solution untill now, do you have any idea about this issue?

Also without mxc_v4l2_capture.h and v4l2_int_device.h libraries can I access the video streaming from gstreamer?

0 Kudos

834 Views
mustafabakircio
Contributor IV

Hello guys; I am confused about changing all the structer because I2C communication is OK and Other structers is fine. I need to change initiliazation stucters only ,actually  ioctl_g_ifparm structer but when I look at the MIPI CSI2 format , all the driver should be changed and written from beggining. Is there any way to change the  ioctl_g_ifparm(); struct by not corrupting other initialization structers or all shape of the code.

This is the initialization structers which I referred from ov5640_mipi.c file;

/****** Could be changed to the MIPI CSI2 Format ******/

static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
{
    if (s == NULL) {
        pr_err("   ERROR!! no slave device set!\n");
        return -1;
    }

    memset(p, 0, sizeof(*p));
    p->u.bt656.clock_curr = imx290_data.mclk;
    pr_debug("   clock_curr=mclk=%d\n", imx290_data.mclk);
    pr_info("   clock_curr=mclk=%d\n", imx290_data.mclk);
    p->if_type = V4L2_IF_TYPE_BT656;
    p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
    p->u.bt656.clock_min = IMX290_XCLK_MIN;
    p->u.bt656.clock_max = IMX290_XCLK_MAX;
    p->u.bt656.bt_sync_correct = 1;  /* Indicate external vsync */

    return 0;
}


static int ioctl_s_power(struct v4l2_int_device *s, int on)
{
    struct sensor_data *sensor = s->priv;

    if (on && !sensor->on) {
        if (io_regulator)
            if (regulator_enable(io_regulator) != 0)
                return -EIO;
        if (core_regulator)
            if (regulator_enable(core_regulator) != 0)
                return -EIO;
        if (gpo_regulator)
            if (regulator_enable(gpo_regulator) != 0)
                return -EIO;
        if (analog_regulator)
            if (regulator_enable(analog_regulator) != 0)
                return -EIO;
    } else if (!on && sensor->on) {
        if (analog_regulator)
            regulator_disable(analog_regulator);
        if (core_regulator)
            regulator_disable(core_regulator);
        if (io_regulator)
            regulator_disable(io_regulator);
        if (gpo_regulator)
            regulator_disable(gpo_regulator);

      
    }

    sensor->on = on;

    return 0;
}

static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) // get parameters
{
    struct sensor_data *sensor = s->priv;   
    struct v4l2_captureparm *cparm = &a->parm.capture;
    int ret = 0;

    switch (a->type) {
    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        memset(a, 0, sizeof(*a));
        a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        cparm->capability = sensor->streamcap.capability;
        cparm->timeperframe = sensor->streamcap.timeperframe;
        cparm->capturemode = sensor->streamcap.capturemode;
        ret = 0;
        break;

    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    case V4L2_BUF_TYPE_VIDEO_OVERLAY:
    case V4L2_BUF_TYPE_VBI_CAPTURE:
    case V4L2_BUF_TYPE_VBI_OUTPUT:
    case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
    case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
        ret = -EINVAL;
        break;

    default:
        pr_debug("   type is unknown - %d\n", a->type);
        ret = -EINVAL;
        break;
    }
    return ret;
}

static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
{
    struct sensor_data *sensor = s->priv;
    struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
    u32 tgt_fps;    /* target frames per secound */
    enum imx290_frame_rate frame_rate; // frame değerleri için
    enum imx290_mode orig_mode;
    int ret = 0;
 
    switch (a->type) {
    /* This is the only case currently handled. */
    case V4L2_BUF_TYPE_VIDEO_CAPTURE:     
        /* Check that the new frame rate is allowed. */
        if ((timeperframe->numerator == 0) ||
            (timeperframe->denominator == 0)) {
            timeperframe->denominator = DEFAULT_FPS;
            timeperframe->numerator = 1;
        }

        tgt_fps = timeperframe->denominator /
              timeperframe->numerator;

        if (tgt_fps > MAX_FPS) {
            timeperframe->denominator = MAX_FPS;
            timeperframe->numerator = 1;
        }

        /* Actual frame rate we use */
        tgt_fps = timeperframe->denominator /
              timeperframe->numerator;

        if (tgt_fps == 25) //full hd1080p 25 fps
            frame_rate = imx290_250_fps;
        else if (tgt_fps == 30)    //720phd 30 fps
            frame_rate = imx290_30_fps;
        else {
            pr_err(" The camera frame rate is not supported!\n");
            return -EINVAL;
        }

        orig_mode = sensor->streamcap.capturemode;
        ret = imx290_init_mode(frame_rate,
                (u32)a->parm.capture.capturemode, orig_mode);        /// camera initialization
        if (ret < 0)
            return ret;

        sensor->streamcap.timeperframe = *timeperframe;
        sensor->streamcap.capturemode =
                (u32)a->parm.capture.capturemode;

        break;

    /* These are all the possible cases. */
    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    case V4L2_BUF_TYPE_VIDEO_OVERLAY:
    case V4L2_BUF_TYPE_VBI_CAPTURE:
    case V4L2_BUF_TYPE_VBI_OUTPUT:
    case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
    case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
        pr_debug("   type is not " \
            "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
            a->type);
        ret = -EINVAL;
        break;

    default:
        pr_debug("   type is unknown - %d\n", a->type);
        ret = -EINVAL;
        break;
    }

    return ret;
}

static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)///get capture format   
{
    struct sensor_data *sensor = s->priv;

    f->fmt.pix = sensor->pix;

    return 0;
}

static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
    int ret = 0;

    switch (vc->id) {
    case V4L2_CID_BRIGHTNESS:
        vc->value = imx290_data.brightness;
        break;
    case V4L2_CID_HUE:
        vc->value = imx290_data.hue;
        break;
    case V4L2_CID_CONTRAST:
        vc->value = imx290_data.contrast;
        break;
    case V4L2_CID_SATURATION:
        vc->value = imx290_data.saturation;
        break;
    case V4L2_CID_RED_BALANCE:
        vc->value = imx290_data.red;
        break;
    case V4L2_CID_BLUE_BALANCE:
        vc->value = imx290_data.blue;
        break;
    case V4L2_CID_EXPOSURE:      
        vc->value = imx290_data.ae_mode;
        break;
    default:
        ret = -EINVAL;
    }

    return ret;
}

static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)  
{
    int retval = 0;

    pr_debug("In imx290:ioctl_s_ctrl %d\n",vc->id);
    switch (vc->id) {
    case V4L2_CID_BRIGHTNESS:
        break;
    case V4L2_CID_CONTRAST:
        break;
    case V4L2_CID_SATURATION:
        break;
    case V4L2_CID_HUE:
        break;
    case V4L2_CID_AUTO_WHITE_BALANCE:
        break;
    case V4L2_CID_DO_WHITE_BALANCE:
        break;
    case V4L2_CID_RED_BALANCE:
        break;
    case V4L2_CID_BLUE_BALANCE:
        break;
    case V4L2_CID_GAMMA:
        break;
    case V4L2_CID_EXPOSURE:
        break;
    case V4L2_CID_AUTOGAIN:
        break;
    case V4L2_CID_GAIN:
        break;
    case V4L2_CID_HFLIP:
        break;
    case V4L2_CID_VFLIP:
        break;
    default:
        retval = -EPERM;
        break;
    }
    return retval;
}

static int ioctl_enum_framesizes(struct v4l2_int_device *s, struct v4l2_frmsizeenum *fsize)   
{
    if (fsize->index > imx290_mode_MAX)
        return -EINVAL;

    fsize->pixel_format = imx290_data.pix.pixelformat;
    fsize->discrete.width =
            max(imx290_mode_info_data[0][fsize->index].width,
                imx290_mode_info_data[1][fsize->index].width);  
    fsize->discrete.height =
            max(imx290_mode_info_data[0][fsize->index].height,
                imx290_mode_info_data[1][fsize->index].height);
    return 0;
}

static int ioctl_enum_frameintervals(struct v4l2_int_device *s,struct v4l2_frmivalenum *fival)
{
    int i, j, count = 0;

    fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
    fival->discrete.numerator = 1;

    for (i = 0; i < ARRAY_SIZE(imx290_mode_info_data); i++)
        for (j = 0; j < (imx290_mode_MAX + 1); j++)
            if (fival->pixel_format == imx290_data.pix.pixelformat
             && fival->width == imx290_mode_info_data[i][j].width
             && fival->height == imx290_mode_info_data[i][j].height
             && imx290_mode_info_data[i][j].init_data_ptr != NULL
             && fival->index == count++) {              
                fival->discrete.denominator =
                        imx290_framerates[i];      
                return 0;
            }

    return -EINVAL;
}

static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)   
{
    ((struct v4l2_dbg_chip_ident *)id)->match.type =V4L2_CHIP_MATCH_I2C_DRIVER;  
    strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name,"imx290_mipi_camera");   
    return 0;
}

static int ioctl_init(struct v4l2_int_device *s)  
{
    return 0;
}

static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, struct v4l2_fmtdesc *fmt)       
{
    if (fmt->index > imx290_mode_MAX)    //fmt->index = Number of the format in the enumeration
        return -EINVAL;

    fmt->pixelformat = imx290_data.pix.pixelformat;    //pixelformat = The image format identifier

    return 0;
}

static int ioctl_dev_init(struct v4l2_int_device *s)    //device initialization
{
    struct sensor_data *sensor = s->priv;
    u32 tgt_xclk;    /* target xclk */
    u32 tgt_fps;    /* target frames per secound */
    int ret;
    enum imx290_frame_rate frame_rate;
    void *mipi_csi2_info;

    imx290_data.on = true;

    /* mclk */
    tgt_xclk = imx290_data.mclk;
    imx290_data.mclk = tgt_xclk;
    pr_debug("   Setting mclk to %d MHz\n", tgt_xclk / 1000000);
    /* Default camera frame rate is set in probe */
    tgt_fps = sensor->streamcap.timeperframe.denominator /
          sensor->streamcap.timeperframe.numerator;

    if (tgt_fps == 25) //full hd
        frame_rate = imx290_25_fps;
    else if (tgt_fps == 30)  // 720HD
        frame_rate = imx290_30_fps;
    else
        return -EINVAL;

    mipi_csi2_info = mipi_csi2_get_info();

    /* enable mipi csi2 */
    if (mipi_csi2_info)
        mipi_csi2_enable(mipi_csi2_info);
    else {
        printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n",
               __func__, __FILE__);
        return -EPERM;
    }

    ret = imx290_init_mode(frame_rate, imx290_mode_INIT, imx290_mode_INIT);

    return ret;
}

static int ioctl_dev_exit(struct v4l2_int_device *s)
{
    void *mipi_csi2_info;

    mipi_csi2_info = mipi_csi2_get_info();

    /* disable mipi csi2 */
    if (mipi_csi2_info)
        if (mipi_csi2_get_status(mipi_csi2_info))
            mipi_csi2_disable(mipi_csi2_info);

    return 0;
}

static struct v4l2_int_ioctl_desc imx290_ioctl_desc[] = {
    {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *) ioctl_dev_init},
    {vidioc_int_dev_exit_num, ioctl_dev_exit},
    {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power},
    {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm},
    {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init},
    {vidioc_int_enum_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap},
    {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
    {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
    {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
    {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl},
    {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
    {vidioc_int_enum_framesizes_num,  (v4l2_int_ioctl_func *) ioctl_enum_framesizes},      
    {vidioc_int_enum_frameintervals_num,(v4l2_int_ioctl_func *) ioctl_enum_frameintervals}, 
    {vidioc_int_g_chip_ident_num, (v4l2_int_ioctl_func *) ioctl_g_chip_ident},    
};

0 Kudos

834 Views
igorpadykov
NXP Employee
NXP Employee

Hi Mustafa

bt656 is not supported by CSI2IPU gasket and seems these codes are from ov5640.c

(parallel camera driver), for supported formats one can look at sect.4.1. Color formats and clock

AN5305 IPI-CSI2 Peripheral on i.MX6 MPUs

https://www.nxp.com/docs/en/application-note/AN5305.pdf 

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

834 Views
mustafabakircio
Contributor IV

Thank youigorpadykov

I think I need the change structer of the static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) ; I guess, I need to change every settings adjustment according to the 13. MIPI CSI-2 — The Linux Kernel documentation this and this 1.19. V4L2 Media Bus functions and data structures — Linux Media Subsystem Documentation documentati...  documentations. Actually I am not master at writing device driver. Would it be possible to show me the steps, referance codes or documents according to the how mipi csi2 camera device driver settings should be ,except Debug steps for customer MIPI sensor.docx and https://www.nxp.com/docs/en/application-note/AN5305.pdf these documents, and also which structers do I need  ?

Thanks.

Best Regards

0 Kudos