1 /* 2 * max9877.c -- amp driver for max9877 3 * 4 * Copyright (C) 2009 Samsung Electronics Co.Ltd 5 * Author: Joonyoung Shim <jy0922.shim@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 */ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/i2c.h> 17 #include <sound/soc.h> 18 #include <sound/tlv.h> 19 20 #include "max9877.h" 21 22 static struct i2c_client *i2c; 23 24 static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 }; 25 26 static void max9877_write_regs(void) 27 { 28 unsigned int i; 29 u8 data[6]; 30 31 data[0] = MAX9877_INPUT_MODE; 32 for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) 33 data[i + 1] = max9877_regs[i]; 34 35 if (i2c_master_send(i2c, data, 6) != 6) 36 dev_err(&i2c->dev, "i2c write failed\n"); 37 } 38 39 static int max9877_get_reg(struct snd_kcontrol *kcontrol, 40 struct snd_ctl_elem_value *ucontrol) 41 { 42 struct soc_mixer_control *mc = 43 (struct soc_mixer_control *)kcontrol->private_value; 44 unsigned int reg = mc->reg; 45 unsigned int shift = mc->shift; 46 unsigned int mask = mc->max; 47 unsigned int invert = mc->invert; 48 49 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; 50 51 if (invert) 52 ucontrol->value.integer.value[0] = 53 mask - ucontrol->value.integer.value[0]; 54 55 return 0; 56 } 57 58 static int max9877_set_reg(struct snd_kcontrol *kcontrol, 59 struct snd_ctl_elem_value *ucontrol) 60 { 61 struct soc_mixer_control *mc = 62 (struct soc_mixer_control *)kcontrol->private_value; 63 unsigned int reg = mc->reg; 64 unsigned int shift = mc->shift; 65 unsigned int mask = mc->max; 66 unsigned int invert = mc->invert; 67 unsigned int val = (ucontrol->value.integer.value[0] & mask); 68 69 if (invert) 70 val = mask - val; 71 72 if (((max9877_regs[reg] >> shift) & mask) == val) 73 return 0; 74 75 max9877_regs[reg] &= ~(mask << shift); 76 max9877_regs[reg] |= val << shift; 77 max9877_write_regs(); 78 79 return 1; 80 } 81 82 static int max9877_get_2reg(struct snd_kcontrol *kcontrol, 83 struct snd_ctl_elem_value *ucontrol) 84 { 85 struct soc_mixer_control *mc = 86 (struct soc_mixer_control *)kcontrol->private_value; 87 unsigned int reg = mc->reg; 88 unsigned int reg2 = mc->rreg; 89 unsigned int shift = mc->shift; 90 unsigned int mask = mc->max; 91 92 ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; 93 ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask; 94 95 return 0; 96 } 97 98 static int max9877_set_2reg(struct snd_kcontrol *kcontrol, 99 struct snd_ctl_elem_value *ucontrol) 100 { 101 struct soc_mixer_control *mc = 102 (struct soc_mixer_control *)kcontrol->private_value; 103 unsigned int reg = mc->reg; 104 unsigned int reg2 = mc->rreg; 105 unsigned int shift = mc->shift; 106 unsigned int mask = mc->max; 107 unsigned int val = (ucontrol->value.integer.value[0] & mask); 108 unsigned int val2 = (ucontrol->value.integer.value[1] & mask); 109 unsigned int change = 0; 110 111 if (((max9877_regs[reg] >> shift) & mask) != val) 112 change = 1; 113 114 if (((max9877_regs[reg2] >> shift) & mask) != val2) 115 change = 1; 116 117 if (change) { 118 max9877_regs[reg] &= ~(mask << shift); 119 max9877_regs[reg] |= val << shift; 120 max9877_regs[reg2] &= ~(mask << shift); 121 max9877_regs[reg2] |= val2 << shift; 122 max9877_write_regs(); 123 } 124 125 return change; 126 } 127 128 static int max9877_get_out_mode(struct snd_kcontrol *kcontrol, 129 struct snd_ctl_elem_value *ucontrol) 130 { 131 u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK; 132 133 if (value) 134 value -= 1; 135 136 ucontrol->value.integer.value[0] = value; 137 return 0; 138 } 139 140 static int max9877_set_out_mode(struct snd_kcontrol *kcontrol, 141 struct snd_ctl_elem_value *ucontrol) 142 { 143 u8 value = ucontrol->value.integer.value[0]; 144 145 value += 1; 146 147 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value) 148 return 0; 149 150 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK; 151 max9877_regs[MAX9877_OUTPUT_MODE] |= value; 152 max9877_write_regs(); 153 return 1; 154 } 155 156 static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol, 157 struct snd_ctl_elem_value *ucontrol) 158 { 159 u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK); 160 161 value = value >> MAX9877_OSC_OFFSET; 162 163 ucontrol->value.integer.value[0] = value; 164 return 0; 165 } 166 167 static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol, 168 struct snd_ctl_elem_value *ucontrol) 169 { 170 u8 value = ucontrol->value.integer.value[0]; 171 172 value = value << MAX9877_OSC_OFFSET; 173 if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value) 174 return 0; 175 176 max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK; 177 max9877_regs[MAX9877_OUTPUT_MODE] |= value; 178 max9877_write_regs(); 179 return 1; 180 } 181 182 static const unsigned int max9877_pgain_tlv[] = { 183 TLV_DB_RANGE_HEAD(2), 184 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0), 185 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0), 186 }; 187 188 static const unsigned int max9877_output_tlv[] = { 189 TLV_DB_RANGE_HEAD(4), 190 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), 191 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), 192 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), 193 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), 194 }; 195 196 static const char *max9877_out_mode[] = { 197 "INA -> SPK", 198 "INA -> HP", 199 "INA -> SPK and HP", 200 "INB -> SPK", 201 "INB -> HP", 202 "INB -> SPK and HP", 203 "INA + INB -> SPK", 204 "INA + INB -> HP", 205 "INA + INB -> SPK and HP", 206 }; 207 208 static const char *max9877_osc_mode[] = { 209 "1176KHz", 210 "1100KHz", 211 "700KHz", 212 }; 213 214 static const struct soc_enum max9877_enum[] = { 215 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode), 216 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), 217 }; 218 219 static const struct snd_kcontrol_new max9877_controls[] = { 220 SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume", 221 MAX9877_INPUT_MODE, 0, 2, 0, 222 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), 223 SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume", 224 MAX9877_INPUT_MODE, 2, 2, 0, 225 max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), 226 SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume", 227 MAX9877_SPK_VOLUME, 0, 31, 0, 228 max9877_get_reg, max9877_set_reg, max9877_output_tlv), 229 SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume", 230 MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, 231 max9877_get_2reg, max9877_set_2reg, max9877_output_tlv), 232 SOC_SINGLE_EXT("MAX9877 INB Stereo Switch", 233 MAX9877_INPUT_MODE, 4, 1, 1, 234 max9877_get_reg, max9877_set_reg), 235 SOC_SINGLE_EXT("MAX9877 INA Stereo Switch", 236 MAX9877_INPUT_MODE, 5, 1, 1, 237 max9877_get_reg, max9877_set_reg), 238 SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch", 239 MAX9877_INPUT_MODE, 6, 1, 0, 240 max9877_get_reg, max9877_set_reg), 241 SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch", 242 MAX9877_OUTPUT_MODE, 6, 1, 0, 243 max9877_get_reg, max9877_set_reg), 244 SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch", 245 MAX9877_OUTPUT_MODE, 7, 1, 1, 246 max9877_get_reg, max9877_set_reg), 247 SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0], 248 max9877_get_out_mode, max9877_set_out_mode), 249 SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1], 250 max9877_get_osc_mode, max9877_set_osc_mode), 251 }; 252 253 /* This function is called from ASoC machine driver */ 254 int max9877_add_controls(struct snd_soc_codec *codec) 255 { 256 return snd_soc_add_codec_controls(codec, max9877_controls, 257 ARRAY_SIZE(max9877_controls)); 258 } 259 EXPORT_SYMBOL_GPL(max9877_add_controls); 260 261 static int __devinit max9877_i2c_probe(struct i2c_client *client, 262 const struct i2c_device_id *id) 263 { 264 i2c = client; 265 266 max9877_write_regs(); 267 268 return 0; 269 } 270 271 static __devexit int max9877_i2c_remove(struct i2c_client *client) 272 { 273 i2c = NULL; 274 275 return 0; 276 } 277 278 static const struct i2c_device_id max9877_i2c_id[] = { 279 { "max9877", 0 }, 280 { } 281 }; 282 MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); 283 284 static struct i2c_driver max9877_i2c_driver = { 285 .driver = { 286 .name = "max9877", 287 .owner = THIS_MODULE, 288 }, 289 .probe = max9877_i2c_probe, 290 .remove = __devexit_p(max9877_i2c_remove), 291 .id_table = max9877_i2c_id, 292 }; 293 294 static int __init max9877_init(void) 295 { 296 return i2c_add_driver(&max9877_i2c_driver); 297 } 298 module_init(max9877_init); 299 300 static void __exit max9877_exit(void) 301 { 302 i2c_del_driver(&max9877_i2c_driver); 303 } 304 module_exit(max9877_exit); 305 306 MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); 307 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); 308 MODULE_LICENSE("GPL"); 309