lc1120 jack detect switch

/* switch data register*/
        struct lc1120_priv *data = container_of(codec, struct lc1120_priv, codec);  //从元素codec,得到lc1120_priv地址
        data->sdev.name = "h2w";  //switch设备只需要给个名字就能注册了。
        ret = switch_dev_register(&data->sdev);  //注册switch设备
        if(ret < 0){
            printk("lc1120 switch register failed\n");
            goto switch_exit;
        }
        lc1120_switch_init(codec);    //switch设备初始化,即根据启动情况设置state初始值
        state = lc1120_comp_state_get(codec, COMP_JACK);  //根据寄存器状况,获得state状态
        switch_set_state(&data->sdev, state);  //把寄存器读出来的状态写入sys/下的 state
        lc1120_comp_state_clear(&data->codec); //清除寄存器状态
        /* irq */
        INIT_WORK(&data->irq_work, lc1120_irq_work_handler);  //初始化一个中断处理程序
        struct i2c_client * client = (struct i2c_client *)(codec->control_data);  //得到client
        ret = gpio_request(client->irq, "lc1120"); //得到client中的irq号,就是board_i2c_info中的i2c设备irq
        if(ret < 0){
            printk(KERN_ERR "lc1120 request GPIO error!!\n");
            return ret;
        }
        ret = gpio_direction_input(client->irq); //把连接irq中断信号的GPIO 设成输入模式
        if(ret < 0){
            printk(KERN_ERR "LC1120: Failed to request GPIO.\n");
            goto gpio_exit;
        }
        client->irq = gpio_to_irq(client->irq); //双核时,把该GPIO映射到另一个cpu的中断控制器
        //注册一个中断,中断号为client->irq
        //中断处理函数为lc1120_irq_handle
        //中断触发模式IRQF_TRIGGER_RISING
        ret = request_irq(client->irq, lc1120_irq_handle, IRQF_TRIGGER_RISING,
                                        "lc1120_IRQ", data); 
        if(ret < 0){
            printk(KERN_ERR "LC1120 i2c probe : request irq failed!\n");
            goto gpio_exit;
        }
        /* register input for headset button*/
        data->input = input_allocate_device();  //申请一个input设备的内存。
        if (!data->input) {
            ret = -ENOMEM;
            goto input_free;
        }
        data->input->name = "HS button";    //input设备初始化
        __set_bit(EV_KEY, data->input->evbit);
        __set_bit(KEY_MEDIA, data->input->keybit);
        __set_bit(KEY_END, data->input->keybit);
        ret = input_register_device(data->input);   //注册一个input设备。
        if (ret < 0)
            goto input_unregister;
        return ret;
    input_unregister:
        input_unregister_device(data->input);
    input_free:
        input_free_device(data->input);
    gpio_exit:
        gpio_free(client->irq);
    switch_exit:
        switch_dev_unregister(&data->sdev);
    pcm_err:
        return ret;
    }

static int lc1120_switch_init(codec){     //switch功能寄存器初始化
        int r85, r84, r94;
    D_ENTER;
        /* JACK detect init */
        r85 = lc1120_read(codec, LC1120_R85);
        r85 |= (1 << LC1120_BIT_JACK_DET_EN);
        r85 &= ~(1 << LC1120_BIT_JACK_DET_POL);
        lc1120_write(codec, LC1120_R85, r85);
        /* hookswitch init*/
        r84 = lc1120_read(codec, LC1120_R84);
        r84 |= (1 << LC1120_BIT_HS_DET_EN);
        lc1120_write(codec, LC1120_R84, r84);
        /* disable ALC irq*/
        r94 = lc1120_read(codec, LC1120_R94);
        r94 |= (1 << LC1120_CD_ENB_ALC);
        lc1120_write(codec, LC1120_R94, r94);
        return 0;
    }

static int lc1120_comp_state_get(struct snd_soc_codec *codec, int id)  //获取jack detect和Hookswitch寄存器状况
    {
    D_ENTER;
        int r100, r101;
        int state, bit;
        r100 = lc1120_read(codec, LC1120_R100);
        switch (id){
            case COMP_JACK:
                bit = LC1120_BIT_COMP_JACK;
                break;
            case COMP_HS:
                bit = LC1120_BIT_COMP_HS;
                break;
            default:
                printk(KERN_INFO "comp id mismatch");
                return 0;
        }
        state = (r100 & (1 << bit)) ? 1 : 0;
        return state;
    }

static int lc1120_comp_state_clear(struct snd_soc_codec *codec){  //清除寄存器状态
    D_ENTER;
        int r9 = 0x0f;
        lc1120_write(codec, LC1120_R9, r9);
        r9 = 0;
        lc1120_write(codec, LC1120_R9, r9);
        return 0;
    }

static irqreturn_t lc1120_irq_handle(int irq, void *dev_id){  //中断处理程序
        struct lc1120_priv *data = (struct lc1120_priv *)dev_id;
    D_ENTER;
        schedule_work(&data->irq_work);   //里面schedule_work()创建了一个工作队列
        return IRQ_HANDLED;
    }

static void lc1120_irq_work_handler(struct work_struct *work)  //工作队列的中断处理程序
    {
        int state;
        struct lc1120_priv *data = container_of(work, struct lc1120_priv, irq_work);
    D_ENTER;
        state = lc1120_comp_state_get(&data->codec, COMP_JACK); //获得寄存器状态
        switch_set_state(&data->sdev, state);                   //再把寄存器状态写入sys/下的state
    #if 0
        state = lc1120_comp_state_get(&data->codec, COMP_HS);
        if (state){
            data->button_time = jiffies;
        }else {
            if (time_after(jiffies, data->button_time + COMIP_SWITCH_BUTTON_LONG_TIME)) {
                printk("Hook long pressed.\n");
                    input_report_key(data->input, KEY_END, 1);
                    input_report_key(data->input, KEY_END, 0);
                } else {
                    printk("Hook pressed.\n");
                    input_report_key(data->input, KEY_MEDIA, 1);
                    input_report_key(data->input, KEY_MEDIA, 0);
                }
                input_sync(data->input);
        }
    #endif
        lc1120_comp_state_clear(&data->codec);
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值