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;
}