I am the beginner of programmation of DM365, now I have a problem that my boss demande me to write a driver of camera MT9D131, now I can successfully register this camera and can read and write the registers in the camera. I have finish my first version of driver with only the fonction ".init .set_fmt .try_fmt .s_stream", but when I use the demo function to test the driver, the demo "encode" reply to me that "No camera was connected", I do not know what is the problem.
My question is:
1.Because I have fused the camera by myself, so I am not sure this is correct, the connection is like this:
MT9D131 DM365(interface of image)
DOUT0...3 -> DDC-DATA12...15
DOUT4...7 -> DDC-DATA0...3
I2C...DATA -> I2C...DATA
I2C...CLK -> I2C...CLK
V_Valide -> CCD-VSYNC
H_Valide -> CCD_HSYNC
RESET -> CCD_DDSRST
PCLK -> PCLK
EXTCLK -> SP14_SD1_GPIO_MD2_CONN(Clock1)
2.Have you any reference about the programmation of DM365, the code of demo is too complicated for me to understande
3. My code of certaine fonction is like this, thank you very much.
static int mt9d131_init(struct v4l2_subdev *sd, u32 val){ int ret; struct i2c_client *client = v4l2_get_subdevdata(sd); ret=pll_disable(client); if(ret<0) return -EIO; //Perform MCU reset ret=change_page(client,1); if(ret<0) return -EIO; ret=reg_write(client,MT9D131_MCU_BOOTMODE,0x0501); if(ret<0) return -EIO; //Enable Reset ret=change_page(client,1); if(ret<0) return -EIO; ret=reg_write(client,MT9D131_RESET_LOGICIEL,0x0021); if(ret<0) return -EIO; //Disable Reset,ignore the pin Standby ret=reg_write(client,MT9D131_RESET_LOGICIEL,0x00A0); if(ret<0) return -EIO; msleep(20); //Enable PLL return pll_enable(client,18,8,2)>0?0:-EIO;}static int mt9d131_s_stream(struct v4l2_subdev *sd, int enable){ struct i2c_client *client = v4l2_get_subdevdata(sd); int ret; //Change mode to capture if(change_mode(client,1)<0) return -EIO; //Enable the output if (enable) { if (driver_write(client,MT9D131_ID_SEQ,MT9D131_SEQ_CMD,2,1) < 0) return -EIO; } else { //Disable the output if (driver_write(client,MT9D131_ID_SEQ,MT9D131_SEQ_CMD,1,1) < 0) return -EIO; } return 0;}static int mt9d131_set_fmt(struct v4l2_subdev *sd,struct v4l2_format *f){ int i,ret; int flag=0; struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_pix_format *pix = &f->fmt.pix; for(i=0;i<mt9d131_num_formats;i++) { if(pix->pixelformat==mt9d131_formats[i].pixelformat) { //bypass the JPEG ret=driver_write(client,MT9D131_ID_MODE,MT9D131_MODE_CONFIG,0x30,1); switch(mt9d131_formats[i].index){ case 0://When output of the format match the YUV ret=driver_clear(client,MT9D131_ID_MODE,MT9D131_OUT_FORMATB,0x21,1); break; case 1://When output of the format match the RGB ret=driver_write(client,MT9D131_ID_MODE,MT9D131_OUT_FORMATB,0x20,1); break; case 2://When output of the format match the JPEG ret=driver_write(client,MT9D131_ID_MODE,MT9D131_MODE_CONFIG,0x10,1);//Allow the JPEG in context B ret=driver_write(client,MT9D131_ID_JPEG,MT9D131_JPEG_FORMAT,0,1); } printk("Use %s.\n",mt9d131_formats[i].description); flag=1; if(ret<0) { printk("Out put register error\n"); return ret; } break; } } if(flag==0) return -EIO; if(pix->width<=MT9D131_MAX_WIDTHB&&pix->height<=MT9D131_MAX_HEIGHTB)//Change the size of window { ret=driver_write(client,MT9D131_ID_MODE,MT9D131_OUTPUT_WIDTHB,pix->width,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_OUTPUT_HEIGHTB,pix->height,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_X0B,0,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_X1B,pix->width,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_Y0B,0,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_Y1B,pix->width,0); if(ret<0) { printk("Out put register error\n"); return ret; } } else return -EIO; ret=change_mode(client,1); ret=driver_write(client,MT9D131_ID_SEQ ,MT9D131_SEQ_CMD,5,1);//Refresh the register ret=driver_write(client,MT9D131_ID_SEQ,MT9D131_SEQ_CMD,2,1);//Begin to start capture return ret<0?ret:0;}static int mt9d131_try_fmt(struct v4l2_subdev *sd,struct v4l2_format *f){ struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_pix_format *pix = &f->fmt.pix; int ret,i; int flag=0; for(i=0;i<mt9d131_num_formats;i++) { if(pix->pixelformat==mt9d131_formats[i].pixelformat) { flag=1; break; } } if(!flag) pix->pixelformat=mt9d131_formats[0].pixelformat; if(pix->width>MT9D131_MAX_WIDTHB) pix->width=MT9D131_MAX_WIDTHB; if(pix->width>MT9D131_MAX_HEIGHTB) pix->width=MT9D131_MAX_HEIGHTB; pix->width &= ~0x01; /* has to be even */ pix->height &= ~0x01; /* has to be even */ return 0;}
One more way to approaching this problem is by checking whether application is built properly corresponding to kernel you built. [Note: Also, you can use simple capture applications to test your driver changes.]
Regards,
Nagabhushana
Does this help in finding the answer? If not, please provide more info. If it helps, please click the Verify Answer button below.
My problem now is like this, when I try to open the node /dev/video0, the system excecute the function S_format automaticlly, like that
ret=open("/dev/video0“, 0_RDWR,0);
int mt9d131.c
int mt9d131_s_fmt()
{
printk("Now set_fmt is running \n");
............
}
when I lance my programme, the result is like that
./test
Now set_fmt is running.
Can not open video0 because of fd=-1
I do not know whether there is my configuration of Kernel of linux, if anyone also has DM365_EVM, can you try to run my test programme and response to me the result, thank you very much
But when I add this command ret=ioctl(fd,VIDIOC_S_FMT,&fmt)
The function mt9d131_s_fmt() was not excecuted,ret=-1
Even if I change the sub_device to Tv7002, I can not excecute VIDIOC_S_FMT now
Mingming Chen,
When you open the device, device tries to setup sensor or decoder internally to default state. Thats why, you are seeing set format call of sensor being called. Looks like set format called in sensor sub-device driver is failing[You need to check that]. Hence opening v4l2 device is ending with failure. Once opening the device fails, any calls which use file descriptor of the device will fail.
Thank you very much for your response, but how can the v4l2 driver know the default state of my driver.
For exemple:
The fonction of my S_fmt is like this:
static int mt9d131_set_fmt(struct v4l2_subdev *sd,struct v4l2_format *f){ struct mt9d131 *mt9d11 = to_mt9d131(sd); int i,ret; int flag=0; printk("Begin to setformat mt9d131"); struct i2c_client *client = v4l2_get_subdevdata(sd); struct v4l2_pix_format *pix = &f->fmt.pix; if (f==NULL) return -EINVAL; for(i=0;i<mt9d131_num_formats;i++) { if(pix->pixelformat==mt9d131_formats[i].pixelformat) { //bypass the JPEG ret=driver_write(client,MT9D131_ID_MODE,MT9D131_MODE_CONFIG,0x30,1); switch(mt9d131_formats[i].index){ case 0://When output of the format match the YUV ret=driver_clear(client,MT9D131_ID_MODE,MT9D131_OUT_FORMATB,0x21,1); break; case 1://When output of the format match the RGB ret=driver_write(client,MT9D131_ID_MODE,MT9D131_OUT_FORMATB,0x20,1); break; case 2://When output of the format match the JPEG ret=driver_write(client,MT9D131_ID_MODE,MT9D131_MODE_CONFIG,0x10,1);//Allow the JPEG in context B ret=driver_write(client,MT9D131_ID_JPEG,MT9D131_JPEG_FORMAT,0,1); } printk("Use %s.\n",mt9d131_formats[i].description); flag=1; if(ret<0) { printk("Out put register error\n"); return -EINVAL; } break; } } if(flag==0) { printk("No format matched\n"); return 1; } if(pix->width<=MT9D131_MAX_WIDTHB&&pix->height<=MT9D131_MAX_HEIGHTB)//Change the size of window { ret=driver_write(client,MT9D131_ID_MODE,MT9D131_OUTPUT_WIDTHB,pix->width,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_OUTPUT_HEIGHTB,pix->height,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_X0B,0,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_X1B,pix->width,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_Y0B,0,0); ret=driver_write(client,MT9D131_ID_MODE,MT9D131_CROP_Y1B,pix->width,0); if(ret<0) { printk("Out put register error\n"); return ret; } } else return -EIO; ret=change_mode(client,1); ret=driver_write(client,MT9D131_ID_SEQ ,MT9D131_SEQ_CMD,5,1);//Refresh the register ret=driver_write(client,MT9D131_ID_SEQ,MT9D131_SEQ_CMD,2,1);//Begin to start capture return ret<0?ret:0;}
My problem is :1 where the parametre struct v4l2_format *f come from by open("/dev/video,mode,0)?
2 when I do nothing in the function S_FMT like that
static int mt9d131_set_fmt(struct v4l2_subdev *sd,struct v4l2_format *f)
printk("Begin to setformat mt9d131");
return 0;
Now the set_format is executed without any problem, after the v4l2 executed the TRY_FORMAT without any problem. Now the fonction open is executed well and return the value fd=3.
But when I try to execute the S_FMT with ret=itocl(fd,VIDIOC_S_FMT,&fmt), I think the S_FMT is not executed because I do not view the phrase "Begin to setformat mt9d131" with ret=-1
Now even I use the decoder TVP7002, I can open the video0 with no problem but I can not execute S_FMT of this camera, I do not know why.
The design of VPFE capture driver takes into consideration design of sensor driver also. Since you added new sensor driver, you need to change VPFE capture driver also appropriately.
How can I change the VPFE capture driver, where can I find the fichier.c? Or is there any reference of the how to modify the driver, thank you very much.
Hi! Mingming,
How did you solve this problem? I just meet the same problem!