Loading sound/soc/codecs/wm8955.c +123 −75 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <sound/core.h> Loading @@ -38,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { /* codec private data */ struct wm8955_priv { enum snd_soc_control_type control_type; struct regmap *regmap; unsigned int mclk_rate; Loading @@ -48,69 +49,85 @@ struct wm8955_priv { struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; }; static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { 0x0000, /* R0 */ 0x0000, /* R1 */ 0x0079, /* R2 - LOUT1 volume */ 0x0079, /* R3 - ROUT1 volume */ 0x0000, /* R4 */ 0x0008, /* R5 - DAC Control */ 0x0000, /* R6 */ 0x000A, /* R7 - Audio Interface */ 0x0000, /* R8 - Sample Rate */ 0x0000, /* R9 */ 0x00FF, /* R10 - Left DAC volume */ 0x00FF, /* R11 - Right DAC volume */ 0x000F, /* R12 - Bass control */ 0x000F, /* R13 - Treble control */ 0x0000, /* R14 */ 0x0000, /* R15 - Reset */ 0x0000, /* R16 */ 0x0000, /* R17 */ 0x0000, /* R18 */ 0x0000, /* R19 */ 0x0000, /* R20 */ 0x0000, /* R21 */ 0x0000, /* R22 */ 0x00C1, /* R23 - Additional control (1) */ 0x0000, /* R24 - Additional control (2) */ 0x0000, /* R25 - Power Management (1) */ 0x0000, /* R26 - Power Management (2) */ 0x0000, /* R27 - Additional Control (3) */ 0x0000, /* R28 */ 0x0000, /* R29 */ 0x0000, /* R30 */ 0x0000, /* R31 */ 0x0000, /* R32 */ 0x0000, /* R33 */ 0x0050, /* R34 - Left out Mix (1) */ 0x0050, /* R35 - Left out Mix (2) */ 0x0050, /* R36 - Right out Mix (1) */ 0x0050, /* R37 - Right Out Mix (2) */ 0x0050, /* R38 - Mono out Mix (1) */ 0x0050, /* R39 - Mono out Mix (2) */ 0x0079, /* R40 - LOUT2 volume */ 0x0079, /* R41 - ROUT2 volume */ 0x0079, /* R42 - MONOOUT volume */ 0x0000, /* R43 - Clocking / PLL */ 0x0103, /* R44 - PLL Control 1 */ 0x0024, /* R45 - PLL Control 2 */ 0x01BA, /* R46 - PLL Control 3 */ 0x0000, /* R47 */ 0x0000, /* R48 */ 0x0000, /* R49 */ 0x0000, /* R50 */ 0x0000, /* R51 */ 0x0000, /* R52 */ 0x0000, /* R53 */ 0x0000, /* R54 */ 0x0000, /* R55 */ 0x0000, /* R56 */ 0x0000, /* R57 */ 0x0000, /* R58 */ 0x0000, /* R59 - PLL Control 4 */ static const struct reg_default wm8955_reg_defaults[] = { { 2, 0x0079 }, /* R2 - LOUT1 volume */ { 3, 0x0079 }, /* R3 - ROUT1 volume */ { 5, 0x0008 }, /* R5 - DAC Control */ { 7, 0x000A }, /* R7 - Audio Interface */ { 8, 0x0000 }, /* R8 - Sample Rate */ { 10, 0x00FF }, /* R10 - Left DAC volume */ { 11, 0x00FF }, /* R11 - Right DAC volume */ { 12, 0x000F }, /* R12 - Bass control */ { 13, 0x000F }, /* R13 - Treble control */ { 23, 0x00C1 }, /* R23 - Additional control (1) */ { 24, 0x0000 }, /* R24 - Additional control (2) */ { 25, 0x0000 }, /* R25 - Power Management (1) */ { 26, 0x0000 }, /* R26 - Power Management (2) */ { 27, 0x0000 }, /* R27 - Additional Control (3) */ { 34, 0x0050 }, /* R34 - Left out Mix (1) */ { 35, 0x0050 }, /* R35 - Left out Mix (2) */ { 36, 0x0050 }, /* R36 - Right out Mix (1) */ { 37, 0x0050 }, /* R37 - Right Out Mix (2) */ { 38, 0x0050 }, /* R38 - Mono out Mix (1) */ { 39, 0x0050 }, /* R39 - Mono out Mix (2) */ { 40, 0x0079 }, /* R40 - LOUT2 volume */ { 41, 0x0079 }, /* R41 - ROUT2 volume */ { 42, 0x0079 }, /* R42 - MONOOUT volume */ { 43, 0x0000 }, /* R43 - Clocking / PLL */ { 44, 0x0103 }, /* R44 - PLL Control 1 */ { 45, 0x0024 }, /* R45 - PLL Control 2 */ { 46, 0x01BA }, /* R46 - PLL Control 3 */ { 59, 0x0000 }, /* R59 - PLL Control 4 */ }; static bool wm8955_writeable(struct device *dev, unsigned int reg) { switch (reg) { case WM8955_LOUT1_VOLUME: case WM8955_ROUT1_VOLUME: case WM8955_DAC_CONTROL: case WM8955_AUDIO_INTERFACE: case WM8955_SAMPLE_RATE: case WM8955_LEFT_DAC_VOLUME: case WM8955_RIGHT_DAC_VOLUME: case WM8955_BASS_CONTROL: case WM8955_TREBLE_CONTROL: case WM8955_RESET: case WM8955_ADDITIONAL_CONTROL_1: case WM8955_ADDITIONAL_CONTROL_2: case WM8955_POWER_MANAGEMENT_1: case WM8955_POWER_MANAGEMENT_2: case WM8955_ADDITIONAL_CONTROL_3: case WM8955_LEFT_OUT_MIX_1: case WM8955_LEFT_OUT_MIX_2: case WM8955_RIGHT_OUT_MIX_1: case WM8955_RIGHT_OUT_MIX_2: case WM8955_MONO_OUT_MIX_1: case WM8955_MONO_OUT_MIX_2: case WM8955_LOUT2_VOLUME: case WM8955_ROUT2_VOLUME: case WM8955_MONOOUT_VOLUME: case WM8955_CLOCKING_PLL: case WM8955_PLL_CONTROL_1: case WM8955_PLL_CONTROL_2: case WM8955_PLL_CONTROL_3: case WM8955_PLL_CONTROL_4: return true; default: return false; } } static bool wm8955_volatile(struct device *dev, unsigned int reg) { switch (reg) { case WM8955_RESET: return true; default: return false; } } static int wm8955_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, WM8955_RESET, 0); Loading Loading @@ -765,8 +782,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache; int ret, i; int ret; switch (level) { case SND_SOC_BIAS_ON: Loading Loading @@ -795,7 +811,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, return ret; } snd_soc_cache_sync(codec); regcache_sync(wm8955->regmap); /* Enable VREF and VMID */ snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, Loading Loading @@ -869,8 +885,12 @@ static struct snd_soc_dai_driver wm8955_dai = { #ifdef CONFIG_PM static int wm8955_suspend(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); regcache_mark_dirty(wm8955->regmap); return 0; } Loading @@ -889,10 +909,11 @@ static int wm8955_probe(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); u16 *reg_cache = codec->reg_cache; int ret, i; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); codec->control_data = wm8955->regmap; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; Loading Loading @@ -947,12 +968,12 @@ static int wm8955_probe(struct snd_soc_codec *codec) /* Set platform data values */ if (pdata) { if (pdata->out2_speaker) reg_cache[WM8955_ADDITIONAL_CONTROL_2] |= WM8955_ROUT2INV; snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2, WM8955_ROUT2INV, WM8955_ROUT2INV); if (pdata->monoin_diff) reg_cache[WM8955_MONO_OUT_MIX_1] |= WM8955_DMEN; snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1, WM8955_DMEN, WM8955_DMEN); } wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); Loading Loading @@ -985,9 +1006,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { .suspend = wm8955_suspend, .resume = wm8955_resume, .set_bias_level = wm8955_set_bias_level, .reg_cache_size = ARRAY_SIZE(wm8955_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8955_reg, }; static const struct regmap_config wm8955_regmap = { .reg_bits = 7, .val_bits = 9, .max_register = WM8955_MAX_REGISTER, .volatile_reg = wm8955_volatile, .writeable_reg = wm8955_writeable, .cache_type = REGCACHE_RBTREE, .reg_defaults = wm8955_reg_defaults, .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults), }; static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, Loading @@ -1001,18 +1032,35 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, if (wm8955 == NULL) return -ENOMEM; wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap); if (IS_ERR(wm8955->regmap)) { ret = PTR_ERR(wm8955->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); return ret; } i2c_set_clientdata(i2c, wm8955); wm8955->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8955, &wm8955_dai, 1); if (ret != 0) goto err; return ret; err: regmap_exit(wm8955->regmap); return ret; } static __devexit int wm8955_i2c_remove(struct i2c_client *client) { struct wm8955_priv *wm8955 = i2c_get_clientdata(client); snd_soc_unregister_codec(&client->dev); regmap_exit(wm8955->regmap); return 0; } Loading Loading
sound/soc/codecs/wm8955.c +123 −75 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <sound/core.h> Loading @@ -38,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { /* codec private data */ struct wm8955_priv { enum snd_soc_control_type control_type; struct regmap *regmap; unsigned int mclk_rate; Loading @@ -48,69 +49,85 @@ struct wm8955_priv { struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; }; static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { 0x0000, /* R0 */ 0x0000, /* R1 */ 0x0079, /* R2 - LOUT1 volume */ 0x0079, /* R3 - ROUT1 volume */ 0x0000, /* R4 */ 0x0008, /* R5 - DAC Control */ 0x0000, /* R6 */ 0x000A, /* R7 - Audio Interface */ 0x0000, /* R8 - Sample Rate */ 0x0000, /* R9 */ 0x00FF, /* R10 - Left DAC volume */ 0x00FF, /* R11 - Right DAC volume */ 0x000F, /* R12 - Bass control */ 0x000F, /* R13 - Treble control */ 0x0000, /* R14 */ 0x0000, /* R15 - Reset */ 0x0000, /* R16 */ 0x0000, /* R17 */ 0x0000, /* R18 */ 0x0000, /* R19 */ 0x0000, /* R20 */ 0x0000, /* R21 */ 0x0000, /* R22 */ 0x00C1, /* R23 - Additional control (1) */ 0x0000, /* R24 - Additional control (2) */ 0x0000, /* R25 - Power Management (1) */ 0x0000, /* R26 - Power Management (2) */ 0x0000, /* R27 - Additional Control (3) */ 0x0000, /* R28 */ 0x0000, /* R29 */ 0x0000, /* R30 */ 0x0000, /* R31 */ 0x0000, /* R32 */ 0x0000, /* R33 */ 0x0050, /* R34 - Left out Mix (1) */ 0x0050, /* R35 - Left out Mix (2) */ 0x0050, /* R36 - Right out Mix (1) */ 0x0050, /* R37 - Right Out Mix (2) */ 0x0050, /* R38 - Mono out Mix (1) */ 0x0050, /* R39 - Mono out Mix (2) */ 0x0079, /* R40 - LOUT2 volume */ 0x0079, /* R41 - ROUT2 volume */ 0x0079, /* R42 - MONOOUT volume */ 0x0000, /* R43 - Clocking / PLL */ 0x0103, /* R44 - PLL Control 1 */ 0x0024, /* R45 - PLL Control 2 */ 0x01BA, /* R46 - PLL Control 3 */ 0x0000, /* R47 */ 0x0000, /* R48 */ 0x0000, /* R49 */ 0x0000, /* R50 */ 0x0000, /* R51 */ 0x0000, /* R52 */ 0x0000, /* R53 */ 0x0000, /* R54 */ 0x0000, /* R55 */ 0x0000, /* R56 */ 0x0000, /* R57 */ 0x0000, /* R58 */ 0x0000, /* R59 - PLL Control 4 */ static const struct reg_default wm8955_reg_defaults[] = { { 2, 0x0079 }, /* R2 - LOUT1 volume */ { 3, 0x0079 }, /* R3 - ROUT1 volume */ { 5, 0x0008 }, /* R5 - DAC Control */ { 7, 0x000A }, /* R7 - Audio Interface */ { 8, 0x0000 }, /* R8 - Sample Rate */ { 10, 0x00FF }, /* R10 - Left DAC volume */ { 11, 0x00FF }, /* R11 - Right DAC volume */ { 12, 0x000F }, /* R12 - Bass control */ { 13, 0x000F }, /* R13 - Treble control */ { 23, 0x00C1 }, /* R23 - Additional control (1) */ { 24, 0x0000 }, /* R24 - Additional control (2) */ { 25, 0x0000 }, /* R25 - Power Management (1) */ { 26, 0x0000 }, /* R26 - Power Management (2) */ { 27, 0x0000 }, /* R27 - Additional Control (3) */ { 34, 0x0050 }, /* R34 - Left out Mix (1) */ { 35, 0x0050 }, /* R35 - Left out Mix (2) */ { 36, 0x0050 }, /* R36 - Right out Mix (1) */ { 37, 0x0050 }, /* R37 - Right Out Mix (2) */ { 38, 0x0050 }, /* R38 - Mono out Mix (1) */ { 39, 0x0050 }, /* R39 - Mono out Mix (2) */ { 40, 0x0079 }, /* R40 - LOUT2 volume */ { 41, 0x0079 }, /* R41 - ROUT2 volume */ { 42, 0x0079 }, /* R42 - MONOOUT volume */ { 43, 0x0000 }, /* R43 - Clocking / PLL */ { 44, 0x0103 }, /* R44 - PLL Control 1 */ { 45, 0x0024 }, /* R45 - PLL Control 2 */ { 46, 0x01BA }, /* R46 - PLL Control 3 */ { 59, 0x0000 }, /* R59 - PLL Control 4 */ }; static bool wm8955_writeable(struct device *dev, unsigned int reg) { switch (reg) { case WM8955_LOUT1_VOLUME: case WM8955_ROUT1_VOLUME: case WM8955_DAC_CONTROL: case WM8955_AUDIO_INTERFACE: case WM8955_SAMPLE_RATE: case WM8955_LEFT_DAC_VOLUME: case WM8955_RIGHT_DAC_VOLUME: case WM8955_BASS_CONTROL: case WM8955_TREBLE_CONTROL: case WM8955_RESET: case WM8955_ADDITIONAL_CONTROL_1: case WM8955_ADDITIONAL_CONTROL_2: case WM8955_POWER_MANAGEMENT_1: case WM8955_POWER_MANAGEMENT_2: case WM8955_ADDITIONAL_CONTROL_3: case WM8955_LEFT_OUT_MIX_1: case WM8955_LEFT_OUT_MIX_2: case WM8955_RIGHT_OUT_MIX_1: case WM8955_RIGHT_OUT_MIX_2: case WM8955_MONO_OUT_MIX_1: case WM8955_MONO_OUT_MIX_2: case WM8955_LOUT2_VOLUME: case WM8955_ROUT2_VOLUME: case WM8955_MONOOUT_VOLUME: case WM8955_CLOCKING_PLL: case WM8955_PLL_CONTROL_1: case WM8955_PLL_CONTROL_2: case WM8955_PLL_CONTROL_3: case WM8955_PLL_CONTROL_4: return true; default: return false; } } static bool wm8955_volatile(struct device *dev, unsigned int reg) { switch (reg) { case WM8955_RESET: return true; default: return false; } } static int wm8955_reset(struct snd_soc_codec *codec) { return snd_soc_write(codec, WM8955_RESET, 0); Loading Loading @@ -765,8 +782,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache; int ret, i; int ret; switch (level) { case SND_SOC_BIAS_ON: Loading Loading @@ -795,7 +811,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, return ret; } snd_soc_cache_sync(codec); regcache_sync(wm8955->regmap); /* Enable VREF and VMID */ snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, Loading Loading @@ -869,8 +885,12 @@ static struct snd_soc_dai_driver wm8955_dai = { #ifdef CONFIG_PM static int wm8955_suspend(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); regcache_mark_dirty(wm8955->regmap); return 0; } Loading @@ -889,10 +909,11 @@ static int wm8955_probe(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); u16 *reg_cache = codec->reg_cache; int ret, i; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); codec->control_data = wm8955->regmap; ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); if (ret != 0) { dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); return ret; Loading Loading @@ -947,12 +968,12 @@ static int wm8955_probe(struct snd_soc_codec *codec) /* Set platform data values */ if (pdata) { if (pdata->out2_speaker) reg_cache[WM8955_ADDITIONAL_CONTROL_2] |= WM8955_ROUT2INV; snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2, WM8955_ROUT2INV, WM8955_ROUT2INV); if (pdata->monoin_diff) reg_cache[WM8955_MONO_OUT_MIX_1] |= WM8955_DMEN; snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1, WM8955_DMEN, WM8955_DMEN); } wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); Loading Loading @@ -985,9 +1006,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { .suspend = wm8955_suspend, .resume = wm8955_resume, .set_bias_level = wm8955_set_bias_level, .reg_cache_size = ARRAY_SIZE(wm8955_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8955_reg, }; static const struct regmap_config wm8955_regmap = { .reg_bits = 7, .val_bits = 9, .max_register = WM8955_MAX_REGISTER, .volatile_reg = wm8955_volatile, .writeable_reg = wm8955_writeable, .cache_type = REGCACHE_RBTREE, .reg_defaults = wm8955_reg_defaults, .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults), }; static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, Loading @@ -1001,18 +1032,35 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, if (wm8955 == NULL) return -ENOMEM; wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap); if (IS_ERR(wm8955->regmap)) { ret = PTR_ERR(wm8955->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d\n", ret); return ret; } i2c_set_clientdata(i2c, wm8955); wm8955->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8955, &wm8955_dai, 1); if (ret != 0) goto err; return ret; err: regmap_exit(wm8955->regmap); return ret; } static __devexit int wm8955_i2c_remove(struct i2c_client *client) { struct wm8955_priv *wm8955 = i2c_get_clientdata(client); snd_soc_unregister_codec(&client->dev); regmap_exit(wm8955->regmap); return 0; } Loading