Merge branch 'topic/emu10k1-fix' into for-next

Pull emu10k1 fix patch series

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2024-04-07 08:38:02 +02:00
commit a9b16d5918
82 changed files with 1006 additions and 523 deletions

View File

@ -598,17 +598,25 @@ SUB_REG(PEFE, FILTERAMOUNT, 0x000000ff) /* Filter envlope amount */
// In stereo mode, the two channels' caches are concatenated into one,
// and hold the interleaved frames.
// The cache holds 64 frames, so the upper half is not used in 8-bit mode.
// All registers mentioned below count in frames.
// The cache is a ring buffer; CCR_READADDRESS operates modulo 64.
// The cache is filled from (CCCA_CURRADDR - CCR_CACHEINVALIDSIZE)
// into (CCR_READADDRESS - CCR_CACHEINVALIDSIZE).
// All registers mentioned below count in frames. Shortcuts:
// CA = CCCA_CURRADDR, CRA = CCR_READADDRESS,
// CLA = CCR_CACHELOOPADDRHI:CLP_CACHELOOPADDR,
// CIS = CCR_CACHEINVALIDSIZE, LIS = CCR_LOOPINVALSIZE,
// CLF = CCR_CACHELOOPFLAG, LF = CCR_LOOPFLAG
// The cache is a ring buffer; CRA operates modulo 64.
// The cache is filled from (CA - CIS) into (CRA - CIS).
// The engine has a fetch threshold of 32 bytes, so it tries to keep
// CCR_CACHEINVALIDSIZE below 8 (16-bit stereo), 16 (16-bit mono,
// 8-bit stereo), or 32 (8-bit mono). The actual transfers are pretty
// unpredictable, especially if several voices are running.
// Frames are consumed at CCR_READADDRESS, which is incremented afterwards,
// along with CCCA_CURRADDR and CCR_CACHEINVALIDSIZE. This implies that the
// actual playback position always lags CCCA_CURRADDR by exactly 64 frames.
// CIS below 8 (16-bit stereo), 16 (16-bit mono, 8-bit stereo), or
// 32 (8-bit mono). The actual transfers are pretty unpredictable,
// especially if several voices are running.
// Frames are consumed at CRA, which is incremented afterwards,
// along with CA and CIS. This implies that the actual playback
// position always lags CA by exactly 64 frames.
// When CA reaches DSL_LOOPENDADDR, LF is set for one frame's time.
// LF's rising edge causes the current values of CA and CIS to be
// copied into CLA and LIS, resp., and CLF to be set.
// If CLF is set, the first LIS of the CIS frames are instead
// filled from (CLA - LIS), and CLF is subsequently reset.
#define CD0 0x20 /* Cache data registers 0 .. 0x1f */
#define PTB 0x40 /* Page table base register */
@ -1882,8 +1890,8 @@ int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
struct snd_dma_buffer *dmab);
struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size);
int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size);
int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, const char __user *data, int size);
int snd_emu10k1_synth_memset(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size, u8 value);
int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, const char __user *data, int size, u32 xor);
int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk);
/* voice allocation */

View File

@ -56,6 +56,9 @@ struct hdac_ext_stream {
u32 pphcldpl;
u32 pphcldpu;
u32 pplcllpl;
u32 pplcllpu;
bool decoupled:1;
bool link_locked:1;
bool link_prepared;

View File

@ -89,7 +89,7 @@ struct snd_sf_list {
int snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
long count, int client);
int snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
long count, int client);
long count);
int snd_soundfont_close_check(struct snd_sf_list *sflist, int client);
struct snd_sf_list *snd_sf_new(struct snd_sf_callback *callback,

View File

@ -15,7 +15,7 @@
#ifndef __TAS2781_TLV_H__
#define __TAS2781_TLV_H__
static const DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0);
static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0);
static const DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0);
#endif

View File

@ -158,7 +158,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
struct device_node *child, *sound = NULL;
struct resource *r;
int i, layout = 0, rlen, ok = force;
char node_name[6];
char node_name[8];
static const char *rnames[] = { "i2sbus: %pOFn (control)",
"i2sbus: %pOFn (tx)",
"i2sbus: %pOFn (rx)" };

View File

@ -148,13 +148,6 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
if (snd_BUG_ON(!sp))
return -EINVAL;
if (sp->v.size == 0)
return 0;
/* be sure loop points start < end */
if (sp->v.loopstart > sp->v.loopend)
swap(sp->v.loopstart, sp->v.loopend);
/* compute true data size to be loaded */
truesize = sp->v.size;
if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
@ -177,12 +170,6 @@ snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
return -EFAULT;
}
/* recalculate address offset */
sp->v.end -= sp->v.start;
sp->v.loopstart -= sp->v.start;
sp->v.loopend -= sp->v.start;
sp->v.start = 0;
/* dram position (in word) -- mem_offset is byte */
dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1);
dram_start = dram_offset;

View File

@ -725,7 +725,13 @@ static void __exit amiga_audio_remove(struct platform_device *pdev)
dmasound_deinit();
}
static struct platform_driver amiga_audio_driver = {
/*
* amiga_audio_remove() lives in .exit.text. For drivers registered via
* module_platform_driver_probe() this is ok because they cannot get unbound at
* runtime. So mark the driver struct with __refdata to prevent modpost
* triggering a section mismatch warning.
*/
static struct platform_driver amiga_audio_driver __refdata = {
.remove_new = __exit_p(amiga_audio_remove),
.driver = {
.name = "amiga-audio",

View File

@ -255,7 +255,7 @@ lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
/* check if sample is finished playing (non-looping only) */
if (bp != best + V_OFF && bp != best + V_FREE &&
(vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch) - 64;
val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch) - 64 + 3;
if (val >= vp->reg.loopstart)
bp = best + V_OFF;
}
@ -310,6 +310,7 @@ start_voice(struct snd_emux_voice *vp)
{
unsigned int temp;
int ch;
bool w_16;
u32 psst, dsl, map, ccca, vtarget;
unsigned int addr, mapped_offset;
struct snd_midi_channel *chan;
@ -321,6 +322,7 @@ start_voice(struct snd_emux_voice *vp)
if (snd_BUG_ON(ch < 0))
return -EINVAL;
chan = vp->chan;
w_16 = !(vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS);
emem = (struct snd_emu10k1_memblk *)vp->block;
if (emem == NULL)
@ -330,7 +332,7 @@ start_voice(struct snd_emux_voice *vp)
/* dev_err(hw->card->devK, "emu: cannot map!\n"); */
return -ENOMEM;
}
mapped_offset = snd_emu10k1_memblk_offset(emem) >> 1;
mapped_offset = snd_emu10k1_memblk_offset(emem) >> w_16;
vp->reg.start += mapped_offset;
vp->reg.end += mapped_offset;
vp->reg.loopstart += mapped_offset;
@ -362,7 +364,7 @@ start_voice(struct snd_emux_voice *vp)
map = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
addr = vp->reg.start + 64;
addr = vp->reg.start + 64 - 3;
temp = vp->reg.parm.filterQ;
ccca = (temp << 28) | addr;
if (vp->apitch < 0xe400)
@ -371,7 +373,7 @@ start_voice(struct snd_emux_voice *vp)
unsigned int shift = (vp->apitch - 0xe000) >> 10;
ccca |= shift << 25;
}
if (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_8BITS)
if (!w_16)
ccca |= CCCA_8BITSELECT;
vtarget = (unsigned int)vp->vtarget << 16;

View File

@ -16,7 +16,7 @@
#define BLANK_LOOP_START 4
#define BLANK_LOOP_END 8
#define BLANK_LOOP_SIZE 12
#define BLANK_HEAD_SIZE 32
#define BLANK_HEAD_SIZE 3
/*
* allocate a sample block and copy data from userspace
@ -26,56 +26,76 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
struct snd_util_memhdr *hdr,
const void __user *data, long count)
{
u8 fill;
u32 xor;
int shift;
int offset;
int truesize, size, blocksize;
__maybe_unused int loopsize;
int loopend, sampleend;
unsigned int start_addr;
int loop_start, loop_end, loop_size, data_end, unroll;
struct snd_emu10k1 *emu;
emu = rec->hw;
if (snd_BUG_ON(!sp || !hdr))
return -EINVAL;
if (sp->v.size == 0) {
dev_dbg(emu->card->dev,
"emu: rom font for sample %d\n", sp->v.sample);
return 0;
if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP | SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
/* should instead return -ENOTSUPP; but compatibility */
printk(KERN_WARNING "Emu10k1 wavetable patch %d with unsupported loop feature\n",
sp->v.sample);
}
/* recalculate address offset */
sp->v.end -= sp->v.start;
sp->v.loopstart -= sp->v.start;
sp->v.loopend -= sp->v.start;
sp->v.start = 0;
/* some samples have invalid data. the addresses are corrected in voice info */
sampleend = sp->v.end;
if (sampleend > sp->v.size)
sampleend = sp->v.size;
loopend = sp->v.loopend;
if (loopend > sampleend)
loopend = sampleend;
/* be sure loop points start < end */
if (sp->v.loopstart >= sp->v.loopend)
swap(sp->v.loopstart, sp->v.loopend);
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
shift = 0;
fill = 0x80;
xor = (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) ? 0 : 0x80808080;
} else {
shift = 1;
fill = 0;
xor = (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) ? 0x80008000 : 0;
}
/* compute true data size to be loaded */
truesize = sp->v.size + BLANK_HEAD_SIZE;
loopsize = 0;
#if 0 /* not supported */
if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
loopsize = sp->v.loopend - sp->v.loopstart;
truesize += loopsize;
#endif
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
truesize += BLANK_LOOP_SIZE;
/* if no blank loop is attached in the sample, add it */
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
sp->v.loopend = sp->v.end + BLANK_LOOP_END;
}
}
loop_start = sp->v.loopstart;
loop_end = sp->v.loopend;
loop_size = loop_end - loop_start;
if (!loop_size)
return -EINVAL;
data_end = sp->v.end;
/* recalculate offset */
sp->v.start += BLANK_HEAD_SIZE;
sp->v.end += BLANK_HEAD_SIZE;
sp->v.loopstart += BLANK_HEAD_SIZE;
sp->v.loopend += BLANK_HEAD_SIZE;
// Automatic pre-filling of the cache does not work in the presence
// of loops (*), and we don't want to fill it manually, as that is
// fiddly and slow. So we unroll the loop until the loop end is
// beyond the cache size.
// (*) Strictly speaking, a single iteration is supported (that's
// how it works when the playback engine runs), but handling this
// special case is not worth it.
unroll = 0;
while (sp->v.loopend < 64) {
truesize += loop_size;
sp->v.loopstart += loop_size;
sp->v.loopend += loop_size;
sp->v.end += loop_size;
unroll++;
}
/* try to allocate a memory block */
blocksize = truesize;
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
blocksize *= 2;
blocksize = truesize << shift;
sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
if (sp->block == NULL) {
dev_dbg(emu->card->dev,
@ -88,110 +108,43 @@ snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
/* write blank samples at head */
offset = 0;
size = BLANK_HEAD_SIZE;
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
size *= 2;
if (offset + size > blocksize)
return -EINVAL;
snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
size = BLANK_HEAD_SIZE << shift;
snd_emu10k1_synth_memset(emu, sp->block, offset, size, fill);
offset += size;
/* copy start->loopend */
size = loopend;
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
size *= 2;
if (offset + size > blocksize)
return -EINVAL;
if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
snd_emu10k1_synth_free(emu, sp->block);
sp->block = NULL;
return -EFAULT;
}
offset += size;
data += size;
/* copy provided samples */
if (unroll && loop_end <= data_end) {
size = loop_end << shift;
if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size, xor))
goto faulty;
offset += size;
#if 0 /* not supported yet */
/* handle reverse (or bidirectional) loop */
if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
/* copy loop in reverse */
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
int woffset;
unsigned short *wblock = (unsigned short*)block;
woffset = offset / 2;
if (offset + loopsize * 2 > blocksize)
return -EINVAL;
for (i = 0; i < loopsize; i++)
wblock[woffset + i] = wblock[woffset - i -1];
offset += loopsize * 2;
} else {
if (offset + loopsize > blocksize)
return -EINVAL;
for (i = 0; i < loopsize; i++)
block[offset + i] = block[offset - i -1];
offset += loopsize;
data += loop_start << shift;
while (--unroll > 0) {
size = loop_size << shift;
if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size, xor))
goto faulty;
offset += size;
}
/* modify loop pointers */
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
sp->v.loopend += loopsize;
} else {
sp->v.loopstart += loopsize;
sp->v.loopend += loopsize;
}
/* add sample pointer */
sp->v.end += loopsize;
}
#endif
/* loopend -> sample end */
size = sp->v.size - loopend;
if (size < 0)
return -EINVAL;
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
size *= 2;
if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
snd_emu10k1_synth_free(emu, sp->block);
sp->block = NULL;
return -EFAULT;
size = (data_end - loop_start) << shift;
} else {
size = data_end << shift;
}
if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size, xor))
goto faulty;
offset += size;
/* clear rest of samples (if any) */
if (offset < blocksize)
snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
/* if no blank loop is attached in the sample, add it */
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
sp->v.loopend = sp->v.end + BLANK_LOOP_END;
}
}
#if 0 /* not supported yet */
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
/* unsigned -> signed */
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
unsigned short *wblock = (unsigned short*)block;
for (i = 0; i < truesize; i++)
wblock[i] ^= 0x8000;
} else {
for (i = 0; i < truesize; i++)
block[i] ^= 0x80;
}
}
#endif
/* recalculate offset */
start_addr = BLANK_HEAD_SIZE * 2;
if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
start_addr >>= 1;
sp->v.start += start_addr;
sp->v.end += start_addr;
sp->v.loopstart += start_addr;
sp->v.loopend += start_addr;
snd_emu10k1_synth_memset(emu, sp->block, offset, blocksize - offset, fill);
return 0;
faulty:
snd_emu10k1_synth_free(emu, sp->block);
sp->block = NULL;
return -EFAULT;
}
/*

View File

@ -565,15 +565,18 @@ static inline void *offset_ptr(struct snd_emu10k1 *emu, int page, int offset)
}
/*
* bzero(blk + offset, size)
* memset(blk + offset, value, size)
*/
int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk,
int offset, int size)
int snd_emu10k1_synth_memset(struct snd_emu10k1 *emu, struct snd_util_memblk *blk,
int offset, int size, u8 value)
{
int page, nextofs, end_offset, temp, temp1;
void *ptr;
struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk;
if (snd_BUG_ON(offset + size > p->mem.size))
return -EFAULT;
offset += blk->offset & (PAGE_SIZE - 1);
end_offset = offset + size;
page = get_aligned_page(offset);
@ -585,25 +588,55 @@ int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk
temp = temp1;
ptr = offset_ptr(emu, page + p->first_page, offset);
if (ptr)
memset(ptr, 0, temp);
memset(ptr, value, temp);
offset = nextofs;
page++;
} while (offset < end_offset);
return 0;
}
EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
EXPORT_SYMBOL(snd_emu10k1_synth_memset);
// Note that the value is assumed to be suitably repetitive.
static void xor_range(void *ptr, int size, u32 value)
{
if ((long)ptr & 1) {
*(u8 *)ptr ^= (u8)value;
ptr++;
size--;
}
if (size > 1 && ((long)ptr & 2)) {
*(u16 *)ptr ^= (u16)value;
ptr += 2;
size -= 2;
}
while (size > 3) {
*(u32 *)ptr ^= value;
ptr += 4;
size -= 4;
}
if (size > 1) {
*(u16 *)ptr ^= (u16)value;
ptr += 2;
size -= 2;
}
if (size > 0)
*(u8 *)ptr ^= (u8)value;
}
/*
* copy_from_user(blk + offset, data, size)
* copy_from_user(blk + offset, data, size) ^ xor
*/
int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk,
int offset, const char __user *data, int size)
int offset, const char __user *data, int size, u32 xor)
{
int page, nextofs, end_offset, temp, temp1;
void *ptr;
struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk;
if (snd_BUG_ON(offset + size > p->mem.size))
return -EFAULT;
offset += blk->offset & (PAGE_SIZE - 1);
end_offset = offset + size;
page = get_aligned_page(offset);
@ -614,8 +647,12 @@ int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_me
if (temp1 < temp)
temp = temp1;
ptr = offset_ptr(emu, page + p->first_page, offset);
if (ptr && copy_from_user(ptr, data, temp))
return -EFAULT;
if (ptr) {
if (copy_from_user(ptr, data, temp))
return -EFAULT;
if (xor)
xor_range(ptr, temp, xor);
}
offset = nextofs;
data += temp;
page++;

View File

@ -108,7 +108,10 @@ static const struct cs35l41_config cs35l41_config_table[] = {
{ "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
{ "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
{ "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
{ "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
{ "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
{ "17AA38AB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
{ "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
@ -496,7 +499,10 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
{ "CSC3551", "10431F12", generic_dsd_config },
{ "CSC3551", "10431F1F", generic_dsd_config },
{ "CSC3551", "10431F62", generic_dsd_config },
{ "CSC3551", "10433A60", generic_dsd_config },
{ "CSC3551", "17AA386F", generic_dsd_config },
{ "CSC3551", "17AA3877", generic_dsd_config },
{ "CSC3551", "17AA3878", generic_dsd_config },
{ "CSC3551", "17AA38A9", generic_dsd_config },
{ "CSC3551", "17AA38AB", generic_dsd_config },
{ "CSC3551", "17AA38B4", generic_dsd_config },

View File

@ -56,10 +56,19 @@ static const struct i2c_device_id cs35l56_hda_i2c_id[] = {
{}
};
static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
{ "CSC3554", 0 },
{ "CSC3556", 0 },
{ "CSC3557", 0 },
{}
};
MODULE_DEVICE_TABLE(acpi, cs35l56_acpi_hda_match);
static struct i2c_driver cs35l56_hda_i2c_driver = {
.driver = {
.name = "cs35l56-hda",
.pm = &cs35l56_hda_pm_ops,
.name = "cs35l56-hda",
.acpi_match_table = cs35l56_acpi_hda_match,
.pm = &cs35l56_hda_pm_ops,
},
.id_table = cs35l56_hda_i2c_id,
.probe = cs35l56_hda_i2c_probe,

View File

@ -56,10 +56,19 @@ static const struct spi_device_id cs35l56_hda_spi_id[] = {
{}
};
static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
{ "CSC3554", 0 },
{ "CSC3556", 0 },
{ "CSC3557", 0 },
{}
};
MODULE_DEVICE_TABLE(acpi, cs35l56_acpi_hda_match);
static struct spi_driver cs35l56_hda_spi_driver = {
.driver = {
.name = "cs35l56-hda",
.pm = &cs35l56_hda_pm_ops,
.name = "cs35l56-hda",
.acpi_match_table = cs35l56_acpi_hda_match,
.pm = &cs35l56_hda_pm_ops,
},
.id_table = cs35l56_hda_spi_id,
.probe = cs35l56_hda_spi_probe,

View File

@ -6875,11 +6875,38 @@ static void alc287_fixup_legion_16ithg6_speakers(struct hda_codec *cdc, const st
comp_generic_fixup(cdc, action, "i2c", "CLSA0101", "-%s:00-cs35l41-hda.%d", 2);
}
static void cs35l56_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
{
comp_generic_fixup(cdc, action, "i2c", "CSC3556", "-%s:00-cs35l56-hda.%d", 2);
}
static void cs35l56_fixup_i2c_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
{
comp_generic_fixup(cdc, action, "i2c", "CSC3556", "-%s:00-cs35l56-hda.%d", 4);
}
static void cs35l56_fixup_spi_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
{
comp_generic_fixup(cdc, action, "spi", "CSC3556", "-%s:00-cs35l56-hda.%d", 2);
}
static void cs35l56_fixup_spi_four(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
{
comp_generic_fixup(cdc, action, "spi", "CSC3556", "-%s:00-cs35l56-hda.%d", 4);
}
static void alc285_fixup_asus_ga403u(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
{
/*
* The same SSID has been re-used in different hardware, they have
* different codecs and the newer GA403U has a ALC285.
*/
if (cdc->core.vendor_id == 0x10ec0285)
cs35l56_fixup_i2c_two(cdc, fix, action);
else
alc_fixup_inv_dmic(cdc, fix, action);
}
static void tas2781_fixup_i2c(struct hda_codec *cdc,
const struct hda_fixup *fix, int action)
{
@ -7436,6 +7463,10 @@ enum {
ALC256_FIXUP_ACER_SFG16_MICMUTE_LED,
ALC256_FIXUP_HEADPHONE_AMP_VOL,
ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX,
ALC285_FIXUP_CS35L56_SPI_2,
ALC285_FIXUP_CS35L56_I2C_2,
ALC285_FIXUP_CS35L56_I2C_4,
ALC285_FIXUP_ASUS_GA403U,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@ -9643,6 +9674,22 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc245_fixup_hp_spectre_x360_eu0xxx,
},
[ALC285_FIXUP_CS35L56_SPI_2] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs35l56_fixup_spi_two,
},
[ALC285_FIXUP_CS35L56_I2C_2] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs35l56_fixup_i2c_two,
},
[ALC285_FIXUP_CS35L56_I2C_4] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs35l56_fixup_i2c_four,
},
[ALC285_FIXUP_ASUS_GA403U] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc285_fixup_asus_ga403u,
},
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@ -10037,6 +10084,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8cde, "HP Spectre", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
@ -10096,7 +10145,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B),
SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U),
SND_PCI_QUIRK(0x1043, 0x1b93, "ASUS G614JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1c03, "ASUS UM3406HA", ALC287_FIXUP_CS35L41_I2C_2),
@ -10104,6 +10153,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1c33, "ASUS UX5304MA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1c43, "ASUS UX8406MA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1c62, "ASUS GU603", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1c63, "ASUS GU605M", ALC285_FIXUP_CS35L56_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS),
SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JU/JV/JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JY/JZ/JI/JG", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
@ -10115,11 +10165,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606", ALC285_FIXUP_CS35L56_I2C_4),
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS),
SND_PCI_QUIRK(0x1043, 0x1e63, "ASUS H7606W", ALC285_FIXUP_CS35L56_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1e83, "ASUS GA605W", ALC285_FIXUP_CS35L56_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401),
@ -10133,7 +10186,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x3a30, "ASUS G814JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3a50, "ASUS G834JYR/JZR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
@ -10159,7 +10212,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10ec, 0x12f6, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
@ -10333,6 +10386,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C),
@ -10403,6 +10458,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d05, 0x1147, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),

View File

@ -89,7 +89,7 @@ struct tas2781_hda {
struct snd_kcontrol *dsp_prog_ctl;
struct snd_kcontrol *dsp_conf_ctl;
struct snd_kcontrol *prof_ctl;
struct snd_kcontrol *snd_ctls[3];
struct snd_kcontrol *snd_ctls[2];
};
static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
@ -161,8 +161,6 @@ static void tas2781_hda_playback_hook(struct device *dev, int action)
pm_runtime_put_autosuspend(dev);
break;
default:
dev_dbg(tas_hda->dev, "Playback action not supported: %d\n",
action);
break;
}
}
@ -185,8 +183,15 @@ static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas_priv->codec_lock);
ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
__func__, kcontrol->id.name, tas_priv->rcabin.profile_cfg_id);
mutex_unlock(&tas_priv->codec_lock);
return 0;
}
@ -200,11 +205,19 @@ static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
val = clamp(nr_profile, 0, max);
mutex_lock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
__func__, kcontrol->id.name,
tas_priv->rcabin.profile_cfg_id, val);
if (tas_priv->rcabin.profile_cfg_id != val) {
tas_priv->rcabin.profile_cfg_id = val;
ret = 1;
}
mutex_unlock(&tas_priv->codec_lock);
return ret;
}
@ -241,8 +254,15 @@ static int tasdevice_program_get(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas_priv->codec_lock);
ucontrol->value.integer.value[0] = tas_priv->cur_prog;
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
__func__, kcontrol->id.name, tas_priv->cur_prog);
mutex_unlock(&tas_priv->codec_lock);
return 0;
}
@ -257,11 +277,18 @@ static int tasdevice_program_put(struct snd_kcontrol *kcontrol,
val = clamp(nr_program, 0, max);
mutex_lock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
__func__, kcontrol->id.name, tas_priv->cur_prog, val);
if (tas_priv->cur_prog != val) {
tas_priv->cur_prog = val;
ret = 1;
}
mutex_unlock(&tas_priv->codec_lock);
return ret;
}
@ -270,8 +297,15 @@ static int tasdevice_config_get(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas_priv->codec_lock);
ucontrol->value.integer.value[0] = tas_priv->cur_conf;
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
__func__, kcontrol->id.name, tas_priv->cur_conf);
mutex_unlock(&tas_priv->codec_lock);
return 0;
}
@ -286,54 +320,39 @@ static int tasdevice_config_put(struct snd_kcontrol *kcontrol,
val = clamp(nr_config, 0, max);
mutex_lock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
__func__, kcontrol->id.name, tas_priv->cur_conf, val);
if (tas_priv->cur_conf != val) {
tas_priv->cur_conf = val;
ret = 1;
}
mutex_unlock(&tas_priv->codec_lock);
return ret;
}
/*
* tas2781_digital_getvol - get the volum control
* @kcontrol: control pointer
* @ucontrol: User data
* Customer Kcontrol for tas2781 is primarily for regmap booking, paging
* depends on internal regmap mechanism.
* tas2781 contains book and page two-level register map, especially
* book switching will set the register BXXP00R7F, after switching to the
* correct book, then leverage the mechanism for paging to access the
* register.
*/
static int tas2781_digital_getvol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
return tasdevice_digital_getvol(tas_priv, ucontrol, mc);
}
static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int ret;
return tasdevice_amp_getvol(tas_priv, ucontrol, mc);
}
mutex_lock(&tas_priv->codec_lock);
static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc);
/* The check of the given value is in tasdevice_digital_putvol. */
return tasdevice_digital_putvol(tas_priv, ucontrol, mc);
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %ld\n",
__func__, kcontrol->id.name, ucontrol->value.integer.value[0]);
mutex_unlock(&tas_priv->codec_lock);
return ret;
}
static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
@ -342,9 +361,19 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int ret;
mutex_lock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s: kcontrol %s: -> %ld\n",
__func__, kcontrol->id.name, ucontrol->value.integer.value[0]);
/* The check of the given value is in tasdevice_amp_putvol. */
return tasdevice_amp_putvol(tas_priv, ucontrol, mc);
ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc);
mutex_unlock(&tas_priv->codec_lock);
return ret;
}
static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
@ -352,9 +381,13 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
mutex_lock(&tas_priv->codec_lock);
ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status;
dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
tas_priv->force_fwload_status ? "ON" : "OFF");
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
__func__, kcontrol->id.name, tas_priv->force_fwload_status);
mutex_unlock(&tas_priv->codec_lock);
return 0;
}
@ -365,14 +398,20 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
bool change, val = (bool)ucontrol->value.integer.value[0];
mutex_lock(&tas_priv->codec_lock);
dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
__func__, kcontrol->id.name,
tas_priv->force_fwload_status, val);
if (tas_priv->force_fwload_status == val)
change = false;
else {
change = true;
tas_priv->force_fwload_status = val;
}
dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
tas_priv->force_fwload_status ? "ON" : "OFF");
mutex_unlock(&tas_priv->codec_lock);
return change;
}
@ -381,9 +420,6 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = {
ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL,
1, 0, 20, 0, tas2781_amp_getvol,
tas2781_amp_putvol, amp_vol_tlv),
ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL,
0, 0, 200, 1, tas2781_digital_getvol,
tas2781_digital_putvol, dvc_tlv),
ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
tas2781_force_fwload_get, tas2781_force_fwload_put),
};
@ -478,10 +514,10 @@ static int tas2563_save_calibration(struct tasdevice_priv *tas_priv)
static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
{
static const unsigned char page_array[CALIB_MAX] = {
0x17, 0x18, 0x18, 0x0d, 0x18
0x17, 0x18, 0x18, 0x13, 0x18,
};
static const unsigned char rgno_array[CALIB_MAX] = {
0x74, 0x0c, 0x14, 0x3c, 0x7c
0x74, 0x0c, 0x14, 0x70, 0x7c,
};
unsigned char *data;
int i, j, rc;

View File

@ -278,7 +278,8 @@ static void run_spu_dma(struct work_struct *work)
dreamcastcard->clicks++;
if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER))
dreamcastcard->clicks %= AICA_PERIOD_NUMBER;
mod_timer(&dreamcastcard->timer, jiffies + 1);
if (snd_pcm_running(dreamcastcard->substream))
mod_timer(&dreamcastcard->timer, jiffies + 1);
}
}
@ -290,6 +291,8 @@ static void aica_period_elapsed(struct timer_list *t)
/*timer function - so cannot sleep */
int play_period;
struct snd_pcm_runtime *runtime;
if (!snd_pcm_running(substream))
return;
runtime = substream->runtime;
dreamcastcard = substream->pcm->private_data;
/* Have we played out an additional period? */
@ -350,12 +353,19 @@ static int snd_aicapcm_pcm_open(struct snd_pcm_substream
return 0;
}
static int snd_aicapcm_pcm_sync_stop(struct snd_pcm_substream *substream)
{
struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
del_timer_sync(&dreamcastcard->timer);
cancel_work_sync(&dreamcastcard->spu_dma_work);
return 0;
}
static int snd_aicapcm_pcm_close(struct snd_pcm_substream
*substream)
{
struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
flush_work(&(dreamcastcard->spu_dma_work));
del_timer(&dreamcastcard->timer);
dreamcastcard->substream = NULL;
kfree(dreamcastcard->channel);
spu_disable();
@ -401,6 +411,7 @@ static const struct snd_pcm_ops snd_aicapcm_playback_ops = {
.prepare = snd_aicapcm_pcm_prepare,
.trigger = snd_aicapcm_pcm_trigger,
.pointer = snd_aicapcm_pcm_pointer,
.sync_stop = snd_aicapcm_pcm_sync_stop,
};
/* TO DO: set up to handle more than one pcm instance */

View File

@ -115,7 +115,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
goto unregister_dmic_dev;
}
acp_init(chip);
ret = acp_init(chip);
if (ret)
goto unregister_dmic_dev;
res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
if (!res) {
ret = -ENOMEM;
@ -133,11 +136,9 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
}
}
if (flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
ret = check_acp_pdm(pci, chip);
if (ret < 0)
goto skip_pdev_creation;
}
ret = check_acp_pdm(pci, chip);
if (ret < 0)
goto skip_pdev_creation;
chip->flag = flag;
memset(&pdevinfo, 0, sizeof(pdevinfo));

View File

@ -56,6 +56,11 @@ static int _cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
dev_dbg(dsp->dev, "Calibration: Ambient=%#x, Status=%#x, CalR=%d\n",
data->calAmbient, data->calStatus, data->calR);
if (list_empty(&dsp->ctl_list)) {
dev_info(dsp->dev, "Calibration disabled due to missing firmware controls\n");
return -ENOENT;
}
ret = cs_amp_write_cal_coeff(dsp, controls, controls->ambient, data->calAmbient);
if (ret)
return ret;

View File

@ -2364,7 +2364,8 @@ static int cs42l43_codec_runtime_resume(struct device *dev)
static int cs42l43_codec_suspend(struct device *dev)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
struct cs42l43_codec *priv = dev_get_drvdata(dev);
struct cs42l43 *cs42l43 = priv->core;
disable_irq(cs42l43->irq);
@ -2373,7 +2374,8 @@ static int cs42l43_codec_suspend(struct device *dev)
static int cs42l43_codec_suspend_noirq(struct device *dev)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
struct cs42l43_codec *priv = dev_get_drvdata(dev);
struct cs42l43 *cs42l43 = priv->core;
enable_irq(cs42l43->irq);
@ -2382,7 +2384,8 @@ static int cs42l43_codec_suspend_noirq(struct device *dev)
static int cs42l43_codec_resume(struct device *dev)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
struct cs42l43_codec *priv = dev_get_drvdata(dev);
struct cs42l43 *cs42l43 = priv->core;
enable_irq(cs42l43->irq);
@ -2391,7 +2394,8 @@ static int cs42l43_codec_resume(struct device *dev)
static int cs42l43_codec_resume_noirq(struct device *dev)
{
struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
struct cs42l43_codec *priv = dev_get_drvdata(dev);
struct cs42l43 *cs42l43 = priv->core;
disable_irq(cs42l43->irq);

View File

@ -412,9 +412,9 @@ static const struct _coeff_div coeff_div_v3[] = {
{125, 48000, 6000000, 0x04, 0x04, 0x1F, 0x2D, 0x8A, 0x0A, 0x27, 0x27},
{128, 8000, 1024000, 0x60, 0x00, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
{128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
{128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x3F},
{128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{144, 8000, 1152000, 0x20, 0x00, 0x03, 0x35, 0x8A, 0x1B, 0x23, 0x47},
{144, 16000, 2304000, 0x20, 0x00, 0x11, 0x35, 0x8A, 0x1B, 0x23, 0x47},
{192, 8000, 1536000, 0x60, 0x02, 0x0D, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
@ -423,10 +423,10 @@ static const struct _coeff_div coeff_div_v3[] = {
{200, 48000, 9600000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{250, 48000, 12000000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x27, 0x27},
{256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
{256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
{256, 44100, 11289600, 0xE0, 0x00, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{256, 48000, 12288000, 0xE0, 0x00, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x7F},
{256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x08, 0x19, 0x1F, 0x3F},
{256, 44100, 11289600, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{256, 48000, 12288000, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{288, 8000, 2304000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x23, 0x47},
{384, 8000, 3072000, 0x60, 0x02, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
{384, 16000, 6144000, 0x20, 0x02, 0x03, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
@ -435,10 +435,10 @@ static const struct _coeff_div coeff_div_v3[] = {
{400, 48000, 19200000, 0xE4, 0x04, 0x35, 0x6d, 0xCA, 0x0A, 0x1F, 0x1F},
{500, 48000, 24000000, 0xF8, 0x04, 0x3F, 0x6D, 0xCA, 0x0A, 0x1F, 0x1F},
{512, 8000, 4096000, 0x60, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
{512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
{512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
{512, 8000, 4096000, 0x60, 0x00, 0x01, 0x08, 0x19, 0x1B, 0x1F, 0x7F},
{512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x08, 0x19, 0x1F, 0x3F},
{512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
{768, 8000, 6144000, 0x60, 0x02, 0x11, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
{768, 16000, 12288000, 0x20, 0x02, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
{768, 32000, 24576000, 0xE0, 0x02, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
@ -835,7 +835,6 @@ static void es8326_jack_detect_handler(struct work_struct *work)
dev_dbg(comp->dev, "Report hp remove event\n");
snd_soc_jack_report(es8326->jack, 0, SND_JACK_HEADSET);
/* mute adc when mic path switch */
regmap_write(es8326->regmap, ES8326_ADC_SCALE, 0x33);
regmap_write(es8326->regmap, ES8326_ADC1_SRC, 0x44);
regmap_write(es8326->regmap, ES8326_ADC2_SRC, 0x66);
es8326->hp = 0;
@ -843,6 +842,7 @@ static void es8326_jack_detect_handler(struct work_struct *work)
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a);
regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03);
regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
/*
* Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event
*/
@ -865,6 +865,8 @@ static void es8326_jack_detect_handler(struct work_struct *work)
* set auto-check mode, then restart jack_detect_work after 400ms.
* Don't report jack status.
*/
regmap_write(es8326->regmap, ES8326_INT_SOURCE,
(ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
es8326_enable_micbias(es8326->component);
usleep_range(50000, 70000);
@ -891,7 +893,6 @@ static void es8326_jack_detect_handler(struct work_struct *work)
snd_soc_jack_report(es8326->jack,
SND_JACK_HEADSET, SND_JACK_HEADSET);
regmap_write(es8326->regmap, ES8326_ADC_SCALE, 0x33);
regmap_update_bits(es8326->regmap, ES8326_PGA_PDN,
0x08, 0x08);
regmap_update_bits(es8326->regmap, ES8326_PGAGAIN,
@ -987,7 +988,7 @@ static int es8326_resume(struct snd_soc_component *component)
regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E);
regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0);
usleep_range(10000, 15000);
regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xe9);
regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xd9);
regmap_write(es8326->regmap, ES8326_ANA_MICBIAS, 0xcb);
/* set headphone default type and detect pin */
regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x83);
@ -1038,8 +1039,7 @@ static int es8326_resume(struct snd_soc_component *component)
es8326_enable_micbias(es8326->component);
usleep_range(50000, 70000);
regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
regmap_write(es8326->regmap, ES8326_INT_SOURCE,
(ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
regmap_write(es8326->regmap, ES8326_INTOUT_IO,
es8326->interrupt_clk);
regmap_write(es8326->regmap, ES8326_SDINOUT1_IO,
@ -1060,6 +1060,8 @@ static int es8326_resume(struct snd_soc_component *component)
es8326->hp = 0;
es8326->hpl_vol = 0x03;
es8326->hpr_vol = 0x03;
es8326_irq(es8326->irq, es8326);
return 0;
}
@ -1070,6 +1072,9 @@ static int es8326_suspend(struct snd_soc_component *component)
cancel_delayed_work_sync(&es8326->jack_detect_work);
es8326_disable_micbias(component);
es8326->calibrated = false;
regmap_write(es8326->regmap, ES8326_CLK_MUX, 0x2d);
regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x00);
regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b);
regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_OFF);
regcache_cache_only(es8326->regmap, true);
regcache_mark_dirty(es8326->regmap);

View File

@ -104,7 +104,7 @@
#define ES8326_MUTE (3 << 0)
/* ES8326_CLK_CTL */
#define ES8326_CLK_ON (0x7e << 0)
#define ES8326_CLK_ON (0x7f << 0)
#define ES8326_CLK_OFF (0 << 0)
/* ES8326_CLK_INV */

View File

@ -537,7 +537,7 @@ static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt1316->sdw_slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@ -577,12 +577,12 @@ static int rt1316_sdw_parse_dt(struct rt1316_sdw_priv *rt1316, struct device *de
if (rt1316->bq_params_cnt) {
rt1316->bq_params = devm_kzalloc(dev, rt1316->bq_params_cnt, GFP_KERNEL);
if (!rt1316->bq_params) {
dev_err(dev, "Could not allocate bq_params memory\n");
dev_err(dev, "%s: Could not allocate bq_params memory\n", __func__);
ret = -ENOMEM;
} else {
ret = device_property_read_u8_array(dev, "realtek,bq-params", rt1316->bq_params, rt1316->bq_params_cnt);
if (ret < 0)
dev_err(dev, "Could not read list of realtek,bq-params\n");
dev_err(dev, "%s: Could not read list of realtek,bq-params\n", __func__);
}
}
@ -759,7 +759,7 @@ static int __maybe_unused rt1316_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT1316_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -606,7 +606,7 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt1318->sdw_slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@ -631,8 +631,8 @@ static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT1318_SDCA_RATE_192000HZ;
break;
default:
dev_err(component->dev, "Rate %d is not supported\n",
params_rate(params));
dev_err(component->dev, "%s: Rate %d is not supported\n",
__func__, params_rate(params));
return -EINVAL;
}
@ -835,7 +835,7 @@ static int __maybe_unused rt1318_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT1318_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
return -ETIMEDOUT;
}

View File

@ -132,7 +132,7 @@ static int rt5682_sdw_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt5682->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@ -315,8 +315,8 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
&rt5682_sdw_indirect_regmap);
if (IS_ERR(rt5682->regmap)) {
ret = PTR_ERR(rt5682->regmap);
dev_err(dev, "Failed to allocate register map: %d\n",
ret);
dev_err(dev, "%s: Failed to allocate register map: %d\n",
__func__, ret);
return ret;
}
@ -400,7 +400,7 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
}
if (val != DEVICE_ID) {
dev_err(dev, "Device with ID register %x is not rt5682\n", val);
dev_err(dev, "%s: Device with ID register %x is not rt5682\n", __func__, val);
ret = -ENODEV;
goto err_nodev;
}
@ -648,7 +648,7 @@ static int rt5682_bus_config(struct sdw_slave *slave,
ret = rt5682_clock_config(&slave->dev);
if (ret < 0)
dev_err(&slave->dev, "Invalid clk config");
dev_err(&slave->dev, "%s: Invalid clk config", __func__);
return ret;
}
@ -763,19 +763,19 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
mutex_lock(&rt5682->disable_irq_lock);
if (rt5682->disable_irq == true) {
mutex_lock(&rt5682->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
rt5682->disable_irq = false;
mutex_unlock(&rt5682->disable_irq_lock);
}
mutex_unlock(&rt5682->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -37,8 +37,8 @@ static int rt700_index_write(struct regmap *regmap,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
pr_err("%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -52,8 +52,8 @@ static int rt700_index_read(struct regmap *regmap,
*value = 0;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
pr_err("Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
pr_err("%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -930,14 +930,14 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream,
port_config.num += 2;
break;
default:
dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
dev_err(component->dev, "%s: Invalid DAI id %d\n", __func__, dai->id);
return -EINVAL;
}
retval = sdw_stream_add_slave(rt700->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@ -945,8 +945,8 @@ static int rt700_pcm_hw_params(struct snd_pcm_substream *substream,
/* bit 3:0 Number of Channel */
val |= (params_channels(params) - 1);
} else {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}

View File

@ -438,20 +438,20 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
mutex_lock(&rt711->disable_irq_lock);
if (rt711->disable_irq == true) {
mutex_lock(&rt711->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt711->disable_irq = false;
mutex_unlock(&rt711->disable_irq_lock);
}
mutex_unlock(&rt711->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT711_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -36,8 +36,8 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt711->slave->dev,
"Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
"%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -52,8 +52,8 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt711->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
"%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -1293,13 +1293,13 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt711->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 16) {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}
@ -1318,8 +1318,8 @@ static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT711_SDCA_RATE_192000HZ;
break;
default:
dev_err(component->dev, "Rate %d is not supported\n",
params_rate(params));
dev_err(component->dev, "%s: Rate %d is not supported\n",
__func__, params_rate(params));
return -EINVAL;
}

View File

@ -408,7 +408,7 @@ static int rt711_bus_config(struct sdw_slave *slave,
ret = rt711_clock_config(&slave->dev);
if (ret < 0)
dev_err(&slave->dev, "Invalid clk config");
dev_err(&slave->dev, "%s: Invalid clk config", __func__);
return ret;
}
@ -536,19 +536,19 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
mutex_lock(&rt711->disable_irq_lock);
if (rt711->disable_irq == true) {
mutex_lock(&rt711->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
rt711->disable_irq = false;
mutex_unlock(&rt711->disable_irq_lock);
}
mutex_unlock(&rt711->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT711_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
return -ETIMEDOUT;
}

View File

@ -37,8 +37,8 @@ static int rt711_index_write(struct regmap *regmap,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
pr_err("%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -52,8 +52,8 @@ static int rt711_index_read(struct regmap *regmap,
*value = 0;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
pr_err("Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
pr_err("%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -428,7 +428,7 @@ static void rt711_jack_init(struct rt711_priv *rt711)
RT711_HP_JD_FINAL_RESULT_CTL_JD12);
break;
default:
dev_warn(rt711->component->dev, "Wrong JD source\n");
dev_warn(rt711->component->dev, "%s: Wrong JD source\n", __func__);
break;
}
@ -1020,7 +1020,7 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt711->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@ -1028,8 +1028,8 @@ static int rt711_pcm_hw_params(struct snd_pcm_substream *substream,
/* bit 3:0 Number of Channel */
val |= (params_channels(params) - 1);
} else {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}

View File

@ -139,8 +139,8 @@ static int rt712_sdca_dmic_index_write(struct rt712_sdca_dmic_priv *rt712,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
"Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
"%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -155,8 +155,8 @@ static int rt712_sdca_dmic_index_read(struct rt712_sdca_dmic_priv *rt712,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
"%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -317,7 +317,8 @@ static int rt712_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol,
for (i = 0; i < p->count; i++) {
err = regmap_write(rt712->mbq_regmap, p->reg_base + i, gain_val[i]);
if (err < 0)
dev_err(&rt712->slave->dev, "0x%08x can't be set\n", p->reg_base + i);
dev_err(&rt712->slave->dev, "%s: 0x%08x can't be set\n",
__func__, p->reg_base + i);
}
return changed;
@ -667,13 +668,13 @@ static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt712->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 4) {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}
@ -698,8 +699,8 @@ static int rt712_sdca_dmic_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT712_SDCA_RATE_192000HZ;
break;
default:
dev_err(component->dev, "Rate %d is not supported\n",
params_rate(params));
dev_err(component->dev, "%s: Rate %d is not supported\n",
__func__, params_rate(params));
return -EINVAL;
}
@ -923,7 +924,8 @@ static int __maybe_unused rt712_sdca_dmic_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT712_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n",
__func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -438,20 +438,21 @@ static int __maybe_unused rt712_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
mutex_lock(&rt712->disable_irq_lock);
if (rt712->disable_irq == true) {
mutex_lock(&rt712->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt712->disable_irq = false;
mutex_unlock(&rt712->disable_irq_lock);
}
mutex_unlock(&rt712->disable_irq_lock);
goto regmap_sync;
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT712_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -34,8 +34,8 @@ static int rt712_sdca_index_write(struct rt712_sdca_priv *rt712,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
"Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
"%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -50,8 +50,8 @@ static int rt712_sdca_index_read(struct rt712_sdca_priv *rt712,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt712->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
"%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -1060,13 +1060,13 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt712->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 16) {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}
@ -1085,8 +1085,8 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT712_SDCA_RATE_192000HZ;
break;
default:
dev_err(component->dev, "Rate %d is not supported\n",
params_rate(params));
dev_err(component->dev, "%s: Rate %d is not supported\n",
__func__, params_rate(params));
return -EINVAL;
}
@ -1106,7 +1106,7 @@ static int rt712_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate);
break;
default:
dev_err(component->dev, "Wrong DAI id\n");
dev_err(component->dev, "%s: Wrong DAI id\n", __func__);
return -EINVAL;
}

View File

@ -237,7 +237,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->enumeration_complete,
msecs_to_jiffies(RT715_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Enumeration not complete, timed out\n");
dev_err(&slave->dev, "%s: Enumeration not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -41,8 +41,8 @@ static int rt715_sdca_index_write(struct rt715_sdca_priv *rt715,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt715->slave->dev,
"Failed to set private value: %08x <= %04x %d\n",
addr, value, ret);
"%s: Failed to set private value: %08x <= %04x %d\n",
__func__, addr, value, ret);
return ret;
}
@ -59,8 +59,8 @@ static int rt715_sdca_index_read(struct rt715_sdca_priv *rt715,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt715->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
"%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -152,8 +152,8 @@ static int rt715_sdca_set_amp_gain_put(struct snd_kcontrol *kcontrol,
mc->shift);
ret = regmap_write(rt715->mbq_regmap, mc->reg + i, gain_val);
if (ret != 0) {
dev_err(component->dev, "Failed to write 0x%x=0x%x\n",
mc->reg + i, gain_val);
dev_err(component->dev, "%s: Failed to write 0x%x=0x%x\n",
__func__, mc->reg + i, gain_val);
return ret;
}
}
@ -188,8 +188,8 @@ static int rt715_sdca_set_amp_gain_4ch_put(struct snd_kcontrol *kcontrol,
ret = regmap_write(rt715->mbq_regmap, reg_base + i,
gain_val);
if (ret != 0) {
dev_err(component->dev, "Failed to write 0x%x=0x%x\n",
reg_base + i, gain_val);
dev_err(component->dev, "%s: Failed to write 0x%x=0x%x\n",
__func__, reg_base + i, gain_val);
return ret;
}
}
@ -224,8 +224,8 @@ static int rt715_sdca_set_amp_gain_8ch_put(struct snd_kcontrol *kcontrol,
reg = i < 7 ? reg_base + i : (reg_base - 1) | BIT(15);
ret = regmap_write(rt715->mbq_regmap, reg, gain_val);
if (ret != 0) {
dev_err(component->dev, "Failed to write 0x%x=0x%x\n",
reg, gain_val);
dev_err(component->dev, "%s: Failed to write 0x%x=0x%x\n",
__func__, reg, gain_val);
return ret;
}
}
@ -246,8 +246,8 @@ static int rt715_sdca_set_amp_gain_get(struct snd_kcontrol *kcontrol,
for (i = 0; i < 2; i++) {
ret = regmap_read(rt715->mbq_regmap, mc->reg + i, &val);
if (ret < 0) {
dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
mc->reg + i, ret);
dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
__func__, mc->reg + i, ret);
return ret;
}
ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, mc->shift);
@ -271,8 +271,8 @@ static int rt715_sdca_set_amp_gain_4ch_get(struct snd_kcontrol *kcontrol,
for (i = 0; i < 4; i++) {
ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val);
if (ret < 0) {
dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
reg_base + i, ret);
dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
__func__, reg_base + i, ret);
return ret;
}
ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, gain_sft);
@ -297,8 +297,8 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
for (i = 0; i < 8; i += 2) {
ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val_l);
if (ret < 0) {
dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
reg_base + i, ret);
dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
__func__, reg_base + i, ret);
return ret;
}
ucontrol->value.integer.value[i] = (val_l >> gain_sft) / 10;
@ -306,8 +306,8 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
reg = (i == 6) ? (reg_base - 1) | BIT(15) : reg_base + 1 + i;
ret = regmap_read(rt715->mbq_regmap, reg, &val_r);
if (ret < 0) {
dev_err(component->dev, "Failed to read 0x%x, ret=%d\n",
reg, ret);
dev_err(component->dev, "%s: Failed to read 0x%x, ret=%d\n",
__func__, reg, ret);
return ret;
}
ucontrol->value.integer.value[i + 1] = (val_r >> gain_sft) / 10;
@ -834,15 +834,15 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
0xaf00);
break;
default:
dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
dev_err(component->dev, "%s: Invalid DAI id %d\n", __func__, dai->id);
return -EINVAL;
}
retval = sdw_stream_add_slave(rt715->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(component->dev, "Unable to configure port, retval:%d\n",
retval);
dev_err(component->dev, "%s: Unable to configure port, retval:%d\n",
__func__, retval);
return retval;
}
@ -893,8 +893,8 @@ static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
val = 0xf;
break;
default:
dev_err(component->dev, "Unsupported sample rate %d\n",
params_rate(params));
dev_err(component->dev, "%s: Unsupported sample rate %d\n",
__func__, params_rate(params));
return -EINVAL;
}

View File

@ -482,7 +482,7 @@ static int rt715_bus_config(struct sdw_slave *slave,
ret = rt715_clock_config(&slave->dev);
if (ret < 0)
dev_err(&slave->dev, "Invalid clk config");
dev_err(&slave->dev, "%s: Invalid clk config", __func__);
return 0;
}
@ -554,7 +554,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev)
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT715_PROBE_TIMEOUT));
if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
sdw_show_ping_status(slave->bus, true);
return -ETIMEDOUT;

View File

@ -40,8 +40,8 @@ static int rt715_index_write(struct regmap *regmap, unsigned int reg,
ret = regmap_write(regmap, addr, value);
if (ret < 0) {
pr_err("Failed to set private value: %08x <= %04x %d\n",
addr, value, ret);
pr_err("%s: Failed to set private value: %08x <= %04x %d\n",
__func__, addr, value, ret);
}
return ret;
@ -55,8 +55,8 @@ static int rt715_index_write_nid(struct regmap *regmap,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
pr_err("Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
pr_err("%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -70,8 +70,8 @@ static int rt715_index_read_nid(struct regmap *regmap,
*value = 0;
ret = regmap_read(regmap, addr, value);
if (ret < 0)
pr_err("Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
pr_err("%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -862,14 +862,14 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
rt715_index_write(rt715->regmap, RT715_SDW_INPUT_SEL, 0xa000);
break;
default:
dev_err(component->dev, "Invalid DAI id %d\n", dai->id);
dev_err(component->dev, "%s: Invalid DAI id %d\n", __func__, dai->id);
return -EINVAL;
}
retval = sdw_stream_add_slave(rt715->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
@ -883,8 +883,8 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
val |= 0x0 << 8;
break;
default:
dev_err(component->dev, "Unsupported sample rate %d\n",
params_rate(params));
dev_err(component->dev, "%s: Unsupported sample rate %d\n",
__func__, params_rate(params));
return -EINVAL;
}
@ -892,8 +892,8 @@ static int rt715_pcm_hw_params(struct snd_pcm_substream *substream,
/* bit 3:0 Number of Channel */
val |= (params_channels(params) - 1);
} else {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}

View File

@ -467,13 +467,13 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
mutex_lock(&rt722->disable_irq_lock);
if (rt722->disable_irq == true) {
mutex_lock(&rt722->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt722->disable_irq = false;
mutex_unlock(&rt722->disable_irq_lock);
}
mutex_unlock(&rt722->disable_irq_lock);
goto regmap_sync;
}

View File

@ -35,8 +35,8 @@ int rt722_sdca_index_write(struct rt722_sdca_priv *rt722,
ret = regmap_write(regmap, addr, value);
if (ret < 0)
dev_err(&rt722->slave->dev,
"Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret);
"%s: Failed to set private value: %06x <= %04x ret=%d\n",
__func__, addr, value, ret);
return ret;
}
@ -51,8 +51,8 @@ int rt722_sdca_index_read(struct rt722_sdca_priv *rt722,
ret = regmap_read(regmap, addr, value);
if (ret < 0)
dev_err(&rt722->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret);
"%s: Failed to get private value: %06x => %04x ret=%d\n",
__func__, addr, *value, ret);
return ret;
}
@ -663,7 +663,8 @@ static int rt722_sdca_dmic_set_gain_put(struct snd_kcontrol *kcontrol,
for (i = 0; i < p->count; i++) {
err = regmap_write(rt722->mbq_regmap, p->reg_base + i, gain_val[i]);
if (err < 0)
dev_err(&rt722->slave->dev, "%#08x can't be set\n", p->reg_base + i);
dev_err(&rt722->slave->dev, "%s: %#08x can't be set\n",
__func__, p->reg_base + i);
}
return changed;
@ -1211,13 +1212,13 @@ static int rt722_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
retval = sdw_stream_add_slave(rt722->slave, &stream_config,
&port_config, 1, sdw_stream);
if (retval) {
dev_err(dai->dev, "Unable to configure port\n");
dev_err(dai->dev, "%s: Unable to configure port\n", __func__);
return retval;
}
if (params_channels(params) > 16) {
dev_err(component->dev, "Unsupported channels %d\n",
params_channels(params));
dev_err(component->dev, "%s: Unsupported channels %d\n",
__func__, params_channels(params));
return -EINVAL;
}
@ -1236,8 +1237,8 @@ static int rt722_sdca_pcm_hw_params(struct snd_pcm_substream *substream,
sampling_rate = RT722_SDCA_RATE_192000HZ;
break;
default:
dev_err(component->dev, "Rate %d is not supported\n",
params_rate(params));
dev_err(component->dev, "%s: Rate %d is not supported\n",
__func__, params_rate(params));
return -EINVAL;
}

View File

@ -683,11 +683,12 @@ static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
unsigned int alg, void *buf, size_t len)
{
struct cs_dsp_coeff_ctl *cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
struct cs_dsp_coeff_ctl *cs_ctl;
struct wm_coeff_ctl *ctl;
int ret;
mutex_lock(&dsp->cs_dsp.pwr_lock);
cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
mutex_unlock(&dsp->cs_dsp.pwr_lock);

View File

@ -296,5 +296,6 @@ static struct platform_driver avs_da7219_driver = {
module_platform_driver(avs_da7219_driver);
MODULE_DESCRIPTION("Intel da7219 machine driver");
MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
MODULE_LICENSE("GPL");

View File

@ -96,4 +96,5 @@ static struct platform_driver avs_dmic_driver = {
module_platform_driver(avs_dmic_driver);
MODULE_DESCRIPTION("Intel DMIC machine driver");
MODULE_LICENSE("GPL");

View File

@ -326,4 +326,5 @@ static struct platform_driver avs_es8336_driver = {
module_platform_driver(avs_es8336_driver);
MODULE_DESCRIPTION("Intel es8336 machine driver");
MODULE_LICENSE("GPL");

View File

@ -204,4 +204,5 @@ static struct platform_driver avs_i2s_test_driver = {
module_platform_driver(avs_i2s_test_driver);
MODULE_DESCRIPTION("Intel i2s test machine driver");
MODULE_LICENSE("GPL");

View File

@ -154,4 +154,5 @@ static struct platform_driver avs_max98357a_driver = {
module_platform_driver(avs_max98357a_driver)
MODULE_DESCRIPTION("Intel max98357a machine driver");
MODULE_LICENSE("GPL");

View File

@ -211,4 +211,5 @@ static struct platform_driver avs_max98373_driver = {
module_platform_driver(avs_max98373_driver)
MODULE_DESCRIPTION("Intel max98373 machine driver");
MODULE_LICENSE("GPL");

View File

@ -208,4 +208,5 @@ static struct platform_driver avs_max98927_driver = {
module_platform_driver(avs_max98927_driver)
MODULE_DESCRIPTION("Intel max98927 machine driver");
MODULE_LICENSE("GPL");

View File

@ -313,4 +313,5 @@ static struct platform_driver avs_nau8825_driver = {
module_platform_driver(avs_nau8825_driver)
MODULE_DESCRIPTION("Intel nau8825 machine driver");
MODULE_LICENSE("GPL");

View File

@ -69,4 +69,5 @@ static struct platform_driver avs_probe_mb_driver = {
module_platform_driver(avs_probe_mb_driver);
MODULE_DESCRIPTION("Intel probe machine driver");
MODULE_LICENSE("GPL");

View File

@ -276,4 +276,5 @@ static struct platform_driver avs_rt274_driver = {
module_platform_driver(avs_rt274_driver);
MODULE_DESCRIPTION("Intel rt274 machine driver");
MODULE_LICENSE("GPL");

View File

@ -247,4 +247,5 @@ static struct platform_driver avs_rt286_driver = {
module_platform_driver(avs_rt286_driver);
MODULE_DESCRIPTION("Intel rt286 machine driver");
MODULE_LICENSE("GPL");

View File

@ -266,4 +266,5 @@ static struct platform_driver avs_rt298_driver = {
module_platform_driver(avs_rt298_driver);
MODULE_DESCRIPTION("Intel rt298 machine driver");
MODULE_LICENSE("GPL");

View File

@ -192,4 +192,5 @@ static struct platform_driver avs_rt5514_driver = {
module_platform_driver(avs_rt5514_driver);
MODULE_DESCRIPTION("Intel rt5514 machine driver");
MODULE_LICENSE("GPL");

View File

@ -265,4 +265,5 @@ static struct platform_driver avs_rt5663_driver = {
module_platform_driver(avs_rt5663_driver);
MODULE_DESCRIPTION("Intel rt5663 machine driver");
MODULE_LICENSE("GPL");

View File

@ -341,5 +341,6 @@ static struct platform_driver avs_rt5682_driver = {
module_platform_driver(avs_rt5682_driver)
MODULE_DESCRIPTION("Intel rt5682 machine driver");
MODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>");
MODULE_LICENSE("GPL");

View File

@ -200,4 +200,5 @@ static struct platform_driver avs_ssm4567_driver = {
module_platform_driver(avs_ssm4567_driver)
MODULE_DESCRIPTION("Intel ssm4567 machine driver");
MODULE_LICENSE("GPL");

View File

@ -263,7 +263,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
int max = mc->max;
int min = mc->min;
int sign_bit = mc->sign_bit;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int mask = (1ULL << fls(max)) - 1;
unsigned int invert = mc->invert;
int val;
int ret;

View File

@ -704,6 +704,10 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
goto unregister_dev;
}
ret = acp_init(sdev);
if (ret < 0)
goto free_smn_dev;
sdev->ipc_irq = pci->irq;
ret = request_threaded_irq(sdev->ipc_irq, acp_irq_handler, acp_irq_thread,
IRQF_SHARED, "AudioDSP", sdev);
@ -713,10 +717,6 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
goto free_smn_dev;
}
ret = acp_init(sdev);
if (ret < 0)
goto free_ipc_irq;
/* scan SoundWire capabilities exposed by DSDT */
ret = acp_sof_scan_sdw_devices(sdev, chip->sdw_acpi_dev_addr);
if (ret < 0) {

View File

@ -339,8 +339,7 @@ static int sof_init_environment(struct snd_sof_dev *sdev)
ret = snd_sof_probe(sdev);
if (ret < 0) {
dev_err(sdev->dev, "failed to probe DSP %d\n", ret);
sof_ops_free(sdev);
return ret;
goto err_sof_probe;
}
/* check machine info */
@ -358,15 +357,18 @@ static int sof_init_environment(struct snd_sof_dev *sdev)
ret = validate_sof_ops(sdev);
if (ret < 0) {
snd_sof_remove(sdev);
snd_sof_remove_late(sdev);
return ret;
}
}
return 0;
err_machine_check:
if (ret) {
snd_sof_remove(sdev);
sof_ops_free(sdev);
}
snd_sof_remove(sdev);
err_sof_probe:
snd_sof_remove_late(sdev);
sof_ops_free(sdev);
return ret;
}

View File

@ -57,6 +57,9 @@ struct snd_sof_dsp_ops sof_hda_common_ops = {
.pcm_pointer = hda_dsp_pcm_pointer,
.pcm_ack = hda_dsp_pcm_ack,
.get_dai_frame_counter = hda_dsp_get_stream_llp,
.get_host_byte_counter = hda_dsp_get_stream_ldp,
/* firmware loading */
.load_firmware = snd_sof_load_firmware_raw,

View File

@ -7,6 +7,7 @@
#include <sound/pcm_params.h>
#include <sound/hdaudio_ext.h>
#include <sound/hda_register.h>
#include <sound/hda-mlink.h>
#include <sound/sof/ipc4/header.h>
#include <uapi/sound/sof/header.h>
@ -362,6 +363,16 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
snd_hdac_ext_stream_clear(hext_stream);
/*
* Save the LLP registers in case the stream is
* restarting due PAUSE_RELEASE, or START without a pcm
* close/open since in this case the LLP register is not reset
* to 0 and the delay calculation will return with invalid
* results.
*/
hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
break;
default:
dev_err(sdev->dev, "unknown trigger command %d\n", cmd);

View File

@ -681,17 +681,27 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
struct hdac_bus *bus = sof_to_bus(sdev);
bool imr_lost = false;
int ret, j;
/*
* The memory used for IMR boot loses its content in deeper than S3 state
* We must not try IMR boot on next power up (as it will fail).
*
* The memory used for IMR boot loses its content in deeper than S3
* state on CAVS platforms.
* On ACE platforms due to the system architecture the IMR content is
* lost at S3 state already, they are tailored for s2idle use.
* We must not try IMR boot on next power up in these cases as it will
* fail.
*/
if (sdev->system_suspend_target > SOF_SUSPEND_S3 ||
(chip->hw_ip_version >= SOF_INTEL_ACE_1_0 &&
sdev->system_suspend_target == SOF_SUSPEND_S3))
imr_lost = true;
/*
* In case of firmware crash or boot failure set the skip_imr_boot to true
* as well in order to try to re-load the firmware to do a 'cold' boot.
*/
if (sdev->system_suspend_target > SOF_SUSPEND_S3 ||
sdev->fw_state == SOF_FW_CRASHED ||
if (imr_lost || sdev->fw_state == SOF_FW_CRASHED ||
sdev->fw_state == SOF_FW_BOOT_FAILED)
hda->skip_imr_boot = true;

View File

@ -259,8 +259,37 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32);
/*
* The dsp_max_burst_size_in_ms is the length of the maximum burst size
* of the host DMA in the ALSA buffer.
*
* On playback start the DMA will transfer dsp_max_burst_size_in_ms
* amount of data in one initial burst to fill up the host DMA buffer.
* Consequent DMA burst sizes are shorter and their length can vary.
* To make sure that userspace allocate large enough ALSA buffer we need
* to place a constraint on the buffer time.
*
* On capture the DMA will transfer 1ms chunks.
*
* Exact dsp_max_burst_size_in_ms constraint is racy, so set the
* constraint to a minimum of 2x dsp_max_burst_size_in_ms.
*/
if (spcm->stream[direction].dsp_max_burst_size_in_ms)
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_BUFFER_TIME,
spcm->stream[direction].dsp_max_burst_size_in_ms * USEC_PER_MSEC * 2,
UINT_MAX);
/* binding pcm substream to hda stream */
substream->runtime->private_data = &dsp_stream->hstream;
/*
* Reset the llp cache values (they are used for LLP compensation in
* case the counter is not reset)
*/
dsp_stream->pplcllpl = 0;
dsp_stream->pplcllpu = 0;
return 0;
}

View File

@ -1063,3 +1063,73 @@ snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
return pos;
}
#define merge_u64(u32_u, u32_l) (((u64)(u32_u) << 32) | (u32_l))
/**
* hda_dsp_get_stream_llp - Retrieve the LLP (Linear Link Position) of the stream
* @sdev: SOF device
* @component: ASoC component
* @substream: PCM substream
*
* Returns the raw Linear Link Position value
*/
u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct hdac_stream *hstream = substream->runtime->private_data;
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
u32 llp_l, llp_u;
/*
* The pplc_addr have been calculated during probe in
* hda_dsp_stream_init():
* pplc_addr = sdev->bar[HDA_DSP_PP_BAR] +
* SOF_HDA_PPLC_BASE +
* SOF_HDA_PPLC_MULTI * total_stream +
* SOF_HDA_PPLC_INTERVAL * stream_index
*
* Use this pre-calculated address to avoid repeated re-calculation.
*/
llp_l = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
llp_u = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
/* Compensate the LLP counter with the saved offset */
if (hext_stream->pplcllpl || hext_stream->pplcllpu)
return merge_u64(llp_u, llp_l) -
merge_u64(hext_stream->pplcllpu, hext_stream->pplcllpl);
return merge_u64(llp_u, llp_l);
}
/**
* hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream
* @sdev: SOF device
* @component: ASoC component
* @substream: PCM substream
*
* Returns the raw Linear Link Position value
*/
u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct hdac_stream *hstream = substream->runtime->private_data;
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
u32 ldp_l, ldp_u;
/*
* The pphc_addr have been calculated during probe in
* hda_dsp_stream_init():
* pphc_addr = sdev->bar[HDA_DSP_PP_BAR] +
* SOF_HDA_PPHC_BASE +
* SOF_HDA_PPHC_INTERVAL * stream_index
*
* Use this pre-calculated address to avoid repeated re-calculation.
*/
ldp_l = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPL);
ldp_u = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPU);
return ((u64)ldp_u << 32) | ldp_l;
}

View File

@ -662,6 +662,12 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
int direction, bool can_sleep);
u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream);
u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream);
struct hdac_ext_stream *
hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);

View File

@ -29,15 +29,17 @@ static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = {
};
/* this helps allows the DSP to setup DMIC/SSP */
static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus)
static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus, bool enable)
{
int ret;
ret = hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_SSP, true);
ret = hdac_bus_eml_enable_offload(bus, true,
AZX_REG_ML_LEPTR_ID_INTEL_SSP, enable);
if (ret < 0)
return ret;
ret = hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_DMIC, true);
ret = hdac_bus_eml_enable_offload(bus, true,
AZX_REG_ML_LEPTR_ID_INTEL_DMIC, enable);
if (ret < 0)
return ret;
@ -52,7 +54,19 @@ static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev)
if (ret < 0)
return ret;
return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev));
return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
}
static void lnl_hda_dsp_remove(struct snd_sof_dev *sdev)
{
int ret;
ret = hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), false);
if (ret < 0)
dev_warn(sdev->dev,
"Failed to disable offload for DMIC/SSP: %d\n", ret);
hda_dsp_remove(sdev);
}
static int lnl_hda_dsp_resume(struct snd_sof_dev *sdev)
@ -63,7 +77,7 @@ static int lnl_hda_dsp_resume(struct snd_sof_dev *sdev)
if (ret < 0)
return ret;
return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev));
return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
}
static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
@ -74,7 +88,7 @@ static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
if (ret < 0)
return ret;
return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev));
return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
}
static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev)
@ -97,9 +111,11 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev)
/* common defaults */
memcpy(&sof_lnl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops));
/* probe */
if (!sdev->dspless_mode_selected)
/* probe/remove */
if (!sdev->dspless_mode_selected) {
sof_lnl_ops.probe = lnl_hda_dsp_probe;
sof_lnl_ops.remove = lnl_hda_dsp_remove;
}
/* shutdown */
sof_lnl_ops.shutdown = hda_dsp_shutdown;
@ -134,8 +150,6 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev)
sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume;
}
sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
/* dsp core get/put */
sof_lnl_ops.core_get = mtl_dsp_core_get;
sof_lnl_ops.core_put = mtl_dsp_core_put;

View File

@ -626,18 +626,6 @@ static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
return mtl_enable_interrupts(sdev, false);
}
u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct hdac_stream *hstream = substream->runtime->private_data;
u32 llp_l, llp_u;
llp_l = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPL(hstream->index));
llp_u = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPU(hstream->index));
return ((u64)llp_u << 32) | llp_l;
}
int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core)
{
const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
@ -707,8 +695,6 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev)
sof_mtl_ops.core_get = mtl_dsp_core_get;
sof_mtl_ops.core_put = mtl_dsp_core_put;
sof_mtl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
if (!sdev->private)
return -ENOMEM;

View File

@ -6,12 +6,6 @@
* Copyright(c) 2020-2022 Intel Corporation. All rights reserved.
*/
/* HDA Registers */
#define MTL_PPLCLLPL_BASE 0x948
#define MTL_PPLCLLPU_STRIDE 0x10
#define MTL_PPLCLLPL(x) (MTL_PPLCLLPL_BASE + (x) * MTL_PPLCLLPU_STRIDE)
#define MTL_PPLCLLPU(x) (MTL_PPLCLLPL_BASE + 0x4 + (x) * MTL_PPLCLLPU_STRIDE)
/* DSP Registers */
#define MTL_HFDSSCS 0x1000
#define MTL_HFDSSCS_SPA_MASK BIT(16)
@ -103,9 +97,5 @@ int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id);
void mtl_ipc_dump(struct snd_sof_dev *sdev);
u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core);
int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core);

View File

@ -4,6 +4,7 @@
#include <linux/debugfs.h>
#include <linux/sched/signal.h>
#include <linux/sched/clock.h>
#include <sound/sof/ipc4/header.h>
#include "sof-priv.h"
#include "ipc4-priv.h"
@ -412,7 +413,6 @@ static int ipc4_mtrace_enable(struct snd_sof_dev *sdev)
const struct sof_ipc_ops *iops = sdev->ipc->ops;
struct sof_ipc4_msg msg;
u64 system_time;
ktime_t kt;
int ret;
if (priv->mtrace_state != SOF_MTRACE_DISABLED)
@ -424,9 +424,12 @@ static int ipc4_mtrace_enable(struct snd_sof_dev *sdev)
msg.primary |= SOF_IPC4_MOD_INSTANCE(SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID);
msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_FW_PARAM_SYSTEM_TIME);
/* The system time is in usec, UTC, epoch is 1601-01-01 00:00:00 */
kt = ktime_add_us(ktime_get_real(), FW_EPOCH_DELTA * USEC_PER_SEC);
system_time = ktime_to_us(kt);
/*
* local_clock() is used to align with dmesg, so both kernel and firmware logs have
* the same base and a minor delta due to the IPC. system time is in us format but
* local_clock() returns the time in ns, so convert to ns.
*/
system_time = div64_u64(local_clock(), NSEC_PER_USEC);
msg.data_size = sizeof(system_time);
msg.data_ptr = &system_time;
ret = iops->set_get_data(sdev, &msg, msg.data_size, true);

View File

@ -15,6 +15,28 @@
#include "ipc4-topology.h"
#include "ipc4-fw-reg.h"
/**
* struct sof_ipc4_timestamp_info - IPC4 timestamp info
* @host_copier: the host copier of the pcm stream
* @dai_copier: the dai copier of the pcm stream
* @stream_start_offset: reported by fw in memory window (converted to frames)
* @stream_end_offset: reported by fw in memory window (converted to frames)
* @llp_offset: llp offset in memory window
* @boundary: wrap boundary should be used for the LLP frame counter
* @delay: Calculated and stored in pointer callback. The stored value is
* returned in the delay callback.
*/
struct sof_ipc4_timestamp_info {
struct sof_ipc4_copier *host_copier;
struct sof_ipc4_copier *dai_copier;
u64 stream_start_offset;
u64 stream_end_offset;
u32 llp_offset;
u64 boundary;
snd_pcm_sframes_t delay;
};
static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
struct ipc4_pipeline_set_state_data *trigger_list)
{
@ -423,8 +445,19 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
}
/* return if this is the final state */
if (state == SOF_IPC4_PIPE_PAUSED)
if (state == SOF_IPC4_PIPE_PAUSED) {
struct sof_ipc4_timestamp_info *time_info;
/*
* Invalidate the stream_start_offset to make sure that it is
* going to be updated if the stream resumes
*/
time_info = spcm->stream[substream->stream].private;
if (time_info)
time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
goto free;
}
skip_pause_transition:
/* else set the RUNNING/RESET state in the DSP */
ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list);
@ -464,14 +497,12 @@ static int sof_ipc4_pcm_trigger(struct snd_soc_component *component,
/* determine the pipeline state */
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
state = SOF_IPC4_PIPE_PAUSED;
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
state = SOF_IPC4_PIPE_RUNNING;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
state = SOF_IPC4_PIPE_PAUSED;
@ -703,6 +734,10 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
if (abi_version < SOF_IPC4_FW_REGS_ABI_VER)
support_info = false;
/* For delay reporting the get_host_byte_counter callback is needed */
if (!sof_ops(sdev) || !sof_ops(sdev)->get_host_byte_counter)
support_info = false;
for_each_pcm_streams(stream) {
pipeline_list = &spcm->stream[stream].pipeline_list;
@ -835,7 +870,6 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
struct sof_ipc4_copier *host_copier = time_info->host_copier;
struct sof_ipc4_copier *dai_copier = time_info->dai_copier;
struct sof_ipc4_pipeline_registers ppl_reg;
u64 stream_start_position;
u32 dai_sample_size;
u32 ch, node_index;
u32 offset;
@ -852,38 +886,51 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
if (ppl_reg.stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION)
return -EINVAL;
stream_start_position = ppl_reg.stream_start_offset;
ch = dai_copier->data.out_format.fmt_cfg;
ch = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(ch);
dai_sample_size = (dai_copier->data.out_format.bit_depth >> 3) * ch;
/* convert offset to sample count */
do_div(stream_start_position, dai_sample_size);
time_info->stream_start_offset = stream_start_position;
/* convert offsets to frame count */
time_info->stream_start_offset = ppl_reg.stream_start_offset;
do_div(time_info->stream_start_offset, dai_sample_size);
time_info->stream_end_offset = ppl_reg.stream_end_offset;
do_div(time_info->stream_end_offset, dai_sample_size);
/*
* Calculate the wrap boundary need to be used for delay calculation
* The host counter is in bytes, it will wrap earlier than the frames
* based link counter.
*/
time_info->boundary = div64_u64(~((u64)0),
frames_to_bytes(substream->runtime, 1));
/* Initialize the delay value to 0 (no delay) */
time_info->delay = 0;
return 0;
}
static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
snd_pcm_uframes_t *pointer)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_timestamp_info *time_info;
struct sof_ipc4_llp_reading_slot llp;
snd_pcm_uframes_t head_ptr, tail_ptr;
snd_pcm_uframes_t head_cnt, tail_cnt;
struct snd_sof_pcm_stream *stream;
u64 dai_cnt, host_cnt, host_ptr;
struct snd_sof_pcm *spcm;
u64 tmp_ptr;
int ret;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
return 0;
return -EOPNOTSUPP;
stream = &spcm->stream[substream->stream];
time_info = stream->private;
if (!time_info)
return 0;
return -EOPNOTSUPP;
/*
* stream_start_offset is updated to memory window by FW based on
@ -893,45 +940,116 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
if (ret < 0)
return 0;
return -EOPNOTSUPP;
}
/* For delay calculation we need the host counter */
host_cnt = snd_sof_pcm_get_host_byte_counter(sdev, component, substream);
host_ptr = host_cnt;
/* convert the host_cnt to frames */
host_cnt = div64_u64(host_cnt, frames_to_bytes(substream->runtime, 1));
/*
* HDaudio links don't support the LLP counter reported by firmware
* the link position is read directly from hardware registers.
* If the LLP counter is not reported by firmware in the SRAM window
* then read the dai (link) counter via host accessible means if
* available.
*/
if (!time_info->llp_offset) {
tmp_ptr = snd_sof_pcm_get_stream_position(sdev, component, substream);
if (!tmp_ptr)
return 0;
dai_cnt = snd_sof_pcm_get_dai_frame_counter(sdev, component, substream);
if (!dai_cnt)
return -EOPNOTSUPP;
} else {
sof_mailbox_read(sdev, time_info->llp_offset, &llp, sizeof(llp));
tmp_ptr = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
dai_cnt = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
}
dai_cnt += time_info->stream_end_offset;
/* In two cases dai dma position is not accurate
/* In two cases dai dma counter is not accurate
* (1) dai pipeline is started before host pipeline
* (2) multiple streams mixed into one. Each stream has the same dai dma position
* (2) multiple streams mixed into one. Each stream has the same dai dma
* counter
*
* Firmware calculates correct stream_start_offset for all cases including above two.
* Driver subtracts stream_start_offset from dai dma position to get accurate one
* Firmware calculates correct stream_start_offset for all cases
* including above two.
* Driver subtracts stream_start_offset from dai dma counter to get
* accurate one
*/
tmp_ptr -= time_info->stream_start_offset;
/* Calculate the delay taking into account that both pointer can wrap */
div64_u64_rem(tmp_ptr, substream->runtime->boundary, &tmp_ptr);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
head_ptr = substream->runtime->status->hw_ptr;
tail_ptr = tmp_ptr;
/*
* On stream start the dai counter might not yet have reached the
* stream_start_offset value which means that no frames have left the
* DSP yet from the audio stream (on playback, capture streams have
* offset of 0 as we start capturing right away).
* In this case we need to adjust the distance between the counters by
* increasing the host counter by (offset - dai_counter).
* Otherwise the dai_counter needs to be adjusted to reflect the number
* of valid frames passed on the DAI side.
*
* The delay is the difference between the counters on the two
* sides of the DSP.
*/
if (dai_cnt < time_info->stream_start_offset) {
host_cnt += time_info->stream_start_offset - dai_cnt;
dai_cnt = 0;
} else {
head_ptr = tmp_ptr;
tail_ptr = substream->runtime->status->hw_ptr;
dai_cnt -= time_info->stream_start_offset;
}
if (head_ptr < tail_ptr)
return substream->runtime->boundary - tail_ptr + head_ptr;
/* Wrap the dai counter at the boundary where the host counter wraps */
div64_u64_rem(dai_cnt, time_info->boundary, &dai_cnt);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
head_cnt = host_cnt;
tail_cnt = dai_cnt;
} else {
head_cnt = dai_cnt;
tail_cnt = host_cnt;
}
if (head_cnt < tail_cnt) {
time_info->delay = time_info->boundary - tail_cnt + head_cnt;
goto out;
}
time_info->delay = head_cnt - tail_cnt;
out:
/*
* Convert the host byte counter to PCM pointer which wraps in buffer
* and it is in frames
*/
div64_u64_rem(host_ptr, snd_pcm_lib_buffer_bytes(substream), &host_ptr);
*pointer = bytes_to_frames(substream->runtime, host_ptr);
return 0;
}
static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct sof_ipc4_timestamp_info *time_info;
struct snd_sof_pcm_stream *stream;
struct snd_sof_pcm *spcm;
spcm = snd_sof_find_spcm_dai(component, rtd);
if (!spcm)
return 0;
stream = &spcm->stream[substream->stream];
time_info = stream->private;
/*
* Report the stored delay value calculated in the pointer callback.
* In the unlikely event that the calculation was skipped/aborted, the
* default 0 delay returned.
*/
if (time_info)
return time_info->delay;
/* No delay information available, report 0 as delay */
return 0;
return head_ptr - tail_ptr;
}
const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
@ -941,6 +1059,7 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
.dai_link_fixup = sof_ipc4_pcm_dai_link_fixup,
.pcm_setup = sof_ipc4_pcm_setup,
.pcm_free = sof_ipc4_pcm_free,
.pointer = sof_ipc4_pcm_pointer,
.delay = sof_ipc4_pcm_delay,
.ipc_first_on_start = true,
.platform_stop_during_hw_free = true,

View File

@ -92,20 +92,6 @@ struct sof_ipc4_fw_data {
struct mutex pipeline_state_mutex; /* protect pipeline triggers, ref counts and states */
};
/**
* struct sof_ipc4_timestamp_info - IPC4 timestamp info
* @host_copier: the host copier of the pcm stream
* @dai_copier: the dai copier of the pcm stream
* @stream_start_offset: reported by fw in memory window
* @llp_offset: llp offset in memory window
*/
struct sof_ipc4_timestamp_info {
struct sof_ipc4_copier *host_copier;
struct sof_ipc4_copier *dai_copier;
u64 stream_start_offset;
u32 llp_offset;
};
extern const struct sof_ipc_fw_loader_ops ipc4_loader_ops;
extern const struct sof_ipc_tplg_ops ipc4_tplg_ops;
extern const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops;

View File

@ -412,8 +412,9 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
struct sof_ipc4_available_audio_format *available_fmt;
struct snd_soc_component *scomp = swidget->scomp;
struct sof_ipc4_copier *ipc4_copier;
struct snd_sof_pcm *spcm;
int node_type = 0;
int ret;
int ret, dir;
ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL);
if (!ipc4_copier)
@ -447,6 +448,25 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
}
dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type);
spcm = snd_sof_find_spcm_comp(scomp, swidget->comp_id, &dir);
if (!spcm)
goto skip_gtw_cfg;
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
struct snd_sof_pcm_stream *sps = &spcm->stream[dir];
sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms,
SOF_COPIER_DEEP_BUFFER_TOKENS,
swidget->tuples,
swidget->num_tuples, sizeof(u32), 1);
/* Set default DMA buffer size if it is not specified in topology */
if (!sps->dsp_max_burst_size_in_ms)
sps->dsp_max_burst_size_in_ms = SOF_IPC4_MIN_DMA_BUFFER_SIZE;
} else {
/* Capture data is copied from DSP to host in 1ms bursts */
spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
}
skip_gtw_cfg:
ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL);
if (!ipc4_copier->gtw_attr) {

View File

@ -523,12 +523,26 @@ static inline int snd_sof_pcm_platform_ack(struct snd_sof_dev *sdev,
return 0;
}
static inline u64 snd_sof_pcm_get_stream_position(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
static inline u64
snd_sof_pcm_get_dai_frame_counter(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
if (sof_ops(sdev) && sof_ops(sdev)->get_stream_position)
return sof_ops(sdev)->get_stream_position(sdev, component, substream);
if (sof_ops(sdev) && sof_ops(sdev)->get_dai_frame_counter)
return sof_ops(sdev)->get_dai_frame_counter(sdev, component,
substream);
return 0;
}
static inline u64
snd_sof_pcm_get_host_byte_counter(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
if (sof_ops(sdev) && sof_ops(sdev)->get_host_byte_counter)
return sof_ops(sdev)->get_host_byte_counter(sdev, component,
substream);
return 0;
}

View File

@ -388,13 +388,21 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
struct snd_sof_pcm *spcm;
snd_pcm_uframes_t host, dai;
int ret = -EOPNOTSUPP;
/* nothing to do for BE */
if (rtd->dai_link->no_pcm)
return 0;
if (pcm_ops && pcm_ops->pointer)
ret = pcm_ops->pointer(component, substream, &host);
if (ret != -EOPNOTSUPP)
return ret ? ret : host;
/* use dsp ops pointer callback directly if set */
if (sof_ops(sdev)->pcm_pointer)
return sof_ops(sdev)->pcm_pointer(sdev, substream);

View File

@ -103,7 +103,10 @@ struct snd_sof_dai_config_data {
* additional memory in the SOF PCM stream structure
* @pcm_free: Function pointer for PCM free that can be used for freeing any
* additional memory in the SOF PCM stream structure
* @delay: Function pointer for pcm delay calculation
* @pointer: Function pointer for pcm pointer
* Note: the @pointer callback may return -EOPNOTSUPP which should be
* handled in a same way as if the callback is not provided
* @delay: Function pointer for pcm delay reporting
* @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the
* STOP pcm trigger
* @ipc_first_on_start: Send IPC before invoking platform trigger during
@ -124,6 +127,9 @@ struct sof_ipc_pcm_ops {
int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
int (*pcm_setup)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
int (*pointer)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
snd_pcm_uframes_t *pointer);
snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
bool reset_hw_params_during_stop;
@ -322,6 +328,7 @@ struct snd_sof_pcm_stream {
struct work_struct period_elapsed_work;
struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */
bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
unsigned int dsp_max_burst_size_in_ms; /* The maximum size of the host DMA burst in ms */
/*
* flag to indicate that the DSP pipelines should be kept
* active or not while suspending the stream

View File

@ -262,13 +262,25 @@ struct snd_sof_dsp_ops {
int (*pcm_ack)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); /* optional */
/*
* optional callback to retrieve the link DMA position for the substream
* when the position is not reported in the shared SRAM windows but
* instead from a host-accessible hardware counter.
* optional callback to retrieve the number of frames left/arrived from/to
* the DSP on the DAI side (link/codec/DMIC/etc).
*
* The callback is used when the firmware does not provide this information
* via the shared SRAM window and it can be retrieved by host.
*/
u64 (*get_stream_position)(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream); /* optional */
u64 (*get_dai_frame_counter)(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream); /* optional */
/*
* Optional callback to retrieve the number of bytes left/arrived from/to
* the DSP on the host side (bytes between host ALSA buffer and DSP).
*
* The callback is needed for ALSA delay reporting.
*/
u64 (*get_host_byte_counter)(struct snd_sof_dev *sdev,
struct snd_soc_component *component,
struct snd_pcm_substream *substream); /* optional */
/* host read DSP stream data */
int (*ipc_msg_data)(struct snd_sof_dev *sdev,

View File

@ -94,10 +94,8 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch
/* create soundfont list */
memset(&sf_cb, 0, sizeof(sf_cb));
sf_cb.private_data = emu;
if (emu->ops.sample_new)
sf_cb.sample_new = sf_sample_new;
if (emu->ops.sample_free)
sf_cb.sample_free = sf_sample_free;
sf_cb.sample_new = sf_sample_new;
sf_cb.sample_free = sf_sample_free;
if (emu->ops.sample_reset)
sf_cb.sample_reset = sf_sample_reset;
emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);

View File

@ -27,8 +27,7 @@ snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg)
if (patch.key == GUS_PATCH)
return snd_soundfont_load_guspatch(emu->sflist, arg,
patch.len + sizeof(patch),
TMP_CLIENT_ID);
patch.len + sizeof(patch));
if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
patch.type <= SNDRV_SFNT_PROBE_DATA) {

View File

@ -205,8 +205,7 @@ snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
return -ENXIO;
if (format == GUS_PATCH)
rc = snd_soundfont_load_guspatch(emu->sflist, buf, count,
SF_CLIENT_NO(p->chset.port));
rc = snd_soundfont_load_guspatch(emu->sflist, buf, count);
else if (format == SNDRV_OSS_SOUNDFONT_PATCH) {
struct soundfont_patch_info patch;
if (count < (int)sizeof(patch))

View File

@ -102,6 +102,7 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device)
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = emu;
entry->c.text.read = snd_emux_proc_info_read;
emu->proc = entry;
}
void snd_emux_proc_free(struct snd_emux *emu)

View File

@ -65,11 +65,11 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index)
return -ENODEV;
}
if (emu->num_ports < 0) {
if (emu->num_ports <= 0) {
snd_printk(KERN_WARNING "seqports must be greater than zero\n");
emu->num_ports = 1;
} else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) {
snd_printk(KERN_WARNING "too many ports."
} else if (emu->num_ports > SNDRV_EMUX_MAX_PORTS) {
snd_printk(KERN_WARNING "too many ports. "
"limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS);
emu->num_ports = SNDRV_EMUX_MAX_PORTS;
}

View File

@ -689,6 +689,21 @@ find_sample(struct snd_soundfont *sf, int sample_id)
}
static int
validate_sample_info(struct soundfont_sample_info *si)
{
if (si->end < 0 || si->end > si->size)
return -EINVAL;
if (si->loopstart < 0 || si->loopstart > si->end)
return -EINVAL;
if (si->loopend < 0 || si->loopend > si->end)
return -EINVAL;
/* be sure loop points start < end */
if (si->loopstart > si->loopend)
swap(si->loopstart, si->loopend);
return 0;
}
/*
* Load sample information, this can include data to be loaded onto
* the soundcard. It can also just be a pointer into soundcard ROM.
@ -701,7 +716,6 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
struct snd_soundfont *sf;
struct soundfont_sample_info sample_info;
struct snd_sf_sample *sp;
long off;
/* patch must be opened */
sf = sflist->currsf;
@ -711,12 +725,16 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
if (is_special_type(sf->type))
return -EINVAL;
if (count < (long)sizeof(sample_info)) {
return -EINVAL;
}
if (copy_from_user(&sample_info, data, sizeof(sample_info)))
return -EFAULT;
data += sizeof(sample_info);
count -= sizeof(sample_info);
off = sizeof(sample_info);
if (sample_info.size != (count-off)/2)
// SoundFont uses S16LE samples.
if (sample_info.size * 2 != count)
return -EINVAL;
/* Check for dup */
@ -727,6 +745,21 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
return -EINVAL;
}
if (sample_info.size > 0) {
if (sample_info.start < 0)
return -EINVAL;
// Here we "rebase out" the start address, because the
// real start is the start of the provided sample data.
sample_info.end -= sample_info.start;
sample_info.loopstart -= sample_info.start;
sample_info.loopend -= sample_info.start;
sample_info.start = 0;
if (validate_sample_info(&sample_info) < 0)
return -EINVAL;
}
/* Allocate a new sample structure */
sp = sf_sample_new(sflist, sf);
if (!sp)
@ -735,7 +768,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
sp->v = sample_info;
sp->v.sf_id = sf->id;
sp->v.dummy = 0;
sp->v.truesize = sp->v.size;
sp->v.truesize = 0;
/*
* If there is wave data then load it.
@ -744,7 +777,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
int rc;
rc = sflist->callback.sample_new
(sflist->callback.private_data, sp, sflist->memhdr,
data + off, count - off);
data, count);
if (rc < 0) {
sf_sample_delete(sflist, sf, sp);
return rc;
@ -941,8 +974,7 @@ int snd_sf_vol_table[128] = {
/* load GUS patch */
static int
load_guspatch(struct snd_sf_list *sflist, const char __user *data,
long count, int client)
load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count)
{
struct patch_info patch;
struct snd_soundfont *sf;
@ -957,10 +989,12 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
}
if (copy_from_user(&patch, data, sizeof(patch)))
return -EFAULT;
count -= sizeof(patch);
data += sizeof(patch);
if ((patch.len << (patch.mode & WAVE_16_BITS ? 1 : 0)) != count)
return -EINVAL;
sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
if (sf == NULL)
return -ENOMEM;
@ -975,6 +1009,11 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
smp->v.loopend = patch.loop_end;
smp->v.size = patch.len;
if (validate_sample_info(&smp->v) < 0) {
sf_sample_delete(sflist, sf, smp);
return -EINVAL;
}
/* set up mode flags */
smp->v.mode_flags = 0;
if (!(patch.mode & WAVE_16_BITS))
@ -1012,7 +1051,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
/*
* load wave data
*/
if (sflist->callback.sample_new) {
if (smp->v.size > 0) {
rc = sflist->callback.sample_new
(sflist->callback.private_data, smp, sflist->memhdr,
data, count);
@ -1122,11 +1161,11 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
/* load GUS patch */
int
snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
long count, int client)
long count)
{
int rc;
lock_preset(sflist);
rc = load_guspatch(sflist, data, count, client);
rc = load_guspatch(sflist, data, count);
unlock_preset(sflist);
return rc;
}
@ -1377,9 +1416,8 @@ snd_sf_clear(struct snd_sf_list *sflist)
}
for (sp = sf->samples; sp; sp = nextsp) {
nextsp = sp->next;
if (sflist->callback.sample_free)
sflist->callback.sample_free(sflist->callback.private_data,
sp, sflist->memhdr);
sflist->callback.sample_free(sflist->callback.private_data,
sp, sflist->memhdr);
kfree(sp);
}
kfree(sf);
@ -1481,9 +1519,8 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
nextsp = sp->next;
sf->samples = nextsp;
sflist->mem_used -= sp->v.truesize;
if (sflist->callback.sample_free)
sflist->callback.sample_free(sflist->callback.private_data,
sp, sflist->memhdr);
sflist->callback.sample_free(sflist->callback.private_data,
sp, sflist->memhdr);
kfree(sp);
}
}

View File

@ -202,7 +202,7 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
struct urb *urb;
/* create message: */
msg = kmalloc(sizeof(struct message), GFP_ATOMIC);
msg = kzalloc(sizeof(struct message), GFP_ATOMIC);
if (msg == NULL)
return -ENOMEM;
@ -688,7 +688,7 @@ static int line6_init_cap_control(struct usb_line6 *line6)
int ret;
/* initialize USB buffers: */
line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
line6->buffer_listen = kzalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
if (!line6->buffer_listen)
return -ENOMEM;
@ -697,7 +697,7 @@ static int line6_init_cap_control(struct usb_line6 *line6)
return -ENOMEM;
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
line6->buffer_message = kzalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
if (!line6->buffer_message)
return -ENOMEM;