Skip to content

Commit b6d5be4

Browse files
committed
Some fixed for ALSA. Mute and volume changing should be improved
1 parent c6851e9 commit b6d5be4

File tree

4 files changed

+106
-151
lines changed

4 files changed

+106
-151
lines changed

sound/arm/bcm2835-ctl.c

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,42 +33,61 @@
3333

3434
#include "bcm2835.h"
3535

36-
37-
/* functions to convert alsa to chip volume and back. */
38-
int alsa2chip(int vol)
39-
{
40-
return -((vol << 8) / 100);
41-
}
42-
43-
int chip2alsa(int vol)
44-
{
45-
return -((vol * 100) >> 8);
46-
}
36+
/* volume maximum and minimum in terms of 0.01dB */
37+
#define CTRL_VOL_MAX 400
38+
#define CTRL_VOL_MIN -10239 /* originally -10240 */
4739

4840

4941
static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
5042
struct snd_ctl_elem_info *uinfo)
5143
{
44+
audio_info(" ... IN ");
5245
if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
5346
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5447
uinfo->count = 1;
55-
uinfo->value.integer.min = -10240;
56-
uinfo->value.integer.max = 400; /* 2303 */
48+
uinfo->value.integer.min = CTRL_VOL_MIN;
49+
uinfo->value.integer.max = CTRL_VOL_MAX; /* 2303 */
5750
} else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
58-
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
51+
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
5952
uinfo->count = 1;
6053
uinfo->value.integer.min = 0;
6154
uinfo->value.integer.max = 1;
6255
} else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
6356
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
6457
uinfo->count = 1;
6558
uinfo->value.integer.min = 0;
66-
uinfo->value.integer.max = AUDIO_DEST_MAX-0;
59+
uinfo->value.integer.max = AUDIO_DEST_MAX-1;
6760
}
68-
61+
audio_info(" ... OUT ");
6962
return 0;
7063
}
7164

65+
/* toggles mute on or off depending on the value of nmute, and returns
66+
* 1 if the mute value was changed, otherwise 0
67+
*/
68+
static int toggle_mute(struct bcm2835_chip *chip, int nmute)
69+
{
70+
/* if settings are ok, just return 0 */
71+
if(chip->mute == nmute)
72+
return 0;
73+
74+
/* if the sound is muted then we need to unmute */
75+
if(chip->mute == CTRL_VOL_MUTE)
76+
{
77+
chip->volume = chip->old_volume; /* copy the old volume back */
78+
audio_info("Unmuting, old_volume = %d, volume = %d ...", chip->old_volume, chip->volume);
79+
}
80+
else /* otherwise we mute */
81+
{
82+
chip->old_volume = chip->volume;
83+
chip->volume = 26214; /* set volume to minimum level AKA mute */
84+
audio_info("Muting, old_volume = %d, volume = %d ...", chip->old_volume, chip->volume);
85+
}
86+
87+
chip->mute = nmute;
88+
return 1;
89+
}
90+
7291
static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
7392
struct snd_ctl_elem_value *ucontrol)
7493
{
@@ -93,9 +112,10 @@ static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
93112
int changed = 0;
94113

95114
if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
96-
if (chip->mute) {
97-
chip->mute = 0;
98-
changed = 1;
115+
audio_info("Volume change attempted.. volume = %d new_volume = %d", chip->volume, (int)ucontrol->value.integer.value[0]);
116+
if (chip->mute == CTRL_VOL_MUTE) {
117+
/* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */
118+
return 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */
99119
}
100120
if (changed
101121
|| (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) {
@@ -105,11 +125,10 @@ static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
105125
}
106126

107127
} else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
108-
/* Not implemented */
109-
if (ucontrol->value.integer.value[0] != chip->mute) {
110-
chip->mute = ucontrol->value.integer.value[0];
111-
changed = 0;
112-
}
128+
/* Now implemented */
129+
audio_info(" Mute attempted");
130+
changed = toggle_mute(chip, ucontrol->value.integer.value[0]);
131+
113132
} else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
114133
if (ucontrol->value.integer.value[0] != chip->dest) {
115134
chip->dest = ucontrol->value.integer.value[0];
@@ -125,22 +144,21 @@ static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
125144
return changed;
126145
}
127146

128-
static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, -10240, 1, 1);
147+
static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1);
129148

130149
static struct snd_kcontrol_new snd_bcm2835_ctl[] __devinitdata = {
131150
{
132151
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
133152
.name = "PCM Playback Volume",
134153
.index = 0,
135-
.access =
136-
SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE,
154+
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
137155
.private_value = PCM_PLAYBACK_VOLUME,
138156
.info = snd_bcm2835_ctl_info,
139157
.get = snd_bcm2835_ctl_get,
140158
.put = snd_bcm2835_ctl_put,
141159
.count = 1,
142160
.tlv = {.p = snd_bcm2835_db_scale}
143-
},
161+
},
144162
{
145163
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
146164
.name = "PCM Playback Switch",
@@ -162,7 +180,7 @@ static struct snd_kcontrol_new snd_bcm2835_ctl[] __devinitdata = {
162180
.get = snd_bcm2835_ctl_get,
163181
.put = snd_bcm2835_ctl_put,
164182
.count = 1,
165-
},
183+
},
166184
};
167185

168186
int __devinit snd_bcm2835_new_ctl(bcm2835_chip_t * chip)

sound/arm/bcm2835-pcm.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ static struct snd_pcm_hardware snd_bcm2835_playback_hw = {
2626
.rate_max = 48000,
2727
.channels_min = 1,
2828
.channels_max = 2,
29-
.buffer_bytes_max = (4 * 8 - 1) * 1024, /* Needs to be less than audioplay buffer size */
29+
.buffer_bytes_max = 32 * 1024, /* Needs to be less than audioplay buffer size */
3030
.period_bytes_min = 1 * 1024,
31-
.period_bytes_max = (4 * 8 - 1) * 1024,
31+
.period_bytes_max = 32 * 1024,
3232
.periods_min = 1,
33-
.periods_max = 4 * 8 - 1,
33+
.periods_max = 32,
3434
};
3535

3636
static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
@@ -64,14 +64,18 @@ static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id)
6464
((alsa_stream->pos + consumed) / alsa_stream->period_size))
6565
new_period = 1;
6666
}
67-
audio_debug("updating pos cur: %d + %d max:%d new_period:%d\n",
67+
audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n",
6868
alsa_stream->pos,
69-
(consumed /** AUDIO_IPC_BLOCK_BUFFER_SIZE*/ ),
70-
alsa_stream->buffer_size, new_period);
69+
consumed,
70+
alsa_stream->buffer_size,
71+
(int)(alsa_stream->period_size*alsa_stream->substream->runtime->periods),
72+
frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr),
73+
new_period);
7174
if (alsa_stream->buffer_size) {
7275
alsa_stream->pos += consumed;
7376
alsa_stream->pos %= alsa_stream->buffer_size;
7477
}
78+
7579
if (alsa_stream->substream) {
7680
if (new_period)
7781
snd_pcm_period_elapsed(alsa_stream->substream);
@@ -135,7 +139,6 @@ static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
135139
runtime->private_data = alsa_stream;
136140
runtime->private_free = snd_bcm2835_playback_free;
137141
runtime->hw = snd_bcm2835_playback_hw;
138-
139142
/* minimum 16 bytes alignment (for vchiq bulk transfers) */
140143
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
141144
16);
@@ -224,6 +227,10 @@ static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
224227
}
225228

226229
bcm2835_audio_setup(alsa_stream);
230+
231+
/* in preparation of the stream, set the controls (volume level) of the stream */
232+
bcm2835_audio_set_ctls(alsa_stream->chip);
233+
227234
audio_info(" .. OUT\n");
228235

229236
return err;
@@ -382,7 +389,8 @@ int __devinit snd_bcm2835_new_pcm(bcm2835_chip_t * chip)
382389
strcpy(pcm->name, "bcm2835 ALSA");
383390
chip->pcm = pcm;
384391
chip->dest = AUDIO_DEST_AUTO;
385-
chip->volume = 100;
392+
chip->volume = alsa2chip(0);
393+
chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */
386394
/* set operators */
387395
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
388396
&snd_bcm2835_playback_ops);

sound/arm/bcm2835-vchiq.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,18 @@
4343

4444
/* Default VCOS logging level */
4545
#define LOG_LEVEL VCOS_LOG_WARN
46-
4746
/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
48-
#define LOG_ERR( fmt, arg... ) vcos_log_error( "%s:%d " fmt, __func__, __LINE__, ##arg)
49-
#define LOG_WARN( fmt, arg... ) vcos_log_warn( "%s:%d " fmt, __func__, __LINE__, ##arg)
50-
#define LOG_INFO( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
51-
#define LOG_DBG( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
47+
#ifdef AUDIO_DEBUG_ENABLE
48+
#define LOG_ERR( fmt, arg... ) pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg)
49+
#define LOG_WARN( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
50+
#define LOG_INFO( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
51+
#define LOG_DBG( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
52+
#else
53+
#define LOG_ERR( fmt, arg... ) vcos_log_error( "%s:%d " fmt, __func__, __LINE__, ##arg)
54+
#define LOG_WARN( fmt, arg... ) vcos_log_warn( "%s:%d " fmt, __func__, __LINE__, ##arg)
55+
#define LOG_INFO( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
56+
#define LOG_DBG( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
57+
#endif
5258

5359
typedef struct opaque_AUDIO_INSTANCE_T {
5460
uint32_t num_connections;
@@ -103,7 +109,7 @@ int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream)
103109
LOG_DBG(" .. IN\n");
104110
if (alsa_stream->my_wq) {
105111
my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC);
106-
/* Queue some work (item 1) */
112+
/*--- Queue some work (item 1) ---*/
107113
if (work) {
108114
INIT_WORK((struct work_struct *)work, my_wq_function);
109115
work->alsa_stream = alsa_stream;
@@ -124,7 +130,7 @@ int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream)
124130
LOG_DBG(" .. IN\n");
125131
if (alsa_stream->my_wq) {
126132
my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC);
127-
/* Queue some work (item 1) */
133+
/*--- Queue some work (item 1) ---*/
128134
if (work) {
129135
INIT_WORK((struct work_struct *)work, my_wq_function);
130136
work->alsa_stream = alsa_stream;
@@ -142,6 +148,7 @@ int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream)
142148
void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream)
143149
{
144150
alsa_stream->my_wq = create_workqueue("my_queue");
151+
return;
145152
}
146153

147154
void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream)
@@ -151,6 +158,7 @@ void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream)
151158
destroy_workqueue(alsa_stream->my_wq);
152159
alsa_stream->my_wq = NULL;
153160
}
161+
return;
154162
}
155163

156164
static void audio_vchi_callback(void *param,
@@ -501,14 +509,22 @@ int bcm2835_audio_set_ctls(bcm2835_chip_t * chip)
501509
int i;
502510
int ret = 0;
503511
LOG_DBG(" .. IN\n");
512+
504513
/* change ctls for all substreams */
505514
for (i = 0; i < MAX_SUBSTREAMS; i++) {
506515
if (chip->avail_substreams & (1 << i)) {
507516
if (!chip->alsa_stream[i])
517+
{
518+
LOG_DBG(" No ALSA stream available?! ");
508519
ret = 0;
509-
else if (bcm2835_audio_set_ctls_chan
520+
}
521+
else if (bcm2835_audio_set_ctls_chan /* returns 0 on success */
510522
(chip->alsa_stream[i], chip) != 0)
511-
ret = -1;
523+
{
524+
LOG_DBG("Couldn't set the controls for stream %d", i);
525+
ret = -1;
526+
}
527+
LOG_DBG(" Controls set for stream %d", i);
512528
}
513529
}
514530
LOG_DBG(" .. OUT ret=%d\n", ret);

0 commit comments

Comments
 (0)