天嵌 ARM开发社区

 找回密码
 注册
查看: 3409|回复: 2

v4l2 adv7180视频解码驱动求助

[复制链接]
jeff_arm 发表于 2013-12-8 23:49:29 | 显示全部楼层 |阅读模式
求助大家,adv7180视频解码驱动问题,
[root@jeff/]#insmod adv7180.ko
adv7180 0-0040: chip found @ 0x80 (s3c2410-i2c)
adv7180: Failed to probe: -6
  1. /*
  2. * adv7180.c Analog Devices ADV7180 video decoder driver
  3. * Copyright (c) 2009 Intel Corporation
  4. */
  5. #include <linux/module.h>
  6. #include <linux/init.h>
  7. #include <linux/errno.h>
  8. #include <linux/kernel.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/i2c.h>
  11. #include <linux/slab.h>
  12. #include <media/v4l2-ioctl.h>
  13. #include <linux/videodev2.h>
  14. #include <media/v4l2-device.h>
  15. #include <media/v4l2-chip-ident.h>
  16. #include <linux/mutex.h>

  17. #define DRIVER_NAME "adv7180"

  18. struct adv7180_state {
  19.         struct v4l2_subdev        sd;
  20.         struct work_struct        work;
  21.         struct mutex                mutex; /* mutual excl. when accessing chip */
  22.         int                        irq;
  23.         v4l2_std_id                curr_norm;
  24.         bool                        autodetect;
  25. };

  26. static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
  27. {
  28.         switch (status1 & ADV7180_STATUS1_AUTOD_MASK) {
  29.         case ADV7180_STATUS1_AUTOD_NTSM_M_J:
  30.                 return V4L2_STD_NTSC;
  31.         case ADV7180_STATUS1_AUTOD_NTSC_4_43:
  32.                 return V4L2_STD_NTSC_443;
  33.         case ADV7180_STATUS1_AUTOD_PAL_M:
  34.                 return V4L2_STD_PAL_M;
  35.         case ADV7180_STATUS1_AUTOD_PAL_60:
  36.                 return V4L2_STD_PAL_60;
  37.         case ADV7180_STATUS1_AUTOD_PAL_B_G:
  38.                 return V4L2_STD_PAL;
  39.         case ADV7180_STATUS1_AUTOD_SECAM:
  40.                 return V4L2_STD_SECAM;
  41.         case ADV7180_STATUS1_AUTOD_PAL_COMB:
  42.                 return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
  43.         case ADV7180_STATUS1_AUTOD_SECAM_525:
  44.                 return V4L2_STD_SECAM;
  45.         default:
  46.                 return V4L2_STD_UNKNOWN;
  47.         }
  48. }

  49. static int v4l2_std_to_adv7180(v4l2_std_id std)
  50. {
  51.         if (std == V4L2_STD_PAL_60)
  52.                 return ADV7180_INPUT_CONTROL_PAL60;
  53.         if (std == V4L2_STD_NTSC_443)
  54.                 return ADV7180_INPUT_CONTROL_NTSC_443;
  55.         if (std == V4L2_STD_PAL_N)
  56.                 return ADV7180_INPUT_CONTROL_PAL_N;
  57.         if (std == V4L2_STD_PAL_M)
  58.                 return ADV7180_INPUT_CONTROL_PAL_M;
  59.         if (std == V4L2_STD_PAL_Nc)
  60.                 return ADV7180_INPUT_CONTROL_PAL_COMB_N;

  61.         if (std & V4L2_STD_PAL)
  62.                 return ADV7180_INPUT_CONTROL_PAL_BG;
  63.         if (std & V4L2_STD_NTSC)
  64.                 return ADV7180_INPUT_CONTROL_NTSC_M;
  65.         if (std & V4L2_STD_SECAM)
  66.                 return ADV7180_INPUT_CONTROL_PAL_SECAM;

  67.         return -EINVAL;
  68. }

  69. static u32 adv7180_status_to_v4l2(u8 status1)
  70. {
  71.         if (!(status1 & ADV7180_STATUS1_IN_LOCK))
  72.                 return V4L2_IN_ST_NO_SIGNAL;

  73.         return 0;
  74. }

  75. static int __adv7180_status(struct i2c_client *client, u32 *status,
  76.         v4l2_std_id *std)
  77. {
  78.         int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG);

  79.         if (status1 < 0)
  80.                 return status1;

  81.         if (status)
  82.                 *status = adv7180_status_to_v4l2(status1);
  83.         if (std)
  84.                 *std = adv7180_std_to_v4l2(status1);

  85.         return 0;
  86. }

  87. static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
  88. {
  89.         return container_of(sd, struct adv7180_state, sd);
  90. }

  91. static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
  92. {
  93.         struct adv7180_state *state = to_state(sd);
  94.         int err = mutex_lock_interruptible(&state->mutex);
  95.         if (err)
  96.                 return err;

  97.         /* when we are interrupt driven we know the state */
  98.         if (!state->autodetect || state->irq > 0)
  99.                 *std = state->curr_norm;
  100.         else
  101.                 err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);

  102.         mutex_unlock(&state->mutex);
  103.         return err;
  104. }

  105. static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
  106. {
  107.         struct adv7180_state *state = to_state(sd);
  108.         int ret = mutex_lock_interruptible(&state->mutex);
  109.         if (ret)
  110.                 return ret;

  111.         ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL);
  112.         mutex_unlock(&state->mutex);
  113.         return ret;
  114. }

  115. static int adv7180_g_chip_ident(struct v4l2_subdev *sd,
  116.         struct v4l2_dbg_chip_ident *chip)
  117. {
  118.         struct i2c_client *client = v4l2_get_subdevdata(sd);

  119.         return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0);
  120. }

  121. static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
  122. {
  123.         struct adv7180_state *state = to_state(sd);
  124.         struct i2c_client *client = v4l2_get_subdevdata(sd);
  125.         int ret = mutex_lock_interruptible(&state->mutex);
  126.         if (ret)
  127.                 return ret;

  128.         /* all standards -> autodetect */
  129.         if (std == V4L2_STD_ALL) {
  130.                 ret = i2c_smbus_write_byte_data(client,
  131.                         ADV7180_INPUT_CONTROL_REG,
  132.                         ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
  133.                 if (ret < 0)
  134.                         goto out;

  135.                 __adv7180_status(client, NULL, &state->curr_norm);
  136.                 state->autodetect = true;
  137.         } else {
  138.                 ret = v4l2_std_to_adv7180(std);
  139.                 if (ret < 0)
  140.                         goto out;

  141.                 ret = i2c_smbus_write_byte_data(client,
  142.                         ADV7180_INPUT_CONTROL_REG, ret);
  143.                 if (ret < 0)
  144.                         goto out;

  145.                 state->curr_norm = std;
  146.                 state->autodetect = false;
  147.         }
  148.         ret = 0;
  149. out:
  150.         mutex_unlock(&state->mutex);
  151.         return ret;
  152. }

  153. static const struct v4l2_subdev_video_ops adv7180_video_ops = {
  154.         .querystd = adv7180_querystd,
  155.         .g_input_status = adv7180_g_input_status,
  156. };

  157. static const struct v4l2_subdev_core_ops adv7180_core_ops = {
  158.         .g_chip_ident = adv7180_g_chip_ident,
  159.         .s_std = adv7180_s_std,
  160. };

  161. static const struct v4l2_subdev_ops adv7180_ops = {
  162.         .core = &adv7180_core_ops,
  163.         .video = &adv7180_video_ops,
  164. };

  165. static void adv7180_work(struct work_struct *work)
  166. {
  167.         struct adv7180_state *state = container_of(work, struct adv7180_state,
  168.                 work);
  169.         struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
  170.         u8 isr3;

  171.         mutex_lock(&state->mutex);
  172.         i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
  173.                 ADV7180_ADI_CTRL_IRQ_SPACE);
  174.         isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI);
  175.         /* clear */
  176.         i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3);
  177.         i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0);

  178.         if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect)
  179.                 __adv7180_status(client, NULL, &state->curr_norm);
  180.         mutex_unlock(&state->mutex);

  181.         enable_irq(state->irq);
  182. }

  183. static irqreturn_t adv7180_irq(int irq, void *devid)
  184. {
  185.         struct adv7180_state *state = devid;

  186.         schedule_work(&state->work);

  187.         disable_irq_nosync(state->irq);

  188.         return IRQ_HANDLED;
  189. }

  190. /*
  191. * Generic i2c probe
  192. * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  193. */

  194. static __devinit int adv7180_probe(struct i2c_client *client,
  195.                         const struct i2c_device_id *id)
  196. {
  197.         struct adv7180_state *state;
  198.         struct v4l2_subdev *sd;
  199.         int ret;

  200.         /* Check if the adapter supports the needed features */
  201.         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
  202.                 return -EIO;

  203.         v4l_info(client, "chip found @ 0x%02x (%s)\n",
  204.                         client->addr << 1, client->adapter->name);

  205.         state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL);
  206.         if (state == NULL) {
  207.                 ret = -ENOMEM;
  208.                 goto err;
  209.         }

  210.         state->irq = client->irq;
  211.         INIT_WORK(&state->work, adv7180_work);
  212.         mutex_init(&state->mutex);
  213.         state->autodetect = true;
  214.         sd = &state->sd;
  215.         v4l2_i2c_subdev_init(sd, client, &adv7180_ops);

  216.         /* Initialize adv7180 */
  217.         /* Enable autodetection */
  218.         ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
  219.                 ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
  220.         if (ret < 0)
  221.                 goto err_unreg_subdev;

  222.         ret = i2c_smbus_write_byte_data(client, ADV7180_AUTODETECT_ENABLE_REG,
  223.                 ADV7180_AUTODETECT_DEFAULT);
  224.         if (ret < 0)
  225.                 goto err_unreg_subdev;

  226.         /* ITU-R BT.656-4 compatible */
  227.         ret = i2c_smbus_write_byte_data(client,
  228.                 ADV7180_EXTENDED_OUTPUT_CONTROL_REG,
  229.                 ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
  230.         if (ret < 0)
  231.                 goto err_unreg_subdev;

  232.         /* read current norm */
  233.         __adv7180_status(client, NULL, &state->curr_norm);

  234.         /* register for interrupts */
  235.         if (state->irq > 0) {
  236.                 ret = request_irq(state->irq, adv7180_irq, 0, DRIVER_NAME,
  237.                         state);
  238.                 if (ret)
  239.                         goto err_unreg_subdev;

  240.                 ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
  241.                         ADV7180_ADI_CTRL_IRQ_SPACE);
  242.                 if (ret < 0)
  243.                         goto err_unreg_subdev;

  244.                 /* config the Interrupt pin to be active low */
  245.                 ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI,
  246.                         ADV7180_ICONF1_ACTIVE_LOW | ADV7180_ICONF1_PSYNC_ONLY);
  247.                 if (ret < 0)
  248.                         goto err_unreg_subdev;

  249.                 ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0);
  250.                 if (ret < 0)
  251.                         goto err_unreg_subdev;

  252.                 ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0);
  253.                 if (ret < 0)
  254.                         goto err_unreg_subdev;

  255.                 /* enable AD change interrupts interrupts */
  256.                 ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI,
  257.                         ADV7180_IRQ3_AD_CHANGE);
  258.                 if (ret < 0)
  259.                         goto err_unreg_subdev;

  260.                 ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0);
  261.                 if (ret < 0)
  262.                         goto err_unreg_subdev;

  263.                 ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
  264.                         0);
  265.                 if (ret < 0)
  266.                         goto err_unreg_subdev;
  267.         }

  268.         return 0;

  269. err_unreg_subdev:
  270.         mutex_destroy(&state->mutex);
  271.         v4l2_device_unregister_subdev(sd);
  272.         kfree(state);
  273. err:
  274.         printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", ret);
  275.         return ret;
  276. }

  277. static __devexit int adv7180_remove(struct i2c_client *client)
  278. {
  279.         struct v4l2_subdev *sd = i2c_get_clientdata(client);
  280.         struct adv7180_state *state = to_state(sd);

  281.         if (state->irq > 0) {
  282.                 free_irq(client->irq, state);
  283.                 if (cancel_work_sync(&state->work)) {
  284.                         /*
  285.                          * Work was pending, therefore we need to enable
  286.                          * IRQ here to balance the disable_irq() done in the
  287.                          * interrupt handler.
  288.                          */
  289.                         enable_irq(state->irq);
  290.                 }
  291.         }

  292.         mutex_destroy(&state->mutex);
  293.         v4l2_device_unregister_subdev(sd);
  294.         kfree(to_state(sd));
  295.         return 0;
  296. }

  297. static const struct i2c_device_id adv7180_id[] = {
  298.         {DRIVER_NAME, 0},
  299.         {},
  300. };

  301. MODULE_DEVICE_TABLE(i2c, adv7180_id);

  302. static struct i2c_driver adv7180_driver = {
  303.         .driver = {
  304.                 .owner        = THIS_MODULE,
  305.                 .name        = DRIVER_NAME,
  306.         },
  307.         .probe                = adv7180_probe,
  308.         .remove                = __devexit_p(adv7180_remove),
  309.         .id_table        = adv7180_id,
  310. };

  311. static __init int adv7180_init(void)
  312. {
  313.         return i2c_add_driver(&adv7180_driver);
  314. }

  315. static __exit void adv7180_exit(void)
  316. {
  317.         i2c_del_driver(&adv7180_driver);
  318. }

  319. module_init(adv7180_init);
  320. module_exit(adv7180_exit);
  321. MODULE_LICENSE("GPL v2");
复制代码
亚瑟王 发表于 2013-12-9 10:33:50 | 显示全部楼层
检查一下mach-tq2440.c文件中中有没有添加相关的初始化代码吧。probe函数的参数来源就是mach-tq2440.c中的初始化。
 楼主| jeff_arm 发表于 2013-12-9 22:05:12 | 显示全部楼层
是的,我改动过mach-tq2440.c  好像有进入probe函数 , 在 state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); 出错吧,基础差了,搞不明白
static struct i2c_board_info __initdata i2c_adv7180[] = {  //jf  add   //s3c2410_i2c_board_info[]
        {
        I2C_BOARD_INFO("adv7180",0x42),   /*0x40 is addr of adv7180*/         //jf  add
//        .platform_data = 0,                                   //jf  add
        },
};

static struct platform_device *tq2440_devices[] __initdata = {
        &s3c_device_usb,
        &s3c_device_lcd,
        &s3c_device_wdt,
        &s3c_device_i2c0,
        &s3c_device_iis,
        &s3c_device_rtc,
//        &s3c_device_adv7180,                  //jf add
#ifdef CONFIG_DM9000
        &s3c_device_dm9000,
#endif
        &s3c_device_usbgadget,
        &s3c_device_uda134x,
//        &s3c_device_ts,
};

static void __init tq2440_map_io(void)
{
        s3c24xx_init_io(tq2440_iodesc, ARRAY_SIZE(tq2440_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(tq2440_uartcfgs, ARRAY_SIZE(tq2440_uartcfgs));
}

static void __init tq2440_machine_init(void)
{
        s3c24xx_fb_set_platdata(&tq2440_fb_info);
//        s3c_device_ts.dev.platform_data = & tq2440_ts_info;
        s3c_i2c0_set_platdata(NULL);

        platform_add_devices(tq2440_devices, ARRAY_SIZE(tq2440_devices));
        i2c_register_board_info(0,i2c_adv7180,ARRAY_SIZE(i2c_adv7180));    //jf add
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-5-29 18:13 , Processed in 1.031250 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表