ALSA: bebob: Uninitialized id returned by saffirepro_both_clk_src_get
snd_bebob_stream_check_internal_clock() may get an id from saffirepro_both_clk_src_get (via clk_src->get()) that was uninitialized. a) make logic in saffirepro_both_clk_src_get explicit b) test if id used in snd_bebob_stream_check_internal_clock matches array size [fixed missing signed prefix to *_maps[] by tiwai] Signed-off-by: Christian Vogel <vogelchr@vogel.cx> Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
d5432503bf
commit
d1d0b6b668
2 changed files with 64 additions and 18 deletions
|
@ -27,12 +27,14 @@
|
||||||
#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
|
#define SAFFIRE_CLOCK_SOURCE_INTERNAL 0
|
||||||
#define SAFFIRE_CLOCK_SOURCE_SPDIF 1
|
#define SAFFIRE_CLOCK_SOURCE_SPDIF 1
|
||||||
|
|
||||||
/* '1' is absent, why... */
|
/* clock sources as returned from register of Saffire Pro 10 and 26 */
|
||||||
#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
|
#define SAFFIREPRO_CLOCK_SOURCE_INTERNAL 0
|
||||||
|
#define SAFFIREPRO_CLOCK_SOURCE_SKIP 1 /* never used on hardware */
|
||||||
#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
|
#define SAFFIREPRO_CLOCK_SOURCE_SPDIF 2
|
||||||
#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3
|
#define SAFFIREPRO_CLOCK_SOURCE_ADAT1 3 /* not used on s.pro. 10 */
|
||||||
#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4
|
#define SAFFIREPRO_CLOCK_SOURCE_ADAT2 4 /* not used on s.pro. 10 */
|
||||||
#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
|
#define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK 5
|
||||||
|
#define SAFFIREPRO_CLOCK_SOURCE_COUNT 6
|
||||||
|
|
||||||
/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
|
/* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
|
||||||
#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
|
#define SAFFIREPRO_ENABLE_DIG_IFACES 0x01a4
|
||||||
|
@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
|
||||||
&data, sizeof(__be32), 0);
|
&data, sizeof(__be32), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *const saffirepro_26_clk_src_labels[] = {
|
|
||||||
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
|
|
||||||
};
|
|
||||||
|
|
||||||
static char *const saffirepro_10_clk_src_labels[] = {
|
static char *const saffirepro_10_clk_src_labels[] = {
|
||||||
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
|
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
|
||||||
};
|
};
|
||||||
|
static char *const saffirepro_26_clk_src_labels[] = {
|
||||||
|
SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
|
||||||
|
};
|
||||||
|
/* Value maps between registers and labels for SaffirePro 10/26. */
|
||||||
|
static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
|
||||||
|
/* SaffirePro 10 */
|
||||||
|
[0] = {
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_ADAT1] = -1, /* not supported */
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_ADAT2] = -1, /* not supported */
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 2,
|
||||||
|
},
|
||||||
|
/* SaffirePro 26 */
|
||||||
|
[1] = {
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_INTERNAL] = 0,
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_SKIP] = -1, /* not supported */
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_SPDIF] = 1,
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_ADAT1] = 2,
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_ADAT2] = 3,
|
||||||
|
[SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] = 4,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
|
saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
|
||||||
{
|
{
|
||||||
|
@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
|
||||||
|
|
||||||
return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
|
return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* query hardware for current clock source, return our internally
|
||||||
|
* used clock index in *id, depending on hardware.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
|
saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
u32 value;
|
u32 value; /* clock source read from hw register */
|
||||||
|
const signed char *map;
|
||||||
|
|
||||||
err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
|
err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) {
|
/* depending on hardware, use a different mapping */
|
||||||
if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK)
|
if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels)
|
||||||
*id = 2;
|
map = saffirepro_clk_maps[0];
|
||||||
else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF)
|
else
|
||||||
*id = 1;
|
map = saffirepro_clk_maps[1];
|
||||||
} else if (value > 1) {
|
|
||||||
*id = value - 1;
|
/* In a case that this driver cannot handle the value of register. */
|
||||||
|
if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
|
||||||
|
err = -EIO;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*id = (unsigned int)map[value];
|
||||||
end:
|
end:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
|
||||||
/* 1.The device has its own operation to switch source of clock */
|
/* 1.The device has its own operation to switch source of clock */
|
||||||
if (clk_spec) {
|
if (clk_spec) {
|
||||||
err = clk_spec->get(bebob, &id);
|
err = clk_spec->get(bebob, &id);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
dev_err(&bebob->unit->device,
|
dev_err(&bebob->unit->device,
|
||||||
"fail to get clock source: %d\n", err);
|
"fail to get clock source: %d\n", err);
|
||||||
else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
|
goto end;
|
||||||
strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
|
}
|
||||||
|
|
||||||
|
if (id >= clk_spec->num) {
|
||||||
|
dev_err(&bebob->unit->device,
|
||||||
|
"clock source %d out of range 0..%d\n",
|
||||||
|
id, clk_spec->num - 1);
|
||||||
|
err = -EIO;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
|
||||||
|
strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
|
||||||
*internal = true;
|
*internal = true;
|
||||||
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue