Skip to content

Commit e632653

Browse files
authored
Merge pull request #3557 from ranj063/merge/sound-upstream-20220330
Merge/sound upstream 20220330
2 parents 029b208 + 5c5b381 commit e632653

45 files changed

Lines changed: 482 additions & 221 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Documentation/sound/hd-audio/models.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ alc-sense-combo
261261
huawei-mbx-stereo
262262
Enable initialization verbs for Huawei MBX stereo speakers;
263263
might be risky, try this at your own risk
264+
alc298-samsung-headphone
265+
Samsung laptops with ALC298
266+
alc256-samsung-headphone
267+
Samsung laptops with ALC256
264268

265269
ALC66x/67x/892
266270
==============

MAINTAINERS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7779,10 +7779,10 @@ F: drivers/net/ethernet/freescale/fs_enet/
77797779
F: include/linux/fs_enet_pd.h
77807780

77817781
FREESCALE SOC SOUND DRIVERS
7782-
M: Nicolin Chen <nicoleotsuka@gmail.com>
7782+
M: Shengjiu Wang <shengjiu.wang@gmail.com>
77837783
M: Xiubo Li <Xiubo.Lee@gmail.com>
77847784
R: Fabio Estevam <festevam@gmail.com>
7785-
R: Shengjiu Wang <shengjiu.wang@gmail.com>
7785+
R: Nicolin Chen <nicoleotsuka@gmail.com>
77867786
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
77877787
L: linuxppc-dev@lists.ozlabs.org
77887788
S: Maintained

drivers/base/regmap/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct regmap_format {
3131
size_t buf_size;
3232
size_t reg_bytes;
3333
size_t pad_bytes;
34+
size_t reg_downshift;
3435
size_t val_bytes;
3536
void (*format_write)(struct regmap *map,
3637
unsigned int reg, unsigned int val);
@@ -62,6 +63,7 @@ struct regmap {
6263
regmap_unlock unlock;
6364
void *lock_arg; /* This is passed to lock/unlock functions */
6465
gfp_t alloc_flags;
66+
unsigned int reg_base;
6567

6668
struct device *dev; /* Device we do I/O on */
6769
void *work_buf; /* Scratch buffer used to format I/O */

drivers/base/regmap/regmap-irq.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
189189
ret = regmap_write(map, reg, d->mask_buf[i]);
190190
if (d->chip->clear_ack) {
191191
if (d->chip->ack_invert && !ret)
192-
ret = regmap_write(map, reg,
193-
d->mask_buf[i]);
192+
ret = regmap_write(map, reg, UINT_MAX);
194193
else if (!ret)
195-
ret = regmap_write(map, reg,
196-
~d->mask_buf[i]);
194+
ret = regmap_write(map, reg, 0);
197195
}
198196
if (ret != 0)
199197
dev_err(d->map->dev, "Failed to ack 0x%x: %d\n",
@@ -556,11 +554,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
556554
data->status_buf[i]);
557555
if (chip->clear_ack) {
558556
if (chip->ack_invert && !ret)
559-
ret = regmap_write(map, reg,
560-
data->status_buf[i]);
557+
ret = regmap_write(map, reg, UINT_MAX);
561558
else if (!ret)
562-
ret = regmap_write(map, reg,
563-
~data->status_buf[i]);
559+
ret = regmap_write(map, reg, 0);
564560
}
565561
if (ret != 0)
566562
dev_err(map->dev, "Failed to ack 0x%x: %d\n",
@@ -817,13 +813,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
817813
d->status_buf[i] & d->mask_buf[i]);
818814
if (chip->clear_ack) {
819815
if (chip->ack_invert && !ret)
820-
ret = regmap_write(map, reg,
821-
(d->status_buf[i] &
822-
d->mask_buf[i]));
816+
ret = regmap_write(map, reg, UINT_MAX);
823817
else if (!ret)
824-
ret = regmap_write(map, reg,
825-
~(d->status_buf[i] &
826-
d->mask_buf[i]));
818+
ret = regmap_write(map, reg, 0);
827819
}
828820
if (ret != 0) {
829821
dev_err(map->dev, "Failed to ack 0x%x: %d\n",

drivers/base/regmap/regmap.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,11 @@ struct regmap *__regmap_init(struct device *dev,
821821
else
822822
map->alloc_flags = GFP_KERNEL;
823823

824+
map->reg_base = config->reg_base;
825+
824826
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
825827
map->format.pad_bytes = config->pad_bits / 8;
828+
map->format.reg_downshift = config->reg_downshift;
826829
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
827830
map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
828831
config->val_bits + config->pad_bits, 8);
@@ -1735,6 +1738,8 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
17351738
return ret;
17361739
}
17371740

1741+
reg += map->reg_base;
1742+
reg >>= map->format.reg_downshift;
17381743
map->format.format_reg(map->work_buf, reg, map->reg_shift);
17391744
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
17401745
map->write_flag_mask);
@@ -1905,6 +1910,8 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
19051910
return ret;
19061911
}
19071912

1913+
reg += map->reg_base;
1914+
reg >>= map->format.reg_downshift;
19081915
map->format.format_write(map, reg, val);
19091916

19101917
trace_regmap_hw_write_start(map, reg, 1);
@@ -2346,6 +2353,8 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
23462353
unsigned int reg = regs[i].reg;
23472354
unsigned int val = regs[i].def;
23482355
trace_regmap_hw_write_start(map, reg, 1);
2356+
reg += map->reg_base;
2357+
reg >>= map->format.reg_downshift;
23492358
map->format.format_reg(u8, reg, map->reg_shift);
23502359
u8 += reg_bytes + pad_bytes;
23512360
map->format.format_val(u8, val, 0);
@@ -2673,6 +2682,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
26732682
return ret;
26742683
}
26752684

2685+
reg += map->reg_base;
2686+
reg >>= map->format.reg_downshift;
26762687
map->format.format_reg(map->work_buf, reg, map->reg_shift);
26772688
regmap_set_work_buf_flag_mask(map, map->format.reg_bytes,
26782689
map->read_flag_mask);

include/linux/regmap.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ typedef void (*regmap_unlock)(void *);
237237
* @reg_stride: The register address stride. Valid register addresses are a
238238
* multiple of this value. If set to 0, a value of 1 will be
239239
* used.
240+
* @reg_downshift: The number of bits to downshift the register before
241+
* performing any operations.
242+
* @reg_base: Value to be added to every register address before performing any
243+
* operation.
240244
* @pad_bits: Number of bits of padding between register and value.
241245
* @val_bits: Number of bits in a register value, mandatory.
242246
*
@@ -360,6 +364,8 @@ struct regmap_config {
360364

361365
int reg_bits;
362366
int reg_stride;
367+
int reg_downshift;
368+
unsigned int reg_base;
363369
int pad_bits;
364370
int val_bits;
365371

include/sound/pcm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ struct snd_pcm_runtime {
401401
wait_queue_head_t tsleep; /* transfer sleep */
402402
struct fasync_struct *fasync;
403403
bool stop_operating; /* sync_stop will be called */
404+
struct mutex buffer_mutex; /* protect for buffer changes */
405+
atomic_t buffer_accessing; /* >0: in r/w operation, <0: blocked */
404406

405407
/* -- private section -- */
406408
void *private_data;

sound/core/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ config SND_PCM_TIMER
8484
help
8585
If you disable this option, pcm timer will be unavailable, so
8686
those stubs that use pcm timer (e.g. dmix, dsnoop & co) may work
87-
incorrectlly.
87+
incorrectly.
8888

8989
For some embedded devices, we may disable it to reduce memory
9090
footprint, about 20KB on x86_64 platform.

sound/core/oss/pcm_oss.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
774774

775775
if (oss_period_size < 16)
776776
return -EINVAL;
777+
778+
/* don't allocate too large period; 1MB period must be enough */
779+
if (oss_period_size > 1024 * 1024)
780+
return -ENOMEM;
781+
777782
runtime->oss.period_bytes = oss_period_size;
778783
runtime->oss.period_frames = 1;
779784
runtime->oss.periods = oss_periods;
@@ -837,6 +842,17 @@ static void unlock_params(struct snd_pcm_runtime *runtime)
837842
mutex_unlock(&runtime->oss.params_lock);
838843
}
839844

845+
static void snd_pcm_oss_release_buffers(struct snd_pcm_substream *substream)
846+
{
847+
struct snd_pcm_runtime *runtime = substream->runtime;
848+
849+
kvfree(runtime->oss.buffer);
850+
runtime->oss.buffer = NULL;
851+
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
852+
snd_pcm_oss_plugin_clear(substream);
853+
#endif
854+
}
855+
840856
/* call with params_lock held */
841857
static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
842858
{
@@ -967,12 +983,10 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
967983
snd_pcm_oss_plugin_clear(substream);
968984
if (!direct) {
969985
/* add necessary plugins */
970-
snd_pcm_oss_plugin_clear(substream);
971986
err = snd_pcm_plug_format_plugins(substream, params, sparams);
972987
if (err < 0) {
973988
pcm_dbg(substream->pcm,
974989
"snd_pcm_plug_format_plugins failed: %i\n", err);
975-
snd_pcm_oss_plugin_clear(substream);
976990
goto failure;
977991
}
978992
if (runtime->oss.plugin_first) {
@@ -981,18 +995,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
981995
if (err < 0) {
982996
pcm_dbg(substream->pcm,
983997
"snd_pcm_plugin_build_io failed: %i\n", err);
984-
snd_pcm_oss_plugin_clear(substream);
985998
goto failure;
986999
}
9871000
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
9881001
err = snd_pcm_plugin_append(plugin);
9891002
} else {
9901003
err = snd_pcm_plugin_insert(plugin);
9911004
}
992-
if (err < 0) {
993-
snd_pcm_oss_plugin_clear(substream);
1005+
if (err < 0)
9941006
goto failure;
995-
}
9961007
}
9971008
}
9981009
#endif
@@ -1043,10 +1054,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
10431054
goto failure;
10441055
}
10451056
#endif
1046-
oss_period_size *= oss_frame_size;
1047-
1048-
oss_buffer_size = oss_period_size * runtime->oss.periods;
1049-
if (oss_buffer_size < 0) {
1057+
oss_period_size = array_size(oss_period_size, oss_frame_size);
1058+
oss_buffer_size = array_size(oss_period_size, runtime->oss.periods);
1059+
if (oss_buffer_size <= 0) {
10501060
err = -EINVAL;
10511061
goto failure;
10521062
}
@@ -1082,6 +1092,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
10821092

10831093
err = 0;
10841094
failure:
1095+
if (err)
1096+
snd_pcm_oss_release_buffers(substream);
10851097
kfree(sw_params);
10861098
kfree(params);
10871099
kfree(sparams);
@@ -2351,13 +2363,7 @@ static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
23512363

23522364
static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
23532365
{
2354-
struct snd_pcm_runtime *runtime;
2355-
runtime = substream->runtime;
2356-
kvfree(runtime->oss.buffer);
2357-
runtime->oss.buffer = NULL;
2358-
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
2359-
snd_pcm_oss_plugin_clear(substream);
2360-
#endif
2366+
snd_pcm_oss_release_buffers(substream);
23612367
substream->oss.oss = 0;
23622368
}
23632369

sound/core/oss/pcm_plugin.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
6262
width = snd_pcm_format_physical_width(format->format);
6363
if (width < 0)
6464
return width;
65-
size = frames * format->channels * width;
65+
size = array3_size(frames, format->channels, width);
66+
/* check for too large period size once again */
67+
if (size > 1024 * 1024)
68+
return -ENOMEM;
6669
if (snd_BUG_ON(size % 8))
6770
return -ENXIO;
6871
size /= 8;

0 commit comments

Comments
 (0)