Changeset 1912b45 in mainline for uspace/drv/audio/sb16/mixer.c
- Timestamp:
- 2013-04-10T20:52:26Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5b77efc
- Parents:
- 8a7d78cc
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/audio/sb16/mixer.c
r8a7d78cc r1912b45 45 45 } channel_t; 46 46 47 typedef struct volume_item {48 const char *description;49 uint8_t channels;50 const channel_t *channel_table;51 } volume_item_t;52 53 47 /* CT1335 channels */ 54 48 static const channel_t channels_table_ct1335[] = { 55 { "M ono", 0x02, 1, 8, false }, /* Master, Mono, 3bit volume level */56 { "M ono", 0x06, 1, 8, false }, /* Midi, Mono, 3bit volume level */57 { " Mono", 0x08, 1, 8, false }, /* CD, Mono, 3bit volume level */58 { " Mono", 0x0a, 1, 4, false }, /* Voice, Mono, 2bit volume level */49 { "Master", 0x02, 1, 8, false }, /* Master, Mono, 3bit volume level */ 50 { "Midi", 0x06, 1, 8, false }, /* Midi, Mono, 3bit volume level */ 51 { "CD", 0x08, 1, 8, false }, /* CD, Mono, 3bit volume level */ 52 { "Voice", 0x0a, 1, 4, false }, /* Voice, Mono, 2bit volume level */ 59 53 }; 60 54 61 55 /* CT1345 channels */ 62 56 static const channel_t channels_table_ct1345[] = { 63 { " Left", 0x22, 5, 8, true }, /* Master, Left, 3bit volume level */64 { " Right", 0x22, 1, 8, true }, /* Master, Right, 3bit volume level */65 { " Left", 0x26, 5, 8, true }, /* Midi, Left, 3bit volume level */66 { " Right", 0x26, 1, 8, true }, /* Midi, Right, 3bit volume level */67 { " Left", 0x28, 5, 8, true }, /* CD, Left, 3bit volume level */68 { " Right", 0x28, 1, 8, true }, /* CD, Right, 3bit volume level */69 { "L eft", 0x2e, 5, 8, true }, /* Line, Left, 3bit volume level */70 { " Right", 0x2e, 1, 8, true }, /* Line, Right, 3bit volume level */71 { " Left", 0x04, 5, 8, true }, /* Voice, Left, 3bit volume level */72 { " Right", 0x04, 1, 8, true }, /* Voice, Right, 3bit volume level */73 { "M ono", 0x0a, 1, 4, false }, /* Mic, Mono, 2bit volume level */57 { "Master Left", 0x22, 5, 8, true }, /* Master, Left, 3bit volume level */ 58 { "Master Right", 0x22, 1, 8, true }, /* Master, Right, 3bit volume level */ 59 { "MIDI Left", 0x26, 5, 8, true }, /* Midi, Left, 3bit volume level */ 60 { "MIDI Right", 0x26, 1, 8, true }, /* Midi, Right, 3bit volume level */ 61 { "CD Left", 0x28, 5, 8, true }, /* CD, Left, 3bit volume level */ 62 { "CD Right", 0x28, 1, 8, true }, /* CD, Right, 3bit volume level */ 63 { "Line In Left", 0x2e, 5, 8, true }, /* Line, Left, 3bit volume level */ 64 { "Line In Right", 0x2e, 1, 8, true }, /* Line, Right, 3bit volume level */ 65 { "Voice Left", 0x04, 5, 8, true }, /* Voice, Left, 3bit volume level */ 66 { "Voice Right", 0x04, 1, 8, true }, /* Voice, Right, 3bit volume level */ 67 { "Mic", 0x0a, 1, 4, false }, /* Mic, Mono, 2bit volume level */ 74 68 }; 75 69 76 70 /* CT1745 channels */ 77 71 static const channel_t channels_table_ct1745[] = { 78 { "Left", 0x30, 3, 32, false }, /* Master, Left, 5bit volume level */ 79 { "Right", 0x31, 3, 32, false }, /* Master, Right, 5bit volume level */ 80 { "Left", 0x32, 3, 32, false }, /* Voice, Left, 5bit volume level */ 81 { "Right", 0x33, 3, 32, false }, /* Voice, Right, 5bit volume level */ 82 { "Left", 0x34, 3, 32, false }, /* MIDI, Left, 5bit volume level */ 83 { "Right", 0x35, 3, 32, false }, /* MIDI, Right, 5bit volume level */ 84 { "Left", 0x36, 3, 32, false }, /* CD, Left, 5bit volume level */ 85 { "Right", 0x37, 3, 32, false }, /* CD, Right, 5bit volume level */ 86 { "Left", 0x38, 3, 32, false }, /* Line, Left, 5bit volume level */ 87 { "Right", 0x39, 3, 32, false }, /* Line, Right, 5bit volume level */ 88 { "Mono", 0x3a, 3, 32, false }, /* Mic, Mono, 5bit volume level */ 89 { "Mono", 0x3b, 6, 4, false }, /* PC speaker, Mono, 2bit level */ 90 { "Left", 0x3f, 6, 4, false }, /* Input Gain, Left, 2bit level */ 91 { "Right", 0x40, 6, 4, false }, /* Input Gain, Right, 2bit level */ 92 { "Left", 0x41, 6, 4, false }, /* Output Gain, Left, 2bit level */ 93 { "Right", 0x42, 6, 4, false }, /* Output Gain, Right, 2bit level */ 94 { "Left", 0x44, 4, 16, false }, /* Treble, Left, 4bit volume level */ 95 { "Right", 0x45, 4, 16, false }, /* Treble, Right, 4bit volume level */ 96 { "Left", 0x46, 4, 16, false }, /* Bass, Left, 4bit volume level */ 97 { "Right", 0x47, 4, 16, false }, /* Bass, Right, 4bit volume level */ 98 }; 99 100 static const volume_item_t volume_ct1335[] = { 101 { "Master", 1, &channels_table_ct1335[0] }, 102 { "MIDI", 1, &channels_table_ct1335[1] }, 103 { "CD", 1, &channels_table_ct1335[2] }, 104 { "Voice", 1, &channels_table_ct1335[3] }, 105 }; 106 107 static const volume_item_t volume_ct1345[] = { 108 { "Master", 2, &channels_table_ct1345[0] }, 109 { "Voice", 2, &channels_table_ct1345[8] }, 110 { "Mic", 1, &channels_table_ct1345[10] }, 111 { "MIDI", 2, &channels_table_ct1345[2] }, 112 { "CD", 2, &channels_table_ct1345[4] }, 113 { "Line", 2, &channels_table_ct1345[6] }, 114 }; 115 116 static const volume_item_t volume_ct1745[] = { 117 { "Master", 2, &channels_table_ct1745[0] }, 118 { "Voice", 2, &channels_table_ct1745[2] }, 119 { "MIDI", 2, &channels_table_ct1745[4] }, 120 { "CD", 2, &channels_table_ct1745[6] }, 121 { "Line", 2, &channels_table_ct1745[8] }, 122 { "Mic", 1, &channels_table_ct1745[10] }, 123 { "PC Speaker", 1, &channels_table_ct1745[11] }, 124 { "Input Gain", 2, &channels_table_ct1745[12] }, 125 { "Output Gain", 2, &channels_table_ct1745[14] }, 126 { "Treble", 2, &channels_table_ct1745[16] }, 127 { "Bass", 2, &channels_table_ct1745[18] }, 72 { "Master Left", 0x30, 3, 32, false }, /* Master, Left, 5bit volume level */ 73 { "Master Right", 0x31, 3, 32, false }, /* Master, Right, 5bit volume level */ 74 { "Voice Left", 0x32, 3, 32, false }, /* Voice, Left, 5bit volume level */ 75 { "Voice Right", 0x33, 3, 32, false }, /* Voice, Right, 5bit volume level */ 76 { "MIDI Left", 0x34, 3, 32, false }, /* MIDI, Left, 5bit volume level */ 77 { "MIDI Right", 0x35, 3, 32, false }, /* MIDI, Right, 5bit volume level */ 78 { "CD Left", 0x36, 3, 32, false }, /* CD, Left, 5bit volume level */ 79 { "CD Right", 0x37, 3, 32, false }, /* CD, Right, 5bit volume level */ 80 { "Line In Left", 0x38, 3, 32, false }, /* Line, Left, 5bit volume level */ 81 { "Line In Right", 0x39, 3, 32, false }, /* Line, Right, 5bit volume level */ 82 { "Mic", 0x3a, 3, 32, false }, /* Mic, Mono, 5bit volume level */ 83 { "PC Speaker", 0x3b, 6, 4, false }, /* PC speaker, Mono, 2bit level */ 84 { "Input Gain Left", 0x3f, 6, 4, false }, /* Input Gain, Left, 2bit level */ 85 { "Input Gain Right", 0x40, 6, 4, false }, /* Input Gain, Right, 2bit level */ 86 { "Output Gain Left", 0x41, 6, 4, false }, /* Output Gain, Left, 2bit level */ 87 { "Output Gain Right", 0x42, 6, 4, false }, /* Output Gain, Right, 2bit level */ 88 { "Treble Left", 0x44, 4, 16, false }, /* Treble, Left, 4bit volume level */ 89 { "Treble Right", 0x45, 4, 16, false }, /* Treble, Right, 4bit volume level */ 90 { "Bass Left", 0x46, 4, 16, false }, /* Bass, Left, 4bit volume level */ 91 { "Bass Right", 0x47, 4, 16, false }, /* Bass, Right, 4bit volume level */ 128 92 }; 129 93 130 94 static const struct { 131 const volume_item_t *table;95 const channel_t *table; 132 96 size_t count; 133 97 } volume_table[] = { 134 98 [SB_MIXER_NONE] = { NULL, 0 }, 135 99 [SB_MIXER_UNKNOWN] = { NULL, 0 }, 136 [SB_MIXER_CT1335] = { volume_ct1335, ARRAY_SIZE(volume_ct1335) }, 137 [SB_MIXER_CT1345] = { volume_ct1345, ARRAY_SIZE(volume_ct1345) }, 138 [SB_MIXER_CT1745] = { volume_ct1745, ARRAY_SIZE(volume_ct1745) }, 100 [SB_MIXER_CT1335] = { 101 channels_table_ct1335, 102 ARRAY_SIZE(channels_table_ct1335), 103 }, 104 [SB_MIXER_CT1345] = { 105 channels_table_ct1345, 106 ARRAY_SIZE(channels_table_ct1345), 107 }, 108 [SB_MIXER_CT1745] = { 109 channels_table_ct1745, 110 ARRAY_SIZE(channels_table_ct1745), 111 }, 139 112 }; 140 113 … … 177 150 } 178 151 179 int sb_mixer_get_control_item_info(const sb_mixer_t *mixer, unsigned i ndex,180 const char** name, unsigned * channels)181 { 182 assert(mixer); 183 if (i ndex> volume_table[mixer->type].count)152 int sb_mixer_get_control_item_info(const sb_mixer_t *mixer, unsigned item, 153 const char** name, unsigned *levels) 154 { 155 assert(mixer); 156 if (item > volume_table[mixer->type].count) 184 157 return ENOENT; 185 158 186 const volume_item_t *item = &volume_table[mixer->type].table[index];159 const channel_t *ch = &volume_table[mixer->type].table[item]; 187 160 if (name) 188 *name = item->description; 189 if (channels) 190 *channels = item->channels; 191 return EOK; 192 } 193 194 int sb_mixer_get_channel_info(const sb_mixer_t *mixer, unsigned index, 195 unsigned channel, const char **name, unsigned *levels) 196 { 197 assert(mixer); 198 if (index > volume_table[mixer->type].count) 161 *name = ch->name; 162 if (levels) 163 *levels = ch->volume_levels; 164 return EOK; 165 } 166 167 /** 168 * Write new volume level from mixer registers. 169 * @param mixer SB Mixer to use. 170 * @param index Control item(channel) index. 171 * @param value New volume level. 172 * @return Error code. 173 */ 174 int sb_mixer_get_control_item_value(const sb_mixer_t *mixer, unsigned item, 175 unsigned *value) 176 { 177 assert(mixer); 178 if (!value) 179 return EBADMEM; 180 if (item > volume_table[mixer->type].count) 199 181 return ENOENT; 200 182 201 const volume_item_t *item = &volume_table[mixer->type].table[index]; 202 if (channel > item->channels) 183 const channel_t *chan = &volume_table[mixer->type].table[item]; 184 pio_write_8(&mixer->regs->mixer_address, chan->address); 185 *value = (pio_read_8(&mixer->regs->mixer_data) >> chan->shift) 186 & (chan->volume_levels - 1); 187 return EOK; 188 } 189 190 /** 191 * Write new volume level to mixer registers. 192 * @param mixer SB Mixer to use. 193 * @param index Control item(channel) index. 194 * @param value New volume level. 195 * @return Error code. 196 */ 197 int sb_mixer_set_control_item_value(const sb_mixer_t *mixer, unsigned item, 198 unsigned value) 199 { 200 assert(mixer); 201 if (item > volume_table[mixer->type].count) 203 202 return ENOENT; 204 203 205 const channel_t *chan = &item->channel_table[channel]; 206 if (name) 207 *name = chan->name; 208 if (levels) 209 *levels = chan->volume_levels; 210 return EOK; 211 } 212 213 int sb_mixer_set_volume_level(const sb_mixer_t *mixer, 214 unsigned index, unsigned channel, unsigned level) 215 { 216 if (mixer->type == SB_MIXER_UNKNOWN || mixer->type == SB_MIXER_NONE) 217 return ENOTSUP; 218 if (index >= volume_table[mixer->type].count) 219 return ENOENT; 220 if (channel >= volume_table[mixer->type].table[index].channels) 221 return ENOENT; 222 223 const channel_t *chan = 224 &volume_table[mixer->type].table[index].channel_table[channel]; 225 226 if (level >= chan->volume_levels) 227 level = chan->volume_levels - 1; 204 const channel_t *chan = &volume_table[mixer->type].table[item]; 205 if (value >= chan->volume_levels) 206 value = chan->volume_levels - 1; 228 207 229 208 pio_write_8(&mixer->regs->mixer_address, chan->address); 230 209 231 uint8_t value= 0;210 uint8_t regv = 0; 232 211 if (chan->preserve_bits) { 233 value= pio_read_8(&mixer->regs->mixer_data);234 value&= ~(uint8_t)((chan->volume_levels - 1) << chan->shift);212 regv = pio_read_8(&mixer->regs->mixer_data); 213 regv &= ~(uint8_t)((chan->volume_levels - 1) << chan->shift); 235 214 } 236 215 237 value |= level << chan->shift; 238 pio_write_8(&mixer->regs->mixer_data, value); 239 ddf_log_note("Channel %s %s volume set to: %u.", 240 volume_table[mixer->type].table[index].description, 241 chan->name, level); 242 return EOK; 243 } 244 245 unsigned sb_mixer_get_volume_level(const sb_mixer_t *mixer, unsigned index, 246 unsigned channel) 247 { 248 assert(mixer); 249 if (mixer->type == SB_MIXER_UNKNOWN 250 || mixer->type == SB_MIXER_NONE 251 || (index >= volume_table[mixer->type].count) 252 || (channel >= volume_table[mixer->type].table[index].channels)) 253 return 0; 254 255 const channel_t *chan = 256 &volume_table[mixer->type].table[index].channel_table[channel]; 257 258 pio_write_8(&mixer->regs->mixer_address, chan->address); 259 return (pio_read_8(&mixer->regs->mixer_data) >> chan->shift) 260 & (chan->volume_levels - 1); 261 } 216 regv |= value << chan->shift; 217 pio_write_8(&mixer->regs->mixer_data, regv); 218 ddf_log_note("Item %s new value is: %u.", 219 volume_table[mixer->type].table[item].name, value); 220 return EOK; 221 }
Note:
See TracChangeset
for help on using the changeset viewer.