diff options
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
-rw-r--r-- | sound/soc/codecs/wm8962.c | 143 |
1 files changed, 104 insertions, 39 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index e9710280e5e1..b1dc7d426438 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -51,6 +51,7 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { | |||
51 | 51 | ||
52 | /* codec private data */ | 52 | /* codec private data */ |
53 | struct wm8962_priv { | 53 | struct wm8962_priv { |
54 | struct wm8962_pdata pdata; | ||
54 | struct regmap *regmap; | 55 | struct regmap *regmap; |
55 | struct snd_soc_codec *codec; | 56 | struct snd_soc_codec *codec; |
56 | 57 | ||
@@ -1600,7 +1601,6 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, | |||
1600 | struct snd_ctl_elem_value *ucontrol) | 1601 | struct snd_ctl_elem_value *ucontrol) |
1601 | { | 1602 | { |
1602 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1603 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1603 | u16 *reg_cache = codec->reg_cache; | ||
1604 | int ret; | 1604 | int ret; |
1605 | 1605 | ||
1606 | /* Apply the update (if any) */ | 1606 | /* Apply the update (if any) */ |
@@ -1609,16 +1609,19 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, | |||
1609 | return 0; | 1609 | return 0; |
1610 | 1610 | ||
1611 | /* If the left PGA is enabled hit that VU bit... */ | 1611 | /* If the left PGA is enabled hit that VU bit... */ |
1612 | if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) | 1612 | ret = snd_soc_read(codec, WM8962_PWR_MGMT_2); |
1613 | return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, | 1613 | if (ret & WM8962_HPOUTL_PGA_ENA) { |
1614 | reg_cache[WM8962_HPOUTL_VOLUME]); | 1614 | snd_soc_write(codec, WM8962_HPOUTL_VOLUME, |
1615 | snd_soc_read(codec, WM8962_HPOUTL_VOLUME)); | ||
1616 | return 1; | ||
1617 | } | ||
1615 | 1618 | ||
1616 | /* ...otherwise the right. The VU is stereo. */ | 1619 | /* ...otherwise the right. The VU is stereo. */ |
1617 | if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) | 1620 | if (ret & WM8962_HPOUTR_PGA_ENA) |
1618 | return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, | 1621 | snd_soc_write(codec, WM8962_HPOUTR_VOLUME, |
1619 | reg_cache[WM8962_HPOUTR_VOLUME]); | 1622 | snd_soc_read(codec, WM8962_HPOUTR_VOLUME)); |
1620 | 1623 | ||
1621 | return 0; | 1624 | return 1; |
1622 | } | 1625 | } |
1623 | 1626 | ||
1624 | /* The VU bits for the speakers are in a different register to the mute | 1627 | /* The VU bits for the speakers are in a different register to the mute |
@@ -2345,12 +2348,13 @@ static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = { | |||
2345 | 2348 | ||
2346 | static int wm8962_add_widgets(struct snd_soc_codec *codec) | 2349 | static int wm8962_add_widgets(struct snd_soc_codec *codec) |
2347 | { | 2350 | { |
2348 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 2351 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
2352 | struct wm8962_pdata *pdata = &wm8962->pdata; | ||
2349 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2353 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
2350 | 2354 | ||
2351 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, | 2355 | snd_soc_add_codec_controls(codec, wm8962_snd_controls, |
2352 | ARRAY_SIZE(wm8962_snd_controls)); | 2356 | ARRAY_SIZE(wm8962_snd_controls)); |
2353 | if (pdata && pdata->spk_mono) | 2357 | if (pdata->spk_mono) |
2354 | snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, | 2358 | snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls, |
2355 | ARRAY_SIZE(wm8962_spk_mono_controls)); | 2359 | ARRAY_SIZE(wm8962_spk_mono_controls)); |
2356 | else | 2360 | else |
@@ -2360,7 +2364,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
2360 | 2364 | ||
2361 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, | 2365 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_widgets, |
2362 | ARRAY_SIZE(wm8962_dapm_widgets)); | 2366 | ARRAY_SIZE(wm8962_dapm_widgets)); |
2363 | if (pdata && pdata->spk_mono) | 2367 | if (pdata->spk_mono) |
2364 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, | 2368 | snd_soc_dapm_new_controls(dapm, wm8962_dapm_spk_mono_widgets, |
2365 | ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); | 2369 | ARRAY_SIZE(wm8962_dapm_spk_mono_widgets)); |
2366 | else | 2370 | else |
@@ -2369,7 +2373,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) | |||
2369 | 2373 | ||
2370 | snd_soc_dapm_add_routes(dapm, wm8962_intercon, | 2374 | snd_soc_dapm_add_routes(dapm, wm8962_intercon, |
2371 | ARRAY_SIZE(wm8962_intercon)); | 2375 | ARRAY_SIZE(wm8962_intercon)); |
2372 | if (pdata && pdata->spk_mono) | 2376 | if (pdata->spk_mono) |
2373 | snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, | 2377 | snd_soc_dapm_add_routes(dapm, wm8962_spk_mono_intercon, |
2374 | ARRAY_SIZE(wm8962_spk_mono_intercon)); | 2378 | ARRAY_SIZE(wm8962_spk_mono_intercon)); |
2375 | else | 2379 | else |
@@ -3333,14 +3337,14 @@ static struct gpio_chip wm8962_template_chip = { | |||
3333 | static void wm8962_init_gpio(struct snd_soc_codec *codec) | 3337 | static void wm8962_init_gpio(struct snd_soc_codec *codec) |
3334 | { | 3338 | { |
3335 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3339 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3336 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3340 | struct wm8962_pdata *pdata = &wm8962->pdata; |
3337 | int ret; | 3341 | int ret; |
3338 | 3342 | ||
3339 | wm8962->gpio_chip = wm8962_template_chip; | 3343 | wm8962->gpio_chip = wm8962_template_chip; |
3340 | wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; | 3344 | wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO; |
3341 | wm8962->gpio_chip.dev = codec->dev; | 3345 | wm8962->gpio_chip.dev = codec->dev; |
3342 | 3346 | ||
3343 | if (pdata && pdata->gpio_base) | 3347 | if (pdata->gpio_base) |
3344 | wm8962->gpio_chip.base = pdata->gpio_base; | 3348 | wm8962->gpio_chip.base = pdata->gpio_base; |
3345 | else | 3349 | else |
3346 | wm8962->gpio_chip.base = -1; | 3350 | wm8962->gpio_chip.base = -1; |
@@ -3374,7 +3378,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3374 | int ret; | 3378 | int ret; |
3375 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3379 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3376 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); | 3380 | struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); |
3377 | u16 *reg_cache = codec->reg_cache; | ||
3378 | int i, trigger, irq_pol; | 3381 | int i, trigger, irq_pol; |
3379 | bool dmicclk, dmicdat; | 3382 | bool dmicclk, dmicdat; |
3380 | 3383 | ||
@@ -3421,30 +3424,29 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3421 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, | 3424 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, |
3422 | 0); | 3425 | 0); |
3423 | 3426 | ||
3424 | if (pdata) { | 3427 | /* Apply static configuration for GPIOs */ |
3425 | /* Apply static configuration for GPIOs */ | 3428 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) |
3426 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) | 3429 | if (pdata->gpio_init[i]) { |
3427 | if (pdata->gpio_init[i]) { | 3430 | wm8962_set_gpio_mode(codec, i + 1); |
3428 | wm8962_set_gpio_mode(codec, i + 1); | 3431 | snd_soc_write(codec, 0x200 + i, |
3429 | snd_soc_write(codec, 0x200 + i, | 3432 | pdata->gpio_init[i] & 0xffff); |
3430 | pdata->gpio_init[i] & 0xffff); | 3433 | } |
3431 | } | ||
3432 | 3434 | ||
3433 | /* Put the speakers into mono mode? */ | ||
3434 | if (pdata->spk_mono) | ||
3435 | reg_cache[WM8962_CLASS_D_CONTROL_2] | ||
3436 | |= WM8962_SPK_MONO; | ||
3437 | 3435 | ||
3438 | /* Micbias setup, detection enable and detection | 3436 | /* Put the speakers into mono mode? */ |
3439 | * threasholds. */ | 3437 | if (pdata->spk_mono) |
3440 | if (pdata->mic_cfg) | 3438 | snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2, |
3441 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, | 3439 | WM8962_SPK_MONO_MASK, WM8962_SPK_MONO); |
3442 | WM8962_MICDET_ENA | | 3440 | |
3443 | WM8962_MICDET_THR_MASK | | 3441 | /* Micbias setup, detection enable and detection |
3444 | WM8962_MICSHORT_THR_MASK | | 3442 | * threasholds. */ |
3445 | WM8962_MICBIAS_LVL, | 3443 | if (pdata->mic_cfg) |
3446 | pdata->mic_cfg); | 3444 | snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4, |
3447 | } | 3445 | WM8962_MICDET_ENA | |
3446 | WM8962_MICDET_THR_MASK | | ||
3447 | WM8962_MICSHORT_THR_MASK | | ||
3448 | WM8962_MICBIAS_LVL, | ||
3449 | pdata->mic_cfg); | ||
3448 | 3450 | ||
3449 | /* Latch volume update bits */ | 3451 | /* Latch volume update bits */ |
3450 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, | 3452 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, |
@@ -3506,7 +3508,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3506 | wm8962_init_gpio(codec); | 3508 | wm8962_init_gpio(codec); |
3507 | 3509 | ||
3508 | if (wm8962->irq) { | 3510 | if (wm8962->irq) { |
3509 | if (pdata && pdata->irq_active_low) { | 3511 | if (pdata->irq_active_low) { |
3510 | trigger = IRQF_TRIGGER_LOW; | 3512 | trigger = IRQF_TRIGGER_LOW; |
3511 | irq_pol = WM8962_IRQ_POL; | 3513 | irq_pol = WM8962_IRQ_POL; |
3512 | } else { | 3514 | } else { |
@@ -3584,6 +3586,34 @@ static const struct regmap_config wm8962_regmap = { | |||
3584 | .cache_type = REGCACHE_RBTREE, | 3586 | .cache_type = REGCACHE_RBTREE, |
3585 | }; | 3587 | }; |
3586 | 3588 | ||
3589 | static int wm8962_set_pdata_from_of(struct i2c_client *i2c, | ||
3590 | struct wm8962_pdata *pdata) | ||
3591 | { | ||
3592 | const struct device_node *np = i2c->dev.of_node; | ||
3593 | u32 val32; | ||
3594 | int i; | ||
3595 | |||
3596 | if (of_property_read_bool(np, "spk-mono")) | ||
3597 | pdata->spk_mono = true; | ||
3598 | |||
3599 | if (of_property_read_u32(np, "mic-cfg", &val32) >= 0) | ||
3600 | pdata->mic_cfg = val32; | ||
3601 | |||
3602 | if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_init, | ||
3603 | ARRAY_SIZE(pdata->gpio_init)) >= 0) | ||
3604 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) { | ||
3605 | /* | ||
3606 | * The range of GPIO register value is [0x0, 0xffff] | ||
3607 | * While the default value of each register is 0x0 | ||
3608 | * Any other value will be regarded as default value | ||
3609 | */ | ||
3610 | if (pdata->gpio_init[i] > 0xffff) | ||
3611 | pdata->gpio_init[i] = 0x0; | ||
3612 | } | ||
3613 | |||
3614 | return 0; | ||
3615 | } | ||
3616 | |||
3587 | static int wm8962_i2c_probe(struct i2c_client *i2c, | 3617 | static int wm8962_i2c_probe(struct i2c_client *i2c, |
3588 | const struct i2c_device_id *id) | 3618 | const struct i2c_device_id *id) |
3589 | { | 3619 | { |
@@ -3603,6 +3633,15 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3603 | init_completion(&wm8962->fll_lock); | 3633 | init_completion(&wm8962->fll_lock); |
3604 | wm8962->irq = i2c->irq; | 3634 | wm8962->irq = i2c->irq; |
3605 | 3635 | ||
3636 | /* If platform data was supplied, update the default data in priv */ | ||
3637 | if (pdata) { | ||
3638 | memcpy(&wm8962->pdata, pdata, sizeof(struct wm8962_pdata)); | ||
3639 | } else if (i2c->dev.of_node) { | ||
3640 | ret = wm8962_set_pdata_from_of(i2c, &wm8962->pdata); | ||
3641 | if (ret != 0) | ||
3642 | return ret; | ||
3643 | } | ||
3644 | |||
3606 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 3645 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
3607 | wm8962->supplies[i].supply = wm8962_supply_names[i]; | 3646 | wm8962->supplies[i].supply = wm8962_supply_names[i]; |
3608 | 3647 | ||
@@ -3666,7 +3705,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3666 | goto err_enable; | 3705 | goto err_enable; |
3667 | } | 3706 | } |
3668 | 3707 | ||
3669 | if (pdata && pdata->in4_dc_measure) { | 3708 | if (wm8962->pdata.in4_dc_measure) { |
3670 | ret = regmap_register_patch(wm8962->regmap, | 3709 | ret = regmap_register_patch(wm8962->regmap, |
3671 | wm8962_dc_measure, | 3710 | wm8962_dc_measure, |
3672 | ARRAY_SIZE(wm8962_dc_measure)); | 3711 | ARRAY_SIZE(wm8962_dc_measure)); |
@@ -3719,8 +3758,34 @@ static int wm8962_runtime_resume(struct device *dev) | |||
3719 | 3758 | ||
3720 | wm8962_reset(wm8962); | 3759 | wm8962_reset(wm8962); |
3721 | 3760 | ||
3761 | /* SYSCLK defaults to on; make sure it is off so we can safely | ||
3762 | * write to registers if the device is declocked. | ||
3763 | */ | ||
3764 | regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2, | ||
3765 | WM8962_SYSCLK_ENA, 0); | ||
3766 | |||
3767 | /* Ensure we have soft control over all registers */ | ||
3768 | regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2, | ||
3769 | WM8962_CLKREG_OVD, WM8962_CLKREG_OVD); | ||
3770 | |||
3771 | /* Ensure that the oscillator and PLLs are disabled */ | ||
3772 | regmap_update_bits(wm8962->regmap, WM8962_PLL2, | ||
3773 | WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA, | ||
3774 | 0); | ||
3775 | |||
3722 | regcache_sync(wm8962->regmap); | 3776 | regcache_sync(wm8962->regmap); |
3723 | 3777 | ||
3778 | regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, | ||
3779 | WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA, | ||
3780 | WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA); | ||
3781 | |||
3782 | /* Bias enable at 2*5k (fast start-up) */ | ||
3783 | regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, | ||
3784 | WM8962_BIAS_ENA | WM8962_VMID_SEL_MASK, | ||
3785 | WM8962_BIAS_ENA | 0x180); | ||
3786 | |||
3787 | msleep(5); | ||
3788 | |||
3724 | return 0; | 3789 | return 0; |
3725 | } | 3790 | } |
3726 | 3791 | ||