diff options
Diffstat (limited to 'sound/i2c')
-rw-r--r-- | sound/i2c/Makefile | 1 | ||||
-rw-r--r-- | sound/i2c/other/Makefile | 4 | ||||
-rw-r--r-- | sound/i2c/other/ak4114.c | 29 | ||||
-rw-r--r-- | sound/i2c/other/ak4117.c | 2 | ||||
-rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 110 | ||||
-rw-r--r-- | sound/i2c/other/pt2258.c | 233 |
6 files changed, 344 insertions, 35 deletions
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile index 816a2e7c88ca..45902d48c89c 100644 --- a/sound/i2c/Makefile +++ b/sound/i2c/Makefile | |||
@@ -16,3 +16,4 @@ obj-$(CONFIG_SND) += other/ | |||
16 | # Toplevel Module Dependency | 16 | # Toplevel Module Dependency |
17 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o | 17 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o |
18 | obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o | 18 | obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o |
19 | obj-$(CONFIG_SND_ICE1724) += snd-i2c.o | ||
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile index 2fe023ef00a7..77a8a7c75dd9 100644 --- a/sound/i2c/other/Makefile +++ b/sound/i2c/other/Makefile | |||
@@ -6,11 +6,11 @@ | |||
6 | snd-ak4114-objs := ak4114.o | 6 | snd-ak4114-objs := ak4114.o |
7 | snd-ak4117-objs := ak4117.o | 7 | snd-ak4117-objs := ak4117.o |
8 | snd-ak4xxx-adda-objs := ak4xxx-adda.o | 8 | snd-ak4xxx-adda-objs := ak4xxx-adda.o |
9 | snd-pt2258-objs := pt2258.o | ||
9 | snd-tea575x-tuner-objs := tea575x-tuner.o | 10 | snd-tea575x-tuner-objs := tea575x-tuner.o |
10 | 11 | ||
11 | # Module Dependency | 12 | # Module Dependency |
12 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o | 13 | obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o |
13 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o | 14 | obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o |
14 | obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o | 15 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o |
15 | obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o | ||
16 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o | 16 | obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o |
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index d2f2c5078e65..adbfd5884d06 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -42,8 +42,8 @@ static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char va | |||
42 | ak4114->write(ak4114->private_data, reg, val); | 42 | ak4114->write(ak4114->private_data, reg, val); |
43 | if (reg <= AK4114_REG_INT1_MASK) | 43 | if (reg <= AK4114_REG_INT1_MASK) |
44 | ak4114->regmap[reg] = val; | 44 | ak4114->regmap[reg] = val; |
45 | else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4) | 45 | else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) |
46 | ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val; | 46 | ak4114->txcsb[reg-AK4114_REG_TXCSB0] = val; |
47 | } | 47 | } |
48 | 48 | ||
49 | static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg) | 49 | static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg) |
@@ -66,10 +66,8 @@ static void snd_ak4114_free(struct ak4114 *chip) | |||
66 | { | 66 | { |
67 | chip->init = 1; /* don't schedule new work */ | 67 | chip->init = 1; /* don't schedule new work */ |
68 | mb(); | 68 | mb(); |
69 | if (chip->workqueue != NULL) { | 69 | cancel_delayed_work(&chip->work); |
70 | flush_workqueue(chip->workqueue); | 70 | flush_scheduled_work(); |
71 | destroy_workqueue(chip->workqueue); | ||
72 | } | ||
73 | kfree(chip); | 71 | kfree(chip); |
74 | } | 72 | } |
75 | 73 | ||
@@ -82,7 +80,7 @@ static int snd_ak4114_dev_free(struct snd_device *device) | |||
82 | 80 | ||
83 | int snd_ak4114_create(struct snd_card *card, | 81 | int snd_ak4114_create(struct snd_card *card, |
84 | ak4114_read_t *read, ak4114_write_t *write, | 82 | ak4114_read_t *read, ak4114_write_t *write, |
85 | unsigned char pgm[7], unsigned char txcsb[5], | 83 | const unsigned char pgm[7], const unsigned char txcsb[5], |
86 | void *private_data, struct ak4114 **r_ak4114) | 84 | void *private_data, struct ak4114 **r_ak4114) |
87 | { | 85 | { |
88 | struct ak4114 *chip; | 86 | struct ak4114 *chip; |
@@ -100,18 +98,13 @@ int snd_ak4114_create(struct snd_card *card, | |||
100 | chip->read = read; | 98 | chip->read = read; |
101 | chip->write = write; | 99 | chip->write = write; |
102 | chip->private_data = private_data; | 100 | chip->private_data = private_data; |
101 | INIT_DELAYED_WORK(&chip->work, ak4114_stats); | ||
103 | 102 | ||
104 | for (reg = 0; reg < 7; reg++) | 103 | for (reg = 0; reg < 7; reg++) |
105 | chip->regmap[reg] = pgm[reg]; | 104 | chip->regmap[reg] = pgm[reg]; |
106 | for (reg = 0; reg < 5; reg++) | 105 | for (reg = 0; reg < 5; reg++) |
107 | chip->txcsb[reg] = txcsb[reg]; | 106 | chip->txcsb[reg] = txcsb[reg]; |
108 | 107 | ||
109 | chip->workqueue = create_workqueue("snd-ak4114"); | ||
110 | if (chip->workqueue == NULL) { | ||
111 | kfree(chip); | ||
112 | return -ENOMEM; | ||
113 | } | ||
114 | |||
115 | snd_ak4114_reinit(chip); | 108 | snd_ak4114_reinit(chip); |
116 | 109 | ||
117 | chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); | 110 | chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); |
@@ -134,7 +127,8 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char | |||
134 | if (reg <= AK4114_REG_INT1_MASK) | 127 | if (reg <= AK4114_REG_INT1_MASK) |
135 | reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); | 128 | reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); |
136 | else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) | 129 | else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) |
137 | reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val); | 130 | reg_write(chip, reg, |
131 | (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val); | ||
138 | } | 132 | } |
139 | 133 | ||
140 | void snd_ak4114_reinit(struct ak4114 *chip) | 134 | void snd_ak4114_reinit(struct ak4114 *chip) |
@@ -143,7 +137,7 @@ void snd_ak4114_reinit(struct ak4114 *chip) | |||
143 | 137 | ||
144 | chip->init = 1; | 138 | chip->init = 1; |
145 | mb(); | 139 | mb(); |
146 | flush_workqueue(chip->workqueue); | 140 | flush_scheduled_work(); |
147 | /* bring the chip to reset state and powerdown state */ | 141 | /* bring the chip to reset state and powerdown state */ |
148 | reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); | 142 | reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); |
149 | udelay(200); | 143 | udelay(200); |
@@ -158,8 +152,7 @@ void snd_ak4114_reinit(struct ak4114 *chip) | |||
158 | reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); | 152 | reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); |
159 | /* bring up statistics / event queing */ | 153 | /* bring up statistics / event queing */ |
160 | chip->init = 0; | 154 | chip->init = 0; |
161 | INIT_DELAYED_WORK(&chip->work, ak4114_stats); | 155 | schedule_delayed_work(&chip->work, HZ / 10); |
162 | queue_delayed_work(chip->workqueue, &chip->work, HZ / 10); | ||
163 | } | 156 | } |
164 | 157 | ||
165 | static unsigned int external_rate(unsigned char rcs1) | 158 | static unsigned int external_rate(unsigned char rcs1) |
@@ -568,7 +561,7 @@ static void ak4114_stats(struct work_struct *work) | |||
568 | if (chip->init) | 561 | if (chip->init) |
569 | return; | 562 | return; |
570 | snd_ak4114_check_rate_and_errors(chip, 0); | 563 | snd_ak4114_check_rate_and_errors(chip, 0); |
571 | queue_delayed_work(chip->workqueue, &chip->work, HZ / 10); | 564 | schedule_delayed_work(&chip->work, HZ / 10); |
572 | } | 565 | } |
573 | 566 | ||
574 | EXPORT_SYMBOL(snd_ak4114_create); | 567 | EXPORT_SYMBOL(snd_ak4114_create); |
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 4e45952dd95a..c022f29da2f7 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c | |||
@@ -74,7 +74,7 @@ static int snd_ak4117_dev_free(struct snd_device *device) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write, | 76 | int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write, |
77 | unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117) | 77 | const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117) |
78 | { | 78 | { |
79 | struct ak4117 *chip; | 79 | struct ak4117 *chip; |
80 | int err = 0; | 80 | int err = 0; |
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 5da49e2eb350..8805110017a7 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -140,7 +140,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset); | |||
140 | * Used for AK4524 input/ouput attenuation, AK4528, and | 140 | * Used for AK4524 input/ouput attenuation, AK4528, and |
141 | * AK5365 input attenuation | 141 | * AK5365 input attenuation |
142 | */ | 142 | */ |
143 | static unsigned char vol_cvt_datt[128] = { | 143 | static const unsigned char vol_cvt_datt[128] = { |
144 | 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, | 144 | 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, |
145 | 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, | 145 | 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, |
146 | 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, | 146 | 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, |
@@ -162,17 +162,17 @@ static unsigned char vol_cvt_datt[128] = { | |||
162 | /* | 162 | /* |
163 | * dB tables | 163 | * dB tables |
164 | */ | 164 | */ |
165 | static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); | 165 | static const DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); |
166 | static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); | 166 | static const DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); |
167 | static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); | 167 | static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); |
168 | static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); | 168 | static const DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * initialize all the ak4xxx chips | 171 | * initialize all the ak4xxx chips |
172 | */ | 172 | */ |
173 | void snd_akm4xxx_init(struct snd_akm4xxx *ak) | 173 | void snd_akm4xxx_init(struct snd_akm4xxx *ak) |
174 | { | 174 | { |
175 | static unsigned char inits_ak4524[] = { | 175 | static const unsigned char inits_ak4524[] = { |
176 | 0x00, 0x07, /* 0: all power up */ | 176 | 0x00, 0x07, /* 0: all power up */ |
177 | 0x01, 0x00, /* 1: ADC/DAC reset */ | 177 | 0x01, 0x00, /* 1: ADC/DAC reset */ |
178 | 0x02, 0x60, /* 2: 24bit I2S */ | 178 | 0x02, 0x60, /* 2: 24bit I2S */ |
@@ -184,7 +184,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
184 | 0x07, 0x00, /* 7: DAC right muted */ | 184 | 0x07, 0x00, /* 7: DAC right muted */ |
185 | 0xff, 0xff | 185 | 0xff, 0xff |
186 | }; | 186 | }; |
187 | static unsigned char inits_ak4528[] = { | 187 | static const unsigned char inits_ak4528[] = { |
188 | 0x00, 0x07, /* 0: all power up */ | 188 | 0x00, 0x07, /* 0: all power up */ |
189 | 0x01, 0x00, /* 1: ADC/DAC reset */ | 189 | 0x01, 0x00, /* 1: ADC/DAC reset */ |
190 | 0x02, 0x60, /* 2: 24bit I2S */ | 190 | 0x02, 0x60, /* 2: 24bit I2S */ |
@@ -194,7 +194,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
194 | 0x05, 0x00, /* 5: ADC right muted */ | 194 | 0x05, 0x00, /* 5: ADC right muted */ |
195 | 0xff, 0xff | 195 | 0xff, 0xff |
196 | }; | 196 | }; |
197 | static unsigned char inits_ak4529[] = { | 197 | static const unsigned char inits_ak4529[] = { |
198 | 0x09, 0x01, /* 9: ATS=0, RSTN=1 */ | 198 | 0x09, 0x01, /* 9: ATS=0, RSTN=1 */ |
199 | 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */ | 199 | 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */ |
200 | 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */ | 200 | 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */ |
@@ -210,7 +210,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
210 | 0x08, 0x55, /* 8: deemphasis all off */ | 210 | 0x08, 0x55, /* 8: deemphasis all off */ |
211 | 0xff, 0xff | 211 | 0xff, 0xff |
212 | }; | 212 | }; |
213 | static unsigned char inits_ak4355[] = { | 213 | static const unsigned char inits_ak4355[] = { |
214 | 0x01, 0x02, /* 1: reset and soft-mute */ | 214 | 0x01, 0x02, /* 1: reset and soft-mute */ |
215 | 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, | 215 | 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, |
216 | * disable DZF, sharp roll-off, RSTN#=0 */ | 216 | * disable DZF, sharp roll-off, RSTN#=0 */ |
@@ -227,7 +227,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
227 | 0x01, 0x01, /* 1: un-reset, unmute */ | 227 | 0x01, 0x01, /* 1: un-reset, unmute */ |
228 | 0xff, 0xff | 228 | 0xff, 0xff |
229 | }; | 229 | }; |
230 | static unsigned char inits_ak4358[] = { | 230 | static const unsigned char inits_ak4358[] = { |
231 | 0x01, 0x02, /* 1: reset and soft-mute */ | 231 | 0x01, 0x02, /* 1: reset and soft-mute */ |
232 | 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, | 232 | 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, |
233 | * disable DZF, sharp roll-off, RSTN#=0 */ | 233 | * disable DZF, sharp roll-off, RSTN#=0 */ |
@@ -246,7 +246,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
246 | 0x01, 0x01, /* 1: un-reset, unmute */ | 246 | 0x01, 0x01, /* 1: un-reset, unmute */ |
247 | 0xff, 0xff | 247 | 0xff, 0xff |
248 | }; | 248 | }; |
249 | static unsigned char inits_ak4381[] = { | 249 | static const unsigned char inits_ak4381[] = { |
250 | 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ | 250 | 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ |
251 | 0x01, 0x02, /* 1: de-emphasis off, normal speed, | 251 | 0x01, 0x02, /* 1: de-emphasis off, normal speed, |
252 | * sharp roll-off, DZF off */ | 252 | * sharp roll-off, DZF off */ |
@@ -259,7 +259,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) | |||
259 | }; | 259 | }; |
260 | 260 | ||
261 | int chip, num_chips; | 261 | int chip, num_chips; |
262 | unsigned char *ptr, reg, data, *inits; | 262 | const unsigned char *ptr, *inits; |
263 | unsigned char reg, data; | ||
263 | 264 | ||
264 | memset(ak->images, 0, sizeof(ak->images)); | 265 | memset(ak->images, 0, sizeof(ak->images)); |
265 | memset(ak->volumes, 0, sizeof(ak->volumes)); | 266 | memset(ak->volumes, 0, sizeof(ak->volumes)); |
@@ -513,6 +514,66 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol, | |||
513 | return change; | 514 | return change; |
514 | } | 515 | } |
515 | 516 | ||
517 | #define AK5365_NUM_INPUTS 5 | ||
518 | |||
519 | static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol, | ||
520 | struct snd_ctl_elem_info *uinfo) | ||
521 | { | ||
522 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
523 | int mixer_ch = AK_GET_SHIFT(kcontrol->private_value); | ||
524 | const char **input_names; | ||
525 | int num_names, idx; | ||
526 | |||
527 | input_names = ak->adc_info[mixer_ch].input_names; | ||
528 | |||
529 | num_names = 0; | ||
530 | while (num_names < AK5365_NUM_INPUTS && input_names[num_names]) | ||
531 | ++num_names; | ||
532 | |||
533 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
534 | uinfo->count = 1; | ||
535 | uinfo->value.enumerated.items = num_names; | ||
536 | idx = uinfo->value.enumerated.item; | ||
537 | if (idx >= num_names) | ||
538 | return -EINVAL; | ||
539 | strncpy(uinfo->value.enumerated.name, input_names[idx], | ||
540 | sizeof(uinfo->value.enumerated.name)); | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol, | ||
545 | struct snd_ctl_elem_value *ucontrol) | ||
546 | { | ||
547 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
548 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
549 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
550 | int mask = AK_GET_MASK(kcontrol->private_value); | ||
551 | unsigned char val; | ||
552 | |||
553 | val = snd_akm4xxx_get(ak, chip, addr) & mask; | ||
554 | ucontrol->value.enumerated.item[0] = val; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol, | ||
559 | struct snd_ctl_elem_value *ucontrol) | ||
560 | { | ||
561 | struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); | ||
562 | int chip = AK_GET_CHIP(kcontrol->private_value); | ||
563 | int addr = AK_GET_ADDR(kcontrol->private_value); | ||
564 | int mask = AK_GET_MASK(kcontrol->private_value); | ||
565 | unsigned char oval, val; | ||
566 | |||
567 | oval = snd_akm4xxx_get(ak, chip, addr); | ||
568 | val = oval & ~mask; | ||
569 | val |= ucontrol->value.enumerated.item[0] & mask; | ||
570 | if (val != oval) { | ||
571 | snd_akm4xxx_write(ak, chip, addr, val); | ||
572 | return 1; | ||
573 | } | ||
574 | return 0; | ||
575 | } | ||
576 | |||
516 | /* | 577 | /* |
517 | * build AK4xxx controls | 578 | * build AK4xxx controls |
518 | */ | 579 | */ |
@@ -647,9 +708,10 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
647 | 708 | ||
648 | if (ak->type == SND_AK5365 && (idx % 2) == 0) { | 709 | if (ak->type == SND_AK5365 && (idx % 2) == 0) { |
649 | if (! ak->adc_info || | 710 | if (! ak->adc_info || |
650 | ! ak->adc_info[mixer_ch].switch_name) | 711 | ! ak->adc_info[mixer_ch].switch_name) { |
651 | knew.name = "Capture Switch"; | 712 | knew.name = "Capture Switch"; |
652 | else | 713 | knew.index = mixer_ch + ak->idx_offset * 2; |
714 | } else | ||
653 | knew.name = ak->adc_info[mixer_ch].switch_name; | 715 | knew.name = ak->adc_info[mixer_ch].switch_name; |
654 | knew.info = ak4xxx_switch_info; | 716 | knew.info = ak4xxx_switch_info; |
655 | knew.get = ak4xxx_switch_get; | 717 | knew.get = ak4xxx_switch_get; |
@@ -662,6 +724,26 @@ static int build_adc_controls(struct snd_akm4xxx *ak) | |||
662 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | 724 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); |
663 | if (err < 0) | 725 | if (err < 0) |
664 | return err; | 726 | return err; |
727 | |||
728 | memset(&knew, 0, sizeof(knew)); | ||
729 | knew.name = ak->adc_info[mixer_ch].selector_name; | ||
730 | if (!knew.name) { | ||
731 | knew.name = "Capture Channel"; | ||
732 | knew.index = mixer_ch + ak->idx_offset * 2; | ||
733 | } | ||
734 | |||
735 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
736 | knew.info = ak4xxx_capture_source_info; | ||
737 | knew.get = ak4xxx_capture_source_get; | ||
738 | knew.put = ak4xxx_capture_source_put; | ||
739 | knew.access = 0; | ||
740 | /* input selector control: reg. 1, bits 0-2. | ||
741 | * mis-use 'shift' to pass mixer_ch */ | ||
742 | knew.private_value | ||
743 | = AK_COMPOSE(idx/2, 1, mixer_ch, 0x07); | ||
744 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
745 | if (err < 0) | ||
746 | return err; | ||
665 | } | 747 | } |
666 | 748 | ||
667 | idx += num_stereo; | 749 | idx += num_stereo; |
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c new file mode 100644 index 000000000000..e91cc3b44de5 --- /dev/null +++ b/sound/i2c/other/pt2258.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* | ||
2 | * ALSA Driver for the PT2258 volume controller. | ||
3 | * | ||
4 | * Copyright (c) 2006 Jochen Voss <voss@seehuhn.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <sound/driver.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/control.h> | ||
25 | #include <sound/tlv.h> | ||
26 | #include <sound/i2c.h> | ||
27 | #include <sound/pt2258.h> | ||
28 | |||
29 | MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>"); | ||
30 | MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | #define PT2258_CMD_RESET 0xc0 | ||
34 | #define PT2258_CMD_UNMUTE 0xf8 | ||
35 | #define PT2258_CMD_MUTE 0xf9 | ||
36 | |||
37 | static const unsigned char pt2258_channel_code[12] = { | ||
38 | 0x80, 0x90, /* channel 1: -10dB, -1dB */ | ||
39 | 0x40, 0x50, /* channel 2: -10dB, -1dB */ | ||
40 | 0x00, 0x10, /* channel 3: -10dB, -1dB */ | ||
41 | 0x20, 0x30, /* channel 4: -10dB, -1dB */ | ||
42 | 0x60, 0x70, /* channel 5: -10dB, -1dB */ | ||
43 | 0xa0, 0xb0 /* channel 6: -10dB, -1dB */ | ||
44 | }; | ||
45 | |||
46 | int snd_pt2258_reset(struct snd_pt2258 *pt) | ||
47 | { | ||
48 | unsigned char bytes[2]; | ||
49 | int i; | ||
50 | |||
51 | /* reset chip */ | ||
52 | bytes[0] = PT2258_CMD_RESET; | ||
53 | snd_i2c_lock(pt->i2c_bus); | ||
54 | if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1) | ||
55 | goto __error; | ||
56 | snd_i2c_unlock(pt->i2c_bus); | ||
57 | |||
58 | /* mute all channels */ | ||
59 | pt->mute = 1; | ||
60 | bytes[0] = PT2258_CMD_MUTE; | ||
61 | snd_i2c_lock(pt->i2c_bus); | ||
62 | if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1) | ||
63 | goto __error; | ||
64 | snd_i2c_unlock(pt->i2c_bus); | ||
65 | |||
66 | /* set all channels to 0dB */ | ||
67 | for (i = 0; i < 6; ++i) | ||
68 | pt->volume[i] = 0; | ||
69 | bytes[0] = 0xd0; | ||
70 | bytes[1] = 0xe0; | ||
71 | snd_i2c_lock(pt->i2c_bus); | ||
72 | if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2) | ||
73 | goto __error; | ||
74 | snd_i2c_unlock(pt->i2c_bus); | ||
75 | |||
76 | return 0; | ||
77 | |||
78 | __error: | ||
79 | snd_i2c_unlock(pt->i2c_bus); | ||
80 | snd_printk(KERN_ERR "PT2258 reset failed\n"); | ||
81 | return -EIO; | ||
82 | } | ||
83 | |||
84 | static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol, | ||
85 | struct snd_ctl_elem_info *uinfo) | ||
86 | { | ||
87 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
88 | uinfo->count = 2; | ||
89 | uinfo->value.integer.min = 0; | ||
90 | uinfo->value.integer.max = 79; | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol, | ||
95 | struct snd_ctl_elem_value *ucontrol) | ||
96 | { | ||
97 | struct snd_pt2258 *pt = kcontrol->private_data; | ||
98 | int base = kcontrol->private_value; | ||
99 | |||
100 | /* chip does not support register reads */ | ||
101 | ucontrol->value.integer.value[0] = 79 - pt->volume[base]; | ||
102 | ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1]; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol, | ||
107 | struct snd_ctl_elem_value *ucontrol) | ||
108 | { | ||
109 | struct snd_pt2258 *pt = kcontrol->private_data; | ||
110 | int base = kcontrol->private_value; | ||
111 | unsigned char bytes[2]; | ||
112 | int val0, val1; | ||
113 | |||
114 | val0 = 79 - ucontrol->value.integer.value[0]; | ||
115 | val1 = 79 - ucontrol->value.integer.value[1]; | ||
116 | if (val0 == pt->volume[base] && val1 == pt->volume[base + 1]) | ||
117 | return 0; | ||
118 | |||
119 | pt->volume[base] = val0; | ||
120 | bytes[0] = pt2258_channel_code[2 * base] | (val0 / 10); | ||
121 | bytes[1] = pt2258_channel_code[2 * base + 1] | (val0 % 10); | ||
122 | snd_i2c_lock(pt->i2c_bus); | ||
123 | if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2) | ||
124 | goto __error; | ||
125 | snd_i2c_unlock(pt->i2c_bus); | ||
126 | |||
127 | pt->volume[base + 1] = val1; | ||
128 | bytes[0] = pt2258_channel_code[2 * base + 2] | (val1 / 10); | ||
129 | bytes[1] = pt2258_channel_code[2 * base + 3] | (val1 % 10); | ||
130 | snd_i2c_lock(pt->i2c_bus); | ||
131 | if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2) | ||
132 | goto __error; | ||
133 | snd_i2c_unlock(pt->i2c_bus); | ||
134 | |||
135 | return 1; | ||
136 | |||
137 | __error: | ||
138 | snd_i2c_unlock(pt->i2c_bus); | ||
139 | snd_printk(KERN_ERR "PT2258 access failed\n"); | ||
140 | return -EIO; | ||
141 | } | ||
142 | |||
143 | static int pt2258_switch_info(struct snd_kcontrol *kcontrol, | ||
144 | struct snd_ctl_elem_info *uinfo) | ||
145 | { | ||
146 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
147 | uinfo->count = 1; | ||
148 | uinfo->value.integer.min = 0; | ||
149 | uinfo->value.integer.max = 1; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int pt2258_switch_get(struct snd_kcontrol *kcontrol, | ||
154 | struct snd_ctl_elem_value *ucontrol) | ||
155 | { | ||
156 | struct snd_pt2258 *pt = kcontrol->private_data; | ||
157 | |||
158 | ucontrol->value.integer.value[0] = !pt->mute; | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int pt2258_switch_put(struct snd_kcontrol *kcontrol, | ||
163 | struct snd_ctl_elem_value *ucontrol) | ||
164 | { | ||
165 | struct snd_pt2258 *pt = kcontrol->private_data; | ||
166 | unsigned char bytes[2]; | ||
167 | int val; | ||
168 | |||
169 | val = !ucontrol->value.integer.value[0]; | ||
170 | if (pt->mute == val) | ||
171 | return 0; | ||
172 | |||
173 | pt->mute = val; | ||
174 | bytes[0] = val ? PT2258_CMD_MUTE : PT2258_CMD_UNMUTE; | ||
175 | snd_i2c_lock(pt->i2c_bus); | ||
176 | if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1) | ||
177 | goto __error; | ||
178 | snd_i2c_unlock(pt->i2c_bus); | ||
179 | |||
180 | return 1; | ||
181 | |||
182 | __error: | ||
183 | snd_i2c_unlock(pt->i2c_bus); | ||
184 | snd_printk(KERN_ERR "PT2258 access failed 2\n"); | ||
185 | return -EIO; | ||
186 | } | ||
187 | |||
188 | static const DECLARE_TLV_DB_SCALE(pt2258_db_scale, -7900, 100, 0); | ||
189 | |||
190 | int snd_pt2258_build_controls(struct snd_pt2258 *pt) | ||
191 | { | ||
192 | struct snd_kcontrol_new knew; | ||
193 | char *names[3] = { | ||
194 | "Mic Loopback Playback Volume", | ||
195 | "Line Loopback Playback Volume", | ||
196 | "CD Loopback Playback Volume" | ||
197 | }; | ||
198 | int i, err; | ||
199 | |||
200 | for (i = 0; i < 3; ++i) { | ||
201 | memset(&knew, 0, sizeof(knew)); | ||
202 | knew.name = names[i]; | ||
203 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
204 | knew.count = 1; | ||
205 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
206 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | ||
207 | knew.private_value = 2 * i; | ||
208 | knew.info = pt2258_stereo_volume_info; | ||
209 | knew.get = pt2258_stereo_volume_get; | ||
210 | knew.put = pt2258_stereo_volume_put; | ||
211 | knew.tlv.p = pt2258_db_scale; | ||
212 | |||
213 | err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt)); | ||
214 | if (err < 0) | ||
215 | return err; | ||
216 | } | ||
217 | |||
218 | memset(&knew, 0, sizeof(knew)); | ||
219 | knew.name = "Loopback Switch"; | ||
220 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
221 | knew.info = pt2258_switch_info; | ||
222 | knew.get = pt2258_switch_get; | ||
223 | knew.put = pt2258_switch_put; | ||
224 | knew.access = 0; | ||
225 | err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt)); | ||
226 | if (err < 0) | ||
227 | return err; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | EXPORT_SYMBOL(snd_pt2258_reset); | ||
233 | EXPORT_SYMBOL(snd_pt2258_build_controls); | ||