static int __devinit twl6040_codec_probe(struct platform_device *pdev) { struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; struct snd_soc_codec *codec; struct twl6040_data *priv; int audpwron, naudint; int ret = 0; priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; if (twl_codec) { audpwron = twl_codec->audpwron_gpio; naudint = twl_codec->naudint_irq; } else { audpwron = -EINVAL; naudint = 0; } priv->audpwron = audpwron; priv->naudint = naudint; codec = &priv->codec; codec->dev = &pdev->dev; twl6040_dai.dev = &pdev->dev; codec->name = "twl6040"; codec->owner = THIS_MODULE; codec->read = twl6040_read_reg_cache; codec->write = twl6040_write; codec->set_bias_level = twl6040_set_bias_level; snd_soc_codec_set_drvdata(codec, priv); codec->dai = &twl6040_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(twl6040_reg); codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg), GFP_KERNEL); if (codec->reg_cache == NULL) { ret = -ENOMEM; goto cache_err; } mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); init_completion(&priv->ready); if (gpio_is_valid(audpwron)) { ret = gpio_request(audpwron, "audpwron"); if (ret) goto gpio1_err; ret = gpio_direction_output(audpwron, 0); if (ret) goto gpio2_err; priv->codec_powered = 0; } if (naudint) { /* audio interrupt */ ret = request_threaded_irq(naudint, NULL, twl6040_naudint_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "twl6040_codec", codec); if (ret) goto gpio2_err; } else { if (gpio_is_valid(audpwron)) { /* enable only codec ready interrupt */ twl6040_write_reg_cache(codec, TWL6040_REG_INTMR, ~TWL6040_READYMSK & TWL6040_ALLINT_MSK); } else { /* no interrupts at all */ twl6040_write_reg_cache(codec, TWL6040_REG_INTMR, TWL6040_ALLINT_MSK); } } /* init vio registers */ twl6040_init_vio_regs(codec); /* power on device */ ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (ret) goto irq_err; ret = snd_soc_register_codec(codec); if (ret) goto reg_err; twl6040_codec = codec; ret = snd_soc_register_dai(&twl6040_dai); if (ret) goto dai_err; return 0; dai_err: snd_soc_unregister_codec(codec); twl6040_codec = NULL; reg_err: twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); irq_err: if (naudint) free_irq(naudint, codec); gpio2_err: if (gpio_is_valid(audpwron)) gpio_free(audpwron); gpio1_err: kfree(codec->reg_cache); cache_err: kfree(priv); return ret; }
static int twl6040_probe(struct snd_soc_codec *codec) { struct twl4030_codec_audio_data *twl_codec = codec->dev->platform_data; struct twl6040_data *priv; struct twl6040_jack_data *jack; int audpwron, naudint; struct input_dev *ip_dev; #if defined(CONFIG_MACH_LGE_COSMO_REV_A) unsigned hsjack_gpio, hsjack_irq; int err; #endif int ret = 0; u8 icrev = 0, intmr = TWL6040_ALLINT_MSK; int idx; for( idx = 0 ; idx < TWL6040_MUTE_DATA_MAX ; idx++ ) { s_mute_data[idx].dai = 0; s_mute_data[idx].mute = 0; } priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, priv); priv->codec = codec; priv->dl_active = 0; priv->ul_active = 0; twl6040_i2c_read(TWL6040_REG_ASICREV, &icrev); if (twl_codec && (icrev > 0)) audpwron = twl_codec->audpwron_gpio; else audpwron = -EINVAL; #if defined(CONFIG_MACH_LGE_COSMO_REV_A) if (twl_codec){ naudint = twl_codec->naudint_irq; hsjack_gpio = twl_codec->hsjack_gpio; hsjack_irq = twl_codec->hsjack_irq; } else { naudint = 0; hsjack_gpio = 0; hsjack_irq = 0; } #else if (twl_codec) naudint = twl_codec->naudint_irq; else naudint = 0; #endif priv->audpwron = audpwron; priv->naudint = naudint; #if defined(CONFIG_MACH_LGE_COSMO_REV_A) priv->hsjack_gpio = hsjack_gpio; priv->hsjack_irq = hsjack_irq; #endif init_completion(&priv->ready); /* Disable safe mode in SYS_NIRQ PAD */ // omap_writew(0x0118, 0x4A1001A0); INIT_DELAYED_WORK(&priv->hsdet_dwork, twl6040_hs_jack_detect_dwork); INIT_DELAYED_WORK(&priv->hook_work, twl6040_hs_hook_detect_work); #ifndef CONFIG_MACH_LGE_COSMOPOLITAN INIT_WORK(&priv->audint_work, twl6040_audint_work); #endif ip_dev = input_allocate_device(); if(!ip_dev){ dev_err(codec->dev, "failed to allocation hook input device"); goto switch_err; } __set_bit(EV_KEY, ip_dev->evbit); __set_bit(EV_SYN, ip_dev->evbit); __set_bit(KEY_HOOK, ip_dev->keybit); ip_dev->name = "headset_hook"; ip_dev->phys = "headset_hook/input0"; priv->hs_jack.headset_input = ip_dev; input_register_device(priv->hs_jack.headset_input); /* switch-class based headset detection */ jack = &priv->hs_jack; jack->sdev.name = "h2w"; ret = switch_dev_register(&jack->sdev); if (ret) { dev_err(codec->dev, "error registering switch device %d\n", ret); goto switch_err; } #if defined(CONFIG_MACH_LGE_COSMO_REV_A) /* GPIO request and direction set */ if(gpio_is_valid(hsjack_gpio)) { err = gpio_request(hsjack_gpio, "ear_sense"); if (err) { printk(KERN_ERR "%s: failed to request GPIO_%d\n", __func__, hsjack_gpio); goto err_hs_gpio_request; } err = gpio_direction_input(hsjack_gpio); if (err) { printk(KERN_ERR "%s: failed to set direction GPIO_%d\n", __func__, hsjack_gpio); goto err_hs_gpio_direction; } } /* IRQ request */ err = request_irq(hsjack_irq, hsjack_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "headset_detect", codec); if (err) { printk(KERN_ERR "%s: failed to request irq (%d)\n", __func__, hsjack_irq); goto err_hs_request_irq; } #endif if (gpio_is_valid(audpwron)) { ret = gpio_request(audpwron, "audpwron"); if (ret) goto gpio1_err; ret = gpio_direction_output(audpwron, 0); if (ret) goto gpio2_err; priv->codec_powered = 0; /* enable only codec ready interrupt */ intmr &= ~(TWL6040_READYMSK | TWL6040_PLUGMSK ); priv->intmask = intmr; /* reset interrupt status to allow correct power up sequence */ twl6040_read_reg_volatile(codec, TWL6040_REG_INTID); } twl6040_write(codec, TWL6040_REG_INTMR, intmr); if (naudint) { /* audio interrupt */ ret = request_threaded_irq(naudint, NULL, twl6040_naudint_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "twl6040_codec", codec); if (ret) goto gpio2_err; } /* init vio registers */ twl6040_init_vio_regs(codec); /* power on device */ ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (ret) goto bias_err; snd_soc_add_controls(codec, twl6040_snd_controls, ARRAY_SIZE(twl6040_snd_controls)); twl6040_add_widgets(codec); wake_lock_init(&priv->wake_lock, WAKE_LOCK_SUSPEND, "twl6040"); cdc_tcxo_set_req_int(CDC_TCXO_CLK3, 0); /* TODO: read HS jack insertion status */ return 0; bias_err: if (naudint) free_irq(naudint, codec); #if defined(CONFIG_MACH_LGE_COSMO_REV_A) err_hs_request_irq: err_hs_gpio_direction: if (gpio_is_valid(hsjack_gpio)) gpio_free(hsjack_gpio); err_hs_gpio_request: #endif gpio2_err: if (gpio_is_valid(audpwron)) gpio_free(audpwron); gpio1_err: switch_dev_unregister(&jack->sdev); switch_err: kfree(priv); return ret; }
static int twl6040_probe(struct snd_soc_codec *codec) { struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev); struct twl6040_data *priv; struct twl6040_jack_data *jack; int ret = 0; codec->control_data = dev_get_drvdata(codec->dev->parent); priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, priv); priv->codec = codec; priv->workqueue = create_singlethread_workqueue("twl6040-codec"); if (!priv->workqueue) goto work_err; #if TWL6040_DEBUG /////////////////////////////////////////////////////////////////////////////////////////////////// { codec_twl6040 = codec->control_data; ret = device_create_file(codec->dev, &dev_attr_reg); if (ret < 0) printk(KERN_WARNING "twl6040: failed to add entries\n"); ret = device_create_file(codec->dev, &dev_attr_val); if (ret < 0) printk(KERN_WARNING "twl6040: failed to add entries\n"); ret = device_create_file(codec->dev, &dev_attr_prt); if (ret < 0) printk(KERN_WARNING "twl6040: failed to add entries\n"); } /////////////////////////////////////////////////////////////////////////////////////////////////// #endif priv->hfl_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN); priv->hfr_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN); priv->hs_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN); INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work); mutex_init(&priv->mutex); priv->vddhf_reg = regulator_get(codec->dev, "vddhf"); if (IS_ERR(priv->vddhf_reg)) { ret = PTR_ERR(priv->vddhf_reg); dev_warn(codec->dev, "couldn't get VDDHF regulator %d\n", ret); priv->vddhf_reg = NULL; } if (priv->vddhf_reg) { ret = regulator_set_voltage(priv->vddhf_reg, pdata->vddhf_uV, pdata->vddhf_uV); if (ret) { dev_warn(codec->dev, "failed to set VDDHF voltage %d\n", ret); goto reg_err; } } /* switch-class based headset detection */ jack = &priv->hs_jack; jack->sdev.name = "h2w"; ret = switch_dev_register(&jack->sdev); if (ret) { dev_err(codec->dev, "error registering switch device %d\n", ret); goto reg_err; } wake_lock_init(&priv->wake_lock, WAKE_LOCK_SUSPEND, "twl6040"); ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_PLUG, twl6040_audio_handler, IRQF_NO_SUSPEND, "twl6040_irq_plug", codec); if (ret) { dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); goto irq_err; } /* init vio registers */ twl6040_init_vio_regs(codec); /* power on device */ ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (ret) goto bias_err; snd_soc_add_controls(codec, twl6040_snd_controls, ARRAY_SIZE(twl6040_snd_controls)); twl6040_add_widgets(codec); /* TODO: read HS jack insertion status */ return 0; bias_err: twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec); irq_err: wake_lock_destroy(&priv->wake_lock); switch_dev_unregister(&jack->sdev); reg_err: if (priv->vddhf_reg) regulator_put(priv->vddhf_reg); destroy_workqueue(priv->workqueue); work_err: kfree(priv); return ret; }
static int twl6040_probe(struct snd_soc_codec *codec) { struct twl6040_data *priv; struct twl6040_jack_data *jack; int ret = 0; codec->control_data = dev_get_drvdata(codec->dev->parent); priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; snd_soc_codec_set_drvdata(codec, priv); priv->codec = codec; priv->workqueue = create_singlethread_workqueue("twl6040-codec"); if (!priv->workqueue) goto work_err; priv->hfl_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFLGAIN); priv->hfr_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HFRGAIN); priv->hs_gain = twl6040_read_reg_cache(codec, TWL6040_REG_HSGAIN); INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work); mutex_init(&priv->mutex); /* switch-class based headset detection */ jack = &priv->hs_jack; jack->sdev.name = "h2w"; ret = switch_dev_register(&jack->sdev); if (ret) { dev_err(codec->dev, "error registering switch device %d\n", ret); goto switch_err; } //--[[ LGE_UBIQUIX_MODIFIED_START : [email protected] : add from DCM_GB wake_lock_init(&priv->wake_lock, WAKE_LOCK_SUSPEND, "twl6040"); ret = twl6040_request_irq(codec->control_data, TWL6040_IRQ_PLUG, twl6040_audio_handler, IRQF_NO_SUSPEND, "twl6040_irq_plug", codec); //--[[ LGE_UBIQUIX_MODIFIED_END : [email protected] : add from DCM_GB if (ret) { dev_err(codec->dev, "PLUG IRQ request failed: %d\n", ret); goto irq_err; } /* init vio registers */ twl6040_init_vio_regs(codec); /* power on device */ ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (ret) goto bias_err; snd_soc_add_controls(codec, twl6040_snd_controls, ARRAY_SIZE(twl6040_snd_controls)); twl6040_add_widgets(codec); /* TODO: read HS jack insertion status */ return 0; bias_err: twl6040_free_irq(codec->control_data, TWL6040_IRQ_PLUG, codec); irq_err: //--[[ LGE_UBIQUIX_MODIFIED_START : [email protected] : add from DCM_GB wake_lock_destroy(&priv->wake_lock); //--[[ LGE_UBIQUIX_MODIFIED_END : [email protected] : add from DCM_GB switch_dev_unregister(&jack->sdev); switch_err: destroy_workqueue(priv->workqueue); work_err: kfree(priv); return ret; }