camera驱动小节一:fimc控制器


//fimc 驱动层

drivers/media/video/samsung/fimc/fimc_dev.c

static int fimc_register(void)
{
platform_driver_register(&fimc_driver);//驱动注册,fimc控制器


return 0;
}


static struct platform_driver fimc_driver = {
.probe = fimc_probe,
.remove = fimc_remove,
.suspend = fimc_suspend,
.resume = fimc_resume,
.driver = {
.name =FIMC_NAME,
.owner = THIS_MODULE, //    "s3c-fimc"
},
};



static int __devinit fimc_probe(struct platform_device *pdev)
{
struct s3c_platform_fimc *pdata;
struct fimc_control *ctrl;
struct clk *srclk;
int ret;


if (!fimc_dev) {
fimc_dev = kzalloc(sizeof(*fimc_dev), GFP_KERNEL);
if (!fimc_dev) {
dev_err(&pdev->dev, "%s: not enough memory\n",
__func__);
return -ENOMEM;
}
}

 
ctrl = fimc_register_controller(pdev);//将三个video_device操作接口fops >> ctrl->vd
if (!ctrl) {
printk(KERN_ERR "%s: cannot register fimc\n", __func__);
goto err_alloc;
}


pdata = to_fimc_plat(&pdev->dev);
if (pdata->cfg_gpio)
pdata->cfg_gpio(pdev);


/* Get fimc power domain regulator */
ctrl->regulator = regulator_get(&pdev->dev, "pd");
if (IS_ERR(ctrl->regulator)) {
fimc_err("%s: failed to get resource %s\n",
__func__, "s3c-fimc");
return PTR_ERR(ctrl->regulator);
}


/* fimc source clock */
srclk = clk_get(&pdev->dev, pdata->srclk_name);
if (IS_ERR(srclk)) {
fimc_err("%s: failed to get source clock of fimc\n",
__func__);
goto err_v4l2;
}


/* fimc clock */
ctrl->clk = clk_get(&pdev->dev, pdata->clk_name);
if (IS_ERR(ctrl->clk)) {
fimc_err("%s: failed to get fimc clock source\n",
__func__);
goto err_v4l2;
}


/* set parent for mclk */
clk_set_parent(ctrl->clk, srclk);


/* set rate for mclk */
clk_set_rate(ctrl->clk, pdata->clk_rate);


/* V4L2 device-subdev registration */
ret = v4l2_device_register(&pdev->dev, &ctrl->v4l2_dev);
if (ret) {
fimc_err("%s: v4l2 device register failed\n", __func__);
goto err_fimc;
}


/* things to initialize once */
if (!fimc_dev->initialized) {
ret = fimc_init_global(pdev);
if (ret)
goto err_v4l2;
}


/* video device register */
ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);//注册ctrl->vd  三个video_device
if (ret) {
fimc_err("%s: cannot register video driver\n", __func__);
goto err_v4l2;
}


video_set_drvdata(ctrl->vd, ctrl);


ret = device_create_file(&(pdev->dev), &dev_attr_log_level);
if (ret < 0) {
fimc_err("failed to add sysfs entries\n");
goto err_global;
}
printk(KERN_INFO "FIMC%d registered successfully\n", ctrl->id);


return 0;


err_global:
video_unregister_device(ctrl->vd);


err_v4l2:
v4l2_device_unregister(&ctrl->v4l2_dev);


err_fimc:
fimc_unregister_controller(pdev);


err_alloc:
kfree(fimc_dev);
return -EINVAL;


}


三个fimc的 video_device :


struct video_device fimc_video_device[FIMC_DEVICES] = {
[0] = {
.fops = &fimc_fops,
.ioctl_ops = &fimc_v4l2_ops,
.release = fimc_vdev_release,
},
[1] = {
.fops = &fimc_fops,
.ioctl_ops = &fimc_v4l2_ops,
.release = fimc_vdev_release,
},
[2] = {
.fops = &fimc_fops,
.ioctl_ops = &fimc_v4l2_ops,
.release = fimc_vdev_release,
},
};

////////////////////////////////////////////////////////////////////////////////////////////////////

//fimc  设备层

static struct resource s3c_fimc0_resource[] = {
[0] = {
.start = S5P_PA_FIMC0,
.end = S5P_PA_FIMC0 + S5P_SZ_FIMC0 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC0,
.end = IRQ_FIMC0,
.flags = IORESOURCE_IRQ,
},
};


struct platform_device s3c_device_fimc0 = {
.name ="s3c-fimc",//fimc  对应设备名 fimc 0 控制器
.id = 0,
.num_resources= ARRAY_SIZE(s3c_fimc0_resource),
.resource = s3c_fimc0_resource,
};


static struct s3c_platform_fimc default_fimc0_data __initdata = { //默认pdata   0
.default_cam = CAMERA_PAR_A,

.hw_ver = 0x45,
};


void __init s3c_fimc0_set_platdata(struct s3c_platform_fimc *pd)//此为 平台数据实现函数 被调用在 arch/arm/mach-s5pv210目录下Mach-cw210.c
{
struct s3c_platform_fimc *npd;


if (!pd)
pd = &default_fimc0_data;


npd = kmemdup(pd, sizeof(struct s3c_platform_fimc), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
else {
if (!npd->cfg_gpio)
npd->cfg_gpio = s3c_fimc0_cfg_gpio;


if (!npd->clk_on)
npd->clk_on = s3c_fimc_clk_on;


if (!npd->clk_off)
npd->clk_off = s3c_fimc_clk_off;


npd->hw_ver = 0x45;


/* starting physical address of memory region */
npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMC0, 1);
/* size of memory region */
npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMC0, 1);


s3c_device_fimc0.dev.platform_data = npd;
}
}


static struct resource s3c_fimc1_resource[] = {
[0] = {
.start = S5P_PA_FIMC1,
.end = S5P_PA_FIMC1 + S5P_SZ_FIMC1 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC1,
.end = IRQ_FIMC1,
.flags = IORESOURCE_IRQ,
},
};


struct platform_device s3c_device_fimc1 = {
.name = "s3c-fimc", //fimc  对应设备名fimc 1 控制器
.id = 1,
.num_resources= ARRAY_SIZE(s3c_fimc1_resource),
.resource = s3c_fimc1_resource,
};


static struct s3c_platform_fimc default_fimc1_data __initdata = {
.default_cam = CAMERA_PAR_A,
.hw_ver = 0x50,
};


void __init s3c_fimc1_set_platdata(struct s3c_platform_fimc *pd)
{
struct s3c_platform_fimc *npd;


if (!pd)
pd = &default_fimc1_data;


npd = kmemdup(pd, sizeof(struct s3c_platform_fimc), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
else {
if (!npd->cfg_gpio)
npd->cfg_gpio = s3c_fimc1_cfg_gpio;


if (!npd->clk_on)
npd->clk_on = s3c_fimc_clk_on;


if (!npd->clk_off)
npd->clk_off = s3c_fimc_clk_off;


npd->hw_ver = 0x50;


/* starting physical address of memory region */
npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMC1, 1);
/* size of memory region */
npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMC1, 1);


s3c_device_fimc1.dev.platform_data = npd;
}
}


static struct resource s3c_fimc2_resource[] = {
[0] = {
.start = S5P_PA_FIMC2,
.end = S5P_PA_FIMC2 + S5P_SZ_FIMC2 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_FIMC2,
.end = IRQ_FIMC2,
.flags = IORESOURCE_IRQ,
},
};


struct platform_device s3c_device_fimc2 = {
.name = "s3c-fimc", //fimc  对应设备名fimc 2 控制器
.id = 2,
.num_resources= ARRAY_SIZE(s3c_fimc2_resource),
.resource = s3c_fimc2_resource,
};


static struct s3c_platform_fimc default_fimc2_data __initdata = {//默认pdata
.default_cam = CAMERA_PAR_A,
.hw_ver = 0x45,
};


void __init s3c_fimc2_set_platdata(struct s3c_platform_fimc *pd)
{
struct s3c_platform_fimc *npd;


if (!pd)
pd = &default_fimc2_data;


npd = kmemdup(pd, sizeof(struct s3c_platform_fimc), GFP_KERNEL);
if (!npd)
printk(KERN_ERR "%s: no memory for platform data\n", __func__);
else {
if (!npd->cfg_gpio)
npd->cfg_gpio = s3c_fimc2_cfg_gpio;


if (!npd->clk_on)
npd->clk_on = s3c_fimc_clk_on;


if (!npd->clk_off)
npd->clk_off = s3c_fimc_clk_off;


npd->hw_ver = 0x45;


/* starting physical address of memory region */
npd->pmem_start = s5p_get_media_memory_bank(S5P_MDEV_FIMC2, 1);
/* size of memory region */
npd->pmem_size = s5p_get_media_memsize_bank(S5P_MDEV_FIMC2, 1);


s3c_device_fimc2.dev.platform_data = npd;
}
}


//实现平台数据在 smdk110_machime_init  arch/arm/mach-s5pv210/mach-cw210.c


static void __init smdkc110_machine_init(void)
{
arm_pm_restart = smdkc110_pm_restart;


s3c_usb_set_serial();
platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));//此处 fimc 设备 被注册
#ifdef CONFIG_ANDROID_PMEM
platform_device_register(&pmem_gpu1_device);
#endif
pm_power_off = smdkc110_power_off ;


#ifdef CONFIG_ANDROID_PMEM
android_pmem_set_platdata();
#endif
/* i2c */
s3c_i2c0_set_platdata(NULL);
s3c_i2c1_set_platdata(NULL);
s3c_i2c2_set_platdata(NULL);


sound_init();


i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
i2c_register_board_info(2, i2c_devs2, ARRAY_SIZE(i2c_devs2));
i2c_register_board_info(5, i2c_devs5, ARRAY_SIZE(i2c_devs5));


#ifdef CONFIG_DM9000
smdkc110_dm9000_set();
#endif


#if defined(CONFIG_FB_S3C_LTE480WV)||defined(CONFIG_FB_S3C_LCD800480)||defined(CONFIG_FB_S3C_LCD800600)||defined(CONFIG_FB_S3C_VGA1024768)||defined(CONFIG_FB_S3C_LCD640480)||defined(CONFIG_FB_S3C_LCD480272)||defined(CONFIG_FB_AT070TN92) ||defined (CONFIG_FB_S3C_VGA640480)
s3cfb_set_platdata(&lte480wv_fb_data);
#endif
#ifdef CONFIG_CW210_VGA
s3cfb_set_platdata(&vga_fb_data);
#endif


/* spi */
#ifdef CONFIG_S3C64XX_DEV_SPI
if (!gpio_request(S5PV210_GPB(1), "SPI_CS0")) {
gpio_direction_output(S5PV210_GPB(1), 1);
s3c_gpio_cfgpin(S5PV210_GPB(1), S3C_GPIO_SFN(1));
s3c_gpio_setpull(S5PV210_GPB(1), S3C_GPIO_PULL_UP);
s5pv210_spi_set_info(0, S5PV210_SPI_SRCCLK_PCLK,
ARRAY_SIZE(smdk_spi0_csi));
}
if (!gpio_request(S5PV210_GPB(5), "SPI_CS1")) {
gpio_direction_output(S5PV210_GPB(5), 1);
s3c_gpio_cfgpin(S5PV210_GPB(5), S3C_GPIO_SFN(1));
s3c_gpio_setpull(S5PV210_GPB(5), S3C_GPIO_PULL_UP);
s5pv210_spi_set_info(1, S5PV210_SPI_SRCCLK_PCLK,
ARRAY_SIZE(smdk_spi1_csi));
}
spi_register_board_info(s3c_spi_devs, ARRAY_SIZE(s3c_spi_devs));
#endif


#if defined(CONFIG_TOUCHSCREEN_S3C)
s3c_ts_set_platdata(&s3c_ts_platform);
#endif


#if defined(CONFIG_S5P_ADC)
s3c_adc_set_platdata(&s3c_adc_platform);
#endif


#if defined(CONFIG_PM)
s3c_pm_init();
#endif


#ifdef CONFIG_VIDEO_FIMC
/* fimc */
s3c_fimc0_set_platdata(&fimc_plat_lsi);
s3c_fimc1_set_platdata(&fimc_plat_lsi);
s3c_fimc2_set_platdata(&fimc_plat_lsi);

/* external camera */
/* smdkv210_cam0_power(1); */
/* smdkv210_cam1_power(1); */
#endif


#ifdef CONFIG_VIDEO_FIMC_MIPI
s3c_csis_set_platdata(NULL);
#endif


#ifdef CONFIG_VIDEO_JPEG_V2
s3c_jpeg_set_platdata(&jpeg_plat);
#endif


#ifdef CONFIG_VIDEO_MFC50
/* mfc */
s3c_mfc_set_platdata(NULL);
#endif


#ifdef CONFIG_VIDEO_TV20
s3c_set_qos();
#endif


#ifdef CONFIG_S3C_DEV_HSMMC
s5pv210_default_sdhci0();
#endif
#ifdef CONFIG_S3C_DEV_HSMMC1
s5pv210_default_sdhci1();
#endif
#ifdef CONFIG_S3C_DEV_HSMMC2
s5pv210_default_sdhci2();
#endif
#ifdef CONFIG_S3C_DEV_HSMMC3
s5pv210_default_sdhci3();
#endif
#ifdef CONFIG_S5PV210_SETUP_SDHCI
s3c_sdhci_set_platdata();
#endif


#ifdef CONFIG_BACKLIGHT_PWM
smdk_backlight_register();
#endif


regulator_has_full_constraints();


smdkc110_setup_clocks();
}

//注册的设备register  list



static struct platform_device *smdkc110_devices[] __initdata = {
#ifdef CONFIG_FIQ_DEBUGGER
&s5pv210_device_fiqdbg_uart2,
#endif
#ifdef CONFIG_MTD_ONENAND
&s5pc110_device_onenand,
#endif
#ifdef CONFIG_MTD_NAND
&s3c_device_nand,
#endif
&s5p_device_rtc,
#ifdef CONFIG_SND_S3C64XX_SOC_I2S_V4
// &s5pv210_device_iis0,
#endif
&s5pv210_device_iis0,
&s5pv210_device_iis1, //lhh add test
#ifdef CONFIG_SND_S3C_SOC_AC97
&s5pv210_device_ac97,
#endif
#ifdef CONFIG_SND_S3C_SOC_PCM
&s5pv210_device_pcm0,
#endif
#ifdef CONFIG_SND_SOC_SPDIF
&s5pv210_device_spdif,
#endif
&s3c_device_wdt,


#ifdef CONFIG_FB_S3C
&s3c_device_fb,
#endif
#ifdef CONFIG_DM9000
&s5p_device_dm9000,
#endif
 
#ifdef CONFIG_VIDEO_MFC50
&s3c_device_mfc,
#endif
#ifdef CONFIG_TOUCHSCREEN_S3C
&s3c_device_ts,
#endif
&s3c_device_keypad,
#ifdef CONFIG_S5P_ADC
&s3c_device_adc,
#endif
#ifdef CONFIG_VIDEO_FIMC
&s3c_device_fimc0,
&s3c_device_fimc1,
&s3c_device_fimc2,

#endif
#ifdef CONFIG_VIDEO_FIMC_MIPI
&s3c_device_csis,
#endif
#ifdef CONFIG_VIDEO_JPEG_V2
&s3c_device_jpeg,
#endif
#ifdef CONFIG_VIDEO_G2D
&s3c_device_g2d,
#endif
#ifdef CONFIG_VIDEO_TV20
&s5p_device_tvout,
&s5p_device_cec,
&s5p_device_hpd,
#endif


&s3c_device_g3d,
&s3c_device_lcd,


&s3c_device_i2c0,
#ifdef CONFIG_S3C_DEV_I2C1
&s3c_device_i2c1,
#endif
#ifdef CONFIG_S3C_DEV_I2C2
&s3c_device_i2c2,
#endif
&s3c_device_i2c5,
&s3c_device_i2c6,


#ifdef CONFIG_USB_EHCI_HCD
&s3c_device_usb_ehci,
#endif
#ifdef CONFIG_USB_OHCI_HCD
&s3c_device_usb_ohci,
#endif


#ifdef CONFIG_USB_GADGET
&s3c_device_usbgadget,
#endif
#ifdef CONFIG_USB_ANDROID
&s3c_device_android_usb,
#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
&s3c_device_usb_mass_storage,
#endif
#ifdef CONFIG_USB_ANDROID_RNDIS
&s3c_device_rndis,
#endif
#endif
#ifdef CONFIG_BATTERY_S3C
&sec_device_battery,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC
&s3c_device_hsmmc0,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC1
&s3c_device_hsmmc1,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC2
&s3c_device_hsmmc2,
#endif
#ifdef CONFIG_S3C_DEV_HSMMC3
&s3c_device_hsmmc3,
#endif


#ifdef CONFIG_S3C64XX_DEV_SPI
&s5pv210_device_spi0,
&s5pv210_device_spi1,
#endif
#ifdef CONFIG_S5PV210_POWER_DOMAIN
&s5pv210_pd_audio,
&s5pv210_pd_cam,
&s5pv210_pd_tv,
&s5pv210_pd_lcd,
&s5pv210_pd_g3d,
&s5pv210_pd_mfc,
#endif
#ifdef CONFIG_SND_S5P_RP
&s3c_device_rp, 
#endif
#ifdef CONFIG_HAVE_PWM
&s3c_device_timer[0],
&s3c_device_timer[1],
&s3c_device_timer[2],
&s3c_device_timer[3],
#endif
#ifdef CONFIG_KEYBOARD_S3C_GPIO
&s3c_device_gpio_button,
#endif
#ifdef CONFIG_KEYBOARD_HS0038
&cw210_hs0038_device,
#endif
};



猜你喜欢

转载自blog.csdn.net/a1028732302/article/details/43689783