0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/init.h>
0009 #include <linux/slab.h>
0010 #include <linux/mutex.h>
0011 #include <linux/module.h>
0012
0013 #include <sound/core.h>
0014 #include <sound/ak4531_codec.h>
0015 #include <sound/tlv.h>
0016
0017
0018
0019
0020
0021
0022
0023 static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531);
0024
0025
0026
0027
0028
0029 #if 0
0030
0031 static void snd_ak4531_dump(struct snd_ak4531 *ak4531)
0032 {
0033 int idx;
0034
0035 for (idx = 0; idx < 0x19; idx++)
0036 printk(KERN_DEBUG "ak4531 0x%x: 0x%x\n",
0037 idx, ak4531->regs[idx]);
0038 }
0039
0040 #endif
0041
0042
0043
0044
0045
0046 #define AK4531_SINGLE(xname, xindex, reg, shift, mask, invert) \
0047 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
0048 .info = snd_ak4531_info_single, \
0049 .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
0050 .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) }
0051 #define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
0052 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
0053 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
0054 .name = xname, .index = xindex, \
0055 .info = snd_ak4531_info_single, \
0056 .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
0057 .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \
0058 .tlv = { .p = (xtlv) } }
0059
0060 static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0061 {
0062 int mask = (kcontrol->private_value >> 24) & 0xff;
0063
0064 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
0065 uinfo->count = 1;
0066 uinfo->value.integer.min = 0;
0067 uinfo->value.integer.max = mask;
0068 return 0;
0069 }
0070
0071 static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0072 {
0073 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
0074 int reg = kcontrol->private_value & 0xff;
0075 int shift = (kcontrol->private_value >> 16) & 0x07;
0076 int mask = (kcontrol->private_value >> 24) & 0xff;
0077 int invert = (kcontrol->private_value >> 22) & 1;
0078 int val;
0079
0080 mutex_lock(&ak4531->reg_mutex);
0081 val = (ak4531->regs[reg] >> shift) & mask;
0082 mutex_unlock(&ak4531->reg_mutex);
0083 if (invert) {
0084 val = mask - val;
0085 }
0086 ucontrol->value.integer.value[0] = val;
0087 return 0;
0088 }
0089
0090 static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0091 {
0092 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
0093 int reg = kcontrol->private_value & 0xff;
0094 int shift = (kcontrol->private_value >> 16) & 0x07;
0095 int mask = (kcontrol->private_value >> 24) & 0xff;
0096 int invert = (kcontrol->private_value >> 22) & 1;
0097 int change;
0098 int val;
0099
0100 val = ucontrol->value.integer.value[0] & mask;
0101 if (invert) {
0102 val = mask - val;
0103 }
0104 val <<= shift;
0105 mutex_lock(&ak4531->reg_mutex);
0106 val = (ak4531->regs[reg] & ~(mask << shift)) | val;
0107 change = val != ak4531->regs[reg];
0108 ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
0109 mutex_unlock(&ak4531->reg_mutex);
0110 return change;
0111 }
0112
0113 #define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
0114 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
0115 .info = snd_ak4531_info_double, \
0116 .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
0117 .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) }
0118 #define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \
0119 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
0120 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
0121 .name = xname, .index = xindex, \
0122 .info = snd_ak4531_info_double, \
0123 .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
0124 .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \
0125 .tlv = { .p = (xtlv) } }
0126
0127 static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0128 {
0129 int mask = (kcontrol->private_value >> 24) & 0xff;
0130
0131 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
0132 uinfo->count = 2;
0133 uinfo->value.integer.min = 0;
0134 uinfo->value.integer.max = mask;
0135 return 0;
0136 }
0137
0138 static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0139 {
0140 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
0141 int left_reg = kcontrol->private_value & 0xff;
0142 int right_reg = (kcontrol->private_value >> 8) & 0xff;
0143 int left_shift = (kcontrol->private_value >> 16) & 0x07;
0144 int right_shift = (kcontrol->private_value >> 19) & 0x07;
0145 int mask = (kcontrol->private_value >> 24) & 0xff;
0146 int invert = (kcontrol->private_value >> 22) & 1;
0147 int left, right;
0148
0149 mutex_lock(&ak4531->reg_mutex);
0150 left = (ak4531->regs[left_reg] >> left_shift) & mask;
0151 right = (ak4531->regs[right_reg] >> right_shift) & mask;
0152 mutex_unlock(&ak4531->reg_mutex);
0153 if (invert) {
0154 left = mask - left;
0155 right = mask - right;
0156 }
0157 ucontrol->value.integer.value[0] = left;
0158 ucontrol->value.integer.value[1] = right;
0159 return 0;
0160 }
0161
0162 static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0163 {
0164 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
0165 int left_reg = kcontrol->private_value & 0xff;
0166 int right_reg = (kcontrol->private_value >> 8) & 0xff;
0167 int left_shift = (kcontrol->private_value >> 16) & 0x07;
0168 int right_shift = (kcontrol->private_value >> 19) & 0x07;
0169 int mask = (kcontrol->private_value >> 24) & 0xff;
0170 int invert = (kcontrol->private_value >> 22) & 1;
0171 int change;
0172 int left, right;
0173
0174 left = ucontrol->value.integer.value[0] & mask;
0175 right = ucontrol->value.integer.value[1] & mask;
0176 if (invert) {
0177 left = mask - left;
0178 right = mask - right;
0179 }
0180 left <<= left_shift;
0181 right <<= right_shift;
0182 mutex_lock(&ak4531->reg_mutex);
0183 if (left_reg == right_reg) {
0184 left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right;
0185 change = left != ak4531->regs[left_reg];
0186 ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
0187 } else {
0188 left = (ak4531->regs[left_reg] & ~(mask << left_shift)) | left;
0189 right = (ak4531->regs[right_reg] & ~(mask << right_shift)) | right;
0190 change = left != ak4531->regs[left_reg] || right != ak4531->regs[right_reg];
0191 ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
0192 ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right);
0193 }
0194 mutex_unlock(&ak4531->reg_mutex);
0195 return change;
0196 }
0197
0198 #define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
0199 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
0200 .info = snd_ak4531_info_input_sw, \
0201 .get = snd_ak4531_get_input_sw, .put = snd_ak4531_put_input_sw, \
0202 .private_value = reg1 | (reg2 << 8) | (left_shift << 16) | (right_shift << 24) }
0203
0204 static int snd_ak4531_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0205 {
0206 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0207 uinfo->count = 4;
0208 uinfo->value.integer.min = 0;
0209 uinfo->value.integer.max = 1;
0210 return 0;
0211 }
0212
0213 static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0214 {
0215 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
0216 int reg1 = kcontrol->private_value & 0xff;
0217 int reg2 = (kcontrol->private_value >> 8) & 0xff;
0218 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
0219 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
0220
0221 mutex_lock(&ak4531->reg_mutex);
0222 ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1;
0223 ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1;
0224 ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1;
0225 ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
0226 mutex_unlock(&ak4531->reg_mutex);
0227 return 0;
0228 }
0229
0230 static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0231 {
0232 struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
0233 int reg1 = kcontrol->private_value & 0xff;
0234 int reg2 = (kcontrol->private_value >> 8) & 0xff;
0235 int left_shift = (kcontrol->private_value >> 16) & 0x0f;
0236 int right_shift = (kcontrol->private_value >> 24) & 0x0f;
0237 int change;
0238 int val1, val2;
0239
0240 mutex_lock(&ak4531->reg_mutex);
0241 val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift));
0242 val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift));
0243 val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
0244 val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
0245 val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
0246 val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
0247 change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2];
0248 ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1);
0249 ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
0250 mutex_unlock(&ak4531->reg_mutex);
0251 return change;
0252 }
0253
0254 static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
0255 static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
0256 static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
0257
0258 static const struct snd_kcontrol_new snd_ak4531_controls[] = {
0259
0260 AK4531_DOUBLE_TLV("Master Playback Switch", 0,
0261 AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
0262 db_scale_master),
0263 AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1),
0264
0265 AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1,
0266 db_scale_mono),
0267 AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1),
0268
0269 AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1),
0270 AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1,
0271 db_scale_input),
0272 AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0),
0273 AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0),
0274
0275 AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1),
0276 AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1,
0277 db_scale_input),
0278 AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0),
0279 AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5),
0280
0281 AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1),
0282 AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1,
0283 db_scale_input),
0284 AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0),
0285 AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1),
0286
0287 AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1),
0288 AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1,
0289 db_scale_input),
0290 AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0),
0291 AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3),
0292
0293 AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1),
0294 AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1,
0295 db_scale_input),
0296 AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0),
0297 AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3),
0298
0299 AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1),
0300 AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input),
0301 AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0),
0302 AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0),
0303
0304 AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1),
0305 AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input),
0306 AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0),
0307 AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0),
0308
0309 AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input),
0310 AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1),
0311 AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0),
0312 AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0),
0313
0314 AK4531_DOUBLE("Mic Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 7, 7, 1, 0),
0315 AK4531_DOUBLE("Mono1 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 6, 6, 1, 0),
0316 AK4531_DOUBLE("Mono2 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 5, 5, 1, 0),
0317
0318 AK4531_SINGLE("AD Input Select", 0, AK4531_AD_IN, 0, 1, 0),
0319 AK4531_SINGLE("Mic Boost (+30dB)", 0, AK4531_MIC_GAIN, 0, 1, 0)
0320 };
0321
0322 static int snd_ak4531_free(struct snd_ak4531 *ak4531)
0323 {
0324 if (ak4531) {
0325 if (ak4531->private_free)
0326 ak4531->private_free(ak4531);
0327 kfree(ak4531);
0328 }
0329 return 0;
0330 }
0331
0332 static int snd_ak4531_dev_free(struct snd_device *device)
0333 {
0334 struct snd_ak4531 *ak4531 = device->device_data;
0335 return snd_ak4531_free(ak4531);
0336 }
0337
0338 static const u8 snd_ak4531_initial_map[0x19 + 1] = {
0339 0x9f,
0340 0x9f,
0341 0x9f,
0342 0x9f,
0343 0x9f,
0344 0x9f,
0345 0x9f,
0346 0x9f,
0347 0x9f,
0348 0x9f,
0349 0x9f,
0350 0x9f,
0351 0x9f,
0352 0x9f,
0353 0x9f,
0354 0x87,
0355 0x00,
0356 0x00,
0357 0x00,
0358 0x00,
0359 0x00,
0360 0x00,
0361 0x00,
0362 0x00,
0363 0x00,
0364 0x01
0365 };
0366
0367 int snd_ak4531_mixer(struct snd_card *card,
0368 struct snd_ak4531 *_ak4531,
0369 struct snd_ak4531 **rak4531)
0370 {
0371 unsigned int idx;
0372 int err;
0373 struct snd_ak4531 *ak4531;
0374 static const struct snd_device_ops ops = {
0375 .dev_free = snd_ak4531_dev_free,
0376 };
0377
0378 if (snd_BUG_ON(!card || !_ak4531))
0379 return -EINVAL;
0380 if (rak4531)
0381 *rak4531 = NULL;
0382 ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
0383 if (ak4531 == NULL)
0384 return -ENOMEM;
0385 *ak4531 = *_ak4531;
0386 mutex_init(&ak4531->reg_mutex);
0387 err = snd_component_add(card, "AK4531");
0388 if (err < 0) {
0389 snd_ak4531_free(ak4531);
0390 return err;
0391 }
0392 strcpy(card->mixername, "Asahi Kasei AK4531");
0393 ak4531->write(ak4531, AK4531_RESET, 0x03);
0394 udelay(100);
0395 ak4531->write(ak4531, AK4531_CLOCK, 0x00);
0396 for (idx = 0; idx <= 0x19; idx++) {
0397 if (idx == AK4531_RESET || idx == AK4531_CLOCK)
0398 continue;
0399 ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]);
0400 }
0401 for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
0402 err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531));
0403 if (err < 0) {
0404 snd_ak4531_free(ak4531);
0405 return err;
0406 }
0407 }
0408 snd_ak4531_proc_init(card, ak4531);
0409 err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops);
0410 if (err < 0) {
0411 snd_ak4531_free(ak4531);
0412 return err;
0413 }
0414
0415 #if 0
0416 snd_ak4531_dump(ak4531);
0417 #endif
0418 if (rak4531)
0419 *rak4531 = ak4531;
0420 return 0;
0421 }
0422
0423
0424
0425
0426 #ifdef CONFIG_PM
0427 void snd_ak4531_suspend(struct snd_ak4531 *ak4531)
0428 {
0429
0430 ak4531->write(ak4531, AK4531_LMASTER, 0x9f);
0431 ak4531->write(ak4531, AK4531_RMASTER, 0x9f);
0432
0433 ak4531->write(ak4531, AK4531_RESET, 0x01);
0434 }
0435
0436 void snd_ak4531_resume(struct snd_ak4531 *ak4531)
0437 {
0438 int idx;
0439
0440
0441 ak4531->write(ak4531, AK4531_RESET, 0x03);
0442 udelay(100);
0443 ak4531->write(ak4531, AK4531_CLOCK, 0x00);
0444
0445 for (idx = 0; idx <= 0x19; idx++) {
0446 if (idx == AK4531_RESET || idx == AK4531_CLOCK)
0447 continue;
0448 ak4531->write(ak4531, idx, ak4531->regs[idx]);
0449 }
0450 }
0451 #endif
0452
0453
0454
0455
0456
0457 static void snd_ak4531_proc_read(struct snd_info_entry *entry,
0458 struct snd_info_buffer *buffer)
0459 {
0460 struct snd_ak4531 *ak4531 = entry->private_data;
0461
0462 snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
0463 snd_iprintf(buffer, "Recording source : %s\n"
0464 "MIC gain : %s\n",
0465 ak4531->regs[AK4531_AD_IN] & 1 ? "external" : "mixer",
0466 ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
0467 }
0468
0469 static void
0470 snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
0471 {
0472 snd_card_ro_proc_new(card, "ak4531", ak4531, snd_ak4531_proc_read);
0473 }